diff --git a/.flake8 b/.flake8 index 1c759147fb..038fcfbaf9 100644 --- a/.flake8 +++ b/.flake8 @@ -164,3 +164,7 @@ exclude = components/wifi_provisioning/python/wifi_constants_pb2.py, components/esp_local_ctrl/python/esp_local_ctrl_pb2.py, examples/provisioning/legacy/custom_config/components/custom_provisioning/python/custom_config_pb2.py, + +per-file-ignores = + # Sphinx conf.py files use star imports to setup config variables + docs/conf_common.py: F405 diff --git a/.github/workflows/python_lint.yml b/.github/workflows/python_lint.yml index b62552fe87..5e36177855 100644 --- a/.github/workflows/python_lint.yml +++ b/.github/workflows/python_lint.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [2.7, 3.5, 3.6, 3.7, 3.8] + python-version: [3.6, 3.7, 3.8] steps: - name: Checkout diff --git a/.gitignore b/.gitignore index 61e02dae70..38ebd38bef 100644 --- a/.gitignore +++ b/.gitignore @@ -88,3 +88,6 @@ build # lock files for examples and components dependencies.lock + +# managed_components for examples +managed_components diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4a57cdb4c6..d1bc5816e1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -48,10 +48,11 @@ variables: # Docker images BOT_DOCKER_IMAGE_TAG: ":latest" - ESP_IDF_DOC_ENV_IMAGE: "$CI_DOCKER_REGISTRY/esp-idf-doc-env:v4.4-1-v2" + ESP_IDF_DOC_ENV_IMAGE: "$CI_DOCKER_REGISTRY/esp-idf-doc-env:v4.4-1-v4" ESP_ENV_IMAGE: "$CI_DOCKER_REGISTRY/esp-env:v4.4-1" AFL_FUZZER_TEST_IMAGE: "$CI_DOCKER_REGISTRY/afl-fuzzer-test:v4.4-1-1" - CLANG_STATIC_ANALYSIS_IMAGE: "${CI_DOCKER_REGISTRY}/clang-static-analysis:v4.4-1-1" + CLANG_STATIC_ANALYSIS_IMAGE: "${CI_DOCKER_REGISTRY}/clang-static-analysis:v4.4-1-2" + SONARQUBE_SCANNER_IMAGE: "${CI_DOCKER_REGISTRY}/sonarqube-scanner:3" # target test config file, used by assign test job CI_TARGET_TEST_CONFIG_FILE: "$CI_PROJECT_DIR/.gitlab/ci/target-test.yml" diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS index f0fd4d6a81..65ba4cb9f7 100644 --- a/.gitlab/CODEOWNERS +++ b/.gitlab/CODEOWNERS @@ -57,6 +57,7 @@ /export.* @esp-idf-codeowners/tools /install.* @esp-idf-codeowners/tools /sdkconfig.rename @esp-idf-codeowners/build-config +/sonar-project.properties @esp-idf-codeowners/ci # sort-order-reset @@ -66,6 +67,7 @@ /components/bootloader*/ @esp-idf-codeowners/system @esp-idf-codeowners/security /components/bt/ @esp-idf-codeowners/bluetooth /components/cbor/ @esp-idf-codeowners/app-utilities +/components/cmock/ @esp-idf-codeowners/system /components/coap/ @esp-idf-codeowners/app-utilities /components/console/ @esp-idf-codeowners/system @esp-idf-codeowners/app-utilities /components/cxx/ @esp-idf-codeowners/system @@ -159,6 +161,7 @@ /examples/ethernet/ @esp-idf-codeowners/network /examples/get-started/ @esp-idf-codeowners/system /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/protocols/ @esp-idf-codeowners/network @esp-idf-codeowners/app-utilities @@ -183,6 +186,7 @@ /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 ## 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 diff --git a/.gitlab/ci/build.yml b/.gitlab/ci/build.yml index fa039e5ca8..7a70c4aa5c 100644 --- a/.gitlab/ci/build.yml +++ b/.gitlab/ci/build.yml @@ -221,6 +221,14 @@ build_examples_cmake_esp32s2: variables: IDF_TARGET: esp32s2 +build_examples_cmake_esp32s3: + extends: + - .build_examples_cmake_template + - .rules:build:example_test-esp32s3 + parallel: 8 + variables: + IDF_TARGET: esp32s3 + build_examples_cmake_esp32c3: extends: - .build_examples_cmake_template @@ -344,6 +352,7 @@ build_docker: - .before_script_minimal - .rules:build:docker stage: host_test + needs: [] image: espressif/docker-builder:1 tags: - build_docker_amd64_brno @@ -366,6 +375,7 @@ build_docker: - .before_script_minimal - .rules:build:windows stage: host_test + needs: [] image: $CI_DOCKER_REGISTRY/esp32-toolchain-win-cross tags: - build diff --git a/.gitlab/ci/docs.yml b/.gitlab/ci/docs.yml index f06869d90a..80e627d605 100644 --- a/.gitlab/ci/docs.yml +++ b/.gitlab/ci/docs.yml @@ -39,7 +39,6 @@ check_readme_links: extends: - .pre_check_job_template - - .doc-rules:build:docs tags: ["build", "amd64", "internet"] allow_failure: true script: @@ -62,12 +61,12 @@ check_docs_lang_sync: dependencies: [] script: - cd docs - - python -m pip install -r requirements.txt - - python ./build_docs.py -bs $DOC_BUILDERS -l $DOCLANG -t $DOCTGT build + - pip install -r requirements.txt + - build-docs -t $DOCTGT -bs $DOC_BUILDERS -l $DOCLANG build parallel: matrix: - DOCLANG: ["en", "zh_CN"] - DOCTGT: ["esp32", "esp32s2", "esp32c3"] + DOCTGT: ["esp32", "esp32s2", "esp32s3", "esp32c3"] check_docs_gh_links: image: $ESP_IDF_DOC_ENV_IMAGE @@ -78,8 +77,8 @@ check_docs_gh_links: - .doc-rules:build:docs script: - cd docs - - python -m pip install -r requirements.txt - - python ./build_docs.py gh-linkcheck + - pip install -r requirements.txt + - build-docs gh-linkcheck # stage: build_doc # Add this stage to let the build_docs job run in parallel with build @@ -129,13 +128,6 @@ build_docs_html_fast: variables: DOC_BUILDERS: "html" DOCS_FAST_BUILD: "yes" - # matrix is redefined to include esp32s3 here - # that we can build for S3 MRs during bringup phase without - # anything being built and published from master branch - parallel: - matrix: - - DOCLANG: ["en", "zh_CN"] - DOCTGT: ["esp32", "esp32s2", "esp32s3", "esp32c3"] build_docs_pdf: extends: @@ -168,7 +160,8 @@ build_docs_pdf: script: - add_doc_server_ssh_keys $DOCS_DEPLOY_PRIVATEKEY $DOCS_DEPLOY_SERVER $DOCS_DEPLOY_SERVER_USER - export GIT_VER=$(git describe --always) - - python ${IDF_PATH}/tools/ci/deploy_docs.py + - pip install -r docs/requirements.txt + - deploy-docs # stage: test_deploy deploy_docs_preview: @@ -227,6 +220,6 @@ check_doc_links: allow_failure: true script: - cd docs - - python -m pip install -r requirements.txt + - pip install -r requirements.txt # At the moment this check will always fail due to multiple known limitations, ignore result - - python ./build_docs.py -l $DOCLANG -t $DOCTGT linkcheck || { echo "THERE ARE ISSUES DUE TO KNOWN LIMITATIONS, PLEASE FIX THEM. Nowadays we're ignored them to pass pipeline."; true; } + - build-docs -t $DOCTGT -l $DOCLANG linkcheck || { echo "THERE ARE ISSUES DUE TO KNOWN LIMITATIONS, PLEASE FIX THEM. Nowadays we're ignored them to pass pipeline."; true; } diff --git a/.gitlab/ci/host-test.yml b/.gitlab/ci/host-test.yml index d228147258..82be5c54aa 100644 --- a/.gitlab/ci/host-test.yml +++ b/.gitlab/ci/host-test.yml @@ -220,11 +220,6 @@ test_efuse_table_on_host_esp32s2: variables: IDF_TARGET: esp32s2 -test_efuse_table_on_host_esp32s2: - extends: .test_efuse_table_on_host_template - variables: - IDF_TARGET: esp32s2 - test_efuse_table_on_host_esp32s3: extends: .test_efuse_table_on_host_template variables: @@ -250,10 +245,11 @@ test_espcoredump: expire_in: 1 week variables: IDF_COREDUMP_ELF_REPO: "https://gitlab-ci-token:${BOT_TOKEN}@${CI_SERVER_HOST}:${CI_SERVER_PORT}/idf/idf-coredump-elf.git" + IDF_COREDUMP_ELF_TAG: idf-20210910-00 # install CMake version specified in tools.json SETUP_TOOLS_LIST: "all" script: - - retry_failed git clone ${IDF_COREDUMP_ELF_REPO} -b master + - retry_failed git clone ${IDF_COREDUMP_ELF_REPO} -b $IDF_COREDUMP_ELF_TAG - cd ${IDF_PATH}/components/espcoredump/test/ - ./test_espcoredump.sh ${CI_PROJECT_DIR}/idf-coredump-elf @@ -295,22 +291,6 @@ test_mkuf2: - cd ${IDF_PATH}/tools/test_mkuf2 - ./test_mkuf2.py -test_docs: - extends: .host_test_template - image: $ESP_IDF_DOC_ENV_IMAGE - variables: - PYTHON_VER: 3.6.13 - artifacts: - when: on_failure - paths: - - docs/test/_build/*/*/*/html/* - expire_in: 1 week - script: - - cd ${IDF_PATH}/docs/test - - python -m pip install -r ${IDF_PATH}/docs/requirements.txt - - ./test_docs.py - - ./test_sphinx_idf_extensions.py - test_autocomplete: extends: .host_test_template image: $CI_DOCKER_REGISTRY/linux-shells:1 @@ -340,7 +320,7 @@ test_nvs_page: script: - cd ${IDF_PATH}/components/nvs_flash/host_test/nvs_page_test - idf.py build - - build/host_nvs_page_test.elf + - build/test_nvs_page_host.elf test_log: extends: .host_test_template @@ -349,9 +329,44 @@ test_log: - idf.py build - build/test_log_host.elf +test_esp_event: + extends: .host_test_template + script: + - cd ${IDF_PATH}/components/esp_event/host_test/esp_event_unit_test + - idf.py build + - build/test_esp_event_host.elf + +test_esp_timer_cxx: + extends: .host_test_template + script: + - cd ${IDF_PATH}/examples/cxx/experimental/experimental_cpp_component/host_test/esp_timer + - idf.py build + - build/test_esp_timer_cxx_host.elf + test_eh_frame_parser: extends: .host_test_template script: - cd ${IDF_PATH}/components/esp_system/test_eh_frame_parser - make - ./eh_frame_test + +test_rom_on_linux_works: + extends: .host_test_template + script: + - cd ${IDF_PATH}/components/esp_rom/host_test/rom_test + - idf.py build + - build/test_rom_host.elf + +test_cxx_gpio: + extends: .host_test_template + script: + - cd ${IDF_PATH}/examples/cxx/experimental/experimental_cpp_component/host_test/gpio + - idf.py build + - build/test_gpio_cxx_host.elf + +test_linux_example: + extends: .host_test_template + script: + - cd ${IDF_PATH}/examples/build_system/cmake/linux_host_app + - idf.py build + - build/linux_host_app.elf diff --git a/.gitlab/ci/pre_check.yml b/.gitlab/ci/pre_check.yml index 3ddccfadca..676ef0a44b 100644 --- a/.gitlab/ci/pre_check.yml +++ b/.gitlab/ci/pre_check.yml @@ -113,6 +113,15 @@ check_public_headers: script: - python tools/ci/check_public_headers.py --jobs 4 --prefix xtensa-esp32-elf- +check_soc_struct_headers: + extends: + - .pre_check_base_template + - .rules:build + tags: + - build + script: + - find ${IDF_PATH}/components/soc/*/include/soc/ -name "*_struct.h" -print0 | xargs -0 -n1 ./tools/ci/check_soc_struct_headers.py + check_esp_err_to_name: extends: - .pre_check_base_template diff --git a/.gitlab/ci/rules.yml b/.gitlab/ci/rules.yml index ba17c56788..d9e8056d1c 100644 --- a/.gitlab/ci/rules.yml +++ b/.gitlab/ci/rules.yml @@ -3,7 +3,10 @@ ############ .patterns-c-files: &patterns-c-files - ".gitlab/ci/static-code-analysis.yml" + - "tools/ci/static-analysis-rules.yml" + - "tools/ci/clang_tidy_dirs.txt" + - "**/*.{c,C}" - "**/*.{h,H}" - "components/**/Kconfig" @@ -37,6 +40,7 @@ .patterns-build_components: &patterns-build_components - "components/**/*" + - "examples/cxx/experimental/experimental_cpp_component/*" .patterns-build_system: &patterns-build_system - "tools/cmake/**/*" diff --git a/.gitlab/ci/static-code-analysis.yml b/.gitlab/ci/static-code-analysis.yml index ecf0c319ef..cdcabfd758 100644 --- a/.gitlab/ci/static-code-analysis.yml +++ b/.gitlab/ci/static-code-analysis.yml @@ -5,17 +5,46 @@ clang_tidy_check: - .rules:patterns:clang_tidy image: ${CLANG_STATIC_ANALYSIS_IMAGE} artifacts: - reports: - junit: $IDF_PATH/output.xml + paths: + - $OUTPUT_DIR + when: always + expire_in: 1 day + variables: + CLANG_TIDY_RUNNER_PROJ: 2107 # idf/clang-tidy-runner + CLANG_TIDY_DIRS_TXT: ${CI_PROJECT_DIR}/tools/ci/clang_tidy_dirs.txt + RULES_FILE: ${CI_PROJECT_DIR}/tools/ci/static-analysis-rules.yml + OUTPUT_DIR: ${CI_PROJECT_DIR}/clang_tidy_reports + script: + - python -m pip install -U pip + - internal_pip_install $CLANG_TIDY_RUNNER_PROJ pyclang + - export PATH=$PATH:$(python -c "import sys; print(sys.executable.rsplit('/', 1)[0])") + - dirs=$(cat ${CLANG_TIDY_DIRS_TXT} | while read line; do echo ${CI_PROJECT_DIR}/${line}; done | xargs) + - run_cmd idf_clang ${dirs} + --output-path ${OUTPUT_DIR} + --limit-file ${RULES_FILE} + --xtensa-include-dir + --run-clang-tidy-py ${RUN_CLANG_TIDY_PY} + +check_pylint: + extends: + - .pre_check_base_template + - .rules:patterns:python-files + - .before_script_minimal + image: $SONARQUBE_SCANNER_IMAGE + artifacts: when: always paths: - - $IDF_PATH/examples/get-started/hello_world/tidybuild/report/* - expire_in: 1 day + - pylint-report.txt + expire_in: 1 week script: - - retry_failed git clone $IDF_ANALYSIS_UTILS static_analysis_utils && cd static_analysis_utils - # Setup parameters of triggered/regular job - - export TARGET_BRANCH=${BOT_CUSTOMIZED_REVISION-} - - ./analyze.sh $IDF_PATH/examples/get-started/hello_world/ $IDF_PATH/tools/ci/static-analysis-rules.yml $IDF_PATH/output.xml + - export PYTHONPATH="$IDF_PATH/tools:$IDF_PATH/tools/ci/python_packages:$PYTHONPATH" + - | + if [ -n "$CI_MERGE_REQUEST_IID" ]; then + export files=$(python ${CI_PROJECT_DIR}/tools/ci/ci_get_mr_info.py files ${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME} | grep ".py"); + else + export files=$(find . -iname "*.py" -print); + fi + - pylint --rcfile=.pylintrc $files -r n --output-format=parseable > pylint-report.txt || exit 0 # build stage # Sonarqube related jobs put here for this reason: @@ -33,26 +62,31 @@ clang_tidy_check: .sonar_scan_template: stage: build image: - name: $CI_DOCKER_REGISTRY/sonarqube-scanner:2 + name: $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 /** - - export SUBMODULES=$(get_all_submodules) + - submodules=$(get_all_submodules) # get all exclude paths specified in tools/ci/sonar_exclude_list.txt | ignore lines start with # | xargs | replace all to - - export CUSTOM_EXCLUDES=$(cat $CI_PROJECT_DIR/tools/ci/sonar_exclude_list.txt | grep -v '^#' | xargs | sed -e 's/ /,/g') + - 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,$REPORT_DIR/**,docs/_static/**,**/*.png,**/*.jpg" - - python $NORMALIZE_CLANGTIDY_PY $CI_PROJECT_DIR/$REPORT_DIR/warnings.txt $CI_PROJECT_DIR/$REPORT_DIR/clang_tidy_report.txt $CI_PROJECT_DIR + - export EXCLUSIONS="$custom_excludes,$submodules" + - export SONAR_SCANNER_OPTS="-Xmx2048m" + variables: GIT_DEPTH: 0 - NORMALIZE_CLANGTIDY_PY: $CI_PROJECT_DIR/tools/ci/normalize_clangtidy_path.py - REPORT_DIR: examples/get-started/hello_world/tidybuild/report + REPORT_PATTERN: clang_tidy_reports/*.txt + artifacts: + when: always + paths: + - $REPORT_PATTERN tags: - host_test 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 + - check_pylint code_quality_check: extends: @@ -67,23 +101,16 @@ code_quality_check: - test -n "$CI_MERGE_REQUEST_COMMITS" || exit 0 - sonar-scanner -Dsonar.analysis.mode=preview - -Dsonar.branch.name=$CI_COMMIT_REF_NAME - -Dsonar.cxx.clangtidy.reportPath=$REPORT_DIR/clang_tidy_report.txt - -Dsonar.cxx.includeDirectories=components,/usr/include + -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.failure_notification_mode=exit-code -Dsonar.gitlab.merge_request_discussion=true - -Dsonar.gitlab.project_id=$CI_PROJECT_ID - -Dsonar.gitlab.ref_name=$CI_COMMIT_REF_NAME + -Dsonar.gitlab.ref_name=$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME -Dsonar.host.url=$SONAR_HOST_URL -Dsonar.login=$SONAR_LOGIN - -Dsonar.projectBaseDir=$CI_PROJECT_DIR - -Dsonar.projectKey=esp-idf - -Dsonar.python.pylint_config=.pylintrc - -Dsonar.sourceEncoding=UTF-8 - -Dsonar.sources=$CI_PROJECT_DIR + -Dsonar.python.pylint.reportPath=pylint-report.txt code_quality_report: extends: @@ -94,41 +121,10 @@ code_quality_report: script: - sonar-scanner -Dsonar.branch.name=$CI_COMMIT_REF_NAME - -Dsonar.cxx.clangtidy.reportPath=$REPORT_DIR/clang_tidy_report.txt - -Dsonar.cxx.includeDirectories=components,/usr/include + -Dsonar.cxx.clangtidy.reportPath=$REPORT_PATTERN -Dsonar.exclusions=$EXCLUSIONS -Dsonar.gitlab.commit_sha=$CI_COMMIT_SHA - -Dsonar.gitlab.failure_notification_mode=exit-code - -Dsonar.gitlab.project_id=$CI_PROJECT_ID -Dsonar.gitlab.ref_name=$CI_COMMIT_REF_NAME -Dsonar.host.url=$SONAR_HOST_URL -Dsonar.login=$SONAR_LOGIN - -Dsonar.projectBaseDir=$CI_PROJECT_DIR - -Dsonar.projectKey=esp-idf - -Dsonar.python.pylint_config=.pylintrc - -Dsonar.sourceEncoding=UTF-8 - -Dsonar.sources=$CI_PROJECT_DIR - -# deploy stage -clang_tidy_deploy: - extends: - - .deploy_job_template - - .rules:patterns:clang_tidy - needs: - - clang_tidy_check - tags: - - deploy - - shiny - script: - - add_doc_server_ssh_keys $DOCS_DEPLOY_KEY $DOCS_SERVER $DOCS_SERVER_USER - - export GIT_VER=$(git describe --always) - - cd $IDF_PATH/examples/get-started/hello_world/tidybuild - - mv report $GIT_VER - - tar czvf $GIT_VER.tar.gz $GIT_VER - - export STATIC_REPORT_PATH="web/static_analysis/esp-idf/" - - ssh $DOCS_SERVER -x "mkdir -p $STATIC_REPORT_PATH/clang-tidy" - - scp $GIT_VER.tar.gz $DOCS_SERVER:$STATIC_REPORT_PATH/clang-tidy - - ssh $DOCS_SERVER -x "cd $STATIC_REPORT_PATH/clang-tidy && tar xzvf $GIT_VER.tar.gz && rm -f latest && ln -s $GIT_VER latest" - # add link to view the report - - echo "[static analysis][clang tidy] $CI_DOCKER_REGISTRY/static_analysis/esp-idf/clang-tidy/${GIT_VER}/index.html" - - test ! -e ${GIT_VER}/FAILED_RULES || { echo 'Failed static analysis rules!'; cat ${GIT_VER}/FAILED_RULES; exit 1; } + -Dsonar.python.pylint.reportPath=pylint-report.txt diff --git a/.gitlab/ci/target-test.yml b/.gitlab/ci/target-test.yml index 8e898b7bfe..f9f3c10c90 100644 --- a/.gitlab/ci/target-test.yml +++ b/.gitlab/ci/target-test.yml @@ -46,7 +46,7 @@ extends: - .example_test_template - .rules:test:example_test-esp32 -variables: + variables: SUBMODULES_TO_FETCH: "all" test_weekend_mqtt: @@ -60,7 +60,7 @@ test_weekend_mqtt: - export MQTT_PUBLISH_TEST=1 - export TEST_PATH=$CI_PROJECT_DIR/tools/test_apps/protocols/mqtt/publish_connect_test - cd $IDF_PATH/tools/ci/python_packages/tiny_test_fw/bin - - run_cmd python Runner.py $TEST_PATH -c $TEST_PATH/publish_connect_mqtt_.yml -e $TEST_PATH/env.yml + - run_cmd python Runner.py $TEST_PATH -c $TEST_PATH/publish_connect_mqtt_.yml .example_test_esp32_template: extends: @@ -97,7 +97,7 @@ example_test_001B_V3: example_test_001C: extends: .example_test_esp32_template - parallel: 3 + parallel: 4 tags: - ESP32 - Example_GENERIC @@ -129,7 +129,7 @@ example_test_002: - ESP32 - Example_ShieldBox_Basic -example_test_enternet: +example_test_ethernet: extends: .example_test_esp32_template tags: - ESP32 @@ -270,20 +270,17 @@ example_test_ESP32_SDSPI: - ESP32 - UT_T1_SPIMODE -# uncomment when ESP32S2 & ESP32C3 runners with external SD connected over SPI are available -# ensure the runners have required tags created -# -#example_test_ESP32S2_SDSPI: -# extends: .example_test_esp32s2_template -# tags: -# - ESP32S2 -# - UT_T1_SPIMODE -# -#example_test_ESP32C3_SDSPI: -# extends: .example_test_esp32c3_template -# tags: -# - ESP32C3 -# - UT_T1_SPIMODE +example_test_ESP32S2_SDSPI: + extends: .example_test_esp32s2_template + tags: + - ESP32S2 + - UT_T1_SPIMODE + +example_test_ESP32C3_SDSPI: + extends: .example_test_esp32c3_template + tags: + - ESP32C3 + - UT_T1_SPIMODE .test_app_template: extends: .target_test_job_template @@ -447,7 +444,7 @@ UT_001: UT_002: extends: .unit_test_esp32_template - parallel: 16 + parallel: 14 tags: - ESP32_IDF - UT_T1_1 @@ -482,7 +479,7 @@ UT_006: UT_007: extends: .unit_test_esp32_template - parallel: 2 + parallel: 4 tags: - ESP32_IDF - UT_T1_1 @@ -508,19 +505,6 @@ UT_014: - UT_T2_RS485 - psram -UT_015: - extends: .unit_test_esp32_template - tags: - - ESP32_IDF - - UT_T1_RMT - -UT_016: - extends: .unit_test_esp32_template - tags: - - ESP32_IDF - - UT_T1_RMT - - psram - UT_017: extends: .unit_test_esp32_template tags: @@ -544,7 +528,6 @@ UT_020: UT_021: extends: .unit_test_esp32_template - parallel: 2 tags: - ESP32_IDF - psram @@ -579,7 +562,7 @@ UT_033: UT_034: extends: .unit_test_esp32_template - parallel: 3 + parallel: 2 tags: - ESP32_IDF - UT_T1_ESP_FLASH @@ -607,7 +590,7 @@ UT_036: UT_038: extends: .unit_test_esp32s2_template - parallel: 3 + parallel: 2 tags: - ESP32S2_IDF - UT_T1_ESP_FLASH @@ -647,7 +630,7 @@ UT_046: UT_047: extends: .unit_test_esp32s2_template - parallel: 3 + parallel: 5 tags: - ESP32S2_IDF - UT_T1_1 @@ -658,9 +641,15 @@ UT_S2_SPI_DUAL: - ESP32S2_IDF - Example_SPI_Multi_device +UT_S2_SDSPI: + extends: .unit_test_esp32s2_template + tags: + - ESP32S2_IDF + - UT_T1_SPIMODE + UT_C3: extends: .unit_test_esp32c3_template - parallel: 33 + parallel: 32 tags: - ESP32C3_IDF - UT_T1_1 @@ -674,7 +663,6 @@ UT_C3_FLASH: UT_C3_SPI_DUAL: extends: .unit_test_esp32c3_template - parallel: 2 tags: - ESP32C3_IDF - Example_SPI_Multi_device @@ -697,9 +685,15 @@ UT_C3_FLASH_SUSPEND: - ESP32C3_IDF - UT_T1_Flash_Suspend +UT_C3_SDSPI: + extends: .unit_test_esp32c3_template + tags: + - ESP32C3_IDF + - UT_T1_SPIMODE + UT_S3: extends: .unit_test_esp32s3_template - parallel: 27 + parallel: 29 tags: - ESP32S3_IDF - UT_T1_1 @@ -717,6 +711,18 @@ UT_S3_FLASH: - ESP32S3_IDF - UT_T1_ESP_FLASH +component_ut_test_ip101: + extends: .component_ut_esp32_template + tags: + - ESP32 + - COMPONENT_UT_IP101 + +component_ut_test_lan8720: + extends: .component_ut_esp32_template + tags: + - ESP32 + - COMPONENT_UT_LAN8720 + .integration_test_template: extends: - .target_test_job_template diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 043c533335..0fa2a43527 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,7 +3,7 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v3.4.0 + rev: v4.0.1 hooks: - id: trailing-whitespace # note: whitespace exclusions use multiline regex, see https://pre-commit.com/#regular-expressions @@ -26,12 +26,12 @@ repos: args: ['-f=lf'] - id: double-quote-string-fixer - repo: https://gitlab.com/pycqa/flake8 - rev: 3.8.4 + rev: 3.9.2 hooks: - id: flake8 args: ['--config=.flake8', '--tee', '--benchmark'] - repo: https://github.com/pycqa/isort - rev: 5.6.4 + rev: 5.9.3 hooks: - id: isort name: isort (python) @@ -92,11 +92,24 @@ repos: - id: mypy-check name: Check type annotations in python files entry: tools/ci/check_type_comments.py - additional_dependencies: ['mypy==0.800', 'mypy-extensions==0.4.3'] + additional_dependencies: + - 'mypy==0.800' + - 'mypy-extensions==0.4.3' language: python types: [python] + - id: check-copyright + name: Check copyright notices + entry: tools/ci/check_copyright.py --verbose --replace + additional_dependencies: + - 'comment_parser == 1.2.3' + - 'thefuzz == 0.19.0' + - 'thefuzz[speedup] == 0.19.0; sys_platform != "win32"' + # don't depend on python-Levenshtein on Windows, as it requires Microsoft C++ Build Tools to install + language: python + files: \.(py|c|h|cpp|hpp|ld)$ + require_serial: true - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v3.4.0 + rev: v4.0.1 hooks: - id: file-contents-sorter - files: '(tools\/ci\/executable-list\.txt|tools\/ci\/mypy_ignore_list\.txt)' + files: 'tools\/ci\/(executable-list\.txt|mypy_ignore_list\.txt|check_copyright_ignore\.txt)' diff --git a/CMakeLists.txt b/CMakeLists.txt index 34e043dd41..f580e8de85 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,9 @@ if(NOT BOOTLOADER_BUILD) if(CONFIG_COMPILER_OPTIMIZATION_SIZE) list(APPEND compile_options "-Os") - list(APPEND compile_options "-freorder-blocks") + if(CMAKE_C_COMPILER_ID MATCHES "GNU") + list(APPEND compile_options "-freorder-blocks") + endif() elseif(CONFIG_COMPILER_OPTIMIZATION_DEFAULT) list(APPEND compile_options "-Og") elseif(CONFIG_COMPILER_OPTIMIZATION_NONE) @@ -33,7 +35,9 @@ else() # BOOTLOADER_BUILD if(CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE) list(APPEND compile_options "-Os") - list(APPEND compile_options "-freorder-blocks") + if(CMAKE_C_COMPILER_ID MATCHES "GNU") + list(APPEND compile_options "-freorder-blocks") + endif() elseif(CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG) list(APPEND compile_options "-Og") elseif(CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE) @@ -74,6 +78,48 @@ if(CONFIG_COMPILER_DISABLE_GCC8_WARNINGS) "-Wno-int-in-bool-context") endif() +if(CMAKE_C_COMPILER_ID MATCHES "GNU") + list(APPEND c_compile_options "-Wno-old-style-declaration") +endif() + +# Clang finds some warnings in IDF code which GCC doesn't. +# All these warnings should be fixed before Clang is presented +# as a toolchain choice for users. +if(CMAKE_C_COMPILER_ID MATCHES "Clang") + # Clang checks Doxygen comments for being in sync with function prototype. + # There are some inconsistencies, especially in ROM headers. + list(APPEND compile_options "-Wno-documentation") + # GCC allows repeated typedefs when the source and target types are the same. + # Clang doesn't allow this. This occurs in many components due to forward + # declarations. + list(APPEND compile_options "-Wno-typedef-redefinition") + # This issue is seemingly related to newlib's char type functions. + # Fix is not clear yet. + list(APPEND compile_options "-Wno-char-subscripts") + # Clang seems to notice format string issues which GCC doesn't. + list(APPEND compile_options "-Wno-format-security") + # Logic bug in essl component + list(APPEND compile_options "-Wno-tautological-overlap-compare") + # Some pointer checks in mDNS component check addresses which can't be NULL + list(APPEND compile_options "-Wno-tautological-pointer-compare") + # Similar to the above, in tcp_transport + list(APPEND compile_options "-Wno-pointer-bool-conversion") + # mbedTLS md5.c triggers this warning in md5_test_buf (false positive) + list(APPEND compile_options "-Wno-string-concatenation") + # multiple cases of implict convertions between unrelated enum types + list(APPEND compile_options "-Wno-enum-conversion") + # When IRAM_ATTR is specified both in function declaration and definition, + # it produces different section names, since section names include __COUNTER__. + # Occurs in multiple places. + list(APPEND compile_options "-Wno-section") + # Multiple cases of attributes unknown to clang, for example + # __attribute__((optimize("-O3"))) + list(APPEND compile_options "-Wno-unknown-attributes") + # Clang also produces many -Wunused-function warnings which GCC doesn't. + # However these aren't treated as errors. +endif() +# More warnings may exist in unit tests and example projects. + if(CONFIG_COMPILER_WARN_WRITE_STRINGS) list(APPEND compile_options "-Wwrite-strings") endif() @@ -118,7 +164,15 @@ list(APPEND link_options "-fno-lto") # Placing jump tables in flash would cause issues with code that required # to be placed in IRAM list(APPEND compile_options "-fno-jump-tables") -list(APPEND compile_options "-fno-tree-switch-conversion") +if(CMAKE_C_COMPILER_ID MATCHES "GNU") + # This flag is GCC-specific. + # Not clear yet if some other flag should be used for Clang. + list(APPEND compile_options "-fno-tree-switch-conversion") +endif() + +if(CMAKE_C_COMPILER_ID MATCHES "LLVM") + list(APPEND compile_options "-fno-use-cxa-atexit") +endif() idf_build_set_property(COMPILE_OPTIONS "${compile_options}" APPEND) idf_build_set_property(C_COMPILE_OPTIONS "${c_compile_options}" APPEND) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 7a9825b0f0..0c506acf4f 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -56,7 +56,6 @@ Related Documents style-guide install-pre-commit-hook documenting-code - add-ons-reference creating-examples ../api-reference/template contributor-agreement diff --git a/Kconfig b/Kconfig index 942837a0ea..65d03788c9 100644 --- a/Kconfig +++ b/Kconfig @@ -11,7 +11,6 @@ mainmenu "Espressif IoT Development Framework Configuration" config IDF_ENV_FPGA # This option is for internal use only bool - default "y" if IDF_TARGET="esp32h2" # ESP32H2-TODO: IDF-3378 option env="IDF_ENV_FPGA" config IDF_TARGET_ARCH_RISCV diff --git a/README.md b/README.md index 10027f474b..73b855e398 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,24 @@ * [中文版](./README_CN.md) -ESP-IDF is the development framework for Espressif SoCs (released after 2016[1](#fn1)) provided for Windows, Linux and macOS. +ESP-IDF is the development framework for Espressif SoCs supported on Windows, Linux and macOS. + +# ESP-IDF Release and SoC Compatibility + +The following table shows ESP-IDF support of Espressif SoCs where ![alt text][preview] and ![alt text][supported] denote preview status and support, respectively. In preview status the build is not yet enabled and some crucial parts could be missing (like documentation, datasheet). Please use an ESP-IDF release where the desired SoC is already supported. + +|Chip | v3.3 | v4.0 | v4.1 | v4.2 | v4.3 | v4.4 | | +|:----------- |:---------------------: | :---------------------:| :---------------------:| :---------------------:| :---------------------:| :---------------------:|:---------------------------------------------------------- | +|ESP32 | ![alt text][supported] | ![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] | | +|ESP32-C3 | | | | | ![alt text][supported] | ![alt text][supported] | | +|ESP32-S3 | | | | | ![alt text][preview] | ![alt text][supported] | [Announcement](https://www.espressif.com/en/news/ESP32_S3) | +|ESP32-H2 | | | | | | ![alt text][preview] | [Announcement](https://www.espressif.com/en/news/ESP32_H2) | + +[supported]: https://img.shields.io/badge/-supported-green "supported" +[preview]: https://img.shields.io/badge/-preview-orange "preview" + +Espressif SoCs released before 2016 (ESP8266 and ESP8285) are supported by [RTOS SDK](https://github.com/espressif/ESP8266_RTOS_SDK) instead. # Developing With ESP-IDF @@ -99,8 +116,3 @@ This can be combined with other targets, ie `idf.py -p PORT erase_flash flash` w * [Check the Issues section on github](https://github.com/espressif/esp-idf/issues) if you find a bug or have a feature request. Please check existing Issues before opening a new one. * If you're interested in contributing to ESP-IDF, please check the [Contributions Guide](https://docs.espressif.com/projects/esp-idf/en/latest/contribute/index.html). - - -________ - -1: ESP8266 and ESP8285 are not supported in ESP-IDF. See [RTOS SDK](https://github.com/espressif/ESP8266_RTOS_SDK) instead. \ No newline at end of file diff --git a/README_CN.md b/README_CN.md index 9d30adddff..123bea47ba 100644 --- a/README_CN.md +++ b/README_CN.md @@ -2,13 +2,30 @@ * [English Version](./README.md) -ESP-IDF 是由乐鑫官方针对乐鑫各系列芯片产品(发布于 2016 年后[1](#fn1))推出的开发框架,支持 Windows、Linux 和 macOS 操作系统。 +ESP-IDF 是乐鑫官方推出的物联网开发框架,支持 Windows、Linux 和 macOS 操作系统。 + +# ESP-IDF 与乐鑫芯片 + +下表总结了乐鑫芯片在 ESP-IDF 各版本中的支持状态,其中 ![alt text][supported] 代表已支持,![alt text][preview] 代表目前处于预览支持状态。在预览支持阶段,因为新芯片尚未完全添加到构建系统目录,所以一些重要的内容(如文档和技术规格书等)可能会缺失。请确保使用与芯片相匹配的 ESP-IDF 版本。 + +| 芯片 | v3.3 | v4.0 | v4.1 | v4.2 | v4.3 | v4.4 | | +|:----------- |:---------------------: | :---------------------:| :---------------------:| :---------------------:| :---------------------:| :---------------------:|:---------------------------------------------------------- | +|ESP32 | ![alt text][supported] | ![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] | | +|ESP32-C3 | | | | | ![alt text][supported] | ![alt text][supported] | | +|ESP32-S3 | | | | | ![alt text][preview] | ![alt text][supported] | [芯片发布公告](https://www.espressif.com/en/news/ESP32_S3) | +|ESP32-H2 | | | | | | ![alt text][preview] | [芯片发布公告](https://www.espressif.com/en/news/ESP32_H2) | + +[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" + +对于 2016 年之前发布的乐鑫芯片(包括 ESP8266 和 ESP8285),请参考 [RTOS SDK](https://github.com/espressif/ESP8266_RTOS_SDK)。 # 使用 ESP-IDF 进行开发 ## 搭建 ESP-IDF 开发环境 -关于不同芯片如何搭建 ESP-IDF 的开发环境,请参考 https://idf.espressif.com/。 +关于不同芯片如何搭建 ESP-IDF 的开发环境,请参考 https://idf.espressif.com/ 。 **注意:** 不同系列芯片和不同 ESP-IDF 版本都有其对应的文档。请参阅[版本](https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/versions.html)部分,获得关于如何查找文档以及如何检出 ESP-IDF 的特定发行版的详细信息。 @@ -99,8 +116,3 @@ ESP-IDF 中的子模块采用相对路径([详见 .gitmodules 文件](.gitmodu * 如果你在使用中发现了错误或者需要新的功能,请先[查看 GitHub Issues](https://github.com/espressif/esp-idf/issues),确保该问题没有重复提交。 * 如果你有兴趣为 ESP-IDF 作贡献,请先阅读[贡献指南](https://docs.espressif.com/projects/esp-idf/en/latest/contribute/index.html)。 - - -__________ - -1: ESP-IDF 不支持 ESP8266 和 ESP8285。如有需要,请参考 [RTOS SDK](https://github.com/espressif/ESP8266_RTOS_SDK)。 diff --git a/components/README.md b/components/README.md new file mode 100644 index 0000000000..c4c33d8674 --- /dev/null +++ b/components/README.md @@ -0,0 +1,160 @@ +# Core Components + +## Overview + +This document contains details about what the core components are, what they contain, and how they are organized. + +## Organization + +The core components are organized into two groups. + +The first group (referred to as `G0` from now on) contains `hal`, `xtensa` and `riscv` (referred to as `arch` components from now on), `esp_rom`, `esp_common`, and `soc`. This +group contain information about and low-level access to underlying hardware; or in the case of `esp_common`, hardware-agnostic code and utilities. +These components can depend on each other, but as much as possible have no dependencies outside the group. The reason for this is that, due to the +nature of what these components contain, the likelihood is high that a lot of other components will require these. Ideally, then, the dependency +relationship only goes one way. This makes it easier for these components, as a group, to be usable in another project. One can conceivably implement +a competing SDK to ESP-IDF on top of these components. + +The second group (referred to as `G1` from now on) sits at a higher level than the first group. This group contains the components `esp_hw_support`, `esp_system`, `newlib`, `spi_flash`, +`freertos`, `log`, and `heap`. Like the first group, circular dependencies within the group are allowed; and being at a higher level, dependency on the first group +is allowed. These components represent software mechanisms essential to building other components. + +## Descriptions + +The following is a short description of the components mentioned above. + +### `G0` Components + +#### `hal` + +Contains the hardware abstraction layer and low-level operation implementations for the various peripherals. The low-level functions assign meaningful names to register-level manipulations; the hardware abstraction provide operations one level above this, grouping these low-level functions +into routines that achieve a meaningful action or state of the peripheral. + +Example: + +- `spi_flash_ll_set_address` is a low-level function part of the hardware abstraction `spi_flash_hal_read_block` + +#### `arch` + +Contains low-level architecture operations and definitions, including those for customizations (can be thought of on the same level as the low-level functions of `hal`). +This can also contain files provided by the architecture vendor. + +Example: + +- `xt_set_exception_handler` +- `riscv_global_interrupts_enable` +- `ERI_PERFMON_MAX` + +#### `esp_common` + +Contains hardware-agnostic definitions, constants, macros, utilities, 'pure' and/or algorithmic functions that is useable by all other components (that is, barring there being a more appropriate component to put them in). + +Example: + +- `BIT(nr)` and other bit manipulation utilities in the future +- `IDF_DEPRECATED(REASON)` +- `ESP_IDF_VERSION_MAJOR` + +#### `soc` + +Contains description of the underlying hardware: register structure, addresses, pins, capabilities, etc. + +Example: + +- `DR_REG_DPORT_BASE` +- `SOC_MCPWM_SUPPORTED` +- `uart_dev_s` + +#### `esp_rom` + +Contains headers, linker scripts, abstraction layer, patches, and other related files to ROM functions. + +Example: + +- `esp32.rom.eco3.ld` +- `rom/aes.h` + +### `G1` Components + +#### `spi_flash` + +SPI flash device access implementation. + +#### `freertos` + +FreeRTOS port to targets supported by ESP-IDF. + +#### `log` + +Logging library. + +#### `heap` + +Heap implementation. + +#### `newlib` + +Some functions n the standard library are implemented here, especially those needing other `G1` components. + +Example: + +- `malloc` is implemented in terms of the component `heap`'s functions +- `gettimeofday` is implemented in terms of system time in `esp_system` + +#### `esp_system` + +Contains implementation of system services and controls system behavior. The implementations +here may take hardware resources and/or decide on a hardware state needed for support of a system service/feature/mechanism. +Currently, this encompasses the following, but not limited to: + +- Startup and initialization +- Panic and debug +- Reset and reset reason +- Task and interrupt watchdogs + +#### `esp_hw_support` + +Contains implementations that provide hardware operations, arbitration, or resource sharing, especially those that +is used in the system. Unlike `esp_system`, implementations here do not decide on a hardware state or takes hardware resource, acting +merely as facilitator to hardware access. Currently, this encompasses the following, but not limited to: + +- Interrupt allocation +- Sleep functions +- Memory functions (external SPIRAM, async memory, etc.) +- Clock and clock control +- Random generation +- CPU utilities +- MAC settings + +### `esp_hw_support` vs `esp_system` + +This section details list some implementations and the reason for placing it in either `esp_hw_support` or `esp_system`. + +#### `task_wdt.c` (`esp_system`) vs `intr_alloc.c` (`esp_hw_support`) + +The task watchdog fits the definition of taking and configuring hardware resources (wdt, interrupt) for implementation of a system service/mechanism. + +This is in contrast with interrupt allocation that merely facilitates access to the underlying hardware for other implementations - +drivers, user code, and even the task watchdog mentioned previously! + +#### `crosscore_int.c` (`esp_system`) + +The current implementation of crosscore interrupts is tightly coupled with a number of interrupt reasons +associated with system services/mechanisms: REASON_YIELD (scheduler), REASON_FREQ_SWITCH (power management) +REASON_PRINT_BACKTRACE (panic and debug). + +However, if an implementation exists that makes it possible to register an arbitrary interrupt reason - a +lower level inter-processor call if you will, then this implementation is a good candidate for `esp_hw_support`. +The current implementation in `esp_system` can then just register the interrupt reasons mentioned above. + +#### `esp_mac.h`, `esp_chip_info.h`, `esp_random.h` (`esp_hw_support`) + +The functions in these headers used to be in `esp_system.h`, but have been split-off. +However, to maintain backward compatibility, `esp_system.h` includes these headers. + +The remaining functions in `esp_system.h` are those that deal with system behavior, such +as `esp_register_shutdown_handler`, or are proxy for other system components's APIs such as +`esp_get_free_heap_size`. + +The functions split-off from `esp_system.h` are much more hardware manipulation oriented such as: +`esp_read_mac`, `esp_random` and `esp_chip_info`. \ No newline at end of file diff --git a/components/app_trace/CMakeLists.txt b/components/app_trace/CMakeLists.txt index db67ffb8c5..e6f4df2c46 100644 --- a/components/app_trace/CMakeLists.txt +++ b/components/app_trace/CMakeLists.txt @@ -47,7 +47,7 @@ endif() idf_component_register(SRCS "${srcs}" INCLUDE_DIRS "${include_dirs}" PRIV_INCLUDE_DIRS "${priv_include_dirs}" - PRIV_REQUIRES soc + PRIV_REQUIRES soc esp_ipc LDFRAGMENTS linker.lf) # disable --coverage for this component, as it is used as transport diff --git a/components/app_trace/gcov/gcov_rtio.c b/components/app_trace/gcov/gcov_rtio.c index 524e1cb3ff..bd470c9a4f 100644 --- a/components/app_trace/gcov/gcov_rtio.c +++ b/components/app_trace/gcov/gcov_rtio.c @@ -14,7 +14,9 @@ #include "soc/cpu.h" #include "soc/timer_periph.h" #include "esp_app_trace.h" +#include "esp_freertos_hooks.h" #include "esp_private/dbg_stubs.h" +#include "esp_ipc.h" #include "hal/wdt_hal.h" #if CONFIG_IDF_TARGET_ESP32 #include "esp32/rom/libc_stubs.h" @@ -28,128 +30,113 @@ #include "esp_log.h" const static char *TAG = "esp_gcov_rtio"; +static volatile bool s_create_gcov_task = false; +static volatile bool s_gcov_task_running = false; extern void __gcov_dump(void); extern void __gcov_reset(void); -static struct syscall_stub_table s_gcov_stub_table; - - -static int gcov_stub_lock_try_acquire_recursive(_lock_t *lock) +void gcov_dump_task(void *pvParameter) { - if (*lock && uxSemaphoreGetCount((xSemaphoreHandle)(*lock)) == 0) { - // we can do nothing here, gcov dump is initiated with some resource locked - // which is also used by gcov functions - ESP_EARLY_LOGE(TAG, "Lock 0x%x is busy during GCOV dump! System state can be inconsistent after dump!", lock); - } - return pdTRUE; -} + int dump_result = 0; + bool *running = (bool *)pvParameter; -static void gcov_stub_lock_acquire_recursive(_lock_t *lock) -{ - gcov_stub_lock_try_acquire_recursive(lock); -} + ESP_EARLY_LOGV(TAG, "%s stack use in %d", __FUNCTION__, uxTaskGetStackHighWaterMark(NULL)); -static void gcov_stub_lock_release_recursive(_lock_t *lock) -{ -} - -static int esp_dbg_stub_gcov_dump_do(void) -{ - int ret = ESP_OK; - FILE* old_stderr = stderr; - FILE* old_stdout = stdout; - static struct syscall_stub_table *old_tables[portNUM_PROCESSORS]; - - old_tables[0] = syscall_table_ptr_pro; -#if portNUM_PROCESSORS > 1 - old_tables[1] = syscall_table_ptr_app; -#endif ESP_EARLY_LOGV(TAG, "Alloc apptrace down buf %d bytes", ESP_GCOV_DOWN_BUF_SIZE); void *down_buf = malloc(ESP_GCOV_DOWN_BUF_SIZE); if (down_buf == NULL) { ESP_EARLY_LOGE(TAG, "Could not allocate memory for the buffer"); - return ESP_ERR_NO_MEM; + dump_result = ESP_ERR_NO_MEM; + goto gcov_exit; } ESP_EARLY_LOGV(TAG, "Config apptrace down buf"); esp_apptrace_down_buffer_config(down_buf, ESP_GCOV_DOWN_BUF_SIZE); + /* we are directing the std outputs to the fake ones in order to reduce stack usage */ + FILE *old_stderr = stderr; + FILE *old_stdout = stdout; + stderr = (FILE *) &__sf_fake_stderr; + stdout = (FILE *) &__sf_fake_stdout; ESP_EARLY_LOGV(TAG, "Dump data..."); - // incase of dual-core chip APP and PRO CPUs share the same table, so it is safe to save only PRO's table - memcpy(&s_gcov_stub_table, syscall_table_ptr_pro, sizeof(s_gcov_stub_table)); - s_gcov_stub_table._lock_acquire_recursive = &gcov_stub_lock_acquire_recursive; - s_gcov_stub_table._lock_release_recursive = &gcov_stub_lock_release_recursive; - s_gcov_stub_table._lock_try_acquire_recursive = &gcov_stub_lock_try_acquire_recursive, - syscall_table_ptr_pro = &s_gcov_stub_table; -#if portNUM_PROCESSORS > 1 - syscall_table_ptr_app = &s_gcov_stub_table; -#endif - stderr = (FILE*) &__sf_fake_stderr; - stdout = (FILE*) &__sf_fake_stdout; __gcov_dump(); // reset dump status to allow incremental data accumulation __gcov_reset(); - stdout = old_stdout; - stderr = old_stderr; - syscall_table_ptr_pro = old_tables[0]; -#if portNUM_PROCESSORS > 1 - syscall_table_ptr_app = old_tables[1]; -#endif - ESP_EARLY_LOGV(TAG, "Free apptrace down buf"); free(down_buf); + stderr = old_stderr; + stdout = old_stdout; ESP_EARLY_LOGV(TAG, "Finish file transfer session"); - ret = esp_apptrace_fstop(ESP_APPTRACE_DEST_TRAX); - if (ret != ESP_OK) { - ESP_EARLY_LOGE(TAG, "Failed to send files transfer stop cmd (%d)!", ret); + dump_result = esp_apptrace_fstop(ESP_APPTRACE_DEST_TRAX); + if (dump_result != ESP_OK) { + ESP_EARLY_LOGE(TAG, "Failed to send files transfer stop cmd (%d)!", dump_result); + } + +gcov_exit: + ESP_EARLY_LOGV(TAG, "dump_result %d", dump_result); + if (running) { + *running = false; + } + + ESP_EARLY_LOGV(TAG, "%s stack use out %d", __FUNCTION__, uxTaskGetStackHighWaterMark(NULL)); + + vTaskDelete(NULL); +} + +void gcov_create_task(void *arg) +{ + ESP_EARLY_LOGV(TAG, "%s", __FUNCTION__); + xTaskCreatePinnedToCore(&gcov_dump_task, "gcov_dump_task", 2048, (void *)&s_gcov_task_running, configMAX_PRIORITIES - 1, NULL, 0); +} + +void gcov_create_task_tick_hook(void) +{ + extern esp_err_t esp_ipc_start_gcov_from_isr(uint32_t cpu_id, esp_ipc_func_t func, void* arg); + if (s_create_gcov_task) { + if (esp_ipc_start_gcov_from_isr(xPortGetCoreID(), &gcov_create_task, NULL) == ESP_OK) { + s_create_gcov_task = false; + } } - ESP_EARLY_LOGV(TAG, "exit %d", ret); - return ret; } /** - * @brief Triggers gcov info dump. + * @brief Triggers gcov info dump task * This function is to be called by OpenOCD, not by normal user code. - * TODO: what about interrupted flash access (when cache disabled)??? + * TODO: what about interrupted flash access (when cache disabled) * * @return ESP_OK on success, otherwise see esp_err_t */ static int esp_dbg_stub_gcov_entry(void) { - return esp_dbg_stub_gcov_dump_do(); + /* we are in isr context here */ + s_create_gcov_task = true; + return ESP_OK; } int gcov_rtio_atexit(void (*function)(void) __attribute__ ((unused))) { + uint32_t capabilities = 0; ESP_EARLY_LOGV(TAG, "%s", __FUNCTION__); esp_dbg_stub_entry_set(ESP_DBG_STUB_ENTRY_GCOV, (uint32_t)&esp_dbg_stub_gcov_entry); - return 0; + if (esp_dbg_stub_entry_get(ESP_DBG_STUB_ENTRY_CAPABILITIES, &capabilities) == ESP_OK) { + esp_dbg_stub_entry_set(ESP_DBG_STUB_ENTRY_CAPABILITIES, capabilities | ESP_DBG_STUB_CAP_GCOV_TASK); + } + esp_register_freertos_tick_hook(gcov_create_task_tick_hook); + return ESP_OK; } void esp_gcov_dump(void) { - // disable IRQs on this CPU, other CPU is halted by OpenOCD - unsigned irq_state = portENTER_CRITICAL_NESTED(); -#if !CONFIG_FREERTOS_UNICORE - int other_core = cpu_hal_get_core_id() ? 0 : 1; - esp_cpu_stall(other_core); -#endif + ESP_EARLY_LOGV(TAG, "%s", __FUNCTION__); + while (!esp_apptrace_host_is_connected(ESP_APPTRACE_DEST_TRAX)) { - wdt_hal_context_t twdt = {.inst = WDT_MWDT0, .mwdt_dev = &TIMERG0}; - wdt_hal_context_t iwdt = {.inst = WDT_MWDT1, .mwdt_dev = &TIMERG1}; - //Feed the Task Watchdog (TG0) to prevent it from timing out - wdt_hal_write_protect_disable(&twdt); - wdt_hal_feed(&twdt); - wdt_hal_write_protect_enable(&twdt); - //Likewise, feed the Interrupt Watchdog (TG1) to prevent a reboot - wdt_hal_write_protect_disable(&iwdt); - wdt_hal_feed(&iwdt); - wdt_hal_write_protect_enable(&iwdt); + vTaskDelay(pdMS_TO_TICKS(10)); } - esp_dbg_stub_gcov_dump_do(); -#if !CONFIG_FREERTOS_UNICORE - esp_cpu_unstall(other_core); -#endif - portEXIT_CRITICAL_NESTED(irq_state); + /* We are not in isr context here. Waiting for the completion is safe */ + s_gcov_task_running = true; + s_create_gcov_task = true; + while (s_gcov_task_running) { + vTaskDelay(pdMS_TO_TICKS(10)); + } } void *gcov_rtio_fopen(const char *path, const char *mode) @@ -168,7 +155,7 @@ int gcov_rtio_fclose(void *stream) size_t gcov_rtio_fread(void *ptr, size_t size, size_t nmemb, void *stream) { - ESP_EARLY_LOGV(TAG, "%s read %u", __FUNCTION__, size*nmemb); + ESP_EARLY_LOGV(TAG, "%s read %u", __FUNCTION__, size * nmemb); size_t sz = esp_apptrace_fread(ESP_APPTRACE_DEST_TRAX, ptr, size, nmemb, stream); ESP_EARLY_LOGV(TAG, "%s actually read %u", __FUNCTION__, sz); return sz; diff --git a/components/app_trace/sys_view/Sample/Config/SEGGER_SYSVIEW_Config_FreeRTOS.c b/components/app_trace/sys_view/Sample/Config/SEGGER_SYSVIEW_Config_FreeRTOS.c index 965b74c5e2..268b389921 100644 --- a/components/app_trace/sys_view/Sample/Config/SEGGER_SYSVIEW_Config_FreeRTOS.c +++ b/components/app_trace/sys_view/Sample/Config/SEGGER_SYSVIEW_Config_FreeRTOS.c @@ -151,16 +151,17 @@ extern const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI; // The lowest RAM address used for IDs (pointers) #define SYSVIEW_RAM_BASE (SOC_DROM_LOW) -#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 +#ifdef CONFIG_FREERTOS_TICK_SUPPORT_CORETIMER #if CONFIG_FREERTOS_CORETIMER_0 #define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER0_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF) #endif #if CONFIG_FREERTOS_CORETIMER_1 #define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER1_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF) #endif -#elif CONFIG_IDF_TARGET_ESP32C3 - #define SYSTICK_INTR_ID (ETS_SYSTIMER_TARGET0_EDGE_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF) -#endif + +#elif CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER + #define SYSTICK_INTR_ID (ETS_SYSTIMER_TARGET0_EDGE_INTR_SOURCE) +#endif // CONFIG_FREERTOS_TICK_SUPPORT_CORETIMER // SystemView is single core specific: it implies that SEGGER_SYSVIEW_LOCK() // disables IRQs (disables rescheduling globally). So we can not use finite timeouts for locks and return error diff --git a/components/app_trace/sys_view/Sample/OS/SEGGER_SYSVIEW_FreeRTOS.h b/components/app_trace/sys_view/Sample/OS/SEGGER_SYSVIEW_FreeRTOS.h index 47624de258..aba3bd3ea3 100644 --- a/components/app_trace/sys_view/Sample/OS/SEGGER_SYSVIEW_FreeRTOS.h +++ b/components/app_trace/sys_view/Sample/OS/SEGGER_SYSVIEW_FreeRTOS.h @@ -209,7 +209,7 @@ Notes: #define apiID_VEVENTGROUPDELETE (72u) #define apiID_UXEVENTGROUPGETNUMBER (73u) -#define traceTASK_NOTIFY_TAKE() SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_ULTASKNOTIFYTAKE, xClearCountOnExit, xTicksToWait) +#define traceTASK_NOTIFY_TAKE( uxIndexToWait ) SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_ULTASKNOTIFYTAKE, xClearCountOnExit, xTicksToWait) #define traceTASK_DELAY() SEGGER_SYSVIEW_RecordU32(apiFastID_OFFSET + apiID_VTASKDELAY, xTicksToDelay) #define traceTASK_DELAY_UNTIL() SEGGER_SYSVIEW_RecordVoid(apiFastID_OFFSET + apiID_VTASKDELAYUNTIL) #define traceTASK_DELETE( pxTCB ) if (pxTCB != NULL) { \ @@ -217,16 +217,16 @@ Notes: SEGGER_SYSVIEW_ShrinkId((U32)pxTCB)); \ SYSVIEW_DeleteTask((U32)pxTCB); \ } -#define traceTASK_NOTIFY_GIVE_FROM_ISR() SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_VTASKNOTIFYGIVEFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB), (U32)pxHigherPriorityTaskWoken) +#define traceTASK_NOTIFY_GIVE_FROM_ISR( uxIndexToNotify ) SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_VTASKNOTIFYGIVEFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB), (U32)pxHigherPriorityTaskWoken) #define traceTASK_PRIORITY_INHERIT( pxTCB, uxPriority ) SEGGER_SYSVIEW_RecordU32(apiFastID_OFFSET + apiID_VTASKPRIORITYINHERIT, (U32)pxMutexHolder) #define traceTASK_RESUME( pxTCB ) SEGGER_SYSVIEW_RecordU32(apiFastID_OFFSET + apiID_VTASKRESUME, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB)) #define traceINCREASE_TICK_COUNT( xTicksToJump ) SEGGER_SYSVIEW_RecordU32(apiFastID_OFFSET + apiID_VTASKSTEPTICK, xTicksToJump) #define traceTASK_SUSPEND( pxTCB ) SEGGER_SYSVIEW_RecordU32(apiFastID_OFFSET + apiID_VTASKSUSPEND, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB)) #define traceTASK_PRIORITY_DISINHERIT( pxTCB, uxBasePriority ) SEGGER_SYSVIEW_RecordU32(apiFastID_OFFSET + apiID_XTASKPRIORITYDISINHERIT, (U32)pxMutexHolder) #define traceTASK_RESUME_FROM_ISR( pxTCB ) SEGGER_SYSVIEW_RecordU32(apiFastID_OFFSET + apiID_XTASKRESUMEFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB)) -#define traceTASK_NOTIFY() SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XTASKGENERICNOTIFY, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB), ulValue, eAction, (U32)pulPreviousNotificationValue) -#define traceTASK_NOTIFY_FROM_ISR() SYSVIEW_RecordU32x5(apiFastID_OFFSET + apiID_XTASKGENERICNOTIFYFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB), ulValue, eAction, (U32)pulPreviousNotificationValue, (U32)pxHigherPriorityTaskWoken) -#define traceTASK_NOTIFY_WAIT() SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XTASKNOTIFYWAIT, ulBitsToClearOnEntry, ulBitsToClearOnExit, (U32)pulNotificationValue, xTicksToWait) +#define traceTASK_NOTIFY( uxIndexToNotify ) SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XTASKGENERICNOTIFY, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB), ulValue, eAction, (U32)pulPreviousNotificationValue) +#define traceTASK_NOTIFY_FROM_ISR( uxIndexToNotify ) SYSVIEW_RecordU32x5(apiFastID_OFFSET + apiID_XTASKGENERICNOTIFYFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB), ulValue, eAction, (U32)pulPreviousNotificationValue, (U32)pxHigherPriorityTaskWoken) +#define traceTASK_NOTIFY_WAIT( uxIndexToWait ) SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XTASKNOTIFYWAIT, ulBitsToClearOnEntry, ulBitsToClearOnExit, (U32)pulNotificationValue, xTicksToWait) #define traceQUEUE_CREATE( pxNewQueue ) SEGGER_SYSVIEW_RecordU32x3(apiFastID_OFFSET + apiID_XQUEUEGENERICCREATE, uxQueueLength, uxItemSize, ucQueueType) #define traceQUEUE_DELETE( pxQueue ) SEGGER_SYSVIEW_RecordU32(apiFastID_OFFSET + apiID_VQUEUEDELETE, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue)) diff --git a/components/app_update/CMakeLists.txt b/components/app_update/CMakeLists.txt index e6329224e6..8dd328215c 100644 --- a/components/app_update/CMakeLists.txt +++ b/components/app_update/CMakeLists.txt @@ -46,6 +46,7 @@ if(NOT BOOTLOADER_BUILD) add_custom_target(blank_ota_data ALL DEPENDS ${blank_otadata_file}) add_dependencies(flash blank_ota_data) + add_dependencies(encrypted-flash blank_ota_data) set(otatool_py ${python} ${COMPONENT_DIR}/otatool.py) diff --git a/components/bootloader/Kconfig.projbuild b/components/bootloader/Kconfig.projbuild index 15f6183c4c..306e4dcd3c 100644 --- a/components/bootloader/Kconfig.projbuild +++ b/components/bootloader/Kconfig.projbuild @@ -386,6 +386,15 @@ menu "Bootloader config" in this area of memory, you can increase it. It must be a multiple of 4 bytes. This area (rtc_retain_mem_t) is reserved and has access from the bootloader and an application. + config BOOTLOADER_FLASH_XMC_SUPPORT + bool "Enable the support for flash chips of XMC (READ HELP FIRST)" + default y + help + Perform the startup flow recommended by XMC. Please consult XMC for the details of this flow. + XMC chips will be forbidden to be used, when this option is disabled. + + DON'T DISABLE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. + endmenu # Bootloader @@ -415,12 +424,12 @@ menu "Security features" config SECURE_BOOT_SUPPORTS_RSA bool default y - depends on ESP32_REV_MIN_3 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3 + depends on ESP32_REV_MIN_3 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 config SECURE_TARGET_HAS_SECURE_ROM_DL_MODE bool default y - depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3 + depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 config SECURE_SIGNED_APPS_NO_SECURE_BOOT @@ -492,7 +501,8 @@ menu "Security features" config SECURE_BOOT bool "Enable hardware Secure Boot in bootloader (READ DOCS FIRST)" default n - depends on IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || ESP32C3_REV_MIN_3 + depends on IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || ESP32C3_REV_MIN_3 || IDF_TARGET_ESP32S3 + select ESPTOOLPY_NO_STUB if !IDF_TARGET_ESP32 && !IDF_TARGET_ESP32S2 help Build a bootloader which enables Secure Boot on first boot. @@ -755,9 +765,17 @@ menu "Security features" efuse when Secure Boot is enabled. This prevents any more efuses from being read protected. If this option is set, it will remain possible to write the EFUSE_RD_DIS efuse field after Secure - Boot is enabled. This may allow an attacker to read-protect the BLK2 efuse holding the public - key digest, causing an immediate denial of service and possibly allowing an additional fault - injection attack to bypass the signature protection. + Boot is enabled. This may allow an attacker to read-protect the BLK2 efuse (for ESP32) and + BLOCK4-BLOCK10 (i.e. BLOCK_KEY0-BLOCK_KEY5)(for other chips) holding the public key digest, causing an + immediate denial of service and possibly allowing an additional fault injection attack to + bypass the signature protection. + + NOTE: Once a BLOCK is read-protected, the application will read all zeros from that block + + NOTE: If "UART ROM download mode (Permanently disabled (recommended))" or + "UART ROM download mode (Permanently switch to Secure mode (recommended))" is set, + then it is __NOT__ possible to read/write efuses using espefuse.py utility. + However, efuse can be read/written from the application config SECURE_BOOT_ALLOW_UNUSED_DIGEST_SLOTS bool "Leave unused digest slots available (not revoke)" @@ -875,6 +893,8 @@ menu "Security features" It is also possible to enable secure download mode at runtime by calling esp_efuse_enable_rom_secure_download_mode() + Note: Secure Download mode is not available for ESP32 (includes revisions till ECO3). + config SECURE_INSECURE_ALLOW_DL_MODE bool "UART ROM download mode (Enabled (not recommended))" help diff --git a/components/bootloader/subproject/main/ld/esp32/bootloader.ld b/components/bootloader/subproject/main/ld/esp32/bootloader.ld index 0c065d2c0c..30e5a79c45 100644 --- a/components/bootloader/subproject/main/ld/esp32/bootloader.ld +++ b/components/bootloader/subproject/main/ld/esp32/bootloader.ld @@ -49,6 +49,7 @@ SECTIONS *libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*) *libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*) *libbootloader_support.a:bootloader_panic.*(.literal .text .literal.* .text.*) + *libbootloader_support.a:bootloader_soc.*(.literal .text .literal.* .text.*) *libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*) *libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*) *libbootloader_support.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*) diff --git a/components/bootloader/subproject/main/ld/esp32c3/bootloader.ld b/components/bootloader/subproject/main/ld/esp32c3/bootloader.ld index 4da19b44de..c9b2da7612 100644 --- a/components/bootloader/subproject/main/ld/esp32c3/bootloader.ld +++ b/components/bootloader/subproject/main/ld/esp32c3/bootloader.ld @@ -36,6 +36,7 @@ SECTIONS *libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*) *libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*) *libbootloader_support.a:bootloader_panic.*(.literal .text .literal.* .text.*) + *libbootloader_support.a:bootloader_soc.*(.literal .text .literal.* .text.*) *libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*) *libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*) *libbootloader_support.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*) diff --git a/components/bootloader/subproject/main/ld/esp32h2/bootloader.ld b/components/bootloader/subproject/main/ld/esp32h2/bootloader.ld index dc49e09123..c5648b815e 100644 --- a/components/bootloader/subproject/main/ld/esp32h2/bootloader.ld +++ b/components/bootloader/subproject/main/ld/esp32h2/bootloader.ld @@ -36,6 +36,7 @@ SECTIONS *libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*) *libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*) *libbootloader_support.a:bootloader_panic.*(.literal .text .literal.* .text.*) + *libbootloader_support.a:bootloader_soc.*(.literal .text .literal.* .text.*) *libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*) *libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*) *libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*) diff --git a/components/bootloader/subproject/main/ld/esp32s2/bootloader.ld b/components/bootloader/subproject/main/ld/esp32s2/bootloader.ld index 6ba052d6aa..92e0126cf0 100644 --- a/components/bootloader/subproject/main/ld/esp32s2/bootloader.ld +++ b/components/bootloader/subproject/main/ld/esp32s2/bootloader.ld @@ -36,6 +36,7 @@ SECTIONS *libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*) *libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*) *libbootloader_support.a:bootloader_panic.*(.literal .text .literal.* .text.*) + *libbootloader_support.a:bootloader_soc.*(.literal .text .literal.* .text.*) *libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*) *libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*) *libbootloader_support.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*) diff --git a/components/bootloader/subproject/main/ld/esp32s3/bootloader.ld b/components/bootloader/subproject/main/ld/esp32s3/bootloader.ld index 85daecd512..244482f823 100644 --- a/components/bootloader/subproject/main/ld/esp32s3/bootloader.ld +++ b/components/bootloader/subproject/main/ld/esp32s3/bootloader.ld @@ -37,6 +37,7 @@ SECTIONS *libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*) *libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*) *libbootloader_support.a:bootloader_panic.*(.literal .text .literal.* .text.*) + *libbootloader_support.a:bootloader_soc.*(.literal .text .literal.* .text.*) *libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*) *libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*) *libbootloader_support.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*) diff --git a/components/bootloader_support/CMakeLists.txt b/components/bootloader_support/CMakeLists.txt index f2da1dbb2e..664a59817d 100644 --- a/components/bootloader_support/CMakeLists.txt +++ b/components/bootloader_support/CMakeLists.txt @@ -26,6 +26,7 @@ if(BOOTLOADER_BUILD) "src/bootloader_console_loader.c" "src/bootloader_panic.c" "src/${IDF_TARGET}/bootloader_sha.c" + "src/${IDF_TARGET}/bootloader_soc.c" "src/${IDF_TARGET}/bootloader_${IDF_TARGET}.c" ) list(APPEND priv_requires hal) diff --git a/components/bootloader_support/include/bootloader_common.h b/components/bootloader_support/include/bootloader_common.h index 2ff0e595a2..2f4e906220 100644 --- a/components/bootloader_support/include/bootloader_common.h +++ b/components/bootloader_support/include/bootloader_common.h @@ -119,6 +119,15 @@ bool bootloader_common_label_search(const char *list, char *label); */ void bootloader_configure_spi_pins(int drv); +/** + * @brief Get flash CS IO + * + * Can be determined by eFuse values, or the default value + * + * @return Flash CS IO + */ +uint8_t bootloader_flash_get_cs_io(void); + /** * @brief Calculates a sha-256 for a given partition or returns a appended digest. * diff --git a/components/bootloader_support/include/bootloader_flash.h b/components/bootloader_support/include/bootloader_flash.h index 61afc2a337..49e457f372 100644 --- a/components/bootloader_support/include/bootloader_flash.h +++ b/components/bootloader_support/include/bootloader_flash.h @@ -14,6 +14,14 @@ extern "C" { #endif +/** + * @brief Read flash ID by sending RDID command (0x9F) + * @return flash raw ID + * mfg_id = (ID >> 16) & 0xFF; + flash_id = ID & 0xffff; + */ +uint32_t bootloader_read_flash_id(void); + #if SOC_CACHE_SUPPORT_WRAP /** * @brief Set the burst mode setting command for specified wrap mode. @@ -32,6 +40,13 @@ esp_err_t bootloader_flash_wrap_set(spi_flash_wrap_mode_t mode); */ esp_err_t bootloader_flash_unlock(void); +/** + * @brief Startup flow recommended by XMC. Call at startup before any erase/write operation. + * + * @return ESP_OK When startup successfully, otherwise ESP_FAIL (indiciating you should reboot before erase/write). + */ +esp_err_t bootloader_flash_xmc_startup(void); + #ifdef __cplusplus } #endif diff --git a/components/bootloader_support/include_bootloader/bootloader_flash_priv.h b/components/bootloader_support/include_bootloader/bootloader_flash_priv.h index 7d703b84fa..d898cae124 100644 --- a/components/bootloader_support/include_bootloader/bootloader_flash_priv.h +++ b/components/bootloader_support/include_bootloader/bootloader_flash_priv.h @@ -29,6 +29,7 @@ #define CMD_RDSR 0x05 #define CMD_RDSR2 0x35 /* Not all SPI flash uses this command */ #define CMD_OTPEN 0x3A /* Enable OTP mode, not all SPI flash uses this command */ +#define CMD_RDSFDP 0x5A /* Read the SFDP of the flash */ #define CMD_WRAP 0x77 /* Set burst with wrap command */ #define CMD_RESUME 0x7A /* Resume command to clear flash suspend bit */ @@ -156,6 +157,15 @@ static inline uint32_t bootloader_cache_pages_to_map(uint32_t size, uint32_t vad */ uint32_t bootloader_execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len); +/** + * @brief Read the SFDP of the flash + * + * @param sfdp_addr Address of the parameter to read + * @param miso_byte_num Bytes to read + * @return The read SFDP, little endian, 4 bytes at most + */ +uint32_t bootloader_flash_read_sfdp(uint32_t sfdp_addr, unsigned int miso_byte_num); + /** * @brief Enable the flash write protect (WEL bit). */ diff --git a/components/bootloader_support/include_bootloader/bootloader_soc.h b/components/bootloader_support/include_bootloader/bootloader_soc.h new file mode 100644 index 0000000000..a7414fd3f3 --- /dev/null +++ b/components/bootloader_support/include_bootloader/bootloader_soc.h @@ -0,0 +1,27 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +/** + * @brief Configure analog super WDT reset + * + * @param enable Boolean to enable or disable super WDT reset + */ +void bootloader_ana_super_wdt_reset_config(bool enable); + +/** + * @brief Configure analog brownout reset + * + * @param enable Boolean to enable or disable brownout reset + */ +void bootloader_ana_bod_reset_config(bool enable); + +/** + * @brief Configure analog clock glitch reset + * + * @param enable Boolean to enable or disable clock glitch reset + */ +void bootloader_ana_clock_glitch_reset_config(bool enable); diff --git a/components/bootloader_support/src/bootloader_common.c b/components/bootloader_support/src/bootloader_common.c index 2369436d7e..2acbd74fa9 100644 --- a/components/bootloader_support/src/bootloader_common.c +++ b/components/bootloader_support/src/bootloader_common.c @@ -23,6 +23,7 @@ #include "esp_rom_crc.h" #include "esp_rom_gpio.h" #include "esp_rom_sys.h" +#include "esp_rom_efuse.h" #include "esp_flash_partitions.h" #include "bootloader_flash_priv.h" #include "bootloader_common.h" @@ -191,8 +192,19 @@ void bootloader_common_vddsdio_configure(void) #endif // CONFIG_BOOTLOADER_VDDSDIO_BOOST } - RESET_REASON bootloader_common_get_reset_reason(int cpu_no) { return (RESET_REASON)esp_rom_get_reset_reason(cpu_no); } + +uint8_t bootloader_flash_get_cs_io(void) +{ + uint8_t cs_io; + const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info(); + if (spiconfig == ESP_ROM_EFUSE_FLASH_DEFAULT_SPI) { + cs_io = SPI_CS0_GPIO_NUM; + } else { + cs_io = (spiconfig >> 18) & 0x3f; + } + return cs_io; +} diff --git a/components/bootloader_support/src/bootloader_console.c b/components/bootloader_support/src/bootloader_console.c index 78152b6647..211e95e30b 100644 --- a/components/bootloader_support/src/bootloader_console.c +++ b/components/bootloader_support/src/bootloader_console.c @@ -71,8 +71,8 @@ void bootloader_console_init(void) gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_U0RXD_U, PIN_FUNC_GPIO); gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_U0TXD_U, PIN_FUNC_GPIO); // Route GPIO signals to/from pins - const uint32_t tx_idx = uart_periph_signal[uart_num].tx_sig; - const uint32_t rx_idx = uart_periph_signal[uart_num].rx_sig; + const uint32_t tx_idx = UART_PERIPH_SIGNAL(uart_num, SOC_UART_TX_PIN_IDX); + const uint32_t rx_idx = UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX); PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[uart_rx_gpio]); esp_rom_gpio_pad_pullup_only(uart_rx_gpio); esp_rom_gpio_connect_out_signal(uart_tx_gpio, tx_idx, 0, 0); diff --git a/components/bootloader_support/src/bootloader_efuse_esp32.c b/components/bootloader_support/src/bootloader_efuse_esp32.c index 3704e16c3a..2a89e63ce4 100644 --- a/components/bootloader_support/src/bootloader_efuse_esp32.c +++ b/components/bootloader_support/src/bootloader_efuse_esp32.c @@ -7,14 +7,14 @@ #include "bootloader_common.h" #include "bootloader_clock.h" #include "soc/efuse_reg.h" -#include "soc/apb_ctrl_reg.h" +#include "soc/syscon_reg.h" uint8_t bootloader_common_get_chip_revision(void) { uint8_t eco_bit0, eco_bit1, eco_bit2; eco_bit0 = (REG_READ(EFUSE_BLK0_RDATA3_REG) & 0xF000) >> 15; eco_bit1 = (REG_READ(EFUSE_BLK0_RDATA5_REG) & 0x100000) >> 20; - eco_bit2 = (REG_READ(APB_CTRL_DATE_REG) & 0x80000000) >> 31; + eco_bit2 = (REG_READ(SYSCON_DATE_REG) & 0x80000000) >> 31; uint32_t combine_value = (eco_bit2 << 2) | (eco_bit1 << 1) | eco_bit0; uint8_t chip_ver = 0; switch (combine_value) { @@ -28,7 +28,7 @@ uint8_t bootloader_common_get_chip_revision(void) chip_ver = 2; break; #if CONFIG_IDF_ENV_FPGA - case 4: /* Empty efuses, but APB_CTRL_DATE_REG bit is set */ + case 4: /* Empty efuses, but SYSCON_DATE_REG bit is set */ chip_ver = 3; break; #endif diff --git a/components/bootloader_support/src/bootloader_efuse_esp32s2.c b/components/bootloader_support/src/bootloader_efuse_esp32s2.c index 072d8add21..0b4334cf43 100644 --- a/components/bootloader_support/src/bootloader_efuse_esp32s2.c +++ b/components/bootloader_support/src/bootloader_efuse_esp32s2.c @@ -19,5 +19,5 @@ uint8_t bootloader_common_get_chip_revision(void) uint32_t bootloader_common_get_chip_ver_pkg(void) { // should return the same value as esp_efuse_get_pkg_ver() - return REG_GET_FIELD(EFUSE_RD_MAC_SPI_SYS_3_REG, EFUSE_PKG_VERSION); + return REG_GET_FIELD(EFUSE_RD_MAC_SPI_SYS_4_REG, EFUSE_PKG_VERSION); } diff --git a/components/bootloader_support/src/bootloader_flash.c b/components/bootloader_support/src/bootloader_flash.c index 8119bdfa1f..8ed1726e67 100644 --- a/components/bootloader_support/src/bootloader_flash.c +++ b/components/bootloader_support/src/bootloader_flash.c @@ -122,7 +122,7 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size) return spi_flash_erase_range(start_addr, size); } -#else +#else //BOOTLOADER_BUILD /* Bootloader version, uses ROM functions only */ #if CONFIG_IDF_TARGET_ESP32 #include "esp32/rom/spi_flash.h" @@ -481,7 +481,8 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size) return spi_to_esp_err(rc); } -#endif +#endif // BOOTLOADER_BUILD + FORCE_INLINE_ATTR bool is_issi_chip(const esp_rom_spiflash_chip_t* chip) { @@ -563,29 +564,49 @@ esp_err_t IRAM_ATTR __attribute__((weak)) bootloader_flash_unlock(void) return err; } +/* dummy_len_plus values defined in ROM for SPI flash configuration */ #ifndef g_rom_spiflash_dummy_len_plus // ESP32-C3 uses a macro to access ROM data here extern uint8_t g_rom_spiflash_dummy_len_plus[]; #endif -uint32_t IRAM_ATTR bootloader_execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len) +IRAM_ATTR static uint32_t bootloader_flash_execute_command_common( + uint8_t command, + uint32_t addr_len, uint32_t address, + uint8_t dummy_len, + uint8_t mosi_len, uint32_t mosi_data, + uint8_t miso_len) { + assert(mosi_len <= 32); + assert(miso_len <= 32); uint32_t old_ctrl_reg = SPIFLASH.ctrl.val; + uint32_t old_user_reg = SPIFLASH.user.val; + uint32_t old_user1_reg = SPIFLASH.user1.val; #if CONFIG_IDF_TARGET_ESP32 SPIFLASH.ctrl.val = SPI_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode #else SPIFLASH.ctrl.val = SPI_MEM_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode #endif - SPIFLASH.user.usr_dummy = 0; - SPIFLASH.user.usr_addr = 0; + //command phase SPIFLASH.user.usr_command = 1; SPIFLASH.user2.usr_command_bitlen = 7; - SPIFLASH.user2.usr_command_value = command; - SPIFLASH.user.usr_miso = miso_len > 0; + //addr phase + SPIFLASH.user.usr_addr = addr_len > 0; + SPIFLASH.user1.usr_addr_bitlen = addr_len - 1; #if CONFIG_IDF_TARGET_ESP32 - SPIFLASH.miso_dlen.usr_miso_dbitlen = miso_len ? (miso_len - 1) : 0; + SPIFLASH.addr = (addr_len > 0)? (address << (32-addr_len)) : 0; #else - SPIFLASH.miso_dlen.usr_miso_bit_len = miso_len ? (miso_len - 1) : 0; + SPIFLASH.addr = address; #endif + //dummy phase + if (miso_len > 0) { + uint32_t total_dummy = dummy_len + g_rom_spiflash_dummy_len_plus[1]; + SPIFLASH.user.usr_dummy = total_dummy > 0; + SPIFLASH.user1.usr_dummy_cyclelen = total_dummy - 1; + } else { + SPIFLASH.user.usr_dummy = 0; + SPIFLASH.user1.usr_dummy_cyclelen = 0; + } + //output data SPIFLASH.user.usr_mosi = mosi_len > 0; #if CONFIG_IDF_TARGET_ESP32 SPIFLASH.mosi_dlen.usr_mosi_dbitlen = mosi_len ? (mosi_len - 1) : 0; @@ -593,24 +614,52 @@ uint32_t IRAM_ATTR bootloader_execute_flash_command(uint8_t command, uint32_t mo SPIFLASH.mosi_dlen.usr_mosi_bit_len = mosi_len ? (mosi_len - 1) : 0; #endif SPIFLASH.data_buf[0] = mosi_data; - - if (g_rom_spiflash_dummy_len_plus[1]) { - /* When flash pins are mapped via GPIO matrix, need a dummy cycle before reading via MISO */ - if (miso_len > 0) { - SPIFLASH.user.usr_dummy = 1; - SPIFLASH.user1.usr_dummy_cyclelen = g_rom_spiflash_dummy_len_plus[1] - 1; - } else { - SPIFLASH.user.usr_dummy = 0; - SPIFLASH.user1.usr_dummy_cyclelen = 0; - } - } + //input data + SPIFLASH.user.usr_miso = miso_len > 0; +#if CONFIG_IDF_TARGET_ESP32 + SPIFLASH.miso_dlen.usr_miso_dbitlen = miso_len ? (miso_len - 1) : 0; +#else + SPIFLASH.miso_dlen.usr_miso_bit_len = miso_len ? (miso_len - 1) : 0; +#endif SPIFLASH.cmd.usr = 1; while (SPIFLASH.cmd.usr != 0) { } - SPIFLASH.ctrl.val = old_ctrl_reg; - return SPIFLASH.data_buf[0]; + SPIFLASH.user.val = old_user_reg; + SPIFLASH.user1.val = old_user1_reg; + + uint32_t ret = SPIFLASH.data_buf[0]; + if (miso_len < 32) { + //set unused bits to 0 + ret &= ~(UINT32_MAX << miso_len); + } + return ret; +} + +uint32_t IRAM_ATTR bootloader_execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len) +{ + const uint8_t addr_len = 0; + const uint8_t address = 0; + const uint8_t dummy_len = 0; + + return bootloader_flash_execute_command_common(command, addr_len, address, + dummy_len, mosi_len, mosi_data, miso_len); +} + +// cmd(0x5A) + 24bit address + 8 cycles dummy +uint32_t IRAM_ATTR bootloader_flash_read_sfdp(uint32_t sfdp_addr, unsigned int miso_byte_num) +{ + assert(miso_byte_num <= 4); + const uint8_t command = CMD_RDSFDP; + const uint8_t addr_len = 24; + const uint8_t dummy_len = 8; + const uint8_t mosi_len = 0; + const uint32_t mosi_data = 0; + const uint8_t miso_len = miso_byte_num * 8; + + return bootloader_flash_execute_command_common(command, addr_len, sfdp_addr, + dummy_len, mosi_len, mosi_data, miso_len); } void bootloader_enable_wp(void) @@ -618,6 +667,13 @@ void bootloader_enable_wp(void) bootloader_execute_flash_command(CMD_WRDI, 0, 0, 0); /* Exit OTP mode */ } +uint32_t IRAM_ATTR bootloader_read_flash_id(void) +{ + uint32_t id = bootloader_execute_flash_command(CMD_RDID, 0, 0, 24); + id = ((id & 0xff) << 16) | ((id >> 16) & 0xff) | (id & 0xff00); + return id; +} + #if SOC_CACHE_SUPPORT_WRAP esp_err_t bootloader_flash_wrap_set(spi_flash_wrap_mode_t mode) { @@ -649,3 +705,104 @@ esp_err_t bootloader_flash_wrap_set(spi_flash_wrap_mode_t mode) return ESP_OK; } #endif //SOC_CACHE_SUPPORT_WRAP + +/******************************************************************************* + * XMC startup flow + ******************************************************************************/ + +#define XMC_SUPPORT CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT +#define XMC_VENDOR_ID 0x20 + +#if BOOTLOADER_BUILD +#define BOOTLOADER_FLASH_LOG(level, ...) ESP_LOG##level(TAG, ##__VA_ARGS__) +#else +static DRAM_ATTR char bootloader_flash_tag[] = "bootloader_flash"; +#define BOOTLOADER_FLASH_LOG(level, ...) ESP_DRAM_LOG##level(bootloader_flash_tag, ##__VA_ARGS__) +#endif + +#if XMC_SUPPORT +//strictly check the model +static IRAM_ATTR bool is_xmc_chip_strict(uint32_t rdid) +{ + uint32_t vendor_id = BYTESHIFT(rdid, 2); + uint32_t mfid = BYTESHIFT(rdid, 1); + uint32_t cpid = BYTESHIFT(rdid, 0); + + if (vendor_id != XMC_VENDOR_ID) { + return false; + } + + bool matched = false; + if (mfid == 0x40) { + if (cpid >= 0x13 && cpid <= 0x20) { + matched = true; + } + } else if (mfid == 0x41) { + if (cpid >= 0x17 && cpid <= 0x20) { + matched = true; + } + } else if (mfid == 0x50) { + if (cpid >= 0x15 && cpid <= 0x16) { + matched = true; + } + } + return matched; +} + +esp_err_t IRAM_ATTR bootloader_flash_xmc_startup(void) +{ + // If the RDID value is a valid XMC one, may skip the flow + const bool fast_check = true; + if (fast_check && is_xmc_chip_strict(g_rom_flashchip.device_id)) { + BOOTLOADER_FLASH_LOG(D, "XMC chip detected by RDID (%08X), skip.", g_rom_flashchip.device_id); + return ESP_OK; + } + + // 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) { + BOOTLOADER_FLASH_LOG(D, "non-XMC chip detected by SFDP Read (%02X), skip.", mf_id); + return ESP_OK; + } + + BOOTLOADER_FLASH_LOG(I, "XM25QHxxC startup flow"); + // Enter DPD + bootloader_execute_flash_command(0xB9, 0, 0, 0); + // Enter UDPD + bootloader_execute_flash_command(0x79, 0, 0, 0); + // Exit UDPD + bootloader_execute_flash_command(0xFF, 0, 0, 0); + // Delay tXUDPD + esp_rom_delay_us(2000); + // Release Power-down + bootloader_execute_flash_command(0xAB, 0, 0, 0); + esp_rom_delay_us(20); + // Read flash ID and check again + g_rom_flashchip.device_id = bootloader_read_flash_id(); + if (!is_xmc_chip_strict(g_rom_flashchip.device_id)) { + BOOTLOADER_FLASH_LOG(E, "XMC flash startup fail"); + return ESP_FAIL; + } + + return ESP_OK; +} + +#else +//only compare the vendor id +static IRAM_ATTR bool is_xmc_chip(uint32_t rdid) +{ + uint32_t vendor_id = (rdid >> 16) & 0xFF; + return (vendor_id == XMC_VENDOR_ID); +} + +esp_err_t IRAM_ATTR bootloader_flash_xmc_startup(void) +{ + if (is_xmc_chip(g_rom_flashchip.device_id)) { + BOOTLOADER_FLASH_LOG(E, "XMC chip detected (%08X) while support disabled.", g_rom_flashchip.device_id); + return ESP_FAIL; + } + return ESP_OK; +} + +#endif //XMC_SUPPORT diff --git a/components/bootloader_support/src/bootloader_flash_config_esp32s3.c b/components/bootloader_support/src/bootloader_flash_config_esp32s3.c index 6266a74e8c..357de775a5 100644 --- a/components/bootloader_support/src/bootloader_flash_config_esp32s3.c +++ b/components/bootloader_support/src/bootloader_flash_config_esp32s3.c @@ -33,18 +33,18 @@ void bootloader_flash_update_id() void IRAM_ATTR bootloader_flash_cs_timing_config() { - // SPI0/1 share the cs_hold / cs_setup, cd_hold_time / cd_setup_time, cs_hold_delay registers for FLASH/PSRAM, so we only need to set SPI0 related registers here + //SPI0/1 share the cs_hold / cs_setup, cd_hold_time / cd_setup_time, cs_hold_delay registers for FLASH, so we only need to set SPI0 related registers here +#if CONFIG_ESPTOOLPY_OCT_FLASH SET_PERI_REG_MASK(SPI_MEM_USER_REG(0), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M); SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_HOLD_TIME_V, FLASH_CS_HOLD_TIME, SPI_MEM_CS_HOLD_TIME_S); SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_SETUP_TIME_V, FLASH_CS_SETUP_TIME, SPI_MEM_CS_SETUP_TIME_S); - - SET_PERI_REG_MASK(SPI_MEM_SPI_SMEM_AC_REG(0), SPI_MEM_SPI_SMEM_CS_HOLD_M | SPI_MEM_SPI_SMEM_CS_SETUP_M); - SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_AC_REG(0), SPI_MEM_SPI_SMEM_CS_HOLD_TIME_V, FLASH_CS_HOLD_TIME, SPI_MEM_SPI_SMEM_CS_HOLD_TIME_S); - SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_AC_REG(0), SPI_MEM_SPI_SMEM_CS_SETUP_TIME_V, FLASH_CS_SETUP_TIME, SPI_MEM_SPI_SMEM_CS_SETUP_TIME_S); - - // cs high time + //CS high time SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_HOLD_DELAY_V, FLASH_CS_HOLD_DELAY, SPI_MEM_CS_HOLD_DELAY_S); - SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_AC_REG(0), SPI_MEM_SPI_SMEM_CS_HOLD_DELAY_V, FLASH_CS_HOLD_DELAY, SPI_MEM_SPI_SMEM_CS_HOLD_DELAY_S); +#else + SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_HOLD_TIME_V, 0, SPI_MEM_CS_HOLD_TIME_S); + SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_SETUP_TIME_V, 0, SPI_MEM_CS_SETUP_TIME_S); + SET_PERI_REG_MASK(SPI_MEM_USER_REG(0), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M); +#endif } void IRAM_ATTR bootloader_flash_clock_config(const esp_image_header_t *pfhdr) diff --git a/components/bootloader_support/src/bootloader_utility.c b/components/bootloader_support/src/bootloader_utility.c index dddf93f3a8..8533f2b3ce 100644 --- a/components/bootloader_support/src/bootloader_utility.c +++ b/components/bootloader_support/src/bootloader_utility.c @@ -76,6 +76,7 @@ #include "bootloader_utility.h" #include "bootloader_sha.h" #include "bootloader_console.h" +#include "bootloader_soc.h" #include "esp_efuse.h" static const char *TAG = "boot"; @@ -636,6 +637,12 @@ static void load_image(const esp_image_metadata_t *image_data) ESP_LOGI(TAG, "Disabling RNG early entropy source..."); bootloader_random_disable(); + /* Disable glitch reset after all the security checks are completed. + * Glitch detection can be falsely triggered by EMI interference (high RF TX power, etc) + * and to avoid such false alarms, disable it. + */ + bootloader_ana_clock_glitch_reset_config(false); + // copy loaded segments to RAM, set up caches for mapped segments, and start application unpack_load_app(image_data); } diff --git a/components/bootloader_support/src/esp32/bootloader_esp32.c b/components/bootloader_support/src/esp32/bootloader_esp32.c index f74d114006..358e398fe5 100644 --- a/components/bootloader_support/src/esp32/bootloader_esp32.c +++ b/components/bootloader_support/src/esp32/bootloader_esp32.c @@ -387,6 +387,11 @@ esp_err_t bootloader_init(void) bootloader_print_banner(); // update flash ID bootloader_flash_update_id(); + // Check and run XMC startup flow + if ((ret = bootloader_flash_xmc_startup()) != ESP_OK) { + ESP_LOGE(TAG, "failed when running XMC startup flow, reboot!"); + goto err; + } // read bootloader header if ((ret = bootloader_read_bootloader_header()) != ESP_OK) { goto err; diff --git a/components/bootloader_support/src/esp32/bootloader_soc.c b/components/bootloader_support/src/esp32/bootloader_soc.c new file mode 100644 index 0000000000..242a575508 --- /dev/null +++ b/components/bootloader_support/src/esp32/bootloader_soc.c @@ -0,0 +1,21 @@ +/* + * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +void bootloader_ana_super_wdt_reset_config(bool enable) +{ + (void)enable; +} + +void bootloader_ana_bod_reset_config(bool enable) +{ + (void)enable; +} + +void bootloader_ana_clock_glitch_reset_config(bool enable) +{ + (void)enable; +} diff --git a/components/bootloader_support/src/esp32c3/bootloader_esp32c3.c b/components/bootloader_support/src/esp32c3/bootloader_esp32c3.c index 7f033c0560..608654e091 100644 --- a/components/bootloader_support/src/esp32c3/bootloader_esp32c3.c +++ b/components/bootloader_support/src/esp32c3/bootloader_esp32c3.c @@ -36,6 +36,7 @@ #include "regi2c_ctrl.h" #include "bootloader_console.h" #include "bootloader_flash_priv.h" +#include "bootloader_soc.h" #include "esp_efuse.h" static const char *TAG = "boot.esp32c3"; @@ -263,7 +264,7 @@ static inline void bootloader_hardware_init(void) } } -static inline void bootloader_glitch_reset_disable(void) +static inline void bootloader_ana_reset_config(void) { /* For origin chip & ECO1: only support swt reset; @@ -271,10 +272,27 @@ static inline void bootloader_glitch_reset_disable(void) For ECO3: fix clock glitch reset bug, support all reset, include: swt & brownout & clock glitch reset. */ uint8_t chip_version = bootloader_common_get_chip_revision(); - if (chip_version < 2) { - REG_SET_FIELD(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SEL, RTC_CNTL_FIB_SUPER_WDT_RST); - } else if (chip_version == 2) { - REG_SET_FIELD(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SEL, RTC_CNTL_FIB_SUPER_WDT_RST | RTC_CNTL_FIB_BOR_RST); + switch (chip_version) { + case 0: + case 1: + //Enable WDT reset. Disable BOR and GLITCH reset + bootloader_ana_super_wdt_reset_config(true); + bootloader_ana_bod_reset_config(false); + bootloader_ana_clock_glitch_reset_config(false); + break; + case 2: + //Enable WDT and BOR reset. Disable GLITCH reset + bootloader_ana_super_wdt_reset_config(true); + bootloader_ana_bod_reset_config(true); + bootloader_ana_clock_glitch_reset_config(false); + break; + case 3: + default: + //Enable WDT, BOR, and GLITCH reset + bootloader_ana_super_wdt_reset_config(true); + bootloader_ana_bod_reset_config(true); + bootloader_ana_clock_glitch_reset_config(true); + break; } } @@ -283,7 +301,7 @@ esp_err_t bootloader_init(void) esp_err_t ret = ESP_OK; bootloader_hardware_init(); - bootloader_glitch_reset_disable(); + bootloader_ana_reset_config(); bootloader_super_wdt_auto_feed(); // protect memory region bootloader_init_mem(); @@ -309,6 +327,11 @@ esp_err_t bootloader_init(void) bootloader_print_banner(); // update flash ID bootloader_flash_update_id(); + // Check and run XMC startup flow + if ((ret = bootloader_flash_xmc_startup()) != ESP_OK) { + ESP_LOGE(TAG, "failed when running XMC startup flow, reboot!"); + goto err; + } // read bootloader header if ((ret = bootloader_read_bootloader_header()) != ESP_OK) { goto err; diff --git a/components/bootloader_support/src/esp32c3/bootloader_soc.c b/components/bootloader_support/src/esp32c3/bootloader_soc.c new file mode 100644 index 0000000000..7104528a58 --- /dev/null +++ b/components/bootloader_support/src/esp32c3/bootloader_soc.c @@ -0,0 +1,41 @@ +/* + * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "soc/soc.h" +#include "soc/rtc_cntl_reg.h" + +void bootloader_ana_super_wdt_reset_config(bool enable) +{ + REG_CLR_BIT(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SUPER_WDT_RST); + + if (enable) { + REG_SET_BIT(RTC_CNTL_SWD_CONF_REG, RTC_CNTL_SWD_BYPASS_RST); + } else { + REG_CLR_BIT(RTC_CNTL_SWD_CONF_REG, RTC_CNTL_SWD_BYPASS_RST); + } +} + +void bootloader_ana_bod_reset_config(bool enable) +{ + REG_CLR_BIT(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_BOR_RST); + + if (enable) { + REG_SET_BIT(RTC_CNTL_BROWN_OUT_REG, RTC_CNTL_BROWN_OUT_ANA_RST_EN); + } else { + REG_CLR_BIT(RTC_CNTL_BROWN_OUT_REG, RTC_CNTL_BROWN_OUT_ANA_RST_EN); + } +} + +void bootloader_ana_clock_glitch_reset_config(bool enable) +{ + REG_CLR_BIT(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_GLITCH_RST); + + if (enable) { + REG_SET_BIT(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_GLITCH_RST_EN); + } else { + REG_CLR_BIT(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_GLITCH_RST_EN); + } +} diff --git a/components/bootloader_support/src/esp32c3/flash_encryption_secure_features.c b/components/bootloader_support/src/esp32c3/flash_encryption_secure_features.c index 0bbadf286c..d00f2d9e15 100644 --- a/components/bootloader_support/src/esp32c3/flash_encryption_secure_features.c +++ b/components/bootloader_support/src/esp32c3/flash_encryption_secure_features.c @@ -40,5 +40,11 @@ esp_err_t esp_flash_encryption_enable_secure_features(void) esp_efuse_write_field_bit(ESP_EFUSE_DIS_LEGACY_SPI_BOOT); +#if defined(CONFIG_SECURE_BOOT_V2_ENABLED) && !defined(CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS) + // This bit is set when enabling Secure Boot V2, but we can't enable it until this later point in the first boot + // otherwise the Flash Encryption key cannot be read protected + esp_efuse_write_field_bit(ESP_EFUSE_WR_DIS_RD_DIS); +#endif + return ESP_OK; } diff --git a/components/bootloader_support/src/esp32c3/secure_boot_secure_features.c b/components/bootloader_support/src/esp32c3/secure_boot_secure_features.c index 647d2fd988..30098bed32 100644 --- a/components/bootloader_support/src/esp32c3/secure_boot_secure_features.c +++ b/components/bootloader_support/src/esp32c3/secure_boot_secure_features.c @@ -40,5 +40,20 @@ esp_err_t esp_secure_boot_enable_secure_features(void) esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_EN); +#ifndef CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS + bool rd_dis_now = true; +#ifdef CONFIG_SECURE_FLASH_ENC_ENABLED + /* If flash encryption is not enabled yet then don't read-disable efuses yet, do it later in the boot + when Flash Encryption is being enabled */ + rd_dis_now = esp_flash_encryption_enabled(); +#endif + if (rd_dis_now) { + ESP_LOGI(TAG, "Prevent read disabling of additional efuses..."); + esp_efuse_write_field_bit(ESP_EFUSE_WR_DIS_RD_DIS); + } +#else + ESP_LOGW(TAG, "Allowing read disabling of additional efuses - SECURITY COMPROMISED"); +#endif + return ESP_OK; } diff --git a/components/bootloader_support/src/esp32h2/bootloader_esp32h2.c b/components/bootloader_support/src/esp32h2/bootloader_esp32h2.c index d763b685da..7ff27dd693 100644 --- a/components/bootloader_support/src/esp32h2/bootloader_esp32h2.c +++ b/components/bootloader_support/src/esp32h2/bootloader_esp32h2.c @@ -36,6 +36,7 @@ #include "regi2c_ctrl.h" #include "bootloader_console.h" #include "bootloader_flash_priv.h" +#include "bootloader_soc.h" static const char *TAG = "boot.esp32h2"; @@ -254,27 +255,15 @@ static void bootloader_super_wdt_auto_feed(void) static inline void bootloader_hardware_init(void) { - // This check is always included in the bootloader so it can - // print the minimum revision error message later in the boot - if (bootloader_common_get_chip_revision() < 3) { - REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_FORCE_XPD_IPH, 1); - REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_DREG_1P1_PVT, 12); - } + } -static inline void bootloader_glitch_reset_disable(void) +static inline void bootloader_ana_reset_config(void) { - /* - For origin chip & ECO1: only support swt reset; - For ECO2: fix brownout reset bug, support swt & brownout reset; - For ECO3: fix clock glitch reset bug, support all reset, include: swt & brownout & clock glitch reset. - */ - uint8_t chip_version = bootloader_common_get_chip_revision(); - if (chip_version < 2) { - REG_SET_FIELD(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SEL, RTC_CNTL_FIB_SUPER_WDT_RST); - } else if (chip_version == 2) { - REG_SET_FIELD(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SEL, RTC_CNTL_FIB_SUPER_WDT_RST | RTC_CNTL_FIB_BOR_RST); - } + //Enable WDT, BOR, and GLITCH reset + bootloader_ana_super_wdt_reset_config(true); + bootloader_ana_bod_reset_config(true); + bootloader_ana_clock_glitch_reset_config(true); } esp_err_t bootloader_init(void) @@ -282,7 +271,7 @@ esp_err_t bootloader_init(void) esp_err_t ret = ESP_OK; bootloader_hardware_init(); - bootloader_glitch_reset_disable(); + bootloader_ana_reset_config(); bootloader_super_wdt_auto_feed(); // protect memory region bootloader_init_mem(); @@ -301,6 +290,11 @@ esp_err_t bootloader_init(void) bootloader_print_banner(); // update flash ID bootloader_flash_update_id(); + // Check and run XMC startup flow + if ((ret = bootloader_flash_xmc_startup()) != ESP_OK) { + ESP_LOGE(TAG, "failed when running XMC startup flow, reboot!"); + goto err; + } // read bootloader header if ((ret = bootloader_read_bootloader_header()) != ESP_OK) { goto err; diff --git a/components/bootloader_support/src/esp32h2/bootloader_soc.c b/components/bootloader_support/src/esp32h2/bootloader_soc.c new file mode 100644 index 0000000000..7104528a58 --- /dev/null +++ b/components/bootloader_support/src/esp32h2/bootloader_soc.c @@ -0,0 +1,41 @@ +/* + * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "soc/soc.h" +#include "soc/rtc_cntl_reg.h" + +void bootloader_ana_super_wdt_reset_config(bool enable) +{ + REG_CLR_BIT(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SUPER_WDT_RST); + + if (enable) { + REG_SET_BIT(RTC_CNTL_SWD_CONF_REG, RTC_CNTL_SWD_BYPASS_RST); + } else { + REG_CLR_BIT(RTC_CNTL_SWD_CONF_REG, RTC_CNTL_SWD_BYPASS_RST); + } +} + +void bootloader_ana_bod_reset_config(bool enable) +{ + REG_CLR_BIT(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_BOR_RST); + + if (enable) { + REG_SET_BIT(RTC_CNTL_BROWN_OUT_REG, RTC_CNTL_BROWN_OUT_ANA_RST_EN); + } else { + REG_CLR_BIT(RTC_CNTL_BROWN_OUT_REG, RTC_CNTL_BROWN_OUT_ANA_RST_EN); + } +} + +void bootloader_ana_clock_glitch_reset_config(bool enable) +{ + REG_CLR_BIT(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_GLITCH_RST); + + if (enable) { + REG_SET_BIT(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_GLITCH_RST_EN); + } else { + REG_CLR_BIT(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_GLITCH_RST_EN); + } +} diff --git a/components/bootloader_support/src/esp32s2/bootloader_esp32s2.c b/components/bootloader_support/src/esp32s2/bootloader_esp32s2.c index 032221b2b1..177ce835c1 100644 --- a/components/bootloader_support/src/esp32s2/bootloader_esp32s2.c +++ b/components/bootloader_support/src/esp32s2/bootloader_esp32s2.c @@ -307,6 +307,11 @@ esp_err_t bootloader_init(void) bootloader_print_banner(); // update flash ID bootloader_flash_update_id(); + // Check and run XMC startup flow + if ((ret = bootloader_flash_xmc_startup()) != ESP_OK) { + ESP_LOGE(TAG, "failed when running XMC startup flow, reboot!"); + goto err; + } // read bootloader header if ((ret = bootloader_read_bootloader_header()) != ESP_OK) { goto err; diff --git a/components/bootloader_support/src/esp32s2/bootloader_soc.c b/components/bootloader_support/src/esp32s2/bootloader_soc.c new file mode 100644 index 0000000000..242a575508 --- /dev/null +++ b/components/bootloader_support/src/esp32s2/bootloader_soc.c @@ -0,0 +1,21 @@ +/* + * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +void bootloader_ana_super_wdt_reset_config(bool enable) +{ + (void)enable; +} + +void bootloader_ana_bod_reset_config(bool enable) +{ + (void)enable; +} + +void bootloader_ana_clock_glitch_reset_config(bool enable) +{ + (void)enable; +} diff --git a/components/bootloader_support/src/esp32s2/flash_encryption_secure_features.c b/components/bootloader_support/src/esp32s2/flash_encryption_secure_features.c index ad5182db22..3927367c3e 100644 --- a/components/bootloader_support/src/esp32s2/flash_encryption_secure_features.c +++ b/components/bootloader_support/src/esp32s2/flash_encryption_secure_features.c @@ -41,5 +41,11 @@ esp_err_t esp_flash_encryption_enable_secure_features(void) esp_efuse_write_field_bit(ESP_EFUSE_DIS_BOOT_REMAP); esp_efuse_write_field_bit(ESP_EFUSE_DIS_LEGACY_SPI_BOOT); +#if defined(CONFIG_SECURE_BOOT_V2_ENABLED) && !defined(CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS) + // This bit is set when enabling Secure Boot V2, but we can't enable it until this later point in the first boot + // otherwise the Flash Encryption key cannot be read protected + esp_efuse_write_field_bit(ESP_EFUSE_WR_DIS_RD_DIS); +#endif + return ESP_OK; } diff --git a/components/bootloader_support/src/esp32s2/secure_boot_secure_features.c b/components/bootloader_support/src/esp32s2/secure_boot_secure_features.c index 74197b45ab..418a932209 100644 --- a/components/bootloader_support/src/esp32s2/secure_boot_secure_features.c +++ b/components/bootloader_support/src/esp32s2/secure_boot_secure_features.c @@ -40,5 +40,20 @@ esp_err_t esp_secure_boot_enable_secure_features(void) esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_EN); +#ifndef CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS + bool rd_dis_now = true; +#ifdef CONFIG_SECURE_FLASH_ENC_ENABLED + /* If flash encryption is not enabled yet then don't read-disable efuses yet, do it later in the boot + when Flash Encryption is being enabled */ + rd_dis_now = esp_flash_encryption_enabled(); +#endif + if (rd_dis_now) { + ESP_LOGI(TAG, "Prevent read disabling of additional efuses..."); + esp_efuse_write_field_bit(ESP_EFUSE_WR_DIS_RD_DIS); + } +#else + ESP_LOGW(TAG, "Allowing read disabling of additional efuses - SECURITY COMPROMISED"); +#endif + return ESP_OK; } diff --git a/components/bootloader_support/src/esp32s3/bootloader_esp32s3.c b/components/bootloader_support/src/esp32s3/bootloader_esp32s3.c index 1bb984fd21..8346b00d02 100644 --- a/components/bootloader_support/src/esp32s3/bootloader_esp32s3.c +++ b/components/bootloader_support/src/esp32s3/bootloader_esp32s3.c @@ -34,6 +34,7 @@ #include "bootloader_mem.h" #include "bootloader_console.h" #include "bootloader_flash_priv.h" +#include "bootloader_soc.h" #include "esp_efuse.h" @@ -139,7 +140,7 @@ static void print_flash_info(const esp_image_header_t *bootloader_hdr) str = "20MHz"; break; } - ESP_LOGI(TAG, "SPI Speed : %s", str); + ESP_LOGI(TAG, "Boot SPI Speed : %s", str); /* SPI mode could have been set to QIO during boot already, so test the SPI registers not the flash header */ @@ -296,9 +297,18 @@ static void bootloader_super_wdt_auto_feed(void) REG_WRITE(RTC_CNTL_SWD_WPROTECT_REG, 0); } +static inline void bootloader_ana_reset_config(void) +{ + //Enable WDT, BOR, and GLITCH reset + bootloader_ana_super_wdt_reset_config(true); + bootloader_ana_bod_reset_config(true); + bootloader_ana_clock_glitch_reset_config(true); +} + esp_err_t bootloader_init(void) { esp_err_t ret = ESP_OK; + bootloader_ana_reset_config(); bootloader_super_wdt_auto_feed(); // protect memory region bootloader_init_mem(); @@ -328,6 +338,11 @@ esp_err_t bootloader_init(void) bootloader_print_banner(); // update flash ID bootloader_flash_update_id(); + // Check and run XMC startup flow + if ((ret = bootloader_flash_xmc_startup()) != ESP_OK) { + ESP_LOGE(TAG, "failed when running XMC startup flow, reboot!"); + goto err; + } // read bootloader header if ((ret = bootloader_read_bootloader_header()) != ESP_OK) { goto err; diff --git a/components/bootloader_support/src/esp32s3/bootloader_soc.c b/components/bootloader_support/src/esp32s3/bootloader_soc.c new file mode 100644 index 0000000000..7104528a58 --- /dev/null +++ b/components/bootloader_support/src/esp32s3/bootloader_soc.c @@ -0,0 +1,41 @@ +/* + * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "soc/soc.h" +#include "soc/rtc_cntl_reg.h" + +void bootloader_ana_super_wdt_reset_config(bool enable) +{ + REG_CLR_BIT(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SUPER_WDT_RST); + + if (enable) { + REG_SET_BIT(RTC_CNTL_SWD_CONF_REG, RTC_CNTL_SWD_BYPASS_RST); + } else { + REG_CLR_BIT(RTC_CNTL_SWD_CONF_REG, RTC_CNTL_SWD_BYPASS_RST); + } +} + +void bootloader_ana_bod_reset_config(bool enable) +{ + REG_CLR_BIT(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_BOR_RST); + + if (enable) { + REG_SET_BIT(RTC_CNTL_BROWN_OUT_REG, RTC_CNTL_BROWN_OUT_ANA_RST_EN); + } else { + REG_CLR_BIT(RTC_CNTL_BROWN_OUT_REG, RTC_CNTL_BROWN_OUT_ANA_RST_EN); + } +} + +void bootloader_ana_clock_glitch_reset_config(bool enable) +{ + REG_CLR_BIT(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_GLITCH_RST); + + if (enable) { + REG_SET_BIT(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_GLITCH_RST_EN); + } else { + REG_CLR_BIT(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_GLITCH_RST_EN); + } +} diff --git a/components/bootloader_support/src/esp32s3/flash_encryption_secure_features.c b/components/bootloader_support/src/esp32s3/flash_encryption_secure_features.c index 837d0e36c9..3d932104da 100644 --- a/components/bootloader_support/src/esp32s3/flash_encryption_secure_features.c +++ b/components/bootloader_support/src/esp32s3/flash_encryption_secure_features.c @@ -41,5 +41,11 @@ esp_err_t esp_flash_encryption_enable_secure_features(void) esp_efuse_write_field_bit(ESP_EFUSE_DIS_LEGACY_SPI_BOOT); +#if defined(CONFIG_SECURE_BOOT_V2_ENABLED) && !defined(CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS) + // This bit is set when enabling Secure Boot V2, but we can't enable it until this later point in the first boot + // otherwise the Flash Encryption key cannot be read protected + esp_efuse_write_field_bit(ESP_EFUSE_WR_DIS_RD_DIS); +#endif + return ESP_OK; } diff --git a/components/bootloader_support/src/esp32s3/secure_boot_secure_features.c b/components/bootloader_support/src/esp32s3/secure_boot_secure_features.c index 7d0bf0512a..4284626a73 100644 --- a/components/bootloader_support/src/esp32s3/secure_boot_secure_features.c +++ b/components/bootloader_support/src/esp32s3/secure_boot_secure_features.c @@ -27,6 +27,7 @@ esp_err_t esp_secure_boot_enable_secure_features(void) #ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG ESP_LOGI(TAG, "Disable hardware & software JTAG..."); + esp_efuse_write_field_bit(ESP_EFUSE_DIS_USB_JTAG); esp_efuse_write_field_bit(ESP_EFUSE_HARD_DIS_JTAG); esp_efuse_write_field_cnt(ESP_EFUSE_SOFT_DIS_JTAG, ESP_EFUSE_SOFT_DIS_JTAG[0]->bit_count); #else @@ -39,5 +40,20 @@ esp_err_t esp_secure_boot_enable_secure_features(void) esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_EN); +#ifndef CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS + bool rd_dis_now = true; +#ifdef CONFIG_SECURE_FLASH_ENC_ENABLED + /* If flash encryption is not enabled yet then don't read-disable efuses yet, do it later in the boot + when Flash Encryption is being enabled */ + rd_dis_now = esp_flash_encryption_enabled(); +#endif + if (rd_dis_now) { + ESP_LOGI(TAG, "Prevent read disabling of additional efuses..."); + esp_efuse_write_field_bit(ESP_EFUSE_WR_DIS_RD_DIS); + } +#else + ESP_LOGW(TAG, "Allowing read disabling of additional efuses - SECURITY COMPROMISED"); +#endif + return ESP_OK; } diff --git a/components/bootloader_support/src/flash_qio_mode.c b/components/bootloader_support/src/flash_qio_mode.c index 83b9377f52..0447627ab9 100644 --- a/components/bootloader_support/src/flash_qio_mode.c +++ b/components/bootloader_support/src/flash_qio_mode.c @@ -105,14 +105,6 @@ static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn, The command passed here is always the on-the-wire command given to the SPI flash unit. */ -/* dummy_len_plus values defined in ROM for SPI flash configuration */ -uint32_t bootloader_read_flash_id(void) -{ - uint32_t id = bootloader_execute_flash_command(CMD_RDID, 0, 0, 24); - id = ((id & 0xff) << 16) | ((id >> 16) & 0xff) | (id & 0xff00); - return id; -} - void bootloader_enable_qio_mode(void) { uint32_t raw_flash_id; diff --git a/components/bt/CMakeLists.txt b/components/bt/CMakeLists.txt index 3ddc13758a..efacc806a1 100644 --- a/components/bt/CMakeLists.txt +++ b/components/bt/CMakeLists.txt @@ -1,6 +1,8 @@ if(CONFIG_BT_ENABLED) if(CONFIG_IDF_TARGET_ESP32) - set(srcs "controller/esp32/bt.c") + set(srcs "controller/esp32/bt.c" + "controller/esp32/hli_api.c" + "controller/esp32/hli_vectors.S") elseif(CONFIG_IDF_TARGET_ESP32C3) set(srcs "controller/esp32c3/bt.c") elseif(CONFIG_IDF_TARGET_ESP32S3) @@ -55,6 +57,7 @@ if(CONFIG_BT_ENABLED) host/bluedroid/bta/gatt/include host/bluedroid/bta/hf_ag/include host/bluedroid/bta/hf_client/include + host/bluedroid/bta/hd/include host/bluedroid/bta/hh/include host/bluedroid/bta/jv/include host/bluedroid/bta/sdp/include @@ -66,12 +69,12 @@ if(CONFIG_BT_ENABLED) host/bluedroid/external/sbc/plc/include host/bluedroid/btc/profile/esp/include host/bluedroid/btc/profile/std/a2dp/include - host/bluedroid/btc/profile/std/hid/include host/bluedroid/btc/profile/std/include host/bluedroid/btc/include host/bluedroid/stack/btm/include host/bluedroid/stack/gap/include host/bluedroid/stack/gatt/include + host/bluedroid/stack/hid/include host/bluedroid/stack/l2cap/include host/bluedroid/stack/sdp/include host/bluedroid/stack/smp/include @@ -94,6 +97,8 @@ if(CONFIG_BT_ENABLED) "host/bluedroid/api/esp_gatt_common_api.c" "host/bluedroid/api/esp_gattc_api.c" "host/bluedroid/api/esp_gatts_api.c" + "host/bluedroid/api/esp_hidd_api.c" + "host/bluedroid/api/esp_hidh_api.c" "host/bluedroid/api/esp_hf_ag_api.c" "host/bluedroid/api/esp_hf_client_api.c" "host/bluedroid/api/esp_spp_api.c" @@ -128,6 +133,9 @@ if(CONFIG_BT_ENABLED) "host/bluedroid/bta/gatt/bta_gatts_co.c" "host/bluedroid/bta/gatt/bta_gatts_main.c" "host/bluedroid/bta/gatt/bta_gatts_utils.c" + "host/bluedroid/bta/hd/bta_hd_api.c" + "host/bluedroid/bta/hd/bta_hd_act.c" + "host/bluedroid/bta/hd/bta_hd_main.c" "host/bluedroid/bta/hh/bta_hh_act.c" "host/bluedroid/bta/hh/bta_hh_api.c" "host/bluedroid/bta/hh/bta_hh_cfg.c" @@ -184,8 +192,9 @@ if(CONFIG_BT_ENABLED) "host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c" "host/bluedroid/btc/profile/std/hf_client/btc_hf_client.c" "host/bluedroid/btc/profile/std/hf_client/bta_hf_client_co.c" - "host/bluedroid/btc/profile/std/hid/hidh_api.c" - "host/bluedroid/btc/profile/std/hid/hidh_conn.c" + "host/bluedroid/btc/profile/std/hid/btc_hd.c" + "host/bluedroid/btc/profile/std/hid/btc_hh.c" + "host/bluedroid/btc/profile/std/hid/bta_hh_co.c" "host/bluedroid/btc/profile/std/gap/btc_gap_ble.c" "host/bluedroid/btc/profile/std/gap/btc_gap_bt.c" "host/bluedroid/btc/profile/std/gap/bta_gap_bt_co.c" @@ -251,6 +260,10 @@ if(CONFIG_BT_ENABLED) "host/bluedroid/stack/avrc/avrc_pars_tg.c" "host/bluedroid/stack/avrc/avrc_sdp.c" "host/bluedroid/stack/avrc/avrc_utils.c" + "host/bluedroid/stack/hid/hidd_api.c" + "host/bluedroid/stack/hid/hidd_conn.c" + "host/bluedroid/stack/hid/hidh_api.c" + "host/bluedroid/stack/hid/hidh_conn.c" "host/bluedroid/stack/btm/btm_acl.c" "host/bluedroid/stack/btm/btm_ble.c" "host/bluedroid/stack/btm/btm_ble_addr.c" @@ -597,6 +610,8 @@ if(CONFIG_BT_ENABLED) if(CONFIG_IDF_TARGET_ESP32) target_link_libraries(${COMPONENT_LIB} INTERFACE "-L${CMAKE_CURRENT_LIST_DIR}/controller/lib_esp32/esp32") target_link_libraries(${COMPONENT_LIB} PUBLIC btdm_app) + + target_link_libraries(${COMPONENT_LIB} INTERFACE "-u ld_include_hli_vectors_bt") elseif(CONFIG_IDF_TARGET_ESP32C3) target_link_libraries(${COMPONENT_LIB} INTERFACE "-L${CMAKE_CURRENT_LIST_DIR}/controller/lib_esp32c3_family/esp32c3") diff --git a/components/bt/Kconfig b/components/bt/Kconfig index ca04f51b4b..8a15de6b86 100644 --- a/components/bt/Kconfig +++ b/components/bt/Kconfig @@ -7,42 +7,16 @@ menu "Bluetooth" help Select this option to enable Bluetooth and show the submenu with Bluetooth configuration choices. - config BT_CTRL_ESP32 - bool - depends on BT_ENABLED && IDF_TARGET_ESP32 - default y - - config BT_CTRL_ESP32C3 - bool - depends on BT_ENABLED && IDF_TARGET_ESP32C3 - default y - config BT_CTRL_ESP32S3 - bool - depends on BT_ENABLED && IDF_TARGET_ESP32S3 - default y - config BT_SOC_SUPPORT_5_0 bool depends on BT_ENABLED && (IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3) default y if BT_ENABLED && (IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3) default n - menu "Bluetooth controller(ESP32 Dual Mode Bluetooth)" - visible if BT_CTRL_ESP32 + menu "Bluetooth controller" + depends on BT_ENABLED - source "$IDF_PATH/components/bt/controller/esp32/Kconfig.in" - endmenu - - menu "Bluetooth controller(ESP32C3 Bluetooth Low Energy)" - visible if BT_CTRL_ESP32C3 - - source "$IDF_PATH/components/bt/controller/esp32c3/Kconfig.in" - endmenu - - menu "Bluetooth controller(ESP32S3 Bluetooth Low Energy)" - visible if BT_CTRL_ESP32S3 - - source "$IDF_PATH/components/bt/controller/esp32s3/Kconfig.in" + source "$IDF_PATH/components/bt/controller/$IDF_TARGET/Kconfig.in" endmenu choice BT_HOST @@ -73,12 +47,12 @@ menu "Bluetooth" endchoice menu "Bluedroid Options" - visible if BT_BLUEDROID_ENABLED + depends on BT_BLUEDROID_ENABLED source "$IDF_PATH/components/bt/host/bluedroid/Kconfig.in" endmenu menu "NimBLE Options" - visible if BT_NIMBLE_ENABLED + depends on BT_NIMBLE_ENABLED source "$IDF_PATH/components/bt/host/nimble/Kconfig.in" endmenu diff --git a/components/bt/common/btc/core/btc_task.c b/components/bt/common/btc/core/btc_task.c index 9579446817..9cc311c52c 100644 --- a/components/bt/common/btc/core/btc_task.c +++ b/components/bt/common/btc/core/btc_task.c @@ -53,6 +53,12 @@ #if BTC_HF_CLIENT_INCLUDED #include "btc_hf_client.h" #endif /* #if BTC_HF_CLIENT_INCLUDED */ +#if BTC_HD_INCLUDED == TRUE +#include "btc_hd.h" +#endif /* BTC_HD_INCLUDED */ +#if BTC_HH_INCLUDED == TRUE +#include "btc_hh.h" +#endif /* BTC_HH_INCLUDED */ #endif /* #if CLASSIC_BT_INCLUDED */ #endif @@ -120,6 +126,12 @@ static const btc_func_t profile_tab[BTC_PID_NUM] = { #if BTC_HF_CLIENT_INCLUDED [BTC_PID_HF_CLIENT] = {btc_hf_client_call_handler, btc_hf_client_cb_handler}, #endif /* #if BTC_HF_CLIENT_INCLUDED */ +#if BTC_HD_INCLUDED + [BTC_PID_HD] = {btc_hd_call_handler, btc_hd_cb_handler }, +#endif +#if BTC_HH_INCLUDED + [BTC_PID_HH] = {btc_hh_call_handler, btc_hh_cb_handler }, +#endif #endif /* #if CLASSIC_BT_INCLUDED */ #endif #if CONFIG_BLE_MESH diff --git a/components/bt/common/btc/include/btc/btc_task.h b/components/bt/common/btc/include/btc/btc_task.h index cc9382590a..f8da6ffd42 100644 --- a/components/bt/common/btc/include/btc/btc_task.h +++ b/components/bt/common/btc/include/btc/btc_task.h @@ -65,6 +65,8 @@ typedef enum { BTC_PID_AVRC_CT, BTC_PID_AVRC_TG, BTC_PID_SPP, + BTC_PID_HD, + BTC_PID_HH, #if (BTC_HF_INCLUDED == TRUE) BTC_PID_HF, #endif /* BTC_HF_INCLUDED */ @@ -99,6 +101,10 @@ typedef struct { typedef void (* btc_arg_deep_copy_t)(btc_msg_t *msg, void *dst, void *src); +#ifdef __cplusplus +extern "C" { +#endif + /** * transfer an message to another module in the different task. * @param msg message @@ -124,4 +130,8 @@ void btc_deinit(void); bool btc_check_queue_is_congest(void); int get_btc_work_queue_size(void); +#ifdef __cplusplus +} +#endif + #endif /* __BTC_TASK_H__ */ diff --git a/components/bt/common/osi/alarm.c b/components/bt/common/osi/alarm.c index c8bfc83ab7..736d67fd08 100644 --- a/components/bt/common/osi/alarm.c +++ b/components/bt/common/osi/alarm.c @@ -318,3 +318,14 @@ uint32_t osi_time_get_os_boottime_ms(void) { return (uint32_t)(esp_timer_get_time() / 1000); } + +bool osi_alarm_is_active(osi_alarm_t *alarm) +{ + assert(alarm != NULL); + + if (alarm->alarm_hdl != NULL) { + return esp_timer_is_active(alarm->alarm_hdl); + } + + return false; +} diff --git a/components/bt/common/osi/include/osi/alarm.h b/components/bt/common/osi/include/osi/alarm.h index a1d3fa8961..fe8344cdb9 100644 --- a/components/bt/common/osi/include/osi/alarm.h +++ b/components/bt/common/osi/include/osi/alarm.h @@ -77,4 +77,8 @@ period_ms_t osi_alarm_get_remaining_ms(const osi_alarm_t *alarm); uint32_t osi_time_get_os_boottime_ms(void); +// This function returns whether the given |alarm| is active or not. +// Return true if active, false otherwise. +bool osi_alarm_is_active(osi_alarm_t *alarm); + #endif /*_ALARM_H_*/ diff --git a/components/bt/component.mk b/components/bt/component.mk index 8ec9205adf..bd8d52371a 100644 --- a/components/bt/component.mk +++ b/components/bt/component.mk @@ -10,6 +10,7 @@ COMPONENT_ADD_INCLUDEDIRS := include LIBS := btdm_app COMPONENT_ADD_LDFLAGS := -lbt -L $(COMPONENT_PATH)/controller/lib_esp32/esp32 \ + -u ld_include_hli_vectors_bt \ $(addprefix -l,$(LIBS)) # re-link program if BT binary libs change @@ -46,6 +47,7 @@ COMPONENT_PRIV_INCLUDEDIRS += host/bluedroid/bta/include \ host/bluedroid/bta/hf_client/include \ host/bluedroid/bta/dm/include \ host/bluedroid/bta/gatt/include \ + host/bluedroid/bta/hd/include \ host/bluedroid/bta/hh/include \ host/bluedroid/bta/jv/include \ host/bluedroid/bta/sdp/include \ @@ -70,6 +72,7 @@ COMPONENT_PRIV_INCLUDEDIRS += host/bluedroid/bta/include \ host/bluedroid/stack/gap/include \ host/bluedroid/stack/gatt/include \ host/bluedroid/stack/hcic/include \ + host/bluedroid/stack/hid/include \ host/bluedroid/stack/l2cap/include \ host/bluedroid/stack/sdp/include \ host/bluedroid/stack/smp/include \ @@ -86,6 +89,7 @@ COMPONENT_ADD_INCLUDEDIRS += host/bluedroid/api/include/api \ COMPONENT_SRCDIRS += host/bluedroid/bta/dm \ host/bluedroid/bta/gatt \ + host/bluedroid/bta/hd \ host/bluedroid/bta/hh \ host/bluedroid/bta/sdp \ host/bluedroid/bta/av \ @@ -118,6 +122,7 @@ COMPONENT_SRCDIRS += host/bluedroid/bta/dm \ host/bluedroid/stack/gap \ host/bluedroid/stack/gatt \ host/bluedroid/stack/hcic \ + host/bluedroid/stack/hid \ host/bluedroid/stack/include \ host/bluedroid/stack/l2cap \ host/bluedroid/stack/sdp \ diff --git a/components/bt/controller/esp32/Kconfig.in b/components/bt/controller/esp32/Kconfig.in index 70a710c9b7..cc71f6563b 100644 --- a/components/bt/controller/esp32/Kconfig.in +++ b/components/bt/controller/esp32/Kconfig.in @@ -1,6 +1,5 @@ choice BTDM_CTRL_MODE prompt "Bluetooth controller mode (BR/EDR/BLE/DUALMODE)" - depends on BT_CTRL_ESP32 help Specify the bluetooth controller mode (BR/EDR, BLE or dual mode). @@ -152,7 +151,7 @@ config BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF choice BTDM_CTRL_PINNED_TO_CORE_CHOICE prompt "The cpu core which bluetooth controller run" - depends on BT_CTRL_ESP32 && !FREERTOS_UNICORE + depends on !FREERTOS_UNICORE help Specify the cpu core to run bluetooth controller. Can not specify no-affinity. @@ -172,7 +171,6 @@ config BTDM_CTRL_PINNED_TO_CORE choice BTDM_CTRL_HCI_MODE_CHOICE prompt "HCI mode" - depends on BT_CTRL_ESP32 help Speicify HCI mode as VHCI or UART(H4) @@ -210,11 +208,8 @@ menu "HCI UART(H4) Options" endmenu menu "MODEM SLEEP Options" - visible if BT_CTRL_ESP32 - config BTDM_CTRL_MODEM_SLEEP bool "Bluetooth modem sleep" - depends on BT_CTRL_ESP32 default y help Enable/disable bluetooth controller low power mode. @@ -415,3 +410,16 @@ config BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD of ADV packets lost in the controller reaches this threshold. It is better to set a larger value. 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. + + +config BTDM_RESERVE_DRAM + hex + default 0xdb5c if BT_ENABLED + default 0 + +config BTDM_CTRL_HLI + bool "High level interrupt" + depends on BT_ENABLED + default y + help + Using Level 4 interrupt for Bluetooth. diff --git a/components/bt/controller/esp32/bt.c b/components/bt/controller/esp32/bt.c index b046109d1a..5bf5d8a318 100644 --- a/components/bt/controller/esp32/bt.c +++ b/components/bt/controller/esp32/bt.c @@ -40,6 +40,7 @@ #include "driver/periph_ctrl.h" #include "soc/rtc.h" #include "soc/soc_memory_layout.h" +#include "soc/dport_reg.h" #include "esp32/clk.h" #include "esp_coexist_internal.h" #if !CONFIG_FREERTOS_UNICORE @@ -47,6 +48,7 @@ #endif #include "esp_rom_sys.h" +#include "hli_api.h" #if CONFIG_BT_ENABLED @@ -54,6 +56,7 @@ ************************************************************************ */ +#define UNUSED(x) (void)(x) #define BTDM_LOG_TAG "BTDM_INIT" #define BTDM_INIT_PERIOD (5000) /* ms */ @@ -92,12 +95,12 @@ do{\ } while(0) #define OSI_FUNCS_TIME_BLOCKING 0xffffffff -#define OSI_VERSION 0x00010002 +#define OSI_VERSION 0x00010003 #define OSI_MAGIC_VALUE 0xFADEBEAD /* SPIRAM Configuration */ #if CONFIG_SPIRAM_USE_MALLOC -#define BTDM_MAX_QUEUE_NUM (5) +#define BTDM_MAX_QUEUE_NUM (6) #endif /* Types definition @@ -184,6 +187,10 @@ struct osi_funcs_t { void *(* _coex_schm_curr_phase_get)(void); int (* _coex_wifi_channel_get)(uint8_t *primary, uint8_t *secondary); int (* _coex_register_wifi_channel_change_callback)(void *cb); + xt_handler (*_set_isr_l3)(int n, xt_handler f, void *arg); + void (*_interrupt_l3_disable)(void); + void (*_interrupt_l3_restore)(void); + void *(* _customer_queue_create)(uint32_t queue_len, uint32_t item_size); uint32_t _magic; }; @@ -268,8 +275,13 @@ extern uint32_t _btdm_data_end; static bool btdm_queue_generic_register(const btdm_queue_item_t *queue); static bool btdm_queue_generic_deregister(btdm_queue_item_t *queue); #endif /* CONFIG_SPIRAM_USE_MALLOC */ -static void IRAM_ATTR interrupt_disable(void); -static void IRAM_ATTR interrupt_restore(void); + +#if CONFIG_BTDM_CTRL_HLI +static xt_handler set_isr_hlevel_wrapper(int n, xt_handler f, void *arg); +static void IRAM_ATTR interrupt_hlevel_disable(void); +static void IRAM_ATTR interrupt_hlevel_restore(void); +#endif /* CONFIG_BTDM_CTRL_HLI */ +static void IRAM_ATTR task_yield(void); static void IRAM_ATTR task_yield_from_isr(void); static void *semphr_create_wrapper(uint32_t max, uint32_t init); static void semphr_delete_wrapper(void *semphr); @@ -281,12 +293,21 @@ static void *mutex_create_wrapper(void); static void mutex_delete_wrapper(void *mutex); static int32_t mutex_lock_wrapper(void *mutex); static int32_t mutex_unlock_wrapper(void *mutex); +#if CONFIG_BTDM_CTRL_HLI +static void *queue_create_hlevel_wrapper(uint32_t queue_len, uint32_t item_size); +static void queue_delete_hlevel_wrapper(void *queue); +static int32_t IRAM_ATTR queue_send_hlevel_wrapper(void *queue, void *item, uint32_t block_time_ms); +static int32_t IRAM_ATTR queue_send_from_isr_hlevel_wrapper(void *queue, void *item, void *hptw); +static int32_t IRAM_ATTR queue_recv_hlevel_wrapper(void *queue, void *item, uint32_t block_time_ms); +static int32_t IRAM_ATTR queue_recv_from_isr_hlevel_wrapper(void *queue, void *item, void *hptw); +#else static void *queue_create_wrapper(uint32_t queue_len, uint32_t item_size); static void queue_delete_wrapper(void *queue); -static int32_t queue_send_wrapper(void *queue, void *item, uint32_t block_time_ms); +static int32_t IRAM_ATTR queue_send_wrapper(void *queue, void *item, uint32_t block_time_ms); static int32_t IRAM_ATTR queue_send_from_isr_wrapper(void *queue, void *item, void *hptw); -static int32_t queue_recv_wrapper(void *queue, void *item, uint32_t block_time_ms); +static int32_t IRAM_ATTR queue_recv_wrapper(void *queue, void *item, uint32_t block_time_ms); static int32_t IRAM_ATTR queue_recv_from_isr_wrapper(void *queue, void *item, void *hptw); +#endif /* CONFIG_BTDM_CTRL_HLI */ static int32_t task_create_wrapper(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle, uint32_t core_id); static void task_delete_wrapper(void *task_handle); static bool IRAM_ATTR is_in_isr_wrapper(void); @@ -317,17 +338,30 @@ static uint8_t coex_schm_curr_period_get_wrapper(void); static void * coex_schm_curr_phase_get_wrapper(void); static int coex_wifi_channel_get_wrapper(uint8_t *primary, uint8_t *secondary); static int coex_register_wifi_channel_change_callback_wrapper(void *cb); +#if CONFIG_BTDM_CTRL_HLI +static void *customer_queue_create_hlevel_wrapper(uint32_t queue_len, uint32_t item_size); +#endif /* CONFIG_BTDM_CTRL_HLI */ +static void IRAM_ATTR interrupt_l3_disable(void); +static void IRAM_ATTR interrupt_l3_restore(void); + /* Local variable definition *************************************************************************** */ /* OSI funcs */ static const struct osi_funcs_t osi_funcs_ro = { ._version = OSI_VERSION, +#if CONFIG_BTDM_CTRL_HLI + ._set_isr = set_isr_hlevel_wrapper, + ._ints_on = xt_ints_on, + ._interrupt_disable = interrupt_hlevel_disable, + ._interrupt_restore = interrupt_hlevel_restore, +#else ._set_isr = xt_set_interrupt_handler, ._ints_on = xt_ints_on, - ._interrupt_disable = interrupt_disable, - ._interrupt_restore = interrupt_restore, - ._task_yield = vPortYield, + ._interrupt_disable = interrupt_l3_disable, + ._interrupt_restore = interrupt_l3_restore, +#endif /* CONFIG_BTDM_CTRL_HLI */ + ._task_yield = task_yield, ._task_yield_from_isr = task_yield_from_isr, ._semphr_create = semphr_create_wrapper, ._semphr_delete = semphr_delete_wrapper, @@ -339,12 +373,21 @@ static const struct osi_funcs_t osi_funcs_ro = { ._mutex_delete = mutex_delete_wrapper, ._mutex_lock = mutex_lock_wrapper, ._mutex_unlock = mutex_unlock_wrapper, +#if CONFIG_BTDM_CTRL_HLI + ._queue_create = queue_create_hlevel_wrapper, + ._queue_delete = queue_delete_hlevel_wrapper, + ._queue_send = queue_send_hlevel_wrapper, + ._queue_send_from_isr = queue_send_from_isr_hlevel_wrapper, + ._queue_recv = queue_recv_hlevel_wrapper, + ._queue_recv_from_isr = queue_recv_from_isr_hlevel_wrapper, +#else ._queue_create = queue_create_wrapper, ._queue_delete = queue_delete_wrapper, ._queue_send = queue_send_wrapper, ._queue_send_from_isr = queue_send_from_isr_wrapper, ._queue_recv = queue_recv_wrapper, ._queue_recv_from_isr = queue_recv_from_isr_wrapper, +#endif /* CONFIG_BTDM_CTRL_HLI */ ._task_create = task_create_wrapper, ._task_delete = task_delete_wrapper, ._is_in_isr = is_in_isr_wrapper, @@ -378,6 +421,14 @@ static const struct osi_funcs_t osi_funcs_ro = { ._coex_schm_curr_phase_get = coex_schm_curr_phase_get_wrapper, ._coex_wifi_channel_get = coex_wifi_channel_get_wrapper, ._coex_register_wifi_channel_change_callback = coex_register_wifi_channel_change_callback_wrapper, + ._set_isr_l3 = xt_set_interrupt_handler, + ._interrupt_l3_disable = interrupt_l3_disable, + ._interrupt_l3_restore = interrupt_l3_restore, +#if CONFIG_BTDM_CTRL_HLI + ._customer_queue_create = customer_queue_create_hlevel_wrapper, +#else + ._customer_queue_create = NULL, +#endif /* CONFIG_BTDM_CTRL_HLI */ ._magic = OSI_MAGIC_VALUE, }; @@ -494,7 +545,48 @@ static bool btdm_queue_generic_deregister(btdm_queue_item_t *queue) #endif /* CONFIG_SPIRAM_USE_MALLOC */ -static void IRAM_ATTR interrupt_disable(void) +#if CONFIG_BTDM_CTRL_HLI +struct interrupt_hlevel_cb{ + uint32_t status; + uint8_t nested; +}; + +static DRAM_ATTR struct interrupt_hlevel_cb hli_cb = { + .status = 0, + .nested = 0, +}; + +static xt_handler set_isr_hlevel_wrapper(int mask, xt_handler f, void *arg) +{ + esp_err_t err = hli_intr_register((intr_handler_t) f, arg, DPORT_PRO_INTR_STATUS_0_REG, mask); + if (err == ESP_OK) { + return f; + } else { + return 0; + } + } + +static void IRAM_ATTR interrupt_hlevel_disable(void) +{ + assert(xPortGetCoreID() == CONFIG_BTDM_CTRL_PINNED_TO_CORE); + assert(hli_cb.nested != ~0); + uint32_t status = hli_intr_disable(); + if (hli_cb.nested++ == 0) { + hli_cb.status = status; + } +} + +static void IRAM_ATTR interrupt_hlevel_restore(void) +{ + assert(xPortGetCoreID() == CONFIG_BTDM_CTRL_PINNED_TO_CORE); + assert(hli_cb.nested > 0); + if (--hli_cb.nested == 0) { + hli_intr_restore(hli_cb.status); + } +} +#endif /* CONFIG_BTDM_CTRL_HLI */ + +static void IRAM_ATTR interrupt_l3_disable(void) { if (xPortInIsrContext()) { portENTER_CRITICAL_ISR(&global_int_mux); @@ -503,7 +595,7 @@ static void IRAM_ATTR interrupt_disable(void) } } -static void IRAM_ATTR interrupt_restore(void) +static void IRAM_ATTR interrupt_l3_restore(void) { if (xPortInIsrContext()) { portEXIT_CRITICAL_ISR(&global_int_mux); @@ -512,6 +604,12 @@ static void IRAM_ATTR interrupt_restore(void) } } +static void IRAM_ATTR task_yield(void) +{ + vPortYield(); +} + + static void IRAM_ATTR task_yield_from_isr(void) { portYIELD_FROM_ISR(); @@ -519,18 +617,19 @@ static void IRAM_ATTR task_yield_from_isr(void) static void *semphr_create_wrapper(uint32_t max, uint32_t init) { + void *handle = NULL; + #if !CONFIG_SPIRAM_USE_MALLOC - return (void *)xSemaphoreCreateCounting(max, init); + handle = (void *)xSemaphoreCreateCounting(max, init); #else StaticQueue_t *queue_buffer = NULL; - QueueHandle_t handle = NULL; queue_buffer = heap_caps_malloc(sizeof(StaticQueue_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); if (!queue_buffer) { goto error; } - handle = xSemaphoreCreateCountingStatic(max, init, queue_buffer); + handle = (void *)xSemaphoreCreateCountingStatic(max, init, queue_buffer); if (!handle) { goto error; } @@ -544,8 +643,19 @@ static void *semphr_create_wrapper(uint32_t max, uint32_t init) if (!btdm_queue_generic_register(&item)) { goto error; } - return handle; +#endif +#if CONFIG_BTDM_CTRL_HLI + SemaphoreHandle_t downstream_semaphore = handle; + assert(downstream_semaphore); + hli_queue_handle_t s_semaphore = hli_semaphore_create(max, downstream_semaphore); + assert(downstream_semaphore); + return s_semaphore; +#else + return handle; +#endif /* CONFIG_BTDM_CTRL_HLI */ + +#if CONFIG_SPIRAM_USE_MALLOC error: if (handle) { vSemaphoreDelete(handle); @@ -560,11 +670,22 @@ static void *semphr_create_wrapper(uint32_t max, uint32_t init) static void semphr_delete_wrapper(void *semphr) { + void *handle = NULL; +#if CONFIG_BTDM_CTRL_HLI + if (((hli_queue_handle_t)semphr)->downstream != NULL) { + handle = ((hli_queue_handle_t)semphr)->downstream; + } + + hli_queue_delete(semphr); +#else + handle = semphr; +#endif /* CONFIG_BTDM_CTRL_HLI */ + #if !CONFIG_SPIRAM_USE_MALLOC - vSemaphoreDelete(semphr); + vSemaphoreDelete(handle); #else btdm_queue_item_t item = { - .handle = semphr, + .handle = handle, .storage = NULL, .buffer = NULL, }; @@ -573,33 +694,55 @@ static void semphr_delete_wrapper(void *semphr) vSemaphoreDelete(item.handle); free(item.buffer); } - - return; #endif } static int32_t IRAM_ATTR semphr_take_from_isr_wrapper(void *semphr, void *hptw) { +#if CONFIG_BTDM_CTRL_HLI + return (int32_t)xSemaphoreTakeFromISR(((hli_queue_handle_t)semphr)->downstream, hptw); +#else return (int32_t)xSemaphoreTakeFromISR(semphr, hptw); +#endif /* CONFIG_BTDM_CTRL_HLI */ } static int32_t IRAM_ATTR semphr_give_from_isr_wrapper(void *semphr, void *hptw) { +#if CONFIG_BTDM_CTRL_HLI + UNUSED(hptw); + assert(xPortGetCoreID() == CONFIG_BTDM_CTRL_PINNED_TO_CORE); + return hli_semaphore_give(semphr); +#else return (int32_t)xSemaphoreGiveFromISR(semphr, hptw); +#endif /* CONFIG_BTDM_CTRL_HLI */ } static int32_t semphr_take_wrapper(void *semphr, uint32_t block_time_ms) { + bool ret; +#if CONFIG_BTDM_CTRL_HLI if (block_time_ms == OSI_FUNCS_TIME_BLOCKING) { - return (int32_t)xSemaphoreTake(semphr, portMAX_DELAY); + ret = xSemaphoreTake(((hli_queue_handle_t)semphr)->downstream, portMAX_DELAY); } else { - return (int32_t)xSemaphoreTake(semphr, block_time_ms / portTICK_PERIOD_MS); + ret = xSemaphoreTake(((hli_queue_handle_t)semphr)->downstream, block_time_ms / portTICK_PERIOD_MS); } +#else + if (block_time_ms == OSI_FUNCS_TIME_BLOCKING) { + ret = xSemaphoreTake(semphr, portMAX_DELAY); + } else { + ret = xSemaphoreTake(semphr, block_time_ms / portTICK_PERIOD_MS); + } +#endif /* CONFIG_BTDM_CTRL_HLI */ + return (int32_t)ret; } static int32_t semphr_give_wrapper(void *semphr) { +#if CONFIG_BTDM_CTRL_HLI + return (int32_t)xSemaphoreGive(((hli_queue_handle_t)semphr)->downstream); +#else return (int32_t)xSemaphoreGive(semphr); +#endif /* CONFIG_BTDM_CTRL_HLI */ } static void *mutex_create_wrapper(void) @@ -745,6 +888,79 @@ static void queue_delete_wrapper(void *queue) #endif } +#if CONFIG_BTDM_CTRL_HLI +static void *queue_create_hlevel_wrapper(uint32_t queue_len, uint32_t item_size) +{ + QueueHandle_t downstream_queue = queue_create_wrapper(queue_len, item_size); + assert(downstream_queue); + hli_queue_handle_t queue = hli_queue_create(queue_len, item_size, downstream_queue); + assert(queue); + return queue; +} + +static void *customer_queue_create_hlevel_wrapper(uint32_t queue_len, uint32_t item_size) +{ + QueueHandle_t downstream_queue = queue_create_wrapper(queue_len, item_size); + assert(downstream_queue); + hli_queue_handle_t queue = hli_customer_queue_create(queue_len, item_size, downstream_queue); + assert(queue); + return queue; +} + +static void queue_delete_hlevel_wrapper(void *queue) +{ + if (((hli_queue_handle_t)queue)->downstream != NULL) { + queue_delete_wrapper(((hli_queue_handle_t)queue)->downstream); + } + hli_queue_delete(queue); +} + +static int32_t queue_send_hlevel_wrapper(void *queue, void *item, uint32_t block_time_ms) +{ + if (block_time_ms == OSI_FUNCS_TIME_BLOCKING) { + return (int32_t)xQueueSend(((hli_queue_handle_t)queue)->downstream, item, portMAX_DELAY); + } else { + return (int32_t)xQueueSend(((hli_queue_handle_t)queue)->downstream, item, block_time_ms / portTICK_PERIOD_MS); + } +} + +/** + * Queue send from isr + * @param queue The queue which will send to + * @param item The message which will be send + * @param hptw need do task yield or not + * @return send success or not + * There is an issue here: When the queue is full, it may reture true but it send fail to the queue, sometimes. + * But in Bluetooth controller's isr, We don't care about the return value. + * It only required tp send success when the queue is empty all the time. + * So, this function meets the requirement. + */ +static int32_t IRAM_ATTR queue_send_from_isr_hlevel_wrapper(void *queue, void *item, void *hptw) +{ + UNUSED(hptw); + assert(xPortGetCoreID() == CONFIG_BTDM_CTRL_PINNED_TO_CORE); + return hli_queue_put(queue, item); +} + +static int32_t queue_recv_hlevel_wrapper(void *queue, void *item, uint32_t block_time_ms) +{ + bool ret; + if (block_time_ms == OSI_FUNCS_TIME_BLOCKING) { + ret = xQueueReceive(((hli_queue_handle_t)queue)->downstream, item, portMAX_DELAY); + } else { + ret = xQueueReceive(((hli_queue_handle_t)queue)->downstream, item, block_time_ms / portTICK_PERIOD_MS); + } + + return (int32_t)ret; +} + +static int32_t IRAM_ATTR queue_recv_from_isr_hlevel_wrapper(void *queue, void *item, void *hptw) +{ + return (int32_t)xQueueReceiveFromISR(((hli_queue_handle_t)queue)->downstream, item, hptw); +} + +#else + static int32_t queue_send_wrapper(void *queue, void *item, uint32_t block_time_ms) { if (block_time_ms == OSI_FUNCS_TIME_BLOCKING) { @@ -760,18 +976,23 @@ static int32_t IRAM_ATTR queue_send_from_isr_wrapper(void *queue, void *item, vo } static int32_t queue_recv_wrapper(void *queue, void *item, uint32_t block_time_ms) -{ + { + bool ret; if (block_time_ms == OSI_FUNCS_TIME_BLOCKING) { - return (int32_t)xQueueReceive(queue, item, portMAX_DELAY); + ret = xQueueReceive(queue, item, portMAX_DELAY); } else { - return (int32_t)xQueueReceive(queue, item, block_time_ms / portTICK_PERIOD_MS); + ret = xQueueReceive(queue, item, block_time_ms / portTICK_PERIOD_MS); } -} + + return (int32_t)ret; + } static int32_t IRAM_ATTR queue_recv_from_isr_wrapper(void *queue, void *item, void *hptw) { return (int32_t)xQueueReceiveFromISR(queue, item, hptw); } +#endif /* CONFIG_BTDM_CTRL_HLI */ + static int32_t task_create_wrapper(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle, uint32_t core_id) { @@ -1317,11 +1538,35 @@ esp_err_t esp_bt_mem_release(esp_bt_mode_t mode) return ESP_OK; } +#if CONFIG_BTDM_CTRL_HLI +static void hli_queue_setup_cb(void* arg) +{ + hli_queue_setup(); +} + +static void hli_queue_setup_pinned_to_core(int core_id) +{ +#if CONFIG_FREERTOS_UNICORE + hli_queue_setup_cb(NULL); +#else /* CONFIG_FREERTOS_UNICORE */ + if (xPortGetCoreID() == core_id) { + hli_queue_setup_cb(NULL); + } else { + esp_ipc_call(core_id, hli_queue_setup_cb, NULL); + } +#endif /* !CONFIG_FREERTOS_UNICORE */ +} +#endif /* CONFIG_BTDM_CTRL_HLI */ + esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) { esp_err_t err; uint32_t btdm_cfg_mask = 0; +#if CONFIG_BTDM_CTRL_HLI + hli_queue_setup_pinned_to_core(CONFIG_BTDM_CTRL_PINNED_TO_CORE); +#endif /* CONFIG_BTDM_CTRL_HLI */ + //if all the bt available memory was already released, cannot initialize bluetooth controller if (btdm_dram_available_region[0].mode == ESP_BT_MODE_IDLE) { return ESP_ERR_INVALID_STATE; @@ -1394,7 +1639,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) #if CONFIG_BTDM_CTRL_LPCLK_SEL_EXT_32K_XTAL // check whether or not EXT_CRYS is working if (rtc_clk_slow_freq_get() == RTC_SLOW_FREQ_32K_XTAL) { - btdm_lpclk_sel = BTDM_LPCLK_SEL_XTAL32K; // set default value + btdm_lpclk_sel = BTDM_LPCLK_SEL_XTAL32K; // External 32kHz XTAL #ifdef CONFIG_PM_ENABLE s_btdm_allow_light_sleep = true; #endif @@ -1736,4 +1981,15 @@ esp_err_t esp_ble_scan_dupilcate_list_flush(void) return ESP_OK; } +/** + * This function re-write controller's function, + * As coredump can not show paramerters in function which is in a .a file. + * + * After coredump fixing this issue, just delete this function. + */ +void IRAM_ATTR r_assert(const char *condition, int param0, int param1, const char *file, int line) +{ + __asm__ __volatile__("ill\n"); +} + #endif /* CONFIG_BT_ENABLED */ diff --git a/components/bt/controller/esp32/hli_api.c b/components/bt/controller/esp32/hli_api.c new file mode 100644 index 0000000000..e1444c2bb0 --- /dev/null +++ b/components/bt/controller/esp32/hli_api.c @@ -0,0 +1,306 @@ +// Copyright 2015-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. + + +#include +#include "esp_log.h" +#include "esp_heap_caps.h" +#include "xtensa/core-macros.h" +#include "soc/dport_reg.h" +#include "hli_api.h" +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" + +#if CONFIG_BTDM_CTRL_HLI +#define HLI_MAX_HANDLERS 4 + +typedef struct { + intr_handler_t handler; + void* arg; + uint32_t intr_reg; + uint32_t intr_mask; +} hli_handler_info_t; + +typedef struct { +#define CUSTOMER_TYPE_REQUEST (0) +#define CUSTOMER_TYPE_RELEASE (1) + struct { + uint32_t cb_type; + union { + int (* request)(uint32_t, uint32_t, uint32_t); + int (* release)(uint32_t); + } cb; + } customer_cb; + uint32_t arg0, arg1, arg2; +} customer_swisr_t; + +static void IRAM_ATTR customer_swisr_handle(customer_swisr_t *cus_swisr) +{ + if (cus_swisr->customer_cb.cb_type == CUSTOMER_TYPE_REQUEST) { + if (cus_swisr->customer_cb.cb.request != NULL) { + cus_swisr->customer_cb.cb.request(cus_swisr->arg0, cus_swisr->arg1, cus_swisr->arg2); + } + } else if(cus_swisr->customer_cb.cb_type == CUSTOMER_TYPE_RELEASE) { + if (cus_swisr->customer_cb.cb.release != NULL) { + cus_swisr->customer_cb.cb.release(cus_swisr->arg0); + } + } +} + +static DRAM_ATTR hli_handler_info_t s_hli_handlers[HLI_MAX_HANDLERS]; + +esp_err_t hli_intr_register(intr_handler_t handler, void* arg, uint32_t intr_reg, uint32_t intr_mask) +{ + for (hli_handler_info_t* hip = s_hli_handlers; + hip < s_hli_handlers + HLI_MAX_HANDLERS; + ++hip) { + if (hip->handler == NULL) { + hip->arg = arg; + hip->intr_reg = intr_reg; + hip->intr_mask = intr_mask; + hip->handler = handler; /* set last, indicates the entry as valid */ + return ESP_OK; + } + } + return ESP_ERR_NO_MEM; +} + +void IRAM_ATTR hli_c_handler(void) +{ + bool handled = false; + /* Iterate over registered interrupt handlers, + * and check if the expected mask is present in the interrupt status register. + */ + for (hli_handler_info_t* hip = s_hli_handlers; + hip < s_hli_handlers + HLI_MAX_HANDLERS; + ++hip) { + if (hip->handler == NULL) { + continue; + } + uint32_t reg = hip->intr_reg; + uint32_t val; + if (reg == 0) { /* special case for CPU internal interrupts */ + val = XTHAL_GET_INTERRUPT(); + } else { + /* "reg" might not be in DPORT, but this will work in any case */ + val = DPORT_REG_READ(reg); + } + if ((val & hip->intr_mask) != 0) { + handled = true; + (*hip->handler)(hip->arg); + } + } + if (!handled) { + /* no handler found, it is OK in this case. */ + } +} + +uint32_t IRAM_ATTR hli_intr_disable(void) +{ + /* disable level 4 and below */ + return XTOS_SET_INTLEVEL(XCHAL_DEBUGLEVEL - 2); +} + +void IRAM_ATTR hli_intr_restore(uint32_t state) +{ + XTOS_RESTORE_JUST_INTLEVEL(state); +} + +#define HLI_META_QUEUE_SIZE 16 +#define HLI_QUEUE_MAX_ELEM_SIZE 32 +#define HLI_QUEUE_SW_INT_NUM 29 + +#define HLI_QUEUE_FLAG_SEMAPHORE BIT(0) +#define HLI_QUEUE_FLAG_CUSTOMER BIT(1) + +static DRAM_ATTR struct hli_queue_t *s_meta_queue_ptr = NULL; +static intr_handle_t ret_handle; + +static inline char* IRAM_ATTR wrap_ptr(hli_queue_handle_t queue, char *ptr) +{ + return (ptr == queue->bufend) ? queue->buf : ptr; +} + +static inline bool IRAM_ATTR queue_empty(hli_queue_handle_t queue) +{ + return queue->begin == queue->end; +} + +static inline bool IRAM_ATTR queue_full(hli_queue_handle_t queue) +{ + return wrap_ptr(queue, queue->end + queue->elem_size) == queue->begin; +} + +static void IRAM_ATTR queue_isr_handler(void* arg) +{ + int do_yield = pdFALSE; + XTHAL_SET_INTCLEAR(BIT(HLI_QUEUE_SW_INT_NUM)); + hli_queue_handle_t queue; + + while (hli_queue_get(s_meta_queue_ptr, &queue)) { + static DRAM_ATTR char scratch[HLI_QUEUE_MAX_ELEM_SIZE]; + while (hli_queue_get(queue, scratch)) { + int res = pdPASS; + if ((queue->flags & HLI_QUEUE_FLAG_CUSTOMER) != 0) { + customer_swisr_handle((customer_swisr_t *)scratch); + } else if ((queue->flags & HLI_QUEUE_FLAG_SEMAPHORE) != 0) { + res = xSemaphoreGiveFromISR((SemaphoreHandle_t) queue->downstream, &do_yield); + } else { + res = xQueueSendFromISR(queue->downstream, scratch, &do_yield); + } + if (res == pdFAIL) { + /* Failed to send to downstream queue, it is OK in this case. */ + } + } + } + if (do_yield) { + portYIELD_FROM_ISR(); + } +} + +/* Notify the level 3 handler that an element is added to the given hli queue. + * Do this by placing the queue handle onto s_meta_queue, and raising a SW interrupt. + * + * This function must be called with HL interrupts disabled! + */ +static void IRAM_ATTR queue_signal(hli_queue_handle_t queue) +{ + /* See if the queue is already in s_meta_queue, before adding */ + bool found = false; + const hli_queue_handle_t *end = (hli_queue_handle_t*) s_meta_queue_ptr->end; + hli_queue_handle_t *item = (hli_queue_handle_t*) s_meta_queue_ptr->begin; + for (;item != end; item = (hli_queue_handle_t*) wrap_ptr(s_meta_queue_ptr, (char*) (item + 1))) { + if (*item == queue) { + found = true; + break; + } + } + if (!found) { + bool res = hli_queue_put(s_meta_queue_ptr, &queue); + if (!res) { + esp_rom_printf(DRAM_STR("Fatal error in queue_signal: s_meta_queue full\n")); + abort(); + } + XTHAL_SET_INTSET(BIT(HLI_QUEUE_SW_INT_NUM)); + } +} + +static void queue_init(hli_queue_handle_t queue, size_t buf_size, size_t elem_size, QueueHandle_t downstream) +{ + queue->elem_size = elem_size; + queue->begin = queue->buf; + queue->end = queue->buf; + queue->bufend = queue->buf + buf_size; + queue->downstream = downstream; + queue->flags = 0; +} + +void hli_queue_setup(void) +{ + if (s_meta_queue_ptr == NULL) { + s_meta_queue_ptr = hli_queue_create(HLI_META_QUEUE_SIZE, sizeof(void*), NULL); + ESP_ERROR_CHECK(esp_intr_alloc(ETS_INTERNAL_SW1_INTR_SOURCE, ESP_INTR_FLAG_IRAM, queue_isr_handler, NULL, &ret_handle)); + xt_ints_on(BIT(HLI_QUEUE_SW_INT_NUM)); + } +} + +void hli_queue_shutdown(void) +{ + if (s_meta_queue_ptr != NULL) { + hli_queue_delete(s_meta_queue_ptr); + s_meta_queue_ptr = NULL; + esp_intr_free(ret_handle); + xt_ints_off(BIT(HLI_QUEUE_SW_INT_NUM)); + } +} + +hli_queue_handle_t hli_queue_create(size_t nelem, size_t elem_size, QueueHandle_t downstream) +{ + const size_t buf_elem = nelem + 1; + if (elem_size > HLI_QUEUE_MAX_ELEM_SIZE) { + return NULL; + } + size_t buf_size = buf_elem * elem_size; + hli_queue_handle_t res = (hli_queue_handle_t) heap_caps_malloc(sizeof(struct hli_queue_t) + buf_size, + MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); + if (res == NULL) { + return NULL; + } + queue_init(res, buf_size, elem_size, downstream); + return res; +} + +hli_queue_handle_t hli_customer_queue_create(size_t nelem, size_t elem_size, QueueHandle_t downstream) +{ + hli_queue_handle_t res = hli_queue_create(nelem, elem_size, (QueueHandle_t) downstream); + if (res == NULL) { + return NULL; + } + res->flags |= HLI_QUEUE_FLAG_CUSTOMER; + return res; +} + +hli_queue_handle_t hli_semaphore_create(size_t max_count, SemaphoreHandle_t downstream) +{ + const size_t elem_size = 1; + hli_queue_handle_t res = hli_queue_create(max_count, elem_size, (QueueHandle_t) downstream); + if (res == NULL) { + return NULL; + } + res->flags |= HLI_QUEUE_FLAG_SEMAPHORE; + return res; +} + +void hli_queue_delete(hli_queue_handle_t queue) +{ + free(queue); +} + +bool IRAM_ATTR hli_queue_get(hli_queue_handle_t queue, void* out) +{ + uint32_t int_state = hli_intr_disable(); + bool res = false; + if (!queue_empty(queue)) { + memcpy(out, queue->begin, queue->elem_size); + queue->begin = wrap_ptr(queue, queue->begin + queue->elem_size); + res = true; + } + hli_intr_restore(int_state); + return res; +} + +bool IRAM_ATTR hli_queue_put(hli_queue_handle_t queue, const void* data) +{ + uint32_t int_state = hli_intr_disable(); + bool res = false; + bool was_empty = queue_empty(queue); + if (!queue_full(queue)) { + memcpy(queue->end, data, queue->elem_size); + queue->end = wrap_ptr(queue, queue->end + queue->elem_size); + if (was_empty && queue != s_meta_queue_ptr) { + queue_signal(queue); + } + res = true; + } + hli_intr_restore(int_state); + return res; +} + +bool IRAM_ATTR hli_semaphore_give(hli_queue_handle_t queue) +{ + uint8_t data = 0; + return hli_queue_put(queue, &data); +} + +#endif /* CONFIG_BTDM_CTRL_HLI */ diff --git a/components/bt/controller/esp32/hli_api.h b/components/bt/controller/esp32/hli_api.h new file mode 100644 index 0000000000..e0049aab32 --- /dev/null +++ b/components/bt/controller/esp32/hli_api.h @@ -0,0 +1,176 @@ +// Copyright 2015-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. + + +#pragma once + +#include +#include "esp_err.h" +#include "esp_intr_alloc.h" +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if CONFIG_BTDM_CTRL_HLI + +/*** Queues ***/ + +struct hli_queue_t +{ + size_t elem_size; + char* begin; + char* end; + const char* bufend; + QueueHandle_t downstream; + int flags; + char buf[0]; +}; + +/** + * @brief Register a high level interrupt function + * + * @param handler interrupt handler function + * @param arg argument to pass to the interrupt handler + * @param intr_reg address of the peripheral register containing the interrupt status, + * or value 0 to get the status from CPU INTERRUPT register + * @param intr_mask mask of the interrupt, in the interrupt status register + * @return + * - ESP_OK on success + * - ESP_ERR_NO_MEM if too many handlers are registered + */ +esp_err_t hli_intr_register(intr_handler_t handler, void* arg, uint32_t intr_reg, uint32_t intr_mask); + +/** + * @brief Mask all interrupts (including high level ones) on the current CPU + * + * @return uint32_t interrupt status, pass it to hli_intr_restore + */ +uint32_t hli_intr_disable(void); + +/** + * @brief Re-enable interrupts + * + * @param state value returned by hli_intr_disable + */ +void hli_intr_restore(uint32_t state); + +/** + * @brief Type of a hli queue + */ +typedef struct hli_queue_t* hli_queue_handle_t; + +/** + * @brief Initialize hli_queue module. Must be called once before using hli queue APIs. + */ +void hli_queue_setup(void); + +/** + * @brief Shutdown hli_queue module. + */ +void hli_queue_shutdown(void); + +/** + * @brief Create a hli queue, wrapping a FreeRTOS queue + * + * This queue can be used from high level interrupts, + * but **ONLY ON THE CPU WHERE hli_queue_setup WAS CALLED**. Values sent to this + * queue are automatically forwarded to "downstream" FreeRTOS queue using a level 3 + * software interrupt. + * + * @param nelem number of elements in the queue + * @param elem_size size of one element; must match element size of a downstream queue + * @param downstream FreeRTOS queue to send the values to + * @return hli_queue_handle_t handle of the created queue, or NULL on failure + */ +hli_queue_handle_t hli_queue_create(size_t nelem, size_t elem_size, QueueHandle_t downstream); + +/** + * @brief Create a customer hli queue, wrapping a FreeRTOS queue + * + * This queue can be used from high level interrupts, + * but **ONLY ON THE CPU WHERE hli_queue_setup WAS CALLED**. Values sent to this + * queue are automatically forwarded to "downstream" FreeRTOS queue using a level 3 + * software interrupt. + * + * @param nelem number of elements in the queue + * @param elem_size size of one element; must match element size of a downstream queue + * @param downstream FreeRTOS queue to send the values to + * @return hli_queue_handle_t handle of the created queue, or NULL on failure + */ +hli_queue_handle_t hli_customer_queue_create(size_t nelem, size_t elem_size, QueueHandle_t downstream); + +/** + * @brief Create a hli queue, wrapping a FreeRTOS semaphore + * + * See notes on hli_queue_create. + * + * @param max_count maximum semaphore count + * @param downstream FreeRTOS semaphore to forward the calls to + * @return hli_queue_handle_t handle of the created queue, or NULL on failure + */ +hli_queue_handle_t hli_semaphore_create(size_t max_count, SemaphoreHandle_t downstream); + +/** + * @brief Delete a hli queue + * + * Make sure noone is using the queue before deleting it. + * + * @param queue handle returned by hli_queue_create or hli_semaphore_create + */ +void hli_queue_delete(hli_queue_handle_t queue); + +/** + * @brief Get one element from a hli queue + * + * Usually not used, values get sent to a downstream FreeRTOS queue automatically. + * However if downstream queue is NULL, this API can be used to get values from a hli queue. + * + * @param queue handle of a queue + * @param out pointer where to store the element + * @return true if the element was successfully read from the queue + */ +bool hli_queue_get(hli_queue_handle_t queue, void* out); + +/** + * @brief Put one element into a hli queue + * + * This puts copies an element into the queue and raises a software interrupt (level 3). + * In the interrupt, the value is copied to a FreeRTOS "downstream" queue. + * + * Note that if the value does not fit into a downstream queue, no error is returned, + * and the value is lost. + * + * @param queue handle of a queue + * @param data pointer to the element to be sent + * @return true if data was placed into the hli queue successfully + */ +bool hli_queue_put(hli_queue_handle_t queue, const void* data); + +/** + * @brief "Give" a semaphore wrapped by a hli queue + * + * @param queue handle returned by hli_semaphore_create + * @return true if the event was sent to a hli queue successfully + */ +bool hli_semaphore_give(hli_queue_handle_t queue); + +#endif /* CONFIG_BTDM_CTRL_HLI */ + +#ifdef __cplusplus +} +#endif diff --git a/components/bt/controller/esp32/hli_vectors.S b/components/bt/controller/esp32/hli_vectors.S new file mode 100644 index 0000000000..9b8a0dd9e1 --- /dev/null +++ b/components/bt/controller/esp32/hli_vectors.S @@ -0,0 +1,275 @@ +// Copyright 2015-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. + + +#include +#include +#include +#include "freertos/xtensa_context.h" +#include "sdkconfig.h" +#include "soc/soc.h" + +#if CONFIG_BTDM_CTRL_HLI + +/* Interrupt stack size, for C code. + * TODO: reduce and make configurable. + */ +#define L4_INTR_STACK_SIZE 4096 + +/* Save area for the CPU state: + * - 64 words for the general purpose registers + * - 7 words for some of the special registers: + * - WINDOWBASE, WINDOWSTART — only WINDOWSTART is truly needed + * - SAR, LBEG, LEND, LCOUNT — since the C code might use these + * - EPC1 — since the C code might cause window overflow exceptions + * This is not laid out as standard exception frame structure + * for simplicity of the save/restore code. + */ +#define REG_FILE_SIZE (64 * 4) +#define SPECREG_OFFSET REG_FILE_SIZE +#define SPECREG_SIZE (7 * 4) +#define REG_SAVE_AREA_SIZE (SPECREG_OFFSET + SPECREG_SIZE) + + .data +_l4_intr_stack: + .space L4_INTR_STACK_SIZE +_l4_save_ctx: + .space REG_SAVE_AREA_SIZE + + .section .iram1,"ax" + .global xt_highint4 + .type xt_highint4,@function + .align 4 + +xt_highint4: + +#if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX + /* + Here, Timer2 is used to count a little time(50us). + The subsequent dram0 write operation is blocked due to live lock, which will + cause timer2 to timeout and trigger a level 5 interrupt. + */ + rsr.ccount a0 + addmi a0, a0, (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ*50) + wsr a0, CCOMPARE2 + + /* Enable Timer 2 interrupt */ + rsr a0, INTENABLE + extui a0, a0, 16, 1 + bnez a0, 1f + movi a0, 0 + xsr a0, INTENABLE /* disable all interrupts */ + /* And a0 with (1 << 16) for Timer 2 interrupt mask */ + addmi a0, a0, (1<<14) + addmi a0, a0, (1<<14) + addmi a0, a0, (1<<14) + addmi a0, a0, (1<<14) + wsr a0, INTENABLE /* Enable Timer 2 */ +1: +#endif + + movi a0, _l4_save_ctx + /* save 4 lower registers */ + s32i a1, a0, 4 + s32i a2, a0, 8 + s32i a3, a0, 12 + rsr a2, EXCSAVE_4 /* holds the value of a0 */ + s32i a2, a0, 0 + + /* Save special registers */ + addi a0, a0, SPECREG_OFFSET + rsr a2, WINDOWBASE + s32i a2, a0, 0 + rsr a2, WINDOWSTART + s32i a2, a0, 4 + rsr a2, SAR + s32i a2, a0, 8 + rsr a2, LBEG + s32i a2, a0, 12 + rsr a2, LEND + s32i a2, a0, 16 + rsr a2, LCOUNT + s32i a2, a0, 20 + rsr a2, EPC1 + s32i a2, a0, 24 + +#if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX + movi a0, 0 + xsr a0, INTENABLE /* disable all interrupts */ + movi a2, ~(1<<16) + and a0, a2, a0 + wsr a0, INTENABLE +#endif + + /* disable exception mode, window overflow */ + movi a0, PS_INTLEVEL(5) | PS_EXCM + wsr a0, PS + rsync + + /* Save the remaining physical registers. + * 4 registers are already saved, which leaves 60 registers to save. + * (FIXME: consider the case when the CPU is configured with physical 32 registers) + * These 60 registers are saved in 5 iterations, 12 registers at a time. + */ + movi a1, 5 + movi a3, _l4_save_ctx + 4 * 4 + + /* This is repeated 5 times, each time the window is shifted by 12 registers. + * We come here with a1 = downcounter, a3 = save pointer, a2 and a0 unused. + */ +1: + s32i a4, a3, 0 + s32i a5, a3, 4 + s32i a6, a3, 8 + s32i a7, a3, 12 + s32i a8, a3, 16 + s32i a9, a3, 20 + s32i a10, a3, 24 + s32i a11, a3, 28 + s32i a12, a3, 32 + s32i a13, a3, 36 + s32i a14, a3, 40 + s32i a15, a3, 44 + + /* We are about to rotate the window, so that a12-a15 will become the new a0-a3. + * Copy a0-a3 to a12-15 to still have access to these values. + * At the same time we can decrement the counter and adjust the save area pointer + */ + + /* a0 is constant (_l4_save_ctx), no need to copy */ + addi a13, a1, -1 /* copy and decrement the downcounter */ + /* a2 is scratch so no need to copy */ + addi a15, a3, 48 /* copy and adjust the save area pointer */ + beqz a13, 2f /* have saved all registers ? */ + rotw 3 /* rotate the window and go back */ + j 1b + + /* the loop is complete */ +2: + rotw 4 /* this brings us back to the original window */ + /* a0 still points to _l4_save_ctx */ + + /* Can clear WINDOWSTART now, all registers are saved */ + rsr a2, WINDOWBASE + /* WINDOWSTART = (1 << WINDOWBASE) */ + movi a3, 1 + ssl a2 + sll a3, a3 + wsr a3, WINDOWSTART + +_highint4_stack_switch: + movi a0, 0 + movi sp, _l4_intr_stack + L4_INTR_STACK_SIZE - 16 + s32e a0, sp, -12 /* For GDB: set null SP */ + s32e a0, sp, -16 /* For GDB: set null PC */ + movi a0, _highint4_stack_switch /* For GDB: cosmetics, for the frame where stack switch happened */ + + /* Set up PS for C, disable all interrupts except NMI and debug, and clear EXCM. */ + movi a6, PS_INTLEVEL(4) | PS_UM | PS_WOE + wsr a6, PS + rsync + + /* Call C handler */ + mov a6, sp + call4 hli_c_handler + + l32e sp, sp, -12 /* switch back to the original stack */ + + /* Done with C handler; re-enable exception mode, disabling window overflow */ + movi a2, PS_INTLEVEL(5) | PS_EXCM /* TOCHECK */ + wsr a2, PS + rsync + + /* Restore the special registers. + * WINDOWSTART will be restored near the end. + */ + movi a0, _l4_save_ctx + SPECREG_OFFSET + l32i a2, a0, 8 + wsr a2, SAR + l32i a2, a0, 12 + wsr a2, LBEG + l32i a2, a0, 16 + wsr a2, LEND + l32i a2, a0, 20 + wsr a2, LCOUNT + l32i a2, a0, 24 + wsr a2, EPC1 + + /* Restoring the physical registers. + * This is the reverse to the saving process above. + */ + + /* Rotate back to the final window, then start loading 12 registers at a time, + * in 5 iterations. + * Again, a1 is the downcounter and a3 is the save area pointer. + * After each rotation, a1 and a3 are copied from a13 and a15. + * To simplify the loop, we put the initial values into a13 and a15. + */ + rotw -4 + movi a15, _l4_save_ctx + 64 * 4 /* point to the end of the save area */ + movi a13, 5 + +1: + /* Copy a1 and a3 from their previous location, + * at the same time decrementing and adjusting the save area pointer. + */ + addi a1, a13, -1 + addi a3, a15, -48 + + /* Load 12 registers */ + l32i a4, a3, 0 + l32i a5, a3, 4 + l32i a6, a3, 8 + l32i a7, a3, 12 + l32i a8, a3, 16 + l32i a9, a3, 20 + l32i a10, a3, 24 + l32i a11, a3, 28 /* ensure PS and EPC written */ + l32i a12, a3, 32 + l32i a13, a3, 36 + l32i a14, a3, 40 + l32i a15, a3, 44 + + /* Done with the loop? */ + beqz a1, 2f + /* If no, rotate the window and repeat */ + rotw -3 + j 1b + +2: + /* Done with the loop. Only 4 registers (a0-a3 in the original window) remain + * to be restored. Also need to restore WINDOWSTART, since all the general + * registers are now in place. + */ + movi a0, _l4_save_ctx + + l32i a2, a0, SPECREG_OFFSET + 4 + wsr a2, WINDOWSTART + + l32i a1, a0, 4 + l32i a2, a0, 8 + l32i a3, a0, 12 + rsr a0, EXCSAVE_4 /* holds the value of a0 before the interrupt handler */ + + /* Return from the interrupt, restoring PS from EPS_4 */ + rfi 4 + +#endif /* CONFIG_BTDM_CTRL_HLI */ + +/* The linker has no reason to link in this file; all symbols it exports are already defined + (weakly!) in the default int handler. Define a symbol here so we can use it to have the + linker inspect this anyway. */ + + .global ld_include_hli_vectors_bt +ld_include_hli_vectors_bt: diff --git a/components/bt/controller/esp32c3/Kconfig.in b/components/bt/controller/esp32c3/Kconfig.in index 6f8fee6cd3..c30f80bc45 100644 --- a/components/bt/controller/esp32c3/Kconfig.in +++ b/components/bt/controller/esp32c3/Kconfig.in @@ -359,7 +359,8 @@ menu "MODEM SLEEP Options" bool "Internal 150kHz RC oscillator" depends on ESP32C3_RTC_CLK_SRC_INT_RC help - Internal 150kHz RC oscillator. + Internal 150kHz RC oscillator. The accuracy of this clock is a lot larger than 500ppm which is required + in Bluetooth communication, so don't select this option in scenarios such as BLE connection state. endchoice diff --git a/components/bt/controller/esp32c3/bt.c b/components/bt/controller/esp32c3/bt.c index c4cd255fc7..8c1b116343 100644 --- a/components/bt/controller/esp32c3/bt.c +++ b/components/bt/controller/esp32c3/bt.c @@ -992,7 +992,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) // configure and initialize resources s_lp_cntl.enable = (cfg->sleep_mode == ESP_BT_SLEEP_MODE_1) ? 1 : 0; - s_lp_cntl.no_light_sleep = 0; + s_lp_cntl.no_light_sleep = 1; if (s_lp_cntl.enable) { #if (CONFIG_MAC_BB_PD) @@ -1029,31 +1029,29 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT; btdm_lpcycle_us = 2 << (btdm_lpcycle_us_frac); - // // set default bluetooth sleep clock source - // s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_XTAL; + // set default bluetooth sleep clock source + s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_XTAL; // set default value #if CONFIG_BT_CTRL_LPCLK_SEL_EXT_32K_XTAL // check whether or not EXT_CRYS is working if (rtc_clk_slow_freq_get() == RTC_SLOW_FREQ_32K_XTAL) { - s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_XTAL32K; // set default value -// #ifdef CONFIG_PM_ENABLE -// s_btdm_allow_light_sleep = true; -// #endif + s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_XTAL32K; // External 32 kHz XTAL + s_lp_cntl.no_light_sleep = 0; } else { ESP_LOGW(BTDM_LOG_TAG, "32.768kHz XTAL not detected, fall back to main XTAL as Bluetooth sleep clock\n" "light sleep mode will not be able to apply when bluetooth is enabled"); - s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_XTAL; // set default value } #elif (CONFIG_BT_CTRL_LPCLK_SEL_RTC_SLOW) // check whether or not EXT_CRYS is working if (rtc_clk_slow_freq_get() == RTC_SLOW_FREQ_RTC) { - s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_RTC_SLOW; // set default value + s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_RTC_SLOW; // Internal 150 kHz RC oscillator + ESP_LOGW(BTDM_LOG_TAG, "Internal 150kHz RC osciallator. The accuracy of this clock is a lot larger than 500ppm which is " + "required in Bluetooth communication, so don't select this option in scenarios such as BLE connection state."); } else { - ESP_LOGW(BTDM_LOG_TAG, "Internal 150kHz RC oscillator not detected, fall back to main XTAL as Bluetooth sleep clock\n" - "light sleep mode will not be able to apply when bluetooth is enabled"); - s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_XTAL; // set default value + ESP_LOGW(BT_LOG_TAG, "Internal 150kHz RC oscillator not detected."); + assert(0); } #else - s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_XTAL; // set default value + s_lp_cntl.no_light_sleep = 1; #endif bool select_src_ret __attribute__((unused)); diff --git a/docs/extensions/__init__.py b/components/bt/controller/esp32h2/Kconfig.in similarity index 100% rename from docs/extensions/__init__.py rename to components/bt/controller/esp32h2/Kconfig.in diff --git a/docs/idf_extensions/__init__.py b/components/bt/controller/esp32s2/Kconfig.in similarity index 100% rename from docs/idf_extensions/__init__.py rename to components/bt/controller/esp32s2/Kconfig.in diff --git a/components/bt/controller/esp32s3/Kconfig.in b/components/bt/controller/esp32s3/Kconfig.in index 53ca7b0616..359dac7b54 100644 --- a/components/bt/controller/esp32s3/Kconfig.in +++ b/components/bt/controller/esp32s3/Kconfig.in @@ -373,10 +373,11 @@ menu "MODEM SLEEP Options" modem sleep to be used with both DFS and light sleep. config BT_CTRL_LPCLK_SEL_RTC_SLOW - bool "Internal 90kHz RC oscillator" + bool "Internal 150kHz RC oscillator" depends on ESP32S3_RTC_CLK_SRC_INT_RC help - Internal 90kHz RC oscillator. + Internal 150kHz RC oscillator. The accuracy of this clock is a lot larger than 500ppm which is required + in Bluetooth communication, so don't select this option in scenarios such as BLE connection state. endchoice diff --git a/components/bt/controller/esp32s3/bt.c b/components/bt/controller/esp32s3/bt.c index a4bacd2d3e..4190c7b05a 100644 --- a/components/bt/controller/esp32s3/bt.c +++ b/components/bt/controller/esp32s3/bt.c @@ -972,7 +972,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) // configure and initialize resources s_lp_cntl.enable = (cfg->sleep_mode == ESP_BT_SLEEP_MODE_1) ? 1 : 0; - s_lp_cntl.no_light_sleep = 0; + s_lp_cntl.no_light_sleep = 1; if (s_lp_cntl.enable) { #if (CONFIG_MAC_BB_PD) @@ -1009,31 +1009,29 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT; btdm_lpcycle_us = 2 << (btdm_lpcycle_us_frac); - // // set default bluetooth sleep clock source - // s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_XTAL; + // set default bluetooth sleep clock source + s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_XTAL; // set default value #if CONFIG_BT_CTRL_LPCLK_SEL_EXT_32K_XTAL // check whether or not EXT_CRYS is working if (rtc_clk_slow_freq_get() == RTC_SLOW_FREQ_32K_XTAL) { - s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_XTAL32K; // set default value -// #ifdef CONFIG_PM_ENABLE -// s_btdm_allow_light_sleep = true; -// #endif + s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_XTAL32K; // External 32 kHz XTAL + s_lp_cntl.no_light_sleep = 0; } else { ESP_LOGW(BT_LOG_TAG, "32.768kHz XTAL not detected, fall back to main XTAL as Bluetooth sleep clock\n" "light sleep mode will not be able to apply when bluetooth is enabled"); - s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_XTAL; // set default value } #elif (CONFIG_BT_CTRL_LPCLK_SEL_RTC_SLOW) // check whether or not EXT_CRYS is working if (rtc_clk_slow_freq_get() == RTC_SLOW_FREQ_RTC) { - s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_RTC_SLOW; // set default value + s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_RTC_SLOW; // Internal 150 kHz RC oscillator + ESP_LOGW(BTDM_LOG_TAG, "Internal 150kHz RC osciallator. The accuracy of this clock is a lot larger than 500ppm which is " + "required in Bluetooth communication, so don't select this option in scenarios such as BLE connection state."); } else { - ESP_LOGW(BT_LOG_TAG, "Internal 90kHz RC oscillator not detected, fall back to main XTAL as Bluetooth sleep clock\n" - "light sleep mode will not be able to apply when bluetooth is enabled"); - s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_XTAL; // set default value + ESP_LOGW(BT_LOG_TAG, "Internal 150kHz RC oscillator not detected."); + assert(0); } #else - s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_XTAL; // set default value + s_lp_cntl.no_light_sleep = 1; #endif bool select_src_ret __attribute__((unused)); diff --git a/components/bt/controller/lib_esp32 b/components/bt/controller/lib_esp32 index b97b2abd1a..fe0a3d00f1 160000 --- a/components/bt/controller/lib_esp32 +++ b/components/bt/controller/lib_esp32 @@ -1 +1 @@ -Subproject commit b97b2abd1a98ab887fb4cdc0553fabcba95aedaf +Subproject commit fe0a3d00f11dbf9d219f2a291e3cab7419e5cac1 diff --git a/components/bt/controller/lib_esp32c3_family b/components/bt/controller/lib_esp32c3_family index b223604efd..32f15e826a 160000 --- a/components/bt/controller/lib_esp32c3_family +++ b/components/bt/controller/lib_esp32c3_family @@ -1 +1 @@ -Subproject commit b223604efd557d0a5314afb3b751229df424d244 +Subproject commit 32f15e826a102d2d64e612620468122ea2234a2e diff --git a/components/bt/esp_ble_mesh/Kconfig.in b/components/bt/esp_ble_mesh/Kconfig.in index 964f52b13f..38e9caa01d 100644 --- a/components/bt/esp_ble_mesh/Kconfig.in +++ b/components/bt/esp_ble_mesh/Kconfig.in @@ -9,10 +9,10 @@ if BLE_MESH config BLE_MESH_USE_DUPLICATE_SCAN bool "Support Duplicate Scan in BLE Mesh" depends on BT_BLUEDROID_ENABLED - select BTDM_BLE_SCAN_DUPL if BT_CTRL_ESP32 - select BTDM_BLE_MESH_SCAN_DUPL_EN if BT_CTRL_ESP32 - select BT_CTRL_BLE_SCAN_DUPL if BT_CTRL_ESP32C3 - select BT_CTRL_BLE_MESH_SCAN_DUPL_EN if BT_CTRL_ESP32C3 + select BTDM_BLE_SCAN_DUPL if IDF_TARGET_ESP32 + select BTDM_BLE_MESH_SCAN_DUPL_EN if IDF_TARGET_ESP32 + select BT_CTRL_BLE_SCAN_DUPL if IDF_TARGET_ESP32C3 + select BT_CTRL_BLE_MESH_SCAN_DUPL_EN if IDF_TARGET_ESP32C3 default y help Enable this option to allow using specific duplicate scan filter diff --git a/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_provisioning_api.h b/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_provisioning_api.h index efa3dc0851..5dac5308b4 100644 --- a/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_provisioning_api.h +++ b/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_provisioning_api.h @@ -69,6 +69,12 @@ esp_err_t esp_ble_mesh_node_prov_disable(esp_ble_mesh_prov_bearer_t bearers); /** * @brief Unprovisioned device set own oob public key & private key pair. * + * @note In order to avoid suffering brute-forcing attack (CVE-2020-26559). + * The Bluetooth SIG recommends that potentially vulnerable mesh provisioners + * use an out-of-band mechanism to exchange the public keys. + * So as an unprovisioned device, it should use this function to input + * the Public Key exchanged through the out-of-band mechanism. + * * @param[in] pub_key_x: Unprovisioned device's Public Key X * @param[in] pub_key_y: Unprovisioned device's Public Key Y * @param[in] private_key: Unprovisioned device's Private Key @@ -121,6 +127,10 @@ esp_err_t esp_ble_mesh_set_unprovisioned_device_name(const char *name); /** * @brief Provisioner inputs unprovisioned device's oob public key. * + * @note In order to avoid suffering brute-forcing attack (CVE-2020-26559). + * The Bluetooth SIG recommends that potentially vulnerable mesh provisioners + * use an out-of-band mechanism to exchange the public keys. + * * @param[in] link_idx: The provisioning link index * @param[in] pub_key_x: Unprovisioned device's Public Key X * @param[in] pub_key_y: Unprovisioned device's Public Key Y @@ -329,6 +339,14 @@ esp_err_t esp_ble_mesh_provisioner_set_prov_data_info(esp_ble_mesh_prov_data_inf * A large entropy helps ensure that a brute-force of the AuthValue, even a static * AuthValue, cannot normally be completed in a reasonable time (CVE-2020-26557). * + * AuthValues selected using a cryptographically secure random or pseudorandom number + * generator and having the maximum permitted entropy (128-bits) will be most difficult + * to brute-force. AuthValues with reduced entropy or generated in a predictable manner + * will not grant the same level of protection against this vulnerability. Selecting a + * new AuthValue with each provisioning attempt can also make it more difficult to launch + * a brute-force attack by requiring the attacker to restart the search with each + * provisioning attempt (CVE-2020-26556). + * * @param[in] value: Pointer to the static oob value. * @param[in] length: Length of the static oob value. * diff --git a/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h b/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h index e056d77ac2..66dccf307c 100644 --- a/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h +++ b/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h @@ -573,8 +573,10 @@ typedef struct { esp_ble_mesh_prov_oob_info_t oob_info; /* NOTE: In order to avoid suffering brute-forcing attack (CVE-2020-26559). - * The Bluetooth SIG recommends that potentially vulnerable mesh node + * The Bluetooth SIG recommends that potentially vulnerable mesh provisioners * support an out-of-band mechanism to exchange the public keys. + * So as an unprovisioned device, it should enable this flag to support + * using an out-of-band mechanism to exchange Public Key. */ /** Flag indicates whether unprovisioned devices support OOB public key */ bool oob_pub_key; @@ -629,7 +631,7 @@ typedef struct { /** Provisioning Algorithm for the Provisioner */ uint8_t prov_algorithm; - /* NOTE: In order to avoid suffering brute-forcing attack(CVE-2020-26559). + /* NOTE: In order to avoid suffering brute-forcing attack (CVE-2020-26559). * The Bluetooth SIG recommends that potentially vulnerable mesh provisioners * use an out-of-band mechanism to exchange the public keys. */ @@ -643,6 +645,14 @@ typedef struct { * selected AuthValue using all of the available bits, where permitted by the * implementation. A large entropy helps ensure that a brute-force of the AuthValue, * even a static AuthValue, cannot normally be completed in a reasonable time (CVE-2020-26557). + * + * AuthValues selected using a cryptographically secure random or pseudorandom number + * generator and having the maximum permitted entropy (128-bits) will be most difficult + * to brute-force. AuthValues with reduced entropy or generated in a predictable manner + * will not grant the same level of protection against this vulnerability. Selecting a + * new AuthValue with each provisioning attempt can also make it more difficult to launch + * a brute-force attack by requiring the attacker to restart the search with each + * provisioning attempt (CVE-2020-26556). */ /** Provisioner static oob value */ uint8_t *prov_static_oob_val; diff --git a/components/bt/esp_ble_mesh/mesh_core/provisioner_prov.c b/components/bt/esp_ble_mesh/mesh_core/provisioner_prov.c index 8cc406a0f0..be549ee40e 100644 --- a/components/bt/esp_ble_mesh/mesh_core/provisioner_prov.c +++ b/components/bt/esp_ble_mesh/mesh_core/provisioner_prov.c @@ -1930,6 +1930,19 @@ static int prov_auth(const uint8_t idx, uint8_t method, uint8_t action, uint8_t /* Provisioner ouput number/string and wait for device's Provisioning Input Complete PDU */ link[idx].expect = PROV_INPUT_COMPLETE; + /* NOTE: The Bluetooth SIG recommends that mesh implementations enforce a randomly + * selected AuthValue using all of the available bits, where permitted by the + * implementation. A large entropy helps ensure that a brute-force of the AuthValue, + * even a static AuthValue, cannot normally be completed in a reasonable time (CVE-2020-26557). + * + * AuthValues selected using a cryptographically secure random or pseudorandom number + * generator and having the maximum permitted entropy (128-bits) will be most difficult + * to brute-force. AuthValues with reduced entropy or generated in a predictable manner + * will not grant the same level of protection against this vulnerability. Selecting a + * new AuthValue with each provisioning attempt can also make it more difficult to launch + * a brute-force attack by requiring the attacker to restart the search with each + * provisioning attempt (CVE-2020-26556). + */ if (input == BLE_MESH_ENTER_STRING) { unsigned char str[9] = {'\0'}; uint8_t j = 0U; @@ -2312,12 +2325,11 @@ static void prov_confirm(const uint8_t idx, const uint8_t *data) BT_DBG("Remote Confirm: %s", bt_hex(data, 16)); - /* NOTE: The Bluetooth SIG recommends that potentially vulnerable mesh - * provisioners restrict the authentication procedure and not accept - * provisioning random and provisioning confirmation numbers from a remote - * peer that are the same as those selected by the local device (CVE-2020-26556 - * & CVE-2020-26560). - * */ + /* NOTE: The Bluetooth SIG recommends that potentially vulnerable mesh provisioners + * restrict the authentication procedure and not accept provisioning random and + * provisioning confirmation numbers from a remote peer that are the same as those + * selected by the local device (CVE-2020-26560). + */ if (!memcmp(data, link[idx].local_conf, 16)) { BT_ERR("Confirmation value is identical to ours, rejecting."); close_link(idx, CLOSE_REASON_FAILED); @@ -2534,12 +2546,11 @@ static void prov_random(const uint8_t idx, const uint8_t *data) BT_DBG("Remote Random: %s", bt_hex(data, 16)); - /* NOTE: The Bluetooth SIG recommends that potentially vulnerable mesh - * provisioners restrict the authentication procedure and not accept - * provisioning random and provisioning confirmation numbers from a remote - * peer that are the same as those selected by the local device (CVE-2020-26556 - * & CVE-2020-26560). - * */ + /* NOTE: The Bluetooth SIG recommends that potentially vulnerable mesh provisioners + * restrict the authentication procedure and not accept provisioning random and + * provisioning confirmation numbers from a remote peer that are the same as those + * selected by the local device (CVE-2020-26560). + */ if (!memcmp(data, link[idx].rand, 16)) { BT_ERR("Random value is identical to ours, rejecting."); goto fail; diff --git a/components/bt/host/bluedroid/Kconfig.in b/components/bt/host/bluedroid/Kconfig.in index 47980eeb28..0b41479221 100644 --- a/components/bt/host/bluedroid/Kconfig.in +++ b/components/bt/host/bluedroid/Kconfig.in @@ -42,7 +42,7 @@ config BT_BLUEDROID_MEM_DEBUG config BT_CLASSIC_ENABLED bool "Classic Bluetooth" - depends on BT_BLUEDROID_ENABLED && BT_CTRL_ESP32 + depends on BT_BLUEDROID_ENABLED && IDF_TARGET_ESP32 default n help For now this option needs "SMP_ENABLE" to be set to yes @@ -99,13 +99,27 @@ config BT_HFP_WBS_ENABLE This enables Wide Band Speech. Should disable it when SCO data path is PCM. Otherwise there will be no data transmited via GPIOs. -config BT_HID_HOST_ENABLED - bool "Classic BT HID Host" +config BT_HID_ENABLED + bool "Classic BT HID" depends on BT_CLASSIC_ENABLED default n help This enables the BT HID Host +choice BT_HID_ROLE + prompt "Profile Role configuration" + depends on BT_HID_ENABLED + config BT_HID_HOST_ENABLED + bool "Classic BT HID Host" + help + This enables the BT HID Host + + config BT_HID_DEVICE_ENABLED + bool "Classic BT HID Device" + help + This enables the BT HID Device +endchoice + config BT_SSP_ENABLED bool "Secure Simple Pairing" depends on BT_CLASSIC_ENABLED @@ -1056,8 +1070,3 @@ config BT_BLE_42_FEATURES_SUPPORTED default n help This enables BLE 4.2 features. - -config BT_RESERVE_DRAM - hex - default 0xdb5c if BT_ENABLED - default 0 diff --git a/components/bt/host/bluedroid/api/esp_hidd_api.c b/components/bt/host/bluedroid/api/esp_hidd_api.c new file mode 100644 index 0000000000..fafe8f8e6e --- /dev/null +++ b/components/bt/host/bluedroid/api/esp_hidd_api.c @@ -0,0 +1,176 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// Copyright 2019 Blake Felt +// +// 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 +#include "esp_err.h" +#include "esp_bt_main.h" +#include "btc/btc_manage.h" +#include "btc_hd.h" +#include "esp_hidd_api.h" + +#if (defined BTC_HD_INCLUDED && BTC_HD_INCLUDED == TRUE) + +esp_err_t esp_bt_hid_device_register_callback(esp_hd_cb_t *callback) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + if (callback == NULL) { + return ESP_FAIL; + } + + btc_profile_cb_set(BTC_PID_HD, callback); + return ESP_OK; +} + +esp_err_t esp_bt_hid_device_init(void) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + btc_msg_t msg; + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HD; + msg.act = BTC_HD_INIT_EVT; + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_bt_hid_device_deinit(void) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + btc_msg_t msg; + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HD; + msg.act = BTC_HD_DEINIT_EVT; + + bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_bt_hid_device_register_app(esp_hidd_app_param_t* app_param, esp_hidd_qos_param_t* in_qos, esp_hidd_qos_param_t* out_qos) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + btc_msg_t msg; + btc_hidd_args_t args; + memset(&args, 0, sizeof(btc_hidd_args_t)); + args.register_app.app_param = app_param; + args.register_app.in_qos = in_qos; + args.register_app.out_qos = out_qos; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HD; + msg.act = BTC_HD_REGISTER_APP_EVT; + + bt_status_t stat = btc_transfer_context(&msg, &args, sizeof(btc_hidd_args_t), NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_bt_hid_device_unregister_app(void) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + btc_msg_t msg; + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HD; + msg.act = BTC_HD_UNREGISTER_APP_EVT; + + bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_bt_hid_device_connect(esp_bd_addr_t bd_addr) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + btc_msg_t msg; + btc_hidd_args_t args; + memset(&args, 0, sizeof(btc_hidd_args_t)); + memcpy(args.connect.bd_addr, bd_addr, sizeof(esp_bd_addr_t)); + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HD; + msg.act = BTC_HD_CONNECT_EVT; + + bt_status_t stat = btc_transfer_context(&msg, &args, sizeof(btc_hidd_args_t), NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_bt_hid_device_disconnect(void) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + btc_msg_t msg; + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HD; + msg.act = BTC_HD_DISCONNECT_EVT; + + bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_bt_hid_device_send_report(esp_hidd_report_type_t type, uint8_t id, uint16_t len, uint8_t* data) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + btc_msg_t msg; + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HD; + msg.act = BTC_HD_SEND_REPORT_EVT; + + btc_hidd_args_t args; + memset(&args, 0, sizeof(btc_hidd_args_t)); + args.send_report.type = type; + args.send_report.id = id; + args.send_report.len = len; + args.send_report.data = data; + + bt_status_t stat = btc_transfer_context(&msg, &args, sizeof(btc_hidd_args_t), btc_hd_arg_deep_copy); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_bt_hid_device_report_error(esp_hidd_handshake_error_t error) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + btc_msg_t msg; + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HD; + msg.act = BTC_HD_REPORT_ERROR_EVT; + + btc_hidd_args_t args; + memset(&args, 0, sizeof(btc_hidd_args_t)); + args.error = error; + + bt_status_t stat = btc_transfer_context(&msg, &args, sizeof(btc_hidd_args_t), NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_bt_hid_device_virtual_cable_unplug(void) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + btc_msg_t msg; + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HD; + msg.act = BTC_HD_UNPLUG_EVT; + + bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +#endif /* defined BTC_HD_INCLUDED && BTC_HD_INCLUDED == TRUE */ diff --git a/components/bt/host/bluedroid/api/esp_hidh_api.c b/components/bt/host/bluedroid/api/esp_hidh_api.c new file mode 100644 index 0000000000..b62a1a7006 --- /dev/null +++ b/components/bt/host/bluedroid/api/esp_hidh_api.c @@ -0,0 +1,254 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// Copyright 2019 Blake Felt +// +// 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 "btc/btc_manage.h" +#include "btc_hh.h" +#include "esp_bt_main.h" +#include "esp_err.h" +#include "esp_hidh_api.h" +#include + +#if (defined BTC_HH_INCLUDED && BTC_HH_INCLUDED == TRUE) + +esp_err_t esp_bt_hid_host_register_callback(esp_hh_cb_t *callback) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + if (callback == NULL) { + return ESP_FAIL; + } + + btc_profile_cb_set(BTC_PID_HH, callback); + return ESP_OK; +} + +esp_err_t esp_bt_hid_host_init(void) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + btc_msg_t msg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HH; + msg.act = BTC_HH_INIT_EVT; + + bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_bt_hid_host_deinit(void) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + btc_msg_t msg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HH; + msg.act = BTC_HH_DEINIT_EVT; + + bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_bt_hid_host_connect(esp_bd_addr_t bd_addr) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + btc_msg_t msg; + btc_hidh_args_t arg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HH; + msg.act = BTC_HH_CONNECT_EVT; + + memcpy(arg.connect.bd_addr, bd_addr, sizeof(esp_bd_addr_t)); + + bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_bt_hid_host_disconnect(esp_bd_addr_t bd_addr) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + btc_msg_t msg; + btc_hidh_args_t arg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HH; + msg.act = BTC_HH_DISCONNECT_EVT; + + memcpy(arg.disconnect.bd_addr, bd_addr, sizeof(esp_bd_addr_t)); + + bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_bt_hid_host_virtual_cable_unplug(esp_bd_addr_t bd_addr) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + btc_msg_t msg; + btc_hidh_args_t arg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HH; + msg.act = BTC_HH_UNPLUG_EVT; + + memcpy(arg.unplug.bd_addr, bd_addr, sizeof(esp_bd_addr_t)); + + bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_bt_hid_host_set_info(esp_bd_addr_t bd_addr, esp_hidh_hid_info_t *hid_info) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + btc_msg_t msg; + btc_hidh_args_t arg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HH; + msg.act = BTC_HH_SET_INFO_EVT; + + memcpy(arg.set_info.bd_addr, bd_addr, sizeof(esp_bd_addr_t)); + arg.set_info.hid_info = hid_info; + + bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), btc_hh_arg_deep_copy); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_bt_hid_host_get_protocol(esp_bd_addr_t bd_addr) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + btc_msg_t msg; + btc_hidh_args_t arg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HH; + msg.act = BTC_HH_GET_PROTO_EVT; + + memcpy(arg.get_protocol.bd_addr, bd_addr, sizeof(esp_bd_addr_t)); + + bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_bt_hid_host_set_protocol(esp_bd_addr_t bd_addr, esp_hidh_protocol_mode_t protocol_mode) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + btc_msg_t msg; + btc_hidh_args_t arg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HH; + msg.act = BTC_HH_SET_PROTO_EVT; + + memcpy(arg.set_protocol.bd_addr, bd_addr, sizeof(esp_bd_addr_t)); + arg.set_protocol.protocol_mode = protocol_mode; + + bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_bt_hid_host_get_idle(esp_bd_addr_t bd_addr) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + btc_msg_t msg; + btc_hidh_args_t arg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HH; + msg.act = BTC_HH_GET_IDLE_EVT; + + memcpy(arg.get_idle.bd_addr, bd_addr, sizeof(esp_bd_addr_t)); + + bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_bt_hid_host_set_idle(esp_bd_addr_t bd_addr, uint16_t idle_time) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + btc_msg_t msg; + btc_hidh_args_t arg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HH; + msg.act = BTC_HH_SET_IDLE_EVT; + + memcpy(arg.set_idle.bd_addr, bd_addr, sizeof(esp_bd_addr_t)); + arg.set_idle.idle_time = idle_time; + + bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_bt_hid_host_get_report(esp_bd_addr_t bd_addr, esp_hidh_report_type_t report_type, uint8_t report_id, + int buffer_size) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + btc_msg_t msg; + btc_hidh_args_t arg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HH; + msg.act = BTC_HH_GET_REPORT_EVT; + + memcpy(arg.get_report.bd_addr, bd_addr, sizeof(esp_bd_addr_t)); + arg.get_report.report_type = report_type; + arg.get_report.report_id = report_id; + arg.get_report.buffer_size = buffer_size; + + bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_bt_hid_host_set_report(esp_bd_addr_t bd_addr, esp_hidh_report_type_t report_type, uint8_t *report, + size_t len) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + btc_msg_t msg; + btc_hidh_args_t arg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HH; + msg.act = BTC_HH_SET_REPORT_EVT; + + memcpy(arg.set_report.bd_addr, bd_addr, sizeof(esp_bd_addr_t)); + arg.set_report.report_type = report_type; + arg.set_report.len = len; + arg.set_report.report = report; + + bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), btc_hh_arg_deep_copy); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_bt_hid_host_send_data(esp_bd_addr_t bd_addr, uint8_t *data, size_t len) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + btc_msg_t msg; + btc_hidh_args_t arg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HH; + msg.act = BTC_HH_SEND_DATA_EVT; + + memcpy(arg.send_data.bd_addr, bd_addr, sizeof(esp_bd_addr_t)); + arg.send_data.len = len; + arg.send_data.data = data; + + bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), btc_hh_arg_deep_copy); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +#endif /* defined BTC_HH_INCLUDED && BTC_HH_INCLUDED == TRUE */ 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 ce30993585..dd48ab982d 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 @@ -467,7 +467,7 @@ typedef struct { uint16_t rx_len; /*!< pkt rx data length value */ uint16_t tx_len; /*!< pkt tx data length value */ -}esp_ble_pkt_data_length_params_t; +} esp_ble_pkt_data_length_params_t; /** * @brief BLE encryption keys @@ -648,7 +648,7 @@ typedef enum { typedef enum{ ESP_BLE_WHITELIST_REMOVE = 0X00, /*!< remove mac from whitelist */ ESP_BLE_WHITELIST_ADD = 0X01, /*!< add address to whitelist */ -}esp_ble_wl_opration_t; +} esp_ble_wl_opration_t; #if (BLE_42_FEATURE_SUPPORT == TRUE) typedef enum { ESP_BLE_DUPLICATE_EXCEPTIONAL_LIST_ADD = 0, /*!< Add device info into duplicate scan exceptional list */ @@ -998,7 +998,7 @@ typedef union { uint16_t conn_int; /*!< Current connection interval */ uint16_t timeout; /*!< Supervision timeout for the LE Link. Range: 0x000A to 0x0C80. Mandatory Range: 0x000A to 0x0C80 Time = N * 10 msec */ - }update_conn_params; /*!< Event parameter of ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT */ + } update_conn_params; /*!< Event parameter of ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT */ /** * @brief ESP_GAP_BLE_SET_PKT_LENGTH_COMPLETE_EVT */ @@ -1018,13 +1018,13 @@ typedef union { struct ble_remove_bond_dev_cmpl_evt_param { esp_bt_status_t status; /*!< Indicate the remove bond device operation success status */ esp_bd_addr_t bd_addr; /*!< The device address which has been remove from the bond list */ - }remove_bond_dev_cmpl; /*!< Event parameter of ESP_GAP_BLE_REMOVE_BOND_DEV_COMPLETE_EVT */ + } remove_bond_dev_cmpl; /*!< Event parameter of ESP_GAP_BLE_REMOVE_BOND_DEV_COMPLETE_EVT */ /** * @brief ESP_GAP_BLE_CLEAR_BOND_DEV_COMPLETE_EVT */ struct ble_clear_bond_dev_cmpl_evt_param { esp_bt_status_t status; /*!< Indicate the clear bond device operation success status */ - }clear_bond_dev_cmpl; /*!< Event parameter of ESP_GAP_BLE_CLEAR_BOND_DEV_COMPLETE_EVT */ + } clear_bond_dev_cmpl; /*!< Event parameter of ESP_GAP_BLE_CLEAR_BOND_DEV_COMPLETE_EVT */ /** * @brief ESP_GAP_BLE_GET_BOND_DEV_COMPLETE_EVT */ @@ -1032,7 +1032,7 @@ typedef union { esp_bt_status_t status; /*!< Indicate the get bond device operation success status */ uint8_t dev_num; /*!< Indicate the get number device in the bond list */ esp_ble_bond_dev_t *bond_dev; /*!< the pointer to the bond device Structure */ - }get_bond_dev_cmpl; /*!< Event parameter of ESP_GAP_BLE_GET_BOND_DEV_COMPLETE_EVT */ + } get_bond_dev_cmpl; /*!< Event parameter of ESP_GAP_BLE_GET_BOND_DEV_COMPLETE_EVT */ /** * @brief ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT */ diff --git a/components/bt/host/bluedroid/api/include/api/esp_gattc_api.h b/components/bt/host/bluedroid/api/include/api/esp_gattc_api.h index 077cca3850..4071909634 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_gattc_api.h +++ b/components/bt/host/bluedroid/api/include/api/esp_gattc_api.h @@ -380,7 +380,7 @@ esp_err_t esp_ble_gattc_search_service(esp_gatt_if_t gattc_if, uint16_t conn_id, /** * @brief Find all the service with the given service uuid in the gattc cache, if the svc_uuid is NULL, find all the service. * Note: It just get service from local cache, won't get from remote devices. If want to get it from remote device, need - * to used the esp_ble_gattc_search_service. + * to used the esp_ble_gattc_cache_refresh, then call esp_ble_gattc_get_service again. * * @param[in] gattc_if: Gatt client access interface. * @param[in] conn_id: connection ID which identify the server. diff --git a/components/bt/host/bluedroid/api/include/api/esp_hidd_api.h b/components/bt/host/bluedroid/api/include/api/esp_hidd_api.h new file mode 100644 index 0000000000..de90ff8efc --- /dev/null +++ b/components/bt/host/bluedroid/api/include/api/esp_hidd_api.h @@ -0,0 +1,379 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// Copyright 2019 Blake Felt +// +// 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. + +#ifndef __ESP_HIDD_API_H__ +#define __ESP_HIDD_API_H__ + +#include "esp_bt_defs.h" +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* sub_class of hid device */ +#define ESP_HID_CLASS_UNKNOWN (0x00<<2) +#define ESP_HID_CLASS_JOS (0x01<<2) /* joy stick */ +#define ESP_HID_CLASS_GPD (0x02<<2) /* game pad */ +#define ESP_HID_CLASS_RMC (0x03<<2) /* remote control */ +#define ESP_HID_CLASS_SED (0x04<<2) /* sensing device */ +#define ESP_HID_CLASS_DGT (0x05<<2) /* Digitizer tablet */ +#define ESP_HID_CLASS_CDR (0x06<<2) /* card reader */ +#define ESP_HID_CLASS_KBD (0x10<<2) /* keyboard */ +#define ESP_HID_CLASS_MIC (0x20<<2) /* pointing device */ +#define ESP_HID_CLASS_COM (0x30<<2) /* Combo keyboard/pointing */ + +/** + * @brief HIDD handshake error + */ +typedef enum { + ESP_HID_PAR_HANDSHAKE_RSP_SUCCESS = 0, + ESP_HID_PAR_HANDSHAKE_RSP_NOT_READY = 1, + ESP_HID_PAR_HANDSHAKE_RSP_ERR_INVALID_REP_ID = 2, + ESP_HID_PAR_HANDSHAKE_RSP_ERR_UNSUPPORTED_REQ = 3, + ESP_HID_PAR_HANDSHAKE_RSP_ERR_INVALID_PARAM = 4, + ESP_HID_PAR_HANDSHAKE_RSP_ERR_UNKNOWN = 14, + ESP_HID_PAR_HANDSHAKE_RSP_ERR_FATAL = 15 +} esp_hidd_handshake_error_t; + +/** + * @brief HIDD report types + */ +typedef enum { + ESP_HIDD_REPORT_TYPE_OTHER = 0, + ESP_HIDD_REPORT_TYPE_INPUT, + ESP_HIDD_REPORT_TYPE_OUTPUT, + ESP_HIDD_REPORT_TYPE_FEATURE, + // special value for reports to be sent on INTR(INPUT is assumed) + ESP_HIDD_REPORT_TYPE_INTRDATA +} esp_hidd_report_type_t; + +/** + * @brief HIDD connection state + */ +typedef enum { + ESP_HIDD_CONN_STATE_CONNECTED, + ESP_HIDD_CONN_STATE_CONNECTING, + ESP_HIDD_CONN_STATE_DISCONNECTED, + ESP_HIDD_CONN_STATE_DISCONNECTING, + ESP_HIDD_CONN_STATE_UNKNOWN +} esp_hidd_connection_state_t; + +/** + * @brief HID device protocol modes + */ +typedef enum { + ESP_HIDD_REPORT_MODE = 0x00, + ESP_HIDD_BOOT_MODE = 0x01, + ESP_HIDD_UNSUPPORTED_MODE = 0xff +} esp_hidd_protocol_mode_t; + + +/** + * @brief HIDD characteristics for SDP report + */ +typedef struct { + const char *name; + const char *description; + const char *provider; + uint8_t subclass; + uint8_t *desc_list; + int desc_list_len; +} esp_hidd_app_param_t; + +/** + * @brief HIDD Quality of Service parameters + */ +typedef struct { + uint8_t service_type; + uint32_t token_rate; + uint32_t token_bucket_size; + uint32_t peak_bandwidth; + uint32_t access_latency; + uint32_t delay_variation; +} esp_hidd_qos_param_t; + +/** + * @brief HID device callback function events + */ +typedef enum { + ESP_HIDD_INIT_EVT = 0, /*!< When HID device is inited, the event comes */ + ESP_HIDD_DEINIT_EVT, /*!< When HID device is deinited, the event comes */ + ESP_HIDD_REGISTER_APP_EVT, /*!< When HID device application registered, the event comes */ + ESP_HIDD_UNREGISTER_APP_EVT, /*!< When HID device application unregistered, the event comes */ + ESP_HIDD_OPEN_EVT, /*!< When HID device connection to host opened, the event comes */ + ESP_HIDD_CLOSE_EVT, /*!< When HID device connection to host closed, the event comes */ + ESP_HIDD_SEND_REPORT_EVT, /*!< When HID device send report to lower layer, the event comes */ + ESP_HIDD_REPORT_ERR_EVT, /*!< When HID device report handshanke error to lower layer, the event comes */ + ESP_HIDD_GET_REPORT_EVT, /*!< When HID device receives GET_REPORT request from host, the event comes */ + ESP_HIDD_SET_REPORT_EVT, /*!< When HID device receives SET_REPORT request from host, the event comes */ + ESP_HIDD_SET_PROTOCOL_EVT, /*!< When HID device receives SET_PROTOCOL request from host, the event comes */ + ESP_HIDD_INTR_DATA_EVT, /*!< When HID device receives DATA from host on intr, the event comes */ + ESP_HIDD_VC_UNPLUG_EVT, /*!< When HID device initiates Virtual Cable Unplug, the event comes */ + ESP_HIDD_API_ERR_EVT /*!< When HID device has API error, the event comes */ +} esp_hidd_cb_event_t; + +typedef enum { + ESP_HIDD_SUCCESS, + ESP_HIDD_ERROR, /*!< general ESP HD error */ + ESP_HIDD_NO_RES, /*!< out of system resources */ + ESP_HIDD_BUSY, /*!< Temporarily can not handle this request. */ + ESP_HIDD_NO_DATA, /*!< No data. */ + ESP_HIDD_NEED_INIT, /*!< HIDD module shall init first */ + ESP_HIDD_NEED_DEINIT, /*!< HIDD module shall deinit first */ + ESP_HIDD_NEED_REG, /*!< HIDD module shall register first */ + ESP_HIDD_NEED_DEREG, /*!< HIDD module shall deregister first */ + ESP_HIDD_NO_CONNECTION, /*!< connection may have been closed */ +} esp_hidd_status_t; + +/** + * @brief HID device callback parameters union + */ +typedef union { + /** + * @brief ESP_HIDD_INIT_EVT + */ + struct hidd_init_evt_param { + esp_hidd_status_t status; /*!< operation status */ + } init; /*!< HIDD callback param of ESP_HIDD_INIT_EVT */ + + /** + * @brief ESP_HIDD_DEINIT_EVT + */ + struct hidd_deinit_evt_param { + esp_hidd_status_t status; /*!< operation status */ + } deinit; /*!< HIDD callback param of ESP_HIDD_DEINIT_EVT */ + + /** + * @brief ESP_HIDD_REGISTER_APP_EVT + */ + struct hidd_register_app_evt_param { + esp_hidd_status_t status; /*!< operation status */ + bool in_use; /*!< indicate whether use virtual cable plug host address */ + esp_bd_addr_t bd_addr; /*!< host address */ + } register_app; /*!< HIDD callback param of ESP_HIDD_REGISTER_APP_EVT */ + + /** + * @brief ESP_HIDD_UNREGISTER_APP_EVT + */ + struct hidd_unregister_app_evt_param { + esp_hidd_status_t status; /*!< operation status */ + } unregister_app; /*!< HIDD callback param of ESP_HIDD_UNREGISTER_APP_EVT */ + + /** + * @brief ESP_HIDD_OPEN_EVT + */ + struct hidd_open_evt_param { + esp_hidd_status_t status; /*!< operation status */ + esp_hidd_connection_state_t conn_status; /*!< connection status */ + esp_bd_addr_t bd_addr; /*!< host address */ + } open; /*!< HIDD callback param of ESP_HIDD_OPEN_EVT */ + + /** + * @brief ESP_HIDD_CLOSE_EVT + */ + struct hidd_close_evt_param { + esp_hidd_status_t status; /*!< operation status */ + esp_hidd_connection_state_t conn_status; /*!< connection status */ + } close; /*!< HIDD callback param of ESP_HIDD_CLOSE_EVT */ + + /** + * @brief ESP_HIDD_SEND_REPORT_EVT + */ + struct hidd_send_report_evt_param { + esp_hidd_status_t status; /*!< operation status */ + uint8_t reason; /*!< lower layer failed reason(ref hiddefs.h) */ + esp_hidd_report_type_t report_type; /*!< report type */ + uint8_t report_id; /*!< report id */ + } send_report; /*!< HIDD callback param of ESP_HIDD_SEND_REPORT_EVT */ + + /** + * @brief ESP_HIDD_REPORT_ERR_EVT + */ + struct hidd_report_err_evt_param { + esp_hidd_status_t status; /*!< operation status */ + uint8_t reason; /*!< lower layer failed reason(ref hiddefs.h) */ + } report_err; /*!< HIDD callback param of ESP_HIDD_REPORT_ERR_EVT */ + + /** + * @brief ESP_HIDD_GET_REPORT_EVT + */ + struct hidd_get_report_evt_param { + esp_hidd_report_type_t report_type; /*!< report type */ + uint8_t report_id; /*!< report id */ + uint16_t buffer_size; /*!< buffer size */ + } get_report; /*!< HIDD callback param of ESP_HIDD_GET_REPORT_EVT */ + + /** + * @brief ESP_HIDD_SET_REPORT_EVT + */ + struct hidd_set_report_evt_param { + esp_hidd_report_type_t report_type; /*!< report type */ + uint8_t report_id; /*!< report id */ + uint16_t len; /*!< set_report data length */ + uint8_t *data; /*!< set_report data pointer */ + } set_report; /*!< HIDD callback param of ESP_HIDD_SET_REPORT_EVT */ + + /** + * @brief ESP_HIDD_SET_PROTOCOL_EVT + */ + struct hidd_set_protocol_evt_param { + esp_hidd_protocol_mode_t protocol_mode; /*!< protocol mode */ + } set_protocol; /*!< HIDD callback param of ESP_HIDD_SET_PROTOCOL_EVT */ + + /** + * @brief ESP_HIDD_INTR_DATA_EVT + */ + struct hidd_intr_data_evt_param { + uint8_t report_id; /*!< interrupt channel report id */ + uint16_t len; /*!< interrupt channel report data length */ + uint8_t *data; /*!< interrupt channel report data pointer */ + } intr_data; /*!< HIDD callback param of ESP_HIDD_INTR_DATA_EVT */ + + /** + * @brief ESP_HIDD_VC_UNPLUG_EVT + */ + struct hidd_vc_unplug_param { + esp_hidd_status_t status; /*!< operation status */ + esp_hidd_connection_state_t conn_status; /*!< connection status */ + } vc_unplug; /*!< HIDD callback param of ESP_HIDD_VC_UNPLUG_EVT */ +} esp_hidd_cb_param_t; + +/** + * @brief HID device callback function type. + * @param event: Event type + * @param param: Point to callback parameter, currently is union type + */ +typedef void (esp_hd_cb_t)(esp_hidd_cb_event_t event, esp_hidd_cb_param_t *param); + +/** + * @brief This function is called to init callbacks with HID device module. + * + * @param[in] callback: pointer to the init callback function. + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_bt_hid_device_register_callback(esp_hd_cb_t callback); + +/** + * @brief This function initializes HIDD. This function should be called after esp_bluedroid_enable and + * esp_blueroid_init success, and should be called after esp_bt_hid_device_register_callback. + * When the operation is complete the callback function will be called with ESP_HIDD_INIT_EVT. + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_bt_hid_device_init(void); + +/** + * @brief This function de-initializes HIDD interface. This function should be called after esp_bluedroid_enable() and + * esp_blueroid_init() success, and should be called after esp_bt_hid_device_init(). When the operation is complete the callback + * function will be called with ESP_HIDD_DEINIT_EVT. + * + * @return - ESP_OK: success + * - other: failed + */ +esp_err_t esp_bt_hid_device_deinit(void); + +/** + * @brief Registers HIDD parameters with SDP and sets l2cap Quality of Service. This function should be called after + * esp_bluedroid_enable and esp_blueroid_init success, and must be done after esp_bt_hid_device_init. When the operation is complete the callback + * function will be called with ESP_HIDD_REGISTER_APP_EVT. + * + * @param[in] app_param: HIDD parameters + * @param[in] in_qos: incoming QoS parameters + * @param[in] out_qos: outgoing QoS parameters + * + * @return - ESP_OK: success + * - other: failed + */ +esp_err_t esp_bt_hid_device_register_app(esp_hidd_app_param_t *app_param, esp_hidd_qos_param_t *in_qos, + esp_hidd_qos_param_t *out_qos); + +/** + * @brief Removes HIDD parameters from SDP and resets l2cap Quality of Service. This function should be called after esp_bluedroid_enable and + * esp_blueroid_init success, and should be called after esp_bt_hid_device_init. When the operation is complete the callback + * function will be called with ESP_HIDD_UNREGISTER_APP_EVT. + * + * @return - ESP_OK: success + * - other: failed + */ +esp_err_t esp_bt_hid_device_unregister_app(void); + +/** + * @brief This function connects HIDD interface to connected bluetooth device, if not done already. When the operation is complete the callback + * function will be called with ESP_HIDD_OPEN_EVT. + * + * @param[in] bd_addr: Remote host bluetooth device address. + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_bt_hid_device_connect(esp_bd_addr_t bd_addr); + +/** + * @brief This function disconnects HIDD interface. When the operation is complete the callback + * function will be called with ESP_HIDD_CLOSE_EVT. + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_bt_hid_device_disconnect(void); + +/** + * @brief Send HIDD report. When the operation is complete the callback + * function will be called with ESP_HIDD_SEND_REPORT_EVT. + * + * @param[in] type: type of report + * @param[in] id: report id as defined by descriptor + * @param[in] len: length of report + * @param[in] data: report data + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_bt_hid_device_send_report(esp_hidd_report_type_t type, uint8_t id, uint16_t len, uint8_t *data); + +/** + * @brief Sends HIDD handshake with error info for invalid set_report. When the operation is complete the callback + * function will be called with ESP_HIDD_REPORT_ERR_EVT. + * + * @param[in] error: type of error + * + * @return - ESP_OK: success + * - other: failed + */ +esp_err_t esp_bt_hid_device_report_error(esp_hidd_handshake_error_t error); + +/** + * @brief Unplug virtual cable of HIDD. When the operation is complete the callback + * function will be called with ESP_HIDD_VC_UNPLUG_EVT. + * + * @return - ESP_OK: success + * - other: failed + */ +esp_err_t esp_bt_hid_device_virtual_cable_unplug(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/bt/host/bluedroid/api/include/api/esp_hidh_api.h b/components/bt/host/bluedroid/api/include/api/esp_hidh_api.h new file mode 100644 index 0000000000..07abdece2d --- /dev/null +++ b/components/bt/host/bluedroid/api/include/api/esp_hidh_api.h @@ -0,0 +1,465 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// Copyright 2019 Blake Felt +// +// 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. + +#ifndef __ESP_HIDH_API_H__ +#define __ESP_HIDH_API_H__ + +#include "esp_bt_defs.h" +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define BTHH_MAX_DSC_LEN 884 + +/** + * @brief HID host connection state + */ +typedef enum { + ESP_HIDH_CONN_STATE_CONNECTED = 0, /*!< connected state */ + ESP_HIDH_CONN_STATE_CONNECTING, /*!< connecting state */ + ESP_HIDH_CONN_STATE_DISCONNECTED, /*!< disconnected state */ + ESP_HIDH_CONN_STATE_DISCONNECTING, /*!< disconnecting state */ + ESP_HIDH_CONN_STATE_UNKNOWN /*!< unknown state(initial state) */ +} esp_hidh_connection_state_t; + +typedef enum { + ESP_HIDH_OK, + ESP_HIDH_HS_HID_NOT_READY, /*!< handshake error : device not ready */ + ESP_HIDH_HS_INVALID_RPT_ID, /*!< handshake error : invalid report ID */ + ESP_HIDH_HS_TRANS_NOT_SPT, /*!< handshake error : transaction not spt */ + ESP_HIDH_HS_INVALID_PARAM, /*!< handshake error : invalid paremter */ + ESP_HIDH_HS_ERROR, /*!< handshake error : unspecified HS error */ + ESP_HIDH_ERR, /*!< general ESP HH error */ + ESP_HIDH_ERR_SDP, /*!< SDP error */ + ESP_HIDH_ERR_PROTO, /*!< SET_Protocol error, + only used in ESP_HIDH_OPEN_EVT callback */ + + ESP_HIDH_ERR_DB_FULL, /*!< device database full error, used in + ESP_HIDH_OPEN_EVT/ESP_HIDH_ADD_DEV_EVT */ + ESP_HIDH_ERR_TOD_UNSPT, /*!< type of device not supported */ + ESP_HIDH_ERR_NO_RES, /*!< out of system resources */ + ESP_HIDH_ERR_AUTH_FAILED, /*!< authentication fail */ + ESP_HIDH_ERR_HDL, /*!< connection handle error */ + ESP_HIDH_ERR_SEC, /*!< encryption error */ + // self_defined + ESP_HIDH_BUSY, /*!< Temporarily can not handle this request. */ + ESP_HIDH_NO_DATA, /*!< No data. */ + ESP_HIDH_NEED_INIT, /*!< HIDH module shall init first */ + ESP_HIDH_NEED_DEINIT, /*!< HIDH module shall deinit first */ + ESP_HIDH_NO_CONNECTION, /*!< connection may have been closed */ +} esp_hidh_status_t; + +/** + * @brief HID host protocol modes + */ +typedef enum { + ESP_HIDH_BOOT_MODE = 0x00, /*!< boot protocol mode */ + ESP_HIDH_REPORT_MODE = 0x01, /*!< report protocol mode */ + ESP_HIDH_UNSUPPORTED_MODE = 0xff /*!< unsupported protocol mode */ +} esp_hidh_protocol_mode_t; + +/** + * @brief HID host report types + */ +typedef enum { + ESP_HIDH_REPORT_TYPE_OTHER = 0, /*!< unsupported report type */ + ESP_HIDH_REPORT_TYPE_INPUT, /*!< input report type */ + ESP_HIDH_REPORT_TYPE_OUTPUT, /*!< output report type */ + ESP_HIDH_REPORT_TYPE_FEATURE, /*!< feature report type */ +} esp_hidh_report_type_t; + +/** + * @brief HID host callback function events + */ +typedef enum { + ESP_HIDH_INIT_EVT = 0, /*!< When HID host is inited, the event comes */ + ESP_HIDH_DEINIT_EVT, /*!< When HID host is deinited, the event comes */ + ESP_HIDH_OPEN_EVT, /*!< When HID host connection opened, the event comes */ + ESP_HIDH_CLOSE_EVT, /*!< When HID host connection closed, the event comes */ + ESP_HIDH_GET_RPT_EVT, /*!< When Get_Report command is called, the event comes */ + ESP_HIDH_SET_RPT_EVT, /*!< When Set_Report command is called, the event comes */ + ESP_HIDH_GET_PROTO_EVT, /*!< When Get_Protocol command is called, the event comes */ + ESP_HIDH_SET_PROTO_EVT, /*!< When Set_Protocol command is called, the event comes */ + ESP_HIDH_GET_IDLE_EVT, /*!< When Get_Idle command is called, the event comes */ + ESP_HIDH_SET_IDLE_EVT, /*!< When Set_Idle command is called, the event comes */ + ESP_HIDH_GET_DSCP_EVT, /*!< When HIDH is inited, the event comes */ + ESP_HIDH_ADD_DEV_EVT, /*!< When a device is added, the event comes */ + ESP_HIDH_RMV_DEV_EVT, /*!< When a device is removed, the event comes */ + ESP_HIDH_VC_UNPLUG_EVT, /*!< When virtually unplugged, the event comes */ + ESP_HIDH_DATA_EVT, /*!< When send data on interrupt channel, the event comes */ + ESP_HIDH_DATA_IND_EVT, /*!< When receive data on interrupt channel, the event comes */ + ESP_HIDH_SET_INFO_EVT /*!< When set the HID device descriptor, the event comes */ +} esp_hidh_cb_event_t; + +typedef struct { + int attr_mask; + uint8_t sub_class; + uint8_t app_id; + int vendor_id; + int product_id; + int version; + uint8_t ctry_code; + int dl_len; + uint8_t dsc_list[BTHH_MAX_DSC_LEN]; +} esp_hidh_hid_info_t; + +/** + * @brief HID host callback parameters union + */ +typedef union { + /** + * @brief ESP_HIDH_INIT_EVT + */ + struct hidh_init_evt_param { + esp_hidh_status_t status; /*!< status */ + } init; /*!< HIDH callback param of ESP_HIDH_INIT_EVT */ + + /** + * @brief ESP_HIDH_DEINIT_EVT + */ + struct hidh_uninit_evt_param { + esp_hidh_status_t status; /*!< status */ + } deinit; /*!< HIDH callback param of ESP_HIDH_DEINIT_EVT */ + + /** + * @brief ESP_HIDH_OPEN_EVT + */ + struct hidh_open_evt_param { + esp_hidh_status_t status; /*!< operation status */ + esp_hidh_connection_state_t conn_status; /*!< connection status */ + bool is_orig; /*!< indicate if host intiate the connection */ + uint8_t handle; /*!< device handle */ + esp_bd_addr_t bd_addr; /*!< device address */ + } open; /*!< HIDH callback param of ESP_HIDH_OPEN_EVT */ + + /** + * @brief ESP_HIDH_CLOSE_EVT + */ + struct hidh_close_evt_param { + esp_hidh_status_t status; /*!< operation status */ + uint8_t reason; /*!< lower layer failed reason(ref hiddefs.h) */ + esp_hidh_connection_state_t conn_status; /*!< connection status */ + uint8_t handle; /*!< device handle */ + } close; /*!< HIDH callback param of ESP_HIDH_CLOSE_EVT */ + + /** + * @brief ESP_HIDH_VC_UNPLUG_EVT + */ + struct hidh_unplug_evt_param { + esp_hidh_status_t status; /*!< operation status */ + esp_hidh_connection_state_t conn_status; /*!< connection status */ + uint8_t handle; /*!< device handle */ + } unplug; /*!< HIDH callback param of ESP_HIDH_VC_UNPLUG_EVT */ + + /** + * @brief ESP_HIDH_GET_PROTO_EVT + */ + struct hidh_get_proto_evt_param { + esp_hidh_status_t status; /*!< operation status */ + uint8_t handle; /*!< device handle */ + esp_hidh_protocol_mode_t proto_mode; /*!< protocol mode */ + } get_proto; /*!< HIDH callback param of ESP_HIDH_GET_PROTO_EVT */ + + /** + * @brief ESP_HIDH_SET_PROTO_EVT + */ + struct hidh_set_proto_evt_param { + esp_hidh_status_t status; /*!< operation status */ + uint8_t handle; /*!< device handle */ + } set_proto; /*!< HIDH callback param of ESP_HIDH_SET_PROTO_EVT */ + + /** + * @brief ESP_HIDH_GET_RPT_EVT + */ + struct hidh_get_rpt_evt_param { + esp_hidh_status_t status; /*!< operation status */ + uint8_t handle; /*!< device handle */ + uint16_t len; /*!< data length */ + uint8_t *data; /*!< data pointer */ + } get_rpt; /*!< HIDH callback param of ESP_HIDH_GET_RPT_EVT */ + + /** + * @brief ESP_HIDH_SET_RPT_EVT + */ + struct hidh_set_rpt_evt_param { + esp_hidh_status_t status; /*!< operation status */ + uint8_t handle; /*!< device handle */ + } set_rpt; /*!< HIDH callback param of ESP_HIDH_SET_RPT_EVT */ + + /** + * @brief ESP_HIDH_DATA_EVT + */ + struct hidh_send_data_evt_param { + esp_hidh_status_t status; /*!< operation status */ + uint8_t handle; /*!< device handle */ + uint8_t reason; /*!< lower layer failed reason(ref hiddefs.h) */ + } send_data; /*!< HIDH callback param of ESP_HIDH_DATA_EVT */ + + /** + * @brief ESP_HIDH_GET_IDLE_EVT + */ + struct hidh_get_idle_evt_param { + esp_hidh_status_t status; /*!< operation status */ + uint8_t handle; /*!< device handle */ + uint8_t idle_rate; /*!< idle rate */ + } get_idle; /*!< HIDH callback param of ESP_HIDH_GET_IDLE_EVT */ + + /** + * @brief ESP_HIDH_SET_IDLE_EVT + */ + struct hidh_set_idle_evt_param { + esp_hidh_status_t status; /*!< operation status */ + uint8_t handle; /*!< device handle */ + } set_idle; /*!< HIDH callback param of ESP_HIDH_SET_IDLE_EVT */ + + /** + * @brief ESP_HIDH_DATA_IND_EVT + */ + struct hidh_data_ind_evt_param { + esp_hidh_status_t status; /*!< operation status */ + uint8_t handle; /*!< device handle */ + esp_hidh_protocol_mode_t proto_mode; /*!< protocol mode */ + uint16_t len; /*!< data length */ + uint8_t *data; /*!< data pointer */ + } data_ind; /*!< HIDH callback param of ESP_HIDH_DATA_IND_EVT */ + + /** + * @brief ESP_HIDH_ADD_DEV_EVT + */ + struct hidh_add_dev_evt_param { + esp_hidh_status_t status; /*!< operation status */ + uint8_t handle; /*!< device handle */ + esp_bd_addr_t bd_addr; /*!< device address */ + } add_dev; /*!< HIDH callback param of ESP_HIDH_ADD_DEV_EVT */ + + /** + * @brief ESP_HIDH_RMV_DEV_EVT + */ + struct hidh_rmv_dev_evt_param { + esp_hidh_status_t status; /*!< operation status */ + uint8_t handle; /*!< device handle */ + esp_bd_addr_t bd_addr; /*!< device address */ + } rmv_dev; /*!< HIDH callback param of ESP_HIDH_RMV_DEV_EVT */ + + /** + * @brief ESP_HIDH_GET_DSCP_EVT + */ + struct hidh_get_dscp_evt_param { + esp_hidh_status_t status; /*!< operation status */ + uint8_t handle; /*!< device handle */ + bool added; /*!< Indicate if added */ + uint16_t vendor_id; /*!< Vendor ID */ + uint16_t product_id; /*!< Product ID */ + uint16_t version; /*!< Version */ + uint16_t ssr_max_latency; /*!< SSR max latency */ + uint16_t ssr_min_tout; /*!< SSR min timeout */ + uint8_t ctry_code; /*!< Country Code */ + uint16_t dl_len; /*!< Device descriptor length */ + uint8_t *dsc_list; /*!< Device descriptor pointer */ + } dscp; /*!< HIDH callback param of ESP_HIDH_GET_DSCP_EVT */ + + /** + * @brief ESP_HIDH_SET_INFO_EVT + */ + struct hidh_set_info_evt_param { + esp_hidh_status_t status; /*!< operation status */ + uint8_t handle; /*!< device handle */ + esp_bd_addr_t bd_addr; /*!< device address */ + } set_info; /*!< HIDH callback param of ESP_HIDH_SET_INFO_EVT */ +} esp_hidh_cb_param_t; + +/** + * @brief HID host callback function type + * @param event: Event type + * @param param: Point to callback parameter, currently is union type + */ +typedef void (esp_hh_cb_t)(esp_hidh_cb_event_t event, esp_hidh_cb_param_t *param); + +/** + * @brief This function is called to init callbacks with HID host module. + * + * @param[in] callback: pointer to the init callback function. + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_bt_hid_host_register_callback(esp_hh_cb_t callback); + +/** + * @brief This function initializes HID host. This function should be called after esp_bluedroid_enable() and + * esp_blueroid_init() success, and should be called after esp_bt_hid_host_register_callback(). + * When the operation is complete the callback function will be called with ESP_HIDH_INIT_EVT. + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_bt_hid_host_init(void); + +/** + * @brief Closes the interface. This function should be called after esp_bluedroid_enable() and + * esp_blueroid_init() success, and should be called after esp_bt_hid_host_init(). + * When the operation is complete the callback function will be called with ESP_HIDH_DEINIT_EVT. + * + * @return - ESP_OK: success + * - other: failed + */ +esp_err_t esp_bt_hid_host_deinit(void); + +/** + * @brief Connect to hid device. When the operation is complete the callback + * function will be called with ESP_HIDH_OPEN_EVT. + * + * @param[in] bd_addr: Remote device bluetooth device address. + * + * @return - ESP_OK: success + * - other: failed + */ +esp_err_t esp_bt_hid_host_connect(esp_bd_addr_t bd_addr); + +/** + * @brief Disconnect from hid device. When the operation is complete the callback + * function will be called with ESP_HIDH_CLOSE_EVT. + * + * @param[in] bd_addr: Remote device bluetooth device address. + * + * @return - ESP_OK: success + * - other: failed + */ +esp_err_t esp_bt_hid_host_disconnect(esp_bd_addr_t bd_addr); + +/** + * @brief Virtual UnPlug (VUP) the specified HID device. When the operation is complete the callback + * function will be called with ESP_HIDH_VC_UNPLUG_EVT. + * + * @param[in] bd_addr: Remote device bluetooth device address. + * + * @return - ESP_OK: success + * - other: failed + */ +esp_err_t esp_bt_hid_host_virtual_cable_unplug(esp_bd_addr_t bd_addr); + +/** + * @brief Set the HID device descriptor for the specified HID device. When the operation is complete the callback + * function will be called with ESP_HIDH_SET_INFO_EVT. + * + * @param[in] bd_addr: Remote device bluetooth device address. + * @param[in] hid_info: HID device descriptor structure. + * + * @return - ESP_OK: success + * - other: failed + */ +esp_err_t esp_bt_hid_host_set_info(esp_bd_addr_t bd_addr, esp_hidh_hid_info_t *hid_info); + +/** + * @brief Get the HID proto mode. When the operation is complete the callback + * function will be called with ESP_HIDH_GET_PROTO_EVT. + * + * @param[in] bd_addr: Remote device bluetooth device address. + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_bt_hid_host_get_protocol(esp_bd_addr_t bd_addr); + +/** + * @brief Set the HID proto mode. When the operation is complete the callback + * function will be called with ESP_HIDH_SET_PROTO_EVT. + * + * @param[in] bd_addr: Remote device bluetooth device address. + * @param[in] protocol_mode: Protocol mode type. + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_bt_hid_host_set_protocol(esp_bd_addr_t bd_addr, esp_hidh_protocol_mode_t protocol_mode); + +/** + * @brief Get the HID Idle Time. When the operation is complete the callback + * function will be called with ESP_HIDH_GET_IDLE_EVT. + * + * @param[in] bd_addr: Remote device bluetooth device address. + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_bt_hid_host_get_idle(esp_bd_addr_t bd_addr); + +/** + * @brief Set the HID Idle Time. When the operation is complete the callback + * function will be called with ESP_HIDH_SET_IDLE_EVT. + * + * @param[in] bd_addr: Remote device bluetooth device address. + * @param[in] idle_time: Idle time rate + * + * @return - ESP_OK: success + * - other: failed + */ +esp_err_t esp_bt_hid_host_set_idle(esp_bd_addr_t bd_addr, uint16_t idle_time); + +/** + * @brief Send a GET_REPORT to HID device. When the operation is complete the callback + * function will be called with ESP_HIDH_GET_RPT_EVT. + * + * @param[in] bd_addr: Remote device bluetooth device address. + * @param[in] report_type: Report type + * @param[in] report_id: Report id + * @param[in] buffer_size: Buffer size + * + * @return - ESP_OK: success + * - other: failed + */ +esp_err_t esp_bt_hid_host_get_report(esp_bd_addr_t bd_addr, esp_hidh_report_type_t report_type, uint8_t report_id, + int buffer_size); + +/** + * @brief Send a SET_REPORT to HID device. When the operation is complete the callback + * function will be called with ESP_HIDH_SET_RPT_EVT. + * + * @param[in] bd_addr: Remote device bluetooth device address. + * @param[in] report_type: Report type + * @param[in] report: Report data pointer + * @param[in] len: Report data length + * + * @return - ESP_OK: success + * - other: failed + */ +esp_err_t esp_bt_hid_host_set_report(esp_bd_addr_t bd_addr, esp_hidh_report_type_t report_type, uint8_t *report, + size_t len); + +/** + * @brief Send data to HID device. When the operation is complete the callback + * function will be called with ESP_HIDH_DATA_EVT. + * + * @param[in] bd_addr: Remote device bluetooth device address. + * @param[in] data: Data pointer + * @param[in] len: Data length + * + * @return - ESP_OK: success + * - other: failed + */ +esp_err_t esp_bt_hid_host_send_data(esp_bd_addr_t bd_addr, uint8_t *data, size_t len); + +#ifdef __cplusplus +} +#endif + +#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 018723a0eb..7b95f520b4 100644 --- a/components/bt/host/bluedroid/bta/dm/bta_dm_act.c +++ b/components/bt/host/bluedroid/bta/dm/bta_dm_act.c @@ -126,7 +126,7 @@ static void bta_dm_ctrl_features_rd_cmpl_cback(tBTM_STATUS result); #endif #endif #if (SMP_INCLUDED == TRUE) -static void bta_dm_remove_sec_dev_entry(BD_ADDR remote_bd_addr); +static BOOLEAN bta_dm_remove_sec_dev_entry(BD_ADDR remote_bd_addr); #endif ///SMP_INCLUDED == TRUE #if (BLE_INCLUDED == TRUE) static void bta_dm_observe_results_cb(tBTM_INQ_RESULTS *p_inq, UINT8 *p_eir); @@ -3069,7 +3069,9 @@ static UINT8 bta_dm_authentication_complete_cback(BD_ADDR bd_addr, DEV_CLASS dev bta_dm_cb.p_sec_cback(BTA_DM_AUTH_CMPL_EVT, &sec_event); } - bta_dm_remove_sec_dev_entry(bd_addr); + if (bta_dm_remove_sec_dev_entry(bd_addr)) { + return BTM_SEC_DEV_REC_REMOVED; + } } return BTM_SUCCESS; @@ -3740,12 +3742,13 @@ static void bta_dm_delay_role_switch_cback(TIMER_LIST_ENT *p_tle) ** remtoe device does not exist, else schedule for dev entry removal upon ACL close ** -** Returns void +** Returns TRUE if device entry is removed from Security device DB, FALSE otherwise ** *******************************************************************************/ #if (SMP_INCLUDED == TRUE) -static void bta_dm_remove_sec_dev_entry(BD_ADDR remote_bd_addr) +static BOOLEAN bta_dm_remove_sec_dev_entry(BD_ADDR remote_bd_addr) { + BOOLEAN is_device_deleted = FALSE; UINT16 index = 0; if ( BTM_IsAclConnectionUp(remote_bd_addr, BT_TRANSPORT_LE) || BTM_IsAclConnectionUp(remote_bd_addr, BT_TRANSPORT_BR_EDR)) { @@ -3763,7 +3766,7 @@ static void bta_dm_remove_sec_dev_entry(BD_ADDR remote_bd_addr) APPL_TRACE_ERROR(" %s Device does not exist in DB", __FUNCTION__); } } else { - BTM_SecDeleteDevice (remote_bd_addr, bta_dm_cb.device_list.peer_device[index].transport); + is_device_deleted = BTM_SecDeleteDevice (remote_bd_addr, bta_dm_cb.device_list.peer_device[index].transport); #if (BLE_INCLUDED == TRUE && GATTC_INCLUDED == TRUE) /* need to remove all pending background connection */ BTA_GATTC_CancelOpen(0, remote_bd_addr, FALSE); @@ -3771,6 +3774,7 @@ static void bta_dm_remove_sec_dev_entry(BD_ADDR remote_bd_addr) BTA_GATTC_Refresh(remote_bd_addr, false); #endif } + return is_device_deleted; } #endif ///SMP_INCLUDED == TRUE @@ -3835,7 +3839,10 @@ static void bta_dm_adjust_roles(BOOLEAN delay_role_switch) } else { bta_dm_cb.switch_delay_timer[i].p_cback = (TIMER_CBACK *)&bta_dm_delay_role_switch_cback; - bta_sys_start_timer(&bta_dm_cb.switch_delay_timer[i], 0, 500); + /* Start the timer if not active */ + if (!bta_sys_timer_is_active(&bta_dm_cb.switch_delay_timer[i])) { + bta_sys_start_timer(&bta_dm_cb.switch_delay_timer[i], 0, 500); + } } } @@ -4495,6 +4502,22 @@ void bta_dm_set_encryption (tBTA_DM_MSG *p_data) } #endif ///SMP_INCLUDED == TRUE +#if (BTA_HD_INCLUDED == TRUE) +BOOLEAN bta_dm_check_if_only_hd_connected(BD_ADDR peer_addr) +{ + APPL_TRACE_DEBUG("%s: count(%d)", __func__, bta_dm_conn_srvcs.count); + for (uint8_t j = 0; j < bta_dm_conn_srvcs.count; j++) { + // Check if profiles other than hid are connected + if ((bta_dm_conn_srvcs.conn_srvc[j].id != BTA_ID_HD) && + !bdcmp(bta_dm_conn_srvcs.conn_srvc[j].peer_bdaddr, peer_addr)) { + APPL_TRACE_DEBUG("%s: Another profile (id=%d) is connected", __func__, bta_dm_conn_srvcs.conn_srvc[j].id); + return FALSE; + } + } + return TRUE; +} +#endif /* BTA_HD_INCLUDED == TRUE */ + #if (BLE_INCLUDED == TRUE) /******************************************************************************* ** @@ -4975,9 +4998,6 @@ void bta_dm_ble_update_conn_params (tBTA_DM_MSG *p_data) p_data->ble_update_conn_params.latency, p_data->ble_update_conn_params.timeout)) { APPL_TRACE_ERROR("Update connection parameters failed!"); - } else { - BTM_BleConfigConnParams(p_data->ble_update_conn_params.min_int, p_data->ble_update_conn_params.max_int, - p_data->ble_update_conn_params.latency, p_data->ble_update_conn_params.timeout); } } /******************************************************************************* 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 5735941de1..31047b1ae3 100644 --- a/components/bt/host/bluedroid/bta/dm/bta_dm_cfg.c +++ b/components/bt/host/bluedroid/bta/dm/bta_dm_cfg.c @@ -117,11 +117,11 @@ tBTA_DM_CFG *const p_bta_dm_cfg = (tBTA_DM_CFG *) &bta_dm_cfg; tBTA_DM_RM *const p_bta_dm_rm_cfg = (tBTA_DM_RM *) &bta_dm_rm_cfg; #if BLE_INCLUDED == TRUE +# define BTA_DM_NUM_PM_ENTRY 10 /* number of entries in bta_dm_pm_cfg except the first */ +# define BTA_DM_NUM_PM_SPEC 10 /* number of entries in bta_dm_pm_spec */ +#else # define BTA_DM_NUM_PM_ENTRY 8 /* number of entries in bta_dm_pm_cfg except the first */ # define BTA_DM_NUM_PM_SPEC 8 /* number of entries in bta_dm_pm_spec */ -#else -# define BTA_DM_NUM_PM_ENTRY 6 /* number of entries in bta_dm_pm_cfg except the first */ -# define BTA_DM_NUM_PM_SPEC 6 /* number of entries in bta_dm_pm_spec */ #endif #if (BTA_DM_PM_INCLUDED == TRUE) @@ -133,10 +133,12 @@ tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_CFG bta_dm_pm_cfg[BTA_DM_NUM_PM_ENTRY + 1] {BTA_ID_JV, BTA_APP_ID_1, 2}, /* app BTA_JV_PM_ID_1, reuse ftc spec table */ {BTA_ID_JV, BTA_ALL_APP_ID, 3}, /* reuse fts spec table */ {BTA_ID_HS, BTA_ALL_APP_ID, 4}, /* HS spec table */ - {BTA_ID_AVK, BTA_ALL_APP_ID, 5} /* avk spec table */ + {BTA_ID_AVK, BTA_ALL_APP_ID, 5}, /* avk spec table */ + {BTA_ID_HD, BTA_ALL_APP_ID, 6}, /* hd spec table */ + {BTA_ID_HH, BTA_ALL_APP_ID, 7} /* hh spec table */ #if BLE_INCLUDED == TRUE - , {BTA_ID_GATTC, BTA_ALL_APP_ID, 6} /* gattc spec table */ - , {BTA_ID_GATTS, BTA_ALL_APP_ID, 7} /* gatts spec table */ + , {BTA_ID_GATTC, BTA_ALL_APP_ID, 8} /* gattc spec table */ + , {BTA_ID_GATTS, BTA_ALL_APP_ID, 9} /* gatts spec table */ #endif }; @@ -254,10 +256,48 @@ tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_SPEC bta_dm_pm_spec[BTA_DM_NUM_PM_SPEC] = { {{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */ } + }, + + /* HD : 6 */ + { + (BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */ +#if (BTM_SSR_INCLUDED == TRUE) + (BTA_DM_PM_SSR3), /* the SSR entry */ +#endif + { + {{BTA_DM_PM_SNIFF_HD_ACTIVE_IDX, 5000 + 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_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open */ + {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close */ + {{BTA_DM_PM_SNIFF_HD_IDLE_IDX, 5000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */ + {{BTA_DM_PM_SNIFF_HD_ACTIVE_IDX, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */ + {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */ + } + }, + + /* HH : 7 */ + { + (BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */ +#if (BTM_SSR_INCLUDED == TRUE) + (BTA_DM_PM_SSR1), /* the SSR entry */ +#endif + { + {{BTA_DM_PM_SNIFF_HH_OPEN_IDX, BTA_DM_PM_HH_OPEN_DELAY + 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_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open */ + {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close, used for HH suspend */ + {{BTA_DM_PM_SNIFF_HH_IDLE_IDX, BTA_DM_PM_HH_IDLE_DELAY + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */ + {{BTA_DM_PM_SNIFF_HH_ACTIVE_IDX, BTA_DM_PM_HH_ACTIVE_DELAY + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */ + {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */ + } } #if BLE_INCLUDED == TRUE - /* GATTC : 6 */ + /* GATTC : 8 */ , { (BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */ #if (BTM_SSR_INCLUDED == TRUE) @@ -278,7 +318,7 @@ tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_SPEC bta_dm_pm_spec[BTA_DM_NUM_PM_SPEC] = { {{BTA_DM_PM_RETRY, 5000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */ } } - /* GATTS : 7 */ + /* GATTS : 9 */ , { (BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */ #if (BTM_SSR_INCLUDED == TRUE) @@ -372,7 +412,7 @@ tBTA_DM_SSR_SPEC bta_dm_ssr_spec[] = { seting 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, 2} /* BTA_DM_PM_SSR3 - HD */ + {360, 160, 1600} /* BTA_DM_PM_SSR3 - HD */ }; tBTA_DM_SSR_SPEC *const p_bta_dm_ssr_spec = (tBTA_DM_SSR_SPEC *) &bta_dm_ssr_spec; 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 8dfd26af5e..8d2f106d0d 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 @@ -26,6 +26,7 @@ #include "common/bt_target.h" #include "freertos/semphr.h" +#include "bta/bta_sys.h" #if (BLE_INCLUDED == TRUE && (defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)) #include "bta/bta_gatt_api.h" #endif @@ -1596,6 +1597,11 @@ extern void bta_dm_ble_get_energy_info(tBTA_DM_MSG *p_data); extern void bta_dm_set_encryption(tBTA_DM_MSG *p_data); extern void bta_dm_confirm(tBTA_DM_MSG *p_data); extern void bta_dm_key_req(tBTA_DM_MSG *p_data); + +#if (BTA_HD_INCLUDED == TRUE) +extern BOOLEAN bta_dm_check_if_only_hd_connected(BD_ADDR peer_addr); +#endif /* BTA_HD_INCLUDED */ + #if (BTM_OOB_INCLUDED == TRUE) extern void bta_dm_loc_oob(tBTA_DM_MSG *p_data); extern void bta_dm_oob_reply(tBTA_DM_MSG *p_data); diff --git a/components/bt/host/bluedroid/bta/gatt/bta_gattc_act.c b/components/bt/host/bluedroid/bta/gatt/bta_gattc_act.c index 9f5417bf76..f35851c60b 100644 --- a/components/bt/host/bluedroid/bta/gatt/bta_gattc_act.c +++ b/components/bt/host/bluedroid/bta/gatt/bta_gattc_act.c @@ -35,6 +35,7 @@ #include "gatt_int.h" #include "osi/allocator.h" #include "osi/mutex.h" +#include "bta_hh_int.h" #if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE) #include "bta_hh_int.h" @@ -304,7 +305,10 @@ void bta_gattc_deregister(tBTA_GATTC_CB *p_cb, tBTA_GATTC_RCB *p_clreg) bta_gattc_deregister_cmpl(p_clreg); } } else { - APPL_TRACE_ERROR("bta_gattc_deregister Deregister Failedm unknown client cif"); + APPL_TRACE_ERROR("Deregister Failed unknown client cif"); +#if defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE) + bta_hh_cleanup_disable(BTA_HH_OK); +#endif } } /******************************************************************************* diff --git a/components/bt/host/bluedroid/bta/hd/bta_hd_act.c b/components/bt/host/bluedroid/bta/hd/bta_hd_act.c new file mode 100644 index 0000000000..addb585a1d --- /dev/null +++ b/components/bt/host/bluedroid/bta/hd/bta_hd_act.c @@ -0,0 +1,774 @@ +/****************************************************************************** + * + * Copyright (C) 2016 The Android Open Source Project + * Copyright (C) 2005-2012 Broadcom Corporation + * + * 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. + * + ******************************************************************************/ +/****************************************************************************** + * + * This file contains the HID device action functions. + * + ******************************************************************************/ +#include "common/bt_target.h" + +#if defined(BTA_HD_INCLUDED) && (BTA_HD_INCLUDED == TRUE) + +#include "bta/bta_sys.h" +#include "bta_hd_int.h" +#include "osi/allocator.h" +#include "osi/osi.h" +#include "stack/btm_api.h" +#include + +static void bta_hd_cback(BD_ADDR bd_addr, uint8_t event, uint32_t data, BT_HDR *pdata); + +static bool check_descriptor(uint8_t *data, uint16_t length, bool *has_report_id) +{ + uint8_t *ptr = data; + *has_report_id = FALSE; + while (ptr < data + length) { + uint8_t item = *ptr++; + switch (item) { + case 0xfe: // long item indicator + if (ptr < data + length) { + ptr += ((*ptr) + 2); + } else { + return false; + } + break; + case 0x85: // Report ID + *has_report_id = TRUE; + default: + ptr += (item & 0x03); + break; + } + } + return (ptr == data + length); +} + +/******************************************************************************* + * + * Function bta_hd_api_enable + * + * Description Enables HID device + * + * Returns void + * + ******************************************************************************/ +void bta_hd_api_enable(tBTA_HD_DATA *p_data) +{ + tBTA_HD_STATUS status = BTA_HD_ERROR; + tHID_STATUS ret; + + APPL_TRACE_API("%s", __func__); + + HID_DevInit(); + + memset(&bta_hd_cb, 0, sizeof(tBTA_HD_CB)); + + HID_DevSetSecurityLevel(BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT); + /* store parameters */ + bta_hd_cb.p_cback = p_data->api_enable.p_cback; + + ret = HID_DevRegister(bta_hd_cback); + if (ret == HID_SUCCESS) { + status = BTA_HD_OK; + } else { + APPL_TRACE_ERROR("%s: Failed to register HID device (%d)", __func__, ret); + } + + /* signal BTA call back event */ + (*bta_hd_cb.p_cback)(BTA_HD_ENABLE_EVT, (tBTA_HD *)&status); +} + +/******************************************************************************* + * + * Function bta_hd_api_disable + * + * Description Disables HID device + * + * Returns void + * + ******************************************************************************/ +void bta_hd_api_disable(void) +{ + tBTA_HD_STATUS status = BTA_HD_ERROR; + tHID_STATUS ret; + + APPL_TRACE_API("%s", __func__); + + /* service is not enabled */ + if (bta_hd_cb.p_cback == NULL) + return; + + /* Remove service record */ + if (bta_hd_cb.sdp_handle != 0) { + SDP_DeleteRecord(bta_hd_cb.sdp_handle); + bta_sys_remove_uuid(UUID_SERVCLASS_HUMAN_INTERFACE); + } + + /* Deregister with lower layer */ + ret = HID_DevDeregister(); + if (ret == HID_SUCCESS) { + status = BTA_HD_OK; + } else { + APPL_TRACE_ERROR("%s: Failed to deregister HID device (%d)", __func__, ret); + } + + (*bta_hd_cb.p_cback)(BTA_HD_DISABLE_EVT, (tBTA_HD *)&status); + + memset(&bta_hd_cb, 0, sizeof(tBTA_HD_CB)); +} + +/******************************************************************************* + * + * Function bta_hd_register_act + * + * Description Registers SDP record + * + * Returns void + * + ******************************************************************************/ +void bta_hd_register_act(tBTA_HD_DATA *p_data) +{ + tBTA_HD ret; + tBTA_HD_REGISTER_APP *p_app_data = (tBTA_HD_REGISTER_APP *)p_data; + bool use_report_id = FALSE; + + APPL_TRACE_API("%s", __func__); + + ret.reg_status.in_use = FALSE; + + /* Check if len doesn't exceed BTA_HD_APP_DESCRIPTOR_LEN and descriptor + * itself is well-formed. Also check if descriptor has Report Id item so we + * know if report will have prefix or not. */ + if (p_app_data->d_len > BTA_HD_APP_DESCRIPTOR_LEN || + !check_descriptor(p_app_data->d_data, p_app_data->d_len, &use_report_id)) { + APPL_TRACE_ERROR("%s: Descriptor is too long or malformed", __func__); + ret.reg_status.status = BTA_HD_ERROR; + (*bta_hd_cb.p_cback)(BTA_HD_REGISTER_APP_EVT, &ret); + return; + } + + ret.reg_status.status = BTA_HD_OK; + + /* Remove old record if for some reason it's already registered */ + if (bta_hd_cb.sdp_handle != 0) { + SDP_DeleteRecord(bta_hd_cb.sdp_handle); + } + + bta_hd_cb.use_report_id = use_report_id; + bta_hd_cb.sdp_handle = SDP_CreateRecord(); + HID_DevAddRecord(bta_hd_cb.sdp_handle, p_app_data->name, p_app_data->description, p_app_data->provider, + p_app_data->subclass, p_app_data->d_len, p_app_data->d_data); + bta_sys_add_uuid(UUID_SERVCLASS_HUMAN_INTERFACE); + + HID_DevSetIncomingQos(p_app_data->in_qos.service_type, p_app_data->in_qos.token_rate, + p_app_data->in_qos.token_bucket_size, p_app_data->in_qos.peak_bandwidth, + p_app_data->in_qos.access_latency, p_app_data->in_qos.delay_variation); + + HID_DevSetOutgoingQos(p_app_data->out_qos.service_type, p_app_data->out_qos.token_rate, + p_app_data->out_qos.token_bucket_size, p_app_data->out_qos.peak_bandwidth, + p_app_data->out_qos.access_latency, p_app_data->out_qos.delay_variation); + + // application is registered so we can accept incoming connections + HID_DevSetIncomingPolicy(TRUE); + + if (HID_DevGetDevice(&ret.reg_status.bda) == HID_SUCCESS) { + ret.reg_status.in_use = TRUE; + } + + (*bta_hd_cb.p_cback)(BTA_HD_REGISTER_APP_EVT, &ret); +} + +/******************************************************************************* + * + * Function bta_hd_unregister_act + * + * Description Unregisters SDP record + * + * Returns void + * + ******************************************************************************/ +void bta_hd_unregister_act(UNUSED_ATTR tBTA_HD_DATA *p_data) +{ + tBTA_HD_STATUS status = BTA_HD_OK; + + APPL_TRACE_API("%s", __func__); + + // application is no longer registered so we do not want incoming connections + HID_DevSetIncomingPolicy(FALSE); + + if (bta_hd_cb.sdp_handle != 0) { + SDP_DeleteRecord(bta_hd_cb.sdp_handle); + } + + bta_hd_cb.sdp_handle = 0; + bta_sys_remove_uuid(UUID_SERVCLASS_HUMAN_INTERFACE); + + (*bta_hd_cb.p_cback)(BTA_HD_UNREGISTER_APP_EVT, (tBTA_HD *)&status); +} + +/******************************************************************************* + * + * Function bta_hd_unregister2_act + * + * Description + * + * Returns void + * + ******************************************************************************/ +void bta_hd_unregister2_act(tBTA_HD_DATA *p_data) +{ + APPL_TRACE_API("%s", __func__); + + // close first + bta_hd_close_act(p_data); + + // then unregister + bta_hd_unregister_act(p_data); + + if (bta_hd_cb.disable_w4_close) { + bta_hd_api_disable(); + } +} + +/******************************************************************************* + * + * Function bta_hd_connect_act + * + * Description Connect to device (must be virtually plugged) + * + * Returns void + * + ******************************************************************************/ +extern void bta_hd_connect_act(tBTA_HD_DATA *p_data) +{ + tHID_STATUS ret; + tBTA_HD_DEVICE_CTRL *p_ctrl = (tBTA_HD_DEVICE_CTRL *)p_data; + tBTA_HD cback_data; + + APPL_TRACE_API("%s", __func__); + do { + ret = HID_DevPlugDevice(p_ctrl->addr); + if (ret != HID_SUCCESS) { + APPL_TRACE_WARNING("%s: HID_DevPlugDevice returned %d", __func__, ret); + return; + } + + ret = HID_DevConnect(); + if (ret != HID_SUCCESS) { + APPL_TRACE_WARNING("%s: HID_DevConnect returned %d", __func__, ret); + return; + } + } while (0); + + bdcpy(cback_data.conn.bda, p_ctrl->addr); + cback_data.conn.status = (ret == HID_SUCCESS ? BTA_HD_OK : BTA_HD_ERROR); + cback_data.conn.conn_status = BTA_HD_CONN_STATE_CONNECTING; + bta_hd_cb.p_cback(BTA_HD_OPEN_EVT, &cback_data); +} + +/******************************************************************************* + * + * Function bta_hd_disconnect_act + * + * Description Disconnect from device + * + * Returns void + * + ******************************************************************************/ +extern void bta_hd_disconnect_act(UNUSED_ATTR tBTA_HD_DATA *p_data) +{ + tHID_STATUS ret; + tBTA_HD cback_data; + + APPL_TRACE_API("%s", __func__); + + ret = HID_DevDisconnect(); + + if (ret != HID_SUCCESS) { + APPL_TRACE_WARNING("%s: HID_DevDisconnect returned %d", __func__, ret); + return; + } + + if (HID_DevGetDevice(&cback_data.conn.bda) == HID_SUCCESS) { + cback_data.conn.status = BTA_HD_OK; + cback_data.conn.conn_status = BTA_HD_CONN_STATE_DISCONNECTING; + bta_hd_cb.p_cback(BTA_HD_CLOSE_EVT, &cback_data); + } +} + +/******************************************************************************* + * + * Function bta_hd_add_device_act + * + * Description + * + * Returns void + * + ******************************************************************************/ +extern void bta_hd_add_device_act(tBTA_HD_DATA *p_data) +{ + tBTA_HD_DEVICE_CTRL *p_ctrl = (tBTA_HD_DEVICE_CTRL *)p_data; + + APPL_TRACE_API("%s", __func__); + + HID_DevPlugDevice(p_ctrl->addr); +} + +/******************************************************************************* + * + * Function bta_hd_remove_device_act + * + * Description + * + * Returns void + * + ******************************************************************************/ +extern void bta_hd_remove_device_act(tBTA_HD_DATA *p_data) +{ + tBTA_HD_DEVICE_CTRL *p_ctrl = (tBTA_HD_DEVICE_CTRL *)p_data; + + APPL_TRACE_API("%s", __func__); + + HID_DevUnplugDevice(p_ctrl->addr); +} + +/******************************************************************************* + * + * Function bta_hd_send_report_act + * + * Description Sends report + * + * Returns void + * + ******************************************************************************/ +extern void bta_hd_send_report_act(tBTA_HD_DATA *p_data) +{ + tBTA_HD_SEND_REPORT *p_report = (tBTA_HD_SEND_REPORT *)p_data; + uint8_t channel; + uint8_t report_id; + tBTA_HD cback_data; + tHID_STATUS ret; + + APPL_TRACE_VERBOSE("%s", __func__); + + channel = p_report->use_intr ? HID_CHANNEL_INTR : HID_CHANNEL_CTRL; + report_id = (bta_hd_cb.use_report_id || bta_hd_cb.boot_mode) ? p_report->id : 0x00; + + ret = HID_DevSendReport(channel, p_report->type, report_id, p_report->len, p_report->data); + + /* trigger PM */ + bta_sys_busy(BTA_ID_HD, 1, bta_hd_cb.bd_addr); + bta_sys_idle(BTA_ID_HD, 1, bta_hd_cb.bd_addr); + + cback_data.send_report.status = (ret == HID_SUCCESS ? BTA_HD_OK : BTA_HD_ERROR); + cback_data.send_report.reason = ret; + cback_data.send_report.report_id = report_id; + cback_data.send_report.report_type = p_report->type; + bta_hd_cb.p_cback(BTA_HD_SEND_REPORT_EVT, &cback_data); +} + +/******************************************************************************* + * + * Function bta_hd_report_error_act + * + * Description + * + * Returns void + * + ******************************************************************************/ +extern void bta_hd_report_error_act(tBTA_HD_DATA *p_data) +{ + tBTA_HD_REPORT_ERR *p_report = (tBTA_HD_REPORT_ERR *)p_data; + tHID_STATUS ret; + tBTA_HD cback_data; + + APPL_TRACE_API("%s: error = %d", __func__, p_report->error); + + ret = HID_DevReportError(p_report->error); + + if (ret != HID_SUCCESS) { + APPL_TRACE_WARNING("%s: HID_DevReportError returned %d", __func__, ret); + } + + cback_data.report_err.status = (ret == HID_SUCCESS ? BTA_HD_OK : BTA_HD_ERROR); + cback_data.report_err.reason = ret; + bta_hd_cb.p_cback(BTA_HD_REPORT_ERR_EVT, &cback_data); +} + +/******************************************************************************* + * + * Function bta_hd_vc_unplug_act + * + * Description Sends Virtual Cable Unplug + * + * Returns void + * + ******************************************************************************/ +extern void bta_hd_vc_unplug_act(UNUSED_ATTR tBTA_HD_DATA *p_data) +{ + tHID_STATUS ret; + + APPL_TRACE_API("%s", __func__); + + bta_hd_cb.vc_unplug = TRUE; + ret = HID_DevVirtualCableUnplug(); + + if (ret != HID_SUCCESS) { + APPL_TRACE_WARNING("%s: HID_DevVirtualCableUnplug returned %d", __func__, ret); + } + + /* trigger PM */ + bta_sys_busy(BTA_ID_HD, 1, bta_hd_cb.bd_addr); + bta_sys_idle(BTA_ID_HD, 1, bta_hd_cb.bd_addr); +} + +/******************************************************************************* + * + * Function bta_hd_open_act + * + * Description + * + * Returns void + * + ******************************************************************************/ +extern void bta_hd_open_act(tBTA_HD_DATA *p_data) +{ + tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data; + tBTA_HD cback_data; + + APPL_TRACE_API("%s", __func__); + + HID_DevPlugDevice(p_cback->addr); + bta_sys_conn_open(BTA_ID_HD, 1, p_cback->addr); + + bdcpy(cback_data.conn.bda, p_cback->addr); + bdcpy(bta_hd_cb.bd_addr, p_cback->addr); + cback_data.conn.status = BTA_HD_OK; + cback_data.conn.conn_status = BTA_HD_CONN_STATE_CONNECTED; + bta_hd_cb.p_cback(BTA_HD_OPEN_EVT, &cback_data); +} + +/******************************************************************************* + * + * Function bta_hd_close_act + * + * Description + * + * Returns void + * + ******************************************************************************/ +extern void bta_hd_close_act(tBTA_HD_DATA *p_data) +{ + tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data; + tBTA_HD cback_data; + tBTA_HD_EVT cback_event = BTA_HD_CLOSE_EVT; + + APPL_TRACE_API("%s", __func__); + + bta_sys_conn_close(BTA_ID_HD, 1, p_cback->addr); + + if (bta_hd_cb.vc_unplug) { + bta_hd_cb.vc_unplug = FALSE; + HID_DevUnplugDevice(p_cback->addr); + cback_event = BTA_HD_VC_UNPLUG_EVT; + } + + bdcpy(cback_data.conn.bda, p_cback->addr); + memset(bta_hd_cb.bd_addr, 0, sizeof(BD_ADDR)); + cback_data.conn.status = BTA_HD_OK; + cback_data.conn.conn_status = BTA_HD_CONN_STATE_DISCONNECTED; + bta_hd_cb.p_cback(cback_event, &cback_data); +} + +/******************************************************************************* + * + * Function bta_hd_intr_data_act + * + * Description Handles incoming DATA request on intr + * + * Returns void + * + ******************************************************************************/ +extern void bta_hd_intr_data_act(tBTA_HD_DATA *p_data) +{ + tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data; + BT_HDR *p_msg = p_cback->p_data; + uint16_t len = p_msg->len; + uint8_t *p_buf = (uint8_t *)(p_msg + 1) + p_msg->offset; + tBTA_HD_INTR_DATA ret; + + APPL_TRACE_API("%s", __func__); + + if (bta_hd_cb.use_report_id || bta_hd_cb.boot_mode) { + ret.report_id = *p_buf; + len--; + p_buf++; + } else { + ret.report_id = 0; + } + + ret.len = len; + ret.p_data = p_buf; + (*bta_hd_cb.p_cback)(BTA_HD_INTR_DATA_EVT, (tBTA_HD *)&ret); + if (p_msg) { + osi_free(p_msg); + } +} + +/******************************************************************************* + * + * Function bta_hd_get_report_act + * + * Description Handles incoming GET_REPORT request + * + * Returns void + * + ******************************************************************************/ +extern void bta_hd_get_report_act(tBTA_HD_DATA *p_data) +{ + tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data; + bool rep_size_follows = p_cback->data; + BT_HDR *p_msg = p_cback->p_data; + uint8_t *p_buf = (uint8_t *)(p_msg + 1) + p_msg->offset; + tBTA_HD_GET_REPORT ret = {0, 0, 0}; + uint16_t remaining_len = p_msg->len; + + APPL_TRACE_API("%s", __func__); + if (remaining_len < 1) { + APPL_TRACE_ERROR("%s invalid data, remaining_len:%d", __func__, remaining_len); + return; + } + + ret.report_type = *p_buf & HID_PAR_REP_TYPE_MASK; + p_buf++; + remaining_len--; + + if (bta_hd_cb.use_report_id) { + if (remaining_len < 1) { + APPL_TRACE_ERROR("%s invalid data, remaining_len:%d", __func__, remaining_len); + return; + } + ret.report_id = *p_buf; + p_buf++; + remaining_len--; + } + + if (rep_size_follows) { + if (remaining_len < 2) { + APPL_TRACE_ERROR("%s invalid data, remaining_len:%d", __func__, remaining_len); + return; + } + ret.buffer_size = *p_buf | (*(p_buf + 1) << 8); + } + + (*bta_hd_cb.p_cback)(BTA_HD_GET_REPORT_EVT, (tBTA_HD *)&ret); + if (p_msg) { + osi_free(p_msg); + } +} + +/******************************************************************************* + * + * Function bta_hd_set_report_act + * + * Description Handles incoming SET_REPORT request + * + * Returns void + * + ******************************************************************************/ +extern void bta_hd_set_report_act(tBTA_HD_DATA *p_data) +{ + tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data; + BT_HDR *p_msg = p_cback->p_data; + uint16_t len = p_msg->len; + uint8_t *p_buf = (uint8_t *)(p_msg + 1) + p_msg->offset; + tBTA_HD_SET_REPORT ret = {0, 0, 0, NULL}; + + APPL_TRACE_API("%s", __func__); + + ret.report_type = *p_buf & HID_PAR_REP_TYPE_MASK; + p_buf++; + len--; + + if (bta_hd_cb.use_report_id || bta_hd_cb.boot_mode) { + ret.report_id = *p_buf; + len--; + p_buf++; + } else { + ret.report_id = 0; + } + + ret.len = len; + ret.p_data = p_buf; + (*bta_hd_cb.p_cback)(BTA_HD_SET_REPORT_EVT, (tBTA_HD *)&ret); + if (p_msg) { + osi_free(p_msg); + } +} + +/******************************************************************************* + * + * Function bta_hd_set_protocol_act + * + * Description + * + * Returns void + * + ******************************************************************************/ +extern void bta_hd_set_protocol_act(tBTA_HD_DATA *p_data) +{ + tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data; + tBTA_HD cback_data; + + APPL_TRACE_API("%s", __func__); + + bta_hd_cb.boot_mode = (p_cback->data == HID_PAR_PROTOCOL_BOOT_MODE); + cback_data.set_protocol = p_cback->data; + + (*bta_hd_cb.p_cback)(BTA_HD_SET_PROTOCOL_EVT, &cback_data); +} + +/******************************************************************************* + * + * Function bta_hd_vc_unplug_done_act + * + * Description + * + * Returns void + * + ******************************************************************************/ +extern void bta_hd_vc_unplug_done_act(tBTA_HD_DATA *p_data) +{ + tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data; + tBTA_HD cback_data; + + APPL_TRACE_API("%s", __func__); + + bta_sys_conn_close(BTA_ID_HD, 1, p_cback->addr); + + HID_DevUnplugDevice(p_cback->addr); + + bdcpy(cback_data.conn.bda, p_cback->addr); + bdcpy(bta_hd_cb.bd_addr, p_cback->addr); + cback_data.conn.status = BTA_HD_OK; + cback_data.conn.conn_status = BTA_HD_CONN_STATE_DISCONNECTED; + (*bta_hd_cb.p_cback)(BTA_HD_VC_UNPLUG_EVT, &cback_data); +} + +/******************************************************************************* + * + * Function bta_hd_suspend_act + * + * Description + * + * Returns void + * + ******************************************************************************/ +extern void bta_hd_suspend_act(tBTA_HD_DATA *p_data) +{ + tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data; + + APPL_TRACE_API("%s", __func__); + + bta_sys_idle(BTA_ID_HD, 1, p_cback->addr); +} + +/******************************************************************************* + * + * Function bta_hd_exit_suspend_act + * + * Description + * + * Returns void + * + ******************************************************************************/ +extern void bta_hd_exit_suspend_act(tBTA_HD_DATA *p_data) +{ + tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data; + + APPL_TRACE_API("%s", __func__); + + bta_sys_busy(BTA_ID_HD, 1, p_cback->addr); + bta_sys_idle(BTA_ID_HD, 1, p_cback->addr); +} + +/******************************************************************************* + * + * Function bta_hd_cback + * + * Description BTA HD callback function + * + * Returns void + * + ******************************************************************************/ +static void bta_hd_cback(BD_ADDR bd_addr, uint8_t event, uint32_t data, BT_HDR *pdata) +{ + tBTA_HD_CBACK_DATA *p_buf = NULL; + uint16_t sm_event = BTA_HD_INVALID_EVT; + + APPL_TRACE_API("%s: event=%d", __func__, event); + + switch (event) { + case HID_DHOST_EVT_OPEN: + sm_event = BTA_HD_INT_OPEN_EVT; + break; + + case HID_DHOST_EVT_CLOSE: + sm_event = BTA_HD_INT_CLOSE_EVT; + break; + + case HID_DHOST_EVT_GET_REPORT: + sm_event = BTA_HD_INT_GET_REPORT_EVT; + break; + + case HID_DHOST_EVT_SET_REPORT: + sm_event = BTA_HD_INT_SET_REPORT_EVT; + break; + + case HID_DHOST_EVT_SET_PROTOCOL: + sm_event = BTA_HD_INT_SET_PROTOCOL_EVT; + break; + + case HID_DHOST_EVT_INTR_DATA: + sm_event = BTA_HD_INT_INTR_DATA_EVT; + break; + + case HID_DHOST_EVT_VC_UNPLUG: + sm_event = BTA_HD_INT_VC_UNPLUG_EVT; + break; + + case HID_DHOST_EVT_SUSPEND: + sm_event = BTA_HD_INT_SUSPEND_EVT; + break; + + case HID_DHOST_EVT_EXIT_SUSPEND: + sm_event = BTA_HD_INT_EXIT_SUSPEND_EVT; + break; + } + + if (sm_event != BTA_HD_INVALID_EVT && + (p_buf = (tBTA_HD_CBACK_DATA *)osi_malloc(sizeof(tBTA_HD_CBACK_DATA) + sizeof(BT_HDR))) != NULL) { + p_buf->hdr.event = sm_event; + bdcpy(p_buf->addr, bd_addr); + p_buf->data = data; + p_buf->p_data = pdata; + + bta_sys_sendmsg(p_buf); + } +} +#endif /* BTA_HD_INCLUDED */ diff --git a/components/bt/host/bluedroid/bta/hd/bta_hd_api.c b/components/bt/host/bluedroid/bta/hd/bta_hd_api.c new file mode 100644 index 0000000000..33875b957a --- /dev/null +++ b/components/bt/host/bluedroid/bta/hd/bta_hd_api.c @@ -0,0 +1,287 @@ +/****************************************************************************** + * + * Copyright (C) 2016 The Android Open Source Project + * Copyright (C) 2005-2012 Broadcom Corporation + * + * 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. + * + ******************************************************************************/ +/****************************************************************************** + * + * This file contains the HID DEVICE API in the subsystem of BTA. + * + ******************************************************************************/ +#include "common/bt_target.h" + +#if defined(BTA_HD_INCLUDED) && (BTA_HD_INCLUDED == TRUE) + +#include "bta/bta_hd_api.h" +#include "bta_hd_int.h" +#include "osi/allocator.h" +#include +#include +#include + +/***************************************************************************** + * Constants + ****************************************************************************/ +static const tBTA_SYS_REG bta_hd_reg = {bta_hd_hdl_event, BTA_HdDisable}; +/******************************************************************************* + * + * Function BTA_HdEnable + * + * Description Enables HID device + * + * Returns void + * + ******************************************************************************/ +void BTA_HdEnable(tBTA_HD_CBACK *p_cback) +{ + tBTA_HD_API_ENABLE *p_buf; + APPL_TRACE_API("%s", __func__); + bta_sys_register(BTA_ID_HD, &bta_hd_reg); + p_buf = (tBTA_HD_API_ENABLE *)osi_malloc((uint16_t)sizeof(tBTA_HD_API_ENABLE)); + if (p_buf != NULL) { + memset(p_buf, 0, sizeof(tBTA_HD_API_ENABLE)); + p_buf->hdr.event = BTA_HD_API_ENABLE_EVT; + p_buf->p_cback = p_cback; + bta_sys_sendmsg(p_buf); + } +} +/******************************************************************************* + * + * Function BTA_HdDisable + * + * Description Disables HID device. + * + * Returns void + * + ******************************************************************************/ +void BTA_HdDisable(void) +{ + BT_HDR *p_buf; + APPL_TRACE_API("%s", __func__); + bta_sys_deregister(BTA_ID_HD); + if ((p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR))) != NULL) { + p_buf->event = BTA_HD_API_DISABLE_EVT; + bta_sys_sendmsg(p_buf); + } +} +/******************************************************************************* + * + * Function BTA_HdRegisterApp + * + * Description This function is called when application should be + *registered + * + * Returns void + * + ******************************************************************************/ +extern void BTA_HdRegisterApp(tBTA_HD_APP_INFO *p_app_info, tBTA_HD_QOS_INFO *p_in_qos, tBTA_HD_QOS_INFO *p_out_qos) +{ + tBTA_HD_REGISTER_APP *p_buf; + APPL_TRACE_API("%s", __func__); + if ((p_buf = (tBTA_HD_REGISTER_APP *)osi_malloc(sizeof(tBTA_HD_REGISTER_APP))) != NULL) { + p_buf->hdr.event = BTA_HD_API_REGISTER_APP_EVT; + if (p_app_info->p_name) { + strncpy(p_buf->name, p_app_info->p_name, BTA_HD_APP_NAME_LEN); + p_buf->name[BTA_HD_APP_NAME_LEN] = '\0'; + } else { + p_buf->name[0] = '\0'; + } + if (p_app_info->p_description) { + strncpy(p_buf->description, p_app_info->p_description, BTA_HD_APP_DESCRIPTION_LEN); + p_buf->description[BTA_HD_APP_DESCRIPTION_LEN] = '\0'; + } else { + p_buf->description[0] = '\0'; + } + if (p_app_info->p_provider) { + strncpy(p_buf->provider, p_app_info->p_provider, BTA_HD_APP_PROVIDER_LEN); + p_buf->provider[BTA_HD_APP_PROVIDER_LEN] = '\0'; + } else { + p_buf->provider[0] = '\0'; + } + p_buf->subclass = p_app_info->subclass; + p_buf->d_len = p_app_info->descriptor.dl_len; + memcpy(p_buf->d_data, p_app_info->descriptor.dsc_list, p_app_info->descriptor.dl_len); + // copy qos data as-is + memcpy(&p_buf->in_qos, p_in_qos, sizeof(tBTA_HD_QOS_INFO)); + memcpy(&p_buf->out_qos, p_out_qos, sizeof(tBTA_HD_QOS_INFO)); + bta_sys_sendmsg(p_buf); + } +} +/******************************************************************************* + * + * Function BTA_HdUnregisterApp + * + * Description This function is called when application should be + *unregistered + * + * Returns void + * + ******************************************************************************/ +extern void BTA_HdUnregisterApp(void) +{ + BT_HDR *p_buf; + APPL_TRACE_API("%s", __func__); + if ((p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR))) != NULL) { + p_buf->event = BTA_HD_API_UNREGISTER_APP_EVT; + bta_sys_sendmsg(p_buf); + } +} +/******************************************************************************* + * + * Function BTA_HdSendReport + * + * Description This function is called when report is to be sent + * + * Returns void + * + ******************************************************************************/ +extern void BTA_HdSendReport(tBTA_HD_REPORT *p_report) +{ + tBTA_HD_SEND_REPORT *p_buf; + APPL_TRACE_VERBOSE("%s", __func__); + if (p_report->len > BTA_HD_REPORT_LEN) { + APPL_TRACE_WARNING("%s, report len (%d) > MTU len (%d), can't send report." + " Increase value of HID_DEV_MTU_SIZE to send larger reports", + __func__, p_report->len, BTA_HD_REPORT_LEN); + return; + } + if ((p_buf = (tBTA_HD_SEND_REPORT *)osi_malloc(sizeof(tBTA_HD_SEND_REPORT))) != NULL) { + p_buf->hdr.event = BTA_HD_API_SEND_REPORT_EVT; + p_buf->use_intr = p_report->use_intr; + p_buf->type = p_report->type; + p_buf->id = p_report->id; + p_buf->len = p_report->len; + memcpy(p_buf->data, p_report->p_data, p_report->len); + bta_sys_sendmsg(p_buf); + } +} +/******************************************************************************* + * + * Function BTA_HdVirtualCableUnplug + * + * Description This function is called when VCU shall be sent + * + * Returns void + * + ******************************************************************************/ +extern void BTA_HdVirtualCableUnplug(void) +{ + BT_HDR *p_buf; + APPL_TRACE_API("%s", __func__); + if ((p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR))) != NULL) { + p_buf->event = BTA_HD_API_VC_UNPLUG_EVT; + bta_sys_sendmsg(p_buf); + } +} + +/******************************************************************************* + * + * Function BTA_HdConnect + * + * Description This function is called when connection to host shall be + * made + * + * Returns void + * + ******************************************************************************/ +extern void BTA_HdConnect(BD_ADDR addr) +{ + tBTA_HD_DEVICE_CTRL *p_buf; + APPL_TRACE_API("%s", __func__); + + if ((p_buf = (tBTA_HD_DEVICE_CTRL *)osi_malloc(sizeof(tBTA_HD_DEVICE_CTRL))) != NULL) { + p_buf->hdr.event = BTA_HD_API_CONNECT_EVT; + memcpy(p_buf->addr, addr, sizeof(BD_ADDR)); + bta_sys_sendmsg(p_buf); + } +} + +/******************************************************************************* + * + * Function BTA_HdDisconnect + * + * Description This function is called when host shall be disconnected + * + * Returns void + * + ******************************************************************************/ +extern void BTA_HdDisconnect(void) +{ + BT_HDR *p_buf; + APPL_TRACE_API("%s", __func__); + if ((p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR))) != NULL) { + p_buf->event = BTA_HD_API_DISCONNECT_EVT; + bta_sys_sendmsg(p_buf); + } +} +/******************************************************************************* + * + * Function BTA_HdAddDevice + * + * Description This function is called when a device is virtually cabled + * + * Returns void + * + ******************************************************************************/ +extern void BTA_HdAddDevice(BD_ADDR addr) +{ + tBTA_HD_DEVICE_CTRL *p_buf; + APPL_TRACE_API("%s", __func__); + if ((p_buf = (tBTA_HD_DEVICE_CTRL *)osi_malloc(sizeof(tBTA_HD_DEVICE_CTRL))) != NULL) { + p_buf->hdr.event = BTA_HD_API_ADD_DEVICE_EVT; + memcpy(p_buf->addr, addr, sizeof(BD_ADDR)); + bta_sys_sendmsg(p_buf); + } +} +/******************************************************************************* + * + * Function BTA_HdRemoveDevice + * + * Description This function is called when a device is virtually uncabled + * + * Returns void + * + ******************************************************************************/ +extern void BTA_HdRemoveDevice(BD_ADDR addr) +{ + tBTA_HD_DEVICE_CTRL *p_buf; + APPL_TRACE_API("%s", __func__); + if ((p_buf = (tBTA_HD_DEVICE_CTRL *)osi_malloc(sizeof(tBTA_HD_DEVICE_CTRL))) != NULL) { + p_buf->hdr.event = BTA_HD_API_REMOVE_DEVICE_EVT; + memcpy(p_buf->addr, addr, sizeof(BD_ADDR)); + bta_sys_sendmsg(p_buf); + } +} +/******************************************************************************* + * + * Function BTA_HdReportError + * + * Description This function is called when reporting error for set report + * + * Returns void + * + ******************************************************************************/ +extern void BTA_HdReportError(uint8_t error) +{ + tBTA_HD_REPORT_ERR *p_buf; + APPL_TRACE_API("%s", __func__); + if ((p_buf = (tBTA_HD_REPORT_ERR *)osi_malloc(sizeof(tBTA_HD_REPORT_ERR))) != NULL) { + p_buf->hdr.event = BTA_HD_API_REPORT_ERROR_EVT; + p_buf->error = error; + bta_sys_sendmsg(p_buf); + } +} +#endif /* BTA_HD_INCLUDED */ diff --git a/components/bt/host/bluedroid/bta/hd/bta_hd_main.c b/components/bt/host/bluedroid/bta/hd/bta_hd_main.c new file mode 100644 index 0000000000..4400b3e172 --- /dev/null +++ b/components/bt/host/bluedroid/bta/hd/bta_hd_main.c @@ -0,0 +1,320 @@ +/****************************************************************************** + * + * Copyright (C) 2016 The Android Open Source Project + * Copyright (C) 2005-2012 Broadcom Corporation + * + * 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. + * + ******************************************************************************/ +/****************************************************************************** + * + * This file contains the HID host main functions and state machine. + * + ******************************************************************************/ +#include "common/bt_target.h" + +#if defined(BTA_HD_INCLUDED) && (BTA_HD_INCLUDED == TRUE) + +#include "bta/bta_hd_api.h" +#include "bta_hd_int.h" +#include + +/***************************************************************************** + * Constants and types + ****************************************************************************/ +/* state machine states */ +enum { + BTA_HD_INIT_ST, + BTA_HD_IDLE_ST, /* not connected, waiting for connection */ + BTA_HD_CONN_ST, /* host connected */ + BTA_HD_TRANSIENT_TO_INIT_ST, /* transient state: going back from CONN to INIT */ +}; +typedef uint8_t tBTA_HD_STATE; + +/* state machine actions */ +enum { + BTA_HD_REGISTER_ACT, + BTA_HD_UNREGISTER_ACT, + BTA_HD_UNREGISTER2_ACT, + BTA_HD_CONNECT_ACT, + BTA_HD_DISCONNECT_ACT, + BTA_HD_ADD_DEVICE_ACT, + BTA_HD_REMOVE_DEVICE_ACT, + BTA_HD_SEND_REPORT_ACT, + BTA_HD_REPORT_ERROR_ACT, + BTA_HD_VC_UNPLUG_ACT, + BTA_HD_OPEN_ACT, + BTA_HD_CLOSE_ACT, + BTA_HD_INTR_DATA_ACT, + BTA_HD_GET_REPORT_ACT, + BTA_HD_SET_REPORT_ACT, + BTA_HD_SET_PROTOCOL_ACT, + BTA_HD_VC_UNPLUG_DONE_ACT, + BTA_HD_SUSPEND_ACT, + BTA_HD_EXIT_SUSPEND_ACT, + BTA_HD_NUM_ACTIONS +}; + +#define BTA_HD_IGNORE BTA_HD_NUM_ACTIONS + +typedef void (*tBTA_HD_ACTION)(tBTA_HD_DATA *p_data); +/* action functions */ +const tBTA_HD_ACTION bta_hd_action[] = { + bta_hd_register_act, bta_hd_unregister_act, bta_hd_unregister2_act, bta_hd_connect_act, + bta_hd_disconnect_act, bta_hd_add_device_act, bta_hd_remove_device_act, bta_hd_send_report_act, + bta_hd_report_error_act, bta_hd_vc_unplug_act, bta_hd_open_act, bta_hd_close_act, + bta_hd_intr_data_act, bta_hd_get_report_act, bta_hd_set_report_act, bta_hd_set_protocol_act, + bta_hd_vc_unplug_done_act, bta_hd_suspend_act, bta_hd_exit_suspend_act, +}; + +/* state table information */ +#define BTA_HD_ACTION 0 /* position of action */ +#define BTA_HD_NEXT_STATE 1 /* position of next state */ +#define BTA_HD_NUM_COLS 2 /* number of columns */ + +const uint8_t bta_hd_st_init[][BTA_HD_NUM_COLS] = { + /* Event Action Next state + */ + /* BTA_HD_API_REGISTER_APP_EVT */ {BTA_HD_REGISTER_ACT, BTA_HD_IDLE_ST}, + /* BTA_HD_API_UNREGISTER_APP_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST}, + /* BTA_HD_API_CONNECT_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST}, + /* BTA_HD_API_DISCONNECT_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST}, + /* BTA_HD_API_ADD_DEVICE_EVT */ {BTA_HD_ADD_DEVICE_ACT, BTA_HD_INIT_ST}, + /* BTA_HD_API_REMOVE_DEVICE_EVT */ {BTA_HD_REMOVE_DEVICE_ACT, BTA_HD_INIT_ST}, + /* BTA_HD_API_SEND_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST}, + /* BTA_HD_API_REPORT_ERROR_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST}, + /* BTA_HD_API_VC_UNPLUG_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST}, + /* BTA_HD_INT_OPEN_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST}, + /* BTA_HD_INT_CLOSE_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST}, + /* BTA_HD_INT_INTR_DATA_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST}, + /* BTA_HD_INT_GET_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST}, + /* BTA_HD_INT_SET_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST}, + /* BTA_HD_INT_SET_PROTOCOL_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST}, + /* BTA_HD_INT_VC_UNPLUG_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST}, + /* BTA_HD_INT_SUSPEND_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST}, + /* BTA_HD_INT_EXIT_SUSPEND_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST}, +}; + +const uint8_t bta_hd_st_idle[][BTA_HD_NUM_COLS] = { + /* Event Action Next state + */ + /* BTA_HD_API_REGISTER_APP_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST}, + /* BTA_HD_API_UNREGISTER_APP_EVT */ {BTA_HD_UNREGISTER_ACT, BTA_HD_INIT_ST}, + /* BTA_HD_API_CONNECT_EVT */ {BTA_HD_CONNECT_ACT, BTA_HD_IDLE_ST}, + /* BTA_HD_API_DISCONNECT_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST}, + /* BTA_HD_API_ADD_DEVICE_EVT */ {BTA_HD_ADD_DEVICE_ACT, BTA_HD_IDLE_ST}, + /* BTA_HD_API_REMOVE_DEVICE_EVT */ {BTA_HD_REMOVE_DEVICE_ACT, BTA_HD_IDLE_ST}, + /* BTA_HD_API_SEND_REPORT_EVT */ {BTA_HD_SEND_REPORT_ACT, BTA_HD_IDLE_ST}, + /* BTA_HD_API_REPORT_ERROR_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST}, + /* BTA_HD_API_VC_UNPLUG_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST}, + /* BTA_HD_INT_OPEN_EVT */ {BTA_HD_OPEN_ACT, BTA_HD_CONN_ST}, + /* BTA_HD_INT_CLOSE_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST}, + /* BTA_HD_INT_INTR_DATA_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST}, + /* BTA_HD_INT_GET_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST}, + /* BTA_HD_INT_SET_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST}, + /* BTA_HD_INT_SET_PROTOCOL_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST}, + /* BTA_HD_INT_VC_UNPLUG_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST}, + /* BTA_HD_INT_SUSPEND_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST}, + /* BTA_HD_INT_EXIT_SUSPEND_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST}, +}; + +const uint8_t bta_hd_st_conn[][BTA_HD_NUM_COLS] = { + /* Event Action Next state */ + /* BTA_HD_API_REGISTER_APP_EVT */ {BTA_HD_IGNORE, BTA_HD_CONN_ST}, + /* BTA_HD_API_UNREGISTER_APP_EVT */ {BTA_HD_DISCONNECT_ACT, BTA_HD_TRANSIENT_TO_INIT_ST}, + /* BTA_HD_API_CONNECT_EVT */ {BTA_HD_IGNORE, BTA_HD_CONN_ST}, + /* BTA_HD_API_DISCONNECT_EVT */ {BTA_HD_DISCONNECT_ACT, BTA_HD_CONN_ST}, + /* BTA_HD_API_ADD_DEVICE_EVT */ {BTA_HD_ADD_DEVICE_ACT, BTA_HD_CONN_ST}, + /* BTA_HD_API_REMOVE_DEVICE_EVT */ {BTA_HD_REMOVE_DEVICE_ACT, BTA_HD_CONN_ST}, + /* BTA_HD_API_SEND_REPORT_EVT */ {BTA_HD_SEND_REPORT_ACT, BTA_HD_CONN_ST}, + /* BTA_HD_API_REPORT_ERROR_EVT */ {BTA_HD_REPORT_ERROR_ACT, BTA_HD_CONN_ST}, + /* BTA_HD_API_VC_UNPLUG_EVT */ {BTA_HD_VC_UNPLUG_ACT, BTA_HD_CONN_ST}, + /* BTA_HD_INT_OPEN_EVT */ {BTA_HD_IGNORE, BTA_HD_CONN_ST}, + /* BTA_HD_INT_CLOSE_EVT */ {BTA_HD_CLOSE_ACT, BTA_HD_IDLE_ST}, + /* BTA_HD_INT_INTR_DATA_EVT */ {BTA_HD_INTR_DATA_ACT, BTA_HD_CONN_ST}, + /* BTA_HD_INT_GET_REPORT_EVT */ {BTA_HD_GET_REPORT_ACT, BTA_HD_CONN_ST}, + /* BTA_HD_INT_SET_REPORT_EVT */ {BTA_HD_SET_REPORT_ACT, BTA_HD_CONN_ST}, + /* BTA_HD_INT_SET_PROTOCOL_EVT */ {BTA_HD_SET_PROTOCOL_ACT, BTA_HD_CONN_ST}, + /* BTA_HD_INT_VC_UNPLUG_EVT */ {BTA_HD_VC_UNPLUG_DONE_ACT, BTA_HD_IDLE_ST}, + /* BTA_HD_INT_SUSPEND_EVT */ {BTA_HD_SUSPEND_ACT, BTA_HD_CONN_ST}, + /* BTA_HD_INT_EXIT_SUSPEND_EVT */ {BTA_HD_EXIT_SUSPEND_ACT, BTA_HD_CONN_ST}, +}; + +const uint8_t bta_hd_st_transient_to_init[][BTA_HD_NUM_COLS] = { + /* Event Action Next state */ + /* BTA_HD_API_REGISTER_APP_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST}, + /* BTA_HD_API_UNREGISTER_APP_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST}, + /* BTA_HD_API_CONNECT_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST}, + /* BTA_HD_API_DISCONNECT_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST}, + /* BTA_HD_API_ADD_DEVICE_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST}, + /* BTA_HD_API_REMOVE_DEVICE_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST}, + /* BTA_HD_API_SEND_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST}, + /* BTA_HD_API_REPORT_ERROR_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST}, + /* BTA_HD_API_VC_UNPLUG_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST}, + /* BTA_HD_INT_OPEN_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST}, + /* BTA_HD_INT_CLOSE_EVT */ {BTA_HD_UNREGISTER2_ACT, BTA_HD_INIT_ST}, + /* BTA_HD_INT_INTR_DATA_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST}, + /* BTA_HD_INT_GET_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST}, + /* BTA_HD_INT_SET_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST}, + /* BTA_HD_INT_SET_PROTOCOL_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST}, + /* BTA_HD_INT_VC_UNPLUG_EVT */ {BTA_HD_UNREGISTER2_ACT, BTA_HD_INIT_ST}, + /* BTA_HD_INT_SUSPEND_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST}, + /* BTA_HD_INT_EXIT_SUSPEND_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST}, +}; + +/* type for state table */ +typedef const uint8_t (*tBTA_HD_ST_TBL)[BTA_HD_NUM_COLS]; +/* state table */ +const tBTA_HD_ST_TBL bta_hd_st_tbl[] = {bta_hd_st_init, bta_hd_st_idle, bta_hd_st_conn, bta_hd_st_transient_to_init}; + +/***************************************************************************** + * Global data + ****************************************************************************/ +#if BTA_DYNAMIC_MEMORY == FALSE +tBTA_HD_CB bta_hd_cb; +#else +tBTA_HD_CB *bta_hd_cb_ptr; +#endif + +static const char *bta_hd_evt_code(tBTA_HD_INT_EVT evt_code); +static const char *bta_hd_state_code(tBTA_HD_STATE state_code); + +/******************************************************************************* + * + * Function bta_hd_sm_execute + * + * Description State machine event handling function for HID Device + * + * Returns void + * + ******************************************************************************/ +void bta_hd_sm_execute(uint16_t event, tBTA_HD_DATA *p_data) +{ + tBTA_HD_ST_TBL state_table; + tBTA_HD_STATE prev_state; + uint8_t action; + tBTA_HD cback_data; + + APPL_TRACE_EVENT("%s: state=%s (%d) event=%s (%d)", __func__, bta_hd_state_code(bta_hd_cb.state), bta_hd_cb.state, + bta_hd_evt_code(event), event); + + prev_state = bta_hd_cb.state; + memset(&cback_data, 0, sizeof(tBTA_HD)); + state_table = bta_hd_st_tbl[bta_hd_cb.state]; + event &= 0xff; + + if ((action = state_table[event][BTA_HD_ACTION]) < BTA_HD_IGNORE) { + (*bta_hd_action[action])(p_data); + } + + bta_hd_cb.state = state_table[event][BTA_HD_NEXT_STATE]; + + if (bta_hd_cb.state != prev_state) { + APPL_TRACE_EVENT("%s: [new] state=%s (%d)", __func__, bta_hd_state_code(bta_hd_cb.state), bta_hd_cb.state); + } + return; +} + +/******************************************************************************* + * + * Function bta_hd_hdl_event + * + * Description HID device main event handling function. + * + * Returns void + * + ******************************************************************************/ +bool bta_hd_hdl_event(BT_HDR *p_msg) +{ + APPL_TRACE_API("%s: p_msg->event=%d", __func__, p_msg->event); + + switch (p_msg->event) { + case BTA_HD_API_ENABLE_EVT: + bta_hd_api_enable((tBTA_HD_DATA *)p_msg); + break; + case BTA_HD_API_DISABLE_EVT: + if (bta_hd_cb.state == BTA_HD_CONN_ST) { + APPL_TRACE_WARNING("%s: host connected, disconnect before disabling", __func__); + // unregister (and disconnect) + bta_hd_cb.disable_w4_close = TRUE; + bta_hd_sm_execute(BTA_HD_API_UNREGISTER_APP_EVT, (tBTA_HD_DATA *)p_msg); + } else { + bta_hd_api_disable(); + } + break; + default: + bta_hd_sm_execute(p_msg->event, (tBTA_HD_DATA *)p_msg); + } + return (TRUE); +} + +static const char *bta_hd_evt_code(tBTA_HD_INT_EVT evt_code) +{ + switch (evt_code) { + case BTA_HD_API_REGISTER_APP_EVT: + return "BTA_HD_API_REGISTER_APP_EVT"; + case BTA_HD_API_UNREGISTER_APP_EVT: + return "BTA_HD_API_UNREGISTER_APP_EVT"; + case BTA_HD_API_CONNECT_EVT: + return "BTA_HD_API_CONNECT_EVT"; + case BTA_HD_API_DISCONNECT_EVT: + return "BTA_HD_API_DISCONNECT_EVT"; + case BTA_HD_API_ADD_DEVICE_EVT: + return "BTA_HD_API_ADD_DEVICE_EVT"; + case BTA_HD_API_REMOVE_DEVICE_EVT: + return "BTA_HD_API_REMOVE_DEVICE_EVT"; + case BTA_HD_API_SEND_REPORT_EVT: + return "BTA_HD_API_SEND_REPORT_EVT"; + case BTA_HD_API_REPORT_ERROR_EVT: + return "BTA_HD_API_REPORT_ERROR_EVT"; + case BTA_HD_API_VC_UNPLUG_EVT: + return "BTA_HD_API_VC_UNPLUG_EVT"; + case BTA_HD_INT_OPEN_EVT: + return "BTA_HD_INT_OPEN_EVT"; + case BTA_HD_INT_CLOSE_EVT: + return "BTA_HD_INT_CLOSE_EVT"; + case BTA_HD_INT_INTR_DATA_EVT: + return "BTA_HD_INT_INTR_DATA_EVT"; + case BTA_HD_INT_GET_REPORT_EVT: + return "BTA_HD_INT_GET_REPORT_EVT"; + case BTA_HD_INT_SET_REPORT_EVT: + return "BTA_HD_INT_SET_REPORT_EVT"; + case BTA_HD_INT_SET_PROTOCOL_EVT: + return "BTA_HD_INT_SET_PROTOCOL_EVT"; + case BTA_HD_INT_VC_UNPLUG_EVT: + return "BTA_HD_INT_VC_UNPLUG_EVT"; + case BTA_HD_INT_SUSPEND_EVT: + return "BTA_HD_INT_SUSPEND_EVT"; + case BTA_HD_INT_EXIT_SUSPEND_EVT: + return "BTA_HD_INT_EXIT_SUSPEND_EVT"; + default: + return ""; + } +} + +static const char *bta_hd_state_code(tBTA_HD_STATE state_code) +{ + switch (state_code) { + case BTA_HD_INIT_ST: + return "BTA_HD_INIT_ST"; + case BTA_HD_IDLE_ST: + return "BTA_HD_IDLE_ST"; + case BTA_HD_CONN_ST: + return "BTA_HD_CONN_ST"; + case BTA_HD_TRANSIENT_TO_INIT_ST: + return "BTA_HD_TRANSIENT_TO_INIT_ST"; + default: + return ""; + } +} +#endif /* BTA_HD_INCLUDED */ diff --git a/components/bt/host/bluedroid/bta/hd/include/bta_hd_int.h b/components/bt/host/bluedroid/bta/hd/include/bta_hd_int.h new file mode 100644 index 0000000000..7a515970e6 --- /dev/null +++ b/components/bt/host/bluedroid/bta/hd/include/bta_hd_int.h @@ -0,0 +1,168 @@ +/****************************************************************************** + * + * Copyright (C) 2016 The Android Open Source Project + * Copyright (C) 2005-2012 Broadcom Corporation + * + * 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. + * + ******************************************************************************/ +/****************************************************************************** + * + * This file contains BTA HID Device internal definitions + * + ******************************************************************************/ +#ifndef BTA_HD_INT_H +#define BTA_HD_INT_H + +#include "bta/bta_hd_api.h" +#include "bta/bta_sys.h" +#include "stack/hiddefs.h" + +enum { + BTA_HD_API_REGISTER_APP_EVT = BTA_SYS_EVT_START(BTA_ID_HD), + BTA_HD_API_UNREGISTER_APP_EVT, + BTA_HD_API_CONNECT_EVT, + BTA_HD_API_DISCONNECT_EVT, + BTA_HD_API_ADD_DEVICE_EVT, + BTA_HD_API_REMOVE_DEVICE_EVT, + BTA_HD_API_SEND_REPORT_EVT, + BTA_HD_API_REPORT_ERROR_EVT, + BTA_HD_API_VC_UNPLUG_EVT, + BTA_HD_INT_OPEN_EVT, + BTA_HD_INT_CLOSE_EVT, + BTA_HD_INT_INTR_DATA_EVT, + BTA_HD_INT_GET_REPORT_EVT, + BTA_HD_INT_SET_REPORT_EVT, + BTA_HD_INT_SET_PROTOCOL_EVT, + BTA_HD_INT_VC_UNPLUG_EVT, + BTA_HD_INT_SUSPEND_EVT, + BTA_HD_INT_EXIT_SUSPEND_EVT, + /* handled outside state machine */ + BTA_HD_API_ENABLE_EVT, + BTA_HD_API_DISABLE_EVT +}; +typedef uint16_t tBTA_HD_INT_EVT; +#define BTA_HD_INVALID_EVT (BTA_HD_API_DISABLE_EVT + 1) +typedef struct { + BT_HDR hdr; + tBTA_HD_CBACK *p_cback; +} tBTA_HD_API_ENABLE; +#define BTA_HD_APP_NAME_LEN 50 +#define BTA_HD_APP_DESCRIPTION_LEN 50 +#define BTA_HD_APP_PROVIDER_LEN 50 +#define BTA_HD_APP_DESCRIPTOR_LEN 2048 +#define BTA_HD_STATE_DISABLED 0x00 +#define BTA_HD_STATE_ENABLED 0x01 +#define BTA_HD_STATE_IDLE 0x02 +#define BTA_HD_STATE_CONNECTED 0x03 +#define BTA_HD_STATE_DISABLING 0x04 +#define BTA_HD_STATE_REMOVING 0x05 +typedef struct { + BT_HDR hdr; + char name[BTA_HD_APP_NAME_LEN + 1]; + char description[BTA_HD_APP_DESCRIPTION_LEN + 1]; + char provider[BTA_HD_APP_PROVIDER_LEN + 1]; + uint8_t subclass; + uint16_t d_len; + uint8_t d_data[BTA_HD_APP_DESCRIPTOR_LEN]; + tBTA_HD_QOS_INFO in_qos; + tBTA_HD_QOS_INFO out_qos; +} tBTA_HD_REGISTER_APP; + +#define BTA_HD_REPORT_LEN HID_DEV_MTU_SIZE + +typedef struct { + BT_HDR hdr; + bool use_intr; + uint8_t type; + uint8_t id; + uint16_t len; + uint8_t data[BTA_HD_REPORT_LEN]; +} tBTA_HD_SEND_REPORT; + +typedef struct { + BT_HDR hdr; + BD_ADDR addr; +} tBTA_HD_DEVICE_CTRL; + +typedef struct { + BT_HDR hdr; + uint8_t error; +} tBTA_HD_REPORT_ERR; + +/* union of all event data types */ +typedef union { + BT_HDR hdr; + tBTA_HD_API_ENABLE api_enable; + tBTA_HD_REGISTER_APP register_app; + tBTA_HD_SEND_REPORT send_report; + tBTA_HD_DEVICE_CTRL device_ctrl; + tBTA_HD_REPORT_ERR report_err; +} tBTA_HD_DATA; + +typedef struct { + BT_HDR hdr; + BD_ADDR addr; + uint32_t data; + BT_HDR *p_data; +} tBTA_HD_CBACK_DATA; + +/****************************************************************************** + * Main Control Block + ******************************************************************************/ +typedef struct { + tBTA_HD_CBACK *p_cback; + uint32_t sdp_handle; + uint8_t trace_level; + uint8_t state; + BD_ADDR bd_addr; + bool use_report_id; + bool boot_mode; + bool vc_unplug; + bool disable_w4_close; +} tBTA_HD_CB; + +#if BTA_DYNAMIC_MEMORY == FALSE +extern tBTA_HD_CB bta_hd_cb; +#else +extern tBTA_HD_CB *bta_hd_cb_ptr; +#define bta_hd_cb (*bta_hd_cb_ptr) +#endif + +/***************************************************************************** + * Function prototypes + ****************************************************************************/ +extern bool bta_hd_hdl_event(BT_HDR *p_msg); +extern void bta_hd_api_enable(tBTA_HD_DATA *p_data); +extern void bta_hd_api_disable(void); +extern void bta_hd_register_act(tBTA_HD_DATA *p_data); +extern void bta_hd_unregister_act(tBTA_HD_DATA *p_data); +extern void bta_hd_unregister2_act(tBTA_HD_DATA *p_data); +extern void bta_hd_connect_act(tBTA_HD_DATA *p_data); +extern void bta_hd_disconnect_act(tBTA_HD_DATA *p_data); +extern void bta_hd_add_device_act(tBTA_HD_DATA *p_data); +extern void bta_hd_remove_device_act(tBTA_HD_DATA *p_data); +extern void bta_hd_send_report_act(tBTA_HD_DATA *p_data); +extern void bta_hd_report_error_act(tBTA_HD_DATA *p_data); +extern void bta_hd_vc_unplug_act(tBTA_HD_DATA *p_data); +extern void bta_hd_open_act(tBTA_HD_DATA *p_data); +extern void bta_hd_close_act(tBTA_HD_DATA *p_data); +extern void bta_hd_intr_data_act(tBTA_HD_DATA *p_data); +extern void bta_hd_get_report_act(tBTA_HD_DATA *p_data); +extern void bta_hd_set_report_act(tBTA_HD_DATA *p_data); +extern void bta_hd_set_protocol_act(tBTA_HD_DATA *p_data); +extern void bta_hd_vc_unplug_done_act(tBTA_HD_DATA *p_data); +extern void bta_hd_suspend_act(tBTA_HD_DATA *p_data); +extern void bta_hd_exit_suspend_act(tBTA_HD_DATA *p_data); + +#endif diff --git a/components/bt/host/bluedroid/bta/hf_client/bta_hf_client_main.c b/components/bt/host/bluedroid/bta/hf_client/bta_hf_client_main.c index dcaf665dbc..4158f015f6 100644 --- a/components/bt/host/bluedroid/bta/hf_client/bta_hf_client_main.c +++ b/components/bt/host/bluedroid/bta/hf_client/bta_hf_client_main.c @@ -214,7 +214,7 @@ const UINT8 bta_hf_client_st_closing[][BTA_HF_CLIENT_NUM_COLS] = { /* DISC_OK_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, /* DISC_FAIL_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, /* SCO_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, - /* SCO_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, + /* SCO_CLOSE_EVT */ {BTA_HF_CLIENT_SCO_CONN_CLOSE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, /* SEND_AT_CMD_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, #if (BTM_SCO_HCI_INCLUDED == TRUE ) /* CI_SCO_DATA_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, diff --git a/components/bt/host/bluedroid/bta/hh/bta_hh_act.c b/components/bt/host/bluedroid/bta/hh/bta_hh_act.c index ce34307707..3edce53bc6 100644 --- a/components/bt/host/bluedroid/bta/hh/bta_hh_act.c +++ b/components/bt/host/bluedroid/bta/hh/bta_hh_act.c @@ -323,6 +323,7 @@ void bta_hh_start_sdp(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) p_cb->sec_mask = p_data->api_conn.sec_mask; p_cb->mode = p_data->api_conn.mode; + p_cb->new_mode = p_data->api_conn.mode; bta_hh_cb.p_cur = p_cb; #if (BTA_HH_LE_INCLUDED == TRUE) @@ -451,6 +452,8 @@ void bta_hh_sdp_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) HID_HostRemoveDev( p_cb->incoming_hid_handle); } conn_dat.status = status; + /* check if host initiate the connection*/ + conn_dat.is_orig = !p_cb->incoming_conn; (* bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn_dat); /* move state machine W4_CONN ->IDLE */ @@ -521,6 +524,8 @@ void bta_hh_open_cmpl_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) memset((void *)&conn, 0, sizeof (tBTA_HH_CONN)); conn.handle = dev_handle; + /* check if host initiate the connection*/ + conn.is_orig = !p_cb->incoming_conn; bdcpy(conn.bda, p_cb->addr); /* increase connection number */ @@ -587,6 +592,7 @@ void bta_hh_open_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) APPL_TRACE_EVENT ("bta_hh_open_act: Device[%d] connected", dev_handle); #endif + p_cb->incoming_conn = TRUE; /* SDP has been done */ if (p_cb->app_id != 0) { bta_hh_sm_execute(p_cb, BTA_HH_OPEN_CMPL_EVT, p_data); @@ -594,7 +600,6 @@ void bta_hh_open_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) /* app_id == 0 indicates an incoming conenction request arrives without SDP performed, do it first */ { - p_cb->incoming_conn = TRUE; /* store the handle here in case sdp fails - need to disconnect */ p_cb->incoming_hid_handle = dev_handle; @@ -676,6 +681,11 @@ void bta_hh_handsk_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) case BTA_HH_SET_IDLE_EVT : cback_data.handle = p_cb->hid_handle; cback_data.status = bta_hh_get_trans_status(p_data->hid_cback.data); + if (cback_data.status == BTA_HH_OK) { + p_cb->mode = p_cb->new_mode; + } else { + p_cb->new_mode = p_cb->mode; + } (* bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH *)&cback_data); p_cb->w4_evt = 0; break; @@ -684,6 +694,8 @@ void bta_hh_handsk_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) case BTA_HH_OPEN_EVT: conn.status = p_data->hid_cback.data ? BTA_HH_ERR_PROTO : BTA_HH_OK; conn.handle = p_cb->hid_handle; + /* check if host initiate the connection*/ + conn.is_orig = !p_cb->incoming_conn; bdcpy(conn.bda, p_cb->addr); (* bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH *)&conn); #if BTA_HH_DEBUG @@ -787,6 +799,8 @@ void bta_hh_open_failure(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) conn_dat.handle = p_cb->hid_handle; conn_dat.status = (reason == HID_ERR_AUTH_FAILED) ? BTA_HH_ERR_AUTH_FAILED : BTA_HH_ERR; + /* check if host initiate the connection*/ + conn_dat.is_orig = !p_cb->incoming_conn; bdcpy(conn_dat.bda, p_cb->addr); HID_HostCloseDev(p_cb->hid_handle); @@ -836,6 +850,8 @@ void bta_hh_close_act (tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) /* Failure in opening connection */ conn_dat.handle = p_cb->hid_handle; conn_dat.status = (reason == HID_ERR_AUTH_FAILED) ? BTA_HH_ERR_AUTH_FAILED : BTA_HH_ERR; + /* check if host initiate the connection*/ + conn_dat.is_orig = !p_cb->incoming_conn; bdcpy(conn_dat.bda, p_cb->addr); HID_HostCloseDev(p_cb->hid_handle); @@ -1019,7 +1035,9 @@ void bta_hh_maint_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) *******************************************************************************/ void bta_hh_write_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) { + tHID_STATUS status; tBTA_HH_CBDATA cbdata = {BTA_HH_OK, 0}; + tBTA_HH_API_SENDDATA send_data = {BTA_HH_OK, 0, 0}; UINT16 event = (p_data->api_sndcmd.t_type - BTA_HH_FST_BTE_TRANS_EVT) + BTA_HH_FST_TRANS_CB_EVT; @@ -1031,25 +1049,33 @@ void bta_hh_write_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) { cbdata.handle = p_cb->hid_handle; + send_data.handle = p_cb->hid_handle; /* match up BTE/BTA report/boot mode def */ if (p_data->api_sndcmd.t_type == HID_TRANS_SET_PROTOCOL) { + p_cb->new_mode = p_data->api_sndcmd.param; p_data->api_sndcmd.param = ( p_data->api_sndcmd.param == BTA_HH_PROTO_RPT_MODE) ? \ HID_PAR_PROTOCOL_REPORT : HID_PAR_PROTOCOL_BOOT_MODE; } - if (HID_HostWriteDev (p_cb->hid_handle, - p_data->api_sndcmd.t_type, - p_data->api_sndcmd.param, - p_data->api_sndcmd.data, - p_data->api_sndcmd.rpt_id, - p_data->api_sndcmd.p_data) != HID_SUCCESS) { - APPL_TRACE_ERROR("HID_HostWriteDev Error "); + status = HID_HostWriteDev(p_cb->hid_handle, p_data->api_sndcmd.t_type, p_data->api_sndcmd.param, + p_data->api_sndcmd.data, p_data->api_sndcmd.rpt_id, p_data->api_sndcmd.p_data); + if (status != HID_SUCCESS) { + APPL_TRACE_ERROR("HID_HostWriteDev status:%d", status); cbdata.status = BTA_HH_ERR; + send_data.status = BTA_HH_ERR; - if (p_data->api_sndcmd.t_type != HID_TRANS_CONTROL && - p_data->api_sndcmd.t_type != HID_TRANS_DATA) { - (* bta_hh_cb.p_cback)(event, (tBTA_HH *)&cbdata); + if (p_data->api_sndcmd.t_type != HID_TRANS_CONTROL) { + switch (p_data->api_sndcmd.t_type) { + case HID_TRANS_DATA: + event = BTA_HH_DATA_EVT; + send_data.reason = status; + (*bta_hh_cb.p_cback)(event, (tBTA_HH *)&send_data); + break; + default: + (*bta_hh_cb.p_cback)(event, (tBTA_HH *)&cbdata); + break; + } } else if (p_data->api_sndcmd.param == BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG) { (* bta_hh_cb.p_cback)(BTA_HH_VC_UNPLUG_EVT, (tBTA_HH *)&cbdata); } @@ -1070,6 +1096,7 @@ void bta_hh_write_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) p_cb->w4_evt = event; break; case HID_TRANS_DATA: /* output report */ + (*bta_hh_cb.p_cback)(BTA_HH_DATA_EVT, (tBTA_HH *)&send_data); /* fall through */ case HID_TRANS_CONTROL: /* no handshake event will be generated */ @@ -1098,7 +1125,6 @@ void bta_hh_write_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) bta_sys_busy(BTA_ID_HH, p_cb->app_id, p_cb->addr); } } - } return; } diff --git a/components/bt/host/bluedroid/bta/hh/bta_hh_cfg.c b/components/bt/host/bluedroid/bta/hh/bta_hh_cfg.c index 65e06c7345..383f23262c 100644 --- a/components/bt/host/bluedroid/bta/hh/bta_hh_cfg.c +++ b/components/bt/host/bluedroid/bta/hh/bta_hh_cfg.c @@ -24,9 +24,9 @@ ******************************************************************************/ #include "common/bt_target.h" -#include "bta/bta_hh_api.h" #if defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE) +#include "bta/bta_hh_api.h" /* max number of device types supported by BTA */ diff --git a/components/bt/host/bluedroid/bta/hh/bta_hh_le.c b/components/bt/host/bluedroid/bta/hh/bta_hh_le.c index 967cd61b08..a80314efa6 100644 --- a/components/bt/host/bluedroid/bta/hh/bta_hh_le.c +++ b/components/bt/host/bluedroid/bta/hh/bta_hh_le.c @@ -32,7 +32,7 @@ #include "bta/utl.h" #define LOG_TAG "bt_bta_hh" -#include "osi/include/log.h" +// #include "osi/include/log.h" #ifndef BTA_HH_LE_RECONN #define BTA_HH_LE_RECONN TRUE diff --git a/components/bt/host/bluedroid/bta/hh/bta_hh_main.c b/components/bt/host/bluedroid/bta/hh/bta_hh_main.c index a5ca868723..663d28e96f 100644 --- a/components/bt/host/bluedroid/bta/hh/bta_hh_main.c +++ b/components/bt/host/bluedroid/bta/hh/bta_hh_main.c @@ -292,6 +292,8 @@ void bta_hh_sm_execute(tBTA_HH_DEV_CB *p_cb, UINT16 event, tBTA_HH_DATA *p_data) bdcpy(cback_data.conn.bda, ((tBTA_HH_API_CONN *)p_data)->bd_addr); cback_data.conn.status = BTA_HH_ERR_DB_FULL; cback_data.conn.handle = BTA_HH_INVALID_HANDLE; + /* check if host initiate the connection*/ + cback_data.conn.is_orig = !p_cb->incoming_conn; break; /* DB full, BTA_HhAddDev */ case BTA_HH_API_MAINT_DEV_EVT: @@ -340,7 +342,7 @@ void bta_hh_sm_execute(tBTA_HH_DEV_CB *p_cb, UINT16 event, tBTA_HH_DATA *p_data) default: /* invalid handle, call bad API event */ - APPL_TRACE_ERROR("wrong device handle: [%d]", p_data->hdr.layer_specific); + APPL_TRACE_ERROR("wrong device handle: [%d], event:%d", p_data->hdr.layer_specific, event - BTA_HH_API_OPEN_EVT); /* Free the callback buffer now */ if (p_data != NULL && p_data->hid_cback.p_data != NULL) { osi_free(p_data->hid_cback.p_data); @@ -443,6 +445,10 @@ BOOLEAN bta_hh_hdl_event(BT_HDR *p_msg) } } else if (p_msg->event == BTA_HH_INT_OPEN_EVT) { index = bta_hh_find_cb(((tBTA_HH_CBACK_DATA *)p_msg)->addr); + uint8_t hdl = BTA_HH_IDX_INVALID; + if (HID_HostGetDev(((tBTA_HH_CBACK_DATA *)p_msg)->addr, &hdl) == HID_SUCCESS && hdl != BTA_HH_IDX_INVALID) { + bta_hh_cb.cb_index[hdl] = bta_hh_cb.kdev[index].index; + } } else { index = bta_hh_dev_handle_to_cb_idx((UINT8)p_msg->layer_specific); } diff --git a/components/bt/host/bluedroid/bta/hh/bta_hh_utils.c b/components/bt/host/bluedroid/bta/hh/bta_hh_utils.c index 121e11834b..8ca8b09c45 100644 --- a/components/bt/host/bluedroid/bta/hh/bta_hh_utils.c +++ b/components/bt/host/bluedroid/bta/hh/bta_hh_utils.c @@ -237,7 +237,7 @@ BOOLEAN bta_hh_tod_spt(tBTA_HH_DEV_CB *p_cb, UINT8 sub_class) } } #if BTA_HH_DEBUG - APPL_TRACE_EVENT("bta_hh_tod_spt sub_class:0x%x NOT supported", sub_class); + APPL_TRACE_ERROR("bta_hh_tod_spt sub_class:0x%x NOT supported", sub_class); #endif return FALSE; } @@ -460,9 +460,11 @@ void bta_hh_cleanup_disable(tBTA_HH_STATUS status) } utl_freebuf((void **)&bta_hh_cb.p_disc_db); - (* bta_hh_cb.p_cback)(BTA_HH_DISABLE_EVT, (tBTA_HH *)&status); - /* all connections are down, no waiting for diconnect */ - memset(&bta_hh_cb, 0, sizeof(tBTA_HH_CB)); + if (bta_hh_cb.p_cback) { + (*bta_hh_cb.p_cback)(BTA_HH_DISABLE_EVT, (tBTA_HH*)&status); + /* all connections are down, no waiting for diconnect */ + memset(&bta_hh_cb, 0, sizeof(tBTA_HH_CB)); + } } /******************************************************************************* diff --git a/components/bt/host/bluedroid/bta/hh/include/bta_hh_int.h b/components/bt/host/bluedroid/bta/hh/include/bta_hh_int.h index 58a8b59a3d..0efb2fcab4 100644 --- a/components/bt/host/bluedroid/bta/hh/include/bta_hh_int.h +++ b/components/bt/host/bluedroid/bta/hh/include/bta_hh_int.h @@ -243,6 +243,7 @@ typedef struct { UINT8 incoming_hid_handle; /* temporary handle for incoming connection? */ BOOLEAN opened; /* TRUE if device successfully opened HID connection */ tBTA_HH_PROTO_MODE mode; /* protocol mode */ + tBTA_HH_PROTO_MODE new_mode; /* protocol mode */ tBTA_HH_STATE state; /* CB state */ #if (BTA_HH_LE_INCLUDED == TRUE) @@ -364,6 +365,7 @@ extern void bta_hh_disc_cmpl(void); extern tBTA_HH_STATUS bta_hh_read_ssr_param(BD_ADDR bd_addr, UINT16 *p_max_ssr_lat, UINT16 *p_min_ssr_tout); /* functions for LE HID */ +#if (BTA_HH_LE_INCLUDED == TRUE) extern void bta_hh_le_enable(void); extern BOOLEAN bta_hh_le_is_hh_gatt_if(tBTA_GATTC_IF client_if); extern void bta_hh_le_deregister(void); @@ -391,6 +393,7 @@ extern void bta_hh_security_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf); extern void bta_hh_le_update_scpp(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf); extern void bta_hh_le_notify_enc_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data); extern void bta_hh_ci_load_rpt (tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf); +#endif #if BTA_HH_DEBUG extern void bta_hh_trace_dev_db(void); 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 32e59d27e2..735c210f2f 100644 --- a/components/bt/host/bluedroid/bta/include/bta/bta_api.h +++ b/components/bt/host/bluedroid/bta/include/bta/bta_api.h @@ -78,7 +78,7 @@ typedef UINT8 tBTA_STATUS; #define BTA_SAP_SERVICE_ID 17 /* SIM Access profile */ #define BTA_A2DP_SINK_SERVICE_ID 18 /* A2DP Sink */ #define BTA_AVRCP_SERVICE_ID 19 /* A/V remote control */ -#define BTA_HID_SERVICE_ID 20 /* HID */ +#define BTA_HID_SERVICE_ID 20 /* HID Host*/ #define BTA_VDP_SERVICE_ID 21 /* Video distribution */ #define BTA_PBAP_SERVICE_ID 22 /* PhoneBook Access Server*/ #define BTA_HSP_HS_SERVICE_ID 23 /* HFP HS role */ @@ -1331,8 +1331,8 @@ typedef UINT8 tBTA_DM_PM_ACTION; #endif #ifndef BTA_DM_PM_SNIFF2_MAX -#define BTA_DM_PM_SNIFF2_MAX 180 -#define BTA_DM_PM_SNIFF2_MIN 150 +#define BTA_DM_PM_SNIFF2_MAX 54 //180 +#define BTA_DM_PM_SNIFF2_MIN 30 //150 #define BTA_DM_PM_SNIFF2_ATTEMPT 4 #define BTA_DM_PM_SNIFF2_TIMEOUT 1 #endif @@ -1345,8 +1345,8 @@ typedef UINT8 tBTA_DM_PM_ACTION; #endif #ifndef BTA_DM_PM_SNIFF4_MAX -#define BTA_DM_PM_SNIFF4_MAX 54 -#define BTA_DM_PM_SNIFF4_MIN 30 +#define BTA_DM_PM_SNIFF4_MAX 18 //54 +#define BTA_DM_PM_SNIFF4_MIN 10 //30 #define BTA_DM_PM_SNIFF4_ATTEMPT 4 #define BTA_DM_PM_SNIFF4_TIMEOUT 1 #endif diff --git a/components/bt/host/bluedroid/bta/include/bta/bta_hd_api.h b/components/bt/host/bluedroid/bta/include/bta/bta_hd_api.h new file mode 100644 index 0000000000..1c7e708e2f --- /dev/null +++ b/components/bt/host/bluedroid/bta/include/bta/bta_hd_api.h @@ -0,0 +1,295 @@ +/****************************************************************************** + * + * Copyright (C) 2016 The Android Open Source Project + * Copyright (C) 2002-2012 Broadcom Corporation + * + * 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. + * + ******************************************************************************/ +#ifndef BTA_HD_API_H +#define BTA_HD_API_H + +#include "bta_api.h" +#include "stack/hidd_api.h" + +#if BTA_HD_INCLUDED == TRUE + +/***************************************************************************** + * Constants and Type Definitions + ****************************************************************************/ + +#ifndef BTA_HD_DEBUG +#define BTA_HD_DEBUG TRUE +#endif + +/* BTA HID Device callback events */ +#define BTA_HD_ENABLE_EVT 0 /* BT-HD enabled */ +#define BTA_HD_DISABLE_EVT 1 /* BT-HD disabled */ +#define BTA_HD_REGISTER_APP_EVT 2 /* application registered */ +#define BTA_HD_UNREGISTER_APP_EVT 3 /* application unregistered */ +#define BTA_HD_OPEN_EVT 4 /* connection to host opened */ +#define BTA_HD_CLOSE_EVT 5 /* connection to host closed */ +#define BTA_HD_GET_REPORT_EVT 6 /* GET_REPORT request from host */ +#define BTA_HD_SET_REPORT_EVT 7 /* SET_REPORT request from host */ +#define BTA_HD_SET_PROTOCOL_EVT 8 /* SET_PROTOCOL request from host */ +#define BTA_HD_INTR_DATA_EVT 9 /* DATA received from host on intr */ +#define BTA_HD_VC_UNPLUG_EVT 10 /* Virtual Cable Unplug */ +// #define BTA_HD_CONN_STATE_EVT 11 /* Report connection state change */ +#define BTA_HD_SEND_REPORT_EVT 12 /* Send report finish */ +#define BTA_HD_REPORT_ERR_EVT 13 /* Report Handshake finish */ +#define BTA_HD_API_ERR_EVT 99 /* BT-HD API error */ + +typedef uint16_t tBTA_HD_EVT; + +enum { BTA_HD_OK, BTA_HD_ERROR }; + +typedef enum { + BTA_HD_CONN_STATE_CONNECTED, + BTA_HD_CONN_STATE_CONNECTING, + BTA_HD_CONN_STATE_DISCONNECTED, + BTA_HD_CONN_STATE_DISCONNECTING, + BTA_HD_CONN_STATE_UNKNOWN +} tBTA_HD_CONN_STAT; + +typedef uint8_t tBTA_HD_STATUS; +typedef tHID_DEV_DSCP_INFO tBTA_HD_DEV_DESCR; + +typedef struct { + char *p_name; + char *p_description; + char *p_provider; + uint8_t subclass; + tBTA_HD_DEV_DESCR descriptor; +} tBTA_HD_APP_INFO; + +typedef struct { + uint8_t service_type; + uint32_t token_rate; + uint32_t token_bucket_size; + uint32_t peak_bandwidth; + uint32_t access_latency; + uint32_t delay_variation; +} tBTA_HD_QOS_INFO; + +typedef struct { + bool use_intr; + uint8_t type; + uint8_t id; + uint16_t len; + uint8_t *p_data; +} tBTA_HD_REPORT; + +typedef struct { + tBTA_HD_STATUS status; + bool in_use; + BD_ADDR bda; +} tBTA_HD_REG_STATUS; + +typedef struct { + BD_ADDR bda; + tBTA_HD_STATUS status; + tBTA_HD_CONN_STAT conn_status; +} tBTA_HD_CONN; + +typedef struct { + uint8_t report_type; + uint8_t report_id; + uint16_t buffer_size; +} tBTA_HD_GET_REPORT; + +typedef struct { + uint8_t report_type; + uint8_t report_id; + uint16_t len; + uint8_t *p_data; +} tBTA_HD_SET_REPORT; + +typedef uint8_t tBTA_HD_SET_PROTOCOL; + +typedef struct { + uint8_t report_id; + uint16_t len; + uint8_t *p_data; +} tBTA_HD_INTR_DATA; + +typedef struct { + tBTA_HD_STATUS status; + uint8_t reason; + uint8_t report_type; + uint8_t report_id; +} tBTA_HD_API_SEND_REPORT; + +typedef struct { + tBTA_HD_STATUS status; + uint8_t reason; +} tBTA_HD_API_REPORT_ERR; + +/* union of data associated with HD callback */ +typedef union { + tBTA_HD_STATUS status; /* BTA_HD_ENABLE_EVT + BTA_HD_DISABLE_EVT + BTA_HD_UNREGISTER_APP_EVT */ + tBTA_HD_REG_STATUS reg_status; /* BTA_HD_REGISTER_APP_EVT */ + tBTA_HD_CONN conn; /* BTA_HD_OPEN_EVT + BTA_HD_CLOSE_EVT + BTA_HD_VC_UNPLUG_EVT + BTA_HD_OWN_VC_UNPLUG_EVT */ + tBTA_HD_GET_REPORT get_report; /* BTA_HD_GET_REPORT */ + tBTA_HD_SET_REPORT set_report; /* BTA_HD_SET_REPORT */ + tBTA_HD_SET_PROTOCOL set_protocol; /* BTA_HD_SETPROTOCOL */ + tBTA_HD_INTR_DATA intr_data; /* BTA_HD_INTR_DATA_EVT */ + tBTA_HD_API_SEND_REPORT send_report; /* BTA_HD_API_SEND_REPORT_EVT */ + tBTA_HD_API_REPORT_ERR report_err; /* BTA_HD_API_REPORT_ERR_EVT */ +} tBTA_HD; + +/* BTA HD callback function */ +typedef void (tBTA_HD_CBACK)(tBTA_HD_EVT event, tBTA_HD *p_data); + +/***************************************************************************** + * External Function Declarations + ****************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif + +/******************************************************************************* + * + * Function BTA_HhRegister + * + * Description This function enable HID host and registers HID-Host with + * lower layers. + * + * Returns void + * + ******************************************************************************/ +extern void BTA_HdEnable(tBTA_HD_CBACK *p_cback); + +/******************************************************************************* + * + * Function BTA_HhDeregister + * + * Description This function is called when the host is about power down. + * + * Returns void + * + ******************************************************************************/ +extern void BTA_HdDisable(void); + +/******************************************************************************* + * + * Function BTA_HdRegisterApp + * + * Description This function is called when application should be + * registered + * + * Returns void + * + ******************************************************************************/ +extern void BTA_HdRegisterApp(tBTA_HD_APP_INFO *p_app_info, tBTA_HD_QOS_INFO *p_in_qos, tBTA_HD_QOS_INFO *p_out_qos); + +/******************************************************************************* + * + * Function BTA_HdUnregisterApp + * + * Description This function is called when application should be + * unregistered + * + * Returns void + * + ******************************************************************************/ +extern void BTA_HdUnregisterApp(void); + +/******************************************************************************* + * + * Function BTA_HdSendReport + * + * Description This function is called when report is to be sent + * + * Returns void + * + ******************************************************************************/ +extern void BTA_HdSendReport(tBTA_HD_REPORT *p_report); + +/******************************************************************************* + * + * Function BTA_HdVirtualCableUnplug + * + * Description This function is called when VCU shall be sent + * + * Returns void + * + ******************************************************************************/ +extern void BTA_HdVirtualCableUnplug(void); + +/******************************************************************************* + * + * Function BTA_HdConnect + * + * Description This function is called when connection to host shall be + * made. + * + * Returns void + * + ******************************************************************************/ +extern void BTA_HdConnect(BD_ADDR addr); + +/******************************************************************************* + * + * Function BTA_HdDisconnect + * + * Description This function is called when host shall be disconnected + * + * Returns void + * + ******************************************************************************/ +extern void BTA_HdDisconnect(void); + +/******************************************************************************* + * + * Function BTA_HdAddDevice + * + * Description This function is called when a device is virtually cabled + * + * Returns void + * + ******************************************************************************/ +extern void BTA_HdAddDevice(BD_ADDR addr); + +/******************************************************************************* + * + * Function BTA_HdRemoveDevice + * + * Description This function is called when a device is virtually uncabled + * + * Returns void + * + ******************************************************************************/ +extern void BTA_HdRemoveDevice(BD_ADDR addr); + +/******************************************************************************* + * + * Function BTA_HdReportError + * + * Description This function is called when reporting error for set report + * + * Returns void + * + ******************************************************************************/ +extern void BTA_HdReportError(uint8_t error); + +#ifdef __cplusplus +} +#endif + +#endif /* BTA_HD_INCLUDED */ +#endif /* BTA_HD_API_H */ diff --git a/components/bt/host/bluedroid/bta/include/bta/bta_hh_api.h b/components/bt/host/bluedroid/bta/include/bta/bta_hh_api.h index e1bf4017fb..88cd192627 100644 --- a/components/bt/host/bluedroid/bta/include/bta/bta_hh_api.h +++ b/components/bt/host/bluedroid/bta/include/bta/bta_hh_api.h @@ -58,7 +58,8 @@ #define BTA_HH_VC_UNPLUG_EVT 13 /* virtually unplugged */ #define BTA_HH_DATA_EVT 15 #define BTA_HH_API_ERR_EVT 16 /* API error is caught */ -#define BTA_HH_UPDATE_SCPP_EVT 17 /* update scan paramter complete */ +#define BTA_HH_UPDATE_SCPP_EVT 17 /* update scan paramter complete */ +#define BTA_HH_DATA_IND_EVT 18 /* Data on interrupt channel */ typedef UINT16 tBTA_HH_EVT; @@ -131,8 +132,8 @@ enum { BTA_HH_ERR_TOD_UNSPT, /* type of device not supported */ BTA_HH_ERR_NO_RES, /* out of system resources */ BTA_HH_ERR_AUTH_FAILED, /* authentication fail */ - BTA_HH_ERR_HDL, - BTA_HH_ERR_SEC + BTA_HH_ERR_HDL, /* connection handle error */ + BTA_HH_ERR_SEC, /* encryption error */ }; typedef UINT8 tBTA_HH_STATUS; @@ -210,6 +211,7 @@ typedef struct { BD_ADDR bda; /* HID device bd address */ tBTA_HH_STATUS status; /* operation status */ UINT8 handle; /* device handle */ + BOOLEAN is_orig; /* indicate if host initiate connection */ #if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE) BOOLEAN le_hid; /* is LE devices? */ BOOLEAN scps_supported; /* scan parameter service supported */ @@ -257,9 +259,9 @@ typedef struct { typedef struct { tBTA_HH_BOOT_RPT_ID dev_type; /* type of device report */ union { - tBTA_HH_KEYBD_RPT keybd_rpt; /* keyboard report */ - tBTA_HH_MICE_RPT mice_rpt; /* mouse report */ - } data_rpt; + tBTA_HH_KEYBD_RPT keybd_rpt; /* keyboard report */ + tBTA_HH_MICE_RPT mice_rpt; /* mouse report */ + } data_rpt; } tBTA_HH_BOOT_RPT; /* handshake data */ @@ -267,13 +269,29 @@ typedef struct { tBTA_HH_STATUS status; /* handshake status */ UINT8 handle; /* device handle */ union { - tBTA_HH_PROTO_MODE proto_mode; /* GET_PROTO_EVT :protocol mode */ - BT_HDR *p_rpt_data; /* GET_RPT_EVT : report data */ - UINT8 idle_rate; /* GET_IDLE_EVT : idle rate */ - } rsp_data; + tBTA_HH_PROTO_MODE proto_mode; /* GET_PROTO_EVT :protocol mode */ + BT_HDR *p_rpt_data; /* GET_RPT_EVT : report data */ + UINT8 idle_rate; /* GET_IDLE_EVT : idle rate */ + } rsp_data; } tBTA_HH_HSDATA; + +/* upper layer send data */ +typedef struct { + tBTA_HH_STATUS status; /* handshake status */ + UINT8 handle; /* device handle */ + UINT8 reason; /* send data failed reason */ +} tBTA_HH_API_SENDDATA; + +/* interrupt channel data */ +typedef struct { + tBTA_HH_STATUS status; /* handshake status */ + UINT8 handle; /* device handle */ + tBTA_HH_PROTO_MODE proto_mode; /* protocol mode */ + BT_HDR *p_data; /* DATA_EVT : feature report data */ +} tBTA_HH_INTDATA; + /* union of data associated with HD callback */ typedef union { tBTA_HH_DEV_INFO dev_info; /* BTA_HH_ADD_DEV_EVT, BTA_HH_RMV_DEV_EVT */ @@ -290,10 +308,12 @@ typedef union { BTA_HH_GET_RPT_EVT BTA_HH_GET_PROTO_EVT BTA_HH_GET_IDLE_EVT */ + tBTA_HH_API_SENDDATA send_data; /* BTA_HH_DATA_EVT */ + tBTA_HH_INTDATA int_data; /* BTA_HH_DATA_IND_EVT */ } tBTA_HH; /* BTA HH callback function */ -typedef void (tBTA_HH_CBACK) (tBTA_HH_EVT event, tBTA_HH *p_data); +typedef void (tBTA_HH_CBACK)(tBTA_HH_EVT event, tBTA_HH *p_data); /***************************************************************************** diff --git a/components/bt/host/bluedroid/bta/include/bta/bta_sys.h b/components/bt/host/bluedroid/bta/include/bta/bta_sys.h index a466028b95..87359b5a9f 100644 --- a/components/bt/host/bluedroid/bta/include/bta/bta_sys.h +++ b/components/bt/host/bluedroid/bta/include/bta/bta_sys.h @@ -225,6 +225,7 @@ extern void bta_sys_sendmsg(void *p_msg); extern void bta_sys_start_timer(TIMER_LIST_ENT *p_tle, UINT16 type, INT32 timeout_ms); extern void bta_sys_stop_timer(TIMER_LIST_ENT *p_tle); extern void bta_sys_free_timer(TIMER_LIST_ENT *p_tle); +extern BOOLEAN bta_sys_timer_is_active(TIMER_LIST_ENT *p_tle); extern void bta_sys_disable(tBTA_SYS_HW_MODULE module); extern UINT32 bta_sys_get_remaining_ticks(TIMER_LIST_ENT *p_target_tle); diff --git a/components/bt/host/bluedroid/bta/sys/bta_sys_main.c b/components/bt/host/bluedroid/bta/sys/bta_sys_main.c index 58983d3a5d..db6ee48972 100644 --- a/components/bt/host/bluedroid/bta/sys/bta_sys_main.c +++ b/components/bt/host/bluedroid/bta/sys/bta_sys_main.c @@ -638,6 +638,27 @@ UINT32 bta_sys_get_remaining_ticks(TIMER_LIST_ENT *p_target_tle) } +/******************************************************************************* +** +** Function bta_sys_timer_is_active +** +** Description Get info of timer is active or not. +** +** Returns true if timer is exist and active, false otherwise. +** +*******************************************************************************/ +BOOLEAN bta_sys_timer_is_active(TIMER_LIST_ENT *p_tle) +{ + assert(p_tle != NULL); + + osi_alarm_t *alarm = hash_map_get(bta_alarm_hash_map, p_tle); + if (alarm != NULL && osi_alarm_is_active(alarm)) { + return TRUE; + } + + return FALSE; +} + /******************************************************************************* ** ** Function bta_sys_stop_timer diff --git a/components/bt/host/bluedroid/btc/core/btc_storage.c b/components/bt/host/bluedroid/btc/core/btc_storage.c index 97bef05fc7..bbaa7f8389 100644 --- a/components/bt/host/bluedroid/btc/core/btc_storage.c +++ b/components/bt/host/bluedroid/btc/core/btc_storage.c @@ -16,11 +16,13 @@ #include "btc/btc_storage.h" #include "btc/btc_util.h" #include "osi/osi.h" +#include "osi/allocator.h" #include "common/bt_trace.h" #include "esp_system.h" #include "bta/bta_api.h" #include "device/bdaddr.h" #include "btc/btc_config.h" +#include "btc_hh.h" /******************************************************************************* ** @@ -247,3 +249,252 @@ bt_status_t btc_storage_get_bonded_bt_devices_list(bt_bdaddr_t *bond_dev, int *d return BT_STATUS_SUCCESS; } + +#if (defined BTC_HH_INCLUDED && BTC_HH_INCLUDED == TRUE) +/******************************************************************************* + * + * Function btc_storage_add_hid_device_info + * + * Description BTC storage API - Adds the hid information of bonded hid + * devices-to NVRAM + * + * Returns BT_STATUS_SUCCESS if the store was successful, + * BT_STATUS_FAIL otherwise + * + ******************************************************************************/ + +bt_status_t btc_storage_add_hid_device_info(bt_bdaddr_t *remote_bd_addr, uint16_t attr_mask, uint8_t sub_class, + uint8_t app_id, uint16_t vendor_id, uint16_t product_id, uint16_t version, + uint8_t ctry_code, uint16_t ssr_max_latency, uint16_t ssr_min_tout, + uint16_t dl_len, uint8_t *dsc_list) +{ + BTC_TRACE_DEBUG("btc_storage_add_hid_device_info:"); + bdstr_t bdstr; + bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr)); + btc_config_lock(); + int ret = btc_config_set_int(bdstr, "HidAttrMask", attr_mask); + ret &= btc_config_set_int(bdstr, "HidSubClass", sub_class); + ret &= btc_config_set_int(bdstr, "HidAppId", app_id); + ret &= btc_config_set_int(bdstr, "HidVendorId", vendor_id); + ret &= btc_config_set_int(bdstr, "HidProductId", product_id); + ret &= btc_config_set_int(bdstr, "HidVersion", version); + ret &= btc_config_set_int(bdstr, "HidCountryCode", ctry_code); + ret &= btc_config_set_int(bdstr, "HidSSRMaxLatency", ssr_max_latency); + ret &= btc_config_set_int(bdstr, "HidSSRMinTimeout", ssr_min_tout); + if (dl_len > 0) + btc_config_set_bin(bdstr, "HidDescriptor", dsc_list, dl_len); + btc_config_flush(); + btc_config_unlock(); + + BTC_TRACE_DEBUG("Storage add hid device info %d\n", ret); + return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL; +} + +/******************************************************************************* + * + * Function btc_storage_load_bonded_hid_info + * + * Description BTIF storage API - Loads hid info for all the bonded devices + * from NVRAM and adds those devices to the BTA_HH. + * + * Returns BT_STATUS_SUCCESS if successful, BT_STATUS_FAIL otherwise + * + ******************************************************************************/ +bt_status_t btc_storage_load_bonded_hid_info(void) +{ + int value; + btc_config_lock(); + for (const btc_config_section_iter_t *iter = btc_config_section_begin(); iter != btc_config_section_end(); + iter = btc_config_section_next(iter)) { + const char *name = btc_config_section_name(iter); + if (string_is_bdaddr(name) && btc_config_exist(name, BTC_STORAGE_LINK_KEY_TYPE_STR) && + btc_config_exist(name, BTC_STORAGE_PIN_LENGTH_STR) && btc_config_exist(name, BTC_STORAGE_SC_SUPPORT) && + btc_config_exist(name, BTC_STORAGE_LINK_KEY_STR) && btc_config_exist(name, "HidAttrMask")) { + btc_config_get_int(name, "HidAttrMask", &value); + uint16_t attr_mask = (uint16_t)value; + + tBTA_HH_DEV_DSCP_INFO dscp_info; + memset(&dscp_info, 0, sizeof(dscp_info)); + + btc_config_get_int(name, "HidSubClass", &value); + uint8_t sub_class = (uint8_t)value; + + btc_config_get_int(name, "HidAppId", &value); + uint8_t app_id = (uint8_t)value; + + btc_config_get_int(name, "HidVendorId", &value); + dscp_info.vendor_id = (uint16_t)value; + + btc_config_get_int(name, "HidProductId", &value); + dscp_info.product_id = (uint16_t)value; + + btc_config_get_int(name, "HidVersion", &value); + dscp_info.version = (uint8_t)value; + + btc_config_get_int(name, "HidCountryCode", &value); + dscp_info.ctry_code = (uint8_t)value; + + value = 0; + btc_config_get_int(name, "HidSSRMaxLatency", &value); + dscp_info.ssr_max_latency = (uint16_t)value; + + value = 0; + btc_config_get_int(name, "HidSSRMinTimeout", &value); + dscp_info.ssr_min_tout = (uint16_t)value; + + size_t len = btc_config_get_bin_length(name, "HidDescriptor"); + if (len > 0) { + dscp_info.descriptor.dl_len = (uint16_t)len; + dscp_info.descriptor.dsc_list = (uint8_t *)osi_malloc(len); + btc_config_get_bin(name, "HidDescriptor", (uint8_t *)dscp_info.descriptor.dsc_list, &len); + } + + // add extracted information to BTA HH + bt_bdaddr_t bd_addr; + if (string_to_bdaddr(name, &bd_addr) && btc_hh_add_added_dev(*(BD_ADDR *)&bd_addr, attr_mask)) { + BTA_HhAddDev(*(BD_ADDR *)&bd_addr, attr_mask, sub_class, app_id, dscp_info); + } + + if (dscp_info.descriptor.dsc_list) { + osi_free(dscp_info.descriptor.dsc_list); + dscp_info.descriptor.dsc_list = NULL; + } + } + } + btc_config_unlock(); + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* + * + * Function btc_storage_remove_hid_info + * + * Description BTC storage API - Deletes the bonded hid device info from + * NVRAM + * + * Returns BT_STATUS_SUCCESS if the deletion was successful, + * BT_STATUS_FAIL otherwise + * + ******************************************************************************/ +bt_status_t btc_storage_remove_hid_info(bt_bdaddr_t *remote_bd_addr) +{ + bdstr_t bdstr; + bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr)); + int ret = 1; + btc_config_lock(); + if (btc_config_exist(bdstr, "HidAttrMask")) { + ret &= btc_config_remove(bdstr, "HidAttrMask"); + } + if (btc_config_exist(bdstr, "HidSubClass")) { + ret &= btc_config_remove(bdstr, "HidSubClass"); + } + if (btc_config_exist(bdstr, "HidAppId")) { + ret &= btc_config_remove(bdstr, "HidAppId"); + } + if (btc_config_exist(bdstr, "HidVendorId")) { + ret &= btc_config_remove(bdstr, "HidVendorId"); + } + if (btc_config_exist(bdstr, "HidProductId")) { + ret &= btc_config_remove(bdstr, "HidProductId"); + } + if (btc_config_exist(bdstr, "HidVersion")) { + ret &= btc_config_remove(bdstr, "HidVersion"); + } + if (btc_config_exist(bdstr, "HidCountryCode")) { + ret &= btc_config_remove(bdstr, "HidCountryCode"); + } + if (btc_config_exist(bdstr, "HidSSRMaxLatency")) { + ret &= btc_config_remove(bdstr, "HidSSRMaxLatency"); + } + if (btc_config_exist(bdstr, "HidSSRMinTimeout")) { + ret &= btc_config_remove(bdstr, "HidSSRMinTimeout"); + } + if (btc_config_exist(bdstr, "HidDescriptor")) { + ret &= btc_config_remove(bdstr, "HidDescriptor"); + } + btc_config_flush(); + btc_config_unlock(); + BTC_TRACE_DEBUG("%s ret:%d", __func__, ret); + return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL; +} +#endif //(defined BTC_HH_INCLUDED && BTC_HH_INCLUDED == TRUE) + +#if (defined BTC_HD_INCLUDED && BTC_HD_INCLUDED == TRUE) +#include "bta/bta_hd_api.h" +/******************************************************************************* + * Function btc_storage_load_hidd + * + * Description Loads hidd bonded device and "plugs" it into hidd + * + * Returns BT_STATUS_SUCCESS if successful, BT_STATUS_FAIL otherwise + * + ******************************************************************************/ +bt_status_t btc_storage_load_hidd(void) +{ + bt_bdaddr_t bd_addr; + int value; + btc_config_lock(); + for (const btc_config_section_iter_t *iter = btc_config_section_begin(); iter != btc_config_section_end(); + iter = btc_config_section_next(iter)) { + const char *name = btc_config_section_name(iter); + if (string_is_bdaddr(name) && btc_config_exist(name, BTC_STORAGE_LINK_KEY_TYPE_STR) && + btc_config_exist(name, BTC_STORAGE_PIN_LENGTH_STR) && btc_config_exist(name, BTC_STORAGE_SC_SUPPORT) && + btc_config_exist(name, BTC_STORAGE_LINK_KEY_STR)) { + BTC_TRACE_DEBUG("Remote device:%s", name); + if (btc_config_get_int(name, "HidDeviceCabled", &value)) { + string_to_bdaddr(name, &bd_addr); + BTA_HdAddDevice(bd_addr.address); + break; + } + } + } + btc_config_unlock(); + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* + * + * Function btc_storage_set_hidd + * + * Description Stores hidd bonded device info in nvram. + * + * Returns BT_STATUS_SUCCESS + * + ******************************************************************************/ +bt_status_t btc_storage_set_hidd(bt_bdaddr_t *remote_bd_addr) +{ + bdstr_t bdstr = {0}; + bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr)); + btc_config_lock(); + int ret = btc_config_set_int(bdstr, "HidDeviceCabled", 1); + btc_config_flush(); + btc_config_unlock(); + BTC_TRACE_DEBUG("%s ret:%d", __func__, ret); + return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL; +} + +/******************************************************************************* + * + * Function btc_storage_remove_hidd + * + * Description Removes hidd bonded device info from nvram + * + * Returns BT_STATUS_SUCCESS + * + ******************************************************************************/ +bt_status_t btc_storage_remove_hidd(bt_bdaddr_t *remote_bd_addr) +{ + bdstr_t bdstr; + int ret = 0; + bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr)); + btc_config_lock(); + if (btc_config_exist(bdstr, "HidVersion")) { + ret = btc_config_remove(bdstr, "HidDeviceCabled"); + } + btc_config_flush(); + btc_config_unlock(); + + BTC_TRACE_DEBUG("%s ret:%d", __func__, ret); + return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL; +} +#endif //(defined BTC_HD_INCLUDED && BTC_HD_INCLUDED == TRUE) diff --git a/components/bt/host/bluedroid/btc/core/btc_util.c b/components/bt/host/bluedroid/btc/core/btc_util.c index 09f178565c..0417198a57 100644 --- a/components/bt/host/bluedroid/btc/core/btc_util.c +++ b/components/bt/host/bluedroid/btc/core/btc_util.c @@ -35,6 +35,10 @@ #include "bta/bta_ag_api.h" #endif ///BTA_AG_INCLUDED == TRUE +#if (BTA_HH_INCLUDED == TRUE) +#include "bta/bta_hh_api.h" +#endif ///BTA_HH_INCLUDED == TRUE +#include "bta/bta_hd_api.h" #include "common/bt_defs.h" #include "stack/btm_api.h" #include "bta/bta_api.h" @@ -209,6 +213,56 @@ const char* dump_hf_call_setup_state(esp_hf_call_setup_status_t call_setup_state #endif // #if (BTA_AG_INCLUDED == TRUE) +#if (BTA_HH_INCLUDED == TRUE) +const char *dump_hh_event(uint16_t event) +{ + switch (event) { + CASE_RETURN_STR(BTA_HH_ENABLE_EVT) + CASE_RETURN_STR(BTA_HH_DISABLE_EVT) + CASE_RETURN_STR(BTA_HH_OPEN_EVT) + CASE_RETURN_STR(BTA_HH_CLOSE_EVT) + CASE_RETURN_STR(BTA_HH_GET_RPT_EVT) + CASE_RETURN_STR(BTA_HH_SET_RPT_EVT) + CASE_RETURN_STR(BTA_HH_GET_PROTO_EVT) + CASE_RETURN_STR(BTA_HH_SET_PROTO_EVT) + CASE_RETURN_STR(BTA_HH_GET_IDLE_EVT) + CASE_RETURN_STR(BTA_HH_SET_IDLE_EVT) + CASE_RETURN_STR(BTA_HH_GET_DSCP_EVT) + CASE_RETURN_STR(BTA_HH_ADD_DEV_EVT) + CASE_RETURN_STR(BTA_HH_RMV_DEV_EVT) + CASE_RETURN_STR(BTA_HH_VC_UNPLUG_EVT) + CASE_RETURN_STR(BTA_HH_DATA_EVT) + CASE_RETURN_STR(BTA_HH_API_ERR_EVT) + CASE_RETURN_STR(BTA_HH_UPDATE_SCPP_EVT) + CASE_RETURN_STR(BTA_HH_DATA_IND_EVT) + default: + return "UNKNOWN MSG ID"; + } +} +#endif ///BTA_HH_INCLUDED + +#if BTA_HD_INCLUDED == TRUE +const char* dump_hd_event(uint16_t event) { + switch (event) { + CASE_RETURN_STR(BTA_HD_ENABLE_EVT) + CASE_RETURN_STR(BTA_HD_DISABLE_EVT) + CASE_RETURN_STR(BTA_HD_REGISTER_APP_EVT) + CASE_RETURN_STR(BTA_HD_UNREGISTER_APP_EVT) + CASE_RETURN_STR(BTA_HD_OPEN_EVT) + CASE_RETURN_STR(BTA_HD_CLOSE_EVT) + CASE_RETURN_STR(BTA_HD_GET_REPORT_EVT) + CASE_RETURN_STR(BTA_HD_SET_REPORT_EVT) + CASE_RETURN_STR(BTA_HD_SET_PROTOCOL_EVT) + CASE_RETURN_STR(BTA_HD_INTR_DATA_EVT) + CASE_RETURN_STR(BTA_HD_VC_UNPLUG_EVT) + //CASE_RETURN_STR(BTA_HD_CONN_STATE_EVT) + CASE_RETURN_STR(BTA_HD_API_ERR_EVT) + default: + return "UNKNOWN MSG ID"; + } +} +#endif ///BTA_HD_INCLUDED + UINT32 devclass2uint(DEV_CLASS dev_class) { UINT32 cod = 0; diff --git a/components/bt/host/bluedroid/btc/include/btc/btc_storage.h b/components/bt/host/bluedroid/btc/include/btc/btc_storage.h index f74c3eeb36..57916e522a 100644 --- a/components/bt/host/bluedroid/btc/include/btc/btc_storage.h +++ b/components/bt/host/bluedroid/btc/include/btc/btc_storage.h @@ -27,6 +27,10 @@ #define BTC_STORAGE_PIN_LENGTH_STR "PinLength" #define BTC_STORAGE_SC_SUPPORT "SCSupport" +#ifdef __cplusplus +extern "C" { +#endif + /******************************************************************************* ** ** Function btc_storage_add_bonded_device @@ -91,4 +95,85 @@ int btc_storage_get_num_bt_bond_devices(void); *******************************************************************************/ bt_status_t btc_storage_get_bonded_bt_devices_list(bt_bdaddr_t *bond_dev, int *dev_num); +#if (defined BTC_HH_INCLUDED && BTC_HH_INCLUDED == TRUE) +/******************************************************************************* + * + * Function btc_storage_add_hid_device_info + * + * Description BTC storage API - Adds the hid information of bonded hid + * devices-to NVRAM + * + * Returns BT_STATUS_SUCCESS if the store was successful, + * BT_STATUS_FAIL otherwise + * + ******************************************************************************/ + +bt_status_t btc_storage_add_hid_device_info(bt_bdaddr_t *remote_bd_addr, uint16_t attr_mask, uint8_t sub_class, + uint8_t app_id, uint16_t vendor_id, uint16_t product_id, uint16_t version, + uint8_t ctry_code, uint16_t ssr_max_latency, uint16_t ssr_min_tout, + uint16_t dl_len, uint8_t *dsc_list); + +/******************************************************************************* + * + * Function btc_storage_load_bonded_hid_info + * + * Description BTIF storage API - Loads hid info for all the bonded devices + * from NVRAM and adds those devices to the BTA_HH. + * + * Returns BT_STATUS_SUCCESS if successful, BT_STATUS_FAIL otherwise + * + ******************************************************************************/ +bt_status_t btc_storage_load_bonded_hid_info(void); + +/******************************************************************************* + * + * Function btc_storage_remove_hid_info + * + * Description BTC storage API - Deletes the bonded hid device info from + * NVRAM + * + * Returns BT_STATUS_SUCCESS if the deletion was successful, + * BT_STATUS_FAIL otherwise + * + ******************************************************************************/ +bt_status_t btc_storage_remove_hid_info(bt_bdaddr_t *remote_bd_addr); +#endif // (defined BTC_HH_INCLUDED && BTC_HH_INCLUDED == TRUE) + +#if (defined BTC_HD_INCLUDED && BTC_HD_INCLUDED == TRUE) +/******************************************************************************* + * Function btc_storage_load_hidd + * + * Description Loads hidd bonded device and "plugs" it into hidd + * + * Returns BT_STATUS_SUCCESS if successful, BT_STATUS_FAIL otherwise + * + ******************************************************************************/ +bt_status_t btc_storage_load_hidd(void); + +/******************************************************************************* + * + * Function btc_storage_set_hidd + * + * Description Stores hidd bonded device info in nvram. + * + * Returns BT_STATUS_SUCCESS + * + ******************************************************************************/ +bt_status_t btc_storage_set_hidd(bt_bdaddr_t *remote_bd_addr); + +/******************************************************************************* + * + * Function btc_storage_remove_hidd + * + * Description Removes hidd bonded device info from nvram + * + * Returns BT_STATUS_SUCCESS + * + ******************************************************************************/ +bt_status_t btc_storage_remove_hidd(bt_bdaddr_t *remote_bd_addr); +#endif //(defined BTC_HD_INCLUDED && BTC_HD_INCLUDED == TRUE) +#ifdef __cplusplus +} +#endif + #endif /* BTC_STORAGE_H */ diff --git a/components/bt/host/bluedroid/btc/include/btc/btc_util.h b/components/bt/host/bluedroid/btc/include/btc/btc_util.h index aa96e46016..1cc3c9bd06 100644 --- a/components/bt/host/bluedroid/btc/include/btc/btc_util.h +++ b/components/bt/host/bluedroid/btc/include/btc/btc_util.h @@ -31,7 +31,9 @@ ********************************************************************************/ typedef char bdstr_t[18]; - +#ifdef __cplusplus +extern "C" { +#endif /******************************************************************************* ** Functions ********************************************************************************/ @@ -48,6 +50,14 @@ const char *dump_hf_call_state(esp_hf_call_status_t call_state); const char* dump_hf_call_setup_state(esp_hf_call_setup_status_t call_setup_state); #endif +#if(BTA_HD_INCLUDED == TRUE) +const char* dump_hd_event(uint16_t event); +#endif + +#if(BTA_HH_INCLUDED == TRUE) +const char* dump_hh_event(uint16_t event); +#endif + UINT32 devclass2uint(DEV_CLASS dev_class); void uint2devclass(UINT32 dev, DEV_CLASS dev_class); void uuid128_be_to_esp_uuid(esp_bt_uuid_t *u, uint8_t* uuid128); @@ -58,4 +68,8 @@ esp_bt_status_t btc_hci_to_esp_status(uint8_t hci_status); esp_bt_status_t btc_btm_status_to_esp_status (uint8_t btm_status); esp_bt_status_t btc_bta_status_to_esp_status (uint8_t bta_status); +#ifdef __cplusplus +} +#endif + #endif /* __BTC_UTIL_H__ */ diff --git a/components/bt/host/bluedroid/btc/profile/std/hid/bta_hh_co.c b/components/bt/host/bluedroid/btc/profile/std/hid/bta_hh_co.c new file mode 100644 index 0000000000..5743f89042 --- /dev/null +++ b/components/bt/host/bluedroid/btc/profile/std/hid/bta_hh_co.c @@ -0,0 +1,152 @@ +#include "btc_hh.h" +#include "osi/allocator.h" +#include "string.h" +#if HID_HOST_INCLUDED == TRUE + +/******************************************************************************* + * + * Function bta_hh_co_open + * + * Description When connection is opened, this call-out function is executed + * by HH to do platform specific initialization. + * + * Returns void. + ******************************************************************************/ +void bta_hh_co_open(uint8_t dev_handle, uint8_t sub_class, tBTA_HH_ATTR_MASK attr_mask, uint8_t app_id) +{ + uint32_t i; + btc_hh_device_t *p_dev = NULL; + + if (dev_handle == BTA_HH_INVALID_HANDLE) { + APPL_TRACE_WARNING("%s: Oops, dev_handle (%d) is invalid...", __func__, dev_handle); + return; + } + + for (i = 0; i < BTC_HH_MAX_HID; i++) { + p_dev = &btc_hh_cb.devices[i]; + if (p_dev->dev_status != ESP_HIDH_CONN_STATE_UNKNOWN && p_dev->dev_handle == dev_handle) { + // We found a device with the same handle. Must be a device reconnected. + APPL_TRACE_WARNING("%s: Found an existing device with the same handle dev_status=%d, " + "dev_handle=0x%2x, attr_mask=0x%04x, sub_class=0x%02x, app_id=%d", + __func__, p_dev->dev_status, dev_handle, p_dev->attr_mask, p_dev->sub_class, + p_dev->app_id); + break; + } + p_dev = NULL; + } + + if (p_dev == NULL) { + // Did not find a device reconnection case. Find an empty slot now. + for (i = 0; i < BTC_HH_MAX_HID; i++) { + if (btc_hh_cb.devices[i].dev_status == ESP_HIDH_CONN_STATE_UNKNOWN) { + p_dev = &btc_hh_cb.devices[i]; + p_dev->dev_handle = dev_handle; + p_dev->attr_mask = attr_mask; + p_dev->sub_class = sub_class; + p_dev->app_id = app_id; + p_dev->local_vup = false; + + btc_hh_cb.device_num++; + break; + } + } + } + + if (p_dev == NULL) { + APPL_TRACE_ERROR("%s: Error: too many HID devices are connected", __func__); + return; + } + + p_dev->dev_status = ESP_HIDH_CONN_STATE_CONNECTED; + APPL_TRACE_DEBUG("%s: Return device status %d", __func__, p_dev->dev_status); +} + +/******************************************************************************* + * + * Function bta_hh_co_close + * + * Description When connection is closed, this call-out function is executed + * by HH to do platform specific finalization. + * + * Parameters dev_handle - device handle + * app_id - application id + * + * Returns void. + ******************************************************************************/ +void bta_hh_co_close(uint8_t dev_handle, uint8_t app_id) +{ + uint32_t i; + btc_hh_device_t *p_dev = NULL; + + APPL_TRACE_WARNING("%s: dev_handle = %d, app_id = %d", __func__, dev_handle, app_id); + if (dev_handle == BTA_HH_INVALID_HANDLE) { + APPL_TRACE_WARNING("%s: Oops, dev_handle (%d) is invalid...", __func__, dev_handle); + return; + } + + for (i = 0; i < BTC_HH_MAX_HID; i++) { + p_dev = &btc_hh_cb.devices[i]; + if (p_dev->dev_status != ESP_HIDH_CONN_STATE_UNKNOWN && p_dev->dev_handle == dev_handle) { + APPL_TRACE_WARNING("%s: Found an existing device with the same handle " + "dev_status = %d, dev_handle =%d", + __func__, p_dev->dev_status, p_dev->dev_handle); + break; + } + } +} + +/******************************************************************************* + * + * Function bta_hh_co_data + * + * Description This function is executed by BTA when HID host receive a + * data report on interrupt channel. + * + * Parameters dev_handle - device handle + * *p_rpt - pointer to the report data + * len - length of report data + * mode - Hid host Protocol Mode + * sub_clas - Device Subclass + * app_id - application id + * + * Returns void + ******************************************************************************/ +void bta_hh_co_data(UINT8 dev_handle, UINT8 *p_rpt, UINT16 len, tBTA_HH_PROTO_MODE mode, UINT8 sub_class, UINT8 ctry_code, + BD_ADDR peer_addr, UINT8 app_id) +{ + btc_msg_t msg; + tBTA_HH p_data; + BT_HDR *p_buf = NULL; + bt_status_t status; + tBTA_HH_STATUS ret = BTA_HH_OK; + + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_HH; + msg.act = BTA_HH_DATA_IND_EVT; + + APPL_TRACE_DEBUG("%s: dev_handle = %d, subclass = 0x%02X, mode = %d, " + "ctry_code = %d, app_id = %d", + __func__, dev_handle, sub_class, mode, ctry_code, app_id); + + do { + if ((p_buf = osi_malloc(sizeof(BT_HDR) + len)) == NULL) { + APPL_TRACE_ERROR("%s malloc failed!", __func__); + ret = BTA_HH_ERR_NO_RES; + break; + } + p_buf->offset = 0; + p_buf->len = len; + p_buf->event = 0; + p_buf->layer_specific = dev_handle; + memcpy(p_buf->data, p_rpt, len); + } while (0); + + p_data.int_data.status = ret; + p_data.int_data.handle = dev_handle; + p_data.int_data.p_data = p_buf; + p_data.int_data.proto_mode = mode; + status = btc_transfer_context(&msg, &p_data, sizeof(tBTA_HH), NULL); + assert(status == BT_STATUS_SUCCESS); +} + +#endif /* HID_HOST_INCLUDED == TRUE */ diff --git a/components/bt/host/bluedroid/btc/profile/std/hid/btc_hd.c b/components/bt/host/bluedroid/btc/profile/std/hid/btc_hd.c new file mode 100644 index 0000000000..0deccf1251 --- /dev/null +++ b/components/bt/host/bluedroid/btc/profile/std/hid/btc_hd.c @@ -0,0 +1,831 @@ +/****************************************************************************** + * + * Copyright (C) 2016 The Android Open Source Project + * Copyright (C) 2009-2012 Broadcom Corporation + * Copyright (C) 2019 Blake Felt + * + * 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. + * + ******************************************************************************/ +/************************************************************************************ + * + * Filename: btc_hd.c + * + * Description: HID Device Profile Bluetooth Interface + * + * + ***********************************************************************************/ + +#include +#include +#include + +#include "bta/bta_api.h" +#include "bta/bta_hd_api.h" +#include "bta/bta_hh_api.h" +#include "bta/utl.h" +#include "btc/btc_storage.h" +#include "btc/btc_util.h" +#include "btc/btc_manage.h" +#include "btc_hd.h" + +#include "osi/allocator.h" + +#include "esp_hidd_api.h" + +#if HID_DEV_INCLUDED == TRUE +#include "bta_dm_int.h" + +/* HD request events */ +typedef enum { BTC_HD_DUMMY_REQ_EVT = 0 } btc_hd_req_evt_t; + +/******************************************************************************* + * Static variables + ******************************************************************************/ +btc_hd_cb_t btc_hd_cb; + +// static tBTA_HD_APP_INFO app_info; +// static tBTA_HD_QOS_INFO in_qos; +// static tBTA_HD_QOS_INFO out_qos; + +/****************************************************************************** + * Constants & Macros + *****************************************************************************/ +#define BTC_HD_APP_NAME_LEN 50 +#define BTC_HD_APP_DESCRIPTION_LEN 50 +#define BTC_HD_APP_PROVIDER_LEN 50 +#define BTC_HD_APP_DESCRIPTOR_LEN 2048 +#define COD_HID_KEYBOARD 0x0540 +#define COD_HID_POINTING 0x0580 +#define COD_HID_COMBO 0x05C0 +#define COD_HID_MAJOR 0x0500 + +#define is_hidd_init() (btc_hd_cb.status > BTC_HD_DISABLED) +#define is_hidd_app_register() (btc_hd_cb.app_registered) + +typedef void (bt_hid_copy_cb_t)(btc_msg_t *msg, void *p_dest, void *p_src); + +static inline void btc_hd_cb_to_app(esp_hidd_cb_event_t event, esp_hidd_cb_param_t *param) +{ + esp_hd_cb_t *btc_hd_cb = (esp_hd_cb_t *)btc_profile_cb_get(BTC_PID_HD); + if (btc_hd_cb) { + btc_hd_cb(event, param); + } +} + +static void free_app_info_param(void) +{ + utl_freebuf((void **)&btc_hd_cb.app_info.descriptor.dsc_list); + utl_freebuf((void **)&btc_hd_cb.app_info.p_provider); + utl_freebuf((void **)&btc_hd_cb.app_info.p_description); + utl_freebuf((void **)&btc_hd_cb.app_info.p_name); +} + +static void bte_hd_arg_deep_copy(btc_msg_t *msg, void *p_dst, void *p_src) +{ + tBTA_HD *p_dst_data = (tBTA_HD *)p_dst; + tBTA_HD *p_src_data = (tBTA_HD *)p_src; + switch (msg->act) + { + case BTA_HD_SET_REPORT_EVT: { + uint8_t *src_data = p_src_data->set_report.p_data; + if (src_data) { + p_dst_data->set_report.p_data = osi_malloc(p_src_data->set_report.len); + if (p_dst_data->set_report.p_data == NULL) { + BTC_TRACE_ERROR("%s malloc set_report data failed!", __func__); + break; + } + memcpy(p_dst_data->set_report.p_data, src_data, p_src_data->set_report.len); + } + break; + } + case BTA_HD_INTR_DATA_EVT: { + uint8_t *src_data = p_src_data->intr_data.p_data; + if (src_data) { + p_dst_data->intr_data.p_data = osi_malloc(p_src_data->intr_data.len); + if (p_dst_data->intr_data.p_data == NULL) { + BTC_TRACE_ERROR("%s malloc intr_data data failed!", __func__); + break; + } + memcpy(p_dst_data->intr_data.p_data, src_data, p_src_data->intr_data.len); + } + break; + } + default: + break; + } +} + +/******************************************************************************* + * + * Function btc_hd_remove_device + * + * Description Removes plugged device + * + * Returns void + * + ******************************************************************************/ +void btc_hd_remove_device(bt_bdaddr_t bd_addr) +{ + BTA_HdRemoveDevice((uint8_t *)&bd_addr); + // btc_storage_remove_hidd(&bd_addr); +} + +/******************************************************************************* + * + * Function bte_hd_evt + * + * Description Switches context from BTE to BTC for all BT-HD events + * + * Returns void + * + ******************************************************************************/ +static void bte_hd_evt(tBTA_HD_EVT event, tBTA_HD *p_data) +{ + bt_status_t status; + int param_len = 0; + + BTC_TRACE_API("%s event=%d", __func__, event); + + switch (event) { + case BTA_HD_ENABLE_EVT: + case BTA_HD_DISABLE_EVT: + case BTA_HD_UNREGISTER_APP_EVT: + param_len = sizeof(tBTA_HD_STATUS); + break; + case BTA_HD_REGISTER_APP_EVT: + param_len = sizeof(tBTA_HD_REG_STATUS); + break; + case BTA_HD_OPEN_EVT: + case BTA_HD_CLOSE_EVT: + case BTA_HD_VC_UNPLUG_EVT: + param_len = sizeof(tBTA_HD_CONN); + break; + case BTA_HD_GET_REPORT_EVT: + param_len += sizeof(tBTA_HD_GET_REPORT); + break; + case BTA_HD_SET_REPORT_EVT: + param_len = sizeof(tBTA_HD_SET_REPORT); + break; + case BTA_HD_SET_PROTOCOL_EVT: + param_len += sizeof(p_data->set_protocol); + break; + case BTA_HD_INTR_DATA_EVT: + param_len = sizeof(tBTA_HD_INTR_DATA); + break; + case BTA_HD_SEND_REPORT_EVT: + param_len = sizeof(tBTA_HD_API_SEND_REPORT); + break; + case BTA_HD_REPORT_ERR_EVT: + param_len = sizeof(tBTA_HD_API_REPORT_ERR); + break; + } + + btc_msg_t msg; + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_HD; + msg.act = event; + + status = btc_transfer_context(&msg, p_data, param_len, bte_hd_arg_deep_copy); + if (status != BT_STATUS_SUCCESS) { + BTC_TRACE_ERROR("context transfer failed"); + } +} + +/******************************************************************************* + * + * Function btc_hd_init + * + * Description Initializes BT-HD interface + * + * Returns void + * + ******************************************************************************/ +static void btc_hd_init(void) +{ + BTC_TRACE_API("%s", __func__); + esp_hidd_status_t ret = ESP_HIDD_SUCCESS; + do { + if (is_hidd_init()) { + BTC_TRACE_ERROR("%s HD has been initiated, shall uninit first!", __func__); + ret = ESP_HIDD_NEED_DEINIT; + break; + } + memset(&btc_hd_cb, 0, sizeof(btc_hd_cb)); + /* enable HD */ + BTA_HdEnable(bte_hd_evt); + } while (0); + + if (ret != ESP_HIDD_SUCCESS) { + esp_hidd_cb_param_t param; + param.init.status = ret; + btc_hd_cb_to_app(ESP_HIDD_INIT_EVT, ¶m); + } +} + +/******************************************************************************* + * + * Function btc_hd_deinit + * + * Description de-initializes the hd interface + * + * Returns void + * + ******************************************************************************/ +static void btc_hd_unregister_app(void); +static void btc_hd_deinit(void) +{ + BTC_TRACE_API("%s", __func__); + esp_hidd_status_t ret = ESP_HIDD_SUCCESS; + do { + if (!is_hidd_init()) { + BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__); + ret = ESP_HIDD_NEED_INIT; + break; + } + + btc_hd_cb.service_dereg_active = FALSE; + btc_hd_cb.status = BTC_HD_DISABLING; + // unresgister app will also relase the connection + // and disable after receiving unregister event from lower layer + if (is_hidd_app_register()) { + btc_hd_unregister_app(); + } else { + BTC_TRACE_WARNING("%s disabling hid device service now", __func__); + BTA_HdDisable(); + } + } while (0); + + if (ret != ESP_HIDD_SUCCESS) { + esp_hidd_cb_param_t param; + param.deinit.status = ret; + btc_hd_cb_to_app(ESP_HIDD_DEINIT_EVT, ¶m); + } +} + +/******************************************************************************* + * + * Function btc_hd_register_app + * + * Description Registers HID Device application + * + * Returns void + * + ******************************************************************************/ +static void btc_hd_register_app(esp_hidd_app_param_t *p_app_param, esp_hidd_qos_param_t *p_in_qos, + esp_hidd_qos_param_t *p_out_qos) +{ + BTC_TRACE_API("%s", __func__); + esp_hidd_status_t ret = ESP_HIDD_SUCCESS; + do { + if (!is_hidd_init()) { + BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__); + ret = ESP_HIDD_NEED_INIT; + break; + } + + if (is_hidd_app_register()) { + BTC_TRACE_ERROR("%s: application already registered, shall deregister first!", __func__); + ret = ESP_HIDD_NEED_DEREG; + break; + } + + if ((btc_hd_cb.app_info.p_name = (char *)osi_malloc(BTC_HD_APP_NAME_LEN)) == NULL || + (btc_hd_cb.app_info.p_description = (char *)osi_malloc(BTC_HD_APP_DESCRIPTION_LEN)) == NULL || + (btc_hd_cb.app_info.p_provider = (char *)osi_malloc(BTC_HD_APP_PROVIDER_LEN)) == NULL || + (btc_hd_cb.app_info.descriptor.dsc_list = (uint8_t *)osi_malloc(p_app_param->desc_list_len)) == NULL) { + BTC_TRACE_ERROR( + "%s malloc app_info failed! p_name:%p, p_description:%p, p_provider:%p, descriptor.dsc_list:%p", + __func__, btc_hd_cb.app_info.p_name, btc_hd_cb.app_info.p_description, btc_hd_cb.app_info.p_provider, + btc_hd_cb.app_info.descriptor.dsc_list); + ret = ESP_HIDD_NO_RES; + break; + } + memcpy(btc_hd_cb.app_info.p_name, p_app_param->name, BTC_HD_APP_NAME_LEN); + memcpy(btc_hd_cb.app_info.p_description, p_app_param->description, BTC_HD_APP_DESCRIPTION_LEN); + memcpy(btc_hd_cb.app_info.p_provider, p_app_param->provider, BTC_HD_APP_PROVIDER_LEN); + memcpy(btc_hd_cb.app_info.descriptor.dsc_list, p_app_param->desc_list, p_app_param->desc_list_len); + btc_hd_cb.app_info.subclass = p_app_param->subclass; + btc_hd_cb.app_info.descriptor.dl_len = p_app_param->desc_list_len; + + btc_hd_cb.in_qos.service_type = p_in_qos->service_type; + btc_hd_cb.in_qos.token_rate = p_in_qos->token_rate; + btc_hd_cb.in_qos.token_bucket_size = p_in_qos->token_bucket_size; + btc_hd_cb.in_qos.peak_bandwidth = p_in_qos->peak_bandwidth; + btc_hd_cb.in_qos.access_latency = p_in_qos->access_latency; + btc_hd_cb.in_qos.delay_variation = p_in_qos->delay_variation; + btc_hd_cb.out_qos.service_type = p_out_qos->service_type; + btc_hd_cb.out_qos.token_rate = p_out_qos->token_rate; + btc_hd_cb.out_qos.token_bucket_size = p_out_qos->token_bucket_size; + btc_hd_cb.out_qos.peak_bandwidth = p_out_qos->peak_bandwidth; + btc_hd_cb.out_qos.access_latency = p_out_qos->access_latency; + btc_hd_cb.out_qos.delay_variation = p_out_qos->delay_variation; + + BTA_HdRegisterApp(&btc_hd_cb.app_info, &btc_hd_cb.in_qos, &btc_hd_cb.out_qos); + } while(0); + + if (ret != ESP_HIDD_SUCCESS) { + esp_hidd_cb_param_t param; + param.register_app.status = ret; + param.register_app.in_use = false; + memset(param.register_app.bd_addr, 0, BD_ADDR_LEN); + btc_hd_cb_to_app(ESP_HIDD_REGISTER_APP_EVT, ¶m); + } + free_app_info_param(); +} + +/******************************************************************************* + * + * Function btc_hd_unregister_app + * + * Description Unregisters HID Device application + * + * Returns void + * + ******************************************************************************/ +static void btc_hd_unregister_app(void) +{ + BTC_TRACE_API("%s", __func__); + esp_hidd_status_t ret = ESP_HIDD_SUCCESS; + do { + if (!is_hidd_init()) { + BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__); + ret = ESP_HIDD_NEED_INIT; + break; + } + + if (!is_hidd_app_register()) { + BTC_TRACE_ERROR("%s: application has not been registered, shall register first!", __func__); + ret = ESP_HIDD_NEED_REG; + break; + } + + if (btc_hd_cb.service_dereg_active) { + BTC_TRACE_ERROR("%s: BT-HD deregistering in progress", __func__); + ret = ESP_HIDD_BUSY; + break; + } + btc_hd_cb.service_dereg_active = TRUE; + BTA_HdUnregisterApp(); + } while(0); + + if (ret != ESP_HIDD_SUCCESS) { + esp_hidd_cb_param_t param; + param.unregister_app.status = ret; + btc_hd_cb_to_app(ESP_HIDD_UNREGISTER_APP_EVT, ¶m); + } +} + +/******************************************************************************* + * + * Function btc_hd_connect + * + * Description Connects to host + * + * Returns void + * + ******************************************************************************/ +static void btc_hd_connect(BD_ADDR bd_addr) +{ + BTC_TRACE_API("%s", __func__); + esp_hidd_status_t ret = ESP_HIDD_SUCCESS; + do { + if (!is_hidd_init()) { + BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__); + ret = ESP_HIDD_NEED_INIT; + break; + } + + if (!is_hidd_app_register()) { + BTC_TRACE_ERROR("%s: application has not been registered, shall register first!", __func__); + ret = ESP_HIDD_NEED_REG; + break; + } + BTA_HdConnect(bd_addr); + } while (0); + + if (ret != ESP_HIDD_SUCCESS) { + esp_hidd_cb_param_t param; + param.open.status = ret; + param.open.conn_status = ESP_HIDD_CONN_STATE_DISCONNECTED; + memcpy(param.open.bd_addr, bd_addr, BD_ADDR_LEN); + btc_hd_cb_to_app(ESP_HIDD_OPEN_EVT, ¶m); + } +} + +/******************************************************************************* + * + * Function btc_hd_disconnect + * + * Description Disconnects from host + * + * Returns void + * + ******************************************************************************/ +static void btc_hd_disconnect(void) +{ + BTC_TRACE_API("%s", __func__); + esp_hidd_status_t ret = ESP_HIDD_SUCCESS; + do { + if (!is_hidd_init()) { + BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__); + ret = ESP_HIDD_NEED_INIT; + break; + } + + if (!is_hidd_app_register()) { + BTC_TRACE_ERROR("%s: application has not been registered, shall register first!", __func__); + ret = ESP_HIDD_NEED_REG; + break; + } + BTA_HdDisconnect(); + } while (0); + + if (ret != ESP_HIDD_SUCCESS) { + esp_hidd_cb_param_t param; + param.close.status = ret; + param.close.conn_status = ESP_HIDD_CONN_STATE_DISCONNECTED; + btc_hd_cb_to_app(ESP_HIDD_CLOSE_EVT, ¶m); + } +} + +/******************************************************************************* + * + * Function btc_hd_send_report + * + * Description Sends Reports to hid host + * + * Returns void + * + ******************************************************************************/ +static void btc_hd_send_report(esp_hidd_report_type_t type, uint8_t id, uint16_t len, uint8_t *p_data) +{ + tBTA_HD_REPORT report; + + BTC_TRACE_API("%s: type=%d id=%d len=%d", __func__, type, id, len); + esp_hidd_status_t ret = ESP_HIDD_SUCCESS; + do { + if (!is_hidd_init()) { + BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__); + ret = ESP_HIDD_NEED_INIT; + break; + } + + if (!is_hidd_app_register()) { + BTC_TRACE_ERROR("%s: application has not been registered, shall register first!", __func__); + ret = ESP_HIDD_NEED_REG; + break; + } + if (type == ESP_HIDD_REPORT_TYPE_INTRDATA) { + report.type = ESP_HIDD_REPORT_TYPE_INPUT; + report.use_intr = TRUE; + } else { + report.type = (type & 0x03); + report.use_intr = FALSE; + } + + report.id = id; + report.len = len; + report.p_data = p_data; + + BTA_HdSendReport(&report); + } while (0); + + if (ret != ESP_HIDD_SUCCESS) { + esp_hidd_cb_param_t param; + param.send_report.status = ret; + param.send_report.reason = 0; + param.send_report.report_type = report.type; + param.send_report.report_id = report.id; + btc_hd_cb_to_app(ESP_HIDD_SEND_REPORT_EVT, ¶m); + } +} + +/******************************************************************************* + * + * Function btc_hd_report_error + * + * Description Sends HANDSHAKE with error info for invalid SET_REPORT + * + * Returns void + * + ******************************************************************************/ +static void btc_hd_report_error(uint8_t error) +{ + BTC_TRACE_API("%s", __func__); + esp_hidd_status_t ret = ESP_HIDD_SUCCESS; + do { + if (!is_hidd_init()) { + BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__); + ret = ESP_HIDD_NEED_INIT; + break; + } + + if (!is_hidd_app_register()) { + BTC_TRACE_ERROR("%s: application has not been registered, shall register first!", __func__); + ret = ESP_HIDD_NEED_REG; + break; + } + BTA_HdReportError(error); + } while (0); + + if (ret != ESP_HIDD_SUCCESS) { + esp_hidd_cb_param_t param; + param.report_err.status = ret; + param.report_err.reason = 0; + btc_hd_cb_to_app(ESP_HIDD_REPORT_ERR_EVT, ¶m); + } +} + +/******************************************************************************* + * + * Function btc_hd_virtual_cable_unplug + * + * Description Sends Virtual Cable Unplug to host + * + * Returns void + * + ******************************************************************************/ +static void btc_hd_virtual_cable_unplug(void) +{ + BTC_TRACE_API("%s", __func__); + esp_hidd_status_t ret = ESP_HIDD_SUCCESS; + do { + if (!is_hidd_init()) { + BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__); + ret = ESP_HIDD_NEED_INIT; + break; + } + + if (!is_hidd_app_register()) { + BTC_TRACE_ERROR("%s: application has not been registered, shall register first!", __func__); + ret = ESP_HIDD_NEED_REG; + break; + } + BTA_HdVirtualCableUnplug(); + } while (0); + + if (ret != ESP_HIDD_SUCCESS) { + esp_hidd_cb_param_t param; + param.report_err.status = ret; + param.report_err.reason = 0; + btc_hd_cb_to_app(ESP_HIDD_VC_UNPLUG_EVT, ¶m); + } +} + +static void btc_hd_call_arg_deep_free(btc_msg_t *msg) +{ + btc_hidd_args_t *arg = (btc_hidd_args_t *)msg->arg; + + switch (msg->act) { + case BTC_HD_SEND_REPORT_EVT: + utl_freebuf((void **)&arg->send_report.data); + break; + default: + break; + } +} + +void btc_hd_call_handler(btc_msg_t *msg) +{ + btc_hidd_args_t *arg = (btc_hidd_args_t *)(msg->arg); + switch (msg->act) { + case BTC_HD_INIT_EVT: + btc_hd_init(); + break; + case BTC_HD_DEINIT_EVT: + btc_hd_deinit(); + break; + case BTC_HD_REGISTER_APP_EVT: + btc_hd_register_app(arg->register_app.app_param, arg->register_app.in_qos, arg->register_app.out_qos); + break; + case BTC_HD_UNREGISTER_APP_EVT: + btc_hd_unregister_app(); + break; + case BTC_HD_CONNECT_EVT: + btc_hd_connect(arg->connect.bd_addr); + break; + case BTC_HD_DISCONNECT_EVT: + btc_hd_disconnect(); + break; + case BTC_HD_SEND_REPORT_EVT: + btc_hd_send_report(arg->send_report.type, arg->send_report.id, arg->send_report.len, arg->send_report.data); + break; + case BTC_HD_REPORT_ERROR_EVT: + btc_hd_report_error(arg->error); + break; + case BTC_HD_UNPLUG_EVT: + btc_hd_virtual_cable_unplug(); + break; + default: + BTC_TRACE_WARNING("unknown hidd action %i", msg->act); + break; + } + btc_hd_call_arg_deep_free(msg); +} + +static void btc_hd_cb_arg_deep_free(btc_msg_t *msg) +{ + tBTA_HD *arg = (tBTA_HD *)msg->arg; + + switch (msg->act) { + case BTA_HD_SET_REPORT_EVT: + utl_freebuf((void **)&arg->set_report.p_data); + break; + case BTA_HD_INTR_DATA_EVT: + utl_freebuf((void **)&arg->intr_data.p_data); + break; + default: + break; + } +} + +void btc_hd_cb_handler(btc_msg_t *msg) +{ + uint16_t event = msg->act; + tBTA_HD *p_data = (tBTA_HD *)msg->arg; + esp_hidd_cb_param_t param = {0}; + BTC_TRACE_API("%s: event=%s", __func__, dump_hd_event(event)); + + switch (event) { + case BTA_HD_ENABLE_EVT: + BTC_TRACE_DEBUG("%s: status=%d", __func__, p_data->status); + if (p_data->status == BTA_HD_OK) { + btc_storage_load_hidd(); + btc_hd_cb.status = BTC_HD_ENABLED; + } else { + btc_hd_cb.status = BTC_HD_DISABLED; + BTC_TRACE_WARNING("Failed to enable BT-HD, status=%d", p_data->status); + } + param.init.status = p_data->status; + btc_hd_cb_to_app(ESP_HIDD_INIT_EVT, ¶m); + break; + case BTA_HD_DISABLE_EVT: + BTC_TRACE_DEBUG("%s: status=%d", __func__, p_data->status); + if (p_data->status == BTA_HD_OK){ + btc_hd_cb.status = BTC_HD_DISABLED; + if (btc_hd_cb.service_dereg_active) { + btc_hd_cb.service_dereg_active = FALSE; + } + free_app_info_param(); + memset(&btc_hd_cb, 0, sizeof(btc_hd_cb)); + } else { + BTC_TRACE_WARNING("Failed to disable BT-HD, status=%d", p_data->status); + } + param.deinit.status = p_data->status; + btc_hd_cb_to_app(ESP_HIDD_DEINIT_EVT, ¶m); + break; + case BTA_HD_REGISTER_APP_EVT: + if (p_data->reg_status.status == BTA_HD_OK) { + btc_hd_cb.app_registered = TRUE; + } + param.register_app.status = p_data->reg_status.status; + param.register_app.in_use = p_data->reg_status.in_use; + if (!p_data->reg_status.in_use) { + memset(param.register_app.bd_addr, 0, BD_ADDR_LEN); + } else { + memcpy(param.register_app.bd_addr, p_data->reg_status.bda, BD_ADDR_LEN); + } + btc_hd_cb_to_app(ESP_HIDD_REGISTER_APP_EVT, ¶m); + break; + case BTA_HD_UNREGISTER_APP_EVT: + btc_hd_cb.app_registered = FALSE; + param.unregister_app.status = p_data->status; + btc_hd_cb_to_app(ESP_HIDD_UNREGISTER_APP_EVT, ¶m); + if (btc_hd_cb.status == BTC_HD_DISABLING) { + BTC_TRACE_WARNING("disabling hid device service now"); + BTA_HdDisable(); + } + break; + case BTA_HD_OPEN_EVT: { + bt_bdaddr_t *addr = (bt_bdaddr_t *)&p_data->conn.bda; + BTC_TRACE_EVENT("BTA_HD_OPEN_EVT, address (%02x:%02x:%02x:%02x:%02x:%02x)", addr->address[0], addr->address[1], + addr->address[2], addr->address[3], addr->address[4], addr->address[5]); + if (p_data->conn.status == BTA_HD_OK && p_data->conn.conn_status == BTA_HD_CONN_STATE_CONNECTED) { + // /* Check if the connection is from hid host and not hid device */ + // if (check_cod_hid(addr)) { + // /* Incoming connection from hid device, reject it */ + // BTC_TRACE_WARNING("remote device is not hid host, disconnecting"); + // btc_hd_cb.forced_disc = TRUE; + // BTA_HdDisconnect(); + // break; + // } + // btc_storage_set_hidd((bt_bdaddr_t *)&p_data->conn.bda); + } + param.open.status = p_data->conn.status; + param.open.conn_status = p_data->conn.conn_status; + memcpy(param.open.bd_addr, p_data->conn.bda, BD_ADDR_LEN); + btc_hd_cb_to_app(ESP_HIDD_OPEN_EVT, ¶m); + break; + } + case BTA_HD_CLOSE_EVT: + if (btc_hd_cb.forced_disc && p_data->conn.conn_status == BTA_HD_CONN_STATE_DISCONNECTED) { + bt_bdaddr_t *addr = (bt_bdaddr_t *)&p_data->conn.bda; + BTC_TRACE_WARNING("remote device was forcefully disconnected"); + btc_hd_remove_device(*addr); + btc_hd_cb.forced_disc = FALSE; + break; + } + param.close.status = p_data->conn.status; + param.close.conn_status = p_data->conn.conn_status; + btc_hd_cb_to_app(ESP_HIDD_CLOSE_EVT, ¶m); + break; + case BTA_HD_GET_REPORT_EVT: + param.get_report.report_type = p_data->get_report.report_type; + param.get_report.report_id = p_data->get_report.report_id; + param.get_report.buffer_size = p_data->get_report.buffer_size; + btc_hd_cb_to_app(ESP_HIDD_GET_REPORT_EVT, ¶m); + break; + case BTA_HD_SET_REPORT_EVT: + param.set_report.report_type = p_data->set_report.report_type; + param.set_report.report_id = p_data->set_report.report_id; + param.set_report.len = p_data->set_report.len; + param.set_report.data = p_data->set_report.p_data; + btc_hd_cb_to_app(ESP_HIDD_SET_REPORT_EVT, ¶m); + break; + case BTA_HD_SET_PROTOCOL_EVT: + switch (p_data->set_protocol) { + case HID_PAR_PROTOCOL_BOOT_MODE: + param.set_protocol.protocol_mode = ESP_HIDD_BOOT_MODE; + break; + case HID_PAR_PROTOCOL_REPORT: + param.set_protocol.protocol_mode = ESP_HIDD_REPORT_MODE; + break; + default: + param.set_protocol.protocol_mode = ESP_HIDD_UNSUPPORTED_MODE; + break; + } + btc_hd_cb_to_app(ESP_HIDD_SET_PROTOCOL_EVT, ¶m); + break; + case BTA_HD_INTR_DATA_EVT: + param.intr_data.report_id = p_data->intr_data.report_id; + param.intr_data.len = p_data->intr_data.len; + param.intr_data.data = p_data->intr_data.p_data; + btc_hd_cb_to_app(ESP_HIDD_INTR_DATA_EVT, ¶m); + break; + case BTA_HD_VC_UNPLUG_EVT: { + bt_bdaddr_t *bd_addr = (bt_bdaddr_t *)&p_data->conn.bda; + if (bta_dm_check_if_only_hd_connected(p_data->conn.bda)) { + BTC_TRACE_DEBUG("%s: Removing bonding as only HID profile connected", __func__); + BTA_DmRemoveDevice((uint8_t *)&p_data->conn.bda, BT_TRANSPORT_BR_EDR); + } else { + BTC_TRACE_DEBUG("%s: Only removing HID data as some other profiles connected", __func__); + btc_hd_remove_device(*bd_addr); + } + param.close.status = p_data->conn.status; + param.close.conn_status = p_data->conn.conn_status; + btc_hd_cb_to_app(ESP_HIDD_CLOSE_EVT, ¶m); + param.vc_unplug.status = p_data->conn.status; + param.vc_unplug.conn_status = p_data->conn.conn_status; + btc_hd_cb_to_app(ESP_HIDD_VC_UNPLUG_EVT, ¶m); + break; + } + case BTA_HD_SEND_REPORT_EVT: + param.send_report.status = p_data->send_report.status; + param.send_report.reason = p_data->send_report.reason; + param.send_report.report_type = p_data->send_report.report_type; + param.send_report.report_id = p_data->send_report.report_id; + btc_hd_cb_to_app(ESP_HIDD_SEND_REPORT_EVT, ¶m); + break; + case BTA_HD_REPORT_ERR_EVT: + param.report_err.status = p_data->report_err.status; + param.report_err.reason = p_data->report_err.reason; + btc_hd_cb_to_app(ESP_HIDD_REPORT_ERR_EVT, ¶m); + break; + default: + BTC_TRACE_WARNING("%s: unknown event (%d)", __func__, event); + break; + } + btc_hd_cb_arg_deep_free(msg); +} + +void btc_hd_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) +{ + btc_hidd_args_t *dst = (btc_hidd_args_t *)p_dest; + btc_hidd_args_t *src = (btc_hidd_args_t *)p_src; + + switch (msg->act) { + case BTC_HD_SEND_REPORT_EVT: + dst->send_report.data = (uint8_t *)osi_malloc(src->send_report.len); + if (dst->send_report.data) { + memcpy(dst->send_report.data, src->send_report.data, src->send_report.len); + } else { + BTC_TRACE_ERROR("%s %d osi_malloc failed\n", __func__, msg->act); + } + break; + default: + break; + } +} + +#endif // HID_DEV_INCLUDED==TRUE diff --git a/components/bt/host/bluedroid/btc/profile/std/hid/btc_hh.c b/components/bt/host/bluedroid/btc/profile/std/hid/btc_hh.c new file mode 100644 index 0000000000..d0744c3236 --- /dev/null +++ b/components/bt/host/bluedroid/btc/profile/std/hid/btc_hh.c @@ -0,0 +1,1569 @@ +/****************************************************************************** + * + * Copyright (C) 2016 The Android Open Source Project + * Copyright (C) 2009-2012 Broadcom Corporation + * Copyright (C) 2019 Blake Felt + * + * 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. + * + ******************************************************************************/ +/************************************************************************************ + * + * Filename: btc_hd.c + * + * Description: HID Device Profile Bluetooth Interface + * + * + ***********************************************************************************/ + +#include +#include +#include +#include "btc/btc_util.h" +#include "btc/btc_manage.h" +#include "device/bdaddr.h" +#include "btc/btc_storage.h" +#include "osi/allocator.h" +#include "bta/utl.h" +#include "bta/bta_hh_api.h" +#include "stack/l2c_api.h" +// #include "bta_dm_int.h" + +#if HID_HOST_INCLUDED == TRUE +#include "btc_hh.h" + + +/******************************************************************************* + * Static variables + ******************************************************************************/ +btc_hh_cb_t btc_hh_cb; +static bdstr_t bdstr; + +/****************************************************************************** + * Constants & Macros + *****************************************************************************/ +#define COD_MASK 0x07FF + +#define COD_UNCLASSIFIED ((0x1F) << 8) +#define COD_HID_KEYBOARD 0x0540 +#define COD_HID_POINTING 0x0580 +#define COD_HID_COMBO 0x05C0 +#define COD_HID_MAJOR 0x0500 +#define COD_HID_MASK 0x0700 + +#define is_hidh_init() (btc_hh_cb.status > BTC_HH_DISABLED) +#define BTC_TIMEOUT_VUP_MS (3 * 1000) + +static inline void btc_hh_cb_to_app(esp_hidh_cb_event_t event, esp_hidh_cb_param_t *param) +{ + esp_hh_cb_t *btc_hh_cb = (esp_hh_cb_t *)btc_profile_cb_get(BTC_PID_HH); + if (btc_hh_cb) { + btc_hh_cb(event, param); + } +} + +/******************************************************************************* + * + * Function proto_mode_change_to_lower_layer + * + * Description Change the upper layer protocol mode definition to the lower layer protocol mode definition + * + * Returns Lower layer protocol mode definition + ******************************************************************************/ +static inline tBTA_HH_PROTO_MODE proto_mode_change_to_lower_layer(esp_hidh_protocol_mode_t protocol_mode) +{ + tBTA_HH_PROTO_MODE proto_mode = BTA_HH_PROTO_UNKNOWN; + + switch (protocol_mode) { + case ESP_HIDH_REPORT_MODE: + proto_mode = BTA_HH_PROTO_RPT_MODE; + break; + case ESP_HIDH_BOOT_MODE: + proto_mode = BTA_HH_PROTO_BOOT_MODE; + break; + default: + break; + } + + return proto_mode; +} + +/******************************************************************************* + * + * Function proto_mode_change_to_upper_layer + * + * Description Change the lower layer protocol mode definition to the upper layer protocol mode definition + * + * Returns Upper layer protocol mode definition + ******************************************************************************/ +static inline esp_hidh_protocol_mode_t proto_mode_change_to_upper_layer(tBTA_HH_PROTO_MODE proto_mode) +{ + esp_hidh_protocol_mode_t protocol_mode = ESP_HIDH_UNSUPPORTED_MODE; + + switch (proto_mode) { + case BTA_HH_PROTO_RPT_MODE: + protocol_mode = ESP_HIDH_REPORT_MODE; + break; + case BTA_HH_PROTO_BOOT_MODE: + protocol_mode = ESP_HIDH_BOOT_MODE; + break; + default: + break; + } + + return protocol_mode; +} + +/******************************************************************************* + * + * Function btc_hh_find_connected_dev_by_handle + * + * Description Return the connected device pointer of the specified device + * handle + * + * Returns Device entry pointer in the device table + ******************************************************************************/ +btc_hh_device_t *btc_hh_find_connected_dev_by_handle(uint8_t handle) +{ + uint32_t i; + for (i = 0; i < BTC_HH_MAX_HID; i++) { + if (btc_hh_cb.devices[i].dev_status == ESP_HIDH_CONN_STATE_CONNECTED && btc_hh_cb.devices[i].dev_handle == handle) { + return &btc_hh_cb.devices[i]; + } + } + return NULL; +} + +/******************************************************************************* + * + * Function btc_hh_find_dev_by_bda + * + * Description Return the device pointer of the specified bd_addr. + * + * Returns Device entry pointer in the device table + ******************************************************************************/ +static btc_hh_device_t *btc_hh_find_dev_by_bda(BD_ADDR bd_addr) +{ + uint8_t i; + for (i = 0; i < BTC_HH_MAX_HID; i++) { + if (btc_hh_cb.devices[i].dev_status != ESP_HIDH_CONN_STATE_UNKNOWN && + memcmp(btc_hh_cb.devices[i].bd_addr, bd_addr, BD_ADDR_LEN) == 0) { + return &btc_hh_cb.devices[i]; + } + } + return NULL; +} + +/******************************************************************************* + * + * Function btc_hh_find_connected_dev_by_bda + * + * Description Return the connected device pointer of the specified + * RawAddress. + * + * Returns Device entry pointer in the device table + ******************************************************************************/ +static btc_hh_device_t *btc_hh_find_connected_dev_by_bda(BD_ADDR bd_addr) +{ + uint32_t i; + for (i = 0; i < BTC_HH_MAX_HID; i++) { + if (btc_hh_cb.devices[i].dev_status == ESP_HIDH_CONN_STATE_CONNECTED && + memcmp(btc_hh_cb.devices[i].bd_addr, bd_addr, BD_ADDR_LEN) == 0) { + return &btc_hh_cb.devices[i]; + } + } + return NULL; +} + +/******************************************************************************* + * + * Function btc_hh_stop_vup_timer + * + * Description stop vitual unplug timer + * + * Returns void + ******************************************************************************/ +void btc_hh_stop_vup_timer(BD_ADDR bd_addr) +{ + BTIF_TRACE_API("%s", __func__); + btc_hh_device_t *p_dev = btc_hh_find_connected_dev_by_bda(bd_addr); + + if (p_dev != NULL) { + BTC_TRACE_DEBUG("stop VUP timer"); + if (p_dev->vup_timer) { + osi_alarm_free(p_dev->vup_timer); + p_dev->vup_timer = NULL; + } + } +} + +/******************************************************************************* + * + * Function btc_hh_timer_timeout + * + * Description Process timer timeout + * + * Returns void + ******************************************************************************/ +void btc_hh_timer_timeout(void *data) +{ + btc_hh_device_t *p_dev = (btc_hh_device_t *)data; + bt_status_t status; + tBTA_HH p_data; + btc_msg_t msg; + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_HH; + msg.act = BTA_HH_VC_UNPLUG_EVT; + + BTC_TRACE_API("%s", __func__); + if (p_dev->dev_status != ESP_HIDH_CONN_STATE_CONNECTED){ + BTC_TRACE_ERROR("%s Device[%s] is not connected!", __func__, + bdaddr_to_string((const bt_bdaddr_t *)p_dev->bd_addr, bdstr, sizeof(bdstr))); + return; + } + + memset(&p_data, 0, sizeof(tBTA_HH)); + p_data.dev_status.status = BTA_HH_ERR; + p_data.dev_status.handle = p_dev->dev_handle; + + /* switch context to btif task context */ + status = btc_transfer_context(&msg, &p_data, sizeof(tBTA_HH), NULL); + if (status != BT_STATUS_SUCCESS) { + BTC_TRACE_ERROR("%s context transfer failed", __func__); + } +} + +/******************************************************************************* + * + * Function btc_hh_start_vup_timer + * + * Description start virtual unplug timer + * + * Returns void + ******************************************************************************/ +void btc_hh_start_vup_timer(BD_ADDR bd_addr) +{ + BTC_TRACE_API("%s", __func__); + + btc_hh_device_t *p_dev = btc_hh_find_connected_dev_by_bda(bd_addr); + if (p_dev == NULL) { + BTC_TRACE_ERROR("%s Error: device not connected!", __func__); + return; + } + + if (p_dev->vup_timer) { + osi_alarm_free(p_dev->vup_timer); + p_dev->vup_timer = NULL; + } + if ((p_dev->vup_timer = osi_alarm_new("btc_hh.vup_timer", btc_hh_timer_timeout, p_dev, BTC_TIMEOUT_VUP_MS)) == + NULL) { + BTC_TRACE_ERROR("%s unable to malloc vup_timer!", __func__); + } +} + +/******************************************************************************* + * + * Function btc_hh_add_added_dev + * + * Description Add a new device to the added device list. + * + * Returns true if add successfully, otherwise false. + ******************************************************************************/ +bool btc_hh_add_added_dev(BD_ADDR bd_addr, tBTA_HH_ATTR_MASK attr_mask) +{ + int i; + for (i = 0; i < BTC_HH_MAX_ADDED_DEV; i++) { + if (memcmp(btc_hh_cb.added_devices[i].bd_addr, bd_addr, BD_ADDR_LEN) == 0) { + return false; + } + } + for (i = 0; i < BTC_HH_MAX_ADDED_DEV; i++) { + if (memcmp(btc_hh_cb.added_devices[i].bd_addr, bd_addr_null, BD_ADDR_LEN) == 0) { + memcpy(btc_hh_cb.added_devices[i].bd_addr, bd_addr, BD_ADDR_LEN); + btc_hh_cb.added_devices[i].dev_handle = BTA_HH_INVALID_HANDLE; + btc_hh_cb.added_devices[i].attr_mask = attr_mask; + return true; + } + } + + BTC_TRACE_ERROR("%s: Error, out of space to add device", __func__); + return false; +} + +/******************************************************************************* + ** + ** Function btc_hh_remove_device + ** + ** Description Remove an added device from the stack. + ** + ** Returns void + ******************************************************************************/ +void btc_hh_remove_device(BD_ADDR bd_addr) +{ + int i; + btc_hh_device_t *p_dev; + btc_hh_added_device_t *p_added_dev; + + for (i = 0; i < BTC_HH_MAX_ADDED_DEV; i++) { + p_added_dev = &btc_hh_cb.added_devices[i]; + if (p_added_dev->bd_addr == bd_addr) { + BTA_HhRemoveDev(p_added_dev->dev_handle); + btc_storage_remove_hid_info((bt_bdaddr_t *)p_added_dev->bd_addr); + memset(p_added_dev->bd_addr, 0, 6); + p_added_dev->dev_handle = BTA_HH_INVALID_HANDLE; + break; + } + } + + p_dev = btc_hh_find_dev_by_bda(bd_addr); + if (p_dev == NULL) { + BTC_TRACE_ERROR("%s Oops, can't find device", __func__); + return; + } + + /* need to notify up-layer device is disconnected to avoid state out of sync + * with up-layer */ //[boblane] + // HAL_CBACK(bt_hh_callbacks, connection_state_cb, &(p_dev->bd_addr), BTHH_CONN_STATE_DISCONNECTED); + + p_dev->dev_status = ESP_HIDH_CONN_STATE_UNKNOWN; + p_dev->dev_handle = BTA_HH_INVALID_HANDLE; + p_dev->ready_for_data = false; + + if (btc_hh_cb.device_num > 0) { + btc_hh_cb.device_num--; + } else { + BTC_TRACE_WARNING("%s: device_num = 0", __func__); + } +} + +static void bte_hh_arg_deep_copy(btc_msg_t *msg, void *p_dst, void *p_src) +{ + tBTA_HH *p_dst_data = (tBTA_HH *)p_dst; + tBTA_HH *p_src_data = (tBTA_HH *)p_src; + switch (msg->act) + { + case BTA_HH_GET_RPT_EVT: { + BT_HDR *src_hdr = p_src_data->hs_data.rsp_data.p_rpt_data; + if (src_hdr) { + p_dst_data->hs_data.rsp_data.p_rpt_data = osi_malloc(sizeof(BT_HDR) + src_hdr->offset + src_hdr->len); + if (p_dst_data->hs_data.rsp_data.p_rpt_data == NULL) { + BTC_TRACE_ERROR("%s malloc p_rpt_data failed!", __func__); + p_dst_data->hs_data.status = ESP_HIDH_ERR_NO_RES; + break; + } + memcpy(p_dst_data->hs_data.rsp_data.p_rpt_data, src_hdr, sizeof(BT_HDR) + src_hdr->offset + src_hdr->len); + } + break; + } + default: + break; + } +} + +static void bte_hh_evt(tBTA_HH_EVT event, tBTA_HH *p_data) +{ + bt_status_t status; + int param_len = 0; + + BTC_TRACE_API("%s event=%d", __func__, event); + + switch (event) { + case BTA_HH_ENABLE_EVT: + param_len = sizeof(tBTA_HH_STATUS); + break; + case BTA_HH_DISABLE_EVT: + param_len = sizeof(tBTA_HH_STATUS); + break; + case BTA_HH_OPEN_EVT: + param_len = sizeof(tBTA_HH_CONN); + break; + case BTA_HH_CLOSE_EVT: + param_len = sizeof(tBTA_HH_CBDATA); + break; + case BTA_HH_GET_RPT_EVT: + param_len = sizeof(tBTA_HH_HSDATA); + break; + case BTA_HH_SET_RPT_EVT: + param_len = sizeof(tBTA_HH_CBDATA); + break; + case BTA_HH_GET_PROTO_EVT: + param_len = sizeof(tBTA_HH_HSDATA); + break; + case BTA_HH_SET_PROTO_EVT: + param_len = sizeof(tBTA_HH_CBDATA); + break; + case BTA_HH_GET_IDLE_EVT: + param_len = sizeof(tBTA_HH_HSDATA); + break; + case BTA_HH_SET_IDLE_EVT: + param_len = sizeof(tBTA_HH_CBDATA); + break; + case BTA_HH_GET_DSCP_EVT: + param_len = sizeof(tBTA_HH_DEV_DSCP_INFO); + break; + case BTA_HH_ADD_DEV_EVT: + param_len = sizeof(tBTA_HH_DEV_INFO); + break; + case BTA_HH_RMV_DEV_EVT: + param_len = sizeof(tBTA_HH_DEV_INFO); + break; + case BTA_HH_VC_UNPLUG_EVT: + param_len = sizeof(tBTA_HH_CBDATA); + break; + case BTA_HH_DATA_EVT: + param_len = sizeof(tBTA_HH_API_SENDDATA); + break; + case BTA_HH_API_ERR_EVT: + param_len = 0; + break; + } + + btc_msg_t msg; + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_HH; + msg.act = event; + + status = btc_transfer_context(&msg, p_data, param_len, bte_hh_arg_deep_copy); + assert(status == BT_STATUS_SUCCESS); +} + +/******************************************************************************* + * + * Function btc_hh_init + * + * Description initializes the hh interface + * + * Returns void + * + ******************************************************************************/ +static void btc_hh_init(void) +{ + BTC_TRACE_API("%s", __func__); + esp_hidh_status_t ret = ESP_HIDH_OK; + do { + if (is_hidh_init()) { + BTC_TRACE_ERROR("%s HH has been initiated, shall uninit first!", __func__); + ret = ESP_HIDH_NEED_DEINIT; + break; + } + + memset(&btc_hh_cb, 0, sizeof(btc_hh_cb)); + for (uint8_t i = 0; i < BTC_HH_MAX_HID; i++) { + btc_hh_cb.devices[i].dev_status = ESP_HIDH_CONN_STATE_UNKNOWN; + } + BTA_HhEnable(BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT, bte_hh_evt); + } while (0); + + if (ret != ESP_HIDH_OK) { + esp_hidh_cb_param_t param; + param.init.status = ret; + btc_hh_cb_to_app(ESP_HIDH_INIT_EVT, ¶m); + } +} + +/******************************************************************************* + * + * Function btc_hh_deinit + * + * Description de-initializes the hh interface + * + * Returns void + * + ******************************************************************************/ +static void btc_hh_deinit(void) +{ + BTC_TRACE_API("%s", __func__); + esp_hidh_status_t ret = ESP_HIDH_OK; + do { + if (!is_hidh_init()) { + BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__); + ret = ESP_HIDH_NEED_INIT; + break; + } + + // close all connections + for (uint8_t i = 0; i < BTC_HH_MAX_HID; i++) { + if(btc_hh_cb.devices[i].dev_status == ESP_HIDH_CONN_STATE_CONNECTED){ + BTA_HhClose(btc_hh_cb.devices[i].dev_handle); + } + } + btc_hh_cb.service_dereg_active = TRUE; + btc_hh_cb.status = BTC_HH_DISABLING; + BTA_HhDisable(); + } while (0); + + if (ret != ESP_HIDH_OK) { + esp_hidh_cb_param_t param; + param.deinit.status = ret; + btc_hh_cb_to_app(ESP_HIDH_DEINIT_EVT, ¶m); + } +} + +/******************************************************************************* + * + * Function btc_hh_connect + * + * Description connection initiated from the BTC thread context + * + * Returns void + * + ******************************************************************************/ +static void btc_hh_connect(btc_hidh_args_t *arg) +{ + BTC_TRACE_API("%s", __func__); + esp_hidh_status_t ret = ESP_HIDH_OK; + btc_hh_added_device_t* added_dev = NULL; + btc_hh_device_t* dev = NULL; + esp_hidh_cb_param_t param; + + do { + if (!is_hidh_init()) { + BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__); + ret = ESP_HIDH_NEED_INIT; + break; + } + + if (btc_hh_cb.status == BTC_HH_DEV_CONNECTING) { + BTC_TRACE_ERROR("%s HH is connecting, ignore!", __func__); + ret = ESP_HIDH_BUSY; + break; + } + + dev = btc_hh_find_dev_by_bda(arg->connect.bd_addr); + if (!dev && btc_hh_cb.device_num >= BTC_HH_MAX_HID) { + BTC_TRACE_ERROR("%s exceeded the maximum supported HID device number %d!", __func__, BTC_HH_MAX_HID); + ret = ESP_HIDH_ERR_NO_RES; + break; + } + + for (int i = 0; i < BTC_HH_MAX_ADDED_DEV; i++) { + if (memcmp(btc_hh_cb.added_devices[i].bd_addr, arg->connect.bd_addr, BD_ADDR_LEN) == 0) { + added_dev = &btc_hh_cb.added_devices[i]; + BTC_TRACE_WARNING("%s Device[%s] already added, attr_mask = 0x%x", __func__, + bdaddr_to_string((const bt_bdaddr_t *)arg->connect.bd_addr, bdstr, sizeof(bdstr)), + added_dev->attr_mask); + } + } + + if (added_dev != NULL) { + if (added_dev->dev_handle == BTA_HH_INVALID_HANDLE) { + // No space for more HID device now. + BTC_TRACE_ERROR("device added but addition failed"); + memset(added_dev->bd_addr, 0, sizeof(added_dev->bd_addr)); + ret = ESP_HIDH_ERR; + break; + } + } + + /* Not checking the NORMALLY_Connectible flags from sdp record, and anyways + sending this request from host, for subsequent user initiated connection. If the remote is + not in pagescan mode, we will do 2 retries to connect before giving up */ + btc_hh_cb.status = BTC_HH_DEV_CONNECTING; + memcpy(btc_hh_cb.pending_conn_address, arg->connect.bd_addr, BD_ADDR_LEN); + BTA_HhOpen(arg->connect.bd_addr, BTA_HH_PROTO_RPT_MODE, (BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT)); + param.open.conn_status = ESP_HIDH_CONN_STATE_CONNECTING; + ret = ESP_HIDH_OK; + } while (0); + + if (ret != ESP_HIDH_OK) { + param.open.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTED; + } + param.open.status = ret; + param.open.handle = BTA_HH_INVALID_HANDLE; + memcpy(param.open.bd_addr, arg->connect.bd_addr, BD_ADDR_LEN); + param.open.is_orig = true; + btc_hh_cb_to_app(ESP_HIDH_OPEN_EVT, ¶m); +} + +/******************************************************************************* + * + * Function btc_hh_disconnect + * + * Description disconnection initiated from the BTC thread context + * + * Returns void + * + ******************************************************************************/ +static void btc_hh_disconnect(btc_hidh_args_t *arg) +{ + BTC_TRACE_API("%s", __func__); + esp_hidh_status_t ret = ESP_HIDH_OK; + btc_hh_device_t *p_dev; + esp_hidh_cb_param_t param; + + do { + if (!is_hidh_init()) { + BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__); + ret = ESP_HIDH_NEED_INIT; + break; + } + p_dev = btc_hh_find_connected_dev_by_bda(arg->disconnect.bd_addr); + if (p_dev != NULL) { + BTA_HhClose(p_dev->dev_handle); + param.close.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTING; + param.close.handle = p_dev->dev_handle; + } else { + ret = ESP_HIDH_NO_CONNECTION; + BTC_TRACE_ERROR("%s Error: device not connected!", __func__); + } + + } while (0); + + if (ret != ESP_HIDH_OK) { + param.close.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTED; + param.close.handle = BTA_HH_INVALID_HANDLE; + } + param.close.status = ret; + btc_hh_cb_to_app(ESP_HIDH_CLOSE_EVT, ¶m); +} + +/******************************************************************************* + * + * Function btc_hh_virtual_unplug + * + * Description Virtual unplug initiated from the BTC thread context + * Special handling for HID mouse- + * + * Returns void + * + ******************************************************************************/ +static void btc_hh_virtual_unplug(btc_hidh_args_t *arg) +{ + BTC_TRACE_API("%s", __func__); + esp_hidh_status_t ret = ESP_HIDH_OK; + btc_hh_device_t *p_dev; + esp_hidh_cb_param_t param; + + do { + if (!is_hidh_init()) { + BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__); + ret = ESP_HIDH_NEED_INIT; + break; + } + p_dev = btc_hh_find_dev_by_bda(arg->unplug.bd_addr); + if ((p_dev != NULL) && (p_dev->dev_status == ESP_HIDH_CONN_STATE_CONNECTED) && + (p_dev->attr_mask & HID_VIRTUAL_CABLE)) { + BTC_TRACE_DEBUG("%s: Sending BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG", __func__); + /* start the timer */ + btc_hh_start_vup_timer(arg->unplug.bd_addr); + p_dev->local_vup = true; + BTA_HhSendCtrl(p_dev->dev_handle, BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG); + + param.unplug.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTING; + param.unplug.handle = p_dev->dev_handle; + } else if ((p_dev != NULL) && (p_dev->dev_status == ESP_HIDH_CONN_STATE_CONNECTED)) { + BTC_TRACE_WARNING("%s: Virtual unplug not suported, disconnecting device", __func__); + /* start the timer */ + btc_hh_start_vup_timer(arg->unplug.bd_addr); + p_dev->local_vup = true; + BTA_HhClose(p_dev->dev_handle); + + param.unplug.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTING; + param.unplug.handle = p_dev->dev_handle; + } else { + BTC_TRACE_ERROR("%s: Error, device not opened, status = %d", __func__, btc_hh_cb.status); + ret = ESP_HIDH_NO_CONNECTION; + if (memcmp(btc_hh_cb.pending_conn_address, arg->unplug.bd_addr, BD_ADDR_LEN) == 0 && + (btc_hh_cb.status == BTC_HH_DEV_CONNECTING)) { + btc_hh_cb.status = (BTC_HH_STATUS)BTC_HH_DEV_DISCONNECTED; + memset(btc_hh_cb.pending_conn_address, 0, BD_ADDR_LEN); + } + } + } while (0); + + if (ret != ESP_HIDH_OK) { + param.unplug.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTED; + param.unplug.handle = BTA_HH_INVALID_HANDLE; + } + param.unplug.status = ret; + btc_hh_cb_to_app(ESP_HIDH_VC_UNPLUG_EVT, ¶m); +} + +/******************************************************************************* + * + * Function btc_hh_set_info + * + * Description Set the HID device descriptor for the specified HID device. + * + * Returns void + * + ******************************************************************************/ +static void btc_hh_set_info(btc_hidh_args_t *arg) +{ + BTC_TRACE_API("%s", __func__); + esp_hidh_status_t ret = ESP_HIDH_OK; + esp_hidh_cb_param_t param; + tBTA_HH_DEV_DSCP_INFO dscp_info; + + BTC_TRACE_DEBUG("%s: sub_class = 0x%02x, app_id = %d, vendor_id = 0x%04x, " + "product_id = 0x%04x, version= 0x%04x", + __func__, arg->set_info.hid_info->sub_class, arg->set_info.hid_info->app_id, + arg->set_info.hid_info->vendor_id, arg->set_info.hid_info->product_id, + arg->set_info.hid_info->version); + do { + if (!is_hidh_init()) { + BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__); + ret = ESP_HIDH_NEED_INIT; + break; + } + + memset(&dscp_info, 0, sizeof(dscp_info)); + dscp_info.vendor_id = arg->set_info.hid_info->vendor_id; + dscp_info.product_id = arg->set_info.hid_info->product_id; + dscp_info.version = arg->set_info.hid_info->version; + dscp_info.ctry_code = arg->set_info.hid_info->ctry_code; + + dscp_info.descriptor.dl_len = arg->set_info.hid_info->dl_len; + dscp_info.descriptor.dsc_list = (uint8_t *)osi_malloc(dscp_info.descriptor.dl_len); + if (dscp_info.descriptor.dsc_list == NULL) { + BTC_TRACE_ERROR("%s malloc dsc_list failed!", __func__); + ret = ESP_HIDH_ERR_NO_RES; + break; + } + memcpy(dscp_info.descriptor.dsc_list, arg->set_info.hid_info->dsc_list, dscp_info.descriptor.dl_len); + + if (btc_hh_add_added_dev(arg->set_info.bd_addr, arg->set_info.hid_info->attr_mask)) { + btc_hh_cb.add_event = BTC_HH_SET_INFO_EVT; + BTA_HhAddDev(arg->set_info.bd_addr, arg->set_info.hid_info->attr_mask, arg->set_info.hid_info->sub_class, + arg->set_info.hid_info->app_id, dscp_info); + } else { + BTC_TRACE_ERROR("%s malloc dsc_list failed!", __func__); + ret = ESP_HIDH_ERR; + break; + } + } while(0); + utl_freebuf((void **)&dscp_info.descriptor.dsc_list); + + if (ret != ESP_HIDH_OK) { + param.set_info.status = ret; + param.set_info.handle = BTA_HH_INVALID_HANDLE; + memcpy(param.set_info.bd_addr, arg->set_info.bd_addr, BD_ADDR_LEN); + btc_hh_cb_to_app(ESP_HIDH_SET_INFO_EVT, ¶m); + } +} + +/******************************************************************************* + * + * Function btc_hh_get_protocol + * + * Description Get the HID proto mode. + * + * Returns void + * + ******************************************************************************/ +static void btc_hh_get_protocol(btc_hidh_args_t *arg) +{ + BTC_TRACE_API("%s", __func__); + esp_hidh_status_t ret = ESP_HIDH_OK; + esp_hidh_cb_param_t param; + btc_hh_device_t *p_dev; + + do { + if (!is_hidh_init()) { + BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__); + ret = ESP_HIDH_NEED_INIT; + break; + } + p_dev = btc_hh_find_connected_dev_by_bda(arg->get_protocol.bd_addr); + if (p_dev == NULL) { + ret = ESP_HIDH_NO_CONNECTION; + BTC_TRACE_ERROR("%s Error: device not connected!", __func__); + break; + } + BTA_HhGetProtoMode(p_dev->dev_handle); + } while(0); + + if (ret != ESP_HIDH_OK) { + param.get_proto.proto_mode = ESP_HIDH_UNSUPPORTED_MODE; + param.get_proto.handle = BTA_HH_INVALID_HANDLE; + param.get_proto.status = ret; + btc_hh_cb_to_app(ESP_HIDH_GET_PROTO_EVT, ¶m); + } +} + +/******************************************************************************* + * + * Function btc_hh_set_protocol + * + * Description Set the HID proto mode. + * + * Returns void + * + ******************************************************************************/ +static void btc_hh_set_protocol(btc_hidh_args_t *arg) +{ + BTC_TRACE_API("%s", __func__); + esp_hidh_status_t ret = ESP_HIDH_OK; + esp_hidh_cb_param_t param; + btc_hh_device_t *p_dev; + + do { + if (!is_hidh_init()) { + BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__); + ret = ESP_HIDH_NEED_INIT; + break; + } + p_dev = btc_hh_find_connected_dev_by_bda(arg->set_protocol.bd_addr); + if (p_dev == NULL) { + ret = ESP_HIDH_NO_CONNECTION; + BTC_TRACE_ERROR("%s Error: device not connected!", __func__); + break; + } else if (arg->set_protocol.protocol_mode != ESP_HIDH_REPORT_MODE && arg->set_protocol.protocol_mode != ESP_HIDH_BOOT_MODE) { + BTC_TRACE_ERROR("%s: Error, device proto_mode = %d.", __func__, arg->set_protocol.protocol_mode); + ret = ESP_HIDH_HS_INVALID_PARAM; + break; + } else { + BTA_HhSetProtoMode(p_dev->dev_handle, proto_mode_change_to_lower_layer(arg->set_protocol.protocol_mode)); + } + } while (0); + + if (ret != ESP_HIDH_OK) { + param.set_proto.handle = BTA_HH_INVALID_HANDLE; + param.set_proto.status = ret; + btc_hh_cb_to_app(ESP_HIDH_SET_PROTO_EVT, ¶m); + } +} + +/******************************************************************************* + * + * Function btc_hh_get_report + * + * Description Send a GET_REPORT to HID device. + * + * Returns void + * + ******************************************************************************/ +static void btc_hh_get_report(btc_hidh_args_t *arg) +{ + BTC_TRACE_API("%s", __func__); + esp_hidh_status_t ret = ESP_HIDH_OK; + esp_hidh_cb_param_t param; + btc_hh_device_t *p_dev; + + do { + if (!is_hidh_init()) { + BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__); + ret = ESP_HIDH_NEED_INIT; + break; + } + + p_dev = btc_hh_find_connected_dev_by_bda(arg->get_report.bd_addr); + if (p_dev == NULL) { + ret = ESP_HIDH_NO_CONNECTION; + BTC_TRACE_ERROR("%s Error: device not connected!", __func__); + break; + } else if (((int)arg->get_report.report_type) <= BTA_HH_RPTT_RESRV || + ((int)arg->get_report.report_type) > BTA_HH_RPTT_FEATURE) { + BTC_TRACE_ERROR("%s Error: report type=%d not supported!", __func__, arg->get_report.report_type); + ret = ESP_HIDH_HS_INVALID_PARAM; + break; + } else { + BTA_HhGetReport(p_dev->dev_handle, arg->get_report.report_type, arg->get_report.report_id, + arg->get_report.buffer_size); + } + } while (0); + + if (ret != ESP_HIDH_OK) { + param.get_rpt.handle = BTA_HH_INVALID_HANDLE; + param.get_rpt.status = ret; + param.get_rpt.len = 0; + param.get_rpt.data = NULL; + btc_hh_cb_to_app(ESP_HIDH_GET_RPT_EVT, ¶m); + } +} + +/******************************************************************************* + * + * Function create_pbuf + * + * Description Helper function to create p_buf for send_data or set_report + * + * Returns BT_HDR * + * + ******************************************************************************/ +static BT_HDR *create_pbuf(uint16_t len, uint8_t *data) +{ + uint8_t *pbuf_data; + BT_HDR *p_buf = (BT_HDR *)osi_malloc(len + BTA_HH_MIN_OFFSET + sizeof(BT_HDR)); + if (p_buf == NULL) { + BTC_TRACE_ERROR("%s failed!", __func__); + return NULL; + } + p_buf->len = len; + p_buf->offset = BTA_HH_MIN_OFFSET; + + pbuf_data = (uint8_t *)(p_buf + 1) + p_buf->offset; + memcpy(pbuf_data, data, len); + + return p_buf; +} + +/******************************************************************************* + * + * Function btc_hh_set_report + * + * Description Send a SET_REPORT to HID device. + * + * Returns void + * + ******************************************************************************/ +static void btc_hh_set_report(btc_hidh_args_t *arg) +{ + BTC_TRACE_API("%s", __func__); + esp_hidh_status_t ret = ESP_HIDH_OK; + esp_hidh_cb_param_t param; + btc_hh_device_t *p_dev; + + do { + if (!is_hidh_init()) { + BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__); + ret = ESP_HIDH_NEED_INIT; + break; + } + + p_dev = btc_hh_find_connected_dev_by_bda(arg->set_report.bd_addr); + if (p_dev == NULL) { + ret = ESP_HIDH_NO_CONNECTION; + BTC_TRACE_ERROR("%s Error: device not connected!", __func__); + break; + } else if (((int)arg->set_report.report_type) <= BTA_HH_RPTT_RESRV || + ((int)arg->set_report.report_type) > BTA_HH_RPTT_FEATURE) { + BTC_TRACE_ERROR("%s Error: report type=%d not supported!", __func__, arg->set_report.report_type); + ret = ESP_HIDH_HS_INVALID_PARAM; + break; + } else if (arg->set_report.report == NULL || arg->set_report.len == 0) { + BTC_TRACE_ERROR("%s Error: report is empty!", __func__); + ret = ESP_HIDH_HS_INVALID_PARAM; + break; + } else { + BT_HDR* p_buf = create_pbuf(arg->set_report.len, arg->set_report.report); + if (p_buf == NULL) { + ret = ESP_HIDH_ERR_NO_RES; + break; + } + BTA_HhSetReport(p_dev->dev_handle, arg->set_report.report_type, p_buf); + } + } while(0); + + if (ret != ESP_HIDH_OK) { + param.set_rpt.handle = BTA_HH_INVALID_HANDLE; + param.set_rpt.status = ret; + btc_hh_cb_to_app(ESP_HIDH_SET_RPT_EVT, ¶m); + } +} + +/******************************************************************************* + * + * Function btc_hh_send_data + * + * Description Send a SEND_DATA to HID device. + * + * Returns void + * + ******************************************************************************/ +static void btc_hh_send_data(btc_hidh_args_t *arg) +{ + BTC_TRACE_API("%s", __func__); + esp_hidh_status_t ret = ESP_HIDH_OK; + esp_hidh_cb_param_t param; + btc_hh_device_t *p_dev; + + do { + if (!is_hidh_init()) { + BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__); + ret = ESP_HIDH_NEED_INIT; + break; + } + + p_dev = btc_hh_find_connected_dev_by_bda(arg->send_data.bd_addr); + if (p_dev == NULL) { + ret = ESP_HIDH_NO_CONNECTION; + BTC_TRACE_ERROR("%s Error: device not connected!", __func__); + break; + } else if (arg->send_data.data == NULL || arg->send_data.len == 0) { + BTC_TRACE_ERROR("%s Error: send data is empty!", __func__); + ret = ESP_HIDH_HS_INVALID_PARAM; + break; + } else { + BT_HDR *p_buf = create_pbuf(arg->send_data.len, arg->send_data.data); + if (p_buf == NULL) { + ret = ESP_HIDH_ERR_NO_RES; + break; + } + p_buf->layer_specific = BTA_HH_RPTT_OUTPUT; + BTA_HhSendData(p_dev->dev_handle, arg->send_data.bd_addr, p_buf); + } + } while(0); + + if (ret != ESP_HIDH_OK) { + param.send_data.handle = BTA_HH_INVALID_HANDLE; + param.send_data.status = ret; + param.send_data.reason = 0; + btc_hh_cb_to_app(ESP_HIDH_DATA_EVT, ¶m); + } +} + +/******************************************************************************* +** +** Function btc_hh_get_idle_time +** +** Description Get the HID idle time +** +** Returns void +** +*******************************************************************************/ +static void btc_hh_get_idle_time(btc_hidh_args_t *arg) +{ + BTC_TRACE_API("%s", __func__); + esp_hidh_status_t ret = ESP_HIDH_OK; + esp_hidh_cb_param_t param; + btc_hh_device_t *p_dev; + + do { + if (!is_hidh_init()) { + BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__); + ret = ESP_HIDH_NEED_INIT; + break; + } + + p_dev = btc_hh_find_connected_dev_by_bda(arg->get_idle.bd_addr); + if (p_dev == NULL) { + ret = ESP_HIDH_NO_CONNECTION; + BTC_TRACE_ERROR("%s Error: device not connected!", __func__); + break; + } + BTA_HhGetIdle(p_dev->dev_handle); + } while (0); + + if (ret != ESP_HIDH_OK) { + param.get_idle.handle = BTA_HH_INVALID_HANDLE; + param.get_idle.status = ret; + param.get_idle.idle_rate = 0; + btc_hh_cb_to_app(ESP_HIDH_GET_IDLE_EVT, ¶m); + } +} + +/******************************************************************************* +** +** Function btc_hh_set_idle_time +** +** Description Set the HID idle time +** +** Returns void +** +*******************************************************************************/ +static void btc_hh_set_idle_time(btc_hidh_args_t *arg) +{ + BTC_TRACE_API("%s", __func__); + esp_hidh_status_t ret = ESP_HIDH_OK; + esp_hidh_cb_param_t param; + btc_hh_device_t *p_dev; + + do { + if (!is_hidh_init()) { + BTC_TRACE_ERROR("%s HH has not been initiated, shall init first!", __func__); + ret = ESP_HIDH_NEED_INIT; + break; + } + + p_dev = btc_hh_find_connected_dev_by_bda(arg->set_idle.bd_addr); + if (p_dev == NULL) { + ret = ESP_HIDH_NO_CONNECTION; + BTC_TRACE_ERROR("%s Error: device not connected!", __func__); + break; + } + BTA_HhSetIdle(p_dev->dev_handle, arg->set_idle.idle_time); + } while (0); + + if (ret != ESP_HIDH_OK) { + param.set_idle.handle = BTA_HH_INVALID_HANDLE; + param.set_idle.status = ret; + btc_hh_cb_to_app(ESP_HIDH_SET_IDLE_EVT, ¶m); + } +} + +static void btc_hh_call_arg_deep_free(btc_msg_t *msg) +{ + btc_hidh_args_t *arg = (btc_hidh_args_t *)msg->arg; + + switch (msg->act) { + case BTC_HH_SET_INFO_EVT: + utl_freebuf((void **)&arg->set_info.hid_info); + break; + case BTC_HH_SET_REPORT_EVT: + utl_freebuf((void **)&arg->set_report.report); + break; + case BTC_HH_SEND_DATA_EVT: + utl_freebuf((void **)&arg->send_data.data); + break; + default: + break; + } +} + +void btc_hh_call_handler(btc_msg_t *msg) +{ + btc_hidh_args_t *arg = (btc_hidh_args_t *)(msg->arg); + switch (msg->act) { + case BTC_HH_INIT_EVT: + btc_hh_init(); + break; + case BTC_HH_CONNECT_EVT: + btc_hh_connect(arg); + break; + case BTC_HH_DISCONNECT_EVT: + btc_hh_disconnect(arg); + break; + case BTC_HH_UNPLUG_EVT: + btc_hh_virtual_unplug(arg); + break; + case BTC_HH_SET_INFO_EVT: + btc_hh_set_info(arg); + break; + case BTC_HH_GET_PROTO_EVT: + btc_hh_get_protocol(arg); + break; + case BTC_HH_SET_PROTO_EVT: + btc_hh_set_protocol(arg); + break; + case BTC_HH_GET_IDLE_EVT: + btc_hh_get_idle_time(arg); + break; + case BTC_HH_SET_IDLE_EVT: + btc_hh_set_idle_time(arg); + break; + case BTC_HH_GET_REPORT_EVT: + btc_hh_get_report(arg); + break; + case BTC_HH_SET_REPORT_EVT: + btc_hh_set_report(arg); + break; + case BTC_HH_SEND_DATA_EVT: + btc_hh_send_data(arg); + break; + case BTC_HH_DEINIT_EVT: + btc_hh_deinit(); + break; + default: + BTC_TRACE_WARNING("unknown hidh action %d", msg->act); + break; + } + btc_hh_call_arg_deep_free(msg); +} + +static void btc_hh_cb_arg_deep_free(btc_msg_t *msg) +{ + tBTA_HH *arg = (tBTA_HH *)msg->arg; + + switch (msg->act) { + case BTA_HH_GET_RPT_EVT: + utl_freebuf((void **)&arg->hs_data.rsp_data.p_rpt_data); + break; + case BTA_HH_DATA_IND_EVT: + utl_freebuf((void **)&arg->int_data.p_data); + break; + default: + break; + } +} + +bool btc_hh_copy_hid_info(tBTA_HH_DEV_DSCP_INFO *dest, tBTA_HH_DEV_DSCP_INFO *src) +{ + dest->descriptor.dl_len = 0; + if (src->descriptor.dl_len > 0) { + dest->descriptor.dsc_list = (uint8_t *)osi_malloc(src->descriptor.dl_len); + } + if (dest->descriptor.dsc_list) { + memcpy(dest->descriptor.dsc_list, src->descriptor.dsc_list, src->descriptor.dl_len); + dest->descriptor.dl_len = src->descriptor.dl_len; + } + dest->vendor_id = src->vendor_id; + dest->product_id = src->product_id; + dest->version = src->version; + dest->ctry_code = src->ctry_code; + dest->ssr_max_latency = src->ssr_max_latency; + dest->ssr_min_tout = src->ssr_min_tout; + return true; +} + +bool btc_hh_cb_copy_hid_info(esp_hidh_cb_param_t *param, tBTA_HH_DEV_DSCP_INFO *src) +{ + param->dscp.dl_len = 0; + if (src->descriptor.dl_len > 0) { + param->dscp.dsc_list = (uint8_t *)osi_malloc(src->descriptor.dl_len); + } + if (param->dscp.dsc_list) { + memcpy(param->dscp.dsc_list, src->descriptor.dsc_list, src->descriptor.dl_len); + param->dscp.dl_len = src->descriptor.dl_len; + } + param->dscp.vendor_id = src->vendor_id; + param->dscp.product_id = src->product_id; + param->dscp.version = src->version; + param->dscp.ctry_code = src->ctry_code; + param->dscp.ssr_max_latency = src->ssr_max_latency; + param->dscp.ssr_min_tout = src->ssr_min_tout; + return true; +} + +void btc_hh_cb_handler(btc_msg_t *msg) +{ + esp_hidh_cb_param_t param = {0}; + tBTA_HH *p_data = (tBTA_HH *)msg->arg; + btc_hh_device_t *p_dev = NULL; + int len, i; + BTC_TRACE_DEBUG("%s: event=%s dereg = %d", __func__, dump_hh_event(msg->act), btc_hh_cb.service_dereg_active); + switch (msg->act) { + case BTA_HH_ENABLE_EVT: + if (p_data->status == BTA_HH_OK) { + btc_hh_cb.status = BTC_HH_ENABLED; + BTC_TRACE_DEBUG("Loading added devices"); + /* Add hid descriptors for already bonded hid devices*/ + // btc_storage_load_bonded_hid_info(); + } else { + btc_hh_cb.status = BTC_HH_DISABLED; + BTC_TRACE_ERROR("Error, HH enabling failed, status = %d", p_data->status); + } + param.init.status = p_data->status; + btc_hh_cb_to_app(ESP_HIDH_INIT_EVT, ¶m); + break; + case BTA_HH_DISABLE_EVT: + btc_hh_cb.status = BTC_HH_DISABLED; + if (btc_hh_cb.service_dereg_active) { + BTIF_TRACE_DEBUG("BTA_HH_DISABLE_EVT: enabling HID Device service"); + // btif_hd_service_registration(); + btc_hh_cb.service_dereg_active = FALSE; + } + if (p_data->status == BTA_HH_OK) { + // Clear the control block + for (uint8_t i = 0; i < BTC_HH_MAX_HID; i++) { + if (btc_hh_cb.devices[i].vup_timer) { + osi_alarm_free(btc_hh_cb.devices[i].vup_timer); + } + } + memset(&btc_hh_cb, 0, sizeof(btc_hh_cb)); + for (i = 0; i < BTC_HH_MAX_HID; i++) { + btc_hh_cb.devices[i].dev_status = ESP_HIDH_CONN_STATE_UNKNOWN; + } + } else { + BTC_TRACE_ERROR("Error, HH disabling failed, status = %d", p_data->status); + } + param.deinit.status = p_data->status; + btc_hh_cb_to_app(ESP_HIDH_DEINIT_EVT, ¶m); + break; + case BTA_HH_OPEN_EVT: + BTC_TRACE_DEBUG("handle=%d, status =%d", p_data->conn.handle, p_data->conn.status); + memset(btc_hh_cb.pending_conn_address, 0, BD_ADDR_LEN); + if (p_data->conn.status == BTA_HH_OK) { + p_dev = btc_hh_find_connected_dev_by_handle(p_data->conn.handle); + if (p_dev == NULL) { + BTC_TRACE_ERROR("Error, cannot find device with handle %d", p_data->conn.handle); + btc_hh_cb.status = (BTC_HH_STATUS)BTC_HH_DEV_DISCONNECTED; + // The connect request must come from device side and exceeded the + // connected HID device number. + BTA_HhClose(p_data->conn.handle); + + param.open.status = ESP_HIDH_ERR; + param.open.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTED; + } else { + BTC_TRACE_DEBUG("Found device...Getting dscp info for handle " + "... %d", + p_data->conn.handle); + memcpy(p_dev->bd_addr, p_data->conn.bda, BD_ADDR_LEN); + btc_hh_cb.status = (BTC_HH_STATUS)BTC_HH_DEV_CONNECTED; + // Send set_idle if the peer_device is a keyboard [boblane] + // if (check_cod(&p_data->conn.bda, COD_HID_KEYBOARD) || check_cod(&p_data->conn.bda, COD_HID_COMBO)) + // BTA_HhSetIdle(p_data->conn.handle, 0); + btc_hh_cb.p_curr_dev = btc_hh_find_connected_dev_by_handle(p_data->conn.handle); + BTA_HhGetDscpInfo(p_data->conn.handle); + p_dev->dev_status = ESP_HIDH_CONN_STATE_CONNECTED; + + param.open.status = ESP_HIDH_OK; + param.open.conn_status = ESP_HIDH_CONN_STATE_CONNECTED; + } + } else { + p_dev = btc_hh_find_dev_by_bda(p_data->conn.bda); + if (p_dev != NULL) { + btc_hh_stop_vup_timer(p_dev->bd_addr); + p_dev->dev_status = ESP_HIDH_CONN_STATE_DISCONNECTED; + } + btc_hh_cb.status = (BTC_HH_STATUS)BTC_HH_DEV_DISCONNECTED; + + param.open.status = p_data->conn.status; + param.open.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTED; + } + param.open.handle = p_data->conn.handle; + param.open.is_orig = p_data->conn.is_orig; + memcpy(param.open.bd_addr, p_data->conn.bda, BD_ADDR_LEN); + btc_hh_cb_to_app(ESP_HIDH_OPEN_EVT, ¶m); + break; + case BTA_HH_GET_DSCP_EVT: + len = p_data->dscp_info.descriptor.dl_len; + BTC_TRACE_DEBUG("len = %d", len); + do { + param.dscp.status = ESP_HIDH_OK; + param.dscp.handle = BTA_HH_INVALID_HANDLE; + param.dscp.added = false; + p_dev = btc_hh_cb.p_curr_dev; + if (p_dev == NULL) { + BTC_TRACE_ERROR("No HID device is currently connected"); + param.dscp.status = ESP_HIDH_NO_CONNECTION; + break; + } + + if (btc_hh_add_added_dev(p_dev->bd_addr, p_dev->attr_mask)) { + tBTA_HH_DEV_DSCP_INFO dscp_info; + bt_status_t ret; + btc_hh_copy_hid_info(&dscp_info, &p_data->dscp_info); + btc_hh_cb.add_event = BTC_HH_CONNECT_EVT; + BTA_HhAddDev(p_dev->bd_addr, p_dev->attr_mask, p_dev->sub_class, p_dev->app_id, dscp_info); + // write hid info to nvs + ret = btc_storage_add_hid_device_info((bt_bdaddr_t *)p_dev->bd_addr, p_dev->attr_mask, p_dev->sub_class, p_dev->app_id, + p_data->dscp_info.vendor_id, p_data->dscp_info.product_id, + p_data->dscp_info.version, p_data->dscp_info.ctry_code, + p_data->dscp_info.ssr_max_latency, p_data->dscp_info.ssr_min_tout, + len, p_data->dscp_info.descriptor.dsc_list); + + if (ret != BT_STATUS_SUCCESS) { + BTC_TRACE_ERROR("write hid info to nvs failed!"); + } + // Free buffer created for dscp_info; + if (dscp_info.descriptor.dl_len > 0 && dscp_info.descriptor.dsc_list != NULL) { + utl_freebuf((void **)&dscp_info.descriptor.dsc_list); + dscp_info.descriptor.dl_len = 0; + } + } else { + // Device already added. + BTC_TRACE_WARNING("%s: Device already added ", __func__); + param.dscp.added = true; + } + btc_hh_cb_copy_hid_info(¶m, &p_data->dscp_info); + param.dscp.handle = p_dev->dev_handle; + } while(0); + btc_hh_cb_to_app(ESP_HIDH_GET_DSCP_EVT, ¶m); + if (param.dscp.dl_len > 0 && param.dscp.dsc_list != NULL) { + utl_freebuf((void **)¶m.dscp.dsc_list); + param.dscp.dl_len = 0; + } + break; + case BTA_HH_CLOSE_EVT: + BTC_TRACE_DEBUG("status = %d, handle = %d", p_data->dev_status.status, + p_data->dev_status.handle); + p_dev = btc_hh_find_connected_dev_by_handle(p_data->dev_status.handle); + if (p_dev != NULL) { + BTC_TRACE_DEBUG("uhid local_vup=%d", p_dev->local_vup); + btc_hh_stop_vup_timer(p_dev->bd_addr); + /* If this is a locally initiated VUP, remove the bond as ACL got + * disconnected while VUP being processed. + */ + if (p_dev->local_vup) { + p_dev->local_vup = false; + BTA_DmRemoveDevice(p_dev->bd_addr, BT_TRANSPORT_BR_EDR); + } + + btc_hh_cb.status = (BTC_HH_STATUS)BTC_HH_DEV_DISCONNECTED; + p_dev->dev_status = ESP_HIDH_CONN_STATE_DISCONNECTED; + param.close.status = p_data->dev_status.status; + } else { + BTC_TRACE_ERROR("Error: cannot find device with handle %d", p_data->dev_status.handle); + param.close.status = ESP_HIDH_NO_CONNECTION; + } + param.close.handle = p_data->dev_status.handle; + param.close.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTED; + btc_hh_cb_to_app(ESP_HIDH_CLOSE_EVT, ¶m); + break; + case BTA_HH_VC_UNPLUG_EVT: + BTC_TRACE_DEBUG("status = %d, handle = %d", p_data->dev_status.status, + p_data->dev_status.handle); + p_dev = btc_hh_find_connected_dev_by_handle(p_data->dev_status.handle); + btc_hh_cb.status = (BTC_HH_STATUS)BTC_HH_DEV_DISCONNECTED; + if (p_dev != NULL) { + /* Stop the VUP timer */ + btc_hh_stop_vup_timer(p_dev->bd_addr); + p_dev->dev_status = ESP_HIDH_CONN_STATE_DISCONNECTED; + BTC_TRACE_DEBUG("%s---Sending connection state change", __func__); + param.close.status = ESP_HIDH_OK; + param.close.handle = p_data->dev_status.handle; + param.close.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTED; + btc_hh_cb_to_app(ESP_HIDH_CLOSE_EVT, ¶m); + BTC_TRACE_DEBUG("%s---Removing HID bond", __func__); + /* If it is locally initiated VUP or remote device has its major COD as + Peripheral removed the bond.*/ + // [boblane] + if (p_dev->local_vup) { + p_dev->local_vup = false; + BTA_DmRemoveDevice(p_dev->bd_addr, BT_TRANSPORT_BR_EDR); + } else { + btc_hh_remove_device(p_dev->bd_addr); + } + param.unplug.status = p_data->dev_status.status; + } else { + BTC_TRACE_ERROR("Error: cannot find device with handle %d", p_data->dev_status.handle); + param.unplug.status = ESP_HIDH_NO_CONNECTION; + } + param.unplug.handle = p_data->dev_status.handle; + param.unplug.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTED; + btc_hh_cb_to_app(ESP_HIDH_VC_UNPLUG_EVT, ¶m); + break; + case BTA_HH_DATA_EVT: + BTC_TRACE_DEBUG("status = %d, handle = %d", p_data->send_data.status, + p_data->send_data.handle); + param.send_data.handle = p_data->send_data.handle; + param.send_data.status = p_data->send_data.status; + param.send_data.reason = p_data->send_data.reason; + btc_hh_cb_to_app(ESP_HIDH_DATA_EVT, ¶m); + break; + case BTA_HH_GET_PROTO_EVT: + BTC_TRACE_DEBUG("status = %d, handle = %d, proto = [%d], %s", p_data->hs_data.status, + p_data->hs_data.handle, p_data->hs_data.rsp_data.proto_mode, + (p_data->hs_data.rsp_data.proto_mode == BTA_HH_PROTO_RPT_MODE) + ? "Report Mode" + : (p_data->hs_data.rsp_data.proto_mode == BTA_HH_PROTO_BOOT_MODE) ? "Boot Mode" + : "Unsupported"); + param.get_proto.proto_mode = proto_mode_change_to_upper_layer(p_data->hs_data.rsp_data.proto_mode); + param.get_proto.handle = p_data->hs_data.handle; + param.get_proto.status = p_data->hs_data.status; + btc_hh_cb_to_app(ESP_HIDH_GET_PROTO_EVT, ¶m); + break; + case BTA_HH_SET_PROTO_EVT: + BTIF_TRACE_DEBUG("status = %d, handle = %d", p_data->dev_status.status, + p_data->dev_status.handle); + param.set_proto.handle = p_data->dev_status.handle; + param.set_proto.status = p_data->dev_status.status; + btc_hh_cb_to_app(ESP_HIDH_SET_PROTO_EVT, ¶m); + break; + case BTA_HH_GET_RPT_EVT: { + BT_HDR *hdr = p_data->hs_data.rsp_data.p_rpt_data; + uint8_t *data = NULL; + uint16_t len = 0; + BTC_TRACE_DEBUG("status = %d, handle = %d", p_data->hs_data.status, p_data->hs_data.handle); + /* p_rpt_data is NULL in HANDSHAKE response case */ + if (hdr) { + data = (uint8_t *)(hdr + 1) + hdr->offset; + len = hdr->len; + } + param.get_rpt.handle = p_data->hs_data.handle; + param.get_rpt.status = p_data->hs_data.status; + param.get_rpt.len = len; + param.get_rpt.data = data; + btc_hh_cb_to_app(ESP_HIDH_GET_RPT_EVT, ¶m); + break; + } + case BTA_HH_SET_RPT_EVT: + BTC_TRACE_DEBUG("status = %d, handle = %d", p_data->dev_status.status, + p_data->dev_status.handle); + param.set_rpt.handle = p_data->dev_status.handle; + param.set_rpt.status = p_data->dev_status.status; + btc_hh_cb_to_app(ESP_HIDH_SET_RPT_EVT, ¶m); + break; + case BTA_HH_GET_IDLE_EVT: + BTC_TRACE_DEBUG("handle = %d, status = %d, rate = %d", p_data->hs_data.handle, p_data->hs_data.status, + p_data->hs_data.rsp_data.idle_rate); + param.get_idle.handle = p_data->hs_data.handle; + param.get_idle.status = p_data->hs_data.status; + param.get_idle.idle_rate = p_data->hs_data.rsp_data.idle_rate; + btc_hh_cb_to_app(ESP_HIDH_GET_IDLE_EVT, ¶m); + break; + case BTA_HH_SET_IDLE_EVT: + BTC_TRACE_DEBUG("status = %d, handle = %d", p_data->dev_status.status, p_data->dev_status.handle); + param.set_idle.handle = p_data->dev_status.handle; + param.set_idle.status = p_data->dev_status.status; + btc_hh_cb_to_app(BTA_HH_SET_IDLE_EVT, ¶m); + break; + case BTA_HH_ADD_DEV_EVT: + BTC_TRACE_DEBUG("status = %d, handle = %d", p_data->dev_info.status, p_data->dev_info.handle); + for (uint8_t i = 0; i < BTC_HH_MAX_ADDED_DEV; i++) { + if (memcmp(btc_hh_cb.added_devices[i].bd_addr, p_data->dev_info.bda, BD_ADDR_LEN) == 0) { + if (p_data->dev_info.status == BTA_HH_OK) { + btc_hh_cb.added_devices[i].dev_handle = p_data->dev_info.handle; + } else { + memset(btc_hh_cb.added_devices[i].bd_addr, 0, BD_ADDR_LEN); + btc_hh_cb.added_devices[i].dev_handle = BTA_HH_INVALID_HANDLE; + } + break; + } + } + if (btc_hh_cb.add_event == BTC_HH_SET_INFO_EVT) { + param.set_info.handle = p_data->dev_info.handle; + param.set_info.status = p_data->dev_info.status; + memcpy(param.set_info.bd_addr, p_data->dev_info.bda, BD_ADDR_LEN); + btc_hh_cb_to_app(ESP_HIDH_SET_INFO_EVT, ¶m); + } else { + param.add_dev.handle = p_data->dev_info.handle; + param.add_dev.status = p_data->dev_info.status; + memcpy(param.add_dev.bd_addr, p_data->dev_info.bda, BD_ADDR_LEN); + btc_hh_cb_to_app(ESP_HIDH_ADD_DEV_EVT, ¶m); + } + break; + case BTA_HH_RMV_DEV_EVT: + BTC_TRACE_DEBUG("status = %d, handle = %d", p_data->dev_info.status, p_data->dev_info.handle); + param.rmv_dev.handle = p_data->dev_info.status; + param.rmv_dev.status = p_data->dev_info.handle; + memcpy(param.rmv_dev.bd_addr, p_data->dev_info.bda, BD_ADDR_LEN); + btc_hh_cb_to_app(ESP_HIDH_RMV_DEV_EVT, ¶m); + break; + case BTA_HH_DATA_IND_EVT: + BTC_TRACE_DEBUG("status = %d, handle = %d", p_data->int_data.status, p_data->int_data.handle); + if (p_data->int_data.status == BTA_HH_OK && p_data->int_data.p_data) { + param.data_ind.len = p_data->int_data.p_data->len; + param.data_ind.data = p_data->int_data.p_data->data + p_data->int_data.p_data->offset; + } + param.data_ind.handle = p_data->int_data.handle; + param.data_ind.status = p_data->int_data.status; + param.data_ind.proto_mode = proto_mode_change_to_upper_layer(p_data->int_data.proto_mode); + btc_hh_cb_to_app(ESP_HIDH_DATA_IND_EVT, ¶m); + break; + case BTA_HH_API_ERR_EVT: + break; + default: + BTC_TRACE_WARNING("%s: Unhandled event: %d", __func__, msg->act); + break; + } + btc_hh_cb_arg_deep_free(msg); +} + +void btc_hh_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) +{ + btc_hidh_args_t *dst = (btc_hidh_args_t *)p_dest; + btc_hidh_args_t *src = (btc_hidh_args_t *)p_src; + + switch (msg->act) { + case BTC_HH_SET_INFO_EVT: + dst->set_info.hid_info = (esp_hidh_hid_info_t *)osi_malloc(sizeof(esp_hidh_hid_info_t)); + if (dst->set_info.hid_info) { + memcpy(dst->set_info.hid_info, src->set_info.hid_info, sizeof(esp_hidh_hid_info_t)); + } else { + BTC_TRACE_ERROR("%s %d osi_malloc failed\n", __func__, msg->act); + } + break; + case BTC_HH_SET_REPORT_EVT: + dst->set_report.report = (uint8_t *)osi_malloc(src->set_report.len); + if (dst->set_report.report) { + memcpy(dst->set_report.report, src->set_report.report, src->set_report.len); + } else { + BTC_TRACE_ERROR("%s %d osi_malloc failed\n", __func__, msg->act); + } + break; + case BTC_HH_SEND_DATA_EVT: + dst->send_data.data = (uint8_t *)osi_malloc(src->send_data.len); + if (dst->send_data.data) { + memcpy(dst->send_data.data, src->send_data.data, src->send_data.len); + } else { + BTC_TRACE_ERROR("%s %d osi_malloc failed\n", __func__, msg->act); + } + break; + default: + break; + } +} + +#endif // HID_HOST_INCLUDED == TRUE diff --git a/components/bt/host/bluedroid/btc/profile/std/include/btc_hd.h b/components/bt/host/bluedroid/btc/profile/std/include/btc_hd.h new file mode 100644 index 0000000000..a2b92cf7ff --- /dev/null +++ b/components/bt/host/bluedroid/btc/profile/std/include/btc_hd.h @@ -0,0 +1,103 @@ +/****************************************************************************** + * + * Copyright (C) 2016 The Android Open Source Project + * Copyright (C) 2009-2012 Broadcom Corporation + * Copyright (C) 2019 Blake Felt + * + * 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. + * + ******************************************************************************/ +#ifndef BTC_HD_H +#define BTC_HD_H + +#if BTC_HD_INCLUDED == TRUE + +#include +#include "bta/bta_hd_api.h" +#include "btc/btc_task.h" +#include "esp_hidd_api.h" + +typedef enum { + BTC_HD_INIT_EVT = 0, + BTC_HD_DEINIT_EVT, + BTC_HD_REGISTER_APP_EVT, + BTC_HD_UNREGISTER_APP_EVT, + BTC_HD_CONNECT_EVT, + BTC_HD_DISCONNECT_EVT, + BTC_HD_SEND_REPORT_EVT, + BTC_HD_REPORT_ERROR_EVT, + BTC_HD_UNPLUG_EVT, +} BTC_HD_EVT; + +typedef enum { BTC_HD_DISABLED = 0, BTC_HD_ENABLED, BTC_HD_DISABLING } BTC_HD_STATUS; + +/* BTIF-HD control block */ +typedef struct { + BTC_HD_STATUS status; + bool app_registered; + bool service_dereg_active; + bool forced_disc; + tBTA_HD_APP_INFO app_info; + tBTA_HD_QOS_INFO in_qos; + tBTA_HD_QOS_INFO out_qos; +} btc_hd_cb_t; + +/* btc_hidd_args_t */ +typedef union { + // BTC_HD_CONNECT_EVT + struct connect_arg { + BD_ADDR bd_addr; + } connect; + + // BTC_HD_REGISTER_APP_EVT + struct register_app_arg { + esp_hidd_app_param_t *app_param; + esp_hidd_qos_param_t *in_qos; + esp_hidd_qos_param_t *out_qos; + } register_app; + + // BTC_HD_SEND_REPORT_EVT + struct send_report_arg { + esp_hidd_report_type_t type; + uint8_t id; + uint16_t len; + uint8_t *data; + } send_report; + + // BTC_HD_REPORT_ERROR_EVT + uint8_t error; +} btc_hidd_args_t; + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************************** + * Functions + ******************************************************************************/ +void btc_hd_call_handler(btc_msg_t *msg); + +void btc_hd_cb_handler(btc_msg_t *msg); + +// extern btc_hd_cb_t btc_hd_cb; +// extern void btc_hd_remove_device(bt_bdaddr_t bd_addr); +// extern void btc_hd_service_registration(); + +void btc_hd_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src); + +#ifdef __cplusplus +} +#endif + +#endif /* BTC_HD_INCLUDED == TRUE */ +#endif /* BTC_HD_H */ diff --git a/components/bt/host/bluedroid/btc/profile/std/include/btc_hh.h b/components/bt/host/bluedroid/btc/profile/std/include/btc_hh.h new file mode 100644 index 0000000000..c07636ed1c --- /dev/null +++ b/components/bt/host/bluedroid/btc/profile/std/include/btc_hh.h @@ -0,0 +1,187 @@ +/****************************************************************************** + * + * Copyright (C) 2016 The Android Open Source Project + * Copyright (C) 2009-2012 Broadcom Corporation + * Copyright (C) 2019 Blake Felt + * + * 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. + * + ******************************************************************************/ +#ifndef BTC_HH_H +#define BTC_HH_H + +#include +#include "bta/bta_hh_api.h" +#include "btc/btc_task.h" +#include "osi/alarm.h" +#include "esp_hidh_api.h" + +#define BTC_HH_MAX_HID 8 +#define BTC_HH_MAX_ADDED_DEV 32 + +#define BTC_HH_MAX_KEYSTATES 3 +#define BTC_HH_KEYSTATE_MASK_NUMLOCK 0x01 +#define BTC_HH_KEYSTATE_MASK_CAPSLOCK 0x02 +#define BTC_HH_KEYSTATE_MASK_SCROLLLOCK 0x04 + +#define BTC_HH_MAX_POLLING_ATTEMPTS 10 +#define BTC_HH_POLLING_SLEEP_DURATION_US 5000 + +/******************************************************************************* + * Type definitions and return values + ******************************************************************************/ +typedef enum { + BTC_HH_INIT_EVT = 0, + BTC_HH_CONNECT_EVT, + BTC_HH_DISCONNECT_EVT, + BTC_HH_UNPLUG_EVT, + BTC_HH_SET_INFO_EVT, + BTC_HH_GET_PROTO_EVT, + BTC_HH_SET_PROTO_EVT, + BTC_HH_GET_IDLE_EVT, + BTC_HH_SET_IDLE_EVT, + BTC_HH_GET_REPORT_EVT, + BTC_HH_SET_REPORT_EVT, + BTC_HH_SEND_DATA_EVT, + BTC_HH_DEINIT_EVT, +} BTC_HH_EVT; + +typedef enum { + BTC_HH_DISABLED = 0, + BTC_HH_ENABLED, + BTC_HH_DISABLING, + BTC_HH_DEV_UNKNOWN, + BTC_HH_DEV_CONNECTING, + BTC_HH_DEV_CONNECTED, + BTC_HH_DEV_DISCONNECTED +} BTC_HH_STATUS; + +typedef struct { + esp_hidh_connection_state_t dev_status; + uint8_t dev_handle; + BD_ADDR bd_addr; + uint16_t attr_mask; + uint8_t sub_class; + uint8_t app_id; + bool ready_for_data; + osi_alarm_t *vup_timer; + bool local_vup; // Indicated locally initiated VUP +} btc_hh_device_t; + +/* Control block to maintain properties of devices */ +typedef struct { + uint8_t dev_handle; + BD_ADDR bd_addr; + uint16_t attr_mask; +} btc_hh_added_device_t; + +/** + * BTC-HH control block to maintain added devices and currently + * connected hid devices + */ +typedef struct { + BTC_HH_STATUS status; + btc_hh_device_t devices[BTC_HH_MAX_HID]; + uint32_t device_num; + BTC_HH_EVT add_event; + btc_hh_added_device_t added_devices[BTC_HH_MAX_ADDED_DEV]; + btc_hh_device_t *p_curr_dev; + bool service_dereg_active; + BD_ADDR pending_conn_address; +} btc_hh_cb_t; + +/* btc_spp_args_t */ +typedef union { + // BTC_HH_CONNECT_EVT + struct connect_arg { + BD_ADDR bd_addr; + } connect; + + // BTC_HH_DISCONNECT_EVT + struct disconnect_arg { + BD_ADDR bd_addr; + } disconnect; + + // BTC_HH_UNPLUG_EVT + struct unplug_arg { + BD_ADDR bd_addr; + } unplug; + + // BTC_HH_SET_INFO_EVT + struct set_info_arg { + BD_ADDR bd_addr; + esp_hidh_hid_info_t *hid_info; + } set_info; + + // BTC_HH_GET_PROTO_EVT + struct get_protocol_arg { + BD_ADDR bd_addr; + } get_protocol; + + // BTC_HH_SET_PROTO_EVT + struct set_protocol_arg { + BD_ADDR bd_addr; + esp_hidh_protocol_mode_t protocol_mode; + } set_protocol; + + // BTC_HH_GET_IDLE_EVT + struct get_idle_arg { + BD_ADDR bd_addr; + } get_idle; + + // BTC_HH_SET_IDLE_EVT + struct set_idle_arg { + BD_ADDR bd_addr; + uint16_t idle_time; + } set_idle; + + // BTC_HH_GET_REPORT_EVT + struct get_report_arg { + BD_ADDR bd_addr; + esp_hidh_report_type_t report_type; + uint8_t report_id; + int buffer_size; + } get_report; + + // BTC_HH_SET_REPORT_EVT + struct set_report_arg { + BD_ADDR bd_addr; + esp_hidh_report_type_t report_type; + size_t len; + uint8_t *report; + } set_report; + + // BTC_HH_SEND_DATA_EVT + struct send_data_arg { + BD_ADDR bd_addr; + size_t len; + uint8_t *data; + } send_data; +} btc_hidh_args_t; +/******************************************************************************* + * Variables + ******************************************************************************/ +extern btc_hh_cb_t btc_hh_cb; +/******************************************************************************* + * Functions + ******************************************************************************/ + +void btc_hh_call_handler(btc_msg_t *msg); + +void btc_hh_cb_handler(btc_msg_t *msg); + +void btc_hh_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src); + +bool btc_hh_add_added_dev(BD_ADDR bd_addr, uint16_t attr_mask); + +#endif /* BTC_HH_H */ 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 a8fe25e352..89b80b4be1 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 @@ -546,6 +546,11 @@ static void btc_spp_uninit(void) osi_mutex_unlock(&spp_local_param.spp_slot_mutex); } while(0); + if (spp_local_param.tx_event_group) { + vEventGroupDelete(spp_local_param.tx_event_group); + spp_local_param.tx_event_group = NULL; + } + if (ret != ESP_SPP_SUCCESS) { esp_spp_cb_param_t param; param.uninit.status = ret; diff --git a/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h b/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h index 07663e6da2..5e94a03403 100644 --- a/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h +++ b/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h @@ -67,6 +67,13 @@ #define UC_BT_HFP_CLIENT_ENABLED FALSE #endif +//HID +#ifdef CONFIG_BT_HID_ENABLED +#define UC_BT_HID_ENABLED CONFIG_BT_HID_ENABLED +#else +#define UC_BT_HID_ENABLED FALSE +#endif + //HID HOST(BT) #ifdef CONFIG_BT_HID_HOST_ENABLED #define UC_BT_HID_HOST_ENABLED CONFIG_BT_HID_HOST_ENABLED @@ -74,6 +81,13 @@ #define UC_BT_HID_HOST_ENABLED FALSE #endif +//HID Device(BT) +#ifdef CONFIG_BT_HID_DEVICE_ENABLED +#define UC_BT_HID_DEVICE_ENABLED CONFIG_BT_HID_DEVICE_ENABLED +#else +#define UC_BT_HID_DEVICE_ENABLED FALSE +#endif + //SSP #ifdef CONFIG_BT_SSP_ENABLED #define UC_BT_SSP_ENABLED CONFIG_BT_SSP_ENABLED @@ -148,7 +162,7 @@ #define UC_BT_SMP_SLAVE_CON_PARAMS_UPD_ENABLE FALSE #endif -#if CONFIG_BT_CTRL_ESP32 +#if CONFIG_IDF_TARGET_ESP32 //BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP #ifdef CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP #define UC_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP @@ -170,9 +184,9 @@ #define UC_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD 20 #endif -#endif //CONFIG_BT_CTRL_ESP32 +#endif //CONFIG_IDF_TARGET_ESP32 -#if (CONFIG_BT_CTRL_ESP32C3 || CONFIG_BT_CTRL_ESP32S3) +#if (CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3) //BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP #ifdef CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP #define UC_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP @@ -194,7 +208,7 @@ #define UC_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD 20 #endif -#endif //(CONFIG_BT_CTRL_ESP32C3 || CONFIG_BT_CTRL_ESP32S3) +#endif //(CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3) //BT ACL CONNECTIONS #ifdef CONFIG_BT_ACL_CONNECTIONS @@ -365,10 +379,18 @@ #define UC_BT_LOG_MCA_TRACE_LEVEL UC_TRACE_LEVEL_WARNING #endif -#ifdef CONFIG_BT_LOG_HIDH_TRACE_LEVEL -#define UC_BT_LOG_HIDH_TRACE_LEVEL CONFIG_BT_LOG_HIDH_TRACE_LEVEL +#ifdef CONFIG_BT_LOG_HID_TRACE_LEVEL +#if UC_BT_HID_HOST_ENABLED +#define UC_BT_LOG_HIDH_TRACE_LEVEL CONFIG_BT_LOG_HID_TRACE_LEVEL +#elif UC_BT_HID_DEVICE_ENABLED +#define UC_BT_LOG_HIDD_TRACE_LEVEL CONFIG_BT_LOG_HID_TRACE_LEVEL +#endif #else +#if UC_BT_HID_HOST_ENABLED #define UC_BT_LOG_HIDH_TRACE_LEVEL UC_TRACE_LEVEL_WARNING +#elif UC_BT_HID_DEVICE_ENABLED +#define UC_BT_LOG_HIDD_TRACE_LEVEL UC_TRACE_LEVEL_WARNING +#endif #endif #ifdef CONFIG_BT_LOG_APPL_TRACE_LEVEL diff --git a/components/bt/host/bluedroid/common/include/common/bt_target.h b/components/bt/host/bluedroid/common/include/common/bt_target.h index 341190268e..4afb853e6e 100644 --- a/components/bt/host/bluedroid/common/include/common/bt_target.h +++ b/components/bt/host/bluedroid/common/include/common/bt_target.h @@ -21,6 +21,7 @@ #define BT_TARGET_H #include +#include "soc/soc_caps.h" #ifndef BUILDCFG #define BUILDCFG @@ -129,11 +130,22 @@ #define BT_SSP_INCLUDED TRUE #endif /* UC_BT_SSP_ENABLED */ +#if UC_BT_HID_ENABLED +#define BT_HID_INCLUDED TRUE +#endif /* UC_BT_HID_ENABLED */ + #if UC_BT_HID_HOST_ENABLED #define HID_HOST_INCLUDED TRUE #define BTA_HH_INCLUDED TRUE +#define BTC_HH_INCLUDED TRUE #endif /* UC_BT_HID_HOST_ENABLED */ +#if UC_BT_HID_DEVICE_ENABLED +#define HID_DEV_INCLUDED TRUE +#define BTA_HD_INCLUDED TRUE +#define BTC_HD_INCLUDED TRUE +#endif /* UC_BT_HID_DEVICE_ENABLED */ + #endif /* UC_BT_CLASSIC_ENABLED */ /* This is set to enable use of GAP L2CAP connections. */ @@ -257,6 +269,11 @@ #define BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT UC_BT_BLE_ESTAB_LINK_CONN_TOUT #endif +#ifdef SOC_BLE_DONT_UPDATE_OWN_RPA +#define BLE_UPDATE_BLE_ADDR_TYPE_RPA FALSE +#else +#define BLE_UPDATE_BLE_ADDR_TYPE_RPA TRUE +#endif //------------------Added from bdroid_buildcfg.h--------------------- #ifndef L2CAP_EXTFEA_SUPPORTED_MASK #define L2CAP_EXTFEA_SUPPORTED_MASK (L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE | L2CAP_EXTFEA_NO_CRC | L2CAP_EXTFEA_FIXED_CHNLS) @@ -315,6 +332,14 @@ #define BTC_SPP_INCLUDED FALSE #endif +#ifndef BTC_HH_INCLUDED +#define BTC_HH_INCLUDED FALSE +#endif + +#ifndef BTC_HD_INCLUDED +#define BTC_HD_INCLUDED FALSE +#endif + #ifndef SBC_DEC_INCLUDED #define SBC_DEC_INCLUDED FALSE #endif @@ -344,6 +369,10 @@ #define BTA_PAN_INCLUDED FALSE #endif +#ifndef BTA_HD_INCLUDED +#define BTA_HD_INCLUDED FALSE +#endif + #ifndef BTA_HH_INCLUDED #define BTA_HH_INCLUDED FALSE #endif @@ -1372,7 +1401,11 @@ /* The maximum number of attributes in each record. */ #ifndef SDP_MAX_REC_ATTR +#if defined(HID_DEV_INCLUDED) && (HID_DEV_INCLUDED==TRUE) +#define SDP_MAX_REC_ATTR 25 +#else #define SDP_MAX_REC_ATTR 8 +#endif /* defined(HID_DEV_INCLUDED) && (HID_DEV_INCLUDED==TRUE) */ #endif #ifndef SDP_MAX_PAD_LEN @@ -1839,6 +1872,18 @@ Range: 2 octets ** HID ** ******************************************************************************/ +#ifndef BT_HID_INCLUDED +#define BT_HID_INCLUDED FALSE +#endif + +/* HID Device Role Included */ +#ifndef HID_DEV_INCLUDED +#define HID_DEV_INCLUDED FALSE +#endif + +#ifndef HID_DEV_SUBCLASS +#define HID_DEV_SUBCLASS COD_MINOR_POINTING +#endif #ifndef HID_CONTROL_BUF_SIZE #define HID_CONTROL_BUF_SIZE BT_DEFAULT_BUFFER_SIZE @@ -1848,6 +1893,14 @@ Range: 2 octets #define HID_INTERRUPT_BUF_SIZE BT_DEFAULT_BUFFER_SIZE #endif +#ifndef HID_DEV_MTU_SIZE +#define HID_DEV_MTU_SIZE 64 +#endif + +#ifndef HID_DEV_FLUSH_TO +#define HID_DEV_FLUSH_TO 0xffff +#endif + /************************************************************************* ** Definitions for Both HID-Host & Device */ diff --git a/components/bt/host/bluedroid/common/include/common/bt_trace.h b/components/bt/host/bluedroid/common/include/common/bt_trace.h index 55babed961..a4f1ca749a 100644 --- a/components/bt/host/bluedroid/common/include/common/bt_trace.h +++ b/components/bt/host/bluedroid/common/include/common/bt_trace.h @@ -106,6 +106,7 @@ static inline void trc_dump_buffer(const char *prefix, uint8_t *data, uint16_t l #define BTTRC_ID_STK_CE 51 #define BTTRC_ID_STK_SNEP 52 #define BTTRC_ID_STK_NDEF 53 +#define BTTRC_ID_STK_HIDD 54 /* LayerIDs for BTA */ #define BTTRC_ID_BTA_ACC 55 /* Advanced Camera Client */ @@ -199,6 +200,7 @@ static inline void trc_dump_buffer(const char *prefix, uint8_t *data, uint16_t l #define AVRC_INITIAL_TRACE_LEVEL UC_BT_LOG_AVRC_TRACE_LEVEL #define MCA_INITIAL_TRACE_LEVEL UC_BT_LOG_MCA_TRACE_LEVEL #define HIDH_INITIAL_TRACE_LEVEL UC_BT_LOG_HIDH_TRACE_LEVEL +#define HIDD_INITIAL_TRACE_LEVEL UC_BT_LOG_HIDD_TRACE_LEVEL #define APPL_INITIAL_TRACE_LEVEL UC_BT_LOG_APPL_TRACE_LEVEL #define GATT_INITIAL_TRACE_LEVEL UC_BT_LOG_GATT_TRACE_LEVEL #define SMP_INITIAL_TRACE_LEVEL UC_BT_LOG_SMP_TRACE_LEVEL @@ -258,6 +260,14 @@ static inline void trc_dump_buffer(const char *prefix, uint8_t *data, uint16_t l #define HIDH_TRACE_EVENT(fmt, args...) {if (hh_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(HIDH,EVENT)) BT_PRINT_D("BT_HIDH", fmt, ## args);} #define HIDH_TRACE_DEBUG(fmt, args...) {if (hh_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(HIDH,DEBUG)) BT_PRINT_D("BT_HIDH", fmt, ## args);} +/* define traces for HID Device */ +#define HIDD_TRACE_ERROR(fmt, args...) {if (hd_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(HIDD, ERROR)) BT_PRINT_E("BT_HIDD", fmt, ## args);} +#define HIDD_TRACE_WARNING(fmt, args...) {if (hd_cb.trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(HIDD, WARNING)) BT_PRINT_W("BT_HIDD", fmt, ## args);} +#define HIDD_TRACE_API(fmt, args...) {if (hd_cb.trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(HIDD,API)) BT_PRINT_I("BT_HIDD", fmt, ## args);} +#define HIDD_TRACE_EVENT(fmt, args...) {if (hd_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(HIDD,EVENT)) BT_PRINT_D("BT_HIDD", fmt, ## args);} +#define HIDD_TRACE_DEBUG(fmt, args...) {if (hd_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(HIDD,DEBUG)) BT_PRINT_D("BT_HIDD", fmt, ## args);} +#define HIDD_TRACE_VERBOSE(fmt, args...) {if (hd_cb.trace_level >= BT_TRACE_LEVEL_VERBOSE && BT_LOG_LEVEL_CHECK(HIDD,VERBOSE)) BT_PRINT_D("BT_HIDD", fmt, ## args);} + /* define traces for BNEP */ #define BNEP_TRACE_ERROR(fmt, args...) {if (bnep_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(BNEP, ERROR)) BT_PRINT_E("BT_BNEP", fmt, ## args);} @@ -418,6 +428,14 @@ extern UINT8 btif_trace_level; #define HIDH_TRACE_EVENT(fmt, args...) #define HIDH_TRACE_DEBUG(fmt, args...) +/* define traces for HID Device */ +#define HIDD_TRACE_ERROR(fmt, args...) +#define HIDD_TRACE_WARNING(fmt, args...) +#define HIDD_TRACE_API(fmt, args...) +#define HIDD_TRACE_EVENT(fmt, args...) +#define HIDD_TRACE_DEBUG(fmt, args...) +#define HIDD_TRACE_VERBOSE(fmt, args...) + /* define traces for BNEP */ #define BNEP_TRACE_ERROR(fmt, args...) diff --git a/components/bt/host/bluedroid/main/bte_init.c b/components/bt/host/bluedroid/main/bte_init.c index d2373d10eb..80c4357b6a 100644 --- a/components/bt/host/bluedroid/main/bte_init.c +++ b/components/bt/host/bluedroid/main/bte_init.c @@ -52,6 +52,14 @@ #include "pan_api.h" #endif +#if (defined(HID_HOST_INCLUDED) && HID_HOST_INCLUDED == TRUE) +#include "stack/hidh_api.h" +#endif + +#if (defined(HID_DEV_INCLUDED) && HID_DEV_INCLUDED == TRUE) +#include "stack/hidd_api.h" +#endif + #if (defined(AVRC_INCLUDED) && AVRC_INCLUDED == TRUE) #include "stack/avrc_api.h" #endif @@ -118,6 +126,10 @@ #include "bta_hh_int.h" #endif +#if BTA_HD_INCLUDED==TRUE +#include "bta_hd_int.h" +#endif + #if BTA_JV_INCLUDED==TRUE #include "bta_jv_int.h" #endif @@ -175,6 +187,12 @@ void BTE_DeinitStack(void) bta_gattc_cb_ptr = NULL; } #endif +#if BTA_HD_INCLUDED==TRUE + if (bta_hd_cb_ptr){ + osi_free(bta_hd_cb_ptr); + bta_hd_cb_ptr = NULL; + } +#endif #if BTA_HH_INCLUDED==TRUE if (bta_hh_cb_ptr){ osi_free(bta_hh_cb_ptr); @@ -249,6 +267,14 @@ void BTE_DeinitStack(void) } #endif // BTA_INCLUDED == TRUE +#if (defined(HID_DEV_INCLUDED) && HID_DEV_INCLUDED == TRUE) + HID_DevDeinit(); +#endif + +#if (defined(HID_HOST_INCLUDED) && HID_HOST_INCLUDED == TRUE) + HID_HostDeinit(); +#endif + #if (defined(GAP_INCLUDED) && GAP_INCLUDED == TRUE) GAP_Deinit(); #endif @@ -347,7 +373,15 @@ bt_status_t BTE_InitStack(void) #endif #if (defined(HID_HOST_INCLUDED) && HID_HOST_INCLUDED == TRUE) - HID_HostInit(); + if (HID_HostInit() != HID_SUCCESS) { + goto error_exit; + } +#endif + +#if (defined(HID_DEV_INCLUDED) && HID_DEV_INCLUDED == TRUE) + if (HID_DevInit() != HID_SUCCESS) { + goto error_exit; + } #endif #if (defined(MCA_INCLUDED) && MCA_INCLUDED == TRUE) @@ -434,6 +468,12 @@ bt_status_t BTE_InitStack(void) } memset((void *)bta_hh_cb_ptr, 0, sizeof(tBTA_HH_CB)); #endif +#if BTA_HD_INCLUDED==TRUE + if ((bta_hd_cb_ptr = (tBTA_HD_CB *)osi_malloc(sizeof(tBTA_HD_CB))) == NULL) { + goto error_exit; + } + memset((void *)bta_hd_cb_ptr, 0, sizeof(tBTA_HD_CB)); +#endif #if BTA_HL_INCLUDED==TRUE memset((void *)bta_hl_cb_ptr, 0, sizeof(tBTA_HL_CB)); #endif diff --git a/components/bt/host/bluedroid/stack/btm/btm_ble_5_gap.c b/components/bt/host/bluedroid/stack/btm/btm_ble_5_gap.c index 8a532a2faa..e6df9b0761 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_ble_5_gap.c +++ b/components/bt/host/bluedroid/stack/btm/btm_ble_5_gap.c @@ -110,8 +110,8 @@ static char *btm_ble_hci_status_to_str(tHCI_STATUS status) return "HCI_ERR_INVALID_LMP_PARAM"; case HCI_ERR_UNSPECIFIED: return "HCI_ERR_UNSPECIFIED"; - case HCI_ERR_UNSUPPORTED_LMP_FEATURE: - return "HCI_ERR_UNSUPPORTED_LMP_FEATURE"; + case HCI_ERR_UNSUPPORTED_LMP_PARAMETERS: + return "HCI_ERR_UNSUPPORTED_LMP_PARAMETERS"; case HCI_ERR_ROLE_CHANGE_NOT_ALLOWED: return "HCI_ERR_ROLE_CHANGE_NOT_ALLOWED"; case HCI_ERR_LMP_RESPONSE_TIMEOUT: 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 6d1ba22186..d3928a0132 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_ble_gap.c +++ b/components/bt/host/bluedroid/stack/btm/btm_ble_gap.c @@ -1015,7 +1015,9 @@ uint32_t BTM_BleUpdateOwnType(uint8_t *own_bda_type, tBTM_START_ADV_CMPL_CBACK * } } else if(*own_bda_type == BLE_ADDR_PUBLIC_ID || *own_bda_type == BLE_ADDR_RANDOM_ID) { if((btm_cb.ble_ctr_cb.addr_mgnt_cb.exist_addr_bit & BTM_BLE_GAP_ADDR_BIT_RESOLVABLE) == BTM_BLE_GAP_ADDR_BIT_RESOLVABLE) { +#if (BLE_UPDATE_BLE_ADDR_TYPE_RPA) *own_bda_type = BLE_ADDR_RANDOM; +#endif btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type = BLE_ADDR_RANDOM; memcpy(btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr, btm_cb.ble_ctr_cb.addr_mgnt_cb.resolvale_addr, BD_ADDR_LEN); btsnd_hcic_ble_set_random_addr(btm_cb.ble_ctr_cb.addr_mgnt_cb.resolvale_addr); diff --git a/components/bt/host/bluedroid/stack/btm/btm_sec.c b/components/bt/host/bluedroid/stack/btm/btm_sec.c index 41ae31f3aa..673cdd4b4d 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_sec.c +++ b/components/bt/host/bluedroid/stack/btm/btm_sec.c @@ -240,6 +240,12 @@ BOOLEAN BTM_SecRegister(tBTM_APPL_INFO *p_cb_info) if (memcmp(btm_cb.devcb.id_keys.ir, &temp_value, sizeof(BT_OCTET16)) == 0) { btm_ble_reset_id(); } +#if (!BLE_UPDATE_BLE_ADDR_TYPE_RPA) + BD_ADDR peer_addr = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; + BT_OCTET16 peer_irk = {0x0}; + /* add local irk to controller */ + btsnd_hcic_ble_add_device_resolving_list (0, peer_addr, peer_irk, btm_cb.devcb.id_keys.irk); +#endif } else { BTM_TRACE_WARNING("%s p_cb_info->p_le_callback == NULL\n", __func__); } @@ -2975,6 +2981,7 @@ void btm_sec_rmt_name_request_complete (UINT8 *p_bd_addr, UINT8 *p_bd_name, UINT int i; DEV_CLASS dev_class; UINT8 old_sec_state; + UINT8 res; BTM_TRACE_EVENT ("btm_sec_rmt_name_request_complete\n"); if (((p_bd_addr == NULL) && !BTM_ACL_IS_CONNECTED(btm_cb.connecting_bda)) @@ -3155,9 +3162,12 @@ void btm_sec_rmt_name_request_complete (UINT8 *p_bd_addr, UINT8 *p_bd_name, UINT /* This is required when different entities receive link notification and auth complete */ if (!(p_dev_rec->security_required & BTM_SEC_OUT_AUTHENTICATE)) { if (btm_cb.api.p_auth_complete_callback) { - (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr, - p_dev_rec->dev_class, - p_dev_rec->sec_bd_name, HCI_SUCCESS); + res = (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr, + p_dev_rec->dev_class, + p_dev_rec->sec_bd_name, HCI_SUCCESS); + if (res == BTM_SEC_DEV_REC_REMOVED) { + p_dev_rec = NULL; + } } } @@ -3847,6 +3857,7 @@ static void btm_sec_auth_collision (UINT16 handle) #if (SMP_INCLUDED == TRUE) void btm_sec_auth_complete (UINT16 handle, UINT8 status) { + UINT8 res; UINT8 old_sm4; tBTM_PAIRING_STATE old_state = btm_cb.pairing_state; tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev_by_handle (handle); @@ -3936,9 +3947,12 @@ void btm_sec_auth_complete (UINT16 handle, UINT8 status) if (btm_cb.api.p_auth_complete_callback) { /* report the authentication status */ if (old_state != BTM_PAIR_STATE_IDLE) { - (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr, - p_dev_rec->dev_class, - p_dev_rec->sec_bd_name, status); + res = (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr, + p_dev_rec->dev_class, + p_dev_rec->sec_bd_name, status); + if (res == BTM_SEC_DEV_REC_REMOVED) { + p_dev_rec = NULL; + } } } @@ -4235,6 +4249,7 @@ void btm_sec_connected (UINT8 *bda, UINT16 handle, UINT8 status, UINT8 enc_mode) { tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bda); UINT8 res; + UINT8 sec_dev_rec_status; BOOLEAN is_pairing_device = FALSE; tACL_CONN *p_acl_cb; UINT8 bit_shift = 0; @@ -4373,9 +4388,12 @@ void btm_sec_connected (UINT8 *bda, UINT16 handle, UINT8 status, UINT8 enc_mode) /* We need to notify host that the key is not known any more */ if (btm_cb.api.p_auth_complete_callback) { - (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr, - p_dev_rec->dev_class, - p_dev_rec->sec_bd_name, status); + sec_dev_rec_status = (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr, + p_dev_rec->dev_class, + p_dev_rec->sec_bd_name, status); + if (sec_dev_rec_status == BTM_SEC_DEV_REC_REMOVED) { + p_dev_rec = NULL; + } } } /* @@ -4406,9 +4424,12 @@ void btm_sec_connected (UINT8 *bda, UINT16 handle, UINT8 status, UINT8 enc_mode) /* We need to notify host that the key is not known any more */ if (btm_cb.api.p_auth_complete_callback) { - (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr, - p_dev_rec->dev_class, - p_dev_rec->sec_bd_name, status); + sec_dev_rec_status = (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr, + p_dev_rec->dev_class, + p_dev_rec->sec_bd_name, status); + if (sec_dev_rec_status == BTM_SEC_DEV_REC_REMOVED) { + p_dev_rec = NULL; + } } } @@ -4441,9 +4462,12 @@ void btm_sec_connected (UINT8 *bda, UINT16 handle, UINT8 status, UINT8 enc_mode) } if (btm_cb.api.p_auth_complete_callback) { - (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr, - p_dev_rec->dev_class, - p_dev_rec->sec_bd_name, HCI_SUCCESS); + sec_dev_rec_status = (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr, + p_dev_rec->dev_class, + p_dev_rec->sec_bd_name, HCI_SUCCESS); + if (sec_dev_rec_status == BTM_SEC_DEV_REC_REMOVED) { + p_dev_rec = NULL; + } } btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE); @@ -4662,6 +4686,7 @@ void btm_sec_link_key_notification (UINT8 *p_bda, UINT8 *p_link_key, UINT8 key_t tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (p_bda); BOOLEAN we_are_bonding = FALSE; BOOLEAN ltk_derived_lk = FALSE; + UINT8 res; BTM_TRACE_EVENT ("btm_sec_link_key_notification() BDA:%04x%08x, TYPE: %d\n", (p_bda[0] << 8) + p_bda[1], (p_bda[2] << 24) + (p_bda[3] << 16) + (p_bda[4] << 8) + p_bda[5], @@ -4766,8 +4791,11 @@ void btm_sec_link_key_notification (UINT8 *p_bda, UINT8 *p_link_key, UINT8 key_t /* for derived key, always send authentication callback for BR channel */ || ltk_derived_lk) { if (btm_cb.api.p_auth_complete_callback) { - (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr, p_dev_rec->dev_class, - p_dev_rec->sec_bd_name, HCI_SUCCESS); + res = (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr, p_dev_rec->dev_class, + p_dev_rec->sec_bd_name, HCI_SUCCESS); + if (res == BTM_SEC_DEV_REC_REMOVED) { + p_dev_rec = NULL; + } } } @@ -5754,9 +5782,10 @@ static char *btm_pair_state_descr (tBTM_PAIRING_STATE state) *******************************************************************************/ void btm_sec_dev_rec_cback_event (tBTM_SEC_DEV_REC *p_dev_rec, UINT8 res, BOOLEAN is_le_transport) { - tBTM_SEC_CALLBACK *p_callback = p_dev_rec->p_callback; + tBTM_SEC_CALLBACK *p_callback; - if (p_dev_rec->p_callback) { + if (p_dev_rec && p_dev_rec->p_callback) { + p_callback = p_dev_rec->p_callback; p_dev_rec->p_callback = NULL; #if BLE_INCLUDED == TRUE 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 017eb89223..790806283b 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 @@ -394,9 +394,7 @@ tBTM_STATUS btm_ble_start_inquiry (UINT8 mode, UINT8 duration); void btm_ble_stop_scan(void); void btm_clear_all_pending_le_entry(void); -BOOLEAN btm_ble_send_extended_scan_params(UINT8 scan_type, UINT32 scan_int, - UINT32 scan_win, UINT8 addr_type_own, - UINT8 scan_filter_policy); +BOOLEAN btm_ble_send_extended_scan_params(UINT8 scan_type, UINT32 scan_int, UINT32 scan_win, UINT8 addr_type_own, UINT8 scan_filter_policy); void btm_ble_stop_inquiry(void); void btm_ble_init (void); void btm_ble_free (void); @@ -407,8 +405,7 @@ void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len, BOOLEAN enhanced); void btm_read_ble_local_supported_states_complete(UINT8 *p, UINT16 evt_len); tBTM_BLE_CONN_ST btm_ble_get_conn_st(void); void btm_ble_set_conn_st(tBTM_BLE_CONN_ST new_st); -UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_dst, - tBTM_BLE_ADV_DATA *p_data); +UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_dst, tBTM_BLE_ADV_DATA *p_data); tBTM_STATUS btm_ble_start_adv(void); tBTM_STATUS btm_ble_stop_adv(void); tBTM_STATUS btm_ble_start_scan(void); 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 ade758a81b..d1498a38a2 100644 --- a/components/bt/host/bluedroid/stack/btm/include/btm_int.h +++ b/components/bt/host/bluedroid/stack/btm/include/btm_int.h @@ -961,12 +961,10 @@ extern tBTM_CallbackFunc conn_param_update_cb; typedef UINT8 tBTM_SEC_ACTION; -/* #ifdef __cplusplus extern "C" { #endif -*/ #if BTM_DYNAMIC_MEMORY == FALSE extern tBTM_CB btm_cb; diff --git a/components/bt/host/bluedroid/stack/btu/btu_task.c b/components/bt/host/bluedroid/stack/btu/btu_task.c index e60fcfa43b..83d4219542 100644 --- a/components/bt/host/bluedroid/stack/btu/btu_task.c +++ b/components/bt/host/bluedroid/stack/btu/btu_task.c @@ -54,7 +54,7 @@ #endif #if (defined(HID_HOST_INCLUDED) && HID_HOST_INCLUDED == TRUE ) -#include "hidh_int.h" +#include "hid_int.h" #endif #if (defined(AVDT_INCLUDED) && AVDT_INCLUDED == TRUE) diff --git a/components/bt/host/bluedroid/stack/hid/hidd_api.c b/components/bt/host/bluedroid/stack/hid/hidd_api.c new file mode 100644 index 0000000000..347ef7ebc2 --- /dev/null +++ b/components/bt/host/bluedroid/stack/hid/hidd_api.c @@ -0,0 +1,586 @@ +/****************************************************************************** + * + * Copyright (C) 2016 The Android Open Source Project + * Copyright (C) 2002-2012 Broadcom Corporation + * + * 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. + * + ******************************************************************************/ +/****************************************************************************** + * + * This file contains the HID Device API entry points + * + ******************************************************************************/ +//#include +//#include +//#include +#include "stack/hidd_api.h" +#include "esp_hidd_api.h" +#include "hid_int.h" +#include "osi/allocator.h" +#include "stack/btm_api.h" +#include "stack/btu.h" +#include "stack/hiddefs.h" +#include +#include +#include + +#if (HID_DEV_INCLUDED == TRUE) + +#if HID_DYNAMIC_MEMORY == FALSE +tHID_DEV_CTB hd_cb; +#else +tHID_DEV_CTB *hidd_cb_ptr = NULL; +#endif + +/******************************************************************************* + * + * Function HID_DevInit + * + * Description Initializes control block + * + * Returns tHID_STATUS + * + ******************************************************************************/ +tHID_STATUS HID_DevInit(void) +{ +#if (HID_DYNAMIC_MEMORY) + if (!hidd_cb_ptr) { + hidd_cb_ptr = (tHID_DEV_CTB *)osi_malloc(sizeof(tHID_DEV_CTB)); + if (!hidd_cb_ptr) { + return HID_ERR_NO_RESOURCES; + } + } +#endif /* #if (HID_DYNAMIC_MEMORY) */ + memset(&hd_cb, 0, sizeof(tHID_DEV_CTB)); +#if defined(HIDD_INITIAL_TRACE_LEVEL) + hd_cb.trace_level = HIDD_INITIAL_TRACE_LEVEL; +#else + hd_cb.trace_level = BT_TRACE_LEVEL_NONE; +#endif + return HID_SUCCESS; +} + +/******************************************************************************* + * + * Function HID_DevDeinit + * + * Description Deinitializes control block + * + * Returns void + * + ******************************************************************************/ +void HID_DevDeinit(void) +{ +#if (HID_DYNAMIC_MEMORY) + if (hidd_cb_ptr) { + osi_free(hidd_cb_ptr); + hidd_cb_ptr = NULL; + } +#endif /* #if (HID_DYNAMIC_MEMORY) */ +} + +/******************************************************************************* + * + * Function HID_DevSetTraceLevel + * + * Description This function sets the trace level for HID Dev. If called + * with + * a value of 0xFF, it simply reads the current trace level. + * + * Returns the new (current) trace level + * + ******************************************************************************/ +uint8_t HID_DevSetTraceLevel(uint8_t new_level) +{ + if (new_level != 0xFF) { + hd_cb.trace_level = new_level; + } + + return (hd_cb.trace_level); +} + +/******************************************************************************* + * + * Function HID_DevRegister + * + * Description Registers HID device with lower layers + * + * Returns tHID_STATUS + * + ******************************************************************************/ +tHID_STATUS HID_DevRegister(tHID_DEV_HOST_CALLBACK *host_cback) +{ + tHID_STATUS st; + HIDD_TRACE_API("%s", __func__); + + if (hd_cb.reg_flag) { + return HID_ERR_ALREADY_REGISTERED; + } + + if (host_cback == NULL) { + return HID_ERR_INVALID_PARAM; + } + /* Register with L2CAP */ + if ((st = hidd_conn_reg()) != HID_SUCCESS) { + return st; + } + + hd_cb.callback = host_cback; + hd_cb.reg_flag = TRUE; + + if (hd_cb.pending_data) { + osi_free(hd_cb.pending_data); + hd_cb.pending_data = NULL; + } + return (HID_SUCCESS); +} + +/******************************************************************************* + * + * Function HID_DevDeregister + * + * Description Deregisters HID device with lower layers + * + * Returns tHID_STATUS + * + ******************************************************************************/ +tHID_STATUS HID_DevDeregister(void) +{ + HIDD_TRACE_API("%s", __func__); + + if (!hd_cb.reg_flag) + return (HID_ERR_NOT_REGISTERED); + hidd_conn_dereg(); + hd_cb.reg_flag = FALSE; + + return (HID_SUCCESS); +} + +tHID_STATUS HID_DevSetSecurityLevel(uint8_t sec_lvl) +{ + HIDD_TRACE_API("%s", __func__); + if (!BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_HIDD_SEC_CTRL, sec_lvl, HID_PSM_CONTROL, BTM_SEC_PROTO_HID, + HIDD_SEC_CHN)) { + HIDD_TRACE_ERROR("Security Registration 1 failed"); + return (HID_ERR_NO_RESOURCES); + } + if (!BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_HIDD_SEC_CTRL, sec_lvl, HID_PSM_CONTROL, BTM_SEC_PROTO_HID, + HIDD_SEC_CHN)) { + HIDD_TRACE_ERROR("Security Registration 2 failed"); + return (HID_ERR_NO_RESOURCES); + } + if (!BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_HIDD_NOSEC_CTRL, BTM_SEC_NONE, HID_PSM_CONTROL, + BTM_SEC_PROTO_HID, HIDD_NOSEC_CHN)) { + HIDD_TRACE_ERROR("Security Registration 3 failed"); + return (HID_ERR_NO_RESOURCES); + } + if (!BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_HIDD_NOSEC_CTRL, BTM_SEC_NONE, HID_PSM_CONTROL, + BTM_SEC_PROTO_HID, HIDD_NOSEC_CHN)) { + HIDD_TRACE_ERROR("Security Registration 4 failed"); + return (HID_ERR_NO_RESOURCES); + } + if (!BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_HIDD_INTR, BTM_SEC_NONE, HID_PSM_INTERRUPT, BTM_SEC_PROTO_HID, + 0)) { + HIDD_TRACE_ERROR("Security Registration 5 failed"); + return (HID_ERR_NO_RESOURCES); + } + if (!BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_HIDD_INTR, BTM_SEC_NONE, HID_PSM_INTERRUPT, BTM_SEC_PROTO_HID, + 0)) { + HIDD_TRACE_ERROR("Security Registration 6 failed"); + return (HID_ERR_NO_RESOURCES); + } + return (HID_SUCCESS); +} + +/******************************************************************************* + * + * Function HID_DevAddRecord + * + * Description Creates SDP record for HID device + * + * Returns tHID_STATUS + * + ******************************************************************************/ +tHID_STATUS HID_DevAddRecord(uint32_t handle, char *p_name, char *p_description, char *p_provider, uint16_t subclass, + uint16_t desc_len, uint8_t *p_desc_data) +{ + bool result = TRUE; + + HIDD_TRACE_API("%s", __func__); + + // Service Class ID List + if (result) { + uint16_t uuid = UUID_SERVCLASS_HUMAN_INTERFACE; + result &= SDP_AddServiceClassIdList(handle, 1, &uuid); + } + // Protocol Descriptor List + if (result) { + tSDP_PROTOCOL_ELEM proto_list[2]; + proto_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP; + proto_list[0].num_params = 1; + proto_list[0].params[0] = BT_PSM_HIDC; + proto_list[1].protocol_uuid = UUID_PROTOCOL_HIDP; + proto_list[1].num_params = 0; + result &= SDP_AddProtocolList(handle, 2, proto_list); + } + // Language Base Attribute ID List + if (result) { + result &= + SDP_AddLanguageBaseAttrIDList(handle, LANG_ID_CODE_ENGLISH, LANG_ID_CHAR_ENCODE_UTF8, LANGUAGE_BASE_ID); + } + // Additional Protocol Descriptor List + if (result) { + tSDP_PROTO_LIST_ELEM add_proto_list; + add_proto_list.num_elems = 2; + add_proto_list.list_elem[0].protocol_uuid = UUID_PROTOCOL_L2CAP; + add_proto_list.list_elem[0].num_params = 1; + add_proto_list.list_elem[0].params[0] = BT_PSM_HIDI; + add_proto_list.list_elem[1].protocol_uuid = UUID_PROTOCOL_HIDP; + add_proto_list.list_elem[1].num_params = 0; + result &= SDP_AddAdditionProtoLists(handle, 1, &add_proto_list); + } + // Service Name (O) + // Service Description (O) + // Provider Name (O) + if (result) { + const char *srv_name = p_name; + const char *srv_desc = p_description; + const char *provider_name = p_provider; + result &= SDP_AddAttribute(handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE, strlen(srv_name) + 1, + (uint8_t *)srv_name); + result &= SDP_AddAttribute(handle, ATTR_ID_SERVICE_DESCRIPTION, TEXT_STR_DESC_TYPE, strlen(srv_desc) + 1, + (uint8_t *)srv_desc); + result &= SDP_AddAttribute(handle, ATTR_ID_PROVIDER_NAME, TEXT_STR_DESC_TYPE, strlen(provider_name) + 1, + (uint8_t *)provider_name); + } + // Bluetooth Profile Descriptor List + if (result) { + const uint16_t profile_uuid = UUID_SERVCLASS_HUMAN_INTERFACE; + const uint16_t version = 0x0100; + result &= SDP_AddProfileDescriptorList(handle, profile_uuid, version); + } + // HID Parser Version + if (result) { + uint8_t *p; + const uint16_t rel_num = 0x0100; + const uint16_t parser_version = 0x0111; + const uint16_t prof_ver = 0x0100; + const uint8_t dev_subclass = subclass; + const uint8_t country_code = 0x21; + const uint8_t bool_false = 0x00; + const uint8_t bool_true = 0x01; + uint16_t temp; + p = (uint8_t *)&temp; + UINT16_TO_BE_STREAM(p, rel_num); + result &= SDP_AddAttribute(handle, ATTR_ID_HID_DEVICE_RELNUM, UINT_DESC_TYPE, 2, (uint8_t *)&temp); + p = (uint8_t *)&temp; + UINT16_TO_BE_STREAM(p, parser_version); + result &= SDP_AddAttribute(handle, ATTR_ID_HID_PARSER_VERSION, UINT_DESC_TYPE, 2, (uint8_t *)&temp); + result &= SDP_AddAttribute(handle, ATTR_ID_HID_DEVICE_SUBCLASS, UINT_DESC_TYPE, 1, (uint8_t *)&dev_subclass); + result &= SDP_AddAttribute(handle, ATTR_ID_HID_COUNTRY_CODE, UINT_DESC_TYPE, 1, (uint8_t *)&country_code); + result &= SDP_AddAttribute(handle, ATTR_ID_HID_VIRTUAL_CABLE, BOOLEAN_DESC_TYPE, 1, (uint8_t *)&bool_true); + result &= SDP_AddAttribute(handle, ATTR_ID_HID_RECONNECT_INITIATE, BOOLEAN_DESC_TYPE, 1, (uint8_t *)&bool_true); + { + static uint8_t cdt = 0x22; + uint8_t *p_buf; + uint8_t seq_len = 4 + desc_len; + p_buf = (uint8_t *)osi_malloc(2048); + if (p_buf == NULL) { + HIDD_TRACE_ERROR("%s: Buffer allocation failure for size = 2048 ", __func__); + return HID_ERR_NOT_REGISTERED; + } + p = p_buf; + UINT8_TO_BE_STREAM(p, (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE); + UINT8_TO_BE_STREAM(p, seq_len); + UINT8_TO_BE_STREAM(p, (UINT_DESC_TYPE << 3) | SIZE_ONE_BYTE); + UINT8_TO_BE_STREAM(p, cdt); + UINT8_TO_BE_STREAM(p, (TEXT_STR_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE); + UINT8_TO_BE_STREAM(p, desc_len); + ARRAY_TO_BE_STREAM(p, p_desc_data, (int)desc_len); + result &= SDP_AddAttribute(handle, ATTR_ID_HID_DESCRIPTOR_LIST, DATA_ELE_SEQ_DESC_TYPE, p - p_buf, p_buf); + osi_free(p_buf); + } + { + uint8_t lang_buf[8]; + p = lang_buf; + uint8_t seq_len = 6; + uint16_t lang_english = 0x0409; + UINT8_TO_BE_STREAM(p, (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE); + UINT8_TO_BE_STREAM(p, seq_len); + UINT8_TO_BE_STREAM(p, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES); + UINT16_TO_BE_STREAM(p, lang_english); + UINT8_TO_BE_STREAM(p, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES); + UINT16_TO_BE_STREAM(p, LANGUAGE_BASE_ID); + result &= + SDP_AddAttribute(handle, ATTR_ID_HID_LANGUAGE_ID_BASE, DATA_ELE_SEQ_DESC_TYPE, p - lang_buf, lang_buf); + } + result &= SDP_AddAttribute(handle, ATTR_ID_HID_BATTERY_POWER, BOOLEAN_DESC_TYPE, 1, (uint8_t *)&bool_true); + result &= SDP_AddAttribute(handle, ATTR_ID_HID_REMOTE_WAKE, BOOLEAN_DESC_TYPE, 1, (uint8_t *)&bool_false); + result &= + SDP_AddAttribute(handle, ATTR_ID_HID_NORMALLY_CONNECTABLE, BOOLEAN_DESC_TYPE, 1, (uint8_t *)&bool_true); + result &= SDP_AddAttribute(handle, ATTR_ID_HID_BOOT_DEVICE, BOOLEAN_DESC_TYPE, 1, (uint8_t *)&bool_true); + p = (uint8_t *)&temp; + UINT16_TO_BE_STREAM(p, prof_ver); + result &= SDP_AddAttribute(handle, ATTR_ID_HID_PROFILE_VERSION, UINT_DESC_TYPE, 2, (uint8_t *)&temp); + } + if (result) { + uint16_t browse_group = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; + result &= SDP_AddUuidSequence(handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse_group); + } + if (!result) { + HIDD_TRACE_ERROR("%s: failed to complete SDP record", __func__); + return HID_ERR_NOT_REGISTERED; + } + return HID_SUCCESS; +} + +/******************************************************************************* + * + * Function HID_DevSendReport + * + * Description Sends report + * + * Returns tHID_STATUS + * + ******************************************************************************/ +tHID_STATUS HID_DevSendReport(uint8_t channel, uint8_t type, uint8_t id, uint16_t len, uint8_t *p_data) +{ + HIDD_TRACE_VERBOSE("%s: channel=%d type=%d id=%d len=%d", __func__, channel, type, id, len); + + if (channel == HID_CHANNEL_CTRL) { + return hidd_conn_send_data(HID_CHANNEL_CTRL, HID_TRANS_DATA, type, id, len, p_data); + } + + if (channel == HID_CHANNEL_INTR && type == HID_PAR_REP_TYPE_INPUT) { + // on INTR we can only send INPUT + return hidd_conn_send_data(HID_CHANNEL_INTR, HID_TRANS_DATA, HID_PAR_REP_TYPE_INPUT, id, len, p_data); + } + + return HID_ERR_INVALID_PARAM; +} + +/******************************************************************************* + * + * Function HID_DevVirtualCableUnplug + * + * Description Sends Virtual Cable Unplug + * + * Returns tHID_STATUS + * + ******************************************************************************/ +tHID_STATUS HID_DevVirtualCableUnplug(void) +{ + HIDD_TRACE_API("%s", __func__); + + return hidd_conn_send_data(HID_CHANNEL_CTRL, HID_TRANS_CONTROL, HID_PAR_CONTROL_VIRTUAL_CABLE_UNPLUG, 0, 0, NULL); +} + +/******************************************************************************* + * + * Function HID_DevPlugDevice + * + * Description Establishes virtual cable to given host + * + * Returns tHID_STATUS + * + ******************************************************************************/ +tHID_STATUS HID_DevPlugDevice(BD_ADDR addr) +{ + hd_cb.device.in_use = TRUE; + memcpy(hd_cb.device.addr, addr, sizeof(BD_ADDR)); + + return HID_SUCCESS; +} + +/******************************************************************************* + * + * Function HID_DevUnplugDevice + * + * Description Unplugs virtual cable from given host + * + * Returns tHID_STATUS + * + ******************************************************************************/ +tHID_STATUS HID_DevUnplugDevice(BD_ADDR addr) +{ + if (!memcmp(hd_cb.device.addr, addr, sizeof(BD_ADDR))) { + hd_cb.device.in_use = FALSE; + hd_cb.device.conn.conn_state = HID_CONN_STATE_UNUSED; + hd_cb.device.conn.ctrl_cid = 0; + hd_cb.device.conn.intr_cid = 0; + } + return HID_SUCCESS; +} + +/******************************************************************************* + * + * Function HID_DevConnect + * + * Description Connects to device + * + * Returns tHID_STATUS + * + ******************************************************************************/ +tHID_STATUS HID_DevConnect(void) +{ + if (!hd_cb.reg_flag) { + return HID_ERR_NOT_REGISTERED; + } + if (!hd_cb.device.in_use) { + return HID_ERR_INVALID_PARAM; + } + if (hd_cb.device.state != HIDD_DEV_NO_CONN) { + return HID_ERR_ALREADY_CONN; + } + return hidd_conn_initiate(); +} + +/******************************************************************************* + * + * Function HID_DevDisconnect + * + * Description Disconnects from device + * + * Returns tHID_STATUS + * + ******************************************************************************/ +tHID_STATUS HID_DevDisconnect(void) +{ + if (!hd_cb.reg_flag) { + return HID_ERR_NOT_REGISTERED; + } + if (!hd_cb.device.in_use) { + return HID_ERR_INVALID_PARAM; + } + if (hd_cb.device.state == HIDD_DEV_NO_CONN) { + return HID_ERR_NO_CONNECTION; + } + return hidd_conn_disconnect(); +} + +/******************************************************************************* + * + * Function HID_DevSetIncomingPolicy + * + * Description Sets policy for incoming connections (allowed/disallowed) + * + * Returns tHID_STATUS + * + ******************************************************************************/ +tHID_STATUS HID_DevSetIncomingPolicy(bool allow) +{ + hd_cb.allow_incoming = allow; + return HID_SUCCESS; +} + +/******************************************************************************* + * + * Function HID_DevReportError + * + * Description Reports error for Set Report via HANDSHAKE + * + * Returns tHID_STATUS + * + ******************************************************************************/ +tHID_STATUS HID_DevReportError(uint8_t error) +{ + uint8_t handshake_param; + + HIDD_TRACE_API("%s: error = %d", __func__, error); + + switch (error) { + case HID_PAR_HANDSHAKE_RSP_SUCCESS: + case HID_PAR_HANDSHAKE_RSP_NOT_READY: + case HID_PAR_HANDSHAKE_RSP_ERR_INVALID_REP_ID: + case HID_PAR_HANDSHAKE_RSP_ERR_UNSUPPORTED_REQ: + case HID_PAR_HANDSHAKE_RSP_ERR_INVALID_PARAM: + case HID_PAR_HANDSHAKE_RSP_ERR_UNKNOWN: + case HID_PAR_HANDSHAKE_RSP_ERR_FATAL: + handshake_param = error; + break; + default: + handshake_param = HID_PAR_HANDSHAKE_RSP_ERR_UNKNOWN; + break; + } + + return hidd_conn_send_data(0, HID_TRANS_HANDSHAKE, handshake_param, 0, 0, NULL); +} + +/******************************************************************************* + * + * Function HID_DevGetDevice + * + * Description Returns the BD Address of virtually cabled device + * + * Returns tHID_STATUS + * + ******************************************************************************/ +tHID_STATUS HID_DevGetDevice(BD_ADDR *addr) +{ + HIDD_TRACE_API("%s", __func__); + + if (hd_cb.device.in_use) { + memcpy(addr, hd_cb.device.addr, sizeof(BD_ADDR)); + } else { + return HID_ERR_NOT_REGISTERED; + } + + return HID_SUCCESS; +} + +/******************************************************************************* + * + * Function HID_DevSetIncomingQos + * + * Description Sets Incoming QoS values for Interrupt L2CAP Channel + * + * Returns tHID_STATUS + * + ******************************************************************************/ +tHID_STATUS HID_DevSetIncomingQos(uint8_t service_type, uint32_t token_rate, uint32_t token_bucket_size, + uint32_t peak_bandwidth, uint32_t latency, uint32_t delay_variation) +{ + HIDD_TRACE_API("%s", __func__); + hd_cb.use_in_qos = TRUE; + hd_cb.in_qos.service_type = service_type; + hd_cb.in_qos.token_rate = token_rate; + hd_cb.in_qos.token_bucket_size = token_bucket_size; + hd_cb.in_qos.peak_bandwidth = peak_bandwidth; + hd_cb.in_qos.latency = latency; + hd_cb.in_qos.delay_variation = delay_variation; + return HID_SUCCESS; +} +/******************************************************************************* + * + * Function HID_DevSetOutgoingQos + * + * Description Sets Outgoing QoS values for Interrupt L2CAP Channel + * + * Returns tHID_STATUS + * + ******************************************************************************/ +tHID_STATUS HID_DevSetOutgoingQos(uint8_t service_type, uint32_t token_rate, uint32_t token_bucket_size, + uint32_t peak_bandwidth, uint32_t latency, uint32_t delay_variation) +{ + HIDD_TRACE_API("%s", __func__); + hd_cb.l2cap_intr_cfg.qos_present = TRUE; + hd_cb.l2cap_intr_cfg.qos.service_type = service_type; + hd_cb.l2cap_intr_cfg.qos.token_rate = token_rate; + hd_cb.l2cap_intr_cfg.qos.token_bucket_size = token_bucket_size; + hd_cb.l2cap_intr_cfg.qos.peak_bandwidth = peak_bandwidth; + hd_cb.l2cap_intr_cfg.qos.latency = latency; + hd_cb.l2cap_intr_cfg.qos.delay_variation = delay_variation; + return HID_SUCCESS; +} +#endif diff --git a/components/bt/host/bluedroid/stack/hid/hidd_conn.c b/components/bt/host/bluedroid/stack/hid/hidd_conn.c new file mode 100644 index 0000000000..05a14799e0 --- /dev/null +++ b/components/bt/host/bluedroid/stack/hid/hidd_conn.c @@ -0,0 +1,780 @@ +/****************************************************************************** + * + * Copyright (C) 2016 The Android Open Source Project + * Copyright (C) 2002-2012 Broadcom Corporation + * + * 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. + * + ******************************************************************************/ +/****************************************************************************** + * + * this file contains the connection interface functions + * + ******************************************************************************/ +#include "btm_int.h" +#include "hid_conn.h" +#include "hid_int.h" +#include "osi/allocator.h" +#include "osi/osi.h" +#include "stack/btm_api.h" +#include "stack/btu.h" +#include "stack/hidd_api.h" +#include "stack/hiddefs.h" +#include "stack/l2c_api.h" +#include "stack/l2cdefs.h" +#include +#include +#include + +#if (HID_DEV_INCLUDED == TRUE) + +static void hidd_l2cif_connect_ind(BD_ADDR bd_addr, uint16_t cid, uint16_t psm, uint8_t id); +static void hidd_l2cif_connect_cfm(uint16_t cid, uint16_t result); +static void hidd_l2cif_config_ind(uint16_t cid, tL2CAP_CFG_INFO *p_cfg); +static void hidd_l2cif_config_cfm(uint16_t cid, tL2CAP_CFG_INFO *p_cfg); +static void hidd_l2cif_disconnect_ind(uint16_t cid, bool ack_needed); +static void hidd_l2cif_disconnect_cfm(uint16_t cid, uint16_t result); +static void hidd_l2cif_data_ind(uint16_t cid, BT_HDR *p_msg); +static void hidd_l2cif_cong_ind(uint16_t cid, bool congested); + +static const tL2CAP_APPL_INFO dev_reg_info = {hidd_l2cif_connect_ind, + hidd_l2cif_connect_cfm, + NULL, + hidd_l2cif_config_ind, + hidd_l2cif_config_cfm, + hidd_l2cif_disconnect_ind, + hidd_l2cif_disconnect_cfm, + NULL, + hidd_l2cif_data_ind, + hidd_l2cif_cong_ind, + NULL}; +/******************************************************************************* + * + * Function hidd_check_config_done + * + * Description Checks if connection is configured and callback can be fired + * + * Returns void + * + ******************************************************************************/ +static void hidd_check_config_done(void) +{ + tHID_CONN *p_hcon; + p_hcon = &hd_cb.device.conn; + if (((p_hcon->conn_flags & HID_CONN_FLAGS_ALL_CONFIGURED) == HID_CONN_FLAGS_ALL_CONFIGURED) && + (p_hcon->conn_state == HID_CONN_STATE_CONFIG)) { + p_hcon->conn_state = HID_CONN_STATE_CONNECTED; + hd_cb.device.state = HIDD_DEV_CONNECTED; + hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_OPEN, 0, NULL); + // send outstanding data on intr + if (hd_cb.pending_data) { + L2CA_DataWrite(p_hcon->intr_cid, hd_cb.pending_data); + hd_cb.pending_data = NULL; + } + } +} +/******************************************************************************* + * + * Function hidh_sec_check_complete_term + * + * Description HID security check complete callback function. + * + * Returns Send L2CA_ConnectRsp OK if secutiry check succeed; otherwise + * send security block L2C connection response. + * + ******************************************************************************/ +static void hidd_sec_check_complete(UNUSED_ATTR BD_ADDR bd_addr, UNUSED_ATTR tBT_TRANSPORT transport, void *p_ref_data, + uint8_t res) +{ + tHID_DEV_DEV_CTB *p_dev = (tHID_DEV_DEV_CTB *)p_ref_data; + if (res == BTM_SUCCESS && p_dev->conn.conn_state == HID_CONN_STATE_SECURITY) { + p_dev->conn.disc_reason = HID_SUCCESS; + p_dev->conn.conn_state = HID_CONN_STATE_CONNECTING_INTR; + L2CA_ConnectRsp(p_dev->addr, p_dev->conn.ctrl_id, p_dev->conn.ctrl_cid, L2CAP_CONN_OK, L2CAP_CONN_OK); + L2CA_ConfigReq(p_dev->conn.ctrl_cid, &hd_cb.l2cap_cfg); + } else if (res != BTM_SUCCESS) { + HIDD_TRACE_WARNING("%s: connection rejected by security", __func__); + p_dev->conn.disc_reason = HID_ERR_AUTH_FAILED; + p_dev->conn.conn_state = HID_CONN_STATE_UNUSED; + L2CA_ConnectRsp(p_dev->addr, p_dev->conn.ctrl_id, p_dev->conn.ctrl_cid, L2CAP_CONN_SECURITY_BLOCK, + L2CAP_CONN_OK); + return; + } +} +/******************************************************************************* + * + * Function hidd_sec_check_complete_orig + * + * Description HID security check complete callback function (device + *originated) + * + * Returns void + * + ******************************************************************************/ +void hidd_sec_check_complete_orig(UNUSED_ATTR BD_ADDR bd_addr, UNUSED_ATTR tBT_TRANSPORT transport, void *p_ref_data, + uint8_t res) +{ + tHID_DEV_DEV_CTB *p_dev = (tHID_DEV_DEV_CTB *)p_ref_data; + if (p_dev->conn.conn_state != HID_CONN_STATE_SECURITY) { + HIDD_TRACE_WARNING("%s: invalid state (%02x)", __func__, p_dev->conn.conn_state); + return; + } + if (res == BTM_SUCCESS) { + HIDD_TRACE_EVENT("%s: security ok", __func__); + p_dev->conn.disc_reason = HID_SUCCESS; + p_dev->conn.conn_state = HID_CONN_STATE_CONFIG; + L2CA_ConfigReq(p_dev->conn.ctrl_cid, &hd_cb.l2cap_cfg); + } else { + HIDD_TRACE_WARNING("%s: security check failed (%02x)", __func__, res); + p_dev->conn.disc_reason = HID_ERR_AUTH_FAILED; + hidd_conn_disconnect(); + } +} +/******************************************************************************* + * + * Function hidd_l2cif_connect_ind + * + * Description Handles incoming L2CAP connection (we act as server) + * + * Returns void + * + ******************************************************************************/ +static void hidd_l2cif_connect_ind(BD_ADDR bd_addr, uint16_t cid, uint16_t psm, uint8_t id) +{ + tHID_CONN *p_hcon; + tHID_DEV_DEV_CTB *p_dev; + bool accept = TRUE; // accept by default + HIDD_TRACE_EVENT("%s: psm=%04x cid=%04x id=%02x", __func__, psm, cid, id); + p_dev = &hd_cb.device; + if (!hd_cb.allow_incoming) { + HIDD_TRACE_WARNING("%s: incoming connections not allowed, rejecting", __func__); + L2CA_ConnectRsp(bd_addr, id, cid, L2CAP_CONN_NO_RESOURCES, 0); + return; + } + if (p_dev->in_use && memcmp(bd_addr, p_dev->addr, sizeof(BD_ADDR))) { + HIDD_TRACE_WARNING("%s: incoming connections from different device, rejecting", __func__); + L2CA_ConnectRsp(bd_addr, id, cid, L2CAP_CONN_NO_RESOURCES, 0); + return; + } else if (!p_dev->in_use) { + p_dev->in_use = TRUE; + memcpy(p_dev->addr, bd_addr, sizeof(BD_ADDR)); + p_dev->state = HIDD_DEV_NO_CONN; + } + p_hcon = &hd_cb.device.conn; + switch (psm) { + case HID_PSM_INTERRUPT: + if (p_hcon->ctrl_cid == 0) { + accept = FALSE; + HIDD_TRACE_WARNING("%s: incoming INTR without CTRL, rejecting", __func__); + } + if (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR) { + accept = FALSE; + HIDD_TRACE_WARNING("%s: incoming INTR in invalid state (%d), rejecting", __func__, p_hcon->conn_state); + } + break; + case HID_PSM_CONTROL: + if (p_hcon->conn_state != HID_CONN_STATE_UNUSED) { + accept = FALSE; + HIDD_TRACE_WARNING("%s: incoming CTRL in invalid state (%d), rejecting", __func__, p_hcon->conn_state); + } + break; + default: + accept = FALSE; + HIDD_TRACE_ERROR("%s: received invalid PSM, rejecting", __func__); + break; + } + if (!accept) { + L2CA_ConnectRsp(bd_addr, id, cid, L2CAP_CONN_NO_RESOURCES, 0); + return; + } + // for CTRL we need to go through security and we reply in callback from there + if (psm == HID_PSM_CONTROL) { + p_hcon->conn_flags = 0; + p_hcon->ctrl_cid = cid; + p_hcon->ctrl_id = id; + p_hcon->disc_reason = HID_L2CAP_CONN_FAIL; + p_hcon->conn_state = HID_CONN_STATE_SECURITY; + if (btm_sec_mx_access_request(p_dev->addr, HID_PSM_CONTROL, FALSE, BTM_SEC_PROTO_HID, HIDD_NOSEC_CHN, + &hidd_sec_check_complete, p_dev) == BTM_CMD_STARTED) { + L2CA_ConnectRsp(bd_addr, id, cid, L2CAP_CONN_PENDING, L2CAP_CONN_OK); + } + return; + } + // for INTR we go directly to config state + p_hcon->conn_state = HID_CONN_STATE_CONFIG; + p_hcon->intr_cid = cid; + L2CA_ConnectRsp(bd_addr, id, cid, L2CAP_CONN_OK, L2CAP_CONN_OK); + L2CA_ConfigReq(cid, &hd_cb.l2cap_intr_cfg); +} +/******************************************************************************* + * + * Function hidd_l2cif_connect_cfm + * + * Description Handles L2CAP connection response (we act as client) + * + * Returns void + * + ******************************************************************************/ +static void hidd_l2cif_connect_cfm(uint16_t cid, uint16_t result) +{ + tHID_DEV_DEV_CTB *p_dev = &hd_cb.device; + tHID_CONN *p_hcon = &hd_cb.device.conn; + HIDD_TRACE_EVENT("%s: cid=%04x result=%d, conn_state=%d", __func__, cid, result, p_hcon->conn_state); + if (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid) { + HIDD_TRACE_WARNING("%s: unknown cid", __func__); + return; + } + if (!(p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) || + ((cid == p_hcon->ctrl_cid) && (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_CTRL && (p_hcon->conn_state != HID_CONN_STATE_DISCONNECTING_INTR))) || + ((cid == p_hcon->intr_cid) && (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR) && (p_hcon->conn_state != HID_CONN_STATE_DISCONNECTING_CTRL))) { + HIDD_TRACE_WARNING("%s: unexpected, cid:0x%04x, ctrl_cid:0x%04x, intr_cid:0x%04x, conn_state:%d", __func__, cid, + p_hcon->ctrl_cid, p_hcon->intr_cid, p_hcon->conn_state); + return; + } + if (result != L2CAP_CONN_OK) { + HIDD_TRACE_WARNING("%s: connection failed, now disconnect", __func__); + if (cid == p_hcon->ctrl_cid) + p_hcon->ctrl_cid = 0; + else + p_hcon->intr_cid = 0; + hidd_conn_disconnect(); + hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, HID_L2CAP_CONN_FAIL | (uint32_t)result, NULL); + return; + } + /* CTRL connect conf */ + if (cid == p_hcon->ctrl_cid) { + p_hcon->conn_state = HID_CONN_STATE_SECURITY; + p_hcon->disc_reason = HID_L2CAP_CONN_FAIL; /* in case disconnected before sec completed */ + btm_sec_mx_access_request(p_dev->addr, HID_PSM_CONTROL, TRUE, BTM_SEC_PROTO_HID, HIDD_SEC_CHN, + &hidd_sec_check_complete_orig, p_dev); + } else { + p_hcon->conn_state = HID_CONN_STATE_CONFIG; + L2CA_ConfigReq(cid, &hd_cb.l2cap_intr_cfg); + } + return; +} +/******************************************************************************* + * + * Function hidd_l2cif_config_ind + * + * Description Handles incoming L2CAP configuration request + * + * Returns void + * + ******************************************************************************/ +static void hidd_l2cif_config_ind(uint16_t cid, tL2CAP_CFG_INFO *p_cfg) +{ + tHID_CONN *p_hcon; + HIDD_TRACE_EVENT("%s: cid=%04x", __func__, cid); + p_hcon = &hd_cb.device.conn; + if (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid) { + HIDD_TRACE_WARNING("%s: unknown cid", __func__); + return; + } + if ((!p_cfg->mtu_present) || (p_cfg->mtu > HID_DEV_MTU_SIZE)) + p_hcon->rem_mtu_size = HID_DEV_MTU_SIZE; + else + p_hcon->rem_mtu_size = p_cfg->mtu; + // accept without changes + p_cfg->flush_to_present = FALSE; + p_cfg->mtu_present = FALSE; + p_cfg->result = L2CAP_CFG_OK; + if (cid == p_hcon->intr_cid && hd_cb.use_in_qos && !p_cfg->qos_present) { + p_cfg->qos_present = TRUE; + memcpy(&p_cfg->qos, &hd_cb.in_qos, sizeof(FLOW_SPEC)); + } + L2CA_ConfigRsp(cid, p_cfg); + // update flags + if (cid == p_hcon->ctrl_cid) { + p_hcon->conn_flags |= HID_CONN_FLAGS_HIS_CTRL_CFG_DONE; + if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) && (p_hcon->conn_flags & HID_CONN_FLAGS_MY_CTRL_CFG_DONE)) { + p_hcon->disc_reason = HID_L2CAP_CONN_FAIL; + if ((p_hcon->intr_cid = L2CA_ConnectReq(HID_PSM_INTERRUPT, hd_cb.device.addr)) == 0) { + p_hcon->conn_state = HID_CONN_STATE_UNUSED; + hidd_conn_disconnect(); + HIDD_TRACE_WARNING("%s: could not start L2CAP connection for INTR", __func__); + hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, HID_ERR_L2CAP_FAILED, NULL); + return; + } else { + p_hcon->conn_state = HID_CONN_STATE_CONNECTING_INTR; + } + } + } else { + p_hcon->conn_flags |= HID_CONN_FLAGS_HIS_INTR_CFG_DONE; + } + hidd_check_config_done(); +} +/******************************************************************************* + * + * Function hidd_l2cif_config_cfm + * + * Description Handles incoming L2CAP configuration response + * + * Returns void + * + ******************************************************************************/ +static void hidd_l2cif_config_cfm(uint16_t cid, tL2CAP_CFG_INFO *p_cfg) +{ + tHID_CONN *p_hcon; + uint32_t reason; + HIDD_TRACE_EVENT("%s: cid=%04x pcfg->result=%d", __func__, cid, p_cfg->result); + p_hcon = &hd_cb.device.conn; + if (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid) { + HIDD_TRACE_WARNING("%s: unknown cid", __func__); + return; + } + if (p_hcon->intr_cid == cid && p_cfg->result == L2CAP_CFG_UNACCEPTABLE_PARAMS && p_cfg->qos_present) { + tL2CAP_CFG_INFO new_qos; + // QoS parameters not accepted for intr, try again with host proposal + memcpy(&new_qos, &hd_cb.l2cap_intr_cfg, sizeof(new_qos)); + memcpy(&new_qos.qos, &p_cfg->qos, sizeof(FLOW_SPEC)); + new_qos.qos_present = TRUE; + HIDD_TRACE_WARNING("%s: config failed, retry", __func__); + L2CA_ConfigReq(cid, &new_qos); + return; + } else if (p_hcon->intr_cid == cid && p_cfg->result == L2CAP_CFG_UNKNOWN_OPTIONS) { + // QoS not understood by remote device, try configuring without QoS + HIDD_TRACE_WARNING("%s: config failed, retry without QoS", __func__); + L2CA_ConfigReq(cid, &hd_cb.l2cap_cfg); + return; + } else if (p_cfg->result != L2CAP_CFG_OK) { + HIDD_TRACE_WARNING("%s: config failed, disconnecting", __func__); + hidd_conn_disconnect(); + reason = HID_L2CAP_CFG_FAIL | (uint32_t)p_cfg->result; + hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, reason, NULL); + return; + } + // update flags + if (cid == p_hcon->ctrl_cid) { + p_hcon->conn_flags |= HID_CONN_FLAGS_MY_CTRL_CFG_DONE; + if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) && (p_hcon->conn_flags & HID_CONN_FLAGS_HIS_CTRL_CFG_DONE)) { + p_hcon->disc_reason = HID_L2CAP_CONN_FAIL; + if ((p_hcon->intr_cid = L2CA_ConnectReq(HID_PSM_INTERRUPT, hd_cb.device.addr)) == 0) { + p_hcon->conn_state = HID_CONN_STATE_UNUSED; + hidd_conn_disconnect(); + HIDD_TRACE_WARNING("%s: could not start L2CAP connection for INTR", __func__); + hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, HID_ERR_L2CAP_FAILED, NULL); + return; + } else { + p_hcon->conn_state = HID_CONN_STATE_CONNECTING_INTR; + } + } + } else { + p_hcon->conn_flags |= HID_CONN_FLAGS_MY_INTR_CFG_DONE; + } + hidd_check_config_done(); +} +/******************************************************************************* + * + * Function hidd_l2cif_disconnect_ind + * + * Description Handler incoming L2CAP disconnection request + * + * Returns void + * + ******************************************************************************/ +static void hidd_l2cif_disconnect_ind(uint16_t cid, bool ack_needed) +{ + tHID_CONN *p_hcon; + HIDD_TRACE_EVENT("%s: cid=%04x ack_needed=%d", __func__, cid, ack_needed); + p_hcon = &hd_cb.device.conn; + if (p_hcon->conn_state == HID_CONN_STATE_UNUSED || (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) { + HIDD_TRACE_WARNING("%s: unknown cid", __func__); + return; + } + if (ack_needed) + L2CA_DisconnectRsp(cid); + if (cid == p_hcon->ctrl_cid) { + p_hcon->ctrl_cid = 0; + p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING_CTRL; + } else { + p_hcon->intr_cid = 0; + p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING_INTR; + } + if ((p_hcon->ctrl_cid == 0) && (p_hcon->intr_cid == 0)) { + HIDD_TRACE_EVENT("%s: INTR and CTRL disconnected", __func__); + // clean any outstanding data on intr + if (hd_cb.pending_data) { + osi_free(hd_cb.pending_data); + hd_cb.pending_data = NULL; + } + hd_cb.device.state = HIDD_DEV_NO_CONN; + p_hcon->conn_state = HID_CONN_STATE_UNUSED; + hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, p_hcon->disc_reason, NULL); + } +} +/******************************************************************************* + * + * Function hidd_l2cif_disconnect_cfm + * + * Description Handles L2CAP disconection response + * + * Returns void + * + ******************************************************************************/ +static void hidd_l2cif_disconnect_cfm(uint16_t cid, uint16_t result) +{ + tHID_CONN *p_hcon; + HIDD_TRACE_EVENT("%s: cid=%04x result=%d", __func__, cid, result); + p_hcon = &hd_cb.device.conn; + if (p_hcon->conn_state == HID_CONN_STATE_UNUSED || (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) { + HIDD_TRACE_WARNING("%s: unknown cid", __func__); + return; + } + if (cid == p_hcon->ctrl_cid) { + p_hcon->ctrl_cid = 0; + } else { + p_hcon->intr_cid = 0; + // now disconnect CTRL + L2CA_DisconnectReq(p_hcon->ctrl_cid); + } + if ((p_hcon->ctrl_cid == 0) && (p_hcon->intr_cid == 0)) { + HIDD_TRACE_EVENT("%s: INTR and CTRL disconnected", __func__); + hd_cb.device.state = HIDD_DEV_NO_CONN; + p_hcon->conn_state = HID_CONN_STATE_UNUSED; + if (hd_cb.pending_vc_unplug) { + hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_VC_UNPLUG, p_hcon->disc_reason, NULL); + hd_cb.pending_vc_unplug = FALSE; + } else { + hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, p_hcon->disc_reason, NULL); + } + } +} +/******************************************************************************* + * + * Function hidd_l2cif_cong_ind + * + * Description Handles L2CAP congestion status event + * + * Returns void + * + ******************************************************************************/ +static void hidd_l2cif_cong_ind(uint16_t cid, bool congested) +{ + tHID_CONN *p_hcon; + HIDD_TRACE_EVENT("%s: cid=%04x congested=%d", __func__, cid, congested); + p_hcon = &hd_cb.device.conn; + if (p_hcon->conn_state == HID_CONN_STATE_UNUSED || (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) { + HIDD_TRACE_WARNING("%s: unknown cid", __func__); + return; + } + if (congested) { + p_hcon->conn_flags |= HID_CONN_FLAGS_CONGESTED; + } else { + p_hcon->conn_flags &= ~HID_CONN_FLAGS_CONGESTED; + } +} +/******************************************************************************* + * + * Function hidd_l2cif_data_ind + * + * Description Handler incoming data on L2CAP channel + * + * Returns void + * + ******************************************************************************/ +static void hidd_l2cif_data_ind(uint16_t cid, BT_HDR *p_msg) +{ + tHID_CONN *p_hcon; + uint8_t *p_data = (uint8_t *)(p_msg + 1) + p_msg->offset; + uint8_t msg_type, param; + bool err = FALSE; + HIDD_TRACE_EVENT("%s: cid=%04x", __func__, cid); + p_hcon = &hd_cb.device.conn; + if (p_hcon->conn_state == HID_CONN_STATE_UNUSED || (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) { + HIDD_TRACE_WARNING("%s: unknown cid", __func__); + osi_free(p_msg); + return; + } + msg_type = HID_GET_TRANS_FROM_HDR(*p_data); + param = HID_GET_PARAM_FROM_HDR(*p_data); + if (msg_type == HID_TRANS_DATA && cid == p_hcon->intr_cid) { + // skip HID header + p_msg->offset++; + p_msg->len--; + hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_INTR_DATA, 0, p_msg); + return; + } + switch (msg_type) { + case HID_TRANS_GET_REPORT: + // at this stage we don't know if Report Id shall be included in request + // so we pass complete packet in callback and let other code analyze this + hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_GET_REPORT, !!(param & HID_PAR_GET_REP_BUFSIZE_FOLLOWS), p_msg); + break; + case HID_TRANS_SET_REPORT: + // as above + hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_SET_REPORT, 0, p_msg); + break; + case HID_TRANS_GET_IDLE: + hidd_conn_send_data(HID_CHANNEL_CTRL, HID_TRANS_DATA, HID_PAR_REP_TYPE_OTHER, hd_cb.device.idle_time, 0, NULL); + osi_free(p_msg); + break; + case HID_TRANS_SET_IDLE: + if (p_msg->len != 2) { + HIDD_TRACE_ERROR("%s: invalid len (%d) set idle request received", __func__, p_msg->len); + err = TRUE; + } else { + hd_cb.device.idle_time = p_data[1]; + HIDD_TRACE_DEBUG("%s: idle_time = %d", __func__, hd_cb.device.idle_time); + if (hd_cb.device.idle_time) { + HIDD_TRACE_WARNING("%s: idle_time of %d ms not supported by HID Device", __func__, + (hd_cb.device.idle_time * 4)); + err = TRUE; + } + } + if (!err) { + hidd_conn_send_data(0, HID_TRANS_HANDSHAKE, HID_PAR_HANDSHAKE_RSP_SUCCESS, 0, 0, NULL); + } else { + hidd_conn_send_data(0, HID_TRANS_HANDSHAKE, HID_PAR_HANDSHAKE_RSP_ERR_INVALID_PARAM, 0, 0, NULL); + } + osi_free(p_msg); + break; + case HID_TRANS_GET_PROTOCOL: + hidd_conn_send_data(HID_CHANNEL_CTRL, HID_TRANS_DATA, HID_PAR_REP_TYPE_OTHER, !hd_cb.device.boot_mode, 0, NULL); + osi_free(p_msg); + break; + case HID_TRANS_SET_PROTOCOL: + hd_cb.device.boot_mode = !(param & HID_PAR_PROTOCOL_MASK); + hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_SET_PROTOCOL, param & HID_PAR_PROTOCOL_MASK, NULL); + hidd_conn_send_data(0, HID_TRANS_HANDSHAKE, HID_PAR_HANDSHAKE_RSP_SUCCESS, 0, 0, NULL); + osi_free(p_msg); + break; + case HID_TRANS_CONTROL: + switch (param) { + case HID_PAR_CONTROL_SUSPEND: + hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_SUSPEND, 0, NULL); + break; + case HID_PAR_CONTROL_EXIT_SUSPEND: + hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_EXIT_SUSPEND, 0, NULL); + break; + case HID_PAR_CONTROL_VIRTUAL_CABLE_UNPLUG: + hidd_conn_disconnect(); + // set flag so we can notify properly when disconnected + hd_cb.pending_vc_unplug = TRUE; + break; + } + osi_free(p_msg); + break; + case HID_TRANS_DATA: + default: + HIDD_TRACE_WARNING("%s: got unsupported msg (%d)", __func__, msg_type); + hidd_conn_send_data(0, HID_TRANS_HANDSHAKE, HID_PAR_HANDSHAKE_RSP_ERR_UNSUPPORTED_REQ, 0, 0, NULL); + osi_free(p_msg); + break; + } +} +/******************************************************************************* + * + * Function hidd_conn_reg + * + * Description Registers L2CAP channels + * + * Returns void + * + ******************************************************************************/ +tHID_STATUS hidd_conn_reg(void) +{ + HIDD_TRACE_API("%s", __func__); + memset(&hd_cb.l2cap_cfg, 0, sizeof(tL2CAP_CFG_INFO)); + hd_cb.l2cap_cfg.mtu_present = TRUE; + hd_cb.l2cap_cfg.mtu = HID_DEV_MTU_SIZE; + hd_cb.l2cap_cfg.flush_to_present = TRUE; + hd_cb.l2cap_cfg.flush_to = HID_DEV_FLUSH_TO; + memset(&hd_cb.l2cap_intr_cfg, 0, sizeof(tL2CAP_CFG_INFO)); + hd_cb.l2cap_intr_cfg.mtu_present = TRUE; + hd_cb.l2cap_intr_cfg.mtu = HID_DEV_MTU_SIZE; + hd_cb.l2cap_intr_cfg.flush_to_present = TRUE; + hd_cb.l2cap_intr_cfg.flush_to = HID_DEV_FLUSH_TO; + if (!L2CA_Register(HID_PSM_CONTROL, (tL2CAP_APPL_INFO *)&dev_reg_info)) { + HIDD_TRACE_ERROR("HID Control (device) registration failed"); + return (HID_ERR_L2CAP_FAILED); + } + if (!L2CA_Register(HID_PSM_INTERRUPT, (tL2CAP_APPL_INFO *)&dev_reg_info)) { + L2CA_Deregister(HID_PSM_CONTROL); + HIDD_TRACE_ERROR("HID Interrupt (device) registration failed"); + return (HID_ERR_L2CAP_FAILED); + } + return (HID_SUCCESS); +} +/******************************************************************************* + * + * Function hidd_conn_dereg + * + * Description Deregisters L2CAP channels + * + * Returns void + * + ******************************************************************************/ +void hidd_conn_dereg(void) +{ + HIDD_TRACE_API("%s", __func__); + L2CA_Deregister(HID_PSM_CONTROL); + L2CA_Deregister(HID_PSM_INTERRUPT); +} +/******************************************************************************* + * + * Function hidd_conn_initiate + * + * Description Initiates HID connection to plugged device + * + * Returns HID_SUCCESS + * + ******************************************************************************/ +tHID_STATUS hidd_conn_initiate(void) +{ + tHID_DEV_DEV_CTB *p_dev = &hd_cb.device; + HIDD_TRACE_API("%s", __func__); + if (!p_dev->in_use) { + HIDD_TRACE_WARNING("%s: no virtual cable established", __func__); + return (HID_ERR_NOT_REGISTERED); + } + if (p_dev->conn.conn_state != HID_CONN_STATE_UNUSED) { + HIDD_TRACE_WARNING("%s: connection already in progress", __func__); + return (HID_ERR_CONN_IN_PROCESS); + } + p_dev->conn.ctrl_cid = 0; + p_dev->conn.intr_cid = 0; + p_dev->conn.disc_reason = HID_L2CAP_CONN_FAIL; + p_dev->conn.conn_flags = HID_CONN_FLAGS_IS_ORIG; + BTM_SetOutService(p_dev->addr, BTM_SEC_SERVICE_HIDD_SEC_CTRL, HIDD_SEC_CHN); + /* Check if L2CAP started the connection process */ + if ((p_dev->conn.ctrl_cid = L2CA_ConnectReq(HID_PSM_CONTROL, p_dev->addr)) == 0) { + HIDD_TRACE_WARNING("%s: could not start L2CAP connection", __func__); + hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, HID_ERR_L2CAP_FAILED, NULL); + } else { + p_dev->conn.conn_state = HID_CONN_STATE_CONNECTING_CTRL; + } + return (HID_SUCCESS); +} +/******************************************************************************* + * + * Function hidd_conn_disconnect + * + * Description Disconnects existing HID connection + * + * Returns HID_SUCCESS + * + ******************************************************************************/ +tHID_STATUS hidd_conn_disconnect(void) +{ + tHID_CONN *p_hcon; + HIDD_TRACE_API("%s", __func__); + // clean any outstanding data on intr + if (hd_cb.pending_data) { + osi_free(hd_cb.pending_data); + hd_cb.pending_data = NULL; + } + p_hcon = &hd_cb.device.conn; + if ((p_hcon->ctrl_cid != 0) || (p_hcon->intr_cid != 0)) { + /* Set l2cap idle timeout to 0 (so ACL link is disconnected + * immediately after last channel is closed) */ + L2CA_SetIdleTimeoutByBdAddr(hd_cb.device.addr, 0, BT_TRANSPORT_BR_EDR); + if (p_hcon->intr_cid) { + p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING_INTR; + L2CA_DisconnectReq(p_hcon->intr_cid); + } else if (p_hcon->ctrl_cid) { + p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING_CTRL; + L2CA_DisconnectReq(p_hcon->ctrl_cid); + } + } else { + HIDD_TRACE_WARNING("%s: already disconnected", __func__); + p_hcon->conn_state = HID_CONN_STATE_UNUSED; + } + return (HID_SUCCESS); +} +/******************************************************************************* + * + * Function hidd_conn_send_data + * + * Description Sends data to host + * + * Returns tHID_STATUS + * + ******************************************************************************/ +tHID_STATUS hidd_conn_send_data(uint8_t channel, uint8_t msg_type, uint8_t param, uint8_t data, uint16_t len, + uint8_t *p_data) +{ + tHID_CONN *p_hcon; + BT_HDR *p_buf; + uint8_t *p_out; + uint16_t cid; + uint16_t buf_size; + HIDD_TRACE_VERBOSE("%s: channel(%d), msg_type(%d), len(%d)", __func__, channel, msg_type, len); + p_hcon = &hd_cb.device.conn; + if (p_hcon->conn_flags & HID_CONN_FLAGS_CONGESTED) { + return HID_ERR_CONGESTED; + } + switch (msg_type) { + case HID_TRANS_HANDSHAKE: + case HID_TRANS_CONTROL: + cid = p_hcon->ctrl_cid; + buf_size = HID_CONTROL_BUF_SIZE; + break; + case HID_TRANS_DATA: + if (channel == HID_CHANNEL_CTRL) { + cid = p_hcon->ctrl_cid; + buf_size = HID_CONTROL_BUF_SIZE; + } else { + cid = p_hcon->intr_cid; + buf_size = HID_INTERRUPT_BUF_SIZE; + } + break; + default: + return (HID_ERR_INVALID_PARAM); + } + p_buf = (BT_HDR *)osi_malloc(buf_size); + if (p_buf == NULL) + return (HID_ERR_NO_RESOURCES); + p_buf->offset = L2CAP_MIN_OFFSET; + p_out = (uint8_t *)(p_buf + 1) + p_buf->offset; + *p_out = HID_BUILD_HDR(msg_type, param); + p_out++; + p_buf->len = 1; // start with header only + // add report id prefix only if non-zero (which is reserved) + if (msg_type == HID_TRANS_DATA && (data || param == HID_PAR_REP_TYPE_OTHER)) { + *p_out = data; // report_id + p_out++; + p_buf->len++; + } + if (len > 0 && p_data != NULL) { + memcpy(p_out, p_data, len); + p_buf->len += len; + } + // check if connected + if (hd_cb.device.state != HIDD_DEV_CONNECTED) { + // for DATA on intr we hold transfer and try to reconnect + if (msg_type == HID_TRANS_DATA && cid == p_hcon->intr_cid) { + // drop previous data, we do not queue it for now + if (hd_cb.pending_data) { + osi_free(hd_cb.pending_data); + } + hd_cb.pending_data = p_buf; + if (hd_cb.device.conn.conn_state == HID_CONN_STATE_UNUSED) { + hidd_conn_initiate(); + } + return HID_SUCCESS; + } + return HID_ERR_NO_CONNECTION; + } +#ifdef REPORT_TRANSFER_TIMESTAMP + if (report_transfer) { + HIDD_TRACE_ERROR("%s: report sent", __func__); + } +#endif + HIDD_TRACE_VERBOSE("%s: report sent", __func__); + if (!L2CA_DataWrite(cid, p_buf)) + return (HID_ERR_CONGESTED); + return (HID_SUCCESS); +} + +#endif diff --git a/components/bt/host/bluedroid/btc/profile/std/hid/hidh_api.c b/components/bt/host/bluedroid/stack/hid/hidh_api.c similarity index 91% rename from components/bt/host/bluedroid/btc/profile/std/hid/hidh_api.c rename to components/bt/host/bluedroid/stack/hid/hidh_api.c index e5a6ab6fcd..188aa0a4ee 100644 --- a/components/bt/host/bluedroid/btc/profile/std/hid/hidh_api.c +++ b/components/bt/host/bluedroid/stack/hid/hidh_api.c @@ -31,7 +31,7 @@ #include "stack/bt_types.h" #include "stack/hiddefs.h" #include "stack/hidh_api.h" -#include "hidh_int.h" +#include "hid_int.h" #include "stack/btm_api.h" #include "stack/btu.h" #include "btm_int.h" @@ -39,7 +39,9 @@ #if (HID_HOST_INCLUDED == TRUE) #if HID_DYNAMIC_MEMORY == FALSE -tHID_HOST_CTB hh_cb; +tHID_HOST_CTB hh_cb; +#else +tHID_HOST_CTB *hidh_cb_ptr = NULL; #endif static void hidh_search_callback (UINT16 sdp_result); @@ -218,18 +220,46 @@ static void hidh_search_callback (UINT16 sdp_result) ** ** Description This function initializes the control block and trace variable ** -** Returns void +** Returns tHID_STATUS ** *******************************************************************************/ -void HID_HostInit (void) +tHID_STATUS HID_HostInit (void) { +#if (HID_DYNAMIC_MEMORY) + if (!hidh_cb_ptr) { + hidh_cb_ptr = (tHID_HOST_CTB *)osi_malloc(sizeof(tHID_HOST_CTB)); + if (!hidh_cb_ptr) { + return HID_ERR_NO_RESOURCES; + } + } +#endif /* #if (HID_DYNAMIC_MEMORY) */ memset(&hh_cb, 0, sizeof(tHID_HOST_CTB)); -#if defined(HID_INITIAL_TRACE_LEVEL) - hh_cb.trace_level = HID_INITIAL_TRACE_LEVEL; +#if defined(HIDH_INITIAL_TRACE_LEVEL) + hh_cb.trace_level = HIDH_INITIAL_TRACE_LEVEL; #else hh_cb.trace_level = BT_TRACE_LEVEL_NONE; #endif + return HID_SUCCESS; +} + +/******************************************************************************* +** +** Function HID_HostInit +** +** Description This function deinitializes the control block +** +** Returns void +** +*******************************************************************************/ +void HID_HostDeinit (void) +{ +#if (HID_DYNAMIC_MEMORY) + if (hidh_cb_ptr) { + osi_free(hidh_cb_ptr); + hidh_cb_ptr = NULL; + } +#endif /* #if (HID_DYNAMIC_MEMORY) */ } /******************************************************************************* @@ -362,6 +392,36 @@ tHID_STATUS HID_HostAddDev ( BD_ADDR addr, UINT16 attr_mask, UINT8 *handle ) return (HID_SUCCESS); } +/******************************************************************************* +** +** Function HID_HostGetDev +** +** Description This is called so HID-host can find this device. +** +** Returns tHID_STATUS +** +*******************************************************************************/ +tHID_STATUS HID_HostGetDev(BD_ADDR addr, UINT8 *handle) +{ + int i; + /* Find an entry for this device in hh_cb.devices array */ + if (!hh_cb.reg_flag) { + return (HID_ERR_NOT_REGISTERED); + } + + for (i = 0; i < HID_HOST_MAX_DEVICES; i++) { + if ((hh_cb.devices[i].in_use) && (!memcmp(addr, hh_cb.devices[i].addr, BD_ADDR_LEN))) { + break; + } + } + + if (i == HID_HOST_MAX_DEVICES) { + *handle = 0xff; + } else { + *handle = i; + } + return (HID_SUCCESS); +} /******************************************************************************* ** diff --git a/components/bt/host/bluedroid/btc/profile/std/hid/hidh_conn.c b/components/bt/host/bluedroid/stack/hid/hidh_conn.c similarity index 97% rename from components/bt/host/bluedroid/btc/profile/std/hid/hidh_conn.c rename to components/bt/host/bluedroid/stack/hid/hidh_conn.c index 83a4c484af..d94d9d1fa0 100644 --- a/components/bt/host/bluedroid/btc/profile/std/hid/hidh_conn.c +++ b/components/bt/host/bluedroid/stack/hid/hidh_conn.c @@ -41,7 +41,7 @@ #include "stack/hiddefs.h" #include "stack/hidh_api.h" -#include "hidh_int.h" +#include "hid_int.h" #include "osi/osi.h" #if (HID_HOST_INCLUDED == TRUE) @@ -132,15 +132,16 @@ tHID_STATUS hidh_conn_disconnect (UINT8 dhandle) HIDH_TRACE_EVENT ("HID-Host disconnect"); if ((p_hcon->ctrl_cid != 0) || (p_hcon->intr_cid != 0)) { - p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING; /* Set l2cap idle timeout to 0 (so ACL link is disconnected * immediately after last channel is closed) */ L2CA_SetIdleTimeoutByBdAddr(hh_cb.devices[dhandle].addr, 0, BT_TRANSPORT_BR_EDR); /* Disconnect both interrupt and control channels */ if (p_hcon->intr_cid) { + p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING_INTR; L2CA_DisconnectReq (p_hcon->intr_cid); } else if (p_hcon->ctrl_cid) { + p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING_CTRL; L2CA_DisconnectReq (p_hcon->ctrl_cid); } } else { @@ -360,12 +361,12 @@ static void hidh_l2cif_connect_cfm (UINT16 l2cap_cid, UINT16 result) p_hcon = &hh_cb.devices[dhandle].conn; } - if ((p_hcon == NULL) - || (!(p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG)) - || ((l2cap_cid == p_hcon->ctrl_cid) && (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_CTRL)) - || ((l2cap_cid == p_hcon->intr_cid) && (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR) - && (p_hcon->conn_state != HID_CONN_STATE_DISCONNECTING))) { - HIDH_TRACE_WARNING ("HID-Host Rcvd unexpected conn cnf, CID 0x%x ", l2cap_cid); + if ((p_hcon == NULL) || (!(p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG)) || + ((l2cap_cid == p_hcon->ctrl_cid) && (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_CTRL) && + (p_hcon->conn_state != HID_CONN_STATE_DISCONNECTING_INTR)) || + ((l2cap_cid == p_hcon->intr_cid) && (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR) && + (p_hcon->conn_state != HID_CONN_STATE_DISCONNECTING_CTRL))) { + HIDH_TRACE_WARNING("HID-Host Rcvd unexpected conn cnf, CID 0x%x ", l2cap_cid); return; } @@ -592,12 +593,12 @@ static void hidh_l2cif_disconnect_ind (UINT16 l2cap_cid, BOOLEAN ack_needed) HIDH_TRACE_EVENT ("HID-Host Rcvd L2CAP disc, CID: 0x%x", l2cap_cid); - p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING; - if (l2cap_cid == p_hcon->ctrl_cid) { p_hcon->ctrl_cid = 0; + p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING_CTRL; } else { p_hcon->intr_cid = 0; + p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING_INTR; } if ((p_hcon->ctrl_cid == 0) && (p_hcon->intr_cid == 0)) { diff --git a/components/bt/host/bluedroid/btc/profile/std/hid/include/hid_conn.h b/components/bt/host/bluedroid/stack/hid/include/hid_conn.h similarity index 78% rename from components/bt/host/bluedroid/btc/profile/std/hid/include/hid_conn.h rename to components/bt/host/bluedroid/stack/hid/include/hid_conn.h index 320694c537..38bb5978f8 100644 --- a/components/bt/host/bluedroid/btc/profile/std/hid/include/hid_conn.h +++ b/components/bt/host/bluedroid/stack/hid/include/hid_conn.h @@ -26,18 +26,21 @@ #define HID_CONN_H #include "common/bt_defs.h" -#if (HID_HOST_INCLUDED == TRUE) + +#if (BT_HID_INCLUDED == TRUE) /* Define the HID Connection Block */ typedef struct hid_conn { -#define HID_CONN_STATE_UNUSED (0) -#define HID_CONN_STATE_CONNECTING_CTRL (1) -#define HID_CONN_STATE_CONNECTING_INTR (2) -#define HID_CONN_STATE_CONFIG (3) -#define HID_CONN_STATE_CONNECTED (4) -#define HID_CONN_STATE_DISCONNECTING (5) -#define HID_CONN_STATE_SECURITY (6) +#define HID_CONN_STATE_UNUSED (0) +#define HID_CONN_STATE_CONNECTING_CTRL (1) +#define HID_CONN_STATE_CONNECTING_INTR (2) +#define HID_CONN_STATE_CONFIG (3) +#define HID_CONN_STATE_CONNECTED (4) +#define HID_CONN_STATE_DISCONNECTING (5) +#define HID_CONN_STATE_SECURITY (6) +#define HID_CONN_STATE_DISCONNECTING_CTRL (7) +#define HID_CONN_STATE_DISCONNECTING_INTR (8) UINT8 conn_state; @@ -62,9 +65,8 @@ typedef struct hid_conn { #define HID_SEC_CHN 1 #define HID_NOSEC_CHN 2 +#define HIDD_SEC_CHN 3 +#define HIDD_NOSEC_CHN 4 -#define HIDD_SEC_CHN 3 -#define HIDD_NOSEC_CHN 4 - -#endif ///HID_HOST_INCLUDED == TRUE +#endif ///BT_HID_INCLUDED == TRUE #endif diff --git a/components/bt/host/bluedroid/btc/profile/std/hid/include/hidh_int.h b/components/bt/host/bluedroid/stack/hid/include/hid_int.h similarity index 60% rename from components/bt/host/bluedroid/btc/profile/std/hid/include/hidh_int.h rename to components/bt/host/bluedroid/stack/hid/include/hid_int.h index 20eda6e3a0..d926e3a891 100644 --- a/components/bt/host/bluedroid/btc/profile/std/hid/include/hidh_int.h +++ b/components/bt/host/bluedroid/stack/hid/include/hid_int.h @@ -1,5 +1,6 @@ /****************************************************************************** * + * Copyright (C) 2016 The Android Open Source Project * Copyright (C) 2002-2012 Broadcom Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,26 +16,21 @@ * limitations under the License. * ******************************************************************************/ - /****************************************************************************** * - * This file contains HID HOST internal definitions + * This file contains HID DEVICE internal definitions * ******************************************************************************/ +#ifndef HID_INT_H +#define HID_INT_H -#ifndef HIDH_INT_H -#define HIDH_INT_H - -#include "stack/hidh_api.h" #include "hid_conn.h" #include "stack/l2c_api.h" +#if (BT_HID_INCLUDED == TRUE) #if (HID_HOST_INCLUDED == TRUE) - -enum { - HID_DEV_NO_CONN, - HID_DEV_CONNECTED -}; +#include "stack/hidh_api.h" +enum { HID_DEV_NO_CONN, HID_DEV_CONNECTED }; typedef struct per_device_ctb { BOOLEAN in_use; @@ -70,17 +66,16 @@ extern void hidh_conn_dereg( void ); extern tHID_STATUS hidh_conn_disconnect (UINT8 dhandle); extern tHID_STATUS hidh_conn_initiate (UINT8 dhandle); extern void hidh_proc_repage_timeout (TIMER_LIST_ENT *p_tle); - #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif /****************************************************************************** -** Main Control Block -*******************************************************************************/ + * Main Control Block + ******************************************************************************/ + #if HID_DYNAMIC_MEMORY == FALSE -extern tHID_HOST_CTB hh_cb; +extern tHID_HOST_CTB hh_cb; #else extern tHID_HOST_CTB *hidh_cb_ptr; #define hh_cb (*hidh_cb_ptr) @@ -89,7 +84,60 @@ extern tHID_HOST_CTB *hidh_cb_ptr; #ifdef __cplusplus } #endif +#endif /* HID_HOST_INCLUDED == TRUE */ -#endif ///HID_HOST_INCLUDED == TRUE +#if (HID_DEV_INCLUDED == TRUE) +#include "stack/hidd_api.h" +enum { HIDD_DEV_NO_CONN, HIDD_DEV_CONNECTED }; +typedef struct device_ctb { + bool in_use; + BD_ADDR addr; + uint8_t state; + tHID_CONN conn; + bool boot_mode; + uint8_t idle_time; +} tHID_DEV_DEV_CTB; + +typedef struct dev_ctb { + tHID_DEV_DEV_CTB device; + tHID_DEV_HOST_CALLBACK *callback; + tL2CAP_CFG_INFO l2cap_cfg; + tL2CAP_CFG_INFO l2cap_intr_cfg; + bool use_in_qos; + FLOW_SPEC in_qos; + bool reg_flag; + uint8_t trace_level; + bool allow_incoming; + BT_HDR *pending_data; + bool pending_vc_unplug; +} tHID_DEV_CTB; + +extern tHID_STATUS hidd_conn_reg(void); +extern void hidd_conn_dereg(void); +extern tHID_STATUS hidd_conn_initiate(void); +extern tHID_STATUS hidd_conn_disconnect(void); +extern tHID_STATUS hidd_conn_send_data(uint8_t channel, uint8_t msg_type, uint8_t param, uint8_t data, uint16_t len, + uint8_t *p_data); +#ifdef __cplusplus +extern "C" { #endif + +/****************************************************************************** + * Main Control Block + ******************************************************************************/ + +#if HID_DYNAMIC_MEMORY == FALSE +extern tHID_DEV_CTB hd_cb; +#else +extern tHID_DEV_CTB *hidd_cb_ptr; +#define hd_cb (*hidd_cb_ptr) +#endif + +#ifdef __cplusplus +} +#endif +#endif /* HID_DEV_INCLUDED == TRUE */ + +#endif /* BT_HID_INCLUDED == TRUE */ +#endif /* HID_INT_H */ diff --git a/components/bt/host/bluedroid/stack/include/stack/btm_api.h b/components/bt/host/bluedroid/stack/include/stack/btm_api.h index 6af1b3ba05..d2dd2c4038 100644 --- a/components/bt/host/bluedroid/stack/include/stack/btm_api.h +++ b/components/bt/host/bluedroid/stack/include/stack/btm_api.h @@ -74,6 +74,7 @@ enum { BTM_SET_PRIVACY_FAIL, /* 24 enable/disable local privacy failed*/ BTM_SET_STATIC_RAND_ADDR_FAIL, /* 25 Command failed */ BTM_INVALID_STATIC_RAND_ADDR, /* 26 invalid static rand addr */ + BTM_SEC_DEV_REC_REMOVED, /* 27 Device record relate to the bd_addr is removed */ }; typedef uint8_t tBTM_STATUS; @@ -1252,9 +1253,12 @@ typedef UINT8 tBTM_LINK_KEY_TYPE; #define BTM_SEC_SERVICE_HDP_SNK 48 #define BTM_SEC_SERVICE_HDP_SRC 49 #define BTM_SEC_SERVICE_ATT 50 +#define BTM_SEC_SERVICE_HIDD_SEC_CTRL 51 +#define BTM_SEC_SERVICE_HIDD_NOSEC_CTRL 52 +#define BTM_SEC_SERVICE_HIDD_INTR 53 /* Update these as services are added */ -#define BTM_SEC_SERVICE_FIRST_EMPTY 51 +#define BTM_SEC_SERVICE_FIRST_EMPTY 54 #ifndef BTM_SEC_MAX_SERVICES #define BTM_SEC_MAX_SERVICES 65 @@ -1915,11 +1919,11 @@ typedef UINT8 tBTM_CONTRL_STATE; /***************************************************************************** ** EXTERNAL FUNCTION DECLARATIONS *****************************************************************************/ -/* + #ifdef __cplusplus extern "C" { #endif -*/ + /***************************************************************************** ** DEVICE CONTROL and COMMON FUNCTIONS *****************************************************************************/ @@ -4141,10 +4145,8 @@ tBTM_STATUS BTM_SetAfhChannels (AFH_CHANNELS channels, tBTM_CMPL_CB *p_afh_chann *******************************************************************************/ tBTM_STATUS BTM_BleSetChannels (BLE_CHANNELS channels, tBTM_CMPL_CB *p_ble_channels_cmpl_cback); -/* #ifdef __cplusplus } #endif -*/ #endif /* BTM_API_H */ diff --git a/components/bt/host/bluedroid/stack/include/stack/hcidefs.h b/components/bt/host/bluedroid/stack/include/stack/hcidefs.h index 064c0ca25a..bf3754f25b 100644 --- a/components/bt/host/bluedroid/stack/include/stack/hcidefs.h +++ b/components/bt/host/bluedroid/stack/include/stack/hcidefs.h @@ -844,7 +844,7 @@ #define HCI_ERR_SCO_AIR_MODE 0x1D #define HCI_ERR_INVALID_LMP_PARAM 0x1E #define HCI_ERR_UNSPECIFIED 0x1F -#define HCI_ERR_UNSUPPORTED_LMP_FEATURE 0x20 +#define HCI_ERR_UNSUPPORTED_LMP_PARAMETERS 0x20 #define HCI_ERR_ROLE_CHANGE_NOT_ALLOWED 0x21 #define HCI_ERR_LMP_RESPONSE_TIMEOUT 0x22 #define HCI_ERR_LMP_ERR_TRANS_COLLISION 0x23 diff --git a/components/bt/host/bluedroid/stack/include/stack/hidd_api.h b/components/bt/host/bluedroid/stack/include/stack/hidd_api.h new file mode 100644 index 0000000000..3e99db9da1 --- /dev/null +++ b/components/bt/host/bluedroid/stack/include/stack/hidd_api.h @@ -0,0 +1,273 @@ +/****************************************************************************** + * + * Copyright (C) 2016 The Android Open Source Project + * Copyright (C) 2002-2012 Broadcom Corporation + * + * 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. + * + ******************************************************************************/ +#ifndef HIDD_API_H +#define HIDD_API_H +#include "hiddefs.h" +#include "sdp_api.h" + +#if (HID_DEV_INCLUDED == TRUE) +/***************************************************************************** + * Type Definitions + ****************************************************************************/ +enum { + HID_CHANNEL_INTR, + HID_CHANNEL_CTRL +}; +/* + HID_DHOST_EVT_OPEN - connected to host device (CTRL and INTR), data = n/a + HID_DHOST_EVT_CLOSE - disconnected from host device, data=reason + HID_DHOST_EVT_GET_REPORT - got GET_REPORT from host + HID_DHOST_EVT_SET_REPORT - got SET_REPORT from host + HID_DHOST_EVT_SET_PROTOCOL - got SET_PROTOCOL from host +*/ + +enum { + HID_DHOST_EVT_OPEN, + HID_DHOST_EVT_CLOSE, + HID_DHOST_EVT_GET_REPORT, + HID_DHOST_EVT_SET_REPORT, + HID_DHOST_EVT_SET_PROTOCOL, + HID_DHOST_EVT_INTR_DATA, + HID_DHOST_EVT_VC_UNPLUG, + HID_DHOST_EVT_SUSPEND, + HID_DHOST_EVT_EXIT_SUSPEND, +}; + +typedef void (tHID_DEV_HOST_CALLBACK)(BD_ADDR bd_addr, uint8_t event, uint32_t data, BT_HDR* p_buf); + +#ifdef __cplusplus +extern "C" { +#endif +/***************************************************************************** + * External Function Declarations + ****************************************************************************/ + +/******************************************************************************* + * + * Function HID_DevInit + * + * Description Initializes control block + * + * Returns tHID_STATUS + * + ******************************************************************************/ +extern tHID_STATUS HID_DevInit(void); + +/******************************************************************************* + * + * Function HID_DevInit + * + * Description Deinitializes control block + * + * Returns void + * + ******************************************************************************/ +extern void HID_DevDeinit(void); + +/******************************************************************************* + * + * Function HID_DevRegister + * + * Description Registers HID device with lower layers + * + * Returns tHID_STATUS + * + ******************************************************************************/ +extern tHID_STATUS HID_DevRegister(tHID_DEV_HOST_CALLBACK* host_cback); + +/******************************************************************************* + * + * Function HID_DevDeregister + * + * Description Deregisters HID device with lower layers + * + * Returns tHID_STATUS + * + ******************************************************************************/ +extern tHID_STATUS HID_DevDeregister(void); + +/******************************************************************************* + * + * Function HID_DevSetSecurityLevel + * + * Description Sets security level for HID device connections + * + * Returns tHID_STATUS + * + ******************************************************************************/ +extern tHID_STATUS HID_DevSetSecurityLevel(uint8_t sec_lvl); + +/******************************************************************************* + * + * Function HID_DevAddRecord + * + * Description Creates SDP record for HID device + * + * Returns tHID_STATUS + * + ******************************************************************************/ +extern tHID_STATUS HID_DevAddRecord(uint32_t handle, char* p_name, + char* p_description, char* p_provider, + uint16_t subclass, uint16_t desc_len, + uint8_t* p_desc_data); + +/******************************************************************************* + * + * Function HID_DevSendReport + * + * Description Sends report + * + * Returns tHID_STATUS + * + ******************************************************************************/ +extern tHID_STATUS HID_DevSendReport(uint8_t channel, uint8_t type, uint8_t id, + uint16_t len, uint8_t* p_data); + +/******************************************************************************* + * + * Function HID_DevVirtualCableUnplug + * + * Description Sends Virtual Cable Unplug + * + * Returns tHID_STATUS + * + ******************************************************************************/ +extern tHID_STATUS HID_DevVirtualCableUnplug(void); + +/******************************************************************************* + * + * Function HID_DevPlugDevice + * + * Description Establishes virtual cable to given host + * + * Returns tHID_STATUS + * + ******************************************************************************/ +extern tHID_STATUS HID_DevPlugDevice(BD_ADDR addr); + +/******************************************************************************* + * + * Function HID_DevUnplugDevice + * + * Description Unplugs virtual cable from given host + * + * Returns tHID_STATUS + * + ******************************************************************************/ +extern tHID_STATUS HID_DevUnplugDevice(BD_ADDR addr); + +/******************************************************************************* + * + * Function HID_DevConnect + * + * Description Connects to device + * + * Returns tHID_STATUS + * + ******************************************************************************/ +extern tHID_STATUS HID_DevConnect(void); + +/******************************************************************************* + * + * Function HID_DevDisconnect + * + * Description Disconnects from device + * + * Returns tHID_STATUS + * + ******************************************************************************/ +extern tHID_STATUS HID_DevDisconnect(void); + +/******************************************************************************* + * + * Function HID_DevSetIncomingPolicy + * + * Description Sets policy for incoming connections (allowed/disallowed) + * + * Returns tHID_STATUS + * + ******************************************************************************/ +extern tHID_STATUS HID_DevSetIncomingPolicy(bool allow); + +/******************************************************************************* + * + * Function HID_DevReportError + * + * Description Reports error for Set Report via HANDSHAKE + * + * Returns tHID_STATUS + * + ******************************************************************************/ +extern tHID_STATUS HID_DevReportError(uint8_t error); + +/******************************************************************************* + * + * Function HID_DevGetDevice + * + * Description Returns the BD Address of virtually cabled device + * + * Returns tHID_STATUS + * + ******************************************************************************/ +extern tHID_STATUS HID_DevGetDevice(BD_ADDR* addr); + +/******************************************************************************* + * + * Function HID_DevSetIncomingQos + * + * Description Sets Incoming QoS values for Interrupt L2CAP Channel + * + * Returns tHID_STATUS + * + ******************************************************************************/ +extern tHID_STATUS HID_DevSetIncomingQos( + uint8_t service_type, uint32_t token_rate, uint32_t token_bucket_size, + uint32_t peak_bandwidth, uint32_t latency, uint32_t delay_variation); + +/******************************************************************************* + * + * Function HID_DevSetOutgoingQos + * + * Description Sets Outgoing QoS values for Interrupt L2CAP Channel + * + * Returns tHID_STATUS + * + ******************************************************************************/ +extern tHID_STATUS HID_DevSetOutgoingQos( + uint8_t service_type, uint32_t token_rate, uint32_t token_bucket_size, + uint32_t peak_bandwidth, uint32_t latency, uint32_t delay_variation); + +/******************************************************************************* + * + * Function HID_DevSetTraceLevel + * + * Description This function sets the trace level for HID Dev. If called + * with a value of 0xFF, it simply reads the current trace level. + * + * Returns the new (current) trace level + * + ******************************************************************************/ +extern uint8_t HID_DevSetTraceLevel(uint8_t new_level); + +#ifdef __cplusplus +} +#endif + +#endif +#endif /* HIDD_API_H */ diff --git a/components/bt/host/bluedroid/stack/include/stack/hiddefs.h b/components/bt/host/bluedroid/stack/include/stack/hiddefs.h index fab7ce2b53..71dd73e052 100644 --- a/components/bt/host/bluedroid/stack/include/stack/hiddefs.h +++ b/components/bt/host/bluedroid/stack/include/stack/hiddefs.h @@ -25,7 +25,8 @@ #ifndef HIDDEFS_H #define HIDDEFS_H #include "common/bt_target.h" -#if (HID_HOST_INCLUDED == TRUE) + +#if (HID_HOST_INCLUDED == TRUE || HID_DEV_INCLUDED == TRUE) #if (SDP_INCLUDED == TRUE) #include "stack/sdp_api.h" diff --git a/components/bt/host/bluedroid/stack/include/stack/hidh_api.h b/components/bt/host/bluedroid/stack/include/stack/hidh_api.h index 3211138cd4..2ddaf1c51a 100644 --- a/components/bt/host/bluedroid/stack/include/stack/hidh_api.h +++ b/components/bt/host/bluedroid/stack/include/stack/hidh_api.h @@ -139,6 +139,17 @@ extern tHID_STATUS HID_HostDeregister(void); extern tHID_STATUS HID_HostAddDev (BD_ADDR addr, UINT16 attr_mask, UINT8 *handle ); +/******************************************************************************* +** +** Function HID_HostGetDev +** +** Description This is called so HID-host can find this device. +** +** Returns tHID_STATUS +** +*******************************************************************************/ +extern tHID_STATUS HID_HostGetDev(BD_ADDR addr, UINT8 *handle); + /******************************************************************************* ** ** Function HID_HostRemoveDev @@ -191,9 +202,18 @@ extern tHID_STATUS HID_HostCloseDev(UINT8 dev_handle ); ** ** Description This function initializes the control block and trace variable ** +** Returns tHID_STATUS +*******************************************************************************/ +extern tHID_STATUS HID_HostInit(void); + +/******************************************************************************* +** Function HID_HostDeinit +** +** Description This function deinitializes the control block +** ** Returns void *******************************************************************************/ -extern void HID_HostInit(void); +extern void HID_HostDeinit(void); /******************************************************************************* ** Function HID_HostSetSecurityLevel diff --git a/components/bt/host/nimble/Kconfig.in b/components/bt/host/nimble/Kconfig.in index dac35641e8..a3a23e1574 100644 --- a/components/bt/host/nimble/Kconfig.in +++ b/components/bt/host/nimble/Kconfig.in @@ -44,8 +44,6 @@ choice BT_NIMBLE_LOG_LEVEL config BT_NIMBLE_LOG_LEVEL_NONE bool "No logs" - config BT_NIMBLE_LOG_LEVEL_CRIT - bool "Critical logs" config BT_NIMBLE_LOG_LEVEL_ERROR bool "Error logs" config BT_NIMBLE_LOG_LEVEL_WARNING @@ -62,8 +60,7 @@ config BT_NIMBLE_LOG_LEVEL default 1 if BT_NIMBLE_LOG_LEVEL_INFO default 2 if BT_NIMBLE_LOG_LEVEL_WARNING default 3 if BT_NIMBLE_LOG_LEVEL_ERROR - default 4 if BT_NIMBLE_LOG_LEVEL_CRIT - default 5 if BT_NIMBLE_LOG_LEVEL_NONE + default 4 if BT_NIMBLE_LOG_LEVEL_NONE config BT_NIMBLE_MAX_CONNECTIONS int "Maximum number of concurrent connections" diff --git a/components/bt/host/nimble/nimble b/components/bt/host/nimble/nimble index aef55bbf63..6a06e0459e 160000 --- a/components/bt/host/nimble/nimble +++ b/components/bt/host/nimble/nimble @@ -1 +1 @@ -Subproject commit aef55bbf636ed580d4d6408a5c2e75d1f70a875e +Subproject commit 6a06e0459e43771066160f5cfade55bb749fbacd diff --git a/components/bt/include/esp32/include/esp_bt.h b/components/bt/include/esp32/include/esp_bt.h index c80dab202a..7c8f2ea744 100644 --- a/components/bt/include/esp32/include/esp_bt.h +++ b/components/bt/include/esp32/include/esp_bt.h @@ -149,6 +149,12 @@ the adv packet will be discarded until the memory is restored. */ #define BTDM_CTRL_AUTO_LATENCY_EFF false #endif +#ifdef CONFIG_BTDM_CTRL_HLI +#define BTDM_CTRL_HLI CONFIG_BTDM_CTRL_HLI +#else +#define BTDM_CTRL_HLI false +#endif + #ifdef CONFIG_BTDM_CTRL_LEGACY_AUTH_VENDOR_EVT_EFF #define BTDM_CTRL_LEGACY_AUTH_VENDOR_EVT_EFF CONFIG_BTDM_CTRL_LEGACY_AUTH_VENDOR_EVT_EFF #else @@ -183,6 +189,7 @@ the adv packet will be discarded until the memory is restored. */ .ble_sca = CONFIG_BTDM_BLE_SLEEP_CLOCK_ACCURACY_INDEX_EFF, \ .pcm_role = CONFIG_BTDM_CTRL_PCM_ROLE_EFF, \ .pcm_polar = CONFIG_BTDM_CTRL_PCM_POLAR_EFF, \ + .hli = BTDM_CTRL_HLI, \ .magic = ESP_BT_CONTROLLER_CONFIG_MAGIC_VAL, \ }; @@ -224,6 +231,7 @@ typedef struct { uint8_t ble_sca; /*!< BLE low power crystal accuracy index */ uint8_t pcm_role; /*!< PCM role (master & slave)*/ uint8_t pcm_polar; /*!< PCM polar trig (falling clk edge & rising clk edge) */ + bool hli; /*!< Using high level interrupt or not */ uint32_t magic; /*!< Magic number */ } esp_bt_controller_config_t; @@ -383,12 +391,6 @@ esp_err_t esp_bt_controller_disable(void); */ esp_bt_controller_status_t esp_bt_controller_get_status(void); -/** - * @brief Get BT MAC address. - * @return Array pointer of length 6 storing MAC address value. - */ -uint8_t* esp_bt_get_mac(void); - /** @brief esp_vhci_host_callback * used for vhci call host function to notify what host need to do */ diff --git a/components/bt/include/esp32c3/include/esp_bt.h b/components/bt/include/esp32c3/include/esp_bt.h index 78f6691740..8860d75ff6 100644 --- a/components/bt/include/esp32c3/include/esp_bt.h +++ b/components/bt/include/esp32c3/include/esp_bt.h @@ -527,12 +527,6 @@ void esp_bt_controller_wakeup_request(void); */ int esp_bt_h4tl_eif_io_event_notify(int event); -/** - * @brief Get BT MAC address. - * @return Array pointer of length 6 storing MAC address value. - */ -uint8_t* esp_bt_get_mac(void); - #ifdef __cplusplus } #endif diff --git a/components/bt/include/esp32s3/include/esp_bt.h b/components/bt/include/esp32s3/include/esp_bt.h index 8e6d6caf28..3bda8248f0 100644 --- a/components/bt/include/esp32s3/include/esp_bt.h +++ b/components/bt/include/esp32s3/include/esp_bt.h @@ -526,12 +526,6 @@ void esp_bt_controller_wakeup_request(void); */ int esp_bt_h4tl_eif_io_event_notify(int event); -/** - * @brief Get BT MAC address. - * @return Array pointer of length 6 storing MAC address value. - */ -uint8_t* esp_bt_get_mac(void); - #ifdef __cplusplus } #endif diff --git a/components/cbor/CMakeLists.txt b/components/cbor/CMakeLists.txt index cb31da5e5a..f213c22733 100644 --- a/components/cbor/CMakeLists.txt +++ b/components/cbor/CMakeLists.txt @@ -14,8 +14,7 @@ idf_component_register(SRCS "tinycbor/src/cborencoder_close_container_checked.c" # for open_memstream.c set_source_files_properties(tinycbor/src/open_memstream.c PROPERTIES COMPILE_DEFINITIONS "__linux__") -# cbortojson.c:378:17: assignment discards 'const' qualifier from pointer target type -target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-discarded-qualifiers") - -# cborvalidation.c:429:22: 'valf' may be used uninitialized -target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-maybe-uninitialized") +# workaround for the fact that we are passing -ffreestanding to Clang +if(CMAKE_C_COMPILER_ID MATCHES "Clang") + target_compile_options(${COMPONENT_LIB} PRIVATE "-U __STDC_HOSTED__") +endif() diff --git a/components/cbor/component.mk b/components/cbor/component.mk index 7f4f1b9632..211ec49ffd 100644 --- a/components/cbor/component.mk +++ b/components/cbor/component.mk @@ -4,5 +4,3 @@ COMPONENT_SRCDIRS := tinycbor/src COMPONENT_PRIV_INCLUDEDIRS := tinycbor/src tinycbor/src/open_memstream.o: CFLAGS += -D__linux__ -tinycbor/src/cbortojson.o: CFLAGS += -Wno-discarded-qualifiers -tinycbor/src/cborvalidation.o: CFLAGS += -Wno-maybe-uninitialized diff --git a/components/coap/CMakeLists.txt b/components/coap/CMakeLists.txt index 2c3b57e1a2..77576e0a40 100644 --- a/components/coap/CMakeLists.txt +++ b/components/coap/CMakeLists.txt @@ -6,17 +6,24 @@ if(NOT CONFIG_LWIP_IPV6 AND NOT CMAKE_BUILD_EARLY_EXPANSION) return() endif() -set(include_dirs port/include port/include/coap libcoap/include libcoap/include/coap2) +set(include_dirs port/include port/include libcoap/include) set(srcs "libcoap/src/address.c" "libcoap/src/async.c" "libcoap/src/block.c" + "libcoap/src/coap_asn1.c" + "libcoap/src/coap_cache.c" + "libcoap/src/coap_debug.c" "libcoap/src/coap_event.c" "libcoap/src/coap_hashkey.c" + "libcoap/src/coap_io.c" + "libcoap/src/coap_mbedtls.c" + "libcoap/src/coap_notls.c" + "libcoap/src/coap_prng.c" "libcoap/src/coap_session.c" + "libcoap/src/coap_tcp.c" "libcoap/src/coap_time.c" - "port/coap_debug.c" "libcoap/src/encode.c" "libcoap/src/mem.c" "libcoap/src/net.c" @@ -25,17 +32,14 @@ set(srcs "libcoap/src/resource.c" "libcoap/src/str.c" "libcoap/src/subscribe.c" - "libcoap/src/uri.c" - "libcoap/src/coap_io.c" - "port/coap_notls.c" - "port/coap_mbedtls.c") + "libcoap/src/uri.c") idf_component_register(SRCS "${srcs}" INCLUDE_DIRS "${include_dirs}" REQUIRES lwip mbedtls) # Silence format truncation warning, until it is fixed upstream -set_source_files_properties(port/coap_debug.c PROPERTIES COMPILE_FLAGS -Wno-format-truncation) +# set_source_files_properties(libcoap/src/coap_debug.c PROPERTIES COMPILE_FLAGS -Wno-format-truncation) # Needed for coap headers in public builds, also. # diff --git a/components/coap/Kconfig b/components/coap/Kconfig index a5d613e146..1221523c2b 100644 --- a/components/coap/Kconfig +++ b/components/coap/Kconfig @@ -52,6 +52,8 @@ menu "CoAP Configuration" bool "Info" config COAP_LOG_DEBUG bool "Debug" + config COAP_LOG_MBEDTLS + bool "mbedTLS" endchoice config COAP_LOG_DEFAULT_LEVEL @@ -65,5 +67,6 @@ menu "CoAP Configuration" default 5 if COAP_LOG_NOTICE default 6 if COAP_LOG_INFO default 7 if COAP_LOG_DEBUG + default 9 if COAP_LOG_MBEDTLS endmenu diff --git a/components/coap/component.mk b/components/coap/component.mk index eeec323f0c..19ef7fd50b 100644 --- a/components/coap/component.mk +++ b/components/coap/component.mk @@ -4,15 +4,15 @@ ifdef CONFIG_LWIP_IPV6 -COMPONENT_ADD_INCLUDEDIRS := port/include port/include/coap libcoap/include libcoap/include/coap2 +COMPONENT_ADD_INCLUDEDIRS := port/include port/include libcoap/include -COMPONENT_OBJS = libcoap/src/address.o libcoap/src/async.o libcoap/src/block.o libcoap/src/coap_event.o libcoap/src/coap_hashkey.o libcoap/src/coap_session.o libcoap/src/coap_time.o port/coap_debug.o libcoap/src/encode.o libcoap/src/mem.o libcoap/src/net.o libcoap/src/option.o libcoap/src/pdu.o libcoap/src/resource.o libcoap/src/str.o libcoap/src/subscribe.o libcoap/src/uri.o port/coap_mbedtls.o libcoap/src/coap_io.o port/coap_notls.o +COMPONENT_OBJS = libcoap/src/address.o libcoap/src/async.o libcoap/src/block.o libcoap/src/coap_asn1.o libcoap/src/coap_cache.o libcoap/src/coap_debug.o libcoap/src/coap_event.o libcoap/src/coap_hashkey.o libcoap/src/coap_io.o libcoap/src/coap_mbedtls.o libcoap/src/coap_notls.o libcoap/src/coap_prng.o libcoap/src/coap_session.o libcoap/src/coap_tcp.o libcoap/src/coap_time.o libcoap/src/encode.o libcoap/src/mem.o libcoap/src/net.o libcoap/src/option.o libcoap/src/pdu.o libcoap/src/resource.o libcoap/src/str.o libcoap/src/subscribe.o libcoap/src/uri.o COMPONENT_SRCDIRS := libcoap/src libcoap port COMPONENT_SUBMODULES += libcoap # Silence format truncation warning, until it is fixed upstream -port/coap_debug.o: CFLAGS += -Wno-format-truncation +# libcoap/src/coap_debug.o: CFLAGS += -Wno-format-truncation endif # CONFIG_LWIP_IPV6 diff --git a/components/coap/libcoap b/components/coap/libcoap index 98954eb30a..9b6451c365 160000 --- a/components/coap/libcoap +++ b/components/coap/libcoap @@ -1 +1 @@ -Subproject commit 98954eb30a2e728e172a6cd29430ae5bc999b585 +Subproject commit 9b6451c3654bc1f625e36c87f018c2da34bea5e6 diff --git a/components/coap/port/coap_debug.c b/components/coap/port/coap_debug.c deleted file mode 100644 index 64d6a01800..0000000000 --- a/components/coap/port/coap_debug.c +++ /dev/null @@ -1,888 +0,0 @@ -/* debug.c -- debug utilities - * - * Copyright (C) 2010--2012,2014--2019 Olaf Bergmann and others - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - -#include "coap_config.h" - -#if defined(HAVE_STRNLEN) && defined(__GNUC__) && !defined(_GNU_SOURCE) -#define _GNU_SOURCE 1 -#endif - -#if defined(HAVE_ASSERT_H) && !defined(assert) -# include -#endif - -#include -#include -#include -#include - -#ifdef HAVE_ARPA_INET_H -#include -#endif -#ifdef HAVE_WS2TCPIP_H -#include -#endif - -#ifdef HAVE_TIME_H -#include -#endif - -#include "libcoap.h" -#include "coap_dtls.h" -#include "block.h" -#include "coap_debug.h" -#include "encode.h" -#include "net.h" -#include "coap_mutex.h" - -#ifdef WITH_LWIP -# define fprintf(fd, ...) LWIP_PLATFORM_DIAG((__VA_ARGS__)) -# define fflush(...) -#endif - -#ifdef WITH_CONTIKI -# ifndef DEBUG -# define DEBUG DEBUG_PRINT -# endif /* DEBUG */ -#include "net/ip/uip-debug.h" -#endif - -static coap_log_t maxlog = LOG_WARNING; /* default maximum log level */ - -static int use_fprintf_for_show_pdu = 1; /* non zero to output with fprintf */ - -const char *coap_package_name(void) { - return PACKAGE_NAME; -} - -const char *coap_package_version(void) { - return PACKAGE_STRING; -} - -void -coap_set_show_pdu_output(int use_fprintf) { - use_fprintf_for_show_pdu = use_fprintf; -} - -coap_log_t -coap_get_log_level(void) { - return maxlog; -} - -void -coap_set_log_level(coap_log_t level) { - maxlog = level; -} - -/* this array has the same order as the type log_t */ -static const char *loglevels[] = { - "EMRG", "ALRT", "CRIT", "ERR ", "WARN", "NOTE", "INFO", "DEBG" -}; - -#ifdef HAVE_TIME_H - -COAP_STATIC_INLINE size_t -print_timestamp(char *s, size_t len, coap_tick_t t) { - struct tm *tmp; - time_t now = coap_ticks_to_rt(t); - tmp = localtime(&now); - return strftime(s, len, "%b %d %H:%M:%S", tmp); -} - -#else /* alternative implementation: just print the timestamp */ - -COAP_STATIC_INLINE size_t -print_timestamp(char *s, size_t len, coap_tick_t t) { -#ifdef HAVE_SNPRINTF - return snprintf(s, len, "%u.%03u", - (unsigned int)coap_ticks_to_rt(t), - (unsigned int)(t % COAP_TICKS_PER_SECOND)); -#else /* HAVE_SNPRINTF */ - /* @todo do manual conversion of timestamp */ - return 0; -#endif /* HAVE_SNPRINTF */ -} - -#endif /* HAVE_TIME_H */ - -#ifndef HAVE_STRNLEN -/** - * A length-safe strlen() fake. - * - * @param s The string to count characters != 0. - * @param maxlen The maximum length of @p s. - * - * @return The length of @p s. - */ -static inline size_t -strnlen(const char *s, size_t maxlen) { - size_t n = 0; - while(*s++ && n < maxlen) - ++n; - return n; -} -#endif /* HAVE_STRNLEN */ - -static size_t -print_readable( const uint8_t *data, size_t len, - unsigned char *result, size_t buflen, int encode_always ) { - const uint8_t hex[] = "0123456789ABCDEF"; - size_t cnt = 0; - assert(data || len == 0); - - if (buflen == 0) { /* there is nothing we can do here but return */ - return 0; - } - - while (len) { - if (!encode_always && isprint(*data)) { - if (cnt+1 < buflen) { /* keep one byte for terminating zero */ - *result++ = *data; - ++cnt; - } else { - break; - } - } else { - if (cnt+4 < buflen) { /* keep one byte for terminating zero */ - *result++ = '\\'; - *result++ = 'x'; - *result++ = hex[(*data & 0xf0) >> 4]; - *result++ = hex[*data & 0x0f]; - cnt += 4; - } else - break; - } - - ++data; --len; - } - - *result = '\0'; /* add a terminating zero */ - return cnt; -} - -#ifndef min -#define min(a,b) ((a) < (b) ? (a) : (b)) -#endif - -size_t -coap_print_addr(const struct coap_address_t *addr, unsigned char *buf, size_t len) { -#if defined( HAVE_ARPA_INET_H ) || defined( HAVE_WS2TCPIP_H ) - const void *addrptr = NULL; - in_port_t port; - unsigned char *p = buf; - size_t need_buf; - - switch (addr->addr.sa.sa_family) { - case AF_INET: - addrptr = &addr->addr.sin.sin_addr; - port = ntohs(addr->addr.sin.sin_port); - need_buf = INET_ADDRSTRLEN; - break; - case AF_INET6: - if (len < 7) /* do not proceed if buffer is even too short for [::]:0 */ - return 0; - - *p++ = '['; - - addrptr = &addr->addr.sin6.sin6_addr; - port = ntohs(addr->addr.sin6.sin6_port); - need_buf = INET6_ADDRSTRLEN; - - break; - default: - memcpy(buf, "(unknown address type)", min(22, len)); - return min(22, len); - } - - /* Cast needed for Windows, since it doesn't have the correct API signature. */ - if (inet_ntop(addr->addr.sa.sa_family, addrptr, (char *)p, - min(len, need_buf)) == 0) { - perror("coap_print_addr"); - return 0; - } - - p += strnlen((char *)p, len); - - if (addr->addr.sa.sa_family == AF_INET6) { - if (p < buf + len) { - *p++ = ']'; - } else - return 0; - } - - p += snprintf((char *)p, buf + len - p + 1, ":%d", port); - - return buf + len - p; -#else /* HAVE_ARPA_INET_H */ -# if WITH_CONTIKI - unsigned char *p = buf; - uint8_t i; -# if NETSTACK_CONF_WITH_IPV6 - const uint8_t hex[] = "0123456789ABCDEF"; - - if (len < 41) - return 0; - - *p++ = '['; - - for (i=0; i < 16; i += 2) { - if (i) { - *p++ = ':'; - } - *p++ = hex[(addr->addr.u8[i] & 0xf0) >> 4]; - *p++ = hex[(addr->addr.u8[i] & 0x0f)]; - *p++ = hex[(addr->addr.u8[i+1] & 0xf0) >> 4]; - *p++ = hex[(addr->addr.u8[i+1] & 0x0f)]; - } - *p++ = ']'; -# else /* WITH_UIP6 */ -# warning "IPv4 network addresses will not be included in debug output" - - if (len < 21) - return 0; -# endif /* WITH_UIP6 */ - if (buf + len - p < 6) - return 0; - -#ifdef HAVE_SNPRINTF - p += snprintf((char *)p, buf + len - p + 1, ":%d", uip_htons(addr->port)); -#else /* HAVE_SNPRINTF */ - /* @todo manual conversion of port number */ -#endif /* HAVE_SNPRINTF */ - - return p - buf; -# else /* WITH_CONTIKI */ - /* TODO: output addresses manually */ -# warning "inet_ntop() not available, network addresses will not be included in debug output" -# endif /* WITH_CONTIKI */ - return 0; -#endif -} - -#ifdef WITH_CONTIKI -# define fprintf(fd, ...) PRINTF(__VA_ARGS__) -# define fflush(...) - -# ifdef HAVE_VPRINTF -# define vfprintf(fd, ...) vprintf(__VA_ARGS__) -# else /* HAVE_VPRINTF */ -# define vfprintf(fd, ...) PRINTF(__VA_ARGS__) -# endif /* HAVE_VPRINTF */ -#endif /* WITH_CONTIKI */ - -/** Returns a textual description of the message type @p t. */ -static const char * -msg_type_string(uint16_t t) { - static const char *types[] = { "CON", "NON", "ACK", "RST", "???" }; - - return types[min(t, sizeof(types)/sizeof(char *) - 1)]; -} - -/** Returns a textual description of the method or response code. */ -static const char * -msg_code_string(uint16_t c) { - static const char *methods[] = { "0.00", "GET", "POST", "PUT", "DELETE", - "FETCH", "PATCH", "iPATCH" }; - static const char *signals[] = { "7.00", "CSM", "Ping", "Pong", "Release", - "Abort" }; - static char buf[5]; - - if (c < sizeof(methods)/sizeof(const char *)) { - return methods[c]; - } else if (c >= 224 && c - 224 < (int)(sizeof(signals)/sizeof(const char *))) { - return signals[c-224]; - } else { - snprintf(buf, sizeof(buf), "%u.%02u", (c >> 5) & 0x7, c & 0x1f); - return buf; - } -} - -/** Returns a textual description of the option name. */ -static const char * -msg_option_string(uint8_t code, uint16_t option_type) { - struct option_desc_t { - uint16_t type; - const char *name; - }; - - static struct option_desc_t options[] = { - { COAP_OPTION_IF_MATCH, "If-Match" }, - { COAP_OPTION_URI_HOST, "Uri-Host" }, - { COAP_OPTION_ETAG, "ETag" }, - { COAP_OPTION_IF_NONE_MATCH, "If-None-Match" }, - { COAP_OPTION_OBSERVE, "Observe" }, - { COAP_OPTION_URI_PORT, "Uri-Port" }, - { COAP_OPTION_LOCATION_PATH, "Location-Path" }, - { COAP_OPTION_URI_PATH, "Uri-Path" }, - { COAP_OPTION_CONTENT_FORMAT, "Content-Format" }, - { COAP_OPTION_MAXAGE, "Max-Age" }, - { COAP_OPTION_URI_QUERY, "Uri-Query" }, - { COAP_OPTION_ACCEPT, "Accept" }, - { COAP_OPTION_LOCATION_QUERY, "Location-Query" }, - { COAP_OPTION_BLOCK2, "Block2" }, - { COAP_OPTION_BLOCK1, "Block1" }, - { COAP_OPTION_PROXY_URI, "Proxy-Uri" }, - { COAP_OPTION_PROXY_SCHEME, "Proxy-Scheme" }, - { COAP_OPTION_SIZE1, "Size1" }, - { COAP_OPTION_SIZE2, "Size2" }, - { COAP_OPTION_NORESPONSE, "No-Response" } - }; - - static struct option_desc_t options_csm[] = { - { COAP_SIGNALING_OPTION_MAX_MESSAGE_SIZE, "Max-Message-Size" }, - { COAP_SIGNALING_OPTION_BLOCK_WISE_TRANSFER, "Block-wise-Transfer" } - }; - - static struct option_desc_t options_pingpong[] = { - { COAP_SIGNALING_OPTION_CUSTODY, "Custody" } - }; - - static struct option_desc_t options_release[] = { - { COAP_SIGNALING_OPTION_ALTERNATIVE_ADDRESS, "Alternative-Address" }, - { COAP_SIGNALING_OPTION_HOLD_OFF, "Hold-Off" } - }; - - static struct option_desc_t options_abort[] = { - { COAP_SIGNALING_OPTION_BAD_CSM_OPTION, "Bad-CSM-Option" } - }; - - static char buf[6]; - size_t i; - - if (code == COAP_SIGNALING_CSM) { - for (i = 0; i < sizeof(options_csm)/sizeof(struct option_desc_t); i++) { - if (option_type == options_csm[i].type) { - return options_csm[i].name; - } - } - } else if (code == COAP_SIGNALING_PING || code == COAP_SIGNALING_PONG) { - for (i = 0; i < sizeof(options_pingpong)/sizeof(struct option_desc_t); i++) { - if (option_type == options_pingpong[i].type) { - return options_pingpong[i].name; - } - } - } else if (code == COAP_SIGNALING_RELEASE) { - for (i = 0; i < sizeof(options_release)/sizeof(struct option_desc_t); i++) { - if (option_type == options_release[i].type) { - return options_release[i].name; - } - } - } else if (code == COAP_SIGNALING_ABORT) { - for (i = 0; i < sizeof(options_abort)/sizeof(struct option_desc_t); i++) { - if (option_type == options_abort[i].type) { - return options_abort[i].name; - } - } - } else { - /* search option_type in list of known options */ - for (i = 0; i < sizeof(options)/sizeof(struct option_desc_t); i++) { - if (option_type == options[i].type) { - return options[i].name; - } - } - } - /* unknown option type, just print to buf */ - snprintf(buf, sizeof(buf), "%u", option_type); - return buf; -} - -static unsigned int -print_content_format(unsigned int format_type, - unsigned char *result, unsigned int buflen) { - struct desc_t { - unsigned int type; - const char *name; - }; - - static struct desc_t formats[] = { - { COAP_MEDIATYPE_TEXT_PLAIN, "text/plain" }, - { COAP_MEDIATYPE_APPLICATION_LINK_FORMAT, "application/link-format" }, - { COAP_MEDIATYPE_APPLICATION_XML, "application/xml" }, - { COAP_MEDIATYPE_APPLICATION_OCTET_STREAM, "application/octet-stream" }, - { COAP_MEDIATYPE_APPLICATION_EXI, "application/exi" }, - { COAP_MEDIATYPE_APPLICATION_JSON, "application/json" }, - { COAP_MEDIATYPE_APPLICATION_CBOR, "application/cbor" }, - { COAP_MEDIATYPE_APPLICATION_COSE_SIGN, "application/cose; cose-type=\"cose-sign\"" }, - { COAP_MEDIATYPE_APPLICATION_COSE_SIGN1, "application/cose; cose-type=\"cose-sign1\"" }, - { COAP_MEDIATYPE_APPLICATION_COSE_ENCRYPT, "application/cose; cose-type=\"cose-encrypt\"" }, - { COAP_MEDIATYPE_APPLICATION_COSE_ENCRYPT0, "application/cose; cose-type=\"cose-encrypt0\"" }, - { COAP_MEDIATYPE_APPLICATION_COSE_MAC, "application/cose; cose-type=\"cose-mac\"" }, - { COAP_MEDIATYPE_APPLICATION_COSE_MAC0, "application/cose; cose-type=\"cose-mac0\"" }, - { COAP_MEDIATYPE_APPLICATION_COSE_KEY, "application/cose-key" }, - { COAP_MEDIATYPE_APPLICATION_COSE_KEY_SET, "application/cose-key-set" }, - { COAP_MEDIATYPE_APPLICATION_SENML_JSON, "application/senml+json" }, - { COAP_MEDIATYPE_APPLICATION_SENSML_JSON, "application/sensml+json" }, - { COAP_MEDIATYPE_APPLICATION_SENML_CBOR, "application/senml+cbor" }, - { COAP_MEDIATYPE_APPLICATION_SENSML_CBOR, "application/sensml+cbor" }, - { COAP_MEDIATYPE_APPLICATION_SENML_EXI, "application/senml-exi" }, - { COAP_MEDIATYPE_APPLICATION_SENSML_EXI, "application/sensml-exi" }, - { COAP_MEDIATYPE_APPLICATION_SENML_XML, "application/senml+xml" }, - { COAP_MEDIATYPE_APPLICATION_SENSML_XML, "application/sensml+xml" }, - { 75, "application/dcaf+cbor" } - }; - - size_t i; - - /* search format_type in list of known content formats */ - for (i = 0; i < sizeof(formats)/sizeof(struct desc_t); i++) { - if (format_type == formats[i].type) { - return snprintf((char *)result, buflen, "%s", formats[i].name); - } - } - - /* unknown content format, just print numeric value to buf */ - return snprintf((char *)result, buflen, "%d", format_type); -} - -/** - * Returns 1 if the given @p content_format is either unknown or known - * to carry binary data. The return value @c 0 hence indicates - * printable data which is also assumed if @p content_format is @c 01. - */ -COAP_STATIC_INLINE int -is_binary(int content_format) { - return !(content_format == -1 || - content_format == COAP_MEDIATYPE_TEXT_PLAIN || - content_format == COAP_MEDIATYPE_APPLICATION_LINK_FORMAT || - content_format == COAP_MEDIATYPE_APPLICATION_XML || - content_format == COAP_MEDIATYPE_APPLICATION_JSON); -} - -#define COAP_DO_SHOW_OUTPUT_LINE \ - do { \ - if (use_fprintf_for_show_pdu) { \ - fprintf(COAP_DEBUG_FD, "%s", outbuf); \ - } \ - else { \ - coap_log(level, "%s", outbuf); \ - } \ - } while (0) - -void -coap_show_pdu(coap_log_t level, const coap_pdu_t *pdu) { -#if COAP_CONSTRAINED_STACK - static coap_mutex_t static_show_pdu_mutex = COAP_MUTEX_INITIALIZER; - static unsigned char buf[1024]; /* need some space for output creation */ - static char outbuf[COAP_DEBUG_BUF_SIZE]; -#else /* ! COAP_CONSTRAINED_STACK */ - unsigned char buf[1024]; /* need some space for output creation */ - char outbuf[COAP_DEBUG_BUF_SIZE]; -#endif /* ! COAP_CONSTRAINED_STACK */ - size_t buf_len = 0; /* takes the number of bytes written to buf */ - int encode = 0, have_options = 0, i; - coap_opt_iterator_t opt_iter; - coap_opt_t *option; - int content_format = -1; - size_t data_len; - unsigned char *data; - int outbuflen = 0; - - /* Save time if not needed */ - if (level > coap_get_log_level()) - return; - -#if COAP_CONSTRAINED_STACK - coap_mutex_lock(&static_show_pdu_mutex); -#endif /* COAP_CONSTRAINED_STACK */ - - snprintf(outbuf, sizeof(outbuf), "v:%d t:%s c:%s i:%04x {", - COAP_DEFAULT_VERSION, msg_type_string(pdu->type), - msg_code_string(pdu->code), pdu->tid); - - for (i = 0; i < pdu->token_length; i++) { - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, - "%02x", pdu->token[i]); - } - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, "}"); - - /* show options, if any */ - coap_option_iterator_init(pdu, &opt_iter, COAP_OPT_ALL); - - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, " ["); - while ((option = coap_option_next(&opt_iter))) { - if (!have_options) { - have_options = 1; - } else { - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, ","); - } - - if (pdu->code == COAP_SIGNALING_CSM) switch(opt_iter.type) { - case COAP_SIGNALING_OPTION_MAX_MESSAGE_SIZE: - buf_len = snprintf((char *)buf, sizeof(buf), "%u", - coap_decode_var_bytes(coap_opt_value(option), - coap_opt_length(option))); - break; - default: - buf_len = 0; - break; - } else if (pdu->code == COAP_SIGNALING_PING - || pdu->code == COAP_SIGNALING_PONG) { - buf_len = 0; - } else if (pdu->code == COAP_SIGNALING_RELEASE) switch(opt_iter.type) { - case COAP_SIGNALING_OPTION_ALTERNATIVE_ADDRESS: - buf_len = print_readable(coap_opt_value(option), - coap_opt_length(option), - buf, sizeof(buf), 0); - break; - case COAP_SIGNALING_OPTION_HOLD_OFF: - buf_len = snprintf((char *)buf, sizeof(buf), "%u", - coap_decode_var_bytes(coap_opt_value(option), - coap_opt_length(option))); - break; - default: - buf_len = 0; - break; - } else if (pdu->code == COAP_SIGNALING_ABORT) switch(opt_iter.type) { - case COAP_SIGNALING_OPTION_BAD_CSM_OPTION: - buf_len = snprintf((char *)buf, sizeof(buf), "%u", - coap_decode_var_bytes(coap_opt_value(option), - coap_opt_length(option))); - break; - default: - buf_len = 0; - break; - } else switch (opt_iter.type) { - case COAP_OPTION_CONTENT_FORMAT: - content_format = (int)coap_decode_var_bytes(coap_opt_value(option), - coap_opt_length(option)); - - buf_len = print_content_format(content_format, buf, sizeof(buf)); - break; - - case COAP_OPTION_BLOCK1: - case COAP_OPTION_BLOCK2: - /* split block option into number/more/size where more is the - * letter M if set, the _ otherwise */ - buf_len = snprintf((char *)buf, sizeof(buf), "%u/%c/%u", - coap_opt_block_num(option), /* block number */ - COAP_OPT_BLOCK_MORE(option) ? 'M' : '_', /* M bit */ - (1 << (COAP_OPT_BLOCK_SZX(option) + 4))); /* block size */ - - break; - - case COAP_OPTION_URI_PORT: - case COAP_OPTION_MAXAGE: - case COAP_OPTION_OBSERVE: - case COAP_OPTION_SIZE1: - case COAP_OPTION_SIZE2: - /* show values as unsigned decimal value */ - buf_len = snprintf((char *)buf, sizeof(buf), "%u", - coap_decode_var_bytes(coap_opt_value(option), - coap_opt_length(option))); - break; - - default: - /* generic output function for all other option types */ - if (opt_iter.type == COAP_OPTION_URI_PATH || - opt_iter.type == COAP_OPTION_PROXY_URI || - opt_iter.type == COAP_OPTION_URI_HOST || - opt_iter.type == COAP_OPTION_LOCATION_PATH || - opt_iter.type == COAP_OPTION_LOCATION_QUERY || - opt_iter.type == COAP_OPTION_URI_QUERY) { - encode = 0; - } else { - encode = 1; - } - - buf_len = print_readable(coap_opt_value(option), - coap_opt_length(option), - buf, sizeof(buf), encode); - } - - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, - " %s:%.*s", msg_option_string(pdu->code, opt_iter.type), - (int)buf_len, buf); - } - - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, " ]"); - - if (coap_get_data(pdu, &data_len, &data)) { - - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, " :: "); - - if (is_binary(content_format)) { - int keep_data_len = data_len; - uint8_t *keep_data = data; - - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, - "binary data length %zu\n", data_len); - COAP_DO_SHOW_OUTPUT_LINE; - /* - * Output hex dump of binary data as a continuous entry - */ - outbuf[0] = '\000'; - snprintf(outbuf, sizeof(outbuf), "<<"); - while (data_len--) { - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, - "%02x", *data++); - } - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, ">>"); - data_len = keep_data_len; - data = keep_data; - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, "\n"); - COAP_DO_SHOW_OUTPUT_LINE; - /* - * Output ascii readable (if possible), immediately under the - * hex value of the character output above to help binary debugging - */ - outbuf[0] = '\000'; - snprintf(outbuf, sizeof(outbuf), "<<"); - while (data_len--) { - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, - "%c ", isprint (*data) ? *data : '.'); - data++; - } - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, ">>"); - } else { - if (print_readable(data, data_len, buf, sizeof(buf), 0)) { - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, "'%s'", buf); - } - } - } - - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, "\n"); - COAP_DO_SHOW_OUTPUT_LINE; - -#if COAP_CONSTRAINED_STACK - coap_mutex_unlock(&static_show_pdu_mutex); -#endif /* COAP_CONSTRAINED_STACK */ -} - -void coap_show_tls_version(coap_log_t level) -{ - char buffer[64]; - coap_string_tls_version(buffer, sizeof(buffer)); - coap_log(level, "%s\n", buffer); -} - -char *coap_string_tls_version(char *buffer, size_t bufsize) -{ - coap_tls_version_t *tls_version = coap_get_tls_library_version(); - char beta[8]; - char sub[2]; - char b_beta[8]; - char b_sub[2]; - - switch (tls_version->type) { - case COAP_TLS_LIBRARY_NOTLS: - snprintf(buffer, bufsize, "TLS Library: None"); - break; - case COAP_TLS_LIBRARY_TINYDTLS: - snprintf(buffer, bufsize, "TLS Library: TinyDTLS - runtime %lu.%lu.%lu, " - "libcoap built for %lu.%lu.%lu", - (unsigned long)(tls_version->version >> 16), - (unsigned long)((tls_version->version >> 8) & 0xff), - (unsigned long)(tls_version->version & 0xff), - (unsigned long)(tls_version->built_version >> 16), - (unsigned long)((tls_version->built_version >> 8) & 0xff), - (unsigned long)(tls_version->built_version & 0xff)); - break; - case COAP_TLS_LIBRARY_OPENSSL: - switch (tls_version->version &0xf) { - case 0: - strcpy(beta, "-dev"); - break; - case 0xf: - strcpy(beta, ""); - break; - default: - strcpy(beta, "-beta"); - beta[5] = (tls_version->version &0xf) + '0'; - beta[6] = '\000'; - break; - } - sub[0] = ((tls_version->version >> 4) & 0xff) ? - ((tls_version->version >> 4) & 0xff) + 'a' -1 : '\000'; - sub[1] = '\000'; - switch (tls_version->built_version &0xf) { - case 0: - strcpy(b_beta, "-dev"); - break; - case 0xf: - strcpy(b_beta, ""); - break; - default: - strcpy(b_beta, "-beta"); - b_beta[5] = (tls_version->built_version &0xf) + '0'; - b_beta[6] = '\000'; - break; - } - b_sub[0] = ((tls_version->built_version >> 4) & 0xff) ? - ((tls_version->built_version >> 4) & 0xff) + 'a' -1 : '\000'; - b_sub[1] = '\000'; - snprintf(buffer, bufsize, "TLS Library: OpenSSL - runtime " - "%lu.%lu.%lu%s%s, libcoap built for %lu.%lu.%lu%s%s", - (unsigned long)(tls_version->version >> 28), - (unsigned long)((tls_version->version >> 20) & 0xff), - (unsigned long)((tls_version->version >> 12) & 0xff), sub, beta, - (unsigned long)(tls_version->built_version >> 28), - (unsigned long)((tls_version->built_version >> 20) & 0xff), - (unsigned long)((tls_version->built_version >> 12) & 0xff), - b_sub, b_beta); - break; - case COAP_TLS_LIBRARY_GNUTLS: - snprintf(buffer, bufsize, "TLS Library: GnuTLS - runtime %lu.%lu.%lu, " - "libcoap built for %lu.%lu.%lu", - (unsigned long)(tls_version->version >> 16), - (unsigned long)((tls_version->version >> 8) & 0xff), - (unsigned long)(tls_version->version & 0xff), - (unsigned long)(tls_version->built_version >> 16), - (unsigned long)((tls_version->built_version >> 8) & 0xff), - (unsigned long)(tls_version->built_version & 0xff)); - break; - case COAP_TLS_LIBRARY_MBEDTLS: - snprintf(buffer, bufsize, "TLS Library: MbedTLS - runtime %lu.%lu.%lu, " - "libcoap built for %lu.%lu.%lu", - (unsigned long)(tls_version->version >> 24), - (unsigned long)((tls_version->version >> 16) & 0xff), - (unsigned long)((tls_version->version >> 8) & 0xff), - (unsigned long)(tls_version->built_version >> 24), - (unsigned long)((tls_version->built_version >> 16) & 0xff), - (unsigned long)((tls_version->built_version >> 8) & 0xff)); - break; - default: - snprintf(buffer, bufsize, "Library type %d unknown", tls_version->type); - break; - } - return buffer; -} - -static coap_log_handler_t log_handler = NULL; - -void coap_set_log_handler(coap_log_handler_t handler) { - log_handler = handler; -} - -void -coap_log_impl(coap_log_t level, const char *format, ...) { - - if (maxlog < level) - return; - - if (log_handler) { -#if COAP_CONSTRAINED_STACK - static coap_mutex_t static_log_mutex = COAP_MUTEX_INITIALIZER; - static char message[COAP_DEBUG_BUF_SIZE]; -#else /* ! COAP_CONSTRAINED_STACK */ - char message[COAP_DEBUG_BUF_SIZE]; -#endif /* ! COAP_CONSTRAINED_STACK */ - va_list ap; - va_start(ap, format); -#if COAP_CONSTRAINED_STACK - coap_mutex_lock(&static_log_mutex); -#endif /* COAP_CONSTRAINED_STACK */ - - vsnprintf( message, sizeof(message), format, ap); - va_end(ap); - log_handler(level, message); -#if COAP_CONSTRAINED_STACK - coap_mutex_unlock(&static_log_mutex); -#endif /* COAP_CONSTRAINED_STACK */ - } else { - char timebuf[32]; - coap_tick_t now; - va_list ap; - FILE *log_fd; - - log_fd = level <= LOG_CRIT ? COAP_ERR_FD : COAP_DEBUG_FD; - - coap_ticks(&now); - if (print_timestamp(timebuf,sizeof(timebuf), now)) - fprintf(log_fd, "%s ", timebuf); - - if (level <= LOG_DEBUG) - fprintf(log_fd, "%s ", loglevels[level]); - - va_start(ap, format); - vfprintf(log_fd, format, ap); - va_end(ap); - fflush(log_fd); - } -} - -static struct packet_num_interval { - int start; - int end; -} packet_loss_intervals[10]; -static int num_packet_loss_intervals = 0; -static int packet_loss_level = 0; -static int send_packet_count = 0; - -int coap_debug_set_packet_loss(const char *loss_level) { - const char *p = loss_level; - char *end = NULL; - int n = (int)strtol(p, &end, 10), i = 0; - if (end == p || n < 0) - return 0; - if (*end == '%') { - if (n > 100) - n = 100; - packet_loss_level = n * 65536 / 100; - coap_log(LOG_DEBUG, "packet loss level set to %d%%\n", n); - } else { - if (n <= 0) - return 0; - while (i < 10) { - packet_loss_intervals[i].start = n; - if (*end == '-') { - p = end + 1; - n = (int)strtol(p, &end, 10); - if (end == p || n <= 0) - return 0; - } - packet_loss_intervals[i++].end = n; - if (*end == 0) - break; - if (*end != ',') - return 0; - p = end + 1; - n = (int)strtol(p, &end, 10); - if (end == p || n <= 0) - return 0; - } - if (i == 10) - return 0; - num_packet_loss_intervals = i; - } - send_packet_count = 0; - return 1; -} - -int coap_debug_send_packet(void) { - ++send_packet_count; - if (num_packet_loss_intervals > 0) { - int i; - for (i = 0; i < num_packet_loss_intervals; i++) { - if (send_packet_count >= packet_loss_intervals[i].start - && send_packet_count <= packet_loss_intervals[i].end) - return 0; - } - } - if ( packet_loss_level > 0 ) { - uint16_t r = 0; - prng( (uint8_t*)&r, 2 ); - if ( r < packet_loss_level ) - return 0; - } - return 1; -} diff --git a/components/coap/port/coap_mbedtls.c b/components/coap/port/coap_mbedtls.c deleted file mode 100644 index ef016a125d..0000000000 --- a/components/coap/port/coap_mbedtls.c +++ /dev/null @@ -1,1869 +0,0 @@ -/* -* coap_mbedtls.c -- mbedTLS Datagram Transport Layer Support for libcoap -* -* Copyright (C) 2019 Jon Shallow -* 2019 Jitin George -* -* This file is part of the CoAP library libcoap. Please see README for terms -* of use. -*/ - -/* - * Naming used to prevent confusion between coap sessions, mbedtls sessions etc. - * when reading the code. - * - * c_context A coap_context_t * - * c_session A coap_session_t * - * m_context A coap_mbedtls_context_t * (held in c_context->dtls_context) - * m_env A coap_mbedtls_env_t * (held in c_session->tls) - */ - -#include "coap_config.h" - -#ifdef HAVE_MBEDTLS - -/* - * Once PS #335 has been merged in, then code following a rebase needs to be - * updated removing sections that are "#ifndef PSK2_PR", and then remove all - * references to PSK2_PR. - */ -#undef PSK2_PR - -#include "libcoap.h" -#include "coap_dtls.h" -#include "net.h" -#include "mem.h" -#include "coap_debug.h" -#include "prng.h" -#include "coap_mutex.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(ESPIDF_VERSION) && defined(CONFIG_MBEDTLS_DEBUG) -#include -#endif /* ESPIDF_VERSION && CONFIG_MBEDTLS_DEBUG */ -#include -#include - -#define mbedtls_malloc(a) malloc(a) -#define mbedtls_realloc(a,b) realloc(a,b) -#define mbedtls_strdup(a) strdup(a) - -#ifdef __GNUC__ -#define UNUSED __attribute__((unused)) -#else /* __GNUC__ */ -#define UNUSED -#endif /* __GNUC__ */ - -#define IS_PSK (1 << 0) -#define IS_PKI (1 << 1) -#define IS_CLIENT (1 << 6) -#define IS_SERVER (1 << 7) - -typedef struct coap_ssl_t { - const uint8_t *pdu; - unsigned pdu_len; - unsigned peekmode; - coap_tick_t timeout; -} coap_ssl_t; - -/* - * This structure encapsulates the mbedTLS session object. - * It handles both TLS and DTLS. - * c_session->tls points to this. - */ -typedef struct coap_mbedtls_env_t { - mbedtls_ssl_context ssl; - mbedtls_entropy_context entropy; - mbedtls_ctr_drbg_context ctr_drbg; - mbedtls_ssl_config conf; - mbedtls_timing_delay_context timer; - mbedtls_x509_crt cacert; - mbedtls_x509_crt public_cert; - mbedtls_pk_context private_key; - mbedtls_ssl_cookie_ctx cookie_ctx; - /* If not set, need to do do_mbedtls_handshake */ - int established; - int seen_client_hello; - coap_ssl_t coap_ssl_data; -} coap_mbedtls_env_t; - -typedef struct pki_sni_entry { - char *sni; - coap_dtls_key_t pki_key; - mbedtls_x509_crt cacert; - mbedtls_x509_crt public_cert; - mbedtls_pk_context private_key; -} pki_sni_entry; - -#ifdef PSK2_PR -typedef struct psk_sni_entry { - coap_string_t sni; - coap_dtls_spsk_info_t psk_info; -} psk_sni_entry; -#endif /* PSK2_PR */ - -typedef struct coap_mbedtls_context_t { - coap_dtls_pki_t setup_data; - size_t pki_sni_count; - pki_sni_entry *pki_sni_entry_list; -#ifdef PSK2_PR - size_t psk_sni_count; - psk_sni_entry *psk_sni_entry_list; -#endif /* PSK2_PR */ - char *root_ca_file; - char *root_ca_path; - int psk_pki_enabled; -} coap_mbedtls_context_t; - -static int coap_dgram_read(void *ctx, unsigned char *out, size_t outl) -{ - ssize_t ret = 0; - coap_session_t *c_session = (struct coap_session_t *)ctx; - coap_ssl_t *data = &((coap_mbedtls_env_t *)c_session->tls)->coap_ssl_data; - - if (!c_session->tls) { - errno = EAGAIN; - return MBEDTLS_ERR_SSL_WANT_READ; - } - - if (out != NULL) { - if (data != NULL && data->pdu_len > 0) { - if (outl < data->pdu_len) { - memcpy(out, data->pdu, outl); - ret = outl; - data->pdu += outl; - data->pdu_len -= outl; - } - else { - memcpy(out, data->pdu, data->pdu_len); - ret = data->pdu_len; - if (!data->peekmode) { - data->pdu_len = 0; - data->pdu = NULL; - } - } - } - else { - ret = MBEDTLS_ERR_SSL_WANT_READ; - errno = EAGAIN; - return ret; - } - } - return ret; -} - -/* - * return +ve data amount - * 0 no more - * -1 error (error in errno) - */ -/* callback function given to mbedtls for sending data over socket */ -static int -coap_dgram_write(void *ctx, const unsigned char *send_buffer, - size_t send_buffer_length) -{ - ssize_t result = -1; - coap_session_t *c_session = (struct coap_session_t *)ctx; - - if (c_session) { - result = coap_session_send(c_session, send_buffer, send_buffer_length); - if (result != (int)send_buffer_length) { - coap_log(LOG_WARNING, "coap_network_send failed (%zd != %zd)\n", - result, send_buffer_length); - result = 0; - } - } else { - result = 0; - } - return result; -} - -#if !defined(ESPIDF_VERSION) || (defined(CONFIG_MBEDTLS_SSL_PROTO_DTLS) && defined(CONFIG_MBEDTLS_TLS_SERVER)) -static char* -get_ip_addr(const struct coap_address_t *addr) -{ - const void *addrptr = NULL; - size_t buf_len; - - if (!addr) { - return NULL; - } - switch (addr->addr.sa.sa_family) { - case AF_INET: - addrptr = &addr->addr.sin.sin_addr; - buf_len = INET_ADDRSTRLEN; - break; - case AF_INET6: - addrptr = &addr->addr.sin6.sin6_addr; - buf_len = INET6_ADDRSTRLEN; - break; - default: - return NULL; - } - char *str = (char *)mbedtls_calloc(1, buf_len); - if (!str) { - coap_log(LOG_ERR, "Memory allocation failed\n"); - return NULL; - } - if (inet_ntop(addr->addr.sa.sa_family, addrptr, str, - buf_len) == 0) { - perror("coap_print_addr"); - return 0; - } - return str; -} -#endif /* !ESPIDF_VERSION || (CONFIG_MBEDTLS_SSL_PROTO_DTLS && CONFIG_MBEDTLS_TLS_SERVER) */ - -#if !defined(ESPIDF_VERSION) || (defined(CONFIG_MBEDTLS_SSL_PROTO_DTLS) && defined(CONFIG_MBEDTLS_PSK_MODES) && defined(CONFIG_MBEDTLS_TLS_SERVER)) -/* - * Server side PSK callback - */ -static int psk_server_callback(void *p_info, mbedtls_ssl_context *ssl, - const unsigned char *name, size_t name_len ) -{ - coap_session_t *c_session = - (coap_session_t *)p_info; - uint8_t buf[128]; - size_t psk_len; -#ifdef PSK2_PR - coap_dtls_spsk_t *setup_data; -#endif /* PSK2_PR */ - coap_mbedtls_env_t *m_env; - - coap_log(LOG_DEBUG, "got psk_identity: '%.*s'\n", - (int)name_len, name); - - if (c_session == NULL || c_session->context == NULL || - c_session->context->get_server_psk == NULL) { - return -1; - } - m_env = (coap_mbedtls_env_t *)c_session->tls; -#ifdef PSK2_PR - setup_data = &c_session->context->spsk_setup_data; - - if (setup_data->validate_id_call_back) { - coap_bin_const_t lidentity; - lidentity.length = name_len; - lidentity.s = (const uint8_t*)name; - const coap_bin_const_t *psk_key = - setup_data->validate_id_call_back(&lidentity, - c_session, - setup_data->id_call_back_arg); - - if (psk_key == NULL) - return -1; - mbedtls_ssl_set_hs_psk(ssl, psk_key->s, psk_key->length); - coap_session_refresh_psk_key(c_session, psk_key); - m_env->seen_client_hello = 1; - return 0; - } -#endif /* PSK2_PR */ - - psk_len = c_session->context->get_server_psk(c_session, - (const uint8_t*)name, - name_len, - (uint8_t*)buf, sizeof(buf)); - m_env->seen_client_hello = 1; - mbedtls_ssl_set_hs_psk(ssl, buf, psk_len); - return 0; -} -#endif /* !ESPIDF_VERSION || (CONFIG_MBEDTLS_SSL_PROTO_DTLS && CONFIG_MBEDTLS_PSK_MODES && CONFIG_MBEDTLS_TLS_SERVER) */ - -static char* -get_san_or_cn_from_cert(mbedtls_x509_crt *crt) -{ - if (crt) { -#if COAP_CONSTRAINED_STACK - static coap_mutex_t a_static_mutex = COAP_MUTEX_INITIALIZER; - static char buf[1024]; -#else /* ! COAP_CONSTRAINED_STACK */ - char buf[1024]; -#endif /* ! COAP_CONSTRAINED_STACK */ - char *cn; - char *cp; - char *tcp; - int n; - -#if COAP_CONSTRAINED_STACK - coap_mutex_lock(&a_static_mutex); -#endif /* COAP_CONSTRAINED_STACK */ - - mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt ); - - /* Look first to see if Subject Alt Name is defined */ - cp = strstr(buf, "subject alt name"); - if (cp) { - cp = strchr(cp, ':'); - if (cp) { - cp++; - while (*cp == ' ') cp++; - tcp = strchr(cp, '\n'); - if (tcp) - *tcp = '\000'; - /* Take only the first entry */ - tcp = strchr(cp, ','); - if (tcp) - *tcp = '\000'; - /* Return the Subject Alt Name */ -#if COAP_CONSTRAINED_STACK - coap_mutex_unlock(&a_static_mutex); -#endif /* COAP_CONSTRAINED_STACK */ - return mbedtls_strdup(cp); - } - } - - /* Pull CN= out of subject name */ - cp = strstr(buf, "subject name"); - if (cp) { - cp = strchr(cp, ':'); - if (cp) { - cp++; - while (*cp == ' ') cp++; - tcp = strchr(cp, '\n'); - if (tcp) - *tcp = '\000'; - - /* Need to emulate strcasestr() here. Looking for CN= */ - n = strlen(cp) - 3; - cn = cp; - while (n > 0) { - if (((cn[0] == 'C') || (cn[0] == 'c')) && - ((cn[1] == 'N') || (cn[1] == 'n')) && - (cn[2] == '=')) { - cn += 3; - break; - } - cn++; - n--; - } - if (n > 0) { - tcp = strchr(cn, ','); - if (tcp) - *tcp = '\000'; -#if COAP_CONSTRAINED_STACK - coap_mutex_unlock(&a_static_mutex); -#endif /* COAP_CONSTRAINED_STACK */ - return mbedtls_strdup(cn); - } - } - } -#if COAP_CONSTRAINED_STACK - coap_mutex_unlock(&a_static_mutex); -#endif /* COAP_CONSTRAINED_STACK */ - } - return NULL; -} - -/* - * return 0 All OK - * -ve Error Code - */ -static int -cert_verify_callback_mbedtls(void *data, mbedtls_x509_crt *crt, - int depth, uint32_t *flags) -{ - coap_session_t *c_session = (coap_session_t*)data; - coap_mbedtls_context_t *m_context = - (coap_mbedtls_context_t *)c_session->context->dtls_context; - coap_dtls_pki_t *setup_data = &m_context->setup_data; - char *cn = NULL; - - if (*flags == 0) - return 0; - - if (!setup_data->verify_peer_cert) { - /* Nothing is being checked */ - *flags = 0; - return 0; - } - - cn = get_san_or_cn_from_cert(crt); - - if (*flags & MBEDTLS_X509_BADCERT_EXPIRED) { - if (setup_data->allow_expired_certs) { - *flags &= ~MBEDTLS_X509_BADCERT_EXPIRED; - coap_log(LOG_WARNING, - " %s: %s: overridden: '%s' depth %d\n", - coap_session_str(c_session), - "The certificate has expired", cn ? cn : "?", depth); - } - } - if (*flags & MBEDTLS_X509_BADCERT_FUTURE) { - if (setup_data->allow_expired_certs) { - *flags &= ~MBEDTLS_X509_BADCERT_FUTURE; - coap_log(LOG_WARNING, - " %s: %s: overridden: '%s' depth %d\n", - coap_session_str(c_session), - "The certificate has a future date", cn ? cn : "?", depth); - } - } - if (*flags & MBEDTLS_X509_BADCERT_BAD_MD) { - if (setup_data->allow_bad_md_hash) { - *flags &= ~MBEDTLS_X509_BADCERT_BAD_MD; - coap_log(LOG_WARNING, - " %s: %s: overridden: '%s' depth %d\n", - coap_session_str(c_session), - "The certificate has a bad MD hash", cn ? cn : "?", depth); - } - } - if (*flags & MBEDTLS_X509_BADCERT_BAD_KEY) { - if (setup_data->allow_short_rsa_length) { - *flags &= ~MBEDTLS_X509_BADCERT_BAD_KEY; - coap_log(LOG_WARNING, - " %s: %s: overridden: '%s' depth %d\n", - coap_session_str(c_session), - "The certificate has a short RSA length", cn ? cn : "?", depth); - } - } - if (*flags & MBEDTLS_X509_BADCRL_EXPIRED) { - if (setup_data->check_cert_revocation && setup_data->allow_expired_crl) { - *flags &= ~MBEDTLS_X509_BADCRL_EXPIRED; - coap_log(LOG_WARNING, - " %s: %s: overridden: '%s' depth %d\n", - coap_session_str(c_session), - "The certificate's CRL has expired", cn ? cn : "?", depth); - } - else if (!setup_data->check_cert_revocation) { - *flags &= ~MBEDTLS_X509_BADCRL_EXPIRED; - } - } - if (*flags & MBEDTLS_X509_BADCRL_FUTURE) { - if (setup_data->check_cert_revocation && setup_data->allow_expired_crl) { - *flags &= ~MBEDTLS_X509_BADCRL_FUTURE; - coap_log(LOG_WARNING, - " %s: %s: overridden: '%s' depth %d\n", - coap_session_str(c_session), - "The certificate's CRL has a future date", cn ? cn : "?", depth); - } - else if (!setup_data->check_cert_revocation) { - *flags &= ~MBEDTLS_X509_BADCRL_FUTURE; - } - } - - if (*flags & MBEDTLS_X509_BADCERT_CN_MISMATCH) { - *flags &= ~MBEDTLS_X509_BADCERT_CN_MISMATCH; - } - if (setup_data->validate_cn_call_back) { - if (!setup_data->validate_cn_call_back(cn, - crt->raw.p, - crt->raw.len, - c_session, - depth, - *flags == 0, - setup_data->cn_call_back_arg)) { - *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; - } - } - if (*flags != 0) { - char buf[128]; - char *tcp; - - mbedtls_x509_crt_verify_info(buf, sizeof(buf), "", *flags); - tcp = strchr(buf, '\n'); - while (tcp) { - *tcp = '\000'; - coap_log(LOG_WARNING, - " %s: %s: issue 0x%x: '%s' depth %d\n", - coap_session_str(c_session), - buf, *flags, cn ? cn : "?", depth); - tcp = strchr(tcp+1, '\n'); - } - } - - if (cn) - mbedtls_free(cn); - - return 0; -} - -static int -setup_pki_credentials(mbedtls_x509_crt *cacert, - mbedtls_x509_crt *public_cert, - mbedtls_pk_context *private_key, - coap_mbedtls_env_t *m_env, - coap_mbedtls_context_t *m_context, - coap_session_t *c_session, - coap_dtls_pki_t *setup_data, - coap_dtls_role_t role) -{ - int ret; - - switch (setup_data->pki_key.key_type) { - case COAP_PKI_KEY_PEM: - if (setup_data->pki_key.key.pem.public_cert && - setup_data->pki_key.key.pem.public_cert[0] && - setup_data->pki_key.key.pem.private_key && - setup_data->pki_key.key.pem.private_key[0]) { - - mbedtls_x509_crt_init(public_cert); - mbedtls_pk_init(private_key); - - ret = mbedtls_x509_crt_parse_file(public_cert, - setup_data->pki_key.key.pem.public_cert); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_x509_crt_parse_file returned -0x%x\n\n", - -ret); - return ret; - } - - ret = mbedtls_pk_parse_keyfile(private_key, - setup_data->pki_key.key.pem.private_key, NULL); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_pk_parse_keyfile returned -0x%x\n\n", -ret); - return ret; - } - - ret = mbedtls_ssl_conf_own_cert(&m_env->conf, public_cert, private_key); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_ssl_conf_own_cert returned -0x%x\n\n", -ret); - return ret; - } - } - else if (role == COAP_DTLS_ROLE_SERVER) { - coap_log(LOG_ERR, - "***setup_pki: (D)TLS: No %s Certificate + Private " - "Key defined\n", - role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client"); - return -1; - } - - if (setup_data->pki_key.key.pem.ca_file && - setup_data->pki_key.key.pem.ca_file[0]) { - mbedtls_x509_crt_init(cacert); - ret = mbedtls_x509_crt_parse_file(cacert, - setup_data->pki_key.key.pem.ca_file); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); - return ret; - } - mbedtls_ssl_conf_authmode(&m_env->conf, setup_data->require_peer_cert ? - MBEDTLS_SSL_VERIFY_REQUIRED : - MBEDTLS_SSL_VERIFY_OPTIONAL); - mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL); - } - break; - case COAP_PKI_KEY_PEM_BUF: - if (setup_data->pki_key.key.pem_buf.public_cert && - setup_data->pki_key.key.pem_buf.public_cert_len && - setup_data->pki_key.key.pem_buf.private_key && - setup_data->pki_key.key.pem_buf.private_key_len > 0) { - mbedtls_x509_crt_init(public_cert); - mbedtls_pk_init(private_key); - ret = mbedtls_x509_crt_parse(public_cert, - (const unsigned char *)setup_data->pki_key.key.pem_buf.public_cert, - setup_data->pki_key.key.pem_buf.public_cert_len); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); - return ret; - } - - ret = mbedtls_pk_parse_key(private_key, - (const unsigned char *)setup_data->pki_key.key.pem_buf.private_key, - setup_data->pki_key.key.pem_buf.private_key_len, NULL, 0); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_pk_parse_keyfile returned -0x%x\n\n", -ret); - return ret; - } - - ret = mbedtls_ssl_conf_own_cert(&m_env->conf, public_cert, private_key); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_ssl_conf_own_cert returned -0x%x\n\n", -ret); - return ret; - } - } else if (role == COAP_DTLS_ROLE_SERVER) { - coap_log(LOG_ERR, - "***setup_pki: (D)TLS: No %s Certificate + Private " - "Key defined\n", - role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client"); - return -1; - } - - if (setup_data->pki_key.key.pem_buf.ca_cert && - setup_data->pki_key.key.pem_buf.ca_cert_len > 0) { - mbedtls_x509_crt_init(cacert); - ret = mbedtls_x509_crt_parse(cacert, - (const unsigned char *)setup_data->pki_key.key.pem_buf.ca_cert, - setup_data->pki_key.key.pem_buf.ca_cert_len); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); - return ret; - } - mbedtls_ssl_conf_authmode(&m_env->conf, setup_data->require_peer_cert ? - MBEDTLS_SSL_VERIFY_REQUIRED : - MBEDTLS_SSL_VERIFY_OPTIONAL); - mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL); - } - break; - case COAP_PKI_KEY_ASN1: - if (setup_data->pki_key.key.asn1.public_cert && - setup_data->pki_key.key.asn1.public_cert_len && - setup_data->pki_key.key.asn1.private_key && - setup_data->pki_key.key.asn1.private_key_len > 0) { - - mbedtls_x509_crt_init(public_cert); - mbedtls_pk_init(private_key); - ret = mbedtls_x509_crt_parse(public_cert, - (const unsigned char *)setup_data->pki_key.key.asn1.public_cert, - setup_data->pki_key.key.asn1.public_cert_len); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); - return ret; - } - - ret = mbedtls_pk_parse_key(private_key, - (const unsigned char *)setup_data->pki_key.key.asn1.private_key, - setup_data->pki_key.key.asn1.private_key_len, NULL, 0); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_pk_parse_keyfile returned -0x%x\n\n", -ret); - return ret; - } - - ret = mbedtls_ssl_conf_own_cert(&m_env->conf, public_cert, private_key); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_ssl_conf_own_cert returned -0x%x\n\n", -ret); - return ret; - } - } else if (role == COAP_DTLS_ROLE_SERVER) { - coap_log(LOG_ERR, - "***setup_pki: (D)TLS: No %s Certificate + Private " - "Key defined\n", - role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client"); - return -1; - } - - if (setup_data->pki_key.key.asn1.ca_cert && - setup_data->pki_key.key.asn1.ca_cert_len > 0) { - mbedtls_x509_crt_init(cacert); - ret = mbedtls_x509_crt_parse(cacert, - (const unsigned char *)setup_data->pki_key.key.asn1.ca_cert, - setup_data->pki_key.key.asn1.ca_cert_len); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); - return ret; - } - mbedtls_ssl_conf_authmode(&m_env->conf, setup_data->require_peer_cert ? - MBEDTLS_SSL_VERIFY_REQUIRED : - MBEDTLS_SSL_VERIFY_OPTIONAL); - mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL); - } - break; - default: - coap_log(LOG_ERR, - "***setup_pki: (D)TLS: Unknown key type %d\n", - setup_data->pki_key.key_type); - return -1; - } - - if (m_context->root_ca_file) { - ret = mbedtls_x509_crt_parse_file(cacert, m_context->root_ca_file); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); - return ret; - } - mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL); - } - if (m_context->root_ca_path) { - ret = mbedtls_x509_crt_parse_file(cacert, m_context->root_ca_path); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); - return ret; - } - mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL); - } - - /* - * Verify Peer. - * Need to do all checking, even if setup_data->verify_peer_cert is not set - */ - mbedtls_ssl_conf_verify(&m_env->conf, - cert_verify_callback_mbedtls, c_session); - - return 0; -} - -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_TLS_SERVER) -/* - * PKI SNI callback. - */ -static int -pki_sni_callback(void *p_info, mbedtls_ssl_context *ssl, - const unsigned char *uname, size_t name_len) -{ - unsigned int i; - coap_dtls_pki_t sni_setup_data; - coap_session_t *c_session = (coap_session_t *)p_info; - coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls; - coap_mbedtls_context_t *m_context = - (coap_mbedtls_context_t *)c_session->context->dtls_context; - int ret = 0; - - /* Is this a cached entry? */ - for (i = 0; i < m_context->pki_sni_count; i++) { - if (name_len == strlen(m_context->pki_sni_entry_list[i].sni) && - memcmp(uname, m_context->pki_sni_entry_list[i].sni, name_len) == 0) { - break; - } - } - if (i == m_context->pki_sni_count) { - /* - * New PKI SNI request - */ - char *name; - coap_dtls_key_t *new_entry; - - name = mbedtls_malloc(name_len+1); - if (name == NULL) { - ret = -1; - goto end; - } - - memcpy(name, uname, name_len); - name[name_len] = '\000'; - new_entry = - m_context->setup_data.validate_sni_call_back(name, - m_context->setup_data.sni_call_back_arg); - if (!new_entry) { - ret = -1; - mbedtls_free(name); - goto end; - } - - m_context->pki_sni_entry_list = - mbedtls_realloc(m_context->pki_sni_entry_list, - (i+1)*sizeof(pki_sni_entry)); - if (m_context->pki_sni_entry_list == NULL) { - ret = -1; - mbedtls_free(name); - goto end; - } - - m_context->pki_sni_entry_list[i].sni = name; - m_context->pki_sni_entry_list[i].pki_key = *new_entry; - sni_setup_data = m_context->setup_data; - sni_setup_data.pki_key = *new_entry; - if ((ret = setup_pki_credentials(&m_context->pki_sni_entry_list[i].cacert, - &m_context->pki_sni_entry_list[i].public_cert, - &m_context->pki_sni_entry_list[i].private_key, - m_env, - m_context, - c_session, - &sni_setup_data, COAP_DTLS_ROLE_SERVER)) < 0) { - ret = -1; - mbedtls_free(name); - goto end; - } - m_context->pki_sni_count++; - } - -end: - if (ret != -1) { - mbedtls_ssl_set_hs_ca_chain(ssl, &m_context->pki_sni_entry_list[i].cacert, - NULL); - return mbedtls_ssl_set_hs_own_cert(ssl, - &m_context->pki_sni_entry_list[i].public_cert, - &m_context->pki_sni_entry_list[i].private_key); - } - return ret; -} -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_TLS_SERVER */ - -#ifdef PSK2_PR -/* - * PSK SNI callback. - */ -static int -psk_sni_callback(void *p_info, mbedtls_ssl_context *ssl, - const unsigned char *uname, size_t name_len) -{ - unsigned int i; - coap_dtls_spsk_t sni_setup_data; - coap_session_t *c_session = (coap_session_t *)p_info; - coap_mbedtls_context_t *m_context = - (coap_mbedtls_context_t *)c_session->context->dtls_context; - int ret = 0; - - /* Is this a cached entry? */ - for (i = 0; i < m_context->psk_sni_count; i++) { - if (name_len == m_context->psk_sni_entry_list[i].sni.length && - memcmp(uname, m_context->psk_sni_entry_list[i].sni.s, name_len) == 0) { - break; - } - } - if (i == m_context->psk_sni_count) { - /* - * New PSK SNI request - */ - coap_str_const_t lsni; - uint8_t *name; - const coap_dtls_spsk_info_t *new_entry; - - name = mbedtls_malloc(name_len+1); - if (name == NULL) { - ret = -1; - goto end; - } - - memcpy(name, uname, name_len); - name[name_len] = '\000'; - - lsni.s = name; - lsni.length = name_len; - new_entry = - c_session->context->spsk_setup_data.validate_sni_call_back(&lsni, - c_session, - c_session->context->spsk_setup_data.sni_call_back_arg); - if (!new_entry) { - ret = -1; - mbedtls_free(name); - goto end; - } - - m_context->psk_sni_entry_list = - mbedtls_realloc(m_context->psk_sni_entry_list, - (i+1)*sizeof(psk_sni_entry)); - - if (m_context->psk_sni_entry_list == NULL) { - ret = -1; - mbedtls_free(name); - goto end; - } - - m_context->psk_sni_entry_list[i].sni.s = name; - m_context->psk_sni_entry_list[i].sni.length = name_len; - m_context->psk_sni_entry_list[i].psk_info = *new_entry; - sni_setup_data = c_session->context->spsk_setup_data; - sni_setup_data.psk_info = *new_entry; - m_context->psk_sni_count++; - } - -end: - if (ret != -1) { - coap_session_refresh_psk_hint(c_session, - &m_context->psk_sni_entry_list[i].psk_info.hint); - coap_session_refresh_psk_key(c_session, - &m_context->psk_sni_entry_list[i].psk_info.key); - return mbedtls_ssl_set_hs_psk(ssl, - m_context->psk_sni_entry_list[i].psk_info.key.s, - m_context->psk_sni_entry_list[i].psk_info.key.length); - } - return ret; -} -#endif /* PSK2_PR */ - -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_TLS_SERVER) - -static int setup_server_ssl_session(coap_session_t *c_session, - coap_mbedtls_env_t *m_env) -{ - coap_mbedtls_context_t *m_context = - (coap_mbedtls_context_t *)c_session->context->dtls_context; - int ret = 0; - m_context->psk_pki_enabled |= IS_SERVER; - - mbedtls_ssl_cookie_init(&m_env->cookie_ctx); - if ((ret = mbedtls_ssl_config_defaults(&m_env->conf, - MBEDTLS_SSL_IS_SERVER, - c_session->proto == COAP_PROTO_DTLS ? - MBEDTLS_SSL_TRANSPORT_DATAGRAM : - MBEDTLS_SSL_TRANSPORT_STREAM, - MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { - coap_log(LOG_ERR, "mbedtls_ssl_config_defaults returned -0x%x\n", -ret); - goto fail; - } - - mbedtls_ssl_conf_rng(&m_env->conf, mbedtls_ctr_drbg_random, &m_env->ctr_drbg); - -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_SSL_PROTO_DTLS) - mbedtls_ssl_conf_handshake_timeout(&m_env->conf, 1000, 60000); - - if (m_context->psk_pki_enabled & IS_PSK) { -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_PSK_MODES) - mbedtls_ssl_conf_psk_cb(&m_env->conf, psk_server_callback, c_session); -#ifdef PSK2_PR - if (c_session->context->spsk_setup_data.validate_sni_call_back) { - mbedtls_ssl_conf_sni(&m_env->conf, psk_sni_callback, c_session); - } -#endif /* PSK2_PR */ -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_PSK_MODES */ - } -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_SSL_PROTO_DTLS */ - - if (m_context->psk_pki_enabled & IS_PKI) { - ret = setup_pki_credentials(&m_env->cacert, &m_env->public_cert, - &m_env->private_key, m_env, m_context, - c_session, &m_context->setup_data, - COAP_DTLS_ROLE_SERVER); - if (ret < 0) { - coap_log(LOG_ERR, "PKI setup failed\n"); - return ret; - } - if (m_context->setup_data.validate_sni_call_back) { - mbedtls_ssl_conf_sni(&m_env->conf, pki_sni_callback, c_session); - } - } - - if ((ret = mbedtls_ssl_cookie_setup(&m_env->cookie_ctx, - mbedtls_ctr_drbg_random, - &m_env->ctr_drbg)) != 0) { - coap_log(LOG_ERR, "mbedtls_ssl_cookie_setup: returned -0x%x\n", -ret); - goto fail; - } - -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_SSL_PROTO_DTLS) - mbedtls_ssl_conf_dtls_cookies(&m_env->conf, mbedtls_ssl_cookie_write, - mbedtls_ssl_cookie_check, - &m_env->cookie_ctx ); - mbedtls_ssl_set_mtu(&m_env->ssl, c_session->mtu); -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_SSL_PROTO_DTLS */ -fail: - return ret; -} -#endif /* !defined(ESPIDF_VERSION) || CONFIG_MBEDTLS_TLS_SERVER) */ - -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_PSK_MODES) -#define MAX_CIPHERS 100 -static int psk_ciphers[MAX_CIPHERS]; -static int pki_ciphers[MAX_CIPHERS]; -static int processed_ciphers = 0; - -static void -set_ciphersuites(mbedtls_ssl_config *conf, int is_psk) -{ - if (!processed_ciphers) { - const int *list = mbedtls_ssl_list_ciphersuites(); - int *psk_list = psk_ciphers; - int *pki_list = pki_ciphers; - - while (*list) { - const mbedtls_ssl_ciphersuite_t *cur = - mbedtls_ssl_ciphersuite_from_id(*list); - - if (cur) { - if (mbedtls_ssl_ciphersuite_uses_psk(cur)) { - if (&psk_ciphers[MAX_CIPHERS] - psk_list > 1) { - *psk_list = *list; - psk_list++; - } - else { - static int done = 0; - - if (!done) { - done = 1; - coap_log(LOG_ERR, "psk_ciphers[MAX_CIPHERS] insufficient\n"); - } - } - } - else { - if (&pki_ciphers[MAX_CIPHERS] - pki_list > 1) { - *pki_list = *list; - pki_list++; - } - else { - static int done = 0; - - if (!done) { - done = 1; - coap_log(LOG_ERR, "pki_ciphers[MAX_CIPHERS] insufficient\n"); - } - } - } - } - list++; - } - /* zero terminate */ - *psk_list = 0; - *pki_list = 0; - processed_ciphers = 1; - } - mbedtls_ssl_conf_ciphersuites(conf, is_psk ? psk_ciphers : pki_ciphers); -} -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_PSK_MODES */ - -static int setup_client_ssl_session(coap_session_t *c_session, - coap_mbedtls_env_t *m_env) -{ - int ret; - - coap_mbedtls_context_t *m_context = - (coap_mbedtls_context_t *)c_session->context->dtls_context; - - m_context->psk_pki_enabled |= IS_CLIENT; - - if ((ret = mbedtls_ssl_config_defaults(&m_env->conf, - MBEDTLS_SSL_IS_CLIENT, - c_session->proto == COAP_PROTO_DTLS ? - MBEDTLS_SSL_TRANSPORT_DATAGRAM : - MBEDTLS_SSL_TRANSPORT_STREAM, - MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { - coap_log(LOG_ERR, "mbedtls_ssl_config_defaults returned -0x%x", -ret); - goto fail; - } - -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_SSL_PROTO_DTLS) - mbedtls_ssl_conf_handshake_timeout(&m_env->conf, 1000, 60000); -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_SSL_PROTO_DTLS */ - - mbedtls_ssl_conf_authmode(&m_env->conf, MBEDTLS_SSL_VERIFY_REQUIRED); - mbedtls_ssl_conf_rng(&m_env->conf, mbedtls_ctr_drbg_random, &m_env->ctr_drbg); - - if (m_context->psk_pki_enabled & IS_PSK) { -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_PSK_MODES) - uint8_t identity[64]; - size_t identity_len; - uint8_t psk_key[64]; - size_t psk_len; - size_t max_identity_len = sizeof(identity); - - coap_log(LOG_INFO, "Setting PSK key\n"); - psk_len = c_session->context->get_client_psk(c_session, - NULL, - 0, - identity, - &identity_len, - max_identity_len, - psk_key, - sizeof(psk_key)); - assert(identity_len < sizeof(identity)); - mbedtls_ssl_conf_psk(&m_env->conf, (const unsigned char *)psk_key, - psk_len, (const unsigned char *)identity, - identity_len); -#ifdef PSK2_PR - if (c_session->cpsk_setup_data.client_sni) { - mbedtls_ssl_set_hostname(&m_env->ssl, - c_session->cpsk_setup_data.client_sni); - } -#if 0 -/* Identity Hint currently not supported in MbedTLS */ - if (c_session->cpsk_setup_data.validate_ih_call_back) { - coap_log(LOG_DEBUG, - "CoAP Client restricted to (D)TLS1.2 with Identity Hint callback\n"); - mbedtls_ssl_conf_max_version(&m_env->conf, MBEDTLS_SSL_MAJOR_VERSION_3, - MBEDTLS_SSL_MINOR_VERSION_3); - } -#endif -#endif /* PSK2_PR */ - set_ciphersuites(&m_env->conf, 1); -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_PSK_MODES */ - } - else if ((m_context->psk_pki_enabled & IS_PKI) || - (m_context->psk_pki_enabled & (IS_PSK | IS_PKI)) == 0) { - /* - * If neither PSK or PKI have been set up, use PKI basics. - * This works providing COAP_PKI_KEY_PEM has a value of 0. - */ - if ((m_context->psk_pki_enabled & (IS_PSK | IS_PKI)) == 0) { - mbedtls_ssl_conf_authmode(&m_env->conf, MBEDTLS_SSL_VERIFY_OPTIONAL); - } - ret = setup_pki_credentials(&m_env->cacert, &m_env->public_cert, - &m_env->private_key, m_env, m_context, - c_session, &m_context->setup_data, - COAP_DTLS_ROLE_CLIENT); - if (ret < 0) { - coap_log(LOG_ERR, "PKI setup failed\n"); - return ret; - } -#if !defined(ESPIDF_VERSION) ||(defined(CONFIG_MBEDTLS_TLS_SERVER) && defined(CONFIG_MBEDTLS_SSL_ALPN)) - if (c_session->proto == COAP_PROTO_TLS) { - const char *alpn_list[2]; - - memset(alpn_list, 0, sizeof(alpn_list)); - alpn_list[0] = "coap"; - ret = mbedtls_ssl_conf_alpn_protocols(&m_env->conf, alpn_list); - if (ret != 0) { - coap_log(LOG_ERR, "ALPN setup failed %d)\n", ret); - } - } -#endif /* !ESPIDF_VERSION || (CONFIG_MBEDTLS_TLS_SERVER && CONFIG_MBEDTLS_SSL_ALPN) */ - if (m_context->setup_data.client_sni) { - mbedtls_ssl_set_hostname(&m_env->ssl, m_context->setup_data.client_sni); - } -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_SSL_PROTO_DTLS) - mbedtls_ssl_set_mtu(&m_env->ssl, c_session->mtu); -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_SSL_PROTO_DTLS */ -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_PSK_MODES) - set_ciphersuites(&m_env->conf, 0); -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_PSK_MODES */ - } - return 0; - -fail: - return ret; -} - -static void mbedtls_cleanup(coap_mbedtls_env_t *m_env) -{ - if (!m_env) { - return; - } - - mbedtls_x509_crt_free(&m_env->cacert); - mbedtls_x509_crt_free(&m_env->public_cert); - mbedtls_pk_free(&m_env->private_key); - mbedtls_entropy_free(&m_env->entropy); - mbedtls_ssl_config_free(&m_env->conf); - mbedtls_ctr_drbg_free(&m_env->ctr_drbg); - mbedtls_ssl_free(&m_env->ssl); - mbedtls_ssl_cookie_free(&m_env->cookie_ctx); -} - -static void -coap_dtls_free_mbedtls_env(coap_mbedtls_env_t *m_env) { - if (m_env) { - mbedtls_cleanup(m_env); - free(m_env); - } -} - -/* - * return -1 failure - * 0 not completed - * 1 established - */ -static int do_mbedtls_handshake(coap_session_t *c_session, - coap_mbedtls_env_t *m_env) { - int ret; - char buf[128]; - - ret = mbedtls_ssl_handshake(&m_env->ssl); - switch (ret) { - case 0: - m_env->established = 1; - coap_log(LOG_DEBUG, "* %s: MbedTLS established\n", - coap_session_str(c_session)); - ret = 1; - break; - case MBEDTLS_ERR_SSL_WANT_READ: - case MBEDTLS_ERR_SSL_WANT_WRITE: - errno = EAGAIN; - ret = 0; - break; - case MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED: - coap_log(LOG_INFO, "hello verification requested\n"); - ret = -1; - mbedtls_ssl_session_reset(&m_env->ssl); - break; - case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE: - c_session->dtls_event = COAP_EVENT_DTLS_CLOSED; - ret = -1; - break; - default: - mbedtls_strerror(ret, buf, sizeof(buf)); - coap_log(LOG_WARNING, - "do_mbedtls_handshake: session establish " - "returned -0x%x: '%s'\n", - -ret, buf); - ret = -1; - break; - } - return ret; -} - -static void -mbedtls_debug_out(void *ctx UNUSED, int level, - const char *file, int line, const char *str) { - int log_level; - - switch (level) { - case 4: - case 3: - case 2: - log_level = LOG_DEBUG; - break; - case 1: - log_level = LOG_ERR; - break; - case 0: - default: - log_level = 0; - break; - } - coap_log(log_level, "%s:%04d: %s", file, line, str); -} - -static coap_mbedtls_env_t *coap_dtls_new_mbedtls_env(coap_session_t *c_session, - coap_dtls_role_t role) -{ - int ret = 0; - coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls; - - if (m_env) - return m_env; - - m_env = (coap_mbedtls_env_t *)calloc(1, sizeof(coap_mbedtls_env_t)); - if (!m_env) { - return NULL; - } - - mbedtls_ssl_init(&m_env->ssl); - mbedtls_ctr_drbg_init(&m_env->ctr_drbg); - mbedtls_ssl_config_init(&m_env->conf); - mbedtls_entropy_init(&m_env->entropy); - -#if defined(ESPIDF_VERSION) && defined(CONFIG_MBEDTLS_DEBUG) - mbedtls_esp_enable_debug_log(&m_env->conf, CONFIG_MBEDTLS_DEBUG_LEVEL); -#endif /* ESPIDF_VERSION && CONFIG_MBEDTLS_DEBUG */ - if ((ret = mbedtls_ctr_drbg_seed(&m_env->ctr_drbg, - mbedtls_entropy_func, &m_env->entropy, NULL, 0)) != 0) { - coap_log(LOG_ERR, "mbedtls_ctr_drbg_seed returned -0x%x", -ret); - goto fail; - } - - if (role == COAP_DTLS_ROLE_CLIENT) { - if (setup_client_ssl_session(c_session, m_env) != 0) { - goto fail; - } -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_TLS_SERVER) - } else if (role == COAP_DTLS_ROLE_SERVER) { - if (setup_server_ssl_session(c_session, m_env) != 0) { - goto fail; - } -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_TLS_SERVER */ - } else { - goto fail; - } - - if ((ret = mbedtls_ssl_setup(&m_env->ssl, &m_env->conf)) != 0) { - goto fail; - } - mbedtls_ssl_set_bio(&m_env->ssl, c_session, coap_dgram_write, - coap_dgram_read, NULL); - mbedtls_ssl_set_timer_cb(&m_env->ssl, &m_env->timer, - mbedtls_timing_set_delay, - mbedtls_timing_get_delay); - - mbedtls_ssl_conf_dbg(&m_env->conf, mbedtls_debug_out, stdout); - return m_env; - -fail: - if (m_env) { - free(m_env); - } - return NULL; -} - -int coap_dtls_is_supported(void) { -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_SSL_PROTO_DTLS) - return 1; -#else /* ESPIDF_VERSION && !CONFIG_MBEDTLS_SSL_PROTO_DTLS */ - coap_log(LOG_EMERG, - "libcoap not compiled for DTLS with MbedTLS" - " - update MbedTLS to include DTLS\n"); - return 0; -#endif /* ESPIDF_VERSION && !CONFIG_MBEDTLS_SSL_PROTO_DTLS */ -} - -int coap_tls_is_supported(void) -{ - return 0; -} - -void *coap_dtls_new_context(struct coap_context_t *c_context) -{ - coap_mbedtls_context_t *m_context; - (void)c_context; - - m_context = (coap_mbedtls_context_t *)calloc(1, sizeof(coap_mbedtls_context_t)); - if (m_context) { - memset(m_context, 0, sizeof(coap_mbedtls_context_t)); - } - return m_context; -} - -#ifndef PSK2_PR -int coap_dtls_context_set_psk(struct coap_context_t *c_context, - const char *identity_hint UNUSED, - coap_dtls_role_t role UNUSED) -{ - coap_mbedtls_context_t *m_context = - ((coap_mbedtls_context_t *)c_context->dtls_context); -#if defined(ESPIDF_VERSION) && (!defined(CONFIG_MBEDTLS_PSK_MODES) || !defined(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK)) - coap_log(LOG_EMERG, "coap_dtls_context_set_psk:" - " libcoap not compiled with MBEDTLS_PSK_MODES and MBEDTLS_KEY_EXCHANGE_PSK" - " - update mbedTLS to include psk mode configs\n"); - return 0; -#endif /* ESPIDF_VERSION && (!CONFIG_MBEDTLS_PSK_MODES || !CONFIG_MBEDTLS_KEY_EXCHANGE_PSK) */ - -#if defined(ESPIDF_VERSION) && !defined(CONFIG_MBEDTLS_TLS_SERVER) - coap_log(LOG_EMERG, "coap_dtls_context_set_psk:" - " libcoap not compiled for Server Mode for MbedTLS" - " - update MbedTLS to include Server Mode\n"); - return 0; -#endif /* ESPIDF_VERSION && !CONFIG_MBEDTLS_TLS_SERVER */ - m_context->psk_pki_enabled |= IS_PSK; - return 1; -} -#else /* PSK2_PR */ -/* - * return 0 failed - * 1 passed - */ -int -coap_dtls_context_set_spsk(coap_context_t *c_context, - coap_dtls_spsk_t *setup_data -) { - coap_mbedtls_context_t *m_context = - ((coap_mbedtls_context_t *)c_context->dtls_context); - -#if defined(ESPIDF_VERSION) && !defined(CONFIG_MBEDTLS_TLS_SERVER) - coap_log(LOG_EMERG, "coap_dtls_context_set_spsk:" - " libcoap not compiled for Server Mode for MbedTLS" - " - update MbedTLS to include Server Mode\n"); - return 0; -#endif /* ESPIDF_VERSION && !CONFIG_MBEDTLS_TLS_SERVER */ - if (!m_context || !setup_data) - return 0; - - m_context->psk_pki_enabled |= IS_PSK; - return 1; -} - -/* - * return 0 failed - * 1 passed - */ -int -coap_dtls_context_set_cpsk(coap_context_t *c_context, - coap_dtls_cpsk_t *setup_data -) { - coap_mbedtls_context_t *m_context = - ((coap_mbedtls_context_t *)c_context->dtls_context); - - if (!m_context || !setup_data) - return 0; - - if (setup_data->validate_ih_call_back) { - coap_log(LOG_WARNING, - "CoAP Client with MbedTLS does not support Identity Hint selection\n"); - } - m_context->psk_pki_enabled |= IS_PSK; - return 1; -} - -#endif /* PSK2_PR */ - -int coap_dtls_context_set_pki(struct coap_context_t *c_context, - coap_dtls_pki_t *setup_data, - coap_dtls_role_t role UNUSED) -{ -#if defined(ESPIDF_VERSION) && (!defined(CONFIG_MBEDTLS_PSK_MODES) || !defined(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK)) - coap_log(LOG_EMERG, "coap_dtls_context_set_pki:" - " libcoap not compiled with MBEDTLS_PSK_MODES and MBEDTLS_KEY_EXCHANGE_PSK" - " - update mbedTLS to include psk mode configs\n"); - return 0; -#endif /* ESPIDF_VERSION && (!CONFIG_MBEDTLS_PSK_MODES || !CONFIG_MBEDTLS_KEY_EXCHANGE_PSK) */ - - coap_mbedtls_context_t *m_context = - ((coap_mbedtls_context_t *)c_context->dtls_context); - - m_context->setup_data = *setup_data; - m_context->psk_pki_enabled |= IS_PKI; - return 1; -} - -int coap_dtls_context_set_pki_root_cas(struct coap_context_t *c_context, - const char *ca_file, - const char *ca_path) -{ - coap_mbedtls_context_t *m_context = - ((coap_mbedtls_context_t *)c_context->dtls_context); - - if (!m_context) { - coap_log(LOG_WARNING, - "coap_context_set_pki_root_cas: (D)TLS environment " - "not set up\n"); - return 0; - } - - if (ca_file == NULL && ca_path == NULL) { - coap_log(LOG_WARNING, - "coap_context_set_pki_root_cas: ca_file and/or ca_path " - "not defined\n"); - return 0; - } - if (m_context->root_ca_file) { - free(m_context->root_ca_file); - m_context->root_ca_file = NULL; - } - - if (ca_file) { - m_context->root_ca_file = mbedtls_strdup(ca_file); - } - - if (m_context->root_ca_path) { - free(m_context->root_ca_path); - m_context->root_ca_path = NULL; - } - - if (ca_path) { - m_context->root_ca_path = mbedtls_strdup(ca_path); - } - return 1; -} - -int coap_dtls_context_check_keys_enabled(struct coap_context_t *c_context) -{ - coap_mbedtls_context_t *m_context = - ((coap_mbedtls_context_t *)c_context->dtls_context); - return m_context->psk_pki_enabled ? 1 : 0; -} - -void coap_dtls_free_context(void *dtls_context) -{ - coap_mbedtls_context_t *m_context = (coap_mbedtls_context_t *)dtls_context; - unsigned int i; - - for (i = 0; i < m_context->pki_sni_count; i++) { - mbedtls_free(m_context->pki_sni_entry_list[i].sni); - - mbedtls_x509_crt_free(&m_context->pki_sni_entry_list[i].public_cert); - - mbedtls_pk_free(&m_context->pki_sni_entry_list[i].private_key); - - mbedtls_x509_crt_free(&m_context->pki_sni_entry_list[i].cacert); - } -#ifdef PSK2_PR - for (i = 0; i < m_context->psk_sni_count; i++) { - mbedtls_free(m_context->psk_sni_entry_list[i].sni.s); - } - if (m_context->psk_sni_entry_list) - mbedtls_free(m_context->pki_sni_entry_list); - -#endif /* PSK2_PR */ - - free(m_context); -} - -void *coap_dtls_new_client_session(coap_session_t *c_session) -{ -#if defined(ESPIDF_VERSION) && !defined(CONFIG_MBEDTLS_TLS_CLIENT) - (void)c_session; - coap_log(LOG_EMERG, "coap_dtls_new_client_session:" - " libcoap not compiled for Client Mode for MbedTLS" - " - update MbedTLS to include Client Mode\n"); - return NULL; -#else /* !ESPIDF_VERSION || CONFIG_MBEDTLS_TLS_CLIENT */ - coap_mbedtls_env_t *m_env = coap_dtls_new_mbedtls_env(c_session, - COAP_DTLS_ROLE_CLIENT); - int ret; - - if (m_env) { - ret = do_mbedtls_handshake(c_session, m_env); - if (ret == -1) { - coap_dtls_free_mbedtls_env(m_env); - return NULL; - } - } - return m_env; -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_TLS_CLIENT */ -} - -void *coap_dtls_new_server_session(coap_session_t *c_session) -{ - coap_mbedtls_env_t *m_env = - (coap_mbedtls_env_t *)c_session->tls; - if (m_env) { - m_env->seen_client_hello = 1; -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_SSL_PROTO_DTLS) - mbedtls_ssl_set_mtu(&m_env->ssl, c_session->mtu); -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_SSL_PROTO_DTLS */ - } - return m_env; -} - -void coap_dtls_free_session(coap_session_t *c_session) -{ - if (c_session && c_session->context) { - coap_dtls_free_mbedtls_env(c_session->tls); - c_session->tls = NULL; - } - return; -} - -void coap_dtls_session_update_mtu(coap_session_t *c_session) -{ -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_SSL_PROTO_DTLS) - coap_mbedtls_env_t *m_env = - (coap_mbedtls_env_t *)c_session->tls; - if (m_env) { - mbedtls_ssl_set_mtu(&m_env->ssl, c_session->mtu); - } -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_SSL_PROTO_DTLS */ -} - -int coap_dtls_send(coap_session_t *c_session, - const uint8_t *data, - size_t data_len) -{ - int ret; - coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls; - char buf[128]; - - assert(m_env != NULL); - - if (!m_env) { - return -1; - } - c_session->dtls_event = -1; - if (m_env->established) { - ret = mbedtls_ssl_write(&m_env->ssl, (const unsigned char*) data, data_len); - if (ret <= 0) { - switch (ret) { - case MBEDTLS_ERR_SSL_WANT_READ: - case MBEDTLS_ERR_SSL_WANT_WRITE: - ret = 0; - break; - case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE: - c_session->dtls_event = COAP_EVENT_DTLS_CLOSED; - ret = -1; - break; - default: - mbedtls_strerror(ret, buf, sizeof(buf)); - coap_log(LOG_WARNING, - "coap_dtls_send: " - "returned -0x%x: '%s'\n", - -ret, buf); - ret = -1; - break; - } - if (ret == -1) { - coap_log(LOG_WARNING, "coap_dtls_send: cannot send PDU\n"); - } - } - } else { - ret = do_mbedtls_handshake(c_session, m_env); - if (ret == 1) { - /* Just connected, so send the data */ - return coap_dtls_send(c_session, data, data_len); - } - ret = -1; - } - - if (c_session->dtls_event >= 0) { - coap_handle_event(c_session->context, c_session->dtls_event, c_session); - if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR || - c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) { - coap_session_disconnected(c_session, COAP_NACK_TLS_FAILED); - ret = -1; - } - } - return ret; -} - -int coap_dtls_is_context_timeout(void) -{ - return 0; -} - -coap_tick_t coap_dtls_get_context_timeout(void *dtls_context UNUSED) -{ - return 0; -} - -coap_tick_t coap_dtls_get_timeout(coap_session_t *c_session, coap_tick_t now) -{ - coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls; - int ret = mbedtls_timing_get_delay(&m_env->timer); - - switch (ret) { - case 0: - case 1: - /* int_ms has timed out, but not fin_ms */ - return now + 1; - case 2: - /* fin_ms has timed out - time for a retry */ - return now; - default: - break; - } - - return 0; -} - -void coap_dtls_handle_timeout(coap_session_t *c_session) -{ - coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls; - - assert(m_env != NULL); - if (((c_session->state == COAP_SESSION_STATE_HANDSHAKE) && - (++c_session->dtls_timeout_count > c_session->max_retransmit)) || - (do_mbedtls_handshake(c_session, m_env) < 0)) { - /* Too many retries */ - coap_session_disconnected(c_session, COAP_NACK_TLS_FAILED); - } - return; -} - -int coap_dtls_receive(coap_session_t *c_session, - const uint8_t *data, - size_t data_len) -{ - int ret = 1; - - c_session->dtls_event = -1; - coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls; - assert(m_env != NULL); - - coap_ssl_t *ssl_data = &m_env->coap_ssl_data; - if (ssl_data->pdu_len) { - coap_log(LOG_INFO, "** %s: Previous data not read %u bytes\n", - coap_session_str(c_session), ssl_data->pdu_len); - } - ssl_data->pdu = data; - ssl_data->pdu_len = (unsigned)data_len; - - if (m_env->established) { -#if COAP_CONSTRAINED_STACK - static coap_mutex_t b_static_mutex = COAP_MUTEX_INITIALIZER; - static uint8_t pdu[COAP_RXBUFFER_SIZE]; -#else /* ! COAP_CONSTRAINED_STACK */ - uint8_t pdu[COAP_RXBUFFER_SIZE]; -#endif /* ! COAP_CONSTRAINED_STACK */ - -#if COAP_CONSTRAINED_STACK - coap_mutex_lock(&b_static_mutex); -#endif /* COAP_CONSTRAINED_STACK */ - - if (c_session->state == COAP_SESSION_STATE_HANDSHAKE) { - coap_handle_event(c_session->context, COAP_EVENT_DTLS_CONNECTED, - c_session); - coap_session_connected(c_session); - } - - ret = mbedtls_ssl_read(&m_env->ssl, pdu, (int)sizeof(pdu)); - if (ret > 0) { - ret = coap_handle_dgram(c_session->context, c_session, pdu, (size_t)ret); -#if COAP_CONSTRAINED_STACK - coap_mutex_unlock(&b_static_mutex); -#endif /* COAP_CONSTRAINED_STACK */ - return ret; - } - else if (ret == 0 || ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { - c_session->dtls_event = COAP_EVENT_DTLS_CLOSED; - } - else if (ret != MBEDTLS_ERR_SSL_WANT_READ) { - char buf[128]; - - mbedtls_strerror(ret, buf, sizeof(buf)); - coap_log(LOG_WARNING, - "coap_dtls_receive: " - "returned -0x%x: '%s' (length %zd)\n", - -ret, buf, data_len); - } -#if COAP_CONSTRAINED_STACK - coap_mutex_unlock(&b_static_mutex); -#endif /* COAP_CONSTRAINED_STACK */ - ret = -1; - } - else { - ret = do_mbedtls_handshake(c_session, m_env); - if (ret == 1) { - /* Just connected, so send the data */ - coap_session_connected(c_session); - } else { - if (ssl_data->pdu_len) { - /* Do the handshake again incase of internal timeout */ - ret = do_mbedtls_handshake(c_session, m_env); - if (ret == 1) { - /* Just connected, so send the data */ - coap_session_connected(c_session); - } else { - ret = -1; - } - } - ret = -1; - } - } - if (c_session->dtls_event >= 0) { - coap_handle_event(c_session->context, c_session->dtls_event, c_session); - if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR || - c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) { - coap_session_disconnected(c_session, COAP_NACK_TLS_FAILED); - ret = -1; - } - } - return ret; -} - -int coap_dtls_hello(coap_session_t *c_session, - const uint8_t *data, - size_t data_len) -{ -#if defined(ESPIDF_VERSION) && (!defined(CONFIG_MBEDTLS_SSL_PROTO_DTLS) || !defined(CONFIG_MBEDTLS_TLS_SERVER)) - (void)c_session; - (void)data; - (void)data_len; - coap_log(LOG_EMERG, "coap_dtls_hello:" - " libcoap not compiled for DTLS or Server Mode for MbedTLS" - " - update MbedTLS to include DTLS and Server Mode\n"); - return -1; -#else /* !ESPIDF_VERSION) || (CONFIG_MBEDTLS_SSL_PROTO_DTLS && CONFIG_MBEDTLS_TLS_SERVER) */ - coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls; - coap_ssl_t *ssl_data = m_env ? &m_env->coap_ssl_data : NULL; - int ret; - - if (m_env) { - char *str = get_ip_addr(&c_session->remote_addr); - if (!str) { - return -1; - } - if((ret = mbedtls_ssl_set_client_transport_id(&m_env->ssl, - (unsigned char *)str, strlen(str))) != 0) { - coap_log(LOG_ERR, - "mbedtls_ssl_set_client_transport_id() returned -0x%x\n\n", - -ret); - free(str); - return -1; - } - free(str); - } - - if (!m_env) { - m_env = coap_dtls_new_mbedtls_env(c_session, COAP_DTLS_ROLE_SERVER); - if (m_env) { - c_session->tls = m_env; - ssl_data = &m_env->coap_ssl_data; - ssl_data->pdu = data; - ssl_data->pdu_len = (unsigned)data_len; - char *str = get_ip_addr(&c_session->remote_addr); - if (!str) { - return -1; - } - if((ret = mbedtls_ssl_set_client_transport_id(&m_env->ssl, - (unsigned char *)str, strlen(str)) ) != 0) { - coap_log(LOG_ERR, - "mbedtls_ssl_set_client_transport_id() returned -0x%x\n", - -ret); - free(str); - return -1; - } - ret = do_mbedtls_handshake(c_session, m_env); - if (ret == 0 || m_env->seen_client_hello) { - m_env->seen_client_hello = 0; - free(str); - return 1; - } - free(str); - } - return 0; - } - - ssl_data->pdu = data; - ssl_data->pdu_len = (unsigned)data_len; - ret = do_mbedtls_handshake(c_session, m_env); - if (ret == 0 || m_env->seen_client_hello) { - /* The test for seen_client_hello gives the ability to setup a new - c_session to continue the do_mbedtls_handshake past the client hello - and safely allow updating of the m_env and separately - letting a new session cleanly start up. - */ - m_env->seen_client_hello = 0; - return 1; - } - return 0; -#endif /* !ESPIDF_VERSION) || (CONFIG_MBEDTLS_SSL_PROTO_DTLS && CONFIG_MBEDTLS_TLS_SERVER) */ -} - -unsigned int coap_dtls_get_overhead(coap_session_t *c_session UNUSED) -{ - return 13 + 8 + 8; -} - -void *coap_tls_new_client_session(coap_session_t *c_session UNUSED, int *connected UNUSED) -{ - return NULL; -} - -void *coap_tls_new_server_session(coap_session_t *c_session UNUSED, int *connected UNUSED) -{ - return NULL; -} - -void coap_tls_free_session( coap_session_t *c_session UNUSED) -{ - return; -} - -ssize_t coap_tls_write(coap_session_t *c_session UNUSED, - const uint8_t *data UNUSED, - size_t data_len UNUSED - ) -{ - return 0; -} - -ssize_t coap_tls_read(coap_session_t *c_session UNUSED, - uint8_t *data UNUSED, - size_t data_len UNUSED - ) -{ - return 0; -} - -void coap_dtls_startup(void) -{ - return; -} - -static int keep_log_level = 0; - -void coap_dtls_set_log_level(int level) -{ -#if !defined(ESPIDF_VERSION) - int use_level; - /* - * MbedTLS debug levels filter - * 0 No debug - * 1 Error - * 2 State change - * 3 Informational - * 4 Verbose - */ - - if (level <= LOG_ERR) { - use_level = 1; - } - else { - use_level = (level >= LOG_DEBUG) ? level - LOG_DEBUG + 2 : 0; - } - mbedtls_debug_set_threshold(use_level); -#endif /* !ESPIDF_VERSION) */ - keep_log_level = level; - return; -} - -int coap_dtls_get_log_level(void) -{ - return keep_log_level; -} - -coap_tls_version_t * coap_get_tls_library_version(void) -{ - static coap_tls_version_t version; - version.version = mbedtls_version_get_number(); - version.built_version = MBEDTLS_VERSION_NUMBER; - version.type = COAP_TLS_LIBRARY_MBEDTLS; - return &version; -} - -#else /* !HAVE_MBEDTLS */ - -#ifdef __clang__ -/* Make compilers happy that do not like empty modules. As this function is - * never used, we ignore -Wunused-function at the end of compiling this file - */ -#pragma GCC diagnostic ignored "-Wunused-function" -#endif -static inline void dummy(void) { -} - -#endif /* HAVE_MBEDTLS */ diff --git a/components/coap/port/coap_notls.c b/components/coap/port/coap_notls.c deleted file mode 100644 index aa2c27c688..0000000000 --- a/components/coap/port/coap_notls.c +++ /dev/null @@ -1,190 +0,0 @@ -/* -* coap_notls.c -- Stub Datagram Transport Layer Support for libcoap -* -* Copyright (C) 2016 Olaf Bergmann -* -* This file is part of the CoAP library libcoap. Please see README for terms -* of use. -*/ - -#include "coap_config.h" - -#if !defined(HAVE_LIBTINYDTLS) && !defined(HAVE_OPENSSL) && !defined(HAVE_LIBGNUTLS) && !defined(HAVE_MBEDTLS) - -#include "net.h" - -#ifdef __GNUC__ -#define UNUSED __attribute__((unused)) -#else /* __GNUC__ */ -#define UNUSED -#endif /* __GNUC__ */ - -int -coap_dtls_is_supported(void) { - return 0; -} - -int -coap_tls_is_supported(void) { - return 0; -} - -coap_tls_version_t * -coap_get_tls_library_version(void) { - static coap_tls_version_t version; - version.version = 0; - version.type = COAP_TLS_LIBRARY_NOTLS; - return &version; -} - -int -coap_dtls_context_set_pki(coap_context_t *ctx UNUSED, - coap_dtls_pki_t* setup_data UNUSED, - coap_dtls_role_t role UNUSED -) { - return 0; -} - -int -coap_dtls_context_set_pki_root_cas(struct coap_context_t *ctx UNUSED, - const char *ca_file UNUSED, - const char *ca_path UNUSED -) { - return 0; -} - -int -coap_dtls_context_set_psk(coap_context_t *ctx UNUSED, - const char *hint UNUSED, - coap_dtls_role_t role UNUSED -) { - return 0; -} - -int -coap_dtls_context_check_keys_enabled(coap_context_t *ctx UNUSED) -{ - return 0; -} - -static int dtls_log_level = 0; - -void coap_dtls_startup(void) { -} - -void -coap_dtls_set_log_level(int level) { - dtls_log_level = level; -} - -int -coap_dtls_get_log_level(void) { - return dtls_log_level; -} - -void * -coap_dtls_new_context(struct coap_context_t *coap_context UNUSED) { - return NULL; -} - -void -coap_dtls_free_context(void *handle UNUSED) { -} - -void *coap_dtls_new_server_session(coap_session_t *session UNUSED) { - return NULL; -} - -void *coap_dtls_new_client_session(coap_session_t *session UNUSED) { - return NULL; -} - -void coap_dtls_free_session(coap_session_t *coap_session UNUSED) { -} - -void coap_dtls_session_update_mtu(coap_session_t *session UNUSED) { -} - -int -coap_dtls_send(coap_session_t *session UNUSED, - const uint8_t *data UNUSED, - size_t data_len UNUSED -) { - return -1; -} - -int coap_dtls_is_context_timeout(void) { - return 1; -} - -coap_tick_t coap_dtls_get_context_timeout(void *dtls_context UNUSED) { - return 0; -} - -coap_tick_t -coap_dtls_get_timeout(coap_session_t *session UNUSED, coap_tick_t now UNUSED) { - return 0; -} - -void coap_dtls_handle_timeout(coap_session_t *session UNUSED) { -} - -int -coap_dtls_receive(coap_session_t *session UNUSED, - const uint8_t *data UNUSED, - size_t data_len UNUSED -) { - return -1; -} - -int -coap_dtls_hello(coap_session_t *session UNUSED, - const uint8_t *data UNUSED, - size_t data_len UNUSED -) { - return 0; -} - -unsigned int coap_dtls_get_overhead(coap_session_t *session UNUSED) { - return 0; -} - -void *coap_tls_new_client_session(coap_session_t *session UNUSED, int *connected UNUSED) { - return NULL; -} - -void *coap_tls_new_server_session(coap_session_t *session UNUSED, int *connected UNUSED) { - return NULL; -} - -void coap_tls_free_session(coap_session_t *coap_session UNUSED) { -} - -ssize_t coap_tls_write(coap_session_t *session UNUSED, - const uint8_t *data UNUSED, - size_t data_len UNUSED -) { - return -1; -} - -ssize_t coap_tls_read(coap_session_t *session UNUSED, - uint8_t *data UNUSED, - size_t data_len UNUSED -) { - return -1; -} - -#undef UNUSED - -#else /* !HAVE_LIBTINYDTLS && !HAVE_OPENSSL && !HAVE_LIBGNUTLS */ - -#ifdef __clang__ -/* Make compilers happy that do not like empty modules. As this function is - * never used, we ignore -Wunused-function at the end of compiling this file - */ -#pragma GCC diagnostic ignored "-Wunused-function" -#endif -static inline void dummy(void) { -} - -#endif /* !HAVE_LIBTINYDTLS && !HAVE_OPENSSL && !HAVE_LIBGNUTLS */ diff --git a/components/coap/port/include/coap/coap_dtls.h b/components/coap/port/include/coap/coap_dtls.h deleted file mode 100644 index 2dd0e88d2e..0000000000 --- a/components/coap/port/include/coap/coap_dtls.h +++ /dev/null @@ -1,631 +0,0 @@ -/* - * coap_dtls.h -- (Datagram) Transport Layer Support for libcoap - * - * Copyright (C) 2016 Olaf Bergmann - * Copyright (C) 2017 Jean-Claude Michelou - * - * This file is part of the CoAP library libcoap. Please see README for terms - * of use. - */ - -#ifndef COAP_DTLS_H_ -#define COAP_DTLS_H_ - -#include "coap_time.h" -#include "str.h" - -struct coap_context_t; -struct coap_session_t; -struct coap_dtls_pki_t; - -/** - * @defgroup dtls DTLS Support - * API functions for interfacing with DTLS libraries. - * @{ - */ - -/** - * Check whether DTLS is available. - * - * @return @c 1 if support for DTLS is enabled, or @c 0 otherwise. - */ -int coap_dtls_is_supported(void); - -/** - * Check whether TLS is available. - * - * @return @c 1 if support for TLS is enabled, or @c 0 otherwise. - */ -int coap_tls_is_supported(void); - -typedef enum coap_tls_library_t { - COAP_TLS_LIBRARY_NOTLS = 0, /**< No DTLS library */ - COAP_TLS_LIBRARY_TINYDTLS, /**< Using TinyDTLS library */ - COAP_TLS_LIBRARY_OPENSSL, /**< Using OpenSSL library */ - COAP_TLS_LIBRARY_GNUTLS, /**< Using GnuTLS library */ - COAP_TLS_LIBRARY_MBEDTLS, /**< Using MbedTLS library */ -} coap_tls_library_t; - -/** - * The structure used for returning the underlying (D)TLS library - * information. - */ -typedef struct coap_tls_version_t { - uint64_t version; /**< (D)TLS runtime Library Version */ - coap_tls_library_t type; /**< Library type. One of COAP_TLS_LIBRARY_* */ - uint64_t built_version; /**< (D)TLS Built against Library Version */ -} coap_tls_version_t; - -/** - * Determine the type and version of the underlying (D)TLS library. - * - * @return The version and type of library libcoap was compiled against. - */ -coap_tls_version_t *coap_get_tls_library_version(void); - -/** - * Additional Security setup handler that can be set up by - * coap_context_set_pki(). - * Invoked when libcoap has done the validation checks at the TLS level, - * but the application needs to do some additional checks/changes/updates. - * - * @param tls_session The security session definition - e.g. SSL * for OpenSSL. - * NULL if server call-back. - * This will be dependent on the underlying TLS library - - * see coap_get_tls_library_version() - * @param setup_data A structure containing setup data originally passed into - * coap_context_set_pki() or coap_new_client_session_pki(). - * - * @return @c 1 if successful, else @c 0. - */ -typedef int (*coap_dtls_security_setup_t)(void* tls_session, - struct coap_dtls_pki_t *setup_data); - -/** - * CN Validation call-back that can be set up by coap_context_set_pki(). - * Invoked when libcoap has done the validation checks at the TLS level, - * but the application needs to check that the CN is allowed. - * CN is the SubjectAltName in the cert, if not present, then the leftmost - * Common Name (CN) component of the subject name. - * - * @param cn The determined CN from the certificate - * @param asn1_public_cert The ASN.1 DER encoded X.509 certificate - * @param asn1_length The ASN.1 length - * @param coap_session The CoAP session associated with the certificate update - * @param depth Depth in cert chain. If 0, then client cert, else a CA - * @param validated TLS layer can find no issues if 1 - * @param arg The same as was passed into coap_context_set_pki() - * in setup_data->cn_call_back_arg - * - * @return @c 1 if accepted, else @c 0 if to be rejected. - */ -typedef int (*coap_dtls_cn_callback_t)(const char *cn, - const uint8_t *asn1_public_cert, - size_t asn1_length, - struct coap_session_t *coap_session, - unsigned depth, - int validated, - void *arg); - -/** - * The enum used for determining the provided PKI ASN.1 (DER) Private Key - * formats. - */ -typedef enum coap_asn1_privatekey_type_t { - COAP_ASN1_PKEY_NONE, /**< NONE */ - COAP_ASN1_PKEY_RSA, /**< RSA type */ - COAP_ASN1_PKEY_RSA2, /**< RSA2 type */ - COAP_ASN1_PKEY_DSA, /**< DSA type */ - COAP_ASN1_PKEY_DSA1, /**< DSA1 type */ - COAP_ASN1_PKEY_DSA2, /**< DSA2 type */ - COAP_ASN1_PKEY_DSA3, /**< DSA3 type */ - COAP_ASN1_PKEY_DSA4, /**< DSA4 type */ - COAP_ASN1_PKEY_DH, /**< DH type */ - COAP_ASN1_PKEY_DHX, /**< DHX type */ - COAP_ASN1_PKEY_EC, /**< EC type */ - COAP_ASN1_PKEY_HMAC, /**< HMAC type */ - COAP_ASN1_PKEY_CMAC, /**< CMAC type */ - COAP_ASN1_PKEY_TLS1_PRF, /**< TLS1_PRF type */ - COAP_ASN1_PKEY_HKDF /**< HKDF type */ -} coap_asn1_privatekey_type_t; - -/** - * The enum used for determining the PKI key formats. - */ -typedef enum coap_pki_key_t { - COAP_PKI_KEY_PEM = 0, /**< The PKI key type is PEM file */ - COAP_PKI_KEY_ASN1, /**< The PKI key type is ASN.1 (DER) */ - COAP_PKI_KEY_PEM_BUF, /**< The PKI key type is PEM buffer */ -} coap_pki_key_t; - -/** - * The structure that holds the PKI PEM definitions. - */ -typedef struct coap_pki_key_pem_t { - const char *ca_file; /**< File location of Common CA in PEM format */ - const char *public_cert; /**< File location of Public Cert in PEM format */ - const char *private_key; /**< File location of Private Key in PEM format */ -} coap_pki_key_pem_t; - -/** - * The structure that holds the PKI PEM buffer definitions. - */ -typedef struct coap_pki_key_pem_buf_t { - const uint8_t *ca_cert; /**< PEM buffer Common CA Cert */ - const uint8_t *public_cert; /**< PEM buffer Public Cert */ - const uint8_t *private_key; /**< PEM buffer Private Key */ - size_t ca_cert_len; /**< PEM buffer CA Cert length */ - size_t public_cert_len; /**< PEM buffer Public Cert length */ - size_t private_key_len; /**< PEM buffer Private Key length */ -} coap_pki_key_pem_buf_t; - -/** - * The structure that holds the PKI ASN.1 (DER) definitions. - */ -typedef struct coap_pki_key_asn1_t { - const uint8_t *ca_cert; /**< ASN1 (DER) Common CA Cert */ - const uint8_t *public_cert; /**< ASN1 (DER) Public Cert */ - const uint8_t *private_key; /**< ASN1 (DER) Private Key */ - size_t ca_cert_len; /**< ASN1 CA Cert length */ - size_t public_cert_len; /**< ASN1 Public Cert length */ - size_t private_key_len; /**< ASN1 Private Key length */ - coap_asn1_privatekey_type_t private_key_type; /**< Private Key Type */ -} coap_pki_key_asn1_t; - -/** - * The structure that holds the PKI key information. - */ -typedef struct coap_dtls_key_t { - coap_pki_key_t key_type; /**< key format type */ - union { - coap_pki_key_pem_t pem; /**< for PEM file keys */ - coap_pki_key_pem_buf_t pem_buf; /**< for PEM memory keys */ - coap_pki_key_asn1_t asn1; /**< for ASN.1 (DER) file keys */ - } key; -} coap_dtls_key_t; - -/** - * Server Name Indication (SNI) Validation call-back that can be set up by - * coap_context_set_pki(). - * Invoked if the SNI is not previously seen and prior to sending a certificate - * set back to the client so that the appropriate certificate set can be used - * based on the requesting SNI. - * - * @param sni The requested SNI - * @param arg The same as was passed into coap_context_set_pki() - * in setup_data->sni_call_back_arg - * - * @return New set of certificates to use, or @c NULL if SNI is to be rejected. - */ -typedef coap_dtls_key_t *(*coap_dtls_sni_callback_t)(const char *sni, - void* arg); - - -#define COAP_DTLS_PKI_SETUP_VERSION 1 /**< Latest PKI setup version */ - -/** - * The structure used for defining the PKI setup data to be used. - */ -typedef struct coap_dtls_pki_t { - uint8_t version; /** Set to 1 to support this version of the struct */ - - /* Options to enable different TLS functionality in libcoap */ - uint8_t verify_peer_cert; /**< 1 if peer cert is to be verified */ - uint8_t require_peer_cert; /**< 1 if peer cert is required */ - uint8_t allow_self_signed; /**< 1 if self signed certs are allowed */ - uint8_t allow_expired_certs; /**< 1 if expired certs are allowed */ - uint8_t cert_chain_validation; /**< 1 if to check cert_chain_verify_depth */ - uint8_t cert_chain_verify_depth; /**< recommended depth is 3 */ - uint8_t check_cert_revocation; /**< 1 if revocation checks wanted */ - uint8_t allow_no_crl; /**< 1 ignore if CRL not there */ - uint8_t allow_expired_crl; /**< 1 if expired crl is allowed */ - uint8_t allow_bad_md_hash; /**< 1 if expired certs are allowed */ - uint8_t allow_short_rsa_length; /**< 1 if expired certs are allowed */ - uint8_t reserved[4]; /**< Reserved - must be set to 0 for - future compatibility */ - /* Size of 4 chosen to align to next - * parameter, so if newly defined option - * it can use one of the reserverd slot so - * no need to change - * COAP_DTLS_PKI_SETUP_VERSION and just - * decrement the reserved[] count. - */ - - /** CN check call-back function. - * If not NULL, is called when the TLS connection has passed the configured - * TLS options above for the application to verify if the CN is valid. - */ - coap_dtls_cn_callback_t validate_cn_call_back; - void *cn_call_back_arg; /**< Passed in to the CN call-back function */ - - /** SNI check call-back function. - * If not @p NULL, called if the SNI is not previously seen and prior to - * sending a certificate set back to the client so that the appropriate - * certificate set can be used based on the requesting SNI. - */ - coap_dtls_sni_callback_t validate_sni_call_back; - void *sni_call_back_arg; /**< Passed in to the sni call-back function */ - - /** Additional Security call-back handler that is invoked when libcoap has - * done the standerd, defined validation checks at the TLS level, - * If not @p NULL, called from within the TLS Client Hello connection - * setup. - */ - coap_dtls_security_setup_t additional_tls_setup_call_back; - - char* client_sni; /**< If not NULL, SNI to use in client TLS setup. - Owned by the client app and must remain valid - during the call to coap_new_client_session_pki() */ - - coap_dtls_key_t pki_key; /**< PKI key definition */ -} coap_dtls_pki_t; - -/** @} */ - -/** - * @defgroup dtls_internal DTLS Support (Internal) - * Internal API functions for interfacing with DTLS libraries. - * @{ - */ - -/** - * Creates a new DTLS context for the given @p coap_context. This function - * returns a pointer to a new DTLS context object or @c NULL on error. - * - * Internal function. - * - * @param coap_context The CoAP context where the DTLS object shall be used. - * - * @return A DTLS context object or @c NULL on error. - */ -void * -coap_dtls_new_context(struct coap_context_t *coap_context); - -typedef enum coap_dtls_role_t { - COAP_DTLS_ROLE_CLIENT, /**< Internal function invoked for client */ - COAP_DTLS_ROLE_SERVER /**< Internal function invoked for server */ -} coap_dtls_role_t; - -/** - * Set the DTLS context's default PSK information. - * This does the PSK specifics following coap_dtls_new_context(). - * If @p COAP_DTLS_ROLE_SERVER, then identity hint will also get set. - * If @p COAP_DTLS_ROLE_SERVER, then the information will get put into the - * TLS library's context (from which sessions are derived). - * If @p COAP_DTLS_ROLE_CLIENT, then the information will get put into the - * TLS library's session. - * - * Internal function. - * - * @param coap_context The CoAP context. - * @param identity_hint The default PSK server identity hint sent to a client. - * Required parameter. If @p NULL, will be set to "". - * Empty string is a valid hint. - * This parameter is ignored if COAP_DTLS_ROLE_CLIENT - * @param role One of @p COAP_DTLS_ROLE_CLIENT or @p COAP_DTLS_ROLE_SERVER - * - * @return @c 1 if successful, else @c 0. - */ - -int -coap_dtls_context_set_psk(struct coap_context_t *coap_context, - const char *identity_hint, - coap_dtls_role_t role); - -/** - * Set the DTLS context's default server PKI information. - * This does the PKI specifics following coap_dtls_new_context(). - * If @p COAP_DTLS_ROLE_SERVER, then the information will get put into the - * TLS library's context (from which sessions are derived). - * If @p COAP_DTLS_ROLE_CLIENT, then the information will get put into the - * TLS library's session. - * - * Internal function. - * - * @param coap_context The CoAP context. - * @param setup_data Setup information defining how PKI is to be setup. - * Required parameter. If @p NULL, PKI will not be - * set up. - * @param role One of @p COAP_DTLS_ROLE_CLIENT or @p COAP_DTLS_ROLE_SERVER - * - * @return @c 1 if successful, else @c 0. - */ - -int -coap_dtls_context_set_pki(struct coap_context_t *coap_context, - coap_dtls_pki_t *setup_data, - coap_dtls_role_t role); - -/** - * Set the dtls context's default Root CA information for a client or server. - * - * Internal function. - * - * @param coap_context The current coap_context_t object. - * @param ca_file If not @p NULL, is the full path name of a PEM encoded - * file containing all the Root CAs to be used. - * @param ca_dir If not @p NULL, points to a directory containing PEM - * encoded files containing all the Root CAs to be used. - * - * @return @c 1 if successful, else @c 0. - */ - -int -coap_dtls_context_set_pki_root_cas(struct coap_context_t *coap_context, - const char *ca_file, - const char *ca_dir); - -/** - * Check whether one of the coap_dtls_context_set_{psk|pki}() functions have - * been called. - * - * Internal function. - * - * @param coap_context The current coap_context_t object. - * - * @return @c 1 if coap_dtls_context_set_{psk|pki}() called, else @c 0. - */ - -int coap_dtls_context_check_keys_enabled(struct coap_context_t *coap_context); - -/** - * Releases the storage allocated for @p dtls_context. - * - * Internal function. - * - * @param dtls_context The DTLS context as returned by coap_dtls_new_context(). - */ -void coap_dtls_free_context(void *dtls_context); - -/** - * Create a new client-side session. This should send a HELLO to the server. - * - * Internal function. - * - * @param coap_session The CoAP session. - * - * @return Opaque handle to underlying TLS library object containing security - * parameters for the session. -*/ -void *coap_dtls_new_client_session(struct coap_session_t *coap_session); - -/** - * Create a new DTLS server-side session. - * Called after coap_dtls_hello() has returned @c 1, signalling that a validated - * HELLO was received from a client. - * This should send a HELLO to the server. - * - * Internal function. - * - * @param coap_session The CoAP session. - * - * @return Opaque handle to underlying TLS library object containing security - * parameters for the DTLS session. - */ -void *coap_dtls_new_server_session(struct coap_session_t *coap_session); - -/** - * Terminates the DTLS session (may send an ALERT if necessary) then frees the - * underlying TLS library object containing security parameters for the session. - * - * Internal function. - * - * @param coap_session The CoAP session. - */ -void coap_dtls_free_session(struct coap_session_t *coap_session); - -/** - * Notify of a change in the CoAP session's MTU, for example after - * a PMTU update. - * - * Internal function. - * - * @param coap_session The CoAP session. - */ -void coap_dtls_session_update_mtu(struct coap_session_t *coap_session); - -/** - * Send data to a DTLS peer. - * - * Internal function. - * - * @param coap_session The CoAP session. - * @param data pointer to data. - * @param data_len Number of bytes to send. - * - * @return @c 0 if this would be blocking, @c -1 if there is an error or the - * number of cleartext bytes sent. - */ -int coap_dtls_send(struct coap_session_t *coap_session, - const uint8_t *data, - size_t data_len); - -/** - * Check if timeout is handled per CoAP session or per CoAP context. - * - * Internal function. - * - * @return @c 1 of timeout and retransmit is per context, @c 0 if it is - * per session. - */ -int coap_dtls_is_context_timeout(void); - -/** - * Do all pending retransmits and get next timeout - * - * Internal function. - * - * @param dtls_context The DTLS context. - * - * @return @c 0 if no event is pending or date of the next retransmit. - */ -coap_tick_t coap_dtls_get_context_timeout(void *dtls_context); - -/** - * Get next timeout for this session. - * - * Internal function. - * - * @param coap_session The CoAP session. - * @param now The current time in ticks. - * - * @return @c 0 If no event is pending or ticks time of the next retransmit. - */ -coap_tick_t coap_dtls_get_timeout(struct coap_session_t *coap_session, - coap_tick_t now); - -/** - * Handle a DTLS timeout expiration. - * - * Internal function. - * - * @param coap_session The CoAP session. - */ -void coap_dtls_handle_timeout(struct coap_session_t *coap_session); - -/** - * Handling incoming data from a DTLS peer. - * - * Internal function. - * - * @param coap_session The CoAP session. - * @param data Encrypted datagram. - * @param data_len Encrypted datagram size. - * - * @return Result of coap_handle_dgram on the decrypted CoAP PDU - * or @c -1 for error. - */ -int coap_dtls_receive(struct coap_session_t *coap_session, - const uint8_t *data, - size_t data_len); - -/** - * Handling client HELLO messages from a new candiate peer. - * Note that session->tls is empty. - * - * Internal function. - * - * @param coap_session The CoAP session. - * @param data Encrypted datagram. - * @param data_len Encrypted datagram size. - * - * @return @c 0 if a cookie verification message has been sent, @c 1 if the - * HELLO contains a valid cookie and a server session should be created, - * @c -1 if the message is invalid. - */ -int coap_dtls_hello(struct coap_session_t *coap_session, - const uint8_t *data, - size_t data_len); - -/** - * Get DTLS overhead over cleartext PDUs. - * - * Internal function. - * - * @param coap_session The CoAP session. - * - * @return Maximum number of bytes added by DTLS layer. - */ -unsigned int coap_dtls_get_overhead(struct coap_session_t *coap_session); - -/** - * Create a new TLS client-side session. - * - * Internal function. - * - * @param coap_session The CoAP session. - * @param connected Updated with whether the connection is connected yet or not. - * @c 0 is not connected, @c 1 is connected. - * - * @return Opaque handle to underlying TLS library object containing security - * parameters for the session. -*/ -void *coap_tls_new_client_session(struct coap_session_t *coap_session, int *connected); - -/** - * Create a TLS new server-side session. - * - * Internal function. - * - * @param coap_session The CoAP session. - * @param connected Updated with whether the connection is connected yet or not. - * @c 0 is not connected, @c 1 is connected. - * - * @return Opaque handle to underlying TLS library object containing security - * parameters for the session. - */ -void *coap_tls_new_server_session(struct coap_session_t *coap_session, int *connected); - -/** - * Terminates the TLS session (may send an ALERT if necessary) then frees the - * underlying TLS library object containing security parameters for the session. - * - * Internal function. - * - * @param coap_session The CoAP session. - */ -void coap_tls_free_session( struct coap_session_t *coap_session ); - -/** - * Send data to a TLS peer, with implicit flush. - * - * Internal function. - * - * @param coap_session The CoAP session. - * @param data Pointer to data. - * @param data_len Number of bytes to send. - * - * @return @c 0 if this should be retried, @c -1 if there is an error - * or the number of cleartext bytes sent. - */ -ssize_t coap_tls_write(struct coap_session_t *coap_session, - const uint8_t *data, - size_t data_len - ); - -/** - * Read some data from a TLS peer. - * - * Internal function. - * - * @param coap_session The CoAP session. - * @param data Pointer to data. - * @param data_len Maximum number of bytes to read. - * - * @return @c 0 if this should be retried, @c -1 if there is an error - * or the number of cleartext bytes read. - */ -ssize_t coap_tls_read(struct coap_session_t *coap_session, - uint8_t *data, - size_t data_len - ); - -/** - * Initialize the underlying (D)TLS Library layer. - * - * Internal function. - * - */ -void coap_dtls_startup(void); - -/** @} */ - -/** - * @ingroup logging - * Sets the (D)TLS logging level to the specified @p level. - * Note: coap_log_level() will influence output if at a specified level. - * - * @param level The logging level to use - LOG_* - */ -void coap_dtls_set_log_level(int level); - -/** - * @ingroup logging - * Get the current (D)TLS logging. - * - * @return The current log level (one of LOG_*). - */ -int coap_dtls_get_log_level(void); - - -#endif /* COAP_DTLS_H */ diff --git a/components/coap/port/include/coap/coap.h b/components/coap/port/include/coap3/coap.h similarity index 53% rename from components/coap/port/include/coap/coap.h rename to components/coap/port/include/coap3/coap.h index f048ca8571..c69d2734b3 100644 --- a/components/coap/port/include/coap/coap.h +++ b/components/coap/port/include/coap3/coap.h @@ -21,27 +21,28 @@ extern "C" { #endif -#include "libcoap.h" +#include "coap3/libcoap.h" -#include "address.h" -#include "async.h" -#include "bits.h" -#include "block.h" -#include "coap_dtls.h" -#include "coap_event.h" -#include "coap_io.h" -#include "coap_time.h" -#include "coap_debug.h" -#include "encode.h" -#include "mem.h" -#include "net.h" -#include "option.h" -#include "pdu.h" -#include "prng.h" -#include "resource.h" -#include "str.h" -#include "subscribe.h" -#include "uri.h" +#include "coap3/coap_forward_decls.h" +#include "coap3/address.h" +#include "coap3/async.h" +#include "coap3/block.h" +#include "coap3/coap_cache.h" +#include "coap3/coap_dtls.h" +#include "coap3/coap_event.h" +#include "coap3/coap_io.h" +#include "coap3/coap_time.h" +#include "coap3/coap_debug.h" +#include "coap3/encode.h" +#include "coap3/mem.h" +#include "coap3/net.h" +#include "coap3/option.h" +#include "coap3/pdu.h" +#include "coap3/coap_prng.h" +#include "coap3/resource.h" +#include "coap3/str.h" +#include "coap3/subscribe.h" +#include "coap3/uri.h" #ifdef __cplusplus } diff --git a/components/coap/port/include/coap_config_posix.h b/components/coap/port/include/coap_config_posix.h index 3f6b7c605f..b24335ad15 100644 --- a/components/coap/port/include/coap_config_posix.h +++ b/components/coap/port/include/coap_config_posix.h @@ -30,6 +30,7 @@ #define HAVE_NETDB_H #define HAVE_NETINET_IN_H #define HAVE_STRUCT_CMSGHDR +#define COAP_DISABLE_TCP 0 #define ipi_spec_dst ipi_addr struct in6_pktinfo { @@ -53,8 +54,6 @@ struct in6_pktinfo { #define COAP_CONSTRAINED_STACK 1 #define ESPIDF_VERSION -#define _POSIX_TIMERS 1 - #define gai_strerror(x) "gai_strerror() not supported" #endif /* WITH_POSIX */ diff --git a/components/console/CMakeLists.txt b/components/console/CMakeLists.txt index 6fddca7f61..cde2b05cd2 100644 --- a/components/console/CMakeLists.txt +++ b/components/console/CMakeLists.txt @@ -6,3 +6,7 @@ idf_component_register(SRCS "commands.c" INCLUDE_DIRS "." REQUIRES vfs PRIV_REQUIRES driver) + +if(CMAKE_C_COMPILER_ID MATCHES "GNU") + set_source_files_properties(argtable3/argtable3.c PROPERTIES COMPILE_FLAGS -Wno-clobbered) +endif() diff --git a/components/console/argtable3/argtable3.c b/components/console/argtable3/argtable3.c index ca9149277c..0c3cb729fd 100644 --- a/components/console/argtable3/argtable3.c +++ b/components/console/argtable3/argtable3.c @@ -30,8 +30,6 @@ #include "argtable3.h" -#pragma GCC diagnostic ignored "-Wclobbered" - /******************************************************************************* * This file is part of the argtable3 library. * diff --git a/components/console/component.mk b/components/console/component.mk index 0a6d4945e3..703e86d80d 100644 --- a/components/console/component.mk +++ b/components/console/component.mk @@ -1,2 +1,4 @@ COMPONENT_ADD_INCLUDEDIRS := . COMPONENT_SRCDIRS := linenoise argtable3 . + +argtable3/argtable3.o: CFLAGS += -Wno-clobbered diff --git a/components/driver/CMakeLists.txt b/components/driver/CMakeLists.txt index 28b1efee72..093e321823 100644 --- a/components/driver/CMakeLists.txt +++ b/components/driver/CMakeLists.txt @@ -67,6 +67,7 @@ if(IDF_TARGET STREQUAL "esp32c3") list(APPEND srcs "gdma.c" "spi_slave_hd.c" "adc_common.c" + "dedic_gpio.c" "usb_serial_jtag.c" "esp32c3/adc.c" "esp32c3/adc2_init_cal.c" @@ -77,6 +78,7 @@ if(IDF_TARGET STREQUAL "esp32h2") list(APPEND srcs "gdma.c" "spi_slave_hd.c" "adc_common.c" + "dedic_gpio.c" "esp32h2/adc.c" "esp32h2/adc2_init_cal.c" "esp32h2/rtc_tempsensor.c") diff --git a/components/driver/Kconfig b/components/driver/Kconfig index aedad08772..6ca95be2ca 100644 --- a/components/driver/Kconfig +++ b/components/driver/Kconfig @@ -21,6 +21,20 @@ menu "Driver configurations" endmenu # ADC Configuration + menu "MCPWM configuration" + + config MCPWM_ISR_IN_IRAM + bool "Place MCPWM ISR function into IRAM" + default n + help + If this option is not selected, the MCPWM interrupt will be deferred when the Cache + is in a disabled state (e.g. Flash write/erase operation). + + Note that if this option is selected, all user registered ISR callbacks should never + try to use cache as well. (with IRAM_ATTR) + + endmenu # MCPWM Configuration + menu "SPI configuration" config SPI_MASTER_IN_IRAM diff --git a/components/driver/adc_common.c b/components/driver/adc_common.c index a231b8134a..8cc8e434df 100644 --- a/components/driver/adc_common.c +++ b/components/driver/adc_common.c @@ -18,16 +18,18 @@ #include "driver/gpio.h" #include "driver/adc.h" #include "adc1_private.h" - #include "hal/adc_types.h" #include "hal/adc_hal.h" +#include "hal/adc_hal_conf.h" #if SOC_DAC_SUPPORTED #include "driver/dac.h" #include "hal/dac_hal.h" #endif -#include "hal/adc_hal_conf.h" +#if CONFIG_IDF_TARGET_ESP32S3 +#include "esp_efuse_rtc_calib.h" +#endif #define ADC_CHECK_RET(fun_ret) ({ \ if (fun_ret != ESP_OK) { \ @@ -123,20 +125,10 @@ static esp_pm_lock_handle_t s_adc2_arbiter_lock; #endif //CONFIG_PM_ENABLE #endif // !CONFIG_IDF_TARGET_ESP32 + /*--------------------------------------------------------------- ADC Common ---------------------------------------------------------------*/ - -#if CONFIG_IDF_TARGET_ESP32S2 -static uint32_t get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t chan) -{ - adc_atten_t atten = adc_hal_get_atten(adc_n, chan); - - extern uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool no_cal); - return adc_get_calibration_offset(adc_n, chan, atten, false); -} -#endif - // ADC Power // This gets incremented when adc_power_acquire() is called, and decremented when @@ -226,7 +218,61 @@ esp_err_t adc2_pad_get_io_num(adc2_channel_t channel, gpio_num_t *gpio_num) return ESP_OK; } -#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 + +//------------------------------------------------------------RTC Single Read----------------------------------------------// +#if SOC_ADC_RTC_CTRL_SUPPORTED + +/*--------------------------------------------------------------- + ADC Calibration +---------------------------------------------------------------*/ +#if CONFIG_IDF_TARGET_ESP32S3 +/** + * Temporarily put this function here. These are about ADC calibration and will be moved driver/adc.c in !14278. + * Reason for putting calibration functions in driver/adc.c: + * adc_common.c is far too confusing. Before a refactor is applied to adc_common.c, will put definite code in driver/adc.c + */ + +static uint16_t s_adc_cali_param[ADC_UNIT_MAX][ADC_ATTEN_MAX] = {}; + +uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten) +{ + if (s_adc_cali_param[adc_n][atten]) { + //These value won't exceed UINT16_MAX + return s_adc_cali_param[adc_n][atten]; + } + + //Get the calibration version + int version = esp_efuse_rtc_calib_get_ver(); + + uint32_t init_code = 0; + if (version == 1) { + init_code = esp_efuse_rtc_calib_get_init_code(version, adc_n, atten); + } else { + ESP_LOGV(ADC_TAG, "Calibration eFuse is not configured, use self-calibration for ICode"); + adc_power_acquire(); + RTC_ENTER_CRITICAL(); + const bool internal_gnd = true; + init_code = adc_hal_self_calibration(adc_n, channel, atten, internal_gnd); + RTC_EXIT_CRITICAL(); + adc_power_release(); + } + s_adc_cali_param[adc_n][atten] = init_code; + return s_adc_cali_param[adc_n][atten]; +} +#elif CONFIG_IDF_TARGET_ESP32S2 +//Temporarily extern this from s2/adc.c. Will be modified in !14278. +extern uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten); +#endif //CONFIG_IDF_TARGET_ESP32S3 + +#if SOC_ADC_CALIBRATION_V1_SUPPORTED +static uint32_t get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t chan) +{ + adc_atten_t atten = adc_hal_get_atten(adc_n, chan); + + return adc_get_calibration_offset(adc_n, chan, atten); +} +#endif //#if SOC_ADC_CALIBRATION_V1_SUPPORTED + esp_err_t adc_set_clk_div(uint8_t clk_div) { DIGI_CONTROLLER_ENTER(); @@ -349,7 +395,7 @@ esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten) adc_hal_set_atten(ADC_NUM_1, channel, atten); SARADC1_EXIT(); -#if SOC_ADC_HW_CALIBRATION_V1 +#if SOC_ADC_CALIBRATION_V1_SUPPORTED adc_hal_calibration_init(ADC_NUM_1); #endif @@ -427,11 +473,11 @@ int adc1_get_raw(adc1_channel_t channel) ADC_CHANNEL_CHECK(ADC_NUM_1, channel); adc1_rtc_mode_acquire(); -#if CONFIG_IDF_TARGET_ESP32S2 +#if SOC_ADC_CALIBRATION_V1_SUPPORTED // Get calibration value before going into critical section uint32_t cal_val = get_calibration_offset(ADC_NUM_1, channel); adc_hal_set_calibration_param(ADC_NUM_1, cal_val); -#endif +#endif //SOC_ADC_CALIBRATION_V1_SUPPORTED SARADC1_ENTER(); #ifdef CONFIG_IDF_TARGET_ESP32 @@ -521,7 +567,7 @@ esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten) SARADC2_RELEASE(); -#if SOC_ADC_HW_CALIBRATION_V1 +#if SOC_ADC_CALIBRATION_V1_SUPPORTED adc_hal_calibration_init(ADC_NUM_2); #endif @@ -578,11 +624,11 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int * ADC_CHECK(width_bit == ADC_WIDTH_MAX - 1, "WIDTH ERR: see `adc_bits_width_t` for supported bit width", ESP_ERR_INVALID_ARG); #endif -#if CONFIG_IDF_TARGET_ESP32S2 +#if SOC_ADC_CALIBRATION_V1_SUPPORTED // Get calibration value before going into critical section uint32_t cal_val = get_calibration_offset(ADC_NUM_2, channel); adc_hal_set_calibration_param(ADC_NUM_2, cal_val); -#endif +#endif //SOC_ADC_CALIBRATION_V1_SUPPORTED if ( SARADC2_TRY_ACQUIRE() == -1 ) { //try the lock, return if failed (wifi using). @@ -679,4 +725,4 @@ esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio) return ESP_OK; } -#endif //CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 +#endif //SOC_ADC_RTC_CTRL_SUPPORTED diff --git a/components/driver/dac_common.c b/components/driver/dac_common.c index 79172eb984..791926b0fc 100644 --- a/components/driver/dac_common.c +++ b/components/driver/dac_common.c @@ -8,6 +8,7 @@ #include #include "esp_log.h" #include "esp_err.h" +#include "esp_check.h" #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" #include "freertos/timers.h" @@ -18,21 +19,14 @@ extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished. -static const char *DAC_TAG = "DAC"; - -#define DAC_CHECK(a, str, ret_val) ({ \ - if (!(a)) { \ - ESP_LOGE(DAC_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ - return (ret_val); \ - } \ -}) +static const char *TAG = "DAC"; /*--------------------------------------------------------------- DAC ---------------------------------------------------------------*/ esp_err_t dac_pad_get_io_num(dac_channel_t channel, gpio_num_t *gpio_num) { - DAC_CHECK(channel < DAC_CHANNEL_MAX, "DAC channel error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(channel < DAC_CHANNEL_MAX, ESP_ERR_INVALID_ARG, TAG, "DAC channel error"); *gpio_num = (gpio_num_t)dac_periph_signal.dac_channel_io_num[channel]; @@ -41,7 +35,7 @@ esp_err_t dac_pad_get_io_num(dac_channel_t channel, gpio_num_t *gpio_num) static esp_err_t dac_rtc_pad_init(dac_channel_t channel) { - DAC_CHECK(channel < DAC_CHANNEL_MAX, "DAC channel error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(channel < DAC_CHANNEL_MAX, ESP_ERR_INVALID_ARG, TAG, "DAC channel error"); gpio_num_t gpio_num = 0; dac_pad_get_io_num(channel, &gpio_num); @@ -55,7 +49,7 @@ static esp_err_t dac_rtc_pad_init(dac_channel_t channel) esp_err_t dac_output_enable(dac_channel_t channel) { - DAC_CHECK(channel < DAC_CHANNEL_MAX, "DAC channel error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(channel < DAC_CHANNEL_MAX, ESP_ERR_INVALID_ARG, TAG, "DAC channel error"); dac_rtc_pad_init(channel); portENTER_CRITICAL(&rtc_spinlock); @@ -68,7 +62,7 @@ esp_err_t dac_output_enable(dac_channel_t channel) esp_err_t dac_output_disable(dac_channel_t channel) { - DAC_CHECK(channel < DAC_CHANNEL_MAX, "DAC channel error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(channel < DAC_CHANNEL_MAX, ESP_ERR_INVALID_ARG, TAG, "DAC channel error"); portENTER_CRITICAL(&rtc_spinlock); dac_hal_power_down(channel); @@ -79,7 +73,7 @@ esp_err_t dac_output_disable(dac_channel_t channel) esp_err_t dac_output_voltage(dac_channel_t channel, uint8_t dac_value) { - DAC_CHECK(channel < DAC_CHANNEL_MAX, "DAC channel error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(channel < DAC_CHANNEL_MAX, ESP_ERR_INVALID_ARG, TAG, "DAC channel error"); portENTER_CRITICAL(&rtc_spinlock); dac_hal_update_output_value(channel, dac_value); @@ -90,7 +84,7 @@ esp_err_t dac_output_voltage(dac_channel_t channel, uint8_t dac_value) esp_err_t dac_out_voltage(dac_channel_t channel, uint8_t dac_value) { - DAC_CHECK(channel < DAC_CHANNEL_MAX, "DAC channel error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(channel < DAC_CHANNEL_MAX, ESP_ERR_INVALID_ARG, TAG, "DAC channel error"); portENTER_CRITICAL(&rtc_spinlock); dac_hal_update_output_value(channel, dac_value); @@ -119,7 +113,7 @@ esp_err_t dac_cw_generator_disable(void) esp_err_t dac_cw_generator_config(dac_cw_config_t *cw) { - if (!cw) return ESP_ERR_INVALID_ARG; + ESP_RETURN_ON_FALSE(cw, ESP_ERR_INVALID_ARG, TAG, "invalid clock configuration"); portENTER_CRITICAL(&rtc_spinlock); dac_hal_cw_generator_config(cw); diff --git a/components/driver/dedic_gpio.c b/components/driver/dedic_gpio.c index 98109f51bd..46daf61ae6 100644 --- a/components/driver/dedic_gpio.c +++ b/components/driver/dedic_gpio.c @@ -63,8 +63,8 @@ struct dedic_gpio_bundle_t { uint32_t in_mask; // mask of input channels in the bank uint32_t out_offset; // offset in the bank (seen from output channel) uint32_t in_offset; // offset in the bank (seen from input channel) - size_t nr_gpio; // number of GPIOs in the gpio_array - int gpio_array[]; // array of GPIO numbers (configured by user) + size_t nr_gpio; // number of GPIOs in the gpio_array + int gpio_array[]; // array of GPIO numbers (configured by user) }; static esp_err_t dedic_gpio_build_platform(uint32_t core_id) @@ -80,8 +80,10 @@ static esp_err_t dedic_gpio_build_platform(uint32_t core_id) s_platform[core_id]->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED; #if SOC_DEDIC_GPIO_ALLOW_REG_ACCESS s_platform[core_id]->dev = &DEDIC_GPIO; -#endif +#endif // SOC_DEDIC_GPIO_ALLOW_REG_ACCESS +#if !SOC_DEDIC_PERIPH_AUTO_ENABLE periph_module_enable(dedic_gpio_periph_signals.module); // enable APB clock to peripheral +#endif // !SOC_DEDIC_PERIPH_AUTO_ENABLE } } _lock_release(&s_platform_mutexlock[core_id]); @@ -102,7 +104,9 @@ static void dedic_gpio_break_platform(uint32_t core_id) if (s_platform[core_id]) { free(s_platform[core_id]); s_platform[core_id] = NULL; +#if !SOC_DEDIC_PERIPH_AUTO_ENABLE periph_module_disable(dedic_gpio_periph_signals.module); // disable module if no GPIO channel is being used +#endif // !SOC_DEDIC_PERIPH_AUTO_ENABLE } _lock_release(&s_platform_mutexlock[core_id]); } @@ -263,6 +267,9 @@ esp_err_t dedic_gpio_new_bundle(const dedic_gpio_bundle_config_t *config, dedic_ gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[config->gpio_array[i]], PIN_FUNC_GPIO); esp_rom_gpio_connect_out_signal(config->gpio_array[i], dedic_gpio_periph_signals.cores[core_id].out_sig_per_channel[out_offset + i], config->flags.out_invert, false); } +#if !SOC_DEDIC_GPIO_OUT_AUTO_ENABLE + cpu_ll_enable_dedic_gpio_output(s_platform[core_id]->out_occupied_mask); +#endif // !SOC_DEDIC_GPIO_OUT_AUTO_ENABLE } // it's safe to initialize bundle members without locks here @@ -340,14 +347,14 @@ err: void dedic_gpio_bundle_write(dedic_gpio_bundle_handle_t bundle, uint32_t mask, uint32_t value) { - // For performace reasons, we don't want to check the validation of parameters here + // For performance reasons, we don't want to check the validation of parameters here // Even didn't check if we're working on the correct CPU core (i.e. bundle->core_id == current core_id) cpu_ll_write_dedic_gpio_mask(bundle->out_mask & (mask << bundle->out_offset), value << bundle->out_offset); } uint32_t dedic_gpio_bundle_read_out(dedic_gpio_bundle_handle_t bundle) { - // For performace reasons, we don't want to check the validation of parameters here + // For performance reasons, we don't want to check the validation of parameters here // Even didn't check if we're working on the correct CPU core (i.e. bundle->core_id == current core_id) uint32_t value = cpu_ll_read_dedic_gpio_out(); return (value & bundle->out_mask) >> (bundle->out_offset); @@ -355,7 +362,7 @@ uint32_t dedic_gpio_bundle_read_out(dedic_gpio_bundle_handle_t bundle) uint32_t dedic_gpio_bundle_read_in(dedic_gpio_bundle_handle_t bundle) { - // For performace reasons, we don't want to check the validation of parameters here + // For performance reasons, we don't want to check the validation of parameters here // Even didn't check if we're working on the correct CPU core (i.e. bundle->core_id == current core_id) uint32_t value = cpu_ll_read_dedic_gpio_in(); return (value & bundle->in_mask) >> (bundle->in_offset); diff --git a/components/driver/esp32c3/adc.c b/components/driver/esp32c3/adc.c index 91dff0b5c5..585a139550 100644 --- a/components/driver/esp32c3/adc.c +++ b/components/driver/esp32c3/adc.c @@ -448,11 +448,11 @@ esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio) if (adc_unit & ADC_UNIT_1) { ADC_ENTER_CRITICAL(); adc_hal_vref_output(ADC_NUM_1, channel, true); - ADC_EXIT_CRITICAL() + ADC_EXIT_CRITICAL(); } else if (adc_unit & ADC_UNIT_2) { ADC_ENTER_CRITICAL(); adc_hal_vref_output(ADC_NUM_2, channel, true); - ADC_EXIT_CRITICAL() + ADC_EXIT_CRITICAL(); } ret = adc_digi_gpio_init(ADC_NUM_2, BIT(channel)); diff --git a/components/driver/esp32s2/adc.c b/components/driver/esp32s2/adc.c index 7609eb5869..a68fd46a32 100644 --- a/components/driver/esp32s2/adc.c +++ b/components/driver/esp32s2/adc.c @@ -437,7 +437,7 @@ static uint16_t s_adc_cali_param[ADC_NUM_MAX][ADC_ATTEN_MAX] = { {0}, {0} }; // 1. Semaphore when reading efuse // 2. Spinlock when actually doing ADC calibration //This function shoudn't be called inside critical section or ISR -uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool no_cal) +uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten) { #ifdef CONFIG_IDF_ENV_FPGA return 0; @@ -448,10 +448,6 @@ uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, a return (uint32_t)s_adc_cali_param[adc_n][atten]; } - if (no_cal) { - return 0; //indicating failure - } - uint32_t dout = 0; // check if we can fetch the values from eFuse. int version = esp_efuse_rtc_table_read_calib_version(); @@ -474,7 +470,7 @@ uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, a esp_err_t adc_cal_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten) { adc_hal_calibration_init(adc_n); - uint32_t cal_val = adc_get_calibration_offset(adc_n, channel, atten, false); + uint32_t cal_val = adc_get_calibration_offset(adc_n, channel, atten); ADC_ENTER_CRITICAL(); adc_hal_set_calibration_param(adc_n, cal_val); ADC_EXIT_CRITICAL(); diff --git a/components/driver/esp32s2/dac.c b/components/driver/esp32s2/dac.c index 7a1d0d40c5..16f8742a90 100644 --- a/components/driver/esp32s2/dac.c +++ b/components/driver/esp32s2/dac.c @@ -8,6 +8,7 @@ #include #include "esp_log.h" #include "esp_err.h" +#include "esp_check.h" #include "esp_pm.h" #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" @@ -17,14 +18,7 @@ #include "soc/dac_periph.h" #include "hal/dac_hal.h" -static const char *DAC_TAG = "DAC"; - -#define DAC_CHECK(a, str, ret_val) ({ \ - if (!(a)) { \ - ESP_LOGE(DAC_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ - return (ret_val); \ - } \ -}) +static const char *TAG = "DAC"; extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished. #define DAC_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock) @@ -64,11 +58,11 @@ esp_err_t dac_digi_deinit(void) esp_err_t dac_digi_controller_config(const dac_digi_config_t *cfg) { - DAC_CHECK(cfg->mode < DAC_CONV_MAX, "DAC mode error", ESP_ERR_INVALID_ARG); - DAC_CHECK(cfg->interval > 0 && cfg->interval < 4096, "DAC interval error", ESP_ERR_INVALID_ARG); - DAC_CHECK(cfg->dig_clk.div_num < 256, "DAC clk div_num error", ESP_ERR_INVALID_ARG); - DAC_CHECK(cfg->dig_clk.div_b > 0 && cfg->dig_clk.div_b < 64, "DAC clk div_b error", ESP_ERR_INVALID_ARG); - DAC_CHECK(cfg->dig_clk.div_a < 64, "DAC clk div_a error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(cfg->mode < DAC_CONV_MAX, ESP_ERR_INVALID_ARG, TAG, "DAC mode error"); + ESP_RETURN_ON_FALSE(cfg->interval > 0 && cfg->interval < 4096, ESP_ERR_INVALID_ARG, TAG, "DAC interval error"); + ESP_RETURN_ON_FALSE(cfg->dig_clk.div_num < 256, ESP_ERR_INVALID_ARG, TAG, "DAC clk div_num error"); + ESP_RETURN_ON_FALSE(cfg->dig_clk.div_b > 0 && cfg->dig_clk.div_b < 64, ESP_ERR_INVALID_ARG, TAG, "DAC clk div_b error"); + ESP_RETURN_ON_FALSE(cfg->dig_clk.div_a < 64, ESP_ERR_INVALID_ARG, TAG, "DAC clk div_a error"); #ifdef CONFIG_PM_ENABLE esp_err_t err; if (s_dac_digi_lock == NULL) { @@ -79,7 +73,7 @@ esp_err_t dac_digi_controller_config(const dac_digi_config_t *cfg) } if (err != ESP_OK) { s_dac_digi_lock = NULL; - ESP_LOGE(DAC_TAG, "DAC-DMA pm lock error"); + ESP_LOGE(TAG, "DAC-DMA pm lock error"); return err; } } @@ -95,7 +89,7 @@ esp_err_t dac_digi_controller_config(const dac_digi_config_t *cfg) esp_err_t dac_digi_start(void) { #ifdef CONFIG_PM_ENABLE - DAC_CHECK((s_dac_digi_lock), "Should start after call `dac_digi_controller_config`", ESP_FAIL); + ESP_RETURN_ON_FALSE(s_dac_digi_lock, ESP_FAIL, TAG, "Should start after call `dac_digi_controller_config`"); esp_pm_lock_acquire(s_dac_digi_lock); #endif DAC_ENTER_CRITICAL(); diff --git a/components/driver/gpio.c b/components/driver/gpio.c index f749c77a34..db27ab45ab 100644 --- a/components/driver/gpio.c +++ b/components/driver/gpio.c @@ -18,15 +18,12 @@ #include "soc/soc_caps.h" #include "soc/gpio_periph.h" #include "esp_log.h" +#include "esp_check.h" #include "hal/gpio_hal.h" #include "esp_rom_gpio.h" static const char *GPIO_TAG = "gpio"; -#define GPIO_CHECK(a, str, ret_val) \ - if (!(a)) { \ - ESP_LOGE(GPIO_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ - return (ret_val); \ - } +#define GPIO_CHECK(a, str, ret_val) ESP_RETURN_ON_FALSE(a, ret_val, GPIO_TAG, "%s", str) #define GPIO_ISR_CORE_ID_UNINIT (3) diff --git a/components/driver/i2c.c b/components/driver/i2c.c index 1ac074a299..438d1efc12 100644 --- a/components/driver/i2c.c +++ b/components/driver/i2c.c @@ -539,6 +539,7 @@ esp_err_t i2c_set_data_mode(i2c_port_t i2c_num, i2c_trans_mode_t tx_trans_mode, ESP_RETURN_ON_FALSE(rx_trans_mode < I2C_DATA_MODE_MAX, ESP_ERR_INVALID_ARG, I2C_TAG, I2C_TRANS_MODE_ERR_STR); I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock)); i2c_hal_set_data_mode(&(i2c_context[i2c_num].hal), tx_trans_mode, rx_trans_mode); + i2c_hal_update_config(&(i2c_context[i2c_num].hal)); I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock)); return ESP_OK; } @@ -690,13 +691,13 @@ esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t *i2c_conf) i2c_hal_set_sda_timing(&(i2c_context[i2c_num].hal), I2C_SLAVE_SDA_SAMPLE_DEFAULT, I2C_SLAVE_SDA_HOLD_DEFAULT); i2c_hal_set_tout(&(i2c_context[i2c_num].hal), I2C_SLAVE_TIMEOUT_DEFAULT); i2c_hal_enable_slave_rx_it(&(i2c_context[i2c_num].hal)); - i2c_hal_update_config(&(i2c_context[i2c_num].hal)); } else { i2c_hal_master_init(&(i2c_context[i2c_num].hal), i2c_num); //Default, we enable hardware filter i2c_hal_set_filter(&(i2c_context[i2c_num].hal), I2C_FILTER_CYC_NUM_DEF); i2c_hal_set_bus_timing(&(i2c_context[i2c_num].hal), i2c_conf->master.clk_speed, src_clk); } + i2c_hal_update_config(&(i2c_context[i2c_num].hal)); I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock)); return ESP_OK; } @@ -709,6 +710,7 @@ esp_err_t i2c_set_period(i2c_port_t i2c_num, int high_period, int low_period) I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock)); i2c_hal_set_scl_timing(&(i2c_context[i2c_num].hal), high_period, low_period); + i2c_hal_update_config(&(i2c_context[i2c_num].hal)); I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock)); return ESP_OK; } @@ -728,6 +730,7 @@ esp_err_t i2c_filter_enable(i2c_port_t i2c_num, uint8_t cyc_num) ESP_RETURN_ON_FALSE(p_i2c_obj[i2c_num] != NULL, ESP_FAIL, I2C_TAG, I2C_DRIVER_ERR_STR); I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock)); i2c_hal_set_filter(&(i2c_context[i2c_num].hal), cyc_num); + i2c_hal_update_config(&(i2c_context[i2c_num].hal)); I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock)); return ESP_OK; } @@ -737,6 +740,7 @@ esp_err_t i2c_filter_disable(i2c_port_t i2c_num) ESP_RETURN_ON_FALSE(i2c_num < I2C_NUM_MAX, ESP_ERR_INVALID_ARG, I2C_TAG, I2C_NUM_ERROR_STR); I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock)); i2c_hal_set_filter(&(i2c_context[i2c_num].hal), 0); + i2c_hal_update_config(&(i2c_context[i2c_num].hal)); I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock)); return ESP_OK; } @@ -749,6 +753,7 @@ esp_err_t i2c_set_start_timing(i2c_port_t i2c_num, int setup_time, int hold_time I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock)); i2c_hal_set_start_timing(&(i2c_context[i2c_num].hal), setup_time, hold_time); + i2c_hal_update_config(&(i2c_context[i2c_num].hal)); I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock)); return ESP_OK; } @@ -770,6 +775,7 @@ esp_err_t i2c_set_stop_timing(i2c_port_t i2c_num, int setup_time, int hold_time) I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock)); i2c_hal_set_stop_timing(&(i2c_context[i2c_num].hal), setup_time, hold_time); + i2c_hal_update_config(&(i2c_context[i2c_num].hal)); I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock)); return ESP_OK; } @@ -791,6 +797,7 @@ esp_err_t i2c_set_data_timing(i2c_port_t i2c_num, int sample_time, int hold_time I2C_ENTER_CRITICAL(&(i2c_context[i2c_num].spinlock)); i2c_hal_set_sda_timing(&(i2c_context[i2c_num].hal), sample_time, hold_time); + i2c_hal_update_config(&(i2c_context[i2c_num].hal)); I2C_EXIT_CRITICAL(&(i2c_context[i2c_num].spinlock)); return ESP_OK; } diff --git a/components/driver/i2s.c b/components/driver/i2s.c index be3e90b3b7..0eb50e4738 100644 --- a/components/driver/i2s.c +++ b/components/driver/i2s.c @@ -17,42 +17,49 @@ #include "driver/gpio.h" #include "driver/i2s.h" #include "hal/gpio_hal.h" -#if SOC_I2S_SUPPORTS_ADC_DAC -#include "driver/dac.h" #include "hal/i2s_hal.h" +#if SOC_I2S_SUPPORTS_DAC +#include "driver/dac.h" +#endif // SOC_I2S_SUPPORTS_DAC + +#if SOC_I2S_SUPPORTS_ADC #include "adc1_private.h" +#endif // SOC_I2S_SUPPORTS_ADC + +#if SOC_GDMA_SUPPORTED +#include "esp_private/gdma.h" #endif #include "soc/rtc.h" #include "esp_intr_alloc.h" #include "esp_err.h" +#include "esp_check.h" #include "esp_attr.h" #include "esp_log.h" #include "esp_pm.h" #include "esp_efuse.h" #include "esp_rom_gpio.h" +#include "esp_private/i2s_platform.h" #include "sdkconfig.h" -static const char* I2S_TAG = "I2S"; +static const char *TAG = "I2S"; -#define I2S_CHECK(a, str, ret) if (!(a)) { \ - ESP_LOGE(I2S_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ - return (ret); \ - } +#define I2S_ENTER_CRITICAL_ISR(i2s_num) portENTER_CRITICAL_ISR(&i2s_spinlock[i2s_num]) +#define I2S_EXIT_CRITICAL_ISR(i2s_num) portEXIT_CRITICAL_ISR(&i2s_spinlock[i2s_num]) +#define I2S_ENTER_CRITICAL(i2s_num) portENTER_CRITICAL(&i2s_spinlock[i2s_num]) +#define I2S_EXIT_CRITICAL(i2s_num) portEXIT_CRITICAL(&i2s_spinlock[i2s_num]) -#define I2S_ENTER_CRITICAL_ISR() portENTER_CRITICAL_ISR(&i2s_spinlock[i2s_num]) -#define I2S_EXIT_CRITICAL_ISR() portEXIT_CRITICAL_ISR(&i2s_spinlock[i2s_num]) -#define I2S_ENTER_CRITICAL() portENTER_CRITICAL(&i2s_spinlock[i2s_num]) -#define I2S_EXIT_CRITICAL() portEXIT_CRITICAL(&i2s_spinlock[i2s_num]) -#define I2S_FULL_DUPLEX_SLAVE_MODE_MASK (I2S_MODE_TX | I2S_MODE_RX | I2S_MODE_SLAVE) -#define I2S_FULL_DUPLEX_MASTER_MODE_MASK (I2S_MODE_TX | I2S_MODE_RX | I2S_MODE_MASTER) +#define I2S_DMA_BUFFER_MAX_SIZE 4092 -//TODO: Refactor to put this logic into LL -#define I2S_AD_BCK_FACTOR (2) -#define I2S_PDM_BCK_FACTOR (64) -#define I2S_BASE_CLK (2*APB_CLK_FREQ) +#if !SOC_GDMA_SUPPORTED +#define I2S_INTR_IN_SUC_EOF BIT(9) +#define I2S_INTR_OUT_EOF BIT(12) +#define I2S_INTR_IN_DSCR_ERR BIT(13) +#define I2S_INTR_OUT_DSCR_ERR BIT(14) +#define I2S_INTR_MAX (~0) +#endif /** * @brief DMA buffer object @@ -61,8 +68,8 @@ static const char* I2S_TAG = "I2S"; typedef struct { char **buf; int buf_size; - int rw_pos; - void *curr_ptr; + volatile int rw_pos; + volatile void *curr_ptr; SemaphoreHandle_t mux; xQueueHandle queue; lldesc_t **desc; @@ -78,36 +85,127 @@ typedef struct { QueueHandle_t i2s_queue; /*!< I2S queue handler*/ int dma_buf_count; /*!< DMA buffer count, number of buffer*/ int dma_buf_len; /*!< DMA buffer length, length of each buffer*/ - i2s_dma_t *rx; /*!< DMA Tx buffer*/ - i2s_dma_t *tx; /*!< DMA Rx buffer*/ + uint32_t last_buf_size; /*!< DMA last buffer size */ + i2s_dma_t *tx; /*!< DMA Tx buffer*/ + i2s_dma_t *rx; /*!< DMA Rx buffer*/ +#if SOC_GDMA_SUPPORTED + gdma_channel_handle_t rx_dma_chan; /*!< I2S rx gDMA channel handle*/ + gdma_channel_handle_t tx_dma_chan; /*!< I2S tx gDMA channel handle*/ +#else i2s_isr_handle_t i2s_isr_handle; /*!< I2S Interrupt handle*/ - int channel_num; /*!< Number of channels*/ - int bytes_per_sample; /*!< Bytes per sample*/ - int bits_per_sample; /*!< Bits per sample*/ - i2s_mode_t mode; /*!< I2S Working mode*/ - uint32_t sample_rate; /*!< I2S sample rate */ - bool use_apll; /*!< I2S use APLL clock */ +#endif bool tx_desc_auto_clear; /*!< I2S auto clear tx descriptor on underflow */ + bool use_apll; /*!< I2S use APLL clock */ int fixed_mclk; /*!< I2S fixed MLCK clock */ - double real_rate; + i2s_mclk_multiple_t mclk_multiple; /*!< The multiple of I2S master clock(MCLK) to sample rate */ + #ifdef CONFIG_PM_ENABLE esp_pm_lock_handle_t pm_lock; #endif - i2s_hal_context_t hal; /*!< I2S hal context*/ + i2s_hal_context_t hal; /*!< I2S hal context*/ + i2s_hal_config_t hal_cfg; /*!< I2S hal configurations*/ } i2s_obj_t; -static i2s_obj_t *p_i2s_obj[I2S_NUM_MAX] = {0}; +static i2s_obj_t *p_i2s[SOC_I2S_NUM]; +static portMUX_TYPE i2s_platform_spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED; +static portMUX_TYPE i2s_spinlock[SOC_I2S_NUM] = { + [0 ... SOC_I2S_NUM - 1] = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED, +}; -static portMUX_TYPE i2s_spinlock[I2S_NUM_MAX]; -#if SOC_I2S_SUPPORTS_ADC_DAC +#if SOC_I2S_SUPPORTS_ADC static int _i2s_adc_unit = -1; static int _i2s_adc_channel = -1; #endif -static i2s_dma_t *i2s_create_dma_queue(i2s_port_t i2s_num, int dma_buf_count, int dma_buf_len); -static esp_err_t i2s_destroy_dma_queue(i2s_port_t i2s_num, i2s_dma_t *dma); +/* + * This block is an overview of APIs in i2s.c + * Functions with [main] tag are summary functions that provide main i2s service + * Functions with [helper] tag are helper functions that served for summary functions + * Functions with [intr] tag are interrupt handling functions or interrupt callback functions + ------------------------------------------------------------- + I2S GPIO operation + ------------------------------------------------------------- + - [helper] gpio_matrix_out_check_and_set + - [helper] gpio_matrix_in_check_and_set + - [helper] i2s_check_set_mclk + - [main] i2s_set_pin + ------------------------------------------------------------- + I2S DMA operation + ------------------------------------------------------------- + - [intr] i2s_dma_rx_callback + - [intr] i2s_dma_tx_callback + - [intr] i2s_intr_handler_default + - [helper] i2s_dma_intr_init + - [helper] i2s_tx_reset + - [helper] i2s_rx_reset + - [helper] i2s_tx_start + - [helper] i2s_rx_start + - [helper] i2s_tx_stop + - [helper] i2s_rx_stop + ------------------------------------------------------------- + I2S buffer operation + ------------------------------------------------------------- + - [helper] i2s_get_buf_size + - [helper] i2s_delete_dma_buffer + - [helper] i2s_alloc_dma_buffer + - [main] i2s_realloc_dma_buffer + - [main] i2s_destroy_dma_object + - [main] i2s_create_dma_object + - [main] i2s_zero_dma_buffer + ------------------------------------------------------------- + I2S clock operation + ------------------------------------------------------------- + - [helper] i2s_config_source_clock + - [helper] i2s_calculate_adc_dac_clock + - [helper] i2s_calculate_pdm_tx_clock + - [helper] i2s_calculate_pdm_rx_clock + - [helper] i2s_calculate_common_clock + - [main] i2s_calculate_clock + ------------------------------------------------------------- + I2S configuration + ------------------------------------------------------------- + - [helper] i2s_get_max_channel_num + - [helper] i2s_get_active_channel_num + - [helper] i2s_set_dac_mode + - [helper] _i2s_adc_mode_recover + - [main] i2s_set_adc_mode + - [main] i2s_adc_enable + - [main] i2s_adc_disable + - [helper] i2s_set_sample_rates + - [main] i2s_pcm_config + - [helper] i2s_set_pdm_rx_down_sample + - [helper] i2s_set_pdm_tx_up_sample + - [helper] i2s_check_cfg_validity + - [helper] i2s_tx_set_clk_and_channel + - [helper] i2s_rx_set_clk_and_channel + - [main] i2s_get_clk + - [main] i2s_set_clk + ------------------------------------------------------------- + I2S driver operation + ------------------------------------------------------------- + - [main] i2s_start + - [main] i2s_stop + - [helper] i2s_driver_init + - [helper] i2s_dma_object_init + - [main] i2s_driver_install + - [main] i2s_driver_uninstall + - [main] i2s_write + - [main] i2s_write_expand + - [main] i2s_read + -------------------------------------------------------------*/ -static inline void gpio_matrix_out_check(int gpio, uint32_t signal_idx, bool out_inv, bool oen_inv) +/*------------------------------------------------------------- + I2S GPIO operation + -------------------------------------------------------------*/ +/** + * @brief I2S GPIO matrix set ouput + * + * @param gpio GPIO number + * @param singal_idx GPIO singnal ID, refer to 'gpio_sig_map.h' + * @param out_inv Output invert enable + * @param oen_inv Output eanble control invert enable + */ +static void gpio_matrix_out_check_and_set(gpio_num_t gpio, uint32_t signal_idx, bool out_inv, bool oen_inv) { //if pin = -1, do not need to configure if (gpio != -1) { @@ -117,68 +215,684 @@ static inline void gpio_matrix_out_check(int gpio, uint32_t signal_idx, bool out } } -static inline void gpio_matrix_in_check(int gpio, uint32_t signal_idx, bool inv) +/** + * @brief I2S GPIO matrix set input + * + * @param gpio GPIO number + * @param singal_idx GPIO singnal ID, refer to 'gpio_sig_map.h' + * @param out_inv Output invert enable + * @param oen_inv Output eanble control invert enable + */ +static void gpio_matrix_in_check_and_set(gpio_num_t gpio, uint32_t signal_idx, bool inv) { if (gpio != -1) { gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[gpio], PIN_FUNC_GPIO); - //Set direction, for some GPIOs, the input function are not enabled as default. + /* Set direction, for some GPIOs, the input function are not enabled as default */ gpio_set_direction(gpio, GPIO_MODE_INPUT); esp_rom_gpio_connect_in_signal(gpio, signal_idx, inv); } } -esp_err_t i2s_clear_intr_status(i2s_port_t i2s_num, uint32_t clr_mask) +/** + * @brief I2S set GPIO for mclk + * + * @param i2s_num I2S device number + * @param gpio_num GPIO number for mclk + * @return + * - ESP_OK Check or set success + * - ESP_ERR_INVALID_ARG GPIO is not available + */ +static esp_err_t i2s_check_set_mclk(i2s_port_t i2s_num, gpio_num_t gpio_num) { - I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); - i2s_hal_clear_intr_status(&(p_i2s_obj[i2s_num]->hal), clr_mask); + if (gpio_num == -1) { + return ESP_OK; + } +#if CONFIG_IDF_TARGET_ESP32 + ESP_RETURN_ON_FALSE((gpio_num == GPIO_NUM_0 || gpio_num == GPIO_NUM_1 || gpio_num == GPIO_NUM_3), + ESP_ERR_INVALID_ARG, TAG, + "ESP32 only support to set GPIO0/GPIO1/GPIO3 as mclk signal, error GPIO number:%d", gpio_num); + bool is_i2s0 = i2s_num == I2S_NUM_0; + if (gpio_num == GPIO_NUM_0) { + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1); + WRITE_PERI_REG(PIN_CTRL, is_i2s0 ? 0xFFF0 : 0xFFFF); + } else if (gpio_num == GPIO_NUM_1) { + PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_CLK_OUT3); + WRITE_PERI_REG(PIN_CTRL, is_i2s0 ? 0xF0F0 : 0xF0FF); + } else { + PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_CLK_OUT2); + WRITE_PERI_REG(PIN_CTRL, is_i2s0 ? 0xFF00 : 0xFF0F); + } +#else + ESP_RETURN_ON_FALSE(GPIO_IS_VALID_GPIO(gpio_num), ESP_ERR_INVALID_ARG, TAG, "mck_io_num invalid"); + gpio_matrix_out_check_and_set(gpio_num, i2s_periph_signal[i2s_num].mck_out_sig, 0, 0); +#endif + ESP_LOGI(TAG, "I2S%d, MCLK output by GPIO%d", i2s_num, gpio_num); return ESP_OK; } -esp_err_t i2s_enable_rx_intr(i2s_port_t i2s_num) +/** + * @brief Set gpio pins for I2S + * + * @param i2s_num I2S device number + * @param pin Pin configuration + * @return + * - ESP_OK Set pin success + * - ESP_ERR_INVALID_ARG GPIO is not available + */ +esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin) { + ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); + if (pin == NULL) { +#if SOC_I2S_SUPPORTS_DAC + return i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN); +#else + return ESP_ERR_INVALID_ARG; +#endif + } + /* Check validity of selected pins */ + ESP_RETURN_ON_FALSE((pin->bck_io_num == -1 || GPIO_IS_VALID_GPIO(pin->bck_io_num)), + ESP_ERR_INVALID_ARG, TAG, "bck_io_num invalid"); + ESP_RETURN_ON_FALSE((pin->ws_io_num == -1 || GPIO_IS_VALID_GPIO(pin->ws_io_num)), + ESP_ERR_INVALID_ARG, TAG, "ws_io_num invalid"); + ESP_RETURN_ON_FALSE((pin->data_out_num == -1 || GPIO_IS_VALID_GPIO(pin->data_out_num)), + ESP_ERR_INVALID_ARG, TAG, "data_out_num invalid"); + ESP_RETURN_ON_FALSE((pin->data_in_num == -1 || GPIO_IS_VALID_GPIO(pin->data_in_num)), + ESP_ERR_INVALID_ARG, TAG, "data_in_num invalid"); - I2S_ENTER_CRITICAL(); - i2s_hal_enable_rx_intr(&(p_i2s_obj[i2s_num]->hal)); - I2S_EXIT_CRITICAL(); + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_SLAVE) { + /* For "tx + rx + slave" or "rx + slave" mode, we should select RX signal index for ws and bck */ + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_RX) { + gpio_matrix_in_check_and_set(pin->ws_io_num, i2s_periph_signal[i2s_num].s_rx_ws_sig, 0); + gpio_matrix_in_check_and_set(pin->bck_io_num, i2s_periph_signal[i2s_num].s_rx_bck_sig, 0); + /* For "tx + slave" mode, we should select TX signal index for ws and bck */ + } else { + gpio_matrix_in_check_and_set(pin->ws_io_num, i2s_periph_signal[i2s_num].s_tx_ws_sig, 0); + gpio_matrix_in_check_and_set(pin->bck_io_num, i2s_periph_signal[i2s_num].s_tx_bck_sig, 0); + } + } else { + /* mclk only available in master mode */ + ESP_RETURN_ON_ERROR(i2s_check_set_mclk(i2s_num, pin->mck_io_num), TAG, "mclk config failed"); + /* For "tx + rx + master" or "tx + master" mode, we should select TX signal index for ws and bck */ + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_TX) { + gpio_matrix_out_check_and_set(pin->ws_io_num, i2s_periph_signal[i2s_num].m_tx_ws_sig, 0, 0); + gpio_matrix_out_check_and_set(pin->bck_io_num, i2s_periph_signal[i2s_num].m_tx_bck_sig, 0, 0); + /* For "rx + master" mode, we should select RX signal index for ws and bck */ + } else { + gpio_matrix_out_check_and_set(pin->ws_io_num, i2s_periph_signal[i2s_num].m_rx_ws_sig, 0, 0); + gpio_matrix_out_check_and_set(pin->bck_io_num, i2s_periph_signal[i2s_num].m_rx_bck_sig, 0, 0); + } + } + + /* Set data input/ouput GPIO */ + gpio_matrix_out_check_and_set(pin->data_out_num, i2s_periph_signal[i2s_num].data_out_sig, 0, 0); + gpio_matrix_in_check_and_set(pin->data_in_num, i2s_periph_signal[i2s_num].data_in_sig, 0); return ESP_OK; } -esp_err_t i2s_disable_rx_intr(i2s_port_t i2s_num) +/*------------------------------------------------------------- + I2S DMA operation + -------------------------------------------------------------*/ +#if SOC_GDMA_SUPPORTED +/** + * @brief GDMA rx callback function + * @note This function is called by GDMA default ISR handler + * + * @param dma_chan GDMA channel handler + * @param event_data GDMA rx event data + * @param user_data GDMA user data + * @return + * - true need yield + * - false no need + */ +static bool IRAM_ATTR i2s_dma_rx_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data) { - I2S_ENTER_CRITICAL(); - i2s_hal_disable_rx_intr(&(p_i2s_obj[i2s_num]->hal)); - I2S_EXIT_CRITICAL(); + i2s_obj_t *p_i2s = (i2s_obj_t *) user_data; + portBASE_TYPE high_priority_task_awoken = 0; + BaseType_t ret = 0; + int dummy; + i2s_event_t i2s_event; + uint32_t finish_desc; + + if (p_i2s->rx) { + finish_desc = event_data->rx_eof_desc_addr; + if (xQueueIsQueueFullFromISR(p_i2s->rx->queue)) { + xQueueReceiveFromISR(p_i2s->rx->queue, &dummy, &high_priority_task_awoken); + } + ret = xQueueSendFromISR(p_i2s->rx->queue, &(((lldesc_t *)finish_desc)->buf), &high_priority_task_awoken); + if (p_i2s->i2s_queue) { + i2s_event.type = (ret == pdPASS) ? I2S_EVENT_RX_DONE : I2S_EVENT_RX_Q_OVF; + if (p_i2s->i2s_queue && xQueueIsQueueFullFromISR(p_i2s->i2s_queue)) { + xQueueReceiveFromISR(p_i2s->i2s_queue, &dummy, &high_priority_task_awoken); + } + xQueueSendFromISR(p_i2s->i2s_queue, (void * )&i2s_event, &high_priority_task_awoken); + } + } + return high_priority_task_awoken; +} + +/** + * @brief GDMA tx callback function + * @note This function is called by GDMA default ISR handler + * + * @param dma_chan GDMA channel handler + * @param event_data GDMA tx event data + * @param user_data GDMA user data + * @return + * - whether need yield + */ +static bool IRAM_ATTR i2s_dma_tx_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data) +{ + i2s_obj_t *p_i2s = (i2s_obj_t *) user_data; + portBASE_TYPE high_priority_task_awoken = 0; + BaseType_t ret; + int dummy; + i2s_event_t i2s_event; + uint32_t finish_desc; + if (p_i2s->tx) { + finish_desc = event_data->tx_eof_desc_addr; + if (xQueueIsQueueFullFromISR(p_i2s->tx->queue)) { + xQueueReceiveFromISR(p_i2s->tx->queue, &dummy, &high_priority_task_awoken); + if (p_i2s->tx_desc_auto_clear) { + memset((void *) dummy, 0, p_i2s->tx->buf_size); + } + } + ret = xQueueSendFromISR(p_i2s->tx->queue, &(((lldesc_t *)finish_desc)->buf), &high_priority_task_awoken); + if (p_i2s->i2s_queue) { + i2s_event.type = (ret == pdPASS) ? I2S_EVENT_TX_DONE : I2S_EVENT_TX_Q_OVF; + if (xQueueIsQueueFullFromISR(p_i2s->i2s_queue)) { + xQueueReceiveFromISR(p_i2s->i2s_queue, &dummy, &high_priority_task_awoken); + } + xQueueSendFromISR(p_i2s->i2s_queue, (void * )&i2s_event, &high_priority_task_awoken); + } + } + return high_priority_task_awoken; +} + +#else + +/** + * @brief I2S defalut interrupt handler + * @note This function is triggered by I2S dedicated DMA interrupt + * + * @param arg Argument transport to ISR, here is the pointer to I2S object + */ +static void IRAM_ATTR i2s_intr_handler_default(void *arg) +{ + i2s_obj_t *p_i2s = (i2s_obj_t *) arg; + uint32_t status = i2s_hal_get_intr_status(&(p_i2s->hal)); + if (status == 0) { + //Avoid spurious interrupt + return; + } + + i2s_event_t i2s_event; + int dummy; + portBASE_TYPE high_priority_task_awoken = 0; + uint32_t finish_desc = 0; + if ((status & I2S_INTR_OUT_DSCR_ERR) || (status & I2S_INTR_IN_DSCR_ERR)) { + ESP_EARLY_LOGE(TAG, "dma error, interrupt status: 0x%08x", status); + if (p_i2s->i2s_queue) { + i2s_event.type = I2S_EVENT_DMA_ERROR; + if (xQueueIsQueueFullFromISR(p_i2s->i2s_queue)) { + xQueueReceiveFromISR(p_i2s->i2s_queue, &dummy, &high_priority_task_awoken); + } + xQueueSendFromISR(p_i2s->i2s_queue, (void * )&i2s_event, &high_priority_task_awoken); + } + } + + if ((status & I2S_INTR_OUT_EOF) && p_i2s->tx) { + i2s_hal_get_out_eof_des_addr(&(p_i2s->hal), &finish_desc); + // All buffers are empty. This means we have an underflow on our hands. + if (xQueueIsQueueFullFromISR(p_i2s->tx->queue)) { + xQueueReceiveFromISR(p_i2s->tx->queue, &dummy, &high_priority_task_awoken); + // See if tx descriptor needs to be auto cleared: + // This will avoid any kind of noise that may get introduced due to transmission + // of previous data from tx descriptor on I2S line. + if (p_i2s->tx_desc_auto_clear == true) { + memset((void *) dummy, 0, p_i2s->tx->buf_size); + } + } + xQueueSendFromISR(p_i2s->tx->queue, &(((lldesc_t *)finish_desc)->buf), &high_priority_task_awoken); + if (p_i2s->i2s_queue) { + i2s_event.type = I2S_EVENT_TX_DONE; + if (xQueueIsQueueFullFromISR(p_i2s->i2s_queue)) { + xQueueReceiveFromISR(p_i2s->i2s_queue, &dummy, &high_priority_task_awoken); + } + xQueueSendFromISR(p_i2s->i2s_queue, (void * )&i2s_event, &high_priority_task_awoken); + } + } + + if ((status & I2S_INTR_IN_SUC_EOF) && p_i2s->rx) { + // All buffers are full. This means we have an overflow. + i2s_hal_get_in_eof_des_addr(&(p_i2s->hal), &finish_desc); + if (xQueueIsQueueFullFromISR(p_i2s->rx->queue)) { + xQueueReceiveFromISR(p_i2s->rx->queue, &dummy, &high_priority_task_awoken); + } + xQueueSendFromISR(p_i2s->rx->queue, &(((lldesc_t *)finish_desc)->buf), &high_priority_task_awoken); + if (p_i2s->i2s_queue) { + i2s_event.type = I2S_EVENT_RX_DONE; + if (p_i2s->i2s_queue && xQueueIsQueueFullFromISR(p_i2s->i2s_queue)) { + xQueueReceiveFromISR(p_i2s->i2s_queue, &dummy, &high_priority_task_awoken); + } + xQueueSendFromISR(p_i2s->i2s_queue, (void * )&i2s_event, &high_priority_task_awoken); + } + } + i2s_hal_clear_intr_status(&(p_i2s->hal), status); + + if (high_priority_task_awoken == pdTRUE) { + portYIELD_FROM_ISR(); + } +} +#endif + + +/** + * @brief I2S DMA interrupt initialization + * @note I2S will use GDMA if chip supports, and the interrupt is triggered by GDMA. + * + * @param i2s_num I2S device number + * @return + * - ESP_OK I2S DMA interrupt initialize success + * - ESP_ERR_NOT_FOUND GDMA channel not found + * - ESP_ERR_INVALID_ARG Invalid arguments + * - ESP_ERR_INVALID_STATE GDMA state error + */ +static esp_err_t i2s_dma_intr_init(i2s_port_t i2s_num, int intr_flag) +{ +#if SOC_GDMA_SUPPORTED + /* Set GDMA trigger module */ + gdma_trigger_t trig = {.periph = GDMA_TRIG_PERIPH_I2S}; + + switch (i2s_num) { +#if SOC_I2S_NUM > 1 + case I2S_NUM_1: + trig.instance_id = SOC_GDMA_TRIG_PERIPH_I2S1; + break; +#endif + default: + trig.instance_id = SOC_GDMA_TRIG_PERIPH_I2S0; + break; + } + + /* Set GDMA config */ + gdma_channel_alloc_config_t dma_cfg = {}; + if ( p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_TX) { + dma_cfg.direction = GDMA_CHANNEL_DIRECTION_TX; + /* Register a new GDMA tx channel */ + ESP_RETURN_ON_ERROR(gdma_new_channel(&dma_cfg, &p_i2s[i2s_num]->tx_dma_chan), TAG, "Register tx dma channel error"); + ESP_RETURN_ON_ERROR(gdma_connect(p_i2s[i2s_num]->tx_dma_chan, trig), TAG, "Connect tx dma channel error"); + gdma_tx_event_callbacks_t cb = {.on_trans_eof = i2s_dma_tx_callback}; + /* Set callback function for GDMA, the interrupt is triggered by GDMA, then the GDMA ISR will call the callback function */ + gdma_register_tx_event_callbacks(p_i2s[i2s_num]->tx_dma_chan, &cb, p_i2s[i2s_num]); + } + if ( p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_RX) { + dma_cfg.direction = GDMA_CHANNEL_DIRECTION_RX; + /* Register a new GDMA rx channel */ + ESP_RETURN_ON_ERROR(gdma_new_channel(&dma_cfg, &p_i2s[i2s_num]->rx_dma_chan), TAG, "Register rx dma channel error"); + ESP_RETURN_ON_ERROR(gdma_connect(p_i2s[i2s_num]->rx_dma_chan, trig), TAG, "Connect rx dma channel error"); + gdma_rx_event_callbacks_t cb = {.on_recv_eof = i2s_dma_rx_callback}; + /* Set callback function for GDMA, the interrupt is triggered by GDMA, then the GDMA ISR will call the callback function */ + gdma_register_rx_event_callbacks(p_i2s[i2s_num]->rx_dma_chan, &cb, p_i2s[i2s_num]); + } +#else + /* Initial I2S module interrupt */ + ESP_RETURN_ON_ERROR(esp_intr_alloc(i2s_periph_signal[i2s_num].irq, intr_flag, i2s_intr_handler_default, p_i2s[i2s_num], &p_i2s[i2s_num]->i2s_isr_handle), TAG, "Register I2S Interrupt error"); +#endif // SOC_GDMA_SUPPORTED return ESP_OK; } -esp_err_t i2s_disable_tx_intr(i2s_port_t i2s_num) +/** + * @brief I2S tx reset + * + * @param i2s_num I2S device number + */ +static void i2s_tx_reset(i2s_port_t i2s_num) { - I2S_ENTER_CRITICAL(); - i2s_hal_disable_tx_intr(&(p_i2s_obj[i2s_num]->hal)); - I2S_EXIT_CRITICAL(); + p_i2s[i2s_num]->tx->curr_ptr = NULL; + p_i2s[i2s_num]->tx->rw_pos = 0; + i2s_hal_reset_tx(&(p_i2s[i2s_num]->hal)); +#if SOC_GDMA_SUPPORTED + gdma_reset(p_i2s[i2s_num]->tx_dma_chan); +#else + i2s_hal_reset_txdma(&(p_i2s[i2s_num]->hal)); +#endif + i2s_hal_reset_tx_fifo(&(p_i2s[i2s_num]->hal)); +} + +/** + * @brief I2S rx reset + * + * @param i2s_num I2S device number + */ +static void i2s_rx_reset(i2s_port_t i2s_num) +{ + p_i2s[i2s_num]->rx->curr_ptr = NULL; + p_i2s[i2s_num]->rx->rw_pos = 0; + i2s_hal_reset_rx(&(p_i2s[i2s_num]->hal)); +#if SOC_GDMA_SUPPORTED + gdma_reset(p_i2s[i2s_num]->rx_dma_chan); +#else + i2s_hal_reset_rxdma(&(p_i2s[i2s_num]->hal)); +#endif + i2s_hal_reset_rx_fifo(&(p_i2s[i2s_num]->hal)); +} + +/** + * @brief I2S tx start + * + * @param i2s_num I2S device number + */ +static void i2s_tx_start(i2s_port_t i2s_num) +{ +#if SOC_GDMA_SUPPORTED + gdma_start(p_i2s[i2s_num]->tx_dma_chan, (uint32_t) p_i2s[i2s_num]->tx->desc[0]); +#else + i2s_hal_enable_tx_dma(&(p_i2s[i2s_num]->hal)); + i2s_hal_enable_tx_intr(&(p_i2s[i2s_num]->hal)); + i2s_hal_start_tx_link(&(p_i2s[i2s_num]->hal), (uint32_t) p_i2s[i2s_num]->tx->desc[0]); +#endif + i2s_hal_start_tx(&(p_i2s[i2s_num]->hal)); +} + +/** + * @brief I2S rx start + * + * @param i2s_num I2S device number + */ +static void i2s_rx_start(i2s_port_t i2s_num) +{ +#if SOC_GDMA_SUPPORTED + gdma_start(p_i2s[i2s_num]->rx_dma_chan, (uint32_t) p_i2s[i2s_num]->rx->desc[0]); +#else + i2s_hal_enable_rx_dma(&(p_i2s[i2s_num]->hal)); + i2s_hal_enable_rx_intr(&(p_i2s[i2s_num]->hal)); + i2s_hal_start_rx_link(&(p_i2s[i2s_num]->hal), (uint32_t) p_i2s[i2s_num]->rx->desc[0]); +#endif + i2s_hal_start_rx(&(p_i2s[i2s_num]->hal)); +} + +/** + * @brief I2S tx stop + * + * @param i2s_num I2S device number + */ +static void i2s_tx_stop(i2s_port_t i2s_num) +{ + i2s_hal_stop_tx(&(p_i2s[i2s_num]->hal)); +#if SOC_GDMA_SUPPORTED + gdma_stop(p_i2s[i2s_num]->tx_dma_chan); +#else + i2s_hal_stop_tx_link(&(p_i2s[i2s_num]->hal)); + i2s_hal_disable_tx_intr(&(p_i2s[i2s_num]->hal)); + i2s_hal_disable_tx_dma(&(p_i2s[i2s_num]->hal)); +#endif +} + +/** + * @brief I2S rx stop + * + * @param i2s_num I2S device number + */ +static void i2s_rx_stop(i2s_port_t i2s_num) +{ + i2s_hal_stop_rx(&(p_i2s[i2s_num]->hal)); +#if SOC_GDMA_SUPPORTED + gdma_stop(p_i2s[i2s_num]->rx_dma_chan); +#else + i2s_hal_stop_rx_link(&(p_i2s[i2s_num]->hal)); + i2s_hal_disable_rx_intr(&(p_i2s[i2s_num]->hal)); + i2s_hal_disable_rx_dma(&(p_i2s[i2s_num]->hal)); +#endif +} + +/*------------------------------------------------------------- + I2S buffer operation + -------------------------------------------------------------*/ +/** + * @brief I2S get DMA buffer size + * + * @param i2s_num I2S device number + * @return + * - DMA buffer size + */ +static inline uint32_t i2s_get_buf_size(i2s_port_t i2s_num) +{ + /* Calculate bytes per sample, align to 16 bit */ + uint32_t bytes_per_sample = ((p_i2s[i2s_num]->hal_cfg.sample_bits + 15) / 16) * 2; + /* The DMA buffer limitation is 4092 bytes */ + uint32_t bytes_per_frame = bytes_per_sample * p_i2s[i2s_num]->hal_cfg.active_chan; + p_i2s[i2s_num]->dma_buf_len = (p_i2s[i2s_num]->dma_buf_len * bytes_per_frame > I2S_DMA_BUFFER_MAX_SIZE) ? + I2S_DMA_BUFFER_MAX_SIZE / bytes_per_frame : p_i2s[i2s_num]->dma_buf_len; + return p_i2s[i2s_num]->dma_buf_len * bytes_per_frame; +} + +/** + * @brief Delete DMA buffer and descriptor + * + * @param i2s_num I2S device number + * @param dma_obj DMA object + * @return + * - ESP_OK DMA buffer delete success + * - ESP_ERR_INVALID_ARG dma_obj is NULL + */ +static esp_err_t i2s_delete_dma_buffer(i2s_port_t i2s_num, i2s_dma_t *dma_obj) +{ + ESP_RETURN_ON_FALSE(dma_obj, ESP_ERR_INVALID_ARG, TAG, "I2S DMA object can't be NULL"); + /* Loop to destroy every descriptor and buffer */ + for (int cnt = 0; cnt < p_i2s[i2s_num]->dma_buf_count; cnt++) { + if (dma_obj->desc && dma_obj->desc[cnt]) { + free(dma_obj->desc[cnt]); + dma_obj->desc[cnt] = NULL; + } + if (dma_obj->buf && dma_obj->buf[cnt]) { + free(dma_obj->buf[cnt]); + dma_obj->buf[cnt] = NULL; + } + } return ESP_OK; } -esp_err_t i2s_enable_tx_intr(i2s_port_t i2s_num) +/** + * @brief Allocate memory for DMA buffer and descriptor + * + * @param i2s_num I2S device number + * @param dma_obj DMA object + * @return + * - ESP_OK Allocate success + * - ESP_ERR_NO_MEM No memory for DMA buffer + */ +static esp_err_t i2s_alloc_dma_buffer(i2s_port_t i2s_num, i2s_dma_t *dma_obj) { - I2S_ENTER_CRITICAL(); - i2s_hal_enable_tx_intr(&(p_i2s_obj[i2s_num]->hal)); - I2S_EXIT_CRITICAL(); + esp_err_t ret = ESP_OK; + ESP_GOTO_ON_FALSE(dma_obj, ESP_ERR_INVALID_ARG, err, TAG, "I2S DMA object can't be NULL"); + + uint32_t buf_cnt = p_i2s[i2s_num]->dma_buf_count; + for (int cnt = 0; cnt < buf_cnt; cnt++) { + /* Allocate DMA buffer */ + dma_obj->buf[cnt] = (char *) heap_caps_calloc(dma_obj->buf_size, sizeof(char), MALLOC_CAP_DMA); + ESP_GOTO_ON_FALSE(dma_obj->buf[cnt], ESP_ERR_NO_MEM, err, TAG, "Error malloc dma buffer"); + /* Initialize DMA buffer to 0 */ + memset(dma_obj->buf[cnt], 0, dma_obj->buf_size); + ESP_LOGD(TAG, "Addr[%d] = %d", cnt, (int)dma_obj->buf[cnt]); + + /* Allocate DMA descpriptor */ + dma_obj->desc[cnt] = (lldesc_t *) heap_caps_calloc(1, sizeof(lldesc_t), MALLOC_CAP_DMA); + ESP_GOTO_ON_FALSE(dma_obj->desc[cnt], ESP_ERR_NO_MEM, err, TAG, "Error malloc dma description entry"); + } + /* DMA descriptor must be initialize after all descriptor has been created, otherwise they can't be linked together as a chain */ + for (int cnt = 0; cnt < buf_cnt; cnt++) { + /* Initialize DMA descriptor */ + dma_obj->desc[cnt]->owner = 1; + dma_obj->desc[cnt]->eof = 1; + dma_obj->desc[cnt]->sosf = 0; + dma_obj->desc[cnt]->length = dma_obj->buf_size; + dma_obj->desc[cnt]->size = dma_obj->buf_size; + dma_obj->desc[cnt]->buf = (uint8_t *) dma_obj->buf[cnt]; + dma_obj->desc[cnt]->offset = 0; + /* Link to the next descriptor */ + dma_obj->desc[cnt]->empty = (uint32_t)((cnt < (buf_cnt - 1)) ? (dma_obj->desc[cnt + 1]) : dma_obj->desc[0]); + } + ESP_LOGI(TAG, "DMA Malloc info, datalen=blocksize=%d, dma_buf_count=%d", dma_obj->buf_size, buf_cnt); + return ESP_OK; +err: + /* Delete DMA buffer if failed to allocate memory */ + i2s_delete_dma_buffer(i2s_num, dma_obj); + return ret; +} + +/** + * @brief Realloc I2S dma buffer + * + * @param i2s_num I2S device number + * @param dma_obj DMA object + * + * @return + * - ESP_OK Success + * - ESP_ERR_NO_MEM No memory for I2S tx dma buffer + */ +static esp_err_t i2s_realloc_dma_buffer(i2s_port_t i2s_num, i2s_dma_t *dma_obj) +{ + ESP_RETURN_ON_FALSE(dma_obj, ESP_ERR_INVALID_ARG, TAG, "I2S DMA object can't be NULL"); + + /* Destroy old dma descriptor and buffer */ + i2s_delete_dma_buffer(i2s_num, dma_obj); + /* Alloc new dma descriptor and buffer */ + ESP_RETURN_ON_ERROR(i2s_alloc_dma_buffer(i2s_num, dma_obj), TAG, "Failed to allocate dma buffer"); + return ESP_OK; } -float i2s_get_clk(i2s_port_t i2s_num) +/** + * @brief I2S destroy the whole DMA object + * + * @param i2s_num I2S device number + * @param dma Secondary pointer to the DMA object + * @return + * - ESP_OK I2S DMA buffer has been destroyed successfully + * - ESP_ERR_INVALID_ARG I2S driver has not installed yet + */ +static esp_err_t i2s_destroy_dma_object(i2s_port_t i2s_num, i2s_dma_t **dma) { - I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); - return p_i2s_obj[i2s_num]->real_rate; + /* Check if DMA truely need destroy */ + ESP_RETURN_ON_FALSE(p_i2s[i2s_num], ESP_ERR_INVALID_ARG, TAG, "I2S not initialized yet"); + if (!(*dma)) { + return ESP_OK; + } + /* Destroy every descriptor and buffer */ + i2s_delete_dma_buffer(i2s_num, (*dma)); + /* Destroy descriptor pointer */ + if ((*dma)->desc) { + free((*dma)->desc); + (*dma)->desc = NULL; + } + /* Destroy buffer pointer */ + if ((*dma)->buf) { + free((*dma)->buf); + (*dma)->buf = NULL; + } + /* Delete DMA mux */ + vSemaphoreDelete((*dma)->mux); + /* Delete DMA queue */ + vQueueDelete((*dma)->queue); + /* Free DMA structure */ + free(*dma); + *dma = NULL; + ESP_LOGI(TAG, "DMA queue destroyed"); + return ESP_OK; } -static esp_err_t i2s_isr_register(i2s_port_t i2s_num, int intr_alloc_flags, void (*fn)(void*), void * arg, i2s_isr_handle_t *handle) +/** + * @brief Create I2S DMA object + * @note This function only create I2S DMA object but will not allocate memory + * for DMA descriptor and buffer, call 'i2s_alloc_dma_buffer' additionally to + * allocate DMA buffer + * + * @param i2s_num I2S device number + * @param dma The secondary pointer of DMA object + * @return + * - ESP_OK The pointer of DMA object + * - ESP_ERR_INVALID_ARG NULL pointer error or DMA object has been created + * - ESP_ERR_NO_MEM No memory for new DMA object + */ +static esp_err_t i2s_create_dma_object(i2s_port_t i2s_num, i2s_dma_t **dma) { - return esp_intr_alloc(i2s_periph_signal[i2s_num].irq, intr_alloc_flags, fn, arg, handle); + ESP_RETURN_ON_FALSE(dma, ESP_ERR_INVALID_ARG, TAG, "DMA object secondary pointer is NULL"); + ESP_RETURN_ON_FALSE((*dma == NULL), ESP_ERR_INVALID_ARG, TAG, "DMA object has been created"); + uint32_t buf_cnt = p_i2s[i2s_num]->dma_buf_count; + /* Allocate new DMA structure */ + *dma = (i2s_dma_t *) malloc(sizeof(i2s_dma_t)); + ESP_RETURN_ON_FALSE(*dma, ESP_ERR_NO_MEM, TAG, "DMA object allocate failed"); + /* Allocate DMA buffer poiter */ + (*dma)->buf = (char **)heap_caps_calloc(buf_cnt, sizeof(char *), MALLOC_CAP_DMA); + if (!(*dma)->buf) { + goto err; + } + /* Allocate secondary pointer of DMA descriptor chain */ + (*dma)->desc = (lldesc_t **)heap_caps_calloc(buf_cnt, sizeof(lldesc_t *), MALLOC_CAP_DMA); + if (!(*dma)->desc) { + goto err; + } + /* Create queue and mutex */ + (*dma)->queue = xQueueCreate(buf_cnt - 1, sizeof(char *)); + if (!(*dma)->queue) { + goto err; + } + (*dma)->mux = xSemaphoreCreateMutex(); + if (!(*dma)->mux) { + goto err; + } + + return ESP_OK; +err: + ESP_LOGE(TAG, "I2S DMA object create failed, preparing to uninstall"); + /* Destroy DMA queue if failed to allocate memory */ + i2s_destroy_dma_object(i2s_num, dma); + return ESP_ERR_NO_MEM; } -static float i2s_apll_get_fi2s(int bits_per_sample, int sdm0, int sdm1, int sdm2, int odir) +/** + * @brief Zero the contents of the TX DMA buffer. + * @note Pushes zero-byte samples into the TX DMA buffer, until it is full. + * + * @param i2s_num I2S device number + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t i2s_zero_dma_buffer(i2s_port_t i2s_num) +{ + ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); + + /* Clear I2S RX DMA buffer */ + if (p_i2s[i2s_num]->rx && p_i2s[i2s_num]->rx->buf != NULL && p_i2s[i2s_num]->rx->buf_size != 0) { + for (int i = 0; i < p_i2s[i2s_num]->dma_buf_count; i++) { + memset(p_i2s[i2s_num]->rx->buf[i], 0, p_i2s[i2s_num]->rx->buf_size); + } + } + + /* Clear I2S TX DMA buffer */ + if (p_i2s[i2s_num]->tx && p_i2s[i2s_num]->tx->buf != NULL && p_i2s[i2s_num]->tx->buf_size != 0) { + /* Finish to write all tx data */ + int bytes_left = (p_i2s[i2s_num]->tx->buf_size - p_i2s[i2s_num]->tx->rw_pos) % 4; + if (bytes_left) { + size_t zero_bytes = 0, bytes_written; + i2s_write(i2s_num, (void *)&zero_bytes, bytes_left, &bytes_written, portMAX_DELAY); + } + for (int i = 0; i < p_i2s[i2s_num]->dma_buf_count; i++) { + memset(p_i2s[i2s_num]->tx->buf[i], 0, p_i2s[i2s_num]->tx->buf_size); + } + } + return ESP_OK; +} + +/*------------------------------------------------------------- + I2S clock operation + -------------------------------------------------------------*/ +#if SOC_I2S_SUPPORTS_APLL +/** + * @brief Get APLL frequency + */ +static float i2s_apll_get_freq(int bits_per_sample, int sdm0, int sdm1, int sdm2, int odir) { int f_xtal = (int)rtc_clk_xtal_freq_get() * 1000000; @@ -193,8 +907,8 @@ static float i2s_apll_get_fi2s(int bits_per_sample, int sdm0, int sdm1, int sdm2 if (fout < SOC_I2S_APLL_MIN_FREQ || fout > SOC_I2S_APLL_MAX_FREQ) { return SOC_I2S_APLL_MAX_FREQ; } - float fpll = fout / (2 * (odir+2)); //== fi2s (N=1, b=0, a=1) - return fpll/2; + float fpll = fout / (2 * (odir + 2)); //== fi2s (N=1, b=0, a=1) + return fpll / 2; } /** @@ -213,7 +927,7 @@ static float i2s_apll_get_fi2s(int bits_per_sample, int sdm0, int sdm1, int sdm2 * * The most accurate way to find the sdm0..2 and odir parameters is to loop through them all, * then apply the above formula, finding the closest frequency to the desired one. - * But 256*256*64*32 = 134.217.728 loops are too slow with ESP32 + * But 256*256*64*32 = 134,217,728 loops are too slow with ESP32 * 1. We will choose the parameters with the highest level of change, * With 350MHz I2S_BITS_PER_SAMPLE_32BIT || bits < I2S_BITS_PER_SAMPLE_16BIT) { - ESP_LOGE(I2S_TAG, "Invalid bits per sample"); - return ESP_ERR_INVALID_ARG; - } - - if (p_i2s_obj[i2s_num] == NULL) { - ESP_LOGE(I2S_TAG, "Not initialized yet"); - return ESP_ERR_INVALID_ARG; - } - p_i2s_obj[i2s_num]->sample_rate = rate; - double clkmdiv = (double)I2S_BASE_CLK / (rate * factor); - - if (clkmdiv > 256) { - ESP_LOGE(I2S_TAG, "clkmdiv is too large\r\n"); - return ESP_ERR_INVALID_ARG; - } - - // wait all on-going writing finish - if ((p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) && p_i2s_obj[i2s_num]->tx) { - xSemaphoreTake(p_i2s_obj[i2s_num]->tx->mux, (portTickType)portMAX_DELAY); - } - if ((p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) && p_i2s_obj[i2s_num]->rx) { - xSemaphoreTake(p_i2s_obj[i2s_num]->rx->mux, (portTickType)portMAX_DELAY); - } - - i2s_stop(i2s_num); -#if SOC_I2S_SUPPORTS_ADC_DAC - /* I2S-ADC only support single channel format. */ - if (!(p_i2s_obj[i2s_num]->mode & I2S_MODE_ADC_BUILT_IN)) { - i2s_hal_set_rx_mode(&(p_i2s_obj[i2s_num]->hal), ch, bits); +#if SOC_I2S_SUPPORTS_APLL + if (use_apll) { + int sdm0 = 0; + int sdm1 = 0; + int sdm2 = 0; + int odir = 0; + if ((mclk / p_i2s[i2s_num]->hal_cfg.chan_bits / p_i2s[i2s_num]->hal_cfg.total_chan) < SOC_I2S_APLL_MIN_RATE) { + ESP_LOGE(TAG, "mclk is too small"); + return 0; + } + i2s_apll_calculate_fi2s(mclk, p_i2s[i2s_num]->hal_cfg.sample_bits, &sdm0, &sdm1, &sdm2, &odir); + ESP_LOGI(TAG, "APLL Enabled, coefficient: sdm0=%d, sdm1=%d, sdm2=%d, odir=%d", sdm0, sdm1, sdm2, odir); + rtc_clk_apll_enable(true, sdm0, sdm1, sdm2, odir); + /* Set I2S_APLL as I2S module clock source */ + i2s_hal_set_clock_src(&(p_i2s[i2s_num]->hal), I2S_CLK_APLL); + /* In APLL mode, there is no sclk but only mclk, so return 0 here to indicate APLL mode */ + return 0; } + /* Set I2S_D2CLK (160M) as default I2S module clock source */ + i2s_hal_set_clock_src(&(p_i2s[i2s_num]->hal), I2S_CLK_D2CLK); + return I2S_LL_BASE_CLK; #else - i2s_hal_set_rx_mode(&(p_i2s_obj[i2s_num]->hal), ch, bits); + if (use_apll) { + ESP_LOGW(TAG, "APLL not supported on current chip, use I2S_CLK_D2CLK as default clock source"); + } + /* Set I2S_D2CLK (160M) as I2S module clock source */ + i2s_hal_set_clock_src(&(p_i2s[i2s_num]->hal), I2S_CLK_D2CLK); + return I2S_LL_BASE_CLK; #endif - i2s_hal_set_tx_mode(&(p_i2s_obj[i2s_num]->hal), ch, bits); +} - if (p_i2s_obj[i2s_num]->channel_num != (int)ch) { - p_i2s_obj[i2s_num]->channel_num = (ch == 2) ? 2 : 1; - } +#if SOC_I2S_SUPPORTS_ADC || SOC_I2S_SUPPORTS_DAC +/** + * @brief I2S calculate clock for built-in ADC/DAC mode + * + * @param i2s_num I2S device number + * @param clk_cfg Struct to restore clock confiuration + * @return + * - ESP_OK Get clock success + * - ESP_ERR_INVALID_ARG Invalid args + */ +static esp_err_t i2s_calculate_adc_dac_clock(int i2s_num, i2s_hal_clock_cfg_t *clk_cfg) +{ + ESP_RETURN_ON_FALSE(clk_cfg, ESP_ERR_INVALID_ARG, TAG, "input clk_cfg is NULL"); + ESP_RETURN_ON_FALSE(p_i2s[i2s_num]->hal_cfg.mode & (I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN), ESP_ERR_INVALID_ARG, TAG, "current mode is not built-in ADC/DAC"); - if ((int)bits != p_i2s_obj[i2s_num]->bits_per_sample) { - p_i2s_obj[i2s_num]->bits_per_sample = bits; + /* Set I2S bit clock */ + clk_cfg->bclk = p_i2s[i2s_num]->hal_cfg.sample_rate * I2S_LL_AD_BCK_FACTOR * 2; + /* Set I2S bit clock default division */ + clk_cfg->bclk_div = I2S_LL_AD_BCK_FACTOR; + /* If fixed_mclk and use_apll are set, use fixed_mclk as mclk frequency, otherwise calculate by mclk = sample_rate * multiple */ + clk_cfg->mclk = (p_i2s[i2s_num]->use_apll && p_i2s[i2s_num]->fixed_mclk) ? + p_i2s[i2s_num]->fixed_mclk : clk_cfg->bclk * clk_cfg->bclk_div; + /* Calculate bclk_div = mclk / bclk */ + clk_cfg->bclk_div = clk_cfg->mclk / clk_cfg->bclk; + /* Get I2S system clock by config source clock */ + clk_cfg->sclk = i2s_config_source_clock(i2s_num, p_i2s[i2s_num]->use_apll, clk_cfg->mclk); + /* Get I2S master clock rough division, later will calculate the fine division parameters in HAL */ + clk_cfg->mclk_div = clk_cfg->sclk / clk_cfg->mclk; - // Round bytes_per_sample up to next multiple of 16 bits - int halfwords_per_sample = (bits + 15) / 16; - p_i2s_obj[i2s_num]->bytes_per_sample = halfwords_per_sample * 2; + /* Check if the configuration is correct */ + ESP_RETURN_ON_FALSE(!clk_cfg->sclk || clk_cfg->mclk <= clk_cfg->sclk, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large"); - // Because limited of DMA buffer is 4092 bytes - if (p_i2s_obj[i2s_num]->dma_buf_len * p_i2s_obj[i2s_num]->bytes_per_sample * p_i2s_obj[i2s_num]->channel_num > 4092) { - p_i2s_obj[i2s_num]->dma_buf_len = 4092 / p_i2s_obj[i2s_num]->bytes_per_sample / p_i2s_obj[i2s_num]->channel_num; - } - // Re-create TX DMA buffer - if (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) { + return ESP_OK; +} +#endif // SOC_I2S_SUPPORTS_ADC || SOC_I2S_SUPPORTS_DAC - save_tx = p_i2s_obj[i2s_num]->tx; +#if SOC_I2S_SUPPORTS_PDM_TX +/** + * @brief I2S calculate clock for PDM tx mode + * + * @param i2s_num I2S device number + * @param clk_cfg Struct to restore clock confiuration + * @return + * - ESP_OK Get clock success + * - ESP_ERR_INVALID_ARG Invalid args + */ +static esp_err_t i2s_calculate_pdm_tx_clock(int i2s_num, i2s_hal_clock_cfg_t *clk_cfg) +{ + ESP_RETURN_ON_FALSE(clk_cfg, ESP_ERR_INVALID_ARG, TAG, "input clk_cfg is NULL"); + ESP_RETURN_ON_FALSE(p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_PDM, ESP_ERR_INVALID_ARG, TAG, "current mode is not PDM"); - p_i2s_obj[i2s_num]->tx = i2s_create_dma_queue(i2s_num, p_i2s_obj[i2s_num]->dma_buf_count, p_i2s_obj[i2s_num]->dma_buf_len); - if (p_i2s_obj[i2s_num]->tx == NULL) { - ESP_LOGE(I2S_TAG, "Failed to create tx dma buffer"); - i2s_driver_uninstall(i2s_num); - return ESP_ERR_NO_MEM; - } - i2s_hal_set_out_link_addr(&(p_i2s_obj[i2s_num]->hal), (uint32_t) p_i2s_obj[i2s_num]->tx->desc[0]); + int fp = i2s_hal_get_tx_pdm_fp(&(p_i2s[i2s_num]->hal)); + int fs = i2s_hal_get_tx_pdm_fs(&(p_i2s[i2s_num]->hal)); + /* Set I2S bit clock */ + clk_cfg->bclk = p_i2s[i2s_num]->hal_cfg.sample_rate * I2S_LL_PDM_BCK_FACTOR * fp / fs; + /* Set I2S bit clock default division */ + clk_cfg->bclk_div = 8; + /* If fixed_mclk and use_apll are set, use fixed_mclk as mclk frequency, otherwise calculate by mclk = sample_rate * multiple */ + clk_cfg->mclk = (p_i2s[i2s_num]->use_apll && p_i2s[i2s_num]->fixed_mclk) ? + p_i2s[i2s_num]->fixed_mclk : clk_cfg->bclk * clk_cfg->bclk_div; + /* Calculate bclk_div = mclk / bclk */ + clk_cfg->bclk_div = clk_cfg->mclk / clk_cfg->bclk; + /* Get I2S system clock by config source clock */ + clk_cfg->sclk = i2s_config_source_clock(i2s_num, p_i2s[i2s_num]->use_apll, clk_cfg->mclk); + /* Get I2S master clock rough division, later will calculate the fine division parameters in HAL */ + clk_cfg->mclk_div = clk_cfg->sclk / clk_cfg->mclk; - //destroy old tx dma if exist - if (save_tx) { - i2s_destroy_dma_queue(i2s_num, save_tx); - } - } - // Re-create RX DMA buffer - if (p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) { + /* Check if the configuration is correct */ + ESP_RETURN_ON_FALSE(!clk_cfg->sclk || clk_cfg->mclk <= clk_cfg->sclk, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large"); - save_rx = p_i2s_obj[i2s_num]->rx; + return ESP_OK; +} +#endif // SOC_I2S_SUPPORTS_PDM_TX - p_i2s_obj[i2s_num]->rx = i2s_create_dma_queue(i2s_num, p_i2s_obj[i2s_num]->dma_buf_count, p_i2s_obj[i2s_num]->dma_buf_len); - if (p_i2s_obj[i2s_num]->rx == NULL){ - ESP_LOGE(I2S_TAG, "Failed to create rx dma buffer"); - i2s_driver_uninstall(i2s_num); - return ESP_ERR_NO_MEM; - } - i2s_hal_set_in_link(&(p_i2s_obj[i2s_num]->hal), p_i2s_obj[i2s_num]->dma_buf_len * p_i2s_obj[i2s_num]->channel_num * p_i2s_obj[i2s_num]->bytes_per_sample, (uint32_t) p_i2s_obj[i2s_num]->rx->desc[0]); - //destroy old rx dma if exist - if (save_rx) { - i2s_destroy_dma_queue(i2s_num, save_rx); - } - } +#if SOC_I2S_SUPPORTS_PDM_RX +/** + * @brief I2S calculate clock for PDM rx mode + * + * @param i2s_num I2S device number + * @param clk_cfg Struct to restore clock confiuration + * @return + * - ESP_OK Get clock success + * - ESP_ERR_INVALID_ARG Invalid args + */ +static esp_err_t i2s_calculate_pdm_rx_clock(int i2s_num, i2s_hal_clock_cfg_t *clk_cfg) +{ + ESP_RETURN_ON_FALSE(clk_cfg, ESP_ERR_INVALID_ARG, TAG, "input clk_cfg is NULL"); + ESP_RETURN_ON_FALSE(p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_PDM, ESP_ERR_INVALID_ARG, TAG, "current mode is not PDM"); - } + i2s_pdm_dsr_t dsr; + i2s_hal_get_rx_pdm_dsr(&(p_i2s[i2s_num]->hal), &dsr); + /* Set I2S bit clock */ + clk_cfg->bclk = p_i2s[i2s_num]->hal_cfg.sample_rate * I2S_LL_PDM_BCK_FACTOR * (dsr == I2S_PDM_DSR_16S ? 2 : 1); + /* Set I2S bit clock default division */ + clk_cfg->bclk_div = 8; + /* If fixed_mclk and use_apll are set, use fixed_mclk as mclk frequency, otherwise calculate by mclk = sample_rate * multiple */ + clk_cfg->mclk = (p_i2s[i2s_num]->use_apll && p_i2s[i2s_num]->fixed_mclk) ? + p_i2s[i2s_num]->fixed_mclk : clk_cfg->bclk * clk_cfg->bclk_div; + /* Calculate bclk_div = mclk / bclk */ + clk_cfg->bclk_div = clk_cfg->mclk / clk_cfg->bclk; + /* Get I2S system clock by config source clock */ + clk_cfg->sclk = i2s_config_source_clock(i2s_num, p_i2s[i2s_num]->use_apll, clk_cfg->mclk); + /* Get I2S master clock rough division, later will calculate the fine division parameters in HAL */ + clk_cfg->mclk_div = clk_cfg->sclk / clk_cfg->mclk; - double mclk; - int sdm0, sdm1, sdm2, odir, m_scale = 8; - int fi2s_clk = rate*channel*bits*m_scale; -#if SOC_I2S_SUPPORTS_ADC_DAC - if (p_i2s_obj[i2s_num]->mode & (I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN)) { + /* Check if the configuration is correct */ + ESP_RETURN_ON_FALSE(!clk_cfg->sclk || clk_cfg->mclk <= clk_cfg->sclk, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large"); - //DAC uses bclk as sample clock, not WS. WS can be something arbitrary. - //Rate as given to this function is the intended sample rate; - //According to the TRM, WS clk equals to the sample rate, and bclk is double the speed of WS - uint32_t b_clk = rate * I2S_AD_BCK_FACTOR; - fi2s_clk /= I2S_AD_BCK_FACTOR; - int factor2 = 60; - mclk = b_clk * factor2; - clkmdiv = ((double) I2S_BASE_CLK) / mclk; - clkmInteger = clkmdiv; - clkmDecimals = (clkmdiv - clkmInteger) / denom; - bck = mclk / b_clk; -#endif -#if SOC_I2S_SUPPORTS_PDM - } else if (p_i2s_obj[i2s_num]->mode & I2S_MODE_PDM) { - uint32_t b_clk = 0; - if (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) { - uint32_t fp, fs; - i2s_hal_get_tx_pdm(&(p_i2s_obj[i2s_num]->hal), &fp, &fs); - // Recommended set `fp = 960, fs = sample_rate / 100` - fs = rate / 100; - i2s_hal_tx_pdm_cfg(&(p_i2s_obj[i2s_num]->hal), fp, fs); - b_clk = rate * I2S_PDM_BCK_FACTOR * fp / fs; + return ESP_OK; +} +#endif // SOC_I2S_SUPPORTS_PDM_RX - } else if (p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) { - uint32_t dsr; - i2s_hal_get_rx_pdm(&(p_i2s_obj[i2s_num]->hal), &dsr); - b_clk = rate * I2S_PDM_BCK_FACTOR * (dsr ? 2 : 1); - } - fi2s_clk = b_clk * m_scale; - int factor2 = 5 ; - mclk = b_clk * factor2; - clkmdiv = ((double) I2S_BASE_CLK) / mclk; - clkmInteger = clkmdiv; - clkmDecimals = (clkmdiv - clkmInteger) / denom; - bck = mclk / b_clk; - } else -#endif - { - clkmInteger = clkmdiv; - clkmDecimals = (clkmdiv - clkmInteger) / denom; - mclk = clkmInteger + denom * clkmDecimals; - bck = factor/(bits * channel); - } +/** + * @brief I2S calculate clock for common mode (philip, MSB, PCM) + * + * @param i2s_num I2S device number + * @param clk_cfg Struct to restore clock confiuration + * @return + * - ESP_OK Get clock success + * - ESP_ERR_INVALID_ARG Invalid args + */ +static esp_err_t i2s_calculate_common_clock(int i2s_num, i2s_hal_clock_cfg_t *clk_cfg) +{ + ESP_RETURN_ON_FALSE(clk_cfg, ESP_ERR_INVALID_ARG, TAG, "input clk_cfg is NULL"); - if(p_i2s_obj[i2s_num]->use_apll && p_i2s_obj[i2s_num]->fixed_mclk) { - fi2s_clk = p_i2s_obj[i2s_num]->fixed_mclk; - m_scale = fi2s_clk/bits/rate/channel; - } - if(p_i2s_obj[i2s_num]->use_apll && i2s_apll_calculate_fi2s(fi2s_clk, bits, &sdm0, &sdm1, &sdm2, &odir) == ESP_OK) { - ESP_LOGD(I2S_TAG, "sdm0=%d, sdm1=%d, sdm2=%d, odir=%d", sdm0, sdm1, sdm2, odir); - rtc_clk_apll_enable(1, sdm0, sdm1, sdm2, odir); - i2s_hal_set_clk_div(&(p_i2s_obj[i2s_num]->hal), 1, 1, 0, m_scale, m_scale); - i2s_hal_set_clock_sel(&(p_i2s_obj[i2s_num]->hal), I2S_CLK_APLL); - double fi2s_rate = i2s_apll_get_fi2s(bits, sdm0, sdm1, sdm2, odir); - p_i2s_obj[i2s_num]->real_rate = fi2s_rate/bits/channel/m_scale; - ESP_LOGI(I2S_TAG, "APLL: Req RATE: %d, real rate: %0.3f, BITS: %u, CLKM: %u, BCK_M: %u, MCLK: %0.3f, SCLK: %f, diva: %d, divb: %d", - rate, fi2s_rate/bits/channel/m_scale, bits, 1, m_scale, fi2s_rate, fi2s_rate/8, 1, 0); + uint32_t rate = p_i2s[i2s_num]->hal_cfg.sample_rate; + uint32_t chan_num = p_i2s[i2s_num]->hal_cfg.total_chan < 2 ? 2 : p_i2s[i2s_num]->hal_cfg.total_chan; + uint32_t chan_bit = p_i2s[i2s_num]->hal_cfg.chan_bits; + uint32_t multi; + /* Calculate multiple */ + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_MASTER || p_i2s[i2s_num]->use_apll) { + multi = p_i2s[i2s_num]->mclk_multiple ? p_i2s[i2s_num]->mclk_multiple : I2S_MCLK_MULTIPLE_256; } else { - i2s_hal_set_clock_sel(&(p_i2s_obj[i2s_num]->hal), I2S_CLK_D2CLK); - i2s_hal_set_clk_div(&(p_i2s_obj[i2s_num]->hal), clkmInteger, 63, clkmDecimals, bck, bck); - double real_rate = (double) (I2S_BASE_CLK / (bck * bits * clkmInteger) / 2); - p_i2s_obj[i2s_num]->real_rate = real_rate; - ESP_LOGI(I2S_TAG, "PLL_D2: Req RATE: %d, real rate: %0.3f, BITS: %u, CLKM: %u, BCK: %u, MCLK: %0.3f, SCLK: %f, diva: %d, divb: %d", - rate, real_rate, bits, clkmInteger, bck, (double)I2S_BASE_CLK / mclk, real_rate*bits*channel, 64, clkmDecimals); - } - if (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) { - p_i2s_obj[i2s_num]->tx->curr_ptr = NULL; - p_i2s_obj[i2s_num]->tx->rw_pos = 0; - } - if (p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) { - p_i2s_obj[i2s_num]->rx->curr_ptr = NULL; - p_i2s_obj[i2s_num]->rx->rw_pos = 0; + /* Only need to set the multiple of mclk to sample rate for MASTER mode, + * because BCK and WS clock are provided by the external codec in SLAVE mode. + * The multiple should be big enough to get a high module clock which could detect the edges of externel clock more accurately, + * otherwise the data we receive or send would get a large latency and go wrong due to the slow module clock. + * But on ESP32 and ESP32S2, due to the different clock work mode in hardware, + * their multiple should be set to an appropriate range according to the sample bits, + * and this particular multiple finally aims at guaranteeing the bclk_div not smaller than 8, + * if not, the I2S may can't send data or send wrong data. + * Here use 'SOC_I2S_SUPPORTS_TDM' to differentialize other chips with ESP32 and ESP32S2. + */ +#if SOC_I2S_SUPPORTS_TDM + multi = I2S_LL_BASE_CLK / rate; +#else + multi = 64 * chan_bit; +#endif } + /* Set I2S bit clock */ + clk_cfg->bclk = rate * chan_num * chan_bit; + /* If fixed_mclk and use_apll are set, use fixed_mclk as mclk frequency, otherwise calculate by mclk = sample_rate * multiple */ + clk_cfg->mclk = (p_i2s[i2s_num]->use_apll && p_i2s[i2s_num]->fixed_mclk) ? + p_i2s[i2s_num]->fixed_mclk : (rate * multi); + /* Calculate bclk_div = mclk / bclk */ + clk_cfg->bclk_div = clk_cfg->mclk / clk_cfg->bclk; + /* Get I2S system clock by config source clock */ + clk_cfg->sclk = i2s_config_source_clock(i2s_num, p_i2s[i2s_num]->use_apll, clk_cfg->mclk); + /* Get I2S master clock rough division, later will calculate the fine division parameters in HAL */ + clk_cfg->mclk_div = clk_cfg->sclk / clk_cfg->mclk; - i2s_hal_set_tx_bits_mod(&(p_i2s_obj[i2s_num]->hal), bits); - i2s_hal_set_rx_bits_mod(&(p_i2s_obj[i2s_num]->hal), bits); + /* Check if the configuration is correct */ + ESP_RETURN_ON_FALSE(!clk_cfg->sclk || clk_cfg->mclk <= clk_cfg->sclk, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large"); - // wait all writing on-going finish - if ((p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) && p_i2s_obj[i2s_num]->tx) { - xSemaphoreGive(p_i2s_obj[i2s_num]->tx->mux); - } - if ((p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) && p_i2s_obj[i2s_num]->rx) { - xSemaphoreGive(p_i2s_obj[i2s_num]->rx->mux); - } - i2s_start(i2s_num); return ESP_OK; } -static void IRAM_ATTR i2s_intr_handler_default(void *arg) +/** + * @brief I2S calculate clocks according to the selected I2S mode + * + * @param i2s_num I2S device number + * @param clk_cfg Struct to restore clock confiuration + * @return + * - ESP_OK Claculate clock success + * - ESP_ERR_INVALID_ARG Invalid args + */ +static esp_err_t i2s_calculate_clock(i2s_port_t i2s_num, i2s_hal_clock_cfg_t *clk_cfg) { - i2s_obj_t *p_i2s = (i2s_obj_t*) arg; - uint32_t status; - i2s_hal_get_intr_status(&(p_i2s->hal), &status); - if(status == 0) { - //Avoid spurious interrupt - return; + /* Calculate clock for ADC mode */ +#if SOC_I2S_SUPPORTS_ADC + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_ADC_BUILT_IN) { + ESP_RETURN_ON_ERROR(i2s_calculate_adc_dac_clock(i2s_num, clk_cfg), TAG, "ADC clock calculate failed"); + return ESP_OK; } +#endif // SOC_I2S_SUPPORTS_ADC + /* Calculate clock for DAC mode */ +#if SOC_I2S_SUPPORTS_DAC + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_DAC_BUILT_IN) { + ESP_RETURN_ON_ERROR(i2s_calculate_adc_dac_clock(i2s_num, clk_cfg), TAG, "DAC clock calculate failed"); + return ESP_OK; + } +#endif // SOC_I2S_SUPPORTS_DAC - i2s_event_t i2s_event; - int dummy; - - portBASE_TYPE high_priority_task_awoken = 0; - - lldesc_t *finish_desc = NULL; - - if ((status & I2S_INTR_OUT_DSCR_ERR) || (status & I2S_INTR_IN_DSCR_ERR)) { - ESP_EARLY_LOGE(I2S_TAG, "dma error, interrupt status: 0x%08x", status); - if (p_i2s->i2s_queue) { - i2s_event.type = I2S_EVENT_DMA_ERROR; - if (xQueueIsQueueFullFromISR(p_i2s->i2s_queue)) { - xQueueReceiveFromISR(p_i2s->i2s_queue, &dummy, &high_priority_task_awoken); - } - xQueueSendFromISR(p_i2s->i2s_queue, (void * )&i2s_event, &high_priority_task_awoken); + /* Calculate clock for PDM mode */ +#if SOC_I2S_SUPPORTS_PDM_TX || SOC_I2S_SUPPORTS_PDM_RX + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_PDM) { +#if SOC_I2S_SUPPORTS_PDM_TX + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_TX) { + ESP_RETURN_ON_ERROR(i2s_calculate_pdm_tx_clock(i2s_num, clk_cfg), TAG, "PDM TX clock calculate failed"); } +#endif // SOC_I2S_SUPPORTS_PDM_TX +#if SOC_I2S_SUPPORTS_PDM_RX + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_RX) { + ESP_RETURN_ON_ERROR(i2s_calculate_pdm_rx_clock(i2s_num, clk_cfg), TAG, "PDM RX clock calculate failed"); + } +#endif // SOC_I2S_SUPPORTS_PDM_RX + return ESP_OK; } +#endif // SOC_I2S_SUPPORTS_PDM_TX || SOC_I2S_SUPPORTS_PDM_RX - if ((status & I2S_INTR_OUT_EOF) && p_i2s->tx) { - i2s_hal_get_out_eof_des_addr(&(p_i2s->hal), (uint32_t *)&finish_desc); - // All buffers are empty. This means we have an underflow on our hands. - if (xQueueIsQueueFullFromISR(p_i2s->tx->queue)) { - xQueueReceiveFromISR(p_i2s->tx->queue, &dummy, &high_priority_task_awoken); - // See if tx descriptor needs to be auto cleared: - // This will avoid any kind of noise that may get introduced due to transmission - // of previous data from tx descriptor on I2S line. - if (p_i2s->tx_desc_auto_clear == true) { - memset((void *) dummy, 0, p_i2s->tx->buf_size); - } - } - xQueueSendFromISR(p_i2s->tx->queue, (void*)(&finish_desc->buf), &high_priority_task_awoken); - if (p_i2s->i2s_queue) { - i2s_event.type = I2S_EVENT_TX_DONE; - if (xQueueIsQueueFullFromISR(p_i2s->i2s_queue)) { - xQueueReceiveFromISR(p_i2s->i2s_queue, &dummy, &high_priority_task_awoken); - } - xQueueSendFromISR(p_i2s->i2s_queue, (void * )&i2s_event, &high_priority_task_awoken); - } - } - - if ((status & I2S_INTR_IN_SUC_EOF) && p_i2s->rx) { - // All buffers are full. This means we have an overflow. - i2s_hal_get_in_eof_des_addr(&(p_i2s->hal), (uint32_t *)&finish_desc); - if (xQueueIsQueueFullFromISR(p_i2s->rx->queue)) { - xQueueReceiveFromISR(p_i2s->rx->queue, &dummy, &high_priority_task_awoken); - } - xQueueSendFromISR(p_i2s->rx->queue, (void*)(&finish_desc->buf), &high_priority_task_awoken); - if (p_i2s->i2s_queue) { - i2s_event.type = I2S_EVENT_RX_DONE; - if (p_i2s->i2s_queue && xQueueIsQueueFullFromISR(p_i2s->i2s_queue)) { - xQueueReceiveFromISR(p_i2s->i2s_queue, &dummy, &high_priority_task_awoken); - } - xQueueSendFromISR(p_i2s->i2s_queue, (void * )&i2s_event, &high_priority_task_awoken); - } - } - i2s_hal_clear_intr_status(&(p_i2s->hal), status); - - if (high_priority_task_awoken == pdTRUE) { - portYIELD_FROM_ISR(); - } -} - -static esp_err_t i2s_destroy_dma_queue(i2s_port_t i2s_num, i2s_dma_t *dma) -{ - int bux_idx; - if (p_i2s_obj[i2s_num] == NULL) { - ESP_LOGE(I2S_TAG, "Not initialized yet"); - return ESP_ERR_INVALID_ARG; - } - if (dma == NULL) { - ESP_LOGE(I2S_TAG, "dma is NULL"); - return ESP_ERR_INVALID_ARG; - } - for (bux_idx = 0; bux_idx < p_i2s_obj[i2s_num]->dma_buf_count; bux_idx++) { - if (dma->desc && dma->desc[bux_idx]) { - free(dma->desc[bux_idx]); - } - if (dma->buf && dma->buf[bux_idx]) { - free(dma->buf[bux_idx]); - } - } - if (dma->buf) { - free(dma->buf); - } - if (dma->desc) { - free(dma->desc); - } - vQueueDelete(dma->queue); - vSemaphoreDelete(dma->mux); - free(dma); + /* Calculate clock for common mode */ + ESP_RETURN_ON_ERROR(i2s_calculate_common_clock(i2s_num, clk_cfg), TAG, "Common clock calculate failed"); return ESP_OK; } -static i2s_dma_t *i2s_create_dma_queue(i2s_port_t i2s_num, int dma_buf_count, int dma_buf_len) +/*------------------------------------------------------------- + I2S configuration + -------------------------------------------------------------*/ +#if SOC_I2S_SUPPORTS_TDM +/** + * @brief Get max actived channel number + * + * @param chan_mask I2S channel mask that indicates which channels are actived + * @return + * - Max actived channel number + */ +static uint32_t i2s_get_max_channel_num(i2s_channel_t chan_mask) { - int bux_idx; - int sample_size = p_i2s_obj[i2s_num]->bytes_per_sample * p_i2s_obj[i2s_num]->channel_num; - i2s_dma_t *dma = (i2s_dma_t*) malloc(sizeof(i2s_dma_t)); - if (dma == NULL) { - ESP_LOGE(I2S_TAG, "Error malloc i2s_dma_t"); - return NULL; - } - memset(dma, 0, sizeof(i2s_dma_t)); - - dma->buf = (char **)malloc(sizeof(char*) * dma_buf_count); - if (dma->buf == NULL) { - ESP_LOGE(I2S_TAG, "Error malloc dma buffer pointer"); - free(dma); - return NULL; - } - memset(dma->buf, 0, sizeof(char*) * dma_buf_count); - - for (bux_idx = 0; bux_idx < dma_buf_count; bux_idx++) { - dma->buf[bux_idx] = (char*) heap_caps_calloc(1, dma_buf_len * sample_size, MALLOC_CAP_DMA); - if (dma->buf[bux_idx] == NULL) { - ESP_LOGE(I2S_TAG, "Error malloc dma buffer"); - i2s_destroy_dma_queue(i2s_num, dma); - return NULL; - } - ESP_LOGD(I2S_TAG, "Addr[%d] = %d", bux_idx, (int)dma->buf[bux_idx]); - } - - dma->desc = (lldesc_t**) malloc(sizeof(lldesc_t*) * dma_buf_count); - if (dma->desc == NULL) { - ESP_LOGE(I2S_TAG, "Error malloc dma description"); - i2s_destroy_dma_queue(i2s_num, dma); - return NULL; - } - for (bux_idx = 0; bux_idx < dma_buf_count; bux_idx++) { - dma->desc[bux_idx] = (lldesc_t*) heap_caps_malloc(sizeof(lldesc_t), MALLOC_CAP_DMA); - if (dma->desc[bux_idx] == NULL) { - ESP_LOGE(I2S_TAG, "Error malloc dma description entry"); - i2s_destroy_dma_queue(i2s_num, dma); - return NULL; + uint32_t max_chan = 0; + uint32_t channel = chan_mask & 0xFFFF; + for (int i = 0; channel && i < 16; i++, channel >>= 1) { + if (channel & 0x01) { + max_chan = i + 1; } } - - for (bux_idx = 0; bux_idx < dma_buf_count; bux_idx++) { - dma->desc[bux_idx]->owner = 1; - dma->desc[bux_idx]->eof = 1; - dma->desc[bux_idx]->sosf = 0; - dma->desc[bux_idx]->length = dma_buf_len * sample_size; - dma->desc[bux_idx]->size = dma_buf_len * sample_size; - dma->desc[bux_idx]->buf = (uint8_t *) dma->buf[bux_idx]; - dma->desc[bux_idx]->offset = 0; - dma->desc[bux_idx]->empty = (uint32_t)((bux_idx < (dma_buf_count - 1)) ? (dma->desc[bux_idx + 1]) : dma->desc[0]); - } - dma->queue = xQueueCreate(dma_buf_count - 1, sizeof(char*)); - dma->mux = xSemaphoreCreateMutex(); - dma->buf_size = dma_buf_len * sample_size; - ESP_LOGI(I2S_TAG, "DMA Malloc info, datalen=blocksize=%d, dma_buf_count=%d", dma_buf_len * sample_size, dma_buf_count); - return dma; + /* Can't be smaller than 2 */ + return max_chan < 2 ? 2 : max_chan; } +#endif -esp_err_t i2s_start(i2s_port_t i2s_num) +/** + * @brief Get active channel number according to channel format + * @note In 'I2S_CHANNEL_FMT_MULTIPLE' format, this function will check + * 'total_chan' and fix it if it is not correct. + * + * @param hal_cfg [input/output] I2S hal configuration structer + * @return + * - Active channel number + */ +static uint32_t i2s_get_active_channel_num(const i2s_hal_config_t *hal_cfg) { - I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); - //start DMA link - I2S_ENTER_CRITICAL(); - i2s_hal_reset(&(p_i2s_obj[i2s_num]->hal)); - - esp_intr_disable(p_i2s_obj[i2s_num]->i2s_isr_handle); - i2s_hal_clear_intr_status(&(p_i2s_obj[i2s_num]->hal), I2S_INTR_MAX); - if (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) { - i2s_enable_tx_intr(i2s_num); - i2s_hal_start_tx(&(p_i2s_obj[i2s_num]->hal)); + switch (hal_cfg->chan_fmt) { + case I2S_CHANNEL_FMT_RIGHT_LEFT: //fall through + case I2S_CHANNEL_FMT_ALL_RIGHT: //fall through + case I2S_CHANNEL_FMT_ALL_LEFT: + return 2; + case I2S_CHANNEL_FMT_ONLY_RIGHT: //fall through + case I2S_CHANNEL_FMT_ONLY_LEFT: + return 1; +#if SOC_I2S_SUPPORTS_TDM + case I2S_CHANNEL_FMT_MULTIPLE: { + uint32_t num = 0; + uint32_t chan_mask = hal_cfg->chan_mask & 0xFFFF; + for (int i = 0; chan_mask && i < 16; i++, chan_mask >>= 1) { + if (chan_mask & 0x01) { + num++; + } + } + return num; } - if (p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) { - i2s_enable_rx_intr(i2s_num); - i2s_hal_start_rx(&(p_i2s_obj[i2s_num]->hal)); +#endif + default: + return 0; } - esp_intr_enable(p_i2s_obj[i2s_num]->i2s_isr_handle); - I2S_EXIT_CRITICAL(); - return ESP_OK; } -esp_err_t i2s_stop(i2s_port_t i2s_num) -{ - I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); - I2S_ENTER_CRITICAL(); - esp_intr_disable(p_i2s_obj[i2s_num]->i2s_isr_handle); - if (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) { - i2s_hal_stop_tx(&(p_i2s_obj[i2s_num]->hal)); - i2s_disable_tx_intr(i2s_num); - } - if (p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) { - i2s_hal_stop_rx(&(p_i2s_obj[i2s_num]->hal)); - i2s_disable_rx_intr(i2s_num); - } - uint32_t mask; - i2s_hal_get_intr_status(&(p_i2s_obj[i2s_num]->hal), &mask); - i2s_hal_clear_intr_status(&(p_i2s_obj[i2s_num]->hal), mask); - I2S_EXIT_CRITICAL(); - return ESP_OK; -} - -#if SOC_I2S_SUPPORTS_ADC_DAC +#if SOC_I2S_SUPPORTS_DAC +/** + * @brief I2S set built-in DAC mode + * + * @param dac_mode DAC mode + * @return + * - ESP_OK Set DAC success + * - ESP_ERR_INVALID_ARG Wrong DAC mode + */ esp_err_t i2s_set_dac_mode(i2s_dac_mode_t dac_mode) { - I2S_CHECK((dac_mode < I2S_DAC_CHANNEL_MAX), "i2s dac mode error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE((dac_mode < I2S_DAC_CHANNEL_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s dac mode error"); if (dac_mode == I2S_DAC_CHANNEL_DISABLE) { dac_output_disable(DAC_CHANNEL_1); dac_output_disable(DAC_CHANNEL_2); @@ -720,427 +1356,819 @@ esp_err_t i2s_set_dac_mode(i2s_dac_mode_t dac_mode) } return ESP_OK; } +#endif // SOC_I2S_SUPPORTS_DAC +#if SOC_I2S_SUPPORTS_ADC +/** + * @brief ADC mode recover + * + * @return + * - ESP_OK ADC Recover success + * - ESP_ERR_INVALID_ARG ADC not initialized yet + */ static esp_err_t _i2s_adc_mode_recover(void) { - I2S_CHECK(((_i2s_adc_unit != -1) && (_i2s_adc_channel != -1)), "i2s ADC recover error, not initialized...", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(((_i2s_adc_unit != -1) && (_i2s_adc_channel != -1)), ESP_ERR_INVALID_ARG, TAG, "i2s ADC recover error, not initialized..."); return adc_i2s_mode_init(_i2s_adc_unit, _i2s_adc_channel); } +/** + * @brief I2S set adc mode + * + * @param adc_unit ADC unit number + * @param adc_channel ADC channel + * @return + * - ESP_OK ADC Recover success + * - ESP_ERR_INVALID_ARG ADC not initialized yet + */ esp_err_t i2s_set_adc_mode(adc_unit_t adc_unit, adc1_channel_t adc_channel) { - I2S_CHECK((adc_unit < ADC_UNIT_2), "i2s ADC unit error, only support ADC1 for now", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE((adc_unit < ADC_UNIT_2), ESP_ERR_INVALID_ARG, TAG, "i2s ADC unit error, only support ADC1 for now"); // For now, we only support SAR ADC1. _i2s_adc_unit = adc_unit; _i2s_adc_channel = adc_channel; return adc_i2s_mode_init(adc_unit, adc_channel); } -#endif -esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin) +/** + * @brief I2S enable ADC mode + * + * @param i2s_num I2S device number + * @return + * - ESP_OK Enable ADC success + * - ESP_ERR_INVALID_ARG Invalid argument + * - ESP_ERR_INVALID_STATE Current I2S mode is not built-in ADC + */ +esp_err_t i2s_adc_enable(i2s_port_t i2s_num) { - I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); - if (pin == NULL) { -#if SOC_I2S_SUPPORTS_ADC_DAC - return i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN); -#else - return ESP_ERR_INVALID_ARG; -#endif - } + ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); + ESP_RETURN_ON_FALSE((p_i2s[i2s_num] != NULL), ESP_ERR_INVALID_STATE, TAG, "Not initialized yet"); + ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_ADC_BUILT_IN), ESP_ERR_INVALID_STATE, TAG, "i2s built-in adc not enabled"); - if (pin->bck_io_num != -1 && !GPIO_IS_VALID_GPIO(pin->bck_io_num)) { - ESP_LOGE(I2S_TAG, "bck_io_num error"); - return ESP_FAIL; - } - if (pin->ws_io_num != -1 && !GPIO_IS_VALID_GPIO(pin->ws_io_num)) { - ESP_LOGE(I2S_TAG, "ws_io_num error"); - return ESP_FAIL; - } - if (pin->data_out_num != -1 && !GPIO_IS_VALID_OUTPUT_GPIO(pin->data_out_num)) { - ESP_LOGE(I2S_TAG, "data_out_num error"); - return ESP_FAIL; - } - if (pin->data_in_num != -1 && !GPIO_IS_VALID_GPIO(pin->data_in_num)) { - ESP_LOGE(I2S_TAG, "data_in_num error"); - return ESP_FAIL; - } - - int bck_sig = -1, ws_sig = -1, data_out_sig = -1, data_in_sig = -1; - //Each IIS hw module has a RX and TX unit. - //For TX unit, the output signal index should be I2SnO_xxx_OUT_IDX - //For TX unit, the input signal index should be I2SnO_xxx_IN_IDX - if (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) { - if (p_i2s_obj[i2s_num]->mode & I2S_MODE_MASTER) { - bck_sig = i2s_periph_signal[i2s_num].o_bck_out_sig; - ws_sig = i2s_periph_signal[i2s_num].o_ws_out_sig; - data_out_sig = i2s_periph_signal[i2s_num].o_data_out_sig; - } else if (p_i2s_obj[i2s_num]->mode & I2S_MODE_SLAVE) { - bck_sig = i2s_periph_signal[i2s_num].o_bck_in_sig; - ws_sig = i2s_periph_signal[i2s_num].o_ws_in_sig; - data_out_sig = i2s_periph_signal[i2s_num].o_data_out_sig; - } - } - //For RX unit, the output signal index should be I2SnI_xxx_OUT_IDX - //For RX unit, the input signal index shuld be I2SnI_xxx_IN_IDX - if (p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) { - if (p_i2s_obj[i2s_num]->mode & I2S_MODE_MASTER) { - bck_sig = i2s_periph_signal[i2s_num].i_bck_out_sig; - ws_sig = i2s_periph_signal[i2s_num].i_ws_out_sig; - data_in_sig = i2s_periph_signal[i2s_num].i_data_in_sig; - } else if (p_i2s_obj[i2s_num]->mode & I2S_MODE_SLAVE) { - bck_sig = i2s_periph_signal[i2s_num].i_bck_in_sig; - ws_sig = i2s_periph_signal[i2s_num].i_ws_in_sig; - data_in_sig = i2s_periph_signal[i2s_num].i_data_in_sig; - } - } - //For "full-duplex + slave" mode, we should select RX signal index for ws and bck. - //For "full-duplex + master" mode, we should select TX signal index for ws and bck. - if ((p_i2s_obj[i2s_num]->mode & I2S_FULL_DUPLEX_SLAVE_MODE_MASK) == I2S_FULL_DUPLEX_SLAVE_MODE_MASK) { - bck_sig = i2s_periph_signal[i2s_num].i_bck_in_sig; - ws_sig = i2s_periph_signal[i2s_num].i_ws_in_sig; - } else if ((p_i2s_obj[i2s_num]->mode & I2S_FULL_DUPLEX_MASTER_MODE_MASK) == I2S_FULL_DUPLEX_MASTER_MODE_MASK) { - bck_sig = i2s_periph_signal[i2s_num].o_bck_out_sig; - ws_sig = i2s_periph_signal[i2s_num].o_ws_out_sig; - } - gpio_matrix_out_check(pin->data_out_num, data_out_sig, 0, 0); - gpio_matrix_in_check(pin->data_in_num, data_in_sig, 0); - if (p_i2s_obj[i2s_num]->mode & I2S_MODE_MASTER) { - gpio_matrix_out_check(pin->ws_io_num, ws_sig, 0, 0); - gpio_matrix_out_check(pin->bck_io_num, bck_sig, 0, 0); - } else if (p_i2s_obj[i2s_num]->mode & I2S_MODE_SLAVE) { - gpio_matrix_in_check(pin->ws_io_num, ws_sig, 0); - gpio_matrix_in_check(pin->bck_io_num, bck_sig, 0); - } - ESP_LOGD(I2S_TAG, "data: out %d, in: %d, ws: %d, bck: %d", data_out_sig, data_in_sig, ws_sig, bck_sig); - - return ESP_OK; + adc1_dma_mode_acquire(); + _i2s_adc_mode_recover(); + i2s_rx_reset(i2s_num); + return i2s_set_clk(i2s_num, p_i2s[i2s_num]->hal_cfg.sample_rate, p_i2s[i2s_num]->hal_cfg.sample_bits, p_i2s[i2s_num]->hal_cfg.active_chan); } +/** + * @brief I2S disable ADC + * + * @param i2s_num I2S device number + * @return + * - ESP_OK I2S ADC mode successfully disabled + * - ESP_ERR_INVALID_ARG Invalid argument + * - ESP_ERR_INVALID_STATE Current I2S mode is not built-in ADC + */ +esp_err_t i2s_adc_disable(i2s_port_t i2s_num) +{ + ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); + ESP_RETURN_ON_FALSE((p_i2s[i2s_num] != NULL), ESP_ERR_INVALID_STATE, TAG, "Not initialized yet"); + ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_ADC_BUILT_IN), ESP_ERR_INVALID_STATE, TAG, "i2s built-in adc not enabled"); + + i2s_hal_stop_rx(&(p_i2s[i2s_num]->hal)); + adc1_lock_release(); + return ESP_OK; +} +#endif + +/** + * @brief Set sample rate used for I2S RX and TX. + * @note The bit clock rate is determined by the sample rate and i2s_config_t configuration parameters (number of channels, bits_per_sample). + * `bit_clock = rate * (number of channels) * bits_per_sample` + * + * @param i2s_num I2S device number + * @param rate I2S sample rate (ex: 8000, 44100...) + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NO_MEM Out of memory + */ esp_err_t i2s_set_sample_rates(i2s_port_t i2s_num, uint32_t rate) { - I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); - I2S_CHECK((p_i2s_obj[i2s_num]->bytes_per_sample > 0), "bits_per_sample not set", ESP_ERR_INVALID_ARG); - return i2s_set_clk(i2s_num, rate, p_i2s_obj[i2s_num]->bits_per_sample, p_i2s_obj[i2s_num]->channel_num); + ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); + ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->hal_cfg.sample_bits > 0), ESP_ERR_INVALID_ARG, TAG, "sample bits not set"); + return i2s_set_clk(i2s_num, rate, p_i2s[i2s_num]->hal_cfg.sample_bits, p_i2s[i2s_num]->hal_cfg.active_chan); } -#if SOC_I2S_SUPPORTS_PDM -esp_err_t i2s_set_pdm_rx_down_sample(i2s_port_t i2s_num, i2s_pdm_dsr_t dsr) +#if SOC_I2S_SUPPORTS_PCM +/** + * @brief Configure I2S a/u-law decompress or compress + * @note This function should be called after i2s driver installed + * Only take effect when the i2s 'communication_format' is set to 'I2S_COMM_FORMAT_STAND_PCM_SHORT' or 'I2S_COMM_FORMAT_STAND_PCM_LONG' + * + * @param i2s_num I2S_NUM_0 + * @param pcm_cfg Including mode selection and a/u-law decompress or compress configuration paramater + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t i2s_pcm_config(i2s_port_t i2s_num, const i2s_pcm_cfg_t *pcm_cfg) { - I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); - i2s_hal_rx_pdm_cfg(&(p_i2s_obj[i2s_num]->hal), dsr); - return i2s_set_clk(i2s_num, p_i2s_obj[i2s_num]->sample_rate, p_i2s_obj[i2s_num]->bits_per_sample, p_i2s_obj[i2s_num]->channel_num); + ESP_RETURN_ON_FALSE(p_i2s[i2s_num], ESP_FAIL, TAG, "i2s has not installed yet"); + ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->hal_cfg.comm_fmt & I2S_COMM_FORMAT_STAND_PCM_SHORT), + ESP_ERR_INVALID_ARG, TAG, "i2s communication mode is not PCM mode"); + i2s_stop(i2s_num); + I2S_ENTER_CRITICAL(i2s_num); + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_TX) { + i2s_hal_tx_pcm_cfg(&(p_i2s[i2s_num]->hal), pcm_cfg->pcm_type); + } else if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_RX) { + i2s_hal_rx_pcm_cfg(&(p_i2s[i2s_num]->hal), pcm_cfg->pcm_type); + } + I2S_EXIT_CRITICAL(i2s_num); + i2s_start(i2s_num); + return ESP_OK; } #endif -static esp_err_t i2s_check_cfg_static(i2s_port_t i2s_num, const i2s_config_t *cfg) +#if SOC_I2S_SUPPORTS_PDM_RX +/** + * @brief Set PDM mode down-sample rate + * In PDM RX mode, there would be 2 rounds of downsample process in hardware. + * In the first downsample process, the sampling number can be 16 or 8. + * In the second downsample process, the sampling number is fixed as 8. + * So the clock frequency in PDM RX mode would be (fpcm * 64) or (fpcm * 128) accordingly. + * @note After calling this function, it would call i2s_set_clk inside to update the clock frequency. + * Please call this function after I2S driver has been initialized. + * + * @param i2s_num I2S device number + * @param downsample i2s RX down sample rate for PDM mode. + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NO_MEM Out of memory + */ +esp_err_t i2s_set_pdm_rx_down_sample(i2s_port_t i2s_num, i2s_pdm_dsr_t downsample) { -#if SOC_I2S_SUPPORTS_ADC_DAC - //We only check if the I2S number is invalid when set to build in ADC and DAC mode. - I2S_CHECK(!((cfg->mode & I2S_MODE_ADC_BUILT_IN) && (i2s_num != I2S_NUM_0)), "I2S ADC built-in only support on I2S0", ESP_ERR_INVALID_ARG); - I2S_CHECK(!((cfg->mode & I2S_MODE_DAC_BUILT_IN) && (i2s_num != I2S_NUM_0)), "I2S DAC built-in only support on I2S0", ESP_ERR_INVALID_ARG); - return ESP_OK; -#endif -#if SOC_I2S_SUPPORTS_PDM - //We only check if the I2S number is invalid when set to PDM mode. - I2S_CHECK(!((cfg->mode & I2S_MODE_PDM) && (i2s_num != I2S_NUM_0)), "I2S DAC PDM only support on I2S0", ESP_ERR_INVALID_ARG); - return ESP_OK; + ESP_RETURN_ON_FALSE(p_i2s[i2s_num], ESP_FAIL, TAG, "i2s has not installed yet"); + ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_PDM), ESP_ERR_INVALID_ARG, TAG, "i2s mode is not PDM mode"); + i2s_stop(i2s_num); + i2s_hal_set_rx_pdm_dsr(&(p_i2s[i2s_num]->hal), downsample); + // i2s will start in 'i2s_set_clk' + return i2s_set_clk(i2s_num, p_i2s[i2s_num]->hal_cfg.sample_rate, p_i2s[i2s_num]->hal_cfg.sample_bits, p_i2s[i2s_num]->hal_cfg.active_chan); +} #endif - I2S_CHECK(cfg->communication_format && (cfg->communication_format < I2S_COMM_FORMAT_STAND_MAX), "invalid communication formats", ESP_ERR_INVALID_ARG); - I2S_CHECK(!((cfg->communication_format & I2S_COMM_FORMAT_STAND_MSB) && (cfg->communication_format & I2S_COMM_FORMAT_STAND_PCM_LONG)), "multiple communication formats specified", ESP_ERR_INVALID_ARG); +#if SOC_I2S_SUPPORTS_PDM_TX +/** + * @brief Set TX PDM mode up-sample rate + * @note If you have set PDM mode while calling 'i2s_driver_install', + * default PDM TX upsample parameters have already been set, + * no need to call this function again if you don't have to change the default configuration + * + * @param i2s_num I2S device number + * @param upsample_cfg Set I2S PDM up-sample rate configuration + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NO_MEM Out of memory + */ +esp_err_t i2s_set_pdm_tx_up_sample(i2s_port_t i2s_num, const i2s_pdm_tx_upsample_cfg_t *upsample_cfg) +{ + ESP_RETURN_ON_FALSE(p_i2s[i2s_num], ESP_FAIL, TAG, "i2s has not installed yet"); + ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_PDM), ESP_ERR_INVALID_ARG, TAG, "i2s mode is not PDM mode"); + i2s_stop(i2s_num); + i2s_hal_set_tx_pdm_fpfs(&(p_i2s[i2s_num]->hal), upsample_cfg->fp, upsample_cfg->fs); + // i2s will start in 'i2s_set_clk' + return i2s_set_clk(i2s_num, upsample_cfg->sample_rate, p_i2s[i2s_num]->hal_cfg.sample_bits, p_i2s[i2s_num]->hal_cfg.active_chan); +} +#endif + +/** + * @brief I2S check the validity of configuration + * + * @param i2s_num I2S device number + * @param cfg I2S HAL configuration + * @return + * - ESP_OK I2S configuration is valid + * - ESP_ERR_INVALID_ARG I2S configuration is invalid + */ +static esp_err_t i2s_check_cfg_validity(i2s_port_t i2s_num, i2s_hal_config_t *cfg) +{ +#if SOC_I2S_SUPPORTS_PDM_TX || SOC_I2S_SUPPORTS_PDM_RX + /* Check PDM mode */ + if (cfg->mode & I2S_MODE_PDM) { + ESP_RETURN_ON_FALSE(i2s_num == I2S_NUM_0, ESP_ERR_INVALID_ARG, TAG, "I2S PDM mode only support on I2S0"); +#if !SOC_I2S_SUPPORTS_PDM_TX + ESP_RETURN_ON_FALSE(cfg->mode & I2S_MODE_TX, ESP_ERR_INVALID_ARG, TAG, "PDM does not support TX on this chip"); +#endif // SOC_I2S_SUPPORTS_PDM_TX +#if !SOC_I2S_SUPPORTS_PDM_RX + ESP_RETURN_ON_FALSE(cfg->mode & I2S_MODE_RX, ESP_ERR_INVALID_ARG, TAG, "PDM does not support RX on this chip"); +#endif // SOC_I2S_SUPPORTS_PDM_RX + } +#else + ESP_RETURN_ON_FALSE(!(cfg->mode & I2S_MODE_PDM), ESP_ERR_INVALID_ARG, TAG, "I2S PDM mode not supported on current chip"); +#endif // SOC_I2S_SUPPORTS_PDM_TX || SOC_I2S_SUPPORTS_PDM_RX + +#if SOC_I2S_SUPPORTS_ADC || SOC_I2S_SUPPORTS_DAC + /* Check built-in ADC/DAC mode */ + if (cfg->mode & (I2S_MODE_ADC_BUILT_IN | I2S_MODE_DAC_BUILT_IN)) { + ESP_RETURN_ON_FALSE(i2s_num == I2S_NUM_0, ESP_ERR_INVALID_ARG, TAG, "I2S built-in ADC/DAC only support on I2S0"); + } +#else + /* Check the transmit/receive mode */ + ESP_RETURN_ON_FALSE((cfg->mode & I2S_MODE_TX) || (cfg->mode & I2S_MODE_RX), ESP_ERR_INVALID_ARG, TAG, "I2S no TX/RX mode selected"); + /* Check communication format */ + ESP_RETURN_ON_FALSE(cfg->comm_fmt && (cfg->comm_fmt < I2S_COMM_FORMAT_STAND_MAX), ESP_ERR_INVALID_ARG, TAG, "invalid communication formats"); +#endif // SOC_I2S_SUPPORTS_ADC || SOC_I2S_SUPPORTS_DAC + return ESP_OK; } -static esp_err_t i2s_param_config(i2s_port_t i2s_num, const i2s_config_t *i2s_config) +static void i2s_tx_set_clk_and_channel(i2s_port_t i2s_num, i2s_hal_clock_cfg_t *clk_cfg) { - I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); - I2S_CHECK((i2s_config), "param null", ESP_ERR_INVALID_ARG); - I2S_CHECK((i2s_check_cfg_static(i2s_num, i2s_config) == ESP_OK), "param check error", ESP_ERR_INVALID_ARG); + i2s_hal_tx_clock_config(&(p_i2s[i2s_num]->hal), clk_cfg); + i2s_hal_set_tx_sample_bit(&(p_i2s[i2s_num]->hal), p_i2s[i2s_num]->hal_cfg.chan_bits, p_i2s[i2s_num]->hal_cfg.sample_bits); + i2s_hal_tx_set_channel_style(&(p_i2s[i2s_num]->hal), &(p_i2s[i2s_num]->hal_cfg)); +} -#if SOC_I2S_SUPPORTS_ADC_DAC - if(i2s_config->mode & I2S_MODE_ADC_BUILT_IN) { - //in ADC built-in mode, we need to call i2s_set_adc_mode to - //initialize the specific ADC channel. - //in the current stage, we only support ADC1 and single channel mode. - //In default data mode, the ADC data is in 12-bit resolution mode. +static void i2s_rx_set_clk_and_channel(i2s_port_t i2s_num, i2s_hal_clock_cfg_t *clk_cfg) +{ + i2s_hal_rx_clock_config(&(p_i2s[i2s_num]->hal), clk_cfg); + i2s_hal_set_rx_sample_bit(&(p_i2s[i2s_num]->hal), p_i2s[i2s_num]->hal_cfg.chan_bits, p_i2s[i2s_num]->hal_cfg.sample_bits); + i2s_hal_rx_set_channel_style(&(p_i2s[i2s_num]->hal), &(p_i2s[i2s_num]->hal_cfg)); +} + +/** + * @brief Get clock set on particular port number. + * + * @param i2s_num I2S device number + * @return + * - sample rate + */ +float i2s_get_clk(i2s_port_t i2s_num) +{ + ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); + return (float)p_i2s[i2s_num]->hal_cfg.sample_rate; +} + +/** + * @brief Set clock & bit width used for I2S RX and TX. + * Similar to i2s_set_sample_rates(), but also sets bit width. + * + * 1. stop i2s + * 2. calculate mclk, bck, bck_factor + * 3. set clock configurations + * 4. realloc dma buffer if DMA buffer size changed + * 5. start i2s + * + * @param i2s_num I2S device number + * @param rate I2S sample rate (ex: 8000, 44100...) + * @param bits_cfg I2S bits configuration + * the low 16 bits is for data bits per sample in one channel (see 'i2s_bits_per_sample_t') + * the high 16 bits is for total bits in one channel (see 'i2s_bits_per_chan_t') + * high 16bits =0 means same as the bits per sample. + * @param ch I2S channel, (I2S_CHANNEL_MONO, I2S_CHANNEL_STEREO or specific channel in TDM mode) + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NO_MEM Out of memory + */ +esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, uint32_t bits_cfg, i2s_channel_t ch) +{ + esp_err_t ret = ESP_OK; + + ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); + ESP_RETURN_ON_FALSE(p_i2s[i2s_num], ESP_ERR_INVALID_ARG, TAG, "I2S%d has not installed yet", i2s_num); + + i2s_hal_config_t *cfg = &p_i2s[i2s_num]->hal_cfg; + /* If not the first time, update configuration */ + if (p_i2s[i2s_num]->last_buf_size) { + cfg->sample_rate = rate; + cfg->sample_bits = bits_cfg & 0xFFFF; + cfg->chan_bits = (bits_cfg >> 16) > cfg->sample_bits ? (bits_cfg >> 16) : cfg->sample_bits; +#if SOC_I2S_SUPPORTS_TDM + cfg->chan_mask = ch; + cfg->chan_fmt = ch == I2S_CHANNEL_MONO ? I2S_CHANNEL_FMT_ONLY_RIGHT : cfg->chan_fmt; + cfg->active_chan = i2s_get_active_channel_num(cfg); + uint32_t max_channel = i2s_get_max_channel_num(cfg->chan_mask); + /* If total channel is smaller than max actived channel number then set it to the max active channel number */ + cfg->total_chan = p_i2s[i2s_num]->hal_cfg.total_chan < max_channel ? max_channel : p_i2s[i2s_num]->hal_cfg.total_chan; +#else + /* Default */ + cfg->chan_fmt = ch == I2S_CHANNEL_MONO ? I2S_CHANNEL_FMT_ONLY_RIGHT : cfg->chan_fmt; + cfg->active_chan = i2s_get_active_channel_num(cfg); + cfg->total_chan = 2; +#endif + if (cfg->mode & I2S_MODE_TX) { + xSemaphoreTake(p_i2s[i2s_num]->tx->mux, (portTickType)portMAX_DELAY); + i2s_hal_tx_set_channel_style(&(p_i2s[i2s_num]->hal), cfg); + xSemaphoreGive(p_i2s[i2s_num]->tx->mux); + } + if (cfg->mode & I2S_MODE_RX) { + xSemaphoreTake(p_i2s[i2s_num]->rx->mux, (portTickType)portMAX_DELAY); + i2s_hal_rx_set_channel_style(&(p_i2s[i2s_num]->hal), cfg); + xSemaphoreGive(p_i2s[i2s_num]->rx->mux); + } + } + uint32_t data_bits = cfg->sample_bits; + + /* Check the validity of sample bits */ + ESP_RETURN_ON_FALSE((data_bits % 8 == 0), ESP_ERR_INVALID_ARG, TAG, "Invalid bits per sample"); + ESP_RETURN_ON_FALSE((data_bits <= I2S_BITS_PER_SAMPLE_32BIT), ESP_ERR_INVALID_ARG, TAG, "Invalid bits per sample"); + + /* Stop I2S */ + i2s_stop(i2s_num); + + i2s_hal_clock_cfg_t clk_cfg; + /* To get sclk, mclk, mclk_div bclk and bclk_div */ + i2s_calculate_clock(i2s_num, &clk_cfg); + + uint32_t buf_size = i2s_get_buf_size(i2s_num); + bool need_realloc = p_i2s[i2s_num]->last_buf_size != buf_size; + + /* TX mode clock reset */ + if (cfg->mode & I2S_MODE_TX) { + ESP_RETURN_ON_FALSE(p_i2s[i2s_num]->tx, ESP_ERR_INVALID_ARG, TAG, "I2S TX DMA object has not initialized yet"); + /* Waiting for transmit finish */ + xSemaphoreTake(p_i2s[i2s_num]->tx->mux, (portTickType)portMAX_DELAY); + i2s_tx_set_clk_and_channel(i2s_num, &clk_cfg); + /* If buffer size changed, the DMA buffer need realloc */ + if (need_realloc) { + p_i2s[i2s_num]->tx->buf_size = buf_size; + ret = i2s_realloc_dma_buffer(i2s_num, p_i2s[i2s_num]->tx); + } + /* If not the first time, update I2S tx channel style */ + if (p_i2s[i2s_num]->last_buf_size) { + i2s_hal_tx_set_channel_style(&(p_i2s[i2s_num]->hal), &(p_i2s[i2s_num]->hal_cfg)); + } + /* Reset the queue to avoid receive invalid data */ + xQueueReset(p_i2s[i2s_num]->tx->queue); + xSemaphoreGive(p_i2s[i2s_num]->tx->mux); + ESP_RETURN_ON_ERROR(ret, TAG, "I2S%d tx DMA buffer malloc failed", i2s_num); + } + /* RX mode clock reset */ + if (cfg->mode & I2S_MODE_RX) { + ESP_RETURN_ON_FALSE(p_i2s[i2s_num]->rx, ESP_ERR_INVALID_ARG, TAG, "I2S TX DMA object has not initialized yet"); + /* Waiting for receive finish */ + xSemaphoreTake(p_i2s[i2s_num]->rx->mux, (portTickType)portMAX_DELAY); + i2s_rx_set_clk_and_channel(i2s_num, &clk_cfg); + /* If buffer size changed, the DMA buffer need realloc */ + if (need_realloc) { + p_i2s[i2s_num]->rx->buf_size = buf_size; + ret = i2s_realloc_dma_buffer(i2s_num, p_i2s[i2s_num]->rx); + /* Reset the end-of-frame number */ + i2s_hal_set_rx_eof_num(&(p_i2s[i2s_num]->hal), buf_size); + } + /* If not the first time, update I2S rx channel style */ + if (p_i2s[i2s_num]->last_buf_size) { + i2s_hal_rx_set_channel_style(&(p_i2s[i2s_num]->hal), &(p_i2s[i2s_num]->hal_cfg)); + } + /* Reset the queue to avoid receiving invalid data */ + xQueueReset(p_i2s[i2s_num]->rx->queue); + xSemaphoreGive(p_i2s[i2s_num]->rx->mux); + ESP_RETURN_ON_ERROR(ret, TAG, "I2S%d rx DMA buffer malloc failed", i2s_num); + } + /* Update last buffer size */ + p_i2s[i2s_num]->last_buf_size = buf_size; + + /* I2S start */ + i2s_start(i2s_num); + + return ESP_OK; +} + +/*------------------------------------------------------------- + I2S driver operation + -------------------------------------------------------------*/ +/** + * @brief Start I2S driver + * @note It is not necessary to call this function after i2s_driver_install() (it is started automatically), however it is necessary to call it after i2s_stop(). + * + * @param i2s_num I2S device number + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t i2s_start(i2s_port_t i2s_num) +{ + ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); + //start DMA link + I2S_ENTER_CRITICAL(i2s_num); + + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_TX) { + i2s_tx_reset(i2s_num); + i2s_tx_start(i2s_num); + } + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_RX) { + i2s_rx_reset(i2s_num); + i2s_rx_start(i2s_num); + } +#if !SOC_GDMA_SUPPORTED + esp_intr_enable(p_i2s[i2s_num]->i2s_isr_handle); +#endif + I2S_EXIT_CRITICAL(i2s_num); + return ESP_OK; +} + +/** + * @brief Stop I2S driver + * @note There is no need to call i2s_stop() before calling i2s_driver_uninstall(). + * Disables I2S TX/RX, until i2s_start() is called. + * + * @param i2s_num I2S device number + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t i2s_stop(i2s_port_t i2s_num) +{ + ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); + I2S_ENTER_CRITICAL(i2s_num); +#if !SOC_GDMA_SUPPORTED + esp_intr_disable(p_i2s[i2s_num]->i2s_isr_handle); +#endif + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_TX) { + i2s_tx_stop(i2s_num); + } + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_RX) { + i2s_rx_stop(i2s_num); + } +#if !SOC_GDMA_SUPPORTED + i2s_hal_clear_intr_status(&(p_i2s[i2s_num]->hal), I2S_INTR_MAX); +#endif + I2S_EXIT_CRITICAL(i2s_num); + return ESP_OK; +} + +/** + * @brief Initialize I2S driver configurations + * + * @param i2s_num I2S device number + * @param i2s_config I2S configurations - see i2s_config_t struct + * @return + * - ESP_OK I2S initialize success + * - ESP_ERR_INVALID_ARG No channel enabled in multiple channel format + */ +static esp_err_t i2s_driver_init(i2s_port_t i2s_num, const i2s_config_t *i2s_config) +{ + ESP_RETURN_ON_FALSE(i2s_config, ESP_ERR_INVALID_ARG, TAG, "The pointer of I2S configuration structure is NULL"); + + /* I2S driver configuration assignment */ + p_i2s[i2s_num]->i2s_num = i2s_num; + p_i2s[i2s_num]->dma_buf_count = i2s_config->dma_buf_count; + p_i2s[i2s_num]->dma_buf_len = i2s_config->dma_buf_len; + p_i2s[i2s_num]->last_buf_size = 0; + p_i2s[i2s_num]->use_apll = i2s_config->use_apll; + p_i2s[i2s_num]->fixed_mclk = i2s_config->fixed_mclk; + p_i2s[i2s_num]->mclk_multiple = i2s_config->mclk_multiple; + p_i2s[i2s_num]->tx_desc_auto_clear = i2s_config->tx_desc_auto_clear; + + /* I2S HAL configuration assignment */ + p_i2s[i2s_num]->hal_cfg.mode = i2s_config->mode; + p_i2s[i2s_num]->hal_cfg.sample_rate = i2s_config->sample_rate; + p_i2s[i2s_num]->hal_cfg.comm_fmt = i2s_config->communication_format; + p_i2s[i2s_num]->hal_cfg.chan_fmt = i2s_config->channel_format; + p_i2s[i2s_num]->hal_cfg.sample_bits = i2s_config->bits_per_sample; + p_i2s[i2s_num]->hal_cfg.chan_bits = (uint32_t)i2s_config->bits_per_chan < (uint32_t)i2s_config->bits_per_sample ? + (uint32_t)i2s_config->bits_per_sample : (uint32_t)i2s_config->bits_per_chan; + +#if SOC_I2S_SUPPORTS_TDM + /* I2S HAL TDM configuration assignment */ + p_i2s[i2s_num]->hal_cfg.left_align = i2s_config->left_align; + p_i2s[i2s_num]->hal_cfg.big_edin = i2s_config->big_edin; + p_i2s[i2s_num]->hal_cfg.bit_order_msb = i2s_config->bit_order_msb; + p_i2s[i2s_num]->hal_cfg.skip_msk = i2s_config->skip_msk; + + /* Set chan_mask according to channel format */ + switch (i2s_config->channel_format) { + case I2S_CHANNEL_FMT_RIGHT_LEFT: // fall through + case I2S_CHANNEL_FMT_ALL_RIGHT: // fall through + case I2S_CHANNEL_FMT_ALL_LEFT: + p_i2s[i2s_num]->hal_cfg.chan_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1; + p_i2s[i2s_num]->hal_cfg.total_chan = 2; + break; + case I2S_CHANNEL_FMT_ONLY_RIGHT: // fall through + case I2S_CHANNEL_FMT_ONLY_LEFT: + p_i2s[i2s_num]->hal_cfg.chan_mask = I2S_TDM_ACTIVE_CH0; + p_i2s[i2s_num]->hal_cfg.total_chan = 2; + break; + case I2S_CHANNEL_FMT_MULTIPLE: + ESP_RETURN_ON_FALSE(i2s_config->chan_mask, ESP_ERR_INVALID_ARG, TAG, "i2s all channel are disabled"); + p_i2s[i2s_num]->hal_cfg.chan_mask = i2s_config->chan_mask; + /* Get the max actived channel number */ + uint32_t max_channel = i2s_get_max_channel_num(p_i2s[i2s_num]->hal_cfg.chan_mask); + /* If total channel is smaller than max actived channel number then set it to the max active channel number */ + p_i2s[i2s_num]->hal_cfg.total_chan = p_i2s[i2s_num]->hal_cfg.total_chan < max_channel ? max_channel : + p_i2s[i2s_num]->hal_cfg.total_chan; + break; + default: + ESP_RETURN_ON_FALSE(false, ESP_ERR_INVALID_ARG, TAG, "wrong i2s channel format, going to uninstall i2s"); + } + + /* Calculate actived channel number in channel mask */ + p_i2s[i2s_num]->hal_cfg.active_chan = i2s_get_active_channel_num(&p_i2s[i2s_num]->hal_cfg); + +#else + /* Calculate actived channel number in channel mask */ + p_i2s[i2s_num]->hal_cfg.active_chan = i2s_get_active_channel_num(&p_i2s[i2s_num]->hal_cfg); + /* Total channel number is equal to the actived channel number in non-TDM mode */ + p_i2s[i2s_num]->hal_cfg.total_chan = 2; +#endif + return ESP_OK; +} + +/** + * @brief Initialize I2S DMA object + * + * @param i2s_num I2S device number + * @return + * - ESP_OK DMA object initialize success + * - ESP_ERR_NO_MEM No memory for DMA object + */ +static esp_err_t i2s_dma_object_init(i2s_port_t i2s_num) +{ + uint32_t buf_size = i2s_get_buf_size(i2s_num); + /* Create DMA object */ + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_TX) { + ESP_RETURN_ON_ERROR(i2s_create_dma_object(i2s_num, &p_i2s[i2s_num]->tx), TAG, "I2S TX DMA object create failed"); + p_i2s[i2s_num]->tx->buf_size = buf_size; + } + if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_RX) { + ESP_RETURN_ON_ERROR(i2s_create_dma_object(i2s_num, &p_i2s[i2s_num]->rx), TAG, "I2S RX DMA object create failed"); + p_i2s[i2s_num]->rx->buf_size = buf_size; + } + return ESP_OK; +} + +/** + * @brief Install and start I2S driver. + * @note This function must be called before any I2S driver read/write operations. + * + * + * @param i2s_num I2S device number + * @param i2s_config I2S configurations - see i2s_config_t struct + * @param queue_size I2S event queue size/depth. + * @param i2s_queue I2S event queue handle, if set NULL, driver will not use an event queue. + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NO_MEM Out of memory + * - ESP_ERR_INVALID_STATE Current I2S port is in use + */ +esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, int queue_size, void *i2s_queue) +{ + esp_err_t ret = ESP_OK; + + /* Step 1: Check the validity of input parameters */ + /* Check the validity of i2s device number */ + ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); + ESP_RETURN_ON_FALSE(i2s_config, ESP_ERR_INVALID_ARG, TAG, "I2S configuration must not be NULL"); + /* Check the size of DMA buffer */ + ESP_RETURN_ON_FALSE((i2s_config->dma_buf_count >= 2 && i2s_config->dma_buf_count <= 128), ESP_ERR_INVALID_ARG, TAG, "I2S buffer count less than 128 and more than 2"); + ESP_RETURN_ON_FALSE((i2s_config->dma_buf_len >= 8 && i2s_config->dma_buf_len <= 1024), ESP_ERR_INVALID_ARG, TAG, "I2S buffer length at most 1024 and more than 8"); + + /* Step 2: Allocate driver object and register to platform */ + i2s_obj_t *pre_alloc_i2s_obj = calloc(1, sizeof(i2s_obj_t)); + ESP_RETURN_ON_FALSE(pre_alloc_i2s_obj, ESP_ERR_NO_MEM, TAG, "no mem for I2S driver"); + ret = i2s_priv_register_object(pre_alloc_i2s_obj, i2s_num); + if (ret != ESP_OK) { + free(pre_alloc_i2s_obj); + ESP_LOGE(TAG, "register I2S object to platform failed"); + return ESP_ERR_INVALID_STATE; + } + + /* Step 3: Initialize I2S object, assign configarations */ + ESP_GOTO_ON_ERROR(i2s_driver_init(i2s_num, i2s_config), err, TAG, "I2S init failed"); + /* Check the validity of I2S configuration */ + ESP_GOTO_ON_ERROR(i2s_check_cfg_validity(i2s_num, &(pre_alloc_i2s_obj->hal_cfg)), err, TAG, "I2S configuration is invalid"); + + /* Get device instance */ + i2s_hal_init(&(pre_alloc_i2s_obj->hal), i2s_num); + +#ifdef CONFIG_PM_ENABLE + esp_pm_lock_type_t pm_lock = ESP_PM_APB_FREQ_MAX; +#if SOC_I2S_SUPPORTS_APLL + if (i2s_config->use_apll) { + pm_lock = ESP_PM_NO_LIGHT_SLEEP; + } +#endif // SOC_I2S_SUPPORTS_APLL + ESP_GOTO_ON_ERROR(esp_pm_lock_create(pm_lock, 0, "i2s_driver", &pre_alloc_i2s_obj->pm_lock), err, TAG, "I2S pm lock error"); +#endif //CONFIG_PM_ENABLE + + /* Step 4: Initialize I2S DMA interrupt and DMA object */ + ESP_GOTO_ON_ERROR(i2s_dma_intr_init(i2s_num, i2s_config->intr_alloc_flags), err, TAG, "I2S interrupt initailze failed"); + /* Initialize I2S DMA object */ + ESP_GOTO_ON_ERROR(i2s_dma_object_init(i2s_num), err, TAG, "I2S dma object create failed"); + +#if SOC_I2S_SUPPORTS_ADC + /* If using built-in ADC, we need to enable ADC power manerge*/ + if (pre_alloc_i2s_obj->hal_cfg.mode & I2S_MODE_ADC_BUILT_IN) { adc_power_acquire(); } #endif - // configure I2S data port interface. - i2s_hal_config_param(&(p_i2s_obj[i2s_num]->hal), i2s_config); - if ((p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) && (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX)) { - i2s_hal_enable_sig_loopback(&(p_i2s_obj[i2s_num]->hal)); - if (p_i2s_obj[i2s_num]->mode & I2S_MODE_MASTER) { - i2s_hal_enable_master_mode(&(p_i2s_obj[i2s_num]->hal)); - } else { - i2s_hal_enable_slave_mode(&(p_i2s_obj[i2s_num]->hal)); - } - } + /* Enable module clock */ + i2s_hal_enable_module_clock(&p_i2s[i2s_num]->hal); - p_i2s_obj[i2s_num]->use_apll = i2s_config->use_apll; - p_i2s_obj[i2s_num]->tx_desc_auto_clear = i2s_config->tx_desc_auto_clear; - p_i2s_obj[i2s_num]->fixed_mclk = i2s_config->fixed_mclk; - return ESP_OK; -} + /* Step 5: Initialize I2S configuration and set the configurations to register */ + i2s_hal_config_param(&(pre_alloc_i2s_obj->hal), &pre_alloc_i2s_obj->hal_cfg); -esp_err_t i2s_zero_dma_buffer(i2s_port_t i2s_num) -{ - I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); - if (p_i2s_obj[i2s_num]->rx && p_i2s_obj[i2s_num]->rx->buf != NULL && p_i2s_obj[i2s_num]->rx->buf_size != 0) { - for (int i = 0; i < p_i2s_obj[i2s_num]->dma_buf_count; i++) { - memset(p_i2s_obj[i2s_num]->rx->buf[i], 0, p_i2s_obj[i2s_num]->rx->buf_size); - } - } - if (p_i2s_obj[i2s_num]->tx && p_i2s_obj[i2s_num]->tx->buf != NULL && p_i2s_obj[i2s_num]->tx->buf_size != 0) { - int bytes_left = 0; - bytes_left = (p_i2s_obj[i2s_num]->tx->buf_size - p_i2s_obj[i2s_num]->tx->rw_pos) % 4; - if (bytes_left) { - size_t zero_bytes = 0, bytes_written; - i2s_write(i2s_num, (void *)&zero_bytes, bytes_left, &bytes_written, portMAX_DELAY); - } - for (int i = 0; i < p_i2s_obj[i2s_num]->dma_buf_count; i++) { - memset(p_i2s_obj[i2s_num]->tx->buf[i], 0, p_i2s_obj[i2s_num]->tx->buf_size); - } - } - return ESP_OK; -} - -esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, int queue_size, void* i2s_queue) -{ - esp_err_t err; - I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); - I2S_CHECK((i2s_config != NULL), "I2S configuration must not NULL", ESP_ERR_INVALID_ARG); - I2S_CHECK((i2s_config->dma_buf_count >= 2 && i2s_config->dma_buf_count <= 128), "I2S buffer count less than 128 and more than 2", ESP_ERR_INVALID_ARG); - I2S_CHECK((i2s_config->dma_buf_len >= 8 && i2s_config->dma_buf_len <= 1024), "I2S buffer length at most 1024 and more than 8", ESP_ERR_INVALID_ARG); - if (p_i2s_obj[i2s_num] == NULL) { - p_i2s_obj[i2s_num] = (i2s_obj_t*) malloc(sizeof(i2s_obj_t)); - if (p_i2s_obj[i2s_num] == NULL) { - ESP_LOGE(I2S_TAG, "Malloc I2S driver error"); - return ESP_ERR_NO_MEM; - } - memset(p_i2s_obj[i2s_num], 0, sizeof(i2s_obj_t)); - - portMUX_TYPE i2s_spinlock_unlocked[1] = {portMUX_INITIALIZER_UNLOCKED}; - for (int x = 0; x < I2S_NUM_MAX; x++) { - i2s_spinlock[x] = i2s_spinlock_unlocked[0]; - } - //To make sure hardware is enabled before any hardware register operations. - periph_module_enable(i2s_periph_signal[i2s_num].module); - i2s_hal_init(&(p_i2s_obj[i2s_num]->hal), i2s_num); - - p_i2s_obj[i2s_num]->i2s_num = i2s_num; - p_i2s_obj[i2s_num]->dma_buf_count = i2s_config->dma_buf_count; - p_i2s_obj[i2s_num]->dma_buf_len = i2s_config->dma_buf_len; - p_i2s_obj[i2s_num]->i2s_queue = i2s_queue; - p_i2s_obj[i2s_num]->mode = i2s_config->mode; - - p_i2s_obj[i2s_num]->bits_per_sample = 0; - p_i2s_obj[i2s_num]->bytes_per_sample = 0; // Not initialized yet - p_i2s_obj[i2s_num]->channel_num = i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? 2 : 1; - -#ifdef CONFIG_PM_ENABLE - if (i2s_config->use_apll) { - err = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "i2s_driver", &p_i2s_obj[i2s_num]->pm_lock); + /* Step 6: Initialise i2s event queue if user needs */ + if (i2s_queue) { + pre_alloc_i2s_obj->i2s_queue = xQueueCreate(queue_size, sizeof(i2s_event_t)); + ESP_GOTO_ON_FALSE(pre_alloc_i2s_obj->i2s_queue, ESP_ERR_NO_MEM, err, TAG, "I2S queue create failed"); + *((QueueHandle_t *) i2s_queue) = pre_alloc_i2s_obj->i2s_queue; + ESP_LOGI(TAG, "queue free spaces: %d", uxQueueSpacesAvailable(pre_alloc_i2s_obj->i2s_queue)); } else { - err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "i2s_driver", &p_i2s_obj[i2s_num]->pm_lock); - } - if (err != ESP_OK) { - free(p_i2s_obj[i2s_num]); - p_i2s_obj[i2s_num] = NULL; - ESP_LOGE(I2S_TAG, "I2S pm lock error"); - return err; - } -#endif //CONFIG_PM_ENABLE - - //initial interrupt - err = i2s_isr_register(i2s_num, i2s_config->intr_alloc_flags, i2s_intr_handler_default, p_i2s_obj[i2s_num], &p_i2s_obj[i2s_num]->i2s_isr_handle); - if (err != ESP_OK) { -#ifdef CONFIG_PM_ENABLE - if (p_i2s_obj[i2s_num]->pm_lock) { - esp_pm_lock_delete(p_i2s_obj[i2s_num]->pm_lock); - } -#endif - free(p_i2s_obj[i2s_num]); - p_i2s_obj[i2s_num] = NULL; - ESP_LOGE(I2S_TAG, "Register I2S Interrupt error"); - return err; - } - i2s_stop(i2s_num); - err = i2s_param_config(i2s_num, i2s_config); - if (err != ESP_OK) { - i2s_driver_uninstall(i2s_num); - ESP_LOGE(I2S_TAG, "I2S param configure error"); - return err; - } - - if (i2s_queue) { - p_i2s_obj[i2s_num]->i2s_queue = xQueueCreate(queue_size, sizeof(i2s_event_t)); - *((QueueHandle_t*) i2s_queue) = p_i2s_obj[i2s_num]->i2s_queue; - ESP_LOGI(I2S_TAG, "queue free spaces: %d", uxQueueSpacesAvailable(p_i2s_obj[i2s_num]->i2s_queue)); - } else { - p_i2s_obj[i2s_num]->i2s_queue = NULL; - } - //set clock and start - return i2s_set_clk(i2s_num, i2s_config->sample_rate, i2s_config->bits_per_sample, p_i2s_obj[i2s_num]->channel_num); + pre_alloc_i2s_obj->i2s_queue = NULL; } - ESP_LOGW(I2S_TAG, "I2S driver already installed"); + /* Step 7: Set I2S clocks and start. No need to give parameters since configurations has been set in 'i2s_driver_init' */ + ESP_GOTO_ON_ERROR(i2s_set_clk(i2s_num, 0, 0, 0), err, TAG, "I2S set clock failed"); return ESP_OK; + +err: + /* I2S install failed, prepare to uninstall */ + i2s_driver_uninstall(i2s_num); + return ret; } +/** + * @brief Uninstall I2S driver. + * + * @param i2s_num I2S device number + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num) { - I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); - if (p_i2s_obj[i2s_num] == NULL) { - ESP_LOGI(I2S_TAG, "already uninstalled"); - return ESP_OK; - } + ESP_RETURN_ON_FALSE(i2s_num < I2S_NUM_MAX, ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); + ESP_RETURN_ON_FALSE(p_i2s[i2s_num], ESP_ERR_INVALID_STATE, TAG, "I2S port %d has not installed", i2s_num); + i2s_obj_t *obj = p_i2s[i2s_num]; i2s_stop(i2s_num); - esp_intr_free(p_i2s_obj[i2s_num]->i2s_isr_handle); - - if (p_i2s_obj[i2s_num]->tx != NULL && p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) { - i2s_destroy_dma_queue(i2s_num, p_i2s_obj[i2s_num]->tx); - p_i2s_obj[i2s_num]->tx = NULL; +#if SOC_I2S_SUPPORTS_DAC + i2s_set_dac_mode(I2S_DAC_CHANNEL_DISABLE); +#endif +#if SOC_GDMA_SUPPORTED + if (p_i2s[i2s_num]->tx_dma_chan) { + gdma_disconnect(p_i2s[i2s_num]->tx_dma_chan); + gdma_del_channel(p_i2s[i2s_num]->tx_dma_chan); } - if (p_i2s_obj[i2s_num]->rx != NULL && p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) { - i2s_destroy_dma_queue(i2s_num, p_i2s_obj[i2s_num]->rx); - p_i2s_obj[i2s_num]->rx = NULL; + if (p_i2s[i2s_num]->rx_dma_chan) { + gdma_disconnect(p_i2s[i2s_num]->rx_dma_chan); + gdma_del_channel(p_i2s[i2s_num]->rx_dma_chan); + } +#else + if (p_i2s[i2s_num]->i2s_isr_handle) { + esp_intr_free(p_i2s[i2s_num]->i2s_isr_handle); + } +#endif + /* Destroy dma object if exist */ + i2s_destroy_dma_object(i2s_num, &p_i2s[i2s_num]->tx); + i2s_destroy_dma_object(i2s_num, &p_i2s[i2s_num]->rx); + + if (p_i2s[i2s_num]->i2s_queue) { + vQueueDelete(p_i2s[i2s_num]->i2s_queue); + p_i2s[i2s_num]->i2s_queue = NULL; } - if (p_i2s_obj[i2s_num]->i2s_queue) { - vQueueDelete(p_i2s_obj[i2s_num]->i2s_queue); - p_i2s_obj[i2s_num]->i2s_queue = NULL; - } - - if(p_i2s_obj[i2s_num]->use_apll) { +#if SOC_I2S_SUPPORTS_APLL + if (p_i2s[i2s_num]->use_apll) { // switch back to PLL clock source - i2s_hal_set_clock_sel(&(p_i2s_obj[i2s_num]->hal), I2S_CLK_D2CLK); + i2s_hal_set_clock_src(&(p_i2s[i2s_num]->hal), I2S_CLK_D2CLK); rtc_clk_apll_enable(0, 0, 0, 0, 0); } -#ifdef CONFIG_PM_ENABLE - if (p_i2s_obj[i2s_num]->pm_lock) { - esp_pm_lock_delete(p_i2s_obj[i2s_num]->pm_lock); - } #endif - free(p_i2s_obj[i2s_num]); - p_i2s_obj[i2s_num] = NULL; - periph_module_disable(i2s_periph_signal[i2s_num].module); - +#ifdef CONFIG_PM_ENABLE + if (p_i2s[i2s_num]->pm_lock) { + esp_pm_lock_delete(p_i2s[i2s_num]->pm_lock); + p_i2s[i2s_num]->pm_lock = NULL; + } +#endif + /* Disable module clock */ + i2s_hal_disable_module_clock(&p_i2s[i2s_num]->hal); + i2s_priv_deregister_object(i2s_num); + free(obj); return ESP_OK; } +/** + * @brief Write data to I2S DMA transmit buffer. + * @note Many ticks pass without space becoming available in the DMA + * transmit buffer, then the function will return (note that if the + * data is written to the DMA buffer in pieces, the overall operation + * may still take longer than this timeout.) Pass portMAX_DELAY for no + * timeout. + * + * @param i2s_num I2S device number + * @param src Source address to write from + * @param size Size of data in bytes + * @param[out] bytes_written Number of bytes written, if timeout, the result will be less than the size passed in. + * @param ticks_to_wait TX buffer wait timeout in RTOS ticks. If this + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ esp_err_t i2s_write(i2s_port_t i2s_num, const void *src, size_t size, size_t *bytes_written, TickType_t ticks_to_wait) { + esp_err_t ret = ESP_OK; char *data_ptr, *src_byte; size_t bytes_can_write; *bytes_written = 0; - I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); - I2S_CHECK((size < SOC_I2S_MAX_BUFFER_SIZE), "size is too large", ESP_ERR_INVALID_ARG); - I2S_CHECK((p_i2s_obj[i2s_num]->tx), "tx NULL", ESP_ERR_INVALID_ARG); - xSemaphoreTake(p_i2s_obj[i2s_num]->tx->mux, (portTickType)portMAX_DELAY); + ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); + ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->tx), ESP_ERR_INVALID_ARG, TAG, "TX mode is not enabled"); + xSemaphoreTake(p_i2s[i2s_num]->tx->mux, (portTickType)portMAX_DELAY); #ifdef CONFIG_PM_ENABLE - esp_pm_lock_acquire(p_i2s_obj[i2s_num]->pm_lock); + esp_pm_lock_acquire(p_i2s[i2s_num]->pm_lock); #endif src_byte = (char *)src; while (size > 0) { - if (p_i2s_obj[i2s_num]->tx->rw_pos == p_i2s_obj[i2s_num]->tx->buf_size || p_i2s_obj[i2s_num]->tx->curr_ptr == NULL) { - if (xQueueReceive(p_i2s_obj[i2s_num]->tx->queue, &p_i2s_obj[i2s_num]->tx->curr_ptr, ticks_to_wait) == pdFALSE) { + if (p_i2s[i2s_num]->tx->rw_pos == p_i2s[i2s_num]->tx->buf_size || p_i2s[i2s_num]->tx->curr_ptr == NULL) { + if (xQueueReceive(p_i2s[i2s_num]->tx->queue, &p_i2s[i2s_num]->tx->curr_ptr, ticks_to_wait) == pdFALSE) { + ret = ESP_ERR_TIMEOUT; break; } - p_i2s_obj[i2s_num]->tx->rw_pos = 0; + p_i2s[i2s_num]->tx->rw_pos = 0; } - ESP_LOGD(I2S_TAG, "size: %d, rw_pos: %d, buf_size: %d, curr_ptr: %d", size, p_i2s_obj[i2s_num]->tx->rw_pos, p_i2s_obj[i2s_num]->tx->buf_size, (int)p_i2s_obj[i2s_num]->tx->curr_ptr); - data_ptr = (char*)p_i2s_obj[i2s_num]->tx->curr_ptr; - data_ptr += p_i2s_obj[i2s_num]->tx->rw_pos; - bytes_can_write = p_i2s_obj[i2s_num]->tx->buf_size - p_i2s_obj[i2s_num]->tx->rw_pos; + ESP_LOGD(TAG, "size: %d, rw_pos: %d, buf_size: %d, curr_ptr: %d", size, p_i2s[i2s_num]->tx->rw_pos, p_i2s[i2s_num]->tx->buf_size, (int)p_i2s[i2s_num]->tx->curr_ptr); + data_ptr = (char *)p_i2s[i2s_num]->tx->curr_ptr; + data_ptr += p_i2s[i2s_num]->tx->rw_pos; + bytes_can_write = p_i2s[i2s_num]->tx->buf_size - p_i2s[i2s_num]->tx->rw_pos; if (bytes_can_write > size) { bytes_can_write = size; } memcpy(data_ptr, src_byte, bytes_can_write); size -= bytes_can_write; src_byte += bytes_can_write; - p_i2s_obj[i2s_num]->tx->rw_pos += bytes_can_write; + p_i2s[i2s_num]->tx->rw_pos += bytes_can_write; (*bytes_written) += bytes_can_write; } #ifdef CONFIG_PM_ENABLE - esp_pm_lock_release(p_i2s_obj[i2s_num]->pm_lock); + esp_pm_lock_release(p_i2s[i2s_num]->pm_lock); #endif - - xSemaphoreGive(p_i2s_obj[i2s_num]->tx->mux); - return ESP_OK; + xSemaphoreGive(p_i2s[i2s_num]->tx->mux); + return ret; } -#if SOC_I2S_SUPPORTS_ADC_DAC -esp_err_t i2s_adc_enable(i2s_port_t i2s_num) -{ - I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); - I2S_CHECK((p_i2s_obj[i2s_num] != NULL), "Not initialized yet", ESP_ERR_INVALID_STATE); - I2S_CHECK((p_i2s_obj[i2s_num]->mode & I2S_MODE_ADC_BUILT_IN), "i2s built-in adc not enabled", ESP_ERR_INVALID_STATE); - - adc1_dma_mode_acquire(); - _i2s_adc_mode_recover(); - i2s_hal_start_rx(&(p_i2s_obj[i2s_num]->hal)); - i2s_hal_reset(&(p_i2s_obj[i2s_num]->hal)); - return i2s_set_clk(i2s_num, p_i2s_obj[i2s_num]->sample_rate, p_i2s_obj[i2s_num]->bits_per_sample, p_i2s_obj[i2s_num]->channel_num); -} - -esp_err_t i2s_adc_disable(i2s_port_t i2s_num) -{ - I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); - I2S_CHECK((p_i2s_obj[i2s_num] != NULL), "Not initialized yet", ESP_ERR_INVALID_STATE); - I2S_CHECK((p_i2s_obj[i2s_num]->mode & I2S_MODE_ADC_BUILT_IN), "i2s built-in adc not enabled", ESP_ERR_INVALID_STATE); - - i2s_hal_stop_rx(&(p_i2s_obj[i2s_num]->hal)); - adc1_lock_release(); - return ESP_OK; -} -#endif - +/** + * @brief Write data to I2S DMA transmit buffer while expanding the number of bits per sample. For example, expanding 16-bit PCM to 32-bit PCM. + * @note Many ticks pass without space becoming available in the DMA + * transmit buffer, then the function will return (note that if the + * data is written to the DMA buffer in pieces, the overall operation + * may still take longer than this timeout.) Pass portMAX_DELAY for no + * timeout. + * Format of the data in source buffer is determined by the I2S configuration (see i2s_config_t). + * + * @param i2s_num I2S device number + * @param src Source address to write from + * @param size Size of data in bytes + * @param src_bits Source audio bit + * @param aim_bits Bit wanted, no more than 32, and must be greater than src_bits + * @param[out] bytes_written Number of bytes written, if timeout, the result will be less than the size passed in. + * @param ticks_to_wait TX buffer wait timeout in RTOS ticks. If this + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ esp_err_t i2s_write_expand(i2s_port_t i2s_num, const void *src, size_t size, size_t src_bits, size_t aim_bits, size_t *bytes_written, TickType_t ticks_to_wait) { + esp_err_t ret = ESP_OK; char *data_ptr; int bytes_can_write, tail; int src_bytes, aim_bytes, zero_bytes; *bytes_written = 0; - I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); - I2S_CHECK((size > 0), "size must greater than zero", ESP_ERR_INVALID_ARG); - I2S_CHECK((aim_bits * size < SOC_I2S_MAX_BUFFER_SIZE), "size is too large", ESP_ERR_INVALID_ARG); - I2S_CHECK((aim_bits >= src_bits), "aim_bits mustn't be less than src_bits", ESP_ERR_INVALID_ARG); - I2S_CHECK((p_i2s_obj[i2s_num]->tx), "tx NULL", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); + ESP_RETURN_ON_FALSE((size > 0), ESP_ERR_INVALID_ARG, TAG, "size must greater than zero"); + ESP_RETURN_ON_FALSE((aim_bits >= src_bits), ESP_ERR_INVALID_ARG, TAG, "aim_bits mustn't be less than src_bits"); + ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->tx), ESP_ERR_INVALID_ARG, TAG, "TX mode is not enabled"); if (src_bits < I2S_BITS_PER_SAMPLE_8BIT || aim_bits < I2S_BITS_PER_SAMPLE_8BIT) { - ESP_LOGE(I2S_TAG,"bits mustn't be less than 8, src_bits %d aim_bits %d", src_bits, aim_bits); + ESP_LOGE(TAG, "bits mustn't be less than 8, src_bits %d aim_bits %d", src_bits, aim_bits); return ESP_ERR_INVALID_ARG; } if (src_bits > I2S_BITS_PER_SAMPLE_32BIT || aim_bits > I2S_BITS_PER_SAMPLE_32BIT) { - ESP_LOGE(I2S_TAG,"bits mustn't be greater than 32, src_bits %d aim_bits %d", src_bits, aim_bits); + ESP_LOGE(TAG, "bits mustn't be greater than 32, src_bits %d aim_bits %d", src_bits, aim_bits); return ESP_ERR_INVALID_ARG; } if ((src_bits == I2S_BITS_PER_SAMPLE_16BIT || src_bits == I2S_BITS_PER_SAMPLE_32BIT) && (size % 2 != 0)) { - ESP_LOGE(I2S_TAG,"size must be a even number while src_bits is even, src_bits %d size %d", src_bits, size); + ESP_LOGE(TAG, "size must be a even number while src_bits is even, src_bits %d size %d", src_bits, size); return ESP_ERR_INVALID_ARG; } if (src_bits == I2S_BITS_PER_SAMPLE_24BIT && (size % 3 != 0)) { - ESP_LOGE(I2S_TAG,"size must be a multiple of 3 while src_bits is 24, size %d", size); + ESP_LOGE(TAG, "size must be a multiple of 3 while src_bits is 24, size %d", size); return ESP_ERR_INVALID_ARG; } src_bytes = src_bits / 8; aim_bytes = aim_bits / 8; zero_bytes = aim_bytes - src_bytes; - xSemaphoreTake(p_i2s_obj[i2s_num]->tx->mux, (portTickType)portMAX_DELAY); + xSemaphoreTake(p_i2s[i2s_num]->tx->mux, (portTickType)portMAX_DELAY); size = size * aim_bytes / src_bytes; - ESP_LOGD(I2S_TAG,"aim_bytes %d src_bytes %d size %d", aim_bytes, src_bytes, size); + ESP_LOGD(TAG, "aim_bytes %d src_bytes %d size %d", aim_bytes, src_bytes, size); while (size > 0) { - if (p_i2s_obj[i2s_num]->tx->rw_pos == p_i2s_obj[i2s_num]->tx->buf_size || p_i2s_obj[i2s_num]->tx->curr_ptr == NULL) { - if (xQueueReceive(p_i2s_obj[i2s_num]->tx->queue, &p_i2s_obj[i2s_num]->tx->curr_ptr, ticks_to_wait) == pdFALSE) { + if (p_i2s[i2s_num]->tx->rw_pos == p_i2s[i2s_num]->tx->buf_size || p_i2s[i2s_num]->tx->curr_ptr == NULL) { + if (xQueueReceive(p_i2s[i2s_num]->tx->queue, &p_i2s[i2s_num]->tx->curr_ptr, ticks_to_wait) == pdFALSE) { + ret = ESP_ERR_TIMEOUT; break; } - p_i2s_obj[i2s_num]->tx->rw_pos = 0; + p_i2s[i2s_num]->tx->rw_pos = 0; } - data_ptr = (char*)p_i2s_obj[i2s_num]->tx->curr_ptr; - data_ptr += p_i2s_obj[i2s_num]->tx->rw_pos; - bytes_can_write = p_i2s_obj[i2s_num]->tx->buf_size - p_i2s_obj[i2s_num]->tx->rw_pos; + data_ptr = (char *)p_i2s[i2s_num]->tx->curr_ptr; + data_ptr += p_i2s[i2s_num]->tx->rw_pos; + bytes_can_write = p_i2s[i2s_num]->tx->buf_size - p_i2s[i2s_num]->tx->rw_pos; if (bytes_can_write > (int)size) { bytes_can_write = size; } @@ -1154,47 +2182,90 @@ esp_err_t i2s_write_expand(i2s_port_t i2s_num, const void *src, size_t size, siz (*bytes_written) += (aim_bytes - zero_bytes); } size -= bytes_can_write; - p_i2s_obj[i2s_num]->tx->rw_pos += bytes_can_write; + p_i2s[i2s_num]->tx->rw_pos += bytes_can_write; } - xSemaphoreGive(p_i2s_obj[i2s_num]->tx->mux); - return ESP_OK; + xSemaphoreGive(p_i2s[i2s_num]->tx->mux); + return ret; } +/** + * @brief Read data from I2S DMA receive buffer + * @note If the built-in ADC mode is enabled, we should call i2s_adc_enable and i2s_adc_disable around the whole reading process, + * to prevent the data getting corrupted. + * + * @param i2s_num I2S device number + * @param dest Destination address to read into + * @param size Size of data in bytes + * @param[out] bytes_read Number of bytes read, if timeout, bytes read will be less than the size passed in. + * @param ticks_to_wait RX buffer wait timeout in RTOS ticks. If this many ticks pass without bytes becoming available in the DMA receive buffer, then the function will return (note that if data is read from the DMA buffer in pieces, the overall operation may still take longer than this timeout.) Pass portMAX_DELAY for no timeout. + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ esp_err_t i2s_read(i2s_port_t i2s_num, void *dest, size_t size, size_t *bytes_read, TickType_t ticks_to_wait) { + esp_err_t ret = ESP_OK; char *data_ptr, *dest_byte; int bytes_can_read; *bytes_read = 0; dest_byte = (char *)dest; - I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); - I2S_CHECK((size < SOC_I2S_MAX_BUFFER_SIZE), "size is too large", ESP_ERR_INVALID_ARG); - I2S_CHECK((p_i2s_obj[i2s_num]->rx), "rx NULL", ESP_ERR_INVALID_ARG); - xSemaphoreTake(p_i2s_obj[i2s_num]->rx->mux, (portTickType)portMAX_DELAY); + ESP_RETURN_ON_FALSE((i2s_num < I2S_NUM_MAX), ESP_ERR_INVALID_ARG, TAG, "i2s_num error"); + ESP_RETURN_ON_FALSE((p_i2s[i2s_num]->rx), ESP_ERR_INVALID_ARG, TAG, "RX mode is not enabled"); + xSemaphoreTake(p_i2s[i2s_num]->rx->mux, (portTickType)portMAX_DELAY); #ifdef CONFIG_PM_ENABLE - esp_pm_lock_acquire(p_i2s_obj[i2s_num]->pm_lock); + esp_pm_lock_acquire(p_i2s[i2s_num]->pm_lock); #endif while (size > 0) { - if (p_i2s_obj[i2s_num]->rx->rw_pos == p_i2s_obj[i2s_num]->rx->buf_size || p_i2s_obj[i2s_num]->rx->curr_ptr == NULL) { - if (xQueueReceive(p_i2s_obj[i2s_num]->rx->queue, &p_i2s_obj[i2s_num]->rx->curr_ptr, ticks_to_wait) == pdFALSE) { + if (p_i2s[i2s_num]->rx->rw_pos == p_i2s[i2s_num]->rx->buf_size || p_i2s[i2s_num]->rx->curr_ptr == NULL) { + if (xQueueReceive(p_i2s[i2s_num]->rx->queue, &p_i2s[i2s_num]->rx->curr_ptr, ticks_to_wait) == pdFALSE) { + ret = ESP_ERR_TIMEOUT; break; } - p_i2s_obj[i2s_num]->rx->rw_pos = 0; + p_i2s[i2s_num]->rx->rw_pos = 0; } - data_ptr = (char*)p_i2s_obj[i2s_num]->rx->curr_ptr; - data_ptr += p_i2s_obj[i2s_num]->rx->rw_pos; - bytes_can_read = p_i2s_obj[i2s_num]->rx->buf_size - p_i2s_obj[i2s_num]->rx->rw_pos; + data_ptr = (char *)p_i2s[i2s_num]->rx->curr_ptr; + data_ptr += p_i2s[i2s_num]->rx->rw_pos; + bytes_can_read = p_i2s[i2s_num]->rx->buf_size - p_i2s[i2s_num]->rx->rw_pos; if (bytes_can_read > (int)size) { bytes_can_read = size; } memcpy(dest_byte, data_ptr, bytes_can_read); size -= bytes_can_read; dest_byte += bytes_can_read; - p_i2s_obj[i2s_num]->rx->rw_pos += bytes_can_read; + p_i2s[i2s_num]->rx->rw_pos += bytes_can_read; (*bytes_read) += bytes_can_read; } #ifdef CONFIG_PM_ENABLE - esp_pm_lock_release(p_i2s_obj[i2s_num]->pm_lock); + esp_pm_lock_release(p_i2s[i2s_num]->pm_lock); #endif - xSemaphoreGive(p_i2s_obj[i2s_num]->rx->mux); - return ESP_OK; + xSemaphoreGive(p_i2s[i2s_num]->rx->mux); + return ret; +} + +esp_err_t i2s_priv_register_object(void *driver_obj, int port_id) +{ + esp_err_t ret = ESP_ERR_NOT_FOUND; + ESP_RETURN_ON_FALSE(driver_obj && (port_id < SOC_I2S_NUM), ESP_ERR_INVALID_ARG, TAG, "invalid arguments"); + portENTER_CRITICAL(&i2s_platform_spinlock); + if (!p_i2s[port_id]) { + ret = ESP_OK; + p_i2s[port_id] = driver_obj; + periph_module_enable(i2s_periph_signal[port_id].module); + } + portEXIT_CRITICAL(&i2s_platform_spinlock); + return ret; +} + +esp_err_t i2s_priv_deregister_object(int port_id) +{ + esp_err_t ret = ESP_ERR_INVALID_STATE; + ESP_RETURN_ON_FALSE(port_id < SOC_I2S_NUM, ESP_ERR_INVALID_ARG, TAG, "invalid arguments"); + portENTER_CRITICAL(&i2s_platform_spinlock); + if (p_i2s[port_id]) { + ret = ESP_OK; + p_i2s[port_id] = NULL; + periph_module_disable(i2s_periph_signal[port_id].module); + } + portEXIT_CRITICAL(&i2s_platform_spinlock); + return ret; } diff --git a/components/driver/include/driver/i2s.h b/components/driver/include/driver/i2s.h index 4ee73b594d..aa649ed479 100644 --- a/components/driver/include/driver/i2s.h +++ b/components/driver/include/driver/i2s.h @@ -13,12 +13,11 @@ #include "soc/i2s_periph.h" #include "soc/rtc_periph.h" #include "soc/soc_caps.h" -#include "hal/i2s_hal.h" #include "hal/i2s_types.h" #include "driver/periph_ctrl.h" #include "esp_intr_alloc.h" -#if SOC_I2S_SUPPORTS_ADC_DAC +#if SOC_I2S_SUPPORTS_ADC #include "driver/adc.h" #endif @@ -28,7 +27,119 @@ extern "C" { #define I2S_PIN_NO_CHANGE (-1) /*!< Use in i2s_pin_config_t for pins which should not be changed */ -typedef intr_handle_t i2s_isr_handle_t; +/** + * @brief I2S port number, the max port number is (I2S_NUM_MAX -1). + */ +typedef enum { + I2S_NUM_0 = 0, /*!< I2S port 0 */ +#if SOC_I2S_NUM > 1 + I2S_NUM_1 = 1, /*!< I2S port 1 */ +#endif + I2S_NUM_MAX, /*!< I2S port max */ +} i2s_port_t; + +#if SOC_I2S_SUPPORTS_PCM +/** + * @brief I2S PCM configuration + * + */ +typedef struct { + i2s_pcm_compress_t pcm_type; /*!< I2S PCM a/u-law decompress or compress type */ +} i2s_pcm_cfg_t; +#endif + +#if SOC_I2S_SUPPORTS_PDM_TX +/** + * @brief Default I2S PDM Up-Sampling Rate configuration + */ +#define I2S_PDM_DEFAULT_UPSAMPLE_CONFIG(rate) { \ + .sample_rate = rate, \ + .fp = 960, \ + .fs = (rate) / 100, \ + } + +/** + * @brief I2S PDM up-sample rate configuration + * @note TX PDM can only be set to the following two upsampling rate configurations: + * 1: fp = 960, fs = sample_rate / 100, in this case, Fpdm = 128*48000 + * 2: fp = 960, fs = 480, in this case, Fpdm = 128*Fpcm = 128*sample_rate + * If the pdm receiver do not care the pdm serial clock, it's recommended set Fpdm = 128*48000. + * Otherwise, the second configuration should be applied. + */ +typedef struct { + int sample_rate; /*!< I2S PDM sample rate */ + int fp; /*!< I2S PDM TX upsampling paramater. Normally it should be set to 960 */ + int fs; /*!< I2S PDM TX upsampling paramater. When it is set to 480, the pdm clock frequency Fpdm = 128 * sample_rate, when it is set to sample_rate / 100, Fpdm will be fixed to 128*48000 */ +} i2s_pdm_tx_upsample_cfg_t; +#endif + +/** + * @brief I2S pin number for i2s_set_pin + * + */ +typedef struct { + int mck_io_num; /*!< MCK in out pin*/ + int bck_io_num; /*!< BCK in out pin*/ + int ws_io_num; /*!< WS in out pin*/ + int data_out_num; /*!< DATA out pin*/ + int data_in_num; /*!< DATA in pin*/ +} i2s_pin_config_t; + +/** + * @brief I2S driver configuration parameters + * + */ +typedef struct { + + i2s_mode_t mode; /*!< I2S work mode */ + uint32_t sample_rate; /*!< I2S sample rate */ + i2s_bits_per_sample_t bits_per_sample; /*!< I2S sample bits in one channel */ + i2s_channel_fmt_t channel_format; /*!< I2S channel format.*/ + i2s_comm_format_t communication_format; /*!< I2S communication format */ + int intr_alloc_flags; /*!< Flags used to allocate the interrupt. One or multiple (ORred) ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info */ + int dma_buf_count; /*!< I2S DMA Buffer Count */ + int dma_buf_len; /*!< I2S DMA Buffer Length */ + bool use_apll; /*!< I2S using APLL as main I2S clock, enable it to get accurate clock */ + bool tx_desc_auto_clear; /*!< I2S auto clear tx descriptor if there is underflow condition (helps in avoiding noise in case of data unavailability) */ + int fixed_mclk; /*!< I2S using fixed MCLK output. If use_apll = true and fixed_mclk > 0, then the clock output for i2s is fixed and equal to the fixed_mclk value. If fixed_mclk set, mclk_multiple won't take effect */ + i2s_mclk_multiple_t mclk_multiple; /*!< The multiple of I2S master clock(MCLK) to sample rate */ + i2s_bits_per_chan_t bits_per_chan; /*!< I2S total bits in one channel, only take effect when larger than 'bits_per_sample', default '0' means equal to 'bits_per_sample' */ + +#if SOC_I2S_SUPPORTS_TDM + i2s_channel_t chan_mask; /*!< I2S active channel bit mask, set value in `i2s_channel_t` to enable specific channel, the bit map of active channel can not exceed (0x1< 4 + PCNT_UNIT_4, /*!< PCNT unit 4 */ + PCNT_UNIT_5, /*!< PCNT unit 5 */ + PCNT_UNIT_6, /*!< PCNT unit 6 */ + PCNT_UNIT_7, /*!< PCNT unit 7 */ +#endif + PCNT_UNIT_MAX, +} pcnt_unit_t; + +/** + * @brief Selection of channels available for a single PCNT unit + */ +typedef enum { + PCNT_CHANNEL_0, /*!< PCNT channel 0 */ + PCNT_CHANNEL_1, /*!< PCNT channel 1 */ + PCNT_CHANNEL_MAX, +} pcnt_channel_t; + +/** + * @brief Selection of counter's events the may trigger an interrupt + */ +typedef enum { + PCNT_EVT_THRES_1 = 1 << 2, /*!< PCNT watch point event: threshold1 value event */ + PCNT_EVT_THRES_0 = 1 << 3, /*!< PCNT watch point event: threshold0 value event */ + PCNT_EVT_L_LIM = 1 << 4, /*!< PCNT watch point event: Minimum counter value */ + PCNT_EVT_H_LIM = 1 << 5, /*!< PCNT watch point event: Maximum counter value */ + PCNT_EVT_ZERO = 1 << 6, /*!< PCNT watch point event: counter value zero event */ + PCNT_EVT_MAX +} pcnt_evt_type_t; + +/** + * @brief Selection of available modes that determine the counter's action depending on the state of the control signal's input GPIO + * @note Configuration covers two actions, one for high, and one for low level on the control input + */ +typedef pcnt_channel_level_action_t pcnt_ctrl_mode_t; +#define PCNT_MODE_KEEP PCNT_CHANNEL_LEVEL_ACTION_KEEP /*!< Control mode: won't change counter mode*/ +#define PCNT_MODE_REVERSE PCNT_CHANNEL_LEVEL_ACTION_INVERSE /*!< Control mode: invert counter mode(increase -> decrease, decrease -> increase) */ +#define PCNT_MODE_DISABLE PCNT_CHANNEL_LEVEL_ACTION_HOLD /*!< Control mode: Inhibit counter(counter value will not change in this condition) */ +#define PCNT_MODE_MAX 3 + +/** + * @brief Selection of available modes that determine the counter's action on the edge of the pulse signal's input GPIO + * @note Configuration covers two actions, one for positive, and one for negative edge on the pulse input + */ +typedef pcnt_channel_edge_action_t pcnt_count_mode_t; +#define PCNT_COUNT_DIS PCNT_CHANNEL_EDGE_ACTION_HOLD /*!< Counter mode: Inhibit counter(counter value will not change in this condition) */ +#define PCNT_COUNT_INC PCNT_CHANNEL_EDGE_ACTION_INCREASE /*!< Counter mode: Increase counter value */ +#define PCNT_COUNT_DEC PCNT_CHANNEL_EDGE_ACTION_DECREASE /*!< Counter mode: Decrease counter value */ +#define PCNT_COUNT_MAX 3 + +/** + * @brief Pulse Counter configuration for a single channel + */ +typedef struct { + int pulse_gpio_num; /*!< Pulse input GPIO number, if you want to use GPIO16, enter pulse_gpio_num = 16, a negative value will be ignored */ + int ctrl_gpio_num; /*!< Control signal input GPIO number, a negative value will be ignored */ + pcnt_ctrl_mode_t lctrl_mode; /*!< PCNT low control mode */ + pcnt_ctrl_mode_t hctrl_mode; /*!< PCNT high control mode */ + pcnt_count_mode_t pos_mode; /*!< PCNT positive edge count mode */ + pcnt_count_mode_t neg_mode; /*!< PCNT negative edge count mode */ + int16_t counter_h_lim; /*!< Maximum counter value */ + int16_t counter_l_lim; /*!< Minimum counter value */ + pcnt_unit_t unit; /*!< PCNT unit number */ + pcnt_channel_t channel; /*!< the PCNT channel */ +} pcnt_config_t; + /** * @brief Configure Pulse Counter unit * @note @@ -173,7 +257,6 @@ esp_err_t pcnt_get_event_value(pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16 * @param unit PCNT unit number * @param status Pointer to accept event status word * @return - * * - ESP_OK Success * - ESP_ERR_INVALID_STATE pcnt driver has not been initialized * - ESP_ERR_INVALID_ARG Parameter error @@ -363,42 +446,6 @@ void pcnt_isr_service_uninstall(void); */ esp_err_t pcnt_isr_handler_remove(pcnt_unit_t unit); -/** - * @addtogroup pcnt-examples - * - * @{ - * - * EXAMPLE OF PCNT CONFIGURATION - * ============================== - * @code{c} - * //1. Config PCNT unit - * pcnt_config_t pcnt_config = { - * .pulse_gpio_num = 4, //set gpio4 as pulse input gpio - * .ctrl_gpio_num = 5, //set gpio5 as control gpio - * .channel = PCNT_CHANNEL_0, //use unit 0 channel 0 - * .lctrl_mode = PCNT_MODE_REVERSE, //when control signal is low, reverse the primary counter mode(inc->dec/dec->inc) - * .hctrl_mode = PCNT_MODE_KEEP, //when control signal is high, keep the primary counter mode - * .pos_mode = PCNT_COUNT_INC, //increment the counter - * .neg_mode = PCNT_COUNT_DIS, //keep the counter value - * .counter_h_lim = 10, - * .counter_l_lim = -10, - * }; - * pcnt_unit_config(&pcnt_config); //init unit - * @endcode - * - * EXAMPLE OF PCNT EVENT SETTING - * ============================== - * @code{c} - * //2. Configure PCNT watchpoint event. - * pcnt_set_event_value(PCNT_UNIT_0, PCNT_EVT_THRES_1, 5); //set thres1 value - * pcnt_event_enable(PCNT_UNIT_0, PCNT_EVT_THRES_1); //enable thres1 event - * @endcode - * - * For more examples please refer to PCNT example code in IDF_PATH/examples - * - * @} - */ - #ifdef __cplusplus } #endif diff --git a/components/driver/include/driver/rmt.h b/components/driver/include/driver/rmt.h index a7e2aad5f2..bc07954a08 100644 --- a/components/driver/include/driver/rmt.h +++ b/components/driver/include/driver/rmt.h @@ -856,16 +856,35 @@ esp_err_t rmt_remove_channel_from_group(rmt_channel_t channel); #if SOC_RMT_SUPPORT_TX_LOOP_COUNT /** - * @brief Set loop count for RMT TX channel + * @brief Set loop count threshold value for RMT TX channel + * + * When tx loop count reaches this value, an ISR callback will notify user * * @param channel RMT channel - * @param count loop count + * @param count loop count, 1 ~ 1023 * @return * - ESP_ERR_INVALID_ARG Parameter error * - ESP_OK Success */ esp_err_t rmt_set_tx_loop_count(rmt_channel_t channel, uint32_t count); -#endif + +/** + * @brief Enable or disable the feature that when loop count reaches the threshold, RMT will stop transmitting. + * + * - When the loop auto-stop feature is enabled will halt RMT transmission after the loop count reaches a certain threshold + * - When disabled, the RMT transmission continue indefinitely until halted by the users + * + * @note The auto-stop feature is implemented in hardware on particular targets (i.e. those with SOC_RMT_SUPPORT_TX_LOOP_AUTOSTOP defined). + * Otherwise, the auto-stop feature is implemented in software via the interrupt. + * + * @param channel RMT channel + * @param en enable bit + * @return + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_OK Success + */ +esp_err_t rmt_enable_tx_loop_autostop(rmt_channel_t channel, bool en); +#endif // SOC_RMT_SUPPORT_TX_LOOP_COUNT /** * @brief Reset RMT TX/RX memory index. diff --git a/components/driver/include/driver/spi_common.h b/components/driver/include/driver/spi_common.h index f6b12255a5..830b8efd8c 100644 --- a/components/driver/include/driver/spi_common.h +++ b/components/driver/include/driver/spi_common.h @@ -63,7 +63,8 @@ extern "C" #define SPICOMMON_BUSFLAG_DUAL (1<<6) ///< Check MOSI and MISO pins can output. Or indicates bus able to work under DIO mode. #define SPICOMMON_BUSFLAG_WPHD (1<<7) ///< Check existing of WP and HD pins. Or indicates WP & HD pins initialized. #define SPICOMMON_BUSFLAG_QUAD (SPICOMMON_BUSFLAG_DUAL|SPICOMMON_BUSFLAG_WPHD) ///< Check existing of MOSI/MISO/WP/HD pins as output. Or indicates bus able to work under QIO mode. - +#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 /** @@ -95,18 +96,34 @@ typedef spi_common_dma_t spi_dma_chan_t; * @note Be advised that the slave driver does not use the quadwp/quadhd lines and fields in spi_bus_config_t refering to these lines will be ignored and can thus safely be left uninitialized. */ typedef struct { - int mosi_io_num; ///< GPIO pin for Master Out Slave In (=spi_d) signal, or -1 if not used. - int miso_io_num; ///< GPIO pin for Master In Slave Out (=spi_q) signal, or -1 if not used. - int sclk_io_num; ///< GPIO pin for Spi CLocK signal, or -1 if not used. - int quadwp_io_num; ///< GPIO pin for WP (Write Protect) signal which is used as D2 in 4-bit communication modes, or -1 if not used. - int quadhd_io_num; ///< GPIO pin for HD (HolD) signal which is used as D3 in 4-bit communication modes, or -1 if not used. - int max_transfer_sz; ///< Maximum transfer size, in bytes. Defaults to 4092 if 0 when DMA enabled, or to `SOC_SPI_MAXIMUM_BUFFER_SIZE` if DMA is disabled. - uint32_t flags; ///< Abilities of bus to be checked by the driver. Or-ed value of ``SPICOMMON_BUSFLAG_*`` flags. - int intr_flags; /**< Interrupt flag for the bus to set the priority, and IRAM attribute, see - * ``esp_intr_alloc.h``. Note that the EDGE, INTRDISABLED attribute are ignored - * by the driver. Note that if ESP_INTR_FLAG_IRAM is set, ALL the callbacks of - * the driver, and their callee functions, should be put in the IRAM. - */ + union { + int mosi_io_num; ///< GPIO pin for Master Out Slave In (=spi_d) signal, or -1 if not used. + int data0_io_num; ///< GPIO pin for spi data0 signal in quad/octal mode, or -1 if not used. + }; + union { + int miso_io_num; ///< GPIO pin for Master In Slave Out (=spi_q) signal, or -1 if not used. + int data1_io_num; ///< GPIO pin for spi data1 signal in quad/octal mode, or -1 if not used. + }; + int sclk_io_num; ///< GPIO pin for SPI Clock signal, or -1 if not used. + union { + int quadwp_io_num; ///< GPIO pin for WP (Write Protect) signal, or -1 if not used. + int data2_io_num; ///< GPIO pin for spi data2 signal in quad/octal mode, or -1 if not used. + }; + union { + int quadhd_io_num; ///< GPIO pin for HD (Hold) signal, or -1 if not used. + int data3_io_num; ///< GPIO pin for spi data3 signal in quad/octal mode, or -1 if not used. + }; + int data4_io_num; ///< GPIO pin for spi data4 signal in octal mode, or -1 if not used. + int data5_io_num; ///< GPIO pin for spi data5 signal in octal mode, or -1 if not used. + int data6_io_num; ///< GPIO pin for spi data6 signal in octal mode, or -1 if not used. + int data7_io_num; ///< GPIO pin for spi data7 signal in octal mode, or -1 if not used. + int max_transfer_sz; ///< Maximum transfer size, in bytes. Defaults to 4092 if 0 when DMA enabled, or to `SOC_SPI_MAXIMUM_BUFFER_SIZE` if DMA is disabled. + uint32_t flags; ///< Abilities of bus to be checked by the driver. Or-ed value of ``SPICOMMON_BUSFLAG_*`` flags. + int intr_flags; /**< Interrupt flag for the bus to set the priority, and IRAM attribute, see + * ``esp_intr_alloc.h``. Note that the EDGE, INTRDISABLED attribute are ignored + * by the driver. Note that if ESP_INTR_FLAG_IRAM is set, ALL the callbacks of + * the driver, and their callee functions, should be put in the IRAM. + */ } spi_bus_config_t; diff --git a/components/driver/include/driver/spi_common_internal.h b/components/driver/include/driver/spi_common_internal.h index 31baaa75d7..90826c0a8e 100644 --- a/components/driver/include/driver/spi_common_internal.h +++ b/components/driver/include/driver/spi_common_internal.h @@ -155,6 +155,8 @@ esp_err_t spicommon_slave_free_dma(spi_host_device_t host_id); * - ``SPICOMMON_BUSFLAG_DUAL``: Make sure both MISO and MOSI are output capable so that DIO mode is capable. * - ``SPICOMMON_BUSFLAG_WPHD`` Make sure WP and HD are set to valid output GPIOs. * - ``SPICOMMON_BUSFLAG_QUAD``: Combination of ``SPICOMMON_BUSFLAG_DUAL`` and ``SPICOMMON_BUSFLAG_WPHD``. + * - ``SPICOMMON_BUSFLAG_IO4_IO7``: Make sure spi data4 ~ spi data7 are set to valid output GPIOs. + * - ``SPICOMMON_BUSFLAG_OCTAL``: Combination of ``SPICOMMON_BUSFLAG_QUAL`` and ``SPICOMMON_BUSFLAG_IO4_IO7``. * @param[out] flags_o A SPICOMMON_BUSFLAG_* flag combination of bus abilities will be written to this address. * Leave to NULL if not needed. * - ``SPICOMMON_BUSFLAG_IOMUX_PINS``: The bus is connected to iomux pins. @@ -163,6 +165,8 @@ esp_err_t spicommon_slave_free_dma(spi_host_device_t host_id); * - ``SPICOMMON_BUSFLAG_DUAL``: The bus is capable with DIO mode. * - ``SPICOMMON_BUSFLAG_WPHD`` The bus has WP and HD connected. * - ``SPICOMMON_BUSFLAG_QUAD``: Combination of ``SPICOMMON_BUSFLAG_DUAL`` and ``SPICOMMON_BUSFLAG_WPHD``. + * - ``SPICOMMON_BUSFLAG_IO4_IO7``: The bus has spi data4 ~ spi data7 connected. + * - ``SPICOMMON_BUSFLAG_OCTAL``: Combination of ``SPICOMMON_BUSFLAG_QUAL`` and ``SPICOMMON_BUSFLAG_IO4_IO7``. * @return * - ESP_ERR_INVALID_ARG if parameter is invalid * - ESP_OK on success diff --git a/components/driver/include/driver/spi_master.h b/components/driver/include/driver/spi_master.h index 8582a33276..d6a202f848 100644 --- a/components/driver/include/driver/spi_master.h +++ b/components/driver/include/driver/spi_master.h @@ -104,8 +104,11 @@ typedef struct { #define SPI_TRANS_VARIABLE_CMD (1<<5) ///< Use the ``command_bits`` in ``spi_transaction_ext_t`` rather than default value in ``spi_device_interface_config_t``. #define SPI_TRANS_VARIABLE_ADDR (1<<6) ///< Use the ``address_bits`` in ``spi_transaction_ext_t`` rather than default value in ``spi_device_interface_config_t``. #define SPI_TRANS_VARIABLE_DUMMY (1<<7) ///< Use the ``dummy_bits`` in ``spi_transaction_ext_t`` rather than default value in ``spi_device_interface_config_t``. -#define SPI_TRANS_SET_CD (1<<7) ///< Set the CD pin #define SPI_TRANS_CS_KEEP_ACTIVE (1<<8) ///< Keep CS active after data transfer +#define SPI_TRANS_MULTILINE_CMD (1<<9) ///< The data lines used at command phase is the same as data phase (otherwise, only one data line is used at command phase) +#define SPI_TRANS_MODE_OCT (1<<10) ///< Transmit/receive data in 8-bit mode +#define SPI_TRANS_MULTILINE_ADDR SPI_TRANS_MODE_DIOQIO_ADDR ///< The data lines used at address phase is the same as data phase (otherwise, only one data line is used at address phase) + /** * This structure describes one SPI transaction. The descriptor should not be modified until the transaction finishes. */ @@ -148,7 +151,7 @@ typedef struct { } spi_transaction_ext_t ; -typedef struct spi_device_t* spi_device_handle_t; ///< Handle for a device on a SPI bus +typedef struct spi_device_t *spi_device_handle_t; ///< Handle for a device on a SPI bus /** * @brief Allocate a device on a SPI bus * @@ -341,7 +344,7 @@ void spi_device_release_bus(spi_device_handle_t dev); * * @return Actual working frequency that most fit. */ -int spi_cal_clock(int fapb, int hz, int duty_cycle, uint32_t* reg_o) __attribute__((deprecated)); +int spi_cal_clock(int fapb, int hz, int duty_cycle, uint32_t *reg_o) __attribute__((deprecated)); /** * @brief Calculate the working frequency that is most close to desired frequency. @@ -368,7 +371,7 @@ int spi_get_actual_clock(int fapb, int hz, int duty_cycle); * * @note If **dummy_o* is not zero, it means dummy bits should be applied in half duplex mode, and full duplex mode may not work. */ -void spi_get_timing(bool gpio_is_used, int input_delay_ns, int eff_clk, int* dummy_o, int* cycles_remain_o); +void spi_get_timing(bool gpio_is_used, int input_delay_ns, int eff_clk, int *dummy_o, int *cycles_remain_o); /** * @brief Get the frequency limit of current configurations. diff --git a/components/driver/include/driver/timer.h b/components/driver/include/driver/timer.h index 204fc9db27..a3ab39267c 100644 --- a/components/driver/include/driver/timer.h +++ b/components/driver/include/driver/timer.h @@ -130,8 +130,9 @@ esp_err_t timer_set_counter_mode(timer_group_t group_num, timer_idx_t timer_num, esp_err_t timer_set_auto_reload(timer_group_t group_num, timer_idx_t timer_num, timer_autoreload_t reload); /** - * @brief Set hardware timer source clock divider. Timer groups clock are divider from APB clock. - * + * @brief Set hardware divider of the source clock to the timer group. + * By default, the source clock is APB clock running at 80 MHz. + * For more information, please check Chapter Reset and Clock in Chip Technical Reference Manual. * @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1 * @param timer_num Timer index, 0 for hw_timer[0] & 1 for hw_timer[1] * @param divider Timer clock divider value. The divider's range is from from 2 to 65536. diff --git a/components/driver/include/driver/twai.h b/components/driver/include/driver/twai.h index ce616fe125..70f88a4da1 100644 --- a/components/driver/include/driver/twai.h +++ b/components/driver/include/driver/twai.h @@ -47,23 +47,24 @@ extern "C" { */ #define TWAI_ALERT_TX_IDLE 0x00000001 /**< Alert(1): No more messages to transmit */ #define TWAI_ALERT_TX_SUCCESS 0x00000002 /**< Alert(2): The previous transmission was successful */ -#define TWAI_ALERT_BELOW_ERR_WARN 0x00000004 /**< Alert(4): Both error counters have dropped below error warning limit */ -#define TWAI_ALERT_ERR_ACTIVE 0x00000008 /**< Alert(8): TWAI controller has become error active */ -#define TWAI_ALERT_RECOVERY_IN_PROGRESS 0x00000010 /**< Alert(16): TWAI controller is undergoing bus recovery */ -#define TWAI_ALERT_BUS_RECOVERED 0x00000020 /**< Alert(32): TWAI controller has successfully completed bus recovery */ -#define TWAI_ALERT_ARB_LOST 0x00000040 /**< Alert(64): The previous transmission lost arbitration */ -#define TWAI_ALERT_ABOVE_ERR_WARN 0x00000080 /**< Alert(128): One of the error counters have exceeded the error warning limit */ -#define TWAI_ALERT_BUS_ERROR 0x00000100 /**< Alert(256): A (Bit, Stuff, CRC, Form, ACK) error has occurred on the bus */ -#define TWAI_ALERT_TX_FAILED 0x00000200 /**< Alert(512): The previous transmission has failed (for single shot transmission) */ -#define TWAI_ALERT_RX_QUEUE_FULL 0x00000400 /**< Alert(1024): The RX queue is full causing a frame to be lost */ -#define TWAI_ALERT_ERR_PASS 0x00000800 /**< Alert(2048): TWAI controller has become error passive */ -#define TWAI_ALERT_BUS_OFF 0x00001000 /**< Alert(4096): Bus-off condition occurred. TWAI controller can no longer influence bus */ -#define TWAI_ALERT_RX_FIFO_OVERRUN 0x00002000 /**< Alert(8192): An RX FIFO overrun has occurred */ -#define TWAI_ALERT_TX_RETRIED 0x00004000 /**< Alert(16384): An message transmission was cancelled and retried due to an errata workaround */ -#define TWAI_ALERT_PERIPH_RESET 0x00008000 /**< Alert(32768): The TWAI controller was reset */ -#define TWAI_ALERT_ALL 0x0000FFFF /**< Bit mask to enable all alerts during configuration */ +#define TWAI_ALERT_RX_DATA 0x00000004 /**< Alert(4): A frame has been received and added to the RX queue */ +#define TWAI_ALERT_BELOW_ERR_WARN 0x00000008 /**< Alert(8): Both error counters have dropped below error warning limit */ +#define TWAI_ALERT_ERR_ACTIVE 0x00000010 /**< Alert(16): TWAI controller has become error active */ +#define TWAI_ALERT_RECOVERY_IN_PROGRESS 0x00000020 /**< Alert(32): TWAI controller is undergoing bus recovery */ +#define TWAI_ALERT_BUS_RECOVERED 0x00000040 /**< Alert(64): TWAI controller has successfully completed bus recovery */ +#define TWAI_ALERT_ARB_LOST 0x00000080 /**< Alert(128): The previous transmission lost arbitration */ +#define TWAI_ALERT_ABOVE_ERR_WARN 0x00000100 /**< Alert(256): One of the error counters have exceeded the error warning limit */ +#define TWAI_ALERT_BUS_ERROR 0x00000200 /**< Alert(512): A (Bit, Stuff, CRC, Form, ACK) error has occurred on the bus */ +#define TWAI_ALERT_TX_FAILED 0x00000400 /**< Alert(1024): The previous transmission has failed (for single shot transmission) */ +#define TWAI_ALERT_RX_QUEUE_FULL 0x00000800 /**< Alert(2048): The RX queue is full causing a frame to be lost */ +#define TWAI_ALERT_ERR_PASS 0x00001000 /**< Alert(4096): TWAI controller has become error passive */ +#define TWAI_ALERT_BUS_OFF 0x00002000 /**< Alert(8192): Bus-off condition occurred. TWAI controller can no longer influence bus */ +#define TWAI_ALERT_RX_FIFO_OVERRUN 0x00004000 /**< Alert(16384): An RX FIFO overrun has occurred */ +#define TWAI_ALERT_TX_RETRIED 0x00008000 /**< Alert(32768): An message transmission was cancelled and retried due to an errata workaround */ +#define TWAI_ALERT_PERIPH_RESET 0x00010000 /**< Alert(65536): The TWAI controller was reset */ +#define TWAI_ALERT_ALL 0x0001FFFF /**< Bit mask to enable all alerts during configuration */ #define TWAI_ALERT_NONE 0x00000000 /**< Bit mask to disable all alerts during configuration */ -#define TWAI_ALERT_AND_LOG 0x00010000 /**< Bit mask to enable alerts to also be logged when they occur. Note that logging from the ISR is disabled if CONFIG_TWAI_ISR_IN_IRAM is enabled (see docs). */ +#define TWAI_ALERT_AND_LOG 0x00020000 /**< Bit mask to enable alerts to also be logged when they occur. Note that logging from the ISR is disabled if CONFIG_TWAI_ISR_IN_IRAM is enabled (see docs). */ /** @endcond */ diff --git a/components/driver/include/driver/uart.h b/components/driver/include/driver/uart.h index 311f21a833..76aa424fa2 100644 --- a/components/driver/include/driver/uart.h +++ b/components/driver/include/driver/uart.h @@ -28,7 +28,10 @@ extern "C" { #endif #define UART_NUM_MAX (SOC_UART_NUM) /*!< UART port max */ -#define UART_PIN_NO_CHANGE (-1) /*!< Constant for uart_set_pin function which indicates that UART pin should not be changed */ +/* @brief When calling `uart_set_pin`, instead of GPIO number, `UART_PIN_NO_CHANGE` + * can be provided to keep the currently allocated pin. + */ +#define UART_PIN_NO_CHANGE (-1) #define UART_FIFO_LEN SOC_UART_FIFO_LEN ///< Length of the UART HW FIFO #define UART_BITRATE_MAX SOC_UART_BITRATE_MAX ///< Maximum configurable bitrate @@ -380,14 +383,23 @@ esp_err_t uart_isr_register(uart_port_t uart_num, void (*fn)(void*), void * arg, esp_err_t uart_isr_free(uart_port_t uart_num); /** - * @brief Set UART pin number + * @brief Assign signals of a UART peripheral to GPIO pins + * + * @note If the GPIO number configured for a UART signal matches one of the + * IOMUX signals for that GPIO, the signal will be connected directly + * via the IOMUX. Otherwise the GPIO and signal will be connected via + * the GPIO Matrix. For example, if on an ESP32 the call + * `uart_set_pin(0, 1, 3, -1, -1)` is performed, as GPIO1 is UART0's + * default TX pin and GPIO3 is UART0's default RX pin, both will be + * connected to respectively U0TXD and U0RXD through the IOMUX, totally + * bypassing the GPIO matrix. + * The check is performed on a per-pin basis. Thus, it is possible to have + * RX pin binded to a GPIO through the GPIO matrix, whereas TX is binded + * to its GPIO through the IOMUX. * * @note Internal signal can be output to multiple GPIO pads. * Only one GPIO pad can connect with input signal. * - * @note Instead of GPIO number a macro 'UART_PIN_NO_CHANGE' may be provided - to keep the currently allocated pin. - * * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). * @param tx_io_num UART TX pin GPIO number. * @param rx_io_num UART RX pin GPIO number. diff --git a/components/driver/include/esp_private/i2s_platform.h b/components/driver/include/esp_private/i2s_platform.h new file mode 100644 index 0000000000..ff1ebdf17a --- /dev/null +++ b/components/driver/include/esp_private/i2s_platform.h @@ -0,0 +1,48 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// DO NOT USE THESE APIS IN YOUR APPLICATIONS +// The following APIs are for internal use, public to other IDF components, but not for users' applications. + +#pragma once + +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Register an I2S or I2S variant driver object to platform + * + * @note This private API is used to avoid applications from using the same I2S instance for different purpose. + * @note This function will help enable the peripheral APB clock as well. + * + * @param driver_obj Driver object + * @param port_id I2S port number + * @return + * - ESP_OK: The specific I2S port is free and register the new device object successfully + * - ESP_ERR_INVALID_ARG: Invalid argument, e.g. wrong port_id + * - ESP_ERR_NOT_FOUND: Specific I2S port is not available + */ +esp_err_t i2s_priv_register_object(void *driver_obj, int port_id); + +/** + * @brief Deregister I2S or I2S variant driver object from platform + * + * @note This function will help disable the peripheral APB clock as well. + * + * @param port_id I2S port number + * @return + * - ESP_OK: Deregister I2S port successfully (i.e. that I2S port can used used by other users after this function returns) + * - ESP_ERR_INVALID_ARG: Invalid argument, e.g. wrong port_id + * - ESP_ERR_INVALID_STATE: Specific I2S port is free already + */ +esp_err_t i2s_priv_deregister_object(int port_id); + +#ifdef __cplusplus +} +#endif diff --git a/components/driver/ledc.c b/components/driver/ledc.c index ef0535b89d..6d82554795 100644 --- a/components/driver/ledc.c +++ b/components/driver/ledc.c @@ -22,8 +22,8 @@ static const char* LEDC_TAG = "ledc"; -#define LEDC_CHECK(a, str, ret_val) ESP_RETURN_ON_FALSE(a, ret_val, LEDC_TAG, "%s", str); -#define LEDC_ARG_CHECK(a, param) ESP_RETURN_ON_FALSE(a, ESP_ERR_INVALID_ARG, LEDC_TAG, param " argument is invalid"); +#define LEDC_CHECK(a, str, ret_val) ESP_RETURN_ON_FALSE(a, ret_val, LEDC_TAG, "%s", str) +#define LEDC_ARG_CHECK(a, param) ESP_RETURN_ON_FALSE(a, ESP_ERR_INVALID_ARG, LEDC_TAG, param " argument is invalid") typedef struct { ledc_mode_t speed_mode; diff --git a/components/driver/mcpwm.c b/components/driver/mcpwm.c index 4eb884b647..d4cb02cd28 100644 --- a/components/driver/mcpwm.c +++ b/components/driver/mcpwm.c @@ -34,6 +34,15 @@ static const char *TAG = "mcpwm"; #define MCPWM_GPIO_ERROR "MCPWM GPIO NUM ERROR" #define MCPWM_GEN_ERROR "MCPWM GENERATOR ERROR" #define MCPWM_DT_ERROR "MCPWM DEADTIME TYPE ERROR" +#define MCPWM_CAP_EXIST_ERROR "MCPWM USER CAP INT SERVICE ALREADY EXISTS" + +#ifdef CONFIG_MCPWM_ISR_IN_IRAM +#define MCPWM_ISR_ATTR IRAM_ATTR +#define MCPWM_INTR_FLAG (ESP_INTR_FLAG_IRAM) +#else +#define MCPWM_ISR_ATTR +#define MCPWM_INTR_FLAG 0 +#endif #define MCPWM_GROUP_CLK_PRESCALE (16) #define MCPWM_GROUP_CLK_HZ (SOC_MCPWM_BASE_CLK_HZ / MCPWM_GROUP_CLK_PRESCALE) @@ -61,27 +70,42 @@ _Static_assert(SOC_MCPWM_GENERATORS_PER_OPERATOR == 2, "This driver assumes the ESP_RETURN_ON_FALSE((gen) < MCPWM_GEN_MAX, ESP_ERR_INVALID_ARG, TAG, MCPWM_GEN_ERROR); \ } while (0) +typedef struct { + cap_isr_cb_t fn; // isr function + void *args; // isr function args +} cap_isr_func_t; + typedef struct { mcpwm_hal_context_t hal; portMUX_TYPE spinlock; + _lock_t mutex_lock; + const int group_id; int group_pre_scale; // starts from 1, not 0. will be subtracted by 1 in ll driver int timer_pre_scale[SOC_MCPWM_TIMERS_PER_GROUP]; // same as above + intr_handle_t mcpwm_intr_handle; // handler for ISR register, one per MCPWM group + cap_isr_func_t cap_isr_func[SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER]; // handler for ISR callback, one for each cap ch } mcpwm_context_t; static mcpwm_context_t context[SOC_MCPWM_GROUPS] = { [0] = { .hal = {MCPWM_LL_GET_HW(0)}, .spinlock = portMUX_INITIALIZER_UNLOCKED, + .group_id = 0, .group_pre_scale = SOC_MCPWM_BASE_CLK_HZ / MCPWM_GROUP_CLK_HZ, .timer_pre_scale = {[0 ... SOC_MCPWM_TIMERS_PER_GROUP - 1] = MCPWM_GROUP_CLK_HZ / MCPWM_TIMER_CLK_HZ}, + .mcpwm_intr_handle = NULL, + .cap_isr_func = {[0 ... SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER - 1] = {NULL, NULL}}, }, [1] = { .hal = {MCPWM_LL_GET_HW(1)}, .spinlock = portMUX_INITIALIZER_UNLOCKED, + .group_id = 1, .group_pre_scale = SOC_MCPWM_BASE_CLK_HZ / MCPWM_GROUP_CLK_HZ, .timer_pre_scale = {[0 ... SOC_MCPWM_TIMERS_PER_GROUP - 1] = MCPWM_GROUP_CLK_HZ / MCPWM_TIMER_CLK_HZ}, + .mcpwm_intr_handle = NULL, + .cap_isr_func = {[0 ... SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER - 1] = {NULL, NULL}}, } }; @@ -97,6 +121,14 @@ static inline void mcpwm_critical_exit(mcpwm_unit_t mcpwm_num) portEXIT_CRITICAL(&context[mcpwm_num].spinlock); } +static inline void mcpwm_mutex_lock(mcpwm_unit_t mcpwm_num){ + _lock_acquire(&context[mcpwm_num].mutex_lock); +} + +static inline void mcpwm_mutex_unlock(mcpwm_unit_t mcpwm_num){ + _lock_release(&context[mcpwm_num].mutex_lock); +} + esp_err_t mcpwm_gpio_init(mcpwm_unit_t mcpwm_num, mcpwm_io_signals_t io_signal, int gpio_num) { if (gpio_num < 0) { // ignore on minus gpio number @@ -548,68 +580,68 @@ esp_err_t mcpwm_deadtime_enable(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, mcpwm_ll_deadtime_set_falling_delay(hal->dev, op, fed + 1); switch (dt_mode) { case MCPWM_BYPASS_RED: - mcpwm_ll_deadtime_bypass_path(hal->dev, op, 1, false); // S0 - mcpwm_ll_deadtime_bypass_path(hal->dev, op, 0, true); // S1 - mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 0, false); // S2 - mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 1, false); // S3 - mcpwm_ll_deadtime_red_select_generator(hal->dev, op, 0); // S4 - mcpwm_ll_deadtime_fed_select_generator(hal->dev, op, 1); // S5 + mcpwm_ll_deadtime_bypass_path(hal->dev, op, 1, false); // S0=0 + mcpwm_ll_deadtime_bypass_path(hal->dev, op, 0, true); // S1=1 + mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 0, false); // S2=0 + mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 1, false); // S3=0 + mcpwm_ll_deadtime_red_select_generator(hal->dev, op, 0); // S4=0 + mcpwm_ll_deadtime_fed_select_generator(hal->dev, op, 0); // S5=0 break; case MCPWM_BYPASS_FED: - mcpwm_ll_deadtime_bypass_path(hal->dev, op, 1, true); // S0 - mcpwm_ll_deadtime_bypass_path(hal->dev, op, 0, false); // S1 - mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 0, false); // S2 - mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 1, false); // S3 - mcpwm_ll_deadtime_red_select_generator(hal->dev, op, 0); // S4 - mcpwm_ll_deadtime_fed_select_generator(hal->dev, op, 0); // S5 + mcpwm_ll_deadtime_bypass_path(hal->dev, op, 1, true); // S0=1 + mcpwm_ll_deadtime_bypass_path(hal->dev, op, 0, false); // S1=0 + mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 0, false); // S2=0 + mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 1, false); // S3=0 + mcpwm_ll_deadtime_red_select_generator(hal->dev, op, 0); // S4=0 + mcpwm_ll_deadtime_fed_select_generator(hal->dev, op, 0); // S5=0 break; case MCPWM_ACTIVE_HIGH_MODE: - mcpwm_ll_deadtime_bypass_path(hal->dev, op, 1, false); // S0 - mcpwm_ll_deadtime_bypass_path(hal->dev, op, 0, false); // S1 - mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 0, false); // S2 - mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 1, false); // S3 - mcpwm_ll_deadtime_red_select_generator(hal->dev, op, 0); // S4 - mcpwm_ll_deadtime_fed_select_generator(hal->dev, op, 1); // S5 + mcpwm_ll_deadtime_bypass_path(hal->dev, op, 1, false); // S0=0 + mcpwm_ll_deadtime_bypass_path(hal->dev, op, 0, false); // S1=0 + mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 0, false); // S2=0 + mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 1, false); // S3=0 + mcpwm_ll_deadtime_red_select_generator(hal->dev, op, 0); // S4=0 + mcpwm_ll_deadtime_fed_select_generator(hal->dev, op, 0); // S5=0 break; case MCPWM_ACTIVE_LOW_MODE: - mcpwm_ll_deadtime_bypass_path(hal->dev, op, 1, false); // S0 - mcpwm_ll_deadtime_bypass_path(hal->dev, op, 0, false); // S1 - mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 0, true); // S2 - mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 1, true); // S3 - mcpwm_ll_deadtime_red_select_generator(hal->dev, op, 0); // S4 - mcpwm_ll_deadtime_fed_select_generator(hal->dev, op, 1); // S5 + mcpwm_ll_deadtime_bypass_path(hal->dev, op, 1, false); // S0=0 + mcpwm_ll_deadtime_bypass_path(hal->dev, op, 0, false); // S1=0 + mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 0, true); // S2=1 + mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 1, true); // S3=1 + mcpwm_ll_deadtime_red_select_generator(hal->dev, op, 0); // S4=0 + mcpwm_ll_deadtime_fed_select_generator(hal->dev, op, 0); // S5=0 break; case MCPWM_ACTIVE_HIGH_COMPLIMENT_MODE: - mcpwm_ll_deadtime_bypass_path(hal->dev, op, 1, false); // S0 - mcpwm_ll_deadtime_bypass_path(hal->dev, op, 0, false); // S1 - mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 0, false); // S2 - mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 1, true); // S3 - mcpwm_ll_deadtime_red_select_generator(hal->dev, op, 0); // S4 - mcpwm_ll_deadtime_fed_select_generator(hal->dev, op, 1); // S5 + mcpwm_ll_deadtime_bypass_path(hal->dev, op, 1, false); // S0=0 + mcpwm_ll_deadtime_bypass_path(hal->dev, op, 0, false); // S1=0 + mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 0, false); // S2=0 + mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 1, true); // S3=1 + mcpwm_ll_deadtime_red_select_generator(hal->dev, op, 0); // S4=0 + mcpwm_ll_deadtime_fed_select_generator(hal->dev, op, 0); // S5=0 break; case MCPWM_ACTIVE_LOW_COMPLIMENT_MODE: - mcpwm_ll_deadtime_bypass_path(hal->dev, op, 1, false); // S0 - mcpwm_ll_deadtime_bypass_path(hal->dev, op, 0, false); // S1 - mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 0, true); // S2 - mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 1, false); // S3 - mcpwm_ll_deadtime_red_select_generator(hal->dev, op, 1); // S4 - mcpwm_ll_deadtime_fed_select_generator(hal->dev, op, 0); // S5 + mcpwm_ll_deadtime_bypass_path(hal->dev, op, 1, false); // S0=0 + mcpwm_ll_deadtime_bypass_path(hal->dev, op, 0, false); // S1=0 + mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 0, true); // S2=1 + mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 1, false); // S3=0 + mcpwm_ll_deadtime_red_select_generator(hal->dev, op, 0); // S4=0 + mcpwm_ll_deadtime_fed_select_generator(hal->dev, op, 0); // S5=0 break; case MCPWM_ACTIVE_RED_FED_FROM_PWMXA: - mcpwm_ll_deadtime_bypass_path(hal->dev, op, 1, false); // S0 - mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 1, false); // S3 - mcpwm_ll_deadtime_red_select_generator(hal->dev, op, 1); // S4 - mcpwm_ll_deadtime_swap_out_path(hal->dev, op, 0, true); // S6 - mcpwm_ll_deadtime_swap_out_path(hal->dev, op, 1, false); // S7 - mcpwm_ll_deadtime_enable_deb(hal->dev, op, true); // S8 + mcpwm_ll_deadtime_bypass_path(hal->dev, op, 1, false); // S0=0 + mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 1, false); // S3=0 + mcpwm_ll_deadtime_red_select_generator(hal->dev, op, 0); // S4=0 + mcpwm_ll_deadtime_swap_out_path(hal->dev, op, 0, true); // S6=1 + mcpwm_ll_deadtime_swap_out_path(hal->dev, op, 1, false); // S7=0 + mcpwm_ll_deadtime_enable_deb(hal->dev, op, true); // S8=1 break; case MCPWM_ACTIVE_RED_FED_FROM_PWMXB: - mcpwm_ll_deadtime_bypass_path(hal->dev, op, 1, false); // S0 - mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 1, false); // S3 - mcpwm_ll_deadtime_red_select_generator(hal->dev, op, 0); // S4 - mcpwm_ll_deadtime_swap_out_path(hal->dev, op, 0, true); // S6 - mcpwm_ll_deadtime_swap_out_path(hal->dev, op, 1, false); // S7 - mcpwm_ll_deadtime_enable_deb(hal->dev, op, true); // S8 + mcpwm_ll_deadtime_bypass_path(hal->dev, op, 1, false); // S0=0 + mcpwm_ll_deadtime_invert_outpath(hal->dev, op, 1, false); // S3=0 + mcpwm_ll_deadtime_red_select_generator(hal->dev, op, 1); // S4=1 + mcpwm_ll_deadtime_swap_out_path(hal->dev, op, 0, true); // S6=1 + mcpwm_ll_deadtime_swap_out_path(hal->dev, op, 1, false); // S7=0 + mcpwm_ll_deadtime_enable_deb(hal->dev, op, true); // S8=1 break; default : break; @@ -705,6 +737,30 @@ esp_err_t mcpwm_fault_set_oneshot_mode(mcpwm_unit_t mcpwm_num, mcpwm_timer_t tim return ESP_OK; } +static void MCPWM_ISR_ATTR mcpwm_default_isr_handler(void *arg) { + mcpwm_context_t *curr_context = (mcpwm_context_t *) arg; + uint32_t intr_status = mcpwm_ll_intr_get_capture_status(curr_context->hal.dev); + mcpwm_ll_intr_clear_capture_status(curr_context->hal.dev, intr_status); + bool need_yield = false; + for (int i = 0; i < SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER; ++i) { + if ((intr_status >> i) & 0x1) { + if (curr_context->cap_isr_func[i].fn != NULL) { + cap_event_data_t edata; + edata.cap_edge = mcpwm_ll_capture_is_negedge(curr_context->hal.dev, i) ? MCPWM_NEG_EDGE + : MCPWM_POS_EDGE; + edata.cap_value = mcpwm_ll_capture_get_value(curr_context->hal.dev, i); + if (curr_context->cap_isr_func[i].fn(curr_context->group_id, i, &edata, + curr_context->cap_isr_func[i].args)) { + need_yield = true; + } + } + } + } + if (need_yield) { + portYIELD_FROM_ISR(); + } +} + esp_err_t mcpwm_capture_enable(mcpwm_unit_t mcpwm_num, mcpwm_capture_signal_t cap_sig, mcpwm_capture_on_edge_t cap_edge, uint32_t num_of_pulse) { @@ -746,7 +802,86 @@ esp_err_t mcpwm_capture_disable(mcpwm_unit_t mcpwm_num, mcpwm_capture_signal_t c return ESP_OK; } -uint32_t mcpwm_capture_signal_get_value(mcpwm_unit_t mcpwm_num, mcpwm_capture_signal_t cap_sig) +esp_err_t mcpwm_capture_enable_channel(mcpwm_unit_t mcpwm_num, mcpwm_capture_channel_id_t cap_channel, const mcpwm_capture_config_t *cap_conf) +{ + ESP_RETURN_ON_FALSE(mcpwm_num < SOC_MCPWM_GROUPS, ESP_ERR_INVALID_ARG, TAG, MCPWM_GROUP_NUM_ERROR); + ESP_RETURN_ON_FALSE(cap_channel < SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER, ESP_ERR_INVALID_ARG, TAG, MCPWM_CAPTURE_ERROR); + ESP_RETURN_ON_FALSE(context[mcpwm_num].cap_isr_func[cap_channel].fn == NULL, ESP_ERR_INVALID_STATE, TAG, + MCPWM_CAP_EXIST_ERROR); + mcpwm_hal_context_t *hal = &context[mcpwm_num].hal; + + // enable MCPWM module incase user don't use `mcpwm_init` at all. always increase reference count + periph_module_enable(mcpwm_periph_signals.groups[mcpwm_num].module); + + mcpwm_hal_init_config_t init_config = { + .host_id = mcpwm_num + }; + mcpwm_hal_init(hal, &init_config); + mcpwm_critical_enter(mcpwm_num); + mcpwm_ll_group_set_clock_prescale(hal->dev, context[mcpwm_num].group_pre_scale); + mcpwm_ll_capture_enable_timer(hal->dev, true); + mcpwm_ll_capture_enable_channel(hal->dev, cap_channel, true); + mcpwm_ll_capture_enable_negedge(hal->dev, cap_channel, cap_conf->cap_edge & MCPWM_NEG_EDGE); + mcpwm_ll_capture_enable_posedge(hal->dev, cap_channel, cap_conf->cap_edge & MCPWM_POS_EDGE); + mcpwm_ll_capture_set_prescale(hal->dev, cap_channel, cap_conf->cap_prescale); + // capture feature should be used with interupt, so enable it by default + mcpwm_ll_intr_enable_capture(hal->dev, cap_channel, true); + mcpwm_ll_intr_clear_capture_status(hal->dev, 1 << cap_channel); + mcpwm_critical_exit(mcpwm_num); + + mcpwm_mutex_lock(mcpwm_num); + context[mcpwm_num].cap_isr_func[cap_channel].fn = cap_conf->capture_cb; + context[mcpwm_num].cap_isr_func[cap_channel].args = cap_conf->user_data; + esp_err_t ret = ESP_OK; + if (context[mcpwm_num].mcpwm_intr_handle == NULL) { + ret = esp_intr_alloc(mcpwm_periph_signals.groups[mcpwm_num].irq_id, MCPWM_INTR_FLAG, + mcpwm_default_isr_handler, + (void *) (context + mcpwm_num), &(context[mcpwm_num].mcpwm_intr_handle)); + } + mcpwm_mutex_unlock(mcpwm_num); + + return ret; +} + +esp_err_t mcpwm_capture_disable_channel(mcpwm_unit_t mcpwm_num, mcpwm_capture_channel_id_t cap_channel) +{ + ESP_RETURN_ON_FALSE(mcpwm_num < SOC_MCPWM_GROUPS, ESP_ERR_INVALID_ARG, TAG, MCPWM_GROUP_NUM_ERROR); + ESP_RETURN_ON_FALSE(cap_channel < SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER, ESP_ERR_INVALID_ARG, TAG, MCPWM_CAPTURE_ERROR); + + mcpwm_hal_context_t *hal = &context[mcpwm_num].hal; + + mcpwm_critical_enter(mcpwm_num); + mcpwm_ll_capture_enable_channel(hal->dev, cap_channel, false); + mcpwm_ll_intr_enable_capture(hal->dev, cap_channel, false); + mcpwm_critical_exit(mcpwm_num); + + mcpwm_mutex_lock(mcpwm_num); + context[mcpwm_num].cap_isr_func[cap_channel].fn = NULL; + context[mcpwm_num].cap_isr_func[cap_channel].args = NULL; + // if all user defined ISR callback is disabled, free the handle + bool should_free_handle = true; + for (int i = 0; i < SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER; ++i) { + if (context[mcpwm_num].cap_isr_func[i].fn != NULL) { + should_free_handle = false; + break; + } + } + esp_err_t ret = ESP_OK; + if (should_free_handle) { + ret = esp_intr_free(context[mcpwm_num].mcpwm_intr_handle); + if (ret != ESP_OK){ + ESP_LOGE(TAG, "failed to free interrupt handle"); + } + context[mcpwm_num].mcpwm_intr_handle = NULL; + } + mcpwm_mutex_unlock(mcpwm_num); + + // always decrease reference count + periph_module_disable(mcpwm_periph_signals.groups[mcpwm_num].module); + return ret; +} + +uint32_t MCPWM_ISR_ATTR mcpwm_capture_signal_get_value(mcpwm_unit_t mcpwm_num, mcpwm_capture_signal_t cap_sig) { ESP_RETURN_ON_FALSE(mcpwm_num < SOC_MCPWM_GROUPS, ESP_ERR_INVALID_ARG, TAG, MCPWM_GROUP_NUM_ERROR); ESP_RETURN_ON_FALSE(cap_sig < SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER, ESP_ERR_INVALID_ARG, TAG, MCPWM_CAPTURE_ERROR); @@ -754,7 +889,7 @@ uint32_t mcpwm_capture_signal_get_value(mcpwm_unit_t mcpwm_num, mcpwm_capture_si return mcpwm_ll_capture_get_value(hal->dev, cap_sig); } -uint32_t mcpwm_capture_signal_get_edge(mcpwm_unit_t mcpwm_num, mcpwm_capture_signal_t cap_sig) +uint32_t MCPWM_ISR_ATTR mcpwm_capture_signal_get_edge(mcpwm_unit_t mcpwm_num, mcpwm_capture_signal_t cap_sig) { ESP_RETURN_ON_FALSE(mcpwm_num < SOC_MCPWM_GROUPS, ESP_ERR_INVALID_ARG, TAG, MCPWM_GROUP_NUM_ERROR); ESP_RETURN_ON_FALSE(cap_sig < SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER, ESP_ERR_INVALID_ARG, TAG, MCPWM_CAPTURE_ERROR); @@ -766,15 +901,44 @@ esp_err_t mcpwm_sync_enable(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, mcp uint32_t phase_val) { MCPWM_TIMER_CHECK(mcpwm_num, timer_num); + ESP_RETURN_ON_FALSE(sync_sig <= MCPWM_SELECT_GPIO_SYNC2, ESP_ERR_INVALID_ARG, TAG, "invalid sync_sig"); + ESP_RETURN_ON_FALSE(phase_val < 1000, ESP_ERR_INVALID_ARG, TAG, "phase_val must within 0~999"); mcpwm_hal_context_t *hal = &context[mcpwm_num].hal; mcpwm_critical_enter(mcpwm_num); uint32_t set_phase = mcpwm_ll_timer_get_peak(hal->dev, timer_num, false) * phase_val / 1000; mcpwm_ll_timer_set_sync_phase_value(hal->dev, timer_num, set_phase); - if (sync_sig >= MCPWM_SELECT_SYNC0) { - mcpwm_ll_timer_set_timer_synchro(hal->dev, timer_num, sync_sig - MCPWM_SELECT_SYNC0); + if (sync_sig == MCPWM_SELECT_NO_INPUT) { + mcpwm_ll_timer_set_soft_synchro(hal->dev, timer_num); + } else if (sync_sig <= MCPWM_SELECT_TIMER2_SYNC) { + mcpwm_ll_timer_set_timer_synchro(hal->dev, timer_num, sync_sig - MCPWM_SELECT_TIMER0_SYNC); + } else { + mcpwm_ll_timer_set_gpio_synchro(hal->dev, timer_num, sync_sig - MCPWM_SELECT_GPIO_SYNC0); + } + mcpwm_ll_timer_enable_sync_input(hal->dev, timer_num, true); + mcpwm_critical_exit(mcpwm_num); + return ESP_OK; +} + +esp_err_t mcpwm_sync_configure(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, const mcpwm_sync_config_t *sync_conf) +{ + MCPWM_TIMER_CHECK(mcpwm_num, timer_num); + ESP_RETURN_ON_FALSE(sync_conf->sync_sig <= MCPWM_SELECT_GPIO_SYNC2, ESP_ERR_INVALID_ARG, TAG, "invalid sync_sig"); + mcpwm_hal_context_t *hal = &context[mcpwm_num].hal; + + mcpwm_critical_enter(mcpwm_num); + mcpwm_ll_timer_set_sync_phase_direction(hal->dev, timer_num, sync_conf->count_direction); + // sync TEP with current setting + uint32_t set_phase = 0; + set_phase = mcpwm_ll_timer_get_peak(hal->dev, timer_num, false) * sync_conf->timer_val / 1000; + mcpwm_ll_timer_set_sync_phase_value(hal->dev, timer_num, set_phase); + if (sync_conf->sync_sig == MCPWM_SELECT_NO_INPUT){ + mcpwm_ll_timer_set_soft_synchro(hal->dev, timer_num); + } else if (sync_conf->sync_sig <= MCPWM_SELECT_TIMER2_SYNC) { + mcpwm_ll_timer_set_timer_synchro(hal->dev, timer_num, sync_conf->sync_sig - MCPWM_SELECT_TIMER0_SYNC); + } else { + mcpwm_ll_timer_set_gpio_synchro(hal->dev, timer_num, sync_conf->sync_sig - MCPWM_SELECT_GPIO_SYNC0); } - mcpwm_ll_timer_sync_out_penetrate(hal->dev, timer_num); mcpwm_ll_timer_enable_sync_input(hal->dev, timer_num, true); mcpwm_critical_exit(mcpwm_num); return ESP_OK; @@ -791,6 +955,55 @@ esp_err_t mcpwm_sync_disable(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num) return ESP_OK; } +esp_err_t mcpwm_timer_trigger_soft_sync(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num) +{ + MCPWM_TIMER_CHECK(mcpwm_num, timer_num); + + mcpwm_hal_context_t *hal = &context[mcpwm_num].hal; + mcpwm_critical_enter(mcpwm_num); + mcpwm_ll_timer_trigger_soft_sync(hal->dev, timer_num); + mcpwm_critical_exit(mcpwm_num); + + return ESP_OK; +} + +esp_err_t mcpwm_sync_invert_gpio_synchro(mcpwm_unit_t mcpwm_num, mcpwm_sync_signal_t sync_sig, bool invert){ + ESP_RETURN_ON_FALSE(sync_sig >= MCPWM_SELECT_GPIO_SYNC0 && sync_sig <= MCPWM_SELECT_GPIO_SYNC2, + ESP_ERR_INVALID_ARG, TAG, "invalid sync sig"); + + mcpwm_hal_context_t *hal = &context[mcpwm_num].hal; + mcpwm_critical_enter(mcpwm_num); + mcpwm_ll_invert_gpio_synchro(hal->dev, sync_sig - MCPWM_SELECT_GPIO_SYNC0, invert); + mcpwm_critical_exit(mcpwm_num); + + return ESP_OK; +} + +esp_err_t mcpwm_set_timer_sync_output(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, mcpwm_timer_sync_trigger_t trigger) +{ + MCPWM_TIMER_CHECK(mcpwm_num, timer_num); + + mcpwm_hal_context_t *hal = &context[mcpwm_num].hal; + mcpwm_critical_enter(mcpwm_num); + switch (trigger) { + case MCPWM_SWSYNC_SOURCE_SYNCIN: + mcpwm_ll_timer_sync_out_penetrate(hal->dev, timer_num); + break; + case MCPWM_SWSYNC_SOURCE_TEZ: + mcpwm_ll_timer_sync_out_on_timer_event(hal->dev, timer_num, MCPWM_TIMER_EVENT_ZERO); + break; + case MCPWM_SWSYNC_SOURCE_TEP: + mcpwm_ll_timer_sync_out_on_timer_event(hal->dev, timer_num, MCPWM_TIMER_EVENT_PEAK); + break; + case MCPWM_SWSYNC_SOURCE_DISABLED: + default: + mcpwm_ll_timer_disable_sync_out(hal->dev, timer_num); + break; + } + mcpwm_critical_exit(mcpwm_num); + return ESP_OK; +} + esp_err_t mcpwm_isr_register(mcpwm_unit_t mcpwm_num, void (*fn)(void *), void *arg, int intr_alloc_flags, intr_handle_t *handle) { esp_err_t ret; diff --git a/components/driver/pcnt.c b/components/driver/pcnt.c index b578d29c82..9c72378d99 100644 --- a/components/driver/pcnt.c +++ b/components/driver/pcnt.c @@ -4,14 +4,16 @@ * SPDX-License-Identifier: Apache-2.0 */ #include "freertos/FreeRTOS.h" -#include "freertos/semphr.h" #include "esp_log.h" +#include "esp_check.h" #include "soc/soc_caps.h" #if SOC_PCNT_SUPPORTED #include "driver/periph_ctrl.h" #include "driver/pcnt.h" #include "hal/pcnt_hal.h" +#include "hal/pcnt_ll.h" #include "hal/gpio_hal.h" +#include "soc/pcnt_periph.h" #include "esp_rom_gpio.h" #define PCNT_CHANNEL_ERR_STR "PCNT CHANNEL ERROR" @@ -31,11 +33,7 @@ static const char *TAG = "pcnt"; -#define PCNT_CHECK(a, str, ret_val) \ - if (!(a)) { \ - ESP_LOGE(TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ - return (ret_val); \ - } +#define PCNT_CHECK(a, str, ret_val) ESP_RETURN_ON_FALSE(a, ret_val, TAG, "%s", str) typedef struct { pcnt_hal_context_t hal; /*!< PCNT hal context*/ @@ -60,19 +58,20 @@ static portMUX_TYPE pcnt_spinlock = portMUX_INITIALIZER_UNLOCKED; static inline esp_err_t _pcnt_set_mode(pcnt_port_t pcnt_port, pcnt_unit_t unit, pcnt_channel_t channel, pcnt_count_mode_t pos_mode, pcnt_count_mode_t neg_mode, pcnt_ctrl_mode_t hctrl_mode, pcnt_ctrl_mode_t lctrl_mode) { PCNT_OBJ_CHECK(pcnt_port); - PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); PCNT_CHECK(channel < PCNT_CHANNEL_MAX, PCNT_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG); PCNT_CHECK((pos_mode < PCNT_COUNT_MAX) && (neg_mode < PCNT_COUNT_MAX), PCNT_COUNT_MODE_ERR_STR, ESP_ERR_INVALID_ARG); PCNT_CHECK((hctrl_mode < PCNT_MODE_MAX) && (lctrl_mode < PCNT_MODE_MAX), PCNT_CTRL_MODE_ERR_STR, ESP_ERR_INVALID_ARG); - pcnt_hal_set_mode(&(p_pcnt_obj[pcnt_port]->hal), unit, channel, pos_mode, neg_mode, hctrl_mode, lctrl_mode); + pcnt_ll_set_edge_action(p_pcnt_obj[pcnt_port]->hal.dev, unit, channel, pos_mode, neg_mode); + pcnt_ll_set_level_action(p_pcnt_obj[pcnt_port]->hal.dev, unit, channel, hctrl_mode, lctrl_mode); return ESP_OK; } static inline esp_err_t _pcnt_set_pin(pcnt_port_t pcnt_port, pcnt_unit_t unit, pcnt_channel_t channel, int pulse_io, int ctrl_io) { PCNT_OBJ_CHECK(pcnt_port); - PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); PCNT_CHECK(channel < PCNT_CHANNEL_MAX, PCNT_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG); PCNT_CHECK(GPIO_IS_VALID_GPIO(pulse_io) || pulse_io < 0, PCNT_GPIO_ERR_STR, ESP_ERR_INVALID_ARG); PCNT_CHECK(GPIO_IS_VALID_GPIO(ctrl_io) || ctrl_io < 0, PCNT_GPIO_ERR_STR, ESP_ERR_INVALID_ARG); @@ -81,14 +80,14 @@ static inline esp_err_t _pcnt_set_pin(pcnt_port_t pcnt_port, pcnt_unit_t unit, p gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[pulse_io], PIN_FUNC_GPIO); gpio_set_direction(pulse_io, GPIO_MODE_INPUT); gpio_set_pull_mode(pulse_io, GPIO_PULLUP_ONLY); - esp_rom_gpio_connect_in_signal(pulse_io, pcnt_periph_signals.units[unit].channels[channel].pulse_sig, 0); + esp_rom_gpio_connect_in_signal(pulse_io, pcnt_periph_signals.groups[pcnt_port].units[unit].channels[channel].pulse_sig, 0); } if (ctrl_io >= 0) { gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[ctrl_io], PIN_FUNC_GPIO); gpio_set_direction(ctrl_io, GPIO_MODE_INPUT); gpio_set_pull_mode(ctrl_io, GPIO_PULLUP_ONLY); - esp_rom_gpio_connect_in_signal(ctrl_io, pcnt_periph_signals.units[unit].channels[channel].control_sig, 0); + esp_rom_gpio_connect_in_signal(ctrl_io, pcnt_periph_signals.groups[pcnt_port].units[unit].channels[channel].control_sig, 0); } return ESP_OK; @@ -97,18 +96,18 @@ static inline esp_err_t _pcnt_set_pin(pcnt_port_t pcnt_port, pcnt_unit_t unit, p static inline esp_err_t _pcnt_get_counter_value(pcnt_port_t pcnt_port, pcnt_unit_t pcnt_unit, int16_t *count) { PCNT_OBJ_CHECK(pcnt_port); - PCNT_CHECK(pcnt_unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_CHECK(pcnt_unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); PCNT_CHECK(count != NULL, PCNT_ADDRESS_ERR_STR, ESP_ERR_INVALID_ARG); - pcnt_hal_get_counter_value(&(p_pcnt_obj[pcnt_port]->hal), pcnt_unit, count); + *count = pcnt_ll_get_count(p_pcnt_obj[pcnt_port]->hal.dev, pcnt_unit); return ESP_OK; } static inline esp_err_t _pcnt_counter_pause(pcnt_port_t pcnt_port, pcnt_unit_t pcnt_unit) { PCNT_OBJ_CHECK(pcnt_port); - PCNT_CHECK(pcnt_unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_CHECK(pcnt_unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); PCNT_ENTER_CRITICAL(&pcnt_spinlock); - pcnt_hal_counter_pause(&(p_pcnt_obj[pcnt_port]->hal), pcnt_unit); + pcnt_ll_stop_count(p_pcnt_obj[pcnt_port]->hal.dev, pcnt_unit); PCNT_EXIT_CRITICAL(&pcnt_spinlock); return ESP_OK; } @@ -116,9 +115,9 @@ static inline esp_err_t _pcnt_counter_pause(pcnt_port_t pcnt_port, pcnt_unit_t p static inline esp_err_t _pcnt_counter_resume(pcnt_port_t pcnt_port, pcnt_unit_t pcnt_unit) { PCNT_OBJ_CHECK(pcnt_port); - PCNT_CHECK(pcnt_unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_CHECK(pcnt_unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); PCNT_ENTER_CRITICAL(&pcnt_spinlock); - pcnt_hal_counter_resume(&(p_pcnt_obj[pcnt_port]->hal), pcnt_unit); + pcnt_ll_start_count(p_pcnt_obj[pcnt_port]->hal.dev, pcnt_unit); PCNT_EXIT_CRITICAL(&pcnt_spinlock); return ESP_OK; } @@ -126,115 +125,136 @@ static inline esp_err_t _pcnt_counter_resume(pcnt_port_t pcnt_port, pcnt_unit_t static inline esp_err_t _pcnt_counter_clear(pcnt_port_t pcnt_port, pcnt_unit_t pcnt_unit) { PCNT_OBJ_CHECK(pcnt_port); - PCNT_CHECK(pcnt_unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_CHECK(pcnt_unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); PCNT_ENTER_CRITICAL(&pcnt_spinlock); - pcnt_hal_counter_clear(&(p_pcnt_obj[pcnt_port]->hal), pcnt_unit); + pcnt_ll_clear_count(p_pcnt_obj[pcnt_port]->hal.dev, pcnt_unit); PCNT_EXIT_CRITICAL(&pcnt_spinlock); return ESP_OK; } -static inline esp_err_t _pcnt_intr_enable(pcnt_port_t pcnt_port, pcnt_unit_t pcnt_unit) +static inline esp_err_t _pcnt_intr_enable(pcnt_port_t pcnt_port, pcnt_unit_t pcnt_unit, bool enable) { PCNT_OBJ_CHECK(pcnt_port); - PCNT_CHECK(pcnt_unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_CHECK(pcnt_unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); PCNT_ENTER_CRITICAL(&pcnt_spinlock); - pcnt_hal_intr_enable(&(p_pcnt_obj[pcnt_port]->hal), pcnt_unit); + pcnt_ll_enable_intr(p_pcnt_obj[pcnt_port]->hal.dev, 1 << pcnt_unit, enable); PCNT_EXIT_CRITICAL(&pcnt_spinlock); return ESP_OK; } -static inline esp_err_t _pcnt_intr_disable(pcnt_port_t pcnt_port, pcnt_unit_t pcnt_unit) +static inline esp_err_t _pcnt_event_enable(pcnt_port_t pcnt_port, pcnt_unit_t unit, pcnt_evt_type_t evt_type, bool enable) { PCNT_OBJ_CHECK(pcnt_port); - PCNT_CHECK(pcnt_unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); - PCNT_ENTER_CRITICAL(&pcnt_spinlock); - pcnt_hal_intr_disable(&(p_pcnt_obj[pcnt_port]->hal), pcnt_unit); - PCNT_EXIT_CRITICAL(&pcnt_spinlock); - return ESP_OK; -} - -static inline esp_err_t _pcnt_event_enable(pcnt_port_t pcnt_port, pcnt_unit_t unit, pcnt_evt_type_t evt_type) -{ - PCNT_OBJ_CHECK(pcnt_port); - PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); PCNT_CHECK(evt_type < PCNT_EVT_MAX, PCNT_EVT_TYPE_ERR_STR, ESP_ERR_INVALID_ARG); - pcnt_hal_event_enable(&(p_pcnt_obj[pcnt_port]->hal), unit, evt_type); - return ESP_OK; -} - -static inline esp_err_t _pcnt_event_disable(pcnt_port_t pcnt_port, pcnt_unit_t unit, pcnt_evt_type_t evt_type) -{ - PCNT_OBJ_CHECK(pcnt_port); - PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); - PCNT_CHECK(evt_type < PCNT_EVT_MAX, PCNT_EVT_TYPE_ERR_STR, ESP_ERR_INVALID_ARG); - pcnt_hal_event_disable(&(p_pcnt_obj[pcnt_port]->hal), unit, evt_type); + switch (evt_type) { + case PCNT_EVT_THRES_1: + pcnt_ll_enable_thres_event(p_pcnt_obj[pcnt_port]->hal.dev, unit, 1, enable); + break; + case PCNT_EVT_THRES_0: + pcnt_ll_enable_thres_event(p_pcnt_obj[pcnt_port]->hal.dev, unit, 0, enable); + break; + case PCNT_EVT_L_LIM: + pcnt_ll_enable_low_limit_event(p_pcnt_obj[pcnt_port]->hal.dev, unit, enable); + break; + case PCNT_EVT_H_LIM: + pcnt_ll_enable_high_limit_event(p_pcnt_obj[pcnt_port]->hal.dev, unit, enable); + break; + case PCNT_EVT_ZERO: + pcnt_ll_enable_zero_cross_event(p_pcnt_obj[pcnt_port]->hal.dev, unit, enable); + break; + default: + PCNT_CHECK(false, PCNT_EVT_TYPE_ERR_STR, ESP_ERR_INVALID_ARG); + break; + } return ESP_OK; } static inline esp_err_t _pcnt_set_event_value(pcnt_port_t pcnt_port, pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t value) { PCNT_OBJ_CHECK(pcnt_port); - PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); PCNT_CHECK(evt_type < PCNT_EVT_MAX, PCNT_EVT_TYPE_ERR_STR, ESP_ERR_INVALID_ARG); PCNT_CHECK(!(evt_type == PCNT_EVT_L_LIM && value > 0), PCNT_LIMT_VAL_ERR_STR, ESP_ERR_INVALID_ARG); PCNT_CHECK(!(evt_type == PCNT_EVT_H_LIM && value < 0), PCNT_LIMT_VAL_ERR_STR, ESP_ERR_INVALID_ARG); - pcnt_hal_set_event_value(&(p_pcnt_obj[pcnt_port]->hal), unit, evt_type, value); + switch (evt_type) { + case PCNT_EVT_THRES_1: + pcnt_ll_set_thres_value(p_pcnt_obj[pcnt_port]->hal.dev, unit, 1, value); + break; + case PCNT_EVT_THRES_0: + pcnt_ll_set_thres_value(p_pcnt_obj[pcnt_port]->hal.dev, unit, 0, value); + break; + case PCNT_EVT_L_LIM: + pcnt_ll_set_low_limit_value(p_pcnt_obj[pcnt_port]->hal.dev, unit, value); + break; + case PCNT_EVT_H_LIM: + pcnt_ll_set_high_limit_value(p_pcnt_obj[pcnt_port]->hal.dev, unit, value); + break; + default: + break; + } return ESP_OK; } static inline esp_err_t _pcnt_get_event_value(pcnt_port_t pcnt_port, pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t *value) { PCNT_OBJ_CHECK(pcnt_port); - PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); PCNT_CHECK(evt_type < PCNT_EVT_MAX, PCNT_EVT_TYPE_ERR_STR, ESP_ERR_INVALID_ARG); PCNT_CHECK(value != NULL, PCNT_ADDRESS_ERR_STR, ESP_ERR_INVALID_ARG); - - pcnt_hal_get_event_value(&(p_pcnt_obj[pcnt_port]->hal), unit, evt_type, value); + switch (evt_type) { + case PCNT_EVT_THRES_1: + *value = pcnt_ll_get_thres_value(p_pcnt_obj[pcnt_port]->hal.dev, unit, 1); + break; + case PCNT_EVT_THRES_0: + *value = pcnt_ll_get_thres_value(p_pcnt_obj[pcnt_port]->hal.dev, unit, 0); + break; + case PCNT_EVT_L_LIM: + *value = pcnt_ll_get_low_limit_value(p_pcnt_obj[pcnt_port]->hal.dev, unit); + break; + case PCNT_EVT_H_LIM: + *value = pcnt_ll_get_high_limit_value(p_pcnt_obj[pcnt_port]->hal.dev, unit); + break; + default: + break; + } return ESP_OK; } static inline esp_err_t _pcnt_get_event_status(pcnt_port_t pcnt_port, pcnt_unit_t unit, uint32_t *status) { PCNT_OBJ_CHECK(pcnt_port); - PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); PCNT_CHECK(status != NULL, PCNT_ADDRESS_ERR_STR, ESP_ERR_INVALID_ARG); - *status = pcnt_hal_get_event_status(&(p_pcnt_obj[pcnt_port]->hal), unit); + *status = pcnt_ll_get_unit_status(p_pcnt_obj[pcnt_port]->hal.dev, unit); return ESP_OK; } static inline esp_err_t _pcnt_set_filter_value(pcnt_port_t pcnt_port, pcnt_unit_t unit, uint16_t filter_val) { PCNT_OBJ_CHECK(pcnt_port); - PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); PCNT_CHECK(filter_val < 1024, PCNT_PARAM_ERR_STR, ESP_ERR_INVALID_ARG); - pcnt_hal_set_filter_value(&(p_pcnt_obj[pcnt_port]->hal), unit, filter_val); + pcnt_ll_set_glitch_filter_thres(p_pcnt_obj[pcnt_port]->hal.dev, unit, filter_val); return ESP_OK; } static inline esp_err_t _pcnt_get_filter_value(pcnt_port_t pcnt_port, pcnt_unit_t unit, uint16_t *filter_val) { PCNT_OBJ_CHECK(pcnt_port); - PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); PCNT_CHECK(filter_val != NULL, PCNT_ADDRESS_ERR_STR, ESP_ERR_INVALID_ARG); - pcnt_hal_get_filter_value(&(p_pcnt_obj[pcnt_port]->hal), unit, filter_val); + *filter_val = (uint16_t)pcnt_ll_get_glitch_filter_thres(p_pcnt_obj[pcnt_port]->hal.dev, unit); return ESP_OK; } -static inline esp_err_t _pcnt_filter_enable(pcnt_port_t pcnt_port, pcnt_unit_t unit) +static inline esp_err_t _pcnt_filter_enable(pcnt_port_t pcnt_port, pcnt_unit_t unit, bool enable) { PCNT_OBJ_CHECK(pcnt_port); - PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); - pcnt_hal_filter_enable(&(p_pcnt_obj[pcnt_port]->hal), unit); - return ESP_OK; -} - -static inline esp_err_t _pcnt_filter_disable(pcnt_port_t pcnt_port, pcnt_unit_t unit) -{ - PCNT_OBJ_CHECK(pcnt_port); - PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); - pcnt_hal_filter_disable(&(p_pcnt_obj[pcnt_port]->hal), unit); + PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); + pcnt_ll_enable_glitch_filter(p_pcnt_obj[pcnt_port]->hal.dev, unit, enable); return ESP_OK; } @@ -242,16 +262,16 @@ static inline esp_err_t _pcnt_isr_handler_add(pcnt_port_t pcnt_port, pcnt_unit_t { PCNT_OBJ_CHECK(pcnt_port); PCNT_CHECK(pcnt_isr_func != NULL, "ISR service is not installed, call pcnt_install_isr_service() first", ESP_ERR_INVALID_STATE); - PCNT_CHECK(unit < PCNT_UNIT_MAX, "PCNT unit error", ESP_ERR_INVALID_ARG); + PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, "PCNT unit error", ESP_ERR_INVALID_ARG); PCNT_ENTER_CRITICAL(&pcnt_spinlock); - _pcnt_intr_disable(PCNT_PORT_0, unit); + _pcnt_intr_enable(PCNT_PORT_0, unit, false); if (pcnt_isr_func) { pcnt_isr_func[unit].fn = isr_handler; pcnt_isr_func[unit].args = args; } - _pcnt_intr_enable(PCNT_PORT_0, unit); + _pcnt_intr_enable(PCNT_PORT_0, unit, true); PCNT_EXIT_CRITICAL(&pcnt_spinlock); return ESP_OK; } @@ -260,9 +280,9 @@ static inline esp_err_t _pcnt_isr_handler_remove(pcnt_port_t pcnt_port, pcnt_uni { PCNT_OBJ_CHECK(pcnt_port); PCNT_CHECK(pcnt_isr_func != NULL, "ISR service is not installed", ESP_ERR_INVALID_STATE); - PCNT_CHECK(unit < PCNT_UNIT_MAX, "PCNT unit error", ESP_ERR_INVALID_ARG); + PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, "PCNT unit error", ESP_ERR_INVALID_ARG); PCNT_ENTER_CRITICAL(&pcnt_spinlock); - _pcnt_intr_disable(PCNT_PORT_0, unit); + _pcnt_intr_enable(PCNT_PORT_0, unit, false); if (pcnt_isr_func) { pcnt_isr_func[unit].fn = NULL; @@ -278,8 +298,8 @@ static void IRAM_ATTR pcnt_intr_service(void *arg) { uint32_t status = 0; pcnt_port_t pcnt_port = (pcnt_port_t)arg; - pcnt_hal_get_intr_status(&(p_pcnt_obj[pcnt_port]->hal), &status); - pcnt_hal_clear_intr_status(&(p_pcnt_obj[pcnt_port]->hal), status); + status = pcnt_ll_get_intr_status(p_pcnt_obj[pcnt_port]->hal.dev); + pcnt_ll_clear_intr_status(p_pcnt_obj[pcnt_port]->hal.dev, status); while (status) { int unit = __builtin_ffs(status) - 1; @@ -296,7 +316,7 @@ static inline esp_err_t _pcnt_isr_service_install(pcnt_port_t pcnt_port, int int PCNT_OBJ_CHECK(pcnt_port); PCNT_CHECK(pcnt_isr_func == NULL, "ISR service already installed", ESP_ERR_INVALID_STATE); esp_err_t ret = ESP_FAIL; - pcnt_isr_func = (pcnt_isr_func_t *) calloc(PCNT_UNIT_MAX, sizeof(pcnt_isr_func_t)); + pcnt_isr_func = (pcnt_isr_func_t *) calloc(SOC_PCNT_UNITS_PER_GROUP, sizeof(pcnt_isr_func_t)); if (pcnt_isr_func == NULL) { ret = ESP_ERR_NO_MEM; @@ -333,7 +353,7 @@ static inline esp_err_t _pcnt_unit_config(pcnt_port_t pcnt_port, const pcnt_conf int input_io = pcnt_config->pulse_gpio_num; int ctrl_io = pcnt_config->ctrl_gpio_num; - PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); + PCNT_CHECK(unit < SOC_PCNT_UNITS_PER_GROUP, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG); PCNT_CHECK(channel < PCNT_CHANNEL_MAX, PCNT_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG); PCNT_CHECK(input_io < 0 || (GPIO_IS_VALID_GPIO(input_io) && (input_io != ctrl_io)), "PCNT pulse input io error", ESP_ERR_INVALID_ARG); PCNT_CHECK(ctrl_io < 0 || GPIO_IS_VALID_GPIO(ctrl_io), "PCNT ctrl io error", ESP_ERR_INVALID_ARG); @@ -342,18 +362,18 @@ static inline esp_err_t _pcnt_unit_config(pcnt_port_t pcnt_port, const pcnt_conf /*Enalbe hardware module*/ static bool pcnt_enable = false; if (pcnt_enable == false) { - periph_module_reset(pcnt_periph_signals.module); + periph_module_reset(pcnt_periph_signals.groups[pcnt_port].module); pcnt_enable = true; } - periph_module_enable(pcnt_periph_signals.module); + periph_module_enable(pcnt_periph_signals.groups[pcnt_port].module); /*Set counter range*/ _pcnt_set_event_value(pcnt_port, unit, PCNT_EVT_H_LIM, pcnt_config->counter_h_lim); _pcnt_set_event_value(pcnt_port, unit, PCNT_EVT_L_LIM, pcnt_config->counter_l_lim); /*Default value after reboot is positive, we disable these events like others*/ - _pcnt_event_disable(pcnt_port, unit, PCNT_EVT_H_LIM); - _pcnt_event_disable(pcnt_port, unit, PCNT_EVT_L_LIM); - _pcnt_event_disable(pcnt_port, unit, PCNT_EVT_ZERO); - _pcnt_filter_disable(pcnt_port, unit); + _pcnt_event_enable(pcnt_port, unit, PCNT_EVT_H_LIM, false); + _pcnt_event_enable(pcnt_port, unit, PCNT_EVT_L_LIM, false); + _pcnt_event_enable(pcnt_port, unit, PCNT_EVT_ZERO, false); + _pcnt_filter_enable(pcnt_port, unit, false); /*set pulse input and control mode*/ _pcnt_set_mode(pcnt_port, unit, channel, pcnt_config->pos_mode, pcnt_config->neg_mode, pcnt_config->hctrl_mode, pcnt_config->lctrl_mode); /*Set pulse input and control pins*/ @@ -386,8 +406,6 @@ esp_err_t pcnt_init(pcnt_port_t pcnt_port) return ESP_OK; } -// TODO: The following functions are wrappers, for compatibility with current API. - esp_err_t pcnt_unit_config(const pcnt_config_t *pcnt_config) { esp_err_t ret; @@ -433,22 +451,22 @@ esp_err_t pcnt_counter_clear(pcnt_unit_t pcnt_unit) esp_err_t pcnt_intr_enable(pcnt_unit_t pcnt_unit) { - return _pcnt_intr_enable(PCNT_PORT_0, pcnt_unit); + return _pcnt_intr_enable(PCNT_PORT_0, pcnt_unit, true); } esp_err_t pcnt_intr_disable(pcnt_unit_t pcnt_unit) { - return _pcnt_intr_disable(PCNT_PORT_0, pcnt_unit); + return _pcnt_intr_enable(PCNT_PORT_0, pcnt_unit, false); } esp_err_t pcnt_event_enable(pcnt_unit_t unit, pcnt_evt_type_t evt_type) { - return _pcnt_event_enable(PCNT_PORT_0, unit, evt_type); + return _pcnt_event_enable(PCNT_PORT_0, unit, evt_type, true); } esp_err_t pcnt_event_disable(pcnt_unit_t unit, pcnt_evt_type_t evt_type) { - return _pcnt_event_disable(PCNT_PORT_0, unit, evt_type); + return _pcnt_event_enable(PCNT_PORT_0, unit, evt_type, false); } esp_err_t pcnt_set_event_value(pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t value) @@ -478,12 +496,12 @@ esp_err_t pcnt_get_filter_value(pcnt_unit_t unit, uint16_t *filter_val) esp_err_t pcnt_filter_enable(pcnt_unit_t unit) { - return _pcnt_filter_enable(PCNT_PORT_0, unit); + return _pcnt_filter_enable(PCNT_PORT_0, unit, true); } esp_err_t pcnt_filter_disable(pcnt_unit_t unit) { - return _pcnt_filter_disable(PCNT_PORT_0, unit); + return _pcnt_filter_enable(PCNT_PORT_0, unit, false); } esp_err_t pcnt_isr_unregister(pcnt_isr_handle_t handle) @@ -500,7 +518,7 @@ esp_err_t pcnt_isr_register(void (*fun)(void *), void *arg, int intr_alloc_flags esp_err_t ret = ESP_FAIL; PCNT_CHECK(fun != NULL, PCNT_ADDRESS_ERR_STR, ESP_ERR_INVALID_ARG); PCNT_ENTER_CRITICAL(&pcnt_spinlock); - ret = esp_intr_alloc(pcnt_periph_signals.irq, intr_alloc_flags, fun, arg, handle); + ret = esp_intr_alloc(pcnt_periph_signals.groups[0].irq, intr_alloc_flags, fun, arg, handle); PCNT_EXIT_CRITICAL(&pcnt_spinlock); return ret; } @@ -515,7 +533,6 @@ esp_err_t pcnt_isr_handler_remove(pcnt_unit_t unit) return _pcnt_isr_handler_remove(PCNT_PORT_0, unit); } - esp_err_t pcnt_isr_service_install(int intr_alloc_flags) { return _pcnt_isr_service_install(PCNT_PORT_0, intr_alloc_flags); diff --git a/components/driver/rmt.c b/components/driver/rmt.c index 3165ae59af..e9cbe41f6f 100644 --- a/components/driver/rmt.c +++ b/components/driver/rmt.c @@ -74,6 +74,7 @@ typedef struct { size_t tx_sub_len; bool translator; bool wait_done; //Mark whether wait tx done. + bool loop_autostop; // mark whether loop auto-stop is enabled rmt_channel_t channel; const rmt_item32_t *tx_data; xSemaphoreHandle tx_sem; @@ -892,6 +893,13 @@ static void IRAM_ATTR rmt_driver_isr_default(void *arg) status &= ~(1 << channel); rmt_obj_t *p_rmt = p_rmt_obj[channel]; if (p_rmt) { + if (p_rmt->loop_autostop) { +#ifndef SOC_RMT_SUPPORT_TX_LOOP_AUTOSTOP + // hardware doesn't support automatically stop output so driver should stop output here (possibility already overshotted several us) + rmt_ll_tx_stop(rmt_contex.hal.regs, channel); + rmt_ll_tx_reset_pointer(rmt_contex.hal.regs, channel); +#endif + } xSemaphoreGiveFromISR(p_rmt->tx_sem, &HPTaskAwoken); if (rmt_contex.rmt_tx_end_callback.function) { rmt_contex.rmt_tx_end_callback.function(channel, rmt_contex.rmt_tx_end_callback.arg); @@ -1039,6 +1047,7 @@ esp_err_t rmt_driver_install(rmt_channel_t channel, size_t rx_buf_size, int intr p_rmt_obj[channel]->tx_offset = 0; p_rmt_obj[channel]->tx_sub_len = 0; p_rmt_obj[channel]->wait_done = false; + p_rmt_obj[channel]->loop_autostop = false; p_rmt_obj[channel]->translator = false; p_rmt_obj[channel]->sample_to_rmt = NULL; if (p_rmt_obj[channel]->tx_sem == NULL) { @@ -1365,9 +1374,22 @@ esp_err_t rmt_memory_rw_rst(rmt_channel_t channel) esp_err_t rmt_set_tx_loop_count(rmt_channel_t channel, uint32_t count) { ESP_RETURN_ON_FALSE(RMT_IS_TX_CHANNEL(channel), ESP_ERR_INVALID_ARG, TAG, RMT_CHANNEL_ERROR_STR); + ESP_RETURN_ON_FALSE(count <= RMT_LL_MAX_LOOP_COUNT, ESP_ERR_INVALID_ARG, TAG, "Invalid count value"); RMT_ENTER_CRITICAL(); rmt_ll_tx_set_loop_count(rmt_contex.hal.regs, channel, count); RMT_EXIT_CRITICAL(); return ESP_OK; } + +esp_err_t rmt_enable_tx_loop_autostop(rmt_channel_t channel, bool en) +{ + ESP_RETURN_ON_FALSE(RMT_IS_TX_CHANNEL(channel), ESP_ERR_INVALID_ARG, TAG, RMT_CHANNEL_ERROR_STR); + p_rmt_obj[channel]->loop_autostop = en; +#if SOC_RMT_SUPPORT_TX_LOOP_AUTOSTOP + RMT_ENTER_CRITICAL(); + rmt_ll_tx_enable_loop_autostop(rmt_contex.hal.regs, channel, en); + RMT_EXIT_CRITICAL(); +#endif + return ESP_OK; +} #endif diff --git a/components/driver/rtc_io.c b/components/driver/rtc_io.c index db168476b2..84515814a2 100644 --- a/components/driver/rtc_io.c +++ b/components/driver/rtc_io.c @@ -7,6 +7,7 @@ #include #include "esp_log.h" #include "esp_err.h" +#include "esp_check.h" #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" #include "freertos/timers.h" @@ -15,13 +16,6 @@ static const char __attribute__((__unused__)) *RTCIO_TAG = "RTCIO"; -#define RTCIO_CHECK(a, str, ret_val) ({ \ - if (!(a)) { \ - ESP_LOGE(RTCIO_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ - return (ret_val); \ - } \ -}) - extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished. #define RTCIO_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock) #define RTCIO_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock) @@ -33,7 +27,7 @@ extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate posi ---------------------------------------------------------------*/ esp_err_t rtc_gpio_init(gpio_num_t gpio_num) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); RTCIO_ENTER_CRITICAL(); rtcio_hal_function_select(rtc_io_number_get(gpio_num), RTCIO_FUNC_RTC); RTCIO_EXIT_CRITICAL(); @@ -43,7 +37,7 @@ esp_err_t rtc_gpio_init(gpio_num_t gpio_num) esp_err_t rtc_gpio_deinit(gpio_num_t gpio_num) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); RTCIO_ENTER_CRITICAL(); // Select Gpio as Digital Gpio rtcio_hal_function_select(rtc_io_number_get(gpio_num), RTCIO_FUNC_DIGITAL); @@ -54,7 +48,7 @@ esp_err_t rtc_gpio_deinit(gpio_num_t gpio_num) esp_err_t rtc_gpio_set_level(gpio_num_t gpio_num, uint32_t level) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); RTCIO_ENTER_CRITICAL(); rtcio_hal_set_level(rtc_io_number_get(gpio_num), level); RTCIO_EXIT_CRITICAL(); @@ -64,15 +58,15 @@ esp_err_t rtc_gpio_set_level(gpio_num_t gpio_num, uint32_t level) uint32_t rtc_gpio_get_level(gpio_num_t gpio_num) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); return rtcio_hal_get_level(rtc_io_number_get(gpio_num)); } esp_err_t rtc_gpio_set_drive_capability(gpio_num_t gpio_num, gpio_drive_cap_t strength) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); - RTCIO_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "Output pad only", ESP_ERR_INVALID_ARG); - RTCIO_CHECK(strength < GPIO_DRIVE_CAP_MAX, "RTCIO drive capability error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); + ESP_RETURN_ON_FALSE(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "Output pad only"); + ESP_RETURN_ON_FALSE(strength < GPIO_DRIVE_CAP_MAX, ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO drive capability error"); RTCIO_ENTER_CRITICAL(); rtcio_hal_set_drive_capability(rtc_io_number_get(gpio_num), strength); RTCIO_EXIT_CRITICAL(); @@ -82,9 +76,9 @@ esp_err_t rtc_gpio_set_drive_capability(gpio_num_t gpio_num, gpio_drive_cap_t st esp_err_t rtc_gpio_get_drive_capability(gpio_num_t gpio_num, gpio_drive_cap_t *strength) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); - RTCIO_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "Output pad only", ESP_ERR_INVALID_ARG); - RTCIO_CHECK(strength != NULL, "GPIO drive pointer error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); + ESP_RETURN_ON_FALSE(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "Output pad only"); + ESP_RETURN_ON_FALSE(strength != NULL, ESP_ERR_INVALID_ARG, RTCIO_TAG, "GPIO drive pointer error"); *strength = (gpio_drive_cap_t)rtcio_hal_get_drive_capability(rtc_io_number_get(gpio_num)); return ESP_OK; @@ -92,7 +86,7 @@ esp_err_t rtc_gpio_get_drive_capability(gpio_num_t gpio_num, gpio_drive_cap_t *s esp_err_t rtc_gpio_set_direction(gpio_num_t gpio_num, rtc_gpio_mode_t mode) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); RTCIO_ENTER_CRITICAL(); rtcio_hal_set_direction(rtc_io_number_get(gpio_num), mode); RTCIO_EXIT_CRITICAL(); @@ -102,7 +96,7 @@ esp_err_t rtc_gpio_set_direction(gpio_num_t gpio_num, rtc_gpio_mode_t mode) esp_err_t rtc_gpio_set_direction_in_sleep(gpio_num_t gpio_num, rtc_gpio_mode_t mode) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); RTCIO_ENTER_CRITICAL(); rtcio_hal_set_direction_in_sleep(rtc_io_number_get(gpio_num), mode); RTCIO_EXIT_CRITICAL(); @@ -112,7 +106,7 @@ esp_err_t rtc_gpio_set_direction_in_sleep(gpio_num_t gpio_num, rtc_gpio_mode_t m esp_err_t rtc_gpio_pullup_en(gpio_num_t gpio_num) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); RTCIO_ENTER_CRITICAL(); rtcio_hal_pullup_enable(rtc_io_number_get(gpio_num)); RTCIO_EXIT_CRITICAL(); @@ -122,7 +116,7 @@ esp_err_t rtc_gpio_pullup_en(gpio_num_t gpio_num) esp_err_t rtc_gpio_pullup_dis(gpio_num_t gpio_num) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); RTCIO_ENTER_CRITICAL(); rtcio_hal_pullup_disable(rtc_io_number_get(gpio_num)); RTCIO_EXIT_CRITICAL(); @@ -132,7 +126,7 @@ esp_err_t rtc_gpio_pullup_dis(gpio_num_t gpio_num) esp_err_t rtc_gpio_pulldown_en(gpio_num_t gpio_num) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); RTCIO_ENTER_CRITICAL(); rtcio_hal_pulldown_enable(rtc_io_number_get(gpio_num)); RTCIO_EXIT_CRITICAL(); @@ -142,7 +136,7 @@ esp_err_t rtc_gpio_pulldown_en(gpio_num_t gpio_num) esp_err_t rtc_gpio_pulldown_dis(gpio_num_t gpio_num) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); RTCIO_ENTER_CRITICAL(); rtcio_hal_pulldown_disable(rtc_io_number_get(gpio_num)); RTCIO_EXIT_CRITICAL(); @@ -156,7 +150,7 @@ esp_err_t rtc_gpio_pulldown_dis(gpio_num_t gpio_num) esp_err_t rtc_gpio_hold_en(gpio_num_t gpio_num) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); RTCIO_ENTER_CRITICAL(); rtcio_hal_hold_enable(rtc_io_number_get(gpio_num)); RTCIO_EXIT_CRITICAL(); @@ -165,7 +159,7 @@ esp_err_t rtc_gpio_hold_en(gpio_num_t gpio_num) esp_err_t rtc_gpio_hold_dis(gpio_num_t gpio_num) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); RTCIO_ENTER_CRITICAL(); rtcio_hal_hold_disable(rtc_io_number_get(gpio_num)); RTCIO_EXIT_CRITICAL(); @@ -174,7 +168,7 @@ esp_err_t rtc_gpio_hold_dis(gpio_num_t gpio_num) esp_err_t rtc_gpio_isolate(gpio_num_t gpio_num) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); RTCIO_ENTER_CRITICAL(); rtcio_hal_isolate(rtc_io_number_get(gpio_num)); RTCIO_EXIT_CRITICAL(); @@ -206,7 +200,7 @@ esp_err_t rtc_gpio_force_hold_dis_all(void) esp_err_t rtc_gpio_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); if (intr_type == GPIO_INTR_POSEDGE || intr_type == GPIO_INTR_NEGEDGE || intr_type == GPIO_INTR_ANYEDGE) { return ESP_ERR_INVALID_ARG; // Dont support this mode. } @@ -218,7 +212,7 @@ esp_err_t rtc_gpio_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type) esp_err_t rtc_gpio_wakeup_disable(gpio_num_t gpio_num) { - RTCIO_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTCIO number error", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); RTCIO_ENTER_CRITICAL(); rtcio_hal_wakeup_disable(rtc_io_number_get(gpio_num)); RTCIO_EXIT_CRITICAL(); diff --git a/components/driver/sigmadelta.c b/components/driver/sigmadelta.c index 9d72c04f47..4e909a043f 100644 --- a/components/driver/sigmadelta.c +++ b/components/driver/sigmadelta.c @@ -5,6 +5,7 @@ */ #include "esp_log.h" +#include "esp_check.h" #include "esp_err.h" #include "driver/sigmadelta.h" #include "esp_heap_caps.h" @@ -14,10 +15,7 @@ static const char *TAG = "sigma-delta"; -#define SIGMADELTA_CHECK(a,str,ret_val) if(!(a)) { \ - ESP_LOGE(TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ - return (ret_val); \ - } +#define SIGMADELTA_CHECK(a,str,ret_val) ESP_RETURN_ON_FALSE(a, ret_val, TAG, "%s", str) typedef struct { sigmadelta_hal_context_t hal; /*!< SIGMADELTA hal context*/ diff --git a/components/driver/spi_common.c b/components/driver/spi_common.c index 00a48b9f1a..9a3cf2dac8 100644 --- a/components/driver/spi_common.c +++ b/components/driver/spi_common.c @@ -15,6 +15,7 @@ #include "esp_err.h" #include "soc/soc.h" #include "soc/soc_caps.h" +#include "soc/soc_pins.h" #include "soc/lldesc.h" #include "driver/gpio.h" #include "driver/periph_ctrl.h" @@ -350,32 +351,116 @@ esp_err_t spicommon_slave_free_dma(spi_host_device_t host_id) } //----------------------------------------------------------IO general-------------------------------------------------------// -static bool bus_uses_iomux_pins(spi_host_device_t host, const spi_bus_config_t* bus_config) +#if SOC_SPI_SUPPORT_OCT +static bool check_iomux_pins_oct(spi_host_device_t host, const spi_bus_config_t* bus_config) +{ + if (host != SPI2_HOST) { + return false; + } + int io_nums[] = {bus_config->data0_io_num, bus_config->data1_io_num, bus_config->data2_io_num, bus_config->data3_io_num, + bus_config->sclk_io_num, bus_config->data4_io_num, bus_config->data5_io_num, bus_config->data6_io_num, bus_config->data7_io_num}; + int io_mux_nums[] = {SPI2_IOMUX_PIN_NUM_MOSI_OCT, SPI2_IOMUX_PIN_NUM_MISO_OCT, SPI2_IOMUX_PIN_NUM_WP_OCT, SPI2_IOMUX_PIN_NUM_HD_OCT, + SPI2_IOMUX_PIN_NUM_CLK_OCT, SPI2_IOMUX_PIN_NUM_IO4_OCT, SPI2_IOMUX_PIN_NUM_IO5_OCT, SPI2_IOMUX_PIN_NUM_IO6_OCT, SPI2_IOMUX_PIN_NUM_IO7_OCT}; + for (size_t i = 0; i < sizeof(io_nums)/sizeof(io_nums[0]); i++) { + if (io_nums[i] >= 0 && io_nums[i] != io_mux_nums[i]) { + return false; + } + } + return true; +} +#endif + +static bool check_iomux_pins_quad(spi_host_device_t host, const spi_bus_config_t* bus_config) { if (bus_config->sclk_io_num>=0 && bus_config->sclk_io_num != spi_periph_signal[host].spiclk_iomux_pin) { - return false; - } + return false; + } if (bus_config->quadwp_io_num>=0 && bus_config->quadwp_io_num != spi_periph_signal[host].spiwp_iomux_pin) { - return false; - } + return false; + } if (bus_config->quadhd_io_num>=0 && bus_config->quadhd_io_num != spi_periph_signal[host].spihd_iomux_pin) { - return false; - } + return false; + } if (bus_config->mosi_io_num >= 0 && bus_config->mosi_io_num != spi_periph_signal[host].spid_iomux_pin) { - return false; - } + return false; + } if (bus_config->miso_io_num>=0 && bus_config->miso_io_num != spi_periph_signal[host].spiq_iomux_pin) { - return false; - } - + return false; + } return true; } +static bool bus_uses_iomux_pins(spi_host_device_t host, const spi_bus_config_t* bus_config) +{ +//Check if SPI pins could be routed to iomux. +#if SOC_SPI_SUPPORT_OCT + //The io mux pins available for Octal mode is not the same as the ones we use for non-Octal mode. + if ((bus_config->flags & SPICOMMON_BUSFLAG_OCTAL) == SPICOMMON_BUSFLAG_OCTAL) { + return check_iomux_pins_oct(host, bus_config); + } +#endif + return check_iomux_pins_quad(host, bus_config); +} + +#if SOC_SPI_SUPPORT_OCT +static void bus_iomux_pins_set_oct(spi_host_device_t host, const spi_bus_config_t* bus_config) +{ + assert(host == SPI2_HOST); + int io_nums[] = {bus_config->data0_io_num, bus_config->data1_io_num, bus_config->data2_io_num, bus_config->data3_io_num, + bus_config->sclk_io_num, bus_config->data4_io_num, bus_config->data5_io_num, bus_config->data6_io_num, bus_config->data7_io_num}; + int io_signals[] = {spi_periph_signal[host].spid_in, spi_periph_signal[host].spiq_in, spi_periph_signal[host].spiwp_in, + spi_periph_signal[host].spihd_in,spi_periph_signal[host].spiclk_in, spi_periph_signal[host].spid4_out, + spi_periph_signal[host].spid5_out, spi_periph_signal[host].spid6_out, spi_periph_signal[host].spid7_out}; + for (size_t i = 0; i < sizeof(io_nums)/sizeof(io_nums[0]); i++) { + if (io_nums[i] > 0) { + gpio_iomux_in(io_nums[i], io_signals[i]); + // In Octal mode use function channel 2 + gpio_iomux_out(io_nums[i], SPI2_FUNC_NUM_OCT, false); + } + } +} +#endif //SOC_SPI_SUPPORT_OCT + +static void bus_iomux_pins_set_quad(spi_host_device_t host, const spi_bus_config_t* bus_config) +{ + if (bus_config->mosi_io_num >= 0) { + gpio_iomux_in(bus_config->mosi_io_num, spi_periph_signal[host].spid_in); + gpio_iomux_out(bus_config->mosi_io_num, spi_periph_signal[host].func, false); + } + if (bus_config->miso_io_num >= 0) { + gpio_iomux_in(bus_config->miso_io_num, spi_periph_signal[host].spiq_in); + gpio_iomux_out(bus_config->miso_io_num, spi_periph_signal[host].func, false); + } + if (bus_config->quadwp_io_num >= 0) { + gpio_iomux_in(bus_config->quadwp_io_num, spi_periph_signal[host].spiwp_in); + gpio_iomux_out(bus_config->quadwp_io_num, spi_periph_signal[host].func, false); + } + if (bus_config->quadhd_io_num >= 0) { + gpio_iomux_in(bus_config->quadhd_io_num, spi_periph_signal[host].spihd_in); + gpio_iomux_out(bus_config->quadhd_io_num, spi_periph_signal[host].func, false); + } + if (bus_config->sclk_io_num >= 0) { + gpio_iomux_in(bus_config->sclk_io_num, spi_periph_signal[host].spiclk_in); + gpio_iomux_out(bus_config->sclk_io_num, spi_periph_signal[host].func, false); + } +} + +static void bus_iomux_pins_set(spi_host_device_t host, const spi_bus_config_t* bus_config) +{ +#if SOC_SPI_SUPPORT_OCT + if ((bus_config->flags & SPICOMMON_BUSFLAG_OCTAL) == SPICOMMON_BUSFLAG_OCTAL) { + bus_iomux_pins_set_oct(host, bus_config); + return; + } +#endif + bus_iomux_pins_set_quad(host, bus_config); +} + /* Do the common stuff to hook up a SPI host to a bus defined by a bunch of GPIO pins. Feed it a host number and a bus config struct and it'll set up the GPIO matrix and enable the device. If a pin is set to non-negative value, @@ -383,6 +468,17 @@ it should be able to be initialized. */ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_config_t *bus_config, uint32_t flags, uint32_t* flags_o) { +#if SOC_SPI_SUPPORT_OCT + // In the driver of previous version, spi data4 ~ spi data7 are not in spi_bus_config_t struct. So the new-added pins come as 0 + // if they are not really set. Add this boolean variable to check if the user has set spi data4 ~spi data7 pins . + bool io4_7_is_blank = !bus_config->data4_io_num && !bus_config->data5_io_num && !bus_config->data6_io_num && !bus_config->data7_io_num; + // This boolean variable specifies if user sets pins used for octal mode (users can set spi data4 ~ spi data7 to -1). + bool io4_7_enabled = !io4_7_is_blank && bus_config->data4_io_num >= 0 && bus_config->data5_io_num >= 0 && + bus_config->data6_io_num >= 0 && bus_config->data7_io_num >= 0; + SPI_CHECK((flags & SPICOMMON_BUSFLAG_MASTER) || !((flags & SPICOMMON_BUSFLAG_OCTAL) == SPICOMMON_BUSFLAG_OCTAL), "Octal SPI mode / OPI mode only works when SPI is used as Master", ESP_ERR_INVALID_ARG); + SPI_CHECK(host == SPI2_HOST || !((flags & SPICOMMON_BUSFLAG_OCTAL) == SPICOMMON_BUSFLAG_OCTAL), "Only SPI2 supports Octal SPI mode / OPI mode", ESP_ERR_INVALID_ARG); +#endif //SOC_SPI_SUPPORT_OCT + uint32_t temp_flag = 0; bool miso_need_output; @@ -414,13 +510,36 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf if (bus_config->quadhd_io_num>=0) { SPI_CHECK_PIN(bus_config->quadhd_io_num, "hd", hd_need_output); } +#if SOC_SPI_SUPPORT_OCT + const bool io4_need_output = true; + const bool io5_need_output = true; + const bool io6_need_output = true; + const bool io7_need_output = true; + // set flags for OCTAL mode according to the existence of spi data4 ~ spi data7 + if (io4_7_enabled) { + temp_flag |= SPICOMMON_BUSFLAG_IO4_IO7; + if (bus_config->data4_io_num >= 0) { + SPI_CHECK_PIN(bus_config->data4_io_num, "spi data4", io4_need_output); + } + if (bus_config->data5_io_num >= 0) { + SPI_CHECK_PIN(bus_config->data5_io_num, "spi data5", io5_need_output); + } + if (bus_config->data6_io_num >= 0) { + SPI_CHECK_PIN(bus_config->data6_io_num, "spi data6", io6_need_output); + } + if (bus_config->data7_io_num >= 0) { + SPI_CHECK_PIN(bus_config->data7_io_num, "spi data7", io7_need_output); + } + } +#endif //SOC_SPI_SUPPORT_OCT + //set flags for QUAD mode according to the existence of wp and hd if (bus_config->quadhd_io_num >= 0 && bus_config->quadwp_io_num >= 0) temp_flag |= SPICOMMON_BUSFLAG_WPHD; if (bus_config->mosi_io_num >= 0) { temp_flag |= SPICOMMON_BUSFLAG_MOSI; SPI_CHECK_PIN(bus_config->mosi_io_num, "mosi", mosi_need_output); } - if (bus_config->miso_io_num>=0) { + if (bus_config->miso_io_num >= 0) { temp_flag |= SPICOMMON_BUSFLAG_MISO; SPI_CHECK_PIN(bus_config->miso_io_num, "miso", miso_need_output); } @@ -443,12 +562,29 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf if (missing_flag != 0) { //check pins existence - if (missing_flag & SPICOMMON_BUSFLAG_SCLK) ESP_LOGE(SPI_TAG, "sclk pin required."); - if (missing_flag & SPICOMMON_BUSFLAG_MOSI) ESP_LOGE(SPI_TAG, "mosi pin required."); - if (missing_flag & SPICOMMON_BUSFLAG_MISO) ESP_LOGE(SPI_TAG, "miso pin required."); - if (missing_flag & SPICOMMON_BUSFLAG_DUAL) ESP_LOGE(SPI_TAG, "not both mosi and miso output capable"); - if (missing_flag & SPICOMMON_BUSFLAG_WPHD) ESP_LOGE(SPI_TAG, "both wp and hd required."); - if (missing_flag & SPICOMMON_BUSFLAG_IOMUX_PINS) ESP_LOGE(SPI_TAG, "not using iomux pins"); + if (missing_flag & SPICOMMON_BUSFLAG_SCLK) { + ESP_LOGE(SPI_TAG, "sclk pin required."); + } + if (missing_flag & SPICOMMON_BUSFLAG_MOSI) { + ESP_LOGE(SPI_TAG, "mosi pin required."); + } + if (missing_flag & SPICOMMON_BUSFLAG_MISO) { + ESP_LOGE(SPI_TAG, "miso pin required."); + } + if (missing_flag & SPICOMMON_BUSFLAG_DUAL) { + ESP_LOGE(SPI_TAG, "not both mosi and miso output capable"); + } + if (missing_flag & SPICOMMON_BUSFLAG_WPHD) { + ESP_LOGE(SPI_TAG, "both wp and hd required."); + } + if (missing_flag & SPICOMMON_BUSFLAG_IOMUX_PINS) { + ESP_LOGE(SPI_TAG, "not using iomux pins"); + } +#if SOC_SPI_SUPPORT_OCT + if (missing_flag & SPICOMMON_BUSFLAG_IO4_IO7) { + ESP_LOGE(SPI_TAG, "spi data4 ~ spi data7 are required."); + } +#endif SPI_CHECK(missing_flag == 0, "not all required capabilities satisfied.", ESP_ERR_INVALID_ARG); } @@ -456,27 +592,7 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf //All SPI iomux pin selections resolve to 1, so we put that here instead of trying to figure //out which FUNC_GPIOx_xSPIxx to grab; they all are defined to 1 anyway. ESP_LOGD(SPI_TAG, "SPI%d use iomux pins.", host+1); - if (bus_config->mosi_io_num >= 0) { - gpio_iomux_in(bus_config->mosi_io_num, spi_periph_signal[host].spid_in); - gpio_iomux_out(bus_config->mosi_io_num, spi_periph_signal[host].func, false); - } - if (bus_config->miso_io_num >= 0) { - gpio_iomux_in(bus_config->miso_io_num, spi_periph_signal[host].spiq_in); - gpio_iomux_out(bus_config->miso_io_num, spi_periph_signal[host].func, false); - } - if (bus_config->quadwp_io_num >= 0) { - gpio_iomux_in(bus_config->quadwp_io_num, spi_periph_signal[host].spiwp_in); - gpio_iomux_out(bus_config->quadwp_io_num, spi_periph_signal[host].func, false); - } - if (bus_config->quadhd_io_num >= 0) { - gpio_iomux_in(bus_config->quadhd_io_num, spi_periph_signal[host].spihd_in); - gpio_iomux_out(bus_config->quadhd_io_num, spi_periph_signal[host].func, false); - } - if (bus_config->sclk_io_num >= 0) { - gpio_iomux_in(bus_config->sclk_io_num, spi_periph_signal[host].spiclk_in); - gpio_iomux_out(bus_config->sclk_io_num, spi_periph_signal[host].func, false); - } - temp_flag |= SPICOMMON_BUSFLAG_IOMUX_PINS; + bus_iomux_pins_set(host, bus_config); } else { //Use GPIO matrix ESP_LOGD(SPI_TAG, "SPI%d use gpio matrix.", host+1); @@ -537,6 +653,26 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf #endif gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[bus_config->sclk_io_num], FUNC_GPIO); } +#if SOC_SPI_SUPPORT_OCT + if (flags & SPICOMMON_BUSFLAG_OCTAL) { + int io_nums[] = {bus_config->data4_io_num, bus_config->data5_io_num, bus_config->data6_io_num, bus_config->data7_io_num}; + uint8_t io_signals[4][2] = {{spi_periph_signal[host].spid4_out, spi_periph_signal[host].spid4_in}, + {spi_periph_signal[host].spid5_out, spi_periph_signal[host].spid5_in}, + {spi_periph_signal[host].spid6_out, spi_periph_signal[host].spid6_in}, + {spi_periph_signal[host].spid7_out, spi_periph_signal[host].spid7_in}}; + for (size_t i = 0; i < sizeof(io_nums) / sizeof(io_nums[0]); i++) { + if (io_nums[i] >= 0) { + gpio_set_direction(io_nums[i], GPIO_MODE_INPUT_OUTPUT); + esp_rom_gpio_connect_out_signal(io_nums[i], io_signals[i][0], false, false); + esp_rom_gpio_connect_in_signal(io_nums[i], io_signals[i][1], false); +#if CONFIG_IDF_TARGET_ESP32S2 + PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[io_nums[i]]); +#endif + gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[io_nums[i]], FUNC_GPIO); + } + } + } +#endif //SOC_SPI_SUPPORT_OCT } if (flags_o) *flags_o = temp_flag; diff --git a/components/driver/spi_master.c b/components/driver/spi_master.c index efac288823..15cfceb9ac 100644 --- a/components/driver/spi_master.c +++ b/components/driver/spi_master.c @@ -496,13 +496,13 @@ static inline SPI_MASTER_ISR_ATTR bool spi_bus_device_is_polling(spi_device_t *d -----------------------------------------------------------------------------*/ // The interrupt may get invoked by the bus lock. -static void spi_bus_intr_enable(void *host) +static void SPI_MASTER_ISR_ATTR spi_bus_intr_enable(void *host) { esp_intr_enable(((spi_host_t*)host)->intr); } // The interrupt is always disabled by the ISR itself, not exposed -static void spi_bus_intr_disable(void *host) +static void SPI_MASTER_ISR_ATTR spi_bus_intr_disable(void *host) { esp_intr_disable(((spi_host_t*)host)->intr); } @@ -530,13 +530,17 @@ static void SPI_MASTER_ISR_ATTR spi_new_trans(spi_device_t *dev, spi_trans_priv_ hal_trans.cmd = trans->cmd; hal_trans.addr = trans->addr; hal_trans.cs_keep_active = (trans->flags & SPI_TRANS_CS_KEEP_ACTIVE) ? 1 : 0; - //Set up QIO/DIO if needed - hal_trans.io_mode = (trans->flags & SPI_TRANS_MODE_DIO ? - (trans->flags & SPI_TRANS_MODE_DIOQIO_ADDR ? SPI_LL_IO_MODE_DIO : SPI_LL_IO_MODE_DUAL) : - (trans->flags & SPI_TRANS_MODE_QIO ? - (trans->flags & SPI_TRANS_MODE_DIOQIO_ADDR ? SPI_LL_IO_MODE_QIO : SPI_LL_IO_MODE_QUAD) : - SPI_LL_IO_MODE_NORMAL - )); + + //Set up OIO/QIO/DIO if needed + hal_trans.line_mode.data_lines = (trans->flags & SPI_TRANS_MODE_DIO) ? 2 : + (trans->flags & SPI_TRANS_MODE_QIO) ? 4 : 1; +#if SOC_SPI_SUPPORT_OCT + if (trans->flags & SPI_TRANS_MODE_OCT) { + hal_trans.line_mode.data_lines = 8; + } +#endif + hal_trans.line_mode.addr_lines = (trans->flags & SPI_TRANS_MULTILINE_ADDR) ? hal_trans.line_mode.data_lines : 1; + hal_trans.line_mode.cmd_lines = (trans->flags & SPI_TRANS_MULTILINE_CMD) ? hal_trans.line_mode.data_lines : 1; if (trans->flags & SPI_TRANS_VARIABLE_CMD) { hal_trans.cmd_bits = ((spi_transaction_ext_t *)trans)->command_bits; @@ -686,8 +690,13 @@ static SPI_MASTER_ISR_ATTR esp_err_t check_trans_valid(spi_device_handle_t handl SPI_CHECK(trans_desc->rxlength <= bus_attr->max_transfer_sz*8, "rxdata transfer > host maximum", ESP_ERR_INVALID_ARG); SPI_CHECK(is_half_duplex || trans_desc->rxlength <= trans_desc->length, "rx length > tx length in full duplex mode", ESP_ERR_INVALID_ARG); //check working mode - SPI_CHECK(!((trans_desc->flags & (SPI_TRANS_MODE_DIO|SPI_TRANS_MODE_QIO)) && (handle->cfg.flags & SPI_DEVICE_3WIRE)), "incompatible iface params", ESP_ERR_INVALID_ARG); - SPI_CHECK(!((trans_desc->flags & (SPI_TRANS_MODE_DIO|SPI_TRANS_MODE_QIO)) && !is_half_duplex), "incompatible iface params", ESP_ERR_INVALID_ARG); +#if SOC_SPI_SUPPORT_OCT + SPI_CHECK(!(host->id == SPI3_HOST && trans_desc->flags & SPI_TRANS_MODE_OCT), "SPI3 does not support octal mode", ESP_ERR_INVALID_ARG); + SPI_CHECK(!((trans_desc->flags & SPI_TRANS_MODE_OCT) && (handle->cfg.flags & SPI_DEVICE_3WIRE)), "Incompatible when setting to both Octal mode and 3-wire-mode", ESP_ERR_INVALID_ARG); + SPI_CHECK(!((trans_desc->flags & SPI_TRANS_MODE_OCT) && !is_half_duplex), "Incompatible when setting to both Octal mode and half duplex mode", ESP_ERR_INVALID_ARG); +#endif + SPI_CHECK(!((trans_desc->flags & (SPI_TRANS_MODE_DIO|SPI_TRANS_MODE_QIO)) && (handle->cfg.flags & SPI_DEVICE_3WIRE)), "Incompatible when setting to both multi-line mode and 3-wire-mode", ESP_ERR_INVALID_ARG); + SPI_CHECK(!((trans_desc->flags & (SPI_TRANS_MODE_DIO|SPI_TRANS_MODE_QIO)) && !is_half_duplex), "Incompatible when setting to both multi-line mode and half duplex mode", ESP_ERR_INVALID_ARG); #ifdef CONFIG_IDF_TARGET_ESP32 SPI_CHECK(!is_half_duplex || !bus_attr->dma_enabled || !rx_enabled || !tx_enabled, "SPI half duplex mode does not support using DMA with both MOSI and MISO phases.", ESP_ERR_INVALID_ARG ); #elif CONFIG_IDF_TARGET_ESP32S3 diff --git a/components/driver/test/adc_dma_test/test_esp32s2.c b/components/driver/test/adc_dma_test/test_esp32s2.c index 9d2fbce34b..2a41f4ff69 100644 --- a/components/driver/test/adc_dma_test/test_esp32s2.c +++ b/components/driver/test/adc_dma_test/test_esp32s2.c @@ -41,8 +41,8 @@ static const char *TAG = "test_adc"; #define PLATFORM_SELECT (1) //0: pxp; 1: chip #if (PLATFORM_SELECT == 0) //PXP platform -#include "soc/apb_ctrl_reg.h" -#define SET_BREAK_POINT(flag) REG_WRITE(APB_CTRL_DATE_REG, flag) +#include "soc/syscon_reg.h" +#define SET_BREAK_POINT(flag) REG_WRITE(SYSCON_DATE_REG, flag) //PXP clk is slower. #define SYS_DELAY_TIME_MOM (1/40) #define RTC_SLOW_CLK_FLAG 1 // Slow clock is 32KHz. diff --git a/components/driver/test/dac_dma_test/test_esp32s2.c b/components/driver/test/dac_dma_test/test_esp32s2.c index a09dad16cf..94dcebaec0 100644 --- a/components/driver/test/dac_dma_test/test_esp32s2.c +++ b/components/driver/test/dac_dma_test/test_esp32s2.c @@ -40,8 +40,8 @@ static const char *TAG = "test_adc"; #define PLATFORM_SELECT (1) //0: pxp; 1: chip #if (PLATFORM_SELECT == 0) //PXP platform -#include "soc/apb_ctrl_reg.h" -#define SET_BREAK_POINT(flag) REG_WRITE(APB_CTRL_DATE_REG, flag) +#include "soc/syscon_reg.h" +#define SET_BREAK_POINT(flag) REG_WRITE(SYSCON_DATE_REG, flag) //PXP clk is slower. #define SYS_DELAY_TIME_MOM (1/40) #define RTC_SLOW_CLK_FLAG 1 // Slow clock is 32KHz. diff --git a/components/driver/test/test_adc_dma.c b/components/driver/test/test_adc.c similarity index 63% rename from components/driver/test/test_adc_dma.c rename to components/driver/test/test_adc.c index c14285ed02..9141590594 100644 --- a/components/driver/test/test_adc_dma.c +++ b/components/driver/test/test_adc.c @@ -4,15 +4,20 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include "sdkconfig.h" #include #include +#include "esp_log.h" #include "test_utils.h" +#include "esp_adc_cal.h" +#include "driver/adc_common.h" + +static const char *TAG = "ADC"; #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32, ESP32S2, ESP32S3) //API only supported for C3 now. #include "driver/adc.h" -#include "esp_adc_cal.h" #include "esp_log.h" #define TEST_COUNT 4096 @@ -274,4 +279,120 @@ TEST_CASE("test_adc_single", "[adc][ignore][manual]") } } +#endif //#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32, ESP32S2, ESP32S3) + + + + + + +/******************************************************************************** + * ADC Speed Related Tests + ********************************************************************************/ +#ifdef CONFIG_IDF_TARGET_ESP32 +#define CPU_FREQ_MHZ CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ +#elif CONFIG_IDF_TARGET_ESP32S2 +#define CPU_FREQ_MHZ CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ +#elif CONFIG_IDF_TARGET_ESP32S3 +#define CPU_FREQ_MHZ CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ +#elif CONFIG_IDF_TARGET_ESP32C3 +#define CPU_FREQ_MHZ CONFIG_ESP32C3_DEFAULT_CPU_FREQ_MHZ #endif + +#define RECORD_TIME_PREPARE() uint32_t __t1, __t2 +#define RECORD_TIME_START() do {__t1 = esp_cpu_get_ccount();}while(0) +#define RECORD_TIME_END(p_time) do{__t2 = esp_cpu_get_ccount(); *p_time = (__t2-__t1);}while(0) +#define GET_US_BY_CCOUNT(t) ((double)t/CPU_FREQ_MHZ) + + +//ADC Channels +#if CONFIG_IDF_TARGET_ESP32 +#define ADC1_CALI_TEST_CHAN0 ADC1_CHANNEL_6 +#define ADC2_CALI_TEST_CHAN0 ADC2_CHANNEL_0 +#else +#define ADC1_CALI_TEST_CHAN0 ADC1_CHANNEL_2 +#define ADC2_CALI_TEST_CHAN0 ADC2_CHANNEL_0 +#endif + +//ADC Calibration +#if CONFIG_IDF_TARGET_ESP32 +#define ADC_TEST_CALI_SCHEME ESP_ADC_CAL_VAL_EFUSE_VREF +#elif CONFIG_IDF_TARGET_ESP32S2 +#define ADC_TEST_CALI_SCHEME ESP_ADC_CAL_VAL_EFUSE_TP +#elif CONFIG_IDF_TARGET_ESP32C3 +#define ADC_TEST_CALI_SCHEME ESP_ADC_CAL_VAL_EFUSE_TP +#elif CONFIG_IDF_TARGET_ESP32S3 +#define ADC_TEST_CALI_SCHEME ESP_ADC_CAL_VAL_EFUSE_TP_FIT +#endif + +#define TIMES_PER_ATTEN 10 + +static esp_adc_cal_characteristics_t adc1_chars; +static esp_adc_cal_characteristics_t adc2_chars; + +static void adc_single_cali_init(adc_unit_t adc_n, adc_channel_t chan, uint32_t atten) +{ + esp_err_t ret; + esp_adc_cal_value_t ret_val = ESP_ADC_CAL_VAL_NOT_SUPPORTED; + + ret = esp_adc_cal_check_efuse(ADC_TEST_CALI_SCHEME); + if (ret == ESP_ERR_NOT_SUPPORTED) { + ESP_LOGE(TAG, "Cali scheme not supported!"); + TEST_ASSERT(ret != ESP_ERR_NOT_SUPPORTED); + } else if (ret != ESP_OK) { + ESP_LOGW(TAG, "No cali eFuse, but will run the test"); + } + + if (adc_n == ADC_UNIT_1) { + ret_val = esp_adc_cal_characterize(adc_n, atten, ADC_WIDTH_BIT_DEFAULT, 0, &adc1_chars); + TEST_ESP_OK(adc1_config_width(ADC_WIDTH_BIT_DEFAULT)); + TEST_ESP_OK(adc1_config_channel_atten((adc1_channel_t)chan, atten)); + } else if (adc_n == ADC_UNIT_2) { + TEST_ESP_OK(adc2_config_channel_atten((adc2_channel_t)chan, atten)); + ret_val = esp_adc_cal_characterize(adc_n, atten, ADC_WIDTH_BIT_DEFAULT, 0, &adc2_chars); + } + if (ret_val == ESP_ADC_CAL_VAL_NOT_SUPPORTED) { + ESP_LOGW(TAG, "No cali eFuse, or invalid arg, but will run the test"); + } + ESP_LOGI(TAG, "ADC%d, channel%d, atten%d", adc_n, chan, atten); +} + +static IRAM_ATTR NOINLINE_ATTR uint32_t get_cali_time_in_ccount(uint32_t adc_raw, esp_adc_cal_characteristics_t *chars) +{ + uint32_t time; + + RECORD_TIME_PREPARE(); + RECORD_TIME_START(); + esp_adc_cal_raw_to_voltage(adc_raw, chars); + RECORD_TIME_END(&time); + + return time; +} + +TEST_CASE("test_adc_single_cali_time", "[adc][ignore][manual]") +{ + ESP_LOGI(TAG, "CPU FREQ is %dMHz", CPU_FREQ_MHZ); + uint32_t adc1_time_record[4][TIMES_PER_ATTEN] = {}; + uint32_t adc2_time_record[4][TIMES_PER_ATTEN] = {}; + int adc1_raw = 0; + int adc2_raw = 0; + + //atten0 ~ atten3 + for (int i = 0; i < 4; i++) { + ESP_LOGI(TAG, "----------------atten%d----------------", i); + adc_single_cali_init(ADC_UNIT_1, ADC1_CALI_TEST_CHAN0, i); + adc_single_cali_init(ADC_UNIT_2, ADC2_CALI_TEST_CHAN0, i); + + for (int j = 0; j < TIMES_PER_ATTEN; j++) { + + adc1_raw = adc1_get_raw(ADC1_CALI_TEST_CHAN0); + TEST_ESP_OK(adc2_get_raw(ADC2_CALI_TEST_CHAN0, ADC_WIDTH_BIT_DEFAULT, &adc2_raw)); + + adc1_time_record[i][j] = get_cali_time_in_ccount(adc1_raw, &adc1_chars); + adc2_time_record[i][j] = get_cali_time_in_ccount(adc2_raw, &adc2_chars); + + IDF_LOG_PERFORMANCE("ADC1 Cali time", "%d us", (int)GET_US_BY_CCOUNT(adc1_time_record[i][j])); + IDF_LOG_PERFORMANCE("ADC2 Cali time", "%d us", (int)GET_US_BY_CCOUNT(adc2_time_record[i][j])); + } + } +} diff --git a/components/driver/test/test_i2s.c b/components/driver/test/test_i2s.c index 41e29cf2dc..7234164cc5 100644 --- a/components/driver/test/test_i2s.c +++ b/components/driver/test/test_i2s.c @@ -21,22 +21,51 @@ #include "math.h" #include "esp_rom_gpio.h" -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3, ESP32C3) - #define SAMPLE_RATE (36000) #define SAMPLE_BITS (16) + +#if CONFIG_IDF_TARGET_ESP32 #define MASTER_BCK_IO 15 +#define MASTER_WS_IO 25 #define SLAVE_BCK_IO 19 #define SLAVE_WS_IO 26 #define DATA_IN_IO 21 - -#if CONFIG_IDF_TARGET_ESP32 -#define MASTER_WS_IO 25 #define DATA_OUT_IO 22 #define ADC1_CHANNEL_4_IO 32 +#define I2S0_DATA_OUT_IDX I2S0O_DATA_OUT23_IDX +#define I2S0_DATA_IN_IDX I2S0I_DATA_IN15_IDX +#define I2S1_DATA_OUT_IDX I2S1O_DATA_OUT23_IDX +#define I2S1_DATA_IN_IDX I2S1I_DATA_IN15_IDX #elif CONFIG_IDF_TARGET_ESP32S2 +#define MASTER_BCK_IO 15 #define MASTER_WS_IO 28 +#define SLAVE_BCK_IO 19 +#define SLAVE_WS_IO 26 +#define DATA_IN_IO 21 #define DATA_OUT_IO 20 +#define I2S0_DATA_OUT_IDX I2S0O_DATA_OUT23_IDX +#define I2S0_DATA_IN_IDX I2S0I_DATA_IN15_IDX +#elif CONFIG_IDF_TARGET_ESP32C3 +// TODO: change pins +#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 +#define I2S0_DATA_OUT_IDX I2SO_SD_OUT_IDX +#define I2S0_DATA_IN_IDX I2SI_SD_IN_IDX +#elif CONFIG_IDF_TARGET_ESP32S3 +#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 +#define I2S0_DATA_OUT_IDX I2S0O_SD_OUT_IDX +#define I2S0_DATA_IN_IDX I2S0I_SD_IN_IDX +#define I2S1_DATA_OUT_IDX I2S1O_SD_OUT_IDX +#define I2S1_DATA_IN_IDX I2S1I_SD_IN_IDX #endif #define PERCENT_DIFF 0.0001 @@ -60,40 +89,40 @@ static void i2s_test_io_config(int mode) switch (mode) { #if SOC_I2S_NUM > 1 - case I2S_TEST_MODE_SLAVE_TO_MAXTER: { - esp_rom_gpio_connect_out_signal(MASTER_BCK_IO, I2S0I_BCK_OUT_IDX, 0, 0); - esp_rom_gpio_connect_in_signal(MASTER_BCK_IO, I2S1O_BCK_IN_IDX, 0); + case I2S_TEST_MODE_SLAVE_TO_MAXTER: { + esp_rom_gpio_connect_out_signal(MASTER_BCK_IO, I2S0I_BCK_OUT_IDX, 0, 0); + esp_rom_gpio_connect_in_signal(MASTER_BCK_IO, I2S1O_BCK_IN_IDX, 0); - esp_rom_gpio_connect_out_signal(MASTER_WS_IO, I2S0I_WS_OUT_IDX, 0, 0); - esp_rom_gpio_connect_in_signal(MASTER_WS_IO, I2S1O_WS_IN_IDX, 0); + esp_rom_gpio_connect_out_signal(MASTER_WS_IO, I2S0I_WS_OUT_IDX, 0, 0); + esp_rom_gpio_connect_in_signal(MASTER_WS_IO, I2S1O_WS_IN_IDX, 0); - esp_rom_gpio_connect_out_signal(DATA_OUT_IO, I2S1O_DATA_OUT23_IDX, 0, 0); - esp_rom_gpio_connect_in_signal(DATA_OUT_IO, I2S0I_DATA_IN15_IDX, 0); - } - break; + esp_rom_gpio_connect_out_signal(DATA_OUT_IO, I2S1_DATA_OUT_IDX, 0, 0); + esp_rom_gpio_connect_in_signal(DATA_OUT_IO, I2S0_DATA_IN_IDX, 0); + } + break; - case I2S_TEST_MODE_MASTER_TO_SLAVE: { - esp_rom_gpio_connect_out_signal(MASTER_BCK_IO, I2S0O_BCK_OUT_IDX, 0, 0); - esp_rom_gpio_connect_in_signal(MASTER_BCK_IO, I2S1I_BCK_IN_IDX, 0); + case I2S_TEST_MODE_MASTER_TO_SLAVE: { + esp_rom_gpio_connect_out_signal(MASTER_BCK_IO, I2S0O_BCK_OUT_IDX, 0, 0); + esp_rom_gpio_connect_in_signal(MASTER_BCK_IO, I2S1I_BCK_IN_IDX, 0); - esp_rom_gpio_connect_out_signal(MASTER_WS_IO, I2S0O_WS_OUT_IDX, 0, 0); - esp_rom_gpio_connect_in_signal(MASTER_WS_IO, I2S1I_WS_IN_IDX, 0); + esp_rom_gpio_connect_out_signal(MASTER_WS_IO, I2S0O_WS_OUT_IDX, 0, 0); + esp_rom_gpio_connect_in_signal(MASTER_WS_IO, I2S1I_WS_IN_IDX, 0); - esp_rom_gpio_connect_out_signal(DATA_OUT_IO, I2S0O_DATA_OUT23_IDX, 0, 0); - esp_rom_gpio_connect_in_signal(DATA_OUT_IO, I2S1I_DATA_IN15_IDX, 0); - } - break; + esp_rom_gpio_connect_out_signal(DATA_OUT_IO, I2S0_DATA_OUT_IDX, 0, 0); + esp_rom_gpio_connect_in_signal(DATA_OUT_IO, I2S1_DATA_IN_IDX, 0); + } + break; #endif - case I2S_TEST_MODE_LOOPBACK: { - esp_rom_gpio_connect_out_signal(DATA_OUT_IO, I2S0O_DATA_OUT23_IDX, 0, 0); - esp_rom_gpio_connect_in_signal(DATA_OUT_IO, I2S0I_DATA_IN15_IDX, 0); - } - break; + case I2S_TEST_MODE_LOOPBACK: { + esp_rom_gpio_connect_out_signal(DATA_OUT_IO, I2S0_DATA_OUT_IDX, 0, 0); + esp_rom_gpio_connect_in_signal(DATA_OUT_IO, I2S0_DATA_IN_IDX, 0); + } + break; - default: { - TEST_FAIL_MESSAGE("error: mode not supported"); - } - break; + default: { + TEST_FAIL_MESSAGE("error: mode not supported"); + } + break; } } @@ -115,17 +144,16 @@ TEST_CASE("I2S basic driver install, uninstall, set pin test", "[i2s]") .dma_buf_count = 6, .dma_buf_len = 60, .use_apll = 0, - .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 , - }; - -#if CONFIG_IDF_TARGET_ESP32 - //install and start i2s driver - TEST_ESP_OK(i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL)); - //for internal DAC, this will enable both of the internal channels - TEST_ESP_OK(i2s_set_pin(I2S_NUM_0, NULL)); - //stop & destroy i2s driver - TEST_ESP_OK(i2s_driver_uninstall(I2S_NUM_0)); + .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, +#if SOC_I2S_SUPPORTS_TDM + .chan_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1, + .total_chan = 2, + .left_align = false, + .big_edin = false, + .bit_order_msb = false, + .skip_msk = false #endif + }; // normal i2s i2s_pin_config_t pin_config = { @@ -145,7 +173,7 @@ TEST_CASE("I2S basic driver install, uninstall, set pin test", "[i2s]") TEST_ASSERT(i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL) == ESP_ERR_INVALID_ARG); i2s_config.dma_buf_count = 129; TEST_ASSERT(i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL) == ESP_ERR_INVALID_ARG); - TEST_ESP_OK(i2s_driver_uninstall(I2S_NUM_0)); + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, i2s_driver_uninstall(I2S_NUM_0)); } TEST_CASE("I2S Loopback test(master tx and rx)", "[i2s]") @@ -160,7 +188,15 @@ TEST_CASE("I2S Loopback test(master tx and rx)", "[i2s]") .dma_buf_count = 6, .dma_buf_len = 100, .use_apll = 0, - .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 , + .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, +#if SOC_I2S_SUPPORTS_TDM + .chan_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1, + .total_chan = 2, + .left_align = false, + .big_edin = false, + .bit_order_msb = false, + .skip_msk = false +#endif }; i2s_pin_config_t master_pin_config = { .bck_io_num = MASTER_BCK_IO, @@ -173,29 +209,28 @@ TEST_CASE("I2S Loopback test(master tx and rx)", "[i2s]") i2s_test_io_config(I2S_TEST_MODE_LOOPBACK); printf("\r\nheap size: %d\n", esp_get_free_heap_size()); - uint8_t* data_wr = (uint8_t*)malloc(sizeof(uint8_t)*400); + uint8_t *data_wr = (uint8_t *)malloc(sizeof(uint8_t) * 400); size_t i2s_bytes_write = 0; size_t bytes_read = 0; int length = 0; - uint8_t *i2s_read_buff = (uint8_t*)malloc(sizeof(uint8_t)*10000); + uint8_t *i2s_read_buff = (uint8_t *)malloc(sizeof(uint8_t) * 10000); - for(int i=0; i<100; i++) { - data_wr[i] = i+1; + for (int i = 0; i < 100; i++) { + data_wr[i] = i + 1; } - int flag=0; // break loop flag + int flag = 0; // break loop flag int end_position = 0; // write data to slave - i2s_write(I2S_NUM_0, data_wr, sizeof(uint8_t)*400, &i2s_bytes_write, 1000 / portTICK_PERIOD_MS); - while(!flag){ + i2s_write(I2S_NUM_0, data_wr, sizeof(uint8_t) * 400, &i2s_bytes_write, 1000 / portTICK_PERIOD_MS); + while (!flag) { if (length >= 10000 - 500) { break; } - i2s_read(I2S_NUM_0, i2s_read_buff + length, sizeof(uint8_t)*500, &bytes_read, 1000/portMAX_DELAY); - if(bytes_read>0) { - printf("read data size: %d\n", bytes_read); - for(int i=length; i 0) { + for (int i = length; i < length + bytes_read; i++) { + if (i2s_read_buff[i] == 100) { + flag = 1; end_position = i; break; } @@ -204,70 +239,16 @@ TEST_CASE("I2S Loopback test(master tx and rx)", "[i2s]") length = length + bytes_read; } // test the read data right or not - for(int i=end_position-99; i<=end_position; i++) { - TEST_ASSERT_EQUAL_UINT8((i-end_position+100), *(i2s_read_buff + i)); + for (int i = end_position - 99; i <= end_position; i++) { + TEST_ASSERT_EQUAL_UINT8((i - end_position + 100), *(i2s_read_buff + i)); } free(data_wr); free(i2s_read_buff); i2s_driver_uninstall(I2S_NUM_0); } -#if !DISABLED_FOR_TARGETS(ESP32S2) -/* ESP32S2 has only single I2S port and hence following test cases are not applicable */ -TEST_CASE("I2S adc test", "[i2s]") -{ - // init I2S ADC - i2s_config_t i2s_config = { - .mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN, - .sample_rate = SAMPLE_RATE, - .bits_per_sample = SAMPLE_BITS, - .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, - .intr_alloc_flags = 0, - .dma_buf_count = 2, - .dma_buf_len = 1024, - .use_apll = 0, - }; - // install and start I2S driver - i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL); - // init ADC pad - i2s_set_adc_mode(ADC_UNIT_1, ADC1_CHANNEL_4); - // enable adc sampling, ADC_WIDTH_BIT_12, ADC_ATTEN_DB_11 hard-coded in adc_i2s_mode_init - i2s_adc_enable(I2S_NUM_0); - // init read buffer - uint16_t* i2sReadBuffer = (uint16_t*)calloc(1024, sizeof(uint16_t)); - size_t bytesRead; - - for (int loop = 0; loop < 10; loop++) { - for (int level = 0; level <= 1; level++) { - if (level == 0) { - gpio_set_pull_mode(ADC1_CHANNEL_4_IO, GPIO_PULLDOWN_ONLY); - } else { - gpio_set_pull_mode(ADC1_CHANNEL_4_IO, GPIO_PULLUP_ONLY); - } - vTaskDelay(200 / portTICK_RATE_MS); - // read data from adc, will block until buffer is full - i2s_read(I2S_NUM_0, (void*)i2sReadBuffer, 1024 * sizeof(uint16_t), &bytesRead, portMAX_DELAY); - - // calc average - int64_t adcSumValue = 0; - for (size_t i = 0; i < 1024; i++) { - adcSumValue += i2sReadBuffer[i] & 0xfff; - } - int adcAvgValue = adcSumValue / 1024; - printf("adc average val: %d\n", adcAvgValue); - - if (level == 0) { - TEST_ASSERT_LESS_THAN(100, adcAvgValue); - } else { - TEST_ASSERT_GREATER_THAN(4000, adcAvgValue); - } - } - } - i2s_adc_disable(I2S_NUM_0); - free(i2sReadBuffer); - i2s_driver_uninstall(I2S_NUM_0); -} - +#if SOC_I2S_NUM > 1 +/* ESP32S2 and ESP32C3 has only single I2S port and hence following test cases are not applicable */ TEST_CASE("I2S write and read test(master tx and slave rx)", "[i2s]") { // master driver installed and send data @@ -280,7 +261,15 @@ TEST_CASE("I2S write and read test(master tx and slave rx)", "[i2s]") .dma_buf_count = 6, .dma_buf_len = 100, .use_apll = 0, - .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 , + .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, +#if SOC_I2S_SUPPORTS_TDM + .chan_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1, + .total_chan = 2, + .left_align = false, + .big_edin = false, + .bit_order_msb = false, + .skip_msk = false +#endif }; i2s_pin_config_t master_pin_config = { .bck_io_num = MASTER_BCK_IO, @@ -302,7 +291,15 @@ TEST_CASE("I2S write and read test(master tx and slave rx)", "[i2s]") .dma_buf_count = 6, .dma_buf_len = 100, .use_apll = 0, - .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 , + .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, +#if SOC_I2S_SUPPORTS_TDM + .chan_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1, + .total_chan = 2, + .left_align = false, + .big_edin = false, + .bit_order_msb = false, + .skip_msk = false +#endif }; i2s_pin_config_t slave_pin_config = { .bck_io_num = SLAVE_BCK_IO, @@ -316,26 +313,27 @@ TEST_CASE("I2S write and read test(master tx and slave rx)", "[i2s]") i2s_test_io_config(I2S_TEST_MODE_MASTER_TO_SLAVE); printf("\r\nheap size: %d\n", esp_get_free_heap_size()); - uint8_t* data_wr = (uint8_t*)malloc(sizeof(uint8_t)*400); + uint8_t *data_wr = (uint8_t *)malloc(sizeof(uint8_t) * 400); size_t i2s_bytes_write = 0; size_t bytes_read = 0; int length = 0; - uint8_t *i2s_read_buff = (uint8_t*)malloc(sizeof(uint8_t)*10000); + uint8_t *i2s_read_buff = (uint8_t *)malloc(sizeof(uint8_t) * 10000); - for(int i=0; i<100; i++) { - data_wr[i] = i+1; + for (int i = 0; i < 100; i++) { + data_wr[i] = i + 1; } - int flag=0; // break loop flag + int flag = 0; // break loop flag int end_position = 0; // write data to slave - i2s_write(I2S_NUM_0, data_wr, sizeof(uint8_t)*400, &i2s_bytes_write, 1000 / portTICK_PERIOD_MS); - while(!flag){ - i2s_read(I2S_NUM_1, i2s_read_buff + length, sizeof(uint8_t)*500, &bytes_read, 1000/portMAX_DELAY); - if(bytes_read>0) { + i2s_write(I2S_NUM_0, data_wr, sizeof(uint8_t) * 400, &i2s_bytes_write, 1000 / portTICK_PERIOD_MS); + printf("write data size: %d\n", i2s_bytes_write); + while (!flag) { + i2s_read(I2S_NUM_1, i2s_read_buff + length, sizeof(uint8_t) * 500, &bytes_read, 1000 / portTICK_PERIOD_MS); + if (bytes_read > 0) { printf("read data size: %d\n", bytes_read); - for(int i=length; i 0) { - for(int i=length; i 0) { + printf("read data size: %d\n", bytes_read); + for (int i = length; i < length + bytes_read; i++) { + if (i2s_read_buff[i] == 100) { + flag = 1; end_position = i; break; } @@ -429,8 +445,8 @@ TEST_CASE("I2S write and read test(master rx and slave tx)", "[i2s]") length = length + bytes_read; } // test the readed data right or not - for(int i=end_position-99; i<=end_position; i++) { - TEST_ASSERT_EQUAL_UINT8((i-end_position+100), *(i2s_read_buff + i)); + for (int i = end_position - 99; i <= end_position; i++) { + TEST_ASSERT_EQUAL_UINT8((i - end_position + 100), *(i2s_read_buff + i)); } free(data_wr); free(i2s_read_buff); @@ -450,7 +466,15 @@ TEST_CASE("I2S memory leaking test", "[i2s]") .dma_buf_count = 6, .dma_buf_len = 100, .use_apll = 0, - .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 , + .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, +#if SOC_I2S_SUPPORTS_TDM + .chan_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1, + .total_chan = 2, + .left_align = false, + .big_edin = false, + .bit_order_msb = false, + .skip_msk = false +#endif }; i2s_pin_config_t master_pin_config = { .bck_io_num = MASTER_BCK_IO, @@ -464,7 +488,7 @@ TEST_CASE("I2S memory leaking test", "[i2s]") i2s_driver_uninstall(I2S_NUM_0); int initial_size = esp_get_free_heap_size(); - for(int i=0; i<100; i++) { + for (int i = 0; i < 100; i++) { TEST_ESP_OK(i2s_driver_install(I2S_NUM_0, &master_i2s_config, 0, NULL)); TEST_ESP_OK(i2s_set_pin(I2S_NUM_0, &master_pin_config)); i2s_driver_uninstall(I2S_NUM_0); @@ -474,6 +498,7 @@ TEST_CASE("I2S memory leaking test", "[i2s]") TEST_ASSERT(initial_size == esp_get_free_heap_size()); } +#if SOC_I2S_SUPPORTS_APLL /* * The I2S APLL clock variation test used to test the difference between the different sample rates, different bits per sample * and the APLL clock generate for it. The TEST_CASE passes PERCENT_DIFF variation from the provided sample rate in APLL generated clock @@ -498,6 +523,14 @@ TEST_CASE("I2S APLL clock variation test", "[i2s]") .dma_buf_len = 60, .use_apll = true, .intr_alloc_flags = 0, +#if SOC_I2S_SUPPORTS_TDM + .chan_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1, + .total_chan = 2, + .left_align = false, + .big_edin = false, + .bit_order_msb = false, + .skip_msk = false +#endif }; TEST_ESP_OK(i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL)); @@ -508,14 +541,14 @@ TEST_CASE("I2S APLL clock variation test", "[i2s]") uint32_t sample_rate_arr[8] = { 10675, 11025, 16000, 22050, 32000, 44100, 48000, 96000 }; int bits_per_sample_arr[3] = { 16, 24, 32 }; - for (int i = 0; i < (sizeof(sample_rate_arr)/sizeof(sample_rate_arr[0])); i++) { - for (int j = 0; j < (sizeof(bits_per_sample_arr)/sizeof(bits_per_sample_arr[0])); j++) { + for (int i = 0; i < (sizeof(sample_rate_arr) / sizeof(sample_rate_arr[0])); i++) { + for (int j = 0; j < (sizeof(bits_per_sample_arr) / sizeof(bits_per_sample_arr[0])); j++) { i2s_config.sample_rate = sample_rate_arr[i]; i2s_config.bits_per_sample = bits_per_sample_arr[j]; TEST_ESP_OK(i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL)); TEST_ESP_OK(i2s_set_pin(I2S_NUM_0, &pin_config)); - TEST_ASSERT((fabs((i2s_get_clk(I2S_NUM_0) - sample_rate_arr[i]))/(sample_rate_arr[i]))*100 < PERCENT_DIFF); + TEST_ASSERT((fabs((i2s_get_clk(I2S_NUM_0) - sample_rate_arr[i])) / (sample_rate_arr[i])) * 100 < PERCENT_DIFF); TEST_ESP_OK(i2s_driver_uninstall(I2S_NUM_0)); TEST_ASSERT(initial_size == esp_get_free_heap_size()); } @@ -524,5 +557,97 @@ TEST_CASE("I2S APLL clock variation test", "[i2s]") vTaskDelay(100 / portTICK_PERIOD_MS); TEST_ASSERT(initial_size == esp_get_free_heap_size()); } - +#endif + +#if SOC_I2S_SUPPORTS_ADC +/* Only ESP32 need I2S adc/dac test */ +TEST_CASE("I2S adc test", "[i2s]") +{ + // init I2S ADC + i2s_config_t i2s_config = { + .mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN, + .sample_rate = SAMPLE_RATE, + .bits_per_sample = SAMPLE_BITS, + .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, + .intr_alloc_flags = 0, + .dma_buf_count = 2, + .dma_buf_len = 1024, + .use_apll = 0, + }; + // install and start I2S driver + i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL); + // init ADC pad + i2s_set_adc_mode(ADC_UNIT_1, ADC1_CHANNEL_4); + // enable adc sampling, ADC_WIDTH_BIT_12, ADC_ATTEN_DB_11 hard-coded in adc_i2s_mode_init + i2s_adc_enable(I2S_NUM_0); + // init read buffer + uint16_t *i2sReadBuffer = (uint16_t *)calloc(1024, sizeof(uint16_t)); + size_t bytesRead; + + for (int loop = 0; loop < 10; loop++) { + for (int level = 0; level <= 1; level++) { + if (level == 0) { + gpio_set_pull_mode(ADC1_CHANNEL_4_IO, GPIO_PULLDOWN_ONLY); + } else { + gpio_set_pull_mode(ADC1_CHANNEL_4_IO, GPIO_PULLUP_ONLY); + } + vTaskDelay(200 / portTICK_RATE_MS); + // read data from adc, will block until buffer is full + i2s_read(I2S_NUM_0, (void *)i2sReadBuffer, 1024 * sizeof(uint16_t), &bytesRead, portMAX_DELAY); + + // calc average + int64_t adcSumValue = 0; + for (size_t i = 0; i < 1024; i++) { + adcSumValue += i2sReadBuffer[i] & 0xfff; + } + int adcAvgValue = adcSumValue / 1024; + printf("adc average val: %d\n", adcAvgValue); + + if (level == 0) { + if (adcAvgValue > 100) { + i2s_adc_disable(I2S_NUM_0); + free(i2sReadBuffer); + i2s_driver_uninstall(I2S_NUM_0); + TEST_ASSERT_LESS_THAN(100, adcAvgValue); + } + } else { + if (adcAvgValue < 4000) { + i2s_adc_disable(I2S_NUM_0); + free(i2sReadBuffer); + i2s_driver_uninstall(I2S_NUM_0); + TEST_ASSERT_GREATER_THAN(4000, adcAvgValue); + } + } + } + } + + i2s_adc_disable(I2S_NUM_0); + free(i2sReadBuffer); + i2s_driver_uninstall(I2S_NUM_0); +} +#endif + +#if SOC_I2S_SUPPORTS_DAC +TEST_CASE("I2S dac test", "[i2s]") +{ + // dac, adc i2s + i2s_config_t i2s_config = { + .mode = I2S_MODE_MASTER | I2S_MODE_TX, + .sample_rate = SAMPLE_RATE, + .bits_per_sample = SAMPLE_BITS, + .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, + .communication_format = I2S_COMM_FORMAT_STAND_I2S, + .dma_buf_count = 6, + .dma_buf_len = 60, + .use_apll = 0, + .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, + }; + + //install and start i2s driver + TEST_ESP_OK(i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL)); + //for internal DAC, this will enable both of the internal channels + TEST_ESP_OK(i2s_set_pin(I2S_NUM_0, NULL)); + //stop & destroy i2s driver + TEST_ESP_OK(i2s_driver_uninstall(I2S_NUM_0)); +} #endif diff --git a/components/driver/test/test_pcnt.c b/components/driver/test/test_pcnt.c index f26594f203..ed094c14e9 100644 --- a/components/driver/test/test_pcnt.c +++ b/components/driver/test/test_pcnt.c @@ -28,6 +28,7 @@ #include "esp_attr.h" #include "esp_log.h" #include "soc/gpio_periph.h" +#include "soc/pcnt_struct.h" #include "unity.h" #include "esp_rom_gpio.h" @@ -59,7 +60,7 @@ static void pcnt_test_io_config(int ctrl_level) gpio_set_direction(PULSE_IO, GPIO_MODE_INPUT_OUTPUT); esp_rom_gpio_connect_out_signal(PULSE_IO, LEDC_LS_SIG_OUT1_IDX, 0, 0); // LEDC_TIMER_1, LEDC_LOW_SPEED_MODE esp_rom_gpio_connect_in_signal(PULSE_IO, PCNT_SIG_CH0_IN0_IDX, 0); // PCNT_UNIT_0, PCNT_CHANNEL_0 - esp_rom_gpio_connect_in_signal(ctrl_level ? GPIO_MATRIX_CONST_ONE_INPUT: GPIO_MATRIX_CONST_ZERO_INPUT, PCNT_CTRL_CH0_IN0_IDX, 0); // PCNT_UNIT_0, PCNT_CHANNEL_0 + esp_rom_gpio_connect_in_signal(ctrl_level ? GPIO_MATRIX_CONST_ONE_INPUT : GPIO_MATRIX_CONST_ZERO_INPUT, PCNT_CTRL_CH0_IN0_IDX, 0); // PCNT_UNIT_0, PCNT_CHANNEL_0 } /* use LEDC to produce pulse for PCNT @@ -96,7 +97,7 @@ static void IRAM_ATTR pcnt_intr_handler(void *arg) uint32_t status; BaseType_t port_status = pdFALSE; - for (i = 0; i < PCNT_UNIT_MAX; i++) { + for (i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) { if (intr_status & (BIT(i))) { status = PCNT.status_unit[i].val; PCNT.int_clr.val = BIT(i); @@ -108,7 +109,7 @@ static void IRAM_ATTR pcnt_intr_handler(void *arg) } } -static void event_calculate(event_times* event) +static void event_calculate(event_times *event) { int16_t test_counter = 0; int times = 0; @@ -147,7 +148,7 @@ static void event_calculate(event_times* event) times++; } printf("%d, %d, %d, %d, %d, %d\n", event->h_threshold, event->l_threshold, - event->l_limit, event->h_limit, event->zero_times, event->filter_time); + event->l_limit, event->h_limit, event->zero_times, event->filter_time); } /* @@ -333,11 +334,11 @@ TEST_CASE("PCNT test config", "[pcnt]") pcnt_config_t temp_pcnt_config = pcnt_config; TEST_ESP_OK(pcnt_unit_config(&pcnt_config)); - // test PCNT_UNIT_MAX units, from 0-(PCNT_UNIT_MAX-1) + // test SOC_PCNT_UNITS_PER_GROUP units, from 0-(SOC_PCNT_UNITS_PER_GROUP-1) pcnt_config = temp_pcnt_config; - pcnt_config.unit = PCNT_UNIT_MAX; + pcnt_config.unit = SOC_PCNT_UNITS_PER_GROUP; TEST_ASSERT_NOT_NULL((void *)pcnt_unit_config(&pcnt_config)); - for (int i = 0; i < PCNT_UNIT_MAX; i++) { + for (int i = 0; i < SOC_PCNT_UNITS_PER_GROUP; i++) { pcnt_config.unit = i; TEST_ESP_OK(pcnt_unit_config(&pcnt_config)); } diff --git a/components/driver/test/test_pwm.c b/components/driver/test/test_pwm.c index 4174757daf..fb34bacc25 100644 --- a/components/driver/test/test_pwm.c +++ b/components/driver/test/test_pwm.c @@ -12,6 +12,7 @@ #include "soc/soc_caps.h" #include "hal/gpio_hal.h" #include "esp_rom_gpio.h" +#include "soc/rtc.h" #if SOC_MCPWM_SUPPORTED #include "soc/mcpwm_periph.h" #include "driver/pcnt.h" @@ -23,19 +24,19 @@ #define TEST_PWMA_GPIO (2) #define TEST_PWMB_GPIO (4) #define TEST_FAULT_GPIO (21) -#define TEST_SYNC_GPIO (21) +#define TEST_SYNC_GPIO_0 (21) +#define TEST_SYNC_GPIO_1 (18) +#define TEST_SYNC_GPIO_2 (19) #define TEST_CAP_GPIO (21) #define MCPWM_TEST_GROUP_CLK_HZ (SOC_MCPWM_BASE_CLK_HZ / 16) #define MCPWM_TEST_TIMER_CLK_HZ (MCPWM_TEST_GROUP_CLK_HZ / 10) - -static mcpwm_dev_t *MCPWM[2] = {&MCPWM0, &MCPWM1}; // interrupt handling still lacks API to get/clear pending event, currently we have to read/write interrupt register const static mcpwm_io_signals_t pwma[] = {MCPWM0A, MCPWM1A, MCPWM2A}; const static mcpwm_io_signals_t pwmb[] = {MCPWM0B, MCPWM1B, MCPWM2B}; const static mcpwm_fault_signal_t fault_sig_array[] = {MCPWM_SELECT_F0, MCPWM_SELECT_F1, MCPWM_SELECT_F2}; const static mcpwm_io_signals_t fault_io_sig_array[] = {MCPWM_FAULT_0, MCPWM_FAULT_1, MCPWM_FAULT_2}; -const static mcpwm_sync_signal_t sync_sig_array[] = {MCPWM_SELECT_SYNC0, MCPWM_SELECT_SYNC1, MCPWM_SELECT_SYNC2}; +const static mcpwm_sync_signal_t sync_sig_array[] = {MCPWM_SELECT_GPIO_SYNC0, MCPWM_SELECT_GPIO_SYNC1, MCPWM_SELECT_GPIO_SYNC2}; const static mcpwm_io_signals_t sync_io_sig_array[] = {MCPWM_SYNC_0, MCPWM_SYNC_1, MCPWM_SYNC_2}; const static mcpwm_capture_signal_t cap_sig_array[] = {MCPWM_SELECT_CAP0, MCPWM_SELECT_CAP1, MCPWM_SELECT_CAP2}; const static mcpwm_io_signals_t cap_io_sig_array[] = {MCPWM_CAP_0, MCPWM_CAP_1, MCPWM_CAP_2}; @@ -354,18 +355,25 @@ static void mcpwm_sync_test(mcpwm_unit_t unit, mcpwm_timer_t timer) mcpwm_io_signals_t sync_io_sig = sync_io_sig_array[timer]; mcpwm_setup_testbench(unit, timer, 1000, 50.0, MCPWM_TEST_GROUP_CLK_HZ, MCPWM_TEST_TIMER_CLK_HZ); - TEST_ESP_OK(test_mcpwm_gpio_init(unit, sync_io_sig, TEST_SYNC_GPIO)); - gpio_set_level(TEST_SYNC_GPIO, 0); + TEST_ESP_OK(test_mcpwm_gpio_init(unit, sync_io_sig, TEST_SYNC_GPIO_0)); + gpio_set_level(TEST_SYNC_GPIO_0, 0); - TEST_ESP_OK(mcpwm_sync_enable(unit, timer, sync_sig, 200)); + mcpwm_sync_config_t sync_conf = { + .sync_sig = sync_sig, + .timer_val = 200, + .count_direction = MCPWM_TIMER_DIRECTION_UP, + }; + TEST_ESP_OK(mcpwm_sync_configure(unit, timer, &sync_conf)); vTaskDelay(pdMS_TO_TICKS(50)); - gpio_set_level(TEST_SYNC_GPIO, 1); // trigger an external sync event + gpio_set_level(TEST_SYNC_GPIO_0, 1); // trigger an external sync event + vTaskDelay(pdMS_TO_TICKS(50)); + mcpwm_timer_trigger_soft_sync(unit, timer); // trigger a software sync event vTaskDelay(pdMS_TO_TICKS(50)); TEST_ESP_OK(mcpwm_sync_disable(unit, timer)); TEST_ESP_OK(mcpwm_stop(unit, timer)); } -TEST_CASE("MCPWM timer sync test", "[mcpwm]") +TEST_CASE("MCPWM timer GPIO sync test", "[mcpwm]") { for (int i = 0; i < SOC_MCPWM_GROUPS; i++) { for (int j = 0; j < SOC_MCPWM_TIMERS_PER_GROUP; j++) { @@ -374,27 +382,110 @@ TEST_CASE("MCPWM timer sync test", "[mcpwm]") } } +static void mcpwm_swsync_test(mcpwm_unit_t unit) { + const uint32_t test_sync_phase = 20; + // used only in this area but need to be reset every time. mutex is not needed + // store timestamps captured from ISR callback + static uint64_t cap_timestamp[3]; + cap_timestamp[0] = 0; + cap_timestamp[1] = 0; + cap_timestamp[2] = 0; + // control the start of capture to avoid unstable data + static volatile bool log_cap; + log_cap = false; + + // cb function, to update capture value + // only log when channel1 comes at first, then channel2, and do not log further more. + bool capture_callback(mcpwm_unit_t mcpwm, mcpwm_capture_channel_id_t cap_channel, const cap_event_data_t *edata, + void *user_data) { + if (log_cap && (cap_timestamp[1] == 0 || cap_timestamp[2] == 0)) { + if (cap_channel == MCPWM_SELECT_CAP1 && cap_timestamp[1] == 0) { + cap_timestamp[1] = edata->cap_value; + } + if (cap_channel == MCPWM_SELECT_CAP2 && cap_timestamp[1] != 0) { + cap_timestamp[2] = edata->cap_value; + } + } + return false; + } + + // configure all timer output 10% PWM + for (int i = 0; i < 3; ++i) { + mcpwm_setup_testbench(unit, i, 1000, 10.0, MCPWM_TEST_GROUP_CLK_HZ, MCPWM_TEST_TIMER_CLK_HZ); + } + + vTaskDelay(pdMS_TO_TICKS(10)); + + // configure capture for verification + mcpwm_capture_config_t conf = { + .cap_edge = MCPWM_POS_EDGE, + .cap_prescale = 1, + .capture_cb = capture_callback, + .user_data = NULL, + }; + TEST_ESP_OK(test_mcpwm_gpio_init(unit, MCPWM_CAP_0, TEST_SYNC_GPIO_0)); + TEST_ESP_OK(test_mcpwm_gpio_init(unit, MCPWM_CAP_1, TEST_SYNC_GPIO_1)); + TEST_ESP_OK(test_mcpwm_gpio_init(unit, MCPWM_CAP_2, TEST_SYNC_GPIO_2)); + TEST_ESP_OK(mcpwm_capture_enable_channel(unit, MCPWM_SELECT_CAP0, &conf)); + TEST_ESP_OK(mcpwm_capture_enable_channel(unit, MCPWM_SELECT_CAP1, &conf)); + TEST_ESP_OK(mcpwm_capture_enable_channel(unit, MCPWM_SELECT_CAP2, &conf)); + // timer0 produce sync sig at TEZ, timer1 and timer2 consume, to make sure last two can be synced precisely + // timer1 and timer2 will be synced with TEZ of timer0 at a known phase. + mcpwm_sync_config_t sync_conf = { + .sync_sig = MCPWM_SELECT_TIMER0_SYNC, + .timer_val = 0, + .count_direction = MCPWM_TIMER_DIRECTION_UP, + }; + TEST_ESP_OK(mcpwm_sync_configure(unit, MCPWM_TIMER_1, &sync_conf)); + sync_conf.timer_val = 1000 - test_sync_phase; + TEST_ESP_OK(mcpwm_sync_configure(unit, MCPWM_TIMER_2, &sync_conf)); + TEST_ESP_OK(mcpwm_set_timer_sync_output(unit, MCPWM_TIMER_0, MCPWM_SWSYNC_SOURCE_TEZ)); + // init gpio at the end + TEST_ESP_OK(test_mcpwm_gpio_init(unit, MCPWM0A, TEST_SYNC_GPIO_0)); + TEST_ESP_OK(test_mcpwm_gpio_init(unit, MCPWM1A, TEST_SYNC_GPIO_1)); + TEST_ESP_OK(test_mcpwm_gpio_init(unit, MCPWM2A, TEST_SYNC_GPIO_2)); + + vTaskDelay(pdMS_TO_TICKS(100)); + + log_cap = true; + + vTaskDelay(pdMS_TO_TICKS(100)); + + uint32_t delta_timestamp_us = (cap_timestamp[2] - cap_timestamp[1]) * 1000000 / rtc_clk_apb_freq_get(); + uint32_t expected_phase_us = 1000000 / mcpwm_get_frequency(unit, MCPWM_TIMER_0) * test_sync_phase / 1000; + // accept +-2 error + TEST_ASSERT_UINT32_WITHIN(2, expected_phase_us, delta_timestamp_us); + + // tear down + for (int i = 0; i < 3; ++i) { + TEST_ESP_OK(mcpwm_capture_disable_channel(unit, i)); + TEST_ESP_OK(mcpwm_sync_disable(unit, i)); + TEST_ESP_OK(mcpwm_stop(unit, i)); + } +} + +TEST_CASE("MCPWM timer swsync test", "[mcpwm]") +{ + for (int i = 0; i < SOC_MCPWM_GROUPS; i++) { + mcpwm_swsync_test(i); + } +} + // ------------------------------------------------------------------------------------- +typedef struct { + mcpwm_unit_t unit; + TaskHandle_t task_hdl; +} test_capture_callback_data_t; + +static bool test_mcpwm_intr_handler(mcpwm_unit_t mcpwm, mcpwm_capture_channel_id_t cap_sig, const cap_event_data_t *edata, void *arg) { + BaseType_t high_task_wakeup = pdFALSE; + test_capture_callback_data_t *cb_data = (test_capture_callback_data_t *)arg; + vTaskNotifyGiveFromISR(cb_data->task_hdl, &high_task_wakeup); + return high_task_wakeup == pdTRUE; +} static void mcpwm_capture_test(mcpwm_unit_t unit, mcpwm_capture_signal_t cap_chan) { - typedef struct { - mcpwm_unit_t unit; - TaskHandle_t task_hdl; - } test_capture_callback_data_t; - - void test_mcpwm_intr_handler(void *arg) { - BaseType_t high_task_wakeup = pdFALSE; - test_capture_callback_data_t *cb_data = (test_capture_callback_data_t *)arg; - uint32_t status = MCPWM[cb_data->unit]->int_st.val; - MCPWM[cb_data->unit]->int_clr.val = status; - vTaskNotifyGiveFromISR(cb_data->task_hdl, &high_task_wakeup); - if (high_task_wakeup == pdTRUE) { - portYIELD_FROM_ISR(); - } - } - - intr_handle_t mcpwm_intr = NULL; test_capture_callback_data_t callback_data = { .unit = unit, .task_hdl = xTaskGetCurrentTaskHandle(), @@ -402,17 +493,23 @@ static void mcpwm_capture_test(mcpwm_unit_t unit, mcpwm_capture_signal_t cap_cha //each timer test the capture sig with the same id with it. mcpwm_io_signals_t cap_io = cap_io_sig_array[cap_chan]; - mcpwm_capture_signal_t cap_sig = cap_sig_array[cap_chan]; + mcpwm_capture_channel_id_t cap_channel = cap_sig_array[cap_chan]; TEST_ESP_OK(test_mcpwm_gpio_init(unit, cap_io, TEST_CAP_GPIO)); - TEST_ESP_OK(mcpwm_capture_enable(unit, cap_sig, MCPWM_POS_EDGE, 0)); - TEST_ESP_OK(mcpwm_isr_register(unit, test_mcpwm_intr_handler, &callback_data, 0, &mcpwm_intr)); + mcpwm_capture_config_t conf = { + .cap_edge = MCPWM_POS_EDGE, + .cap_prescale = 1, + .capture_cb = test_mcpwm_intr_handler, + .user_data = &callback_data + }; + TEST_ESP_OK(mcpwm_capture_enable_channel(unit, cap_channel, &conf)); // generate an posage gpio_set_level(TEST_CAP_GPIO, 0); gpio_set_level(TEST_CAP_GPIO, 1); vTaskDelay(pdMS_TO_TICKS(100)); TEST_ASSERT_NOT_EQUAL(0, ulTaskNotifyTake(pdFALSE, pdMS_TO_TICKS(40))); uint32_t cap_val0 = mcpwm_capture_signal_get_value(unit, cap_chan); + // generate another posage gpio_set_level(TEST_CAP_GPIO, 0); gpio_set_level(TEST_CAP_GPIO, 1); @@ -421,8 +518,7 @@ static void mcpwm_capture_test(mcpwm_unit_t unit, mcpwm_capture_signal_t cap_cha // capture clock source is APB (80MHz), 100ms means 8000000 ticks TEST_ASSERT_UINT_WITHIN(100000, 8000000, cap_val1 - cap_val0); - TEST_ESP_OK(mcpwm_capture_disable(unit, cap_sig)); - TEST_ESP_OK(esp_intr_free(mcpwm_intr)); + TEST_ESP_OK(mcpwm_capture_disable_channel(unit, cap_channel)); } TEST_CASE("MCPWM capture test", "[mcpwm]") diff --git a/components/driver/test/test_timer.c b/components/driver/test/test_timer.c index fde33e3bf8..48eb782c5b 100644 --- a/components/driver/test/test_timer.c +++ b/components/driver/test/test_timer.c @@ -960,8 +960,8 @@ TEST_CASE("Timer memory test", "[hw_timer]") // This case will check under this fix, whether the interrupt status is cleared after timer_group initialization. static void timer_group_test_init(void) { - static const uint32_t time_ms = 100; //Alarm value 100ms. - static const uint16_t timer_div = 10; //Timer prescaler + static const uint32_t time_ms = 100; // Alarm value 100ms. + static const uint16_t timer_div = TIMER_DIVIDER; // Timer prescaler static const uint32_t ste_val = time_ms * (TIMER_BASE_CLK / timer_div / 1000); timer_config_t config = { .divider = timer_div, @@ -998,6 +998,9 @@ static void timer_group_test_second_stage(void) { TEST_ASSERT_EQUAL(ESP_RST_SW, esp_reset_reason()); timer_group_test_init(); + TEST_ASSERT_EQUAL(0, timer_group_get_intr_status_in_isr(TIMER_GROUP_0) & TIMER_INTR_T0); + // After enable the interrupt, timer alarm should not trigger immediately + TEST_ESP_OK(timer_enable_intr(TIMER_GROUP_0, TIMER_0)); //After the timer_group is initialized, TIMERG0.int_raw.t0 should be cleared. TEST_ASSERT_EQUAL(0, timer_group_get_intr_status_in_isr(TIMER_GROUP_0) & TIMER_INTR_T0); } @@ -1006,3 +1009,34 @@ TEST_CASE_MULTIPLE_STAGES("timer_group software reset test", "[intr_status][intr_status = 0]", timer_group_test_first_stage, timer_group_test_second_stage); + +// +// Timer check reinitialization sequence +// +TEST_CASE("Timer check reinitialization sequence", "[hw_timer]") +{ + // 1. step - install driver + timer_group_test_init(); + // 2 - register interrupt and start timer + TEST_ESP_OK(timer_enable_intr(TIMER_GROUP_0, TIMER_0)); + TEST_ESP_OK(timer_start(TIMER_GROUP_0, TIMER_0)); + // Do some work + vTaskDelay(80 / portTICK_PERIOD_MS); + // 3 - deinit timer driver + TEST_ESP_OK(timer_deinit(TIMER_GROUP_0, TIMER_0)); + timer_config_t config = { + .divider = TIMER_DIVIDER, + .counter_dir = TIMER_COUNT_UP, + .counter_en = TIMER_START, + .alarm_en = TIMER_ALARM_EN, + .intr_type = TIMER_INTR_LEVEL, + .auto_reload = TIMER_AUTORELOAD_EN, + }; + // 4 - reinstall driver + TEST_ESP_OK(timer_init(TIMER_GROUP_0, TIMER_0, &config)); + // 5 - enable interrupt + TEST_ESP_OK(timer_enable_intr(TIMER_GROUP_0, TIMER_0)); + vTaskDelay(30 / portTICK_PERIOD_MS); + // The pending timer interrupt should not be triggered + TEST_ASSERT_EQUAL(0, timer_group_get_intr_status_in_isr(TIMER_GROUP_0) & TIMER_INTR_T0); +} diff --git a/components/driver/test/test_uart.c b/components/driver/test/test_uart.c index 99f2781ccf..3c3f7eface 100644 --- a/components/driver/test/test_uart.c +++ b/components/driver/test/test_uart.c @@ -276,7 +276,7 @@ TEST_CASE("uart read write test", "[uart]") TEST_ESP_OK(uart_set_loop_back(uart_num, true)); TEST_ESP_OK(uart_set_pin(uart_num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART1_CTS_PIN)); //Connect the RTS out_signal to the CTS pin (which is mapped to CTS in_signal) - esp_rom_gpio_connect_out_signal(UART1_CTS_PIN, uart_periph_signal[uart_num].rts_sig, 0, 0); + esp_rom_gpio_connect_out_signal(UART1_CTS_PIN, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RTS_PIN_IDX), 0, 0); TEST_ESP_OK(uart_wait_tx_done(uart_num, portMAX_DELAY)); vTaskDelay(1 / portTICK_PERIOD_MS); // make sure last byte has flushed from TX FIFO @@ -345,7 +345,7 @@ TEST_CASE("uart tx with ringbuffer test", "[uart]") TEST_ESP_OK(uart_set_loop_back(uart_num, true)); TEST_ESP_OK(uart_set_pin(uart_num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART1_CTS_PIN)); //Connect the RTS out_signal to the CTS pin (which is mapped to CTS in_signal) - esp_rom_gpio_connect_out_signal(UART1_CTS_PIN, uart_periph_signal[uart_num].rts_sig, 0, 0); + esp_rom_gpio_connect_out_signal(UART1_CTS_PIN, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RTS_PIN_IDX), 0, 0); for (int i = 0; i < 1024; i++) { wr_data[i] = i; diff --git a/components/driver/test/touch_sensor_test/test_esp32s2.c b/components/driver/test/touch_sensor_test/test_esp32s2.c index 741adce9b4..a5ddf94ee7 100644 --- a/components/driver/test/touch_sensor_test/test_esp32s2.c +++ b/components/driver/test/touch_sensor_test/test_esp32s2.c @@ -29,7 +29,7 @@ #include "soc/rtc_cntl_struct.h" #include "soc/rtc_io_reg.h" #include "soc/rtc_io_struct.h" -#include "soc/apb_ctrl_reg.h" +#include "soc/syscon_reg.h" #include "driver/rtc_io.h" #include "esp_rom_sys.h" @@ -37,7 +37,7 @@ static const char *TAG = "test_touch"; #define PLATFORM_SELECT (1) //0: pxp; 1: chip #if (PLATFORM_SELECT == 0) //PXP platform -#define SET_BREAK_POINT(flag) REG_WRITE(APB_CTRL_DATE_REG, flag) +#define SET_BREAK_POINT(flag) REG_WRITE(SYSCON_DATE_REG, flag) //PXP clk is slower. #define SYS_DELAY_TIME_MOM (1/40) #define RTC_SLOW_CLK_FLAG 1 // Slow clock is 32KHz. diff --git a/components/driver/timer.c b/components/driver/timer.c index 38b9f7ded3..b31a784d4c 100644 --- a/components/driver/timer.c +++ b/components/driver/timer.c @@ -282,13 +282,13 @@ esp_err_t timer_init(timer_group_t group_num, timer_idx_t timer_num, const timer TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]); timer_hal_init(&(p_timer_obj[group_num][timer_num]->hal), group_num, timer_num); - timer_hal_intr_disable(&(p_timer_obj[group_num][timer_num]->hal)); + timer_hal_reset_periph(&(p_timer_obj[group_num][timer_num]->hal)); timer_hal_clear_intr_status(&(p_timer_obj[group_num][timer_num]->hal)); timer_hal_set_auto_reload(&(p_timer_obj[group_num][timer_num]->hal), config->auto_reload); timer_hal_set_divider(&(p_timer_obj[group_num][timer_num]->hal), config->divider); timer_hal_set_counter_increase(&(p_timer_obj[group_num][timer_num]->hal), config->counter_dir); timer_hal_set_alarm_enable(&(p_timer_obj[group_num][timer_num]->hal), config->alarm_en); - timer_hal_set_level_int_enable(&(p_timer_obj[group_num][timer_num]->hal), true); + timer_hal_set_level_int_enable(&(p_timer_obj[group_num][timer_num]->hal), config->intr_type == TIMER_INTR_LEVEL); if (config->intr_type != TIMER_INTR_LEVEL) { ESP_LOGW(TIMER_TAG, "only support Level Interrupt, switch to Level Interrupt instead"); } diff --git a/components/driver/twai.c b/components/driver/twai.c index 08b8d048f0..17d34e9ccd 100644 --- a/components/driver/twai.c +++ b/components/driver/twai.c @@ -130,6 +130,7 @@ static inline void twai_handle_rx_buffer_frames(BaseType_t *task_woken, int *ale //Valid frame copied from RX buffer if (xQueueSendFromISR(p_twai_obj->rx_queue, &frame, task_woken) == pdTRUE) { p_twai_obj->rx_msg_count++; + twai_alert_handler(TWAI_ALERT_RX_DATA, alert_req); } else { //Failed to send to queue p_twai_obj->rx_missed_count++; twai_alert_handler(TWAI_ALERT_RX_QUEUE_FULL, alert_req); @@ -149,6 +150,7 @@ static inline void twai_handle_rx_buffer_frames(BaseType_t *task_woken, int *ale //Valid frame copied from RX buffer if (xQueueSendFromISR(p_twai_obj->rx_queue, &frame, task_woken) == pdTRUE) { p_twai_obj->rx_msg_count++; + twai_alert_handler(TWAI_ALERT_RX_DATA, alert_req); } else { p_twai_obj->rx_missed_count++; twai_alert_handler(TWAI_ALERT_RX_QUEUE_FULL, alert_req); @@ -391,8 +393,6 @@ cleanup: return NULL; } - - /* ---------------------------- Public Functions ---------------------------- */ esp_err_t twai_driver_install(const twai_general_config_t *g_config, const twai_timing_config_t *t_config, const twai_filter_config_t *f_config) diff --git a/components/driver/uart.c b/components/driver/uart.c index bda9a712b6..8bc55f25c9 100644 --- a/components/driver/uart.c +++ b/components/driver/uart.c @@ -38,15 +38,17 @@ #endif #ifdef CONFIG_UART_ISR_IN_IRAM -#define UART_ISR_ATTR IRAM_ATTR +#define UART_ISR_ATTR IRAM_ATTR +#define UART_MALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT) #else #define UART_ISR_ATTR +#define UART_MALLOC_CAPS MALLOC_CAP_DEFAULT #endif #define XOFF (0x13) #define XON (0x11) -static const char* UART_TAG = "uart"; +static const char *UART_TAG = "uart"; #define UART_EMPTY_THRESH_DEFAULT (10) #define UART_FULL_THRESH_DEFAULT (120) @@ -94,47 +96,56 @@ typedef struct { int wr; int rd; int len; - int* data; + int *data; } uart_pat_rb_t; typedef struct { uart_port_t uart_num; /*!< UART port number*/ - int queue_size; /*!< UART event queue size*/ - QueueHandle_t xQueueUart; /*!< UART queue handler*/ + int event_queue_size; /*!< UART event queue size*/ intr_handle_t intr_handle; /*!< UART interrupt handle*/ uart_mode_t uart_mode; /*!< UART controller actual mode set by uart_set_mode() */ bool coll_det_flg; /*!< UART collision detection flag */ bool rx_always_timeout_flg; /*!< UART always detect rx timeout flag */ - - //rx parameters - int rx_buffered_len; /*!< UART cached data length */ - SemaphoreHandle_t rx_mux; /*!< UART RX data mutex*/ + int rx_buffered_len; /*!< UART cached data length */ int rx_buf_size; /*!< RX ring buffer size */ - RingbufHandle_t rx_ring_buf; /*!< RX ring buffer handler*/ bool rx_buffer_full_flg; /*!< RX ring buffer full flag. */ - uint32_t rx_cur_remain; /*!< Data number that waiting to be read out in ring buffer item*/ - uint8_t* rx_ptr; /*!< pointer to the current data in ring buffer*/ - uint8_t* rx_head_ptr; /*!< pointer to the head of RX item*/ + uint32_t rx_cur_remain; /*!< Data number that waiting to be read out in ring buffer item*/ + uint8_t *rx_ptr; /*!< pointer to the current data in ring buffer*/ + uint8_t *rx_head_ptr; /*!< pointer to the head of RX item*/ uint8_t rx_data_buf[SOC_UART_FIFO_LEN]; /*!< Data buffer to stash FIFO data*/ uint8_t rx_stash_len; /*!< stashed data length.(When using flow control, after reading out FIFO data, if we fail to push to buffer, we can just stash them.) */ uart_pat_rb_t rx_pattern_pos; - - //tx parameters - SemaphoreHandle_t tx_fifo_sem; /*!< UART TX FIFO semaphore*/ - SemaphoreHandle_t tx_mux; /*!< UART TX mutex*/ - SemaphoreHandle_t tx_done_sem; /*!< UART TX done semaphore*/ - SemaphoreHandle_t tx_brk_sem; /*!< UART TX send break done semaphore*/ int tx_buf_size; /*!< TX ring buffer size */ - RingbufHandle_t tx_ring_buf; /*!< TX ring buffer handler*/ bool tx_waiting_fifo; /*!< this flag indicates that some task is waiting for FIFO empty interrupt, used to send all data without any data buffer*/ - uint8_t* tx_ptr; /*!< TX data pointer to push to FIFO in TX buffer mode*/ - uart_tx_data_t* tx_head; /*!< TX data pointer to head of the current buffer in TX ring buffer*/ + uint8_t *tx_ptr; /*!< TX data pointer to push to FIFO in TX buffer mode*/ + uart_tx_data_t *tx_head; /*!< TX data pointer to head of the current buffer in TX ring buffer*/ uint32_t tx_len_tot; /*!< Total length of current item in ring buffer*/ uint32_t tx_len_cur; uint8_t tx_brk_flg; /*!< Flag to indicate to send a break signal in the end of the item sending procedure */ uint8_t tx_brk_len; /*!< TX break signal cycle length/number */ uint8_t tx_waiting_brk; /*!< Flag to indicate that TX FIFO is ready to send break signal after FIFO is empty, do not push data into TX FIFO right now.*/ uart_select_notif_callback_t uart_select_notif_callback; /*!< Notification about select() events */ + QueueHandle_t event_queue; /*!< UART event queue handler*/ + RingbufHandle_t rx_ring_buf; /*!< RX ring buffer handler*/ + RingbufHandle_t tx_ring_buf; /*!< TX ring buffer handler*/ + SemaphoreHandle_t rx_mux; /*!< UART RX data mutex*/ + SemaphoreHandle_t tx_mux; /*!< UART TX mutex*/ + SemaphoreHandle_t tx_fifo_sem; /*!< UART TX FIFO semaphore*/ + SemaphoreHandle_t tx_done_sem; /*!< UART TX done semaphore*/ + SemaphoreHandle_t tx_brk_sem; /*!< UART TX send break done semaphore*/ +#if CONFIG_UART_ISR_IN_IRAM + void *event_queue_storage; + void *event_queue_struct; + void *rx_ring_buf_storage; + void *rx_ring_buf_struct; + void *tx_ring_buf_storage; + void *tx_ring_buf_struct; + void *rx_mux_struct; + void *tx_mux_struct; + void *tx_fifo_sem_struct; + void *tx_done_sem_struct; + void *tx_brk_sem_struct; +#endif } uart_obj_t; typedef struct { @@ -189,16 +200,16 @@ static void uart_module_enable(uart_port_t uart_num) if (uart_context[uart_num].hw_enabled != true) { periph_module_enable(uart_periph_signal[uart_num].module); if (uart_num != CONFIG_ESP_CONSOLE_UART_NUM) { - // Workaround for ESP32C3: enable core reset - // before enabling uart module clock - // to prevent uart output garbage value. - #if SOC_UART_REQUIRE_CORE_RESET + // Workaround for ESP32C3: enable core reset + // before enabling uart module clock + // to prevent uart output garbage value. +#if SOC_UART_REQUIRE_CORE_RESET uart_hal_set_reset_core(&(uart_context[uart_num].hal), true); periph_module_reset(uart_periph_signal[uart_num].module); uart_hal_set_reset_core(&(uart_context[uart_num].hal), false); - #else +#else periph_module_reset(uart_periph_signal[uart_num].module); - #endif +#endif } uart_context[uart_num].hw_enabled = true; } @@ -227,7 +238,7 @@ esp_err_t uart_set_word_length(uart_port_t uart_num, uart_word_length_t data_bit return ESP_OK; } -esp_err_t uart_get_word_length(uart_port_t uart_num, uart_word_length_t* data_bit) +esp_err_t uart_get_word_length(uart_port_t uart_num, uart_word_length_t *data_bit) { ESP_RETURN_ON_FALSE((uart_num < UART_NUM_MAX), ESP_FAIL, UART_TAG, "uart_num error"); uart_hal_get_data_bit_num(&(uart_context[uart_num].hal), data_bit); @@ -244,10 +255,12 @@ esp_err_t uart_set_stop_bits(uart_port_t uart_num, uart_stop_bits_t stop_bit) return ESP_OK; } -esp_err_t uart_get_stop_bits(uart_port_t uart_num, uart_stop_bits_t* stop_bit) +esp_err_t uart_get_stop_bits(uart_port_t uart_num, uart_stop_bits_t *stop_bit) { ESP_RETURN_ON_FALSE((uart_num < UART_NUM_MAX), ESP_FAIL, UART_TAG, "uart_num error"); + UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); uart_hal_get_stop_bits(&(uart_context[uart_num].hal), stop_bit); + UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock)); return ESP_OK; } @@ -260,10 +273,12 @@ esp_err_t uart_set_parity(uart_port_t uart_num, uart_parity_t parity_mode) return ESP_OK; } -esp_err_t uart_get_parity(uart_port_t uart_num, uart_parity_t* parity_mode) +esp_err_t uart_get_parity(uart_port_t uart_num, uart_parity_t *parity_mode) { ESP_RETURN_ON_FALSE((uart_num < UART_NUM_MAX), ESP_FAIL, UART_TAG, "uart_num error"); + UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); uart_hal_get_parity(&(uart_context[uart_num].hal), parity_mode); + UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock)); return ESP_OK; } @@ -322,7 +337,7 @@ esp_err_t uart_set_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t flow return ESP_OK; } -esp_err_t uart_get_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t* flow_ctrl) +esp_err_t uart_get_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t *flow_ctrl) { ESP_RETURN_ON_FALSE((uart_num < UART_NUM_MAX), ESP_FAIL, UART_TAG, "uart_num error"); UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); @@ -359,7 +374,7 @@ esp_err_t uart_disable_intr_mask(uart_port_t uart_num, uint32_t disable_mask) static esp_err_t uart_pattern_link_free(uart_port_t uart_num) { - int* pdata = NULL; + int *pdata = NULL; UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); if (p_uart_obj[uart_num]->rx_pattern_pos.data != NULL) { pdata = p_uart_obj[uart_num]->rx_pattern_pos.data; @@ -375,13 +390,15 @@ static esp_err_t uart_pattern_link_free(uart_port_t uart_num) static esp_err_t UART_ISR_ATTR uart_pattern_enqueue(uart_port_t uart_num, int pos) { esp_err_t ret = ESP_OK; - uart_pat_rb_t* p_pos = &p_uart_obj[uart_num]->rx_pattern_pos; + uart_pat_rb_t *p_pos = &p_uart_obj[uart_num]->rx_pattern_pos; int next = p_pos->wr + 1; if (next >= p_pos->len) { next = 0; } if (next == p_pos->rd) { +#ifndef CONFIG_UART_ISR_IN_IRAM //Only log if ISR is not in IRAM ESP_EARLY_LOGW(UART_TAG, "Fail to enqueue pattern position, pattern queue is full."); +#endif ret = ESP_FAIL; } else { p_pos->data[p_pos->wr] = pos; @@ -393,11 +410,11 @@ static esp_err_t UART_ISR_ATTR uart_pattern_enqueue(uart_port_t uart_num, int po static esp_err_t uart_pattern_dequeue(uart_port_t uart_num) { - if(p_uart_obj[uart_num]->rx_pattern_pos.data == NULL) { + if (p_uart_obj[uart_num]->rx_pattern_pos.data == NULL) { return ESP_ERR_INVALID_STATE; } else { esp_err_t ret = ESP_OK; - uart_pat_rb_t* p_pos = &p_uart_obj[uart_num]->rx_pattern_pos; + uart_pat_rb_t *p_pos = &p_uart_obj[uart_num]->rx_pattern_pos; if (p_pos->rd == p_pos->wr) { ret = ESP_FAIL; } else { @@ -412,9 +429,9 @@ static esp_err_t uart_pattern_dequeue(uart_port_t uart_num) static esp_err_t uart_pattern_queue_update(uart_port_t uart_num, int diff_len) { - uart_pat_rb_t* p_pos = &p_uart_obj[uart_num]->rx_pattern_pos; + uart_pat_rb_t *p_pos = &p_uart_obj[uart_num]->rx_pattern_pos; int rd = p_pos->rd; - while(rd != p_pos->wr) { + while (rd != p_pos->wr) { p_pos->data[rd] -= diff_len; int rd_rec = rd; rd ++; @@ -432,7 +449,7 @@ int uart_pattern_pop_pos(uart_port_t uart_num) { ESP_RETURN_ON_FALSE((p_uart_obj[uart_num]), (-1), UART_TAG, "uart driver error"); UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); - uart_pat_rb_t* pat_pos = &p_uart_obj[uart_num]->rx_pattern_pos; + uart_pat_rb_t *pat_pos = &p_uart_obj[uart_num]->rx_pattern_pos; int pos = -1; if (pat_pos != NULL && pat_pos->rd != pat_pos->wr) { pos = pat_pos->data[pat_pos->rd]; @@ -446,7 +463,7 @@ int uart_pattern_get_pos(uart_port_t uart_num) { ESP_RETURN_ON_FALSE((p_uart_obj[uart_num]), (-1), UART_TAG, "uart driver error"); UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); - uart_pat_rb_t* pat_pos = &p_uart_obj[uart_num]->rx_pattern_pos; + uart_pat_rb_t *pat_pos = &p_uart_obj[uart_num]->rx_pattern_pos; int pos = -1; if (pat_pos != NULL && pat_pos->rd != pat_pos->wr) { pos = pat_pos->data[pat_pos->rd]; @@ -460,12 +477,12 @@ esp_err_t uart_pattern_queue_reset(uart_port_t uart_num, int queue_length) ESP_RETURN_ON_FALSE((uart_num < UART_NUM_MAX), ESP_FAIL, UART_TAG, "uart_num error"); ESP_RETURN_ON_FALSE((p_uart_obj[uart_num]), ESP_ERR_INVALID_STATE, UART_TAG, "uart driver error"); - int* pdata = (int*) malloc(queue_length * sizeof(int)); - if(pdata == NULL) { + int *pdata = (int *) malloc(queue_length * sizeof(int)); + if (pdata == NULL) { return ESP_ERR_NO_MEM; } UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); - int* ptmp = p_uart_obj[uart_num]->rx_pattern_pos.data; + int *ptmp = p_uart_obj[uart_num]->rx_pattern_pos.data; p_uart_obj[uart_num]->rx_pattern_pos.data = pdata; p_uart_obj[uart_num]->rx_pattern_pos.len = queue_length; p_uart_obj[uart_num]->rx_pattern_pos.rd = 0; @@ -539,12 +556,12 @@ esp_err_t uart_disable_pattern_det_intr(uart_port_t uart_num) esp_err_t uart_enable_rx_intr(uart_port_t uart_num) { - return uart_enable_intr_mask(uart_num, UART_INTR_RXFIFO_FULL|UART_INTR_RXFIFO_TOUT); + return uart_enable_intr_mask(uart_num, UART_INTR_RXFIFO_FULL | UART_INTR_RXFIFO_TOUT); } esp_err_t uart_disable_rx_intr(uart_port_t uart_num) { - return uart_disable_intr_mask(uart_num, UART_INTR_RXFIFO_FULL|UART_INTR_RXFIFO_TOUT); + return uart_disable_intr_mask(uart_num, UART_INTR_RXFIFO_FULL | UART_INTR_RXFIFO_TOUT); } esp_err_t uart_disable_tx_intr(uart_port_t uart_num) @@ -564,12 +581,12 @@ esp_err_t uart_enable_tx_intr(uart_port_t uart_num, int enable, int thresh) return ESP_OK; } -esp_err_t uart_isr_register(uart_port_t uart_num, void (*fn)(void*), void * arg, int intr_alloc_flags, uart_isr_handle_t *handle) +esp_err_t uart_isr_register(uart_port_t uart_num, void (*fn)(void *), void *arg, int intr_alloc_flags, uart_isr_handle_t *handle) { int ret; ESP_RETURN_ON_FALSE((uart_num < UART_NUM_MAX), ESP_FAIL, UART_TAG, "uart_num error"); UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); - ret=esp_intr_alloc(uart_periph_signal[uart_num].irq, intr_alloc_flags, fn, arg, handle); + ret = esp_intr_alloc(uart_periph_signal[uart_num].irq, intr_alloc_flags, fn, arg, handle); UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock)); return ret; } @@ -581,44 +598,74 @@ esp_err_t uart_isr_free(uart_port_t uart_num) ESP_RETURN_ON_FALSE((p_uart_obj[uart_num]), ESP_FAIL, UART_TAG, "uart driver error"); ESP_RETURN_ON_FALSE((p_uart_obj[uart_num]->intr_handle != NULL), ESP_ERR_INVALID_ARG, UART_TAG, "uart driver error"); UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); - ret=esp_intr_free(p_uart_obj[uart_num]->intr_handle); - p_uart_obj[uart_num]->intr_handle=NULL; + ret = esp_intr_free(p_uart_obj[uart_num]->intr_handle); + p_uart_obj[uart_num]->intr_handle = NULL; UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock)); return ret; } +static bool uart_try_set_iomux_pin(uart_port_t uart_num, int io_num, uint32_t idx) +{ + /* Store a pointer to the default pin, to optimize access to its fields. */ + const uart_periph_sig_t *upin = &uart_periph_signal[uart_num].pins[idx]; + + /* In theory, if default_gpio is -1, iomux_func should also be -1, but + * let's be safe and test both. */ + if (upin->iomux_func == -1 || upin->default_gpio == -1 || upin->default_gpio != io_num) { + return false; + } + + /* Assign the correct funct to the GPIO. */ + assert (upin->iomux_func != -1); + gpio_iomux_out(io_num, upin->iomux_func, false); + + /* If the pin is input, we also have to redirect the signal, + * in order to bypasse the GPIO matrix. */ + if (upin->input) { + gpio_iomux_in(io_num, upin->signal); + } + + return true; +} + //internal signal can be output to multiple GPIO pads //only one GPIO pad can connect with input signal esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int rts_io_num, int cts_io_num) { + ESP_RETURN_ON_FALSE((uart_num >= 0), ESP_FAIL, UART_TAG, "uart_num error"); ESP_RETURN_ON_FALSE((uart_num < UART_NUM_MAX), ESP_FAIL, UART_TAG, "uart_num error"); ESP_RETURN_ON_FALSE((tx_io_num < 0 || (GPIO_IS_VALID_OUTPUT_GPIO(tx_io_num))), ESP_FAIL, UART_TAG, "tx_io_num error"); ESP_RETURN_ON_FALSE((rx_io_num < 0 || (GPIO_IS_VALID_GPIO(rx_io_num))), ESP_FAIL, UART_TAG, "rx_io_num error"); ESP_RETURN_ON_FALSE((rts_io_num < 0 || (GPIO_IS_VALID_OUTPUT_GPIO(rts_io_num))), ESP_FAIL, UART_TAG, "rts_io_num error"); ESP_RETURN_ON_FALSE((cts_io_num < 0 || (GPIO_IS_VALID_GPIO(cts_io_num))), ESP_FAIL, UART_TAG, "cts_io_num error"); - if(tx_io_num >= 0) { + /* In the following statements, if the io_num is negative, no need to configure anything. */ + if (tx_io_num >= 0 && !uart_try_set_iomux_pin(uart_num, tx_io_num, SOC_UART_TX_PIN_IDX)) { gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[tx_io_num], PIN_FUNC_GPIO); gpio_set_level(tx_io_num, 1); - esp_rom_gpio_connect_out_signal(tx_io_num, uart_periph_signal[uart_num].tx_sig, 0, 0); + esp_rom_gpio_connect_out_signal(tx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_TX_PIN_IDX), 0, 0); } - if(rx_io_num >= 0) { + + if (rx_io_num >= 0 && !uart_try_set_iomux_pin(uart_num, rx_io_num, SOC_UART_RX_PIN_IDX)) { gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[rx_io_num], PIN_FUNC_GPIO); gpio_set_pull_mode(rx_io_num, GPIO_PULLUP_ONLY); gpio_set_direction(rx_io_num, GPIO_MODE_INPUT); - esp_rom_gpio_connect_in_signal(rx_io_num, uart_periph_signal[uart_num].rx_sig, 0); + esp_rom_gpio_connect_in_signal(rx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), 0); } - if(rts_io_num >= 0) { + + if (rts_io_num >= 0 && !uart_try_set_iomux_pin(uart_num, rts_io_num, SOC_UART_RTS_PIN_IDX)) { gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[rts_io_num], PIN_FUNC_GPIO); gpio_set_direction(rts_io_num, GPIO_MODE_OUTPUT); - esp_rom_gpio_connect_out_signal(rts_io_num, uart_periph_signal[uart_num].rts_sig, 0, 0); + esp_rom_gpio_connect_out_signal(rts_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RTS_PIN_IDX), 0, 0); } - if(cts_io_num >= 0) { + + if (cts_io_num >= 0 && !uart_try_set_iomux_pin(uart_num, cts_io_num, SOC_UART_CTS_PIN_IDX)) { gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[cts_io_num], PIN_FUNC_GPIO); gpio_set_pull_mode(cts_io_num, GPIO_PULLUP_ONLY); gpio_set_direction(cts_io_num, GPIO_MODE_INPUT); - esp_rom_gpio_connect_in_signal(cts_io_num, uart_periph_signal[uart_num].cts_sig, 0); + esp_rom_gpio_connect_in_signal(cts_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_CTS_PIN_IDX), 0); } + return ESP_OK; } @@ -685,16 +732,16 @@ esp_err_t uart_intr_config(uart_port_t uart_num, const uart_intr_config_t *intr_ ESP_RETURN_ON_FALSE((intr_conf), ESP_FAIL, UART_TAG, "param null"); uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), UART_LL_INTR_MASK); UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); - if(intr_conf->intr_enable_mask & UART_INTR_RXFIFO_TOUT) { + if (intr_conf->intr_enable_mask & UART_INTR_RXFIFO_TOUT) { uart_hal_set_rx_timeout(&(uart_context[uart_num].hal), intr_conf->rx_timeout_thresh); } else { //Disable rx_tout intr uart_hal_set_rx_timeout(&(uart_context[uart_num].hal), 0); } - if(intr_conf->intr_enable_mask & UART_INTR_RXFIFO_FULL) { + if (intr_conf->intr_enable_mask & UART_INTR_RXFIFO_FULL) { uart_hal_set_rxfifo_full_thr(&(uart_context[uart_num].hal), intr_conf->rxfifo_full_thresh); } - if(intr_conf->intr_enable_mask & UART_INTR_TXFIFO_EMPTY) { + if (intr_conf->intr_enable_mask & UART_INTR_TXFIFO_EMPTY) { uart_hal_set_txfifo_empty_thr(&(uart_context[uart_num].hal), intr_conf->txfifo_empty_intr_thresh); } uart_hal_ena_intr_mask(&(uart_context[uart_num].hal), intr_conf->intr_enable_mask); @@ -702,7 +749,7 @@ esp_err_t uart_intr_config(uart_port_t uart_num, const uart_intr_config_t *intr_ return ESP_OK; } -static int UART_ISR_ATTR uart_find_pattern_from_last(uint8_t* buf, int length, uint8_t pat_chr, uint8_t pat_num) +static int UART_ISR_ATTR uart_find_pattern_from_last(uint8_t *buf, int length, uint8_t pat_chr, uint8_t pat_num) { int cnt = 0; int len = length; @@ -723,37 +770,37 @@ static int UART_ISR_ATTR uart_find_pattern_from_last(uint8_t* buf, int length, u //internal isr handler for default driver code. static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param) { - uart_obj_t *p_uart = (uart_obj_t*) param; + uart_obj_t *p_uart = (uart_obj_t *) param; uint8_t uart_num = p_uart->uart_num; int rx_fifo_len = 0; uint32_t uart_intr_status = 0; uart_event_t uart_event; portBASE_TYPE HPTaskAwoken = 0; static uint8_t pat_flg = 0; - while(1) { + while (1) { // The `continue statement` may cause the interrupt to loop infinitely // we exit the interrupt here uart_intr_status = uart_hal_get_intsts_mask(&(uart_context[uart_num].hal)); //Exit form while loop - if(uart_intr_status == 0){ + if (uart_intr_status == 0) { break; } uart_event.type = UART_EVENT_MAX; - if(uart_intr_status & UART_INTR_TXFIFO_EMPTY) { + if (uart_intr_status & UART_INTR_TXFIFO_EMPTY) { UART_ENTER_CRITICAL_ISR(&(uart_context[uart_num].spinlock)); uart_hal_disable_intr_mask(&(uart_context[uart_num].hal), UART_INTR_TXFIFO_EMPTY); UART_EXIT_CRITICAL_ISR(&(uart_context[uart_num].spinlock)); uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), UART_INTR_TXFIFO_EMPTY); - if(p_uart->tx_waiting_brk) { + if (p_uart->tx_waiting_brk) { continue; } //TX semaphore will only be used when tx_buf_size is zero. - if(p_uart->tx_waiting_fifo == true && p_uart->tx_buf_size == 0) { + if (p_uart->tx_waiting_fifo == true && p_uart->tx_buf_size == 0) { p_uart->tx_waiting_fifo = false; xSemaphoreGiveFromISR(p_uart->tx_fifo_sem, &HPTaskAwoken); } else { //We don't use TX ring buffer, because the size is zero. - if(p_uart->tx_buf_size == 0) { + if (p_uart->tx_buf_size == 0) { continue; } bool en_tx_flg = false; @@ -761,25 +808,25 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param) //We need to put a loop here, in case all the buffer items are very short. //That would cause a watch_dog reset because empty interrupt happens so often. //Although this is a loop in ISR, this loop will execute at most 128 turns. - while(tx_fifo_rem) { - if(p_uart->tx_len_tot == 0 || p_uart->tx_ptr == NULL || p_uart->tx_len_cur == 0) { + while (tx_fifo_rem) { + if (p_uart->tx_len_tot == 0 || p_uart->tx_ptr == NULL || p_uart->tx_len_cur == 0) { size_t size; - p_uart->tx_head = (uart_tx_data_t*) xRingbufferReceiveFromISR(p_uart->tx_ring_buf, &size); - if(p_uart->tx_head) { + p_uart->tx_head = (uart_tx_data_t *) xRingbufferReceiveFromISR(p_uart->tx_ring_buf, &size); + if (p_uart->tx_head) { //The first item is the data description //Get the first item to get the data information - if(p_uart->tx_len_tot == 0) { + if (p_uart->tx_len_tot == 0) { p_uart->tx_ptr = NULL; p_uart->tx_len_tot = p_uart->tx_head->tx_data.size; - if(p_uart->tx_head->type == UART_DATA_BREAK) { + if (p_uart->tx_head->type == UART_DATA_BREAK) { p_uart->tx_brk_flg = 1; p_uart->tx_brk_len = p_uart->tx_head->tx_data.brk_len; } //We have saved the data description from the 1st item, return buffer. vRingbufferReturnItemFromISR(p_uart->tx_ring_buf, p_uart->tx_head, &HPTaskAwoken); - } else if(p_uart->tx_ptr == NULL) { + } else if (p_uart->tx_ptr == NULL) { //Update the TX item pointer, we will need this to return item to buffer. - p_uart->tx_ptr = (uint8_t*)p_uart->tx_head; + p_uart->tx_ptr = (uint8_t *)p_uart->tx_head; en_tx_flg = true; p_uart->tx_len_cur = size; } @@ -813,7 +860,7 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param) p_uart->tx_ptr = NULL; //Sending item done, now we need to send break if there is a record. //Set TX break signal after FIFO is empty - if(p_uart->tx_len_tot == 0 && p_uart->tx_brk_flg == 1) { + if (p_uart->tx_len_tot == 0 && p_uart->tx_brk_flg == 1) { uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), UART_INTR_TX_BRK_DONE); UART_ENTER_CRITICAL_ISR(&(uart_context[uart_num].spinlock)); uart_hal_tx_break(&(uart_context[uart_num].hal), p_uart->tx_brk_len); @@ -839,12 +886,11 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param) UART_EXIT_CRITICAL_ISR(&(uart_context[uart_num].spinlock)); } } - } - else if ((uart_intr_status & UART_INTR_RXFIFO_TOUT) - || (uart_intr_status & UART_INTR_RXFIFO_FULL) - || (uart_intr_status & UART_INTR_CMD_CHAR_DET) - ) { - if(pat_flg == 1) { + } else if ((uart_intr_status & UART_INTR_RXFIFO_TOUT) + || (uart_intr_status & UART_INTR_RXFIFO_FULL) + || (uart_intr_status & UART_INTR_CMD_CHAR_DET) + ) { + if (pat_flg == 1) { uart_intr_status |= UART_INTR_CMD_CHAR_DET; pat_flg = 0; } @@ -880,7 +926,7 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param) p_uart->rx_stash_len = rx_fifo_len; //If we fail to push data to ring buffer, we will have to stash the data, and send next time. //Mainly for applications that uses flow control or small ring buffer. - if(pdFALSE == xRingbufferSendFromISR(p_uart->rx_ring_buf, p_uart->rx_data_buf, p_uart->rx_stash_len, &HPTaskAwoken)) { + if (pdFALSE == xRingbufferSendFromISR(p_uart->rx_ring_buf, p_uart->rx_data_buf, p_uart->rx_stash_len, &HPTaskAwoken)) { p_uart->rx_buffer_full_flg = true; UART_ENTER_CRITICAL_ISR(&(uart_context[uart_num].spinlock)); uart_hal_disable_intr_mask(&(uart_context[uart_num].hal), UART_INTR_RXFIFO_TOUT | UART_INTR_RXFIFO_FULL); @@ -892,15 +938,17 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param) uart_pattern_enqueue(uart_num, p_uart->rx_buffered_len - (pat_num - rx_fifo_len)); } else { uart_pattern_enqueue(uart_num, - pat_idx <= -1 ? - //can not find the pattern in buffer, - p_uart->rx_buffered_len + p_uart->rx_stash_len : - // find the pattern in buffer - p_uart->rx_buffered_len + pat_idx); + pat_idx <= -1 ? + //can not find the pattern in buffer, + p_uart->rx_buffered_len + p_uart->rx_stash_len : + // find the pattern in buffer + p_uart->rx_buffered_len + pat_idx); } UART_EXIT_CRITICAL_ISR(&(uart_context[uart_num].spinlock)); - if ((p_uart->xQueueUart != NULL) && (pdFALSE == xQueueSendFromISR(p_uart->xQueueUart, (void * )&uart_event, &HPTaskAwoken))) { + if ((p_uart->event_queue != NULL) && (pdFALSE == xQueueSendFromISR(p_uart->event_queue, (void * )&uart_event, &HPTaskAwoken))) { +#ifndef CONFIG_UART_ISR_IN_IRAM //Only log if ISR is not in IRAM ESP_EARLY_LOGV(UART_TAG, "UART event queue full"); +#endif } } uart_event.type = UART_BUFFER_FULL; @@ -910,7 +958,7 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param) if (rx_fifo_len < pat_num) { //some of the characters are read out in last interrupt uart_pattern_enqueue(uart_num, p_uart->rx_buffered_len - (pat_num - rx_fifo_len)); - } else if(pat_idx >= 0) { + } else if (pat_idx >= 0) { // find the pattern in stash buffer. uart_pattern_enqueue(uart_num, p_uart->rx_buffered_len + pat_idx); } @@ -923,14 +971,14 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param) uart_hal_disable_intr_mask(&(uart_context[uart_num].hal), UART_INTR_RXFIFO_FULL | UART_INTR_RXFIFO_TOUT); UART_EXIT_CRITICAL_ISR(&(uart_context[uart_num].spinlock)); uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), UART_INTR_RXFIFO_FULL | UART_INTR_RXFIFO_TOUT); - if(uart_intr_status & UART_INTR_CMD_CHAR_DET) { + if (uart_intr_status & UART_INTR_CMD_CHAR_DET) { uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), UART_INTR_CMD_CHAR_DET); uart_event.type = UART_PATTERN_DET; uart_event.size = rx_fifo_len; pat_flg = 1; } } - } else if(uart_intr_status & UART_INTR_RXFIFO_OVF) { + } else if (uart_intr_status & UART_INTR_RXFIFO_OVF) { // When fifo overflows, we reset the fifo. UART_ENTER_CRITICAL_ISR(&(uart_context[uart_num].spinlock)); uart_hal_rxfifo_rst(&(uart_context[uart_num].hal)); @@ -942,10 +990,10 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param) UART_EXIT_CRITICAL_ISR(&uart_selectlock); uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), UART_INTR_RXFIFO_OVF); uart_event.type = UART_FIFO_OVF; - } else if(uart_intr_status & UART_INTR_BRK_DET) { + } else if (uart_intr_status & UART_INTR_BRK_DET) { uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), UART_INTR_BRK_DET); uart_event.type = UART_BREAK; - } else if(uart_intr_status & UART_INTR_FRAM_ERR) { + } else if (uart_intr_status & UART_INTR_FRAM_ERR) { UART_ENTER_CRITICAL_ISR(&uart_selectlock); if (p_uart->uart_select_notif_callback) { p_uart->uart_select_notif_callback(uart_num, UART_SELECT_ERROR_NOTIF, &HPTaskAwoken); @@ -953,7 +1001,7 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param) UART_EXIT_CRITICAL_ISR(&uart_selectlock); uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), UART_INTR_FRAM_ERR); uart_event.type = UART_FRAME_ERR; - } else if(uart_intr_status & UART_INTR_PARITY_ERR) { + } else if (uart_intr_status & UART_INTR_PARITY_ERR) { UART_ENTER_CRITICAL_ISR(&uart_selectlock); if (p_uart->uart_select_notif_callback) { p_uart->uart_select_notif_callback(uart_num, UART_SELECT_ERROR_NOTIF, &HPTaskAwoken); @@ -961,32 +1009,32 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param) UART_EXIT_CRITICAL_ISR(&uart_selectlock); uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), UART_INTR_PARITY_ERR); uart_event.type = UART_PARITY_ERR; - } else if(uart_intr_status & UART_INTR_TX_BRK_DONE) { + } else if (uart_intr_status & UART_INTR_TX_BRK_DONE) { UART_ENTER_CRITICAL_ISR(&(uart_context[uart_num].spinlock)); uart_hal_tx_break(&(uart_context[uart_num].hal), 0); uart_hal_disable_intr_mask(&(uart_context[uart_num].hal), UART_INTR_TX_BRK_DONE); - if(p_uart->tx_brk_flg == 1) { + if (p_uart->tx_brk_flg == 1) { uart_hal_ena_intr_mask(&(uart_context[uart_num].hal), UART_INTR_TXFIFO_EMPTY); } UART_EXIT_CRITICAL_ISR(&(uart_context[uart_num].spinlock)); uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), UART_INTR_TX_BRK_DONE); - if(p_uart->tx_brk_flg == 1) { + if (p_uart->tx_brk_flg == 1) { p_uart->tx_brk_flg = 0; p_uart->tx_waiting_brk = 0; } else { xSemaphoreGiveFromISR(p_uart->tx_brk_sem, &HPTaskAwoken); } - } else if(uart_intr_status & UART_INTR_TX_BRK_IDLE) { + } else if (uart_intr_status & UART_INTR_TX_BRK_IDLE) { UART_ENTER_CRITICAL_ISR(&(uart_context[uart_num].spinlock)); uart_hal_disable_intr_mask(&(uart_context[uart_num].hal), UART_INTR_TX_BRK_IDLE); UART_EXIT_CRITICAL_ISR(&(uart_context[uart_num].spinlock)); uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), UART_INTR_TX_BRK_IDLE); - } else if(uart_intr_status & UART_INTR_CMD_CHAR_DET) { + } else if (uart_intr_status & UART_INTR_CMD_CHAR_DET) { uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), UART_INTR_CMD_CHAR_DET); uart_event.type = UART_PATTERN_DET; } else if ((uart_intr_status & UART_INTR_RS485_PARITY_ERR) - || (uart_intr_status & UART_INTR_RS485_FRM_ERR) - || (uart_intr_status & UART_INTR_RS485_CLASH)) { + || (uart_intr_status & UART_INTR_RS485_FRM_ERR) + || (uart_intr_status & UART_INTR_RS485_CLASH)) { // RS485 collision or frame error interrupt triggered UART_ENTER_CRITICAL_ISR(&(uart_context[uart_num].spinlock)); uart_hal_rxfifo_rst(&(uart_context[uart_num].hal)); @@ -995,7 +1043,7 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param) UART_EXIT_CRITICAL_ISR(&(uart_context[uart_num].spinlock)); uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), UART_INTR_RS485_CLASH | UART_INTR_RS485_FRM_ERR | UART_INTR_RS485_PARITY_ERR); uart_event.type = UART_EVENT_MAX; - } else if(uart_intr_status & UART_INTR_TX_DONE) { + } else if (uart_intr_status & UART_INTR_TX_DONE) { if (UART_IS_MODE_SET(uart_num, UART_MODE_RS485_HALF_DUPLEX) && uart_hal_is_tx_idle(&(uart_context[uart_num].hal)) != true) { // The TX_DONE interrupt is triggered but transmit is active // then postpone interrupt processing for next interrupt @@ -1019,13 +1067,15 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param) uart_event.type = UART_EVENT_MAX; } - if(uart_event.type != UART_EVENT_MAX && p_uart->xQueueUart) { - if (pdFALSE == xQueueSendFromISR(p_uart->xQueueUart, (void * )&uart_event, &HPTaskAwoken)) { + if (uart_event.type != UART_EVENT_MAX && p_uart->event_queue) { + if (pdFALSE == xQueueSendFromISR(p_uart->event_queue, (void * )&uart_event, &HPTaskAwoken)) { +#ifndef CONFIG_UART_ISR_IN_IRAM //Only log if ISR is not in IRAM ESP_EARLY_LOGV(UART_TAG, "UART event queue full"); +#endif } } } - if(HPTaskAwoken == pdTRUE) { + if (HPTaskAwoken == pdTRUE) { portYIELD_FROM_ISR(); } } @@ -1039,11 +1089,11 @@ esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait) portTickType ticks_start = xTaskGetTickCount(); //Take tx_mux res = xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)ticks_to_wait); - if(res == pdFALSE) { + if (res == pdFALSE) { return ESP_ERR_TIMEOUT; } xSemaphoreTake(p_uart_obj[uart_num]->tx_done_sem, 0); - if(uart_hal_is_tx_idle(&(uart_context[uart_num].hal))) { + if (uart_hal_is_tx_idle(&(uart_context[uart_num].hal))) { xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); return ESP_OK; } @@ -1059,7 +1109,7 @@ esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait) } //take 2nd tx_done_sem, wait given from ISR res = xSemaphoreTake(p_uart_obj[uart_num]->tx_done_sem, (portTickType)ticks_to_wait); - if(res == pdFALSE) { + if (res == pdFALSE) { // The TX_DONE interrupt will be disabled in ISR xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); return ESP_ERR_TIMEOUT; @@ -1068,12 +1118,12 @@ esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait) return ESP_OK; } -int uart_tx_chars(uart_port_t uart_num, const char* buffer, uint32_t len) +int uart_tx_chars(uart_port_t uart_num, const char *buffer, uint32_t len) { ESP_RETURN_ON_FALSE((uart_num < UART_NUM_MAX), (-1), UART_TAG, "uart_num error"); ESP_RETURN_ON_FALSE((p_uart_obj[uart_num]), (-1), UART_TAG, "uart driver error"); ESP_RETURN_ON_FALSE(buffer, (-1), UART_TAG, "buffer null"); - if(len == 0) { + if (len == 0) { return 0; } int tx_len = 0; @@ -1084,14 +1134,14 @@ int uart_tx_chars(uart_port_t uart_num, const char* buffer, uint32_t len) uart_hal_ena_intr_mask(&(uart_context[uart_num].hal), UART_INTR_TX_DONE); UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock)); } - uart_hal_write_txfifo(&(uart_context[uart_num].hal), (const uint8_t*) buffer, len, (uint32_t *)&tx_len); + uart_hal_write_txfifo(&(uart_context[uart_num].hal), (const uint8_t *) buffer, len, (uint32_t *)&tx_len); xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); return tx_len; } -static int uart_tx_all(uart_port_t uart_num, const char* src, size_t size, bool brk_en, int brk_len) +static int uart_tx_all(uart_port_t uart_num, const char *src, size_t size, bool brk_en, int brk_len) { - if(size == 0) { + if (size == 0) { return 0; } size_t original_size = size; @@ -1099,29 +1149,29 @@ static int uart_tx_all(uart_port_t uart_num, const char* src, size_t size, bool //lock for uart_tx xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)portMAX_DELAY); p_uart_obj[uart_num]->coll_det_flg = false; - if(p_uart_obj[uart_num]->tx_buf_size > 0) { + if (p_uart_obj[uart_num]->tx_buf_size > 0) { size_t max_size = xRingbufferGetMaxItemSize(p_uart_obj[uart_num]->tx_ring_buf); int offset = 0; uart_tx_data_t evt; evt.tx_data.size = size; evt.tx_data.brk_len = brk_len; - if(brk_en) { + if (brk_en) { evt.type = UART_DATA_BREAK; } else { evt.type = UART_DATA; } - xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) &evt, sizeof(uart_tx_data_t), portMAX_DELAY); - while(size > 0) { + xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void *) &evt, sizeof(uart_tx_data_t), portMAX_DELAY); + while (size > 0) { size_t send_size = size > max_size / 2 ? max_size / 2 : size; - xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) (src + offset), send_size, portMAX_DELAY); + xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void *) (src + offset), send_size, portMAX_DELAY); size -= send_size; offset += send_size; uart_enable_tx_intr(uart_num, 1, UART_EMPTY_THRESH_DEFAULT); } } else { - while(size) { + while (size) { //semaphore for tx_fifo available - if(pdTRUE == xSemaphoreTake(p_uart_obj[uart_num]->tx_fifo_sem, (portTickType)portMAX_DELAY)) { + if (pdTRUE == xSemaphoreTake(p_uart_obj[uart_num]->tx_fifo_sem, (portTickType)portMAX_DELAY)) { uint32_t sent = 0; if (UART_IS_MODE_SET(uart_num, UART_MODE_RS485_HALF_DUPLEX)) { UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); @@ -1129,8 +1179,8 @@ static int uart_tx_all(uart_port_t uart_num, const char* src, size_t size, bool uart_hal_ena_intr_mask(&(uart_context[uart_num].hal), UART_INTR_TX_DONE); UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock)); } - uart_hal_write_txfifo(&(uart_context[uart_num].hal), (const uint8_t*)src, size, &sent); - if(sent < size) { + uart_hal_write_txfifo(&(uart_context[uart_num].hal), (const uint8_t *)src, size, &sent); + if (sent < size) { p_uart_obj[uart_num]->tx_waiting_fifo = true; uart_enable_tx_intr(uart_num, 1, UART_EMPTY_THRESH_DEFAULT); } @@ -1138,7 +1188,7 @@ static int uart_tx_all(uart_port_t uart_num, const char* src, size_t size, bool src += sent; } } - if(brk_en) { + if (brk_en) { uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), UART_INTR_TX_BRK_DONE); UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); uart_hal_tx_break(&(uart_context[uart_num].hal), brk_len); @@ -1152,7 +1202,7 @@ static int uart_tx_all(uart_port_t uart_num, const char* src, size_t size, bool return original_size; } -int uart_write_bytes(uart_port_t uart_num, const void* src, size_t size) +int uart_write_bytes(uart_port_t uart_num, const void *src, size_t size) { ESP_RETURN_ON_FALSE((uart_num < UART_NUM_MAX), (-1), UART_TAG, "uart_num error"); ESP_RETURN_ON_FALSE((p_uart_obj[uart_num] != NULL), (-1), UART_TAG, "uart driver error"); @@ -1160,7 +1210,7 @@ int uart_write_bytes(uart_port_t uart_num, const void* src, size_t size) return uart_tx_all(uart_num, src, size, 0, 0); } -int uart_write_bytes_with_break(uart_port_t uart_num, const void* src, size_t size, int brk_len) +int uart_write_bytes_with_break(uart_port_t uart_num, const void *src, size_t size, int brk_len) { ESP_RETURN_ON_FALSE((uart_num < UART_NUM_MAX), (-1), UART_TAG, "uart_num error"); ESP_RETURN_ON_FALSE((p_uart_obj[uart_num]), (-1), UART_TAG, "uart driver error"); @@ -1172,9 +1222,9 @@ int uart_write_bytes_with_break(uart_port_t uart_num, const void* src, size_t si static bool uart_check_buf_full(uart_port_t uart_num) { - if(p_uart_obj[uart_num]->rx_buffer_full_flg) { + if (p_uart_obj[uart_num]->rx_buffer_full_flg) { BaseType_t res = xRingbufferSend(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->rx_data_buf, p_uart_obj[uart_num]->rx_stash_len, 1); - if(res == pdTRUE) { + if (res == pdTRUE) { UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); p_uart_obj[uart_num]->rx_buffered_len += p_uart_obj[uart_num]->rx_stash_len; p_uart_obj[uart_num]->rx_buffer_full_flg = false; @@ -1186,22 +1236,22 @@ static bool uart_check_buf_full(uart_port_t uart_num) return false; } -int uart_read_bytes(uart_port_t uart_num, void* buf, uint32_t length, TickType_t ticks_to_wait) +int uart_read_bytes(uart_port_t uart_num, void *buf, uint32_t length, TickType_t ticks_to_wait) { ESP_RETURN_ON_FALSE((uart_num < UART_NUM_MAX), (-1), UART_TAG, "uart_num error"); ESP_RETURN_ON_FALSE((buf), (-1), UART_TAG, "uart data null"); ESP_RETURN_ON_FALSE((p_uart_obj[uart_num]), (-1), UART_TAG, "uart driver error"); - uint8_t* data = NULL; + uint8_t *data = NULL; size_t size; size_t copy_len = 0; int len_tmp; - if(xSemaphoreTake(p_uart_obj[uart_num]->rx_mux,(portTickType)ticks_to_wait) != pdTRUE) { + if (xSemaphoreTake(p_uart_obj[uart_num]->rx_mux, (portTickType)ticks_to_wait) != pdTRUE) { return -1; } - while(length) { - if(p_uart_obj[uart_num]->rx_cur_remain == 0) { - data = (uint8_t*) xRingbufferReceive(p_uart_obj[uart_num]->rx_ring_buf, &size, (portTickType) ticks_to_wait); - if(data) { + while (length) { + if (p_uart_obj[uart_num]->rx_cur_remain == 0) { + data = (uint8_t *) xRingbufferReceive(p_uart_obj[uart_num]->rx_ring_buf, &size, (portTickType) ticks_to_wait); + if (data) { p_uart_obj[uart_num]->rx_head_ptr = data; p_uart_obj[uart_num]->rx_ptr = data; p_uart_obj[uart_num]->rx_cur_remain = size; @@ -1209,7 +1259,7 @@ int uart_read_bytes(uart_port_t uart_num, void* buf, uint32_t length, TickType_t //When using dual cores, `rx_buffer_full_flg` may read and write on different cores at same time, //which may lose synchronization. So we also need to call `uart_check_buf_full` once when ringbuffer is empty //to solve the possible asynchronous issues. - if(uart_check_buf_full(uart_num)) { + if (uart_check_buf_full(uart_num)) { //This condition will never be true if `uart_read_bytes` //and `uart_rx_intr_handler_default` are scheduled on the same core. continue; @@ -1219,7 +1269,7 @@ int uart_read_bytes(uart_port_t uart_num, void* buf, uint32_t length, TickType_t } } } - if(p_uart_obj[uart_num]->rx_cur_remain > length) { + if (p_uart_obj[uart_num]->rx_cur_remain > length) { len_tmp = length; } else { len_tmp = p_uart_obj[uart_num]->rx_cur_remain; @@ -1233,7 +1283,7 @@ int uart_read_bytes(uart_port_t uart_num, void* buf, uint32_t length, TickType_t p_uart_obj[uart_num]->rx_cur_remain -= len_tmp; copy_len += len_tmp; length -= len_tmp; - if(p_uart_obj[uart_num]->rx_cur_remain == 0) { + if (p_uart_obj[uart_num]->rx_cur_remain == 0) { vRingbufferReturnItem(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->rx_head_ptr); p_uart_obj[uart_num]->rx_head_ptr = NULL; p_uart_obj[uart_num]->rx_ptr = NULL; @@ -1245,17 +1295,19 @@ int uart_read_bytes(uart_port_t uart_num, void* buf, uint32_t length, TickType_t return copy_len; } -esp_err_t uart_get_buffered_data_len(uart_port_t uart_num, size_t* size) +esp_err_t uart_get_buffered_data_len(uart_port_t uart_num, size_t *size) { ESP_RETURN_ON_FALSE((uart_num < UART_NUM_MAX), ESP_FAIL, UART_TAG, "uart_num error"); ESP_RETURN_ON_FALSE((p_uart_obj[uart_num]), ESP_FAIL, UART_TAG, "uart driver error"); + UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); *size = p_uart_obj[uart_num]->rx_buffered_len; + UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock)); return ESP_OK; } esp_err_t uart_flush(uart_port_t uart_num) __attribute__((alias("uart_flush_input"))); -static esp_err_t uart_disable_intr_mask_and_return_prev(uart_port_t uart_num, uint32_t disable_mask, uint32_t* prev_mask) +static esp_err_t uart_disable_intr_mask_and_return_prev(uart_port_t uart_num, uint32_t disable_mask, uint32_t *prev_mask) { ESP_RETURN_ON_FALSE((uart_num < UART_NUM_MAX), ESP_FAIL, UART_TAG, "uart_num error"); UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); @@ -1269,16 +1321,16 @@ esp_err_t uart_flush_input(uart_port_t uart_num) { ESP_RETURN_ON_FALSE((uart_num < UART_NUM_MAX), ESP_FAIL, UART_TAG, "uart_num error"); ESP_RETURN_ON_FALSE((p_uart_obj[uart_num]), ESP_FAIL, UART_TAG, "uart driver error"); - uart_obj_t* p_uart = p_uart_obj[uart_num]; - uint8_t* data; + uart_obj_t *p_uart = p_uart_obj[uart_num]; + uint8_t *data; size_t size; uint32_t prev_mask; //rx sem protect the ring buffer read related functions xSemaphoreTake(p_uart->rx_mux, (portTickType)portMAX_DELAY); - uart_disable_intr_mask_and_return_prev(uart_num, UART_INTR_RXFIFO_FULL|UART_INTR_RXFIFO_TOUT, &prev_mask); - while(true) { - if(p_uart->rx_head_ptr) { + uart_disable_intr_mask_and_return_prev(uart_num, UART_INTR_RXFIFO_FULL | UART_INTR_RXFIFO_TOUT, &prev_mask); + while (true) { + if (p_uart->rx_head_ptr) { vRingbufferReturnItem(p_uart->rx_ring_buf, p_uart->rx_head_ptr); UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); p_uart_obj[uart_num]->rx_buffered_len -= p_uart->rx_cur_remain; @@ -1290,14 +1342,19 @@ esp_err_t uart_flush_input(uart_port_t uart_num) } data = (uint8_t*) xRingbufferReceive(p_uart->rx_ring_buf, &size, (portTickType) 0); if(data == NULL) { + bool error = false; + UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); if( p_uart_obj[uart_num]->rx_buffered_len != 0 ) { - ESP_LOGE(UART_TAG, "rx_buffered_len error"); p_uart_obj[uart_num]->rx_buffered_len = 0; + error = true; } //We also need to clear the `rx_buffer_full_flg` here. - UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); p_uart_obj[uart_num]->rx_buffer_full_flg = false; UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock)); + if (error) { + // this must be called outside the critical section + ESP_LOGE(UART_TAG, "rx_buffered_len error"); + } break; } UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); @@ -1305,9 +1362,9 @@ esp_err_t uart_flush_input(uart_port_t uart_num) uart_pattern_queue_update(uart_num, size); UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock)); vRingbufferReturnItem(p_uart->rx_ring_buf, data); - if(p_uart_obj[uart_num]->rx_buffer_full_flg) { + if (p_uart_obj[uart_num]->rx_buffer_full_flg) { BaseType_t res = xRingbufferSend(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->rx_data_buf, p_uart_obj[uart_num]->rx_stash_len, 1); - if(res == pdTRUE) { + if (res == pdTRUE) { UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); p_uart_obj[uart_num]->rx_buffered_len += p_uart_obj[uart_num]->rx_stash_len; p_uart_obj[uart_num]->rx_buffer_full_flg = false; @@ -1324,12 +1381,143 @@ esp_err_t uart_flush_input(uart_port_t uart_num) return ESP_OK; } -esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, QueueHandle_t *uart_queue, int intr_alloc_flags) +static void uart_free_driver_obj(uart_obj_t *uart_obj) +{ + if (uart_obj->tx_fifo_sem) { + vSemaphoreDelete(uart_obj->tx_fifo_sem); + } + if (uart_obj->tx_done_sem) { + vSemaphoreDelete(uart_obj->tx_done_sem); + } + if (uart_obj->tx_brk_sem) { + vSemaphoreDelete(uart_obj->tx_brk_sem); + } + if (uart_obj->tx_mux) { + vSemaphoreDelete(uart_obj->tx_mux); + } + if (uart_obj->rx_mux) { + vSemaphoreDelete(uart_obj->rx_mux); + } + if (uart_obj->event_queue) { + vQueueDelete(uart_obj->event_queue); + } + if (uart_obj->rx_ring_buf) { + vRingbufferDelete(uart_obj->rx_ring_buf); + } + if (uart_obj->tx_ring_buf) { + vRingbufferDelete(uart_obj->tx_ring_buf); + } +#if CONFIG_UART_ISR_IN_IRAM + free(uart_obj->event_queue_storage); + free(uart_obj->event_queue_struct); + free(uart_obj->tx_ring_buf_storage); + free(uart_obj->tx_ring_buf_struct); + free(uart_obj->rx_ring_buf_storage); + free(uart_obj->rx_ring_buf_struct); + free(uart_obj->rx_mux_struct); + free(uart_obj->tx_mux_struct); + free(uart_obj->tx_brk_sem_struct); + free(uart_obj->tx_done_sem_struct); + free(uart_obj->tx_fifo_sem_struct); +#endif + free(uart_obj); +} + +static uart_obj_t *uart_alloc_driver_obj(int event_queue_size, int tx_buffer_size, int rx_buffer_size) +{ + uart_obj_t *uart_obj = heap_caps_calloc(1, sizeof(uart_obj_t), UART_MALLOC_CAPS); + if (!uart_obj) { + return NULL; + } +#if CONFIG_UART_ISR_IN_IRAM + if (event_queue_size > 0) { + uart_obj->event_queue_storage = heap_caps_calloc(event_queue_size, sizeof(uart_event_t), UART_MALLOC_CAPS); + uart_obj->event_queue_struct = heap_caps_calloc(1, sizeof(StaticQueue_t), UART_MALLOC_CAPS); + if (!uart_obj->event_queue_storage || !uart_obj->event_queue_struct) { + goto err; + } + } + if (tx_buffer_size > 0) { + uart_obj->tx_ring_buf_storage = heap_caps_calloc(1, tx_buffer_size, UART_MALLOC_CAPS); + uart_obj->tx_ring_buf_struct = heap_caps_calloc(1, sizeof(StaticRingbuffer_t), UART_MALLOC_CAPS); + if (!uart_obj->tx_ring_buf_storage || !uart_obj->tx_ring_buf_struct) { + goto err; + } + } + uart_obj->rx_ring_buf_storage = heap_caps_calloc(1, rx_buffer_size, UART_MALLOC_CAPS); + uart_obj->rx_ring_buf_struct = heap_caps_calloc(1, sizeof(StaticRingbuffer_t), UART_MALLOC_CAPS); + uart_obj->rx_mux_struct = heap_caps_calloc(1, sizeof(StaticSemaphore_t), UART_MALLOC_CAPS); + uart_obj->tx_mux_struct = heap_caps_calloc(1, sizeof(StaticSemaphore_t), UART_MALLOC_CAPS); + uart_obj->tx_brk_sem_struct = heap_caps_calloc(1, sizeof(StaticSemaphore_t), UART_MALLOC_CAPS); + uart_obj->tx_done_sem_struct = heap_caps_calloc(1, sizeof(StaticSemaphore_t), UART_MALLOC_CAPS); + uart_obj->tx_fifo_sem_struct = heap_caps_calloc(1, sizeof(StaticSemaphore_t), UART_MALLOC_CAPS); + if (!uart_obj->rx_ring_buf_storage || !uart_obj->rx_ring_buf_struct || !uart_obj->rx_mux_struct || + !uart_obj->tx_mux_struct || !uart_obj->tx_brk_sem_struct || !uart_obj->tx_done_sem_struct || + !uart_obj->tx_fifo_sem_struct) { + goto err; + } + if (event_queue_size > 0) { + uart_obj->event_queue = xQueueCreateStatic(event_queue_size, sizeof(uart_event_t), + uart_obj->event_queue_storage, uart_obj->event_queue_struct); + if (!uart_obj->event_queue) { + goto err; + } + } + if (tx_buffer_size > 0) { + uart_obj->tx_ring_buf = xRingbufferCreateStatic(tx_buffer_size, RINGBUF_TYPE_NOSPLIT, + uart_obj->tx_ring_buf_storage, uart_obj->tx_ring_buf_struct); + if (!uart_obj->tx_ring_buf) { + goto err; + } + } + uart_obj->rx_ring_buf = xRingbufferCreateStatic(rx_buffer_size, RINGBUF_TYPE_BYTEBUF, + uart_obj->rx_ring_buf_storage, uart_obj->rx_ring_buf_struct); + uart_obj->rx_mux = xSemaphoreCreateMutexStatic(uart_obj->rx_mux_struct); + uart_obj->tx_mux = xSemaphoreCreateMutexStatic(uart_obj->tx_mux_struct); + uart_obj->tx_brk_sem = xSemaphoreCreateBinaryStatic(uart_obj->tx_brk_sem_struct); + uart_obj->tx_done_sem = xSemaphoreCreateBinaryStatic(uart_obj->tx_done_sem_struct); + uart_obj->tx_fifo_sem = xSemaphoreCreateBinaryStatic(uart_obj->tx_fifo_sem_struct); + if (!uart_obj->rx_ring_buf || !uart_obj->rx_mux || !uart_obj->tx_mux || !uart_obj->tx_brk_sem || + !uart_obj->tx_done_sem || !uart_obj->tx_fifo_sem) { + goto err; + } +#else + if (event_queue_size > 0) { + uart_obj->event_queue = xQueueCreate(event_queue_size, sizeof(uart_event_t)); + if (!uart_obj->event_queue) { + goto err; + } + } + if (tx_buffer_size > 0) { + uart_obj->tx_ring_buf = xRingbufferCreate(tx_buffer_size, RINGBUF_TYPE_NOSPLIT); + if (!uart_obj->tx_ring_buf) { + goto err; + } + } + uart_obj->rx_ring_buf = xRingbufferCreate(rx_buffer_size, RINGBUF_TYPE_BYTEBUF); + uart_obj->tx_mux = xSemaphoreCreateMutex(); + uart_obj->rx_mux = xSemaphoreCreateMutex(); + uart_obj->tx_brk_sem = xSemaphoreCreateBinary(); + uart_obj->tx_done_sem = xSemaphoreCreateBinary(); + uart_obj->tx_fifo_sem = xSemaphoreCreateBinary(); + if (!uart_obj->rx_ring_buf || !uart_obj->rx_mux || !uart_obj->tx_mux || !uart_obj->tx_brk_sem || + !uart_obj->tx_done_sem || !uart_obj->tx_fifo_sem) { + goto err; + } +#endif + return uart_obj; + +err: + uart_free_driver_obj(uart_obj); + return NULL; +} + +esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int event_queue_size, QueueHandle_t *uart_queue, int intr_alloc_flags) { esp_err_t r; -#ifdef CONFIG_ESP_GDBSTUB_ENABLED +#ifdef CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME ESP_RETURN_ON_FALSE((uart_num != CONFIG_ESP_CONSOLE_UART_NUM), ESP_FAIL, UART_TAG, "UART used by GDB-stubs! Please disable GDB in menuconfig."); -#endif // CONFIG_ESP_GDBSTUB_ENABLED +#endif // CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME ESP_RETURN_ON_FALSE((uart_num < UART_NUM_MAX), ESP_FAIL, UART_TAG, "uart_num error"); ESP_RETURN_ON_FALSE((rx_buffer_size > SOC_UART_FIFO_LEN), ESP_FAIL, UART_TAG, "uart rx buffer length error"); ESP_RETURN_ON_FALSE((tx_buffer_size > SOC_UART_FIFO_LEN) || (tx_buffer_size == 0), ESP_FAIL, UART_TAG, "uart tx buffer length error"); @@ -1345,9 +1533,9 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b } #endif - if(p_uart_obj[uart_num] == NULL) { - p_uart_obj[uart_num] = (uart_obj_t*) heap_caps_calloc(1, sizeof(uart_obj_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); - if(p_uart_obj[uart_num] == NULL) { + if (p_uart_obj[uart_num] == NULL) { + p_uart_obj[uart_num] = uart_alloc_driver_obj(event_queue_size, tx_buffer_size, rx_buffer_size); + if (p_uart_obj[uart_num] == NULL) { ESP_LOGE(UART_TAG, "UART driver malloc error"); return ESP_FAIL; } @@ -1355,13 +1543,7 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b p_uart_obj[uart_num]->uart_mode = UART_MODE_UART; p_uart_obj[uart_num]->coll_det_flg = false; p_uart_obj[uart_num]->rx_always_timeout_flg = false; - p_uart_obj[uart_num]->tx_fifo_sem = xSemaphoreCreateBinary(); - xSemaphoreGive(p_uart_obj[uart_num]->tx_fifo_sem); - p_uart_obj[uart_num]->tx_done_sem = xSemaphoreCreateBinary(); - p_uart_obj[uart_num]->tx_brk_sem = xSemaphoreCreateBinary(); - p_uart_obj[uart_num]->tx_mux = xSemaphoreCreateMutex(); - p_uart_obj[uart_num]->rx_mux = xSemaphoreCreateMutex(); - p_uart_obj[uart_num]->queue_size = queue_size; + p_uart_obj[uart_num]->event_queue_size = event_queue_size; p_uart_obj[uart_num]->tx_ptr = NULL; p_uart_obj[uart_num]->tx_head = NULL; p_uart_obj[uart_num]->tx_len_tot = 0; @@ -1369,29 +1551,19 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b p_uart_obj[uart_num]->tx_brk_len = 0; p_uart_obj[uart_num]->tx_waiting_brk = 0; p_uart_obj[uart_num]->rx_buffered_len = 0; - uart_pattern_queue_reset(uart_num, UART_PATTERN_DET_QLEN_DEFAULT); - - if(uart_queue) { - p_uart_obj[uart_num]->xQueueUart = xQueueCreate(queue_size, sizeof(uart_event_t)); - *uart_queue = p_uart_obj[uart_num]->xQueueUart; - ESP_LOGI(UART_TAG, "queue free spaces: %d", uxQueueSpacesAvailable(p_uart_obj[uart_num]->xQueueUart)); - } else { - p_uart_obj[uart_num]->xQueueUart = NULL; - } p_uart_obj[uart_num]->rx_buffer_full_flg = false; p_uart_obj[uart_num]->tx_waiting_fifo = false; p_uart_obj[uart_num]->rx_ptr = NULL; p_uart_obj[uart_num]->rx_cur_remain = 0; p_uart_obj[uart_num]->rx_head_ptr = NULL; - p_uart_obj[uart_num]->rx_ring_buf = xRingbufferCreate(rx_buffer_size, RINGBUF_TYPE_BYTEBUF); - if(tx_buffer_size > 0) { - p_uart_obj[uart_num]->tx_ring_buf = xRingbufferCreate(tx_buffer_size, RINGBUF_TYPE_NOSPLIT); - p_uart_obj[uart_num]->tx_buf_size = tx_buffer_size; - } else { - p_uart_obj[uart_num]->tx_ring_buf = NULL; - p_uart_obj[uart_num]->tx_buf_size = 0; - } + p_uart_obj[uart_num]->tx_buf_size = tx_buffer_size; p_uart_obj[uart_num]->uart_select_notif_callback = NULL; + xSemaphoreGive(p_uart_obj[uart_num]->tx_fifo_sem); + uart_pattern_queue_reset(uart_num, UART_PATTERN_DET_QLEN_DEFAULT); + if (uart_queue) { + *uart_queue = p_uart_obj[uart_num]->event_queue; + ESP_LOGI(UART_TAG, "queue free spaces: %d", uxQueueSpacesAvailable(p_uart_obj[uart_num]->event_queue)); + } } else { ESP_LOGE(UART_TAG, "UART driver already installed"); return ESP_FAIL; @@ -1406,10 +1578,14 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b uart_module_enable(uart_num); uart_hal_disable_intr_mask(&(uart_context[uart_num].hal), UART_LL_INTR_MASK); uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), UART_LL_INTR_MASK); - r=uart_isr_register(uart_num, uart_rx_intr_handler_default, p_uart_obj[uart_num], intr_alloc_flags, &p_uart_obj[uart_num]->intr_handle); - if (r!=ESP_OK) goto err; - r=uart_intr_config(uart_num, &uart_intr); - if (r!=ESP_OK) goto err; + r = uart_isr_register(uart_num, uart_rx_intr_handler_default, p_uart_obj[uart_num], intr_alloc_flags, &p_uart_obj[uart_num]->intr_handle); + if (r != ESP_OK) { + goto err; + } + r = uart_intr_config(uart_num, &uart_intr); + if (r != ESP_OK) { + goto err; + } return r; err: @@ -1421,7 +1597,7 @@ err: esp_err_t uart_driver_delete(uart_port_t uart_num) { ESP_RETURN_ON_FALSE((uart_num < UART_NUM_MAX), ESP_FAIL, UART_TAG, "uart_num error"); - if(p_uart_obj[uart_num] == NULL) { + if (p_uart_obj[uart_num] == NULL) { ESP_LOGI(UART_TAG, "ALREADY NULL"); return ESP_OK; } @@ -1429,45 +1605,10 @@ esp_err_t uart_driver_delete(uart_port_t uart_num) uart_disable_rx_intr(uart_num); uart_disable_tx_intr(uart_num); uart_pattern_link_free(uart_num); - - if(p_uart_obj[uart_num]->tx_fifo_sem) { - vSemaphoreDelete(p_uart_obj[uart_num]->tx_fifo_sem); - p_uart_obj[uart_num]->tx_fifo_sem = NULL; - } - if(p_uart_obj[uart_num]->tx_done_sem) { - vSemaphoreDelete(p_uart_obj[uart_num]->tx_done_sem); - p_uart_obj[uart_num]->tx_done_sem = NULL; - } - if(p_uart_obj[uart_num]->tx_brk_sem) { - vSemaphoreDelete(p_uart_obj[uart_num]->tx_brk_sem); - p_uart_obj[uart_num]->tx_brk_sem = NULL; - } - if(p_uart_obj[uart_num]->tx_mux) { - vSemaphoreDelete(p_uart_obj[uart_num]->tx_mux); - p_uart_obj[uart_num]->tx_mux = NULL; - } - if(p_uart_obj[uart_num]->rx_mux) { - vSemaphoreDelete(p_uart_obj[uart_num]->rx_mux); - p_uart_obj[uart_num]->rx_mux = NULL; - } - if(p_uart_obj[uart_num]->xQueueUart) { - vQueueDelete(p_uart_obj[uart_num]->xQueueUart); - p_uart_obj[uart_num]->xQueueUart = NULL; - } - if(p_uart_obj[uart_num]->rx_ring_buf) { - vRingbufferDelete(p_uart_obj[uart_num]->rx_ring_buf); - p_uart_obj[uart_num]->rx_ring_buf = NULL; - } - if(p_uart_obj[uart_num]->tx_ring_buf) { - vRingbufferDelete(p_uart_obj[uart_num]->tx_ring_buf); - p_uart_obj[uart_num]->tx_ring_buf = NULL; - } - - heap_caps_free(p_uart_obj[uart_num]); + uart_free_driver_obj(p_uart_obj[uart_num]); p_uart_obj[uart_num] = NULL; #if SOC_UART_SUPPORT_RTC_CLK - uart_sclk_t sclk = 0; uart_hal_get_sclk(&(uart_context[uart_num].hal), &sclk); if (sclk == UART_SCLK_RTC) { @@ -1503,19 +1644,19 @@ esp_err_t uart_set_mode(uart_port_t uart_num, uart_mode_t mode) if ((mode == UART_MODE_RS485_COLLISION_DETECT) || (mode == UART_MODE_RS485_APP_CTRL) || (mode == UART_MODE_RS485_HALF_DUPLEX)) { ESP_RETURN_ON_FALSE((!uart_hal_is_hw_rts_en(&(uart_context[uart_num].hal))), ESP_ERR_INVALID_ARG, UART_TAG, - "disable hw flowctrl before using RS485 mode"); + "disable hw flowctrl before using RS485 mode"); } UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); uart_hal_set_mode(&(uart_context[uart_num].hal), mode); - if(mode == UART_MODE_RS485_COLLISION_DETECT) { + if (mode == UART_MODE_RS485_COLLISION_DETECT) { // This mode allows read while transmitting that allows collision detection p_uart_obj[uart_num]->coll_det_flg = false; // Enable collision detection interrupts uart_hal_ena_intr_mask(&(uart_context[uart_num].hal), UART_INTR_RXFIFO_TOUT - | UART_INTR_RXFIFO_FULL - | UART_INTR_RS485_CLASH - | UART_INTR_RS485_FRM_ERR - | UART_INTR_RS485_PARITY_ERR); + | UART_INTR_RXFIFO_FULL + | UART_INTR_RS485_CLASH + | UART_INTR_RS485_FRM_ERR + | UART_INTR_RS485_PARITY_ERR); } p_uart_obj[uart_num]->uart_mode = mode; UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock)); @@ -1526,7 +1667,7 @@ esp_err_t uart_set_rx_full_threshold(uart_port_t uart_num, int threshold) { ESP_RETURN_ON_FALSE((uart_num < UART_NUM_MAX), ESP_ERR_INVALID_ARG, UART_TAG, "uart_num error"); ESP_RETURN_ON_FALSE((threshold < UART_RXFIFO_FULL_THRHD_V) && (threshold > 0), ESP_ERR_INVALID_ARG, UART_TAG, - "rx fifo full threshold value error"); + "rx fifo full threshold value error"); if (p_uart_obj[uart_num] == NULL) { ESP_LOGE(UART_TAG, "call uart_driver_install API first"); return ESP_ERR_INVALID_STATE; @@ -1543,7 +1684,7 @@ esp_err_t uart_set_tx_empty_threshold(uart_port_t uart_num, int threshold) { ESP_RETURN_ON_FALSE((uart_num < UART_NUM_MAX), ESP_ERR_INVALID_ARG, UART_TAG, "uart_num error"); ESP_RETURN_ON_FALSE((threshold < UART_TXFIFO_EMPTY_THRHD_V) && (threshold > 0), ESP_ERR_INVALID_ARG, UART_TAG, - "tx fifo empty threshold value error"); + "tx fifo empty threshold value error"); if (p_uart_obj[uart_num] == NULL) { ESP_LOGE(UART_TAG, "call uart_driver_install API first"); return ESP_ERR_INVALID_STATE; @@ -1571,15 +1712,13 @@ esp_err_t uart_set_rx_timeout(uart_port_t uart_num, const uint8_t tout_thresh) return ESP_OK; } -esp_err_t uart_get_collision_flag(uart_port_t uart_num, bool* collision_flag) +esp_err_t uart_get_collision_flag(uart_port_t uart_num, bool *collision_flag) { ESP_RETURN_ON_FALSE((uart_num < UART_NUM_MAX), ESP_ERR_INVALID_ARG, UART_TAG, "uart_num error"); ESP_RETURN_ON_FALSE((p_uart_obj[uart_num]), ESP_FAIL, UART_TAG, "uart driver error"); ESP_RETURN_ON_FALSE((collision_flag != NULL), ESP_ERR_INVALID_ARG, UART_TAG, "wrong parameter pointer"); - ESP_RETURN_ON_FALSE( - (UART_IS_MODE_SET(uart_num, UART_MODE_RS485_HALF_DUPLEX) - || UART_IS_MODE_SET(uart_num, UART_MODE_RS485_COLLISION_DETECT)), - ESP_ERR_INVALID_ARG, UART_TAG, "wrong mode"); + ESP_RETURN_ON_FALSE((UART_IS_MODE_SET(uart_num, UART_MODE_RS485_HALF_DUPLEX) || UART_IS_MODE_SET(uart_num, UART_MODE_RS485_COLLISION_DETECT)), + ESP_ERR_INVALID_ARG, UART_TAG, "wrong mode"); *collision_flag = p_uart_obj[uart_num]->coll_det_flg; return ESP_OK; } @@ -1587,16 +1726,15 @@ esp_err_t uart_get_collision_flag(uart_port_t uart_num, bool* collision_flag) esp_err_t uart_set_wakeup_threshold(uart_port_t uart_num, int wakeup_threshold) { ESP_RETURN_ON_FALSE((uart_num < UART_NUM_MAX), ESP_ERR_INVALID_ARG, UART_TAG, "uart_num error"); - ESP_RETURN_ON_FALSE((wakeup_threshold <= UART_ACTIVE_THRESHOLD_V && - wakeup_threshold > UART_MIN_WAKEUP_THRESH), ESP_ERR_INVALID_ARG, UART_TAG, - "wakeup_threshold out of bounds"); + ESP_RETURN_ON_FALSE((wakeup_threshold <= UART_ACTIVE_THRESHOLD_V && wakeup_threshold > UART_MIN_WAKEUP_THRESH), ESP_ERR_INVALID_ARG, UART_TAG, + "wakeup_threshold out of bounds"); UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); uart_hal_set_wakeup_thrd(&(uart_context[uart_num].hal), wakeup_threshold); UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock)); return ESP_OK; } -esp_err_t uart_get_wakeup_threshold(uart_port_t uart_num, int* out_wakeup_threshold) +esp_err_t uart_get_wakeup_threshold(uart_port_t uart_num, int *out_wakeup_threshold) { ESP_RETURN_ON_FALSE((uart_num < UART_NUM_MAX), ESP_ERR_INVALID_ARG, UART_TAG, "uart_num error"); ESP_RETURN_ON_FALSE((out_wakeup_threshold != NULL), ESP_ERR_INVALID_ARG, UART_TAG, "argument is NULL"); @@ -1607,7 +1745,7 @@ esp_err_t uart_get_wakeup_threshold(uart_port_t uart_num, int* out_wakeup_thresh esp_err_t uart_wait_tx_idle_polling(uart_port_t uart_num) { ESP_RETURN_ON_FALSE((uart_num < UART_NUM_MAX), ESP_ERR_INVALID_ARG, UART_TAG, "uart_num error"); - while(!uart_hal_is_tx_idle(&(uart_context[uart_num].hal))); + while (!uart_hal_is_tx_idle(&(uart_context[uart_num].hal))); return ESP_OK; } diff --git a/components/efuse/esp32/esp_efuse_fields.c b/components/efuse/esp32/esp_efuse_fields.c index b79bf14a38..7d45cfd68c 100644 --- a/components/efuse/esp32/esp_efuse_fields.c +++ b/components/efuse/esp32/esp_efuse_fields.c @@ -15,7 +15,7 @@ #include "soc/efuse_periph.h" #include "bootloader_random.h" #include "sys/param.h" -#include "soc/apb_ctrl_reg.h" +#include "soc/syscon_reg.h" const static char *TAG = "efuse"; @@ -27,7 +27,7 @@ uint8_t esp_efuse_get_chip_ver(void) uint8_t eco_bit0, eco_bit1, eco_bit2; esp_efuse_read_field_blob(ESP_EFUSE_CHIP_VER_REV1, &eco_bit0, 1); esp_efuse_read_field_blob(ESP_EFUSE_CHIP_VER_REV2, &eco_bit1, 1); - eco_bit2 = (REG_READ(APB_CTRL_DATE_REG) & 0x80000000) >> 31; + eco_bit2 = (REG_READ(SYSCON_DATE_REG) & 0x80000000) >> 31; uint32_t combine_value = (eco_bit2 << 2) | (eco_bit1 << 1) | eco_bit0; uint8_t chip_ver = 0; switch (combine_value) { diff --git a/components/efuse/esp32c3/esp_efuse_table.c b/components/efuse/esp32c3/esp_efuse_table.c index 7615e16047..3076547b73 100644 --- a/components/efuse/esp32c3/esp_efuse_table.c +++ b/components/efuse/esp32c3/esp_efuse_table.c @@ -9,7 +9,7 @@ #include #include "esp_efuse_table.h" -// md5_digest_table 7a50fdd084e3b80b143c5bd2a36f9c26 +// md5_digest_table ef33779021404fbaddc878eefebaddc1 // This file was generated from the file esp_efuse_table.csv. DO NOT CHANGE THIS FILE MANUALLY. // If you want to change some fields, you need to change esp_efuse_table.csv file // then run `efuse_common_table` or `efuse_custom_table` command it will generate this file. @@ -155,10 +155,6 @@ static const esp_efuse_desc_t RD_DIS_SYS_DATA_PART2[] = { {EFUSE_BLK0, 38, 1}, // Read protection for EFUSE_BLK10. SYS_DATA_PART2, }; -static const esp_efuse_desc_t DIS_RTC_RAM_BOOT[] = { - {EFUSE_BLK0, 39, 1}, // Disable boot from RTC RAM, -}; - static const esp_efuse_desc_t DIS_ICACHE[] = { {EFUSE_BLK0, 40, 1}, // Disable Icache, }; @@ -456,6 +452,10 @@ static const esp_efuse_desc_t USER_DATA[] = { {EFUSE_BLK3, 0, 256}, // User data, }; +static const esp_efuse_desc_t USER_DATA_MAC_CUSTOM[] = { + {EFUSE_BLK3, 200, 48}, // Custom MAC, +}; + static const esp_efuse_desc_t KEY0[] = { {EFUSE_BLK4, 0, 256}, // Key0 or user data, }; @@ -687,11 +687,6 @@ const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_SYS_DATA_PART2[] = { NULL }; -const esp_efuse_desc_t* ESP_EFUSE_DIS_RTC_RAM_BOOT[] = { - &DIS_RTC_RAM_BOOT[0], // Disable boot from RTC RAM - NULL -}; - const esp_efuse_desc_t* ESP_EFUSE_DIS_ICACHE[] = { &DIS_ICACHE[0], // Disable Icache NULL @@ -1062,6 +1057,11 @@ const esp_efuse_desc_t* ESP_EFUSE_USER_DATA[] = { NULL }; +const esp_efuse_desc_t* ESP_EFUSE_USER_DATA_MAC_CUSTOM[] = { + &USER_DATA_MAC_CUSTOM[0], // Custom MAC + NULL +}; + const esp_efuse_desc_t* ESP_EFUSE_KEY0[] = { &KEY0[0], // Key0 or user data NULL diff --git a/components/efuse/esp32c3/esp_efuse_table.csv b/components/efuse/esp32c3/esp_efuse_table.csv index f9c4cb8e12..a9939e912b 100644 --- a/components/efuse/esp32c3/esp_efuse_table.csv +++ b/components/efuse/esp32c3/esp_efuse_table.csv @@ -50,7 +50,6 @@ RD_DIS.KEY4, EFUSE_BLK0, 36, 1, Read protection for EFUSE_BLK8. KEY4 RD_DIS.KEY5, EFUSE_BLK0, 37, 1, Read protection for EFUSE_BLK9. KEY5 RD_DIS.SYS_DATA_PART2, EFUSE_BLK0, 38, 1, Read protection for EFUSE_BLK10. SYS_DATA_PART2 - DIS_RTC_RAM_BOOT, EFUSE_BLK0, 39, 1, Disable boot from RTC RAM DIS_ICACHE, EFUSE_BLK0, 40, 1, Disable Icache DIS_USB_JTAG, EFUSE_BLK0, 41, 1, Disable USB JTAG DIS_DOWNLOAD_ICACHE, EFUSE_BLK0, 42, 1, Disable Icache in download mode @@ -146,6 +145,9 @@ ################ USER_DATA, EFUSE_BLK3, 0, 256, User data +USER_DATA.MAC_CUSTOM, EFUSE_BLK3, 200, 48, Custom MAC + +################ KEY0, EFUSE_BLK4, 0, 256, Key0 or user data KEY1, EFUSE_BLK5, 0, 256, Key1 or user data KEY2, EFUSE_BLK6, 0, 256, Key2 or user data diff --git a/components/efuse/esp32c3/include/esp_efuse_table.h b/components/efuse/esp32c3/include/esp_efuse_table.h index 96fba50913..839116af26 100644 --- a/components/efuse/esp32c3/include/esp_efuse_table.h +++ b/components/efuse/esp32c3/include/esp_efuse_table.h @@ -9,7 +9,7 @@ extern "C" { #endif -// md5_digest_table 7a50fdd084e3b80b143c5bd2a36f9c26 +// md5_digest_table ef33779021404fbaddc878eefebaddc1 // This file was generated from the file esp_efuse_table.csv. DO NOT CHANGE THIS FILE MANUALLY. // If you want to change some fields, you need to change esp_efuse_table.csv file // then run `efuse_common_table` or `efuse_custom_table` command it will generate this file. @@ -51,7 +51,6 @@ extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY3[]; extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY4[]; extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY5[]; extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_SYS_DATA_PART2[]; -extern const esp_efuse_desc_t* ESP_EFUSE_DIS_RTC_RAM_BOOT[]; extern const esp_efuse_desc_t* ESP_EFUSE_DIS_ICACHE[]; extern const esp_efuse_desc_t* ESP_EFUSE_DIS_USB_JTAG[]; extern const esp_efuse_desc_t* ESP_EFUSE_DIS_DOWNLOAD_ICACHE[]; @@ -125,6 +124,7 @@ extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN1[]; extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN2[]; extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN3[]; extern const esp_efuse_desc_t* ESP_EFUSE_USER_DATA[]; +extern const esp_efuse_desc_t* ESP_EFUSE_USER_DATA_MAC_CUSTOM[]; extern const esp_efuse_desc_t* ESP_EFUSE_KEY0[]; extern const esp_efuse_desc_t* ESP_EFUSE_KEY1[]; extern const esp_efuse_desc_t* ESP_EFUSE_KEY2[]; diff --git a/components/efuse/esp32h2/esp_efuse_table.c b/components/efuse/esp32h2/esp_efuse_table.c index 06060ed9d4..540e2e050a 100644 --- a/components/efuse/esp32h2/esp_efuse_table.c +++ b/components/efuse/esp32h2/esp_efuse_table.c @@ -9,7 +9,7 @@ #include #include "esp_efuse_table.h" -// md5_digest_table 54e3ee07e1f682ea20e8af0561df669c +// md5_digest_table a007943ae37fe41884a23d505a6e7dbb // This file was generated from the file esp_efuse_table.csv. DO NOT CHANGE THIS FILE MANUALLY. // If you want to change some fields, you need to change esp_efuse_table.csv file // then run `efuse_common_table` or `efuse_custom_table` command it will generate this file. @@ -155,10 +155,6 @@ static const esp_efuse_desc_t RD_DIS_SYS_DATA_PART2[] = { {EFUSE_BLK0, 38, 1}, // Read protection for EFUSE_BLK10. SYS_DATA_PART2, }; -static const esp_efuse_desc_t DIS_RTC_RAM_BOOT[] = { - {EFUSE_BLK0, 39, 1}, // Disable boot from RTC RAM, -}; - static const esp_efuse_desc_t DIS_ICACHE[] = { {EFUSE_BLK0, 40, 1}, // Disable Icache, }; @@ -350,6 +346,9 @@ static const esp_efuse_desc_t MAC_FACTORY[] = { {EFUSE_BLK1, 16, 8}, // Factory MAC addr [3], {EFUSE_BLK1, 8, 8}, // Factory MAC addr [4], {EFUSE_BLK1, 0, 8}, // Factory MAC addr [5], +}; + +static const esp_efuse_desc_t MAC_EXT[] = { {EFUSE_BLK1, 123, 8}, // Factory MAC addr [6], {EFUSE_BLK1, 131, 8}, // Factory MAC addr [7], }; @@ -462,6 +461,10 @@ static const esp_efuse_desc_t USER_DATA[] = { {EFUSE_BLK3, 0, 256}, // User data, }; +static const esp_efuse_desc_t USER_DATA_MAC_CUSTOM[] = { + {EFUSE_BLK3, 200, 48}, // Custom MAC, +}; + static const esp_efuse_desc_t KEY0[] = { {EFUSE_BLK4, 0, 256}, // Key0 or user data, }; @@ -669,11 +672,6 @@ const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_SYS_DATA_PART2[] = { NULL }; -const esp_efuse_desc_t* ESP_EFUSE_DIS_RTC_RAM_BOOT[] = { - &DIS_RTC_RAM_BOOT[0], // Disable boot from RTC RAM - NULL -}; - const esp_efuse_desc_t* ESP_EFUSE_DIS_ICACHE[] = { &DIS_ICACHE[0], // Disable Icache NULL @@ -911,8 +909,12 @@ const esp_efuse_desc_t* ESP_EFUSE_MAC_FACTORY[] = { &MAC_FACTORY[3], // Factory MAC addr [3] &MAC_FACTORY[4], // Factory MAC addr [4] &MAC_FACTORY[5], // Factory MAC addr [5] - &MAC_FACTORY[6], // Factory MAC addr [6] - &MAC_FACTORY[7], // Factory MAC addr [7] + NULL +}; + +const esp_efuse_desc_t* ESP_EFUSE_MAC_EXT[] = { + &MAC_EXT[6], // Factory MAC addr [6] + &MAC_EXT[7], // Factory MAC addr [7] NULL }; @@ -1051,6 +1053,11 @@ const esp_efuse_desc_t* ESP_EFUSE_USER_DATA[] = { NULL }; +const esp_efuse_desc_t* ESP_EFUSE_USER_DATA_MAC_CUSTOM[] = { + &USER_DATA_MAC_CUSTOM[0], // Custom MAC + NULL +}; + const esp_efuse_desc_t* ESP_EFUSE_KEY0[] = { &KEY0[0], // Key0 or user data NULL diff --git a/components/efuse/esp32h2/esp_efuse_table.csv b/components/efuse/esp32h2/esp_efuse_table.csv index 873440b2c7..08467f0ec0 100644 --- a/components/efuse/esp32h2/esp_efuse_table.csv +++ b/components/efuse/esp32h2/esp_efuse_table.csv @@ -51,7 +51,6 @@ RD_DIS.KEY4, EFUSE_BLK0, 36, 1, Read protection for EFUSE_BLK8. KEY4 RD_DIS.KEY5, EFUSE_BLK0, 37, 1, Read protection for EFUSE_BLK9. KEY5 RD_DIS.SYS_DATA_PART2, EFUSE_BLK0, 38, 1, Read protection for EFUSE_BLK10. SYS_DATA_PART2 - DIS_RTC_RAM_BOOT, EFUSE_BLK0, 39, 1, Disable boot from RTC RAM DIS_ICACHE, EFUSE_BLK0, 40, 1, Disable Icache DIS_USB_JTAG, EFUSE_BLK0, 41, 1, Disable USB JTAG DIS_DOWNLOAD_ICACHE, EFUSE_BLK0, 42, 1, Disable Icache in download mode @@ -116,7 +115,7 @@ , EFUSE_BLK1, 16, 8, Factory MAC addr [3] , EFUSE_BLK1, 8, 8, Factory MAC addr [4] , EFUSE_BLK1, 0, 8, Factory MAC addr [5] - , EFUSE_BLK1, 123, 8, Factory MAC addr [6] + MAC_EXT, EFUSE_BLK1, 123, 8, Factory MAC addr [6] , EFUSE_BLK1, 131, 8, Factory MAC addr [7] SPI_PAD_CONFIG_CLK, EFUSE_BLK1, 48, 6, SPI_PAD_configure CLK SPI_PAD_CONFIG_Q_D1, EFUSE_BLK1, 54, 6, SPI_PAD_configure Q(D1) @@ -150,6 +149,9 @@ ################ USER_DATA, EFUSE_BLK3, 0, 256, User data +USER_DATA.MAC_CUSTOM, EFUSE_BLK3, 200, 48, Custom MAC + +################ KEY0, EFUSE_BLK4, 0, 256, Key0 or user data KEY1, EFUSE_BLK5, 0, 256, Key1 or user data KEY2, EFUSE_BLK6, 0, 256, Key2 or user data diff --git a/components/efuse/esp32h2/include/esp_efuse_table.h b/components/efuse/esp32h2/include/esp_efuse_table.h index 84c808a15d..a35a2ea1de 100644 --- a/components/efuse/esp32h2/include/esp_efuse_table.h +++ b/components/efuse/esp32h2/include/esp_efuse_table.h @@ -9,7 +9,7 @@ extern "C" { #endif -// md5_digest_table 54e3ee07e1f682ea20e8af0561df669c +// md5_digest_table a007943ae37fe41884a23d505a6e7dbb // This file was generated from the file esp_efuse_table.csv. DO NOT CHANGE THIS FILE MANUALLY. // If you want to change some fields, you need to change esp_efuse_table.csv file // then run `efuse_common_table` or `efuse_custom_table` command it will generate this file. @@ -51,7 +51,6 @@ extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY3[]; extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY4[]; extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY5[]; extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_SYS_DATA_PART2[]; -extern const esp_efuse_desc_t* ESP_EFUSE_DIS_RTC_RAM_BOOT[]; extern const esp_efuse_desc_t* ESP_EFUSE_DIS_ICACHE[]; extern const esp_efuse_desc_t* ESP_EFUSE_DIS_USB_JTAG[]; extern const esp_efuse_desc_t* ESP_EFUSE_DIS_DOWNLOAD_ICACHE[]; @@ -99,6 +98,7 @@ extern const esp_efuse_desc_t* ESP_EFUSE_FORCE_SEND_RESUME[]; extern const esp_efuse_desc_t* ESP_EFUSE_SECURE_VERSION[]; extern const esp_efuse_desc_t* ESP_EFUSE_BOOT_DISABLE_FAST_WAKE[]; extern const esp_efuse_desc_t* ESP_EFUSE_MAC_FACTORY[]; +extern const esp_efuse_desc_t* ESP_EFUSE_MAC_EXT[]; extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_CLK[]; extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_Q_D1[]; extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_D_D0[]; @@ -126,6 +126,7 @@ extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN1[]; extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN2[]; extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN3[]; extern const esp_efuse_desc_t* ESP_EFUSE_USER_DATA[]; +extern const esp_efuse_desc_t* ESP_EFUSE_USER_DATA_MAC_CUSTOM[]; extern const esp_efuse_desc_t* ESP_EFUSE_KEY0[]; extern const esp_efuse_desc_t* ESP_EFUSE_KEY1[]; extern const esp_efuse_desc_t* ESP_EFUSE_KEY2[]; diff --git a/components/efuse/esp32s2/esp_efuse_table.c b/components/efuse/esp32s2/esp_efuse_table.c index 5e7ecff4a9..84deae88b3 100644 --- a/components/efuse/esp32s2/esp_efuse_table.c +++ b/components/efuse/esp32s2/esp_efuse_table.c @@ -9,7 +9,7 @@ #include #include "esp_efuse_table.h" -// md5_digest_table bc8611ed5c3a91ac0a8ba29879968d70 +// md5_digest_table 614c862c2cfa8ccda3a79183ce767255 // This file was generated from the file esp_efuse_table.csv. DO NOT CHANGE THIS FILE MANUALLY. // If you want to change some fields, you need to change esp_efuse_table.csv file // then run `efuse_common_table` or `efuse_custom_table` command it will generate this file. @@ -388,16 +388,20 @@ static const esp_efuse_desc_t WAFER_VERSION[] = { {EFUSE_BLK1, 114, 3}, // WAFER version 0:A, }; -static const esp_efuse_desc_t PKG_VERSION[] = { - {EFUSE_BLK1, 117, 4}, // Package version 0:ESP32-S2 1:ESP32-S2FH16 2:ESP32-S2FH32, +static const esp_efuse_desc_t FLASH_VERSION[] = { + {EFUSE_BLK1, 117, 4}, // Flash_version, }; static const esp_efuse_desc_t BLOCK1_VERSION[] = { - {EFUSE_BLK1, 121, 3}, // BLOCK1 efuse version 0:No calibration 1:With calibration, + {EFUSE_BLK1, 121, 3}, // BLOCK1 efuse version, }; -static const esp_efuse_desc_t SYS_DATA_PART0[] = { - {EFUSE_BLK1, 126, 66}, // System configuration, +static const esp_efuse_desc_t PSRAM_VERSION[] = { + {EFUSE_BLK1, 124, 4}, // PSRAM version, +}; + +static const esp_efuse_desc_t PKG_VERSION[] = { + {EFUSE_BLK1, 128, 4}, // Package version, }; static const esp_efuse_desc_t OPTIONAL_UNIQUE_ID[] = { @@ -405,13 +409,17 @@ static const esp_efuse_desc_t OPTIONAL_UNIQUE_ID[] = { }; static const esp_efuse_desc_t BLOCK2_VERSION[] = { - {EFUSE_BLK2, 132, 3}, // Version of BLOCK2, + {EFUSE_BLK2, 132, 3}, // Version of BLOCK2: 0-No ADC calib; 1-ADC calib V1; 2-ADC calib V2, }; static const esp_efuse_desc_t USER_DATA[] = { {EFUSE_BLK3, 0, 256}, // User data, }; +static const esp_efuse_desc_t USER_DATA_MAC_CUSTOM[] = { + {EFUSE_BLK3, 200, 48}, // Custom MAC, +}; + static const esp_efuse_desc_t KEY0[] = { {EFUSE_BLK4, 0, 256}, // Key0 or user data, }; @@ -909,18 +917,23 @@ const esp_efuse_desc_t* ESP_EFUSE_WAFER_VERSION[] = { NULL }; -const esp_efuse_desc_t* ESP_EFUSE_PKG_VERSION[] = { - &PKG_VERSION[0], // Package version 0:ESP32-S2 1:ESP32-S2FH16 2:ESP32-S2FH32 +const esp_efuse_desc_t* ESP_EFUSE_FLASH_VERSION[] = { + &FLASH_VERSION[0], // Flash_version NULL }; const esp_efuse_desc_t* ESP_EFUSE_BLOCK1_VERSION[] = { - &BLOCK1_VERSION[0], // BLOCK1 efuse version 0:No calibration 1:With calibration + &BLOCK1_VERSION[0], // BLOCK1 efuse version NULL }; -const esp_efuse_desc_t* ESP_EFUSE_SYS_DATA_PART0[] = { - &SYS_DATA_PART0[0], // System configuration +const esp_efuse_desc_t* ESP_EFUSE_PSRAM_VERSION[] = { + &PSRAM_VERSION[0], // PSRAM version + NULL +}; + +const esp_efuse_desc_t* ESP_EFUSE_PKG_VERSION[] = { + &PKG_VERSION[0], // Package version NULL }; @@ -930,7 +943,7 @@ const esp_efuse_desc_t* ESP_EFUSE_OPTIONAL_UNIQUE_ID[] = { }; const esp_efuse_desc_t* ESP_EFUSE_BLOCK2_VERSION[] = { - &BLOCK2_VERSION[0], // Version of BLOCK2 + &BLOCK2_VERSION[0], // Version of BLOCK2: 0-No ADC calib; 1-ADC calib V1; 2-ADC calib V2 NULL }; @@ -939,6 +952,11 @@ const esp_efuse_desc_t* ESP_EFUSE_USER_DATA[] = { NULL }; +const esp_efuse_desc_t* ESP_EFUSE_USER_DATA_MAC_CUSTOM[] = { + &USER_DATA_MAC_CUSTOM[0], // Custom MAC + NULL +}; + const esp_efuse_desc_t* ESP_EFUSE_KEY0[] = { &KEY0[0], // Key0 or user data NULL diff --git a/components/efuse/esp32s2/esp_efuse_table.csv b/components/efuse/esp32s2/esp_efuse_table.csv index cb0c16c6ff..9c26819915 100644 --- a/components/efuse/esp32s2/esp_efuse_table.csv +++ b/components/efuse/esp32s2/esp_efuse_table.csv @@ -124,17 +124,22 @@ SPI_PAD_CONFIG_D6, EFUSE_BLK1, 102, 6, SPI_PAD_configure D6 SPI_PAD_CONFIG_D7, EFUSE_BLK1, 108, 6, SPI_PAD_configure D7 WAFER_VERSION, EFUSE_BLK1, 114, 3, WAFER version 0:A - PKG_VERSION, EFUSE_BLK1, 117, 4, Package version 0:ESP32-S2 1:ESP32-S2FH16 2:ESP32-S2FH32 - BLOCK1_VERSION, EFUSE_BLK1, 121, 3, BLOCK1 efuse version 0:No calibration 1:With calibration - SYS_DATA_PART0, EFUSE_BLK1, 126, 66, System configuration + FLASH_VERSION, EFUSE_BLK1, 117, 4, Flash_version + BLOCK1_VERSION, EFUSE_BLK1, 121, 3, BLOCK1 efuse version + PSRAM_VERSION, EFUSE_BLK1, 124, 4, PSRAM version + PKG_VERSION, EFUSE_BLK1, 128, 4, Package version + # SYS_DATA_PART0, EFUSE_BLK1, 132, 60, System configuration (Reserve) # SYS_DATA_PART1 BLOCK# - System configuration ####################### OPTIONAL_UNIQUE_ID, EFUSE_BLK2, 0, 128, Optional unique 128-bit ID - BLOCK2_VERSION, EFUSE_BLK2, 132, 3, Version of BLOCK2 + BLOCK2_VERSION, EFUSE_BLK2, 132, 3, Version of BLOCK2: 0-No ADC calib; 1-ADC calib V1; 2-ADC calib V2 ################ USER_DATA, EFUSE_BLK3, 0, 256, User data +USER_DATA.MAC_CUSTOM, EFUSE_BLK3, 200, 48, Custom MAC + +################ KEY0, EFUSE_BLK4, 0, 256, Key0 or user data KEY1, EFUSE_BLK5, 0, 256, Key1 or user data KEY2, EFUSE_BLK6, 0, 256, Key2 or user data diff --git a/components/efuse/esp32s2/include/esp_efuse_table.h b/components/efuse/esp32s2/include/esp_efuse_table.h index 22dbec14b2..f2a1d9ce3f 100644 --- a/components/efuse/esp32s2/include/esp_efuse_table.h +++ b/components/efuse/esp32s2/include/esp_efuse_table.h @@ -9,7 +9,7 @@ extern "C" { #endif -// md5_digest_table bc8611ed5c3a91ac0a8ba29879968d70 +// md5_digest_table 614c862c2cfa8ccda3a79183ce767255 // This file was generated from the file esp_efuse_table.csv. DO NOT CHANGE THIS FILE MANUALLY. // If you want to change some fields, you need to change esp_efuse_table.csv file // then run `efuse_common_table` or `efuse_custom_table` command it will generate this file. @@ -108,12 +108,14 @@ extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_D5[]; extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_D6[]; extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_D7[]; extern const esp_efuse_desc_t* ESP_EFUSE_WAFER_VERSION[]; -extern const esp_efuse_desc_t* ESP_EFUSE_PKG_VERSION[]; +extern const esp_efuse_desc_t* ESP_EFUSE_FLASH_VERSION[]; extern const esp_efuse_desc_t* ESP_EFUSE_BLOCK1_VERSION[]; -extern const esp_efuse_desc_t* ESP_EFUSE_SYS_DATA_PART0[]; +extern const esp_efuse_desc_t* ESP_EFUSE_PSRAM_VERSION[]; +extern const esp_efuse_desc_t* ESP_EFUSE_PKG_VERSION[]; extern const esp_efuse_desc_t* ESP_EFUSE_OPTIONAL_UNIQUE_ID[]; extern const esp_efuse_desc_t* ESP_EFUSE_BLOCK2_VERSION[]; extern const esp_efuse_desc_t* ESP_EFUSE_USER_DATA[]; +extern const esp_efuse_desc_t* ESP_EFUSE_USER_DATA_MAC_CUSTOM[]; extern const esp_efuse_desc_t* ESP_EFUSE_KEY0[]; extern const esp_efuse_desc_t* ESP_EFUSE_KEY1[]; extern const esp_efuse_desc_t* ESP_EFUSE_KEY2[]; diff --git a/components/efuse/esp32s3/esp_efuse_fields.c b/components/efuse/esp32s3/esp_efuse_fields.c index 76c62d86e4..5263fb0394 100644 --- a/components/efuse/esp32s3/esp_efuse_fields.c +++ b/components/efuse/esp32s3/esp_efuse_fields.c @@ -33,7 +33,7 @@ uint8_t esp_efuse_get_chip_ver(void) uint32_t esp_efuse_get_pkg_ver(void) { uint32_t pkg_ver = 0; - esp_efuse_read_field_blob(ESP_EFUSE_PKG_VERSION, &pkg_ver, 4); + esp_efuse_read_field_blob(ESP_EFUSE_PKG_VERSION, &pkg_ver, ESP_EFUSE_PKG_VERSION[0]->bit_count); return pkg_ver; } @@ -45,9 +45,9 @@ esp_err_t esp_efuse_disable_rom_download_mode(void) esp_err_t esp_efuse_set_rom_log_scheme(esp_efuse_rom_log_scheme_t log_scheme) { int cur_log_scheme = 0; - esp_efuse_read_field_blob(ESP_EFUSE_UART_PRINT_CONTROL, &cur_log_scheme, 2); + esp_efuse_read_field_blob(ESP_EFUSE_UART_PRINT_CONTROL, &cur_log_scheme, ESP_EFUSE_UART_PRINT_CONTROL[0]->bit_count); if (!cur_log_scheme) { // not burned yet - return esp_efuse_write_field_blob(ESP_EFUSE_UART_PRINT_CONTROL, &log_scheme, 2); + return esp_efuse_write_field_blob(ESP_EFUSE_UART_PRINT_CONTROL, &log_scheme, ESP_EFUSE_UART_PRINT_CONTROL[0]->bit_count); } else { return ESP_ERR_INVALID_STATE; } diff --git a/components/efuse/esp32s3/esp_efuse_rtc_calib.c b/components/efuse/esp32s3/esp_efuse_rtc_calib.c new file mode 100644 index 0000000000..981209ab73 --- /dev/null +++ b/components/efuse/esp32s3/esp_efuse_rtc_calib.c @@ -0,0 +1,103 @@ +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "esp_err.h" +#include "esp_log.h" +#include "esp_efuse.h" +#include "esp_efuse_table.h" + +//Don't introduce new dependency of ADC, keep these macro same as ADC related definations +#define ADC_ATTEN_MAX 4 +#define ADC_NUM_MAX 2 +#define ADC_NUM_1 0 +#define ADC_NUM_2 1 + + +int esp_efuse_rtc_calib_get_ver(void) +{ + uint32_t blk1_version = 0; + uint32_t blk2_version = 0; + ESP_ERROR_CHECK(esp_efuse_read_field_blob(ESP_EFUSE_BLOCK1_VERSION, &blk1_version, ESP_EFUSE_BLOCK1_VERSION[0]->bit_count)); + ESP_ERROR_CHECK(esp_efuse_read_field_blob(ESP_EFUSE_BLOCK2_VERSION, &blk2_version, ESP_EFUSE_BLOCK2_VERSION[0]->bit_count)); + + if (blk1_version == blk2_version) { + return blk1_version; + } else { + blk1_version = 0; + blk2_version = 0; + ESP_LOGW("eFuse", "calibration efuse version does not match, set default version: %d", 0); + } + + return blk2_version; +} + +uint16_t esp_efuse_rtc_calib_get_init_code(int version, uint32_t adc_unit, int atten) +{ + assert(version == 1); + assert(atten < 4); + assert(adc_unit < ADC_NUM_MAX); + + const esp_efuse_desc_t **desc[8] = {ESP_EFUSE_ADC1_INIT_CODE_ATTEN0, ESP_EFUSE_ADC1_INIT_CODE_ATTEN1, ESP_EFUSE_ADC1_INIT_CODE_ATTEN2, ESP_EFUSE_ADC1_INIT_CODE_ATTEN3, + ESP_EFUSE_ADC2_INIT_CODE_ATTEN0, ESP_EFUSE_ADC2_INIT_CODE_ATTEN1, ESP_EFUSE_ADC2_INIT_CODE_ATTEN2, ESP_EFUSE_ADC2_INIT_CODE_ATTEN3}; + int efuse_icode_bits = 0; + uint32_t adc_icode[4] = {}; + uint32_t adc_icode_diff[4] = {}; + uint8_t desc_index = (adc_unit == ADC_NUM_1) ? 0 : 4; + + for (int diff_index = 0; diff_index < 4; diff_index++) { + efuse_icode_bits = esp_efuse_get_field_size(desc[desc_index]); + ESP_ERROR_CHECK(esp_efuse_read_field_blob(desc[desc_index], &adc_icode_diff[diff_index], efuse_icode_bits)); + desc_index++; + } + + //Version 1 logic for calculating ADC ICode based on EFUSE burnt value + if (adc_unit == ADC_NUM_1) { + adc_icode[0] = adc_icode_diff[0] + 1850; + adc_icode[1] = adc_icode_diff[1] + adc_icode[0] + 90; + adc_icode[2] = adc_icode_diff[2] + adc_icode[1]; + adc_icode[3] = adc_icode_diff[3] + adc_icode[2] + 70; + } else { + adc_icode[0] = adc_icode_diff[0] + 2020; + adc_icode[1] = adc_icode_diff[1] + adc_icode[0]; + adc_icode[2] = adc_icode_diff[2] + adc_icode[1]; + adc_icode[3] = adc_icode_diff[3] + adc_icode[2]; + } + + return adc_icode[atten]; +} + +esp_err_t esp_efuse_rtc_calib_get_cal_voltage(int version, uint32_t adc_unit, int atten, uint32_t *out_digi, uint32_t *out_vol_mv) +{ + assert(version == 1); + assert(atten < 4); + assert(adc_unit < ADC_NUM_MAX); + + int efuse_vol_bits = 0; + uint32_t adc_vol_diff[8] = {}; + uint32_t adc1_vol[4] = {}; + uint32_t adc2_vol[4] = {}; + const esp_efuse_desc_t **desc[8] = {ESP_EFUSE_ADC1_CAL_VOL_ATTEN0, ESP_EFUSE_ADC1_CAL_VOL_ATTEN1, ESP_EFUSE_ADC1_CAL_VOL_ATTEN2, ESP_EFUSE_ADC1_CAL_VOL_ATTEN3, + ESP_EFUSE_ADC2_CAL_VOL_ATTEN0, ESP_EFUSE_ADC2_CAL_VOL_ATTEN1, ESP_EFUSE_ADC2_CAL_VOL_ATTEN2, ESP_EFUSE_ADC2_CAL_VOL_ATTEN3}; + for (int i = 0; i < 8; i++) { + efuse_vol_bits = esp_efuse_get_field_size(desc[i]); + ESP_ERROR_CHECK(esp_efuse_read_field_blob(desc[i], &adc_vol_diff[i], efuse_vol_bits)); + } + + adc1_vol[3] = adc_vol_diff[3] + 900; + adc1_vol[2] = adc_vol_diff[2] + adc1_vol[3] + 800; + adc1_vol[1] = adc_vol_diff[1] + adc1_vol[2] + 700; + adc1_vol[0] = adc_vol_diff[0] + adc1_vol[1] + 800; + adc2_vol[3] = adc1_vol[3] - adc_vol_diff[7] + 15; + adc2_vol[2] = adc1_vol[2] - adc_vol_diff[6] + 20; + adc2_vol[1] = adc1_vol[1] - adc_vol_diff[5] + 10; + adc2_vol[0] = adc1_vol[0] - adc_vol_diff[4] + 40; + + *out_digi = (adc_unit == ADC_NUM_1) ? adc1_vol[atten] : adc2_vol[atten]; + *out_vol_mv = 850; + + return ESP_OK; +} diff --git a/components/efuse/esp32s3/esp_efuse_table.c b/components/efuse/esp32s3/esp_efuse_table.c index 7224a2ecfb..5d8a53eda6 100644 --- a/components/efuse/esp32s3/esp_efuse_table.c +++ b/components/efuse/esp32s3/esp_efuse_table.c @@ -9,7 +9,7 @@ #include #include "esp_efuse_table.h" -// md5_digest_table 7d78e15a6be433d8520eaf462b450cdc +// md5_digest_table ee5142bc489eee22230a49b5c7cafe00 // This file was generated from the file esp_efuse_table.csv. DO NOT CHANGE THIS FILE MANUALLY. // If you want to change some fields, you need to change esp_efuse_table.csv file // then run `efuse_common_table` or `efuse_custom_table` command it will generate this file. @@ -23,10 +23,6 @@ static const esp_efuse_desc_t WR_DIS_RD_DIS[] = { {EFUSE_BLK0, 0, 1}, // Write protection for RD_DIS_KEY0 RD_DIS_KEY1 RD_DIS_KEY2 RD_DIS_KEY3 RD_DIS_KEY4 RD_DIS_KEY5 RD_DIS_SYS_DATA_PART2, }; -static const esp_efuse_desc_t WR_DIS_DIS_RTC_RAM_BOOT[] = { - {EFUSE_BLK0, 1, 1}, // Write protection for DIS_RTC_RAM_BOOT, -}; - static const esp_efuse_desc_t WR_DIS_GROUP_1[] = { {EFUSE_BLK0, 2, 1}, // Write protection for DIS_ICACHE DIS_DCACHE DIS_DOWNLOAD_ICACHE DIS_DOWNLOAD_DCACHE DIS_FORCE_DOWNLOAD DIS_USB DIS_CAN SOFT_DIS_JTAG HARD_DIS_JTAG DIS_DOWNLOAD_MANUAL_ENCRYPT, }; @@ -163,10 +159,6 @@ static const esp_efuse_desc_t RD_DIS_SYS_DATA_PART2[] = { {EFUSE_BLK0, 38, 1}, // Read protection for EFUSE_BLK10. SYS_DATA_PART2, }; -static const esp_efuse_desc_t DIS_RTC_RAM_BOOT[] = { - {EFUSE_BLK0, 39, 1}, // Disable boot from RTC RAM, -}; - static const esp_efuse_desc_t DIS_ICACHE[] = { {EFUSE_BLK0, 40, 1}, // Disable Icache, }; @@ -417,15 +409,15 @@ static const esp_efuse_desc_t WAFER_VERSION[] = { }; static const esp_efuse_desc_t PKG_VERSION[] = { - {EFUSE_BLK1, 117, 4}, // Package version 0:ESP32-S2 1:ESP32-S2FH16 2:ESP32-S2FH32, + {EFUSE_BLK1, 117, 3}, // Package version, }; static const esp_efuse_desc_t BLOCK1_VERSION[] = { - {EFUSE_BLK1, 121, 3}, // BLOCK1 efuse version 0:No calibration 1:With calibration, + {EFUSE_BLK1, 120, 3}, // BLOCK1 efuse version 0:No calibration 1:With calibration, }; -static const esp_efuse_desc_t SYS_DATA_PART0[] = { - {EFUSE_BLK1, 126, 66}, // System configuration, +static const esp_efuse_desc_t ADC2_CAL_VOL_ATTEN3[] = { + {EFUSE_BLK1, 186, 6}, // ADC2 calibration voltage at atten3, }; static const esp_efuse_desc_t OPTIONAL_UNIQUE_ID[] = { @@ -433,13 +425,85 @@ static const esp_efuse_desc_t OPTIONAL_UNIQUE_ID[] = { }; static const esp_efuse_desc_t BLOCK2_VERSION[] = { - {EFUSE_BLK2, 132, 3}, // Version of BLOCK2, + {EFUSE_BLK2, 128, 4}, // Version of BLOCK2, +}; + +static const esp_efuse_desc_t TEMP_CALIB[] = { + {EFUSE_BLK2, 132, 9}, // Temperature calibration data, +}; + +static const esp_efuse_desc_t OCODE[] = { + {EFUSE_BLK2, 141, 8}, // ADC OCode, +}; + +static const esp_efuse_desc_t ADC1_INIT_CODE_ATTEN0[] = { + {EFUSE_BLK2, 149, 8}, // ADC1 init code at atten0, +}; + +static const esp_efuse_desc_t ADC1_INIT_CODE_ATTEN1[] = { + {EFUSE_BLK2, 157, 6}, // ADC1 init code at atten1, +}; + +static const esp_efuse_desc_t ADC1_INIT_CODE_ATTEN2[] = { + {EFUSE_BLK2, 163, 6}, // ADC1 init code at atten2, +}; + +static const esp_efuse_desc_t ADC1_INIT_CODE_ATTEN3[] = { + {EFUSE_BLK2, 169, 6}, // ADC1 init code at atten3, +}; + +static const esp_efuse_desc_t ADC2_INIT_CODE_ATTEN0[] = { + {EFUSE_BLK2, 175, 8}, // ADC2 init code at atten0, +}; + +static const esp_efuse_desc_t ADC2_INIT_CODE_ATTEN1[] = { + {EFUSE_BLK2, 183, 6}, // ADC2 init code at atten1, +}; + +static const esp_efuse_desc_t ADC2_INIT_CODE_ATTEN2[] = { + {EFUSE_BLK2, 189, 6}, // ADC2 init code at atten2, +}; + +static const esp_efuse_desc_t ADC2_INIT_CODE_ATTEN3[] = { + {EFUSE_BLK2, 195, 6}, // ADC2 init code at atten3, +}; + +static const esp_efuse_desc_t ADC1_CAL_VOL_ATTEN0[] = { + {EFUSE_BLK2, 201, 8}, // ADC1 calibration voltage at atten0, +}; + +static const esp_efuse_desc_t ADC1_CAL_VOL_ATTEN1[] = { + {EFUSE_BLK2, 209, 8}, // ADC1 calibration voltage at atten1, +}; + +static const esp_efuse_desc_t ADC1_CAL_VOL_ATTEN2[] = { + {EFUSE_BLK2, 217, 8}, // ADC1 calibration voltage at atten2, +}; + +static const esp_efuse_desc_t ADC1_CAL_VOL_ATTEN3[] = { + {EFUSE_BLK2, 225, 8}, // ADC1 calibration voltage at atten3, +}; + +static const esp_efuse_desc_t ADC2_CAL_VOL_ATTEN0[] = { + {EFUSE_BLK2, 233, 8}, // ADC2 calibration voltage at atten0, +}; + +static const esp_efuse_desc_t ADC2_CAL_VOL_ATTEN1[] = { + {EFUSE_BLK2, 241, 7}, // ADC2 calibration voltage at atten1, +}; + +static const esp_efuse_desc_t ADC2_CAL_VOL_ATTEN2[] = { + {EFUSE_BLK2, 248, 7}, // ADC2 calibration voltage at atten2, }; static const esp_efuse_desc_t USER_DATA[] = { {EFUSE_BLK3, 0, 256}, // User data, }; +static const esp_efuse_desc_t USER_DATA_MAC_CUSTOM[] = { + {EFUSE_BLK3, 200, 48}, // Custom MAC, +}; + static const esp_efuse_desc_t KEY0[] = { {EFUSE_BLK4, 0, 256}, // Key0 or user data, }; @@ -482,11 +546,6 @@ const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_RD_DIS[] = { NULL }; -const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_DIS_RTC_RAM_BOOT[] = { - &WR_DIS_DIS_RTC_RAM_BOOT[0], // Write protection for DIS_RTC_RAM_BOOT - NULL -}; - const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_GROUP_1[] = { &WR_DIS_GROUP_1[0], // Write protection for DIS_ICACHE DIS_DCACHE DIS_DOWNLOAD_ICACHE DIS_DOWNLOAD_DCACHE DIS_FORCE_DOWNLOAD DIS_USB DIS_CAN SOFT_DIS_JTAG HARD_DIS_JTAG DIS_DOWNLOAD_MANUAL_ENCRYPT NULL @@ -657,11 +716,6 @@ const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_SYS_DATA_PART2[] = { NULL }; -const esp_efuse_desc_t* ESP_EFUSE_DIS_RTC_RAM_BOOT[] = { - &DIS_RTC_RAM_BOOT[0], // Disable boot from RTC RAM - NULL -}; - const esp_efuse_desc_t* ESP_EFUSE_DIS_ICACHE[] = { &DIS_ICACHE[0], // Disable Icache NULL @@ -973,7 +1027,7 @@ const esp_efuse_desc_t* ESP_EFUSE_WAFER_VERSION[] = { }; const esp_efuse_desc_t* ESP_EFUSE_PKG_VERSION[] = { - &PKG_VERSION[0], // Package version 0:ESP32-S2 1:ESP32-S2FH16 2:ESP32-S2FH32 + &PKG_VERSION[0], // Package version NULL }; @@ -982,8 +1036,8 @@ const esp_efuse_desc_t* ESP_EFUSE_BLOCK1_VERSION[] = { NULL }; -const esp_efuse_desc_t* ESP_EFUSE_SYS_DATA_PART0[] = { - &SYS_DATA_PART0[0], // System configuration +const esp_efuse_desc_t* ESP_EFUSE_ADC2_CAL_VOL_ATTEN3[] = { + &ADC2_CAL_VOL_ATTEN3[0], // ADC2 calibration voltage at atten3 NULL }; @@ -997,11 +1051,101 @@ const esp_efuse_desc_t* ESP_EFUSE_BLOCK2_VERSION[] = { NULL }; +const esp_efuse_desc_t* ESP_EFUSE_TEMP_CALIB[] = { + &TEMP_CALIB[0], // Temperature calibration data + NULL +}; + +const esp_efuse_desc_t* ESP_EFUSE_OCODE[] = { + &OCODE[0], // ADC OCode + NULL +}; + +const esp_efuse_desc_t* ESP_EFUSE_ADC1_INIT_CODE_ATTEN0[] = { + &ADC1_INIT_CODE_ATTEN0[0], // ADC1 init code at atten0 + NULL +}; + +const esp_efuse_desc_t* ESP_EFUSE_ADC1_INIT_CODE_ATTEN1[] = { + &ADC1_INIT_CODE_ATTEN1[0], // ADC1 init code at atten1 + NULL +}; + +const esp_efuse_desc_t* ESP_EFUSE_ADC1_INIT_CODE_ATTEN2[] = { + &ADC1_INIT_CODE_ATTEN2[0], // ADC1 init code at atten2 + NULL +}; + +const esp_efuse_desc_t* ESP_EFUSE_ADC1_INIT_CODE_ATTEN3[] = { + &ADC1_INIT_CODE_ATTEN3[0], // ADC1 init code at atten3 + NULL +}; + +const esp_efuse_desc_t* ESP_EFUSE_ADC2_INIT_CODE_ATTEN0[] = { + &ADC2_INIT_CODE_ATTEN0[0], // ADC2 init code at atten0 + NULL +}; + +const esp_efuse_desc_t* ESP_EFUSE_ADC2_INIT_CODE_ATTEN1[] = { + &ADC2_INIT_CODE_ATTEN1[0], // ADC2 init code at atten1 + NULL +}; + +const esp_efuse_desc_t* ESP_EFUSE_ADC2_INIT_CODE_ATTEN2[] = { + &ADC2_INIT_CODE_ATTEN2[0], // ADC2 init code at atten2 + NULL +}; + +const esp_efuse_desc_t* ESP_EFUSE_ADC2_INIT_CODE_ATTEN3[] = { + &ADC2_INIT_CODE_ATTEN3[0], // ADC2 init code at atten3 + NULL +}; + +const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN0[] = { + &ADC1_CAL_VOL_ATTEN0[0], // ADC1 calibration voltage at atten0 + NULL +}; + +const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN1[] = { + &ADC1_CAL_VOL_ATTEN1[0], // ADC1 calibration voltage at atten1 + NULL +}; + +const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN2[] = { + &ADC1_CAL_VOL_ATTEN2[0], // ADC1 calibration voltage at atten2 + NULL +}; + +const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN3[] = { + &ADC1_CAL_VOL_ATTEN3[0], // ADC1 calibration voltage at atten3 + NULL +}; + +const esp_efuse_desc_t* ESP_EFUSE_ADC2_CAL_VOL_ATTEN0[] = { + &ADC2_CAL_VOL_ATTEN0[0], // ADC2 calibration voltage at atten0 + NULL +}; + +const esp_efuse_desc_t* ESP_EFUSE_ADC2_CAL_VOL_ATTEN1[] = { + &ADC2_CAL_VOL_ATTEN1[0], // ADC2 calibration voltage at atten1 + NULL +}; + +const esp_efuse_desc_t* ESP_EFUSE_ADC2_CAL_VOL_ATTEN2[] = { + &ADC2_CAL_VOL_ATTEN2[0], // ADC2 calibration voltage at atten2 + NULL +}; + const esp_efuse_desc_t* ESP_EFUSE_USER_DATA[] = { &USER_DATA[0], // User data NULL }; +const esp_efuse_desc_t* ESP_EFUSE_USER_DATA_MAC_CUSTOM[] = { + &USER_DATA_MAC_CUSTOM[0], // Custom MAC + NULL +}; + const esp_efuse_desc_t* ESP_EFUSE_KEY0[] = { &KEY0[0], // Key0 or user data NULL diff --git a/components/efuse/esp32s3/esp_efuse_table.csv b/components/efuse/esp32s3/esp_efuse_table.csv index 7194f0b71a..40decc2f29 100644 --- a/components/efuse/esp32s3/esp_efuse_table.csv +++ b/components/efuse/esp32s3/esp_efuse_table.csv @@ -14,7 +14,6 @@ # EFUSE_RD_WR_DIS_REG # WR_DIS, EFUSE_BLK0, 0, 32, Write protection WR_DIS.RD_DIS, EFUSE_BLK0, 0, 1, Write protection for RD_DIS_KEY0 RD_DIS_KEY1 RD_DIS_KEY2 RD_DIS_KEY3 RD_DIS_KEY4 RD_DIS_KEY5 RD_DIS_SYS_DATA_PART2 - WR_DIS.DIS_RTC_RAM_BOOT, EFUSE_BLK0, 1, 1, Write protection for DIS_RTC_RAM_BOOT WR_DIS.GROUP_1, EFUSE_BLK0, 2, 1, Write protection for DIS_ICACHE DIS_DCACHE DIS_DOWNLOAD_ICACHE DIS_DOWNLOAD_DCACHE DIS_FORCE_DOWNLOAD DIS_USB DIS_CAN SOFT_DIS_JTAG HARD_DIS_JTAG DIS_DOWNLOAD_MANUAL_ENCRYPT WR_DIS.GROUP_2, EFUSE_BLK0, 3, 1, Write protection for VDD_SPI_XPD VDD_SPI_TIEH VDD_SPI_FORCE VDD_SPI_INIT VDD_SPI_DCAP WDT_DELAY_SEL WR_DIS.SPI_BOOT_CRYPT_CNT, EFUSE_BLK0, 4, 1, Write protection for SPI_BOOT_CRYPT_CNT @@ -51,7 +50,6 @@ RD_DIS.KEY4, EFUSE_BLK0, 36, 1, Read protection for EFUSE_BLK8. KEY4 RD_DIS.KEY5, EFUSE_BLK0, 37, 1, Read protection for EFUSE_BLK9. KEY5 RD_DIS.SYS_DATA_PART2, EFUSE_BLK0, 38, 1, Read protection for EFUSE_BLK10. SYS_DATA_PART2 - DIS_RTC_RAM_BOOT, EFUSE_BLK0, 39, 1, Disable boot from RTC RAM DIS_ICACHE, EFUSE_BLK0, 40, 1, Disable Icache DIS_DCACHE, EFUSE_BLK0, 41, 1, Disable Dcace DIS_DOWNLOAD_ICACHE, EFUSE_BLK0, 42, 1, Disable Icache in download mode include boot_mode 0 1 2 3 6 7 @@ -130,17 +128,37 @@ SPI_PAD_CONFIG_D6, EFUSE_BLK1, 102, 6, SPI_PAD_configure D6 SPI_PAD_CONFIG_D7, EFUSE_BLK1, 108, 6, SPI_PAD_configure D7 WAFER_VERSION, EFUSE_BLK1, 114, 3, WAFER version 0:A - PKG_VERSION, EFUSE_BLK1, 117, 4, Package version 0:ESP32-S2 1:ESP32-S2FH16 2:ESP32-S2FH32 - BLOCK1_VERSION, EFUSE_BLK1, 121, 3, BLOCK1 efuse version 0:No calibration 1:With calibration - SYS_DATA_PART0, EFUSE_BLK1, 126, 66, System configuration + PKG_VERSION, EFUSE_BLK1, 117, 3, Package version + BLOCK1_VERSION, EFUSE_BLK1, 120, 3, BLOCK1 efuse version 0:No calibration 1:With calibration + ADC2_CAL_VOL_ATTEN3, EFUSE_BLK1, 186, 6, ADC2 calibration voltage at atten3 # SYS_DATA_PART1 BLOCK# - System configuration ####################### OPTIONAL_UNIQUE_ID, EFUSE_BLK2, 0, 128, Optional unique 128-bit ID - BLOCK2_VERSION, EFUSE_BLK2, 132, 3, Version of BLOCK2 + BLOCK2_VERSION, EFUSE_BLK2, 128, 4, Version of BLOCK2 + TEMP_CALIB, EFUSE_BLK2, 132, 9, Temperature calibration data + OCODE, EFUSE_BLK2, 141, 8, ADC OCode + ADC1_INIT_CODE_ATTEN0, EFUSE_BLK2, 149, 8, ADC1 init code at atten0 + ADC1_INIT_CODE_ATTEN1, EFUSE_BLK2, 157, 6, ADC1 init code at atten1 + ADC1_INIT_CODE_ATTEN2, EFUSE_BLK2, 163, 6, ADC1 init code at atten2 + ADC1_INIT_CODE_ATTEN3, EFUSE_BLK2, 169, 6, ADC1 init code at atten3 + ADC2_INIT_CODE_ATTEN0, EFUSE_BLK2, 175, 8, ADC2 init code at atten0 + ADC2_INIT_CODE_ATTEN1, EFUSE_BLK2, 183, 6, ADC2 init code at atten1 + ADC2_INIT_CODE_ATTEN2, EFUSE_BLK2, 189, 6, ADC2 init code at atten2 + ADC2_INIT_CODE_ATTEN3, EFUSE_BLK2, 195, 6, ADC2 init code at atten3 + ADC1_CAL_VOL_ATTEN0, EFUSE_BLK2, 201, 8, ADC1 calibration voltage at atten0 + ADC1_CAL_VOL_ATTEN1, EFUSE_BLK2, 209, 8, ADC1 calibration voltage at atten1 + ADC1_CAL_VOL_ATTEN2, EFUSE_BLK2, 217, 8, ADC1 calibration voltage at atten2 + ADC1_CAL_VOL_ATTEN3, EFUSE_BLK2, 225, 8, ADC1 calibration voltage at atten3 + ADC2_CAL_VOL_ATTEN0, EFUSE_BLK2, 233, 8, ADC2 calibration voltage at atten0 + ADC2_CAL_VOL_ATTEN1, EFUSE_BLK2, 241, 7, ADC2 calibration voltage at atten1 + ADC2_CAL_VOL_ATTEN2, EFUSE_BLK2, 248, 7, ADC2 calibration voltage at atten2 ################ USER_DATA, EFUSE_BLK3, 0, 256, User data +USER_DATA.MAC_CUSTOM, EFUSE_BLK3, 200, 48, Custom MAC + +################ KEY0, EFUSE_BLK4, 0, 256, Key0 or user data KEY1, EFUSE_BLK5, 0, 256, Key1 or user data KEY2, EFUSE_BLK6, 0, 256, Key2 or user data diff --git a/components/efuse/esp32s3/include/esp_efuse_rtc_calib.h b/components/efuse/esp32s3/include/esp_efuse_rtc_calib.h new file mode 100644 index 0000000000..b0ba57669d --- /dev/null +++ b/components/efuse/esp32s3/include/esp_efuse_rtc_calib.h @@ -0,0 +1,56 @@ +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Get the RTC calibration efuse version + * + * @return Version of the stored efuse + */ +int esp_efuse_rtc_calib_get_ver(void); + +/** + * @brief Get the init code in the efuse, for the corresponding attenuation. + * + * @param version Version of the stored efuse + * @param adc_unit ADC unit + * @param atten Attenuation of the init code + * @return The init code stored in efuse + */ +uint16_t esp_efuse_rtc_calib_get_init_code(int version, uint32_t adc_unit, int atten); + +/** + * @brief Get the calibration digits stored in the efuse, and the corresponding voltage. + * + * @param version Version of the stored efuse + * @param adc_unit ADC unit + * @param atten Attenuation to use + * @param out_digi Output buffer of the digits + * @param out_vol_mv Output of the voltage, in mV + * @return + * - ESP_ERR_INVALID_ARG: If efuse version or attenuation is invalid + * - ESP_OK: if success + */ +esp_err_t esp_efuse_rtc_calib_get_cal_voltage(int version, uint32_t adc_unit, int atten, uint32_t* out_digi, uint32_t* out_vol_mv); + +/** + * @brief Get the temperature sensor calibration number delta_T stored in the efuse. + * + * @param version Version of the stored efuse + * + * @return The specification of temperature sensor calibration number in efuse. + */ +float esp_efuse_rtc_calib_get_cal_temp(int version); + +#ifdef __cplusplus +} +#endif diff --git a/components/efuse/esp32s3/include/esp_efuse_table.h b/components/efuse/esp32s3/include/esp_efuse_table.h index 5707c5585f..1f9ed383d7 100644 --- a/components/efuse/esp32s3/include/esp_efuse_table.h +++ b/components/efuse/esp32s3/include/esp_efuse_table.h @@ -9,7 +9,7 @@ extern "C" { #endif -// md5_digest_table 7d78e15a6be433d8520eaf462b450cdc +// md5_digest_table ee5142bc489eee22230a49b5c7cafe00 // This file was generated from the file esp_efuse_table.csv. DO NOT CHANGE THIS FILE MANUALLY. // If you want to change some fields, you need to change esp_efuse_table.csv file // then run `efuse_common_table` or `efuse_custom_table` command it will generate this file. @@ -18,7 +18,6 @@ extern "C" { extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS[]; extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_RD_DIS[]; -extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_DIS_RTC_RAM_BOOT[]; extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_GROUP_1[]; extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_GROUP_2[]; extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SPI_BOOT_CRYPT_CNT[]; @@ -53,7 +52,6 @@ extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY3[]; extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY4[]; extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY5[]; extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_SYS_DATA_PART2[]; -extern const esp_efuse_desc_t* ESP_EFUSE_DIS_RTC_RAM_BOOT[]; extern const esp_efuse_desc_t* ESP_EFUSE_DIS_ICACHE[]; extern const esp_efuse_desc_t* ESP_EFUSE_DIS_DCACHE[]; extern const esp_efuse_desc_t* ESP_EFUSE_DIS_DOWNLOAD_ICACHE[]; @@ -117,10 +115,28 @@ extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_D7[]; extern const esp_efuse_desc_t* ESP_EFUSE_WAFER_VERSION[]; extern const esp_efuse_desc_t* ESP_EFUSE_PKG_VERSION[]; extern const esp_efuse_desc_t* ESP_EFUSE_BLOCK1_VERSION[]; -extern const esp_efuse_desc_t* ESP_EFUSE_SYS_DATA_PART0[]; +extern const esp_efuse_desc_t* ESP_EFUSE_ADC2_CAL_VOL_ATTEN3[]; extern const esp_efuse_desc_t* ESP_EFUSE_OPTIONAL_UNIQUE_ID[]; extern const esp_efuse_desc_t* ESP_EFUSE_BLOCK2_VERSION[]; +extern const esp_efuse_desc_t* ESP_EFUSE_TEMP_CALIB[]; +extern const esp_efuse_desc_t* ESP_EFUSE_OCODE[]; +extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_INIT_CODE_ATTEN0[]; +extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_INIT_CODE_ATTEN1[]; +extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_INIT_CODE_ATTEN2[]; +extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_INIT_CODE_ATTEN3[]; +extern const esp_efuse_desc_t* ESP_EFUSE_ADC2_INIT_CODE_ATTEN0[]; +extern const esp_efuse_desc_t* ESP_EFUSE_ADC2_INIT_CODE_ATTEN1[]; +extern const esp_efuse_desc_t* ESP_EFUSE_ADC2_INIT_CODE_ATTEN2[]; +extern const esp_efuse_desc_t* ESP_EFUSE_ADC2_INIT_CODE_ATTEN3[]; +extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN0[]; +extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN1[]; +extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN2[]; +extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN3[]; +extern const esp_efuse_desc_t* ESP_EFUSE_ADC2_CAL_VOL_ATTEN0[]; +extern const esp_efuse_desc_t* ESP_EFUSE_ADC2_CAL_VOL_ATTEN1[]; +extern const esp_efuse_desc_t* ESP_EFUSE_ADC2_CAL_VOL_ATTEN2[]; extern const esp_efuse_desc_t* ESP_EFUSE_USER_DATA[]; +extern const esp_efuse_desc_t* ESP_EFUSE_USER_DATA_MAC_CUSTOM[]; extern const esp_efuse_desc_t* ESP_EFUSE_KEY0[]; extern const esp_efuse_desc_t* ESP_EFUSE_KEY1[]; extern const esp_efuse_desc_t* ESP_EFUSE_KEY2[]; diff --git a/components/efuse/esp32s3/sources.cmake b/components/efuse/esp32s3/sources.cmake index 32e2583fcc..9dffd72008 100644 --- a/components/efuse/esp32s3/sources.cmake +++ b/components/efuse/esp32s3/sources.cmake @@ -1,3 +1,4 @@ set(EFUSE_SOC_SRCS "esp_efuse_table.c" "esp_efuse_fields.c" + "esp_efuse_rtc_calib.c" "esp_efuse_utility.c") diff --git a/components/efuse/src/esp_efuse_fields.c b/components/efuse/src/esp_efuse_fields.c index 5c390711ae..5e27f936c2 100644 --- a/components/efuse/src/esp_efuse_fields.c +++ b/components/efuse/src/esp_efuse_fields.c @@ -15,7 +15,7 @@ #include "esp_log.h" #include "soc/efuse_periph.h" #include "bootloader_random.h" -#include "soc/apb_ctrl_reg.h" +#include "soc/syscon_reg.h" #include "sys/param.h" static __attribute__((unused)) const char *TAG = "efuse"; diff --git a/components/efuse/test/test_efuse.c b/components/efuse/test/test_efuse.c index 0cd39c0381..f94a0c58a4 100644 --- a/components/efuse/test/test_efuse.c +++ b/components/efuse/test/test_efuse.c @@ -854,7 +854,7 @@ static void reset_task(void* arg) ESP_LOGI(TAG, "Start reset task"); while (!cmd_stop_reset_task) { esp_efuse_utility_reset(); - vTaskDelay(1); + vTaskDelay(2); } vTaskDelete(NULL); } diff --git a/components/esp-tls/Kconfig b/components/esp-tls/Kconfig index fe38ea79f7..636860986e 100644 --- a/components/esp-tls/Kconfig +++ b/components/esp-tls/Kconfig @@ -26,7 +26,8 @@ menu "ESP-TLS" config ESP_TLS_USE_DS_PERIPHERAL bool "Use Digital Signature (DS) Peripheral with ESP-TLS" - depends on (IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32H2) && ESP_TLS_USING_MBEDTLS + depends on (IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32H2 || IDF_TARGET_ESP32S3) + depends on ESP_TLS_USING_MBEDTLS default y help Enable use of the Digital Signature Peripheral for ESP-TLS.The DS peripheral @@ -40,6 +41,27 @@ menu "ESP-TLS" Enable support for creating server side SSL/TLS session, available for mbedTLS as well as wolfSSL TLS library. + config ESP_TLS_CLIENT_SESSION_TICKETS + bool "Enable client session tickets" + depends on ESP_TLS_USING_MBEDTLS && MBEDTLS_CLIENT_SSL_SESSION_TICKETS + default n + help + Enable session ticket support as specified in RFC5077. + + config ESP_TLS_SERVER_SESSION_TICKETS + bool "Enable server session tickets" + depends on ESP_TLS_SERVER && ESP_TLS_USING_MBEDTLS && MBEDTLS_SERVER_SSL_SESSION_TICKETS + default n + help + Enable session ticket support as specified in RFC5077 + + config ESP_TLS_SERVER_SESSION_TICKET_TIMEOUT + int "Server session ticket timeout in seconds" + depends on ESP_TLS_SERVER_SESSION_TICKETS + default 86400 + help + Sets the session ticket timeout used in the tls server. + config ESP_TLS_PSK_VERIFICATION bool "Enable PSK verification" select MBEDTLS_PSK_MODES if ESP_TLS_USING_MBEDTLS diff --git a/components/esp-tls/esp_tls.c b/components/esp-tls/esp_tls.c index 867e1012d9..29b14f508c 100644 --- a/components/esp-tls/esp_tls.c +++ b/components/esp-tls/esp_tls.c @@ -38,9 +38,12 @@ static const char *TAG = "esp-tls"; #define _esp_tls_write esp_mbedtls_write #define _esp_tls_conn_delete esp_mbedtls_conn_delete #define _esp_tls_net_init esp_mbedtls_net_init +#define _esp_tls_get_client_session esp_mbedtls_get_client_session #ifdef CONFIG_ESP_TLS_SERVER #define _esp_tls_server_session_create esp_mbedtls_server_session_create #define _esp_tls_server_session_delete esp_mbedtls_server_session_delete +#define _esp_tls_server_session_ticket_ctx_init esp_mbedtls_server_session_ticket_ctx_init +#define _esp_tls_server_session_ticket_ctx_free esp_mbedtls_server_session_ticket_ctx_free #endif /* CONFIG_ESP_TLS_SERVER */ #define _esp_tls_get_bytes_avail esp_mbedtls_get_bytes_avail #define _esp_tls_init_global_ca_store esp_mbedtls_init_global_ca_store @@ -568,7 +571,45 @@ mbedtls_x509_crt *esp_tls_get_global_ca_store(void) } #endif /* CONFIG_ESP_TLS_USING_MBEDTLS */ + +#ifdef CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS +esp_tls_client_session_t *esp_tls_get_client_session(esp_tls_t *tls) +{ + return _esp_tls_get_client_session(tls); +} +#endif /* CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS */ + + #ifdef CONFIG_ESP_TLS_SERVER +esp_err_t esp_tls_cfg_server_session_tickets_init(esp_tls_cfg_server_t *cfg) +{ +#if defined(CONFIG_ESP_TLS_SERVER_SESSION_TICKETS) + if (!cfg || cfg->ticket_ctx) { + return ESP_ERR_INVALID_ARG; + } + cfg->ticket_ctx = calloc(1, sizeof(esp_tls_server_session_ticket_ctx_t)); + if (!cfg->ticket_ctx) { + return ESP_ERR_NO_MEM; + } + esp_err_t ret = _esp_tls_server_session_ticket_ctx_init(cfg->ticket_ctx); + if (ret != ESP_OK) { + free(cfg->ticket_ctx); + } + return ret; +#else + return ESP_ERR_NOT_SUPPORTED; +#endif +} + +void esp_tls_cfg_server_session_tickets_free(esp_tls_cfg_server_t *cfg) +{ +#if defined(CONFIG_ESP_TLS_SERVER_SESSION_TICKETS) + if (cfg && cfg->ticket_ctx) { + _esp_tls_server_session_ticket_ctx_free(cfg->ticket_ctx); + } +#endif +} + /** * @brief Create a server side TLS/SSL connection */ diff --git a/components/esp-tls/esp_tls.h b/components/esp-tls/esp_tls.h index 9330f9dd69..588f70d83f 100644 --- a/components/esp-tls/esp_tls.h +++ b/components/esp-tls/esp_tls.h @@ -20,6 +20,9 @@ #include "mbedtls/ctr_drbg.h" #include "mbedtls/error.h" #include "mbedtls/certs.h" +#ifdef CONFIG_ESP_TLS_SERVER_SESSION_TICKETS +#include "mbedtls/ssl_ticket.h" +#endif #elif CONFIG_ESP_TLS_USING_WOLFSSL #include "wolfssl/wolfcrypt/settings.h" #include "wolfssl/ssl.h" @@ -54,6 +57,15 @@ typedef struct psk_key_hint { const char* hint; /*!< hint in PSK authentication mode in string format */ } psk_hint_key_t; +/** + * @brief esp-tls client session ticket ctx + */ +#ifdef CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS +typedef struct esp_tls_client_session { + mbedtls_ssl_session saved_session; +} esp_tls_client_session_t; +#endif /* CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS */ + /** * @brief Keep alive parameters structure */ @@ -168,9 +180,27 @@ typedef struct esp_tls_cfg { directly with esp_tls_plain_tcp_connect() API */ struct ifreq *if_name; /*!< The name of interface for data to go through. Use the default interface without setting */ + +#ifdef CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS + esp_tls_client_session_t *client_session; /*! Pointer for the client session ticket context. */ +#endif /* CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS */ } esp_tls_cfg_t; #ifdef CONFIG_ESP_TLS_SERVER +#if defined(CONFIG_ESP_TLS_SERVER_SESSION_TICKETS) +/** + * @brief Data structures necessary to support TLS session tickets according to RFC5077 + */ +typedef struct esp_tls_server_session_ticket_ctx { + mbedtls_entropy_context entropy; /*!< mbedTLS entropy context structure */ + + mbedtls_ctr_drbg_context ctr_drbg; /*!< mbedTLS ctr drbg context structure. + CTR_DRBG is deterministic random + bit generation based on AES-256 */ + mbedtls_ssl_ticket_context ticket_ctx; /*!< Session ticket generation context */ +} esp_tls_server_session_ticket_ctx_t; +#endif + typedef struct esp_tls_cfg_server { const char **alpn_protos; /*!< Application protocols required for HTTP2. If HTTP2/ALPN support is required, a list @@ -222,7 +252,39 @@ typedef struct esp_tls_cfg_server { unsigned int serverkey_password_len; /*!< String length of the password pointed to by serverkey_password */ +#if defined(CONFIG_ESP_TLS_SERVER_SESSION_TICKETS) + esp_tls_server_session_ticket_ctx_t * ticket_ctx; /*!< Session ticket generation context. + You have to call esp_tls_cfg_server_session_tickets_init + to use it. + Call esp_tls_cfg_server_session_tickets_free + to free the data associated with this context. */ +#endif } esp_tls_cfg_server_t; + +/** + * @brief Initialize the server side TLS session ticket context + * + * This function initializes the server side tls session ticket context + * which holds all necessary data structures to enable tls session tickets + * according to RFC5077. + * Use esp_tls_cfg_server_session_tickets_free to free the data. + * + * @param[in] cfg server configuration as esp_tls_cfg_server_t + * @return + * ESP_OK if setup succeeded + * ESP_ERR_INVALID_ARG if context is already initialized + * ESP_ERR_NO_MEM if memory allocation failed + * ESP_ERR_NOT_SUPPORTED if session tickets are not available due to build configuration + * ESP_FAIL if setup failed + */ +esp_err_t esp_tls_cfg_server_session_tickets_init(esp_tls_cfg_server_t *cfg); + +/** + * @brief Free the server side TLS session ticket context + * + * @param cfg server configuration as esp_tls_cfg_server_t + */ +void esp_tls_cfg_server_session_tickets_free(esp_tls_cfg_server_t *cfg); #endif /* ! CONFIG_ESP_TLS_SERVER */ /** @@ -404,6 +466,10 @@ int esp_tls_conn_http_new_async(const char *url, const esp_tls_cfg_t *cfg, esp_t * of bytes actually written to the TLS/SSL connection. * - <0 if write operation was not successful, because either an * error occured or an action must be taken by the calling process. + * - ESP_TLS_ERR_SSL_WANT_READ/ + * ESP_TLS_ERR_SSL_WANT_WRITE. + * if the handshake is incomplete and waiting for data to be available for reading. + * In this case this functions needs to be called again when the underlying transport is ready for operation. */ static inline ssize_t esp_tls_conn_write(esp_tls_t *tls, const void *data, size_t datalen) { @@ -609,6 +675,20 @@ void esp_tls_server_session_delete(esp_tls_t *tls); */ esp_err_t esp_tls_plain_tcp_connect(const char *host, int hostlen, int port, const esp_tls_cfg_t *cfg, esp_tls_error_handle_t error_handle, int *sockfd); +#ifdef CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS +/** + * @brief Obtain the client session ticket + * + * This function should be called when the TLS connection is already established. + * This can be passed again in the esp_tls_cfg_t structure, to appropriate tls session create (e.g. esp_tls_conn_http_new) API for session resumption. + * + * @param[in] esp_tls context as esp_tls_t + * @return + * Pointer to the saved client session. + * NULL on Failure + */ +esp_tls_client_session_t *esp_tls_get_client_session(esp_tls_t *tls); +#endif /* CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS */ #ifdef __cplusplus } #endif diff --git a/components/esp-tls/esp_tls_errors.h b/components/esp-tls/esp_tls_errors.h index 5dfe74791c..ad104895aa 100644 --- a/components/esp-tls/esp_tls_errors.h +++ b/components/esp-tls/esp_tls_errors.h @@ -14,35 +14,42 @@ extern "C" { #endif #define ESP_ERR_ESP_TLS_BASE 0x8000 /*!< Starting number of ESP-TLS error codes */ + +/* generic esp-tls error codes */ #define ESP_ERR_ESP_TLS_CANNOT_RESOLVE_HOSTNAME (ESP_ERR_ESP_TLS_BASE + 0x01) /*!< Error if hostname couldn't be resolved upon tls connection */ #define ESP_ERR_ESP_TLS_CANNOT_CREATE_SOCKET (ESP_ERR_ESP_TLS_BASE + 0x02) /*!< Failed to create socket */ #define ESP_ERR_ESP_TLS_UNSUPPORTED_PROTOCOL_FAMILY (ESP_ERR_ESP_TLS_BASE + 0x03) /*!< Unsupported protocol family */ #define ESP_ERR_ESP_TLS_FAILED_CONNECT_TO_HOST (ESP_ERR_ESP_TLS_BASE + 0x04) /*!< Failed to connect to host */ #define ESP_ERR_ESP_TLS_SOCKET_SETOPT_FAILED (ESP_ERR_ESP_TLS_BASE + 0x05) /*!< failed to set/get socket option */ -#define ESP_ERR_MBEDTLS_CERT_PARTLY_OK (ESP_ERR_ESP_TLS_BASE + 0x06) /*!< mbedtls parse certificates was partly successful */ -#define ESP_ERR_MBEDTLS_CTR_DRBG_SEED_FAILED (ESP_ERR_ESP_TLS_BASE + 0x07) /*!< mbedtls api returned error */ -#define ESP_ERR_MBEDTLS_SSL_SET_HOSTNAME_FAILED (ESP_ERR_ESP_TLS_BASE + 0x08) /*!< mbedtls api returned error */ -#define ESP_ERR_MBEDTLS_SSL_CONFIG_DEFAULTS_FAILED (ESP_ERR_ESP_TLS_BASE + 0x09) /*!< mbedtls api returned error */ -#define ESP_ERR_MBEDTLS_SSL_CONF_ALPN_PROTOCOLS_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0A) /*!< mbedtls api returned error */ -#define ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0B) /*!< mbedtls api returned error */ -#define ESP_ERR_MBEDTLS_SSL_CONF_OWN_CERT_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0C) /*!< mbedtls api returned error */ -#define ESP_ERR_MBEDTLS_SSL_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0D) /*!< mbedtls api returned error */ -#define ESP_ERR_MBEDTLS_SSL_WRITE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0E) /*!< mbedtls api returned error */ -#define ESP_ERR_MBEDTLS_PK_PARSE_KEY_FAILED (ESP_ERR_ESP_TLS_BASE + 0x0F) /*!< mbedtls api returned failed */ -#define ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x10) /*!< mbedtls api returned failed */ -#define ESP_ERR_MBEDTLS_SSL_CONF_PSK_FAILED (ESP_ERR_ESP_TLS_BASE + 0x11) /*!< mbedtls api returned failed */ -#define ESP_ERR_ESP_TLS_CONNECTION_TIMEOUT (ESP_ERR_ESP_TLS_BASE + 0x12) /*!< new connection in esp_tls_low_level_conn connection timeouted */ -#define ESP_ERR_WOLFSSL_SSL_SET_HOSTNAME_FAILED (ESP_ERR_ESP_TLS_BASE + 0x13) /*!< wolfSSL api returned error */ -#define ESP_ERR_WOLFSSL_SSL_CONF_ALPN_PROTOCOLS_FAILED (ESP_ERR_ESP_TLS_BASE + 0x14) /*!< wolfSSL api returned error */ -#define ESP_ERR_WOLFSSL_CERT_VERIFY_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x15) /*!< wolfSSL api returned error */ -#define ESP_ERR_WOLFSSL_KEY_VERIFY_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x16) /*!< wolfSSL api returned error */ -#define ESP_ERR_WOLFSSL_SSL_HANDSHAKE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x17) /*!< wolfSSL api returned failed */ -#define ESP_ERR_WOLFSSL_CTX_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x18) /*!< wolfSSL api returned failed */ -#define ESP_ERR_WOLFSSL_SSL_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x19) /*!< wolfSSL api returned failed */ -#define ESP_ERR_WOLFSSL_SSL_WRITE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x1A) /*!< wolfSSL api returned failed */ +#define ESP_ERR_ESP_TLS_CONNECTION_TIMEOUT (ESP_ERR_ESP_TLS_BASE + 0x06) /*!< new connection in esp_tls_low_level_conn connection timeouted */ +#define ESP_ERR_ESP_TLS_SE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x07) /*< esp-tls use Secure Element returned failed */ +#define ESP_ERR_ESP_TLS_TCP_CLOSED_FIN (ESP_ERR_ESP_TLS_BASE + 0x08) /*< esp-tls's TPC transport connection has benn closed (in a clean way) */ + +/* mbedtls specific error codes */ +#define ESP_ERR_MBEDTLS_CERT_PARTLY_OK (ESP_ERR_ESP_TLS_BASE + 0x10) /*!< mbedtls parse certificates was partly successful */ +#define ESP_ERR_MBEDTLS_CTR_DRBG_SEED_FAILED (ESP_ERR_ESP_TLS_BASE + 0x11) /*!< mbedtls api returned error */ +#define ESP_ERR_MBEDTLS_SSL_SET_HOSTNAME_FAILED (ESP_ERR_ESP_TLS_BASE + 0x12) /*!< mbedtls api returned error */ +#define ESP_ERR_MBEDTLS_SSL_CONFIG_DEFAULTS_FAILED (ESP_ERR_ESP_TLS_BASE + 0x13) /*!< mbedtls api returned error */ +#define ESP_ERR_MBEDTLS_SSL_CONF_ALPN_PROTOCOLS_FAILED (ESP_ERR_ESP_TLS_BASE + 0x14) /*!< mbedtls api returned error */ +#define ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x15) /*!< mbedtls api returned error */ +#define ESP_ERR_MBEDTLS_SSL_CONF_OWN_CERT_FAILED (ESP_ERR_ESP_TLS_BASE + 0x16) /*!< mbedtls api returned error */ +#define ESP_ERR_MBEDTLS_SSL_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x17) /*!< mbedtls api returned error */ +#define ESP_ERR_MBEDTLS_SSL_WRITE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x18) /*!< mbedtls api returned error */ +#define ESP_ERR_MBEDTLS_PK_PARSE_KEY_FAILED (ESP_ERR_ESP_TLS_BASE + 0x19) /*!< mbedtls api returned failed */ +#define ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x1A) /*!< mbedtls api returned failed */ +#define ESP_ERR_MBEDTLS_SSL_CONF_PSK_FAILED (ESP_ERR_ESP_TLS_BASE + 0x1B) /*!< mbedtls api returned failed */ +#define ESP_ERR_MBEDTLS_SSL_TICKET_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x1C) /*!< mbedtls api returned failed */ + +/* wolfssl specific error codes */ +#define ESP_ERR_WOLFSSL_SSL_SET_HOSTNAME_FAILED (ESP_ERR_ESP_TLS_BASE + 0x31) /*!< wolfSSL api returned error */ +#define ESP_ERR_WOLFSSL_SSL_CONF_ALPN_PROTOCOLS_FAILED (ESP_ERR_ESP_TLS_BASE + 0x32) /*!< wolfSSL api returned error */ +#define ESP_ERR_WOLFSSL_CERT_VERIFY_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x33) /*!< wolfSSL api returned error */ +#define ESP_ERR_WOLFSSL_KEY_VERIFY_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x34) /*!< wolfSSL api returned error */ +#define ESP_ERR_WOLFSSL_SSL_HANDSHAKE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x35) /*!< wolfSSL api returned failed */ +#define ESP_ERR_WOLFSSL_CTX_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x36) /*!< wolfSSL api returned failed */ +#define ESP_ERR_WOLFSSL_SSL_SETUP_FAILED (ESP_ERR_ESP_TLS_BASE + 0x37) /*!< wolfSSL api returned failed */ +#define ESP_ERR_WOLFSSL_SSL_WRITE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x38) /*!< wolfSSL api returned failed */ -#define ESP_ERR_ESP_TLS_SE_FAILED (ESP_ERR_ESP_TLS_BASE + 0x1B) /*< esp-tls use Secure Element returned failed */ -#define ESP_ERR_ESP_TLS_TCP_CLOSED_FIN (ESP_ERR_ESP_TLS_BASE + 0x1C) /*< esp-tls's TPC transport connection has benn closed (in a clean way) */ /** * Definition of errors reported from IO API (potentially non-blocking) in case of error: diff --git a/components/esp-tls/esp_tls_mbedtls.c b/components/esp-tls/esp_tls_mbedtls.c index 35064399c9..fb6e10366a 100644 --- a/components/esp-tls/esp_tls_mbedtls.c +++ b/components/esp-tls/esp_tls_mbedtls.c @@ -44,7 +44,6 @@ static esp_err_t esp_mbedtls_init_pk_ctx_for_ds(const void *pki); static const char *TAG = "esp-tls-mbedtls"; static mbedtls_x509_crt *global_cacert = NULL; - /* This function shall return the error message when appropriate log level has been set, otherwise this function shall do nothing */ static void mbedtls_print_error_msg(int error) { @@ -132,12 +131,48 @@ exit: } +#ifdef CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS +esp_tls_client_session_t *esp_mbedtls_get_client_session(esp_tls_t *tls) +{ + if (tls == NULL) { + ESP_LOGE(TAG, "esp_tls session context cannot be NULL"); + return NULL; + } + + esp_tls_client_session_t *client_session = (esp_tls_client_session_t*)calloc(1, sizeof(esp_tls_client_session_t)); + if (client_session == NULL) { + ESP_LOGE(TAG, "Failed to allocate memory for client session ctx"); + return NULL; + } + + int ret = mbedtls_ssl_get_session(&tls->ssl, &(client_session->saved_session)); + if (ret != 0) { + ESP_LOGE(TAG, "Error in obtaining the client ssl session"); + mbedtls_print_error_msg(ret); + free(client_session); + return NULL; + } + + return client_session; +} +#endif /* CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS */ + int esp_mbedtls_handshake(esp_tls_t *tls, const esp_tls_cfg_t *cfg) { int ret; +#ifdef CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS + if (cfg->client_session != NULL) { + ESP_LOGD(TAG, "Reusing the already saved client session context"); + if ((ret = mbedtls_ssl_set_session(&tls->ssl, &(cfg->client_session->saved_session))) != 0 ) { + ESP_LOGE(TAG, " mbedtls_ssl_conf_session returned -0x%04X", -ret); + return -1; + } + } +#endif ret = mbedtls_ssl_handshake(&tls->ssl); if (ret == 0) { tls->conn_state = ESP_TLS_DONE; + #ifdef CONFIG_ESP_TLS_USE_DS_PERIPHERAL esp_ds_release_ds_lock(); #endif @@ -198,10 +233,10 @@ ssize_t esp_mbedtls_write(esp_tls_t *tls, const char *data, size_t datalen) mbedtls_print_error_msg(ret); return ret; } else { - // Exitting the tls-write process as less than desired datalen are writable + // Exiting the tls-write process as less than desired datalen are writable ESP_LOGD(TAG, "mbedtls_ssl_write() returned -0x%04X, already written %d, exitting...", -ret, written); mbedtls_print_error_msg(ret); - return written; + return (written > 0) ? written : ret; } } written += ret; @@ -368,8 +403,75 @@ static esp_err_t set_global_ca_store(esp_tls_t *tls) return ESP_OK; } - #ifdef CONFIG_ESP_TLS_SERVER +#ifdef CONFIG_ESP_TLS_SERVER_SESSION_TICKETS +int esp_mbedtls_server_session_ticket_write(void *p_ticket, const mbedtls_ssl_session *session, unsigned char *start, const unsigned char *end, size_t *tlen, uint32_t *lifetime) +{ + int ret = mbedtls_ssl_ticket_write(p_ticket, session, start, end, tlen, lifetime); +#ifndef NDEBUG + if (ret != 0) { + ESP_LOGE(TAG, "Writing session ticket resulted in error code -0x%04X", -ret); + mbedtls_print_error_msg(ret); + } +#endif + return ret; +} + +int esp_mbedtls_server_session_ticket_parse(void *p_ticket, mbedtls_ssl_session *session, unsigned char *buf, size_t len) +{ + int ret = mbedtls_ssl_ticket_parse(p_ticket, session, buf, len); +#ifndef NDEBUG + if (ret != 0) { + ESP_LOGD(TAG, "Parsing session ticket resulted in error code -0x%04X", -ret); + mbedtls_print_error_msg(ret); + } +#endif + return ret; +} + +esp_err_t esp_mbedtls_server_session_ticket_ctx_init(esp_tls_server_session_ticket_ctx_t *ctx) +{ + if (!ctx) { + return ESP_ERR_INVALID_ARG; + } + mbedtls_ctr_drbg_init(&ctx->ctr_drbg); + mbedtls_entropy_init(&ctx->entropy); + mbedtls_ssl_ticket_init(&ctx->ticket_ctx); + int ret; + esp_err_t esp_ret; + if ((ret = mbedtls_ctr_drbg_seed(&ctx->ctr_drbg, + mbedtls_entropy_func, &ctx->entropy, NULL, 0)) != 0) { + ESP_LOGE(TAG, "mbedtls_ctr_drbg_seed returned -0x%04X", -ret); + mbedtls_print_error_msg(ret); + esp_ret = ESP_ERR_MBEDTLS_CTR_DRBG_SEED_FAILED; + goto exit; + } + + if((ret = mbedtls_ssl_ticket_setup(&ctx->ticket_ctx, + mbedtls_ctr_drbg_random, &ctx->ctr_drbg, + MBEDTLS_CIPHER_AES_256_GCM, + CONFIG_ESP_TLS_SERVER_SESSION_TICKET_TIMEOUT)) != 0) { + ESP_LOGE(TAG, "mbedtls_ssl_ticket_setup returned -0x%04X", -ret); + mbedtls_print_error_msg(ret); + esp_ret = ESP_ERR_MBEDTLS_SSL_TICKET_SETUP_FAILED; + goto exit; + } + return ESP_OK; +exit: + esp_mbedtls_server_session_ticket_ctx_free(ctx); + return esp_ret; +} + +void esp_mbedtls_server_session_ticket_ctx_free(esp_tls_server_session_ticket_ctx_t *ctx) +{ + if (ctx) { + mbedtls_ssl_ticket_free(&ctx->ticket_ctx); + mbedtls_ctr_drbg_init(&ctx->ctr_drbg); + mbedtls_entropy_free(&ctx->entropy); + } +} +#endif + esp_err_t set_server_config(esp_tls_cfg_server_t *cfg, esp_tls_t *tls) { assert(cfg != NULL); @@ -421,6 +523,18 @@ esp_err_t set_server_config(esp_tls_cfg_server_t *cfg, esp_tls_t *tls) ESP_LOGE(TAG, "Missing server certificate and/or key"); return ESP_ERR_INVALID_STATE; } + +#ifdef CONFIG_ESP_TLS_SERVER_SESSION_TICKETS + if (cfg->ticket_ctx) { + ESP_LOGD(TAG, "Enabling server-side tls session ticket support"); + + mbedtls_ssl_conf_session_tickets_cb( &tls->conf, + esp_mbedtls_server_session_ticket_write, + esp_mbedtls_server_session_ticket_parse, + &cfg->ticket_ctx->ticket_ctx ); + } +#endif + return ESP_OK; } #endif /* ! CONFIG_ESP_TLS_SERVER */ @@ -480,6 +594,13 @@ esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t #endif } +#ifdef CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS + ESP_LOGD(TAG, "Enabling client-side tls session ticket support"); + mbedtls_ssl_conf_session_tickets(&tls->conf, MBEDTLS_SSL_SESSION_TICKETS_ENABLED); + mbedtls_ssl_conf_renegotiation(&tls->conf, MBEDTLS_SSL_RENEGOTIATION_ENABLED); + +#endif /* CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS */ + if (cfg->crt_bundle_attach != NULL) { #ifdef CONFIG_MBEDTLS_CERTIFICATE_BUNDLE ESP_LOGD(TAG, "Use certificate bundle"); @@ -516,6 +637,10 @@ esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t #else ESP_LOGE(TAG, "psk_hint_key configured but not enabled in menuconfig: Please enable ESP_TLS_PSK_VERIFICATION option"); return ESP_ERR_INVALID_STATE; +#endif +#ifdef CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS + } else if (cfg->client_session != NULL) { + ESP_LOGD(TAG, "Resuing the saved client session"); #endif } else { #ifdef CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY diff --git a/components/esp-tls/esp_tls_wolfssl.c b/components/esp-tls/esp_tls_wolfssl.c index dabcd6225c..08dca316d4 100644 --- a/components/esp-tls/esp_tls_wolfssl.c +++ b/components/esp-tls/esp_tls_wolfssl.c @@ -409,7 +409,7 @@ ssize_t esp_wolfssl_read(esp_tls_t *tls, char *data, size_t datalen) ssize_t esp_wolfssl_write(esp_tls_t *tls, const char *data, size_t datalen) { ssize_t ret = wolfSSL_write( (WOLFSSL *)tls->priv_ssl, (unsigned char *) data, datalen); - if (ret < 0) { + if (ret <= 0) { int err = wolfSSL_get_error( (WOLFSSL *)tls->priv_ssl, ret); if (err != WOLFSSL_ERROR_WANT_READ && err != WOLFSSL_ERROR_WANT_WRITE) { ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_WOLFSSL, -err); diff --git a/components/esp-tls/private_include/esp_tls_mbedtls.h b/components/esp-tls/private_include/esp_tls_mbedtls.h index 78694fc858..c1c5d4f328 100644 --- a/components/esp-tls/private_include/esp_tls_mbedtls.h +++ b/components/esp-tls/private_include/esp_tls_mbedtls.h @@ -76,6 +76,22 @@ int esp_mbedtls_server_session_create(esp_tls_cfg_server_t *cfg, int sockfd, esp * /note :- The function can only be used with mbedtls ssl library */ void esp_mbedtls_server_session_delete(esp_tls_t *tls); + +#ifdef CONFIG_ESP_TLS_SERVER_SESSION_TICKETS +/** + * Internal function to setup server side session ticket context + * + * /note :- The function can only be used with mbedtls ssl library + */ +esp_err_t esp_mbedtls_server_session_ticket_ctx_init(esp_tls_server_session_ticket_ctx_t *cfg); + +/** + * Internal function to free server side session ticket context + * + * /note :- The function can only be used with mbedtls ssl library + */ +void esp_mbedtls_server_session_ticket_ctx_free(esp_tls_server_session_ticket_ctx_t *cfg); +#endif #endif /** @@ -83,6 +99,13 @@ void esp_mbedtls_server_session_delete(esp_tls_t *tls); */ esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t *cfg, esp_tls_t *tls); +#ifdef CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS +/** + * Internal Callback for mbedtls_get_client_session + */ +esp_tls_client_session_t *esp_mbedtls_get_client_session(esp_tls_t *tls); +#endif + /** * Internal Callback for mbedtls_init_global_ca_store */ diff --git a/components/esp32/Kconfig b/components/esp32/Kconfig index b166fcdc7b..3b65e05d6e 100644 --- a/components/esp32/Kconfig +++ b/components/esp32/Kconfig @@ -646,6 +646,7 @@ menu "ESP32-specific" select ESP_SYSTEM_RTC_EXT_XTAL config ESP32_RTC_CLK_SRC_EXT_OSC bool "External 32kHz oscillator at 32K_XN pin" + select ESP_SYSTEM_RTC_EXT_OSC config ESP32_RTC_CLK_SRC_INT_8MD256 bool "Internal 8.5MHz oscillator, divided by 256 (~33kHz)" endchoice @@ -846,7 +847,7 @@ menu "ESP32-specific" depends on ESP32_USE_FIXED_STATIC_RAM_SIZE help RAM size dedicated for static variables (.data & .bss sections). - Please note that the actual length will be reduced by BT_RESERVE_DRAM if Bluetooth + Please note that the actual length will be reduced by BTDM_RESERVE_DRAM if Bluetooth controller is enabled. config ESP32_DPORT_DIS_INTERRUPT_LVL diff --git a/components/esp32c3/Kconfig b/components/esp32c3/Kconfig index bb583c732e..dd6e5543bc 100644 --- a/components/esp32c3/Kconfig +++ b/components/esp32c3/Kconfig @@ -157,6 +157,7 @@ menu "ESP32C3-Specific" select ESP_SYSTEM_RTC_EXT_XTAL config ESP32C3_RTC_CLK_SRC_EXT_OSC bool "External 32kHz oscillator at 32K_XP pin" + select ESP_SYSTEM_RTC_EXT_OSC config ESP32C3_RTC_CLK_SRC_INT_8MD256 bool "Internal 8MHz oscillator, divided by 256 (~32kHz)" endchoice diff --git a/components/esp32h2/Kconfig b/components/esp32h2/Kconfig index 4413c4b0e5..9144e0d96e 100644 --- a/components/esp32h2/Kconfig +++ b/components/esp32h2/Kconfig @@ -10,10 +10,13 @@ menu "ESP32H2-Specific" config ESP32H2_DEFAULT_CPU_FREQ_16 bool "16 MHz" + depends on IDF_ENV_FPGA #ESP32H2-TODO: IDF-3786 config ESP32H2_DEFAULT_CPU_FREQ_32 bool "32 MHz" + depends on IDF_ENV_FPGA #ESP32H2-TODO: IDF-3786 config ESP32H2_DEFAULT_CPU_FREQ_64 bool "64 MHz" + depends on IDF_ENV_FPGA #ESP32H2-TODO: IDF-3786 config ESP32H2_DEFAULT_CPU_FREQ_96 bool "96 MHz" depends on !IDF_ENV_FPGA @@ -150,6 +153,7 @@ menu "ESP32H2-Specific" select ESP_SYSTEM_RTC_EXT_XTAL config ESP32H2_RTC_CLK_SRC_EXT_OSC bool "External 32kHz oscillator at 32K_XP pin" + select ESP_SYSTEM_RTC_EXT_OSC config ESP32H2_RTC_CLK_SRC_INT_8MD256 bool "Internal 8MHz oscillator, divided by 256 (~32kHz)" endchoice diff --git a/components/esp32s2/Kconfig b/components/esp32s2/Kconfig index 9c8805dacf..997c553ddc 100644 --- a/components/esp32s2/Kconfig +++ b/components/esp32s2/Kconfig @@ -382,6 +382,7 @@ menu "ESP32S2-specific" select ESP_SYSTEM_RTC_EXT_XTAL config ESP32S2_RTC_CLK_SRC_EXT_OSC bool "External 32kHz oscillator at 32K_XN pin" + select ESP_SYSTEM_RTC_EXT_OSC config ESP32S2_RTC_CLK_SRC_INT_8MD256 bool "Internal 8MHz oscillator, divided by 256 (~32kHz)" endchoice diff --git a/components/esp32s3/Kconfig b/components/esp32s3/Kconfig index 2205b88470..725659b551 100644 --- a/components/esp32s3/Kconfig +++ b/components/esp32s3/Kconfig @@ -108,7 +108,8 @@ menu "ESP32S3-Specific" config ESP32S3_DATA_CACHE_SIZE hex - default 0x4000 if ESP32S3_DATA_CACHE_16KB + # For 16KB the actual configuration is 32kb cache, but 16kb will be reserved for heap at startup + default 0x8000 if ESP32S3_DATA_CACHE_16KB default 0x8000 if ESP32S3_DATA_CACHE_32KB default 0x10000 if ESP32S3_DATA_CACHE_64KB @@ -140,12 +141,15 @@ menu "ESP32S3-Specific" depends on ESP32S3_DATA_CACHE_16KB || ESP32S3_DATA_CACHE_32KB config ESP32S3_DATA_CACHE_LINE_32B bool "32 Bytes" + config ESP32S3_DATA_CACHE_LINE_64B + bool "64 Bytes" endchoice config ESP32S3_DATA_CACHE_LINE_SIZE int default 16 if ESP32S3_DATA_CACHE_LINE_16B default 32 if ESP32S3_DATA_CACHE_LINE_32B + default 64 if ESP32S3_DATA_CACHE_LINE_64B config ESP32S3_DATA_CACHE_WRAP bool "Enable data cache wrap mode" @@ -246,6 +250,9 @@ menu "ESP32S3-Specific" help Select the speed for the SPI RAM chip. + config SPIRAM_SPEED_120M + depends on SPIRAM_MODE_QUAD + bool "120MHz clock speed" config SPIRAM_SPEED_80M bool "80MHz clock speed" config SPIRAM_SPEED_40M @@ -430,6 +437,7 @@ menu "ESP32S3-Specific" select ESP_SYSTEM_RTC_EXT_XTAL config ESP32S3_RTC_CLK_SRC_EXT_OSC bool "External 32kHz oscillator at 32K_XP pin" + select ESP_SYSTEM_RTC_EXT_OSC config ESP32S3_RTC_CLK_SRC_INT_8MD256 bool "Internal 8MHz oscillator, divided by 256 (~32kHz)" endchoice diff --git a/components/esp32s3/README.md b/components/esp32s3/README.md deleted file mode 100644 index d5cf8378f6..0000000000 --- a/components/esp32s3/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# ESP32-S3 component - -This directory contains support for the upcoming ESP32-S3 SoC. This code is **still work in progress and not intended for public use**. - -Please follow announcements on [espressif.com](https://www.espressif.com/) and [esp32.com](https://esp32.com/) to be informed about the ESP32-S3 SoC. - -*This note will be removed once the ESP32-S3 initial support is ready.* diff --git a/components/esp_adc_cal/CMakeLists.txt b/components/esp_adc_cal/CMakeLists.txt index 8b859d31ec..fe2961545b 100644 --- a/components/esp_adc_cal/CMakeLists.txt +++ b/components/esp_adc_cal/CMakeLists.txt @@ -15,6 +15,12 @@ elseif(${target} STREQUAL "esp32c3") INCLUDE_DIRS "include" REQUIRES driver efuse) +elseif(${target} STREQUAL "esp32s3") +idf_component_register(SRCS "esp_adc_cal_esp32s3.c" + INCLUDE_DIRS "include" + REQUIRES driver efuse) + + elseif(${target} STREQUAL "esp32h2") idf_component_register(SRCS "esp_adc_cal_esp32h2.c" INCLUDE_DIRS "include" diff --git a/components/esp_adc_cal/component.mk b/components/esp_adc_cal/component.mk index 260fc1345c..e85ba07e4d 100644 --- a/components/esp_adc_cal/component.mk +++ b/components/esp_adc_cal/component.mk @@ -3,4 +3,4 @@ # COMPONENT_ADD_INCLUDEDIRS := include -COMPONENT_OBJEXCLUDE += esp_adc_cal_esp32s2.o esp_adc_cal_esp32c3.o esp_adc_cal_esp32h2.o +COMPONENT_OBJEXCLUDE += esp_adc_cal_esp32s2.o esp_adc_cal_esp32c3.o esp_adc_cal_esp32h2.o esp_adc_cal_esp32s3.o diff --git a/components/esp_adc_cal/esp_adc_cal_esp32.c b/components/esp_adc_cal/esp_adc_cal_esp32.c index 43b08c1461..9c21e3ec33 100644 --- a/components/esp_adc_cal/esp_adc_cal_esp32.c +++ b/components/esp_adc_cal/esp_adc_cal_esp32.c @@ -17,6 +17,7 @@ #include "driver/adc.h" #include "soc/efuse_periph.h" #include "esp_err.h" +#include "esp_check.h" #include "assert.h" #include "esp_adc_cal.h" @@ -82,11 +83,7 @@ #define LUT_HIGH_THRESH (LUT_LOW_THRESH + LUT_ADC_STEP_SIZE) #define ADC_12_BIT_RES 4096 -#define ADC_CAL_CHECK(cond, ret) ({ \ - if(!(cond)){ \ - return ret; \ - } \ -}) +const static char LOG_TAG[] = "ADC_CALI"; /* ------------------------ Characterization Constants ---------------------- */ static const uint32_t adc1_tp_atten_scale[4] = {65504, 86975, 120389, 224310}; @@ -372,21 +369,20 @@ esp_err_t esp_adc_cal_get_voltage(adc_channel_t channel, uint32_t *voltage) { //Check parameters - ADC_CAL_CHECK(chars != NULL, ESP_ERR_INVALID_ARG); - ADC_CAL_CHECK(voltage != NULL, ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(chars != NULL, ESP_ERR_INVALID_ARG, LOG_TAG, "No characteristic input"); + ESP_RETURN_ON_FALSE(voltage != NULL, ESP_ERR_INVALID_ARG, LOG_TAG, "No output buffer"); + esp_err_t ret = ESP_OK; int adc_reading; if (chars->adc_num == ADC_UNIT_1) { //Check channel is valid on ADC1 - ADC_CAL_CHECK((adc1_channel_t)channel < ADC1_CHANNEL_MAX, ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(0), ESP_ERR_INVALID_ARG, LOG_TAG, "Invalid channel"); adc_reading = adc1_get_raw(channel); } else { //Check channel is valid on ADC2 - ADC_CAL_CHECK((adc2_channel_t)channel < ADC2_CHANNEL_MAX, ESP_ERR_INVALID_ARG); - if (adc2_get_raw(channel, chars->bit_width, &adc_reading) != ESP_OK) { - return ESP_ERR_TIMEOUT; //Timed out waiting for ADC2 - } + ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(1), ESP_ERR_INVALID_ARG, LOG_TAG, "Invalid channel"); + ret = adc2_get_raw(channel, chars->bit_width, &adc_reading); } *voltage = esp_adc_cal_raw_to_voltage((uint32_t)adc_reading, chars); - return ESP_OK; + return ret; } diff --git a/components/esp_adc_cal/esp_adc_cal_esp32c3.c b/components/esp_adc_cal/esp_adc_cal_esp32c3.c index ddae0efea3..7799e5cb1a 100644 --- a/components/esp_adc_cal/esp_adc_cal_esp32c3.c +++ b/components/esp_adc_cal/esp_adc_cal_esp32c3.c @@ -18,19 +18,12 @@ #include "esp_types.h" #include "esp_err.h" #include "esp_log.h" +#include "esp_check.h" #include "driver/adc.h" #include "hal/adc_ll.h" #include "esp_efuse_rtc_calib.h" #include "esp_adc_cal.h" - -#define ADC_CALIB_CHECK(cond, err_msg, ret) do {\ - if (!(cond)) { \ - ESP_LOGE(LOG_TAG, err_msg); \ - return (ret); \ - } \ - } while(0) - const static char LOG_TAG[] = "adc_calib"; @@ -110,13 +103,13 @@ esp_adc_cal_value_t esp_adc_cal_characterize(adc_unit_t adc_num, esp_err_t ret; adc_calib_parsed_info efuse_parsed_data = {0}; // Check parameters - ADC_CALIB_CHECK(adc_num == ADC_UNIT_1 || adc_num == ADC_UNIT_2, "Invalid unit num", ESP_ADC_CAL_VAL_NOT_SUPPORTED); - ADC_CALIB_CHECK(chars != NULL, "Invalid characteristic", ESP_ADC_CAL_VAL_NOT_SUPPORTED); - ADC_CALIB_CHECK(bit_width == ADC_WIDTH_BIT_12, "Invalid bit_width", ESP_ADC_CAL_VAL_NOT_SUPPORTED); - ADC_CALIB_CHECK(atten < 4, "Invalid attenuation", ESP_ADC_CAL_VAL_NOT_SUPPORTED); + ESP_RETURN_ON_FALSE(adc_num == ADC_UNIT_1 || adc_num == ADC_UNIT_2, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "Invalid unit num"); + ESP_RETURN_ON_FALSE(chars != NULL, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "Ivalid characteristic"); + ESP_RETURN_ON_FALSE(bit_width == ADC_WIDTH_BIT_12, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "Invalid bit_width"); + ESP_RETURN_ON_FALSE(atten < 4, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "Invalid attenuation"); int version_num = esp_efuse_rtc_calib_get_ver(); - ADC_CALIB_CHECK(version_num == 1, "No calibration efuse burnt", ESP_ADC_CAL_VAL_NOT_SUPPORTED); + ESP_RETURN_ON_FALSE(version_num == 1, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "No calibration efuse burnt"); memset(chars, 0, sizeof(esp_adc_cal_characteristics_t)); @@ -140,8 +133,7 @@ esp_adc_cal_value_t esp_adc_cal_characterize(adc_unit_t adc_num, uint32_t esp_adc_cal_raw_to_voltage(uint32_t adc_reading, const esp_adc_cal_characteristics_t *chars) { - ADC_CALIB_CHECK(chars != NULL, "No characteristic input.", ESP_ERR_INVALID_ARG); - + assert(chars != NULL); return adc_reading * chars->coeff_a / coeff_a_scaling + chars->coeff_b / coeff_b_scaling; } @@ -150,21 +142,20 @@ esp_err_t esp_adc_cal_get_voltage(adc_channel_t channel, uint32_t *voltage) { // Check parameters - ADC_CALIB_CHECK(chars != NULL, "No characteristic input.", ESP_ERR_INVALID_ARG); - ADC_CALIB_CHECK(voltage != NULL, "No output buffer.", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(chars != NULL, ESP_ERR_INVALID_ARG, LOG_TAG, "No characteristic input"); + ESP_RETURN_ON_FALSE(voltage != NULL, ESP_ERR_INVALID_ARG, LOG_TAG, "No output buffer"); + esp_err_t ret = ESP_OK; int adc_reading; if (chars->adc_num == ADC_UNIT_1) { //Check if channel is valid on ADC1 - ADC_CALIB_CHECK((adc1_channel_t)channel < ADC1_CHANNEL_MAX, "Invalid channel", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(0), ESP_ERR_INVALID_ARG, LOG_TAG, "Invalid channel"); adc_reading = adc1_get_raw(channel); } else { //Check if channel is valid on ADC2 - ADC_CALIB_CHECK((adc2_channel_t)channel < ADC2_CHANNEL_MAX, "Invalid channel", ESP_ERR_INVALID_ARG); - if (adc2_get_raw(channel, chars->bit_width, &adc_reading) != ESP_OK) { - return ESP_ERR_TIMEOUT; //Timed out waiting for ADC2 - } + ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(1), ESP_ERR_INVALID_ARG, LOG_TAG, "Invalid channel"); + ret = adc2_get_raw(channel, chars->bit_width, &adc_reading); } *voltage = esp_adc_cal_raw_to_voltage((uint32_t)adc_reading, chars); - return ESP_OK; + return ret; } diff --git a/components/esp_adc_cal/esp_adc_cal_esp32s2.c b/components/esp_adc_cal/esp_adc_cal_esp32s2.c index f3d058ccdf..94b9682cdb 100644 --- a/components/esp_adc_cal/esp_adc_cal_esp32s2.c +++ b/components/esp_adc_cal/esp_adc_cal_esp32s2.c @@ -17,6 +17,7 @@ #include "driver/adc.h" #include "soc/efuse_periph.h" #include "esp_err.h" +#include "esp_check.h" #include "assert.h" #include "esp_adc_cal.h" #include "esp_efuse.h" @@ -24,11 +25,6 @@ #include "esp_efuse_rtc_table.h" #include "hal/adc_hal.h" -#define ADC_CAL_CHECK(cond, ret) ({ \ - if(!(cond)){ \ - return ret; \ - } \ -}) const static char LOG_TAG[] = "adc_calib"; /* ------------------------ Characterization Constants ---------------------- */ @@ -207,8 +203,7 @@ esp_adc_cal_value_t esp_adc_cal_characterize(adc_unit_t adc_num, uint32_t esp_adc_cal_raw_to_voltage(uint32_t adc_reading, const esp_adc_cal_characteristics_t *chars) { - ADC_CAL_CHECK(chars != NULL, ESP_ERR_INVALID_ARG); - + assert(chars != NULL); return adc_reading * chars->coeff_a / coeff_a_scaling + chars->coeff_b / coeff_b_scaling; } @@ -217,21 +212,20 @@ esp_err_t esp_adc_cal_get_voltage(adc_channel_t channel, uint32_t *voltage) { // Check parameters - ADC_CAL_CHECK(chars != NULL, ESP_ERR_INVALID_ARG); - ADC_CAL_CHECK(voltage != NULL, ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(chars != NULL, ESP_ERR_INVALID_ARG, LOG_TAG, "No characteristic input"); + ESP_RETURN_ON_FALSE(voltage != NULL, ESP_ERR_INVALID_ARG, LOG_TAG, "No output buffer"); + esp_err_t ret = ESP_OK; int adc_reading; if (chars->adc_num == ADC_UNIT_1) { //Check if channel is valid on ADC1 - ADC_CAL_CHECK((adc1_channel_t)channel < ADC1_CHANNEL_MAX, ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(0), ESP_ERR_INVALID_ARG, LOG_TAG, "Invalid channel"); adc_reading = adc1_get_raw(channel); } else { //Check if channel is valid on ADC2 - ADC_CAL_CHECK((adc2_channel_t)channel < ADC2_CHANNEL_MAX, ESP_ERR_INVALID_ARG); - if (adc2_get_raw(channel, chars->bit_width, &adc_reading) != ESP_OK) { - return ESP_ERR_TIMEOUT; //Timed out waiting for ADC2 - } + ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(1), ESP_ERR_INVALID_ARG, LOG_TAG, "Invalid channel"); + ret = adc2_get_raw(channel, chars->bit_width, &adc_reading); } *voltage = esp_adc_cal_raw_to_voltage((uint32_t)adc_reading, chars); - return ESP_OK; + return ret; } diff --git a/components/esp_adc_cal/esp_adc_cal_esp32s3.c b/components/esp_adc_cal/esp_adc_cal_esp32s3.c new file mode 100644 index 0000000000..f7014fdf9f --- /dev/null +++ b/components/esp_adc_cal/esp_adc_cal_esp32s3.c @@ -0,0 +1,237 @@ +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "esp_types.h" +#include "esp_err.h" +#include "esp_log.h" +#include "esp_check.h" +#include "driver/adc.h" +#include "hal/adc_types.h" +#include "esp_efuse_rtc_calib.h" +#include "esp_adc_cal.h" + +const static char LOG_TAG[] = "ADC_CALI"; + +/* ------------------------ Characterization Constants ---------------------- */ + +//coeff_a is actually a float number +//it is scaled to put them into uint32_t so that the headers do not have to be changed +static const int coeff_a_scaling = 1000000; + +/** + * @note Error Calculation + * Coefficients for calculating the reading voltage error. + * Four sets of coefficients for atten0 ~ atten3 respectively. + * + * For each item, first element is the Coefficient, second element is the Multiple. (Coefficient / Multiple) is the real coefficient. + * + * @note {0,0} stands for unused item + * @note In case of the overflow, these coeffcients are recorded as Absolute Value + * @note For atten0 ~ 2, error = a1 * X^2 + a2 * X + a3; For atten3, error = a1 * X^4 + a2 * X^3 + a3 * X^2 + a4 * X + a5; + */ +const static uint64_t adc_error_coef_atten[4][10][2] = { + {{9798249589, 1e15}, {50871540569528, 1e16}, {3, 1}, {0, 0}, {0, 0}, //ADC1 atten0 + {36615265189, 1e16}, {1353548869615, 1e16}, {3, 1}, {0, 0}, {0, 0}}, //ADC2 atten0 + + {{101379430548, 1e16}, {49393185868806, 1e16}, {3, 1}, {0, 0}, {0, 0}, //ADC1 atten1 + {118964995959, 1e16}, {66319894226185, 1e16}, {2, 1}, {0, 0}, {0, 0}}, //ADC2 atten1 + + {{208385525314, 1e16}, {147640181047414, 1e16}, {2, 1}, {0, 0}, {0, 0}, //ADC1 atten2 + {259011467956, 1e16}, {200996773954387, 1e16}, {1, 1}, {0, 0}, {0, 0}}, //ADC2 atten2 + + {{13515, 1e15}, {70769718, 1e15}, {1297891447611, 1e16}, {644334888647536, 1e16}, {1,1}, //ADC1 atten3 + {15038, 1e15}, {79672528, 1e15}, {1478791187119, 1e16}, {755717904943462, 1e16}, {1,1}} //ADC2 atten3 + }; +const static int32_t adc_error_sign[4][10] = { + {1, -1, -1, 0, 0, //ADC1 atten0 + 1, 1, -1, 0, 0}, //ADC2 atten0 + + {1, -1, -1, 0, 0, //ADC1 atten1 + 1, -1, -1, 0, 0}, //ADC2 atten1 + + {1, -1, -1, 0, 0, //ADC1 atten2 + 1, -1, -1, 0, 0}, //ADC2 atten2 + + {1, -1, 1, -1, -1, //ADC1 atten3 + 1, -1, 1, -1, 1} //ADC2 atten3 + }; + +/* -------------------- Characterization Helper Data Types ------------------ */ +typedef struct { + uint32_t voltage; + uint32_t digi; +} adc_calib_data_ver1_t; + +typedef struct { + char version_num; + adc_unit_t adc_num; + adc_atten_t atten_level; + union { + adc_calib_data_ver1_t ver1; + } ref_data; +} adc_calib_info_t; + + +//To get the reference point (Dout, Vin) +static esp_err_t get_reference_point(int version_num, adc_unit_t adc_num, adc_atten_t atten, adc_calib_info_t *calib_info) +{ + assert(version_num == 1); + esp_err_t ret; + + calib_info->version_num = version_num; + calib_info->adc_num = adc_num; + calib_info->atten_level = atten; + + uint32_t voltage = 0; + uint32_t digi = 0; + ret = esp_efuse_rtc_calib_get_cal_voltage(version_num, ((adc_num == ADC_UNIT_1) ? 0 : 1), atten, &digi, &voltage); + assert(ret == ESP_OK); + calib_info->ref_data.ver1.voltage = voltage; + calib_info->ref_data.ver1.digi = digi; + return ret; +} + +esp_err_t esp_adc_cal_check_efuse(esp_adc_cal_value_t source) +{ + if (source != ESP_ADC_CAL_VAL_EFUSE_TP_FIT) { + return ESP_ERR_NOT_SUPPORTED; + } + uint8_t adc_encoding_version = esp_efuse_rtc_calib_get_ver(); + if (adc_encoding_version != 1) { + // current version only accepts encoding ver 1. + return ESP_ERR_INVALID_VERSION; + } + return ESP_OK; +} + +/* + * Get an expected linear relationship btwn Vin and Dout + */ +static void calculate_characterization_coefficients(const adc_calib_info_t *parsed_data, esp_adc_cal_characteristics_t *chars) +{ + chars->coeff_a = coeff_a_scaling * parsed_data->ref_data.ver1.voltage / parsed_data->ref_data.ver1.digi; + chars->coeff_b = 0; + ESP_LOGV(LOG_TAG, "Calib V1, Cal Voltage = %d, Digi out = %d, Coef_a = %d\n", parsed_data->ref_data.ver1.voltage, parsed_data->ref_data.ver1.digi, chars->coeff_a); +} + +esp_adc_cal_value_t esp_adc_cal_characterize(adc_unit_t adc_num, + adc_atten_t atten, + adc_bits_width_t bit_width, + uint32_t default_vref, + esp_adc_cal_characteristics_t *chars) +{ + (void) default_vref; + + // Check parameters + ESP_RETURN_ON_FALSE(adc_num == ADC_UNIT_1 || adc_num == ADC_UNIT_2, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "Invalid unit num"); + ESP_RETURN_ON_FALSE(chars != NULL, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "Ivalid characteristic"); + ESP_RETURN_ON_FALSE(atten < ADC_ATTEN_MAX, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "Invalid attenuation"); + + int version_num = esp_efuse_rtc_calib_get_ver(); + ESP_RETURN_ON_FALSE(version_num == 1, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "No calibration efuse burnt"); + + memset(chars, 0, sizeof(esp_adc_cal_characteristics_t)); + + adc_calib_info_t calib_info = {0}; + // make sure adc is calibrated. + get_reference_point(version_num, adc_num, atten, &calib_info); + calculate_characterization_coefficients(&calib_info, chars); + + // Initialize remaining fields + chars->adc_num = adc_num; + chars->atten = atten; + chars->bit_width = bit_width; + + return ESP_ADC_CAL_VAL_EFUSE_TP_FIT; +} + +static int32_t get_reading_error(uint64_t v_cali_1, uint8_t adc_num, uint8_t atten) +{ + if (v_cali_1 == 0) { + return 0; + } + + uint8_t term_max = (atten == 3) ? 5 : 3; + int32_t error = 0; + uint64_t coeff = 0; + uint64_t term[5] = {0}; + + /** + * For atten0 ~ 2: + * error = a1 * X^2 + a2 * X + a3; + * + * For atten3: + * error = a1 * X^4 + a2 * X^3 + a3 * X^2 + a4 * X + a5; + */ + + //Calculate all the power beforehand + term[term_max-1] = 1; + term[term_max-2] = v_cali_1; + for (int term_id = term_max - 3; term_id >= 0; term_id--) { + term[term_id] = term[term_id + 1] * v_cali_1; + } + + //Calculate each term + uint8_t coef_id_start = (adc_num == ADC_UNIT_1) ? 0 : 5; + for (int i = 0; i < term_max; i++) { + coeff = adc_error_coef_atten[atten][coef_id_start + i][0]; + term[i] = term[i] * coeff; + ESP_LOGV(LOG_TAG, "big coef is %llu, big term%d is %llu, coef_id is %d", coeff, i, term[i], coef_id_start + i); + + term[i] = term[i] / adc_error_coef_atten[atten][coef_id_start + i][1]; + error += (int32_t)term[i] * adc_error_sign[atten][i]; + ESP_LOGV(LOG_TAG, "term%d is %llu, error is %d", i, term[i], error); + } + + return error; +} + +uint32_t esp_adc_cal_raw_to_voltage(uint32_t adc_reading, const esp_adc_cal_characteristics_t *chars) +{ + assert(chars != NULL); + + //ADC reading won't exceed 4096. Otherwise the raw reading result is wrong, the next calculation will overflow. + assert(adc_reading < 4096); + + uint32_t voltage = 0; + int32_t error = 0; + uint64_t v_cali_1 = 0; + + //raw * gradient * 1000000 + v_cali_1 = adc_reading * chars->coeff_a; + //convert to real number + v_cali_1 = v_cali_1 / coeff_a_scaling; + ESP_LOGV(LOG_TAG, "v_cali_1 is %llu", v_cali_1); + + error = get_reading_error(v_cali_1, chars->adc_num, chars->atten); + voltage = (int32_t)v_cali_1 - error; + + return voltage; +} + +esp_err_t esp_adc_cal_get_voltage(adc_channel_t channel, + const esp_adc_cal_characteristics_t *chars, + uint32_t *voltage) +{ + // Check parameters + ESP_RETURN_ON_FALSE(chars != NULL, ESP_ERR_INVALID_ARG, LOG_TAG, "No characteristic input"); + ESP_RETURN_ON_FALSE(voltage != NULL, ESP_ERR_INVALID_ARG, LOG_TAG, "No output buffer"); + + esp_err_t ret = ESP_OK; + int adc_reading; + if (chars->adc_num == ADC_UNIT_1) { + ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(0), ESP_ERR_INVALID_ARG, LOG_TAG, "Invalid channel"); + adc_reading = adc1_get_raw(channel); + } else { + ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(1), ESP_ERR_INVALID_ARG, LOG_TAG, "Invalid channel"); + ret = adc2_get_raw(channel, chars->bit_width, &adc_reading); + } + *voltage = esp_adc_cal_raw_to_voltage((uint32_t)adc_reading, chars); + return ret; +} diff --git a/components/esp_adc_cal/include/esp_adc_cal.h b/components/esp_adc_cal/include/esp_adc_cal.h index 9adf28078d..171b2ed850 100644 --- a/components/esp_adc_cal/include/esp_adc_cal.h +++ b/components/esp_adc_cal/include/esp_adc_cal.h @@ -30,6 +30,7 @@ typedef enum { ESP_ADC_CAL_VAL_EFUSE_VREF = 0, /**< Characterization based on reference voltage stored in eFuse*/ ESP_ADC_CAL_VAL_EFUSE_TP = 1, /**< Characterization based on Two Point values stored in eFuse*/ ESP_ADC_CAL_VAL_DEFAULT_VREF = 2, /**< Characterization based on default reference voltage*/ + ESP_ADC_CAL_VAL_EFUSE_TP_FIT = 3, /**< Characterization based on Two Point values and fitting curve coefficients stored in eFuse */ ESP_ADC_CAL_VAL_MAX, ESP_ADC_CAL_VAL_NOT_SUPPORTED = ESP_ADC_CAL_VAL_MAX, } esp_adc_cal_value_t; @@ -48,6 +49,7 @@ typedef struct { uint32_t vref; /**< Vref used by lookup table*/ const uint32_t *low_curve; /**< Pointer to low Vref curve of lookup table (NULL if unused)*/ const uint32_t *high_curve; /**< Pointer to high Vref curve of lookup table (NULL if unused)*/ + uint8_t version; /**< ADC Calibration */ } esp_adc_cal_characteristics_t; /** @@ -129,8 +131,8 @@ uint32_t esp_adc_cal_raw_to_voltage(uint32_t adc_reading, const esp_adc_cal_char * * @return * - ESP_OK: ADC read and converted to mV - * - ESP_ERR_TIMEOUT: Error, timed out attempting to read ADC * - ESP_ERR_INVALID_ARG: Error due to invalid arguments + * - ESP_ERR_INVALID_STATE: Reading result is invalid. Try to read again. */ esp_err_t esp_adc_cal_get_voltage(adc_channel_t channel, const esp_adc_cal_characteristics_t *chars, uint32_t *voltage); diff --git a/components/esp_common/include/esp_attr.h b/components/esp_common/include/esp_attr.h index 88a230b77c..7b73af7663 100644 --- a/components/esp_common/include/esp_attr.h +++ b/components/esp_common/include/esp_attr.h @@ -91,7 +91,7 @@ extern "C" { #if CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY // Forces data into external memory noinit section to avoid initialization after restart. -#define EXT_RAM_NOINIT_ATTR _SECTION_ATTR_IMPL(".ext_ram.noinit", __COUNTER__) +#define EXT_RAM_NOINIT_ATTR _SECTION_ATTR_IMPL(".ext_ram_noinit", __COUNTER__) #else // Place in internal noinit section #define EXT_RAM_NOINIT_ATTR __NOINIT_ATTR diff --git a/components/esp_common/project_include.cmake b/components/esp_common/project_include.cmake index 2199570434..e7b1d65448 100644 --- a/components/esp_common/project_include.cmake +++ b/components/esp_common/project_include.cmake @@ -1,8 +1,12 @@ # # Warn if the toolchain version doesn't match # -if(NOT ${target} STREQUAL "linux") +if(NOT (${target} STREQUAL "linux" OR CMAKE_C_COMPILER_ID MATCHES "Clang")) get_expected_ctng_version(expected_toolchain expected_gcc) gcc_version_check("${expected_gcc}") crosstool_version_check("${expected_toolchain}") endif() + +if(NOT ${target} STREQUAL "linux" AND CMAKE_C_COMPILER_ID MATCHES "Clang") + message(WARNING "Building ESP-IDF with clang is an experimental feature and is not yet officially supported.") +endif() diff --git a/components/esp_common/src/esp_err_to_name.c b/components/esp_common/src/esp_err_to_name.c index c683e2004c..ac06862a0c 100644 --- a/components/esp_common/src/esp_err_to_name.c +++ b/components/esp_common/src/esp_err_to_name.c @@ -620,75 +620,78 @@ static const esp_err_msg_t esp_err_msg_table[] = { # ifdef ESP_ERR_ESP_TLS_SOCKET_SETOPT_FAILED ERR_TBL_IT(ESP_ERR_ESP_TLS_SOCKET_SETOPT_FAILED), /* 32773 0x8005 failed to set/get socket option */ # endif -# ifdef ESP_ERR_MBEDTLS_CERT_PARTLY_OK - ERR_TBL_IT(ESP_ERR_MBEDTLS_CERT_PARTLY_OK), /* 32774 0x8006 mbedtls parse certificates was partly successful */ -# endif -# ifdef ESP_ERR_MBEDTLS_CTR_DRBG_SEED_FAILED - ERR_TBL_IT(ESP_ERR_MBEDTLS_CTR_DRBG_SEED_FAILED), /* 32775 0x8007 mbedtls api returned error */ -# endif -# ifdef ESP_ERR_MBEDTLS_SSL_SET_HOSTNAME_FAILED - ERR_TBL_IT(ESP_ERR_MBEDTLS_SSL_SET_HOSTNAME_FAILED), /* 32776 0x8008 mbedtls api returned error */ -# endif -# ifdef ESP_ERR_MBEDTLS_SSL_CONFIG_DEFAULTS_FAILED - ERR_TBL_IT(ESP_ERR_MBEDTLS_SSL_CONFIG_DEFAULTS_FAILED), /* 32777 0x8009 mbedtls api returned error */ -# endif -# ifdef ESP_ERR_MBEDTLS_SSL_CONF_ALPN_PROTOCOLS_FAILED - ERR_TBL_IT(ESP_ERR_MBEDTLS_SSL_CONF_ALPN_PROTOCOLS_FAILED), /* 32778 0x800a mbedtls api returned error */ -# endif -# ifdef ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED - ERR_TBL_IT(ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED), /* 32779 0x800b mbedtls api returned error */ -# endif -# ifdef ESP_ERR_MBEDTLS_SSL_CONF_OWN_CERT_FAILED - ERR_TBL_IT(ESP_ERR_MBEDTLS_SSL_CONF_OWN_CERT_FAILED), /* 32780 0x800c mbedtls api returned error */ -# endif -# ifdef ESP_ERR_MBEDTLS_SSL_SETUP_FAILED - ERR_TBL_IT(ESP_ERR_MBEDTLS_SSL_SETUP_FAILED), /* 32781 0x800d mbedtls api returned error */ -# endif -# ifdef ESP_ERR_MBEDTLS_SSL_WRITE_FAILED - ERR_TBL_IT(ESP_ERR_MBEDTLS_SSL_WRITE_FAILED), /* 32782 0x800e mbedtls api returned error */ -# endif -# ifdef ESP_ERR_MBEDTLS_PK_PARSE_KEY_FAILED - ERR_TBL_IT(ESP_ERR_MBEDTLS_PK_PARSE_KEY_FAILED), /* 32783 0x800f mbedtls api returned failed */ -# endif -# ifdef ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED - ERR_TBL_IT(ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED), /* 32784 0x8010 mbedtls api returned failed */ -# endif -# ifdef ESP_ERR_MBEDTLS_SSL_CONF_PSK_FAILED - ERR_TBL_IT(ESP_ERR_MBEDTLS_SSL_CONF_PSK_FAILED), /* 32785 0x8011 mbedtls api returned failed */ -# endif # ifdef ESP_ERR_ESP_TLS_CONNECTION_TIMEOUT - ERR_TBL_IT(ESP_ERR_ESP_TLS_CONNECTION_TIMEOUT), /* 32786 0x8012 new connection in esp_tls_low_level_conn + ERR_TBL_IT(ESP_ERR_ESP_TLS_CONNECTION_TIMEOUT), /* 32774 0x8006 new connection in esp_tls_low_level_conn connection timeouted */ # endif -# ifdef ESP_ERR_WOLFSSL_SSL_SET_HOSTNAME_FAILED - ERR_TBL_IT(ESP_ERR_WOLFSSL_SSL_SET_HOSTNAME_FAILED), /* 32787 0x8013 wolfSSL api returned error */ -# endif -# ifdef ESP_ERR_WOLFSSL_SSL_CONF_ALPN_PROTOCOLS_FAILED - ERR_TBL_IT(ESP_ERR_WOLFSSL_SSL_CONF_ALPN_PROTOCOLS_FAILED), /* 32788 0x8014 wolfSSL api returned error */ -# endif -# ifdef ESP_ERR_WOLFSSL_CERT_VERIFY_SETUP_FAILED - ERR_TBL_IT(ESP_ERR_WOLFSSL_CERT_VERIFY_SETUP_FAILED), /* 32789 0x8015 wolfSSL api returned error */ -# endif -# ifdef ESP_ERR_WOLFSSL_KEY_VERIFY_SETUP_FAILED - ERR_TBL_IT(ESP_ERR_WOLFSSL_KEY_VERIFY_SETUP_FAILED), /* 32790 0x8016 wolfSSL api returned error */ -# endif -# ifdef ESP_ERR_WOLFSSL_SSL_HANDSHAKE_FAILED - ERR_TBL_IT(ESP_ERR_WOLFSSL_SSL_HANDSHAKE_FAILED), /* 32791 0x8017 wolfSSL api returned failed */ -# endif -# ifdef ESP_ERR_WOLFSSL_CTX_SETUP_FAILED - ERR_TBL_IT(ESP_ERR_WOLFSSL_CTX_SETUP_FAILED), /* 32792 0x8018 wolfSSL api returned failed */ -# endif -# ifdef ESP_ERR_WOLFSSL_SSL_SETUP_FAILED - ERR_TBL_IT(ESP_ERR_WOLFSSL_SSL_SETUP_FAILED), /* 32793 0x8019 wolfSSL api returned failed */ -# endif -# ifdef ESP_ERR_WOLFSSL_SSL_WRITE_FAILED - ERR_TBL_IT(ESP_ERR_WOLFSSL_SSL_WRITE_FAILED), /* 32794 0x801a wolfSSL api returned failed */ -# endif # ifdef ESP_ERR_ESP_TLS_SE_FAILED - ERR_TBL_IT(ESP_ERR_ESP_TLS_SE_FAILED), /* 32795 0x801b */ + ERR_TBL_IT(ESP_ERR_ESP_TLS_SE_FAILED), /* 32775 0x8007 */ # endif # ifdef ESP_ERR_ESP_TLS_TCP_CLOSED_FIN - ERR_TBL_IT(ESP_ERR_ESP_TLS_TCP_CLOSED_FIN), /* 32796 0x801c */ + ERR_TBL_IT(ESP_ERR_ESP_TLS_TCP_CLOSED_FIN), /* 32776 0x8008 */ +# endif +# ifdef ESP_ERR_MBEDTLS_CERT_PARTLY_OK + ERR_TBL_IT(ESP_ERR_MBEDTLS_CERT_PARTLY_OK), /* 32784 0x8010 mbedtls parse certificates was partly successful */ +# endif +# ifdef ESP_ERR_MBEDTLS_CTR_DRBG_SEED_FAILED + ERR_TBL_IT(ESP_ERR_MBEDTLS_CTR_DRBG_SEED_FAILED), /* 32785 0x8011 mbedtls api returned error */ +# endif +# ifdef ESP_ERR_MBEDTLS_SSL_SET_HOSTNAME_FAILED + ERR_TBL_IT(ESP_ERR_MBEDTLS_SSL_SET_HOSTNAME_FAILED), /* 32786 0x8012 mbedtls api returned error */ +# endif +# ifdef ESP_ERR_MBEDTLS_SSL_CONFIG_DEFAULTS_FAILED + ERR_TBL_IT(ESP_ERR_MBEDTLS_SSL_CONFIG_DEFAULTS_FAILED), /* 32787 0x8013 mbedtls api returned error */ +# endif +# ifdef ESP_ERR_MBEDTLS_SSL_CONF_ALPN_PROTOCOLS_FAILED + ERR_TBL_IT(ESP_ERR_MBEDTLS_SSL_CONF_ALPN_PROTOCOLS_FAILED), /* 32788 0x8014 mbedtls api returned error */ +# endif +# ifdef ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED + ERR_TBL_IT(ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED), /* 32789 0x8015 mbedtls api returned error */ +# endif +# ifdef ESP_ERR_MBEDTLS_SSL_CONF_OWN_CERT_FAILED + ERR_TBL_IT(ESP_ERR_MBEDTLS_SSL_CONF_OWN_CERT_FAILED), /* 32790 0x8016 mbedtls api returned error */ +# endif +# ifdef ESP_ERR_MBEDTLS_SSL_SETUP_FAILED + ERR_TBL_IT(ESP_ERR_MBEDTLS_SSL_SETUP_FAILED), /* 32791 0x8017 mbedtls api returned error */ +# endif +# ifdef ESP_ERR_MBEDTLS_SSL_WRITE_FAILED + ERR_TBL_IT(ESP_ERR_MBEDTLS_SSL_WRITE_FAILED), /* 32792 0x8018 mbedtls api returned error */ +# endif +# ifdef ESP_ERR_MBEDTLS_PK_PARSE_KEY_FAILED + ERR_TBL_IT(ESP_ERR_MBEDTLS_PK_PARSE_KEY_FAILED), /* 32793 0x8019 mbedtls api returned failed */ +# endif +# ifdef ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED + ERR_TBL_IT(ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED), /* 32794 0x801a mbedtls api returned failed */ +# endif +# ifdef ESP_ERR_MBEDTLS_SSL_CONF_PSK_FAILED + ERR_TBL_IT(ESP_ERR_MBEDTLS_SSL_CONF_PSK_FAILED), /* 32795 0x801b mbedtls api returned failed */ +# endif +# ifdef ESP_ERR_MBEDTLS_SSL_TICKET_SETUP_FAILED + ERR_TBL_IT(ESP_ERR_MBEDTLS_SSL_TICKET_SETUP_FAILED), /* 32796 0x801c mbedtls api returned failed */ +# endif +# ifdef ESP_ERR_WOLFSSL_SSL_SET_HOSTNAME_FAILED + ERR_TBL_IT(ESP_ERR_WOLFSSL_SSL_SET_HOSTNAME_FAILED), /* 32817 0x8031 wolfSSL api returned error */ +# endif +# ifdef ESP_ERR_WOLFSSL_SSL_CONF_ALPN_PROTOCOLS_FAILED + ERR_TBL_IT(ESP_ERR_WOLFSSL_SSL_CONF_ALPN_PROTOCOLS_FAILED), /* 32818 0x8032 wolfSSL api returned error */ +# endif +# ifdef ESP_ERR_WOLFSSL_CERT_VERIFY_SETUP_FAILED + ERR_TBL_IT(ESP_ERR_WOLFSSL_CERT_VERIFY_SETUP_FAILED), /* 32819 0x8033 wolfSSL api returned error */ +# endif +# ifdef ESP_ERR_WOLFSSL_KEY_VERIFY_SETUP_FAILED + ERR_TBL_IT(ESP_ERR_WOLFSSL_KEY_VERIFY_SETUP_FAILED), /* 32820 0x8034 wolfSSL api returned error */ +# endif +# ifdef ESP_ERR_WOLFSSL_SSL_HANDSHAKE_FAILED + ERR_TBL_IT(ESP_ERR_WOLFSSL_SSL_HANDSHAKE_FAILED), /* 32821 0x8035 wolfSSL api returned failed */ +# endif +# ifdef ESP_ERR_WOLFSSL_CTX_SETUP_FAILED + ERR_TBL_IT(ESP_ERR_WOLFSSL_CTX_SETUP_FAILED), /* 32822 0x8036 wolfSSL api returned failed */ +# endif +# ifdef ESP_ERR_WOLFSSL_SSL_SETUP_FAILED + ERR_TBL_IT(ESP_ERR_WOLFSSL_SSL_SETUP_FAILED), /* 32823 0x8037 wolfSSL api returned failed */ +# endif +# ifdef ESP_ERR_WOLFSSL_SSL_WRITE_FAILED + ERR_TBL_IT(ESP_ERR_WOLFSSL_SSL_WRITE_FAILED), /* 32824 0x8038 wolfSSL api returned failed */ # endif // components/esp_https_ota/include/esp_https_ota.h # ifdef ESP_ERR_HTTPS_OTA_BASE diff --git a/components/esp_eth/include/esp_eth.h b/components/esp_eth/include/esp_eth.h index d204b50898..6aea512a69 100644 --- a/components/esp_eth/include/esp_eth.h +++ b/components/esp_eth/include/esp_eth.h @@ -265,12 +265,24 @@ esp_err_t esp_eth_receive(esp_eth_handle_t hdl, uint8_t *buf, uint32_t *length) * * @param[in] hdl: handle of Ethernet driver * @param[in] cmd: IO control command -* @param[in] data: specificed data for command +* @param[in, out] data: address of data for `set` command or address where to store the data when used with `get` command * * @return * - ESP_OK: process io command successfully * - ESP_ERR_INVALID_ARG: process io command failed because of some invalid argument * - ESP_FAIL: process io command failed because some other error occurred +* +* The following IO control commands are supported: +* @li @c ETH_CMD_S_MAC_ADDR sets Ethernet interface MAC address. @c data argument is pointer to MAC address buffer with expected size of 6 bytes. +* @li @c ETH_CMD_G_MAC_ADDR gets Ethernet interface MAC address. @c data argument is pointer to a buffer to which MAC address is to be copied. The buffer size must be at least 6 bytes. +* @li @c ETH_CMD_S_PHY_ADDR sets PHY address in range of <0-31>. @c data argument is pointer to memory of uint32_t datatype from where the configuration option is read. +* @li @c ETH_CMD_G_PHY_ADDR gets PHY address. @c data argument is pointer to memory of uint32_t datatype to which the PHY address is to be stored. +* @li @c ETH_CMD_G_SPEED gets current Ethernet link speed. @c data argument is pointer to memory of eth_speed_t datatype to which the speed is to be stored. +* @li @c ETH_CMD_S_PROMISCUOUS sets/resets Ethernet interface promiscuous mode. @c data argument is pointer to memory of bool datatype from which the configuration option is read. +* @li @c ETH_CMD_S_FLOW_CTRL sets/resets Ethernet interface flow control. @c data argument is pointer to memory of bool datatype from which the configuration option is read. +* @li @c ETH_CMD_G_DUPLEX_MODE gets current Ethernet link duplex mode. @c data argument is pointer to memory of eth_duplex_t datatype to which the duplex mode is to be stored. +* @li @c ETH_CMD_S_PHY_LOOPBACK sets/resets PHY to/from loopback mode. @c data argument is pointer to memory of bool datatype from which the configuration option is read. +* */ esp_err_t esp_eth_ioctl(esp_eth_handle_t hdl, esp_eth_io_cmd_t cmd, void *data); diff --git a/components/esp_eth/include/esp_eth_com.h b/components/esp_eth/include/esp_eth_com.h index 46409ed710..7ce0538fbe 100644 --- a/components/esp_eth/include/esp_eth_com.h +++ b/components/esp_eth/include/esp_eth_com.h @@ -89,6 +89,7 @@ typedef enum { ETH_CMD_S_PROMISCUOUS, /*!< Set promiscuous mode */ ETH_CMD_S_FLOW_CTRL, /*!< Set flow control */ ETH_CMD_G_DUPLEX_MODE, /*!< Get Duplex mode */ + ETH_CMD_S_PHY_LOOPBACK,/*!< Set PHY loopback */ } esp_eth_io_cmd_t; /** diff --git a/components/esp_eth/include/esp_eth_mac.h b/components/esp_eth/include/esp_eth_mac.h index f1e790c756..db462728a1 100644 --- a/components/esp_eth/include/esp_eth_mac.h +++ b/components/esp_eth/include/esp_eth_mac.h @@ -391,7 +391,7 @@ typedef struct { #define ETH_MAC_DEFAULT_CONFIG() \ { \ .sw_reset_timeout_ms = 100, \ - .rx_task_stack_size = 4096, \ + .rx_task_stack_size = 2048, \ .rx_task_prio = 15, \ .smi_mdc_gpio_num = 23, \ .smi_mdio_gpio_num = 18, \ diff --git a/components/esp_eth/include/esp_eth_netif_glue.h b/components/esp_eth/include/esp_eth_netif_glue.h index 5e88b5ba5e..d577fc00b7 100644 --- a/components/esp_eth/include/esp_eth_netif_glue.h +++ b/components/esp_eth/include/esp_eth_netif_glue.h @@ -19,6 +19,12 @@ extern "C" { #endif +/** + * @brief Handle of netif glue - an intermediate layer between netif and Ethernet driver + * + */ +typedef struct esp_eth_netif_glue_t* esp_eth_netif_glue_handle_t; + /** * @brief Create a netif glue for Ethernet driver * @note netif glue is used to attach io driver to TCP/IP netif @@ -26,20 +32,23 @@ extern "C" { * @param eth_hdl Ethernet driver handle * @return glue object, which inherits esp_netif_driver_base_t */ -void *esp_eth_new_netif_glue(esp_eth_handle_t eth_hdl); +esp_eth_netif_glue_handle_t esp_eth_new_netif_glue(esp_eth_handle_t eth_hdl); /** * @brief Delete netif glue of Ethernet driver * - * @param glue netif glue + * @param eth_netif_glue netif glue * @return -ESP_OK: delete netif glue successfully */ -esp_err_t esp_eth_del_netif_glue(void *glue); +esp_err_t esp_eth_del_netif_glue(esp_eth_netif_glue_handle_t eth_netif_glue); /** * @brief Register default IP layer handlers for Ethernet * * @note: Ethernet handle might not yet properly initialized when setting up these default handlers + * @warning: This function is deprecated and is kept here only for compatibility reasons. Registration + * of default IP layer handlers for Ethernet is now handled automatically. Do not call this + * function if you want to use multiple Ethernet instances at a time. * * @param[in] esp_netif esp network interface handle created for Ethernet driver * @return @@ -47,12 +56,15 @@ esp_err_t esp_eth_del_netif_glue(void *glue); * - ESP_OK: set default IP layer handlers successfully * - others: other failure occurred during register esp_event handler */ - -esp_err_t esp_eth_set_default_handlers(void *esp_netif); +esp_err_t esp_eth_set_default_handlers(void *esp_netif) __attribute__ ((deprecated)); /** * @brief Unregister default IP layer handlers for Ethernet * + * @warning: This function is deprecated and is kept here only for compatibility reasons. Unregistration + * of default IP layer handlers for Ethernet is now handled automatically if not registered + * by calling esp_eth_set_default_handlers. + * * @param[in] esp_netif esp network interface handle created for Ethernet driver * @return * - ESP_ERR_INVALID_ARG: invalid parameter (esp_netif is NULL) diff --git a/components/esp_eth/include/esp_eth_phy.h b/components/esp_eth/include/esp_eth_phy.h index 4b4d860bd7..f85b7d4304 100644 --- a/components/esp_eth/include/esp_eth_phy.h +++ b/components/esp_eth/include/esp_eth_phy.h @@ -173,6 +173,19 @@ struct esp_eth_phy_s { */ esp_err_t (*advertise_pause_ability)(esp_eth_phy_t *phy, uint32_t ability); + /** + * @brief + * + * @param[in] phy: Ethernet PHY instance + * @param[in] enable: enables or disables PHY loopback + * + * @return + * - ESP_OK: configures PHY instance loopback function successfully + * - ESP_FAIL: PHY instance loopback configuration failed because some error occurred + * + */ + esp_err_t (*loopback)(esp_eth_phy_t *phy, bool enable); + /** * @brief Free memory of Ethernet PHY instance * diff --git a/components/esp_eth/src/esp_eth.c b/components/esp_eth/src/esp_eth.c index 611ba936c9..bef3e7966c 100644 --- a/components/esp_eth/src/esp_eth.c +++ b/components/esp_eth/src/esp_eth.c @@ -20,6 +20,7 @@ #include "esp_event.h" #include "esp_heap_caps.h" #include "esp_timer.h" +#include "soc/soc.h" // TODO: for esp_eth_ioctl API compatibility reasons, will be removed with next major release #include "freertos/FreeRTOS.h" #include "freertos/task.h" @@ -360,8 +361,11 @@ esp_err_t esp_eth_ioctl(esp_eth_handle_t hdl, esp_eth_io_cmd_t cmd, void *data) ESP_GOTO_ON_ERROR(mac->get_addr(mac, (uint8_t *)data), err, TAG, "get mac address failed"); break; case ETH_CMD_S_PHY_ADDR: - ESP_GOTO_ON_FALSE(data, ESP_ERR_INVALID_ARG, err, TAG, "can't set phy addr to null"); - ESP_GOTO_ON_ERROR(phy->set_addr(phy, (uint32_t)data), err, TAG, "set phy address failed"); + if ((uint32_t)data >= SOC_DRAM_LOW) { + ESP_GOTO_ON_ERROR(phy->set_addr(phy, *(uint32_t *)data), err, TAG, "set phy address failed"); + } else { // TODO: for API compatibility reasons, will be removed with next major release + ESP_GOTO_ON_ERROR(phy->set_addr(phy, (uint32_t)data), err, TAG, "set phy address failed"); + } break; case ETH_CMD_G_PHY_ADDR: ESP_GOTO_ON_FALSE(data, ESP_ERR_INVALID_ARG, err, TAG, "no mem to store phy addr"); @@ -372,16 +376,32 @@ esp_err_t esp_eth_ioctl(esp_eth_handle_t hdl, esp_eth_io_cmd_t cmd, void *data) *(eth_speed_t *)data = eth_driver->speed; break; case ETH_CMD_S_PROMISCUOUS: - ESP_GOTO_ON_ERROR(mac->set_promiscuous(mac, (bool)data), err, TAG, "set promiscuous mode failed"); + if ((uint32_t)data >= SOC_DRAM_LOW) { + ESP_GOTO_ON_ERROR(mac->set_promiscuous(mac, *(bool *)data), err, TAG, "set promiscuous mode failed"); + } else { // TODO: for API compatibility reasons, will be removed with next major release + ESP_GOTO_ON_ERROR(mac->set_promiscuous(mac, (bool)data), err, TAG, "set promiscuous mode failed"); + } break; case ETH_CMD_S_FLOW_CTRL: - ESP_GOTO_ON_ERROR(mac->enable_flow_ctrl(mac, (bool)data), err, TAG, "enable mac flow control failed"); - ESP_GOTO_ON_ERROR(phy->advertise_pause_ability(phy, (uint32_t)data), err, TAG, "phy advertise pause ability failed"); + if ((uint32_t)data >= SOC_DRAM_LOW) { + ESP_GOTO_ON_ERROR(mac->enable_flow_ctrl(mac, *(bool *)data), err, TAG, "enable mac flow control failed"); + ESP_GOTO_ON_ERROR(phy->advertise_pause_ability(phy, *(uint32_t *)data), err, TAG, "phy advertise pause ability failed"); + } else { // TODO: for API compatibility reasons, will be removed with next major release + ESP_GOTO_ON_ERROR(mac->enable_flow_ctrl(mac, (bool)data), err, TAG, "enable mac flow control failed"); + ESP_GOTO_ON_ERROR(phy->advertise_pause_ability(phy, (uint32_t)data), err, TAG, "phy advertise pause ability failed"); + } break; case ETH_CMD_G_DUPLEX_MODE: ESP_GOTO_ON_FALSE(data, ESP_ERR_INVALID_ARG, err, TAG, "no mem to store duplex value"); *(eth_duplex_t *)data = eth_driver->duplex; break; + case ETH_CMD_S_PHY_LOOPBACK: + if ((uint32_t)data >= SOC_DRAM_LOW) { + ESP_GOTO_ON_ERROR(phy->loopback(phy, *(bool *)data), err, TAG, "configuration of phy loopback mode failed"); + } else { // TODO: for API compatibility reasons, will be removed with next major release + ESP_GOTO_ON_ERROR(phy->loopback(phy, (bool)data), err, TAG, "configuration of phy loopback mode failed"); + } + break; default: ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "unknown io command: %d", cmd); break; diff --git a/components/esp_eth/src/esp_eth_mac_dm9051.c b/components/esp_eth/src/esp_eth_mac_dm9051.c index 65a7b8d02c..2040dfedcc 100644 --- a/components/esp_eth/src/esp_eth_mac_dm9051.c +++ b/components/esp_eth/src/esp_eth_mac_dm9051.c @@ -347,8 +347,8 @@ static esp_err_t emac_dm9051_start(esp_eth_mac_t *mac) { esp_err_t ret = ESP_OK; emac_dm9051_t *emac = __containerof(mac, emac_dm9051_t, parent); - /* enable interrupt */ - ESP_GOTO_ON_ERROR(dm9051_register_write(emac, DM9051_IMR, IMR_ALL), err, TAG, "write IMR failed"); + /* enable only Rx related interrupts as others are processed synchronously */ + ESP_GOTO_ON_ERROR(dm9051_register_write(emac, DM9051_IMR, IMR_PAR | IMR_PRI), err, TAG, "write IMR failed"); /* enable rx */ uint8_t rcr = 0; ESP_GOTO_ON_ERROR(dm9051_register_read(emac, DM9051_RCR, &rcr), err, TAG, "read RCR failed"); @@ -396,8 +396,11 @@ static void emac_dm9051_task(void *arg) uint8_t *buffer = NULL; uint32_t length = 0; while (1) { - // block indefinitely until some task notifies me - ulTaskNotifyTake(pdTRUE, portMAX_DELAY); + // check if the task receives any notification + if (ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(1000)) == 0 && // if no notification ... + gpio_get_level(emac->int_gpio_num) == 0) { // ...and no interrupt asserted + continue; // -> just continue to check again + } /* clear interrupt status */ dm9051_register_read(emac, DM9051_ISR, &status); dm9051_register_write(emac, DM9051_ISR, status); diff --git a/components/esp_eth/src/esp_eth_netif_glue.c b/components/esp_eth/src/esp_eth_netif_glue.c index 7a4e5e1a7d..a1ac4c5594 100644 --- a/components/esp_eth/src/esp_eth_netif_glue.c +++ b/components/esp_eth/src/esp_eth_netif_glue.c @@ -17,13 +17,23 @@ #include "esp_eth_netif_glue.h" #include "esp_event.h" #include "esp_log.h" +#include "esp_check.h" -const static char *TAG = "esp_eth.netif.glue"; +const static char *TAG = "esp_eth.netif.netif_glue"; -typedef struct { +typedef struct esp_eth_netif_glue_t esp_eth_netif_glue_t; + +struct esp_eth_netif_glue_t { esp_netif_driver_base_t base; esp_eth_handle_t eth_driver; -} esp_eth_netif_glue_t; + esp_event_handler_instance_t start_ctx_handler; + esp_event_handler_instance_t stop_ctx_handler; + esp_event_handler_instance_t connect_ctx_handler; + esp_event_handler_instance_t disconnect_ctx_handler; + esp_event_handler_instance_t get_ip_ctx_handler; +}; + +bool s_netif_glue_legacy_events_registered = false; static esp_err_t eth_input_to_netif(esp_eth_handle_t eth_handle, uint8_t *buffer, uint32_t length, void *priv) { @@ -33,20 +43,20 @@ static esp_err_t eth_input_to_netif(esp_eth_handle_t eth_handle, uint8_t *buffer static esp_err_t esp_eth_post_attach(esp_netif_t *esp_netif, void *args) { uint8_t eth_mac[6]; - esp_eth_netif_glue_t *glue = (esp_eth_netif_glue_t *)args; - glue->base.netif = esp_netif; + esp_eth_netif_glue_t *netif_glue = (esp_eth_netif_glue_t *)args; + netif_glue->base.netif = esp_netif; - esp_eth_update_input_path(glue->eth_driver, eth_input_to_netif, esp_netif); + esp_eth_update_input_path(netif_glue->eth_driver, eth_input_to_netif, esp_netif); // set driver related config to esp-netif esp_netif_driver_ifconfig_t driver_ifconfig = { - .handle = glue->eth_driver, + .handle = netif_glue->eth_driver, .transmit = esp_eth_transmit, .driver_free_rx_buffer = NULL }; ESP_ERROR_CHECK(esp_netif_set_driver_config(esp_netif, &driver_ifconfig)); - esp_eth_ioctl(glue->eth_driver, ETH_CMD_G_MAC_ADDR, eth_mac); + esp_eth_ioctl(netif_glue->eth_driver, ETH_CMD_G_MAC_ADDR, eth_mac); ESP_LOGI(TAG, "%02x:%02x:%02x:%02x:%02x:%02x", eth_mac[0], eth_mac[1], eth_mac[2], eth_mac[3], eth_mac[4], eth_mac[5]); @@ -56,39 +66,18 @@ static esp_err_t esp_eth_post_attach(esp_netif_t *esp_netif, void *args) return ESP_OK; } -void *esp_eth_new_netif_glue(esp_eth_handle_t eth_hdl) -{ - esp_eth_netif_glue_t *glue = calloc(1, sizeof(esp_eth_netif_glue_t)); - if (!glue) { - ESP_LOGE(TAG, "create netif glue failed"); - return NULL; - } - glue->eth_driver = eth_hdl; - glue->base.post_attach = esp_eth_post_attach; - esp_eth_increase_reference(eth_hdl); - return &glue->base; -} - -esp_err_t esp_eth_del_netif_glue(void *g) -{ - esp_eth_netif_glue_t *glue = (esp_eth_netif_glue_t *)g; - esp_eth_decrease_reference(glue->eth_driver); - free(glue); - return ESP_OK; -} - esp_err_t esp_eth_clear_default_handlers(void *esp_netif) { - if (!esp_netif) { - ESP_LOGE(TAG, "esp-netif handle can't be null"); - return ESP_ERR_INVALID_ARG; - } + ESP_RETURN_ON_FALSE(esp_netif, ESP_ERR_INVALID_ARG, TAG, "esp_netif handle can't be null"); + esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_START, esp_netif_action_start); esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_STOP, esp_netif_action_stop); esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_CONNECTED, esp_netif_action_connected); esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_DISCONNECTED, esp_netif_action_disconnected); esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, esp_netif_action_got_ip); + s_netif_glue_legacy_events_registered = false; + return ESP_OK; } @@ -96,10 +85,7 @@ esp_err_t esp_eth_set_default_handlers(void *esp_netif) { esp_err_t ret; - if (!esp_netif) { - ESP_LOGE(TAG, "esp-netif handle can't be null"); - return ESP_ERR_INVALID_ARG; - } + ESP_RETURN_ON_FALSE(esp_netif, ESP_ERR_INVALID_ARG, TAG, "esp_netif handle can't be null"); ret = esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_START, esp_netif_action_start, esp_netif); if (ret != ESP_OK) { @@ -126,9 +112,158 @@ esp_err_t esp_eth_set_default_handlers(void *esp_netif) goto fail; } + s_netif_glue_legacy_events_registered = true; + return ESP_OK; fail: esp_eth_clear_default_handlers(esp_netif); return ret; } + +static void eth_action_start(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) +{ + esp_eth_handle_t eth_handle = *(esp_eth_handle_t *)event_data; + esp_eth_netif_glue_t *netif_glue = handler_args; + ESP_LOGD(TAG, "eth_action_start: %p, %p, %d, %p, %p", netif_glue, base, event_id, event_data, *(esp_eth_handle_t *)event_data); + if (netif_glue->eth_driver == eth_handle) { + esp_netif_action_start(netif_glue->base.netif, base, event_id, event_data); + } +} + +static void eth_action_stop(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) +{ + esp_eth_handle_t eth_handle = *(esp_eth_handle_t *)event_data; + esp_eth_netif_glue_t *netif_glue = handler_args; + ESP_LOGD(TAG, "eth_action_stop: %p, %p, %d, %p, %p", netif_glue, base, event_id, event_data, *(esp_eth_handle_t *)event_data); + if (netif_glue->eth_driver == eth_handle) { + esp_netif_action_stop(netif_glue->base.netif, base, event_id, event_data); + } +} + +static void eth_action_connected(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) +{ + esp_eth_handle_t eth_handle = *(esp_eth_handle_t *)event_data; + esp_eth_netif_glue_t *netif_glue = handler_args; + ESP_LOGD(TAG, "eth_action_connected: %p, %p, %d, %p, %p", netif_glue, base, event_id, event_data, *(esp_eth_handle_t *)event_data); + if (netif_glue->eth_driver == eth_handle) { + esp_netif_action_connected(netif_glue->base.netif, base, event_id, event_data); + } +} + +static void eth_action_disconnected(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) +{ + esp_eth_handle_t eth_handle = *(esp_eth_handle_t *)event_data; + esp_eth_netif_glue_t *netif_glue = handler_args; + ESP_LOGD(TAG, "eth_action_disconnected: %p, %p, %d, %p, %p", netif_glue, base, event_id, event_data, *(esp_eth_handle_t *)event_data); + if (netif_glue->eth_driver == eth_handle) { + esp_netif_action_disconnected(netif_glue->base.netif, base, event_id, event_data); + } +} + +static void eth_action_got_ip(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) +{ + ip_event_got_ip_t *ip_event = (ip_event_got_ip_t *)event_data; + esp_eth_netif_glue_t *netif_glue = handler_args; + ESP_LOGD(TAG, "eth_action_got_ip: %p, %p, %d, %p, %p", netif_glue, base, event_id, event_data, *(esp_eth_handle_t *)event_data); + if (netif_glue->base.netif == ip_event->esp_netif) { + esp_netif_action_got_ip(ip_event->esp_netif, base, event_id, event_data); + } +} + +static esp_err_t esp_eth_clear_glue_instance_handlers(esp_eth_netif_glue_handle_t eth_netif_glue) +{ + ESP_RETURN_ON_FALSE(eth_netif_glue, ESP_ERR_INVALID_ARG, TAG, "eth_netif_glue handle can't be null"); + + if (eth_netif_glue->start_ctx_handler) { + esp_event_handler_instance_unregister(ETH_EVENT, ETHERNET_EVENT_START, eth_netif_glue->start_ctx_handler); + eth_netif_glue->start_ctx_handler = NULL; + } + + if (eth_netif_glue->stop_ctx_handler) { + esp_event_handler_instance_unregister(ETH_EVENT, ETHERNET_EVENT_STOP, eth_netif_glue->stop_ctx_handler); + eth_netif_glue->stop_ctx_handler = NULL; + } + + if (eth_netif_glue->connect_ctx_handler) { + esp_event_handler_instance_unregister(ETH_EVENT, ETHERNET_EVENT_CONNECTED, eth_netif_glue->connect_ctx_handler); + eth_netif_glue->connect_ctx_handler = NULL; + } + + if (eth_netif_glue->disconnect_ctx_handler) { + esp_event_handler_instance_unregister(ETH_EVENT, ETHERNET_EVENT_DISCONNECTED, eth_netif_glue->disconnect_ctx_handler); + eth_netif_glue->disconnect_ctx_handler = NULL; + } + + if (eth_netif_glue->get_ip_ctx_handler) { + esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, eth_netif_glue->get_ip_ctx_handler); + eth_netif_glue->get_ip_ctx_handler = NULL; + } + + return ESP_OK; +} + +static esp_err_t esp_eth_set_glue_instance_handlers(esp_eth_netif_glue_handle_t eth_netif_glue) +{ + ESP_RETURN_ON_FALSE(eth_netif_glue, ESP_ERR_INVALID_ARG, TAG, "eth_netif_glue handle can't be null"); + + esp_err_t ret = esp_event_handler_instance_register(ETH_EVENT, ETHERNET_EVENT_START, eth_action_start, eth_netif_glue, ð_netif_glue->start_ctx_handler); + if (ret != ESP_OK) { + goto fail; + } + + ret = esp_event_handler_instance_register(ETH_EVENT, ETHERNET_EVENT_STOP, eth_action_stop, eth_netif_glue, ð_netif_glue->stop_ctx_handler); + if (ret != ESP_OK) { + goto fail; + } + + ret = esp_event_handler_instance_register(ETH_EVENT, ETHERNET_EVENT_CONNECTED, eth_action_connected, eth_netif_glue, ð_netif_glue->connect_ctx_handler); + if (ret != ESP_OK) { + goto fail; + } + + ret = esp_event_handler_instance_register(ETH_EVENT, ETHERNET_EVENT_DISCONNECTED, eth_action_disconnected, eth_netif_glue, ð_netif_glue->disconnect_ctx_handler); + if (ret != ESP_OK) { + goto fail; + } + + ret = esp_event_handler_instance_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, eth_action_got_ip, eth_netif_glue, ð_netif_glue->get_ip_ctx_handler); + if (ret != ESP_OK) { + goto fail; + } + + return ESP_OK; + +fail: + esp_eth_clear_glue_instance_handlers(eth_netif_glue); + return ret; +} + +esp_err_t esp_eth_del_netif_glue(esp_eth_netif_glue_handle_t eth_netif_glue) +{ + esp_eth_clear_glue_instance_handlers(eth_netif_glue); + + esp_eth_decrease_reference(eth_netif_glue->eth_driver); + free(eth_netif_glue); + return ESP_OK; +} + +esp_eth_netif_glue_handle_t esp_eth_new_netif_glue(esp_eth_handle_t eth_hdl) +{ + esp_eth_netif_glue_t *netif_glue = calloc(1, sizeof(esp_eth_netif_glue_t)); + if (!netif_glue) { + ESP_LOGE(TAG, "create netif glue failed"); + return NULL; + } + netif_glue->eth_driver = eth_hdl; + netif_glue->base.post_attach = esp_eth_post_attach; + esp_eth_increase_reference(eth_hdl); + + if (s_netif_glue_legacy_events_registered == false) { + if (esp_eth_set_glue_instance_handlers(netif_glue) != ESP_OK) { + esp_eth_del_netif_glue(netif_glue); + return NULL; + } + } + return netif_glue; +} diff --git a/components/esp_eth/src/esp_eth_phy_dm9051.c b/components/esp_eth/src/esp_eth_phy_dm9051.c index 5c1c112a61..9f31d71253 100644 --- a/components/esp_eth/src/esp_eth_phy_dm9051.c +++ b/components/esp_eth/src/esp_eth_phy_dm9051.c @@ -195,6 +195,11 @@ static esp_err_t dm9051_reset_hw(esp_eth_phy_t *phy) return ESP_OK; } +/** + * @note This function is responsible for restarting a new auto-negotiation, + * the result of negotiation won't be relected to uppler layers. + * Instead, the negotiation result is fetched by linker timer, see `dm9051_get_link()` + */ static esp_err_t dm9051_negotiate(esp_eth_phy_t *phy) { esp_err_t ret = ESP_OK; @@ -222,7 +227,7 @@ static esp_err_t dm9051_negotiate(esp_eth_phy_t *phy) break; } } - if (to >= dm9051->autonego_timeout_ms / 100) { + if ((to >= dm9051->autonego_timeout_ms / 100) && (dm9051->link_status == ETH_LINK_UP)) { ESP_LOGW(TAG, "Ethernet PHY auto negotiation timeout"); } return ESP_OK; @@ -311,6 +316,25 @@ err: return ret; } +static esp_err_t dm9051_loopback(esp_eth_phy_t *phy, bool enable) +{ + esp_err_t ret = ESP_OK; + phy_dm9051_t *dm9051 = __containerof(phy, phy_dm9051_t, parent); + esp_eth_mediator_t *eth = dm9051->eth; + /* Set Loopback function */ + bmcr_reg_t bmcr; + ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, dm9051->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)), err, TAG, "read BMCR failed"); + if (enable) { + bmcr.en_loopback = 1; + } else { + bmcr.en_loopback = 0; + } + ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, dm9051->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val), err, TAG, "write BMCR failed"); + return ESP_OK; +err: + return ret; +} + static esp_err_t dm9051_init(esp_eth_phy_t *phy) { esp_err_t ret = ESP_OK; @@ -367,6 +391,7 @@ esp_eth_phy_t *esp_eth_phy_new_dm9051(const eth_phy_config_t *config) dm9051->parent.get_addr = dm9051_get_addr; dm9051->parent.set_addr = dm9051_set_addr; dm9051->parent.advertise_pause_ability = dm9051_advertise_pause_ability; + dm9051->parent.loopback = dm9051_loopback; dm9051->parent.del = dm9051_del; return &(dm9051->parent); err: diff --git a/components/esp_eth/src/esp_eth_phy_dp83848.c b/components/esp_eth/src/esp_eth_phy_dp83848.c index cafef8d59c..bbc6bffbf2 100644 --- a/components/esp_eth/src/esp_eth_phy_dp83848.c +++ b/components/esp_eth/src/esp_eth_phy_dp83848.c @@ -189,6 +189,11 @@ static esp_err_t dp83848_reset_hw(esp_eth_phy_t *phy) return ESP_OK; } +/** + * @note This function is responsible for restarting a new auto-negotiation, + * the result of negotiation won't be relected to uppler layers. + * Instead, the negotiation result is fetched by linker timer, see `dp83848_get_link()` + */ static esp_err_t dp83848_negotiate(esp_eth_phy_t *phy) { esp_err_t ret = ESP_OK; @@ -216,8 +221,7 @@ static esp_err_t dp83848_negotiate(esp_eth_phy_t *phy) break; } } - /* Auto negotiation failed, maybe no network cable plugged in, so output a warning */ - if (to >= dp83848->autonego_timeout_ms / 100) { + if ((to >= dp83848->autonego_timeout_ms / 100) && (dp83848->link_status == ETH_LINK_UP)) { ESP_LOGW(TAG, "auto negotiation timeout"); } return ESP_OK; @@ -306,6 +310,25 @@ err: return ret; } +static esp_err_t dp83848_loopback(esp_eth_phy_t *phy, bool enable) +{ + esp_err_t ret = ESP_OK; + phy_dp83848_t *dp83848 = __containerof(phy, phy_dp83848_t, parent); + esp_eth_mediator_t *eth = dp83848->eth; + /* Set Loopback function */ + bmcr_reg_t bmcr; + ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)), err, TAG, "read BMCR failed"); + if (enable) { + bmcr.en_loopback = 1; + } else { + bmcr.en_loopback = 0; + } + ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, dp83848->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val), err, TAG, "write BMCR failed"); + return ESP_OK; +err: + return ret; +} + static esp_err_t dp83848_init(esp_eth_phy_t *phy) { esp_err_t ret = ESP_OK; @@ -362,6 +385,7 @@ esp_eth_phy_t *esp_eth_phy_new_dp83848(const eth_phy_config_t *config) dp83848->parent.get_addr = dp83848_get_addr; dp83848->parent.set_addr = dp83848_set_addr; dp83848->parent.advertise_pause_ability = dp83848_advertise_pause_ability; + dp83848->parent.loopback = dp83848_loopback; dp83848->parent.del = dp83848_del; return &(dp83848->parent); err: diff --git a/components/esp_eth/src/esp_eth_phy_ip101.c b/components/esp_eth/src/esp_eth_phy_ip101.c index e8424288b6..ac72e3eec3 100644 --- a/components/esp_eth/src/esp_eth_phy_ip101.c +++ b/components/esp_eth/src/esp_eth_phy_ip101.c @@ -230,6 +230,11 @@ static esp_err_t ip101_reset_hw(esp_eth_phy_t *phy) return ESP_OK; } +/** + * @note This function is responsible for restarting a new auto-negotiation, + * the result of negotiation won't be relected to uppler layers. + * Instead, the negotiation result is fetched by linker timer, see `ip101_get_link()` + */ static esp_err_t ip101_negotiate(esp_eth_phy_t *phy) { esp_err_t ret = ESP_OK; @@ -255,8 +260,7 @@ static esp_err_t ip101_negotiate(esp_eth_phy_t *phy) break; } } - /* Auto negotiation failed, maybe no network cable plugged in, so output a warning */ - if (to >= ip101->autonego_timeout_ms / 100) { + if ((to >= ip101->autonego_timeout_ms / 100) && (ip101->link_status == ETH_LINK_UP)) { ESP_LOGW(TAG, "auto negotiation timeout"); } return ESP_OK; @@ -345,6 +349,25 @@ err: return ret; } +static esp_err_t ip101_loopback(esp_eth_phy_t *phy, bool enable) +{ + esp_err_t ret = ESP_OK; + phy_ip101_t *ip101 = __containerof(phy, phy_ip101_t, parent); + esp_eth_mediator_t *eth = ip101->eth; + /* Set Loopback function */ + bmcr_reg_t bmcr; + ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, ip101->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)), err, TAG, "read BMCR failed"); + if (enable) { + bmcr.en_loopback = 1; + } else { + bmcr.en_loopback = 0; + } + ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, ip101->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val), err, TAG, "write BMCR failed"); + return ESP_OK; +err: + return ret; +} + static esp_err_t ip101_init(esp_eth_phy_t *phy) { esp_err_t ret = ESP_OK; @@ -401,6 +424,7 @@ esp_eth_phy_t *esp_eth_phy_new_ip101(const eth_phy_config_t *config) ip101->parent.get_addr = ip101_get_addr; ip101->parent.set_addr = ip101_set_addr; ip101->parent.advertise_pause_ability = ip101_advertise_pause_ability; + ip101->parent.loopback = ip101_loopback; ip101->parent.del = ip101_del; return &(ip101->parent); diff --git a/components/esp_eth/src/esp_eth_phy_ksz80xx.c b/components/esp_eth/src/esp_eth_phy_ksz80xx.c index 1674648085..79d65fd2a3 100644 --- a/components/esp_eth/src/esp_eth_phy_ksz80xx.c +++ b/components/esp_eth/src/esp_eth_phy_ksz80xx.c @@ -208,6 +208,11 @@ static esp_err_t ksz80xx_reset_hw(esp_eth_phy_t *phy) return ESP_OK; } +/** + * @note This function is responsible for restarting a new auto-negotiation, + * the result of negotiation won't be relected to uppler layers. + * Instead, the negotiation result is fetched by linker timer, see `ksz80xx_get_link()` + */ static esp_err_t ksz80xx_negotiate(esp_eth_phy_t *phy) { esp_err_t ret = ESP_OK; @@ -233,8 +238,7 @@ static esp_err_t ksz80xx_negotiate(esp_eth_phy_t *phy) break; } } - /* Auto negotiation failed, maybe no network cable plugged in, so output a warning */ - if (to >= ksz80xx->autonego_timeout_ms / 100) { + if ((to >= ksz80xx->autonego_timeout_ms / 100) && (ksz80xx->link_status == ETH_LINK_UP)) { ESP_LOGW(TAG, "auto negotiation timeout"); } return ESP_OK; @@ -323,6 +327,25 @@ err: return ret; } +static esp_err_t ksz80xx_loopback(esp_eth_phy_t *phy, bool enable) +{ + esp_err_t ret = ESP_OK; + phy_ksz80xx_t *ksz80xx = __containerof(phy, phy_ksz80xx_t, parent); + esp_eth_mediator_t *eth = ksz80xx->eth; + /* Set Loopback function */ + bmcr_reg_t bmcr; + ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, ksz80xx->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)), err, TAG, "read BMCR failed"); + if (enable) { + bmcr.en_loopback = 1; + } else { + bmcr.en_loopback = 0; + } + ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, ksz80xx->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val), err, TAG, "write BMCR failed"); + return ESP_OK; +err: + return ret; +} + static esp_err_t ksz80xx_init(esp_eth_phy_t *phy) { esp_err_t ret = ESP_OK; @@ -376,6 +399,7 @@ esp_eth_phy_t *esp_eth_phy_new_ksz8041(const eth_phy_config_t *config) ksz8041->parent.get_addr = ksz80xx_get_addr; ksz8041->parent.set_addr = ksz80xx_set_addr; ksz8041->parent.advertise_pause_ability = ksz80xx_advertise_pause_ability; + ksz8041->parent.loopback = ksz80xx_loopback; ksz8041->parent.del = ksz80xx_del; return &(ksz8041->parent); err: diff --git a/components/esp_eth/src/esp_eth_phy_ksz8851snl.c b/components/esp_eth/src/esp_eth_phy_ksz8851snl.c index 2f72e6b394..4f85ad8ea9 100644 --- a/components/esp_eth/src/esp_eth_phy_ksz8851snl.c +++ b/components/esp_eth/src/esp_eth_phy_ksz8851snl.c @@ -160,6 +160,11 @@ err: return ret; } +/** + * @note This function is responsible for restarting a new auto-negotiation, + * the result of negotiation won't be relected to uppler layers. + * Instead, the negotiation result is fetched by linker timer, see `phy_ksz8851_get_link()` + */ static esp_err_t phy_ksz8851_negotiate(esp_eth_phy_t *phy) { esp_err_t ret = ESP_OK; @@ -181,8 +186,8 @@ static esp_err_t phy_ksz8851_negotiate(esp_eth_phy_t *phy) break; } } - if (to >= ksz8851->autonego_timeout_ms / 100) { - ESP_LOGW(TAG, "Ethernet PHY auto negotiation timeout"); + if ((to >= ksz8851->autonego_timeout_ms / 100) && (ksz8851->link_status == ETH_LINK_UP)) { + ESP_LOGW(TAG, "auto negotiation timeout"); } ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, ksz8851->addr, KSZ8851_P1CR, control), err, TAG, "P1CR write failed"); @@ -239,6 +244,26 @@ err: return ret; } +static esp_err_t phy_ksz8851_loopback(esp_eth_phy_t *phy, bool enable) +{ + esp_err_t ret = ESP_OK; + phy_ksz8851snl_t *ksz8851 = __containerof(phy, phy_ksz8851snl_t, parent); + esp_eth_mediator_t *eth = ksz8851->eth; + + uint32_t mbcr; + ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, ksz8851->addr, KSZ8851_P1MBCR, &mbcr), err, TAG, "P1MBCR read failed"); + if (enable) { + ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, ksz8851->addr, KSZ8851_P1MBCR, mbcr | P1MBCR_LOCAL_LOOPBACK), err, TAG, "P1MBCR write failed"); + ESP_LOGD(TAG, "set Local (far-end) loopback"); + } else { + ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, ksz8851->addr, KSZ8851_P1MBCR, mbcr & ~P1MBCR_LOCAL_LOOPBACK), err, TAG, "P1MBCR write failed"); + ESP_LOGD(TAG, "disabled Local (far-end) loopback"); + } + return ESP_OK; +err: + return ret; +} + static esp_err_t phy_ksz8851_del(esp_eth_phy_t *phy) { ESP_LOGD(TAG, "deleting PHY"); @@ -269,6 +294,7 @@ esp_eth_phy_t *esp_eth_phy_new_ksz8851snl(const eth_phy_config_t *config) ksz8851->parent.set_addr = phy_ksz8851_set_addr; ksz8851->parent.get_addr = phy_ksz8851_get_addr; ksz8851->parent.advertise_pause_ability = phy_ksz8851_advertise_pause_ability; + ksz8851->parent.loopback = phy_ksz8851_loopback; ksz8851->parent.del = phy_ksz8851_del; return &(ksz8851->parent); err: diff --git a/components/esp_eth/src/esp_eth_phy_lan87xx.c b/components/esp_eth/src/esp_eth_phy_lan87xx.c index ef2510b5ba..e6465501f0 100644 --- a/components/esp_eth/src/esp_eth_phy_lan87xx.c +++ b/components/esp_eth/src/esp_eth_phy_lan87xx.c @@ -73,14 +73,48 @@ typedef union { */ typedef union { struct { - uint32_t phy_addr : 5; /* PHY Address */ - uint32_t mode : 3; /* Transceiver Mode of Operation */ - uint32_t reserved : 8; /* Reserved */ + uint32_t phy_addr : 5; /* PHY Address */ + uint32_t mode : 3; /* Transceiver Mode of Operation */ + uint32_t reserved_1 : 6; /* Reserved */ + uint32_t mii_mode : 1; /* Mode of the digital interface (only LAN8710A/LAN8740A/LAN8741A) */ + uint32_t reserved_2 : 1; /* Reserved */ }; uint32_t val; } smr_reg_t; #define ETH_PHY_SMR_REG_ADDR (0x12) +/** + * @brief Time Domain Reflectometry Patterns/Delay Control Register + * Only available in LAN8740A/LAN8742A + */ +typedef union { + struct { + uint32_t tdr_pattern_low : 6; /* Data pattern sent in TDR mode for the low cycle */ + uint32_t tdr_pattern_high : 6; /* Data pattern sent in TDR mode for the high cycle */ + uint32_t tdr_line_break_counter : 3; /* Increments of 256ms of break time */ + uint32_t tdr_delay_in : 1; /* Line break counter used */ + }; + uint32_t val; +} tdr_pattern_reg_t; +#define EHT_PHY_TDRPD_REG_ADDR (0x18) + +/** + * @brief Time Domain Reflectometry Control/Status Register) + * Only available in LAN8740A/LAN8742A + */ +typedef union { + struct { + uint32_t tdr_channel_length : 8; /* TDR channel length */ + uint32_t tdr_channel_status : 1; /* TDR channel status */ + uint32_t tdr_channel_cable_type : 2; /* TDR channel cable type */ + uint32_t reserved : 3; /* Reserved */ + uint32_t tdr_a2d_filter_enable: 1; /* Analog to Digital Filter Enabled */ + uint32_t tdr_enable : 1; /* Enable TDR */ + }; + uint32_t val; +} tdr_control_reg_t; +#define EHT_PHY_TDRC_REG_ADDR (0x19) + /** * @brief SECR(Symbol Error Counter Register) * @@ -112,6 +146,19 @@ typedef union { } scsir_reg_t; #define ETH_PHY_CSIR_REG_ADDR (0x1B) +/** + * @brief Cable Length Register + * Only available in LAN8740A/LAN8742A + */ +typedef union { + struct { + uint32_t reserved : 12; /* Reserved */ + uint32_t cable_length : 4; /* Cable length */ + }; + uint32_t val; +} cbln_reg_t; +#define EHT_PHY_CBLN_REG_ADDR (0x1C) + /** * @brief ISR(Interrupt Source Register) * @@ -125,8 +172,9 @@ typedef union { uint32_t link_down : 1; /* Link Down */ uint32_t remote_fault_detect : 1; /* Remote Fault Detect */ uint32_t auto_nego_complete : 1; /* Auto-Negotiation Complete */ - uint32_t energy_on_generate : 1; /* ENERYON generated */ - uint32_t reserved2 : 8; /* Reserved */ + uint32_t energy_on_generate : 1; /* ENERGY ON generated */ + uint32_t wake_on_lan : 1; /* Wake on Lan (WOL) event detected (only LAN8740A/LAN8742A) */ + uint32_t reserved2 : 7; /* Reserved */ }; uint32_t val; } isfr_reg_t; @@ -146,7 +194,8 @@ typedef union { uint32_t remote_fault_detect : 1; /* Remote Fault Detect */ uint32_t auto_nego_complete : 1; /* Auto-Negotiation Complete */ uint32_t energy_on_generate : 1; /* ENERGY ON generated */ - uint32_t reserved2 : 8; /* Reserved */ + uint32_t wake_on_lan : 1; /* Wake on Lan (WOL) event detected (only LAN8740A/LAN8742A) */ + uint32_t reserved2 : 7; /* Reserved */ }; uint32_t val; } imr_reg_t; @@ -160,9 +209,11 @@ typedef union { struct { uint32_t reserved1 : 2; /* Reserved */ uint32_t speed_indication : 3; /* Speed Indication */ - uint32_t reserved2 : 7; /* Reserved */ + uint32_t reserved2 : 1; /* Reserved */ + uint32_t enable_4b5b : 1; /* Enable 4B5B encoder (only LAN8740A/LAN8741A) */ + uint32_t reserved3 : 5; /* Reserved */ uint32_t auto_nego_done : 1; /* Auto Negotiation Done */ - uint32_t reserved3 : 3; /* Reserved */ + uint32_t reserved4 : 3; /* Reserved */ }; uint32_t val; } pscsr_reg_t; @@ -292,6 +343,11 @@ static esp_err_t lan87xx_reset_hw(esp_eth_phy_t *phy) return ESP_OK; } +/** + * @note This function is responsible for restarting a new auto-negotiation, + * the result of negotiation won't be relected to uppler layers. + * Instead, the negotiation result is fetched by linker timer, see `lan87xx_get_link()` + */ static esp_err_t lan87xx_negotiate(esp_eth_phy_t *phy) { esp_err_t ret = ESP_OK; @@ -320,7 +376,7 @@ static esp_err_t lan87xx_negotiate(esp_eth_phy_t *phy) } } /* Auto negotiation failed, maybe no network cable plugged in, so output a warning */ - if (to >= lan87xx->autonego_timeout_ms / 100) { + if (to >= lan87xx->autonego_timeout_ms / 100 && (lan87xx->link_status == ETH_LINK_UP)) { ESP_LOGW(TAG, "auto negotiation timeout"); } return ESP_OK; @@ -409,6 +465,25 @@ err: return ret; } +static esp_err_t lan87xx_loopback(esp_eth_phy_t *phy, bool enable) +{ + esp_err_t ret = ESP_OK; + phy_lan87xx_t *lan87xx = __containerof(phy, phy_lan87xx_t, parent); + esp_eth_mediator_t *eth = lan87xx->eth; + /* Set Loopback function */ + bmcr_reg_t bmcr; + ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, lan87xx->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)), err, TAG, "read BMCR failed"); + if (enable) { + bmcr.en_loopback = 1; + } else { + bmcr.en_loopback = 0; + } + ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, lan87xx->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val), err, TAG, "write BMCR failed"); + return ESP_OK; +err: + return ret; +} + static esp_err_t lan87xx_init(esp_eth_phy_t *phy) { esp_err_t ret = ESP_OK; @@ -472,6 +547,7 @@ esp_eth_phy_t *esp_eth_phy_new_lan87xx(const eth_phy_config_t *config) lan87xx->parent.pwrctl = lan87xx_pwrctl; lan87xx->parent.get_addr = lan87xx_get_addr; lan87xx->parent.set_addr = lan87xx_set_addr; + lan87xx->parent.loopback = lan87xx_loopback; lan87xx->parent.advertise_pause_ability = lan87xx_advertise_pause_ability; lan87xx->parent.del = lan87xx_del; diff --git a/components/esp_eth/src/esp_eth_phy_rtl8201.c b/components/esp_eth/src/esp_eth_phy_rtl8201.c index 8ba4a35445..2f05b000d8 100644 --- a/components/esp_eth/src/esp_eth_phy_rtl8201.c +++ b/components/esp_eth/src/esp_eth_phy_rtl8201.c @@ -183,6 +183,11 @@ static esp_err_t rtl8201_reset_hw(esp_eth_phy_t *phy) return ESP_OK; } +/** + * @note This function is responsible for restarting a new auto-negotiation, + * the result of negotiation won't be relected to uppler layers. + * Instead, the negotiation result is fetched by linker timer, see `rtl8201_get_link()` + */ static esp_err_t rtl8201_negotiate(esp_eth_phy_t *phy) { esp_err_t ret = ESP_OK; @@ -208,8 +213,7 @@ static esp_err_t rtl8201_negotiate(esp_eth_phy_t *phy) break; } } - /* Auto negotiation failed, maybe no network cable plugged in, so output a warning */ - if (to >= rtl8201->autonego_timeout_ms / 100) { + if ((to >= rtl8201->autonego_timeout_ms / 100) && (rtl8201->link_status == ETH_LINK_UP)) { ESP_LOGW(TAG, "auto negotiation timeout"); } return ESP_OK; @@ -298,6 +302,25 @@ err: return ret; } +static esp_err_t rtl8201_loopback(esp_eth_phy_t *phy, bool enable) +{ + esp_err_t ret = ESP_OK; + phy_rtl8201_t *rtl8201 = __containerof(phy, phy_rtl8201_t, parent); + esp_eth_mediator_t *eth = rtl8201->eth; + /* Set Loopback function */ + bmcr_reg_t bmcr; + ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, rtl8201->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)), err, TAG, "read BMCR failed"); + if (enable) { + bmcr.en_loopback = 1; + } else { + bmcr.en_loopback = 0; + } + ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, rtl8201->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val), err, TAG, "write BMCR failed"); + return ESP_OK; +err: + return ret; +} + static esp_err_t rtl8201_init(esp_eth_phy_t *phy) { esp_err_t ret = ESP_OK; @@ -354,6 +377,7 @@ esp_eth_phy_t *esp_eth_phy_new_rtl8201(const eth_phy_config_t *config) rtl8201->parent.get_addr = rtl8201_get_addr; rtl8201->parent.set_addr = rtl8201_set_addr; rtl8201->parent.advertise_pause_ability = rtl8201_advertise_pause_ability; + rtl8201->parent.loopback = rtl8201_loopback; rtl8201->parent.del = rtl8201_del; return &(rtl8201->parent); diff --git a/components/esp_eth/src/esp_eth_phy_w5500.c b/components/esp_eth/src/esp_eth_phy_w5500.c index 2ec157c6b4..4296582d97 100644 --- a/components/esp_eth/src/esp_eth_phy_w5500.c +++ b/components/esp_eth/src/esp_eth_phy_w5500.c @@ -197,6 +197,12 @@ static esp_err_t w5500_advertise_pause_ability(esp_eth_phy_t *phy, uint32_t abil return ESP_OK; } +static esp_err_t w5500_loopback(esp_eth_phy_t *phy, bool enable) +{ + // Loopback is not supported for W5500 internal PHY + return ESP_ERR_NOT_SUPPORTED; +} + static esp_err_t w5500_init(esp_eth_phy_t *phy) { esp_err_t ret = ESP_OK; @@ -241,6 +247,7 @@ esp_eth_phy_t *esp_eth_phy_new_w5500(const eth_phy_config_t *config) w5500->parent.get_addr = w5500_get_addr; w5500->parent.set_addr = w5500_set_addr; w5500->parent.advertise_pause_ability = w5500_advertise_pause_ability; + w5500->parent.loopback = w5500_loopback; w5500->parent.del = w5500_del; return &(w5500->parent); err: diff --git a/components/esp_eth/test/test_emac.c b/components/esp_eth/test/test_emac.c index 51b20917e7..cd47098b56 100644 --- a/components/esp_eth/test/test_emac.c +++ b/components/esp_eth/test/test_emac.c @@ -9,10 +9,6 @@ #include "esp_eth.h" #include "esp_log.h" #include "esp_http_client.h" -#include "lwip/inet.h" -#include "lwip/netdb.h" -#include "lwip/sockets.h" -#include "ping/ping_sock.h" #include "esp_rom_md5.h" #include "soc/soc_caps.h" @@ -24,18 +20,13 @@ static const char *TAG = "esp32_eth_test"; #define ETH_STOP_BIT BIT(1) #define ETH_CONNECT_BIT BIT(2) #define ETH_GOT_IP_BIT BIT(3) -#define ETH_PING_END_BIT BIT(4) -#define ETH_DOWNLOAD_END_BIT BIT(5) +#define ETH_DOWNLOAD_END_BIT BIT(4) #define ETH_START_TIMEOUT_MS (10000) #define ETH_CONNECT_TIMEOUT_MS (40000) #define ETH_STOP_TIMEOUT_MS (10000) #define ETH_GET_IP_TIMEOUT_MS (60000) #define ETH_DOWNLOAD_END_TIMEOUT_MS (240000) -#define ETH_PING_DURATION_MS (5000) -#define ETH_PING_END_TIMEOUT_MS (ETH_PING_DURATION_MS * 2) - -#define TEST_ICMP_DESTINATION_DOMAIN_NAME "127.0.0.1" extern const char dl_espressif_com_root_cert_pem_start[] asm("_binary_dl_espressif_com_root_cert_pem_start"); extern const char dl_espressif_com_root_cert_pem_end[] asm("_binary_dl_espressif_com_root_cert_pem_end"); @@ -86,46 +77,6 @@ static void got_ip_event_handler(void *arg, esp_event_base_t event_base, xEventGroupSetBits(eth_event_group, ETH_GOT_IP_BIT); } -static void test_on_ping_success(esp_ping_handle_t hdl, void *args) -{ - uint8_t ttl; - uint16_t seqno; - uint32_t elapsed_time, recv_len; - ip_addr_t target_addr; - esp_ping_get_profile(hdl, ESP_PING_PROF_SEQNO, &seqno, sizeof(seqno)); - esp_ping_get_profile(hdl, ESP_PING_PROF_TTL, &ttl, sizeof(ttl)); - esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr)); - esp_ping_get_profile(hdl, ESP_PING_PROF_SIZE, &recv_len, sizeof(recv_len)); - esp_ping_get_profile(hdl, ESP_PING_PROF_TIMEGAP, &elapsed_time, sizeof(elapsed_time)); - printf("%d bytes from %s icmp_seq=%d ttl=%d time=%d ms\n", - recv_len, inet_ntoa(target_addr.u_addr.ip4), seqno, ttl, elapsed_time); -} - -static void test_on_ping_timeout(esp_ping_handle_t hdl, void *args) -{ - uint16_t seqno; - ip_addr_t target_addr; - esp_ping_get_profile(hdl, ESP_PING_PROF_SEQNO, &seqno, sizeof(seqno)); - esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr)); - printf("From %s icmp_seq=%d timeout\n", inet_ntoa(target_addr.u_addr.ip4), seqno); -} - -static void test_on_ping_end(esp_ping_handle_t hdl, void *args) -{ - EventGroupHandle_t eth_event_group = (EventGroupHandle_t)args; - uint32_t transmitted; - uint32_t received; - uint32_t total_time_ms; - - esp_ping_get_profile(hdl, ESP_PING_PROF_REQUEST, &transmitted, sizeof(transmitted)); - esp_ping_get_profile(hdl, ESP_PING_PROF_REPLY, &received, sizeof(received)); - esp_ping_get_profile(hdl, ESP_PING_PROF_DURATION, &total_time_ms, sizeof(total_time_ms)); - printf("%d packets transmitted, %d received, time %dms\n", transmitted, received, total_time_ms); - if (transmitted == received) { - xEventGroupSetBits(eth_event_group, ETH_PING_END_BIT); - } -} - static esp_err_t test_uninstall_driver(esp_eth_handle_t eth_hdl, uint32_t ms_to_wait) { int i = 0; @@ -218,11 +169,7 @@ TEST_CASE("esp32 ethernet dhcp test", "[ethernet][test_env=UT_T2_Ethernet]") // create TCP/IP netif esp_netif_config_t netif_cfg = ESP_NETIF_DEFAULT_ETH(); esp_netif_t *eth_netif = esp_netif_new(&netif_cfg); - // set default handlers to do layer 3 (and up) stuffs - TEST_ESP_OK(esp_eth_set_default_handlers(eth_netif)); - // register user defined event handers - TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, eth_event_group)); - TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, eth_event_group)); + eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config); eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); @@ -232,8 +179,11 @@ TEST_CASE("esp32 ethernet dhcp test", "[ethernet][test_env=UT_T2_Ethernet]") // install Ethernet driver TEST_ESP_OK(esp_eth_driver_install(ð_config, ð_handle)); // combine driver with netif - void *glue = esp_eth_new_netif_glue(eth_handle); + esp_eth_netif_glue_handle_t glue = esp_eth_new_netif_glue(eth_handle); TEST_ESP_OK(esp_netif_attach(eth_netif, glue)); + // register user defined event handers + TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, eth_event_group)); + TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, eth_event_group)); // start Ethernet driver TEST_ESP_OK(esp_eth_start(eth_handle)); /* wait for IP lease */ @@ -251,7 +201,6 @@ TEST_CASE("esp32 ethernet dhcp test", "[ethernet][test_env=UT_T2_Ethernet]") TEST_ESP_OK(mac->del(mac)); TEST_ESP_OK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, got_ip_event_handler)); TEST_ESP_OK(esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, eth_event_handler)); - TEST_ESP_OK(esp_eth_clear_default_handlers(eth_netif)); esp_netif_destroy(eth_netif); TEST_ESP_OK(esp_event_loop_delete_default()); vEventGroupDelete(eth_event_group); @@ -267,11 +216,7 @@ TEST_CASE("esp32 ethernet start/stop stress test", "[ethernet][test_env=UT_T2_Et // create TCP/IP netif esp_netif_config_t netif_cfg = ESP_NETIF_DEFAULT_ETH(); esp_netif_t *eth_netif = esp_netif_new(&netif_cfg); - // set default handlers to do layer 3 (and up) stuffs - TEST_ESP_OK(esp_eth_set_default_handlers(eth_netif)); - // register user defined event handers - TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, eth_event_group)); - TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, eth_event_group)); + eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config); eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); @@ -281,8 +226,11 @@ TEST_CASE("esp32 ethernet start/stop stress test", "[ethernet][test_env=UT_T2_Et // install Ethernet driver TEST_ESP_OK(esp_eth_driver_install(ð_config, ð_handle)); // combine driver with netif - void *glue = esp_eth_new_netif_glue(eth_handle); + esp_eth_netif_glue_handle_t glue = esp_eth_new_netif_glue(eth_handle); TEST_ESP_OK(esp_netif_attach(eth_netif, glue)); + // register user defined event handers + TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, eth_event_group)); + TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, eth_event_group)); for (int i = 0; i < 10; i++) { // start Ethernet driver @@ -304,98 +252,6 @@ TEST_CASE("esp32 ethernet start/stop stress test", "[ethernet][test_env=UT_T2_Et TEST_ESP_OK(mac->del(mac)); TEST_ESP_OK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, got_ip_event_handler)); TEST_ESP_OK(esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, eth_event_handler)); - TEST_ESP_OK(esp_eth_clear_default_handlers(eth_netif)); - esp_netif_destroy(eth_netif); - TEST_ESP_OK(esp_event_loop_delete_default()); - vEventGroupDelete(eth_event_group); -} - -TEST_CASE("esp32 ethernet icmp test", "[ethernet][test_env=UT_T2_Ethernet]") -{ - EventBits_t bits = 0; - EventGroupHandle_t eth_event_group = xEventGroupCreate(); - TEST_ASSERT(eth_event_group != NULL); - test_case_uses_tcpip(); - TEST_ESP_OK(esp_event_loop_create_default()); - // create TCP/IP netif - esp_netif_config_t netif_cfg = ESP_NETIF_DEFAULT_ETH(); - esp_netif_t *eth_netif = esp_netif_new(&netif_cfg); - // set default handlers to do layer 3 (and up) stuffs - TEST_ESP_OK(esp_eth_set_default_handlers(eth_netif)); - // register user defined event handers - TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, eth_event_group)); - TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, eth_event_group)); - eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); - esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config); - eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); - esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config); - esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(mac, phy); - esp_eth_handle_t eth_handle = NULL; - TEST_ESP_OK(esp_eth_driver_install(ð_config, ð_handle)); - // combine driver with netif - void *glue = esp_eth_new_netif_glue(eth_handle); - TEST_ESP_OK(esp_netif_attach(eth_netif, glue)); - // start Ethernet driver - TEST_ESP_OK(esp_eth_start(eth_handle)); - /* wait for IP lease */ - bits = xEventGroupWaitBits(eth_event_group, ETH_GOT_IP_BIT, true, true, pdMS_TO_TICKS(ETH_GET_IP_TIMEOUT_MS)); - TEST_ASSERT((bits & ETH_GOT_IP_BIT) == ETH_GOT_IP_BIT); - - // Parse IP address - ip_addr_t target_addr; - struct addrinfo hint; - struct addrinfo *res = NULL; - memset(&hint, 0, sizeof(hint)); - memset(&target_addr, 0, sizeof(target_addr)); - /* convert URL to IP */ - TEST_ASSERT(getaddrinfo(TEST_ICMP_DESTINATION_DOMAIN_NAME, NULL, &hint, &res) == 0); - struct in_addr addr4 = ((struct sockaddr_in *)(res->ai_addr))->sin_addr; - inet_addr_to_ip4addr(ip_2_ip4(&target_addr), &addr4); - freeaddrinfo(res); - - esp_ping_config_t ping_config = ESP_PING_DEFAULT_CONFIG(); - ping_config.timeout_ms = 2000; - ping_config.target_addr = target_addr; - ping_config.count = 0; // ping in infinite mode - /* set callback functions */ - esp_ping_callbacks_t cbs; - cbs.on_ping_success = test_on_ping_success; - cbs.on_ping_timeout = test_on_ping_timeout; - cbs.on_ping_end = test_on_ping_end; - cbs.cb_args = eth_event_group; - - esp_ping_handle_t ping; - TEST_ESP_OK(esp_ping_new_session(&ping_config, &cbs, &ping)); - /* start ping */ - TEST_ESP_OK(esp_ping_start(ping)); - /* ping for a while */ - vTaskDelay(pdMS_TO_TICKS(ETH_PING_DURATION_MS)); - /* stop ping */ - TEST_ESP_OK(esp_ping_stop(ping)); - /* wait for end of ping */ - bits = xEventGroupWaitBits(eth_event_group, ETH_PING_END_BIT, true, true, pdMS_TO_TICKS(ETH_PING_END_TIMEOUT_MS)); - TEST_ASSERT((bits & ETH_PING_END_BIT) == ETH_PING_END_BIT); - /* restart ping */ - TEST_ESP_OK(esp_ping_start(ping)); - vTaskDelay(pdMS_TO_TICKS(ETH_PING_DURATION_MS)); - TEST_ESP_OK(esp_ping_stop(ping)); - bits = xEventGroupWaitBits(eth_event_group, ETH_PING_END_BIT, true, true, pdMS_TO_TICKS(ETH_PING_END_TIMEOUT_MS)); - TEST_ASSERT((bits & ETH_PING_END_BIT) == ETH_PING_END_BIT); - /* de-initialize ping process */ - TEST_ESP_OK(esp_ping_delete_session(ping)); - - // stop Ethernet driver - TEST_ESP_OK(esp_eth_stop(eth_handle)); - /* wait for connection stop */ - bits = xEventGroupWaitBits(eth_event_group, ETH_STOP_BIT, true, true, pdMS_TO_TICKS(ETH_STOP_TIMEOUT_MS)); - TEST_ASSERT((bits & ETH_STOP_BIT) == ETH_STOP_BIT); - TEST_ESP_OK(esp_eth_del_netif_glue(glue)); - /* driver should be uninstalled within 2 seconds */ - TEST_ESP_OK(test_uninstall_driver(eth_handle, 2000)); - TEST_ESP_OK(phy->del(phy)); - TEST_ESP_OK(mac->del(mac)); - TEST_ESP_OK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, got_ip_event_handler)); - TEST_ESP_OK(esp_eth_clear_default_handlers(eth_netif)); esp_netif_destroy(eth_netif); TEST_ESP_OK(esp_event_loop_delete_default()); vEventGroupDelete(eth_event_group); @@ -458,11 +314,7 @@ TEST_CASE("esp32 ethernet download test", "[ethernet][test_env=UT_T2_Ethernet][t // create TCP/IP netif esp_netif_config_t netif_cfg = ESP_NETIF_DEFAULT_ETH(); esp_netif_t *eth_netif = esp_netif_new(&netif_cfg); - // set default handlers to do layer 3 (and up) stuffs - TEST_ESP_OK(esp_eth_set_default_handlers(eth_netif)); - // register user defined event handers - TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, eth_event_group)); - TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, eth_event_group)); + eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config); eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); @@ -472,8 +324,11 @@ TEST_CASE("esp32 ethernet download test", "[ethernet][test_env=UT_T2_Ethernet][t // install Ethernet driver TEST_ESP_OK(esp_eth_driver_install(ð_config, ð_handle)); // combine driver with netif - void *glue = esp_eth_new_netif_glue(eth_handle); + esp_eth_netif_glue_handle_t glue = esp_eth_new_netif_glue(eth_handle); TEST_ESP_OK(esp_netif_attach(eth_netif, glue)); + // register user defined event handers + TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, eth_event_group)); + TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, eth_event_group)); // start Ethernet driver TEST_ESP_OK(esp_eth_start(eth_handle)); /* wait for IP lease */ @@ -506,7 +361,6 @@ TEST_CASE("esp32 ethernet download test", "[ethernet][test_env=UT_T2_Ethernet][t TEST_ESP_OK(mac->del(mac)); TEST_ESP_OK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, got_ip_event_handler)); TEST_ESP_OK(esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, eth_event_handler)); - TEST_ESP_OK(esp_eth_clear_default_handlers(eth_netif)); esp_netif_destroy(eth_netif); TEST_ESP_OK(esp_event_loop_delete_default()); vEventGroupDelete(eth_event_group); diff --git a/components/esp_eth/test_apps/.gitignore b/components/esp_eth/test_apps/.gitignore new file mode 100644 index 0000000000..fd64f641a5 --- /dev/null +++ b/components/esp_eth/test_apps/.gitignore @@ -0,0 +1,2 @@ +# JUnit report +*XUNIT_RESULT.xml diff --git a/components/esp_eth/test_apps/CMakeLists.txt b/components/esp_eth/test_apps/CMakeLists.txt new file mode 100644 index 0000000000..9ac3394bf3 --- /dev/null +++ b/components/esp_eth/test_apps/CMakeLists.txt @@ -0,0 +1,8 @@ +# This is the project CMakeLists.txt file for the test subproject +cmake_minimum_required(VERSION 3.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(esp_eth_test) + +idf_component_get_property(lib esp_eth COMPONENT_LIB) +target_compile_options(${lib} PRIVATE "-fsanitize=undefined" "-fno-sanitize=shift-base") diff --git a/components/esp_eth/test_apps/README.md b/components/esp_eth/test_apps/README.md new file mode 100644 index 0000000000..f4c88b87b9 --- /dev/null +++ b/components/esp_eth/test_apps/README.md @@ -0,0 +1,7 @@ +| Supported Targets | ESP32 | +| ----------------- | ----- | + +This test app is used to test MAC layer behavior with different PHY chips: + +- ip101 +- lan8720 diff --git a/components/esp_eth/test_apps/component_ut_test.py b/components/esp_eth/test_apps/component_ut_test.py new file mode 100644 index 0000000000..b511fe9a52 --- /dev/null +++ b/components/esp_eth/test_apps/component_ut_test.py @@ -0,0 +1,102 @@ +import os +import re +import socket + +import tiny_test_fw +import ttfw_idf +from ttfw_idf import TestFormat + +try: + import typing # noqa: F401 # pylint: disable=unused-import +except ImportError: + pass + + +def configure_eth_if(func): # type: (typing.Any) -> typing.Any + def inner(*args, **kwargs): # type: (typing.Any, typing.Any) -> typing.Any + # try to determine which interface to use + netifs = os.listdir('/sys/class/net/') + target_if = '' + print('detected interfaces: ' + str(netifs)) + for netif in netifs: + if netif.find('eth') == 0 or netif.find('enp') == 0 or netif.find('eno') == 0: + target_if = netif + break + if target_if == '': + raise Exception('no network interface found') + print('Use ' + target_if + ' for testing') + so = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, 0x2222) + so.bind((target_if, 0)) + + func(so, *args, **kwargs) + + so.close() + + return inner + + +@configure_eth_if +def check_eth_recv_packet(so): # type: (socket.socket) -> None + so.settimeout(10) + try: + pkt = so.recv(1024) + for i in range(128, 1024): + if pkt[i] != i & 0xff: + raise Exception('Packet content mismatch') + except Exception as e: + raise e + + +@configure_eth_if +def send_eth_packet(so, mac): # type: (socket.socket, bytes) -> None + so.settimeout(10) + pkt = bytearray() + pkt += mac # dest + pkt += so.getsockname()[4] # src + pkt += bytes.fromhex('2222') # proto + pkt += bytes(1010) # padding to 1024 + for i in range(128, 1024): + pkt[i] = i & 0xff + try: + so.send(pkt) + except Exception as e: + raise e + + +def test_component_ut_esp_eth(env, appname): # type: (tiny_test_fw.Env, str) -> None + dut = env.get_dut('esp_eth', 'components/esp_eth/test_apps', app_config_name=appname) + dut.start_app() + stdout = dut.expect('Press ENTER to see the list of tests', full_stdout=True) + dut.write('"start_and_stop"') + stdout += dut.expect("Enter next test, or 'enter' to see menu", full_stdout=True) + ttfw_idf.ComponentUTResult.parse_result(stdout, test_format=TestFormat.UNITY_BASIC) + dut.write('"get_set_mac"') + stdout = dut.expect("Enter next test, or 'enter' to see menu", full_stdout=True) + ttfw_idf.ComponentUTResult.parse_result(stdout, test_format=TestFormat.UNITY_BASIC) + dut.write('"ethernet_broadcast_transmit"') + check_eth_recv_packet() + stdout = dut.expect("Enter next test, or 'enter' to see menu", full_stdout=True) + ttfw_idf.ComponentUTResult.parse_result(stdout, test_format=TestFormat.UNITY_BASIC) + dut.write('"recv_pkt"') + expect_result = dut.expect(re.compile(r'([\s\S]*)DUT MAC: ([0-9a-zA-Z:]*)'), timeout=10) + stdout = expect_result[0] + send_eth_packet(bytes.fromhex('ffffffffffff')) # broadcast frame + send_eth_packet(bytes.fromhex('010000000000')) # multicast frame + send_eth_packet(bytes.fromhex(expect_result[1].replace(':', ''))) # unicast frame + stdout += dut.expect("Enter next test, or 'enter' to see menu", full_stdout=True) + ttfw_idf.ComponentUTResult.parse_result(stdout, test_format=TestFormat.UNITY_BASIC) + + +@ttfw_idf.idf_component_unit_test(env_tag='COMPONENT_UT_IP101', target=['esp32']) +def test_component_ut_esp_eth_ip101(env, _): # type: (tiny_test_fw.Env, typing.Any) -> None + test_component_ut_esp_eth(env, 'ip101') + + +@ttfw_idf.idf_component_unit_test(env_tag='COMPONENT_UT_LAN8720', target=['esp32']) +def test_component_ut_esp_eth_lan8720(env, _): # type: (tiny_test_fw.Env, typing.Any) -> None + test_component_ut_esp_eth(env, 'lan8720') + + +if __name__ == '__main__': + test_component_ut_esp_eth_ip101() + test_component_ut_esp_eth_lan8720() diff --git a/components/esp_eth/test_apps/main/CMakeLists.txt b/components/esp_eth/test_apps/main/CMakeLists.txt new file mode 100644 index 0000000000..f682367521 --- /dev/null +++ b/components/esp_eth/test_apps/main/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register(SRCS "esp_eth_test.c" + INCLUDE_DIRS "." + PRIV_INCLUDE_DIRS "." + PRIV_REQUIRES unity esp_eth) diff --git a/components/esp_eth/test_apps/main/Kconfig.projbuild b/components/esp_eth/test_apps/main/Kconfig.projbuild new file mode 100644 index 0000000000..c10b08d3e0 --- /dev/null +++ b/components/esp_eth/test_apps/main/Kconfig.projbuild @@ -0,0 +1,14 @@ +menu "esp_eth TEST_APPS Configuration" + + choice TARGET_ETH_PHY_DEVICE + prompt "Ethernet peripheral device" + default TARGET_ETH_PHY_DEVICE_IP101 + help + Select one of the devices listed here + + config TARGET_ETH_PHY_DEVICE_IP101 + bool "IP101" + config TARGET_ETH_PHY_DEVICE_LAN8720 + bool "LAN8720" + endchoice +endmenu diff --git a/components/esp_eth/test_apps/main/esp_eth_test.c b/components/esp_eth/test_apps/main/esp_eth_test.c new file mode 100644 index 0000000000..2ed5a685f2 --- /dev/null +++ b/components/esp_eth/test_apps/main/esp_eth_test.c @@ -0,0 +1,265 @@ +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/event_groups.h" +#include "esp_event.h" +#include "unity.h" +#include "esp_netif.h" +#include "esp_eth.h" +#include "sdkconfig.h" +#include "lwip/sockets.h" + +#define ETH_START_BIT BIT(0) +#define ETH_STOP_BIT BIT(1) +#define ETH_CONNECT_BIT BIT(2) + +#define ETH_BROADCAST_RECV_BIT BIT(0) +#define ETH_MULTICAST_RECV_BIT BIT(1) +#define ETH_UNICAST_RECV_BIT BIT(2) + +typedef struct { + uint8_t dest[6]; + uint8_t src[6]; + uint16_t proto; + uint8_t data[]; +} __attribute__((__packed__)) emac_frame_t; + +TEST_CASE("start_and_stop", "[esp_eth]") +{ + void eth_event_handler(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data){ + EventGroupHandle_t eth_event_group = (EventGroupHandle_t)arg; + switch (event_id) { + case ETHERNET_EVENT_CONNECTED: + xEventGroupSetBits(eth_event_group, ETH_CONNECT_BIT); + break; + case ETHERNET_EVENT_START: + xEventGroupSetBits(eth_event_group, ETH_START_BIT); + break; + case ETHERNET_EVENT_STOP: + xEventGroupSetBits(eth_event_group, ETH_STOP_BIT); + break; + default: + break; + } + } + + EventGroupHandle_t eth_event_group = xEventGroupCreate(); + TEST_ASSERT(eth_event_group != NULL); + + eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); // apply default MAC configuration + esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config); // create MAC instance + TEST_ASSERT_NOT_NULL(mac); + eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); // apply default PHY configuration +#if defined(CONFIG_TARGET_ETH_PHY_DEVICE_IP101) + esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config); // create PHY instance +#elif defined(CONFIG_TARGET_ETH_PHY_DEVICE_LAN8720) + esp_eth_phy_t *phy = esp_eth_phy_new_lan8720(&phy_config); +#endif + TEST_ASSERT_NOT_NULL(phy); + esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy); // apply default driver configuration + esp_eth_handle_t eth_handle = NULL; // after driver installed, we will get the handle of the driver + TEST_ASSERT_EQUAL(ESP_OK, esp_eth_driver_install(&config, ð_handle)); // install driver + TEST_ASSERT_NOT_NULL(eth_handle); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create_default()); + TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, eth_event_group)); + TEST_ASSERT_EQUAL(ESP_OK, esp_eth_start(eth_handle)); // start Ethernet driver state machine + + EventBits_t bits = 0; + bits = xEventGroupWaitBits(eth_event_group, ETH_START_BIT, true, true, pdMS_TO_TICKS(3000)); + TEST_ASSERT((bits & ETH_START_BIT) == ETH_START_BIT); + + TEST_ASSERT_EQUAL(ESP_OK, esp_eth_stop(eth_handle)); + + bits = xEventGroupWaitBits(eth_event_group, ETH_STOP_BIT, true, true, pdMS_TO_TICKS(3000)); + TEST_ASSERT((bits & ETH_STOP_BIT) == ETH_STOP_BIT); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete_default()); + TEST_ASSERT_EQUAL(ESP_OK, esp_eth_driver_uninstall(eth_handle)); + phy->del(phy); + mac->del(mac); + vEventGroupDelete(eth_event_group); +} + +TEST_CASE("get_set_mac", "[esp_eth]") +{ + void eth_event_handler(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data){ + SemaphoreHandle_t mutex = (SemaphoreHandle_t)arg; + switch (event_id) { + case ETHERNET_EVENT_CONNECTED: + xSemaphoreGive(mutex); + break; + default: + break; + } + } + + SemaphoreHandle_t mutex = xSemaphoreCreateBinary(); + TEST_ASSERT_NOT_NULL(mutex); + + eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); // apply default MAC configuration + esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config); // create MAC instance + TEST_ASSERT_NOT_NULL(mac); + eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); // apply default PHY configuration +#if defined(CONFIG_TARGET_ETH_PHY_DEVICE_IP101) + esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config); // create PHY instance +#elif defined(CONFIG_TARGET_ETH_PHY_DEVICE_LAN8720) + esp_eth_phy_t *phy = esp_eth_phy_new_lan8720(&phy_config); +#endif + TEST_ASSERT_NOT_NULL(phy); + esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy); // apply default driver configuration + esp_eth_handle_t eth_handle = NULL; // after driver installed, we will get the handle of the driver + TEST_ASSERT_EQUAL(ESP_OK, esp_eth_driver_install(&config, ð_handle)); // install driver + TEST_ASSERT_NOT_NULL(eth_handle); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create_default()); + TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, mutex)); + TEST_ASSERT_EQUAL(ESP_OK, esp_eth_start(eth_handle)); // start Ethernet driver state machine + + TEST_ASSERT(xSemaphoreTake(mutex, pdMS_TO_TICKS(3000))); + + uint8_t mac_addr[6] = {}; + TEST_ASSERT_EQUAL(ESP_OK, mac->get_addr(mac, mac_addr)); + TEST_ASSERT_BITS(0b00000011, 0b00, mac_addr[0]); // Check UL&IG, should be UI + mac_addr[5] ^= mac_addr[4]; + TEST_ASSERT_EQUAL(ESP_OK, mac->set_addr(mac, mac_addr)); + uint8_t new_mac_addr[6] = {}; + TEST_ASSERT_EQUAL(ESP_OK, mac->get_addr(mac, new_mac_addr)); + TEST_ASSERT_EQUAL(0, memcmp(mac_addr, new_mac_addr, 6)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_eth_stop(eth_handle)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete_default()); + TEST_ASSERT_EQUAL(ESP_OK, esp_eth_driver_uninstall(eth_handle)); + phy->del(phy); + mac->del(mac); + vSemaphoreDelete(mutex); +} + +TEST_CASE("ethernet_broadcast_transmit", "[esp_eth]") +{ + void eth_event_handler(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data){ + SemaphoreHandle_t mutex = (SemaphoreHandle_t)arg; + switch (event_id) { + case ETHERNET_EVENT_CONNECTED: + xSemaphoreGive(mutex); + break; + default: + break; + } + } + SemaphoreHandle_t mutex = xSemaphoreCreateBinary(); + TEST_ASSERT_NOT_NULL(mutex); + + eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); // apply default MAC configuration + esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config); // create MAC instance + TEST_ASSERT_NOT_NULL(mac); + eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); // apply default PHY configuration +#if defined(CONFIG_TARGET_ETH_PHY_DEVICE_IP101) + esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config); // create PHY instance +#elif defined(CONFIG_TARGET_ETH_PHY_DEVICE_LAN8720) + esp_eth_phy_t *phy = esp_eth_phy_new_lan8720(&phy_config); +#endif + TEST_ASSERT_NOT_NULL(phy); + esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy); // apply default driver configuration + esp_eth_handle_t eth_handle = NULL; // after driver installed, we will get the handle of the driver + TEST_ASSERT_EQUAL(ESP_OK, esp_eth_driver_install(&config, ð_handle)); // install driver + TEST_ASSERT_NOT_NULL(eth_handle); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create_default()); + TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, mutex)); + TEST_ASSERT_EQUAL(ESP_OK, esp_eth_start(eth_handle)); // start Ethernet driver state machine + + TEST_ASSERT(xSemaphoreTake(mutex, pdMS_TO_TICKS(3000))); + + emac_frame_t *pkt = malloc(1024); + pkt->proto = 0x2222; + memset(pkt->dest, 0xff, 6); // broadcast addr + for (int i = 128; i < 1024; ++i){ + ((uint8_t*)pkt)[i] = i & 0xff; + } + + TEST_ASSERT_EQUAL(ESP_OK, esp_eth_transmit(eth_handle, pkt, 1024)); + vTaskDelay(pdMS_TO_TICKS(100)); + free(pkt); + + TEST_ASSERT_EQUAL(ESP_OK, esp_eth_stop(eth_handle)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete_default()); + TEST_ASSERT_EQUAL(ESP_OK, esp_eth_driver_uninstall(eth_handle)); + phy->del(phy); + mac->del(mac); + vSemaphoreDelete(mutex); +} + +static uint8_t local_mac_addr[6] = {}; + +esp_err_t l2_packet_txrx_test_cb(esp_eth_handle_t hdl, uint8_t *buffer, uint32_t length, void *priv) { + EventGroupHandle_t eth_event_group = (EventGroupHandle_t)priv; + emac_frame_t *pkt = (emac_frame_t *) buffer; + // check header + if (pkt->proto == 0x2222 && length == 1024) { + // check content + for (int i = 128; i < 1024; ++i) { + if (buffer[i] != (i & 0xff)) { + return ESP_OK; + } + } + if (memcmp(pkt->dest, "\xff\xff\xff\xff\xff\xff", 6) == 0) { + xEventGroupSetBits(eth_event_group, ETH_BROADCAST_RECV_BIT); + } + if (pkt->dest[0] & 0x1) { + xEventGroupSetBits(eth_event_group, ETH_MULTICAST_RECV_BIT); + } + if (memcmp(pkt->dest, local_mac_addr, 6) == 0) { + xEventGroupSetBits(eth_event_group, ETH_UNICAST_RECV_BIT); + } + } + return ESP_OK; +}; + +TEST_CASE("recv_pkt", "[esp_eth]") +{ + EventGroupHandle_t eth_event_group = xEventGroupCreate(); + TEST_ASSERT(eth_event_group != NULL); + + eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); // apply default MAC configuration + esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config); // create MAC instance + TEST_ASSERT_NOT_NULL(mac); + eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); // apply default PHY configuration +#if defined(CONFIG_TARGET_ETH_PHY_DEVICE_IP101) + esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config); // create PHY instance +#elif defined(CONFIG_TARGET_ETH_PHY_DEVICE_LAN8720) + esp_eth_phy_t *phy = esp_eth_phy_new_lan8720(&phy_config); +#endif + TEST_ASSERT_NOT_NULL(phy); + esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy); // apply default driver configuration + esp_eth_handle_t eth_handle = NULL; // after driver installed, we will get the handle of the driver + TEST_ASSERT_EQUAL(ESP_OK, esp_eth_driver_install(&config, ð_handle)); // install driver + TEST_ASSERT_NOT_NULL(eth_handle); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create_default()); + TEST_ASSERT_EQUAL(ESP_OK, esp_eth_start(eth_handle)); // start Ethernet driver state machine + + TEST_ASSERT_EQUAL(ESP_OK, mac->get_addr(mac, local_mac_addr)); + // test app will parse the DUT MAC from this line of log output + printf("DUT MAC: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", local_mac_addr[0], local_mac_addr[1], local_mac_addr[2], + local_mac_addr[3], local_mac_addr[4], local_mac_addr[5]); + + TEST_ASSERT_EQUAL(ESP_OK, esp_eth_update_input_path(eth_handle, l2_packet_txrx_test_cb, eth_event_group)); + + EventBits_t bits = 0; + bits = xEventGroupWaitBits(eth_event_group, ETH_BROADCAST_RECV_BIT | ETH_MULTICAST_RECV_BIT | ETH_UNICAST_RECV_BIT, + true, true, pdMS_TO_TICKS(3000)); + TEST_ASSERT((bits & (ETH_BROADCAST_RECV_BIT | ETH_MULTICAST_RECV_BIT | ETH_UNICAST_RECV_BIT)) == + (ETH_BROADCAST_RECV_BIT | ETH_MULTICAST_RECV_BIT | ETH_UNICAST_RECV_BIT)); + + TEST_ASSERT_EQUAL(ESP_OK, esp_eth_stop(eth_handle)); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete_default()); + TEST_ASSERT_EQUAL(ESP_OK, esp_eth_driver_uninstall(eth_handle)); + phy->del(phy); + mac->del(mac); + vEventGroupDelete(eth_event_group); +} + +void app_main(void) +{ + unity_run_menu(); +} diff --git a/components/esp_eth/test_apps/sdkconfig.ci.ip101 b/components/esp_eth/test_apps/sdkconfig.ci.ip101 new file mode 100644 index 0000000000..a09d07030c --- /dev/null +++ b/components/esp_eth/test_apps/sdkconfig.ci.ip101 @@ -0,0 +1,7 @@ +CONFIG_IDF_TARGET="esp32" +CONFIG_UNITY_ENABLE_FIXTURE=y +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y +CONFIG_ETH_USE_ESP32_EMAC=y +CONFIG_ESP_TASK_WDT=n + +CONFIG_TARGET_ETH_PHY_DEVICE_IP101=y diff --git a/components/esp_eth/test_apps/sdkconfig.ci.lan8720 b/components/esp_eth/test_apps/sdkconfig.ci.lan8720 new file mode 100644 index 0000000000..a130a815fb --- /dev/null +++ b/components/esp_eth/test_apps/sdkconfig.ci.lan8720 @@ -0,0 +1,9 @@ +CONFIG_IDF_TARGET="esp32" +CONFIG_UNITY_ENABLE_FIXTURE=y +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y +CONFIG_ETH_USE_ESP32_EMAC=y +CONFIG_ESP_TASK_WDT=n + +CONFIG_TARGET_ETH_PHY_DEVICE_LAN8720=y +CONFIG_ETH_RMII_CLK_OUTPUT=y +CONFIG_ETH_RMII_CLK_OUT_GPIO=17 diff --git a/components/esp_event/CMakeLists.txt b/components/esp_event/CMakeLists.txt index 6384b8fe3c..c8cb9f92a6 100644 --- a/components/esp_event/CMakeLists.txt +++ b/components/esp_event/CMakeLists.txt @@ -1,17 +1,29 @@ -if(IDF_TARGET STREQUAL "esp32") - set(priv_requires esp_eth esp_timer) +idf_build_get_property(target IDF_TARGET) +set(priv_include_dirs "private_include") +set(priv_requires "") +set(requires "log" "esp_common" "freertos") +set(srcs "default_event_loop.c" + "esp_event.c" + "esp_event_private.c") + +if(${target} STREQUAL "linux") + list(APPEND requires "linux") + # Temporary fix until esp_system is available for linux, too + list(APPEND priv_include_dirs "$ENV{IDF_PATH}/tools/mocks/esp_system/include") else() - set(priv_requires esp_timer) + list(APPEND requires "esp_netif") + list(APPEND srcs "event_loop_legacy.c" "event_send.c") + if(${target} STREQUAL "esp32") + list(APPEND priv_requires esp_eth esp_timer) + else() + list(APPEND priv_requires esp_timer) + endif() endif() -idf_component_register(SRCS "default_event_loop.c" - "esp_event.c" - "esp_event_private.c" - "event_loop_legacy.c" - "event_send.c" +idf_component_register(SRCS ${srcs} INCLUDE_DIRS "include" - PRIV_INCLUDE_DIRS "private_include" - REQUIRES log esp_netif + PRIV_INCLUDE_DIRS ${priv_include_dirs} + REQUIRES ${requires} PRIV_REQUIRES ${priv_requires} LDFRAGMENTS linker.lf) diff --git a/components/esp_event/default_event_loop.c b/components/esp_event/default_event_loop.c index 93b37d2803..506cf8e56c 100644 --- a/components/esp_event/default_event_loop.c +++ b/components/esp_event/default_event_loop.c @@ -142,8 +142,9 @@ esp_err_t esp_event_loop_delete_default(void) return ESP_OK; } - +#if !CONFIG_IDF_TARGET_LINUX /* Include the code to forward legacy system_event_t events to the this default * event loop. */ #include "event_send_compat.inc" +#endif diff --git a/components/esp_event/host_test/esp_event_unit_test/CMakeLists.txt b/components/esp_event/host_test/esp_event_unit_test/CMakeLists.txt new file mode 100644 index 0000000000..415e0d64ca --- /dev/null +++ b/components/esp_event/host_test/esp_event_unit_test/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +set(COMPONENTS main) + +idf_build_set_property(COMPILE_DEFINITIONS "-DNO_DEBUG_STORAGE" APPEND) +list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/mocks/freertos/") +project(test_esp_event_host) diff --git a/components/esp_event/host_test/esp_event_unit_test/main/CMakeLists.txt b/components/esp_event/host_test/esp_event_unit_test/main/CMakeLists.txt new file mode 100644 index 0000000000..e118569643 --- /dev/null +++ b/components/esp_event/host_test/esp_event_unit_test/main/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "esp_event_test.cpp" + INCLUDE_DIRS "../../" $ENV{IDF_PATH}/tools/catch + REQUIRES esp_event cmock) diff --git a/components/esp_event/host_test/esp_event_unit_test/main/esp_event_test.cpp b/components/esp_event/host_test/esp_event_unit_test/main/esp_event_test.cpp new file mode 100644 index 0000000000..16c2c590c5 --- /dev/null +++ b/components/esp_event/host_test/esp_event_unit_test/main/esp_event_test.cpp @@ -0,0 +1,152 @@ +/* ESP Event Host-Based Test + + This 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. +*/ + +#define CATCH_CONFIG_MAIN + +#include +#include "esp_event.h" + +#include "catch.hpp" + +#include "fixtures.hpp" + +extern "C" { +#include "Mocktask.h" +#include "Mockqueue.h" +} + + +namespace { + +const uint32_t QUEUE_SIZE = 32; + +static UBaseType_t s_test_priority; + +static esp_event_loop_args_t test_event_get_default_loop_args(void) +{ + esp_event_loop_args_t loop_config = { + .queue_size = QUEUE_SIZE, // TODO: CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE from esp_system should be used + .task_name = "loop", + .task_priority = s_test_priority, + .task_stack_size = 2048, + .task_core_id = 0 + }; + + return loop_config; +} + +void dummy_handler(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { } + +} + +// TODO: IDF-2693, function definition just to satisfy linker, implement esp_common instead +const char *esp_err_to_name(esp_err_t code) { + return "test"; +} + +TEST_CASE("create an event loop with any NULL argument fails") +{ + MockQueue queue(CreateAnd::IGNORE); + MockMutex sem(CreateAnd::IGNORE); + MockTask task(CreateAnd::IGNORE); + esp_event_loop_handle_t loop; // with dedicated task + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + CHECK(ESP_ERR_INVALID_ARG == esp_event_loop_create(NULL, &loop)); + CHECK(ESP_ERR_INVALID_ARG == esp_event_loop_create(&loop_args, NULL)); +} + +TEST_CASE("test esp_event_loop_create create_queue_fails(void)") +{ + MockQueue queue(CreateAnd::FAIL); + MockMutex sem(CreateAnd::IGNORE); + MockTask task(CreateAnd::IGNORE); + esp_event_loop_handle_t loop; + + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + CHECK(ESP_ERR_NO_MEM == esp_event_loop_create(&loop_args, &loop)); +} + +TEST_CASE("test esp_event_loop_create create_mutex_fails(void)") +{ + MockQueue queue(CreateAnd::IGNORE); + MockMutex sem(CreateAnd::FAIL); + MockTask task(CreateAnd::IGNORE); + esp_event_loop_handle_t loop; + + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + CHECK(ESP_ERR_NO_MEM == esp_event_loop_create(&loop_args, &loop)); +} + +TEST_CASE("test esp_event_loop_create create_task_fails(void)") +{ + MockQueue queue(CreateAnd::IGNORE); + MockMutex sem(CreateAnd::IGNORE); + MockTask task(CreateAnd::FAIL); + esp_event_loop_handle_t loop; + + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + + CHECK(ESP_FAIL == esp_event_loop_create(&loop_args, &loop)); +} + +TEST_CASE("test esp_event_loop_create no_task(void)") +{ + MockQueue queue(CreateAnd::IGNORE); + MockMutex sem(CreateAnd::IGNORE); + xQueueTakeMutexRecursive_IgnoreAndReturn(0); + xQueueGiveMutexRecursive_IgnoreAndReturn(0); + xQueueReceive_IgnoreAndReturn(0); + esp_event_loop_handle_t loop = nullptr; + + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + loop_args.task_name = nullptr; + + CHECK(ESP_OK == esp_event_loop_create(&loop_args, &loop)); + CHECK(loop != nullptr); + + CHECK(ESP_OK == esp_event_loop_delete(loop)); + + xQueueReceive_StopIgnore(); + xQueueTakeMutexRecursive_StopIgnore(); + xQueueGiveMutexRecursive_StopIgnore(); +} + +TEST_CASE("test esp_event_loop_create with_task(void)") +{ + MockQueue queue(CreateAnd::IGNORE); + MockMutex sem(CreateAnd::IGNORE); + MockTask task(CreateAnd::SUCCEED); + xQueueTakeMutexRecursive_IgnoreAndReturn(0); + xQueueGiveMutexRecursive_IgnoreAndReturn(0); + xQueueReceive_IgnoreAndReturn(0); + esp_event_loop_handle_t loop = nullptr; + + esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); + loop_args.task_name = "test"; + + CHECK(ESP_OK == esp_event_loop_create(&loop_args, &loop)); + CHECK(loop != nullptr); + + CHECK(ESP_OK == esp_event_loop_delete(loop)); + + xQueueReceive_StopIgnore(); + xQueueTakeMutexRecursive_StopIgnore(); + xQueueGiveMutexRecursive_StopIgnore(); +} + +TEST_CASE("registering with ANY_BASE but specific ID fails") { + esp_event_loop_handle_t loop = reinterpret_cast(1); + CHECK(esp_event_handler_register_with(loop, + ESP_EVENT_ANY_BASE, + 47, + dummy_handler, + nullptr) == ESP_ERR_INVALID_ARG); +} diff --git a/components/esp_event/host_test/esp_event_unit_test/sdkconfig.defaults b/components/esp_event/host_test/esp_event_unit_test/sdkconfig.defaults new file mode 100644 index 0000000000..c3180f3309 --- /dev/null +++ b/components/esp_event/host_test/esp_event_unit_test/sdkconfig.defaults @@ -0,0 +1,4 @@ +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=n +CONFIG_IDF_TARGET="linux" +CONFIG_CXX_EXCEPTIONS=y +CONFIG_LOG_DEFAULT_LEVEL_NONE=y diff --git a/components/esp_event/host_test/fixtures.hpp b/components/esp_event/host_test/fixtures.hpp new file mode 100644 index 0000000000..1a8c4ed7b8 --- /dev/null +++ b/components/esp_event/host_test/fixtures.hpp @@ -0,0 +1,148 @@ +/* ESP Event Fixtures + + This 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_event.h" + +#include "catch.hpp" + +extern "C" { +#include "Mocktask.h" +#include "Mockqueue.h" +} + +/** + * Exception which is thrown if there is some internal cmock error which results in a + * longjump to the location of a TEST_PROTECT() call. + * + * @note This is a temporary solution until there is a better integration of CATCH into CMock. + * Note also that usually there will be a segfault when cmock fails a second time. + * This means paying attention to the first error message is crucial for removing errors. + */ +class CMockException : public std::exception { +public: + virtual ~CMockException() { } + + /** + * @return A reminder to look at the actual cmock log. + */ + virtual const char *what() const noexcept + { + return "CMock encountered an error. Look at the CMock log"; + } +}; + +/** + * Helper macro for setting up a test protect call for CMock. + * + * This macro should be used at the beginning of any test cases + * which use generated CMock mock functions. + * This is necessary because CMock uses longjmp which screws up C++ stacks and + * also the CATCH mechanisms. + * + * @note This is a temporary solution until there is a better integration of CATCH into CMock. + * Note also that usually there will be a segfault when cmock fails a second time. + * This means paying attention to the first error message is crucial for removing errors. + */ +#define CMOCK_SETUP() \ + do { \ + if (!TEST_PROTECT()) { \ + throw CMockException(); \ + } \ + } \ + while (0) + +struct CMockFix { + CMockFix() + { + CMOCK_SETUP(); + } + + ~CMockFix() + { + Mocktask_Verify(); + Mockqueue_Verify(); + } +}; + +enum class CreateAnd { + FAIL, + SUCCEED, + IGNORE +}; + +struct MockQueue : public CMockFix { + MockQueue (CreateAnd flags) : queue(reinterpret_cast(0xdeadbeef)) + { + if (flags == CreateAnd::FAIL) { + xQueueGenericCreate_ExpectAnyArgsAndReturn(nullptr); + } else if (flags == CreateAnd::IGNORE) { + xQueueGenericCreate_IgnoreAndReturn(queue); + vQueueDelete_Ignore(); + } else { + xQueueGenericCreate_ExpectAnyArgsAndReturn(queue); + vQueueDelete_Expect(queue); + } + } + + ~MockQueue() + { + xQueueGenericCreate_StopIgnore(); + vQueueDelete_StopIgnore(); + } + + QueueHandle_t queue; +}; + +struct MockMutex : public CMockFix { + MockMutex (CreateAnd flags) : sem(reinterpret_cast(0xdeadbeef)) + { + if (flags == CreateAnd::FAIL) { + xQueueCreateMutex_ExpectAnyArgsAndReturn(nullptr); + } else if (flags == CreateAnd::IGNORE) { + xQueueCreateMutex_IgnoreAndReturn(sem); + vQueueDelete_Ignore(); + } else { + xQueueCreateMutex_ExpectAnyArgsAndReturn(sem); + vQueueDelete_Expect(sem); + } + } + + ~MockMutex() + { + xQueueCreateMutex_StopIgnore(); + vQueueDelete_StopIgnore(); + } + + QueueHandle_t sem; +}; + +struct MockTask : public CMockFix { + MockTask (CreateAnd flags) : task((void*) 1) + { + if (flags == CreateAnd::FAIL) { + xTaskCreatePinnedToCore_ExpectAnyArgsAndReturn(pdFALSE); + } else if (flags == CreateAnd::IGNORE) { + xTaskCreatePinnedToCore_IgnoreAndReturn(pdTRUE); + xTaskCreatePinnedToCore_ReturnThruPtr_pvCreatedTask(&task); + vTaskDelete_Ignore(); + } else { + xTaskCreatePinnedToCore_ExpectAnyArgsAndReturn(pdTRUE); + xTaskCreatePinnedToCore_ReturnThruPtr_pvCreatedTask(&task); + vTaskDelete_Expect(task); + } + } + + ~MockTask() + { + xTaskCreatePinnedToCore_StopIgnore(); + vTaskDelete_StopIgnore(); + } + + TaskHandle_t task; +}; diff --git a/components/esp_event/include/esp_event.h b/components/esp_event/include/esp_event.h index 2d39422db5..2c069b0c68 100644 --- a/components/esp_event/include/esp_event.h +++ b/components/esp_event/include/esp_event.h @@ -23,7 +23,10 @@ #include "freertos/semphr.h" #include "esp_event_base.h" +// Legacy event loop not implemented on Linux target +#if !CONFIG_IDF_TARGET_LINUX #include "esp_event_legacy.h" +#endif #ifdef __cplusplus extern "C" { diff --git a/components/esp_event/private_include/esp_event_internal.h b/components/esp_event/private_include/esp_event_internal.h index 02403e0399..dd403f6d7c 100644 --- a/components/esp_event/private_include/esp_event_internal.h +++ b/components/esp_event/private_include/esp_event_internal.h @@ -15,6 +15,8 @@ #ifndef ESP_EVENT_INTERNAL_H_ #define ESP_EVENT_INTERNAL_H_ +#include "sys/queue.h" +#include #include "esp_event.h" #include "stdatomic.h" diff --git a/components/esp_event/private_include/esp_event_private.h b/components/esp_event/private_include/esp_event_private.h index fc434876a9..64ccf133c5 100644 --- a/components/esp_event/private_include/esp_event_private.h +++ b/components/esp_event/private_include/esp_event_private.h @@ -15,6 +15,7 @@ #ifndef ESP_EVENT_PRIVATE_H_ #define ESP_EVENT_PRIVATE_H_ +#include #include "esp_event.h" #ifdef __cplusplus diff --git a/components/esp_event/test/test_event.c b/components/esp_event/test/test_event.c index 1e1625e596..605cbc3381 100644 --- a/components/esp_event/test/test_event.c +++ b/components/esp_event/test/test_event.c @@ -306,14 +306,6 @@ static void test_teardown(void) #define TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER) // convert counter value to seconds #define TIMER_INTERVAL0_SEC (2.0) // sample test interval for the first timer -TEST_CASE("create and event loop with any NULL argument fails", "[event]") -{ - esp_event_loop_handle_t loop; // with dedicated task - esp_event_loop_args_t loop_args = test_event_get_default_loop_args(); - TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_event_loop_create(NULL, &loop)); - TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_event_loop_create(&loop_args, NULL)); -} - TEST_CASE("can create and delete event loops", "[event]") { /* this test aims to verify that: diff --git a/components/esp_gdbstub/Kconfig b/components/esp_gdbstub/Kconfig index 14e7d859c2..e380c34880 100644 --- a/components/esp_gdbstub/Kconfig +++ b/components/esp_gdbstub/Kconfig @@ -4,6 +4,7 @@ menu "GDB Stub" # menu in the target component. config ESP_GDBSTUB_ENABLED bool + select FREERTOS_ENABLE_TASK_SNAPSHOT config ESP_GDBSTUB_SUPPORT_TASKS bool "Enable listing FreeRTOS tasks through GDB Stub" diff --git a/components/esp_gdbstub/private_include/esp_gdbstub_common.h b/components/esp_gdbstub/private_include/esp_gdbstub_common.h index d9f261c9d2..b74f1e6c09 100644 --- a/components/esp_gdbstub/private_include/esp_gdbstub_common.h +++ b/components/esp_gdbstub/private_include/esp_gdbstub_common.h @@ -25,6 +25,7 @@ #ifdef CONFIG_ESP_GDBSTUB_SUPPORT_TASKS #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "freertos/task_snapshot.h" #endif // CONFIG_ESP_GDBSTUB_SUPPORT_TASKS /* Internal error codes used by the routines that parse the incoming gdb packet */ diff --git a/components/esp_hid/CMakeLists.txt b/components/esp_hid/CMakeLists.txt index 890d5f575c..5209d0ce3c 100644 --- a/components/esp_hid/CMakeLists.txt +++ b/components/esp_hid/CMakeLists.txt @@ -10,7 +10,8 @@ if(CONFIG_BT_ENABLED) list(APPEND srcs "src/ble_hidd.c" "src/ble_hidh.c" - "src/bt_hidh.c") + "src/bt_hidh.c" + "src/bt_hidd.c") endif() endif() diff --git a/components/esp_hid/include/esp_hid_common.h b/components/esp_hid/include/esp_hid_common.h index 9fd7a2c637..d7582cbc84 100644 --- a/components/esp_hid/include/esp_hid_common.h +++ b/components/esp_hid/include/esp_hid_common.h @@ -126,6 +126,21 @@ typedef enum { ESP_HID_COD_MIN_MAX } esp_hid_cod_min_t; +/* HID transaction Types */ +typedef enum { + ESP_HID_TRANS_HANDSHAKE = 0, + ESP_HID_TRANS_CONTROL = 1, + ESP_HID_TRANS_GET_REPORT = 4, + ESP_HID_TRANS_SET_REPORT = 5, + ESP_HID_TRANS_GET_PROTOCOL = 6, + ESP_HID_TRANS_SET_PROTOCOL = 7, + ESP_HID_TRANS_GET_IDLE = 8, + ESP_HID_TRANS_SET_IDLE = 9, + ESP_HID_TRANS_DATA = 10, + ESP_HID_TRANS_DATAC = 11, + ESP_HID_TRANS_MAX +} esp_hid_trans_type_t; + /** * @brief HID report item structure */ diff --git a/components/esp_hid/include/esp_hidd.h b/components/esp_hid/include/esp_hidd.h index ef596c6b2b..3e1bfc2c06 100644 --- a/components/esp_hid/include/esp_hidd.h +++ b/components/esp_hid/include/esp_hidd.h @@ -53,11 +53,28 @@ typedef struct esp_hidd_dev_s esp_hidd_dev_t; * @brief HIDD callback parameters union */ typedef union { + /** + * @brief ESP_HIDD_START_EVENT + * @note Used only for Classic Bluetooth. + */ + struct { + esp_err_t status; /*!< HID device operation status */ + } start; /*!< HID callback param of ESP_HIDD_START_EVENT */ + + /** + * @brief ESP_HIDD_STOP_EVENT + * @note Used only for Classic Bluetooth. + */ + struct { + esp_err_t status; /*!< HID device operation status */ + } stop; /*!< HID callback param of ESP_HIDD_STOP_EVENT */ + /** * @brief ESP_HIDD_CONNECT_EVENT */ struct { esp_hidd_dev_t *dev; /*!< HID device structure */ + esp_err_t status; /*!< HID device operation status, used only for Classic Bluetooth */ } connect; /*!< HID callback param of ESP_HIDD_CONNECT_EVENT */ /** @@ -66,6 +83,7 @@ typedef union { struct { esp_hidd_dev_t *dev; /*!< HID device structure */ int reason; /*!< Indicate the reason of disconnection */ + esp_err_t status; /*!< HID device operation status, used only for Classic Bluetooth */ } disconnect; /*!< HID callback param of ESP_HIDD_DISCONNECT_EVENT */ /** @@ -90,6 +108,8 @@ typedef union { uint16_t length; /*!< data length */ uint8_t *data; /*!< The pointer to the data */ uint8_t map_index; /*!< HID config report map index */ + uint8_t trans_type; /*!< HID device feature transaction type, used only for Classic Bluetooth */ + uint8_t report_type; /*!< HID device feature report type, used only for Classic Bluetooth */ } feature; /*!< HID callback param of ESP_HIDD_FEATURE_EVENT */ /** diff --git a/components/esp_hid/include/esp_hidh.h b/components/esp_hid/include/esp_hidh.h index d3d1002103..d49f76e680 100644 --- a/components/esp_hid/include/esp_hidh.h +++ b/components/esp_hid/include/esp_hidh.h @@ -42,6 +42,8 @@ typedef enum { ESP_HIDH_INPUT_EVENT, /*!< Received HID device INPUT report */ ESP_HIDH_FEATURE_EVENT, /*!< Received HID device FEATURE report */ ESP_HIDH_CLOSE_EVENT, /*!< HID device closed */ + ESP_HIDH_START_EVENT, /*!< HID host stack started, used only for Classic Bluetooth */ + ESP_HIDH_STOP_EVENT, /*!< HID host stack stopped, used only for Classic Bluetooth */ ESP_HIDH_MAX_EVENT, /*!< HID events end marker */ } esp_hidh_event_t; @@ -49,11 +51,28 @@ typedef enum { * @brief HIDH callback parameters union */ typedef union { + /** + * @brief ESP_HIDH_START_EVENT + * @note Used only for Classic Bluetooth. + */ + struct { + esp_err_t status; /*!< HID host operation status */ + } start; /*!< HID callback param of ESP_HIDH_START_EVENT */ + + /** + * @brief ESP_HIDH_STOP_EVENT + * @note Used only for Classic Bluetooth. + */ + struct { + esp_err_t status; /*!< HID host operation status */ + } stop; /*!< HID callback param of ESP_HIDH_STOP_EVENT */ + /** * @brief ESP_HIDH_OPEN_EVENT */ struct { esp_hidh_dev_t *dev; /*!< HID Remote bluetooth device */ + esp_err_t status; /*!< HID host operation status, used only for Classic Bluetooth */ } open; /*!< HID callback param of ESP_HIDH_OPEN_EVENT */ /** @@ -62,6 +81,7 @@ typedef union { struct { esp_hidh_dev_t *dev; /*!< HID Remote bluetooth device. */ int reason; /*!< Reason why the connection was closed. BLE Only */ + esp_err_t status; /*!< HID host operation status, used only for Classic Bluetooth */ } close; /*!< HID callback param of ESP_HIDH_CLOSE_EVENT */ /** @@ -70,6 +90,7 @@ typedef union { struct { esp_hidh_dev_t *dev; /*!< HID Remote bluetooth device */ uint8_t level; /*!< Battery Level (0-100%) */ + esp_err_t status; /*!< HID host operation status */ } battery; /*!< HID callback param of ESP_HIDH_BATTERY_EVENT */ /** @@ -80,7 +101,7 @@ typedef union { esp_hid_usage_t usage; /*!< HID report usage */ uint16_t report_id; /*!< HID report index */ uint16_t length; /*!< HID data length */ - uint8_t *data; /*!< The pointer to the HID data */ + uint8_t *data; /*!< The pointer to the HID data */ uint8_t map_index; /*!< HID report map index */ } input; /*!< HID callback param of ESP_HIDH_INPUT_EVENT */ @@ -92,8 +113,10 @@ typedef union { esp_hid_usage_t usage; /*!< HID report usage */ uint16_t report_id; /*!< HID report index */ uint16_t length; /*!< HID data length */ - uint8_t *data; /*!< The pointer to the HID data */ + uint8_t *data; /*!< The pointer to the HID data */ uint8_t map_index; /*!< HID report map index */ + esp_err_t status; /*!< HID host operation status, used only for Classic Bluetooth */ + esp_hid_trans_type_t trans_type; /*!< HID host feature transaction type, used only for Classic Bluetooth */ } feature; /*!< HID callback param of ESP_HIDH_FEATURE_EVENT */ } esp_hidh_event_data_t; @@ -101,6 +124,7 @@ typedef union { typedef struct { esp_event_handler_t callback; uint16_t event_stack_size; + void *callback_arg; } esp_hidh_config_t; /** @@ -136,6 +160,14 @@ esp_err_t esp_hidh_dev_close(esp_hidh_dev_t *dev); */ esp_err_t esp_hidh_dev_free(esp_hidh_dev_t *dev); +/** + * @brief Check if the device still exists. + * @param dev : pointer to the device + * + * @return: true if exists + */ +bool esp_hidh_dev_exists(esp_hidh_dev_t *dev); + /** * @brief Send an OUTPUT report to the device * @param dev : pointer to the device @@ -173,6 +205,79 @@ esp_err_t esp_hidh_dev_feature_set(esp_hidh_dev_t *dev, size_t map_index, size_t */ esp_err_t esp_hidh_dev_feature_get(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, size_t max_len, uint8_t *data, size_t *length); +/** + * @brief Set_Report command. + * @note For now, this function used only for Classic Bluetooth. + * + * @param dev : pointer to the device + * @param map_index : index of the device report map + * @param report_id : id of the HID FEATURE report + * @param report_type : report type, defines in `esp_hid_common.h` + * @param data : pointer to the data to send + * @param length : length of the data to send + * + * @return: ESP_OK on success + */ +esp_err_t esp_hidh_dev_set_report(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, int report_type, + uint8_t *data, size_t length); + +/** + * @brief Get_Report command. + * @note For now, this function used only for Classic Bluetooth. + * + * @param dev : pointer to the device + * @param map_index : index of the device report map + * @param report_id : id of the HID FEATURE report + * @param report_type : report type, defines in `esp_hid_common.h` + * @param max_len : size of the buffer that will hold the data + * + * @return: ESP_OK on success + */ +esp_err_t esp_hidh_dev_get_report(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, int report_type, + size_t max_len); + +/** + * @brief Get_Idle Command. + * @note For now, this function used only for Classic Bluetooth. + * + * @param dev : pointer to the device + * + * @return: ESP_OK on success + */ +esp_err_t esp_hidh_dev_get_idle(esp_hidh_dev_t *dev); + +/** + * @brief Set_Idle Command. + * @note For now, this function used only for Classic Bluetooth. + * + * @param dev : pointer to the device + * @param idle_time : idle_time + * + * @return: ESP_OK on success + */ +esp_err_t esp_hidh_dev_set_idle(esp_hidh_dev_t *dev, uint8_t idle_time); + +/** + * @brief Get_Protocol Command. + * @note For now, this function used only for Classic Bluetooth. + * + * @param dev : pointer to the device + * + * @return: ESP_OK on success + */ +esp_err_t esp_hidh_dev_get_protocol(esp_hidh_dev_t *dev); + +/** + * @brief Set_Protocol Command. + * @note For now, this function used only for Classic Bluetooth. + * + * @param dev : pointer to the device + * @param protocol_mode : protocol_mode + * + * @return: ESP_OK on success + */ +esp_err_t esp_hidh_dev_set_protocol(esp_hidh_dev_t *dev, uint8_t protocol_mode); + /** * @brief Dump the properties of HID Device to UART * @param dev : pointer to the HID Device diff --git a/components/soc/esp32s3/include/soc/i2s_caps.h b/components/esp_hid/private/bt_hidd.h similarity index 56% rename from components/soc/esp32s3/include/soc/i2s_caps.h rename to components/esp_hid/private/bt_hidd.h index cd21be8893..0ff874aea6 100644 --- a/components/soc/esp32s3/include/soc/i2s_caps.h +++ b/components/esp_hid/private/bt_hidd.h @@ -1,9 +1,9 @@ -// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD +// Copyright 2017-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 @@ -14,10 +14,20 @@ #pragma once -#define SOC_I2S_APLL_MIN_FREQ (250000000) -#define SOC_I2S_APLL_MAX_FREQ (500000000) -#define SOC_I2S_APLL_MIN_RATE (10675) //in Hz, I2S Clock rate limited by hardware -#define SOC_I2S_MAX_BUFFER_SIZE (4 * 1024 * 1024) //the maximum RAM can be allocated +#include "esp_hidd.h" +#include "esp_err.h" +#include "esp_hid_common.h" -// ESP32-S3 have 1 I2S -#define SOC_I2S_NUM (1) +#ifdef __cplusplus +extern "C" { +#endif + +#if CONFIG_BT_HID_DEVICE_ENABLED + +esp_err_t esp_bt_hidd_dev_init(esp_hidd_dev_t *dev, const esp_hid_device_config_t *config, esp_event_handler_t callback); + +#endif /* CONFIG_BT_HID_DEVICE_ENABLED */ + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hid/private/esp_bt_hh_api.h b/components/esp_hid/private/esp_bt_hh_api.h deleted file mode 100644 index 0d438c28b3..0000000000 --- a/components/esp_hid/private/esp_bt_hh_api.h +++ /dev/null @@ -1,367 +0,0 @@ -/****************************************************************************** - * - * Copyright (C) 2005-2012 Broadcom Corporation - * - * 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. - * - ******************************************************************************/ - -#ifndef _ESP_BT_HH_API_H_ -#define _ESP_BT_HH_API_H_ - -#include "esp_err.h" -#include "esp_bt_defs.h" - -/***************************************************************************** -** Constants and Type Definitions -*****************************************************************************/ -#ifndef BTA_HH_DEBUG -#define BTA_HH_DEBUG TRUE -#endif - -#ifndef BTA_HH_SSR_MAX_LATENCY_DEF -#define BTA_HH_SSR_MAX_LATENCY_DEF 800 /* 500 ms*/ -#endif - -#ifndef BTA_HH_SSR_MIN_TOUT_DEF -#define BTA_HH_SSR_MIN_TOUT_DEF 2 -#endif - -/* defined the minimum offset */ -#define BTA_HH_MIN_OFFSET L2CAP_MIN_OFFSET+1 - -/* HID_HOST_MAX_DEVICES can not exceed 15 for th design of BTA HH */ -#define BTA_HH_IDX_INVALID 0xff -#define BTA_HH_MAX_KNOWN HID_HOST_MAX_DEVICES - -/* Security Service Levels [bit mask] (BTM_SetSecurityLevel) - ** Encryption should not be used without authentication - */ -#define BTM_SEC_NONE 0x0000 /* Nothing required */ -#define BTM_SEC_IN_AUTHORIZE 0x0001 /* Inbound call requires authorization */ -#define BTM_SEC_IN_AUTHENTICATE 0x0002 /* Inbound call requires authentication */ -#define BTM_SEC_IN_ENCRYPT 0x0004 /* Inbound call requires encryption */ -#define BTM_SEC_OUT_AUTHORIZE 0x0008 /* Outbound call requires authorization */ -#define BTM_SEC_OUT_AUTHENTICATE 0x0010 /* Outbound call requires authentication */ -#define BTM_SEC_OUT_ENCRYPT 0x0020 /* Outbound call requires encryption */ -#define BTM_SEC_MODE4_LEVEL4 0x0040 /* Secure Connections Only Mode */ -#define BTM_SEC_FORCE_MASTER 0x0100 /* Need to switch connection to be master */ -#define BTM_SEC_ATTEMPT_MASTER 0x0200 /* Try to switch connection to be master */ -#define BTM_SEC_FORCE_SLAVE 0x0400 /* Need to switch connection to be master */ -#define BTM_SEC_ATTEMPT_SLAVE 0x0800 /* Try to switch connection to be slave */ -#define BTM_SEC_IN_MITM 0x1000 /* inbound Do man in the middle protection */ -#define BTM_SEC_OUT_MITM 0x2000 /* outbound Do man in the middle protection */ -#define BTM_SEC_IN_MIN_16_DIGIT_PIN 0x4000 /* enforce a minimum of 16 digit for sec mode 2 */ - -/* Security Setting Mask */ -#define BTA_SEC_NONE BTM_SEC_NONE /* No security. */ -#define BTA_SEC_AUTHORIZE (BTM_SEC_IN_AUTHORIZE ) /* Authorization required (only needed for out going connection )*/ -#define BTA_SEC_AUTHENTICATE (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_OUT_AUTHENTICATE) /* Authentication required. */ -#define BTA_SEC_ENCRYPT (BTM_SEC_IN_ENCRYPT | BTM_SEC_OUT_ENCRYPT) /* Encryption required. */ -#define BTA_SEC_MODE4_LEVEL4 (BTM_SEC_MODE4_LEVEL4) /* Mode 4 level 4 service, i.e. incoming/outgoing MITM and P-256 encryption */ -#define BTA_SEC_MITM (BTM_SEC_IN_MITM | BTM_SEC_OUT_MITM) /* Man-In-The_Middle protection */ -#define BTA_SEC_IN_16_DIGITS (BTM_SEC_IN_MIN_16_DIGIT_PIN) /* Min 16 digit for pin code */ - -#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE) -/* GATT_MAX_PHY_CHANNEL can not exceed 14 for the design of BTA HH */ -#define BTA_HH_LE_MAX_KNOWN GATT_MAX_PHY_CHANNEL -#define BTA_HH_MAX_DEVICE (HID_HOST_MAX_DEVICES + GATT_MAX_PHY_CHANNEL) -#else -#define BTA_HH_MAX_DEVICE HID_HOST_MAX_DEVICES -#endif -/* invalid device handle */ -#define BTA_HH_INVALID_HANDLE 0xff - -#define BTA_HH_SSR_PARAM_INVALID HID_SSR_PARAM_INVALID - -/* id DI is not existing in remote device, vendor_id in tBTA_HH_DEV_DSCP_INFO will be set to 0xffff */ -#define BTA_HH_VENDOR_ID_INVALID 0xffff - -/* application ID(none-zero) for each type of device */ -#define BTA_HH_APP_ID_MI 1 -#define BTA_HH_APP_ID_KB 2 -#define BTA_HH_APP_ID_RMC 3 -#define BTA_HH_APP_ID_3DSG 4 -#define BTA_HH_APP_ID_JOY 5 -#define BTA_HH_APP_ID_GPAD 6 -#define BTA_HH_APP_ID_LE 0xff - -/* type of devices, bit mask */ -#define BTA_HH_DEVT_UNKNOWN 0x00 -#define BTA_HH_DEVT_JOS 0x01 /* joy stick */ -#define BTA_HH_DEVT_GPD 0x02 /* game pad */ -#define BTA_HH_DEVT_RMC 0x03 /* remote control */ -#define BTA_HH_DEVT_SED 0x04 /* sensing device */ -#define BTA_HH_DEVT_DGT 0x05 /* Digitizer tablet */ -#define BTA_HH_DEVT_CDR 0x06 /* card reader */ -#define BTA_HH_DEVT_KBD 0x10 /* keyboard */ -#define BTA_HH_DEVT_MIC 0x20 /* pointing device */ -#define BTA_HH_DEVT_COM 0x30 /* Combo keyboard/pointing */ -#define BTA_HH_DEVT_OTHER 0x80 -typedef uint8_t tBTA_HH_DEVT; - - -/* BTA HID Host callback events */ -#define BTA_HH_ENABLE_EVT 0 /* HH enabled */ -#define BTA_HH_DISABLE_EVT 1 /* HH disabled */ -#define BTA_HH_OPEN_EVT 2 /* connection opened */ -#define BTA_HH_CLOSE_EVT 3 /* connection closed */ -#define BTA_HH_GET_RPT_EVT 4 /* BTA_HhGetReport callback */ -#define BTA_HH_SET_RPT_EVT 5 /* BTA_HhSetReport callback */ -#define BTA_HH_GET_PROTO_EVT 6 /* BTA_GetProtoMode callback */ -#define BTA_HH_SET_PROTO_EVT 7 /* BTA_HhSetProtoMode callback */ -#define BTA_HH_GET_IDLE_EVT 8 /* BTA_HhGetIdle comes callback */ -#define BTA_HH_SET_IDLE_EVT 9 /* BTA_HhSetIdle finish callback */ -#define BTA_HH_GET_DSCP_EVT 10 /* Get report descriptor */ -#define BTA_HH_ADD_DEV_EVT 11 /* Add Device callback */ -#define BTA_HH_RMV_DEV_EVT 12 /* remove device finished */ -#define BTA_HH_VC_UNPLUG_EVT 13 /* virtually unplugged */ -#define BTA_HH_DATA_EVT 15 -#define BTA_HH_API_ERR_EVT 16 /* API error is caught */ -#define BTA_HH_UPDATE_SCPP_EVT 17 /* update scan paramter complete */ -typedef uint16_t tBTA_HH_EVT; - -/* type of protocol mode */ -#define BTA_HH_PROTO_RPT_MODE (0x00) -#define BTA_HH_PROTO_BOOT_MODE (0x01) -#define BTA_HH_PROTO_UNKNOWN (0xff) -typedef uint8_t tBTA_HH_PROTO_MODE; - -#define BTA_HH_VIRTUAL_CABLE HID_VIRTUAL_CABLE -#define BTA_HH_NORMALLY_CONNECTABLE HID_NORMALLY_CONNECTABLE -#define BTA_HH_RECONN_INIT HID_RECONN_INIT -#define BTA_HH_SDP_DISABLE HID_SDP_DISABLE -#define BTA_HH_BATTERY_POWER HID_BATTERY_POWER -#define BTA_HH_REMOTE_WAKE HID_REMOTE_WAKE -#define BTA_HH_SUP_TOUT_AVLBL HID_SUP_TOUT_AVLBL -#define BTA_HH_SEC_REQUIRED HID_SEC_REQUIRED -typedef uint16_t tBTA_HH_ATTR_MASK; - -enum { - BTA_HH_OK, - BTA_HH_HS_HID_NOT_READY, /* handshake error : device not ready */ - BTA_HH_HS_INVALID_RPT_ID, /* handshake error : invalid report ID */ - BTA_HH_HS_TRANS_NOT_SPT, /* handshake error : transaction not spt */ - BTA_HH_HS_INVALID_PARAM, /* handshake error : invalid paremter */ - BTA_HH_HS_ERROR, /* handshake error : unspecified HS error */ - BTA_HH_ERR, /* general BTA HH error */ - BTA_HH_ERR_SDP, /* SDP error */ - BTA_HH_ERR_PROTO, /* SET_Protocol error, only used in BTA_HH_OPEN_EVT callback */ - BTA_HH_ERR_DB_FULL, /* device database full error, used in BTA_HH_OPEN_EVT/BTA_HH_ADD_DEV_EVT */ - BTA_HH_ERR_TOD_UNSPT, /* type of device not supported */ - BTA_HH_ERR_NO_RES, /* out of system resources */ - BTA_HH_ERR_AUTH_FAILED, /* authentication fail */ - BTA_HH_ERR_HDL, - BTA_HH_ERR_SEC -}; -typedef uint8_t tBTA_HH_STATUS; - -enum { - BTA_HH_RPTT_RESRV, /* reserved */ - BTA_HH_RPTT_INPUT, /* input report */ - BTA_HH_RPTT_OUTPUT, /* output report */ - BTA_HH_RPTT_FEATURE /* feature report */ -}; -typedef uint8_t tBTA_HH_RPT_TYPE; - -/* HID_CONTROL operation code used in BTA_HhSendCtrl() -*/ -enum { - BTA_HH_CTRL_NOP = 0, /* mapping from BTE */ - BTA_HH_CTRL_HARD_RESET, /* hard reset */ - BTA_HH_CTRL_SOFT_RESET, /* soft reset */ - BTA_HH_CTRL_SUSPEND, /* enter suspend */ - BTA_HH_CTRL_EXIT_SUSPEND, /* exit suspend */ - BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG /* virtual unplug */ -}; -typedef uint8_t tBTA_HH_TRANS_CTRL_TYPE; - - -typedef struct desc_info { - uint16_t dl_len; - uint8_t *dsc_list; -} tBTA_HH_DEV_DESCR; - -/* Define the header of each buffer used in the Bluetooth stack. */ -typedef struct { - uint16_t event; - uint16_t len; - uint16_t offset; - uint16_t layer_specific; - uint8_t data[]; -} BT_HDR; - -#define BT_HDR_SIZE (sizeof (BT_HDR)) - -/* callback event data for BTA_HH_OPEN_EVT */ -typedef struct { - esp_bd_addr_t bda; /* HID device bd address */ - tBTA_HH_STATUS status; /* operation status */ - uint8_t handle; /* device handle */ - -} tBTA_HH_CONN; - -typedef tBTA_HH_CONN tBTA_HH_DEV_INFO; - -/* callback event data */ -typedef struct { - tBTA_HH_STATUS status; /* operation status */ - uint8_t handle; /* device handle */ -} tBTA_HH_CBDATA; - -/* report descriptor information */ -typedef struct { - uint16_t vendor_id; /* vendor ID */ - uint16_t product_id; /* product ID */ - uint16_t version; /* version */ - uint16_t ssr_max_latency;/* SSR max latency, BTA_HH_SSR_PARAM_INVALID if unknown */ - uint16_t ssr_min_tout; /* SSR min timeout, BTA_HH_SSR_PARAM_INVALID if unknown */ - uint8_t ctry_code; /*Country Code.*/ - tBTA_HH_DEV_DESCR descriptor; -} tBTA_HH_DEV_DSCP_INFO; - -/* handshake data */ -typedef struct { - tBTA_HH_STATUS status; /* handshake status */ - uint8_t handle; /* device handle */ - union { - tBTA_HH_PROTO_MODE proto_mode; /* GET_PROTO_EVT :protocol mode */ - BT_HDR *p_rpt_data;/* GET_RPT_EVT : report data */ - uint8_t idle_rate; /* GET_IDLE_EVT : idle rate */ - } rsp_data; - -} tBTA_HH_HSDATA; - -/* union of data associated with HD callback */ -typedef union { - tBTA_HH_DEV_INFO dev_info; /* BTA_HH_ADD_DEV_EVT, BTA_HH_RMV_DEV_EVT */ - tBTA_HH_CONN conn; /* BTA_HH_OPEN_EVT */ - tBTA_HH_CBDATA dev_status; /* BTA_HH_CLOSE_EVT, - BTA_HH_SET_PROTO_EVT - BTA_HH_SET_RPT_EVT - BTA_HH_SET_IDLE_EVT - BTA_HH_UPDATE_SCPP_EVT */ - - tBTA_HH_STATUS status; /* BTA_HH_ENABLE_EVT */ - tBTA_HH_DEV_DSCP_INFO dscp_info; /* BTA_HH_GET_DSCP_EVT */ - tBTA_HH_HSDATA hs_data; /* GET_ transaction callback - BTA_HH_GET_RPT_EVT - BTA_HH_GET_PROTO_EVT - BTA_HH_GET_IDLE_EVT */ -} tBTA_HH; - -/* BTA HH callback function */ -typedef void (tBTA_HH_CBACK) (tBTA_HH_EVT event, tBTA_HH *p_data); - -/***************************************************************************** -** External Function Declarations -*****************************************************************************/ -#ifdef __cplusplus -extern "C" -{ -#endif - -/* This function enable HID host and registers HID-Host with lower layers.*/ -extern void BTA_HhEnable(uint16_t sec_mask, tBTA_HH_CBACK *p_cback); - -/* This function is called when the host is about power down. */ -extern void BTA_HhDisable(void); - -/* This function is called to start an inquiry and read SDP record of responding devices; connect to a device if only one active HID device is found. */ -extern void BTA_HhOpen (esp_bd_addr_t dev_bda, uint8_t bd_type, tBTA_HH_PROTO_MODE mode, uint16_t sec_mask); - -/* This function disconnects the device. */ -extern void BTA_HhClose(uint8_t dev_handle); - -/* This function set the protocol mode at specified HID handle */ -extern void BTA_HhSetProtoMode(uint8_t handle, tBTA_HH_PROTO_MODE t_type); - -/* This function get the protocol mode of a specified HID device. */ -extern void BTA_HhGetProtoMode(uint8_t dev_handle); - -/* send SET_REPORT to device. */ -extern void BTA_HhSetReport(uint8_t dev_handle, tBTA_HH_RPT_TYPE r_type, BT_HDR *p_data); - -/* Send a GET_REPORT to HID device. */ -extern void BTA_HhGetReport(uint8_t dev_handle, tBTA_HH_RPT_TYPE r_type, uint8_t rpt_id, uint16_t buf_size); - -/* send SET_IDLE to device. */ -extern void BTA_HhSetIdle(uint8_t dev_handle, uint16_t idle_rate); - -/* Send a GET_IDLE to HID device. */ -extern void BTA_HhGetIdle(uint8_t dev_handle); - -/* Send HID_CONTROL request to a HID device. */ -extern void BTA_HhSendCtrl(uint8_t dev_handle, tBTA_HH_TRANS_CTRL_TYPE c_type); - -/* Send DATA transaction to a HID device. */ -extern void BTA_HhSendData(uint8_t dev_handle, esp_bd_addr_t dev_bda, BT_HDR *p_buf); - -/* Get report descriptor of the device */ -extern void BTA_HhGetDscpInfo(uint8_t dev_handle); - -/* Add a virtually cabled device into HID-Host device list to manage and assign a device handle for future API call, host applciation call this API at start-up to initialize its virtually cabled devices. */ -extern void BTA_HhAddDev(esp_bd_addr_t bda, tBTA_HH_ATTR_MASK attr_mask, uint8_t sub_class, uint8_t app_id, tBTA_HH_DEV_DSCP_INFO dscp_info); - -/* Remove a device from the HID host devices list. */ -extern void BTA_HhRemoveDev(uint8_t dev_handle ); - -enum { - BTA_HH_MOD_CTRL_KEY, - BTA_HH_MOD_SHFT_KEY, - BTA_HH_MOD_ALT_KEY, - BTA_HH_MOD_GUI_KEY, - BTA_HH_MOD_MAX_KEY -}; - -/* parsed boot mode keyboard report */ -typedef struct { - uint8_t this_char[6]; /* virtual key code */ - bool mod_key[BTA_HH_MOD_MAX_KEY];/* ctrl, shift, Alt, GUI */ - bool caps_lock; /* is caps locked */ - bool num_lock; /* is Num key pressed */ -} tBTA_HH_KEYBD_RPT; - -/* parsed boot mode mouse report */ -typedef struct { - uint8_t mouse_button; /* mouse button is clicked */ - int8_t delta_x; /* displacement x */ - int8_t delta_y; /* displacement y */ -} tBTA_HH_MICE_RPT; - -enum { - BTA_HH_KEYBD_RPT_ID = 1, - BTA_HH_MOUSE_RPT_ID -}; -typedef uint8_t tBTA_HH_BOOT_RPT_ID; - -/* parsed Boot report */ -typedef struct { - tBTA_HH_BOOT_RPT_ID dev_type; /* type of device report */ - union { - tBTA_HH_KEYBD_RPT keybd_rpt; /* keyboard report */ - tBTA_HH_MICE_RPT mice_rpt; /* mouse report */ - } data_rpt; -} tBTA_HH_BOOT_RPT; - -/* This utility function parse a boot mode report. */ -extern void BTA_HhParseBootRpt(tBTA_HH_BOOT_RPT *p_data, uint8_t *p_report, uint16_t report_len); - - - - -#ifdef __cplusplus -} -#endif - -#endif /* _ESP_BT_HH_API_H_ */ diff --git a/components/esp_hid/private/esp_hidd_private.h b/components/esp_hid/private/esp_hidd_private.h index 544fd9b58a..abb76efc11 100644 --- a/components/esp_hid/private/esp_hidd_private.h +++ b/components/esp_hid/private/esp_hidd_private.h @@ -22,12 +22,37 @@ extern "C" { #endif +typedef union { + struct { + uint16_t notify_enable : 1; + uint16_t indicate_enable : 1; + uint16_t reserved : 14; + }; + uint16_t value; +} hidd_le_ccc_value_t; + +typedef struct { + uint8_t map_index; // the index of the report map + uint8_t report_id; // the id of the report + uint8_t report_type; // input, output or feature + uint8_t protocol_mode; // boot or report + esp_hid_usage_t usage; // generic, keyboard, mouse, joystick or gamepad + uint16_t value_len; // maximum len of value by report map + // used by gatts + uint8_t index; // index of the value in the gatts attr db + uint16_t handle; // obtained once all attributes are registered + uint16_t ccc_handle; // obtained once all attributes are registered + hidd_le_ccc_value_t ccc; // notifications and/or indications enabled +} hidd_report_item_t; + struct esp_hidd_dev_s { void *dev; esp_hid_transport_t transport; bool (*connected) (void *dev); esp_err_t (*deinit) (void *dev); + esp_err_t (*disconnect) (void *dev); + esp_err_t (*virtual_unplug) (void *dev); esp_err_t (*battery_set) (void *dev, uint8_t level); esp_err_t (*input_set) (void *dev, size_t map_index, size_t report_id, uint8_t *data, size_t length); esp_err_t (*feature_set) (void *dev, size_t map_index, size_t report_id, uint8_t *data, size_t length); @@ -37,6 +62,9 @@ struct esp_hidd_dev_s { typedef struct esp_hidd_dev_s esp_hidd_dev_t; +void esp_hidd_process_event_data_handler(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id, + void *event_data); + #ifdef __cplusplus } #endif diff --git a/components/esp_hid/private/esp_hidh_private.h b/components/esp_hid/private/esp_hidh_private.h index 1cd5e50605..1e5ac5afbe 100644 --- a/components/esp_hid/private/esp_hidh_private.h +++ b/components/esp_hid/private/esp_hidh_private.h @@ -24,6 +24,7 @@ #include "freertos/semphr.h" #include "esp_event.h" #include "sys/queue.h" +#include "esp_timer.h" #ifdef __cplusplus extern "C" { @@ -54,10 +55,18 @@ struct esp_hidh_dev_s { esp_hid_device_config_t config; esp_hid_usage_t usage; - esp_hid_transport_t transport; //BT, BLE or USB - bool connected; //we have all required data to communicate - bool opened; //we opened the device manually, else the device connected to us - int status; //status of the last command + esp_hid_transport_t transport; //BT, BLE or USB + esp_hid_trans_type_t trans_type; //indicate what transaction is going on, new transaction only be allowed after the previous done + esp_timer_handle_t trans_timer; //transactiion timer + uint8_t report_type; //Get_Report tansaction report_type + uint8_t report_id; //Get_Report tansaction report_id + uint8_t protocol_mode; //device protocol mode + bool connected; //we have all required data to communicate + bool opened; //we opened the device manually, else the device connected to us + bool added; //If lower layer has added the device + bool is_orig; //If host initiate the connection + bool in_use; //If false, it will be deleted from the devices list. + int status; //status of the last command size_t reports_len; esp_hidh_dev_report_t *reports; @@ -66,10 +75,16 @@ struct esp_hidh_dev_s { size_t tmp_len; xSemaphoreHandle semaphore; + xSemaphoreHandle mutex; esp_err_t (*close) (esp_hidh_dev_t *dev); esp_err_t (*report_write) (esp_hidh_dev_t *dev, size_t map_index, size_t report_id, int report_type, uint8_t *data, size_t len); esp_err_t (*report_read) (esp_hidh_dev_t *dev, size_t map_index, size_t report_id, int report_type, size_t max_length, uint8_t *value, size_t *value_len); + esp_err_t (*set_report) (esp_hidh_dev_t *dev, size_t map_index, size_t report_id, int report_type, uint8_t *data, size_t len); + esp_err_t (*get_idle) (esp_hidh_dev_t *dev); + esp_err_t (*set_idle) (esp_hidh_dev_t *dev, uint8_t idle_time); + esp_err_t (*get_protocol) (esp_hidh_dev_t *dev); + esp_err_t (*set_protocol) (esp_hidh_dev_t *dev, uint8_t protocol_mode); void (*dump) (esp_hidh_dev_t *dev, FILE *fp); #if CONFIG_BLUEDROID_ENABLED @@ -80,10 +95,10 @@ struct esp_hidh_dev_s { #if CONFIG_BT_HID_HOST_ENABLED struct { esp_bt_cod_t cod; - int handle; - uint8_t sub_class; - uint8_t app_id; - uint16_t attr_mask; + uint8_t handle; + // uint8_t sub_class; + // uint8_t app_id; + // uint16_t attr_mask; } bt; #endif /* CONFIG_BT_HID_HOST_ENABLED */ #if CONFIG_GATTC_ENABLE @@ -105,15 +120,24 @@ esp_hidh_dev_t *esp_hidh_dev_malloc(void); #if CONFIG_BLUEDROID_ENABLED esp_hidh_dev_t *esp_hidh_dev_get_by_bda(esp_bd_addr_t bda); //BT/BLE -esp_hidh_dev_t *esp_hidh_dev_get_by_handle(int handle); //BT Only +esp_hidh_dev_t *esp_hidh_dev_get_by_handle(uint8_t handle); //Classic Bluetooth Only esp_hidh_dev_t *esp_hidh_dev_get_by_conn_id(uint16_t conn_id); //BLE Only #endif /* CONFIG_BLUEDROID_ENABLED */ +esp_hidh_dev_report_t *esp_hidh_dev_get_report_by_id_type_proto(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, int report_type, uint8_t protocol_mode); esp_hidh_dev_report_t *esp_hidh_dev_get_report_by_id_and_type(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, int report_type); +esp_hidh_dev_report_t *esp_hidh_dev_get_input_report_by_len_and_proto(esp_hidh_dev_t *dev, size_t len, int protocol_mode); esp_hidh_dev_report_t *esp_hidh_dev_get_input_report_by_id_and_proto(esp_hidh_dev_t *dev, size_t report_id, int protocol_mode); +esp_hidh_dev_report_t *esp_hidh_dev_get_input_report_by_proto_and_data(esp_hidh_dev_t *dev, int protocol_mode, + size_t len, const uint8_t *data, bool *has_report_id); esp_hidh_dev_report_t *esp_hidh_dev_get_report_by_handle(esp_hidh_dev_t *dev, uint16_t handle); //BLE Only - - +void esp_hidh_process_event_data_handler(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id, + void *event_data); +void esp_hidh_dev_lock(esp_hidh_dev_t *dev); +void esp_hidh_dev_unlock(esp_hidh_dev_t *dev); +void esp_hidh_dev_wait(esp_hidh_dev_t *dev); +void esp_hidh_dev_send(esp_hidh_dev_t *dev); +esp_err_t esp_hidh_dev_free_inner(esp_hidh_dev_t *dev); #ifdef __cplusplus } #endif diff --git a/components/esp_hid/src/ble_hidd.c b/components/esp_hid/src/ble_hidd.c index b62ce623a2..85b49bcf22 100644 --- a/components/esp_hid/src/ble_hidd.c +++ b/components/esp_hid/src/ble_hidd.c @@ -38,6 +38,8 @@ static const char *TAG = "BLE_HIDD"; /// Length of Boot Report Char. Value Maximal Length #define HIDD_LE_BOOT_REPORT_MAX_LEN (8) +typedef hidd_report_item_t hidd_le_report_item_t; + /* * UUIDs * */ @@ -126,30 +128,6 @@ enum { HIDD_LE_IDX_NB, }; -/* Client Characteristic Configuration value structure */ -typedef union { - struct { - uint16_t notify_enable: 1; - uint16_t indicate_enable: 1; - uint16_t reserved: 14; - }; - uint16_t value; -} hidd_le_ccc_value_t; - -typedef struct { - uint8_t map_index; //the index of the report map - uint8_t report_id; //the id of the report - uint8_t report_type; //input, output or feature - uint8_t protocol_mode; //boot or report - esp_hid_usage_t usage; //generic, keyboard, mouse, joystick or gamepad - uint16_t value_len; //maximum len of value by report map - //used by gatts - uint8_t index; //index of the value in the gatts attr db - uint16_t handle; //obtained once all attributes are registered - uint16_t ccc_handle; //obtained once all attributes are registered - hidd_le_ccc_value_t ccc; //notifications and/or indications enabled -} hidd_le_report_item_t; - typedef struct { esp_gatt_if_t gatt_if; uint16_t handle; @@ -559,23 +537,43 @@ static void hid_event_handler(esp_ble_hidd_dev_t *dev, int device_index, esp_gat } else { ESP_LOGV(TAG, "HID WRITE %8s %7s %6s id: %d, len: %d", esp_hid_usage_str(map->usage), esp_hid_report_type_str(map->report_type), esp_hid_protocol_mode_str(map->protocol_mode), map->report_id, param->write.len); - esp_hidd_event_data_t cb_param = {0}; + esp_hidd_event_data_t *p_cb_param = NULL; + size_t event_data_size = sizeof(esp_hidd_event_data_t); + if (param->write.len > 0 && param->write.value) { + event_data_size += param->write.len; + } + + if ((p_cb_param = (esp_hidd_event_data_t *)malloc(event_data_size)) == NULL) { + ESP_LOGE(TAG, "%s malloc event data failed!", __func__); + break; + } + memset(p_cb_param, 0, event_data_size); + if (param->write.len > 0 && param->write.value) { + memcpy(((uint8_t *)p_cb_param) + sizeof(esp_hidd_event_data_t), param->write.value, + param->write.len); + } + if (map->report_type == ESP_HID_REPORT_TYPE_OUTPUT) { - cb_param.output.dev = dev->dev; - cb_param.output.report_id = map->report_id; - cb_param.output.usage = map->usage; - cb_param.output.length = param->write.len; - cb_param.output.data = param->write.value; - cb_param.output.map_index = device_index; - esp_event_post_to(dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_OUTPUT_EVENT, &cb_param, sizeof(esp_hidd_event_data_t), portMAX_DELAY); + p_cb_param->output.dev = dev->dev; + p_cb_param->output.report_id = map->report_id; + p_cb_param->output.usage = map->usage; + p_cb_param->output.length = param->write.len; + p_cb_param->output.data = param->write.value; /* move the data pointer in the wrapper loop handler */ + p_cb_param->output.map_index = device_index; + esp_event_post_to(dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_OUTPUT_EVENT, p_cb_param, event_data_size, portMAX_DELAY); } else { - cb_param.feature.dev = dev->dev; - cb_param.feature.report_id = map->report_id; - cb_param.feature.usage = map->usage; - cb_param.feature.length = param->write.len; - cb_param.feature.data = param->write.value; - cb_param.feature.map_index = device_index; - esp_event_post_to(dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_FEATURE_EVENT, &cb_param, sizeof(esp_hidd_event_data_t), portMAX_DELAY); + p_cb_param->feature.dev = dev->dev; + p_cb_param->feature.report_id = map->report_id; + p_cb_param->feature.usage = map->usage; + p_cb_param->feature.length = param->write.len; + p_cb_param->feature.data = param->write.value; /* move the data pointer in the wrapper loop handler */ + p_cb_param->feature.map_index = device_index; + esp_event_post_to(dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_FEATURE_EVENT, p_cb_param, event_data_size, portMAX_DELAY); + } + + if (p_cb_param) { + free(p_cb_param); + p_cb_param = NULL; } } } @@ -852,8 +850,14 @@ static esp_err_t esp_ble_hidd_dev_input_set(void *devp, size_t index, size_t id, if (!dev || s_dev != dev) { return ESP_FAIL; } + if (!dev->connected) { - ESP_LOGE(TAG, "Device Not Connected: %d", index); + ESP_LOGE(TAG, "%s Device Not Connected", __func__); + return ESP_FAIL; + } + + if (index >= dev->devices_len) { + ESP_LOGE(TAG, "%s index out of range[0-%d]", __func__, dev->devices_len - 1); return ESP_FAIL; } @@ -878,6 +882,17 @@ static esp_err_t esp_ble_hidd_dev_feature_set(void *devp, size_t index, size_t i if (!dev || s_dev != dev) { return ESP_FAIL; } + + if (!dev->connected) { + ESP_LOGE(TAG, "%s Device Not Connected", __func__); + return ESP_FAIL; + } + + if (index >= dev->devices_len) { + ESP_LOGE(TAG, "%s index out of range[0-%d]", __func__, dev->devices_len - 1); + return ESP_FAIL; + } + hidd_le_report_item_t *p_rpt; if ((p_rpt = get_report_by_id_and_type(dev, id, ESP_HID_REPORT_TYPE_FEATURE)) != NULL) { ret = esp_ble_gatts_set_attr_value(p_rpt->handle, length, data); @@ -921,9 +936,11 @@ static esp_err_t esp_ble_hidd_dev_event_handler_unregister(void *devp, esp_event static void ble_hidd_dev_free(void) { - ble_hid_free_config(s_dev); - free(s_dev); - s_dev = NULL; + if (s_dev) { + ble_hid_free_config(s_dev); + free(s_dev); + s_dev = NULL; + } } esp_err_t esp_ble_hidd_dev_init(esp_hidd_dev_t *dev_p, const esp_hid_device_config_t *config, esp_event_handler_t callback) @@ -985,6 +1002,12 @@ esp_err_t esp_ble_hidd_dev_init(esp_hidd_dev_t *dev_p, const esp_hid_device_conf dev_p->event_handler_register = esp_ble_hidd_dev_event_handler_register; dev_p->event_handler_unregister = esp_ble_hidd_dev_event_handler_unregister; + ret = esp_ble_hidd_dev_event_handler_register(s_dev, esp_hidd_process_event_data_handler, ESP_EVENT_ANY_ID); + if (ret != ESP_OK) { + ble_hidd_dev_free(); + return ret; + } + if (callback != NULL) { ret = esp_ble_hidd_dev_event_handler_register(s_dev, callback, ESP_EVENT_ANY_ID); if (ret != ESP_OK) { diff --git a/components/esp_hid/src/ble_hidh.c b/components/esp_hid/src/ble_hidh.c index a56eb04c44..6116384ee7 100644 --- a/components/esp_hid/src/ble_hidh.c +++ b/components/esp_hid/src/ble_hidh.c @@ -475,22 +475,44 @@ void esp_hidh_gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gatt } else { report = esp_hidh_dev_get_report_by_handle(dev, p_data->notify.handle); if (report) { + esp_hidh_event_data_t *p_param = NULL; + size_t event_data_size = sizeof(esp_hidh_event_data_t); + + if (p_data->notify.value_len && p_data->notify.value) { + event_data_size += p_data->notify.value_len; + } + + if ((p_param = (esp_hidh_event_data_t *)malloc(event_data_size)) == NULL) { + ESP_LOGE(TAG, "%s malloc event data failed!", __func__); + break; + } + memset(p_param, 0, event_data_size); + if (p_data->notify.value_len && p_data->notify.value) { + memcpy(((uint8_t *)p_param) + sizeof(esp_hidh_event_data_t), p_data->notify.value, + p_data->notify.value_len); + } + if (report->report_type == ESP_HID_REPORT_TYPE_FEATURE) { - p.feature.dev = dev; - p.feature.map_index = report->map_index; - p.feature.report_id = report->report_id; - p.feature.usage = report->usage; - p.feature.data = p_data->notify.value; - p.feature.length = p_data->notify.value_len; - esp_event_post_to(event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_INPUT_EVENT, &p, sizeof(esp_hidh_event_data_t), portMAX_DELAY); + p_param->feature.dev = dev; + p_param->feature.map_index = report->map_index; + p_param->feature.report_id = report->report_id; + p_param->feature.usage = report->usage; + p_param->feature.length = p_data->notify.value_len; + p_param->feature.data = p_data->notify.value; + esp_event_post_to(event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_FEATURE_EVENT, p_param, event_data_size, portMAX_DELAY); } else { - p.input.dev = dev; - p.input.map_index = report->map_index; - p.input.report_id = report->report_id; - p.input.usage = report->usage; - p.input.data = p_data->notify.value; - p.input.length = p_data->notify.value_len; - esp_event_post_to(event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_INPUT_EVENT, &p, sizeof(esp_hidh_event_data_t), portMAX_DELAY); + p_param->input.dev = dev; + p_param->input.map_index = report->map_index; + p_param->input.report_id = report->report_id; + p_param->input.usage = report->usage; + p_param->input.length = p_data->notify.value_len; + p_param->input.data = p_data->notify.value; + esp_event_post_to(event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_INPUT_EVENT, p_param, event_data_size, portMAX_DELAY); + } + + if (p_param) { + free(p_param); + p_param = NULL; } } } @@ -512,13 +534,16 @@ void esp_hidh_gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gatt } else { dev->connected = false; dev->status = p_data->close.status; + // free the device in the wrapper event handler + dev->in_use = false; if (event_loop_handle) { esp_hidh_event_data_t p = {0}; p.close.dev = dev; p.close.reason = p_data->close.reason; + p.close.status = ESP_OK; esp_event_post_to(event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_CLOSE_EVENT, &p, sizeof(esp_hidh_event_data_t), portMAX_DELAY); } else { - esp_hidh_dev_free(dev); + esp_hidh_dev_free_inner(dev); } } break; @@ -620,22 +645,37 @@ esp_err_t esp_ble_hidh_init(const esp_hidh_config_t *config) .task_stack_size = config->event_stack_size > 0 ? config->event_stack_size : 2048, .task_core_id = tskNO_AFFINITY }; - ret = esp_event_loop_create(&event_task_args, &event_loop_handle); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "esp_event_loop_create failed!"); - return ESP_FAIL; - } + do { + ret = esp_event_loop_create(&event_task_args, &event_loop_handle); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "%s esp_event_loop_create failed!", __func__); + break; + } + + ret = esp_ble_gattc_app_register(0); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "esp_ble_gattc_app_register failed!"); + break; + } + WAIT_CB(); + ret = esp_event_handler_register_with(event_loop_handle, ESP_HIDH_EVENTS, ESP_EVENT_ANY_ID, + esp_hidh_process_event_data_handler, NULL); + ret |= esp_event_handler_register_with(event_loop_handle, ESP_HIDH_EVENTS, ESP_EVENT_ANY_ID, config->callback, + config->callback_arg); + } while (0); - ret = esp_ble_gattc_app_register(0); if (ret != ESP_OK) { - vSemaphoreDelete(s_ble_hidh_cb_semaphore); - s_ble_hidh_cb_semaphore = NULL; - return ret; + if (event_loop_handle) { + esp_event_loop_delete(event_loop_handle); + } + + if (s_ble_hidh_cb_semaphore) { + vSemaphoreDelete(s_ble_hidh_cb_semaphore); + s_ble_hidh_cb_semaphore = NULL; + } } - WAIT_CB(); - esp_event_handler_register_with(event_loop_handle, ESP_HIDH_EVENTS, ESP_EVENT_ANY_ID, config->callback, NULL); - return ESP_OK; + return ret; } esp_err_t esp_ble_hidh_deinit(void) @@ -669,6 +709,7 @@ esp_hidh_dev_t *esp_ble_hidh_dev_open(esp_bd_addr_t bda, esp_ble_addr_type_t add return NULL; } + dev->in_use = true; dev->transport = ESP_HID_TRANSPORT_BLE; memcpy(dev->bda, bda, sizeof(esp_bd_addr_t)); dev->ble.address_type = address_type; @@ -676,7 +717,7 @@ esp_hidh_dev_t *esp_ble_hidh_dev_open(esp_bd_addr_t bda, esp_ble_addr_type_t add ret = esp_ble_gattc_open(hid_gattc_if, dev->bda, dev->ble.address_type, true); if (ret) { - esp_hidh_dev_free(dev); + esp_hidh_dev_free_inner(dev); ESP_LOGE(TAG, "esp_ble_gattc_open failed: %d", ret); return NULL; } @@ -684,7 +725,7 @@ esp_hidh_dev_t *esp_ble_hidh_dev_open(esp_bd_addr_t bda, esp_ble_addr_type_t add if (dev->ble.conn_id < 0) { ret = dev->status; ESP_LOGE(TAG, "dev open failed! status: 0x%x", dev->status); - esp_hidh_dev_free(dev); + esp_hidh_dev_free_inner(dev); return NULL; } @@ -697,6 +738,7 @@ esp_hidh_dev_t *esp_ble_hidh_dev_open(esp_bd_addr_t bda, esp_ble_addr_type_t add if (event_loop_handle) { esp_hidh_event_data_t p = {0}; + p.open.status = ESP_OK; p.open.dev = dev; esp_event_post_to(event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_OPEN_EVENT, &p, sizeof(esp_hidh_event_data_t), portMAX_DELAY); } diff --git a/components/esp_hid/src/bt_hidd.c b/components/esp_hid/src/bt_hidd.c new file mode 100644 index 0000000000..0af5424d08 --- /dev/null +++ b/components/esp_hid/src/bt_hidd.c @@ -0,0 +1,879 @@ +// Copyright 2017-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. +#include "bt_hidd.h" + +#if CONFIG_BT_HID_DEVICE_ENABLED +#include "esp_bt.h" +#include "esp_bt_defs.h" +#include "esp_bt_main.h" +#include "esp_hidd.h" +#include "esp_hidd_api.h" +#include "esp_hidd_private.h" +#include "esp_log.h" +#include "osi/mutex.h" +#include "string.h" + +/* Values for service_type */ +#define NO_TRAFFIC 0 +#define BEST_EFFORT 1 +#define GUARANTEED 2 + +static const char *TAG = "BT_HIDD"; + +typedef struct { + esp_hid_raw_report_map_t reports_map; + uint8_t reports_len; + hidd_report_item_t *reports; +} hidd_dev_map_t; + +typedef struct { + esp_hidd_dev_t *dev; + esp_event_loop_handle_t event_loop_handle; + esp_hid_device_config_t config; + uint16_t appearance; + bool registered; + bool connected; + esp_bd_addr_t remote_bda; + uint8_t bat_level; // 0 - 100 - battery percentage + uint8_t control; // 0x00 suspend, 0x01 suspend off + uint8_t protocol_mode; // 0x00 boot, 0x01 report + hidd_dev_map_t *devices; + uint8_t devices_len; +} esp_bt_hidd_dev_t; + +typedef struct +{ + osi_mutex_t mutex; + esp_bt_hidd_dev_t *dev; + esp_hidd_app_param_t app_param; + esp_hidd_qos_param_t in_qos; + esp_hidd_qos_param_t out_qos; +} hidd_param_t; + +static hidd_param_t s_hidd_param = {0}; +#define is_init() (s_hidd_param.dev != NULL) +#define UNUSED(x) (void)(x) + +static esp_err_t bt_hidd_get_status(esp_hidd_status_t status) +{ + esp_err_t ret = ESP_OK; + switch (status) { + case ESP_HIDD_SUCCESS: + ret = ESP_OK; + break; + case ESP_HIDD_NO_RES: + ret = ESP_ERR_NO_MEM; + break; + default: + ret = ESP_FAIL; + break; + } + return ret; +} + +static esp_err_t bt_hidd_init_config(esp_bt_hidd_dev_t *dev, const esp_hid_device_config_t *config) +{ + if (config->report_maps == NULL || config->report_maps_len == 0 || config->report_maps_len > 1) { + return ESP_ERR_INVALID_ARG; + } + memset((uint8_t *)(&dev->config), 0, sizeof(esp_hid_device_config_t)); + dev->config.vendor_id = config->vendor_id; + dev->config.product_id = config->product_id; + dev->config.version = config->version; + if (config->device_name != NULL) { + dev->config.device_name = strdup(config->device_name); + } + if (config->manufacturer_name != NULL) { + dev->config.manufacturer_name = strdup(config->manufacturer_name); + } + if (config->serial_number != NULL) { + dev->config.serial_number = strdup(config->serial_number); + } + dev->appearance = ESP_HID_APPEARANCE_GENERIC; + + if (config->report_maps_len) { + dev->devices = (hidd_dev_map_t *)malloc(config->report_maps_len * sizeof(hidd_dev_map_t)); + if (dev->devices == NULL) { + ESP_LOGE(TAG, "devices malloc(%d) failed", config->report_maps_len); + return ESP_ERR_NO_MEM; + } + memset(dev->devices, 0, config->report_maps_len * sizeof(hidd_dev_map_t)); + dev->devices_len = config->report_maps_len; + for (uint8_t d = 0; d < dev->devices_len; d++) { + + //raw report map + uint8_t *map = (uint8_t *)malloc(config->report_maps[d].len); + if (map == NULL) { + ESP_LOGE(TAG, "report map malloc(%d) failed", config->report_maps[d].len); + return ESP_ERR_NO_MEM; + } + memcpy(map, config->report_maps[d].data, config->report_maps[d].len); + + dev->devices[d].reports_map.data = (const uint8_t *)map; + dev->devices[d].reports_map.len = config->report_maps[d].len; + + esp_hid_report_map_t *rmap = esp_hid_parse_report_map(config->report_maps[d].data, config->report_maps[d].len); + if (rmap == NULL) { + ESP_LOGE(TAG, "hid_parse_report_map[%d](%d) failed", d, config->report_maps[d].len); + return ESP_FAIL; + } + dev->appearance = rmap->appearance; + dev->devices[d].reports_len = rmap->reports_len; + dev->devices[d].reports = (hidd_report_item_t *)malloc(rmap->reports_len * sizeof(hidd_report_item_t)); + if (dev->devices[d].reports == NULL) { + ESP_LOGE(TAG, "reports malloc(%d) failed", rmap->reports_len * sizeof(hidd_report_item_t)); + free(rmap); + return ESP_ERR_NO_MEM; + } + for (uint8_t r = 0; r < rmap->reports_len; r++) { + dev->devices[d].reports[r].map_index = d; + dev->devices[d].reports[r].report_id = rmap->reports[r].report_id; + dev->devices[d].reports[r].protocol_mode = rmap->reports[r].protocol_mode; + dev->devices[d].reports[r].report_type = rmap->reports[r].report_type; + dev->devices[d].reports[r].usage = rmap->reports[r].usage; + dev->devices[d].reports[r].value_len = rmap->reports[r].value_len; + } + free(rmap->reports); + free(rmap); + } + } + + return ESP_OK; +} + +static hidd_report_item_t *get_report_by_idx_id_type(esp_bt_hidd_dev_t *dev, size_t index, uint8_t id, uint8_t type) +{ + hidd_report_item_t *rpt = NULL; + if (index >= dev->devices_len) { + ESP_LOGE(TAG, "index out of range[0-%d]", dev->devices_len - 1); + return NULL; + } + for (uint8_t i = 0; i < dev->devices[index].reports_len; i++) { + rpt = &dev->devices[index].reports[i]; + if (rpt->report_id == id && rpt->report_type == type && rpt->protocol_mode == dev->protocol_mode) { + return rpt; + } + } + return NULL; +} + +static hidd_report_item_t *get_report_by_id_and_type(esp_bt_hidd_dev_t *dev, uint8_t id, uint8_t type, uint8_t *index) +{ + hidd_report_item_t *rpt = NULL; + for (uint8_t idx = 0; idx < dev->devices_len; idx++) { + for (uint8_t i = 0; i < dev->devices[idx].reports_len; i++) { + rpt = &dev->devices[idx].reports[i]; + if (rpt->report_id == id && rpt->report_type == type && rpt->protocol_mode == dev->protocol_mode) { + if (index) { + *index = idx; + } + return rpt; + } + } + } + return NULL; +} + +static esp_err_t bt_hid_free_config(esp_bt_hidd_dev_t *dev) +{ + for (uint8_t d = 0; d < dev->devices_len; d++) { + free((void *)dev->devices[d].reports); + free((void *)dev->devices[d].reports_map.data); + } + + free((void *)dev->devices); + free((void *)dev->config.device_name); + free((void *)dev->config.manufacturer_name); + free((void *)dev->config.serial_number); + if (dev->event_loop_handle != NULL) { + esp_event_loop_delete(dev->event_loop_handle); + dev->event_loop_handle = NULL; + } + return ESP_OK; +} + +static void bt_hidd_dev_free(void) +{ + if (s_hidd_param.dev) { + osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT); + bt_hid_free_config(s_hidd_param.dev); + free(s_hidd_param.dev); + s_hidd_param.dev = NULL; + osi_mutex_unlock(&s_hidd_param.mutex); + osi_mutex_free(&s_hidd_param.mutex); + } +} + +static void build_default_in_qos(esp_hidd_qos_param_t *in_qos, uint32_t value_len) +{ + + if (value_len > 0) { + in_qos->service_type = GUARANTEED; + in_qos->token_rate = value_len * 100; + in_qos->token_bucket_size = value_len; + in_qos->peak_bandwidth = value_len * 100; + in_qos->access_latency = 10; + in_qos->delay_variation = 10; + } else { + memset(in_qos, 0, sizeof(esp_hidd_qos_param_t)); + } +} + +static void build_default_out_qos(esp_hidd_qos_param_t *out_qos, uint32_t value_len) +{ + if (value_len > 0) { + out_qos->service_type = GUARANTEED; + out_qos->token_rate = value_len * 100; + out_qos->token_bucket_size = value_len; + out_qos->peak_bandwidth = value_len * 100; + out_qos->access_latency = 10; + out_qos->delay_variation = 10; + } else { + memset(out_qos, 0, sizeof(esp_hidd_qos_param_t)); + } +} + +static uint8_t get_subclass_by_appearance(uint16_t appearance) +{ + uint8_t ret = ESP_HID_CLASS_UNKNOWN; + switch (appearance) { + case ESP_HID_APPEARANCE_KEYBOARD: + ret = ESP_HID_CLASS_KBD; + break; + case ESP_HID_APPEARANCE_MOUSE: + ret = ESP_HID_CLASS_MIC; + break; + case ESP_HID_APPEARANCE_JOYSTICK: + ret = ESP_HID_CLASS_JOS; + break; + case ESP_HID_APPEARANCE_GAMEPAD: + ret = ESP_HID_CLASS_GPD; + break; + default: + ret = ESP_HID_CLASS_UNKNOWN; + break; + } + return ret; +} + +static uint32_t get_value_len_by_type_protocol(esp_bt_hidd_dev_t *dev, uint8_t report_type, uint8_t protocol_mode) +{ + uint32_t value_len = 0; + hidd_report_item_t *rpt = NULL; + for (uint8_t d = 0; d < dev->devices_len; d++) { + for (uint8_t i = 0; i < dev->devices[d].reports_len; i++) { + rpt = &dev->devices[d].reports[i]; + if (rpt->report_type == report_type && rpt->protocol_mode == dev->protocol_mode) { + value_len += rpt->value_len; + } + } + } + return value_len; +} + +static void bt_hidd_init_app(void) +{ + esp_hid_device_config_t *p_config = &s_hidd_param.dev->config; + s_hidd_param.app_param.name = p_config->device_name; + s_hidd_param.app_param.description = p_config->device_name; + s_hidd_param.app_param.provider = p_config->manufacturer_name; + s_hidd_param.app_param.subclass = get_subclass_by_appearance(s_hidd_param.dev->appearance); + s_hidd_param.app_param.desc_list = (uint8_t *)s_hidd_param.dev->devices[0].reports_map.data; + s_hidd_param.app_param.desc_list_len = s_hidd_param.dev->devices[0].reports_map.len; +} + +static void bt_hidd_init_qos(void) +{ + uint32_t value_len = 0; + value_len = + get_value_len_by_type_protocol(s_hidd_param.dev, ESP_HID_REPORT_TYPE_INPUT, s_hidd_param.dev->protocol_mode); + build_default_in_qos(&s_hidd_param.in_qos, value_len); + + value_len = + get_value_len_by_type_protocol(s_hidd_param.dev, ESP_HID_REPORT_TYPE_INPUT, s_hidd_param.dev->protocol_mode); + build_default_out_qos(&s_hidd_param.out_qos, value_len); +} + +static bool esp_bt_hidd_dev_connected(void *devp) +{ + esp_bt_hidd_dev_t *dev = (esp_bt_hidd_dev_t *)devp; + bool ret = true; + osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT); + do { + if (!is_init()) { + ESP_LOGE(TAG, "HID device profile is uninit"); + ret = false; + break; + } + + if (s_hidd_param.dev != dev) { + ESP_LOGE(TAG, "Wrong HID device provided"); + ret = false; + break; + } + } while(0); + if (ret) { + ret = dev->connected; + } + osi_mutex_unlock(&s_hidd_param.mutex); + return ret; +} + +static esp_err_t esp_bt_hidd_dev_deinit(void *devp) +{ + esp_bt_hidd_dev_t *dev = (esp_bt_hidd_dev_t *)devp; + esp_err_t ret = ESP_OK; + osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT); + do { + if (!is_init()) { + osi_mutex_unlock(&s_hidd_param.mutex); + ESP_LOGE(TAG, "HID device profile already uninitialized"); + return ESP_OK; + } + + if (s_hidd_param.dev != dev) { + ESP_LOGE(TAG, "Wrong HID device provided"); + ret = ESP_FAIL; + } + } while(0); + osi_mutex_unlock(&s_hidd_param.mutex); + + if (ret == ESP_OK) { + ret = esp_bt_hid_device_deinit(); + } + return ret; +} + +static esp_err_t esp_bt_hidd_dev_disconnect(void *devp) +{ + esp_bt_hidd_dev_t *dev = (esp_bt_hidd_dev_t *)devp; + esp_err_t ret = ESP_OK; + osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT); + do { + if (!is_init()) { + ESP_LOGE(TAG, "HID device is uninit"); + ret = ESP_FAIL; + break; + } + + if (s_hidd_param.dev != dev) { + ESP_LOGE(TAG, "Wrong HID device provided"); + ret = ESP_FAIL; + break; + } + + if (!dev->connected) { + osi_mutex_unlock(&s_hidd_param.mutex); + ESP_LOGW(TAG, "already disconnected"); + return ESP_OK; + } + } while(0); + osi_mutex_unlock(&s_hidd_param.mutex); + + if (ret == ESP_OK) { + ret = esp_bt_hid_device_disconnect(); + } + return ret; +} + +static esp_err_t esp_bt_hidd_dev_battery_set(void *devp, uint8_t level) +{ + UNUSED(devp); + UNUSED(level); + ESP_LOGW(TAG, "Not implement yet!"); + return ESP_OK; +} + +static esp_err_t esp_bt_hidd_dev_input_set(void *devp, size_t index, size_t id, uint8_t *data, size_t length) +{ + hidd_report_item_t *p_rpt; + esp_bt_hidd_dev_t *dev = (esp_bt_hidd_dev_t *)devp; + esp_err_t ret = ESP_OK; + osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT); + do { + if (!is_init()) { + ESP_LOGE(TAG, "HID device is uninit"); + ret = ESP_FAIL; + break; + } + + if (s_hidd_param.dev != dev) { + ESP_LOGE(TAG, "Wrong HID device provided"); + ret = ESP_FAIL; + break; + } + + if (!dev->connected) { + ESP_LOGE(TAG, "HID device not connected!"); + ret = ESP_FAIL; + break; + } + + p_rpt = get_report_by_idx_id_type(dev, index, id, ESP_HID_REPORT_TYPE_INPUT); + if (p_rpt == NULL) { + ESP_LOGE(TAG, "HID device not connected!"); + ret = ESP_FAIL; + break; + } + + if (length > p_rpt->value_len) { + ESP_LOGE(TAG, "Data size over %d!", p_rpt->value_len); + ret = ESP_FAIL; + break; + } + } while(0); + osi_mutex_unlock(&s_hidd_param.mutex); + + if (ret == ESP_OK) { + ret = esp_bt_hid_device_send_report(ESP_HIDD_REPORT_TYPE_INTRDATA, id, length, data); + } + return ret; +} + +static esp_err_t esp_bt_hidd_dev_feature_set(void *devp, size_t index, size_t id, uint8_t *data, size_t length) +{ + hidd_report_item_t *p_rpt; + esp_bt_hidd_dev_t *dev = (esp_bt_hidd_dev_t *)devp; + esp_err_t ret = ESP_OK; + osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT); + do { + if (!is_init()) { + ESP_LOGE(TAG, "HID device is uninit"); + ret = ESP_FAIL; + break; + } + + if (s_hidd_param.dev != dev) { + ESP_LOGE(TAG, "Wrong HID device provided"); + ret = ESP_FAIL; + break; + } + + if (!dev->connected) { + ESP_LOGE(TAG, "HID device not connected!"); + ret = ESP_FAIL; + break; + } + + p_rpt = get_report_by_idx_id_type(dev, index, id, ESP_HID_REPORT_TYPE_FEATURE); + if (p_rpt == NULL) { + ESP_LOGE(TAG, "HID device not connected!"); + ret = ESP_FAIL; + break; + } + + if (length > p_rpt->value_len) { + ESP_LOGE(TAG, "Data size over %d!", p_rpt->value_len); + ret = ESP_FAIL; + break; + } + } while(0); + osi_mutex_unlock(&s_hidd_param.mutex); + + if (ret == ESP_OK) { + ret = esp_bt_hid_device_send_report(ESP_HID_REPORT_TYPE_FEATURE, id, length, data); + } + return ret; +} + +static esp_err_t esp_bt_hidd_dev_event_handler_register(void *devp, esp_event_handler_t callback, esp_hidd_event_t event) +{ + esp_bt_hidd_dev_t *dev = (esp_bt_hidd_dev_t *)devp; + esp_err_t ret = ESP_OK; + osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT); + do { + if (!is_init()) { + ESP_LOGE(TAG, "HID device is uninit"); + ret = ESP_FAIL; + break; + } + + if (s_hidd_param.dev != dev) { + ESP_LOGE(TAG, "Wrong HID device provided"); + ret = ESP_FAIL; + break; + } + + ret = esp_event_handler_register_with(dev->event_loop_handle, ESP_HIDD_EVENTS, event, callback, dev->dev); + } while (0); + osi_mutex_unlock(&s_hidd_param.mutex); + return ret; +} + +static esp_err_t esp_bt_hidd_dev_event_handler_unregister(void *devp, esp_event_handler_t callback, esp_hidd_event_t event) +{ + esp_bt_hidd_dev_t *dev = (esp_bt_hidd_dev_t *)devp; + esp_err_t ret = ESP_OK; + osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT); + do { + if (!is_init()) { + ESP_LOGE(TAG, "HID device is uninit"); + ret = ESP_FAIL; + break; + } + + if (s_hidd_param.dev != dev) { + ESP_LOGE(TAG, "Wrong HID device provided"); + ret = ESP_FAIL; + break; + } + ret = esp_event_handler_unregister_with(dev->event_loop_handle, ESP_HIDD_EVENTS, event, callback); + } while (0); + osi_mutex_unlock(&s_hidd_param.mutex); + return ret; +} + +void bt_hidd_cb(esp_hidd_cb_event_t event, esp_hidd_cb_param_t *param) +{ + esp_hidd_event_data_t cb_param = {0}; + esp_hidd_event_data_t *p_cb_param = NULL; + size_t event_data_size = 0; + uint8_t map_index = 0; + hidd_report_item_t *p_rpt = NULL; + + if (!is_init()) { + ESP_LOGE(TAG, "HID device is uninit, event(%d)", event); + return; + } + + switch (event) { + case ESP_HIDD_INIT_EVT: { + if (param->init.status == ESP_HIDD_SUCCESS) { + ESP_LOGD(TAG, "Setting hid parameters in_qos:%d, out_qos:%d", s_hidd_param.in_qos.token_bucket_size, + s_hidd_param.out_qos.token_bucket_size); + esp_bt_hid_device_register_app(&s_hidd_param.app_param, &s_hidd_param.in_qos, &s_hidd_param.out_qos); + } else { + ESP_LOGE(TAG, "Init hidd failed (%d)!", param->init.status); + cb_param.start.status = bt_hidd_get_status(param->init.status); + esp_event_post_to(s_hidd_param.dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_START_EVENT, &cb_param, + sizeof(esp_hidd_event_data_t), portMAX_DELAY); + + bt_hidd_dev_free(); + } + break; + } + case ESP_HIDD_DEINIT_EVT: { + cb_param.stop.status = bt_hidd_get_status(param->deinit.status); + esp_event_post_to(s_hidd_param.dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_STOP_EVENT, &cb_param, + sizeof(esp_hidd_event_data_t), portMAX_DELAY); + if (param->deinit.status == ESP_HIDD_SUCCESS) { + bt_hidd_dev_free(); + } else { + ESP_LOGE(TAG, "Deinit hidd failed (%d)!", param->deinit.status); + } + break; + } + case ESP_HIDD_REGISTER_APP_EVT: { + if (param->register_app.status == ESP_HIDD_SUCCESS) { + ESP_LOGD(TAG, "Setting hid parameters success!"); + if (param->register_app.in_use && param->register_app.bd_addr != NULL) { + ESP_LOGI(TAG, "Start virtual cable plug!"); + esp_bt_hid_device_connect(param->register_app.bd_addr); + } + + osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT); + s_hidd_param.dev->registered = true; + osi_mutex_unlock(&s_hidd_param.mutex); + + cb_param.start.status = bt_hidd_get_status(param->init.status); + esp_event_post_to(s_hidd_param.dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_START_EVENT, &cb_param, + sizeof(esp_hidd_event_data_t), portMAX_DELAY); + } else { + ESP_LOGE(TAG, "Setting hid parameters failed (%d), now deint!", param->register_app.status); + esp_bt_hid_device_deinit(); + } + break; + } + case ESP_HIDD_UNREGISTER_APP_EVT: { + break; + } + case ESP_HIDD_OPEN_EVT: { + if (param->open.conn_status == ESP_HIDD_CONN_STATE_CONNECTING) { + break; + } + if (param->open.status == ESP_HIDD_SUCCESS && param->open.conn_status == ESP_HIDD_CONN_STATE_CONNECTED) { + ESP_LOGI(TAG, "Connected to %02x:%02x:%02x:%02x:%02x:%02x", param->open.bd_addr[0], param->open.bd_addr[1], + param->open.bd_addr[2], param->open.bd_addr[3], param->open.bd_addr[4], param->open.bd_addr[5]); + osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT); + s_hidd_param.dev->connected = true; + memcpy(s_hidd_param.dev->remote_bda, param->open.bd_addr, ESP_BD_ADDR_LEN); + osi_mutex_unlock(&s_hidd_param.mutex); + } else { + ESP_LOGE(TAG, "Connect failed (%d)!", param->open.status); + } + cb_param.connect.status = bt_hidd_get_status(param->open.status); + cb_param.connect.dev = s_hidd_param.dev->dev; + esp_event_post_to(s_hidd_param.dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_CONNECT_EVENT, &cb_param, + sizeof(esp_hidd_event_data_t), portMAX_DELAY); + break; + } + case ESP_HIDD_CLOSE_EVT: { + if (param->close.conn_status == ESP_HIDD_CONN_STATE_DISCONNECTING) { + break; + } + if (param->close.status == ESP_HIDD_SUCCESS && param->close.conn_status == ESP_HIDD_CONN_STATE_DISCONNECTED) { + osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT); + s_hidd_param.dev->connected = false; + memset(s_hidd_param.dev->remote_bda, 0, ESP_BD_ADDR_LEN); + osi_mutex_unlock(&s_hidd_param.mutex); + } else { + ESP_LOGE(TAG, "Disconnect failed (%d)!", param->close.status); + } + cb_param.disconnect.status = bt_hidd_get_status(param->close.status); + cb_param.disconnect.dev = s_hidd_param.dev->dev; + cb_param.disconnect.reason = param->close.status; + esp_event_post_to(s_hidd_param.dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_DISCONNECT_EVENT, &cb_param, + sizeof(esp_hidd_event_data_t), portMAX_DELAY); + break; + } + case ESP_HIDD_SEND_REPORT_EVT: + break; + case ESP_HIDD_REPORT_ERR_EVT: + break; + case ESP_HIDD_GET_REPORT_EVT: { + uint8_t *data_ptr = NULL; + p_rpt = get_report_by_id_and_type((esp_bt_hidd_dev_t *)s_hidd_param.dev->dev, param->get_report.report_id, + param->get_report.report_type, &map_index); + if (p_rpt == NULL) { + ESP_LOGE(TAG, "Can not find report!"); + esp_bt_hid_device_report_error(ESP_HID_PAR_HANDSHAKE_RSP_ERR_INVALID_REP_ID); + break; + } + if (param->get_report.buffer_size > p_rpt->value_len) { + ESP_LOGE(TAG, "Data size over %d!", p_rpt->value_len); + esp_bt_hid_device_report_error(ESP_HID_PAR_HANDSHAKE_RSP_ERR_INVALID_PARAM); + break; + } + + event_data_size = sizeof(esp_hidd_event_data_t); + if (param->get_report.buffer_size) { + event_data_size += 2; + } + + if ((p_cb_param = (esp_hidd_event_data_t *)malloc(event_data_size)) == NULL) { + ESP_LOGE(TAG, "%s malloc event data failed!", __func__); + break; + } + memset(p_cb_param, 0, event_data_size); + p_cb_param->feature.dev = s_hidd_param.dev->dev; + p_cb_param->feature.trans_type = ESP_HID_TRANS_GET_REPORT; + p_cb_param->feature.report_type = param->get_report.report_type; + p_cb_param->feature.report_id = p_rpt->report_id; + p_cb_param->feature.usage = p_rpt->usage; + p_cb_param->feature.length = param->get_report.buffer_size ? 2 : 0; + p_cb_param->feature.data = ((uint8_t *)p_cb_param) + sizeof(esp_hidd_event_data_t); + p_cb_param->feature.map_index = map_index; + if (param->get_report.buffer_size) { + data_ptr = ((uint8_t *)p_cb_param) + sizeof(esp_hidd_event_data_t); + *data_ptr++ = (uint8_t)param->get_report.buffer_size; + *data_ptr++ = (uint8_t)(param->get_report.buffer_size >> 8); + } + esp_event_post_to(s_hidd_param.dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_FEATURE_EVENT, p_cb_param, + event_data_size, portMAX_DELAY); + break; + } + case ESP_HIDD_SET_REPORT_EVT: { + p_rpt = get_report_by_id_and_type((esp_bt_hidd_dev_t *)s_hidd_param.dev->dev, param->set_report.report_id, + param->set_report.report_type, &map_index); + if (p_rpt == NULL) { + ESP_LOGE(TAG, "Can not find report!"); + esp_bt_hid_device_report_error(ESP_HID_PAR_HANDSHAKE_RSP_ERR_INVALID_REP_ID); + break; + } + if (param->set_report.len > p_rpt->value_len) { + ESP_LOGE(TAG, "Data size over %d!", p_rpt->value_len); + esp_bt_hid_device_report_error(ESP_HID_PAR_HANDSHAKE_RSP_ERR_INVALID_PARAM); + break; + } + + event_data_size = sizeof(esp_hidd_event_data_t); + if (param->set_report.len && param->set_report.data) { + event_data_size += param->set_report.len; + } + + if ((p_cb_param = (esp_hidd_event_data_t *)malloc(event_data_size)) == NULL) { + ESP_LOGE(TAG, "%s malloc event data failed!", __func__); + break; + } + memset(p_cb_param, 0, event_data_size); + p_cb_param->feature.dev = s_hidd_param.dev->dev; + p_cb_param->feature.trans_type = ESP_HID_TRANS_SET_REPORT; + p_cb_param->feature.report_type = param->set_report.report_type; + p_cb_param->feature.report_id = p_rpt->report_id; + p_cb_param->feature.usage = p_rpt->usage; + p_cb_param->feature.length = param->set_report.len; + p_cb_param->feature.data = param->set_report.data; + p_cb_param->feature.map_index = map_index; + if (param->set_report.len && param->set_report.data) { + memcpy(((uint8_t *)p_cb_param) + sizeof(esp_hidd_event_data_t), param->set_report.data, + param->set_report.len); + } + esp_event_post_to(s_hidd_param.dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_FEATURE_EVENT, p_cb_param, + event_data_size, portMAX_DELAY); + break; + } + case ESP_HIDD_SET_PROTOCOL_EVT: { + if (param->set_protocol.protocol_mode != ESP_HIDD_UNSUPPORTED_MODE) { + if (s_hidd_param.dev->protocol_mode == param->set_protocol.protocol_mode) { + break; + } + osi_mutex_lock(&s_hidd_param.mutex, OSI_MUTEX_MAX_TIMEOUT); + s_hidd_param.dev->protocol_mode = param->set_protocol.protocol_mode; + osi_mutex_unlock(&s_hidd_param.mutex); + cb_param.protocol_mode.dev = s_hidd_param.dev->dev; + cb_param.protocol_mode.protocol_mode = s_hidd_param.dev->protocol_mode; + cb_param.protocol_mode.map_index = 0; + esp_event_post_to(s_hidd_param.dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_PROTOCOL_MODE_EVENT, + &cb_param, sizeof(esp_hidd_event_data_t), portMAX_DELAY); + } else { + ESP_LOGE(TAG, "Unsupported protocol mode!"); + break; + } + break; + } + case ESP_HIDD_INTR_DATA_EVT: { + p_rpt = get_report_by_id_and_type((esp_bt_hidd_dev_t *)s_hidd_param.dev->dev, param->intr_data.report_id, + ESP_HID_REPORT_TYPE_OUTPUT, &map_index); + if (p_rpt == NULL) { + ESP_LOGE(TAG, "Can not find report!"); + break; + } + + event_data_size = sizeof(esp_hidd_event_data_t); + if (param->intr_data.len && param->intr_data.data) { + event_data_size += param->intr_data.len; + } + + if ((p_cb_param = (esp_hidd_event_data_t *)malloc(event_data_size)) == NULL) { + ESP_LOGE(TAG, "%s malloc event data failed!", __func__); + break; + } + memset(p_cb_param, 0, event_data_size); + p_cb_param->output.dev = s_hidd_param.dev->dev; + p_cb_param->output.report_id = p_rpt->report_id; + p_cb_param->output.usage = p_rpt->usage; + p_cb_param->output.length = param->intr_data.len; + p_cb_param->output.data = param->intr_data.data; + p_cb_param->output.map_index = map_index; + if (param->intr_data.len && param->intr_data.data) { + memcpy(((uint8_t *)p_cb_param) + sizeof(esp_hidd_event_data_t), param->intr_data.data, + param->intr_data.len); + } + esp_event_post_to(s_hidd_param.dev->event_loop_handle, ESP_HIDD_EVENTS, ESP_HIDD_OUTPUT_EVENT, p_cb_param, + event_data_size, portMAX_DELAY); + break; + } + default: + break; + } + + if (p_cb_param) { + free(p_cb_param); + p_cb_param = NULL; + } +} + +esp_err_t esp_bt_hidd_dev_init(esp_hidd_dev_t *dev_p, const esp_hid_device_config_t *config, esp_event_handler_t callback) +{ + esp_err_t ret = ESP_OK; + if (dev_p == NULL || config == NULL) { + return ESP_ERR_INVALID_ARG; + } + + if (is_init()) { + ESP_LOGE(TAG, "HID device profile already initialized"); + return ESP_FAIL; + } + + osi_mutex_new(&s_hidd_param.mutex); + if (s_hidd_param.mutex == NULL) { + ESP_LOGE(TAG, "HID device mutex could not be allocated"); + return ESP_ERR_NO_MEM; + } + + s_hidd_param.dev = (esp_bt_hidd_dev_t *)calloc(1, sizeof(esp_bt_hidd_dev_t)); + if (s_hidd_param.dev == NULL) { + ESP_LOGE(TAG, "HID device could not be allocated"); + return ESP_ERR_NO_MEM; + } + + //[1] Reset the hid device target environment + s_hidd_param.dev->connected = false; + s_hidd_param.dev->registered = false; + s_hidd_param.dev->bat_level = 100; + s_hidd_param.dev->control = ESP_HID_CONTROL_EXIT_SUSPEND; + s_hidd_param.dev->protocol_mode = ESP_HID_PROTOCOL_MODE_REPORT; + s_hidd_param.dev->event_loop_handle = NULL; + s_hidd_param.dev->dev = dev_p; + + esp_event_loop_args_t event_task_args = { + .queue_size = 5, + .task_name = "bt_hidd_events", + .task_priority = uxTaskPriorityGet(NULL), + .task_stack_size = 2048, + .task_core_id = tskNO_AFFINITY + }; + ret = esp_event_loop_create(&event_task_args, &s_hidd_param.dev->event_loop_handle); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "HID device event loop could not be created"); + bt_hidd_dev_free(); + return ret; + } + + //[2] parse hid descriptor + ret = bt_hidd_init_config(s_hidd_param.dev, config); + if (ret != ESP_OK) { + bt_hidd_dev_free(); + return ret; + } + + //[3] configure hidd app param and qos param + bt_hidd_init_app(); + bt_hidd_init_qos(); + + //[4] implement the interface + dev_p->dev = s_hidd_param.dev; + dev_p->connected = esp_bt_hidd_dev_connected; + dev_p->disconnect = esp_bt_hidd_dev_disconnect; + dev_p->deinit = esp_bt_hidd_dev_deinit; + dev_p->battery_set = esp_bt_hidd_dev_battery_set; + dev_p->input_set = esp_bt_hidd_dev_input_set; + dev_p->feature_set = esp_bt_hidd_dev_feature_set; + dev_p->event_handler_register = esp_bt_hidd_dev_event_handler_register; + dev_p->event_handler_unregister = esp_bt_hidd_dev_event_handler_unregister; + + ret = esp_bt_hidd_dev_event_handler_register(s_hidd_param.dev, esp_hidd_process_event_data_handler, ESP_EVENT_ANY_ID); + if (ret != ESP_OK) { + bt_hidd_dev_free(); + return ret; + } + + if (callback != NULL) { + ret = esp_bt_hidd_dev_event_handler_register(s_hidd_param.dev, callback, ESP_EVENT_ANY_ID); + if (ret != ESP_OK) { + bt_hidd_dev_free(); + return ret; + } + } + + ret = esp_bt_hid_device_register_callback(bt_hidd_cb); + ret |= esp_bt_hid_device_init(); + if (ret != ESP_OK) { + bt_hidd_dev_free(); + return ret; + } + + return ret; +} +#endif /* CONFIG_BT_HID_DEVICE_ENABLED */ diff --git a/components/esp_hid/src/bt_hidh.c b/components/esp_hid/src/bt_hidh.c index cfaf23584b..6c3ea158d5 100644 --- a/components/esp_hid/src/bt_hidh.c +++ b/components/esp_hid/src/bt_hidh.c @@ -21,202 +21,723 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/semphr.h" - -#include "esp_bt_hh_api.h" +#include "osi/fixed_queue.h" +#include "string.h" +#include "esp_hidh_api.h" static const char *TAG = "BT_HIDH"; -static esp_event_loop_handle_t event_loop_handle; +// element of connection queue +typedef struct { + esp_hidh_dev_t* dev; +} conn_item_t; -static const char *s_bta_hh_evt_names[] = {"ENABLE", "DISABLE", "OPEN", "CLOSE", "GET_RPT", "SET_RPT", "GET_PROTO", "SET_PROTO", "GET_IDLE", "SET_IDLE", "GET_DSCP", "ADD_DEV", "RMV_DEV", "VC_UNPLUG", "DATA", "API_ERR", "UPDATE_SCPP"}; -static const char *s_bta_hh_status_names[] = {"OK", "HS_HID_NOT_READY", "HS_INVALID_RPT_ID", "HS_TRANS_NOT_SPT", "HS_INVALID_PARAM", "HS_ERROR", "ERR", "ERR_SDP", "ERR_PROTO", "ERR_DB_FULL", "ERR_TOD_UNSPT", "ERR_NO_RES", "ERR_AUTH_FAILED", "ERR_HDL", "ERR_SEC"}; +typedef struct { + fixed_queue_t *connection_queue; /* Queue of connection */ + esp_event_loop_handle_t event_loop_handle; +} hidh_local_param_t; -static inline void WAIT_DEV(esp_hidh_dev_t *dev) +static hidh_local_param_t hidh_local_param; +#define TRANS_TO 1000000 // us +#define is_init() (hidh_local_param.event_loop_handle != NULL) + +#define get_protocol_mode(mode) (mode) ? "REPORT" : "BOOT" +static const char *s_esp_hh_evt_names[] = {"INIT", "DEINIT", "OPEN", "CLOSE", "GET_RPT", "SET_RPT", "GET_PROTO", "SET_PROTO", "GET_IDLE", "SET_IDLE", "GET_DSCP", "ADD_DEV", "RMV_DEV", "VC_UNPLUG", "DATA", "DATA_IND", "SET_INFO"}; +static const char *s_esp_hh_status_names[] = {"OK", + "HS_HID_NOT_READY", + "HS_INVALID_RPT_ID", + "HS_TRANS_NOT_SPT", + "HS_INVALID_PARAM", + "HS_ERROR", + "ERR", + "ERR_SDP", + "ERR_PROTO", + "ERR_DB_FULL", + "ERR_TOD_UNSPT", + "ERR_NO_RES", + "ERR_AUTH_FAILED", + "ERR_HDL", + "ERR_SEC", + "BUSY", + "NO_DATA", + "NEED_INIT", + "NEED_DEINIT", + "NO_CONNECTION"}; + +static esp_hidh_dev_t *hidh_dev_ctor(esp_bd_addr_t bda); + +static char *get_trans_type_str(esp_hid_trans_type_t trans_type) { - xSemaphoreTake(dev->semaphore, portMAX_DELAY); + switch (trans_type) { + case ESP_HID_TRANS_HANDSHAKE: + return "TRANS_HANDSHAKE"; + case ESP_HID_TRANS_CONTROL: + return "TRANS_CONTROL"; + case ESP_HID_TRANS_GET_REPORT: + return "TRANS_GET_REPORT"; + case ESP_HID_TRANS_SET_REPORT: + return "TRANS_SET_REPORT"; + case ESP_HID_TRANS_GET_PROTOCOL: + return "TRANS_GET_PROTOCOL"; + case ESP_HID_TRANS_SET_PROTOCOL: + return "TRANS_SET_PROTOCOL"; + case ESP_HID_TRANS_GET_IDLE: + return "TRANS_GET_IDLE"; + case ESP_HID_TRANS_SET_IDLE: + return "TRANS_SET_IDLE"; + case ESP_HID_TRANS_DATA: + return "TRANS_DATA"; + case ESP_HID_TRANS_DATAC: + return "TRANS_DATAC"; + case ESP_HID_TRANS_MAX: + return "TRANS_MAX"; + default: + return "UNKOWN"; + } } -static inline void SEND_DEV(esp_hidh_dev_t *dev) +static esp_err_t bt_hidh_get_status(esp_hidh_status_t status) { - xSemaphoreGive(dev->semaphore); + esp_err_t ret = ESP_OK; + switch (status) { + case ESP_HIDH_OK: + ret = ESP_OK; + break; + case ESP_HIDH_ERR_NO_RES: + ret = ESP_ERR_NO_MEM; + break; + default: + ret = ESP_FAIL; + break; + } + return ret; } -static void bta_hh_cb(tBTA_HH_EVT event, tBTA_HH *p_data) +static void utl_freebuf(void **p) { - static esp_hidh_dev_t *descr_dev = NULL; + if (*p != NULL) { + free(*p); + *p = NULL; + } +} + +static void transaction_timeout_handler(void *arg) +{ + esp_hidh_dev_t *dev = (esp_hidh_dev_t *)arg; + if (dev != NULL && esp_hidh_dev_exists(dev)) { + ESP_LOGW(TAG, "transaction timeout!"); + esp_hidh_dev_lock(dev); + dev->trans_type = ESP_HID_TRANS_MAX; + dev->report_id = 0; + dev->report_type = 0; + esp_hidh_dev_unlock(dev); + } +} + +static inline void set_trans(esp_hidh_dev_t *dev, esp_hid_trans_type_t trans_type) +{ + dev->trans_type = trans_type; + if (dev->trans_timer == NULL) { + esp_timer_create_args_t config = { + .callback = &transaction_timeout_handler, + .arg = (void *)dev, + .name = "hid_trans" + }; + if (esp_timer_create(&config, &dev->trans_timer) != ESP_OK) { + ESP_LOGE(TAG, "create trans timer failed! trans:%s", get_trans_type_str(trans_type)); + return; + } + } + if (!esp_timer_is_active(dev->trans_timer) && esp_timer_start_once(dev->trans_timer, TRANS_TO) != ESP_OK) { + ESP_LOGE(TAG, "set trans timer failed! trans:%s", get_trans_type_str(trans_type)); + } +} + +static inline void reset_trans(esp_hidh_dev_t *dev) +{ + esp_hidh_dev_lock(dev); + dev->trans_type = ESP_HID_TRANS_MAX; + dev->report_id = 0; + dev->report_type = 0; + if (dev->trans_timer) { + esp_timer_stop(dev->trans_timer); + } + esp_hidh_dev_unlock(dev); +} + +static inline bool is_trans_done(esp_hidh_dev_t *dev) +{ + bool ret = (dev->trans_type == ESP_HID_TRANS_MAX); + return ret; +} + +static void free_local_param(void) +{ + if (hidh_local_param.event_loop_handle) { + esp_event_loop_delete(hidh_local_param.event_loop_handle); + } + + if (hidh_local_param.connection_queue) { + fixed_queue_free(hidh_local_param.connection_queue, free); + } +} + +static void open_failed_cb(esp_hidh_dev_t *dev, esp_hidh_status_t status, esp_hidh_event_data_t *p, + size_t event_data_size) +{ + p->open.status = bt_hidh_get_status(status); + p->open.dev = dev; + if (dev != NULL) { + esp_hidh_dev_lock(dev); + if (dev->connected) { + esp_bt_hid_host_disconnect(dev->bda); + } else { + dev->in_use = false; + } + esp_hidh_dev_unlock(dev); + } + esp_event_post_to(hidh_local_param.event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_OPEN_EVENT, p, event_data_size, + portMAX_DELAY); +} + +static void esp_hh_cb(esp_hidh_cb_event_t event, esp_hidh_cb_param_t *param) +{ + conn_item_t *conn_item = NULL; esp_hidh_dev_t *dev = NULL; + esp_hidh_dev_report_t *report = NULL; + bool has_report_id = false; + size_t data_len = 0; + uint8_t *p_data = NULL; + esp_hidh_event_data_t p = {0}; + esp_hidh_event_data_t *p_param = NULL; + size_t event_data_size = sizeof(esp_hidh_event_data_t); + switch (event) { - case BTA_HH_ENABLE_EVT: { - if (p_data->status) { - ESP_LOGE(TAG, "ENABLE ERROR: %s", s_bta_hh_status_names[p_data->status]); + case ESP_HIDH_INIT_EVT: { + p.start.status = bt_hidh_get_status(param->init.status); + esp_event_post_to(hidh_local_param.event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_START_EVENT, &p, + event_data_size, portMAX_DELAY); + if (param->init.status != ESP_HIDH_OK) { + ESP_LOGE(TAG, "ENABLE ERROR: %s", s_esp_hh_status_names[param->init.status]); + free_local_param(); } - } break; - case BTA_HH_OPEN_EVT: { - dev = esp_hidh_dev_get_by_handle(p_data->conn.handle); - if (dev == NULL) { - ESP_LOGE(TAG, "OPEN ERROR: Device Not Found"); - return; - } - dev->status = p_data->conn.status; - memcpy(dev->bda, p_data->conn.bda, sizeof(esp_bd_addr_t)); - if (dev->status == BTA_HH_OK) { - descr_dev = dev; - BTA_HhGetDscpInfo(dev->bt.handle); + break; + } + case ESP_HIDH_DEINIT_EVT: { + p.stop.status = bt_hidh_get_status(param->deinit.status); + esp_event_post_to(hidh_local_param.event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_STOP_EVENT, &p, + event_data_size, portMAX_DELAY); + if (param->deinit.status != ESP_HIDH_OK) { + ESP_LOGE(TAG, "DISABLE ERROR: %s", s_esp_hh_status_names[param->deinit.status]); } else { - ESP_LOGE(TAG, "OPEN ERROR: %s", s_bta_hh_status_names[dev->status]); - if (dev->opened) { - SEND_DEV(dev); - } else { - esp_hidh_dev_free(dev); - } + free_local_param(); + } + break; + } + case ESP_HIDH_OPEN_EVT: { + if (param->open.conn_status == ESP_HIDH_CONN_STATE_CONNECTING) { + // ignore this conn_status + break; } - } break; - case BTA_HH_GET_DSCP_EVT: { - ESP_LOGV(TAG, "DESCRIPTOR: PID: 0x%04x, VID: 0x%04x, VERSION: 0x%04x, REPORT_LEN: %u", p_data->dscp_info.product_id, p_data->dscp_info.vendor_id, p_data->dscp_info.version, p_data->dscp_info.descriptor.dl_len); - if (descr_dev == NULL) { - ESP_LOGE(TAG, "Device Not Found"); - return; - } - dev = descr_dev; - dev->config.product_id = p_data->dscp_info.product_id; - dev->config.vendor_id = p_data->dscp_info.vendor_id; - dev->config.version = p_data->dscp_info.version; - - - dev->config.report_maps_len = 1; - dev->config.report_maps = (esp_hid_raw_report_map_t *)malloc(dev->config.report_maps_len * sizeof(esp_hid_raw_report_map_t)); - if (dev->config.report_maps == NULL) { - ESP_LOGE(TAG, "malloc report maps failed"); - return; - } - - dev->config.report_maps[0].data = (uint8_t *)malloc(p_data->dscp_info.descriptor.dl_len); - if (dev->config.report_maps[0].data == NULL) { - ESP_LOGE(TAG, "Malloc Report Map Failed"); - dev->status = BTA_HH_ERR_NO_RES; - } else { - dev->config.report_maps[0].len = p_data->dscp_info.descriptor.dl_len; - memcpy((uint8_t *)dev->config.report_maps[0].data, p_data->dscp_info.descriptor.dsc_list, dev->config.report_maps[0].len); - //generate reports - - if (dev->config.report_maps[0].len && dev->config.report_maps[0].data) { - esp_hid_report_map_t *map; - esp_hidh_dev_report_t *report; - esp_hid_report_item_t *r; - map = esp_hid_parse_report_map(dev->config.report_maps[0].data, dev->config.report_maps[0].len); - if (map) { - if (dev->usage == 0) { - dev->usage = map->usage; - } - dev->connected = true; - dev->reports = NULL; - for (uint8_t i = 0; i < map->reports_len; i++) { - r = &map->reports[i]; - report = (esp_hidh_dev_report_t *)malloc(sizeof(esp_hidh_dev_report_t)); - if (report == NULL) { - ESP_LOGE(TAG, "Malloc Report Failed"); - dev->status = BTA_HH_ERR_NO_RES; - dev->connected = false; + do { + dev = esp_hidh_dev_get_by_bda(param->open.bd_addr); + if (dev == NULL) { + if (param->open.is_orig) { + ESP_LOGE(TAG, "OPEN ERROR: Device Not Found"); + param->open.status = ESP_HIDH_NO_CONNECTION; + break; + } else { + ESP_LOGD(TAG, "incoming device connect"); + if (param->open.status == ESP_HIDH_OK) { + if ((dev = hidh_dev_ctor(param->open.bd_addr)) == NULL) { + ESP_LOGE(TAG, "%s create device failed!", __func__); + param->open.status = ESP_HIDH_ERR_NO_RES; break; } - report->map_index = 0; - report->protocol_mode = r->protocol_mode; - report->report_type = r->report_type; - report->report_id = r->report_id; - report->value_len = r->value_len; - report->usage = r->usage; - report->next = dev->reports; - dev->reports = report; + esp_hidh_dev_lock(dev); + dev->opened = false; // not opened by ourself + dev->is_orig = false; + esp_hidh_dev_unlock(dev); } - dev->reports_len = map->reports_len; - free(map->reports); - free(map); - map = NULL; - } else { - ESP_LOGE(TAG, "Parse Report Map Failed"); - dev->status = BTA_HH_ERR; } } + if (param->open.status != ESP_HIDH_OK) { + break; + } + esp_hidh_dev_lock(dev); + dev->connected = true; + dev->bt.handle = param->open.handle; + esp_hidh_dev_unlock(dev); + conn_item = malloc(sizeof(conn_item_t)); + if (conn_item == NULL) { + ESP_LOGE(TAG, "conn_item malloc failed!"); + param->open.status = ESP_HIDH_ERR_NO_RES; + break; + } + conn_item->dev = dev; + bool ret = fixed_queue_enqueue(hidh_local_param.connection_queue, conn_item, FIXED_QUEUE_MAX_TIMEOUT); + assert(ret == true); + } while (0); + + if (param->open.status != ESP_HIDH_OK) { + ESP_LOGE(TAG, "OPEN ERROR: %s", s_esp_hh_status_names[param->open.status]); + open_failed_cb(dev, param->open.status, &p, event_data_size); } - descr_dev = NULL; - if (dev->status == BTA_HH_OK) { - BTA_HhAddDev(dev->bda, dev->bt.attr_mask, dev->bt.sub_class, dev->bt.app_id, p_data->dscp_info); - } else { - ESP_LOGE(TAG, "Read Report Map Failed, status: %s", s_bta_hh_status_names[dev->status]); - if (dev->opened) { - SEND_DEV(dev); + + if (dev != NULL) { + esp_hidh_dev_lock(dev); + dev->status = param->open.status; + esp_hidh_dev_unlock(dev); + } + break; + } + case ESP_HIDH_GET_DSCP_EVT: { + do { + ESP_LOGV(TAG, "DESCRIPTOR: PID: 0x%04x, VID: 0x%04x, VERSION: 0x%04x, REPORT_LEN: %u", + param->dscp.product_id, param->dscp.vendor_id, param->dscp.version, param->dscp.dl_len); + if ((conn_item = (conn_item_t *)fixed_queue_dequeue(hidh_local_param.connection_queue, + FIXED_QUEUE_MAX_TIMEOUT)) == NULL) { + ESP_LOGE(TAG, "No pending connect device!"); + param->dscp.status = ESP_HIDH_NO_CONNECTION; + break; + } + dev = conn_item->dev; + utl_freebuf((void **)&conn_item); + // in case the dev has been freed + if (!esp_hidh_dev_exists(dev)) { + ESP_LOGE(TAG, "Device Not Found"); + dev = NULL; + param->dscp.status = ESP_HIDH_NO_CONNECTION; + break; + } + // check if connected + esp_hidh_dev_lock(dev); + if (!dev->connected) { + esp_hidh_dev_unlock(dev); + ESP_LOGE(TAG, "Connection has been released!"); + param->dscp.status = ESP_HIDH_NO_CONNECTION; + break; + } + // check if get descriptor failed + if (param->dscp.status != ESP_HIDH_OK) { + esp_hidh_dev_unlock(dev); + ESP_LOGE(TAG, "GET_DSCP ERROR: %s", s_esp_hh_status_names[param->dscp.status]); + break; + } + dev->added = param->dscp.added; + dev->config.product_id = param->dscp.product_id; + dev->config.vendor_id = param->dscp.vendor_id; + dev->config.version = param->dscp.version; + + dev->config.report_maps_len = 1; + dev->config.report_maps = + (esp_hid_raw_report_map_t *)malloc(dev->config.report_maps_len * sizeof(esp_hid_raw_report_map_t)); + if (dev->config.report_maps == NULL) { + esp_hidh_dev_unlock(dev); + ESP_LOGE(TAG, "malloc report maps failed"); + param->dscp.status = ESP_HIDH_ERR_NO_RES; + break; + } + + dev->config.report_maps[0].data = (uint8_t *)malloc(param->dscp.dl_len); + if (dev->config.report_maps[0].data == NULL) { + ESP_LOGE(TAG, "Malloc Report Map Failed"); + param->dscp.status = ESP_HIDH_ERR_NO_RES; } else { - esp_hidh_dev_free(dev); + dev->config.report_maps[0].len = param->dscp.dl_len; + memcpy((uint8_t *)dev->config.report_maps[0].data, param->dscp.dsc_list, + dev->config.report_maps[0].len); + // generate reports + + if (dev->config.report_maps[0].len && dev->config.report_maps[0].data) { + esp_hid_report_map_t *map; + esp_hidh_dev_report_t *report; + esp_hid_report_item_t *r; + map = esp_hid_parse_report_map(dev->config.report_maps[0].data, dev->config.report_maps[0].len); + if (map) { + if (dev->usage == 0) { + dev->usage = map->usage; + } + dev->reports = NULL; + for (uint8_t i = 0; i < map->reports_len; i++) { + r = &map->reports[i]; + report = (esp_hidh_dev_report_t *)malloc(sizeof(esp_hidh_dev_report_t)); + if (report == NULL) { + ESP_LOGE(TAG, "Malloc Report Failed"); + param->dscp.status = ESP_HIDH_ERR_NO_RES; + break; + } + report->map_index = 0; + report->protocol_mode = r->protocol_mode; + report->report_type = r->report_type; + report->report_id = r->report_id; + report->value_len = r->value_len; + report->usage = r->usage; + report->next = dev->reports; + dev->reports = report; + } + dev->reports_len = map->reports_len; + free(map->reports); + free(map); + map = NULL; + } else { + ESP_LOGE(TAG, "Parse Report Map Failed"); + param->dscp.status = ESP_HIDH_ERR; + } + } + } + esp_hidh_dev_unlock(dev); + } while (0); + + if (param->dscp.status != ESP_HIDH_OK) { + open_failed_cb(dev, param->dscp.status, &p, event_data_size); + } + + if (dev != NULL) { + esp_hidh_dev_lock(dev); + dev->status = param->dscp.status; + // if has been added by lower layer, tell up layer + if (dev->status == ESP_HIDH_OK && dev->connected && dev->added) { + p.open.status = bt_hidh_get_status(ESP_HIDH_OK); + p.open.dev = dev; + esp_hidh_dev_unlock(dev); + esp_event_post_to(hidh_local_param.event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_OPEN_EVENT, &p, + event_data_size, portMAX_DELAY); + } else { + esp_hidh_dev_unlock(dev); } } - } break; - case BTA_HH_ADD_DEV_EVT: { - ESP_LOGV(TAG, "ADD_DEV: BDA: " ESP_BD_ADDR_STR ", handle: %d, status: %s", ESP_BD_ADDR_HEX(p_data->dev_info.bda), p_data->dev_info.handle, s_bta_hh_status_names[p_data->dev_info.status]); - dev = esp_hidh_dev_get_by_handle(p_data->conn.handle); - if (dev == NULL) { - ESP_LOGE(TAG, "Device Not Found"); - return; - } - dev->status = p_data->conn.status; - if (dev->status == BTA_HH_OK) { - esp_hidh_event_data_t p; - p.open.dev = dev; - esp_event_post_to(event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_OPEN_EVENT, &p, sizeof(esp_hidh_event_data_t), portMAX_DELAY); - } else { - ESP_LOGE(TAG, "Device Add Failed, status: %s", s_bta_hh_status_names[dev->status]); - } - if (dev->opened) { - SEND_DEV(dev); - } else if (dev->status != BTA_HH_OK) { - esp_hidh_dev_free(dev); - } - } break; - case BTA_HH_CLOSE_EVT: { - ESP_LOGV(TAG, "CLOSE: handle: %d, status: %s", p_data->dev_status.handle, s_bta_hh_status_names[p_data->dev_status.status]); - dev = esp_hidh_dev_get_by_handle(p_data->dev_status.handle); - if (dev == NULL) { - ESP_LOGE(TAG, "Device Not Found"); - return; - } - dev->status = p_data->dev_status.status; - esp_hidh_event_data_t p; - p.close.dev = dev; - p.close.reason = 0; - esp_event_post_to(event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_CLOSE_EVENT, &p, sizeof(esp_hidh_event_data_t), portMAX_DELAY); - } break; - case BTA_HH_SET_RPT_EVT: { - dev = esp_hidh_dev_get_by_handle(p_data->dev_status.handle); - if (dev == NULL) { - ESP_LOGE(TAG, "SET_RPT ERROR: hDevice Not Found"); - return; - } - if (p_data->dev_status.status) { - ESP_LOGE(TAG, "SET_RPT ERROR: handle: %d, status: %s", p_data->dev_status.handle, s_bta_hh_status_names[p_data->dev_status.status]); - } - dev->status = p_data->dev_status.status; - SEND_DEV(dev); - } break; - case BTA_HH_GET_RPT_EVT: { - dev = esp_hidh_dev_get_by_handle(p_data->hs_data.handle); - if (dev == NULL) { - ESP_LOGE(TAG, "Device Not Found"); - return; - } - if (p_data->hs_data.status) { - ESP_LOGE(TAG, "GET_RPT ERROR: handle: %d, status: %s", p_data->hs_data.handle, s_bta_hh_status_names[p_data->hs_data.status]); - } - dev->status = p_data->hs_data.status; - BT_HDR *rpt = p_data->hs_data.rsp_data.p_rpt_data; - dev->tmp = rpt->data + rpt->offset; - dev->tmp_len = rpt->len; - SEND_DEV(dev); - } break; - default: - ESP_LOGV(TAG, "BTA_HH EVENT: %s", s_bta_hh_evt_names[event]); break; } + case ESP_HIDH_ADD_DEV_EVT: { + ESP_LOGV(TAG, "ADD_DEV: BDA: " ESP_BD_ADDR_STR ", handle: %d, status: %s", + ESP_BD_ADDR_HEX(param->add_dev.bd_addr), param->add_dev.handle, + s_esp_hh_status_names[param->add_dev.status]); + do { + dev = esp_hidh_dev_get_by_handle(param->add_dev.handle); + if (dev == NULL) { + ESP_LOGE(TAG, "Device Not Found"); + param->add_dev.status = ESP_HIDH_NO_CONNECTION; + break; + } + esp_hidh_dev_lock(dev); + dev->added = param->add_dev.status == ESP_HIDH_OK ? true : false; + esp_hidh_dev_unlock(dev); + } while(0); + + if (param->add_dev.status != ESP_HIDH_OK) { + ESP_LOGE(TAG, "ADD_DEV ERROR: %s", s_esp_hh_status_names[param->add_dev.status]); + open_failed_cb(dev, param->add_dev.status, &p, event_data_size); + } + if (dev != NULL) { + esp_hidh_dev_lock(dev); + dev->status = param->add_dev.status; + if (dev->status == ESP_HIDH_OK && dev->connected && dev->added) { + p.open.status = bt_hidh_get_status(ESP_HIDH_OK); + p.open.dev = dev; + esp_hidh_dev_unlock(dev); + esp_event_post_to(hidh_local_param.event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_OPEN_EVENT, &p, + event_data_size, portMAX_DELAY); + } else { + esp_hidh_dev_unlock(dev); + } + } + break; + } + case ESP_HIDH_CLOSE_EVT: { + if (param->close.conn_status == ESP_HIDH_CONN_STATE_DISCONNECTING) { + // ignore this conn_status + break; + } + ESP_LOGV(TAG, "CLOSE: handle: %d, status: %s", param->close.handle, s_esp_hh_status_names[param->close.status]); + do { + dev = esp_hidh_dev_get_by_handle(param->close.handle); + if (dev == NULL) { + ESP_LOGE(TAG, "Device Not Found"); + param->close.status = ESP_HIDH_NO_CONNECTION; + break; + } + esp_hidh_dev_lock(dev); + dev->status = param->close.status; + if (dev->connected) { + dev->connected = false; + } + // free the device in the wrapper event handler + dev->in_use = false; + esp_hidh_dev_unlock(dev); + } while(0); + + if (param->close.status != ESP_HIDH_OK) { + ESP_LOGE(TAG, "CLOSE ERROR: %s", s_esp_hh_status_names[param->close.status]); + } + p.close.dev = dev; + p.close.status = bt_hidh_get_status(param->close.status); + esp_event_post_to(hidh_local_param.event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_CLOSE_EVENT, &p, + event_data_size, portMAX_DELAY); + + break; + } + case ESP_HIDH_SET_RPT_EVT: { + if (param->set_rpt.status != ESP_HIDH_OK) { + ESP_LOGE(TAG, "SET_RPT ERROR: handle: %d, status: %s", param->set_rpt.handle, + s_esp_hh_status_names[param->set_rpt.status]); + } + dev = esp_hidh_dev_get_by_handle(param->set_rpt.handle); + if (dev == NULL) { + ESP_LOGE(TAG, "SET_RPT ERROR: Device Not Found"); + break; + } + esp_hidh_dev_lock(dev); + dev->status = param->set_rpt.status; + p.feature.dev = dev; + esp_hidh_dev_unlock(dev); + p.feature.status = bt_hidh_get_status(param->set_rpt.status); + p.feature.trans_type = ESP_HID_TRANS_SET_REPORT; + esp_event_post_to(hidh_local_param.event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_FEATURE_EVENT, &p, + event_data_size, portMAX_DELAY); + reset_trans(dev); + break; + } + case ESP_HIDH_GET_RPT_EVT: { + if (param->get_rpt.status != ESP_HIDH_OK) { + ESP_LOGE(TAG, "GET_RPT ERROR: handle: %d, status: %s", param->get_rpt.handle, + s_esp_hh_status_names[param->get_rpt.status]); + } else if (param->get_rpt.len > 0 && param->get_rpt.data) { + event_data_size += param->get_rpt.len; + } + dev = esp_hidh_dev_get_by_handle(param->get_rpt.handle); + if (dev == NULL) { + ESP_LOGE(TAG, "GET_RPT ERROR: Device Not Found"); + break; + } + esp_hidh_dev_lock(dev); + dev->status = param->get_rpt.status; + if ((p_param = (esp_hidh_event_data_t *)malloc(event_data_size)) != NULL) { + memset(p_param, 0, event_data_size); + p_param->feature.dev = dev; + p_param->feature.status = bt_hidh_get_status(param->get_rpt.status); + p_param->feature.trans_type = ESP_HID_TRANS_GET_REPORT; + if (param->get_rpt.status == ESP_HIDH_OK && param->get_rpt.len > 0 && param->get_rpt.data) { + if (dev->report_id) { + data_len = param->get_rpt.len - 1; + p_data = (uint8_t *)param->get_rpt.data + 1; + } else { + data_len = param->get_rpt.len; + p_data = (uint8_t *)param->get_rpt.data; + } + memcpy(((uint8_t *)p_param) + sizeof(esp_hidh_event_data_t), p_data, data_len); + p_param->feature.length = data_len; + p_param->feature.data = p_data; + p_param->feature.report_id = dev->report_id; + esp_hidh_dev_unlock(dev); + } + esp_event_post_to(hidh_local_param.event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_FEATURE_EVENT, p_param, + event_data_size, portMAX_DELAY); + } else { + esp_hidh_dev_unlock(dev); + ESP_LOGE(TAG, "GET_RPT ERROR: malloc event data failed!"); + } + reset_trans(dev); + break; + } + case ESP_HIDH_GET_IDLE_EVT:{ + if (param->get_idle.status != ESP_HIDH_OK) { + ESP_LOGE(TAG, "GET_IDLE ERROR: handle: %d, status: %s", param->get_idle.handle, + s_esp_hh_status_names[param->get_idle.status]); + } else { + event_data_size += 1; + } + dev = esp_hidh_dev_get_by_handle(param->get_idle.handle); + if (dev == NULL) { + ESP_LOGE(TAG, "GET_IDLE ERROR: Device Not Found"); + break; + } + esp_hidh_dev_lock(dev); + dev->status = param->get_idle.status; + if ((p_param = (esp_hidh_event_data_t *)malloc(event_data_size)) != NULL) { + memset(p_param, 0, event_data_size); + p_param->feature.dev = dev; + p_param->feature.status = bt_hidh_get_status(param->get_idle.status); + p_param->feature.trans_type = ESP_HID_TRANS_GET_IDLE; + if (param->get_idle.status == ESP_HIDH_OK) { + *(((uint8_t *)p_param) + sizeof(esp_hidh_event_data_t)) = param->get_idle.idle_rate; + p_param->feature.length = 1; + p_param->feature.data = ((uint8_t *)p_param) + sizeof(esp_hidh_event_data_t); + } + esp_hidh_dev_unlock(dev); + esp_event_post_to(hidh_local_param.event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_FEATURE_EVENT, p_param, + event_data_size, portMAX_DELAY); + } else { + esp_hidh_dev_unlock(dev); + ESP_LOGE(TAG, "GET_IDLE ERROR: malloc event data failed!"); + } + reset_trans(dev); + break; + } + case ESP_HIDH_SET_IDLE_EVT: { + if (param->set_idle.status != ESP_HIDH_OK) { + ESP_LOGE(TAG, "SET_IDLE ERROR: handle: %d, status: %s", param->set_idle.handle, + s_esp_hh_status_names[param->set_idle.status]); + } + dev = esp_hidh_dev_get_by_handle(param->set_idle.handle); + if (dev == NULL) { + ESP_LOGE(TAG, "SET_IDLE ERROR: Device Not Found"); + break; + } + esp_hidh_dev_lock(dev); + dev->status = param->set_idle.status; + p.feature.dev = dev; + esp_hidh_dev_unlock(dev); + p.feature.status = bt_hidh_get_status(param->set_idle.status); + p.feature.trans_type = ESP_HID_TRANS_SET_IDLE; + esp_event_post_to(hidh_local_param.event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_FEATURE_EVENT, &p, + event_data_size, portMAX_DELAY); + reset_trans(dev); + break; + } + case ESP_HIDH_GET_PROTO_EVT: { + if (param->get_proto.status != ESP_HIDH_OK) { + ESP_LOGE(TAG, "GET_PROTO ERROR: handle: %d, status: %s", param->get_proto.handle, + s_esp_hh_status_names[param->get_proto.status]); + } else { + event_data_size += 1; + } + dev = esp_hidh_dev_get_by_handle(param->get_proto.handle); + if (dev == NULL) { + ESP_LOGE(TAG, "GET_PROTO ERROR: Device Not Found"); + break; + } + esp_hidh_dev_lock(dev); + dev->status = param->get_proto.status; + if ((p_param = (esp_hidh_event_data_t *)malloc(event_data_size)) != NULL) { + memset(p_param, 0, event_data_size); + p_param->feature.dev = dev; + p_param->feature.status = bt_hidh_get_status(param->get_proto.status); + p_param->feature.trans_type = ESP_HID_TRANS_GET_PROTOCOL; + if (param->get_proto.status == ESP_HIDH_OK) { + dev->protocol_mode = param->get_proto.proto_mode; // update the device protocol mode + *(((uint8_t *)p_param) + sizeof(esp_hidh_event_data_t)) = param->get_proto.proto_mode; + p_param->feature.length = 1; + p_param->feature.data = ((uint8_t *)p_param) + sizeof(esp_hidh_event_data_t); + } + esp_hidh_dev_unlock(dev); + esp_event_post_to(hidh_local_param.event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_FEATURE_EVENT, p_param, + event_data_size, portMAX_DELAY); + } else { + esp_hidh_dev_unlock(dev); + ESP_LOGE(TAG, "GET_PROTO ERROR: malloc event data failed!"); + } + reset_trans(dev); + break; + } + case ESP_HIDH_SET_PROTO_EVT: { + if (param->set_proto.status != ESP_HIDH_OK) { + ESP_LOGE(TAG, "SET_PROTO ERROR: handle: %d, status: %s", param->set_proto.handle, + s_esp_hh_status_names[param->set_proto.status]); + } + dev = esp_hidh_dev_get_by_handle(param->set_proto.handle); + if (dev == NULL) { + ESP_LOGE(TAG, "Device Not Found"); + break; + } + esp_hidh_dev_lock(dev); + dev->status = param->set_proto.status; + p.feature.dev = dev; + esp_hidh_dev_unlock(dev); + p.feature.status = bt_hidh_get_status(param->set_proto.status); + p.feature.trans_type = ESP_HID_TRANS_SET_PROTOCOL; + esp_event_post_to(hidh_local_param.event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_FEATURE_EVENT, &p, + event_data_size, portMAX_DELAY); + reset_trans(dev); + break; + } + case ESP_HIDH_DATA_IND_EVT: { + esp_hid_usage_t _usage; + if (param->data_ind.status != ESP_HIDH_OK) { + ESP_LOGE(TAG, "DATA_IND ERROR: handle: %d, status: %s", param->data_ind.handle, + s_esp_hh_status_names[param->data_ind.status]); + } + dev = esp_hidh_dev_get_by_handle(param->data_ind.handle); + if (dev == NULL) { + ESP_LOGE(TAG, "Device Not Found: handle %u", param->data_ind.handle); + break; + } + + if (param->data_ind.len > 0 && param->data_ind.data != NULL) { + esp_hidh_dev_lock(dev); + event_data_size += param->data_ind.len; + if (param->data_ind.proto_mode == ESP_HID_PROTOCOL_MODE_BOOT) { + /** + * first data shall have report_id, according to HID_SPEC_V10 + * | Device | Report ID | Report Size | + * -------------------------------------- + * | Keyboard | 1 | 9 Bytes | + * | Mouse | 2 | 4 Bytes | + * | Reserved | 0, 3-255 | N/A | + */ + if (param->data_ind.len == 9 && *(param->data_ind.data) == 1) { + has_report_id = true; + _usage = ESP_HID_USAGE_KEYBOARD; + } else if (param->data_ind.len == 4 && *(param->data_ind.data) == 2) { + has_report_id = true; + _usage = ESP_HID_USAGE_MOUSE; + } else { + esp_hidh_dev_unlock(dev); + ESP_LOGE(TAG, "Invalid Boot Report format, rpt_len:%d, rpt_id:%d!", param->data_ind.len, + *(param->data_ind.data)); + break; + } + } else { + report = esp_hidh_dev_get_input_report_by_proto_and_data( + dev, ESP_HID_PROTOCOL_MODE_REPORT, param->data_ind.len, param->data_ind.data, &has_report_id); + if (report == NULL) { + esp_hidh_dev_unlock(dev); + ESP_LOGE(TAG, "Not find report handle: %d mode: %s", param->data_ind.handle, + param->data_ind.proto_mode == ESP_HID_PROTOCOL_MODE_REPORT ? "REPORT" : "BOOT"); + break; + } + _usage = report->usage; + } + + if ((p_param = (esp_hidh_event_data_t *)malloc(event_data_size)) == NULL) { + esp_hidh_dev_unlock(dev); + ESP_LOGE(TAG, "DATA_IND ERROR: malloc event data failed!"); + break; + } + memset(p_param, 0, event_data_size); + p_param->input.dev = dev; + p_param->input.usage = _usage; + if (has_report_id) { + data_len = param->data_ind.len - 1; + p_data = (uint8_t *)param->data_ind.data + 1; + p_param->input.report_id = *(uint8_t *)param->data_ind.data; + } else { + data_len = param->data_ind.len; + p_data = (uint8_t *)param->data_ind.data; + p_param->input.report_id = report->report_id; + } + memcpy(((uint8_t *)p_param) + sizeof(esp_hidh_event_data_t), p_data, data_len); + p_param->input.length = data_len; + p_param->input.data = p_data; + esp_hidh_dev_unlock(dev); + esp_event_post_to(hidh_local_param.event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_INPUT_EVENT, p_param, + event_data_size, portMAX_DELAY); + } + break; + } + case ESP_HIDH_DATA_EVT: + break; + default: + ESP_LOGV(TAG, "BTA_HH EVENT: %s", s_esp_hh_evt_names[event]); + break; + } + + if (p_param) { + free(p_param); + p_param = NULL; + } } /* @@ -225,91 +746,244 @@ static void bta_hh_cb(tBTA_HH_EVT event, tBTA_HH *p_data) static esp_err_t esp_bt_hidh_dev_close(esp_hidh_dev_t *dev) { - BTA_HhClose(dev->bt.handle); - return ESP_OK; + esp_err_t ret = ESP_OK; + do { + if (dev == NULL) { + ret = ESP_ERR_INVALID_ARG; + break; + } + if (!dev->connected) { + ESP_LOGW(TAG, "%s hdl:0x%02x not connected", __func__, dev->bt.handle); + ret = ESP_ERR_INVALID_STATE; + break; + } + ret = esp_bt_hid_host_disconnect(dev->bda); + } while (0); + return ret; } -static esp_err_t esp_bt_hidh_dev_report_write(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, int report_type, uint8_t *data, size_t len) +static esp_err_t esp_bt_hidh_dev_report_write(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, + int report_type, uint8_t *data, size_t len) { - esp_hidh_dev_report_t *report = esp_hidh_dev_get_report_by_id_and_type(dev, map_index, report_id, report_type); - if (!report) { - ESP_LOGE(TAG, "%s report %d not found", esp_hid_report_type_str(report_type), report_id); - return ESP_FAIL; - } - if (len > report->value_len) { - ESP_LOGE(TAG, "%s report %d takes maximum %d bytes. you have provided %d", esp_hid_report_type_str(report_type), report_id, report->value_len, len); - return ESP_FAIL; - } + esp_err_t ret = ESP_OK; + uint8_t *p_data = NULL; + do { + esp_hidh_dev_report_t *report = + esp_hidh_dev_get_report_by_id_type_proto(dev, map_index, report_id, report_type, dev->protocol_mode); + if (!report) { + ESP_LOGE(TAG, "mode:%s report:%s id:%d not found", get_protocol_mode(dev->protocol_mode), + esp_hid_report_type_str(report_type), report_id); + ret = ESP_FAIL; + break; + } + if (len > report->value_len) { + ESP_LOGE(TAG, "%s report %d takes maximum %d bytes. you have provided %d", + esp_hid_report_type_str(report_type), report_id, report->value_len, len); + ret = ESP_FAIL; + break; + } -#define BT_HDR_HID_DATA_OFFSET 14 //this equals to L2CAP_MIN_OFFSET + 1 (1 byte to hold the HID transaction header) + if (report_type != ESP_HID_REPORT_TYPE_OUTPUT) { + ESP_LOGE(TAG, + "Only OUTPUT type data can be send on interrupt channel.\n" \ + "You have provided %s, try Set_Report!", + esp_hid_report_type_str(report_type)); + ret = ESP_FAIL; + break; + } - uint8_t *pbuf_data; - BT_HDR *p_buf = (BT_HDR *)malloc((uint16_t) (len + 1 + BT_HDR_HID_DATA_OFFSET + sizeof(BT_HDR))); - - if (p_buf == NULL) { - ESP_LOGE(TAG, "Could not allocate BT_HDR buffer"); - return ESP_ERR_NO_MEM; - } - - p_buf->len = len + 1; - p_buf->offset = BT_HDR_HID_DATA_OFFSET; - - pbuf_data = (uint8_t *) (p_buf + 1) + p_buf->offset; - pbuf_data[0] = report_id; - memcpy(pbuf_data + 1, data, len); - - if (report_type == ESP_HID_REPORT_TYPE_OUTPUT) { - p_buf->layer_specific = BTA_HH_RPTT_OUTPUT; - BTA_HhSendData(dev->bt.handle, dev->bda, p_buf); - } else { - BTA_HhSetReport(dev->bt.handle, report_type, p_buf); - WAIT_DEV(dev); - } - if (dev->status) { - ESP_LOGE(TAG, "Write %s: %s", esp_hid_report_type_str(report_type), s_bta_hh_status_names[dev->status]); - return ESP_FAIL; - } - return ESP_OK; + if (report_id) { + if ((p_data = malloc(len + 1)) == NULL) { + ESP_LOGE(TAG, "%s malloc failed!", __func__); + ret = ESP_FAIL; + break; + } + *p_data = report_id; + memcpy(p_data + 1, data, len); + data = p_data; + len = len + 1; + } + ret = esp_bt_hid_host_send_data(dev->bda, data, len); + } while (0); + return ret; } -static esp_err_t esp_bt_hidh_dev_report_read(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, int report_type, size_t max_length, uint8_t *value, size_t *value_len) +static esp_err_t esp_bt_hidh_dev_set_report(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, + int report_type, uint8_t *data, size_t len) { - esp_hidh_dev_report_t *report = esp_hidh_dev_get_report_by_id_and_type(dev, map_index, report_id, report_type); - if (!report) { - ESP_LOGE(TAG, "%s report %d not found", esp_hid_report_type_str(report_type), report_id); - return ESP_FAIL; - } - BTA_HhGetReport(dev->bt.handle, report_type, report_id, max_length); - if (xSemaphoreTake(dev->semaphore, 500 / portTICK_PERIOD_MS) != pdTRUE) { - ESP_LOGE(TAG, "Read Timeout %s", esp_hid_report_type_str(report_type)); - return ESP_FAIL; - } - if (dev->status) { - ESP_LOGE(TAG, "Read %s: %s", esp_hid_report_type_str(report_type), s_bta_hh_status_names[dev->status]); - return ESP_FAIL; - } - if (report_id) { - dev->tmp++; - dev->tmp_len--; - } - if (dev->tmp_len > max_length) { - dev->tmp_len = max_length; - } - *value_len = dev->tmp_len; - memcpy(value, dev->tmp, dev->tmp_len); - return ESP_OK; + esp_err_t ret = ESP_OK; + uint8_t *p_data = NULL; + esp_hidh_dev_report_t *report = NULL; + do { + if (!is_trans_done(dev)) { + ESP_LOGE(TAG, "Pending previous tansaction %s done, try later!", get_trans_type_str(dev->trans_type)); + ret = ESP_FAIL; + break; + } + report = esp_hidh_dev_get_report_by_id_type_proto(dev, map_index, report_id, report_type, dev->protocol_mode); + if (!report) { + ESP_LOGE(TAG, "mode:%s report:%s id:%d not found", get_protocol_mode(dev->protocol_mode), + esp_hid_report_type_str(report_type), report_id); + ret = ESP_FAIL; + break; + } + if (len > report->value_len) { + ESP_LOGE(TAG, "%s report %d takes maximum %d bytes. you have provided %d", + esp_hid_report_type_str(report_type), report_id, report->value_len, len); + ret = ESP_FAIL; + break; + } + + if (report_id) { + if ((p_data = malloc(len + 1)) == NULL) { + ESP_LOGE(TAG, "%s malloc failed!", __func__); + ret = ESP_FAIL; + break; + } + *p_data = report_id; + memcpy(p_data + 1, data, len); + data = p_data; + len = len + 1; + } + ret = esp_bt_hid_host_set_report(dev->bda, report_type, data, len); + if (ret == ESP_OK) { + set_trans(dev, ESP_HID_TRANS_SET_REPORT); + } + } while (0); + return ret; +} + +static esp_err_t esp_bt_hidh_dev_report_read(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, int report_type, + size_t max_length, uint8_t *value, size_t *value_len) +{ + esp_err_t ret = ESP_OK; + esp_hidh_dev_report_t *report = NULL; + do { + if (!is_trans_done(dev)) { + ESP_LOGE(TAG, "Pending previous tansaction %s done, try later!", get_trans_type_str(dev->trans_type)); + ret = ESP_FAIL; + break; + } + report = esp_hidh_dev_get_report_by_id_type_proto(dev, map_index, report_id, report_type, dev->protocol_mode); + if (!report) { + ESP_LOGE(TAG, "mode:%s report:%s id:%d not found", get_protocol_mode(dev->protocol_mode), + esp_hid_report_type_str(report_type), report_id); + ret = ESP_FAIL; + break; + } + ret = esp_bt_hid_host_get_report(dev->bda, report_type, report_id, max_length); + if (ret == ESP_OK) { + dev->trans_type = ESP_HID_TRANS_GET_REPORT; + dev->report_id = report_id; + dev->report_type = report_type; + } + } while (0); + return ret; +} + +static esp_err_t esp_bt_hidh_dev_get_idle(esp_hidh_dev_t *dev) +{ + esp_err_t ret = ESP_OK; + do { + if (!is_trans_done(dev)) { + ESP_LOGE(TAG, "Pending previous tansaction %s done, try later!", get_trans_type_str(dev->trans_type)); + ret = ESP_FAIL; + break; + } + if (!dev->connected) { + ESP_LOGW(TAG, "%s hdl:0x%02x not connected", __func__, dev->bt.handle); + ret = ESP_ERR_INVALID_STATE; + break; + } + ret = esp_bt_hid_host_get_idle(dev->bda); + if (ret == ESP_OK) { + set_trans(dev, ESP_HID_TRANS_GET_IDLE); + } + } while(0); + + return ret; +} + +static esp_err_t esp_bt_hidh_dev_set_idle(esp_hidh_dev_t *dev, uint8_t idle_time) +{ + esp_err_t ret = ESP_OK; + do { + if (!is_trans_done(dev)) { + ESP_LOGE(TAG, "Pending previous tansaction %s done, try later!", get_trans_type_str(dev->trans_type)); + ret = ESP_FAIL; + break; + } + if (!dev->connected) { + ESP_LOGW(TAG, "%s hdl:0x%02x not connected", __func__, dev->bt.handle); + ret = ESP_ERR_INVALID_STATE; + break; + } + ret = esp_bt_hid_host_set_idle(dev->bda, idle_time); + if (ret == ESP_OK) { + set_trans(dev, ESP_HID_TRANS_SET_IDLE); + } + } while(0); + + return ret; +} + +static esp_err_t esp_bt_hidh_dev_get_protocol(esp_hidh_dev_t *dev) +{ + esp_err_t ret = ESP_OK; + do { + if (!is_trans_done(dev)) { + ESP_LOGE(TAG, "Pending previous tansaction %s done, try later!", get_trans_type_str(dev->trans_type)); + ret = ESP_FAIL; + break; + } + if (!dev->connected) { + ESP_LOGW(TAG, "%s hdl:0x%02x not connected", __func__, dev->bt.handle); + ret = ESP_ERR_INVALID_STATE; + break; + } + ret = esp_bt_hid_host_get_protocol(dev->bda); + if (ret == ESP_OK) { + set_trans(dev, ESP_HID_TRANS_GET_PROTOCOL); + } + } while(0); + + return ret; +} + +static esp_err_t esp_bt_hidh_dev_set_protocol(esp_hidh_dev_t *dev, uint8_t protocol_mode) +{ + esp_err_t ret = ESP_OK; + + do { + if (!is_trans_done(dev)) { + ESP_LOGE(TAG, "Pending previous tansaction %s done, try later!", get_trans_type_str(dev->trans_type)); + ret = ESP_FAIL; + break; + } + if (!dev->connected) { + ESP_LOGW(TAG, "%s hdl:0x%02x not connected", __func__, dev->bt.handle); + ret = ESP_ERR_INVALID_STATE; + break; + } + ret = esp_bt_hid_host_set_protocol(dev->bda, protocol_mode); + if (ret == ESP_OK) { + set_trans(dev, ESP_HID_TRANS_SET_PROTOCOL); + } + } while(0); + + return ret; } static void esp_bt_hidh_dev_dump(esp_hidh_dev_t *dev, FILE *fp) { - fprintf(fp, "BDA:" ESP_BD_ADDR_STR ", Status: %s, Connected: %s, Handle: %d, Usage: %s\n", ESP_BD_ADDR_HEX(dev->bda), s_bta_hh_status_names[dev->status], dev->connected ? "YES" : "NO", dev->bt.handle, esp_hid_usage_str(dev->usage)); + fprintf(fp, "BDA:" ESP_BD_ADDR_STR ", Status: %s, Connected: %s, Handle: %d, Usage: %s\n", ESP_BD_ADDR_HEX(dev->bda), s_esp_hh_status_names[dev->status], dev->connected ? "YES" : "NO", dev->bt.handle, esp_hid_usage_str(dev->usage)); fprintf(fp, "Name: %s, Manufacturer: %s, Serial Number: %s\n", dev->config.device_name ? dev->config.device_name : "", dev->config.manufacturer_name ? dev->config.manufacturer_name : "", dev->config.serial_number ? dev->config.serial_number : ""); fprintf(fp, "PID: 0x%04x, VID: 0x%04x, VERSION: 0x%04x\n", dev->config.product_id, dev->config.vendor_id, dev->config.version); fprintf(fp, "Report Map Length: %d\n", dev->config.report_maps[0].len); esp_hidh_dev_report_t *report = dev->reports; while (report) { fprintf(fp, " %8s %7s %6s, ID: %3u, Length: %3u\n", - esp_hid_usage_str(report->usage), esp_hid_report_type_str(report->report_type), esp_hid_protocol_mode_str(report->protocol_mode), + esp_hid_usage_str(report->usage), esp_hid_report_type_str(report->report_type), get_protocol_mode(report->protocol_mode), report->report_id, report->value_len); report = report->next; } @@ -317,134 +991,108 @@ static void esp_bt_hidh_dev_dump(esp_hidh_dev_t *dev, FILE *fp) esp_err_t esp_bt_hidh_init(const esp_hidh_config_t *config) { + esp_err_t ret = ESP_OK; if (config == NULL) { ESP_LOGE(TAG, "Config is NULL"); - return ESP_FAIL; + return ESP_ERR_INVALID_ARG; } esp_event_loop_args_t event_task_args = { .queue_size = 5, .task_name = "esp_bt_hidh_events", .task_priority = uxTaskPriorityGet(NULL), - .task_stack_size = config->event_stack_size > 0 ? config->event_stack_size : 2048, + .task_stack_size = config->event_stack_size > 0 ? config->event_stack_size : 4096, .task_core_id = tskNO_AFFINITY }; - esp_err_t ret = esp_event_loop_create(&event_task_args, &event_loop_handle); + + do { + if ((hidh_local_param.connection_queue = fixed_queue_new(QUEUE_SIZE_MAX)) == NULL) { + ESP_LOGE(TAG, "connection_queue create failed!"); + ret = ESP_FAIL; + break; + } + ret = esp_event_loop_create(&event_task_args, &hidh_local_param.event_loop_handle); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "esp_event_loop_create failed!"); + ret = ESP_FAIL; + break; + } + ret = esp_event_handler_register_with(hidh_local_param.event_loop_handle, ESP_HIDH_EVENTS, ESP_EVENT_ANY_ID, + esp_hidh_process_event_data_handler, NULL); + ret |= esp_event_handler_register_with(hidh_local_param.event_loop_handle, ESP_HIDH_EVENTS, ESP_EVENT_ANY_ID, + config->callback, config->callback_arg); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "event_loop register failed!"); + ret = ESP_FAIL; + break; + } + ret = esp_bt_hid_host_register_callback(esp_hh_cb); + ret |= esp_bt_hid_host_init(); + } while (0); + if (ret != ESP_OK) { - ESP_LOGE(TAG, "esp_event_loop_create failed!"); - return ret; + free_local_param(); } - esp_event_handler_register_with(event_loop_handle, ESP_HIDH_EVENTS, ESP_EVENT_ANY_ID, config->callback, NULL); - BTA_HhEnable(0, bta_hh_cb); - return ESP_OK; + return ret; } esp_err_t esp_bt_hidh_deinit(void) { - if (event_loop_handle) { - esp_event_loop_delete(event_loop_handle); + esp_err_t ret = esp_bt_hid_host_deinit(); + return ret; +} + +static esp_hidh_dev_t *hidh_dev_ctor(esp_bd_addr_t bda) +{ + esp_hidh_dev_t *dev = NULL; + dev = esp_hidh_dev_malloc(); + if (dev == NULL) { + return NULL; } - BTA_HhDisable(); - return ESP_OK; + dev->in_use = true; + dev->transport = ESP_HID_TRANSPORT_BT; + dev->trans_type = ESP_HID_TRANS_MAX; + dev->trans_timer = NULL; + dev->protocol_mode = ESP_HID_PROTOCOL_MODE_REPORT; // device default protocol mode + dev->connected = false; + dev->opened = true; + dev->added = false; + dev->is_orig = true; + dev->reports = NULL; + dev->reports_len = 0; + dev->tmp = NULL; + dev->tmp_len = 0; + memcpy(dev->bda, bda, sizeof(esp_bd_addr_t)); + dev->bt.handle = 0xff; + + dev->close = esp_bt_hidh_dev_close; + dev->report_write = esp_bt_hidh_dev_report_write; + dev->report_read = esp_bt_hidh_dev_report_read; + dev->set_report = esp_bt_hidh_dev_set_report; + dev->get_idle = esp_bt_hidh_dev_get_idle; + dev->set_idle = esp_bt_hidh_dev_set_idle; + dev->get_protocol = esp_bt_hidh_dev_get_protocol; + dev->set_protocol = esp_bt_hidh_dev_set_protocol; + dev->dump = esp_bt_hidh_dev_dump; + + return dev; } esp_hidh_dev_t *esp_bt_hidh_dev_open(esp_bd_addr_t bda) { - esp_hidh_dev_t *dev = esp_hidh_dev_malloc(); + esp_hidh_dev_t *dev = esp_hidh_dev_get_by_bda(bda); if (dev == NULL) { - ESP_LOGE(TAG, "malloc esp_hidh_dev_t failed"); - return NULL; + if ((dev = hidh_dev_ctor(bda)) == NULL) { + ESP_LOGE(TAG, "%s create device failed!", __func__); + return NULL; + } + } else { + ESP_LOGW(TAG, "device has opened, connected: %d", dev->connected); } - dev->transport = ESP_HID_TRANSPORT_BT; - memcpy(dev->bda, bda, sizeof(esp_bd_addr_t)); - dev->bt.handle = -1; - - dev->opened = true; - BTA_HhOpen(dev->bda, 0, BTA_HH_PROTO_RPT_MODE, (BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT)); - WAIT_DEV(dev); - if (dev->status != BTA_HH_OK) { - esp_hidh_dev_free(dev); - return NULL; + if (!dev->connected) { + esp_bt_hid_host_connect(dev->bda); } - dev->close = esp_bt_hidh_dev_close; - dev->report_write = esp_bt_hidh_dev_report_write; - dev->report_read = esp_bt_hidh_dev_report_read; - dev->dump = esp_bt_hidh_dev_dump; return dev; } -/* - * BlueDroid BT HIDH Stack Callbacks - * */ - -/* This callback function is executed by BTA_HH when data is received on an interrupt channel. */ -void bta_hh_co_data(uint8_t handle, uint8_t *p_rpt, uint16_t len, tBTA_HH_PROTO_MODE mode, uint8_t sub_class, uint8_t country_code, esp_bd_addr_t bda, uint8_t app_id) -{ - if (len < 2) { - ESP_LOGE(TAG, "Not Enough Data"); - return; - } - esp_hidh_dev_t *dev = NULL; - esp_hidh_dev_report_t *report = NULL; - dev = esp_hidh_dev_get_by_handle(handle); - if (dev == NULL) { - ESP_LOGE(TAG, "Device Not Found: handle %u", handle); - return; - } - report = esp_hidh_dev_get_input_report_by_id_and_proto(dev, p_rpt[0], mode ? ESP_HID_PROTOCOL_MODE_BOOT : ESP_HID_PROTOCOL_MODE_REPORT); - if (report == NULL) { - ESP_LOGE(TAG, "Report Not Found: %d mode: %s", p_rpt[0], mode ? "BOOT" : "REPORT"); - return; - } - if (len != (report->value_len + 1)) { - ESP_LOGW(TAG, "Wrong Data Len: %u != %u", len, (report->value_len + 1)); - } - - if (event_loop_handle) { - esp_hidh_event_data_t p = {0}; - if (report->report_type == ESP_HID_REPORT_TYPE_FEATURE) { - p.feature.dev = dev; - p.feature.report_id = report->report_id; - p.feature.usage = report->usage; - p.feature.data = p_rpt + 1; - p.feature.length = len - 1; - esp_event_post_to(event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_FEATURE_EVENT, &p, sizeof(esp_hidh_event_data_t), portMAX_DELAY); - } else { - p.input.dev = dev; - p.input.report_id = report->report_id; - p.input.usage = report->usage; - p.input.data = p_rpt + 1; - p.input.length = len - 1; - esp_event_post_to(event_loop_handle, ESP_HIDH_EVENTS, ESP_HIDH_INPUT_EVENT, &p, sizeof(esp_hidh_event_data_t), portMAX_DELAY); - } - } -} - -/* This callback function is executed by BTA_HH when connection is opened, and application may do some device specific initialization. */ -void bta_hh_co_open(uint8_t handle, uint8_t sub_class, uint16_t attr_mask, uint8_t app_id) -{ - esp_hidh_dev_t *dev = NULL; - dev = esp_hidh_dev_get_by_handle(-1); - if (dev == NULL) { - ESP_LOGI(TAG, "Device Not Found? It's probably a reconnect."); - dev = esp_hidh_dev_malloc(); - if (dev == NULL) { - ESP_LOGE(TAG, "DEV Malloc Failed"); - return; - } - dev->transport = ESP_HID_TRANSPORT_BT; - dev->close = esp_bt_hidh_dev_close; - dev->report_write = esp_bt_hidh_dev_report_write; - dev->report_read = esp_bt_hidh_dev_report_read; - dev->dump = esp_bt_hidh_dev_dump; - } - dev->bt.attr_mask = attr_mask; - dev->bt.app_id = app_id; - dev->bt.sub_class = sub_class; - dev->bt.handle = handle; -} - -/* This callback function is executed by BTA_HH when connection is closed, and device specific finalization may be needed. */ -void bta_hh_co_close(uint8_t dev_handle, uint8_t app_id) {} - #endif /* CONFIG_BT_HID_HOST_ENABLED */ diff --git a/components/esp_hid/src/esp_hid_common.c b/components/esp_hid/src/esp_hid_common.c index 9d1f4167f4..b549d00663 100644 --- a/components/esp_hid/src/esp_hid_common.c +++ b/components/esp_hid/src/esp_hid_common.c @@ -142,7 +142,7 @@ static int handle_report(hid_report_params_t *report, bool first) } item.protocol_mode = ESP_HID_PROTOCOL_MODE_BOOT; - item.value_len = 4; + item.value_len = 3; if (add_report(map, &item) != 0) { return -1; } diff --git a/components/esp_hid/src/esp_hidd.c b/components/esp_hid/src/esp_hidd.c index e6e3c57988..56b9c23a5a 100644 --- a/components/esp_hid/src/esp_hidd.c +++ b/components/esp_hid/src/esp_hidd.c @@ -20,11 +20,14 @@ #include "ble_hidd.h" #endif /* CONFIG_GATTS_ENABLE */ +#if CONFIG_BT_HID_DEVICE_ENABLED +#include "bt_hidd.h" +#endif /* CONFIG_BT_HID_DEVICE_ENABLED */ + ESP_EVENT_DEFINE_BASE(ESP_HIDD_EVENTS); esp_err_t esp_hidd_dev_init(const esp_hid_device_config_t *config, esp_hid_transport_t transport, esp_event_handler_t callback, esp_hidd_dev_t **dev_out) { - esp_err_t ret = ESP_OK; esp_hidd_dev_t *dev = (esp_hidd_dev_t *)calloc(1, sizeof(esp_hidd_dev_t)); if (dev == NULL) { @@ -37,6 +40,11 @@ esp_err_t esp_hidd_dev_init(const esp_hid_device_config_t *config, esp_hid_trans ret = esp_ble_hidd_dev_init(dev, config, callback); break; #endif /* CONFIG_GATTS_ENABLE */ +#if CONFIG_BT_HID_DEVICE_ENABLED + case ESP_HID_TRANSPORT_BT: + ret = esp_bt_hidd_dev_init(dev, config, callback); + break; +#endif /* CONFIG_BT_HID_DEVICE_ENABLED */ default: ret = ESP_FAIL; break; @@ -119,3 +127,29 @@ esp_err_t esp_hidd_dev_event_handler_unregister(esp_hidd_dev_t *dev, esp_event_h } return dev->event_handler_unregister(dev->dev, callback, event); } + +/** + * The deep copy data append the end of the esp_hidd_event_data_t, move the data pointer to the correct address. This is + * a workaround way, it's better to use flexiable array in the interface. + */ +void esp_hidd_process_event_data_handler(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id, + void *event_data) +{ + esp_hidd_event_t event = (esp_hidd_event_t)event_id; + esp_hidd_event_data_t *param = (esp_hidd_event_data_t *)event_data; + + switch (event) { + case ESP_HIDD_OUTPUT_EVENT: + if (param->output.length && param->output.data) { + param->output.data = (uint8_t *)param + sizeof(esp_hidd_event_data_t); + } + break; + case ESP_HIDD_FEATURE_EVENT: + if (param->feature.length && param->feature.data) { + param->feature.data = (uint8_t *)param + sizeof(esp_hidd_event_data_t); + } + break; + default: + break; + } +} diff --git a/components/esp_hid/src/esp_hidh.c b/components/esp_hid/src/esp_hidh.c index 3d318427f4..484092c885 100644 --- a/components/esp_hid/src/esp_hidh.c +++ b/components/esp_hid/src/esp_hidh.c @@ -21,13 +21,16 @@ #include "esp_event_base.h" ESP_EVENT_DEFINE_BASE(ESP_HIDH_EVENTS); +#define ESP_HIDH_DELAY_FREE_TO 100000 // us static const char *TAG = "ESP_HIDH"; static esp_hidh_dev_head_t s_esp_hidh_devices; - +static esp_timer_handle_t s_esp_hidh_timer; static xSemaphoreHandle s_esp_hidh_devices_semaphore = NULL; +static void esp_hidh_dev_delay_free(void *arg); + static inline void lock_devices(void) { if (s_esp_hidh_devices_semaphore != NULL) { @@ -42,7 +45,12 @@ static inline void unlock_devices(void) } } -static bool esp_hidh_dev_exists(esp_hidh_dev_t *dev) + +/* + * Public Functions + * */ + +bool esp_hidh_dev_exists(esp_hidh_dev_t *dev) { if (dev == NULL) { return false; @@ -59,10 +67,6 @@ static bool esp_hidh_dev_exists(esp_hidh_dev_t *dev) return false; } -/* - * Public Functions - * */ - esp_err_t esp_hidh_init(const esp_hidh_config_t *config) { esp_err_t err = ESP_FAIL; @@ -76,12 +80,25 @@ esp_err_t esp_hidh_init(const esp_hidh_config_t *config) return err; } - s_esp_hidh_devices_semaphore = xSemaphoreCreateBinary(); + TAILQ_INIT(&s_esp_hidh_devices); + + esp_timer_create_args_t timer_config = { + .callback = &esp_hidh_dev_delay_free, + .arg = NULL, + .name = "hidh_timer" + }; + + if ((err = esp_timer_create(&timer_config, &s_esp_hidh_timer)) != ESP_OK) { + ESP_LOGE(TAG, "%s create timer failed!", __func__); + return err; + } + + s_esp_hidh_devices_semaphore = xSemaphoreCreateMutex(); if (s_esp_hidh_devices_semaphore == NULL) { ESP_LOGE(TAG, "xSemaphoreCreateMutex failed!"); return err; } - + // unlock_devices(); err = ESP_OK; #if CONFIG_BT_HID_HOST_ENABLED @@ -96,12 +113,11 @@ esp_err_t esp_hidh_init(const esp_hidh_config_t *config) } #endif /* CONFIG_GATTC_ENABLE */ - if (err == ESP_OK) { - TAILQ_INIT(&s_esp_hidh_devices); - unlock_devices(); - } else { + if (err != ESP_OK) { vSemaphoreDelete(s_esp_hidh_devices_semaphore); s_esp_hidh_devices_semaphore = NULL; + esp_timer_delete(s_esp_hidh_timer); + s_esp_hidh_timer = NULL; } return err; @@ -115,6 +131,11 @@ esp_err_t esp_hidh_deinit(void) return err; } + if (esp_timer_is_active(s_esp_hidh_timer)) { + ESP_LOGE(TAG, "Busy, try again later!"); + return ESP_ERR_NOT_FINISHED; + } + if (!TAILQ_EMPTY(&s_esp_hidh_devices)) { ESP_LOGE(TAG, "Please disconnect all devices first!"); return err; @@ -138,6 +159,8 @@ esp_err_t esp_hidh_deinit(void) TAILQ_INIT(&s_esp_hidh_devices); vSemaphoreDelete(s_esp_hidh_devices_semaphore); s_esp_hidh_devices_semaphore = NULL; + esp_timer_delete(s_esp_hidh_timer); + s_esp_hidh_timer = NULL; } return err; } @@ -166,156 +189,317 @@ esp_hidh_dev_t *esp_hidh_dev_open(esp_bd_addr_t bda, esp_hid_transport_t transpo esp_err_t esp_hidh_dev_close(esp_hidh_dev_t *dev) { - if (!esp_hidh_dev_exists(dev)) { - return ESP_FAIL; + esp_err_t ret = ESP_OK; + if (esp_hidh_dev_exists(dev)) { + esp_hidh_dev_lock(dev); + ret = dev->close(dev); + esp_hidh_dev_unlock(dev); + } else { + ret = ESP_FAIL; } - return dev->close(dev); + return ret; } void esp_hidh_dev_dump(esp_hidh_dev_t *dev, FILE *fp) { - if (!esp_hidh_dev_exists(dev)) { - return; + if (esp_hidh_dev_exists(dev)) { + esp_hidh_dev_lock(dev); + dev->dump(dev, fp); + esp_hidh_dev_unlock(dev); } - dev->dump(dev, fp); } esp_err_t esp_hidh_dev_output_set(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, uint8_t *value, size_t value_len) { - if (!esp_hidh_dev_exists(dev)) { - return ESP_FAIL; + esp_err_t ret = ESP_OK; + if (esp_hidh_dev_exists(dev)) { + esp_hidh_dev_lock(dev); + ret = dev->report_write(dev, map_index, report_id, ESP_HID_REPORT_TYPE_OUTPUT, value, value_len); + esp_hidh_dev_unlock(dev); + } else { + ret = ESP_FAIL; } - return dev->report_write(dev, map_index, report_id, ESP_HID_REPORT_TYPE_OUTPUT, value, value_len); + return ret; } esp_err_t esp_hidh_dev_feature_set(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, uint8_t *value, size_t value_len) { - if (!esp_hidh_dev_exists(dev)) { - return ESP_FAIL; + esp_err_t ret = ESP_OK; + if (esp_hidh_dev_exists(dev)) { + esp_hidh_dev_lock(dev); + ret = dev->report_write(dev, map_index, report_id, ESP_HID_REPORT_TYPE_FEATURE, value, value_len); + esp_hidh_dev_unlock(dev); + } else { + ret = ESP_FAIL; } - return dev->report_write(dev, map_index, report_id, ESP_HID_REPORT_TYPE_FEATURE, value, value_len); + return ret; } esp_err_t esp_hidh_dev_feature_get(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, size_t max_length, uint8_t *value, size_t *value_len) { - if (!esp_hidh_dev_exists(dev)) { - return ESP_FAIL; + esp_err_t ret = ESP_OK; + if (esp_hidh_dev_exists(dev)) { + esp_hidh_dev_lock(dev); + ret = dev->report_read(dev, map_index, report_id, ESP_HID_REPORT_TYPE_FEATURE, max_length, value, value_len); + esp_hidh_dev_unlock(dev); + } else { + ret = ESP_FAIL; } - return dev->report_read(dev, map_index, report_id, ESP_HID_REPORT_TYPE_FEATURE, max_length, value, value_len); + return ret; +} + +esp_err_t esp_hidh_dev_set_report(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, int report_type, uint8_t *data, size_t length) +{ + esp_err_t ret = ESP_OK; + if (esp_hidh_dev_exists(dev)) { + esp_hidh_dev_lock(dev); + if (dev->set_report) { + ret = dev->set_report(dev, map_index, report_id, report_type, data, length); + } else { + ret = ESP_ERR_NOT_SUPPORTED; + } + esp_hidh_dev_unlock(dev); + } else { + ret = ESP_FAIL; + } + return ret; +} + +esp_err_t esp_hidh_dev_get_report(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, int report_type, + size_t max_len) +{ + esp_err_t ret = ESP_OK; + if (esp_hidh_dev_exists(dev)) { + esp_hidh_dev_lock(dev); + ret = dev->report_read(dev, map_index, report_id, report_type, max_len, NULL, NULL); + esp_hidh_dev_unlock(dev); + } else { + ret = ESP_FAIL; + } + return ret; +} + +esp_err_t esp_hidh_dev_get_idle(esp_hidh_dev_t *dev) +{ + esp_err_t ret = ESP_OK; + if (esp_hidh_dev_exists(dev)) { + esp_hidh_dev_lock(dev); + if (dev->get_idle) { + ret = dev->get_idle(dev); + } else { + ret = ESP_ERR_NOT_SUPPORTED; + } + esp_hidh_dev_unlock(dev); + } else { + ret = ESP_FAIL; + } + return ret; +} + +esp_err_t esp_hidh_dev_set_idle(esp_hidh_dev_t *dev, uint8_t idle_time) +{ + esp_err_t ret = ESP_OK; + if (esp_hidh_dev_exists(dev)) { + esp_hidh_dev_lock(dev); + if (dev->set_idle) { + ret = dev->set_idle(dev, idle_time); + } else { + ret = ESP_ERR_NOT_SUPPORTED; + } + esp_hidh_dev_unlock(dev); + } else { + ret = ESP_FAIL; + } + return ret; +} + +esp_err_t esp_hidh_dev_get_protocol(esp_hidh_dev_t *dev) +{ + esp_err_t ret = ESP_OK; + if (esp_hidh_dev_exists(dev)) { + esp_hidh_dev_lock(dev); + if (dev->get_protocol) { + ret = dev->get_protocol(dev); + } else { + ret = ESP_ERR_NOT_SUPPORTED; + } + esp_hidh_dev_unlock(dev); + } else { + ret = ESP_FAIL; + } + return ret; +} + +esp_err_t esp_hidh_dev_set_protocol(esp_hidh_dev_t *dev, uint8_t protocol_mode) +{ + esp_err_t ret = ESP_OK; + if (esp_hidh_dev_exists(dev)) { + esp_hidh_dev_lock(dev); + if (dev->set_protocol) { + ret = dev->set_protocol(dev, protocol_mode); + } else { + ret = ESP_ERR_NOT_SUPPORTED; + } + esp_hidh_dev_unlock(dev); + } else { + ret = ESP_FAIL; + } + return ret; } const uint8_t *esp_hidh_dev_bda_get(esp_hidh_dev_t *dev) { + uint8_t *ret = NULL; #if CONFIG_BLUEDROID_ENABLED if (esp_hidh_dev_exists(dev)) { - return dev->bda; + esp_hidh_dev_lock(dev); + ret = dev->bda; + esp_hidh_dev_unlock(dev); } #endif /* CONFIG_BLUEDROID_ENABLED */ - return NULL; + return ret; } esp_hid_transport_t esp_hidh_dev_transport_get(esp_hidh_dev_t *dev) { - if (!esp_hidh_dev_exists(dev)) { - return ESP_HID_TRANSPORT_MAX; + esp_hid_transport_t ret = ESP_HID_TRANSPORT_MAX; + if (esp_hidh_dev_exists(dev)) { + esp_hidh_dev_lock(dev); + ret = dev->transport; + esp_hidh_dev_unlock(dev); } - return dev->transport; + return ret; } const esp_hid_device_config_t *esp_hidh_dev_config_get(esp_hidh_dev_t *dev) { - if (!esp_hidh_dev_exists(dev)) { - return NULL; + esp_hid_device_config_t *ret = NULL; + if (esp_hidh_dev_exists(dev)) { + esp_hidh_dev_lock(dev); + ret = &dev->config; + esp_hidh_dev_unlock(dev); } - return &dev->config; + return ret; } const char *esp_hidh_dev_name_get(esp_hidh_dev_t *dev) { - if (!esp_hidh_dev_exists(dev)) { - return NULL; + const char * ret = NULL; + if (esp_hidh_dev_exists(dev)) { + esp_hidh_dev_lock(dev); + ret = dev->config.device_name ? dev->config.device_name : ""; + esp_hidh_dev_unlock(dev); } - return dev->config.device_name ? dev->config.device_name : ""; + return ret; } const char *esp_hidh_dev_manufacturer_get(esp_hidh_dev_t *dev) { - if (!esp_hidh_dev_exists(dev)) { - return NULL; + const char *ret = NULL; + if (esp_hidh_dev_exists(dev)) { + esp_hidh_dev_lock(dev); + ret = dev->config.manufacturer_name ? dev->config.manufacturer_name : ""; + esp_hidh_dev_unlock(dev); } - return dev->config.manufacturer_name ? dev->config.manufacturer_name : ""; + return ret; } const char *esp_hidh_dev_serial_get(esp_hidh_dev_t *dev) { - if (!esp_hidh_dev_exists(dev)) { - return NULL; + const char *ret = NULL; + if (esp_hidh_dev_exists(dev)) { + esp_hidh_dev_lock(dev); + ret = dev->config.serial_number ? dev->config.serial_number : ""; + esp_hidh_dev_unlock(dev); } - return dev->config.serial_number ? dev->config.serial_number : ""; + return ret; } uint16_t esp_hidh_dev_vendor_id_get(esp_hidh_dev_t *dev) { - if (!esp_hidh_dev_exists(dev)) { - return 0; + uint16_t ret = 0; + if (esp_hidh_dev_exists(dev)) { + esp_hidh_dev_lock(dev); + ret = dev->config.vendor_id; + esp_hidh_dev_unlock(dev); } - return dev->config.vendor_id; + return ret; } uint16_t esp_hidh_dev_product_id_get(esp_hidh_dev_t *dev) { - if (!esp_hidh_dev_exists(dev)) { - return 0; + uint16_t ret = 0; + if (esp_hidh_dev_exists(dev)) { + esp_hidh_dev_lock(dev); + ret = dev->config.product_id; + esp_hidh_dev_unlock(dev); } - return dev->config.product_id; + return ret; } uint16_t esp_hidh_dev_version_get(esp_hidh_dev_t *dev) { + uint16_t ret = 0; if (!esp_hidh_dev_exists(dev)) { - return 0; + esp_hidh_dev_lock(dev); + ret = dev->config.version; + esp_hidh_dev_unlock(dev); } - return dev->config.version; + return ret; } esp_hid_usage_t esp_hidh_dev_usage_get(esp_hidh_dev_t *dev) { - if (!esp_hidh_dev_exists(dev)) { - return ESP_HID_USAGE_GENERIC; + esp_hid_usage_t ret = ESP_HID_USAGE_GENERIC; + if (esp_hidh_dev_exists(dev)) { + esp_hidh_dev_lock(dev); + ret = dev->usage; + esp_hidh_dev_unlock(dev); } - return dev->usage; + return ret; } esp_err_t esp_hidh_dev_reports_get(esp_hidh_dev_t *dev, size_t *num_reports, esp_hid_report_item_t **reports) { + esp_err_t ret = 0; + esp_hid_report_item_t *r = NULL; + if (!esp_hidh_dev_exists(dev)) { return ESP_FAIL; } - esp_hid_report_item_t *r = (esp_hid_report_item_t *)malloc(sizeof(esp_hid_report_item_t) * dev->reports_len); - if (r == NULL) { - return ESP_FAIL; - } - - esp_hidh_dev_report_t *dr = dev->reports; - for (uint8_t i = 0; i < dev->reports_len; i++) { - if (dr == NULL) { - //error - free(r); - return ESP_FAIL; + esp_hidh_dev_lock(dev); + do { + r = (esp_hid_report_item_t *)malloc(sizeof(esp_hid_report_item_t) * dev->reports_len); + if (r == NULL) { + ret = ESP_FAIL; + break; } - r[i].map_index = dr->map_index; - r[i].protocol_mode = dr->protocol_mode; - r[i].usage = dr->usage; - r[i].report_id = dr->report_id; - r[i].report_type = dr->report_type; - r[i].value_len = dr->value_len; - dr = dr->next; - } - *reports = r; - *num_reports = dev->reports_len; - return ESP_OK; + esp_hidh_dev_report_t *dr = dev->reports; + for (uint8_t i = 0; i < dev->reports_len; i++) { + if (dr == NULL) { + // error + free(r); + ret = ESP_FAIL; + goto error_; + } + r[i].map_index = dr->map_index; + r[i].protocol_mode = dr->protocol_mode; + r[i].usage = dr->usage; + r[i].report_id = dr->report_id; + r[i].report_type = dr->report_type; + r[i].value_len = dr->value_len; + + dr = dr->next; + } + *reports = r; + *num_reports = dev->reports_len; + } while (0); +error_:; + esp_hidh_dev_unlock(dev); + + return ret; } esp_err_t esp_hidh_dev_report_maps_get(esp_hidh_dev_t *dev, size_t *num_maps, esp_hid_raw_report_map_t **maps) @@ -323,8 +507,10 @@ esp_err_t esp_hidh_dev_report_maps_get(esp_hidh_dev_t *dev, size_t *num_maps, es if (!esp_hidh_dev_exists(dev)) { return ESP_FAIL; } + esp_hidh_dev_lock(dev); *num_maps = dev->config.report_maps_len; *maps = dev->config.report_maps; + esp_hidh_dev_unlock(dev); return ESP_OK; } @@ -333,6 +519,37 @@ esp_err_t esp_hidh_dev_report_maps_get(esp_hidh_dev_t *dev, size_t *num_maps, es * Private Functions * */ +/** + * `lock_devices()` only protect the devices list, this mutex protect the single deivce instance. + */ +inline void esp_hidh_dev_lock(esp_hidh_dev_t *dev) +{ + if (dev && dev->mutex != NULL) { + xSemaphoreTake(dev->mutex, portMAX_DELAY); + } +} + +inline void esp_hidh_dev_unlock(esp_hidh_dev_t *dev) +{ + if (dev && dev->mutex != NULL) { + xSemaphoreGive(dev->mutex); + } +} + +inline void esp_hidh_dev_wait(esp_hidh_dev_t *dev) +{ + if (dev && dev->semaphore != NULL) { + xSemaphoreTake(dev->semaphore, portMAX_DELAY); + } +} + +inline void esp_hidh_dev_send(esp_hidh_dev_t *dev) +{ + if (dev && dev->semaphore != NULL) { + xSemaphoreGive(dev->semaphore); + } +} + esp_hidh_dev_report_t *esp_hidh_dev_get_report_by_handle(esp_hidh_dev_t *dev, uint16_t handle) { esp_hidh_dev_report_t *r = dev->reports; @@ -345,6 +562,19 @@ esp_hidh_dev_report_t *esp_hidh_dev_get_report_by_handle(esp_hidh_dev_t *dev, ui return NULL; } +esp_hidh_dev_report_t *esp_hidh_dev_get_report_by_id_type_proto(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, int report_type, uint8_t protocol_mode) +{ + esp_hidh_dev_report_t *r = dev->reports; + while (r) { + if (r->map_index == map_index && r->report_type == report_type && r->report_id == report_id && + r->protocol_mode == protocol_mode) { + return r; + } + r = r->next; + } + return NULL; +} + esp_hidh_dev_report_t *esp_hidh_dev_get_report_by_id_and_type(esp_hidh_dev_t *dev, size_t map_index, size_t report_id, int report_type) { esp_hidh_dev_report_t *r = dev->reports; @@ -369,11 +599,68 @@ esp_hidh_dev_report_t *esp_hidh_dev_get_input_report_by_id_and_proto(esp_hidh_de return NULL; } +esp_hidh_dev_report_t *esp_hidh_dev_get_input_report_by_len_and_proto(esp_hidh_dev_t *dev, size_t len, int protocol_mode) +{ + esp_hidh_dev_report_t *r = dev->reports; + while (r) { + if (r->value_len == len && (r->report_type & 1) && r->protocol_mode == protocol_mode) { + return r; + } + r = r->next; + } + return NULL; +} + +/** + * If no Report ID item tags are present in the Report descriptor, it + * can be assumed that only one Input, Output, and Feature report structure exists + * and together they represent all of the device’s data. + */ +esp_hidh_dev_report_t *esp_hidh_dev_get_input_report_by_proto_and_data(esp_hidh_dev_t *dev, int protocol_mode, + size_t len, const uint8_t *data, bool *has_report_id) +{ + esp_hidh_dev_report_t *r = dev->reports; + *has_report_id = false; + // first, assume data not include report id + while (r) { + if (r->value_len == len && r->report_id == 0 && (r->report_type & 1) && + r->protocol_mode == protocol_mode) { + *has_report_id = false; + break; + } + r = r->next; + } + // indicate data include report id + if (r == NULL) { + if (*data == 0) { + ESP_LOGE(TAG, "data not include report id!"); + *has_report_id = false; + return NULL; + } + r = dev->reports; + while (r) { + if (r->value_len == len + 1 && r->report_id == *data && (r->report_type & 1) && + r->protocol_mode == protocol_mode) { + *has_report_id = true; + break; + } + r = r->next; + } + } + return r; +} + static void esp_hidh_dev_resources_free(esp_hidh_dev_t *dev) { + esp_hidh_dev_lock(dev); if (dev->semaphore) { vSemaphoreDelete(dev->semaphore); } + if (dev->trans_timer) { + esp_timer_stop(dev->trans_timer); + esp_timer_delete(dev->trans_timer); + dev->trans_timer = NULL; + } free((void *)dev->config.device_name); free((void *)dev->config.manufacturer_name); free((void *)dev->config.serial_number); @@ -387,6 +674,10 @@ static void esp_hidh_dev_resources_free(esp_hidh_dev_t *dev) dev->reports = dev->reports->next; free(r); } + esp_hidh_dev_unlock(dev); + if (dev->mutex) { + vSemaphoreDelete(dev->mutex); + } free(dev); } @@ -405,6 +696,13 @@ esp_hidh_dev_t *esp_hidh_dev_malloc() return NULL; } + dev->mutex = xSemaphoreCreateMutex(); + if (dev->mutex == NULL) { + ESP_LOGE(TAG, "malloc mutex failed"); + esp_hidh_dev_resources_free(dev); + return NULL; + } + lock_devices(); TAILQ_INSERT_TAIL(&s_esp_hidh_devices, dev, devices); unlock_devices(); @@ -412,7 +710,16 @@ esp_hidh_dev_t *esp_hidh_dev_malloc() return dev; } +/** + * The `dev` is allocated by the internal function, and it should also be freed by the internal function. So, when the + * user call this function, it will do nothing. + */ esp_err_t esp_hidh_dev_free(esp_hidh_dev_t *dev) +{ + return ESP_OK; +} + +esp_err_t esp_hidh_dev_free_inner(esp_hidh_dev_t *dev) { esp_err_t ret = ESP_FAIL; @@ -440,6 +747,20 @@ esp_err_t esp_hidh_dev_free(esp_hidh_dev_t *dev) return ret; } +static void esp_hidh_dev_delay_free(void *arg) +{ + esp_hidh_dev_t *d = NULL; + esp_hidh_dev_t *next = NULL; + lock_devices(); + TAILQ_FOREACH_SAFE(d, &s_esp_hidh_devices, devices, next) { + if (!d->in_use) { + TAILQ_REMOVE(&s_esp_hidh_devices, d, devices); + esp_hidh_dev_resources_free(d); + } + } + unlock_devices(); +} + #if CONFIG_BLUEDROID_ENABLED esp_hidh_dev_t *esp_hidh_dev_get_by_bda(esp_bd_addr_t bda) { @@ -455,7 +776,7 @@ esp_hidh_dev_t *esp_hidh_dev_get_by_bda(esp_bd_addr_t bda) return NULL; } -esp_hidh_dev_t *esp_hidh_dev_get_by_handle(int handle) +esp_hidh_dev_t *esp_hidh_dev_get_by_handle(uint8_t handle) { #if CONFIG_BT_HID_HOST_ENABLED esp_hidh_dev_t * d = NULL; @@ -486,4 +807,44 @@ esp_hidh_dev_t *esp_hidh_dev_get_by_conn_id(uint16_t conn_id) #endif /* CONFIG_GATTC_ENABLE */ return NULL; } + +/** + * The deep copy data append the end of the esp_hidh_event_data_t, move the data pointer to the correct address. This is + * a workaround way, it's better to use flexiable array in the interface. + */ +void esp_hidh_process_event_data_handler(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id, + void *event_data) +{ + esp_hidh_event_t event = (esp_hidh_event_t)event_id; + esp_hidh_event_data_t *param = (esp_hidh_event_data_t *)event_data; + + switch (event) { + case ESP_HIDH_INPUT_EVENT: + if (param->input.length && param->input.data) { + param->input.data = (uint8_t *)param + sizeof(esp_hidh_event_data_t); + } + break; + case ESP_HIDH_FEATURE_EVENT: + if (param->feature.length && param->feature.data) { + param->feature.data = (uint8_t *)param + sizeof(esp_hidh_event_data_t); + } + break; + case ESP_HIDH_OPEN_EVENT: + if (param->open.status != ESP_OK) { + if (s_esp_hidh_timer && !esp_timer_is_active(s_esp_hidh_timer) && + esp_timer_start_once(s_esp_hidh_timer, ESP_HIDH_DELAY_FREE_TO) != ESP_OK) { + ESP_LOGE(TAG, "%s set hidh timer failed!", __func__); + } + } + break; + case ESP_HIDH_CLOSE_EVENT: + if (s_esp_hidh_timer && !esp_timer_is_active(s_esp_hidh_timer) && + esp_timer_start_once(s_esp_hidh_timer, ESP_HIDH_DELAY_FREE_TO) != ESP_OK) { + ESP_LOGE(TAG, "%s set hidh timer failed!", __func__); + } + break; + default: + break; + } +} #endif /* CONFIG_BLUEDROID_ENABLED */ diff --git a/components/esp_hid/test/test_esp_hid.c b/components/esp_hid/test/test_esp_hid.c index 2bdde5b30e..db9b0d10af 100644 --- a/components/esp_hid/test/test_esp_hid.c +++ b/components/esp_hid/test/test_esp_hid.c @@ -39,7 +39,7 @@ TEST_CASE("can parse hidReportMap", "[esp_hid]") TEST_ASSERT(report_map->reports[1].report_type == ESP_HID_REPORT_TYPE_INPUT); TEST_ASSERT(report_map->reports[1].protocol_mode == ESP_HID_PROTOCOL_MODE_BOOT); TEST_ASSERT(report_map->reports[1].usage == ESP_HID_USAGE_MOUSE); - TEST_ASSERT(report_map->reports[1].value_len == 4); + TEST_ASSERT(report_map->reports[1].value_len == 3); TEST_ASSERT(report_map->reports[2].report_id == 2); TEST_ASSERT(report_map->reports[2].report_type == ESP_HID_REPORT_TYPE_INPUT); TEST_ASSERT(report_map->reports[2].protocol_mode == ESP_HID_PROTOCOL_MODE_REPORT); @@ -89,7 +89,7 @@ TEST_CASE("can parse relMouseReportMap", "[esp_hid]") TEST_ASSERT(report_map->reports[1].report_type == ESP_HID_REPORT_TYPE_INPUT); TEST_ASSERT(report_map->reports[1].protocol_mode == ESP_HID_PROTOCOL_MODE_BOOT); TEST_ASSERT(report_map->reports[1].usage == ESP_HID_USAGE_MOUSE); - TEST_ASSERT(report_map->reports[1].value_len == 4); + TEST_ASSERT(report_map->reports[1].value_len == 3); esp_hid_free_report_map(report_map); } @@ -109,7 +109,7 @@ TEST_CASE("can parse absMouseReportMap", "[esp_hid]") TEST_ASSERT(report_map->reports[1].report_type == ESP_HID_REPORT_TYPE_INPUT); TEST_ASSERT(report_map->reports[1].protocol_mode == ESP_HID_PROTOCOL_MODE_BOOT); TEST_ASSERT(report_map->reports[1].usage == ESP_HID_USAGE_MOUSE); - TEST_ASSERT(report_map->reports[1].value_len == 4); + TEST_ASSERT(report_map->reports[1].value_len == 3); esp_hid_free_report_map(report_map); } diff --git a/components/esp_http_client/esp_http_client.c b/components/esp_http_client/esp_http_client.c index 30cc3c9824..61cb52a946 100644 --- a/components/esp_http_client/esp_http_client.c +++ b/components/esp_http_client/esp_http_client.c @@ -632,6 +632,10 @@ esp_http_client_handle_t esp_http_client_init(const esp_http_client_config_t *co } } + if (config->client_key_password && config->client_key_password_len > 0) { + esp_transport_ssl_set_client_key_password(ssl, config->client_key_password, config->client_key_password_len); + } + if (config->skip_cert_common_name_check) { esp_transport_ssl_skip_common_name_check(ssl); } @@ -993,11 +997,19 @@ int esp_http_client_read(esp_http_client_handle_t client, char *buffer, int len) } ESP_LOG_LEVEL(sev, TAG, "esp_transport_read returned:%d and errno:%d ", rlen, errno); } - if (rlen < 0 && ridx == 0 && !esp_http_client_is_complete_data_received(client)) { - return ESP_FAIL; - } else { +#ifdef CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS + if (rlen == ESP_TLS_ERR_SSL_WANT_READ || errno == EAGAIN) { +#else + if (errno == EAGAIN) { +#endif + ESP_LOGD(TAG, "Received EAGAIN! rlen = %d, errno %d", rlen, errno); return ridx; } + if (rlen < 0 && ridx == 0 && !esp_http_client_is_complete_data_received(client)) { + http_dispatch_event(client, HTTP_EVENT_ERROR, esp_transport_get_error_handle(client->transport), 0); + return ESP_FAIL; + } + return ridx; } res_buffer->output_ptr = buffer + ridx; http_parser_execute(client->parser, client->parser_settings, res_buffer->data, rlen); @@ -1028,6 +1040,7 @@ esp_err_t esp_http_client_perform(esp_http_client_handle_t client) if (client->is_async && err == ESP_ERR_HTTP_CONNECTING) { return ESP_ERR_HTTP_EAGAIN; } + http_dispatch_event(client, HTTP_EVENT_ERROR, esp_transport_get_error_handle(client->transport), 0); return err; } /* falls through */ @@ -1036,6 +1049,7 @@ esp_err_t esp_http_client_perform(esp_http_client_handle_t client) if (client->is_async && errno == EAGAIN) { return ESP_ERR_HTTP_EAGAIN; } + http_dispatch_event(client, HTTP_EVENT_ERROR, esp_transport_get_error_handle(client->transport), 0); return err; } /* falls through */ @@ -1044,6 +1058,7 @@ esp_err_t esp_http_client_perform(esp_http_client_handle_t client) if (client->is_async && errno == EAGAIN) { return ESP_ERR_HTTP_EAGAIN; } + http_dispatch_event(client, HTTP_EVENT_ERROR, esp_transport_get_error_handle(client->transport), 0); return err; } /* falls through */ @@ -1052,17 +1067,20 @@ esp_err_t esp_http_client_perform(esp_http_client_handle_t client) if (client->is_async && errno == EAGAIN) { return ESP_ERR_HTTP_EAGAIN; } - if (esp_tls_get_and_clear_last_error(esp_transport_get_error_handle(client->transport), NULL, NULL) == ESP_ERR_ESP_TLS_TCP_CLOSED_FIN) { + if (esp_transport_get_errno(client->transport) == ENOTCONN) { ESP_LOGW(TAG, "Close connection due to FIN received"); esp_http_client_close(client); + http_dispatch_event(client, HTTP_EVENT_ERROR, esp_transport_get_error_handle(client->transport), 0); return ESP_ERR_HTTP_CONNECTION_CLOSED; } + http_dispatch_event(client, HTTP_EVENT_ERROR, esp_transport_get_error_handle(client->transport), 0); return ESP_ERR_HTTP_FETCH_HEADER; } /* falls through */ case HTTP_STATE_RES_COMPLETE_HEADER: if ((err = esp_http_check_response(client)) != ESP_OK) { ESP_LOGE(TAG, "Error response"); + http_dispatch_event(client, HTTP_EVENT_ERROR, esp_transport_get_error_handle(client->transport), 0); return err; } while (client->response->is_chunked && !client->is_chunk_complete) { @@ -1312,9 +1330,11 @@ esp_err_t esp_http_client_open(esp_http_client_handle_t client, int write_len) client->post_len = write_len; esp_err_t err; if ((err = esp_http_client_connect(client)) != ESP_OK) { + http_dispatch_event(client, HTTP_EVENT_ERROR, esp_transport_get_error_handle(client->transport), 0); return err; } if ((err = esp_http_client_request_send(client, write_len)) != ESP_OK) { + http_dispatch_event(client, HTTP_EVENT_ERROR, esp_transport_get_error_handle(client->transport), 0); return err; } return ESP_OK; diff --git a/components/esp_http_client/include/esp_http_client.h b/components/esp_http_client/include/esp_http_client.h index ab7e3c2e32..820c4168f6 100644 --- a/components/esp_http_client/include/esp_http_client.h +++ b/components/esp_http_client/include/esp_http_client.h @@ -113,6 +113,8 @@ typedef struct { size_t client_cert_len; /*!< Length of the buffer pointed to by client_cert_pem. May be 0 for null-terminated pem */ const char *client_key_pem; /*!< SSL client key, PEM format as string, if the server requires to verify client */ size_t client_key_len; /*!< Length of the buffer pointed to by client_key_pem. May be 0 for null-terminated pem */ + const char *client_key_password; /*!< Client key decryption password string */ + size_t client_key_password_len; /*!< String length of the password pointed to by client_key_password */ const char *user_agent; /*!< The User Agent string to send with HTTP requests */ esp_http_client_method_t method; /*!< HTTP Method */ int timeout_ms; /*!< Network timeout in milliseconds */ diff --git a/components/esp_http_server/include/esp_http_server.h b/components/esp_http_server/include/esp_http_server.h index d583bf1d60..1c8b78583f 100644 --- a/components/esp_http_server/include/esp_http_server.h +++ b/components/esp_http_server/include/esp_http_server.h @@ -1603,6 +1603,11 @@ typedef struct httpd_ws_frame { size_t len; /*!< Length of the WebSocket data */ } httpd_ws_frame_t; +/** + * @brief Transfer complete callback + */ +typedef void (*transfer_complete_cb)(esp_err_t err, int socket, void *arg); + /** * @brief Receive and parse a WebSocket frame * @@ -1663,6 +1668,35 @@ esp_err_t httpd_ws_send_frame_async(httpd_handle_t hd, int fd, httpd_ws_frame_t */ httpd_ws_client_info_t httpd_ws_get_fd_info(httpd_handle_t hd, int fd); +/** + * @brief Sends data to to specified websocket synchronously + * + * @param[in] handle Server instance data + * @param[in] socket Socket descriptor + * @param[in] frame Websocket frame + * @return + * - ESP_OK : On successful + * - ESP_FAIL : When socket errors occurs + * - ESP_ERR_NO_MEM : Unable to allocate memory + */ +esp_err_t httpd_ws_send_data(httpd_handle_t handle, int socket, httpd_ws_frame_t *frame); + +/** + * @brief Sends data to to specified websocket asynchronously + * + * @param[in] handle Server instance data + * @param[in] socket Socket descriptor + * @param[in] frame Websocket frame + * @param[in] callback Callback invoked after sending data + * @param[in] arg User data passed to provided callback + * @return + * - ESP_OK : On successful + * - ESP_FAIL : When socket errors occurs + * - ESP_ERR_NO_MEM : Unable to allocate memory + */ +esp_err_t httpd_ws_send_data_async(httpd_handle_t handle, int socket, httpd_ws_frame_t *frame, + transfer_complete_cb callback, void *arg); + #endif /* CONFIG_HTTPD_WS_SUPPORT */ /** End of WebSocket related stuff * @} diff --git a/components/esp_http_server/src/httpd_ws.c b/components/esp_http_server/src/httpd_ws.c index c4dd8c07e3..4a4c2373df 100644 --- a/components/esp_http_server/src/httpd_ws.c +++ b/components/esp_http_server/src/httpd_ws.c @@ -16,9 +16,23 @@ #include #include "esp_httpd_priv.h" +#include "freertos/event_groups.h" #ifdef CONFIG_HTTPD_WS_SUPPORT +#define WS_SEND_OK (1 << 0) +#define WS_SEND_FAILED (1 << 1) + +typedef struct { + httpd_ws_frame_t frame; + httpd_handle_t handle; + int socket; + transfer_complete_cb callback; + void *arg; + bool blocking; + EventGroupHandle_t transfer_done; +} async_transfer_t; + static const char *TAG="httpd_ws"; /* @@ -328,15 +342,19 @@ esp_err_t httpd_ws_recv_frame(httpd_req_t *req, httpd_ws_frame_t *frame, size_t return ESP_FAIL; } - int read_len = 0, left_len = frame->len; + size_t left_len = frame->len; + size_t offset = 0; + while (left_len > 0) { - if ((read_len = httpd_recv_with_opt(req, (char *)frame->payload + read_len, left_len, false)) <= 0) { + int read_len = httpd_recv_with_opt(req, (char *)frame->payload + offset, left_len, false); + if (read_len <= 0) { ESP_LOGW(TAG, LOG_FMT("Failed to receive payload")); return ESP_FAIL; } - if (left_len -= read_len) { - ESP_LOGD(TAG, "recv data length is less than the data length we want. Read again!"); - } + offset += read_len; + left_len -= read_len; + + ESP_LOGD(TAG, "Frame length: %d, Bytes Read: %d", frame->len, offset); } /* Unmask payload */ @@ -480,4 +498,77 @@ httpd_ws_client_info_t httpd_ws_get_fd_info(httpd_handle_t hd, int fd) return is_active_ws ? HTTPD_WS_CLIENT_WEBSOCKET : HTTPD_WS_CLIENT_HTTP; } +static void httpd_ws_send_cb(void *arg) +{ + async_transfer_t *trans = arg; + + esp_err_t err = httpd_ws_send_frame_async(trans->handle, trans->socket, &trans->frame); + + if (trans->blocking) { + xEventGroupSetBits(trans->transfer_done, err ? WS_SEND_FAILED : WS_SEND_OK); + } else if (trans->callback) { + trans->callback(err, trans->socket, trans->arg); + } + + free(trans); +} + +esp_err_t httpd_ws_send_data(httpd_handle_t handle, int socket, httpd_ws_frame_t *frame) +{ + async_transfer_t *transfer = calloc(1, sizeof(async_transfer_t)); + if (transfer == NULL) { + return ESP_ERR_NO_MEM; + } + + EventGroupHandle_t transfer_done = xEventGroupCreate(); + if (!transfer_done) { + free(transfer); + return ESP_ERR_NO_MEM; + } + + transfer->blocking = true; + transfer->handle = handle; + transfer->socket = socket; + transfer->transfer_done = transfer_done; + memcpy(&transfer->frame, frame, sizeof(httpd_ws_frame_t)); + + esp_err_t err = httpd_queue_work(handle, httpd_ws_send_cb, transfer); + if (err != ESP_OK) { + vEventGroupDelete(transfer_done); + free(transfer); + return err; + } + + EventBits_t status = xEventGroupWaitBits(transfer_done, WS_SEND_OK | WS_SEND_FAILED, + pdTRUE, pdFALSE, portMAX_DELAY); + + vEventGroupDelete(transfer_done); + + return (status & WS_SEND_OK) ? ESP_OK : ESP_FAIL; +} + +esp_err_t httpd_ws_send_data_async(httpd_handle_t handle, int socket, httpd_ws_frame_t *frame, + transfer_complete_cb callback, void *arg) +{ + async_transfer_t *transfer = calloc(1, sizeof(async_transfer_t)); + if (transfer == NULL) { + return ESP_ERR_NO_MEM; + } + + transfer->arg = arg; + transfer->callback = callback; + transfer->handle = handle; + transfer->socket = socket; + memcpy(&transfer->frame, frame, sizeof(httpd_ws_frame_t)); + + esp_err_t err = httpd_queue_work(handle, httpd_ws_send_cb, transfer); + + if (err) { + free(transfer); + return err; + } + + return ESP_OK; +} + #endif /* CONFIG_HTTPD_WS_SUPPORT */ diff --git a/components/esp_https_ota/src/esp_https_ota.c b/components/esp_https_ota/src/esp_https_ota.c index 910d652c91..ddbf73a565 100644 --- a/components/esp_https_ota/src/esp_https_ota.c +++ b/components/esp_https_ota/src/esp_https_ota.c @@ -390,10 +390,11 @@ esp_err_t esp_https_ota_perform(esp_https_ota_handle_t https_ota_handle) } else if (!is_recv_complete) { return ESP_ERR_HTTPS_OTA_IN_PROGRESS; } - ESP_LOGI(TAG, "Connection closed"); + ESP_LOGD(TAG, "Connection closed"); } else if (data_read > 0) { return _ota_write(handle, (const void *)handle->ota_upgrade_buf, data_read); } else { + ESP_LOGE(TAG, "data read %d, errno %d", data_read, errno); return ESP_FAIL; } if (!handle->partial_http_download || (handle->partial_http_download && handle->image_length == handle->binary_file_len)) { @@ -425,6 +426,7 @@ esp_err_t esp_https_ota_perform(esp_https_ota_handle_t https_ota_handle) ESP_LOGE(TAG, "Failed to establish HTTP connection"); return ESP_FAIL; } + ESP_LOGD(TAG, "Connection start"); return ESP_ERR_HTTPS_OTA_IN_PROGRESS; } } diff --git a/components/esp_https_server/include/esp_https_server.h b/components/esp_https_server/include/esp_https_server.h index 52f9dc2132..00565a963a 100644 --- a/components/esp_https_server/include/esp_https_server.h +++ b/components/esp_https_server/include/esp_https_server.h @@ -63,6 +63,9 @@ struct httpd_ssl_config { /** Port used when transport mode is insecure (default 80) */ uint16_t port_insecure; + + /** Enable tls session tickets */ + bool session_tickets; }; typedef struct httpd_ssl_config httpd_ssl_config_t; @@ -109,6 +112,7 @@ typedef struct httpd_ssl_config httpd_ssl_config_t; .transport_mode = HTTPD_SSL_TRANSPORT_SECURE, \ .port_secure = 443, \ .port_insecure = 80, \ + .session_tickets = false, \ } /** diff --git a/components/esp_https_server/src/https_server.c b/components/esp_https_server/src/https_server.c index 6949bf52af..9864ead3b2 100644 --- a/components/esp_https_server/src/https_server.c +++ b/components/esp_https_server/src/https_server.c @@ -145,6 +145,7 @@ static void free_secure_context(void *ctx) if (cfg->serverkey_buf) { free((void *)cfg->serverkey_buf); } + esp_tls_cfg_server_session_tickets_free(cfg); free(cfg); free(ssl_ctx); } @@ -160,6 +161,16 @@ static httpd_ssl_ctx_t *create_secure_context(const struct httpd_ssl_config *con free(ssl_ctx); return NULL; } + + if (config->session_tickets) { + if ( esp_tls_cfg_server_session_tickets_init(cfg) != ESP_OK ) { + ESP_LOGE(TAG, "Failed to init session ticket support"); + free(ssl_ctx); + free(cfg); + return NULL; + } + } + ssl_ctx->tls_cfg = cfg; /* cacert = CA which signs client cert, or client cert itself , which is mapped to client_verify_cert_pem */ if(config->client_verify_cert_pem != NULL) { diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index 236f930ec5..2846fab097 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -1,6 +1,5 @@ idf_build_get_property(target IDF_TARGET) -set(priv_requires efuse) set(requires soc) set(priv_requires efuse bootloader_support spi_flash) if(${target} STREQUAL "esp32") @@ -16,8 +15,13 @@ if(NOT BOOTLOADER_BUILD) "intr_alloc.c" "mac_addr.c" "sleep_modes.c" + "sleep_gpio.c" + "sleep_mac_bb.c" "regi2c_ctrl.c") - list(APPEND priv_requires esp_ipc) + if(NOT CONFIG_IDF_TARGET_ESP32 AND NOT CONFIG_IDF_TARGET_ESP32S2) + list(APPEND srcs "sleep_retention.c") + endif() + list(APPEND requires esp_ipc) else() # Requires "_esp_error_check_failed()" function list(APPEND priv_requires "esp_system") diff --git a/components/esp_hw_support/Kconfig b/components/esp_hw_support/Kconfig index 22b4b6a56f..2d09fa5f12 100644 --- a/components/esp_hw_support/Kconfig +++ b/components/esp_hw_support/Kconfig @@ -29,5 +29,26 @@ menu "Hardware Settings" This option will in fact consider VDD_SDIO auto power value (ESP_PD_OPTION_AUTO) as OFF. Also, it is possible to force a power domain to stay ON during light sleep by using esp_sleep_pd_config() function. + + config ESP_SLEEP_RTC_BUS_ISO_WORKAROUND + bool + default y if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 + + config ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND + bool "PSRAM leakage current workaround in light sleep" + depends on SPIRAM + help + When the CS pin of SPIRAM is not pulled up, the sleep current will + increase during light sleep. If the CS pin of SPIRAM has an external + pull-up, you do not need to select this option, otherwise, you + should enable this option. + + config ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND + bool "Flash leakage current workaround in light sleep" + help + When the CS pin of Flash is not pulled up, the sleep current will + increase during light sleep. If the CS pin of Flash has an external + pull-up, you do not need to select this option, otherwise, you + should enable this option. endmenu endmenu diff --git a/components/esp_hw_support/Kconfig.spiram.common b/components/esp_hw_support/Kconfig.spiram.common index a0616bf444..ae9b298b4a 100644 --- a/components/esp_hw_support/Kconfig.spiram.common +++ b/components/esp_hw_support/Kconfig.spiram.common @@ -92,7 +92,7 @@ config SPIRAM_MALLOC_RESERVE_INTERNAL config SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY bool "Allow .bss segment placed in external memory" default n - depends on SPIRAM && IDF_TARGET_ESP32 # TODO ESP32-S2 IDFGH-4320, ESP32-S3 IDF-1974 + depends on SPIRAM && (IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2) # ESP32-S3 IDF-1974 select ESP_ALLOW_BSS_SEG_EXTERNAL_MEMORY help If enabled, variables with EXT_RAM_ATTR attribute will be placed in SPIRAM instead of internal DRAM. diff --git a/components/esp_hw_support/clk_ctrl_os.c b/components/esp_hw_support/clk_ctrl_os.c index ae1d42c0ed..d3cc0d5248 100644 --- a/components/esp_hw_support/clk_ctrl_os.c +++ b/components/esp_hw_support/clk_ctrl_os.c @@ -1,19 +1,12 @@ -// 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "soc/clk_ctrl_os.h" +#include "sdkconfig.h" #define DELAY_RTC_CLK_SWITCH 5 @@ -27,7 +20,11 @@ bool periph_rtc_dig_clk8m_enable(void) portENTER_CRITICAL(&periph_spinlock); if (s_periph_ref_counts == 0) { rtc_dig_clk8m_enable(); +#if CONFIG_IDF_TARGET_ESP32H2 + s_rtc_clk_freq = rtc_clk_freq_cal(rtc_clk_cal(RTC_CAL_RC32K, 100)); +#else s_rtc_clk_freq = rtc_clk_freq_cal(rtc_clk_cal(RTC_CAL_8MD256, 100)); +#endif if (s_rtc_clk_freq == 0) { portEXIT_CRITICAL(&periph_spinlock); return false; diff --git a/components/esp_hw_support/compare_set.c b/components/esp_hw_support/compare_set.c index 09487eb63f..ebce9c127a 100644 --- a/components/esp_hw_support/compare_set.c +++ b/components/esp_hw_support/compare_set.c @@ -1,16 +1,8 @@ -// Copyright 2015-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: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "soc/compare_set.h" #include "soc/spinlock.h" #include "soc/soc_caps.h" diff --git a/components/esp_hw_support/component.mk b/components/esp_hw_support/component.mk index 5e75d5e0e3..f0f472034f 100644 --- a/components/esp_hw_support/component.mk +++ b/components/esp_hw_support/component.mk @@ -6,6 +6,9 @@ ifdef IS_BOOTLOADER_BUILD COMPONENT_OBJEXCLUDE += clk_ctrl_os.o \ intr_alloc.o \ sleep_modes.o \ + sleep_gpio.o \ + sleep_mac_bb.o \ + sleep_retention.o \ esp_async_memcpy.o \ mac_addr.o \ regi2c_ctrl.o \ @@ -16,4 +19,11 @@ COMPONENT_OBJEXCLUDE += clk_ctrl_os.o \ port/$(IDF_TARGET)/spiram_psram.o endif +ifdef CONFIG_IDF_TARGET_ESP32 +COMPONENT_OBJEXCLUDE += sleep_retention.o +endif +ifdef CONFIG_IDF_TARGET_ESP32S2 +COMPONENT_OBJEXCLUDE += sleep_retention.o +endif + COMPONENT_OBJEXCLUDE += esp_async_memcpy.o diff --git a/components/esp_hw_support/cpu_util.c b/components/esp_hw_support/cpu_util.c index bd01235d6c..54700e2b69 100644 --- a/components/esp_hw_support/cpu_util.c +++ b/components/esp_hw_support/cpu_util.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "esp_attr.h" #include "soc/cpu.h" diff --git a/components/esp_hw_support/esp_async_memcpy.c b/components/esp_hw_support/esp_async_memcpy.c index 465bf82197..dda8c6cca9 100644 --- a/components/esp_hw_support/esp_async_memcpy.c +++ b/components/esp_hw_support/esp_async_memcpy.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "freertos/FreeRTOS.h" diff --git a/components/esp_hw_support/esp_clk.c b/components/esp_hw_support/esp_clk.c index 8328b4d05e..591a33370b 100644 --- a/components/esp_hw_support/esp_clk.c +++ b/components/esp_hw_support/esp_clk.c @@ -1,16 +1,8 @@ -// Copyright 2015-2017 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include diff --git a/components/esp_hw_support/hw_random.c b/components/esp_hw_support/hw_random.c index 05b60b4028..9ba4e66a15 100644 --- a/components/esp_hw_support/hw_random.c +++ b/components/esp_hw_support/hw_random.c @@ -1,16 +1,8 @@ -// Copyright 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. +/* + * SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include diff --git a/components/esp_hw_support/include/esp_async_memcpy.h b/components/esp_hw_support/include/esp_async_memcpy.h index e95f9638e7..c45c61b2d1 100644 --- a/components/esp_hw_support/include/esp_async_memcpy.h +++ b/components/esp_hw_support/include/esp_async_memcpy.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/include/esp_chip_info.h b/components/esp_hw_support/include/esp_chip_info.h index d04dcaf424..69d23c08d3 100644 --- a/components/esp_hw_support/include/esp_chip_info.h +++ b/components/esp_hw_support/include/esp_chip_info.h @@ -1,16 +1,8 @@ -// Copyright 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: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -30,7 +22,7 @@ extern "C" { typedef enum { CHIP_ESP32 = 1, //!< ESP32 CHIP_ESP32S2 = 2, //!< ESP32-S2 - CHIP_ESP32S3 = 4, //!< ESP32-S3 + CHIP_ESP32S3 = 9, //!< ESP32-S3 CHIP_ESP32C3 = 5, //!< ESP32-C3 CHIP_ESP32H2 = 6, //!< ESP32-H2 } esp_chip_model_t; diff --git a/components/esp_hw_support/include/esp_cpu.h b/components/esp_hw_support/include/esp_cpu.h index e1536e979b..2a810aba44 100644 --- a/components/esp_hw_support/include/esp_cpu.h +++ b/components/esp_hw_support/include/esp_cpu.h @@ -1,16 +1,8 @@ -// Copyright 2010-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. +/* + * SPDX-FileCopyrightText: 2010-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _ESP_CPU_H #define _ESP_CPU_H diff --git a/components/esp_hw_support/include/esp_crc.h b/components/esp_hw_support/include/esp_crc.h index 6294a7b621..f12dcf767d 100644 --- a/components/esp_hw_support/include/esp_crc.h +++ b/components/esp_hw_support/include/esp_crc.h @@ -1,16 +1,8 @@ -// Copyright 2015-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: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once #ifdef __cplusplus diff --git a/components/esp_hw_support/include/esp_fault.h b/components/esp_hw_support/include/esp_fault.h index fe9de33425..910ba59d06 100644 --- a/components/esp_hw_support/include/esp_fault.h +++ b/components/esp_hw_support/include/esp_fault.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "sdkconfig.h" #include "soc/rtc_cntl_reg.h" #include "esp_rom_sys.h" diff --git a/components/esp_hw_support/include/esp_interface.h b/components/esp_hw_support/include/esp_interface.h index 950c05bb22..fdb4c0056c 100644 --- a/components/esp_hw_support/include/esp_interface.h +++ b/components/esp_hw_support/include/esp_interface.h @@ -1,16 +1,8 @@ -// 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. +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef __ESP_INTERFACE_H__ diff --git a/components/esp_hw_support/include/esp_intr.h b/components/esp_hw_support/include/esp_intr.h index c29dc9bfd1..0818ed3fea 100644 --- a/components/esp_hw_support/include/esp_intr.h +++ b/components/esp_hw_support/include/esp_intr.h @@ -1,16 +1,8 @@ -// Copyright 2010-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. +/* + * SPDX-FileCopyrightText: 2010-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once #warning esp_intr.h is deprecated, please include esp_intr_alloc.h instead diff --git a/components/esp_hw_support/include/esp_intr_alloc.h b/components/esp_hw_support/include/esp_intr_alloc.h index 33f70b9597..a26fde9394 100644 --- a/components/esp_hw_support/include/esp_intr_alloc.h +++ b/components/esp_hw_support/include/esp_intr_alloc.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/include/esp_mac.h b/components/esp_hw_support/include/esp_mac.h index 75e01ebbd1..f0efddfc2f 100644 --- a/components/esp_hw_support/include/esp_mac.h +++ b/components/esp_hw_support/include/esp_mac.h @@ -1,16 +1,8 @@ -// Copyright 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: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -79,6 +71,7 @@ esp_err_t esp_base_mac_addr_set(const uint8_t *mac); * 8 bytes for EUI-64(used for IEEE 802.15.4) * * @return ESP_OK on success + * ESP_ERR_INVALID_ARG mac is NULL * ESP_ERR_INVALID_MAC base MAC address has not been set */ esp_err_t esp_base_mac_addr_get(uint8_t *mac); @@ -100,8 +93,10 @@ esp_err_t esp_base_mac_addr_get(uint8_t *mac); * 8 bytes for EUI-64(used for IEEE 802.15.4) * * @return ESP_OK on success - * ESP_ERR_INVALID_VERSION An invalid MAC version field was read from BLK3 of EFUSE - * ESP_ERR_INVALID_CRC An invalid MAC CRC was read from BLK3 of EFUSE + * ESP_ERR_INVALID_ARG mac is NULL + * ESP_ERR_INVALID_MAC CUSTOM_MAC address has not been set, all zeros (for esp32-xx) + * ESP_ERR_INVALID_VERSION An invalid MAC version field was read from BLK3 of EFUSE (for esp32) + * ESP_ERR_INVALID_CRC An invalid MAC CRC was read from BLK3 of EFUSE (for esp32) */ esp_err_t esp_efuse_mac_get_custom(uint8_t *mac); @@ -113,6 +108,7 @@ esp_err_t esp_efuse_mac_get_custom(uint8_t *mac); * 8 bytes for EUI-64(used for IEEE 802.15.4) * * @return ESP_OK on success + * ESP_ERR_INVALID_ARG mac is NULL */ esp_err_t esp_efuse_mac_get_default(uint8_t *mac); diff --git a/components/esp_hw_support/include/esp_private/esp_clk.h b/components/esp_hw_support/include/esp_private/esp_clk.h index 14326898bd..5a4666fddd 100644 --- a/components/esp_hw_support/include/esp_private/esp_clk.h +++ b/components/esp_hw_support/include/esp_private/esp_clk.h @@ -1,16 +1,8 @@ -// Copyright 2015-2017 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once #include diff --git a/components/esp_hw_support/include/esp_private/sleep_gpio.h b/components/esp_hw_support/include/esp_private/sleep_gpio.h new file mode 100644 index 0000000000..abab21871a --- /dev/null +++ b/components/esp_hw_support/include/esp_private/sleep_gpio.h @@ -0,0 +1,46 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once +#include +#include "sdkconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file sleep_gpio.h + * + * This file contains declarations of GPIO related functions in light sleep mode. + */ + +#if SOC_GPIO_SUPPORT_SLP_SWITCH && CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL + +/** + * @brief Save GPIO pull-up and pull-down configuration information in the wake-up state + * + * In light sleep mode, the pull-up and pull-down resistors of GPIO will cause + * leakage current when the system sleeps. In order to reduce the power + * consumption of system sleep, it needs to save the configuration information + * of all GPIO pull-up and pull-down resistors and disable the pull-up and + * pull-down resistors of GPIO before the system enters sleep. + */ +void gpio_sleep_mode_config_apply(void); + +/** + * @brief Restore GPIO pull-up and pull-down configuration information in the wake-up state + * + * In light sleep mode, after the system wakes up, it needs to restore all GPIO + * pull-up and pull-down configurations before the last sleep. + */ +void gpio_sleep_mode_config_unapply(void); + +#endif // SOC_GPIO_SUPPORT_SLP_SWITCH && CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/include/esp_private/sleep_mac_bb.h b/components/esp_hw_support/include/esp_private/sleep_mac_bb.h new file mode 100644 index 0000000000..6b4019639d --- /dev/null +++ b/components/esp_hw_support/include/esp_private/sleep_mac_bb.h @@ -0,0 +1,43 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once +#include +#include "sdkconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file sleep_mac_bb.h + * + * This file contains declarations of MAC and baseband power consumption related functions in light sleep mode. + */ + +#if CONFIG_MAC_BB_PD + +/** + * @brief A callback function completes MAC and baseband power down operation + * + * In light sleep mode, execute Wi-Fi and Bluetooth module MAC and baseband + * power down and backup register configuration information operations. + */ +void mac_bb_power_down_cb_execute(void); + +/** + * @brief A callback function completes MAC and baseband power up operation + * + * In light sleep mode, execute Wi-Fi and Bluetooth module MAC and baseband + * power up and restore register configuration information operations. + */ +void mac_bb_power_up_cb_execute(void); + +#endif // CONFIG_MAC_BB_PD + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/include/esp_private/sleep_retention.h b/components/esp_hw_support/include/esp_private/sleep_retention.h new file mode 100644 index 0000000000..001e559c0c --- /dev/null +++ b/components/esp_hw_support/include/esp_private/sleep_retention.h @@ -0,0 +1,55 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once +#include +#include "sdkconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file sleep_retention.h + * + * This file contains declarations of memory retention related functions in light sleeo mode. + */ + +#if SOC_PM_SUPPORT_CPU_PD + +/** + * @brief Whether to allow the cpu power domain to be powered off. + * + * In light sleep mode, only when the system can provide enough memory + * for cpu retention, the cpu power domain can be powered off. + */ +bool cpu_domain_pd_allowed(void); + +#endif + +#if SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD + +/** + * @brief Enable memory retention of some modules. + * + * In light sleep mode, before the system goes to sleep, enable the memory + * retention of modules such as CPU and I/D-cache tag memory. + */ +void sleep_enable_memory_retention(void); + +/** + * @brief Disable memory retention of some modules. + * + * In light sleep mode, after the system exits sleep, disable the memory + * retention of moudles such as CPU and I/D-cache tag memory. + */ +void sleep_disable_memory_retention(void); + +#endif // SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/include/esp_random.h b/components/esp_hw_support/include/esp_random.h index cf4f408b51..a6b8a884b6 100644 --- a/components/esp_hw_support/include/esp_random.h +++ b/components/esp_hw_support/include/esp_random.h @@ -1,16 +1,8 @@ -// Copyright 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: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/include/esp_sleep.h b/components/esp_hw_support/include/esp_sleep.h index 000d020aeb..75d2f9726c 100644 --- a/components/esp_hw_support/include/esp_sleep.h +++ b/components/esp_hw_support/include/esp_sleep.h @@ -1,16 +1,8 @@ -// Copyright 2015-2017 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -49,7 +41,10 @@ typedef enum { ESP_PD_DOMAIN_RTC_SLOW_MEM, //!< RTC slow memory ESP_PD_DOMAIN_RTC_FAST_MEM, //!< RTC fast memory ESP_PD_DOMAIN_XTAL, //!< XTAL oscillator +#if SOC_PM_SUPPORT_CPU_PD ESP_PD_DOMAIN_CPU, //!< CPU core +#endif + ESP_PD_DOMAIN_RTC8M, //!< Internal 8M oscillator ESP_PD_DOMAIN_VDDSDIO, //!< VDD_SDIO ESP_PD_DOMAIN_MAX //!< Number of domains } esp_sleep_pd_domain_t; @@ -380,6 +375,8 @@ esp_err_t esp_light_sleep_start(void); * * This function does not return. * + * @note The device will wake up immediately if the deep-sleep time is set to 0 + * * @param time_in_us deep-sleep time, unit: microsecond */ void esp_deep_sleep(uint64_t time_in_us) __attribute__((noreturn)); diff --git a/components/esp_hw_support/include/soc/clk_ctrl_os.h b/components/esp_hw_support/include/soc/clk_ctrl_os.h index f4d769b801..b5eff46930 100644 --- a/components/esp_hw_support/include/soc/clk_ctrl_os.h +++ b/components/esp_hw_support/include/soc/clk_ctrl_os.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "soc/rtc.h" diff --git a/components/esp_hw_support/include/soc/compare_set.h b/components/esp_hw_support/include/soc/compare_set.h index ddbaeb7e3d..b5a35fa701 100644 --- a/components/esp_hw_support/include/soc/compare_set.h +++ b/components/esp_hw_support/include/soc/compare_set.h @@ -1,16 +1,8 @@ -// Copyright 2015-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: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/include/soc/cpu.h b/components/esp_hw_support/include/soc/cpu.h index 0e4d1688ca..526171bc1c 100644 --- a/components/esp_hw_support/include/soc/cpu.h +++ b/components/esp_hw_support/include/soc/cpu.h @@ -1,16 +1,8 @@ -// Copyright 2010-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. +/* + * SPDX-FileCopyrightText: 2010-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_CPU_H #define _SOC_CPU_H diff --git a/components/esp_hw_support/include/soc/esp32/clk.h b/components/esp_hw_support/include/soc/esp32/clk.h index 31902ebad0..a9ed302852 100644 --- a/components/esp_hw_support/include/soc/esp32/clk.h +++ b/components/esp_hw_support/include/soc/esp32/clk.h @@ -1,16 +1,8 @@ -// Copyright 2015-2017 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once #include "esp_private/esp_clk.h" diff --git a/components/esp_hw_support/include/soc/esp32/dport_access.h b/components/esp_hw_support/include/soc/esp32/dport_access.h index 4f473940ad..8e04674951 100644 --- a/components/esp_hw_support/include/soc/esp32/dport_access.h +++ b/components/esp_hw_support/include/soc/esp32/dport_access.h @@ -3,30 +3,28 @@ * * SPDX-License-Identifier: Apache-2.0 */ + +#pragma once + #include - #include - -#ifndef _ESP_DPORT_ACCESS_H_ -#define _ESP_DPORT_ACCESS_H_ - #include "xtensa/xtruntime.h" #ifdef __cplusplus extern "C" { #endif -void esp_dport_access_stall_other_cpu_start(void); -void esp_dport_access_stall_other_cpu_end(void); -void esp_dport_access_int_init(void); -void esp_dport_access_int_pause(void); -void esp_dport_access_int_resume(void); +void esp_dport_access_stall_other_cpu_start(void) __attribute__ ((deprecated)); +void esp_dport_access_stall_other_cpu_end(void) __attribute__ ((deprecated)); +void esp_dport_access_int_init(void) __attribute__ ((deprecated)); +void esp_dport_access_int_pause(void) __attribute__ ((deprecated)); +void esp_dport_access_int_resume(void) __attribute__ ((deprecated)); void esp_dport_access_read_buffer(uint32_t *buff_out, uint32_t address, uint32_t num_words); uint32_t esp_dport_access_reg_read(uint32_t reg); uint32_t esp_dport_access_sequence_reg_read(uint32_t reg); //This routine does not stop the dport routines in any way that is recoverable. Please //only call in case of panic(). -void esp_dport_access_int_abort(void); +void esp_dport_access_int_abort(void) __attribute__ ((deprecated)); #if defined(BOOTLOADER_BUILD) || !defined(CONFIG_ESP32_DPORT_WORKAROUND) || !defined(ESP_PLATFORM) #define DPORT_STALL_OTHER_CPU_START() @@ -34,8 +32,9 @@ void esp_dport_access_int_abort(void); #define DPORT_INTERRUPT_DISABLE() #define DPORT_INTERRUPT_RESTORE() #else -#define DPORT_STALL_OTHER_CPU_START() esp_dport_access_stall_other_cpu_start() -#define DPORT_STALL_OTHER_CPU_END() esp_dport_access_stall_other_cpu_end() +#include "esp_ipc_isr.h" +#define DPORT_STALL_OTHER_CPU_START() esp_ipc_isr_stall_other_cpu() +#define DPORT_STALL_OTHER_CPU_END() esp_ipc_isr_release_other_cpu() #define DPORT_INTERRUPT_DISABLE() unsigned int intLvl = XTOS_SET_INTLEVEL(CONFIG_ESP32_DPORT_DIS_INTERRUPT_LVL) #define DPORT_INTERRUPT_RESTORE() XTOS_RESTORE_JUST_INTLEVEL(intLvl) #endif @@ -43,5 +42,3 @@ void esp_dport_access_int_abort(void); #ifdef __cplusplus } #endif - -#endif /* _ESP_DPORT_ACCESS_H_ */ diff --git a/components/esp_hw_support/include/soc/esp32/spiram.h b/components/esp_hw_support/include/soc/esp32/spiram.h index e58712d1fa..a6086f3d31 100644 --- a/components/esp_hw_support/include/soc/esp32/spiram.h +++ b/components/esp_hw_support/include/soc/esp32/spiram.h @@ -85,6 +85,15 @@ size_t esp_spiram_get_size(void); */ void esp_spiram_writeback_cache(void); +/** + * @brief get psram CS IO + * + * This interface should be called after PSRAM is enabled, otherwise it will + * return an invalid value -1/0xff. + * + * @return psram CS IO or -1/0xff if psram not enabled + */ +uint8_t esp_spiram_get_cs_io(void); /** diff --git a/components/esp_hw_support/include/soc/esp32c3/clk.h b/components/esp_hw_support/include/soc/esp32c3/clk.h index 31902ebad0..a9ed302852 100644 --- a/components/esp_hw_support/include/soc/esp32c3/clk.h +++ b/components/esp_hw_support/include/soc/esp32c3/clk.h @@ -1,16 +1,8 @@ -// Copyright 2015-2017 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once #include "esp_private/esp_clk.h" diff --git a/components/esp_hw_support/include/soc/esp32c3/dport_access.h b/components/esp_hw_support/include/soc/esp32c3/dport_access.h index f3f7007a9c..e5aedd2e1b 100644 --- a/components/esp_hw_support/include/soc/esp32c3/dport_access.h +++ b/components/esp_hw_support/include/soc/esp32c3/dport_access.h @@ -1,16 +1,8 @@ -// Copyright 2010-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: 2010-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _ESP_DPORT_ACCESS_H_ #define _ESP_DPORT_ACCESS_H_ diff --git a/components/esp_hw_support/include/soc/esp32c3/esp_crypto_lock.h b/components/esp_hw_support/include/soc/esp32c3/esp_crypto_lock.h index 3149d34692..67a08741b5 100644 --- a/components/esp_hw_support/include/soc/esp32c3/esp_crypto_lock.h +++ b/components/esp_hw_support/include/soc/esp32c3/esp_crypto_lock.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/include/soc/esp32c3/esp_ds.h b/components/esp_hw_support/include/soc/esp32c3/esp_ds.h index 911e44c837..9d59aa71c6 100644 --- a/components/esp_hw_support/include/soc/esp32c3/esp_ds.h +++ b/components/esp_hw_support/include/soc/esp32c3/esp_ds.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/include/soc/esp32c3/esp_hmac.h b/components/esp_hw_support/include/soc/esp32c3/esp_hmac.h index 391ba12fe1..26e2bc71a0 100644 --- a/components/esp_hw_support/include/soc/esp32c3/esp_hmac.h +++ b/components/esp_hw_support/include/soc/esp32c3/esp_hmac.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _ESP_HMAC_H_ #define _ESP_HMAC_H_ @@ -60,6 +52,35 @@ esp_err_t esp_hmac_calculate(hmac_key_id_t key_id, size_t message_len, uint8_t *hmac); +/** + * @brief Use HMAC peripheral in Downstream mode to re-enable the JTAG, if it is not permanently disabled by HW. + * In downstream mode, HMAC calculations performed by peripheral are used internally and not provided back to user. + * + * @param key_id Determines which of the 6 key blocks in the efuses should be used for the HMAC calculation. + * The corresponding purpose field of the key block in the efuse must be set to HMAC downstream purpose. + * + * @param token Pre calculated HMAC value of the 32-byte 0x00 using SHA-256 and the known private HMAC key. The key is already + * programmed to a eFuse key block. The key block number is provided as the first parameter to this function. + * + * @return + * * ESP_OK, if the calculation was successful, + * if the calculated HMAC value matches with provided token, + * JTAG will be re-enable otherwise JTAG will remain disabled. + * Return value does not indicate the JTAG status. + * * ESP_FAIL, if the hmac calculation failed or JTAG is permanently disabled by EFUSE_HARD_DIS_JTAG eFuse parameter. + * * ESP_ERR_INVALID_ARG, invalid input arguments + */ +esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token); + +/** + * @brief Disable the JTAG which might be enabled using the HMAC downstream mode. This function just clears the result generated + * by calling esp_hmac_jtag_enable() API. + * + * @return + * * ESP_OK return ESP_OK after writing the HMAC_SET_INVALIDATE_JTAG_REG with value 1. + */ +esp_err_t esp_hmac_jtag_disable(void); + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/include/soc/esp32c3/memprot.h b/components/esp_hw_support/include/soc/esp32c3/memprot.h index 0d7e6ca40d..818cd677dc 100644 --- a/components/esp_hw_support/include/soc/esp32c3/memprot.h +++ b/components/esp_hw_support/include/soc/esp32c3/memprot.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ /* INTERNAL API diff --git a/components/esp_hw_support/include/soc/esp32c3/rtc.h b/components/esp_hw_support/include/soc/esp32c3/rtc.h index b090ae5cfb..4d46831ded 100644 --- a/components/esp_hw_support/include/soc/esp32c3/rtc.h +++ b/components/esp_hw_support/include/soc/esp32c3/rtc.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/include/soc/esp32h2/clk.h b/components/esp_hw_support/include/soc/esp32h2/clk.h index 31902ebad0..a9ed302852 100644 --- a/components/esp_hw_support/include/soc/esp32h2/clk.h +++ b/components/esp_hw_support/include/soc/esp32h2/clk.h @@ -1,16 +1,8 @@ -// Copyright 2015-2017 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once #include "esp_private/esp_clk.h" diff --git a/components/esp_hw_support/include/soc/esp32h2/dport_access.h b/components/esp_hw_support/include/soc/esp32h2/dport_access.h index f3f7007a9c..e5aedd2e1b 100644 --- a/components/esp_hw_support/include/soc/esp32h2/dport_access.h +++ b/components/esp_hw_support/include/soc/esp32h2/dport_access.h @@ -1,16 +1,8 @@ -// Copyright 2010-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: 2010-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _ESP_DPORT_ACCESS_H_ #define _ESP_DPORT_ACCESS_H_ diff --git a/components/esp_hw_support/include/soc/esp32h2/esp_crypto_lock.h b/components/esp_hw_support/include/soc/esp32h2/esp_crypto_lock.h index 3149d34692..67a08741b5 100644 --- a/components/esp_hw_support/include/soc/esp32h2/esp_crypto_lock.h +++ b/components/esp_hw_support/include/soc/esp32h2/esp_crypto_lock.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/include/soc/esp32h2/esp_ds.h b/components/esp_hw_support/include/soc/esp32h2/esp_ds.h index 79e963fc6b..6bad707558 100644 --- a/components/esp_hw_support/include/soc/esp32h2/esp_ds.h +++ b/components/esp_hw_support/include/soc/esp32h2/esp_ds.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/include/soc/esp32h2/esp_hmac.h b/components/esp_hw_support/include/soc/esp32h2/esp_hmac.h index 391ba12fe1..26e2bc71a0 100644 --- a/components/esp_hw_support/include/soc/esp32h2/esp_hmac.h +++ b/components/esp_hw_support/include/soc/esp32h2/esp_hmac.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _ESP_HMAC_H_ #define _ESP_HMAC_H_ @@ -60,6 +52,35 @@ esp_err_t esp_hmac_calculate(hmac_key_id_t key_id, size_t message_len, uint8_t *hmac); +/** + * @brief Use HMAC peripheral in Downstream mode to re-enable the JTAG, if it is not permanently disabled by HW. + * In downstream mode, HMAC calculations performed by peripheral are used internally and not provided back to user. + * + * @param key_id Determines which of the 6 key blocks in the efuses should be used for the HMAC calculation. + * The corresponding purpose field of the key block in the efuse must be set to HMAC downstream purpose. + * + * @param token Pre calculated HMAC value of the 32-byte 0x00 using SHA-256 and the known private HMAC key. The key is already + * programmed to a eFuse key block. The key block number is provided as the first parameter to this function. + * + * @return + * * ESP_OK, if the calculation was successful, + * if the calculated HMAC value matches with provided token, + * JTAG will be re-enable otherwise JTAG will remain disabled. + * Return value does not indicate the JTAG status. + * * ESP_FAIL, if the hmac calculation failed or JTAG is permanently disabled by EFUSE_HARD_DIS_JTAG eFuse parameter. + * * ESP_ERR_INVALID_ARG, invalid input arguments + */ +esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token); + +/** + * @brief Disable the JTAG which might be enabled using the HMAC downstream mode. This function just clears the result generated + * by calling esp_hmac_jtag_enable() API. + * + * @return + * * ESP_OK return ESP_OK after writing the HMAC_SET_INVALIDATE_JTAG_REG with value 1. + */ +esp_err_t esp_hmac_jtag_disable(void); + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/include/soc/esp32h2/memprot.h b/components/esp_hw_support/include/soc/esp32h2/memprot.h index 2567b604b0..75228580ff 100644 --- a/components/esp_hw_support/include/soc/esp32h2/memprot.h +++ b/components/esp_hw_support/include/soc/esp32h2/memprot.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ /* INTERNAL API diff --git a/components/esp_hw_support/include/soc/esp32h2/rtc.h b/components/esp_hw_support/include/soc/esp32h2/rtc.h index cca748df91..75460416c7 100644 --- a/components/esp_hw_support/include/soc/esp32h2/rtc.h +++ b/components/esp_hw_support/include/soc/esp32h2/rtc.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/include/soc/esp32s2/clk.h b/components/esp_hw_support/include/soc/esp32s2/clk.h index 31902ebad0..a9ed302852 100644 --- a/components/esp_hw_support/include/soc/esp32s2/clk.h +++ b/components/esp_hw_support/include/soc/esp32s2/clk.h @@ -1,16 +1,8 @@ -// Copyright 2015-2017 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once #include "esp_private/esp_clk.h" diff --git a/components/esp_hw_support/include/soc/esp32s2/dport_access.h b/components/esp_hw_support/include/soc/esp32s2/dport_access.h index 6ba6fd6555..e5aedd2e1b 100644 --- a/components/esp_hw_support/include/soc/esp32s2/dport_access.h +++ b/components/esp_hw_support/include/soc/esp32s2/dport_access.h @@ -1,16 +1,8 @@ -// Copyright 2010-2017 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: 2010-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _ESP_DPORT_ACCESS_H_ #define _ESP_DPORT_ACCESS_H_ diff --git a/components/esp_hw_support/include/soc/esp32s2/esp_crypto_lock.h b/components/esp_hw_support/include/soc/esp32s2/esp_crypto_lock.h index e1df0399f3..2c337c9371 100644 --- a/components/esp_hw_support/include/soc/esp32s2/esp_crypto_lock.h +++ b/components/esp_hw_support/include/soc/esp32s2/esp_crypto_lock.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/include/soc/esp32s2/esp_ds.h b/components/esp_hw_support/include/soc/esp32s2/esp_ds.h index 12906377ee..2ef0bd00fb 100644 --- a/components/esp_hw_support/include/soc/esp32s2/esp_ds.h +++ b/components/esp_hw_support/include/soc/esp32s2/esp_ds.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/include/soc/esp32s2/esp_hmac.h b/components/esp_hw_support/include/soc/esp32s2/esp_hmac.h index 5fa836c47d..409217c06b 100644 --- a/components/esp_hw_support/include/soc/esp32s2/esp_hmac.h +++ b/components/esp_hw_support/include/soc/esp32s2/esp_hmac.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _ESP_HMAC_H_ #define _ESP_HMAC_H_ diff --git a/components/esp_hw_support/include/soc/esp32s2/memprot.h b/components/esp_hw_support/include/soc/esp32s2/memprot.h index c63fb395e6..0ebd647457 100644 --- a/components/esp_hw_support/include/soc/esp32s2/memprot.h +++ b/components/esp_hw_support/include/soc/esp32s2/memprot.h @@ -1,17 +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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ /* INTERNAL API * generic interface to MMU memory protection features @@ -21,6 +12,7 @@ #include #include #include "esp_attr.h" +#include "esp_err.h" #ifdef __cplusplus extern "C" { @@ -51,6 +43,8 @@ extern "C" { #define MEMPROT_UNLOCK false #define DEF_SPLIT_LINE NULL +#define MEMPROT_INVALID_ADDRESS -1 + //memory range types typedef enum { MEMPROT_NONE = 0x00000000, @@ -77,23 +71,27 @@ typedef enum { uint32_t *IRAM_ATTR esp_memprot_get_split_addr(mem_type_prot_t mem_type); /** - * @brief Initializes illegal memory access control (MMU) for required memory section. + * @brief Initializes illegal memory access control for required memory section. * * All memory access interrupts share ETS_MEMACCESS_ERR_INUM input channel, it is caller's * responsibility to properly detect actual intr. source as well as possible prioritization in case * of multiple source reported during one intr.handling routine run * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * @param mem_type Memory protection area type (see mem_type_prot_t enum)\ + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_intr_init(mem_type_prot_t mem_type); +esp_err_t esp_memprot_intr_init(mem_type_prot_t mem_type); /** * @brief Enable/disable the memory protection interrupt * * @param mem_type Memory protection area type (see mem_type_prot_t enum) * @param enable enable/disable + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_intr_ena(mem_type_prot_t mem_type, bool enable); +esp_err_t esp_memprot_intr_ena(mem_type_prot_t mem_type, bool enable); /** * @brief Sets a request for clearing interrupt-on flag for specified memory region (register write) @@ -102,8 +100,10 @@ void esp_memprot_intr_ena(mem_type_prot_t mem_type, bool enable); * Should be used only after the real interrupt appears, typically as the last step in interrupt handler's routine. * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_clear_intr(mem_type_prot_t mem_type); +esp_err_t esp_memprot_clear_intr(mem_type_prot_t mem_type); /** * @brief Detects which memory protection interrupt is active @@ -122,10 +122,11 @@ mem_type_prot_t IRAM_ATTR esp_memprot_get_active_intr_memtype(void); * @brief Gets interrupt status register contents for specified memory region * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * @param fault_reg_val Contents of status register * - * @return Contents of status register + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -uint32_t esp_memprot_get_fault_reg(mem_type_prot_t mem_type); +esp_err_t esp_memprot_get_fault_reg(mem_type_prot_t mem_type, uint32_t *fault_reg_val); /** * @brief Get details of given interrupt status @@ -138,8 +139,9 @@ uint32_t esp_memprot_get_fault_reg(mem_type_prot_t mem_type); * @param op_subtype Additional info for op_type [out] * IRAM0: 0 - instruction segment access, 1 - data segment access * DRAM0: 0 - non-atomic operation, 1 - atomic operation + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void IRAM_ATTR esp_memprot_get_fault_status(mem_type_prot_t mem_type, uint32_t **faulting_address, uint32_t *op_type, uint32_t *op_subtype); +esp_err_t IRAM_ATTR esp_memprot_get_fault_status(mem_type_prot_t mem_type, uint32_t **faulting_address, uint32_t *op_type, uint32_t *op_subtype); /** * @brief Gets string representation of required memory region identifier @@ -163,26 +165,30 @@ bool esp_memprot_is_locked_any(void); * Locks can be unlocked only by digital system reset * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_set_lock(mem_type_prot_t mem_type); +esp_err_t esp_memprot_set_lock(mem_type_prot_t mem_type); /** * @brief Gets lock status for required memory region * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * @param locked Settings locked: true/false (locked/unlocked) * - * @return true/false (locked/unlocked) + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -bool esp_memprot_get_lock(mem_type_prot_t mem_type); +esp_err_t esp_memprot_get_lock(mem_type_prot_t mem_type, bool *locked); /** * @brief Gets permission control configuration register contents for required memory region * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * @param conf_reg_val Permission control register contents * - * @return Permission control register contents + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -uint32_t esp_memprot_get_conf_reg(mem_type_prot_t mem_type); +esp_err_t esp_memprot_get_conf_reg(mem_type_prot_t mem_type, uint32_t *conf_reg_val); /** * @brief Gets interrupt permission settings for unified management block @@ -190,21 +196,23 @@ uint32_t esp_memprot_get_conf_reg(mem_type_prot_t mem_type); * Gets interrupt permission settings register contents for required memory region, returns settings for unified management blocks * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * @param perm_reg Permission settings register contents * - * @return Permission settings register contents + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -uint32_t esp_memprot_get_perm_uni_reg(mem_type_prot_t mem_type); +esp_err_t esp_memprot_get_perm_uni_reg(mem_type_prot_t mem_type, uint32_t *perm_reg); /** * @brief Gets interrupt permission settings for split management block * - * Gets interrupt permission settings register contents for required memory region, returns settings for split management blocks + * Gets interrupt permission settings register contents for required memory region (unified management blocks) * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * @return split_reg Unified management settings register contents * - * @return Permission settings register contents + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -uint32_t esp_memprot_get_perm_split_reg(mem_type_prot_t mem_type); +esp_err_t esp_memprot_get_perm_split_reg(mem_type_prot_t mem_type, uint32_t *split_reg); /** * @brief Detects whether any of the memory protection interrupts is enabled @@ -217,28 +225,30 @@ bool esp_memprot_is_intr_ena_any(void); * @brief Gets interrupt-enabled flag for given memory region * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * @param enable_bit Interrupt-enabled flag * - * @return Interrupt-enabled value + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -uint32_t esp_memprot_get_intr_ena_bit(mem_type_prot_t mem_type); +esp_err_t esp_memprot_get_intr_ena_bit(mem_type_prot_t mem_type, uint32_t *enable_bit); /** * @brief Gets interrupt-active flag for given memory region * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * @param intr_on_bit Interrupt-active flag * - * @return Interrupt-active value - */ -uint32_t esp_memprot_get_intr_on_bit(mem_type_prot_t mem_type); + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ +esp_err_t esp_memprot_get_intr_on_bit(mem_type_prot_t mem_type, uint32_t *intr_on_bit); /** * @brief Gets interrupt-clear request flag for given memory region * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * @param clear_bit Interrupt-clear request flag * - * @return Interrupt-clear request value + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -uint32_t esp_memprot_get_intr_clr_bit(mem_type_prot_t mem_type); +esp_err_t esp_memprot_get_intr_clr_bit(mem_type_prot_t mem_type, uint32_t *clear_bit); /** * @brief Gets read permission value for specified block and memory region @@ -248,10 +258,11 @@ uint32_t esp_memprot_get_intr_clr_bit(mem_type_prot_t mem_type); * * @param mem_type Memory protection area type (see mem_type_prot_t enum) * @param block Memory block identifier (0-3) + * @param read_bit Read permission value for required block * - * @return Read permission value for required block + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -uint32_t esp_memprot_get_uni_block_read_bit(mem_type_prot_t mem_type, uint32_t block); +esp_err_t esp_memprot_get_uni_block_read_bit(mem_type_prot_t mem_type, uint32_t block, uint32_t *read_bit); /** * @brief Gets write permission value for specified block and memory region @@ -261,10 +272,11 @@ uint32_t esp_memprot_get_uni_block_read_bit(mem_type_prot_t mem_type, uint32_t b * * @param mem_type Memory protection area type (see mem_type_prot_t enum) * @param block Memory block identifier (0-3) + * @param write_bit Write permission value for required block * - * @return Write permission value for required block + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -uint32_t esp_memprot_get_uni_block_write_bit(mem_type_prot_t mem_type, uint32_t block); +esp_err_t esp_memprot_get_uni_block_write_bit(mem_type_prot_t mem_type, uint32_t block, uint32_t *write_bit); /** * @brief Gets execute permission value for specified block and memory region @@ -274,10 +286,11 @@ uint32_t esp_memprot_get_uni_block_write_bit(mem_type_prot_t mem_type, uint32_t * * @param mem_type Memory protection area type (see mem_type_prot_t enum) * @param block Memory block identifier (0-3) + * @param exec_bit Execute permission value for required block * - * @return Execute permission value for required block + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -uint32_t esp_memprot_get_uni_block_exec_bit(mem_type_prot_t mem_type, uint32_t block); +esp_err_t esp_memprot_get_uni_block_exec_bit(mem_type_prot_t mem_type, uint32_t block, uint32_t *exec_bit); /** * @brief Sets permissions for specified block in DRAM region @@ -289,8 +302,10 @@ uint32_t esp_memprot_get_uni_block_exec_bit(mem_type_prot_t mem_type, uint32_t b * @param block Memory block identifier (0-3) * @param write_perm Write permission flag * @param read_perm Read permission flag + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_set_uni_block_perm_dram(mem_type_prot_t mem_type, uint32_t block, bool write_perm, bool read_perm); +esp_err_t esp_memprot_set_uni_block_perm_dram(mem_type_prot_t mem_type, uint32_t block, bool write_perm, bool read_perm); /** * @brief Sets permissions for high and low memory segment in DRAM region @@ -305,8 +320,10 @@ void esp_memprot_set_uni_block_perm_dram(mem_type_prot_t mem_type, uint32_t bloc * @param lr Low segment Read permission flag * @param hw High segment Write permission flag * @param hr High segment Read permission flag + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_set_prot_dram(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr); +esp_err_t esp_memprot_set_prot_dram(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr); /** * @brief Sets permissions for specified block in IRAM region @@ -314,12 +331,17 @@ void esp_memprot_set_prot_dram(mem_type_prot_t mem_type, uint32_t *split_addr, b * Sets Read, Write and Execute permission for specified unified-management block (0-3) in given memory region. * Applicable only to IRAM memory types * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * @param mem_type Memory protection area type (MEMPROT_IRAM0_SRAM) * @param block Memory block identifier (0-3) * @param write_perm Write permission flag + * @param read_perm Read permission flag * @param exec_perm Execute permission flag + * + * @return ESP_OK on success + * ESP_ERR_NOT_SUPPORTED on invalid mem_type + * ESP_ERR_INVALID_ARG on incorrect block number */ -void esp_memprot_set_uni_block_perm_iram(mem_type_prot_t mem_type, uint32_t block, bool write_perm, bool read_perm, bool exec_perm); +esp_err_t esp_memprot_set_uni_block_perm_iram(mem_type_prot_t mem_type, uint32_t block, bool write_perm, bool read_perm, bool exec_perm); /** * @brief Sets permissions for high and low memory segment in IRAM region @@ -336,8 +358,10 @@ void esp_memprot_set_uni_block_perm_iram(mem_type_prot_t mem_type, uint32_t bloc * @param hw High segment Write permission flag * @param hr High segment Read permission flag * @param hx High segment Execute permission flag + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_set_prot_iram(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx); +esp_err_t esp_memprot_set_prot_iram(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx); /** * @brief Activates memory protection for all supported memory region types @@ -347,8 +371,10 @@ void esp_memprot_set_prot_iram(mem_type_prot_t mem_type, uint32_t *split_addr, b * @param invoke_panic_handler map mem.prot interrupt to ETS_MEMACCESS_ERR_INUM and thus invokes panic handler when fired ('true' not suitable for testing) * @param lock_feature sets LOCK bit, see esp_memprot_set_lock() ('true' not suitable for testing) * @param mem_type_mask holds a set of required memory protection types (bitmask built of mem_type_prot_t). NULL means default (MEMPROT_ALL in this version) + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask); +esp_err_t esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask); /** * @brief Get permission settings bits for IRAM0 split mgmt. Only IRAM0 memory types allowed @@ -360,8 +386,10 @@ void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t * @param hw High segment Write permission flag * @param hr High segment Read permission flag * @param hx High segment Execute permission flag + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_get_perm_split_bits_iram(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx); +esp_err_t esp_memprot_get_perm_split_bits_iram(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx); /** * @brief Get permission settings bits for DRAM0 split mgmt. Only DRAM0 memory types allowed @@ -371,8 +399,10 @@ void esp_memprot_get_perm_split_bits_iram(mem_type_prot_t mem_type, bool *lw, bo * @param lr Low segment Read permission flag * @param hw High segment Write permission flag * @param hr High segment Read permission flag + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_get_perm_split_bits_dram(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *hw, bool *hr); +esp_err_t esp_memprot_get_perm_split_bits_dram(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *hw, bool *hr); /** * @brief Sets permissions for high and low memory segment in PERIBUS1 region @@ -386,8 +416,10 @@ void esp_memprot_get_perm_split_bits_dram(mem_type_prot_t mem_type, bool *lw, bo * @param lr Low segment Read permission flag * @param hw High segment Write permission flag * @param hr High segment Read permission flag + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_set_prot_peri1(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr); +esp_err_t esp_memprot_set_prot_peri1(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr); /** * @brief Get permission settings bits for PERIBUS1 split mgmt. Only PERIBUS1 memory types allowed @@ -397,8 +429,10 @@ void esp_memprot_set_prot_peri1(mem_type_prot_t mem_type, uint32_t *split_addr, * @param lr Low segment Read permission flag * @param hw High segment Write permission flag * @param hr High segment Read permission flag + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_get_perm_split_bits_peri1(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *hw, bool *hr); +esp_err_t esp_memprot_get_perm_split_bits_peri1(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *hw, bool *hr); /** * @brief Get permission settings bits for PERIBUS2 split mgmt. Only PERIBUS2 memory types allowed @@ -410,25 +444,32 @@ void esp_memprot_get_perm_split_bits_peri1(mem_type_prot_t mem_type, bool *lw, b * @param hw High segment Write permission flag * @param hr High segment Read permission flag * @param hx High segment Execute permission flag + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_get_perm_split_bits_peri2(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx); +esp_err_t esp_memprot_get_perm_split_bits_peri2(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx); /** - * @brief Sets permissions for high and low memory segment in PERIBUS2 region + * @brief Configures the memory protection for high and low segment in PERIBUS2 region * * Sets Read Write permission for both low and high memory segments given by splitting address. * Applicable only to PERIBUS2 memory types * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * @param split_addr Address to split the memory region to lower and higher segment + * @param mem_type Memory protection area type (MEMPROT_PERI2_RTCSLOW_0, MEMPROT_PERI2_RTCSLOW_1) + * @param split_addr Address to split the memory region to lower and higher segment (32bit aligned) * @param lw Low segment Write permission flag * @param lr Low segment Read permission flag * @param lx Low segment Execute permission flag * @param hw High segment Write permission flag * @param hr High segment Read permission flag * @param hx High segment Execute permission flag + * + * @return ESP_OK on success + * ESP_ERR_NOT_SUPPORTED on invalid mem_type + * ESP_ERR_INVALID_STATE on splitting address out of PERIBUS2 range + * ESP_ERR_INVALID_SIZE on splitting address not 32-bit aligned */ -void esp_memprot_set_prot_peri2(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx); +esp_err_t esp_memprot_set_prot_peri2(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx); /** * @brief Get permissions for specified memory type. Irrelevant bits are ignored @@ -440,8 +481,12 @@ void esp_memprot_set_prot_peri2(mem_type_prot_t mem_type, uint32_t *split_addr, * @param hw High segment Write permission flag * @param hr High segment Read permission flag * @param hx High segment Execute permission flag + * + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG on NULL lw/lr/lx/hw/hr/hx args + * ESP_ERR_NOT_SUPPORTED on invalid mem_type */ -void esp_memprot_get_permissions(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx); +esp_err_t esp_memprot_get_permissions(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx); /** * @brief Get Read permission settings for low and high regions of given memory type @@ -449,8 +494,12 @@ void esp_memprot_get_permissions(mem_type_prot_t mem_type, bool *lw, bool *lr, b * @param mem_type Memory protection area type (see mem_type_prot_t enum) * @param lr Low segment Read permission flag * @param hr High segment Read permission flag + * + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG on NULL lr/hr args + * ESP_ERR_NOT_SUPPORTED on invalid mem_type */ -void esp_memprot_get_perm_read(mem_type_prot_t mem_type, bool *lr, bool *hr); +esp_err_t esp_memprot_get_perm_read(mem_type_prot_t mem_type, bool *lr, bool *hr); /** * @brief Get Write permission settings for low and high regions of given memory type @@ -458,23 +507,33 @@ void esp_memprot_get_perm_read(mem_type_prot_t mem_type, bool *lr, bool *hr); * @param mem_type Memory protection area type (see mem_type_prot_t enum) * @param lr Low segment Write permission flag * @param hr High segment Write permission flag + * + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG on NULL lw/hw args + * ESP_ERR_NOT_SUPPORTED on invalid mem_type */ -void esp_memprot_get_perm_write(mem_type_prot_t mem_type, bool *lw, bool *hw); +esp_err_t esp_memprot_get_perm_write(mem_type_prot_t mem_type, bool *lw, bool *hw); /** * @brief Get Execute permission settings for low and high regions of given memory type * Applicable only to IBUS-compatible memory types * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) - * @param lr Low segment Exec permission flag - * @param hr High segment Exec permission flag + * @param mem_type Memory protection area type (MEMPROT_IRAM0_SRAM, MEMPROT_IRAM0_RTCFAST, MEMPROT_PERI2_RTCSLOW_0, MEMPROT_PERI2_RTCSLOW_1) + * @param lx Low segment Exec permission flag + * @param hx High segment Exec permission flag + * + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG on NULL lx/hx args + * ESP_ERR_NOT_SUPPORTED on invalid mem_type */ -void esp_memprot_get_perm_exec(mem_type_prot_t mem_type, bool *lx, bool *hx); +esp_err_t esp_memprot_get_perm_exec(mem_type_prot_t mem_type, bool *lx, bool *hx); /** * @brief Returns the lowest address in required memory region * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * + * @return Required address or MEMPROT_INVALID_ADDRESS for invalid mem_type */ uint32_t esp_memprot_get_low_limit(mem_type_prot_t mem_type); @@ -482,6 +541,8 @@ uint32_t esp_memprot_get_low_limit(mem_type_prot_t mem_type); * @brief Returns the highest address in required memory region * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * + * @return Required address or MEMPROT_INVALID_ADDRESS for invalid mem_type */ uint32_t esp_memprot_get_high_limit(mem_type_prot_t mem_type); @@ -491,8 +552,11 @@ uint32_t esp_memprot_get_high_limit(mem_type_prot_t mem_type); * @param mem_type Memory protection area type (see mem_type_prot_t enum) * @param lr Low segment Read permission flag * @param hr High segment Read permission flag + * + * @return ESP_OK on success + * ESP_ERR_NOT_SUPPORTED on invalid mem_type */ -void esp_memprot_set_read_perm(mem_type_prot_t mem_type, bool lr, bool hr); +esp_err_t esp_memprot_set_read_perm(mem_type_prot_t mem_type, bool lr, bool hr); /** * @brief Sets WRITE permission bit for required memory region @@ -500,17 +564,23 @@ void esp_memprot_set_read_perm(mem_type_prot_t mem_type, bool lr, bool hr); * @param mem_type Memory protection area type (see mem_type_prot_t enum) * @param lr Low segment Write permission flag * @param hr High segment Write permission flag + * + * @return ESP_OK on success + * ESP_ERR_NOT_SUPPORTED on invalid mem_type */ -void esp_memprot_set_write_perm(mem_type_prot_t mem_type, bool lw, bool hw); +esp_err_t esp_memprot_set_write_perm(mem_type_prot_t mem_type, bool lw, bool hw); /** * @brief Sets EXECUTE permission bit for required memory region * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * @param mem_type Memory protection area type (MEMPROT_IRAM0_SRAM, MEMPROT_IRAM0_RTCFAST, MEMPROT_PERI2_RTCSLOW_0, MEMPROT_PERI2_RTCSLOW_1) * @param lr Low segment Exec permission flag * @param hr High segment Exec permission flag + * + * @return ESP_OK on success + * ESP_ERR_NOT_SUPPORTED on invalid mem_type */ -void esp_memprot_set_exec_perm(mem_type_prot_t mem_type, bool lx, bool hx); +esp_err_t esp_memprot_set_exec_perm(mem_type_prot_t mem_type, bool lx, bool hx); #ifdef __cplusplus diff --git a/components/esp_hw_support/include/soc/esp32s2/rtc.h b/components/esp_hw_support/include/soc/esp32s2/rtc.h index 296292e21d..3ab96b3787 100644 --- a/components/esp_hw_support/include/soc/esp32s2/rtc.h +++ b/components/esp_hw_support/include/soc/esp32s2/rtc.h @@ -1,16 +1,8 @@ -// Copyright 2015-2017 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once #include diff --git a/components/esp_hw_support/include/soc/esp32s2/spiram.h b/components/esp_hw_support/include/soc/esp32s2/spiram.h index 47871e627f..70d07e61a8 100644 --- a/components/esp_hw_support/include/soc/esp32s2/spiram.h +++ b/components/esp_hw_support/include/soc/esp32s2/spiram.h @@ -1,16 +1,8 @@ -// Copyright 2015-2017 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef __ESP_SPIRAM_H @@ -78,6 +70,15 @@ size_t esp_spiram_get_size(void); */ void esp_spiram_writeback_cache(void); +/** + * @brief get psram CS IO + * + * This interface should be called after PSRAM is enabled, otherwise it will + * return an invalid value -1/0xff. + * + * @return psram CS IO or -1/0xff if psram not enabled + */ +uint8_t esp_spiram_get_cs_io(void); /** diff --git a/components/esp_hw_support/include/soc/esp32s3/clk.h b/components/esp_hw_support/include/soc/esp32s3/clk.h index 31902ebad0..a9ed302852 100644 --- a/components/esp_hw_support/include/soc/esp32s3/clk.h +++ b/components/esp_hw_support/include/soc/esp32s3/clk.h @@ -1,16 +1,8 @@ -// Copyright 2015-2017 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once #include "esp_private/esp_clk.h" diff --git a/components/esp_hw_support/include/soc/esp32s3/dport_access.h b/components/esp_hw_support/include/soc/esp32s3/dport_access.h index f3f7007a9c..e5aedd2e1b 100644 --- a/components/esp_hw_support/include/soc/esp32s3/dport_access.h +++ b/components/esp_hw_support/include/soc/esp32s3/dport_access.h @@ -1,16 +1,8 @@ -// Copyright 2010-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: 2010-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _ESP_DPORT_ACCESS_H_ #define _ESP_DPORT_ACCESS_H_ diff --git a/components/esp_hw_support/include/soc/esp32s3/esp_crypto_lock.h b/components/esp_hw_support/include/soc/esp32s3/esp_crypto_lock.h index 781ac07780..074754a86b 100644 --- a/components/esp_hw_support/include/soc/esp32s3/esp_crypto_lock.h +++ b/components/esp_hw_support/include/soc/esp32s3/esp_crypto_lock.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -26,6 +18,34 @@ extern "C" { * Other unrelated components must not use it. */ +/** + * @brief Acquire lock for Digital Signature(DS) cryptography peripheral + * + * Internally also takes the HMAC lock, as the DS depends on the HMAC peripheral + */ +void esp_crypto_ds_lock_acquire(void); + +/** + * @brief Release lock for Digital Signature(DS) cryptography peripheral + * + * Internally also releases the HMAC lock, as the DS depends on the HMAC peripheral + */ +void esp_crypto_ds_lock_release(void); + +/** + * @brief Acquire lock for HMAC cryptography peripheral + * + * Internally also takes the SHA & AES lock, as the HMAC depends on the SHA peripheral + */ +void esp_crypto_hmac_lock_acquire(void); + +/** + * @brief Release lock for HMAC cryptography peripheral + * + * Internally also releases the SHA & AES lock, as the HMAC depends on the SHA peripheral + */ +void esp_crypto_hmac_lock_release(void); + /** * @brief Acquire lock for the SHA and AES cryptography peripheral. * diff --git a/components/esp_hw_support/include/soc/esp32s3/esp_ds.h b/components/esp_hw_support/include/soc/esp32s3/esp_ds.h new file mode 100644 index 0000000000..46a1d22a54 --- /dev/null +++ b/components/esp_hw_support/include/soc/esp32s3/esp_ds.h @@ -0,0 +1,192 @@ +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once +#include + +#include "esp_hmac.h" +#include "esp_err.h" +#include "soc/soc_caps.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ESP32S3_ERR_HW_CRYPTO_DS_HMAC_FAIL ESP_ERR_HW_CRYPTO_BASE + 0x1 /*!< HMAC peripheral problem */ +#define ESP32S3_ERR_HW_CRYPTO_DS_INVALID_KEY ESP_ERR_HW_CRYPTO_BASE + 0x2 /*!< given HMAC key isn't correct, + HMAC peripheral problem */ +#define ESP32S3_ERR_HW_CRYPTO_DS_INVALID_DIGEST ESP_ERR_HW_CRYPTO_BASE + 0x4 /*!< message digest check failed, + result is invalid */ +#define ESP32S3_ERR_HW_CRYPTO_DS_INVALID_PADDING ESP_ERR_HW_CRYPTO_BASE + 0x5 /*!< padding check failed, but result + is produced anyway and can be read*/ + +#define ESP_DS_IV_LEN 16 + +/* Length of parameter 'C' stored in flash */ +#define ESP_DS_C_LEN (12672 / 8) + +typedef struct esp_ds_context esp_ds_context_t; + +typedef enum { + ESP_DS_RSA_1024 = (1024 / 32) - 1, + ESP_DS_RSA_2048 = (2048 / 32) - 1, + ESP_DS_RSA_3072 = (3072 / 32) - 1, + ESP_DS_RSA_4096 = (4096 / 32) - 1 +} esp_digital_signature_length_t; + +/** + * Encrypted private key data. Recommended to store in flash in this format. + * + * @note This struct has to match to one from the ROM code! This documentation is mostly taken from there. + */ +typedef struct esp_digital_signature_data { + /** + * RSA LENGTH register parameters + * (number of words in RSA key & operands, minus one). + * + * Max value 127 (for RSA 4096). + * + * This value must match the length field encrypted and stored in 'c', + * or invalid results will be returned. (The DS peripheral will + * always use the value in 'c', not this value, so an attacker can't + * alter the DS peripheral results this way, it will just truncate or + * extend the message and the resulting signature in software.) + * + * @note In IDF, the enum type length is the same as of type unsigned, so they can be used interchangably. + * See the ROM code for the original declaration of struct \c ets_ds_data_t. + */ + esp_digital_signature_length_t rsa_length; + + /** + * IV value used to encrypt 'c' + */ + uint8_t iv[ESP_DS_IV_LEN]; + + /** + * Encrypted Digital Signature parameters. Result of AES-CBC encryption + * of plaintext values. Includes an encrypted message digest. + */ + uint8_t c[ESP_DS_C_LEN]; +} esp_ds_data_t; + +/** Plaintext parameters used by Digital Signature. + * + * Not used for signing with DS peripheral, but can be encrypted + * in-device by calling esp_ds_encrypt_params() + * + * @note This documentation is mostly taken from the ROM code. + */ +typedef struct { + uint32_t Y[SOC_RSA_MAX_BIT_LEN / 32]; //!< RSA exponent + uint32_t M[SOC_RSA_MAX_BIT_LEN / 32]; //!< RSA modulus + uint32_t Rb[SOC_RSA_MAX_BIT_LEN / 32]; //!< RSA r inverse operand + uint32_t M_prime; //!< RSA M prime operand + esp_digital_signature_length_t length; //!< RSA length +} esp_ds_p_data_t; + +/** + * Sign the message. + * + * This function is a wrapper around \c esp_ds_finish_sign() and \c esp_ds_start_sign(), so do not use them + * in parallel. + * It blocks until the signing is finished and then returns the signature. + * + * @note This function locks the HMAC, SHA, AES and RSA components during its entire execution time. + * + * @param message the message to be signed; its length is determined by data->rsa_length + * @param data the encrypted signing key data (AES encrypted RSA key + IV) + * @param key_id the HMAC key ID determining the HMAC key of the HMAC which will be used to decrypt the + * signing key data + * @param signature the destination of the signature, should be (data->rsa_length + 1)*4 bytes long + * + * @return + * - ESP_OK if successful, the signature was written to the parameter \c signature. + * - ESP_ERR_INVALID_ARG if one of the parameters is NULL or data->rsa_length is too long or 0 + * - ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL if there was an HMAC failure during retrieval of the decryption key + * - ESP_ERR_NO_MEM if there hasn't been enough memory to allocate the context object + * - ESP_ERR_HW_CRYPTO_DS_INVALID_KEY if there's a problem with passing the HMAC key to the DS component + * - ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST if the message digest didn't match; the signature is invalid. + * - ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING if the message padding is incorrect, the signature can be read though + * since the message digest matches. + */ +esp_err_t esp_ds_sign(const void *message, + const esp_ds_data_t *data, + hmac_key_id_t key_id, + void *signature); + +/** + * Start the signing process. + * + * This function yields a context object which needs to be passed to \c esp_ds_finish_sign() to finish the signing + * process. + * + * @note This function locks the HMAC, SHA, AES and RSA components, so the user has to ensure to call + * \c esp_ds_finish_sign() in a timely manner. + * + * @param message the message to be signed; its length is determined by data->rsa_length + * @param data the encrypted signing key data (AES encrypted RSA key + IV) + * @param key_id the HMAC key ID determining the HMAC key of the HMAC which will be used to decrypt the + * signing key data + * @param esp_ds_ctx the context object which is needed for finishing the signing process later + * + * @return + * - ESP_OK if successful, the ds operation was started now and has to be finished with \c esp_ds_finish_sign() + * - ESP_ERR_INVALID_ARG if one of the parameters is NULL or data->rsa_length is too long or 0 + * - ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL if there was an HMAC failure during retrieval of the decryption key + * - ESP_ERR_NO_MEM if there hasn't been enough memory to allocate the context object + * - ESP_ERR_HW_CRYPTO_DS_INVALID_KEY if there's a problem with passing the HMAC key to the DS component + */ +esp_err_t esp_ds_start_sign(const void *message, + const esp_ds_data_t *data, + hmac_key_id_t key_id, + esp_ds_context_t **esp_ds_ctx); + +/** + * Return true if the DS peripheral is busy, otherwise false. + * + * @note Only valid if \c esp_ds_start_sign() was called before. + */ +bool esp_ds_is_busy(void); + +/** + * Finish the signing process. + * + * @param signature the destination of the signature, should be (data->rsa_length + 1)*4 bytes long + * @param esp_ds_ctx the context object retreived by \c esp_ds_start_sign() + * + * @return + * - ESP_OK if successful, the ds operation has been finished and the result is written to signature. + * - ESP_ERR_INVALID_ARG if one of the parameters is NULL + * - ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST if the message digest didn't match; the signature is invalid. + * - ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING if the message padding is incorrect, the signature can be read though + * since the message digest matches. + */ +esp_err_t esp_ds_finish_sign(void *signature, esp_ds_context_t *esp_ds_ctx); + +/** + * Encrypt the private key parameters. + * + * @param data Output buffer to store encrypted data, suitable for later use generating signatures. + * The allocated memory must be in internal memory and word aligned since it's filled by DMA. Both is asserted + * at run time. + * @param iv Pointer to 16 byte IV buffer, will be copied into 'data'. Should be randomly generated bytes each time. + * @param p_data Pointer to input plaintext key data. The expectation is this data will be deleted after this process + * is done and 'data' is stored. + * @param key Pointer to 32 bytes of key data. Type determined by key_type parameter. The expectation is the + * corresponding HMAC key will be stored to efuse and then permanently erased. + * + * @return + * - ESP_OK if successful, the ds operation has been finished and the result is written to signature. + * - ESP_ERR_INVALID_ARG if one of the parameters is NULL or p_data->rsa_length is too long + */ +esp_err_t esp_ds_encrypt_params(esp_ds_data_t *data, + const void *iv, + const esp_ds_p_data_t *p_data, + const void *key); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/include/soc/esp32s3/esp_hmac.h b/components/esp_hw_support/include/soc/esp32s3/esp_hmac.h new file mode 100644 index 0000000000..101dce556b --- /dev/null +++ b/components/esp_hw_support/include/soc/esp32s3/esp_hmac.h @@ -0,0 +1,84 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * The possible efuse keys for the HMAC peripheral + */ +typedef enum { + HMAC_KEY0 = 0, + HMAC_KEY1, + HMAC_KEY2, + HMAC_KEY3, + HMAC_KEY4, + HMAC_KEY5, + HMAC_KEY_MAX +} hmac_key_id_t; + +/** + * @brief + * Calculate the HMAC of a given message. + * + * Calculate the HMAC \c hmac of a given message \c message with length \c message_len. + * SHA256 is used for the calculation (fixed on ESP32S3). + * + * @note Uses the HMAC peripheral in "upstream" mode. + * + * @param key_id Determines which of the 6 key blocks in the efuses should be used for the HMAC calcuation. + * The corresponding purpose field of the key block in the efuse must be set to the HMAC upstream purpose value. + * @param message the message for which to calculate the HMAC + * @param message_len message length + * @param [out] hmac the hmac result; the buffer behind the provided pointer must be 32 bytes long + * + * @return + * * ESP_OK, if the calculation was successful, + * * ESP_ERR_INVALID_ARG if message or hmac is a nullptr or if key_id out of range + * * ESP_FAIL, if the hmac calculation failed + */ +esp_err_t esp_hmac_calculate(hmac_key_id_t key_id, + const void *message, + size_t message_len, + uint8_t *hmac); + +/** + * @brief Use HMAC peripheral in Downstream mode to re-enable the JTAG, if it is not permanently disabled by HW. + * In downstream mode, HMAC calculations performed by peripheral are used internally and not provided back to user. + * + * @param key_id Determines which of the 6 key blocks in the efuses should be used for the HMAC calculation. + * The corresponding purpose field of the key block in the efuse must be set to HMAC downstream purpose. + * + * @param token Pre calculated HMAC value of the 32-byte 0x00 using SHA-256 and the known private HMAC key. The key is already + * programmed to a eFuse key block. The key block number is provided as the first parameter to this function. + * + * @return + * * ESP_OK, if the calculation was successful, + * if the calculated HMAC value matches with provided token, + * JTAG will be re-enable otherwise JTAG will remain disabled. + * Return value does not indicate the JTAG status. + * * ESP_FAIL, if the hmac calculation failed or JTAG is permanently disabled by EFUSE_HARD_DIS_JTAG eFuse parameter. + * * ESP_ERR_INVALID_ARG, invalid input arguments + */ +esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token); + +/** + * @brief Disable the JTAG which might be enabled using the HMAC downstream mode. This function just clears the result generated + * by calling esp_hmac_jtag_enable() API. + * + * @return + * * ESP_OK return ESP_OK after writing the HMAC_SET_INVALIDATE_JTAG_REG with value 1. + */ +esp_err_t esp_hmac_jtag_disable(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/include/soc/esp32s3/memprot.h b/components/esp_hw_support/include/soc/esp32s3/memprot.h index 7e47a8cfa3..948e067668 100644 --- a/components/esp_hw_support/include/soc/esp32s3/memprot.h +++ b/components/esp_hw_support/include/soc/esp32s3/memprot.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ /* INTERNAL API diff --git a/components/esp_hw_support/include/soc/esp32s3/rtc.h b/components/esp_hw_support/include/soc/esp32s3/rtc.h index 296292e21d..3ab96b3787 100644 --- a/components/esp_hw_support/include/soc/esp32s3/rtc.h +++ b/components/esp_hw_support/include/soc/esp32s3/rtc.h @@ -1,16 +1,8 @@ -// Copyright 2015-2017 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once #include diff --git a/components/esp_hw_support/include/soc/esp32s3/spiram.h b/components/esp_hw_support/include/soc/esp32s3/spiram.h index 863f0c48aa..067c3d27bf 100644 --- a/components/esp_hw_support/include/soc/esp32s3/spiram.h +++ b/components/esp_hw_support/include/soc/esp32s3/spiram.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef __ESP_SPIRAM_H @@ -87,6 +79,16 @@ void esp_spiram_writeback_cache(void); */ bool esp_spiram_is_initialized(void); +/** + * @brief get psram CS IO + * + * This interface should be called after PSRAM is enabled, otherwise it will + * return an invalid value -1/0xff. + * + * @return psram CS IO or -1/0xff if psram not enabled + */ +uint8_t esp_spiram_get_cs_io(void); + /** * @brief Reserve a pool of internal memory for specific DMA/internal allocations * diff --git a/components/esp_hw_support/include/soc/rtc_wdt.h b/components/esp_hw_support/include/soc/rtc_wdt.h index 7d13e6a4f7..97d1d8425b 100644 --- a/components/esp_hw_support/include/soc/rtc_wdt.h +++ b/components/esp_hw_support/include/soc/rtc_wdt.h @@ -1,16 +1,8 @@ -// Copyright 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: 2018-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ /* Recommendation of using API RTC_WDT. 1) Setting and enabling rtc_wdt: diff --git a/components/esp_hw_support/include/soc/spinlock.h b/components/esp_hw_support/include/soc/spinlock.h index 66baa93066..97cc9e514a 100644 --- a/components/esp_hw_support/include/soc/spinlock.h +++ b/components/esp_hw_support/include/soc/spinlock.h @@ -1,16 +1,8 @@ -// Copyright 2015-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: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once #include diff --git a/components/esp_hw_support/include/soc_log.h b/components/esp_hw_support/include/soc_log.h index ea2ecce8f8..64268433fb 100644 --- a/components/esp_hw_support/include/soc_log.h +++ b/components/esp_hw_support/include/soc_log.h @@ -1,16 +1,8 @@ -// Copyright 2016-2017 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: 2016-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once #include "esp_rom_sys.h" diff --git a/components/esp_hw_support/intr_alloc.c b/components/esp_hw_support/intr_alloc.c index a68d180531..208653cdf4 100644 --- a/components/esp_hw_support/intr_alloc.c +++ b/components/esp_hw_support/intr_alloc.c @@ -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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include diff --git a/components/esp_hw_support/mac_addr.c b/components/esp_hw_support/mac_addr.c index 7a722a3a24..be80a98d6e 100644 --- a/components/esp_hw_support/mac_addr.c +++ b/components/esp_hw_support/mac_addr.c @@ -1,16 +1,8 @@ -// Copyright 2015-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: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "sdkconfig.h" #include "esp_rom_efuse.h" @@ -55,9 +47,10 @@ esp_err_t esp_base_mac_addr_set(const uint8_t *mac) esp_err_t esp_base_mac_addr_get(uint8_t *mac) { - uint8_t null_mac[ESP_MAC_ADDRESS_LEN] = {0}; - - if (memcmp(base_mac_addr, null_mac, ESP_MAC_ADDRESS_LEN) == 0) { + if (mac == NULL) { + return ESP_ERR_INVALID_ARG; + } + if (base_mac_addr[0] == 0 && memcmp(base_mac_addr, &base_mac_addr[1], ESP_MAC_ADDRESS_LEN - 1) == 0) { ESP_LOGI(TAG, "Base MAC address is not set"); return ESP_ERR_INVALID_MAC; } @@ -70,7 +63,24 @@ esp_err_t esp_base_mac_addr_get(uint8_t *mac) esp_err_t esp_efuse_mac_get_custom(uint8_t *mac) { #if !CONFIG_IDF_TARGET_ESP32 - return ESP_ERR_NOT_SUPPORTED; // TODO IDF-1326 + size_t size_bits = esp_efuse_get_field_size(ESP_EFUSE_USER_DATA_MAC_CUSTOM); + assert((size_bits % 8) == 0); + esp_err_t err = esp_efuse_read_field_blob(ESP_EFUSE_USER_DATA_MAC_CUSTOM, mac, size_bits); + if (err != ESP_OK) { + return err; + } + size_t size = size_bits / 8; + if (mac[0] == 0 && memcmp(mac, &mac[1], size - 1) == 0) { + ESP_LOGE(TAG, "eFuse MAC_CUSTOM is empty"); + return ESP_ERR_INVALID_MAC; + } +#if (ESP_MAC_ADDRESS_LEN == 8) + err = esp_efuse_read_field_blob(ESP_EFUSE_MAC_EXT, &mac[6], ESP_MAC_ADDRESS_LEN - size); + if (err != ESP_OK) { + return err; + } +#endif + return ESP_OK; #else uint8_t version; esp_efuse_read_field_blob(ESP_EFUSE_MAC_CUSTOM_VER, &version, 8); @@ -94,14 +104,18 @@ esp_err_t esp_efuse_mac_get_custom(uint8_t *mac) esp_err_t esp_efuse_mac_get_default(uint8_t *mac) { - if ( esp_efuse_get_field_size(ESP_EFUSE_MAC_FACTORY) != ESP_MAC_ADDRESS_LEN * 8) { - ESP_LOGE(TAG, "mac address length is incorrect, please check the mac address length which your type of the chip is supported"); - abort(); - } - esp_err_t err = esp_efuse_read_field_blob(ESP_EFUSE_MAC_FACTORY, mac, ESP_MAC_ADDRESS_LEN * 8); + size_t size_bits = esp_efuse_get_field_size(ESP_EFUSE_MAC_FACTORY); + assert((size_bits % 8) == 0); + esp_err_t err = esp_efuse_read_field_blob(ESP_EFUSE_MAC_FACTORY, mac, size_bits); if (err != ESP_OK) { return err; } +#if (ESP_MAC_ADDRESS_LEN == 8) + err = esp_efuse_read_field_blob(ESP_EFUSE_MAC_EXT, &mac[6], ESP_MAC_ADDRESS_LEN - size_bits / 8); + if (err != ESP_OK) { + return err; + } +#endif #ifdef CONFIG_IDF_TARGET_ESP32 // Only ESP32 has MAC CRC in efuse uint8_t efuse_crc; diff --git a/components/esp_hw_support/port/async_memcpy_impl_gdma.c b/components/esp_hw_support/port/async_memcpy_impl_gdma.c index 7ecf7b6866..e480d0649f 100644 --- a/components/esp_hw_support/port/async_memcpy_impl_gdma.c +++ b/components/esp_hw_support/port/async_memcpy_impl_gdma.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "freertos/FreeRTOS.h" #include "soc/periph_defs.h" diff --git a/components/esp_hw_support/port/esp32/chip_info.c b/components/esp_hw_support/port/esp32/chip_info.c index 023da564c8..2c26e10488 100644 --- a/components/esp_hw_support/port/esp32/chip_info.c +++ b/components/esp_hw_support/port/esp32/chip_info.c @@ -1,16 +1,8 @@ -// Copyright 2013-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. +/* + * SPDX-FileCopyrightText: 2013-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "esp_chip_info.h" diff --git a/components/esp_hw_support/port/esp32/dport_access.c b/components/esp_hw_support/port/esp32/dport_access.c index 99aa2cb410..6c5c6ad440 100644 --- a/components/esp_hw_support/port/esp32/dport_access.c +++ b/components/esp_hw_support/port/esp32/dport_access.c @@ -4,202 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -/* - * DPORT access is used for do protection when dual core access DPORT internal register and APB register via DPORT simultaneously - * This function will be initialize after FreeRTOS startup. - * When cpu0 want to access DPORT register, it should notify cpu1 enter in high-priority interrupt for be mute. When cpu1 already in high-priority interrupt, - * cpu0 can access DPORT register. Currently, cpu1 will wait for cpu0 finish access and exit high-priority interrupt. - */ - #include #include - -#include "esp_attr.h" -#include "esp_err.h" -#include "esp_intr_alloc.h" - -#include "soc/cpu.h" +#include #include "soc/dport_reg.h" -#include "soc/spi_periph.h" -#include "hal/cpu_hal.h" - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/semphr.h" -#include "freertos/queue.h" - -#include "sdkconfig.h" - -#ifndef CONFIG_FREERTOS_UNICORE -static portMUX_TYPE g_dport_mux = portMUX_INITIALIZER_UNLOCKED; - -#define DPORT_CORE_STATE_IDLE 0 -#define DPORT_CORE_STATE_RUNNING 1 -static uint32_t volatile dport_core_state[portNUM_PROCESSORS]; //cpu is already run - -/* these global variables are accessed from interrupt vector, hence not declared as static */ -uint32_t volatile dport_access_start[portNUM_PROCESSORS]; //dport register could be accessed -uint32_t volatile dport_access_end[portNUM_PROCESSORS]; //dport register is accessed over - -static uint32_t volatile dport_access_ref[portNUM_PROCESSORS]; //dport access reference - -#ifdef DPORT_ACCESS_BENCHMARK -#define DPORT_ACCESS_BENCHMARK_STORE_NUM -static uint32_t ccount_start[portNUM_PROCESSORS]; -static uint32_t ccount_end[portNUM_PROCESSORS]; -static uint32_t ccount_margin[portNUM_PROCESSORS][DPORT_ACCESS_BENCHMARK_STORE_NUM]; -static uint32_t ccount_margin_cnt; -#endif - - -static BaseType_t oldInterruptLevel[2]; -#endif // CONFIG_FREERTOS_UNICORE - -/* stall other cpu that this cpu is pending to access dport register start */ -void IRAM_ATTR esp_dport_access_stall_other_cpu_start(void) -{ -#ifndef CONFIG_FREERTOS_UNICORE - if (dport_core_state[0] == DPORT_CORE_STATE_IDLE - || dport_core_state[1] == DPORT_CORE_STATE_IDLE) { - return; - } - - BaseType_t intLvl = portENTER_CRITICAL_NESTED(); - - int cpu_id = xPortGetCoreID(); - -#ifdef DPORT_ACCESS_BENCHMARK - ccount_start[cpu_id] = cpu_hal_get_cycle_count(); -#endif - - if (dport_access_ref[cpu_id] == 0) { - portENTER_CRITICAL_ISR(&g_dport_mux); - - oldInterruptLevel[cpu_id]=intLvl; - - dport_access_start[cpu_id] = 0; - dport_access_end[cpu_id] = 0; - - if (cpu_id == 0) { - _DPORT_REG_WRITE(DPORT_CPU_INTR_FROM_CPU_3_REG, DPORT_CPU_INTR_FROM_CPU_3); //interrupt on cpu1 - } else { - _DPORT_REG_WRITE(DPORT_CPU_INTR_FROM_CPU_2_REG, DPORT_CPU_INTR_FROM_CPU_2); //interrupt on cpu0 - } - - while (!dport_access_start[cpu_id]) {}; - - REG_READ(SPI_DATE_REG(3)); //just read a APB register sure that the APB-bus is idle - } - - dport_access_ref[cpu_id]++; - - if (dport_access_ref[cpu_id] > 1) { - /* Interrupts are already disabled by the parent, we're nested here. */ - portEXIT_CRITICAL_NESTED(intLvl); - } -#endif /* CONFIG_FREERTOS_UNICORE */ -} - -/* stall other cpu that this cpu is pending to access dport register end */ -void IRAM_ATTR esp_dport_access_stall_other_cpu_end(void) -{ -#ifndef CONFIG_FREERTOS_UNICORE - int cpu_id = xPortGetCoreID(); - - if (dport_core_state[0] == DPORT_CORE_STATE_IDLE - || dport_core_state[1] == DPORT_CORE_STATE_IDLE) { - return; - } - - if (dport_access_ref[cpu_id] == 0) { - assert(0); - } - - dport_access_ref[cpu_id]--; - - if (dport_access_ref[cpu_id] == 0) { - dport_access_end[cpu_id] = 1; - - portEXIT_CRITICAL_ISR(&g_dport_mux); - - portEXIT_CRITICAL_NESTED(oldInterruptLevel[cpu_id]); - } - -#ifdef DPORT_ACCESS_BENCHMARK - ccount_end[cpu_id] = cpu_hal_get_cycle_count(); - ccount_margin[cpu_id][ccount_margin_cnt] = ccount_end[cpu_id] - ccount_start[cpu_id]; - ccount_margin_cnt = (ccount_margin_cnt + 1)&(DPORT_ACCESS_BENCHMARK_STORE_NUM - 1); -#endif -#endif /* CONFIG_FREERTOS_UNICORE */ -} - - -#ifndef CONFIG_FREERTOS_UNICORE -static void dport_access_init_core(void *arg) -{ - int core_id = 0; - uint32_t intr_source = ETS_FROM_CPU_INTR2_SOURCE; - - - core_id = xPortGetCoreID(); - if (core_id == 1) { - intr_source = ETS_FROM_CPU_INTR3_SOURCE; - } - - ESP_INTR_DISABLE(ETS_DPORT_INUM); - intr_matrix_set(core_id, intr_source, ETS_DPORT_INUM); - ESP_INTR_ENABLE(ETS_DPORT_INUM); - - dport_access_ref[core_id] = 0; - dport_access_start[core_id] = 0; - dport_access_end[core_id] = 0; - dport_core_state[core_id] = DPORT_CORE_STATE_RUNNING; - - /* If this fails then the minimum stack size for this config is too close to running out */ - assert(uxTaskGetStackHighWaterMark(NULL) > 128); - - vTaskDelete(NULL); -} -#endif - -/* Defer initialisation until after scheduler is running */ -void esp_dport_access_int_init(void) -{ -#ifndef CONFIG_FREERTOS_UNICORE - portBASE_TYPE res = xTaskCreatePinnedToCore(&dport_access_init_core, "dport", configMINIMAL_STACK_SIZE, NULL, 5, NULL, xPortGetCoreID()); - assert(res == pdTRUE); - (void)res; -#endif -} - -void IRAM_ATTR esp_dport_access_int_pause(void) -{ -#ifndef CONFIG_FREERTOS_UNICORE - portENTER_CRITICAL_ISR(&g_dport_mux); - dport_core_state[0] = DPORT_CORE_STATE_IDLE; - dport_core_state[1] = DPORT_CORE_STATE_IDLE; - portEXIT_CRITICAL_ISR(&g_dport_mux); -#endif -} - -//Used in panic code: the enter_critical stuff may be messed up so we just stop everything without checking the mux. -void IRAM_ATTR esp_dport_access_int_abort(void) -{ -#ifndef CONFIG_FREERTOS_UNICORE - dport_core_state[0] = DPORT_CORE_STATE_IDLE; - dport_core_state[1] = DPORT_CORE_STATE_IDLE; -#endif -} - -void IRAM_ATTR esp_dport_access_int_resume(void) -{ -#ifndef CONFIG_FREERTOS_UNICORE - portENTER_CRITICAL_ISR(&g_dport_mux); - dport_core_state[0] = DPORT_CORE_STATE_RUNNING; - dport_core_state[1] = DPORT_CORE_STATE_RUNNING; - portEXIT_CRITICAL_ISR(&g_dport_mux); -#endif -} +#include "xtensa/core-macros.h" /** * @brief Read a sequence of DPORT registers to the buffer, SMP-safe version. diff --git a/components/esp_hw_support/port/esp32/esp_himem.c b/components/esp_hw_support/port/esp32/esp_himem.c index 12862b8037..061b2661aa 100644 --- a/components/esp_hw_support/port/esp32/esp_himem.c +++ b/components/esp_hw_support/port/esp32/esp_himem.c @@ -12,6 +12,7 @@ #include "esp32/himem.h" #include "soc/soc.h" #include "esp_log.h" +#include "esp_check.h" /* So, why does the API look this way and is so inflexible to not allow any maps beyond the full 32K chunks? Most of @@ -56,8 +57,6 @@ peripheral. This needs support for SPI1 to be in the SPI driver, however. #define TAG "esp_himem" -#define HIMEM_CHECK(cond, str, err) if (cond) do {ESP_LOGE(TAG, "%s: %s", __FUNCTION__, str); return err; } while(0) - // Metadata for a block of physical RAM typedef struct { unsigned int is_alloced: 1; @@ -134,10 +133,10 @@ void __attribute__((constructor)) esp_himem_init(void) if (SPIRAM_BANKSWITCH_RESERVE == 0) return; int maxram=esp_spiram_get_size(); //catch double init - HIMEM_CHECK(s_ram_descriptor != NULL, "already initialized", ); //Looks weird; last arg is empty so it expands to 'return ;' - HIMEM_CHECK(s_range_descriptor != NULL, "already initialized", ); + ESP_RETURN_ON_FALSE(s_ram_descriptor == NULL, , TAG, "already initialized"); //Looks weird; last arg is empty so it expands to 'return ;' + ESP_RETURN_ON_FALSE(s_range_descriptor == NULL, , TAG, "already initialized"); //need to have some reserved banks - HIMEM_CHECK(SPIRAM_BANKSWITCH_RESERVE == 0, "No banks reserved for himem", ); + ESP_RETURN_ON_FALSE(SPIRAM_BANKSWITCH_RESERVE != 0, , TAG, "No banks reserved for himem"); //Start and end of physical reserved memory. Note it starts slightly under //the 4MiB mark as the reserved banks can't have an unity mapping to be used by malloc //anymore; we treat them as himem instead. @@ -219,7 +218,7 @@ esp_err_t esp_himem_free(esp_himem_handle_t handle) //Check if any of the blocks is still mapped; fail if this is the case. for (int i = 0; i < handle->block_ct; i++) { assert(ramblock_idx_valid(handle->block[i])); - HIMEM_CHECK(s_ram_descriptor[handle->block[i]].is_mapped, "block in range still mapped", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(!s_ram_descriptor[handle->block[i]].is_mapped, ESP_ERR_INVALID_ARG, TAG, "block in range still mapped"); } //Mark blocks as free portENTER_CRITICAL(&spinlock); @@ -237,8 +236,8 @@ esp_err_t esp_himem_free(esp_himem_handle_t handle) esp_err_t esp_himem_alloc_map_range(size_t size, esp_himem_rangehandle_t *handle_out) { - HIMEM_CHECK(s_ram_descriptor == NULL, "Himem not available!", ESP_ERR_INVALID_STATE); - HIMEM_CHECK(size % CACHE_BLOCKSIZE != 0, "requested size not aligned to blocksize", ESP_ERR_INVALID_SIZE); + ESP_RETURN_ON_FALSE(s_ram_descriptor != NULL, ESP_ERR_INVALID_STATE, TAG, "Himem not available!"); + ESP_RETURN_ON_FALSE(size % CACHE_BLOCKSIZE == 0, ESP_ERR_INVALID_SIZE, TAG, "requested size not aligned to blocksize"); int blocks = size / CACHE_BLOCKSIZE; esp_himem_rangedata_t *r = calloc(sizeof(esp_himem_rangedata_t), 1); if (!r) { @@ -280,7 +279,7 @@ esp_err_t esp_himem_free_map_range(esp_himem_rangehandle_t handle) for (int i = 0; i < handle->block_ct; i++) { assert(rangeblock_idx_valid(handle->block_start + i)); assert(s_range_descriptor[i + handle->block_start].is_alloced == 1); //should be, if handle is valid - HIMEM_CHECK(s_range_descriptor[i + handle->block_start].is_mapped, "memory still mapped to range", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(!s_range_descriptor[i + handle->block_start].is_mapped, ESP_ERR_INVALID_ARG, TAG, "memory still mapped to range"); } //We should be good to free this. Mark blocks as free. portENTER_CRITICAL(&spinlock); @@ -298,19 +297,19 @@ esp_err_t esp_himem_map(esp_himem_handle_t handle, esp_himem_rangehandle_t range int ram_block = ram_offset / CACHE_BLOCKSIZE; int range_block = range_offset / CACHE_BLOCKSIZE; int blockcount = len / CACHE_BLOCKSIZE; - HIMEM_CHECK(s_ram_descriptor == NULL, "Himem not available!", ESP_ERR_INVALID_STATE); + ESP_RETURN_ON_FALSE(s_ram_descriptor != NULL, ESP_ERR_INVALID_STATE, TAG, "Himem not available!"); //Offsets and length must be block-aligned - HIMEM_CHECK(ram_offset % CACHE_BLOCKSIZE != 0, "ram offset not aligned to blocksize", ESP_ERR_INVALID_ARG); - HIMEM_CHECK(range_offset % CACHE_BLOCKSIZE != 0, "range not aligned to blocksize", ESP_ERR_INVALID_ARG); - HIMEM_CHECK(len % CACHE_BLOCKSIZE != 0, "length not aligned to blocksize", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(ram_offset % CACHE_BLOCKSIZE == 0, ESP_ERR_INVALID_ARG, TAG, "ram offset not aligned to blocksize"); + ESP_RETURN_ON_FALSE(range_offset % CACHE_BLOCKSIZE == 0, ESP_ERR_INVALID_ARG, TAG, "range not aligned to blocksize"); + ESP_RETURN_ON_FALSE(len % CACHE_BLOCKSIZE == 0, ESP_ERR_INVALID_ARG, TAG, "length not aligned to blocksize"); //ram and range should be within allocated range - HIMEM_CHECK(ram_block + blockcount > handle->block_ct, "args not in range of phys ram handle", ESP_ERR_INVALID_SIZE); - HIMEM_CHECK(range_block + blockcount > range->block_ct, "args not in range of range handle", ESP_ERR_INVALID_SIZE); + ESP_RETURN_ON_FALSE(ram_block + blockcount <= handle->block_ct, ESP_ERR_INVALID_SIZE, TAG, "args not in range of phys ram handle"); + ESP_RETURN_ON_FALSE(range_block + blockcount <= range->block_ct, ESP_ERR_INVALID_SIZE, TAG, "args not in range of range handle"); //Check if ram blocks aren't already mapped, and if memory range is unmapped for (int i = 0; i < blockcount; i++) { - HIMEM_CHECK(s_ram_descriptor[handle->block[i + ram_block]].is_mapped, "ram already mapped", ESP_ERR_INVALID_STATE); - HIMEM_CHECK(s_range_descriptor[range->block_start + i + range_block].is_mapped, "range already mapped", ESP_ERR_INVALID_STATE); + ESP_RETURN_ON_FALSE(!s_ram_descriptor[handle->block[i + ram_block]].is_mapped, ESP_ERR_INVALID_STATE, TAG, "ram already mapped"); + ESP_RETURN_ON_FALSE(!s_range_descriptor[range->block_start + i + range_block].is_mapped, ESP_ERR_INVALID_STATE, TAG, "range already mapped"); } //Map and mark as mapped @@ -339,9 +338,9 @@ esp_err_t esp_himem_unmap(esp_himem_rangehandle_t range, void *ptr, size_t len) int range_offset = (uint32_t)ptr - VIRT_HIMEM_RANGE_START; int range_block = (range_offset / CACHE_BLOCKSIZE) - range->block_start; int blockcount = len / CACHE_BLOCKSIZE; - HIMEM_CHECK(range_offset % CACHE_BLOCKSIZE != 0, "range offset not block-aligned", ESP_ERR_INVALID_ARG); - HIMEM_CHECK(len % CACHE_BLOCKSIZE != 0, "map length not block-aligned", ESP_ERR_INVALID_ARG); - HIMEM_CHECK(range_block + blockcount > range->block_ct, "range out of bounds for handle", ESP_ERR_INVALID_ARG); + ESP_RETURN_ON_FALSE(range_offset % CACHE_BLOCKSIZE == 0, ESP_ERR_INVALID_ARG, TAG, "range offset not block-aligned"); + ESP_RETURN_ON_FALSE(len % CACHE_BLOCKSIZE == 0, ESP_ERR_INVALID_ARG, TAG, "map length not block-aligned"); + ESP_RETURN_ON_FALSE(range_block + blockcount <= range->block_ct, ESP_ERR_INVALID_ARG, TAG, "range out of bounds for handle"); portENTER_CRITICAL(&spinlock); for (int i = 0; i < blockcount; i++) { diff --git a/components/esp_hw_support/port/esp32/private_include/regi2c_apll.h b/components/esp_hw_support/port/esp32/private_include/regi2c_apll.h index db49027546..f2651045ae 100644 --- a/components/esp_hw_support/port/esp32/private_include/regi2c_apll.h +++ b/components/esp_hw_support/port/esp32/private_include/regi2c_apll.h @@ -1,16 +1,8 @@ -// Copyright 2015-2017 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/port/esp32/private_include/regi2c_bbpll.h b/components/esp_hw_support/port/esp32/private_include/regi2c_bbpll.h index 8a9fcef372..b2d07574ab 100644 --- a/components/esp_hw_support/port/esp32/private_include/regi2c_bbpll.h +++ b/components/esp_hw_support/port/esp32/private_include/regi2c_bbpll.h @@ -1,16 +1,8 @@ -// Copyright 2015-2017 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/port/esp32/regi2c_ctrl.h b/components/esp_hw_support/port/esp32/regi2c_ctrl.h index 69f2919207..ea2870e99b 100644 --- a/components/esp_hw_support/port/esp32/regi2c_ctrl.h +++ b/components/esp_hw_support/port/esp32/regi2c_ctrl.h @@ -1,16 +1,8 @@ -// Copyright 2015-2017 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/port/esp32/rtc_clk.c b/components/esp_hw_support/port/esp32/rtc_clk.c index 79365bb181..737daa88f4 100644 --- a/components/esp_hw_support/port/esp32/rtc_clk.c +++ b/components/esp_hw_support/port/esp32/rtc_clk.c @@ -1,16 +1,8 @@ -// Copyright 2015-2017 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -25,7 +17,7 @@ #include "soc/sens_periph.h" #include "soc/dport_reg.h" #include "soc/efuse_periph.h" -#include "soc/apb_ctrl_reg.h" +#include "soc/syscon_reg.h" #include "soc/gpio_struct.h" #include "hal/cpu_hal.h" #include "hal/gpio_ll.h" @@ -463,9 +455,9 @@ void rtc_clk_cpu_freq_to_xtal(int freq, int div) { ets_update_cpu_frequency(freq); /* set divider from XTAL to APB clock */ - REG_SET_FIELD(APB_CTRL_SYSCLK_CONF_REG, APB_CTRL_PRE_DIV_CNT, div - 1); + REG_SET_FIELD(SYSCON_SYSCLK_CONF_REG, SYSCON_PRE_DIV_CNT, div - 1); /* adjust ref_tick */ - REG_WRITE(APB_CTRL_XTAL_TICK_CONF_REG, freq * MHZ / REF_CLK_FREQ - 1); + REG_WRITE(SYSCON_XTAL_TICK_CONF_REG, freq * MHZ / REF_CLK_FREQ - 1); /* switch clock source */ REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL, RTC_CNTL_SOC_CLK_SEL_XTL); rtc_clk_apb_freq_update(freq * MHZ); @@ -481,7 +473,7 @@ static void rtc_clk_cpu_freq_to_8m(void) { ets_update_cpu_frequency(8); REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_XTAL); - REG_SET_FIELD(APB_CTRL_SYSCLK_CONF_REG, APB_CTRL_PRE_DIV_CNT, 0); + REG_SET_FIELD(SYSCON_SYSCLK_CONF_REG, SYSCON_PRE_DIV_CNT, 0); REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL, RTC_CNTL_SOC_CLK_SEL_8M); rtc_clk_apb_freq_update(RTC_FAST_CLK_FREQ_8M); } @@ -684,7 +676,7 @@ void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t* out_config) switch (soc_clk_sel) { case RTC_CNTL_SOC_CLK_SEL_XTL: { source = RTC_CPU_FREQ_SRC_XTAL; - div = REG_GET_FIELD(APB_CTRL_SYSCLK_CONF_REG, APB_CTRL_PRE_DIV_CNT) + 1; + div = REG_GET_FIELD(SYSCON_SYSCLK_CONF_REG, SYSCON_PRE_DIV_CNT) + 1; source_freq_mhz = (uint32_t) rtc_clk_xtal_freq_get(); freq_mhz = source_freq_mhz / div; } diff --git a/components/esp_hw_support/port/esp32/rtc_clk_common.h b/components/esp_hw_support/port/esp32/rtc_clk_common.h index dec179e3be..6721cf6f41 100644 --- a/components/esp_hw_support/port/esp32/rtc_clk_common.h +++ b/components/esp_hw_support/port/esp32/rtc_clk_common.h @@ -1,16 +1,8 @@ -// Copyright 2015-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: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/port/esp32/rtc_clk_init.c b/components/esp_hw_support/port/esp32/rtc_clk_init.c index c058c7c63e..a1790c230e 100644 --- a/components/esp_hw_support/port/esp32/rtc_clk_init.c +++ b/components/esp_hw_support/port/esp32/rtc_clk_init.c @@ -1,16 +1,8 @@ -// Copyright 2015-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: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -22,7 +14,7 @@ #include "soc/rtc_periph.h" #include "soc/sens_periph.h" #include "soc/efuse_periph.h" -#include "soc/apb_ctrl_reg.h" +#include "soc/syscon_reg.h" #include "hal/cpu_hal.h" #include "regi2c_ctrl.h" #include "soc_log.h" @@ -120,8 +112,8 @@ void rtc_clk_init(rtc_clk_config_t cfg) rtc_clk_cpu_freq_set_config(&new_config); /* Configure REF_TICK */ - REG_WRITE(APB_CTRL_XTAL_TICK_CONF_REG, xtal_freq - 1); - REG_WRITE(APB_CTRL_PLL_TICK_CONF_REG, APB_CLK_FREQ / MHZ - 1); /* Under PLL, APB frequency is always 80MHz */ + REG_WRITE(SYSCON_XTAL_TICK_CONF_REG, xtal_freq - 1); + REG_WRITE(SYSCON_PLL_TICK_CONF_REG, APB_CLK_FREQ / MHZ - 1); /* Under PLL, APB frequency is always 80MHz */ /* Re-calculate the ccount to make time calculation correct. */ cpu_hal_set_cycle_count( (uint64_t)cpu_hal_get_cycle_count() * cfg.cpu_freq_mhz / freq_before ); diff --git a/components/esp_hw_support/port/esp32/rtc_init.c b/components/esp_hw_support/port/esp32/rtc_init.c index f86811a99f..0ebd6e2f05 100644 --- a/components/esp_hw_support/port/esp32/rtc_init.c +++ b/components/esp_hw_support/port/esp32/rtc_init.c @@ -1,16 +1,8 @@ -// Copyright 2015-2017 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include diff --git a/components/esp_hw_support/port/esp32/rtc_pm.c b/components/esp_hw_support/port/esp32/rtc_pm.c index 47baedf952..43ca6cdd92 100644 --- a/components/esp_hw_support/port/esp32/rtc_pm.c +++ b/components/esp_hw_support/port/esp32/rtc_pm.c @@ -1,16 +1,8 @@ -// Copyright 2015-2017 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include diff --git a/components/esp_hw_support/port/esp32/rtc_sleep.c b/components/esp_hw_support/port/esp32/rtc_sleep.c index fa8444fdcb..dff1b49acd 100644 --- a/components/esp_hw_support/port/esp32/rtc_sleep.c +++ b/components/esp_hw_support/port/esp32/rtc_sleep.c @@ -1,16 +1,8 @@ -// Copyright 2015-2017 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "soc/soc.h" @@ -194,9 +186,11 @@ void rtc_sleep_init(rtc_sleep_config_t cfg) REG_CLR_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU); } //Keep the RTC8M_CLK on in light_sleep mode if the ledc low-speed channel is clocked by RTC8M_CLK. - if (!cfg.deep_slp && GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M)) { + if (!cfg.int_8m_pd_en && GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M)) { REG_CLR_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PD); REG_SET_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU); + } else { + REG_CLR_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU); } /* enable VDDSDIO control by state machine */ diff --git a/components/esp_hw_support/port/esp32/rtc_time.c b/components/esp_hw_support/port/esp32/rtc_time.c index 99539e0d55..95b59789ee 100644 --- a/components/esp_hw_support/port/esp32/rtc_time.c +++ b/components/esp_hw_support/port/esp32/rtc_time.c @@ -1,16 +1,8 @@ -// Copyright 2015-2017 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "esp_rom_sys.h" diff --git a/components/esp_hw_support/port/esp32/rtc_wdt.c b/components/esp_hw_support/port/esp32/rtc_wdt.c index facf8d4449..42ab860e69 100644 --- a/components/esp_hw_support/port/esp32/rtc_wdt.c +++ b/components/esp_hw_support/port/esp32/rtc_wdt.c @@ -1,16 +1,8 @@ -// Copyright 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: 2018-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "soc/rtc_wdt.h" #include "soc/rtc.h" diff --git a/components/esp_hw_support/port/esp32/spiram.c b/components/esp_hw_support/port/esp32/spiram.c index d0806f16ef..651aff4e12 100644 --- a/components/esp_hw_support/port/esp32/spiram.c +++ b/components/esp_hw_support/port/esp32/spiram.c @@ -316,4 +316,8 @@ bool esp_spiram_is_initialized(void) return spiram_inited; } +uint8_t esp_spiram_get_cs_io(void) +{ + return psram_get_cs_io(); +} #endif diff --git a/components/esp_hw_support/port/esp32/spiram_psram.c b/components/esp_hw_support/port/esp32/spiram_psram.c index f0d579a13d..e3de144b53 100644 --- a/components/esp_hw_support/port/esp32/spiram_psram.c +++ b/components/esp_hw_support/port/esp32/spiram_psram.c @@ -195,6 +195,13 @@ typedef struct { static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psram_vaddr_mode_t vaddrmode); +static uint8_t s_psram_cs_io = (uint8_t)-1; + +uint8_t psram_get_cs_io(void) +{ + return s_psram_cs_io; +} + static void psram_clear_spi_fifo(psram_spi_num_t spi_num) { int i; @@ -839,6 +846,7 @@ esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vad ESP_EARLY_LOGE(TAG, "Not a valid or known package id: %d", pkg_ver); abort(); } + s_psram_cs_io = psram_io.psram_cs_io; const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info(); if (spiconfig == ESP_ROM_EFUSE_FLASH_DEFAULT_SPI) { diff --git a/components/esp_hw_support/port/esp32/spiram_psram.h b/components/esp_hw_support/port/esp32/spiram_psram.h index 263fb924dc..abcc98f0ff 100644 --- a/components/esp_hw_support/port/esp32/spiram_psram.h +++ b/components/esp_hw_support/port/esp32/spiram_psram.h @@ -63,6 +63,13 @@ psram_size_t psram_get_size(void); */ esp_err_t psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vaddrmode); +/** + * @brief get psram CS IO + * + * @return psram CS IO + */ +uint8_t psram_get_cs_io(void); + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/port/esp32c3/chip_info.c b/components/esp_hw_support/port/esp32c3/chip_info.c index ffd37a23c0..bb178b47fa 100644 --- a/components/esp_hw_support/port/esp32c3/chip_info.c +++ b/components/esp_hw_support/port/esp32c3/chip_info.c @@ -1,16 +1,8 @@ -// Copyright 2013-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: 2013-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "esp_chip_info.h" diff --git a/components/esp_hw_support/port/esp32c3/cpu_util_esp32c3.c b/components/esp_hw_support/port/esp32c3/cpu_util_esp32c3.c index b070320bb2..3d797ea8c0 100644 --- a/components/esp_hw_support/port/esp32c3/cpu_util_esp32c3.c +++ b/components/esp_hw_support/port/esp32c3/cpu_util_esp32c3.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "soc/cpu.h" diff --git a/components/esp_hw_support/port/esp32c3/dport_access.c b/components/esp_hw_support/port/esp32c3/dport_access.c index 08b55a96fb..8364f5687e 100644 --- a/components/esp_hw_support/port/esp32c3/dport_access.c +++ b/components/esp_hw_support/port/esp32c3/dport_access.c @@ -1,16 +1,8 @@ -// Copyright 2010-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: 2010-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include diff --git a/components/esp_hw_support/port/esp32c3/esp_crypto_lock.c b/components/esp_hw_support/port/esp32c3/esp_crypto_lock.c index 46a90ca08b..51b02be94d 100644 --- a/components/esp_hw_support/port/esp32c3/esp_crypto_lock.c +++ b/components/esp_hw_support/port/esp32c3/esp_crypto_lock.c @@ -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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include diff --git a/components/esp_hw_support/port/esp32c3/esp_ds.c b/components/esp_hw_support/port/esp32c3/esp_ds.c index 3dbaa79dc5..1b63b21b96 100644 --- a/components/esp_hw_support/port/esp32c3/esp_ds.c +++ b/components/esp_hw_support/port/esp32c3/esp_ds.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include diff --git a/components/esp_hw_support/port/esp32c3/esp_hmac.c b/components/esp_hw_support/port/esp32c3/esp_hmac.c index 9f71353e30..0c85d7429c 100644 --- a/components/esp_hw_support/port/esp32c3/esp_hmac.c +++ b/components/esp_hw_support/port/esp32c3/esp_hmac.c @@ -1,29 +1,27 @@ -// 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "driver/periph_ctrl.h" #include "esp32c3/rom/hmac.h" #include "esp32c3/rom/ets_sys.h" +#include "esp_efuse.h" +#include "esp_efuse_table.h" #include "esp_hmac.h" +#include "esp_log.h" #include "esp_crypto_lock.h" +#include "soc/hwcrypto_reg.h" #include "hal/hmac_hal.h" #define SHA256_BLOCK_SZ 64 #define SHA256_PAD_SZ 8 +static const char *TAG = "esp_hmac"; + /** * @brief Apply the HMAC padding without the embedded length. * @@ -130,3 +128,53 @@ esp_err_t esp_hmac_calculate(hmac_key_id_t key_id, return ESP_OK; } + +static ets_efuse_block_t convert_key_type(hmac_key_id_t key_id) { + return ETS_EFUSE_BLOCK_KEY0 + (ets_efuse_block_t) key_id; +} + +esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token) +{ + int ets_status; + esp_err_t err = ESP_OK; + + if ((!token) || (key_id >= HMAC_KEY_MAX)) + return ESP_ERR_INVALID_ARG; + + /* Check if JTAG is permanently disabled by HW Disable eFuse */ + if (esp_efuse_read_field_bit(ESP_EFUSE_DIS_PAD_JTAG)) { + ESP_LOGE(TAG, "JTAG disabled permanently."); + return ESP_FAIL; + } + + esp_crypto_hmac_lock_acquire(); + + ets_status = ets_jtag_enable_temporarily(token, convert_key_type(key_id)); + + if (ets_status != ETS_OK) { + // ets_jtag_enable_temporarily returns either ETS_OK or ETS_FAIL + err = ESP_FAIL; + ESP_LOGE(TAG, "JTAG re-enabling failed (%d)", err); + } + + ESP_LOGD(TAG, "HMAC computation in downstream mode is completed."); + + ets_hmac_disable(); + + esp_crypto_hmac_lock_release(); + + return err; +} + +esp_err_t esp_hmac_jtag_disable() +{ + esp_crypto_hmac_lock_acquire(); + + REG_SET_BIT(HMAC_SET_INVALIDATE_JTAG_REG, HMAC_INVALIDATE_JTAG); + + esp_crypto_hmac_lock_release(); + + ESP_LOGD(TAG, "Invalidate JTAG result register. JTAG disabled."); + + return ESP_OK; +} diff --git a/components/esp_hw_support/port/esp32c3/i2c_brownout.h b/components/esp_hw_support/port/esp32c3/i2c_brownout.h index 5fac2c91b3..1d2ab34411 100644 --- a/components/esp_hw_support/port/esp32c3/i2c_brownout.h +++ b/components/esp_hw_support/port/esp32c3/i2c_brownout.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/port/esp32c3/i2c_rtc_clk.h b/components/esp_hw_support/port/esp32c3/i2c_rtc_clk.h index 0bbe0ee1a1..dbb7d73dc4 100644 --- a/components/esp_hw_support/port/esp32c3/i2c_rtc_clk.h +++ b/components/esp_hw_support/port/esp32c3/i2c_rtc_clk.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/port/esp32c3/memprot.c b/components/esp_hw_support/port/esp32c3/memprot.c index 35251a8b90..2cd942a71c 100644 --- a/components/esp_hw_support/port/esp32c3/memprot.c +++ b/components/esp_hw_support/port/esp32c3/memprot.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ /* INTERNAL API * implementation of PMS memory protection features diff --git a/components/esp_hw_support/port/esp32c3/private_include/regi2c_bbpll.h b/components/esp_hw_support/port/esp32c3/private_include/regi2c_bbpll.h index 842f702934..8235741d58 100644 --- a/components/esp_hw_support/port/esp32c3/private_include/regi2c_bbpll.h +++ b/components/esp_hw_support/port/esp32c3/private_include/regi2c_bbpll.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/port/esp32c3/private_include/regi2c_bias.h b/components/esp_hw_support/port/esp32c3/private_include/regi2c_bias.h index f459a344ba..e359ef0a69 100644 --- a/components/esp_hw_support/port/esp32c3/private_include/regi2c_bias.h +++ b/components/esp_hw_support/port/esp32c3/private_include/regi2c_bias.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/port/esp32c3/private_include/regi2c_brownout.h b/components/esp_hw_support/port/esp32c3/private_include/regi2c_brownout.h index d81751347c..1aa54a2017 100644 --- a/components/esp_hw_support/port/esp32c3/private_include/regi2c_brownout.h +++ b/components/esp_hw_support/port/esp32c3/private_include/regi2c_brownout.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/port/esp32c3/private_include/regi2c_dig_reg.h b/components/esp_hw_support/port/esp32c3/private_include/regi2c_dig_reg.h index 2510f43ae5..9d2032b60e 100644 --- a/components/esp_hw_support/port/esp32c3/private_include/regi2c_dig_reg.h +++ b/components/esp_hw_support/port/esp32c3/private_include/regi2c_dig_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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/port/esp32c3/private_include/regi2c_lp_bias.h b/components/esp_hw_support/port/esp32c3/private_include/regi2c_lp_bias.h index 0dae77107c..c50c1a941a 100644 --- a/components/esp_hw_support/port/esp32c3/private_include/regi2c_lp_bias.h +++ b/components/esp_hw_support/port/esp32c3/private_include/regi2c_lp_bias.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/port/esp32c3/private_include/regi2c_saradc.h b/components/esp_hw_support/port/esp32c3/private_include/regi2c_saradc.h index e9def9583d..1c35fd61ef 100644 --- a/components/esp_hw_support/port/esp32c3/private_include/regi2c_saradc.h +++ b/components/esp_hw_support/port/esp32c3/private_include/regi2c_saradc.h @@ -1,16 +1,8 @@ -// Copyright 2019-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: 2019-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/port/esp32c3/regi2c_ctrl.h b/components/esp_hw_support/port/esp32c3/regi2c_ctrl.h index 95f2626656..27e969eda8 100644 --- a/components/esp_hw_support/port/esp32c3/regi2c_ctrl.h +++ b/components/esp_hw_support/port/esp32c3/regi2c_ctrl.h @@ -1,30 +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. - -// 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/port/esp32c3/rtc_clk.c b/components/esp_hw_support/port/esp32c3/rtc_clk.c index f47848a523..8816a0e935 100644 --- a/components/esp_hw_support/port/esp32c3/rtc_clk.c +++ b/components/esp_hw_support/port/esp32c3/rtc_clk.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include diff --git a/components/esp_hw_support/port/esp32c3/rtc_clk_common.h b/components/esp_hw_support/port/esp32c3/rtc_clk_common.h index c3e8a86e09..07f8c1243c 100644 --- a/components/esp_hw_support/port/esp32c3/rtc_clk_common.h +++ b/components/esp_hw_support/port/esp32c3/rtc_clk_common.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/port/esp32c3/rtc_clk_init.c b/components/esp_hw_support/port/esp32c3/rtc_clk_init.c index ca9dd74cba..930407d139 100644 --- a/components/esp_hw_support/port/esp32c3/rtc_clk_init.c +++ b/components/esp_hw_support/port/esp32c3/rtc_clk_init.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -22,7 +14,7 @@ #include "soc/rtc.h" #include "soc/rtc_periph.h" #include "soc/efuse_periph.h" -#include "soc/apb_ctrl_reg.h" +#include "soc/syscon_reg.h" #include "hal/cpu_hal.h" #include "regi2c_ctrl.h" #include "soc_log.h" diff --git a/components/esp_hw_support/port/esp32c3/rtc_init.c b/components/esp_hw_support/port/esp32c3/rtc_init.c index 7a33720bea..e0431196b2 100644 --- a/components/esp_hw_support/port/esp32c3/rtc_init.c +++ b/components/esp_hw_support/port/esp32c3/rtc_init.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "sdkconfig.h" @@ -296,7 +288,7 @@ uint32_t get_rtc_dbias_by_efuse(uint8_t chip_version, uint32_t dig_dbias) signed int k_dig_ldo_real_mul10000 = K_DIG_MID_MUL10000 + k_dig_ldo; uint32_t v_dig_nearest_1v15_mul10000 = v_dig_dbias20_real_mul10000 + k_dig_ldo_real_mul10000 * (dig_dbias - 20); uint32_t v_rtc_nearest_1v15_mul10000 = 0; - for (rtc_dbias = 15; rtc_dbias < 32; rtc_dbias++) { + for (rtc_dbias = 15; rtc_dbias < 31; rtc_dbias++) { v_rtc_nearest_1v15_mul10000 = v_rtc_dbias20_real_mul10000 + k_rtc_ldo_real_mul10000 * (rtc_dbias - 20); if (v_rtc_nearest_1v15_mul10000 >= v_dig_nearest_1v15_mul10000 - 250) break; diff --git a/components/esp_hw_support/port/esp32c3/rtc_pm.c b/components/esp_hw_support/port/esp32c3/rtc_pm.c index 58f2719418..93174cd519 100644 --- a/components/esp_hw_support/port/esp32c3/rtc_pm.c +++ b/components/esp_hw_support/port/esp32c3/rtc_pm.c @@ -1,22 +1,14 @@ -// 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include #include "soc/rtc.h" #include "soc/rtc_cntl_reg.h" -#include "soc/apb_ctrl_reg.h" +#include "soc/syscon_reg.h" typedef enum { PM_LIGHT_SLEEP = BIT(2), /*!< WiFi PD, memory in light sleep */ diff --git a/components/esp_hw_support/port/esp32c3/rtc_sleep.c b/components/esp_hw_support/port/esp32c3/rtc_sleep.c index 4dd1cad1e6..456934a99a 100644 --- a/components/esp_hw_support/port/esp32c3/rtc_sleep.c +++ b/components/esp_hw_support/port/esp32c3/rtc_sleep.c @@ -1,23 +1,15 @@ -// 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include #include "soc/soc.h" #include "soc/rtc.h" #include "soc/rtc_cntl_reg.h" -#include "soc/apb_ctrl_reg.h" +#include "soc/syscon_reg.h" #include "soc/rtc.h" #include "soc/i2s_reg.h" #include "soc/bb_reg.h" @@ -39,9 +31,9 @@ void rtc_sleep_pu(rtc_sleep_pu_config_t cfg) { REG_SET_FIELD(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_LSLP_MEM_FORCE_PU, cfg.dig_fpu); REG_SET_FIELD(RTC_CNTL_PWC_REG, RTC_CNTL_FASTMEM_FORCE_LPU, cfg.rtc_fpu); - REG_SET_FIELD(APB_CTRL_FRONT_END_MEM_PD_REG, APB_CTRL_DC_MEM_FORCE_PU, cfg.fe_fpu); - REG_SET_FIELD(APB_CTRL_FRONT_END_MEM_PD_REG, APB_CTRL_PBUS_MEM_FORCE_PU, cfg.fe_fpu); - REG_SET_FIELD(APB_CTRL_FRONT_END_MEM_PD_REG, APB_CTRL_AGC_MEM_FORCE_PU, cfg.fe_fpu); + REG_SET_FIELD(SYSCON_FRONT_END_MEM_PD_REG, SYSCON_DC_MEM_FORCE_PU, cfg.fe_fpu); + REG_SET_FIELD(SYSCON_FRONT_END_MEM_PD_REG, SYSCON_PBUS_MEM_FORCE_PU, cfg.fe_fpu); + REG_SET_FIELD(SYSCON_FRONT_END_MEM_PD_REG, SYSCON_AGC_MEM_FORCE_PU, cfg.fe_fpu); REG_SET_FIELD(BBPD_CTRL, BB_FFT_FORCE_PU, cfg.bb_fpu); REG_SET_FIELD(BBPD_CTRL, BB_DC_EST_FORCE_PU, cfg.bb_fpu); REG_SET_FIELD(NRXPD_CTRL, NRX_RX_ROT_FORCE_PU, cfg.nrx_fpu); @@ -50,14 +42,14 @@ void rtc_sleep_pu(rtc_sleep_pu_config_t cfg) REG_SET_FIELD(FE_GEN_CTRL, FE_IQ_EST_FORCE_PU, cfg.fe_fpu); REG_SET_FIELD(FE2_TX_INTERP_CTRL, FE2_TX_INF_FORCE_PU, cfg.fe_fpu); if (cfg.sram_fpu) { - REG_SET_FIELD(APB_CTRL_MEM_POWER_UP_REG, APB_CTRL_SRAM_POWER_UP, APB_CTRL_SRAM_POWER_UP); + REG_SET_FIELD(SYSCON_MEM_POWER_UP_REG, SYSCON_SRAM_POWER_UP, SYSCON_SRAM_POWER_UP); } else { - REG_SET_FIELD(APB_CTRL_MEM_POWER_UP_REG, APB_CTRL_SRAM_POWER_UP, 0); + REG_SET_FIELD(SYSCON_MEM_POWER_UP_REG, SYSCON_SRAM_POWER_UP, 0); } if (cfg.rom_ram_fpu) { - REG_SET_FIELD(APB_CTRL_MEM_POWER_UP_REG, APB_CTRL_ROM_POWER_UP, APB_CTRL_ROM_POWER_UP); + REG_SET_FIELD(SYSCON_MEM_POWER_UP_REG, SYSCON_ROM_POWER_UP, SYSCON_ROM_POWER_UP); } else { - REG_SET_FIELD(APB_CTRL_MEM_POWER_UP_REG, APB_CTRL_ROM_POWER_UP, 0); + REG_SET_FIELD(SYSCON_MEM_POWER_UP_REG, SYSCON_ROM_POWER_UP, 0); } } @@ -90,9 +82,11 @@ void rtc_sleep_init(rtc_sleep_config_t cfg) REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_MONITOR, RTC_CNTL_DBG_ATTEN_MONITOR_DEFAULT); REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_BIAS_SLEEP_MONITOR, RTC_CNTL_BIASSLP_MONITOR_DEFAULT); - REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_BIAS_SLEEP_DEEP_SLP, RTC_CNTL_BIASSLP_SLEEP_DEFAULT); + REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_BIAS_SLEEP_DEEP_SLP, + (!cfg.deep_slp && cfg.xtal_fpu) ? RTC_CNTL_BIASSLP_SLEEP_ON : RTC_CNTL_BIASSLP_SLEEP_DEFAULT); REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_PD_CUR_MONITOR, RTC_CNTL_PD_CUR_MONITOR_DEFAULT); - REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_PD_CUR_DEEP_SLP, RTC_CNTL_PD_CUR_SLEEP_DEFAULT); + REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_PD_CUR_DEEP_SLP, + (!cfg.deep_slp && cfg.xtal_fpu) ? RTC_CNTL_PD_CUR_SLEEP_ON : RTC_CNTL_PD_CUR_SLEEP_DEFAULT); if (cfg.deep_slp) { REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_FORCE_XPD_CK, 0); CLEAR_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU); @@ -113,7 +107,18 @@ void rtc_sleep_init(rtc_sleep_config_t cfg) REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DG_VDD_DRV_B_SLP, RTC_CNTL_DG_VDD_DRV_B_SLP_DEFAULT); SET_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU); CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_WRAP_PD_EN); - REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_DEEP_SLP, RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_DEFAULT); + REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_DEEP_SLP, + cfg.int_8m_pd_en ? RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_DEFAULT : RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_NODROP); + } + + //Keep the RTC8M_CLK on in light_sleep mode if the ledc low-speed channel is clocked by RTC8M_CLK. + if (!cfg.int_8m_pd_en && GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M)) { + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PD); + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU); + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_NOGATING); + } else { + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU); + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_NOGATING); } /* enable VDDSDIO control by state machine */ @@ -126,8 +131,8 @@ void rtc_sleep_init(rtc_sleep_config_t cfg) REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_DEEP_SLP_REJECT_EN, cfg.deep_slp_reject); REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_LIGHT_SLP_REJECT_EN, cfg.light_slp_reject); - /* gating XTAL clock */ - REG_CLR_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_XTAL_GLOBAL_FORCE_NOGATING); + REG_SET_FIELD(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_XTL_FORCE_PU, cfg.xtal_fpu); + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_XTAL_GLOBAL_FORCE_NOGATING, cfg.xtal_fpu); } void rtc_sleep_low_init(uint32_t slowclk_period) diff --git a/components/esp_hw_support/port/esp32c3/rtc_time.c b/components/esp_hw_support/port/esp32c3/rtc_time.c index 7792d5cf13..59f8a68d38 100644 --- a/components/esp_hw_support/port/esp32c3/rtc_time.c +++ b/components/esp_hw_support/port/esp32c3/rtc_time.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "esp32c3/rom/ets_sys.h" @@ -51,7 +43,11 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) } else if (slow_freq == RTC_SLOW_FREQ_8MD256) { cal_clk = RTC_CAL_8MD256; } + } else if (cal_clk == RTC_CAL_INTERNAL_OSC) { + cal_clk = RTC_CAL_RTC_MUX; } + + /* Enable requested clock (150k clock is always on) */ int dig_32k_xtal_state = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN); if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_state) { diff --git a/components/esp_hw_support/port/esp32h2/chip_info.c b/components/esp_hw_support/port/esp32h2/chip_info.c index 5664ca34b6..9d1105b599 100644 --- a/components/esp_hw_support/port/esp32h2/chip_info.c +++ b/components/esp_hw_support/port/esp32h2/chip_info.c @@ -1,16 +1,8 @@ -// Copyright 2013-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: 2013-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "esp_chip_info.h" diff --git a/components/esp_hw_support/port/esp32h2/cpu_util_esp32h2.c b/components/esp_hw_support/port/esp32h2/cpu_util_esp32h2.c index b070320bb2..3d797ea8c0 100644 --- a/components/esp_hw_support/port/esp32h2/cpu_util_esp32h2.c +++ b/components/esp_hw_support/port/esp32h2/cpu_util_esp32h2.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "soc/cpu.h" diff --git a/components/esp_hw_support/port/esp32h2/dport_access.c b/components/esp_hw_support/port/esp32h2/dport_access.c index 08b55a96fb..8364f5687e 100644 --- a/components/esp_hw_support/port/esp32h2/dport_access.c +++ b/components/esp_hw_support/port/esp32h2/dport_access.c @@ -1,16 +1,8 @@ -// Copyright 2010-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: 2010-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include diff --git a/components/esp_hw_support/port/esp32h2/esp_crypto_lock.c b/components/esp_hw_support/port/esp32h2/esp_crypto_lock.c index 46a90ca08b..51b02be94d 100644 --- a/components/esp_hw_support/port/esp32h2/esp_crypto_lock.c +++ b/components/esp_hw_support/port/esp32h2/esp_crypto_lock.c @@ -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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include diff --git a/components/esp_hw_support/port/esp32h2/esp_ds.c b/components/esp_hw_support/port/esp32h2/esp_ds.c index 1ae6ab8221..6835f60f5a 100644 --- a/components/esp_hw_support/port/esp32h2/esp_ds.c +++ b/components/esp_hw_support/port/esp32h2/esp_ds.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include diff --git a/components/esp_hw_support/port/esp32h2/esp_hmac.c b/components/esp_hw_support/port/esp32h2/esp_hmac.c index 9ca245f2d8..84340d8164 100644 --- a/components/esp_hw_support/port/esp32h2/esp_hmac.c +++ b/components/esp_hw_support/port/esp32h2/esp_hmac.c @@ -1,29 +1,27 @@ -// 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "driver/periph_ctrl.h" -#include "esp32h2/rom/hmac.h" -#include "esp32h2/rom/ets_sys.h" +#include "esp32c3/rom/hmac.h" +#include "esp32c3/rom/ets_sys.h" +#include "esp_efuse.h" +#include "esp_efuse_table.h" #include "esp_hmac.h" +#include "esp_log.h" #include "esp_crypto_lock.h" +#include "soc/hwcrypto_reg.h" #include "hal/hmac_hal.h" #define SHA256_BLOCK_SZ 64 #define SHA256_PAD_SZ 8 +static const char *TAG = "esp_hmac"; + /** * @brief Apply the HMAC padding without the embedded length. * @@ -130,3 +128,53 @@ esp_err_t esp_hmac_calculate(hmac_key_id_t key_id, return ESP_OK; } + +static ets_efuse_block_t convert_key_type(hmac_key_id_t key_id) { + return ETS_EFUSE_BLOCK_KEY0 + (ets_efuse_block_t) key_id; +} + +esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token) +{ + int ets_status; + esp_err_t err = ESP_OK; + + if ((!token) || (key_id >= HMAC_KEY_MAX)) + return ESP_ERR_INVALID_ARG; + + /* Check if JTAG is permanently disabled by HW Disable eFuse */ + if (esp_efuse_read_field_bit(ESP_EFUSE_DIS_PAD_JTAG)) { + ESP_LOGE(TAG, "JTAG disabled permanently."); + return ESP_FAIL; + } + + esp_crypto_hmac_lock_acquire(); + + ets_status = ets_jtag_enable_temporarily(token, convert_key_type(key_id)); + + if (ets_status != ETS_OK) { + // ets_jtag_enable_temporarily returns either ETS_OK or ETS_FAIL + err = ESP_FAIL; + ESP_LOGE(TAG, "JTAG re-enabling failed (%d)", err); + } + + ESP_LOGD(TAG, "HMAC computation in downstream mode is completed."); + + ets_hmac_disable(); + + esp_crypto_hmac_lock_release(); + + return err; +} + +esp_err_t esp_hmac_jtag_disable() +{ + esp_crypto_hmac_lock_acquire(); + + REG_SET_BIT(HMAC_SET_INVALIDATE_JTAG_REG, HMAC_INVALIDATE_JTAG); + + esp_crypto_hmac_lock_release(); + + ESP_LOGD(TAG, "Invalidate JTAG result register. JTAG disabled."); + + return ESP_OK; +} diff --git a/components/esp_hw_support/port/esp32h2/i2c_brownout.h b/components/esp_hw_support/port/esp32h2/i2c_brownout.h index 5fac2c91b3..1d2ab34411 100644 --- a/components/esp_hw_support/port/esp32h2/i2c_brownout.h +++ b/components/esp_hw_support/port/esp32h2/i2c_brownout.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/port/esp32h2/i2c_rtc_clk.h b/components/esp_hw_support/port/esp32h2/i2c_rtc_clk.h index 0bbe0ee1a1..dbb7d73dc4 100644 --- a/components/esp_hw_support/port/esp32h2/i2c_rtc_clk.h +++ b/components/esp_hw_support/port/esp32h2/i2c_rtc_clk.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/port/esp32h2/memprot.c b/components/esp_hw_support/port/esp32h2/memprot.c index 5897ad67f0..9e79de34f4 100644 --- a/components/esp_hw_support/port/esp32h2/memprot.c +++ b/components/esp_hw_support/port/esp32h2/memprot.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ /* INTERNAL API * implementation of PMS memory protection features diff --git a/components/esp_hw_support/port/esp32h2/private_include/regi2c_bbpll.h b/components/esp_hw_support/port/esp32h2/private_include/regi2c_bbpll.h index 842f702934..56e31cd6b5 100644 --- a/components/esp_hw_support/port/esp32h2/private_include/regi2c_bbpll.h +++ b/components/esp_hw_support/port/esp32h2/private_include/regi2c_bbpll.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -58,71 +50,39 @@ #define I2C_BBPLL_OC_REF_DIV_MSB 3 #define I2C_BBPLL_OC_REF_DIV_LSB 0 -#define I2C_BBPLL_OC_DCHGP 2 -#define I2C_BBPLL_OC_DCHGP_MSB 6 -#define I2C_BBPLL_OC_DCHGP_LSB 4 +#define I2C_BBPLL_OC_DIV 3 +#define I2C_BBPLL_OC_DIV_MSB 5 +#define I2C_BBPLL_OC_DIV_LSB 0 -#define I2C_BBPLL_OC_ENB_FCAL 2 +#define I2C_BBPLL_OC_CHGP_DCUR 4 +#define I2C_BBPLL_OC_CHGP_DCUR_MSB 2 +#define I2C_BBPLL_OC_CHGP_DCUR_LSB 0 + +#define I2C_BBPLL_OC_BUFF_DCUR 4 +#define I2C_BBPLL_OC_BUFF_DCUR_MSB 5 +#define I2C_BBPLL_OC_BUFF_DCUR_LSB 3 + +#define I2C_BBPLL_OC_TSCHGP 4 +#define I2C_BBPLL_OC_TSCHGP_MSB 6 +#define I2C_BBPLL_OC_TSCHGP_LSB 6 + +#define I2C_BBPLL_OC_ENB_FCAL 4 #define I2C_BBPLL_OC_ENB_FCAL_MSB 7 #define I2C_BBPLL_OC_ENB_FCAL_LSB 7 -#define I2C_BBPLL_OC_DIV_7_0 3 -#define I2C_BBPLL_OC_DIV_7_0_MSB 7 -#define I2C_BBPLL_OC_DIV_7_0_LSB 0 +#define I2C_BBPLL_OC_LPF_DR 5 +#define I2C_BBPLL_OC_LPF_DR_MSB 1 +#define I2C_BBPLL_OC_LPF_DR_LSB 0 -#define I2C_BBPLL_RSTB_DIV_ADC 4 -#define I2C_BBPLL_RSTB_DIV_ADC_MSB 0 -#define I2C_BBPLL_RSTB_DIV_ADC_LSB 0 +#define I2C_BBPLL_OC_VCO_DCUR 5 +#define I2C_BBPLL_OC_VCO_DCUR_MSB 3 +#define I2C_BBPLL_OC_VCO_DCUR_LSB 2 -#define I2C_BBPLL_MODE_HF 4 -#define I2C_BBPLL_MODE_HF_MSB 1 -#define I2C_BBPLL_MODE_HF_LSB 1 - -#define I2C_BBPLL_DIV_ADC 4 -#define I2C_BBPLL_DIV_ADC_MSB 3 -#define I2C_BBPLL_DIV_ADC_LSB 2 - -#define I2C_BBPLL_DIV_DAC 4 -#define I2C_BBPLL_DIV_DAC_MSB 4 -#define I2C_BBPLL_DIV_DAC_LSB 4 - -#define I2C_BBPLL_DIV_CPU 4 -#define I2C_BBPLL_DIV_CPU_MSB 5 -#define I2C_BBPLL_DIV_CPU_LSB 5 - -#define I2C_BBPLL_OC_ENB_VCON 4 -#define I2C_BBPLL_OC_ENB_VCON_MSB 6 -#define I2C_BBPLL_OC_ENB_VCON_LSB 6 - -#define I2C_BBPLL_OC_TSCHGP 4 -#define I2C_BBPLL_OC_TSCHGP_MSB 7 -#define I2C_BBPLL_OC_TSCHGP_LSB 7 - -#define I2C_BBPLL_OC_DR1 5 -#define I2C_BBPLL_OC_DR1_MSB 2 -#define I2C_BBPLL_OC_DR1_LSB 0 - -#define I2C_BBPLL_OC_DR3 5 -#define I2C_BBPLL_OC_DR3_MSB 6 -#define I2C_BBPLL_OC_DR3_LSB 4 - -#define I2C_BBPLL_EN_USB 5 -#define I2C_BBPLL_EN_USB_MSB 7 -#define I2C_BBPLL_EN_USB_LSB 7 - -#define I2C_BBPLL_OC_DCUR 6 -#define I2C_BBPLL_OC_DCUR_MSB 2 -#define I2C_BBPLL_OC_DCUR_LSB 0 - -#define I2C_BBPLL_INC_CUR 6 -#define I2C_BBPLL_INC_CUR_MSB 3 -#define I2C_BBPLL_INC_CUR_LSB 3 - -#define I2C_BBPLL_OC_DHREF_SEL 6 +#define I2C_BBPLL_OC_DHREF_SEL 5 #define I2C_BBPLL_OC_DHREF_SEL_MSB 5 #define I2C_BBPLL_OC_DHREF_SEL_LSB 4 -#define I2C_BBPLL_OC_DLREF_SEL 6 +#define I2C_BBPLL_OC_DLREF_SEL 5 #define I2C_BBPLL_OC_DLREF_SEL_MSB 7 #define I2C_BBPLL_OC_DLREF_SEL_LSB 6 @@ -146,38 +106,14 @@ #define I2C_BBPLL_OR_LOCK_MSB 7 #define I2C_BBPLL_OR_LOCK_LSB 7 -#define I2C_BBPLL_OC_VCO_DBIAS 9 -#define I2C_BBPLL_OC_VCO_DBIAS_MSB 1 -#define I2C_BBPLL_OC_VCO_DBIAS_LSB 0 - -#define I2C_BBPLL_BBADC_DELAY2 9 -#define I2C_BBPLL_BBADC_DELAY2_MSB 3 -#define I2C_BBPLL_BBADC_DELAY2_LSB 2 - -#define I2C_BBPLL_BBADC_DVDD 9 -#define I2C_BBPLL_BBADC_DVDD_MSB 5 -#define I2C_BBPLL_BBADC_DVDD_LSB 4 - -#define I2C_BBPLL_BBADC_DREF 9 -#define I2C_BBPLL_BBADC_DREF_MSB 7 -#define I2C_BBPLL_BBADC_DREF_LSB 6 - -#define I2C_BBPLL_BBADC_DCUR 10 -#define I2C_BBPLL_BBADC_DCUR_MSB 1 -#define I2C_BBPLL_BBADC_DCUR_LSB 0 - -#define I2C_BBPLL_BBADC_INPUT_SHORT 10 -#define I2C_BBPLL_BBADC_INPUT_SHORT_MSB 2 -#define I2C_BBPLL_BBADC_INPUT_SHORT_LSB 2 +#define I2C_BBPLL_DTEST 10 +#define I2C_BBPLL_DTEST_MSB 1 +#define I2C_BBPLL_DTEST_LSB 0 #define I2C_BBPLL_ENT_PLL 10 -#define I2C_BBPLL_ENT_PLL_MSB 3 -#define I2C_BBPLL_ENT_PLL_LSB 3 +#define I2C_BBPLL_ENT_PLL_MSB 2 +#define I2C_BBPLL_ENT_PLL_LSB 2 -#define I2C_BBPLL_DTEST 10 -#define I2C_BBPLL_DTEST_MSB 5 -#define I2C_BBPLL_DTEST_LSB 4 - -#define I2C_BBPLL_ENT_ADC 10 -#define I2C_BBPLL_ENT_ADC_MSB 7 -#define I2C_BBPLL_ENT_ADC_LSB 6 +#define I2C_BBPLL_DIV_CPU 10 +#define I2C_BBPLL_DIV_CPU_MSB 3 +#define I2C_BBPLL_DIV_CPU_LSB 3 diff --git a/components/esp_hw_support/port/esp32h2/private_include/regi2c_bias.h b/components/esp_hw_support/port/esp32h2/private_include/regi2c_bias.h index f459a344ba..2d6b73a45e 100644 --- a/components/esp_hw_support/port/esp32h2/private_include/regi2c_bias.h +++ b/components/esp_hw_support/port/esp32h2/private_include/regi2c_bias.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -22,9 +14,109 @@ * bootloader_hardware_init function in bootloader_esp32c3.c. */ -#define I2C_BIAS 0X6A -#define I2C_BIAS_HOSTID 0 +#define I2C_BIAS 0x6a +#define I2C_BIAS_HOSTID 0 -#define I2C_BIAS_DREG_1P1_PVT 1 -#define I2C_BIAS_DREG_1P1_PVT_MSB 3 -#define I2C_BIAS_DREG_1P1_PVT_LSB 0 +#define I2C_BIAS_DREG_1P6 0 +#define I2C_BIAS_DREG_1P6_MSB 3 +#define I2C_BIAS_DREG_1P6_LSB 0 + +#define I2C_BIAS_DREG_0P8 0 +#define I2C_BIAS_DREG_0P8_MSB 7 +#define I2C_BIAS_DREG_0P8_LSB 4 + +#define I2C_BIAS_DREG_1P1_PVT 1 +#define I2C_BIAS_DREG_1P1_PVT_MSB 3 +#define I2C_BIAS_DREG_1P1_PVT_LSB 0 + +#define I2C_BIAS_DREG_1P2 1 +#define I2C_BIAS_DREG_1P2_MSB 7 +#define I2C_BIAS_DREG_1P2_LSB 4 + +#define I2C_BIAS_ENT_CPREG 2 +#define I2C_BIAS_ENT_CPREG_MSB 0 +#define I2C_BIAS_ENT_CPREG_LSB 0 + +#define I2C_BIAS_ENT_CGM 2 +#define I2C_BIAS_ENT_CGM_MSB 1 +#define I2C_BIAS_ENT_CGM_LSB 1 + +#define I2C_BIAS_CGM_BIAS 2 +#define I2C_BIAS_CGM_BIAS_MSB 3 +#define I2C_BIAS_CGM_BIAS_LSB 2 + +#define I2C_BIAS_DREF_IGM 2 +#define I2C_BIAS_DREF_IGM_MSB 4 +#define I2C_BIAS_DREF_IGM_LSB 4 + +#define I2C_BIAS_RC_DVREF 2 +#define I2C_BIAS_RC_DVREF_MSB 6 +#define I2C_BIAS_RC_DVREF_LSB 5 + +#define I2C_BIAS_FORCE_DISABLE_BIAS_SLEEP 2 +#define I2C_BIAS_FORCE_DISABLE_BIAS_SLEEP_MSB 7 +#define I2C_BIAS_FORCE_DISABLE_BIAS_SLEEP_LSB 7 + +#define I2C_BIAS_RC_ENX 3 +#define I2C_BIAS_RC_ENX_MSB 0 +#define I2C_BIAS_RC_ENX_LSB 0 + +#define I2C_BIAS_RC_START 3 +#define I2C_BIAS_RC_START_MSB 1 +#define I2C_BIAS_RC_START_LSB 1 + +#define I2C_BIAS_RC_DCAP_EXT 3 +#define I2C_BIAS_RC_DCAP_EXT_MSB 7 +#define I2C_BIAS_RC_DCAP_EXT_LSB 2 + +#define I2C_BIAS_XPD_RC 4 +#define I2C_BIAS_XPD_RC_MSB 0 +#define I2C_BIAS_XPD_RC_LSB 0 + +#define I2C_BIAS_ENT_CONSTI 4 +#define I2C_BIAS_ENT_CONSTI_MSB 1 +#define I2C_BIAS_ENT_CONSTI_LSB 1 + +#define I2C_BIAS_XPD_ICX 4 +#define I2C_BIAS_XPD_ICX_MSB 2 +#define I2C_BIAS_XPD_ICX_LSB 2 + +#define I2C_BIAS_RC_RSTB 4 +#define I2C_BIAS_RC_RSTB_MSB 3 +#define I2C_BIAS_RC_RSTB_LSB 3 + +#define I2C_BIAS_RC_DIV 4 +#define I2C_BIAS_RC_DIV_MSB 7 +#define I2C_BIAS_RC_DIV_LSB 4 + +#define I2C_BIAS_RC_CAP 5 +#define I2C_BIAS_RC_CAP_MSB 5 +#define I2C_BIAS_RC_CAP_LSB 0 + +#define I2C_BIAS_RC_UD 5 +#define I2C_BIAS_RC_UD_MSB 6 +#define I2C_BIAS_RC_UD_LSB 6 + +#define I2C_BIAS_RC_LOCKB 5 +#define I2C_BIAS_RC_LOCKB_MSB 7 +#define I2C_BIAS_RC_LOCKB_LSB 7 + +#define I2C_BIAS_RC_CHG_COUNT 6 +#define I2C_BIAS_RC_CHG_COUNT_MSB 4 +#define I2C_BIAS_RC_CHG_COUNT_LSB 0 + +#define I2C_BIAS_XPD_CPREG 7 +#define I2C_BIAS_XPD_CPREG_MSB 0 +#define I2C_BIAS_XPD_CPREG_LSB 0 + +#define I2C_BIAS_XPD_CGM 7 +#define I2C_BIAS_XPD_CGM_MSB 1 +#define I2C_BIAS_XPD_CGM_LSB 1 + +#define I2C_BIAS_DTEST 7 +#define I2C_BIAS_DTEST_MSB 3 +#define I2C_BIAS_DTEST_LSB 2 + +#define I2C_BIAS_DRES12K 7 +#define I2C_BIAS_DRES12K_MSB 7 +#define I2C_BIAS_DRES12K_LSB 4 diff --git a/components/esp_hw_support/port/esp32h2/private_include/regi2c_brownout.h b/components/esp_hw_support/port/esp32h2/private_include/regi2c_brownout.h index d81751347c..1aa54a2017 100644 --- a/components/esp_hw_support/port/esp32h2/private_include/regi2c_brownout.h +++ b/components/esp_hw_support/port/esp32h2/private_include/regi2c_brownout.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/port/esp32h2/private_include/regi2c_dig_reg.h b/components/esp_hw_support/port/esp32h2/private_include/regi2c_dig_reg.h index 2510f43ae5..9d2032b60e 100644 --- a/components/esp_hw_support/port/esp32h2/private_include/regi2c_dig_reg.h +++ b/components/esp_hw_support/port/esp32h2/private_include/regi2c_dig_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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/port/esp32h2/private_include/regi2c_lp_bias.h b/components/esp_hw_support/port/esp32h2/private_include/regi2c_lp_bias.h index 0dae77107c..d10669d34a 100644 --- a/components/esp_hw_support/port/esp32h2/private_include/regi2c_lp_bias.h +++ b/components/esp_hw_support/port/esp32h2/private_include/regi2c_lp_bias.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -22,42 +14,105 @@ * bus. These definitions are used via macros defined in regi2c_ctrl.h, by * rtc_init function in rtc_init.c. */ +#define I2C_ULP 0x61 +#define I2C_ULP_HOSTID 0 -#define I2C_ULP 0x61 -#define I2C_ULP_HOSTID 0 +#define I2C_ULP_IR_RESETB 0 +#define I2C_ULP_IR_RESETB_MSB 0 +#define I2C_ULP_IR_RESETB_LSB 0 -#define I2C_ULP_IR_RESETB 0 -#define I2C_ULP_IR_RESETB_MSB 0 -#define I2C_ULP_IR_RESETB_LSB 0 +#define I2C_ULP_XPD_REG_SLP 0 +#define I2C_ULP_XPD_REG_SLP_MSB 1 +#define I2C_ULP_XPD_REG_SLP_LSB 1 -#define I2C_ULP_IR_FORCE_XPD_CK 0 -#define I2C_ULP_IR_FORCE_XPD_CK_MSB 2 -#define I2C_ULP_IR_FORCE_XPD_CK_LSB 2 +#define I2C_ULP_DBIAS_SLP 0 +#define I2C_ULP_DBIAS_SLP_MSB 7 +#define I2C_ULP_DBIAS_SLP_LSB 4 -#define I2C_ULP_IR_FORCE_XPD_IPH 0 -#define I2C_ULP_IR_FORCE_XPD_IPH_MSB 4 -#define I2C_ULP_IR_FORCE_XPD_IPH_LSB 4 +#define I2C_ULP_IR_FORCE_XPD_BIAS_BUF 1 +#define I2C_ULP_IR_FORCE_XPD_BIAS_BUF_MSB 1 +#define I2C_ULP_IR_FORCE_XPD_BIAS_BUF_LSB 1 -#define I2C_ULP_IR_DISABLE_WATCHDOG_CK 0 -#define I2C_ULP_IR_DISABLE_WATCHDOG_CK_MSB 6 -#define I2C_ULP_IR_DISABLE_WATCHDOG_CK_LSB 6 +#define I2C_ULP_IR_FORCE_XPD_IPH 1 +#define I2C_ULP_IR_FORCE_XPD_IPH_MSB 2 +#define I2C_ULP_IR_FORCE_XPD_IPH_LSB 2 -#define I2C_ULP_O_DONE_FLAG 3 -#define I2C_ULP_O_DONE_FLAG_MSB 0 -#define I2C_ULP_O_DONE_FLAG_LSB 0 +#define I2C_ULP_IR_FORCE_XPD_VGATE_BUF 1 +#define I2C_ULP_IR_FORCE_XPD_VGATE_BUF_MSB 3 +#define I2C_ULP_IR_FORCE_XPD_VGATE_BUF_LSB 3 -#define I2C_ULP_BG_O_DONE_FLAG 3 -#define I2C_ULP_BG_O_DONE_FLAG_MSB 3 -#define I2C_ULP_BG_O_DONE_FLAG_LSB 3 +#define I2C_ULP_IR_FORCE_DISABLE_BIAS_SLEEP 1 +#define I2C_ULP_IR_FORCE_DISABLE_BIAS_SLEEP_MSB 4 +#define I2C_ULP_IR_FORCE_DISABLE_BIAS_SLEEP_LSB 4 -#define I2C_ULP_OCODE 4 -#define I2C_ULP_OCODE_MSB 7 -#define I2C_ULP_OCODE_LSB 0 +#define I2C_ULP_IR_ZOS_XPD 2 +#define I2C_ULP_IR_ZOS_XPD_MSB 0 +#define I2C_ULP_IR_ZOS_XPD_LSB 0 -#define I2C_ULP_IR_FORCE_CODE 5 -#define I2C_ULP_IR_FORCE_CODE_MSB 6 -#define I2C_ULP_IR_FORCE_CODE_LSB 6 +#define I2C_ULP_IR_ZOS_RSTB 2 +#define I2C_ULP_IR_ZOS_RSTB_MSB 1 +#define I2C_ULP_IR_ZOS_RSTB_LSB 1 -#define I2C_ULP_EXT_CODE 6 -#define I2C_ULP_EXT_CODE_MSB 7 -#define I2C_ULP_EXT_CODE_LSB 0 +#define I2C_ULP_IR_ZOS_RESTART 2 +#define I2C_ULP_IR_ZOS_RESTART_MSB 2 +#define I2C_ULP_IR_ZOS_RESTART_LSB 2 + +#define I2C_ULP_DTEST 3 +#define I2C_ULP_DTEST_MSB 1 +#define I2C_ULP_DTEST_LSB 0 + +#define I2C_ULP_ENT_BG 3 +#define I2C_ULP_ENT_BG_MSB 2 +#define I2C_ULP_ENT_BG_LSB 2 + +#define I2C_ULP_MODE_LVDET 3 +#define I2C_ULP_MODE_LVDET_MSB 3 +#define I2C_ULP_MODE_LVDET_LSB 3 + +#define I2C_ULP_DREF_LVDET 3 +#define I2C_ULP_DREF_LVDET_MSB 6 +#define I2C_ULP_DREF_LVDET_LSB 4 + +#define I2C_ULP_XPD_LVDET 3 +#define I2C_ULP_XPD_LVDET_MSB 7 +#define I2C_ULP_XPD_LVDET_LSB 7 + +#define I2C_ULP_INT_XPD_XTAL_CK_DIG_REG 4 +#define I2C_ULP_INT_XPD_XTAL_CK_DIG_REG_MSB 0 +#define I2C_ULP_INT_XPD_XTAL_CK_DIG_REG_LSB 0 + +#define I2C_ULP_INT_XPD_XTAL_BUF 4 +#define I2C_ULP_INT_XPD_XTAL_BUF_MSB 1 +#define I2C_ULP_INT_XPD_XTAL_BUF_LSB 1 + +#define I2C_ULP_INT_XPD_RC_CK 4 +#define I2C_ULP_INT_XPD_RC_CK_MSB 2 +#define I2C_ULP_INT_XPD_RC_CK_LSB 2 + +#define I2C_ULP_XTAL_DPHASE 4 +#define I2C_ULP_XTAL_DPHASE_MSB 3 +#define I2C_ULP_XTAL_DPHASE_LSB 3 + +#define I2C_ULP_INT_XPD_XTAL_LIN_REG 4 +#define I2C_ULP_INT_XPD_XTAL_LIN_REG_MSB 4 +#define I2C_ULP_INT_XPD_XTAL_LIN_REG_LSB 4 + +#define I2C_ULP_XTAL_RESTART_DC_CAL 4 +#define I2C_ULP_XTAL_RESTART_DC_CAL_MSB 5 +#define I2C_ULP_XTAL_RESTART_DC_CAL_LSB 5 + +#define I2C_ULP_XTAL_DAC 5 +#define I2C_ULP_XTAL_DAC_MSB 3 +#define I2C_ULP_XTAL_DAC_LSB 0 + +#define I2C_ULP_XTAL_DBLEED 6 +#define I2C_ULP_XTAL_DBLEED_MSB 4 +#define I2C_ULP_XTAL_DBLEED_LSB 0 + +#define I2C_ULP_XTAL_CAL_DONE 6 +#define I2C_ULP_XTAL_CAL_DONE_MSB 5 +#define I2C_ULP_XTAL_CAL_DONE_LSB 5 + +#define I2C_ULP_ZOS_DONE 6 +#define I2C_ULP_ZOS_DONE_MSB 6 +#define I2C_ULP_ZOS_DONE_LSB 6 diff --git a/components/esp_hw_support/port/esp32h2/private_include/regi2c_pmu.h b/components/esp_hw_support/port/esp32h2/private_include/regi2c_pmu.h new file mode 100644 index 0000000000..24ddd77826 --- /dev/null +++ b/components/esp_hw_support/port/esp32h2/private_include/regi2c_pmu.h @@ -0,0 +1,280 @@ +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define I2C_PMU 0x6d +#define I2C_PMU_HOSTID 0 + +#define I2C_PMU_THRES_HIGH_7_0 0 +#define I2C_PMU_THRES_HIGH_7_0_MSB 7 +#define I2C_PMU_THRES_HIGH_7_0_LSB 0 + +#define I2C_PMU_THRES_LOW_7_0 1 +#define I2C_PMU_THRES_LOW_7_0_MSB 7 +#define I2C_PMU_THRES_LOW_7_0_LSB 0 + +#define I2C_PMU_THRES_HIGH_11_8 2 +#define I2C_PMU_THRES_HIGH_11_8_MSB 3 +#define I2C_PMU_THRES_HIGH_11_8_LSB 0 + +#define I2C_PMU_THRES_LOW_11_8 2 +#define I2C_PMU_THRES_LOW_11_8_MSB 7 +#define I2C_PMU_THRES_LOW_11_8_LSB 4 + +#define I2C_PMU_PVT_DELAY_INIT 3 +#define I2C_PMU_PVT_DELAY_INIT_MSB 7 +#define I2C_PMU_PVT_DELAY_INIT_LSB 0 + +#define I2C_PMU_PVT_DELAY_COUNT 4 +#define I2C_PMU_PVT_DELAY_COUNT_MSB 5 +#define I2C_PMU_PVT_DELAY_COUNT_LSB 0 + +#define I2C_PMU_OR_EN_CONT_CAL 4 +#define I2C_PMU_OR_EN_CONT_CAL_MSB 7 +#define I2C_PMU_OR_EN_CONT_CAL_LSB 7 + +#define I2C_PMU_I2C_RTC_DREG 5 +#define I2C_PMU_I2C_RTC_DREG_MSB 4 +#define I2C_PMU_I2C_RTC_DREG_LSB 0 + +#define I2C_PMU_I2C_DIG_DREG 6 +#define I2C_PMU_I2C_DIG_DREG_MSB 4 +#define I2C_PMU_I2C_DIG_DREG_LSB 0 + +#define I2C_PMU_I2C_RTC_DREG_SLP 7 +#define I2C_PMU_I2C_RTC_DREG_SLP_MSB 3 +#define I2C_PMU_I2C_RTC_DREG_SLP_LSB 0 + +#define I2C_PMU_I2C_DIG_DREG_SLP 7 +#define I2C_PMU_I2C_DIG_DREG_SLP_MSB 7 +#define I2C_PMU_I2C_DIG_DREG_SLP_LSB 4 + +#define I2C_PMU_EN_I2C_RTC_DREG 10 +#define I2C_PMU_EN_I2C_RTC_DREG_MSB 0 +#define I2C_PMU_EN_I2C_RTC_DREG_LSB 0 + +#define I2C_PMU_EN_I2C_DIG_DREG 10 +#define I2C_PMU_EN_I2C_DIG_DREG_MSB 1 +#define I2C_PMU_EN_I2C_DIG_DREG_LSB 1 + +#define I2C_PMU_EN_I2C_RTC_DREG_SLP 10 +#define I2C_PMU_EN_I2C_RTC_DREG_SLP_MSB 2 +#define I2C_PMU_EN_I2C_RTC_DREG_SLP_LSB 2 + +#define I2C_PMU_EN_I2C_DIG_DREG_SLP 10 +#define I2C_PMU_EN_I2C_DIG_DREG_SLP_MSB 3 +#define I2C_PMU_EN_I2C_DIG_DREG_SLP_LSB 3 + +#define I2C_PMU_ENX_RTC_DREG 11 +#define I2C_PMU_ENX_RTC_DREG_MSB 0 +#define I2C_PMU_ENX_RTC_DREG_LSB 0 + +#define I2C_PMU_ENX_DIG_DREG 11 +#define I2C_PMU_ENX_DIG_DREG_MSB 1 +#define I2C_PMU_ENX_DIG_DREG_LSB 1 + +#define I2C_PMU_OR_XPD_RTC_SLAVE_3P3 11 +#define I2C_PMU_OR_XPD_RTC_SLAVE_3P3_MSB 2 +#define I2C_PMU_OR_XPD_RTC_SLAVE_3P3_LSB 2 + +#define I2C_PMU_OR_XPD_RTC_REG 11 +#define I2C_PMU_OR_XPD_RTC_REG_MSB 4 +#define I2C_PMU_OR_XPD_RTC_REG_LSB 4 + +#define I2C_PMU_OR_XPD_DIG_REG 11 +#define I2C_PMU_OR_XPD_DIG_REG_MSB 5 +#define I2C_PMU_OR_XPD_DIG_REG_LSB 5 + +#define I2C_PMU_OR_PD_RTC_REG_SLP 11 +#define I2C_PMU_OR_PD_RTC_REG_SLP_MSB 6 +#define I2C_PMU_OR_PD_RTC_REG_SLP_LSB 6 + +#define I2C_PMU_OR_PD_DIG_REG_SLP 11 +#define I2C_PMU_OR_PD_DIG_REG_SLP_MSB 7 +#define I2C_PMU_OR_PD_DIG_REG_SLP_LSB 7 + +#define I2C_PMU_INT_DREG 12 +#define I2C_PMU_INT_DREG_MSB 4 +#define I2C_PMU_INT_DREG_LSB 0 + +#define I2C_PMU_O_UDF 12 +#define I2C_PMU_O_UDF_MSB 5 +#define I2C_PMU_O_UDF_LSB 5 + +#define I2C_PMU_O_OVF 12 +#define I2C_PMU_O_OVF_MSB 6 +#define I2C_PMU_O_OVF_LSB 6 + +#define I2C_PMU_O_UPDATE 12 +#define I2C_PMU_O_UPDATE_MSB 7 +#define I2C_PMU_O_UPDATE_LSB 7 + +#define I2C_PMU_PVT_COUNT 13 +#define I2C_PMU_PVT_COUNT_MSB 7 +#define I2C_PMU_PVT_COUNT_LSB 0 + +#define I2C_PMU_PVT_COUNT 14 +#define I2C_PMU_PVT_COUNT_MSB 3 +#define I2C_PMU_PVT_COUNT_LSB 0 + +#define I2C_PMU_IC_VGOOD_LVDET 14 +#define I2C_PMU_IC_VGOOD_LVDET_MSB 4 +#define I2C_PMU_IC_VGOOD_LVDET_LSB 4 + +#define I2C_PMU_IC_POWER_GOOD_DCDC 14 +#define I2C_PMU_IC_POWER_GOOD_DCDC_MSB 5 +#define I2C_PMU_IC_POWER_GOOD_DCDC_LSB 5 + +#define I2C_PMU_IC_VGOOD_DIGDET 14 +#define I2C_PMU_IC_VGOOD_DIGDET_MSB 6 +#define I2C_PMU_IC_VGOOD_DIGDET_LSB 6 + +#define I2C_PMU_OR_XPD_DCDC 15 +#define I2C_PMU_OR_XPD_DCDC_MSB 0 +#define I2C_PMU_OR_XPD_DCDC_LSB 0 + +#define I2C_PMU_OR_DISALBE_DEEP_SLEEP_DCDC 15 +#define I2C_PMU_OR_DISALBE_DEEP_SLEEP_DCDC_MSB 1 +#define I2C_PMU_OR_DISALBE_DEEP_SLEEP_DCDC_LSB 1 + +#define I2C_PMU_OR_DISALBE_LIGHT_SLEEP_DCDC 15 +#define I2C_PMU_OR_DISALBE_LIGHT_SLEEP_DCDC_MSB 2 +#define I2C_PMU_OR_DISALBE_LIGHT_SLEEP_DCDC_LSB 2 + +#define I2C_PMU_OR_ENALBE_TRX_MODE_DCDC 15 +#define I2C_PMU_OR_ENALBE_TRX_MODE_DCDC_MSB 3 +#define I2C_PMU_OR_ENALBE_TRX_MODE_DCDC_LSB 3 + +#define I2C_PMU_OR_ENX_REG_DCDC 15 +#define I2C_PMU_OR_ENX_REG_DCDC_MSB 4 +#define I2C_PMU_OR_ENX_REG_DCDC_LSB 4 + +#define I2C_PMU_OR_UNLOCK_DCDC 15 +#define I2C_PMU_OR_UNLOCK_DCDC_MSB 5 +#define I2C_PMU_OR_UNLOCK_DCDC_LSB 5 + +#define I2C_PMU_OR_FORCE_LOCK_DCDC 15 +#define I2C_PMU_OR_FORCE_LOCK_DCDC_MSB 6 +#define I2C_PMU_OR_FORCE_LOCK_DCDC_LSB 6 + +#define I2C_PMU_OR_ENB_SLOW_CLK 15 +#define I2C_PMU_OR_ENB_SLOW_CLK_MSB 7 +#define I2C_PMU_OR_ENB_SLOW_CLK_LSB 7 + +#define I2C_PMU_OC_SCK_DCAP 16 +#define I2C_PMU_OC_SCK_DCAP_MSB 7 +#define I2C_PMU_OC_SCK_DCAP_LSB 0 + +#define I2C_PMU_OC_XPD_LVDET 17 +#define I2C_PMU_OC_XPD_LVDET_MSB 0 +#define I2C_PMU_OC_XPD_LVDET_LSB 0 + +#define I2C_PMU_OC_MODE_LVDET 17 +#define I2C_PMU_OC_MODE_LVDET_MSB 1 +#define I2C_PMU_OC_MODE_LVDET_LSB 1 + +#define I2C_PMU_OR_XPD_TRX 17 +#define I2C_PMU_OR_XPD_TRX_MSB 2 +#define I2C_PMU_OR_XPD_TRX_LSB 2 + +#define I2C_PMU_OR_EN_RESET_CHIP 17 +#define I2C_PMU_OR_EN_RESET_CHIP_MSB 3 +#define I2C_PMU_OR_EN_RESET_CHIP_LSB 3 + +#define I2C_PMU_OC_DREF_LVDET 17 +#define I2C_PMU_OC_DREF_LVDET_MSB 6 +#define I2C_PMU_OC_DREF_LVDET_LSB 4 + +#define I2C_PMU_OR_FORCE_XPD_REG_SLAVE 17 +#define I2C_PMU_OR_FORCE_XPD_REG_SLAVE_MSB 7 +#define I2C_PMU_OR_FORCE_XPD_REG_SLAVE_LSB 7 + +#define I2C_PMU_DTEST 18 +#define I2C_PMU_DTEST_MSB 1 +#define I2C_PMU_DTEST_LSB 0 + +#define I2C_PMU_ENT_BIAS 18 +#define I2C_PMU_ENT_BIAS_MSB 2 +#define I2C_PMU_ENT_BIAS_LSB 2 + +#define I2C_PMU_ENT_VDD 18 +#define I2C_PMU_ENT_VDD_MSB 5 +#define I2C_PMU_ENT_VDD_LSB 3 + +#define I2C_PMU_EN_DMUX 18 +#define I2C_PMU_EN_DMUX_MSB 6 +#define I2C_PMU_EN_DMUX_LSB 6 + +#define I2C_PMU_WD_DISABLE 18 +#define I2C_PMU_WD_DISABLE_MSB 7 +#define I2C_PMU_WD_DISABLE_LSB 7 + +#define I2C_PMU_DTEST_DCDC 19 +#define I2C_PMU_DTEST_DCDC_MSB 0 +#define I2C_PMU_DTEST_DCDC_LSB 0 + +#define I2C_PMU_TESTEN_DCDC 19 +#define I2C_PMU_TESTEN_DCDC_MSB 1 +#define I2C_PMU_TESTEN_DCDC_LSB 1 + +#define I2C_PMU_ADD_DCDC 19 +#define I2C_PMU_ADD_DCDC_MSB 6 +#define I2C_PMU_ADD_DCDC_LSB 4 + +#define I2C_PMU_OR_POCPENB_DCDC 20 +#define I2C_PMU_OR_POCPENB_DCDC_MSB 0 +#define I2C_PMU_OR_POCPENB_DCDC_LSB 0 + +#define I2C_PMU_OR_SSTIME_DCDC 20 +#define I2C_PMU_OR_SSTIME_DCDC_MSB 1 +#define I2C_PMU_OR_SSTIME_DCDC_LSB 1 + +#define I2C_PMU_OR_CCM_DCDC 20 +#define I2C_PMU_OR_CCM_DCDC_MSB 2 +#define I2C_PMU_OR_CCM_DCDC_LSB 2 + +#define I2C_PMU_OR_VSET_LOW_DCDC 20 +#define I2C_PMU_OR_VSET_LOW_DCDC_MSB 7 +#define I2C_PMU_OR_VSET_LOW_DCDC_LSB 3 + +#define I2C_PMU_OR_FSW_DCDC 21 +#define I2C_PMU_OR_FSW_DCDC_MSB 2 +#define I2C_PMU_OR_FSW_DCDC_LSB 0 + +#define I2C_PMU_OR_DCMLEVEL_DCDC 21 +#define I2C_PMU_OR_DCMLEVEL_DCDC_MSB 4 +#define I2C_PMU_OR_DCMLEVEL_DCDC_LSB 3 + +#define I2C_PMU_OR_DCM2ENB_DCDC 21 +#define I2C_PMU_OR_DCM2ENB_DCDC_MSB 5 +#define I2C_PMU_OR_DCM2ENB_DCDC_LSB 5 + +#define I2C_PMU_OR_RAMP_DCDC 21 +#define I2C_PMU_OR_RAMP_DCDC_MSB 6 +#define I2C_PMU_OR_RAMP_DCDC_LSB 6 + +#define I2C_PMU_OR_RAMPLEVEL_DCDC 21 +#define I2C_PMU_OR_RAMPLEVEL_DCDC_MSB 7 +#define I2C_PMU_OR_RAMPLEVEL_DCDC_LSB 7 + +#define I2C_PMU_OR_VSET_HIGH_DCDC 22 +#define I2C_PMU_OR_VSET_HIGH_DCDC_MSB 4 +#define I2C_PMU_OR_VSET_HIGH_DCDC_LSB 0 + +#define I2C_PMU_OC_DEL_SSEND 22 +#define I2C_PMU_OC_DEL_SSEND_MSB 7 +#define I2C_PMU_OC_DEL_SSEND_LSB 5 + +#define I2C_PMU_OC_XPD_DIGDET 23 +#define I2C_PMU_OC_XPD_DIGDET_MSB 0 +#define I2C_PMU_OC_XPD_DIGDET_LSB 0 + +#define I2C_PMU_OC_MODE_DIGDET 23 +#define I2C_PMU_OC_MODE_DIGDET_MSB 1 +#define I2C_PMU_OC_MODE_DIGDET_LSB 1 + +#define I2C_PMU_OC_DREF_DIGDET 23 +#define I2C_PMU_OC_DREF_DIGDET_MSB 6 +#define I2C_PMU_OC_DREF_DIGDET_LSB 4 diff --git a/components/esp_hw_support/port/esp32h2/private_include/regi2c_saradc.h b/components/esp_hw_support/port/esp32h2/private_include/regi2c_saradc.h index e9def9583d..1c35fd61ef 100644 --- a/components/esp_hw_support/port/esp32h2/private_include/regi2c_saradc.h +++ b/components/esp_hw_support/port/esp32h2/private_include/regi2c_saradc.h @@ -1,16 +1,8 @@ -// Copyright 2019-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: 2019-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/port/esp32h2/private_include/regi2c_ulp.h b/components/esp_hw_support/port/esp32h2/private_include/regi2c_ulp.h new file mode 100644 index 0000000000..5751f01936 --- /dev/null +++ b/components/esp_hw_support/port/esp32h2/private_include/regi2c_ulp.h @@ -0,0 +1,108 @@ +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define I2C_ULP 0x61 +#define I2C_ULP_HOSTID 0 + +#define I2C_ULP_IR_RESETB 0 +#define I2C_ULP_IR_RESETB_MSB 0 +#define I2C_ULP_IR_RESETB_LSB 0 + +#define I2C_ULP_XPD_REG_SLP 0 +#define I2C_ULP_XPD_REG_SLP_MSB 1 +#define I2C_ULP_XPD_REG_SLP_LSB 1 + +#define I2C_ULP_DBIAS_SLP 0 +#define I2C_ULP_DBIAS_SLP_MSB 7 +#define I2C_ULP_DBIAS_SLP_LSB 4 + +#define I2C_ULP_IR_FORCE_XPD_BIAS_BUF 1 +#define I2C_ULP_IR_FORCE_XPD_BIAS_BUF_MSB 1 +#define I2C_ULP_IR_FORCE_XPD_BIAS_BUF_LSB 1 + +#define I2C_ULP_IR_FORCE_XPD_IPH 1 +#define I2C_ULP_IR_FORCE_XPD_IPH_MSB 2 +#define I2C_ULP_IR_FORCE_XPD_IPH_LSB 2 + +#define I2C_ULP_IR_FORCE_XPD_VGATE_BUF 1 +#define I2C_ULP_IR_FORCE_XPD_VGATE_BUF_MSB 3 +#define I2C_ULP_IR_FORCE_XPD_VGATE_BUF_LSB 3 + +#define I2C_ULP_IR_FORCE_DISABLE_BIAS_SLEEP 1 +#define I2C_ULP_IR_FORCE_DISABLE_BIAS_SLEEP_MSB 4 +#define I2C_ULP_IR_FORCE_DISABLE_BIAS_SLEEP_LSB 4 + +#define I2C_ULP_IR_ZOS_XPD 2 +#define I2C_ULP_IR_ZOS_XPD_MSB 0 +#define I2C_ULP_IR_ZOS_XPD_LSB 0 + +#define I2C_ULP_IR_ZOS_RSTB 2 +#define I2C_ULP_IR_ZOS_RSTB_MSB 1 +#define I2C_ULP_IR_ZOS_RSTB_LSB 1 + +#define I2C_ULP_IR_ZOS_RESTART 2 +#define I2C_ULP_IR_ZOS_RESTART_MSB 2 +#define I2C_ULP_IR_ZOS_RESTART_LSB 2 + +#define I2C_ULP_DTEST 3 +#define I2C_ULP_DTEST_MSB 1 +#define I2C_ULP_DTEST_LSB 0 + +#define I2C_ULP_ENT_BG 3 +#define I2C_ULP_ENT_BG_MSB 2 +#define I2C_ULP_ENT_BG_LSB 2 + +#define I2C_ULP_MODE_LVDET 3 +#define I2C_ULP_MODE_LVDET_MSB 3 +#define I2C_ULP_MODE_LVDET_LSB 3 + +#define I2C_ULP_DREF_LVDET 3 +#define I2C_ULP_DREF_LVDET_MSB 6 +#define I2C_ULP_DREF_LVDET_LSB 4 + +#define I2C_ULP_XPD_LVDET 3 +#define I2C_ULP_XPD_LVDET_MSB 7 +#define I2C_ULP_XPD_LVDET_LSB 7 + +#define I2C_ULP_INT_XPD_XTAL_CK_DIG_REG 4 +#define I2C_ULP_INT_XPD_XTAL_CK_DIG_REG_MSB 0 +#define I2C_ULP_INT_XPD_XTAL_CK_DIG_REG_LSB 0 + +#define I2C_ULP_INT_XPD_XTAL_BUF 4 +#define I2C_ULP_INT_XPD_XTAL_BUF_MSB 1 +#define I2C_ULP_INT_XPD_XTAL_BUF_LSB 1 + +#define I2C_ULP_INT_XPD_RC_CK 4 +#define I2C_ULP_INT_XPD_RC_CK_MSB 2 +#define I2C_ULP_INT_XPD_RC_CK_LSB 2 + +#define I2C_ULP_XTAL_DPHASE 4 +#define I2C_ULP_XTAL_DPHASE_MSB 3 +#define I2C_ULP_XTAL_DPHASE_LSB 3 + +#define I2C_ULP_INT_XPD_XTAL_LIN_REG 4 +#define I2C_ULP_INT_XPD_XTAL_LIN_REG_MSB 4 +#define I2C_ULP_INT_XPD_XTAL_LIN_REG_LSB 4 + +#define I2C_ULP_XTAL_RESTART_DC_CAL 4 +#define I2C_ULP_XTAL_RESTART_DC_CAL_MSB 5 +#define I2C_ULP_XTAL_RESTART_DC_CAL_LSB 5 + +#define I2C_ULP_XTAL_DAC 5 +#define I2C_ULP_XTAL_DAC_MSB 3 +#define I2C_ULP_XTAL_DAC_LSB 0 + +#define I2C_ULP_XTAL_DBLEED 6 +#define I2C_ULP_XTAL_DBLEED_MSB 4 +#define I2C_ULP_XTAL_DBLEED_LSB 0 + +#define I2C_ULP_XTAL_CAL_DONE 6 +#define I2C_ULP_XTAL_CAL_DONE_MSB 5 +#define I2C_ULP_XTAL_CAL_DONE_LSB 5 + +#define I2C_ULP_ZOS_DONE 6 +#define I2C_ULP_ZOS_DONE_MSB 6 +#define I2C_ULP_ZOS_DONE_LSB 6 diff --git a/components/esp_hw_support/port/esp32h2/regi2c_ctrl.h b/components/esp_hw_support/port/esp32h2/regi2c_ctrl.h index 95f2626656..28436f5790 100644 --- a/components/esp_hw_support/port/esp32h2/regi2c_ctrl.h +++ b/components/esp_hw_support/port/esp32h2/regi2c_ctrl.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ // Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD // diff --git a/components/esp_hw_support/port/esp32h2/rtc_clk.c b/components/esp_hw_support/port/esp32h2/rtc_clk.c index a2de52ef75..550d84058a 100644 --- a/components/esp_hw_support/port/esp32h2/rtc_clk.c +++ b/components/esp_hw_support/port/esp32h2/rtc_clk.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -23,6 +15,7 @@ #include "esp32h2/rom/uart.h" #include "esp32h2/rom/gpio.h" #include "soc/rtc.h" +#include "i2c_bbpll.h" #include "soc/rtc_cntl_reg.h" #include "soc/efuse_reg.h" #include "soc/syscon_reg.h" @@ -34,14 +27,19 @@ static const char *TAG = "rtc_clk"; -#define RTC_PLL_FREQ_320M 320 -#define RTC_PLL_FREQ_480M 480 +#define RTC_PLL_FREQ_96M 96 +#define RTC_OSC_FREQ_RC8M 18 #define DELAY_RTC_CLK_SWITCH 5 +#define RTC_CNTL_ANA_CONF0_CAL_REG 0x6000e040 +#define RTC_CNTL_ANA_CONF0_CAL_START BIT(2) +#define RTC_CNTL_ANA_CONF0_CAL_STOP BIT(3) +#define RTC_CNTL_ANA_CONF0_CAL_DONE BIT(24) -// Current PLL frequency, in MHZ (320 or 480). Zero if PLL is not enabled. +// Current PLL frequency, in 96MHZ. Zero if PLL is not enabled. static int s_cur_pll_freq; -static void rtc_clk_cpu_freq_to_8m(void); +void rtc_clk_cpu_freq_to_8m(void); +static uint32_t rtc_clk_ahb_freq_set(uint32_t div); void rtc_clk_32k_enable_internal(x32k_config_t cfg) { @@ -55,6 +53,9 @@ void rtc_clk_32k_enable_internal(x32k_config_t cfg) void rtc_clk_32k_enable(bool enable) { if (enable) { + /* need to hangup gpio0 & 1 before enable xtal_32k */ + rtc_gpio_hangup(0); + rtc_gpio_hangup(1); x32k_config_t cfg = X32K_CONFIG_DEFAULT(); rtc_clk_32k_enable_internal(cfg); } else { @@ -63,16 +64,26 @@ void rtc_clk_32k_enable(bool enable) } } +void rtc_clk_rc32k_dfreq(uint32_t dfreq) +{ + REG_SET_FIELD(RTC_CNTL_RC32K_CTRL_REG, RTC_CNTL_RC32K_DFREQ, dfreq); +} + +void rtc_clk_rc32k_enable(bool enable) +{ + rc32k_config_t cfg = RC32K_CONFIG_DEFAULT(); + rtc_clk_rc32k_dfreq(cfg.dfreq); + REG_SET_FIELD(RTC_CNTL_RC32K_CTRL_REG, RTC_CNTL_RC32K_XPD, enable); +} + void rtc_clk_32k_enable_external(void) { - /* TODO ESP32-C3 IDF-2408: external 32k source may need different settings */ - x32k_config_t cfg = X32K_CONFIG_DEFAULT(); - rtc_clk_32k_enable_internal(cfg); + rtc_clk_32k_enable(true); } void rtc_clk_32k_bootstrap(uint32_t cycle) { - /* No special bootstrapping needed for ESP32-C3, 'cycle' argument is to keep the signature + /* No special bootstrapping needed for ESP32-H2, 'cycle' argument is to keep the signature * same as for the ESP32. Just enable the XTAL here. */ (void) cycle; @@ -90,53 +101,11 @@ bool rtc_clk_32k_enabled(void) return !disabled; } -void rtc_clk_8m_enable(bool clk_8m_en, bool d256_en) -{ - if (clk_8m_en) { - // CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M); // ESP32H2-TODO: IDF-3396 - /* no need to wait once enabled by software */ - REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CK8M_ENABLE_WAIT_DEFAULT); - esp_rom_delay_us(DELAY_8M_ENABLE); - } else { - // SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M); - REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CNTL_CK8M_WAIT_DEFAULT); - } - /* d256 should be independent configured with 8M - * Maybe we can split this function into 8m and dmd256 - */ - if (d256_en) { - // CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV); - } else { - // SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV); - } -} - -bool rtc_clk_8m_enabled(void) -{ - return false; - // return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M) == 0; // ESP32H2-TODO: IDF-3396 -} - -bool rtc_clk_8md256_enabled(void) -{ - return false; - // return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV) == 0; // ESP32H2-TODO: IDF-3396 -} - void rtc_clk_slow_freq_set(rtc_slow_freq_t slow_freq) { REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, slow_freq); - - /* Why we need to connect this clock to digital? - * Or maybe this clock should be connected to digital when xtal 32k clock is enabled instead? - */ - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, - (slow_freq == RTC_SLOW_FREQ_32K_XTAL) ? 1 : 0); - - /* The clk_8m_d256 will be closed when rtc_state in SLEEP, - so if the slow_clk is 8md256, clk_8m must be force power on - */ - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU, (slow_freq == RTC_SLOW_FREQ_8MD256) ? 1 : 0); + rtc_clk_32k_enable((slow_freq == RTC_SLOW_FREQ_32K_XTAL) ? 1 : 0); + rtc_clk_rc32k_enable((slow_freq == RTC_SLOW_FREQ_RC32K) ? 1 : 0); esp_rom_delay_us(DELAY_SLOW_CLK_SWITCH); } @@ -150,7 +119,7 @@ uint32_t rtc_clk_slow_freq_get_hz(void) switch (rtc_clk_slow_freq_get()) { case RTC_SLOW_FREQ_RTC: return RTC_SLOW_CLK_FREQ_150K; case RTC_SLOW_FREQ_32K_XTAL: return RTC_SLOW_CLK_FREQ_32K; - case RTC_SLOW_FREQ_8MD256: return RTC_SLOW_CLK_FREQ_8MD256; + case RTC_SLOW_FREQ_RC32K: return RTC_SLOW_CLK_FREQ_RC32; } return 0; } @@ -178,100 +147,32 @@ static void rtc_clk_bbpll_enable(void) CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD | RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD); } +static void rtc_clk_bbpll_cali_stop(void) +{ + while (!REG_GET_BIT(RTC_CNTL_ANA_CONF0_CAL_REG, RTC_CNTL_ANA_CONF0_CAL_DONE)); + REG_CLR_BIT(RTC_CNTL_ANA_CONF0_CAL_REG, RTC_CNTL_ANA_CONF0_CAL_STOP); + REG_SET_BIT(RTC_CNTL_ANA_CONF0_CAL_REG, RTC_CNTL_ANA_CONF0_CAL_START); + +} void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq) { uint8_t div_ref; - uint8_t div7_0; - uint8_t dr1; - uint8_t dr3; - uint8_t dchgp; - uint8_t dcur; - uint8_t dbias; - - CLEAR_PERI_REG_MASK(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_HIGH); - SET_PERI_REG_MASK(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_LOW); - if (pll_freq == RTC_PLL_FREQ_480M) { - /* Set this register to let the digital part know 480M PLL is used */ - // SET_PERI_REG_MASK(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL); // ESP32H2-TODO: IDF-3396 - /* Configure 480M PLL */ - switch (xtal_freq) { - case RTC_XTAL_FREQ_40M: - div_ref = 0; - div7_0 = 8; - dr1 = 0; - dr3 = 0; - dchgp = 5; - dcur = 3; - dbias = 2; - break; - case RTC_XTAL_FREQ_32M: - div_ref = 1; - div7_0 = 26; - dr1 = 1; - dr3 = 1; - dchgp = 4; - dcur = 0; - dbias = 2; - break; - default: - div_ref = 0; - div7_0 = 8; - dr1 = 0; - dr3 = 0; - dchgp = 5; - dcur = 3; - dbias = 2; - break; - } - REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_MODE_HF, 0x6B); + uint8_t div5_0; + if ((pll_freq == RTC_PLL_FREQ_96M) && (xtal_freq == RTC_XTAL_FREQ_32M)) { + /* Configure 96M PLL */ + div_ref = 0; + div5_0 = 1; } else { - /* Clear this register to let the digital part know 320M PLL is used */ - // CLEAR_PERI_REG_MASK(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL); // ESP32H2-TODO: IDF-3396 - /* Configure 320M PLL */ - switch (xtal_freq) { - case RTC_XTAL_FREQ_40M: - div_ref = 0; - div7_0 = 4; - dr1 = 0; - dr3 = 0; - dchgp = 5; - dcur = 3; - dbias = 2; - break; - case RTC_XTAL_FREQ_32M: - div_ref = 1; - div7_0 = 6; - dr1 = 0; - dr3 = 0; - dchgp = 5; - dcur = 3; - dbias = 2; - break; - default: - div_ref = 0; - div7_0 = 4; - dr1 = 0; - dr3 = 0; - dchgp = 5; - dcur = 3; - dbias = 2; - break; - } - REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_MODE_HF, 0x69); + div_ref = 0; + div5_0 = 1; + SOC_LOGE(TAG, "invalid pll frequency"); } - uint8_t i2c_bbpll_lref = (dchgp << I2C_BBPLL_OC_DCHGP_LSB) | (div_ref); - uint8_t i2c_bbpll_div_7_0 = div7_0; - uint8_t i2c_bbpll_dcur = (2 << I2C_BBPLL_OC_DLREF_SEL_LSB ) | (1 << I2C_BBPLL_OC_DHREF_SEL_LSB) | dcur; - REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_REF_DIV, i2c_bbpll_lref); - REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_DIV_7_0, i2c_bbpll_div_7_0); - REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DR1, dr1); - REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DR3, dr3); - REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_DCUR, i2c_bbpll_dcur); - REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_VCO_DBIAS, dbias); - REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DHREF_SEL, 2); - REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DLREF_SEL, 1); + REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_REF_DIV, div_ref); + REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DIV, div5_0); //I2C_BBPLL_OC_DIV_5_0 + REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DHREF_SEL, 3); // need update to 3 since s2 + REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DLREF_SEL, 1); s_cur_pll_freq = pll_freq; } @@ -282,19 +183,21 @@ void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq) */ static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz) { - // int per_conf = DPORT_CPUPERIOD_SEL_80; - if (cpu_freq_mhz == 80) { - /* nothing to do */ - } else if (cpu_freq_mhz == 160) { - // per_conf = DPORT_CPUPERIOD_SEL_160; + int div = 1; + if (RTC_PLL_FREQ_96M % cpu_freq_mhz == 0) { + div = RTC_PLL_FREQ_96M / cpu_freq_mhz; } else { SOC_LOGE(TAG, "invalid frequency"); abort(); } - // REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL, per_conf); // ESP32H2-TODO: IDF-3396 - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0); - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_PLL); - rtc_clk_apb_freq_update(80 * MHZ); + rtc_clk_cpu_freq_set(DPORT_SOC_CLK_SEL_PLL, div - 1); + if (cpu_freq_mhz > RTC_XTAL_FREQ_32M) { + rtc_clk_ahb_freq_set(2); + } else { + rtc_clk_ahb_freq_set(1); + } + + rtc_clk_apb_freq_update(rtc_clk_apb_freq_get()); ets_update_cpu_frequency(cpu_freq_mhz); } @@ -303,62 +206,32 @@ bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *ou uint32_t source_freq_mhz; rtc_cpu_freq_src_t source; uint32_t divider; - uint32_t real_freq_mhz; - uint32_t xtal_freq = (uint32_t) rtc_clk_xtal_freq_get(); - if (freq_mhz <= xtal_freq) { - divider = xtal_freq / freq_mhz; - real_freq_mhz = (xtal_freq + divider / 2) / divider; /* round */ - if (real_freq_mhz != freq_mhz) { - // no suitable divider - return false; - } - - source_freq_mhz = xtal_freq; - source = RTC_CPU_FREQ_SRC_XTAL; - } else if (freq_mhz == 80) { - real_freq_mhz = freq_mhz; + if (freq_mhz > xtal_freq) { source = RTC_CPU_FREQ_SRC_PLL; - source_freq_mhz = RTC_PLL_FREQ_480M; - divider = 6; - } else if (freq_mhz == 160) { - real_freq_mhz = freq_mhz; - source = RTC_CPU_FREQ_SRC_PLL; - source_freq_mhz = RTC_PLL_FREQ_480M; - divider = 3; + source_freq_mhz = RTC_PLL_FREQ_96M; + divider = RTC_PLL_FREQ_96M / freq_mhz; + rtc_clk_ahb_freq_set(2); } else { - // unsupported frequency - return false; + source = root_clk_get(); + source_freq_mhz = root_clk_slt(source); + divider = source_freq_mhz / freq_mhz; + rtc_clk_ahb_freq_set(1); } *out_config = (rtc_cpu_freq_config_t) { .source = source, .div = divider, .source_freq_mhz = source_freq_mhz, - .freq_mhz = real_freq_mhz + .freq_mhz = freq_mhz }; return true; } void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config) { - uint32_t soc_clk_sel = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL); - if (config->source == RTC_CPU_FREQ_SRC_XTAL) { - rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div); - if (soc_clk_sel == DPORT_SOC_CLK_SEL_PLL) { - rtc_clk_bbpll_disable(); - } - } else if (config->source == RTC_CPU_FREQ_SRC_PLL) { - if (soc_clk_sel != DPORT_SOC_CLK_SEL_PLL) { - rtc_clk_bbpll_enable(); - rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), config->source_freq_mhz); - } - rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz); - } else if (config->source == RTC_CPU_FREQ_SRC_8M) { - rtc_clk_cpu_freq_to_8m(); - if (soc_clk_sel == DPORT_SOC_CLK_SEL_PLL) { - rtc_clk_bbpll_disable(); - } - } + uint32_t src_freq_mhz = root_clk_slt(config->source); + uint32_t div = src_freq_mhz / (config->freq_mhz); + rtc_clk_cpu_freq_set(config->source, div); } void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config) @@ -371,29 +244,37 @@ void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config) switch (soc_clk_sel) { case DPORT_SOC_CLK_SEL_XTAL: { source = RTC_CPU_FREQ_SRC_XTAL; - div = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT) + 1; + div = REG_GET_FIELD(SYSTEM_CPUCLK_CONF_REG, SYSTEM_PRE_DIV_CNT) + 1; source_freq_mhz = (uint32_t) rtc_clk_xtal_freq_get(); freq_mhz = source_freq_mhz / div; + break; } - break; case DPORT_SOC_CLK_SEL_PLL: { - // ESP32H2-TODO: IDF-3396 - source = 0; - div = 0; - source_freq_mhz = 0; - freq_mhz = 0; + source = RTC_CPU_FREQ_SRC_PLL; + div = REG_GET_FIELD(SYSTEM_CPUCLK_CONF_REG, SYSTEM_PRE_DIV_CNT) + 1; + source_freq_mhz = RTC_PLL_FREQ_96M; + freq_mhz = source_freq_mhz / div; break; } - case DPORT_SOC_CLK_SEL_8M: + case DPORT_SOC_CLK_SEL_8M: { source = RTC_CPU_FREQ_SRC_8M; - source_freq_mhz = 8; - div = 1; - freq_mhz = source_freq_mhz; + source_freq_mhz = RTC_OSC_FREQ_RC8M; + div = REG_GET_FIELD(SYSTEM_CPUCLK_CONF_REG, SYSTEM_PRE_DIV_CNT) + 1; + freq_mhz = source_freq_mhz / div; break; - default: + } + case DPORT_SOC_CLK_SEL_XTAL_D2: { + source = RTC_CPU_FREQ_SRC_XTAL_D2; + div = REG_GET_FIELD(SYSTEM_CPUCLK_CONF_REG, SYSTEM_PRE_DIV_CNT) + 1; + source_freq_mhz = (uint32_t) rtc_clk_xtal_freq_get(); + freq_mhz = source_freq_mhz / div / 2; + break; + } + default: { SOC_LOGE(TAG, "unsupported frequency configuration"); abort(); } + } *out_config = (rtc_cpu_freq_config_t) { .source = source, .source_freq_mhz = source_freq_mhz, @@ -418,7 +299,6 @@ void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config) void rtc_clk_cpu_freq_set_xtal(void) { int freq_mhz = (int) rtc_clk_xtal_freq_get(); - rtc_clk_cpu_freq_to_xtal(freq_mhz, 1); rtc_clk_bbpll_disable(); } @@ -430,20 +310,17 @@ void rtc_clk_cpu_freq_to_xtal(int freq, int div) { ets_update_cpu_frequency(freq); /* Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0) first. */ - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0); - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, div - 1); + rtc_clk_cpu_freq_set(DPORT_SOC_CLK_SEL_XTAL, div); /* no need to adjust the REF_TICK */ /* switch clock source */ - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_XTAL); - rtc_clk_apb_freq_update(freq * MHZ); + rtc_clk_apb_freq_update(rtc_clk_apb_freq_get()); } -static void rtc_clk_cpu_freq_to_8m(void) +void rtc_clk_cpu_freq_to_8m(void) { - ets_update_cpu_frequency(8); - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0); - REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_8M); - rtc_clk_apb_freq_update(RTC_FAST_CLK_FREQ_8M); + ets_update_cpu_frequency(RTC_OSC_FREQ_RC8M); + root_clk_slt(DPORT_SOC_CLK_SEL_8M); + rtc_clk_apb_freq_update(rtc_clk_apb_freq_get()); } rtc_xtal_freq_t rtc_clk_xtal_freq_get(void) @@ -451,7 +328,7 @@ rtc_xtal_freq_t rtc_clk_xtal_freq_get(void) uint32_t xtal_freq_reg = READ_PERI_REG(RTC_XTAL_FREQ_REG); if (!clk_val_is_valid(xtal_freq_reg)) { SOC_LOGW(TAG, "invalid RTC_XTAL_FREQ_REG value: 0x%08x", xtal_freq_reg); - return RTC_XTAL_FREQ_40M; + return RTC_XTAL_FREQ_32M; } return reg_val_to_clk_val(xtal_freq_reg); } @@ -466,41 +343,121 @@ void rtc_clk_apb_freq_update(uint32_t apb_freq) WRITE_PERI_REG(RTC_APB_FREQ_REG, clk_val_to_reg_val(apb_freq >> 12)); } + uint32_t rtc_clk_apb_freq_get(void) { - uint32_t freq_hz = reg_val_to_clk_val(READ_PERI_REG(RTC_APB_FREQ_REG)) << 12; - // round to the nearest MHz - freq_hz += MHZ / 2; - uint32_t remainder = freq_hz % MHZ; - return freq_hz - remainder; + uint32_t apb_div = REG_GET_FIELD(SYSTEM_BUSCLK_CONF_REG, SYSTEM_APB_DIV_NUM) + 1; + return rtc_clk_ahb_freq_get() / apb_div; +} + +uint32_t rtc_clk_ahb_freq_get() +{ + rtc_cpu_freq_config_t cpu_config; + uint32_t ahb_div = REG_GET_FIELD(SYSTEM_BUSCLK_CONF_REG, SYSTEM_AHB_DIV_NUM) + 1; + rtc_clk_cpu_freq_get_config(&cpu_config) ; + return cpu_config.freq_mhz / ahb_div; +} + +uint32_t rtc_clk_ahb_freq_set(uint32_t div) +{ + REG_SET_FIELD(SYSTEM_BUSCLK_CONF_REG, SYSTEM_AHB_DIV_NUM, div - 1); + return rtc_clk_ahb_freq_get(); +} + +uint32_t rtc_clk_apb_freq_set(uint32_t div) +{ + REG_SET_FIELD(SYSTEM_BUSCLK_CONF_REG, SYSTEM_APB_DIV_NUM, div - 1); + return rtc_clk_apb_freq_get(); +} + +void rtc_clk_cpu_freq_set(uint32_t source, uint32_t div) +{ + if (root_clk_get() != source) { + root_clk_slt(source); + } + REG_SET_FIELD(SYSTEM_CPUCLK_CONF_REG, SYSTEM_CPU_DIV_NUM, div - 1); } void rtc_clk_divider_set(uint32_t div) { CLEAR_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV_VLD); - REG_SET_FIELD(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV, div); + REG_SET_FIELD(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV, div - 1); SET_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV_VLD); } void rtc_clk_8m_divider_set(uint32_t div) { CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD); - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL, div); + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL, div - 1); SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD); } void rtc_dig_clk8m_enable(void) { - SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN); esp_rom_delay_us(DELAY_RTC_CLK_SWITCH); } void rtc_dig_clk8m_disable(void) { - CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN); esp_rom_delay_us(DELAY_RTC_CLK_SWITCH); } +uint32_t read_spll_freq(void) +{ + return REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SPLL_FREQ); +} + +uint32_t read_xtal_freq(void) +{ + return REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_CLK_XTAL_FREQ); +} + +/* Select clock root source for esp32h2. return source clk freq_mhz + */ +uint32_t root_clk_slt(uint32_t source) +{ + uint32_t root_clk_freq_mhz; + switch (source) { + case RTC_CPU_FREQ_SRC_XTAL: + root_clk_freq_mhz = RTC_XTAL_FREQ_32M; + rtc_clk_bbpll_disable(); + break; + case RTC_CPU_FREQ_SRC_PLL: + // SPLL_ENABLE + root_clk_freq_mhz = RTC_PLL_FREQ_96M; + rtc_clk_bbpll_enable(); + rtc_clk_bbpll_configure(RTC_XTAL_FREQ_32M, root_clk_freq_mhz); + rtc_clk_bbpll_cali_stop(); + break; + case RTC_CPU_FREQ_SRC_8M: + root_clk_freq_mhz = RTC_OSC_FREQ_RC8M; + rtc_dig_clk8m_enable(); + rtc_clk_8m_divider_set(1); + rtc_clk_bbpll_disable(); + break; + case RTC_CPU_FREQ_SRC_XTAL_D2: + root_clk_freq_mhz = RTC_XTAL_FREQ_32M / 2; + rtc_clk_bbpll_disable(); + break; + default: + SOC_LOGE(TAG, "unsupported source clk configuration"); + root_clk_freq_mhz = RTC_XTAL_FREQ_32M; + rtc_clk_bbpll_disable(); + source = 0; + break; + } + REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, source); + return root_clk_freq_mhz; +} + +uint32_t root_clk_get() +{ + uint32_t src_slt = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL); + return src_slt; +} + /* Name used in libphy.a:phy_chip_v7.o * TODO: update the library to use rtc_clk_xtal_freq_get */ diff --git a/components/esp_hw_support/port/esp32h2/rtc_clk_common.h b/components/esp_hw_support/port/esp32h2/rtc_clk_common.h index c3e8a86e09..76e3fd3208 100644 --- a/components/esp_hw_support/port/esp32h2/rtc_clk_common.h +++ b/components/esp_hw_support/port/esp32h2/rtc_clk_common.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -22,6 +14,7 @@ #define DPORT_SOC_CLK_SEL_XTAL 0 #define DPORT_SOC_CLK_SEL_PLL 1 #define DPORT_SOC_CLK_SEL_8M 2 +#define DPORT_SOC_CLK_SEL_XTAL_D2 3 #define RTC_FAST_CLK_FREQ_8M 8500000 diff --git a/components/esp_hw_support/port/esp32h2/rtc_clk_init.c b/components/esp_hw_support/port/esp32h2/rtc_clk_init.c index 3cf971437a..38c2ac8e34 100644 --- a/components/esp_hw_support/port/esp32h2/rtc_clk_init.c +++ b/components/esp_hw_support/port/esp32h2/rtc_clk_init.c @@ -1,35 +1,34 @@ -// 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include #include #include +#include "sdkconfig.h" #include "esp32h2/rom/ets_sys.h" #include "esp32h2/rom/rtc.h" #include "esp32h2/rom/uart.h" +#include "esp32h2/rom/gpio.h" #include "soc/rtc.h" #include "soc/rtc_periph.h" +#include "soc/rtc_cntl_reg.h" #include "soc/efuse_periph.h" -#include "soc/apb_ctrl_reg.h" +#include "soc/syscon_reg.h" #include "hal/cpu_hal.h" #include "regi2c_ctrl.h" #include "soc_log.h" #include "sdkconfig.h" #include "rtc_clk_common.h" #include "esp_rom_uart.h" - +#include "soc/efuse_reg.h" +#include "soc/syscon_reg.h" +#include "soc/system_reg.h" +#include "rtc_clk_common.h" +#include "esp_rom_sys.h" static const char *TAG = "rtc_clk_init"; void rtc_clk_init(rtc_clk_config_t cfg) @@ -47,24 +46,25 @@ void rtc_clk_init(rtc_clk_config_t cfg) REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_SCK_DCAP, cfg.slow_clk_dcap); REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DFREQ, cfg.clk_8m_dfreq); + /* enable modem clk */ + REG_WRITE(SYSTEM_MODEM_CLK_EN_REG, UINT32_MAX); + /* Configure 150k clock division */ rtc_clk_divider_set(cfg.clk_rtc_clk_div); /* Configure 8M clock division */ rtc_clk_8m_divider_set(cfg.clk_8m_clk_div); - /* Enable the internal bus used to configure PLLs */ - SET_PERI_REG_BITS(ANA_CONFIG_REG, ANA_CONFIG_M, ANA_CONFIG_M, ANA_CONFIG_S); - CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, ANA_I2C_APLL_M | ANA_I2C_BBPLL_M); - rtc_xtal_freq_t xtal_freq = cfg.xtal_freq; esp_rom_uart_tx_wait_idle(0); rtc_clk_xtal_freq_update(xtal_freq); - rtc_clk_apb_freq_update(xtal_freq * MHZ); + rtc_clk_apb_freq_update(rtc_clk_apb_freq_get() * MHZ); /* Set CPU frequency */ rtc_clk_cpu_freq_get_config(&old_config); uint32_t freq_before = old_config.freq_mhz; + + root_clk_slt(cfg.root_clk_slt); bool res = rtc_clk_cpu_freq_mhz_to_config(cfg.cpu_freq_mhz, &new_config); if (!res) { SOC_LOGE(TAG, "invalid CPU frequency value"); @@ -80,8 +80,7 @@ void rtc_clk_init(rtc_clk_config_t cfg) rtc_clk_32k_enable(true); } if (cfg.fast_freq == RTC_FAST_FREQ_8M) { - bool need_8md256 = cfg.slow_freq == RTC_SLOW_FREQ_8MD256; - rtc_clk_8m_enable(true, need_8md256); + rtc_dig_clk8m_enable(); } rtc_clk_fast_freq_set(cfg.fast_freq); rtc_clk_slow_freq_set(cfg.slow_freq); diff --git a/components/esp_hw_support/port/esp32h2/rtc_init.c b/components/esp_hw_support/port/esp32h2/rtc_init.c index f40ba5ed3a..7b684d3d3d 100644 --- a/components/esp_hw_support/port/esp32h2/rtc_init.c +++ b/components/esp_hw_support/port/esp32h2/rtc_init.c @@ -1,39 +1,34 @@ -// 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "sdkconfig.h" #include "soc/soc.h" #include "soc/rtc.h" #include "soc/rtc_cntl_reg.h" +#include "soc/io_mux_reg.h" #include "soc/efuse_periph.h" #include "soc/gpio_reg.h" #include "soc/spi_mem_reg.h" #include "soc/extmem_reg.h" #include "soc/system_reg.h" +#include "soc/syscon_reg.h" #include "regi2c_ctrl.h" #include "soc_log.h" #include "esp_efuse.h" #include "esp_efuse_table.h" +#include "i2c_pmu.h" +#include "soc/clkrst_reg.h" -// ESP32H2-TODO: IDF-3396 +void pmu_ctl(void); +void dcdc_ctl(uint32_t mode); +void regulator_slt(regulator_config_t regula_cfg); void rtc_init(rtc_config_t cfg) { - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_DIG_REG, 0); - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_RTC_REG, 0); - CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PVTMON_PU); REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_PLL_BUF_WAIT, cfg.pll_wait); REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, cfg.ck8m_wait); @@ -52,8 +47,6 @@ void rtc_init(rtc_config_t cfg) REG_SET_FIELD(RTC_CNTL_TIMER6_REG, RTC_CNTL_DG_PERI_POWERUP_TIMER, rtc_init_cfg.dg_peri_powerup_cycles); REG_SET_FIELD(RTC_CNTL_TIMER6_REG, RTC_CNTL_DG_PERI_WAIT_TIMER, rtc_init_cfg.dg_peri_wait_cycles); - // set_rtc_dig_dbias(); // ESP32H2-TODO: IDF-3396 - if (cfg.clkctl_init) { //clear CMMU clock force on CLEAR_PERI_REG_MASK(EXTMEM_CACHE_MMU_POWER_CTRL_REG, EXTMEM_CACHE_MMU_MEM_FORCE_ON); @@ -77,10 +70,6 @@ void rtc_init(rtc_config_t cfg) CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PU); SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PD); - //open sar_i2c protect function to avoid sar_i2c reset when rtc_ldo is low. - CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_I2C_RESET_POR_FORCE_PD); - - //cancel bbpll force pu if setting no force power up if (!cfg.bbpll_fpu) { CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BBPLL_FORCE_PU); CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BBPLL_I2C_FORCE_PU); @@ -94,14 +83,8 @@ void rtc_init(rtc_config_t cfg) CLEAR_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU); CLEAR_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_DBOOST_FORCE_PU); - if (cfg.rtc_dboost_fpd) { - SET_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_DBOOST_FORCE_PD); - } else { - CLEAR_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_DBOOST_FORCE_PD); - } - - //clear i2c_reset_protect pd force, need tested in low temperature. - //CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG,RTC_CNTL_I2C_RESET_POR_FORCE_PD); + // clear i2c_reset_protect pd force, need tested in low temperature. + CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG,RTC_CNTL_I2C_RESET_POR_FORCE_PD); /* If this mask is enabled, all soc memories cannot enter power down mode */ /* We should control soc memory power down mode from RTC, so we will not touch this register any more */ @@ -112,18 +95,25 @@ void rtc_init(rtc_config_t cfg) rtc_sleep_pu_config_t pu_cfg = RTC_SLEEP_PU_CONFIG_ALL(0); rtc_sleep_pu(pu_cfg); - CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_WRAP_FORCE_PU); - CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PU); - CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_FORCE_PU); + //cancel digital PADS force pu CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_CPU_TOP_FORCE_PU); + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PU); + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_FASTMEM_FORCE_LPU); // CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_PERI_FORCE_PU); + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_FORCE_PU); + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_WRAP_FORCE_PU); + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_MEM_FORCE_PU); // + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_LSLP_MEM_FORCE_PU); // + //cancel digital PADS force no iso CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_WRAP_FORCE_NOISO); CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_NOISO); - CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_BT_FORCE_NOISO); CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_CPU_TOP_FORCE_NOISO); CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PERI_FORCE_NOISO); - //cancel digital PADS force no iso + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_BT_FORCE_NOISO); + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_NOISO); // + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_MEM_FORCE_NOISO); // + if (cfg.cpu_waiti_clk_gate) { CLEAR_PERI_REG_MASK(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPU_WAIT_MODE_FORCE_ON); } else { @@ -133,10 +123,49 @@ void rtc_init(rtc_config_t cfg) CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD); CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_NOISO); } + REG_WRITE(RTC_CNTL_INT_ENA_REG, 0); REG_WRITE(RTC_CNTL_INT_CLR_REG, UINT32_MAX); + if (cfg.pmu_ctl) { + /* pmu init*/ + pmu_ctl(); + } + /* config dcdc frequency */ + REG_SET_FIELD(RTC_CNTL_DCDC_CTRL0_REG, RTC_CNTL_FSW_DCDC, RTC_CNTL_DCDC_FREQ_DEFAULT); } +void pmu_ctl(void) +{ + pmu_config_t pmu_cfg = PMU_CONFIG_DEFAULT(); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_EN_CONT_CAL, pmu_cfg.or_en_cont_cal); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_ENX_RTC_DREG, pmu_cfg.enx_rtc_dreg); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_ENX_DIG_DREG, pmu_cfg.enx_dig_dreg); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_RTC_DREG, pmu_cfg.en_i2c_rtc_dreg); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_DIG_DREG, pmu_cfg.en_i2c_dig_dreg); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_RTC_DREG_SLP, pmu_cfg.en_i2c_rtc_dreg_slp); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_EN_I2C_DIG_DREG_SLP, pmu_cfg.en_i2c_dig_dreg_slp); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_XPD_RTC_SLAVE_3P3, pmu_cfg.or_xpd_rtc_slave_3p3); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_XPD_RTC_REG, pmu_cfg.or_xpd_rtc_reg); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_XPD_DIG_REG, pmu_cfg.or_xpd_dig_reg); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_PD_RTC_REG_SLP, pmu_cfg.or_pd_rtc_reg_slp); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_PD_DIG_REG_SLP, pmu_cfg.or_pd_dig_reg_slp); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_XPD_DCDC, pmu_cfg.or_xpd_dcdc); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_DISALBE_DEEP_SLEEP_DCDC, pmu_cfg.or_disalbe_deep_sleep_dcdc); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_DISALBE_LIGHT_SLEEP_DCDC, pmu_cfg.or_disalbe_light_sleep_dcdc); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_ENALBE_TRX_MODE_DCDC, pmu_cfg.or_enalbe_trx_mode_dcdc); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_ENX_REG_DCDC, pmu_cfg.or_enx_reg_dcdc); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_UNLOCK_DCDC, pmu_cfg.or_unlock_dcdc); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_FORCE_LOCK_DCDC, pmu_cfg.or_force_lock_dcdc); + // REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_ENB_SLOW_CLK, pmu_cfg.or_enb_slow_clk); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_XPD_TRX, pmu_cfg.or_xpd_trx); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_EN_RESET_CHIP, pmu_cfg.or_en_reset_chip); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OR_FORCE_XPD_REG_SLAVE, pmu_cfg.or_force_xpd_reg_slave); +} + +void dslp_osc_pd(void){ + REG_SET_FIELD(RTC_CNTL_RC32K_CTRL_REG,RTC_CNTL_RC32K_XPD, 0); + REG_SET_FIELD(RTC_CNTL_PLL8M_REG, RTC_CNTL_XPD_PLL8M, 0); +} rtc_vddsdio_config_t rtc_vddsdio_get_config(void) { rtc_vddsdio_config_t result; @@ -174,3 +203,41 @@ void rtc_vddsdio_set_config(rtc_vddsdio_config_t config) val |= RTC_CNTL_SDIO_PD_EN; REG_WRITE(RTC_CNTL_SDIO_CONF_REG, val); } + +void dig_gpio_setpd(uint32_t gpio_no, bool pd) +{ + SET_PERI_REG_BITS(PERIPHS_IO_MUX_XTAL_32K_P_U + 4 * gpio_no, 0x1, pd, FUN_PD_S); +} + +void dig_gpio_setpu(uint32_t gpio_no, bool pu) +{ + SET_PERI_REG_BITS(PERIPHS_IO_MUX_XTAL_32K_P_U + 4 * gpio_no, 0x1, pu, FUN_PU_S); +} + +void dig_gpio_in_en(uint32_t gpio_no, bool enable) +{ + SET_PERI_REG_BITS(PERIPHS_IO_MUX_XTAL_32K_P_U + 4 * gpio_no, 0x1, enable, FUN_IE_S); +} + +void dig_gpio_out_en(uint32_t gpio_no, bool enable) +{ + if (enable) + SET_PERI_REG_MASK(GPIO_ENABLE_W1TS_REG, 1 << gpio_no); + else + SET_PERI_REG_MASK(GPIO_ENABLE_W1TC_REG, 1 << gpio_no); +} + +void dig_gpio_mcusel(uint32_t gpio_no, uint32_t mcu_sel) +{ + SET_PERI_REG_BITS(PERIPHS_IO_MUX_XTAL_32K_P_U + 4 * gpio_no, MCU_SEL, mcu_sel, MCU_SEL_S); +} + + +void rtc_gpio_hangup(uint32_t gpio_no) +{ + dig_gpio_setpd(gpio_no, 0); + dig_gpio_setpu(gpio_no, 0); + dig_gpio_out_en(gpio_no, 0); + dig_gpio_in_en(gpio_no, 0); + dig_gpio_mcusel(gpio_no, 1); +} diff --git a/components/esp_hw_support/port/esp32h2/rtc_pm.c b/components/esp_hw_support/port/esp32h2/rtc_pm.c index 58f2719418..3b6c44967a 100644 --- a/components/esp_hw_support/port/esp32h2/rtc_pm.c +++ b/components/esp_hw_support/port/esp32h2/rtc_pm.c @@ -1,22 +1,14 @@ -// 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include #include "soc/rtc.h" #include "soc/rtc_cntl_reg.h" -#include "soc/apb_ctrl_reg.h" +#include "soc/syscon_reg.h" typedef enum { PM_LIGHT_SLEEP = BIT(2), /*!< WiFi PD, memory in light sleep */ @@ -52,7 +44,7 @@ pm_sw_reject_t pm_set_sleep_mode(pm_sleep_mode_t sleep_mode, void(*pmac_save_par switch (sleep_mode) { case PM_LIGHT_SLEEP: - cfg.wifi_pd_en = 1; + // cfg.wifi_pd_en = 1; // ESP32-H2 TO-DO: IDF-3693 cfg.dig_dbias_wak = 4; cfg.dig_dbias_slp = 0; cfg.rtc_dbias_wak = 0; diff --git a/components/esp_hw_support/port/esp32h2/rtc_sleep.c b/components/esp_hw_support/port/esp32h2/rtc_sleep.c index cb61062412..97d8ddae6a 100644 --- a/components/esp_hw_support/port/esp32h2/rtc_sleep.c +++ b/components/esp_hw_support/port/esp32h2/rtc_sleep.c @@ -1,47 +1,42 @@ -// 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include #include "soc/soc.h" #include "soc/rtc.h" #include "soc/rtc_cntl_reg.h" -#include "soc/apb_ctrl_reg.h" -#include "soc/rtc.h" +#include "soc/syscon_reg.h" #include "soc/i2s_reg.h" #include "soc/bb_reg.h" #include "soc/nrx_reg.h" #include "soc/fe_reg.h" #include "soc/timer_group_reg.h" #include "soc/system_reg.h" -#include "soc/rtc.h" #include "esp32h2/rom/ets_sys.h" #include "esp32h2/rom/rtc.h" #include "regi2c_ctrl.h" #include "esp_efuse.h" +#include "i2c_pmu.h" +#include "soc_log.h" +#include "esp_rom_uart.h" /** * Configure whether certain peripherals are powered down in deep sleep * @param cfg power down flags as rtc_sleep_pu_config_t structure */ +static const char *TAG = "rtc_sleep"; + void rtc_sleep_pu(rtc_sleep_pu_config_t cfg) { REG_SET_FIELD(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_LSLP_MEM_FORCE_PU, cfg.dig_fpu); REG_SET_FIELD(RTC_CNTL_PWC_REG, RTC_CNTL_FASTMEM_FORCE_LPU, cfg.rtc_fpu); - REG_SET_FIELD(APB_CTRL_FRONT_END_MEM_PD_REG, APB_CTRL_DC_MEM_FORCE_PU, cfg.fe_fpu); - REG_SET_FIELD(APB_CTRL_FRONT_END_MEM_PD_REG, APB_CTRL_PBUS_MEM_FORCE_PU, cfg.fe_fpu); - REG_SET_FIELD(APB_CTRL_FRONT_END_MEM_PD_REG, APB_CTRL_AGC_MEM_FORCE_PU, cfg.fe_fpu); + REG_SET_FIELD(SYSCON_FRONT_END_MEM_PD_REG, SYSCON_DC_MEM_FORCE_PU, cfg.fe_fpu); + REG_SET_FIELD(SYSCON_FRONT_END_MEM_PD_REG, SYSCON_PBUS_MEM_FORCE_PU, cfg.fe_fpu); + REG_SET_FIELD(SYSCON_FRONT_END_MEM_PD_REG, SYSCON_AGC_MEM_FORCE_PU, cfg.fe_fpu); REG_SET_FIELD(BBPD_CTRL, BB_FFT_FORCE_PU, cfg.bb_fpu); REG_SET_FIELD(BBPD_CTRL, BB_DC_EST_FORCE_PU, cfg.bb_fpu); REG_SET_FIELD(NRXPD_CTRL, NRX_RX_ROT_FORCE_PU, cfg.nrx_fpu); @@ -50,28 +45,122 @@ void rtc_sleep_pu(rtc_sleep_pu_config_t cfg) REG_SET_FIELD(FE_GEN_CTRL, FE_IQ_EST_FORCE_PU, cfg.fe_fpu); REG_SET_FIELD(FE2_TX_INTERP_CTRL, FE2_TX_INF_FORCE_PU, cfg.fe_fpu); if (cfg.sram_fpu) { - REG_SET_FIELD(APB_CTRL_MEM_POWER_UP_REG, APB_CTRL_SRAM_POWER_UP, APB_CTRL_SRAM_POWER_UP); + REG_SET_FIELD(SYSCON_MEM_POWER_UP_REG, SYSCON_SRAM_POWER_UP, SYSCON_SRAM_POWER_UP); } else { - REG_SET_FIELD(APB_CTRL_MEM_POWER_UP_REG, APB_CTRL_SRAM_POWER_UP, 0); + REG_SET_FIELD(SYSCON_MEM_POWER_UP_REG, SYSCON_SRAM_POWER_UP, 0); } if (cfg.rom_ram_fpu) { - REG_SET_FIELD(APB_CTRL_MEM_POWER_UP_REG, APB_CTRL_ROM_POWER_UP, APB_CTRL_ROM_POWER_UP); + REG_SET_FIELD(SYSCON_MEM_POWER_UP_REG, SYSCON_ROM_POWER_UP, SYSCON_ROM_POWER_UP); } else { - REG_SET_FIELD(APB_CTRL_MEM_POWER_UP_REG, APB_CTRL_ROM_POWER_UP, 0); + REG_SET_FIELD(SYSCON_MEM_POWER_UP_REG, SYSCON_ROM_POWER_UP, 0); } } +void dcdc_ctl(uint32_t mode) +{ + REG_SET_FIELD(RTC_CNTL_DCDC_CTRL1_REG, RTC_CNTL_DCDC_MODE_IDLE, RTC_CNTL_DCDC_TRX_MODE); + REG_SET_FIELD(RTC_CNTL_DCDC_CTRL1_REG, RTC_CNTL_DCDC_MODE_MONITOR, RTC_CNTL_DCDC_TRX_MODE); + if ((mode & 0x10) == 0x10) { + REG_SET_FIELD(RTC_CNTL_DCDC_CTRL1_REG, RTC_CNTL_DCDC_MODE_SLP, mode); + } else if (mode == 0) { + REG_SET_FIELD(RTC_CNTL_DCDC_CTRL1_REG, RTC_CNTL_DCDC_MODE_SLP, RTC_CNTL_DCDC_TRX_MODE); + } else if (mode == 1) { + REG_SET_FIELD(RTC_CNTL_DCDC_CTRL1_REG, RTC_CNTL_DCDC_MODE_SLP, RTC_CNTL_DCDC_LSLP_MODE); + } else if (mode == 2) { + REG_SET_FIELD(RTC_CNTL_DCDC_CTRL1_REG, RTC_CNTL_DCDC_MODE_SLP, RTC_CNTL_DCDC_DSLP_MODE); + } else { + SOC_LOGE(TAG, "invalid dcdc mode!\n"); + } +} + +void regulator_set(regulator_cfg_t cfg) +{ + // DIG REGULATOR0 + if (cfg.dig_regul0_en) { + REG_SET_FIELD(RTC_CNTL_DIGULATOR_REG, RTC_CNTL_DG_REGULATOR_FORCE_PU, 0); + REG_SET_FIELD(RTC_CNTL_DIGULATOR_REG, RTC_CNTL_DG_REGULATOR_FORCE_PD, 0); + } else { + REG_SET_FIELD(RTC_CNTL_DIGULATOR_REG, RTC_CNTL_DG_REGULATOR_FORCE_PU, 0); + REG_SET_FIELD(RTC_CNTL_DIGULATOR_REG, RTC_CNTL_DG_REGULATOR_FORCE_PD, 1); + } + // DIG REGULATOR1 + if (cfg.dig_regul1_en) { + REG_SET_FIELD(RTC_CNTL_DIGULATOR_REG, RTC_CNTL_DG_REGULATOR_SLP_FORCE_PU, 0); + REG_SET_FIELD(RTC_CNTL_DIGULATOR_REG, RTC_CNTL_DG_REGULATOR_SLP_FORCE_PD, 0); + } else { + REG_SET_FIELD(RTC_CNTL_DIGULATOR_REG, RTC_CNTL_DG_REGULATOR_SLP_FORCE_PU, 0); + REG_SET_FIELD(RTC_CNTL_DIGULATOR_REG, RTC_CNTL_DG_REGULATOR_SLP_FORCE_PD, 1); + } + // RTC REGULATOR0 + if (cfg.rtc_regul0_en) { + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU, 0); + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PD, 0); + } else { + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU, 0); + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PD, 1); + } +} + +void regulator_slt(regulator_config_t regula_cfg) +{ + // dig regulator + if (regula_cfg.dig_source == 1) { + REG_SET_FIELD(RTC_CNTL_DIGULATOR1_DBIAS_REG, RTC_CNTL_DIG_REGULATOR1_DBIAS_SLP, regula_cfg.dig_slp_dbias); + REG_SET_FIELD(RTC_CNTL_DIGULATOR1_DBIAS_REG, RTC_CNTL_DIG_REGULATOR1_DBIAS_ACTIVE, regula_cfg.dig_active_dbias); + } else { + REG_SET_FIELD(RTC_CNTL_DIGULATOR0_DBIAS_REG, RTC_CNTL_DIG_REGULATOR0_DBIAS_SLP, regula_cfg.dig_slp_dbias); + REG_SET_FIELD(RTC_CNTL_DIGULATOR0_DBIAS_REG, RTC_CNTL_DIG_REGULATOR0_DBIAS_ACTIVE, regula_cfg.dig_active_dbias); + } + // rtc regulator + if (regula_cfg.rtc_source == 1) { + REG_SET_FIELD(RTC_CNTL_RTCULATOR1_DBIAS_REG, RTC_CNTL_REGULATOR1_DBIAS_SLP, regula_cfg.rtc_slp_dbias); + REG_SET_FIELD(RTC_CNTL_RTCULATOR1_DBIAS_REG, RTC_CNTL_REGULATOR1_DBIAS_ACTIVE, regula_cfg.rtc_active_dbias); + } else { + REG_SET_FIELD(RTC_CNTL_RTCULATOR0_DBIAS_REG, RTC_CNTL_REGULATOR0_DBIAS_SLP, regula_cfg.rtc_slp_dbias); + REG_SET_FIELD(RTC_CNTL_RTCULATOR0_DBIAS_REG, RTC_CNTL_REGULATOR0_DBIAS_ACTIVE, regula_cfg.rtc_active_dbias); + } +} + +void dbias_switch_set(dbias_swt_cfg_t cfg) +{ + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_SWITCH_IDLE, cfg.swt_idle); + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_SWITCH_MONITOR, cfg.swt_monitor); + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_SWITCH_SLP, cfg.swt_slp); +} + +void left_up_trx_fpu(bool fpu) +{ + if (fpu) { + REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_FORCE_DISABLE_BIAS_SLEEP, 0); + REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_FORCE_XPD_BIAS_BUF, 0); + REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_FORCE_XPD_IPH, 0); + SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_XPD_TRX_FORCE_PU); + } else { + CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_XPD_TRX_FORCE_PU); + } +} + +void rtc_sleep_pmu_init(void) +{ + dcdc_ctl(DCDC_SLP_DSLP_MODE); + dbias_swt_cfg_t swt_cfg = DBIAS_SWITCH_CONFIG_DEFAULT(); + dbias_switch_set(swt_cfg); + regulator_config_t regula0_cfg = REGULATOR0_CONFIG_DEFAULT(); + regulator_slt(regula0_cfg); + regulator_config_t regula1_cfg = REGULATOR1_CONFIG_DEFAULT(); + regulator_slt(regula1_cfg); + regulator_cfg_t rg_set = REGULATOR_SET_DEFAULT(); + regulator_set(rg_set); + left_up_trx_fpu(0); +} + + void rtc_sleep_init(rtc_sleep_config_t cfg) { if (cfg.lslp_mem_inf_fpu) { rtc_sleep_pu_config_t pu_cfg = RTC_SLEEP_PU_CONFIG_ALL(1); rtc_sleep_pu(pu_cfg); } - if (cfg.wifi_pd_en) { - SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_PD_EN); - } else { - CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_PD_EN); - } if (cfg.bt_pd_en) { SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_PD_EN); } else { @@ -87,43 +176,43 @@ void rtc_sleep_init(rtc_sleep_config_t cfg) } else { CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_PERI_PD_EN); } + if (cfg.dig_ret_pd_en) { + SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_WRAP_RET_PD_EN); + } else { + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_WRAP_RET_PD_EN); + } - REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_MONITOR, RTC_CNTL_DBG_ATTEN_MONITOR_DEFAULT); REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_BIAS_SLEEP_MONITOR, RTC_CNTL_BIASSLP_MONITOR_DEFAULT); REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_BIAS_SLEEP_DEEP_SLP, RTC_CNTL_BIASSLP_SLEEP_DEFAULT); REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_PD_CUR_MONITOR, RTC_CNTL_PD_CUR_MONITOR_DEFAULT); REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_PD_CUR_DEEP_SLP, RTC_CNTL_PD_CUR_SLEEP_DEFAULT); + // ESP32-H2 TO-DO: IDF-3693 if (cfg.deep_slp) { - REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_FORCE_XPD_CK, 0); - CLEAR_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU); - unsigned atten_deep_sleep = RTC_CNTL_DBG_ATTEN_DEEPSLEEP_DEFAULT; - - REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_DEEP_SLP, atten_deep_sleep); + // REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_FORCE_XPD_CK, 0); + // CLEAR_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU); SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_WRAP_PD_EN); CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_CKGEN_I2C_PU | RTC_CNTL_PLL_I2C_PU | RTC_CNTL_RFRX_PBUS_PU | RTC_CNTL_TXRF_I2C_PU); CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PU); } else { - SET_PERI_REG_MASK(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DG_VDD_DRV_B_SLP_EN); - REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DG_VDD_DRV_B_SLP, RTC_CNTL_DG_VDD_DRV_B_SLP_DEFAULT); - SET_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU); + SET_PERI_REG_MASK(RTC_CNTL_DIGULATOR_REG, RTC_CNTL_DG_VDD_DRV_B_SLP_EN); + REG_SET_FIELD(RTC_CNTL_DIGULATOR_REG, RTC_CNTL_DG_VDD_DRV_B_SLP, RTC_CNTL_DG_VDD_DRV_B_SLP_DEFAULT); + // SET_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU); CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_WRAP_PD_EN); - REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_DEEP_SLP, RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_DEFAULT); } /* enable VDDSDIO control by state machine */ REG_CLR_BIT(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_FORCE); REG_SET_FIELD(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_PD_EN, cfg.vddsdio_pd_en); - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG_SLEEP, cfg.rtc_dbias_slp); - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG_SLEEP, cfg.dig_dbias_slp); - REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_DEEP_SLP_REJECT_EN, cfg.deep_slp_reject); REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_LIGHT_SLP_REJECT_EN, cfg.light_slp_reject); /* gating XTAL clock */ REG_CLR_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_XTAL_GLOBAL_FORCE_NOGATING); + esp_rom_uart_tx_wait_idle(0); + } void rtc_sleep_low_init(uint32_t slowclk_period) @@ -149,7 +238,6 @@ uint32_t rtc_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp /* Start entry into sleep mode */ SET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_SLEEP_EN); - while (GET_PERI_REG_MASK(RTC_CNTL_INT_RAW_REG, RTC_CNTL_SLP_REJECT_INT_RAW | RTC_CNTL_SLP_WAKEUP_INT_RAW) == 0) { ; @@ -180,56 +268,56 @@ uint32_t rtc_deep_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt) const unsigned CRC_LEN = 0x7ff; asm volatile( - /* Start CRC calculation */ - "sw %1, 0(%0)\n" // set RTC_MEM_CRC_ADDR & RTC_MEM_CRC_LEN - "or t0, %1, %2\n" - "sw t0, 0(%0)\n" // set RTC_MEM_CRC_START + /* Start CRC calculation */ + "sw %1, 0(%0)\n" // set RTC_MEM_CRC_ADDR & RTC_MEM_CRC_LEN + "or t0, %1, %2\n" + "sw t0, 0(%0)\n" // set RTC_MEM_CRC_START - /* Wait for the CRC calculation to finish */ - ".Lwaitcrc:\n" - "fence\n" - "lw t0, 0(%0)\n" - "li t1, "STR(SYSTEM_RTC_MEM_CRC_FINISH)"\n" - "and t0, t0, t1\n" - "beqz t0, .Lwaitcrc\n" - "not %2, %2\n" // %2 -> ~DPORT_RTC_MEM_CRC_START - "and t0, t0, %2\n" - "sw t0, 0(%0)\n" // clear RTC_MEM_CRC_START - "fence\n" - "not %2, %2\n" // %2 -> DPORT_RTC_MEM_CRC_START, probably unnecessary but gcc assumes inputs unchanged + /* Wait for the CRC calculation to finish */ + ".Lwaitcrc:\n" + "fence\n" + "lw t0, 0(%0)\n" + "li t1, "STR(SYSTEM_RTC_MEM_CRC_FINISH)"\n" + "and t0, t0, t1\n" + "beqz t0, .Lwaitcrc\n" + "not %2, %2\n" // %2 -> ~DPORT_RTC_MEM_CRC_START + "and t0, t0, %2\n" + "sw t0, 0(%0)\n" // clear RTC_MEM_CRC_START + "fence\n" + "not %2, %2\n" // %2 -> DPORT_RTC_MEM_CRC_START, probably unnecessary but gcc assumes inputs unchanged - /* Store the calculated value in RTC_MEM_CRC_REG */ - "lw t0, 0(%3)\n" - "sw t0, 0(%4)\n" - "fence\n" + /* Store the calculated value in RTC_MEM_CRC_REG */ + "lw t0, 0(%3)\n" + "sw t0, 0(%4)\n" + "fence\n" - /* Set register bit to go into deep sleep */ - "lw t0, 0(%5)\n" - "or t0, t0, %6\n" - "sw t0, 0(%5)\n" - "fence\n" + /* Set register bit to go into deep sleep */ + "lw t0, 0(%5)\n" + "or t0, t0, %6\n" + "sw t0, 0(%5)\n" + "fence\n" - /* Wait for sleep reject interrupt (never finishes if successful) */ - ".Lwaitsleep:" - "fence\n" - "lw t0, 0(%7)\n" - "and t0, t0, %8\n" - "beqz t0, .Lwaitsleep\n" + /* Wait for sleep reject interrupt (never finishes if successful) */ + ".Lwaitsleep:" + "fence\n" + "lw t0, 0(%7)\n" + "and t0, t0, %8\n" + "beqz t0, .Lwaitsleep\n" - : - : - "r" (SYSTEM_RTC_FASTMEM_CONFIG_REG), // %0 - "r" ( (CRC_START_ADDR << SYSTEM_RTC_MEM_CRC_START_S) - | (CRC_LEN << SYSTEM_RTC_MEM_CRC_LEN_S)), // %1 - "r" (SYSTEM_RTC_MEM_CRC_START), // %2 - "r" (SYSTEM_RTC_FASTMEM_CRC_REG), // %3 - "r" (RTC_MEMORY_CRC_REG), // %4 - "r" (RTC_CNTL_STATE0_REG), // %5 - "r" (RTC_CNTL_SLEEP_EN), // %6 - "r" (RTC_CNTL_INT_RAW_REG), // %7 - "r" (RTC_CNTL_SLP_REJECT_INT_RAW | RTC_CNTL_SLP_WAKEUP_INT_RAW) // %8 - : "t0", "t1" // working registers - ); + : + : + "r" (SYSTEM_RTC_FASTMEM_CONFIG_REG), // %0 + "r" ( (CRC_START_ADDR << SYSTEM_RTC_MEM_CRC_START_S) + | (CRC_LEN << SYSTEM_RTC_MEM_CRC_LEN_S)), // %1 + "r" (SYSTEM_RTC_MEM_CRC_START), // %2 + "r" (SYSTEM_RTC_FASTMEM_CRC_REG), // %3 + "r" (RTC_MEMORY_CRC_REG), // %4 + "r" (RTC_CNTL_STATE0_REG), // %5 + "r" (RTC_CNTL_SLEEP_EN), // %6 + "r" (RTC_CNTL_INT_RAW_REG), // %7 + "r" (RTC_CNTL_SLP_REJECT_INT_RAW | RTC_CNTL_SLP_WAKEUP_INT_RAW) // %8 + : "t0", "t1" // working registers + ); return rtc_sleep_finish(0); } diff --git a/components/esp_hw_support/port/esp32h2/rtc_time.c b/components/esp_hw_support/port/esp32h2/rtc_time.c index 22ffb959c7..3efad7ce3d 100644 --- a/components/esp_hw_support/port/esp32h2/rtc_time.c +++ b/components/esp_hw_support/port/esp32h2/rtc_time.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "esp32h2/rom/ets_sys.h" @@ -48,18 +40,19 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) rtc_slow_freq_t slow_freq = rtc_clk_slow_freq_get(); if (slow_freq == RTC_SLOW_FREQ_32K_XTAL) { cal_clk = RTC_CAL_32K_XTAL; - } else if (slow_freq == RTC_SLOW_FREQ_8MD256) { - cal_clk = RTC_CAL_8MD256; + } else if (slow_freq == RTC_SLOW_FREQ_RC32K) { + cal_clk = RTC_CAL_RC32K; } } /* Enable requested clock (150k clock is always on) */ - int dig_32k_xtal_state = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN); + bool dig_32k_xtal_state = REG_GET_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN); if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_state) { REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, 1); - } - if (cal_clk == RTC_CAL_8MD256) { - // SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN); // ESP32H2-TODO: IDF-3396 + } + bool dig_rc32k_state = REG_GET_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_RC32K_EN); + if (cal_clk == RTC_CAL_RC32K && !dig_rc32k_state) { + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_RC32K_EN, 1); } /* Prepare calibration */ REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cal_clk); @@ -80,9 +73,9 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) if (cal_clk == RTC_CAL_32K_XTAL) { REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_X32K_CAL_TIMEOUT_THRES(slowclk_cycles)); expected_freq = RTC_SLOW_CLK_FREQ_32K; - } else if (cal_clk == RTC_CAL_8MD256) { - REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_8MD256_CAL_TIMEOUT_THRES(slowclk_cycles)); - expected_freq = RTC_SLOW_CLK_FREQ_8MD256; + } else if (cal_clk == RTC_CAL_RC32K) { + REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_RC32K_CAL_TIMEOUT_THRES(slowclk_cycles)); + expected_freq = RTC_SLOW_CLK_FREQ_RC32; } else { REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_150K_CAL_TIMEOUT_THRES(slowclk_cycles)); expected_freq = RTC_SLOW_CLK_FREQ_150K; @@ -93,7 +86,7 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) SET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START); /* Wait for calibration to finish up to another us_time_estimate */ - esp_rom_delay_us(us_time_estimate); + esp_rom_delay_us(us_time_estimate * 3); uint32_t cal_val; while (true) { if (GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_RDY)) { @@ -106,12 +99,8 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) } } CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START); - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, dig_32k_xtal_state); - - if (cal_clk == RTC_CAL_8MD256) { - // CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN); // ESP32H2-TODO: IDF-3396 - } + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_RC32K_EN, dig_rc32k_state); return cal_val; } diff --git a/components/esp_hw_support/port/esp32s2/async_memcpy_impl_cp_dma.c b/components/esp_hw_support/port/esp32s2/async_memcpy_impl_cp_dma.c index b468c5efb4..8d268a20b6 100644 --- a/components/esp_hw_support/port/esp32s2/async_memcpy_impl_cp_dma.c +++ b/components/esp_hw_support/port/esp32s2/async_memcpy_impl_cp_dma.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "freertos/FreeRTOS.h" #include "soc/periph_defs.h" diff --git a/components/esp_hw_support/port/esp32s2/chip_info.c b/components/esp_hw_support/port/esp32s2/chip_info.c index 05f26b450c..d03c16cb6d 100644 --- a/components/esp_hw_support/port/esp32s2/chip_info.c +++ b/components/esp_hw_support/port/esp32s2/chip_info.c @@ -1,16 +1,8 @@ -// Copyright 2013-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. +/* + * SPDX-FileCopyrightText: 2013-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "esp_chip_info.h" diff --git a/components/esp_hw_support/port/esp32s2/dport_access.c b/components/esp_hw_support/port/esp32s2/dport_access.c index a1be9ccd5a..ab24c510a5 100644 --- a/components/esp_hw_support/port/esp32s2/dport_access.c +++ b/components/esp_hw_support/port/esp32s2/dport_access.c @@ -1,16 +1,8 @@ -// Copyright 2010-2017 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: 2010-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include diff --git a/components/esp_hw_support/port/esp32s2/esp_crypto_lock.c b/components/esp_hw_support/port/esp32s2/esp_crypto_lock.c index 8bd5ccf6cf..94269d4776 100644 --- a/components/esp_hw_support/port/esp32s2/esp_crypto_lock.c +++ b/components/esp_hw_support/port/esp32s2/esp_crypto_lock.c @@ -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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include diff --git a/components/esp_hw_support/port/esp32s2/esp_ds.c b/components/esp_hw_support/port/esp32s2/esp_ds.c index 635e83e2a2..e592ee7a46 100644 --- a/components/esp_hw_support/port/esp32s2/esp_ds.c +++ b/components/esp_hw_support/port/esp32s2/esp_ds.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include diff --git a/components/esp_hw_support/port/esp32s2/esp_hmac.c b/components/esp_hw_support/port/esp32s2/esp_hmac.c index 93f54a2a5c..328ccbd90d 100644 --- a/components/esp_hw_support/port/esp32s2/esp_hmac.c +++ b/components/esp_hw_support/port/esp32s2/esp_hmac.c @@ -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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "esp32s2/rom/hmac.h" @@ -55,7 +47,8 @@ esp_err_t esp_hmac_calculate(hmac_key_id_t key_id, esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token) { - esp_err_t err; + int ets_status; + esp_err_t err = ESP_OK; if ((!token) || (key_id >= HMAC_KEY_MAX)) return ESP_ERR_INVALID_ARG; @@ -77,10 +70,10 @@ esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token) REG_WRITE(DPORT_JTAG_CTRL_0_REG + i, __builtin_bswap32(key_word)); } - err = ets_hmac_calculate_downstream(convert_key_type(key_id), ETS_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG); - if (err != ETS_OK) { - ESP_LOGE(TAG, "HMAC downstream JTAG enable mode setting failed."); - return ESP_FAIL; + ets_status = ets_hmac_calculate_downstream(convert_key_type(key_id), ETS_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG); + if (ets_status != ETS_OK) { + err = ESP_FAIL; + ESP_LOGE(TAG, "HMAC downstream JTAG enable mode setting failed. (%d)", err); } ESP_LOGD(TAG, "HMAC computation in downstream mode is completed."); @@ -89,7 +82,7 @@ esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token) esp_crypto_dma_lock_release(); - return ESP_OK; + return err; } esp_err_t esp_hmac_jtag_disable() diff --git a/components/esp_hw_support/port/esp32s2/memprot.c b/components/esp_hw_support/port/esp32s2/memprot.c index 96ce98c8eb..685acfa2f6 100644 --- a/components/esp_hw_support/port/esp32s2/memprot.c +++ b/components/esp_hw_support/port/esp32s2/memprot.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ /* INTERNAL API * implementation of generic interface to MMU memory protection features @@ -22,22 +14,30 @@ #include "soc/dport_access.h" #include "soc/periph_defs.h" #include "esp_intr_alloc.h" - -#include "esp_log.h" -static const char *TAG = "memprot"; - -#include "esp32s2/memprot.h" #include "hal/memprot_ll.h" #include "hal/memprot_peri_ll.h" +#include "esp32s2/memprot.h" #include "esp_fault.h" - #include "soc/cpu.h" +#include "esp32s2/rom/ets_sys.h" extern int _iram_text_end; extern int _data_start; extern int _rtc_text_end; extern int _rtc_dummy_end; +static inline esp_err_t esp_memprot_ll_err_to_esp_err(memprot_ll_err_t err) +{ + switch (err) { + case MEMP_LL_OK: return ESP_OK; + case MEMP_LL_FAIL: return ESP_FAIL; + case MEMP_LL_ERR_SPLIT_ADDR_INVALID: return ESP_ERR_INVALID_STATE; + case MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED: return ESP_ERR_INVALID_SIZE; + case MEMP_LL_ERR_UNI_BLOCK_INVALID: return ESP_ERR_NOT_FOUND; + default: + return ESP_FAIL; + } +} uint32_t *esp_memprot_iram0_sram_get_min_split_addr(void) { @@ -61,17 +61,17 @@ uint32_t *esp_memprot_dram0_rtcfast_get_min_split_addr(void) uint32_t *esp_memprot_peri1_rtcslow_get_min_split_addr(void) { - return (uint32_t *)(PERI1_RTCSLOW_ADDRESS_BASE); + return (uint32_t *)PERI1_RTCSLOW_ADDRESS_BASE; } uint32_t *esp_memprot_peri2_rtcslow_0_get_min_split_addr(void) { - return (uint32_t *)(PERI2_RTCSLOW_0_ADDRESS_BASE); + return (uint32_t *)PERI2_RTCSLOW_0_ADDRESS_BASE; } uint32_t *esp_memprot_peri2_rtcslow_1_get_min_split_addr(void) { - return (uint32_t *)(PERI2_RTCSLOW_1_ADDRESS_BASE); + return (uint32_t *)PERI2_RTCSLOW_1_ADDRESS_BASE; } uint32_t *esp_memprot_get_split_addr(mem_type_prot_t mem_type) @@ -92,8 +92,7 @@ uint32_t *esp_memprot_get_split_addr(mem_type_prot_t mem_type) case MEMPROT_PERI2_RTCSLOW_1: return esp_memprot_peri2_rtcslow_1_get_min_split_addr(); default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return (uint32_t *)MEMPROT_INVALID_ADDRESS; } } @@ -115,541 +114,673 @@ const char *esp_memprot_type_to_str(mem_type_prot_t mem_type) case MEMPROT_PERI2_RTCSLOW_1: return "PERI2_RTCSLOW_1"; default: - return "UNKOWN"; + return "INVALID_MEM_TYPE"; } } -void esp_memprot_intr_init(mem_type_prot_t mem_type) +esp_err_t esp_memprot_intr_init(mem_type_prot_t mem_type) { ESP_INTR_DISABLE(ETS_MEMACCESS_ERR_INUM); switch (mem_type) { case MEMPROT_IRAM0_SRAM: case MEMPROT_IRAM0_RTCFAST: - intr_matrix_set(PRO_CPU_NUM, esp_memprot_iram0_get_intr_source_num(), ETS_MEMACCESS_ERR_INUM); + intr_matrix_set(PRO_CPU_NUM, memprot_ll_iram0_get_intr_source_num(), ETS_MEMACCESS_ERR_INUM); break; case MEMPROT_DRAM0_SRAM: case MEMPROT_DRAM0_RTCFAST: - intr_matrix_set(PRO_CPU_NUM, esp_memprot_dram0_get_intr_source_num(), ETS_MEMACCESS_ERR_INUM); + intr_matrix_set(PRO_CPU_NUM, memprot_ll_dram0_get_intr_source_num(), ETS_MEMACCESS_ERR_INUM); break; case MEMPROT_PERI1_RTCSLOW: - intr_matrix_set(PRO_CPU_NUM, esp_memprot_peri1_get_intr_source_num(), ETS_MEMACCESS_ERR_INUM); + intr_matrix_set(PRO_CPU_NUM, memprot_ll_peri1_get_intr_source_num(), ETS_MEMACCESS_ERR_INUM); break; case MEMPROT_PERI2_RTCSLOW_0: case MEMPROT_PERI2_RTCSLOW_1: - intr_matrix_set(PRO_CPU_NUM, esp_memprot_peri2_get_intr_source_num(), ETS_MEMACCESS_ERR_INUM); + intr_matrix_set(PRO_CPU_NUM, memprot_ll_peri2_get_intr_source_num(), ETS_MEMACCESS_ERR_INUM); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } ESP_INTR_ENABLE(ETS_MEMACCESS_ERR_INUM); + + return ESP_OK; } -void esp_memprot_intr_ena(mem_type_prot_t mem_type, bool enable) +esp_err_t esp_memprot_intr_ena(mem_type_prot_t mem_type, bool enable) { switch (mem_type) { case MEMPROT_IRAM0_SRAM: case MEMPROT_IRAM0_RTCFAST: - esp_memprot_iram0_intr_ena(enable); + memprot_ll_iram0_intr_ena(enable); break; case MEMPROT_DRAM0_SRAM: case MEMPROT_DRAM0_RTCFAST: - esp_memprot_dram0_intr_ena(enable); + memprot_ll_dram0_intr_ena(enable); break; case MEMPROT_PERI1_RTCSLOW: - esp_memprot_peri1_intr_ena(enable); + memprot_ll_peri1_intr_ena(enable); break; case MEMPROT_PERI2_RTCSLOW_0: case MEMPROT_PERI2_RTCSLOW_1: - esp_memprot_peri2_intr_ena(enable); + memprot_ll_peri2_intr_ena(enable); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } mem_type_prot_t esp_memprot_get_active_intr_memtype() { - if (esp_memprot_iram0_sram_is_intr_mine()) { + if (memprot_ll_iram0_sram_is_intr_mine()) { return MEMPROT_IRAM0_SRAM; - } else if (esp_memprot_iram0_rtcfast_is_intr_mine()) { + } else if (memprot_ll_iram0_rtcfast_is_intr_mine()) { return MEMPROT_IRAM0_RTCFAST; - } else if (esp_memprot_dram0_sram_is_intr_mine()) { + } else if (memprot_ll_dram0_sram_is_intr_mine()) { return MEMPROT_DRAM0_SRAM; - } else if (esp_memprot_dram0_rtcfast_is_intr_mine()) { + } else if (memprot_ll_dram0_rtcfast_is_intr_mine()) { return MEMPROT_DRAM0_RTCFAST; - } else if (esp_memprot_peri1_rtcslow_is_intr_mine()) { + } else if (memprot_ll_peri1_rtcslow_is_intr_mine()) { return MEMPROT_PERI1_RTCSLOW; - } else if (esp_memprot_peri2_rtcslow_0_is_intr_mine()) { + } else if (memprot_ll_peri2_rtcslow_0_is_intr_mine()) { return MEMPROT_PERI2_RTCSLOW_0; - } else if (esp_memprot_peri2_rtcslow_1_is_intr_mine()) { + } else if (memprot_ll_peri2_rtcslow_1_is_intr_mine()) { return MEMPROT_PERI2_RTCSLOW_1; } return MEMPROT_NONE; } -void esp_memprot_clear_intr(mem_type_prot_t mem_type) +esp_err_t esp_memprot_clear_intr(mem_type_prot_t mem_type) { switch (mem_type) { case MEMPROT_IRAM0_SRAM: case MEMPROT_IRAM0_RTCFAST: - esp_memprot_iram0_clear_intr(); + memprot_ll_iram0_clear_intr(); break; case MEMPROT_DRAM0_SRAM: case MEMPROT_DRAM0_RTCFAST: - esp_memprot_dram0_clear_intr(); + memprot_ll_dram0_clear_intr(); break; case MEMPROT_PERI1_RTCSLOW: - esp_memprot_peri1_clear_intr(); + memprot_ll_peri1_clear_intr(); break; case MEMPROT_PERI2_RTCSLOW_0: case MEMPROT_PERI2_RTCSLOW_1: - esp_memprot_peri2_clear_intr(); + memprot_ll_peri2_clear_intr(); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -void esp_memprot_set_lock(mem_type_prot_t mem_type) +esp_err_t esp_memprot_set_lock(mem_type_prot_t mem_type) { switch (mem_type) { case MEMPROT_IRAM0_SRAM: case MEMPROT_IRAM0_RTCFAST: - esp_memprot_iram0_set_lock(); + memprot_ll_iram0_set_lock(); break; case MEMPROT_DRAM0_SRAM: case MEMPROT_DRAM0_RTCFAST: - esp_memprot_dram0_set_lock(); + memprot_ll_dram0_set_lock(); break; case MEMPROT_PERI1_RTCSLOW: - esp_memprot_peri1_set_lock(); + memprot_ll_peri1_set_lock(); break; case MEMPROT_PERI2_RTCSLOW_0: case MEMPROT_PERI2_RTCSLOW_1: - esp_memprot_peri2_set_lock(); + memprot_ll_peri2_set_lock(); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -bool esp_memprot_get_lock(mem_type_prot_t mem_type) +esp_err_t esp_memprot_get_lock(mem_type_prot_t mem_type, bool *locked) { + if (locked == NULL) { + return ESP_ERR_INVALID_ARG; + } + switch (mem_type) { case MEMPROT_IRAM0_SRAM: case MEMPROT_IRAM0_RTCFAST: - return esp_memprot_iram0_get_lock_bit() > 0; + *locked = memprot_ll_iram0_get_lock_bit() > 0; + break; case MEMPROT_DRAM0_SRAM: case MEMPROT_DRAM0_RTCFAST: - return esp_memprot_dram0_get_lock_bit() > 0; + *locked = memprot_ll_dram0_get_lock_bit() > 0; + break; case MEMPROT_PERI1_RTCSLOW: - return esp_memprot_peri1_get_lock_bit() > 0; + *locked = memprot_ll_peri1_get_lock_bit() > 0; + break; case MEMPROT_PERI2_RTCSLOW_0: case MEMPROT_PERI2_RTCSLOW_1: - return esp_memprot_peri2_get_lock_bit() > 0; + *locked = memprot_ll_peri2_get_lock_bit() > 0; + break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } bool esp_memprot_is_locked_any() { return - esp_memprot_iram0_get_lock_bit() > 0 || - esp_memprot_dram0_get_lock_bit() > 0 || - esp_memprot_peri1_get_lock_bit() > 0 || - esp_memprot_peri2_get_lock_bit() > 0; + memprot_ll_iram0_get_lock_bit() > 0 || + memprot_ll_dram0_get_lock_bit() > 0 || + memprot_ll_peri1_get_lock_bit() > 0 || + memprot_ll_peri2_get_lock_bit() > 0; } -uint32_t esp_memprot_get_lock_bit(mem_type_prot_t mem_type) +esp_err_t esp_memprot_get_conf_reg(mem_type_prot_t mem_type, uint32_t *conf_reg_val) { + if (conf_reg_val == NULL) { + return ESP_ERR_INVALID_ARG; + } + switch (mem_type) { case MEMPROT_IRAM0_SRAM: case MEMPROT_IRAM0_RTCFAST: - return esp_memprot_iram0_get_lock_bit(); + *conf_reg_val = memprot_ll_iram0_get_conf_reg(); + break; case MEMPROT_DRAM0_SRAM: case MEMPROT_DRAM0_RTCFAST: - return esp_memprot_dram0_get_lock_bit(); + *conf_reg_val = memprot_ll_dram0_get_conf_reg(); + break; case MEMPROT_PERI1_RTCSLOW: - return esp_memprot_peri1_get_lock_bit(); + *conf_reg_val = memprot_ll_peri1_rtcslow_get_conf_reg(); + break; case MEMPROT_PERI2_RTCSLOW_0: + *conf_reg_val = memprot_ll_peri2_rtcslow_0_get_conf_reg(); + break; case MEMPROT_PERI2_RTCSLOW_1: - return esp_memprot_peri2_get_lock_bit(); + *conf_reg_val = memprot_ll_peri2_rtcslow_1_get_conf_reg(); + break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -uint32_t esp_memprot_get_conf_reg(mem_type_prot_t mem_type) +esp_err_t esp_memprot_get_fault_reg(mem_type_prot_t mem_type, uint32_t *fault_reg_val) { + if (fault_reg_val == NULL) { + return ESP_ERR_INVALID_ARG; + } + switch (mem_type) { case MEMPROT_IRAM0_SRAM: case MEMPROT_IRAM0_RTCFAST: - return esp_memprot_iram0_get_conf_reg(); + *fault_reg_val = memprot_ll_iram0_get_fault_reg(); + break; case MEMPROT_DRAM0_SRAM: case MEMPROT_DRAM0_RTCFAST: - return esp_memprot_dram0_get_conf_reg(); + *fault_reg_val = memprot_ll_dram0_get_fault_reg(); + break; case MEMPROT_PERI1_RTCSLOW: - return esp_memprot_peri1_rtcslow_get_conf_reg(); + *fault_reg_val = memprot_ll_peri1_get_fault_reg(); + break; case MEMPROT_PERI2_RTCSLOW_0: - return esp_memprot_peri2_rtcslow_0_get_conf_reg(); case MEMPROT_PERI2_RTCSLOW_1: - return esp_memprot_peri2_rtcslow_1_get_conf_reg(); + *fault_reg_val = memprot_ll_peri2_get_fault_reg(); + break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -uint32_t esp_memprot_get_fault_reg(mem_type_prot_t mem_type) +esp_err_t esp_memprot_get_fault_status(mem_type_prot_t mem_type, uint32_t **faulting_address, uint32_t *op_type, uint32_t *op_subtype) { - switch (mem_type) { - case MEMPROT_IRAM0_SRAM: - case MEMPROT_IRAM0_RTCFAST: - return esp_memprot_iram0_get_fault_reg(); - case MEMPROT_DRAM0_SRAM: - case MEMPROT_DRAM0_RTCFAST: - return esp_memprot_dram0_get_fault_reg(); - case MEMPROT_PERI1_RTCSLOW: - return esp_memprot_peri1_get_fault_reg(); - case MEMPROT_PERI2_RTCSLOW_0: - case MEMPROT_PERI2_RTCSLOW_1: - return esp_memprot_peri2_get_fault_reg(); - default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + if (*faulting_address == NULL || op_type == NULL || op_subtype == NULL) { + return ESP_ERR_INVALID_ARG; } -} -void esp_memprot_get_fault_status(mem_type_prot_t mem_type, uint32_t **faulting_address, uint32_t *op_type, uint32_t *op_subtype) -{ switch (mem_type) { case MEMPROT_IRAM0_SRAM: - *faulting_address = esp_memprot_iram0_sram_get_fault_address(); + *faulting_address = (uint32_t *)memprot_ll_iram0_sram_get_fault_address(); + memprot_ll_iram0_get_fault_op_type(op_type, op_subtype); break; case MEMPROT_IRAM0_RTCFAST: - *faulting_address = esp_memprot_iram0_rtcfast_get_fault_address(); + *faulting_address = (uint32_t *)memprot_ll_iram0_rtcfast_get_fault_address(); + memprot_ll_iram0_get_fault_op_type(op_type, op_subtype); break; case MEMPROT_DRAM0_SRAM: - *faulting_address = esp_memprot_dram0_sram_get_fault_address(); + *faulting_address = (uint32_t *)memprot_ll_dram0_sram_get_fault_address(); + memprot_ll_dram0_get_fault_op_type(op_type, op_subtype); break; case MEMPROT_DRAM0_RTCFAST: - *faulting_address = esp_memprot_dram0_rtcfast_get_fault_address(); + *faulting_address = (uint32_t *)memprot_ll_dram0_rtcfast_get_fault_address(); + memprot_ll_dram0_get_fault_op_type(op_type, op_subtype); break; case MEMPROT_PERI1_RTCSLOW: - *faulting_address = esp_memprot_peri1_rtcslow_get_fault_address(); + *faulting_address = (uint32_t *)memprot_ll_peri1_rtcslow_get_fault_address(); + memprot_ll_peri1_get_fault_op_type(op_type, op_subtype); break; case MEMPROT_PERI2_RTCSLOW_0: case MEMPROT_PERI2_RTCSLOW_1: - *faulting_address = esp_memprot_peri2_rtcslow_get_fault_address(); + *faulting_address = (uint32_t *)memprot_ll_peri2_rtcslow_get_fault_address(); + memprot_ll_peri2_get_fault_op_type(op_type, op_subtype); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } - if (mem_type == MEMPROT_IRAM0_SRAM || mem_type == MEMPROT_IRAM0_RTCFAST) { - esp_memprot_iram0_get_fault_op_type(op_type, op_subtype); - } else if (mem_type == MEMPROT_DRAM0_SRAM || mem_type == MEMPROT_DRAM0_RTCFAST) { - esp_memprot_dram0_get_fault_op_type(op_type, op_subtype); - } else if (mem_type == MEMPROT_PERI1_RTCSLOW) { - esp_memprot_peri1_get_fault_op_type(op_type, op_subtype); - } else if (mem_type == MEMPROT_PERI2_RTCSLOW_0 || mem_type == MEMPROT_PERI2_RTCSLOW_1) { - esp_memprot_peri2_get_fault_op_type(op_type, op_subtype); - } + return ESP_OK; } bool esp_memprot_is_intr_ena_any() { return - esp_memprot_iram0_get_intr_ena_bit() > 0 || - esp_memprot_dram0_get_intr_ena_bit() > 0 || - esp_memprot_peri1_get_intr_ena_bit() > 0 || - esp_memprot_peri2_get_intr_ena_bit() > 0; + memprot_ll_iram0_get_intr_ena_bit() > 0 || + memprot_ll_dram0_get_intr_ena_bit() > 0 || + memprot_ll_peri1_get_intr_ena_bit() > 0 || + memprot_ll_peri2_get_intr_ena_bit() > 0; } -uint32_t esp_memprot_get_intr_ena_bit(mem_type_prot_t mem_type) +esp_err_t esp_memprot_get_intr_ena_bit(mem_type_prot_t mem_type, uint32_t *enable_bit) { + if (enable_bit == NULL) { + return ESP_ERR_INVALID_ARG; + } + switch (mem_type) { case MEMPROT_IRAM0_SRAM: case MEMPROT_IRAM0_RTCFAST: - return esp_memprot_iram0_get_intr_ena_bit(); + *enable_bit = memprot_ll_iram0_get_intr_ena_bit(); + break; case MEMPROT_DRAM0_SRAM: case MEMPROT_DRAM0_RTCFAST: - return esp_memprot_dram0_get_intr_ena_bit(); + *enable_bit = memprot_ll_dram0_get_intr_ena_bit(); + break; case MEMPROT_PERI1_RTCSLOW: - return esp_memprot_peri1_get_intr_ena_bit(); + *enable_bit = memprot_ll_peri1_get_intr_ena_bit(); + break; case MEMPROT_PERI2_RTCSLOW_0: case MEMPROT_PERI2_RTCSLOW_1: - return esp_memprot_peri2_get_intr_ena_bit(); + *enable_bit = memprot_ll_peri2_get_intr_ena_bit(); + break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -uint32_t esp_memprot_get_intr_on_bit(mem_type_prot_t mem_type) +esp_err_t esp_memprot_get_intr_on_bit(mem_type_prot_t mem_type, uint32_t *intr_on_bit) { + if (intr_on_bit == NULL) { + return ESP_ERR_INVALID_ARG; + } + switch (mem_type) { case MEMPROT_IRAM0_SRAM: case MEMPROT_IRAM0_RTCFAST: - return esp_memprot_iram0_get_intr_on_bit(); + *intr_on_bit = memprot_ll_iram0_get_intr_on_bit(); + break; case MEMPROT_DRAM0_SRAM: case MEMPROT_DRAM0_RTCFAST: - return esp_memprot_dram0_get_intr_on_bit(); + *intr_on_bit = memprot_ll_dram0_get_intr_on_bit(); + break; case MEMPROT_PERI1_RTCSLOW: - return esp_memprot_peri1_get_intr_on_bit(); + *intr_on_bit = memprot_ll_peri1_get_intr_on_bit(); + break; case MEMPROT_PERI2_RTCSLOW_0: case MEMPROT_PERI2_RTCSLOW_1: - return esp_memprot_peri2_get_intr_on_bit(); + *intr_on_bit = memprot_ll_peri2_get_intr_on_bit(); + break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -uint32_t esp_memprot_get_intr_clr_bit(mem_type_prot_t mem_type) +esp_err_t esp_memprot_get_intr_clr_bit(mem_type_prot_t mem_type, uint32_t *clear_bit) { + if (clear_bit == NULL) { + return ESP_ERR_INVALID_ARG; + } + switch (mem_type) { case MEMPROT_IRAM0_SRAM: case MEMPROT_IRAM0_RTCFAST: - return esp_memprot_iram0_get_intr_clr_bit(); + *clear_bit = memprot_ll_iram0_get_intr_clr_bit(); + break; case MEMPROT_DRAM0_SRAM: case MEMPROT_DRAM0_RTCFAST: - return esp_memprot_dram0_get_intr_clr_bit(); + *clear_bit = memprot_ll_dram0_get_intr_clr_bit(); + break; case MEMPROT_PERI1_RTCSLOW: - return esp_memprot_peri1_get_intr_clr_bit(); + *clear_bit = memprot_ll_peri1_get_intr_clr_bit(); + break; case MEMPROT_PERI2_RTCSLOW_0: case MEMPROT_PERI2_RTCSLOW_1: - return esp_memprot_peri2_get_intr_clr_bit(); - default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); - } -} - -uint32_t esp_memprot_get_uni_block_read_bit(mem_type_prot_t mem_type, uint32_t block) -{ - switch (mem_type) { - case MEMPROT_IRAM0_SRAM: - return esp_memprot_iram0_sram_get_uni_block_read_bit(block); - case MEMPROT_DRAM0_SRAM: - return esp_memprot_dram0_sram_get_uni_block_read_bit(block); - default: - ESP_LOGE(TAG, "Invalid mem_type %d (unified block management not supported)", mem_type); - abort(); - } -} - -uint32_t esp_memprot_get_uni_block_write_bit(mem_type_prot_t mem_type, uint32_t block) -{ - switch (mem_type) { - case MEMPROT_IRAM0_SRAM: - return esp_memprot_iram0_sram_get_uni_block_write_bit(block); - case MEMPROT_DRAM0_SRAM: - return esp_memprot_dram0_sram_get_uni_block_write_bit(block); - default: - ESP_LOGE(TAG, "Invalid mem_type %d (unified block management not supported)", mem_type); - abort(); - } -} - -uint32_t esp_memprot_get_uni_block_exec_bit(mem_type_prot_t mem_type, uint32_t block) -{ - switch (mem_type) { - case MEMPROT_IRAM0_SRAM: - return esp_memprot_iram0_sram_get_uni_block_exec_bit(block); - default: - ESP_LOGE(TAG, "Invalid mem_type %d (unified block management not supported)", mem_type); - abort(); - } -} - -void esp_memprot_set_uni_block_perm_dram(mem_type_prot_t mem_type, uint32_t block, bool write_perm, bool read_perm) -{ - switch (mem_type) { - case MEMPROT_DRAM0_SRAM: - esp_memprot_dram0_sram_set_uni_block_perm(block, write_perm, read_perm); + *clear_bit = memprot_ll_peri2_get_intr_clr_bit(); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d (unified block management not supported)", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -uint32_t esp_memprot_get_perm_uni_reg(mem_type_prot_t mem_type) +esp_err_t esp_memprot_get_uni_block_read_bit(mem_type_prot_t mem_type, uint32_t block, uint32_t *read_bit) { + if (read_bit == NULL) { + return ESP_ERR_INVALID_ARG; + } + + esp_err_t ret = ESP_OK; + switch (mem_type) { case MEMPROT_IRAM0_SRAM: - return esp_memprot_iram0_sram_get_perm_uni_reg(); + if (!memprot_ll_iram0_sram_get_uni_block_read_bit(block, read_bit)) { + ret = ESP_ERR_NOT_FOUND; + } + break; case MEMPROT_DRAM0_SRAM: - return esp_memprot_dram0_sram_get_perm_reg(); + if (!memprot_ll_dram0_sram_get_uni_block_read_bit(block, read_bit)) { + ret = ESP_ERR_NOT_FOUND; + } + break; default: - ESP_LOGE(TAG, "Invalid mem_type %d (unified block management not supported)", mem_type); - abort(); + ret = ESP_ERR_NOT_SUPPORTED; + break; } + + return ret; } -uint32_t esp_memprot_get_perm_split_reg(mem_type_prot_t mem_type) +esp_err_t esp_memprot_get_uni_block_write_bit(mem_type_prot_t mem_type, uint32_t block, uint32_t *write_bit) { + if (write_bit == NULL) { + return ESP_ERR_INVALID_ARG; + } + + esp_err_t ret = ESP_OK; + switch (mem_type) { case MEMPROT_IRAM0_SRAM: - return esp_memprot_iram0_sram_get_perm_split_reg(); - case MEMPROT_IRAM0_RTCFAST: - return esp_memprot_iram0_rtcfast_get_perm_split_reg(); + if (!memprot_ll_iram0_sram_get_uni_block_write_bit(block, write_bit)) { + ret = ESP_ERR_NOT_FOUND; + } + break; case MEMPROT_DRAM0_SRAM: - return esp_memprot_dram0_sram_get_perm_reg(); - case MEMPROT_DRAM0_RTCFAST: - return esp_memprot_dram0_rtcfast_get_perm_split_reg(); - case MEMPROT_PERI1_RTCSLOW: - return esp_memprot_peri1_rtcslow_get_conf_reg(); - case MEMPROT_PERI2_RTCSLOW_0: - return esp_memprot_peri2_rtcslow_0_get_conf_reg(); - case MEMPROT_PERI2_RTCSLOW_1: - return esp_memprot_peri2_rtcslow_1_get_conf_reg(); + if (!memprot_ll_dram0_sram_get_uni_block_write_bit(block, write_bit)) { + ret = ESP_ERR_NOT_FOUND; + } + break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + ret = ESP_ERR_NOT_SUPPORTED; + break; } + + return ret; } -void esp_memprot_set_prot_dram(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr) +esp_err_t esp_memprot_get_uni_block_exec_bit(mem_type_prot_t mem_type, uint32_t block, uint32_t *exec_bit) +{ + if (exec_bit == NULL) { + return ESP_ERR_INVALID_ARG; + } + + switch (mem_type) { + case MEMPROT_IRAM0_SRAM: + if (!memprot_ll_iram0_sram_get_uni_block_exec_bit(block, exec_bit)) { + return ESP_ERR_NOT_FOUND; + } + break; + default: + return ESP_ERR_NOT_SUPPORTED; + } + + return ESP_OK; +} + +esp_err_t esp_memprot_set_uni_block_perm_dram(mem_type_prot_t mem_type, uint32_t block, bool write_perm, bool read_perm) { switch (mem_type) { case MEMPROT_DRAM0_SRAM: - esp_memprot_dram0_sram_set_prot(split_addr != NULL ? split_addr : esp_memprot_dram0_sram_get_min_split_addr(), lw, lr, hw, hr); - break; - case MEMPROT_DRAM0_RTCFAST: - esp_memprot_dram0_rtcfast_set_prot(split_addr != NULL ? split_addr : esp_memprot_dram0_rtcfast_get_min_split_addr(), lw, lr, hw, hr); - break; + return esp_memprot_ll_err_to_esp_err(memprot_ll_dram0_sram_set_uni_block_perm(block, write_perm, read_perm)); default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } } -void esp_memprot_set_uni_block_perm_iram(mem_type_prot_t mem_type, uint32_t block, bool write_perm, bool read_perm, bool exec_perm) +esp_err_t esp_memprot_get_perm_uni_reg(mem_type_prot_t mem_type, uint32_t *perm_reg) { + if (perm_reg == NULL) { + return ESP_ERR_INVALID_ARG; + } + switch (mem_type) { case MEMPROT_IRAM0_SRAM: - esp_memprot_iram0_sram_set_uni_block_perm(block, write_perm, read_perm, exec_perm); + *perm_reg = memprot_ll_iram0_sram_get_perm_uni_reg(); + break; + case MEMPROT_DRAM0_SRAM: + *perm_reg = memprot_ll_dram0_sram_get_perm_reg(); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d (unified block management not supported)", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -void esp_memprot_set_prot_iram(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx) +esp_err_t esp_memprot_get_perm_split_reg(mem_type_prot_t mem_type, uint32_t *split_reg) { + if (split_reg == NULL) { + return ESP_ERR_INVALID_ARG; + } + switch (mem_type) { case MEMPROT_IRAM0_SRAM: - esp_memprot_iram0_sram_set_prot(split_addr != NULL ? split_addr : esp_memprot_iram0_sram_get_min_split_addr(), lw, lr, lx, hw, hr, hx); + *split_reg = memprot_ll_iram0_sram_get_perm_split_reg(); break; case MEMPROT_IRAM0_RTCFAST: - esp_memprot_iram0_rtcfast_set_prot(split_addr != NULL ? split_addr : esp_memprot_iram0_rtcfast_get_min_split_addr(), lw, lr, lx, hw, hr, hx); + *split_reg = memprot_ll_iram0_rtcfast_get_perm_split_reg(); + break; + case MEMPROT_DRAM0_SRAM: + *split_reg = memprot_ll_dram0_sram_get_perm_reg(); + break; + case MEMPROT_DRAM0_RTCFAST: + *split_reg = memprot_ll_dram0_rtcfast_get_perm_split_reg(); + break; + case MEMPROT_PERI1_RTCSLOW: + *split_reg = memprot_ll_peri1_rtcslow_get_conf_reg(); + break; + case MEMPROT_PERI2_RTCSLOW_0: + *split_reg = memprot_ll_peri2_rtcslow_0_get_conf_reg(); + break; + case MEMPROT_PERI2_RTCSLOW_1: + *split_reg = memprot_ll_peri2_rtcslow_1_get_conf_reg(); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -void esp_memprot_get_perm_split_bits_iram(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) -{ - switch (mem_type) { - case MEMPROT_IRAM0_SRAM: - esp_memprot_iram0_sram_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); - break; - case MEMPROT_IRAM0_RTCFAST: - esp_memprot_iram0_rtcfast_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); - break; - default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); - } -} - -void esp_memprot_get_perm_split_bits_dram(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *hw, bool *hr) +esp_err_t esp_memprot_set_prot_dram(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr) { switch (mem_type) { case MEMPROT_DRAM0_SRAM: - esp_memprot_dram0_sram_get_split_sgnf_bits(lw, lr, hw, hr); + return esp_memprot_ll_err_to_esp_err(memprot_ll_dram0_sram_set_prot(split_addr != NULL ? split_addr : esp_memprot_dram0_sram_get_min_split_addr(), lw, lr, hw, hr)); + case MEMPROT_DRAM0_RTCFAST: + return esp_memprot_ll_err_to_esp_err(memprot_ll_dram0_rtcfast_set_prot(split_addr != NULL ? split_addr : esp_memprot_dram0_rtcfast_get_min_split_addr(), lw, lr, hw, hr)); + default: + return ESP_ERR_NOT_SUPPORTED; + } +} + +esp_err_t esp_memprot_set_uni_block_perm_iram(mem_type_prot_t mem_type, uint32_t block, bool write_perm, bool read_perm, bool exec_perm) +{ + switch (mem_type) { + case MEMPROT_IRAM0_SRAM: + if (!memprot_ll_iram0_sram_set_uni_block_perm(block, write_perm, read_perm, exec_perm)) { + return ESP_ERR_INVALID_ARG; + } + break; + default: + return ESP_ERR_NOT_SUPPORTED; + } + + return ESP_OK; +} + +esp_err_t esp_memprot_set_prot_iram(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx) +{ + switch (mem_type) { + case MEMPROT_IRAM0_SRAM: + return esp_memprot_ll_err_to_esp_err(memprot_ll_iram0_sram_set_prot(split_addr != NULL ? split_addr : esp_memprot_iram0_sram_get_min_split_addr(), lw, lr, lx, hw, hr, hx)); + case MEMPROT_IRAM0_RTCFAST: + return esp_memprot_ll_err_to_esp_err(memprot_ll_iram0_rtcfast_set_prot(split_addr != NULL ? split_addr : esp_memprot_iram0_rtcfast_get_min_split_addr(), lw, lr, lx, hw, hr, hx)); + default: + return ESP_ERR_NOT_SUPPORTED; + } +} + +esp_err_t esp_memprot_get_perm_split_bits_iram(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) +{ + if (lw == NULL || lr == NULL || lx == NULL || hw == NULL || hr == NULL || hx == NULL) { + return ESP_ERR_INVALID_ARG; + } + + switch (mem_type) { + case MEMPROT_IRAM0_SRAM: + memprot_ll_iram0_sram_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); + break; + case MEMPROT_IRAM0_RTCFAST: + memprot_ll_iram0_rtcfast_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); + break; + default: + return ESP_ERR_NOT_SUPPORTED; + } + + return ESP_OK; +} + +esp_err_t esp_memprot_get_perm_split_bits_dram(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *hw, bool *hr) +{ + if (lw == NULL || lr == NULL || hw == NULL || hr == NULL) { + return ESP_ERR_INVALID_ARG; + } + + switch (mem_type) { + case MEMPROT_DRAM0_SRAM: + memprot_ll_dram0_sram_get_split_sgnf_bits(lw, lr, hw, hr); break; case MEMPROT_DRAM0_RTCFAST: - esp_memprot_dram0_rtcfast_get_split_sgnf_bits(lw, lr, hw, hr); + memprot_ll_dram0_rtcfast_get_split_sgnf_bits(lw, lr, hw, hr); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -void esp_memprot_get_perm_split_bits_peri1(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *hw, bool *hr) +esp_err_t esp_memprot_get_perm_split_bits_peri1(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *hw, bool *hr) +{ + if (lw == NULL || lr == NULL || hw == NULL || hr == NULL) { + return ESP_ERR_INVALID_ARG; + } + + switch (mem_type) { + case MEMPROT_PERI1_RTCSLOW: + memprot_ll_peri1_rtcslow_get_split_sgnf_bits(lw, lr, hw, hr); + break; + default: + return ESP_ERR_NOT_SUPPORTED; + } + + return ESP_OK; +} + +esp_err_t esp_memprot_set_prot_peri1(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr) { switch (mem_type) { case MEMPROT_PERI1_RTCSLOW: - esp_memprot_peri1_rtcslow_get_split_sgnf_bits(lw, lr, hw, hr); - break; + return esp_memprot_ll_err_to_esp_err( + memprot_ll_peri1_rtcslow_set_prot( + split_addr != NULL ? split_addr : esp_memprot_peri1_rtcslow_get_min_split_addr(), + lw, + lr, + hw, + hr) + ); default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } } -void esp_memprot_set_prot_peri1(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr) +esp_err_t esp_memprot_get_perm_split_bits_peri2(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) { + if (lw == NULL || lr == NULL || lx == NULL || hw == NULL || hr == NULL || hx == NULL) { + return ESP_ERR_INVALID_ARG; + } + switch (mem_type) { - case MEMPROT_PERI1_RTCSLOW: - esp_memprot_peri1_rtcslow_set_prot(split_addr != NULL ? split_addr : esp_memprot_peri1_rtcslow_get_min_split_addr(), lw, lr, hw, hr); + case MEMPROT_PERI2_RTCSLOW_0: + memprot_ll_peri2_rtcslow_0_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); + break; + case MEMPROT_PERI2_RTCSLOW_1: + memprot_ll_peri2_rtcslow_1_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -void esp_memprot_get_perm_split_bits_peri2(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) +esp_err_t esp_memprot_set_prot_peri2(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx) { switch (mem_type) { case MEMPROT_PERI2_RTCSLOW_0: - esp_memprot_peri2_rtcslow_0_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); - break; + return esp_memprot_ll_err_to_esp_err( + memprot_ll_peri2_rtcslow_0_set_prot( + split_addr != NULL ? split_addr : esp_memprot_peri2_rtcslow_0_get_min_split_addr(), + lw, + lr, + lx, + hw, + hr, + hx) + ); case MEMPROT_PERI2_RTCSLOW_1: - esp_memprot_peri2_rtcslow_1_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); - break; + return esp_memprot_ll_err_to_esp_err( + memprot_ll_peri2_rtcslow_1_set_prot( + split_addr != NULL ? split_addr : esp_memprot_peri2_rtcslow_1_get_min_split_addr(), + lw, + lr, + lx, + hw, + hr, + hx) + ); default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } } -void esp_memprot_set_prot_peri2(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx) +esp_err_t esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask) { - switch (mem_type) { - case MEMPROT_PERI2_RTCSLOW_0: - esp_memprot_peri2_rtcslow_0_set_prot(split_addr != NULL ? split_addr : esp_memprot_peri2_rtcslow_0_get_min_split_addr(), lw, lr, lx, hw, hr, hx); - break; - case MEMPROT_PERI2_RTCSLOW_1: - esp_memprot_peri2_rtcslow_1_set_prot(split_addr != NULL ? split_addr : esp_memprot_peri2_rtcslow_1_get_min_split_addr(), lw, lr, lx, hw, hr, hx); - break; - default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); - } -} + esp_err_t ret; -void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask) -{ //any IRAM0/DRAM0 enable/disable call applies to all memory modules connected uint32_t required_mem_prot = mem_type_mask == NULL ? (uint32_t)MEMPROT_ALL : *mem_type_mask; bool use_iram0 = required_mem_prot & MEMPROT_IRAM0_SRAM || required_mem_prot & MEMPROT_IRAM0_RTCFAST; @@ -658,17 +789,17 @@ void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t bool use_peri2 = required_mem_prot & MEMPROT_PERI2_RTCSLOW_0 || required_mem_prot & MEMPROT_PERI2_RTCSLOW_1; //disable protection - if (use_iram0) { - esp_memprot_intr_ena(MEMPROT_IRAM0_SRAM, false); + if (use_iram0 && (ret = esp_memprot_intr_ena(MEMPROT_IRAM0_SRAM, false)) != ESP_OK) { + return ret; } - if (use_dram0) { - esp_memprot_intr_ena(MEMPROT_DRAM0_SRAM, false); + if (use_dram0 && (ret = esp_memprot_intr_ena(MEMPROT_DRAM0_SRAM, false)) != ESP_OK) { + return ret; } - if (use_peri1) { - esp_memprot_intr_ena(MEMPROT_PERI1_RTCSLOW, false); + if (use_peri1 && (ret = esp_memprot_intr_ena(MEMPROT_PERI1_RTCSLOW, false)) != ESP_OK) { + return ret; } - if (use_peri2) { - esp_memprot_intr_ena(MEMPROT_PERI2_RTCSLOW_0, false); + if (use_peri2 && (ret = esp_memprot_intr_ena(MEMPROT_PERI2_RTCSLOW_0, false)) != ESP_OK) { + return ret; } //connect to intr. matrix if not being debugged @@ -678,134 +809,172 @@ void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t //initialize for specific buses (any memory type does the job) if (invoke_panic_handler) { - if (use_iram0) { - esp_memprot_intr_init(MEMPROT_IRAM0_SRAM); + if (use_iram0 && (ret = esp_memprot_intr_init(MEMPROT_IRAM0_SRAM)) != ESP_OK) { + return ret; } - if (use_dram0) { - esp_memprot_intr_init(MEMPROT_DRAM0_SRAM); + if (use_dram0 && (ret = esp_memprot_intr_init(MEMPROT_DRAM0_SRAM)) != ESP_OK) { + return ret; } - if (use_peri1) { - esp_memprot_intr_init(MEMPROT_PERI1_RTCSLOW); + if (use_peri1 && (ret = esp_memprot_intr_init(MEMPROT_PERI1_RTCSLOW)) != ESP_OK) { + return ret; } - if (use_peri2) { - esp_memprot_intr_init(MEMPROT_PERI2_RTCSLOW_0); + if (use_peri2 && (ret = esp_memprot_intr_init(MEMPROT_PERI2_RTCSLOW_0)) != ESP_OK) { + return ret; } } //set permissions if (required_mem_prot & MEMPROT_IRAM0_SRAM) { - esp_memprot_set_prot_iram(MEMPROT_IRAM0_SRAM, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_ENA, EX_LOW_ENA, WR_HIGH_DIS, RD_HIGH_DIS, EX_HIGH_DIS); + ret = esp_memprot_set_prot_iram(MEMPROT_IRAM0_SRAM, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_ENA, EX_LOW_ENA, WR_HIGH_DIS, RD_HIGH_DIS, EX_HIGH_DIS); + if (ret != ESP_OK) { + return ret; + } } if (required_mem_prot & MEMPROT_IRAM0_RTCFAST) { - esp_memprot_set_prot_iram(MEMPROT_IRAM0_RTCFAST, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_ENA, EX_LOW_ENA, WR_HIGH_DIS, RD_HIGH_DIS, EX_HIGH_DIS); + ret = esp_memprot_set_prot_iram(MEMPROT_IRAM0_RTCFAST, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_ENA, EX_LOW_ENA, WR_HIGH_DIS, RD_HIGH_DIS, EX_HIGH_DIS); + if (ret != ESP_OK) { + return ret; + } } if (required_mem_prot & MEMPROT_DRAM0_SRAM) { - esp_memprot_set_prot_dram(MEMPROT_DRAM0_SRAM, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_ENA, WR_HIGH_ENA, RD_HIGH_ENA); + ret = esp_memprot_set_prot_dram(MEMPROT_DRAM0_SRAM, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_ENA, WR_HIGH_ENA, RD_HIGH_ENA); + if (ret != ESP_OK) { + return ret; + } } if (required_mem_prot & MEMPROT_DRAM0_RTCFAST) { - esp_memprot_set_prot_dram(MEMPROT_DRAM0_RTCFAST, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_ENA, WR_HIGH_ENA, RD_HIGH_ENA); + ret = esp_memprot_set_prot_dram(MEMPROT_DRAM0_RTCFAST, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_ENA, WR_HIGH_ENA, RD_HIGH_ENA); + if (ret != ESP_OK) { + return ret; + } } if (required_mem_prot & MEMPROT_PERI1_RTCSLOW) { - esp_memprot_set_prot_peri1(MEMPROT_PERI1_RTCSLOW, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_DIS, WR_HIGH_DIS, RD_HIGH_DIS); + ret = esp_memprot_set_prot_peri1(MEMPROT_PERI1_RTCSLOW, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_DIS, WR_HIGH_DIS, RD_HIGH_DIS); + if (ret != ESP_OK) { + return ret; + } } if (required_mem_prot & MEMPROT_PERI2_RTCSLOW_0) { - esp_memprot_set_prot_peri2(MEMPROT_PERI2_RTCSLOW_0, DEF_SPLIT_LINE, WR_LOW_ENA, RD_LOW_ENA, EX_LOW_DIS, WR_HIGH_ENA, RD_HIGH_ENA, EX_HIGH_DIS); + ret = esp_memprot_set_prot_peri2(MEMPROT_PERI2_RTCSLOW_0, DEF_SPLIT_LINE, WR_LOW_ENA, RD_LOW_ENA, EX_LOW_DIS, WR_HIGH_ENA, RD_HIGH_ENA, EX_HIGH_DIS); + if (ret != ESP_OK) { + return ret; + } } if (required_mem_prot & MEMPROT_PERI2_RTCSLOW_1) { - esp_memprot_set_prot_peri2(MEMPROT_PERI2_RTCSLOW_1, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_DIS, EX_LOW_DIS, WR_HIGH_DIS, RD_HIGH_DIS, EX_HIGH_DIS); + ret = esp_memprot_set_prot_peri2(MEMPROT_PERI2_RTCSLOW_1, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_DIS, EX_LOW_DIS, WR_HIGH_DIS, RD_HIGH_DIS, EX_HIGH_DIS); + if (ret != ESP_OK) { + return ret; + } } //reenable protection (bus based) - if (use_iram0) { - esp_memprot_intr_ena(MEMPROT_IRAM0_SRAM, true); + if (use_iram0 && (ret = esp_memprot_intr_ena(MEMPROT_IRAM0_SRAM, true)) != ESP_OK) { + return ret; } - if (use_dram0) { - esp_memprot_intr_ena(MEMPROT_DRAM0_SRAM, true); + if (use_dram0 && (ret = esp_memprot_intr_ena(MEMPROT_DRAM0_SRAM, true)) != ESP_OK) { + return ret; } - if (use_peri1) { - esp_memprot_intr_ena(MEMPROT_PERI1_RTCSLOW, true); + if (use_peri1 && (ret = esp_memprot_intr_ena(MEMPROT_PERI1_RTCSLOW, true)) != ESP_OK) { + return ret; } - if (use_peri2) { - esp_memprot_intr_ena(MEMPROT_PERI2_RTCSLOW_0, true); + if (use_peri2 && (ret = esp_memprot_intr_ena(MEMPROT_PERI2_RTCSLOW_0, true)) != ESP_OK) { + return ret; } //lock if required (bus based) if (lock_feature) { - if (use_iram0) { - esp_memprot_set_lock(MEMPROT_IRAM0_SRAM); + if (use_iram0 && (ret = esp_memprot_set_lock(MEMPROT_IRAM0_SRAM)) != ESP_OK) { + return ret; } - if (use_dram0) { - esp_memprot_set_lock(MEMPROT_DRAM0_SRAM); + if (use_dram0 && (ret = esp_memprot_set_lock(MEMPROT_DRAM0_SRAM)) != ESP_OK) { + return ret; } - if (use_peri1) { - esp_memprot_set_lock(MEMPROT_PERI1_RTCSLOW); + if (use_peri1 && (ret = esp_memprot_set_lock(MEMPROT_PERI1_RTCSLOW)) != ESP_OK) { + return ret; } - if (use_peri2) { - esp_memprot_set_lock(MEMPROT_PERI2_RTCSLOW_0); + if (use_peri2 && (ret = esp_memprot_set_lock(MEMPROT_PERI2_RTCSLOW_0)) != ESP_OK) { + return ret; } } } + + return ESP_OK; } -void esp_memprot_get_permissions(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) +esp_err_t esp_memprot_get_permissions(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) { + if (lw == NULL || lr == NULL || lx == NULL || hw == NULL || hr == NULL || hx == NULL) { + return ESP_ERR_INVALID_ARG; + } + switch (mem_type) { case MEMPROT_IRAM0_SRAM: - esp_memprot_iram0_sram_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); + memprot_ll_iram0_sram_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); break; case MEMPROT_DRAM0_SRAM: - esp_memprot_dram0_sram_get_split_sgnf_bits(lw, lr, hw, hr); + memprot_ll_dram0_sram_get_split_sgnf_bits(lw, lr, hw, hr); break; case MEMPROT_IRAM0_RTCFAST: - esp_memprot_iram0_rtcfast_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); + memprot_ll_iram0_rtcfast_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); break; case MEMPROT_DRAM0_RTCFAST: - esp_memprot_dram0_rtcfast_get_split_sgnf_bits(lw, lr, hw, hr); + memprot_ll_dram0_rtcfast_get_split_sgnf_bits(lw, lr, hw, hr); break; case MEMPROT_PERI1_RTCSLOW: - esp_memprot_peri1_rtcslow_get_split_sgnf_bits(lw, lr, hw, hr); + memprot_ll_peri1_rtcslow_get_split_sgnf_bits(lw, lr, hw, hr); break; case MEMPROT_PERI2_RTCSLOW_0: - esp_memprot_peri2_rtcslow_0_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); + memprot_ll_peri2_rtcslow_0_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); break; case MEMPROT_PERI2_RTCSLOW_1: - esp_memprot_peri2_rtcslow_1_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); + memprot_ll_peri2_rtcslow_1_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -void esp_memprot_get_perm_read(mem_type_prot_t mem_type, bool *lr, bool *hr) +esp_err_t esp_memprot_get_perm_read(mem_type_prot_t mem_type, bool *lr, bool *hr) { bool _lw, _lr, _lx, _hw, _hr, _hx; - esp_memprot_get_permissions(mem_type, &_lw, &_lr, &_lx, &_hw, &_hr, &_hx); - *lr = _lr; - *hr = _hr; + esp_err_t ret = esp_memprot_get_permissions(mem_type, &_lw, &_lr, &_lx, &_hw, &_hr, &_hx); + if (ret == ESP_OK) { + *lr = _lr; + *hr = _hr; + } + return ret; } -void esp_memprot_get_perm_write(mem_type_prot_t mem_type, bool *lw, bool *hw) +esp_err_t esp_memprot_get_perm_write(mem_type_prot_t mem_type, bool *lw, bool *hw) { bool _lw, _lr, _lx, _hw, _hr, _hx; - esp_memprot_get_permissions(mem_type, &_lw, &_lr, &_lx, &_hw, &_hr, &_hx); - *lw = _lw; - *hw = _hw; + esp_err_t ret = esp_memprot_get_permissions(mem_type, &_lw, &_lr, &_lx, &_hw, &_hr, &_hx); + if (ret == ESP_OK) { + *lw = _lw; + *hw = _hw; + } + + return ret; } -void esp_memprot_get_perm_exec(mem_type_prot_t mem_type, bool *lx, bool *hx) +esp_err_t esp_memprot_get_perm_exec(mem_type_prot_t mem_type, bool *lx, bool *hx) { - if ( mem_type == MEMPROT_DRAM0_SRAM || + if (mem_type == MEMPROT_DRAM0_SRAM || mem_type == MEMPROT_DRAM0_RTCFAST || - mem_type == MEMPROT_PERI1_RTCSLOW ) { - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + mem_type == MEMPROT_PERI1_RTCSLOW) { + return ESP_ERR_NOT_SUPPORTED; } bool _lw, _lr, _lx, _hw, _hr, _hx; - esp_memprot_get_permissions(mem_type, &_lw, &_lr, &_lx, &_hw, &_hr, &_hx); - *lx = _lx; - *hx = _hx; + esp_err_t ret = esp_memprot_get_permissions(mem_type, &_lw, &_lr, &_lx, &_hw, &_hr, &_hx); + if (ret == ESP_OK) { + *lx = _lx; + *hx = _hx; + } + + return ret; } uint32_t esp_memprot_get_low_limit(mem_type_prot_t mem_type) @@ -826,8 +995,7 @@ uint32_t esp_memprot_get_low_limit(mem_type_prot_t mem_type) case MEMPROT_PERI2_RTCSLOW_1: return PERI2_RTCSLOW_1_ADDRESS_LOW; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return MEMPROT_INVALID_ADDRESS; } } @@ -849,88 +1017,90 @@ uint32_t esp_memprot_get_high_limit(mem_type_prot_t mem_type) case MEMPROT_PERI2_RTCSLOW_1: return PERI2_RTCSLOW_1_ADDRESS_HIGH; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return MEMPROT_INVALID_ADDRESS; } } -void esp_memprot_set_read_perm(mem_type_prot_t mem_type, bool lr, bool hr) +esp_err_t esp_memprot_set_read_perm(mem_type_prot_t mem_type, bool lr, bool hr) { switch (mem_type) { case MEMPROT_IRAM0_SRAM: - esp_memprot_iram0_sram_set_read_perm(lr, hr); + memprot_ll_iram0_sram_set_read_perm(lr, hr); break; case MEMPROT_DRAM0_SRAM: - esp_memprot_dram0_sram_set_read_perm(lr, hr); + memprot_ll_dram0_sram_set_read_perm(lr, hr); break; case MEMPROT_IRAM0_RTCFAST: - esp_memprot_iram0_rtcfast_set_read_perm(lr, hr); + memprot_ll_iram0_rtcfast_set_read_perm(lr, hr); break; case MEMPROT_DRAM0_RTCFAST: - esp_memprot_dram0_rtcfast_set_read_perm(lr, hr); + memprot_ll_dram0_rtcfast_set_read_perm(lr, hr); break; case MEMPROT_PERI1_RTCSLOW: - esp_memprot_peri1_rtcslow_set_read_perm(lr, hr); + memprot_ll_peri1_rtcslow_set_read_perm(lr, hr); break; case MEMPROT_PERI2_RTCSLOW_0: - esp_memprot_peri2_rtcslow_0_set_read_perm(lr, hr); + memprot_ll_peri2_rtcslow_0_set_read_perm(lr, hr); break; case MEMPROT_PERI2_RTCSLOW_1: - esp_memprot_peri2_rtcslow_1_set_read_perm(lr, hr); + memprot_ll_peri2_rtcslow_1_set_read_perm(lr, hr); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -void esp_memprot_set_write_perm(mem_type_prot_t mem_type, bool lw, bool hw) +esp_err_t esp_memprot_set_write_perm(mem_type_prot_t mem_type, bool lw, bool hw) { switch (mem_type) { case MEMPROT_IRAM0_SRAM: - esp_memprot_iram0_sram_set_write_perm(lw, hw); + memprot_ll_iram0_sram_set_write_perm(lw, hw); break; case MEMPROT_DRAM0_SRAM: - esp_memprot_dram0_sram_set_write_perm(lw, hw); + memprot_ll_dram0_sram_set_write_perm(lw, hw); break; case MEMPROT_IRAM0_RTCFAST: - esp_memprot_iram0_rtcfast_set_write_perm(lw, hw); + memprot_ll_iram0_rtcfast_set_write_perm(lw, hw); break; case MEMPROT_DRAM0_RTCFAST: - esp_memprot_dram0_rtcfast_set_write_perm(lw, hw); + memprot_ll_dram0_rtcfast_set_write_perm(lw, hw); break; case MEMPROT_PERI1_RTCSLOW: - esp_memprot_peri1_rtcslow_set_write_perm(lw, hw); + memprot_ll_peri1_rtcslow_set_write_perm(lw, hw); break; case MEMPROT_PERI2_RTCSLOW_0: - esp_memprot_peri2_rtcslow_0_set_write_perm(lw, hw); + memprot_ll_peri2_rtcslow_0_set_write_perm(lw, hw); break; case MEMPROT_PERI2_RTCSLOW_1: - esp_memprot_peri2_rtcslow_1_set_write_perm(lw, hw); + memprot_ll_peri2_rtcslow_1_set_write_perm(lw, hw); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -void esp_memprot_set_exec_perm(mem_type_prot_t mem_type, bool lx, bool hx) +esp_err_t esp_memprot_set_exec_perm(mem_type_prot_t mem_type, bool lx, bool hx) { switch (mem_type) { case MEMPROT_IRAM0_SRAM: - esp_memprot_iram0_sram_set_exec_perm(lx, hx); + memprot_ll_iram0_sram_set_exec_perm(lx, hx); break; case MEMPROT_IRAM0_RTCFAST: - esp_memprot_iram0_rtcfast_set_exec_perm(lx, hx); + memprot_ll_iram0_rtcfast_set_exec_perm(lx, hx); break; case MEMPROT_PERI2_RTCSLOW_0: - esp_memprot_peri2_rtcslow_0_set_exec_perm(lx, hx); + memprot_ll_peri2_rtcslow_0_set_exec_perm(lx, hx); break; case MEMPROT_PERI2_RTCSLOW_1: - esp_memprot_peri2_rtcslow_1_set_exec_perm(lx, hx); + memprot_ll_peri2_rtcslow_1_set_exec_perm(lx, hx); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } diff --git a/components/esp_hw_support/port/esp32s2/private_include/regi2c_apll.h b/components/esp_hw_support/port/esp32s2/private_include/regi2c_apll.h index d63ceb1f48..d62caa1daf 100644 --- a/components/esp_hw_support/port/esp32s2/private_include/regi2c_apll.h +++ b/components/esp_hw_support/port/esp32s2/private_include/regi2c_apll.h @@ -1,16 +1,8 @@ -// Copyright 2015-2017 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/port/esp32s2/private_include/regi2c_bbpll.h b/components/esp_hw_support/port/esp32s2/private_include/regi2c_bbpll.h index edc9938842..e7423b1e6e 100644 --- a/components/esp_hw_support/port/esp32s2/private_include/regi2c_bbpll.h +++ b/components/esp_hw_support/port/esp32s2/private_include/regi2c_bbpll.h @@ -1,16 +1,8 @@ -// Copyright 2015-2017 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/port/esp32s2/private_include/regi2c_brownout.h b/components/esp_hw_support/port/esp32s2/private_include/regi2c_brownout.h index 0b8b618bba..8073b72a27 100644 --- a/components/esp_hw_support/port/esp32s2/private_include/regi2c_brownout.h +++ b/components/esp_hw_support/port/esp32s2/private_include/regi2c_brownout.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/port/esp32s2/private_include/regi2c_saradc.h b/components/esp_hw_support/port/esp32s2/private_include/regi2c_saradc.h index 2345e0a5aa..388f9c6221 100644 --- a/components/esp_hw_support/port/esp32s2/private_include/regi2c_saradc.h +++ b/components/esp_hw_support/port/esp32s2/private_include/regi2c_saradc.h @@ -1,16 +1,8 @@ -// Copyright 2019-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: 2019-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/port/esp32s2/private_include/regi2c_ulp.h b/components/esp_hw_support/port/esp32s2/private_include/regi2c_ulp.h index 4be3a499d2..43a8c0d41e 100644 --- a/components/esp_hw_support/port/esp32s2/private_include/regi2c_ulp.h +++ b/components/esp_hw_support/port/esp32s2/private_include/regi2c_ulp.h @@ -1,16 +1,8 @@ -// Copyright 2015-2017 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/port/esp32s2/regi2c_ctrl.c b/components/esp_hw_support/port/esp32s2/regi2c_ctrl.c index 0b191ac027..9a37dfc6c3 100644 --- a/components/esp_hw_support/port/esp32s2/regi2c_ctrl.c +++ b/components/esp_hw_support/port/esp32s2/regi2c_ctrl.c @@ -1,23 +1,15 @@ -// Copyright 2019-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: 2019-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "soc/soc.h" -#include "soc/apb_ctrl_reg.h" +#include "soc/syscon_reg.h" #include "regi2c_ctrl.h" #include "regi2c_brownout.h" -#define I2C_RTC_WIFI_CLK_EN (APB_CTRL_WIFI_CLK_EN_REG) +#define I2C_RTC_WIFI_CLK_EN (SYSCON_WIFI_CLK_EN_REG) #define I2C_RTC_CLK_GATE_EN (BIT(18)) #define I2C_RTC_CLK_GATE_EN_M (BIT(18)) diff --git a/components/esp_hw_support/port/esp32s2/regi2c_ctrl.h b/components/esp_hw_support/port/esp32s2/regi2c_ctrl.h index 51a0a22dcb..741c0b1020 100644 --- a/components/esp_hw_support/port/esp32s2/regi2c_ctrl.h +++ b/components/esp_hw_support/port/esp32s2/regi2c_ctrl.h @@ -1,16 +1,8 @@ -// Copyright 2015-2017 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/port/esp32s2/rtc_clk.c b/components/esp_hw_support/port/esp32s2/rtc_clk.c index 3c65515988..d03de58477 100644 --- a/components/esp_hw_support/port/esp32s2/rtc_clk.c +++ b/components/esp_hw_support/port/esp32s2/rtc_clk.c @@ -1,16 +1,8 @@ -// Copyright 2015-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: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include diff --git a/components/esp_hw_support/port/esp32s2/rtc_clk_common.h b/components/esp_hw_support/port/esp32s2/rtc_clk_common.h index d4dad103ad..570c34c865 100644 --- a/components/esp_hw_support/port/esp32s2/rtc_clk_common.h +++ b/components/esp_hw_support/port/esp32s2/rtc_clk_common.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/port/esp32s2/rtc_clk_init.c b/components/esp_hw_support/port/esp32s2/rtc_clk_init.c index a2f75688ae..569b995112 100644 --- a/components/esp_hw_support/port/esp32s2/rtc_clk_init.c +++ b/components/esp_hw_support/port/esp32s2/rtc_clk_init.c @@ -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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -22,7 +14,7 @@ #include "soc/rtc_periph.h" #include "soc/sens_periph.h" #include "soc/efuse_periph.h" -#include "soc/apb_ctrl_reg.h" +#include "soc/syscon_reg.h" #include "hal/cpu_hal.h" #include "regi2c_ctrl.h" #include "soc_log.h" diff --git a/components/esp_hw_support/port/esp32s2/rtc_init.c b/components/esp_hw_support/port/esp32s2/rtc_init.c index de9ca71d04..369a372cba 100644 --- a/components/esp_hw_support/port/esp32s2/rtc_init.c +++ b/components/esp_hw_support/port/esp32s2/rtc_init.c @@ -1,16 +1,8 @@ -// Copyright 2015-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: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "soc/soc.h" diff --git a/components/esp_hw_support/port/esp32s2/rtc_pm.c b/components/esp_hw_support/port/esp32s2/rtc_pm.c index 2f63dc8beb..d1fb320830 100644 --- a/components/esp_hw_support/port/esp32s2/rtc_pm.c +++ b/components/esp_hw_support/port/esp32s2/rtc_pm.c @@ -1,22 +1,14 @@ -// Copyright 2015-2017 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include #include "soc/rtc.h" #include "soc/rtc_cntl_reg.h" -#include "soc/apb_ctrl_reg.h" +#include "soc/syscon_reg.h" typedef enum { PM_LIGHT_SLEEP = BIT(2), /*!< WiFi PD, memory in light sleep */ diff --git a/components/esp_hw_support/port/esp32s2/rtc_sleep.c b/components/esp_hw_support/port/esp32s2/rtc_sleep.c index 6d958fbf13..3398718072 100644 --- a/components/esp_hw_support/port/esp32s2/rtc_sleep.c +++ b/components/esp_hw_support/port/esp32s2/rtc_sleep.c @@ -1,22 +1,14 @@ -// Copyright 2015-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: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "soc/soc.h" #include "soc/rtc.h" #include "soc/rtc_cntl_reg.h" -#include "soc/apb_ctrl_reg.h" +#include "soc/syscon_reg.h" #include "soc/dport_reg.h" #include "soc/rtc.h" #include "soc/i2s_reg.h" @@ -40,9 +32,9 @@ void rtc_sleep_pd(rtc_sleep_pd_config_t cfg) REG_SET_FIELD(RTC_CNTL_PWC_REG, RTC_CNTL_SLOWMEM_FORCE_LPU, cfg.rtc_fpu); REG_SET_FIELD(I2S_PD_CONF_REG(0), I2S_PLC_MEM_FORCE_PU, cfg.i2s_fpu); REG_SET_FIELD(I2S_PD_CONF_REG(0), I2S_FIFO_FORCE_PU, cfg.i2s_fpu); - REG_SET_FIELD(APB_CTRL_FRONT_END_MEM_PD_REG, APB_CTRL_DC_MEM_FORCE_PU, cfg.fe_fpu); - REG_SET_FIELD(APB_CTRL_FRONT_END_MEM_PD_REG, APB_CTRL_PBUS_MEM_FORCE_PU, cfg.fe_fpu); - REG_SET_FIELD(APB_CTRL_FRONT_END_MEM_PD_REG, APB_CTRL_AGC_MEM_FORCE_PU, cfg.fe_fpu); + REG_SET_FIELD(SYSCON_FRONT_END_MEM_PD_REG, SYSCON_DC_MEM_FORCE_PU, cfg.fe_fpu); + REG_SET_FIELD(SYSCON_FRONT_END_MEM_PD_REG, SYSCON_PBUS_MEM_FORCE_PU, cfg.fe_fpu); + REG_SET_FIELD(SYSCON_FRONT_END_MEM_PD_REG, SYSCON_AGC_MEM_FORCE_PU, cfg.fe_fpu); REG_SET_FIELD(BBPD_CTRL, BB_FFT_FORCE_PU, cfg.bb_fpu); REG_SET_FIELD(BBPD_CTRL, BB_DC_EST_FORCE_PU, cfg.bb_fpu); REG_SET_FIELD(NRXPD_CTRL, NRX_RX_ROT_FORCE_PU, cfg.nrx_fpu); @@ -99,9 +91,11 @@ void rtc_sleep_init(rtc_sleep_config_t cfg) REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_MONITOR, RTC_CNTL_DBG_ATTEN_MONITOR_DEFAULT); REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_BIAS_SLEEP_MONITOR, RTC_CNTL_BIASSLP_MONITOR_DEFAULT); - REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_BIAS_SLEEP_DEEP_SLP, RTC_CNTL_BIASSLP_SLEEP_DEFAULT); + REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_BIAS_SLEEP_DEEP_SLP, + (!cfg.deep_slp && cfg.xtal_fpu) ? RTC_CNTL_BIASSLP_SLEEP_ON : RTC_CNTL_BIASSLP_SLEEP_DEFAULT); REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_PD_CUR_MONITOR, RTC_CNTL_PD_CUR_MONITOR_DEFAULT); - REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_PD_CUR_DEEP_SLP, RTC_CNTL_PD_CUR_SLEEP_DEFAULT); + REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_PD_CUR_DEEP_SLP, + (!cfg.deep_slp && cfg.xtal_fpu) ? RTC_CNTL_PD_CUR_SLEEP_ON : RTC_CNTL_PD_CUR_SLEEP_DEFAULT); if (cfg.deep_slp) { CLEAR_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU); REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_DEEP_SLP, RTC_CNTL_DBG_ATTEN_DEEPSLEEP_DEFAULT); @@ -111,9 +105,18 @@ void rtc_sleep_init(rtc_sleep_config_t cfg) RTC_CNTL_RFRX_PBUS_PU | RTC_CNTL_TXRF_I2C_PU); CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PU); } else { - SET_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU); + SET_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU); CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_WRAP_PD_EN); - REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_DEEP_SLP, RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_DEFAULT); + REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_DEEP_SLP, + cfg.int_8m_pd_en ? RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_DEFAULT : RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_NODROP); + } + + //Keep the RTC8M_CLK on in light_sleep mode if the ledc low-speed channel is clocked by RTC8M_CLK. + if (!cfg.int_8m_pd_en && GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M)) { + REG_CLR_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PD); + REG_SET_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU); + } else { + REG_CLR_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU); } /* enable VDDSDIO control by state machine */ @@ -129,6 +132,8 @@ void rtc_sleep_init(rtc_sleep_config_t cfg) REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_LIGHT_SLP_REJECT_EN, cfg.light_slp_reject); /* Set wait cycle for touch or COCPU after deep sleep and light sleep. */ REG_SET_FIELD(RTC_CNTL_TIMER2_REG, RTC_CNTL_ULPCP_TOUCH_START_WAIT, RTC_CNTL_ULPCP_TOUCH_START_WAIT_IN_SLEEP); + + REG_SET_FIELD(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_XTL_FORCE_PU, cfg.xtal_fpu); } void rtc_sleep_low_init(uint32_t slowclk_period) diff --git a/components/esp_hw_support/port/esp32s2/rtc_time.c b/components/esp_hw_support/port/esp32s2/rtc_time.c index cbdbb71e3b..a18f36981b 100644 --- a/components/esp_hw_support/port/esp32s2/rtc_time.c +++ b/components/esp_hw_support/port/esp32s2/rtc_time.c @@ -1,16 +1,8 @@ -// Copyright 2015-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: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "esp_rom_sys.h" @@ -149,7 +141,10 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles, ui } else if (slow_freq == RTC_SLOW_FREQ_8MD256) { cal_clk = RTC_CAL_8MD256; } + } else if (cal_clk == RTC_CAL_INTERNAL_OSC) { + cal_clk = RTC_CAL_RTC_MUX; } + /* Enable requested clock (90k clock is always on) */ int dig_32k_xtal_state = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN); if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_state) { diff --git a/components/esp_hw_support/port/esp32s2/rtc_wdt.c b/components/esp_hw_support/port/esp32s2/rtc_wdt.c index 53861772a4..10110275a5 100644 --- a/components/esp_hw_support/port/esp32s2/rtc_wdt.c +++ b/components/esp_hw_support/port/esp32s2/rtc_wdt.c @@ -1,16 +1,8 @@ -// Copyright 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: 2018-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "soc/rtc_wdt.h" #include "soc/rtc.h" diff --git a/components/esp_hw_support/port/esp32s2/spiram.c b/components/esp_hw_support/port/esp32s2/spiram.c index 23cbd137bc..ebb2be078b 100644 --- a/components/esp_hw_support/port/esp32s2/spiram.c +++ b/components/esp_hw_support/port/esp32s2/spiram.c @@ -3,19 +3,11 @@ Abstraction layer for spi-ram. For now, it's no more than a stub for the spiram_ we add more types of external RAM memory, this can be made into a more intelligent dispatcher. */ -// Copyright 2015-2017 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -52,99 +44,36 @@ static const char* TAG = "spiram"; static bool spiram_inited=false; -/* - Simple RAM test. Writes a word every 32 bytes. Takes about a second to complete for 4MiB. Returns - true when RAM seems OK, false when test fails. WARNING: Do not run this before the 2nd cpu has been - initialized (in a two-core system) or after the heap allocator has taken ownership of the memory. -*/ -bool esp_spiram_test(void) -{ - size_t spiram_size = esp_spiram_get_size(); - volatile int *spiram=(volatile int*)(SOC_EXTRAM_DATA_HIGH - spiram_size); - size_t p; - size_t s = spiram_size; - int errct=0; - int initial_err=-1; - - if (SOC_EXTRAM_DATA_SIZE < spiram_size) { - ESP_EARLY_LOGW(TAG, "Only test spiram from %08x to %08x\n", SOC_EXTRAM_DATA_LOW, SOC_EXTRAM_DATA_HIGH); - spiram=(volatile int*)SOC_EXTRAM_DATA_LOW; - s = SOC_EXTRAM_DATA_SIZE; - } - for (p=0; p<(s/sizeof(int)); p+=8) { - spiram[p]=p^0xAAAAAAAA; - } - for (p=0; p<(s/sizeof(int)); p+=8) { - if (spiram[p]!=(p^0xAAAAAAAA)) { - errct++; - if (errct==1) initial_err=p*4; - if (errct < 4) { - ESP_EARLY_LOGE(TAG, "SPI SRAM error@%08x:%08x/%08x \n", &spiram[p], spiram[p], p^0xAAAAAAAA); - } - } - } - if (errct) { - ESP_EARLY_LOGE(TAG, "SPI SRAM memory test fail. %d/%d writes failed, first @ %X\n", errct, s/32, initial_err+SOC_EXTRAM_DATA_LOW); - return false; - } else { - ESP_EARLY_LOGI(TAG, "SPI SRAM memory test OK"); - return true; - } -} - #define DRAM0_ONLY_CACHE_SIZE BUS_IRAM0_CACHE_SIZE -#define DRAM0_DRAM1_CACHE_SIZE (BUS_IRAM0_CACHE_SIZE + BUS_IRAM1_CACHE_SIZE) +#define DRAM0_DRAM1_CACHE_SIZE (BUS_IRAM0_CACHE_SIZE + BUS_IRAM1_CACHE_SIZE) #define DRAM0_DRAM1_DPORT_CACHE_SIZE (BUS_IRAM0_CACHE_SIZE + BUS_IRAM1_CACHE_SIZE + BUS_DPORT_CACHE_SIZE) -#define DBUS3_ONLY_CACHE_SIZE BUS_AHB_DBUS3_CACHE_SIZE -#define DRAM0_DRAM1_DPORT_DBUS3_CACHE_SIZE (DRAM0_DRAM1_DPORT_CACHE_SIZE + DBUS3_ONLY_CACHE_SIZE) +#define SPIRAM_SIZE_EXC_DRAM0_DRAM1_DPORT (spiram_size - DRAM0_DRAM1_DPORT_CACHE_SIZE) -#define SPIRAM_SIZE_EXC_DRAM0_DRAM1_DPORT (spiram_size - DRAM0_DRAM1_DPORT_CACHE_SIZE) -#define SPIRAM_SIZE_EXC_DATA_CACHE (spiram_size - DRAM0_DRAM1_DPORT_DBUS3_CACHE_SIZE) +#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY +extern uint8_t _ext_ram_bss_start, _ext_ram_bss_end; +#define ALIGN_UP_BY(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) +#define EXT_BSS_SIZE ((uint32_t)(&_ext_ram_bss_end - &_ext_ram_bss_start)) +#define EXT_BSS_PAGE_ALIGN_SIZE (ALIGN_UP_BY(EXT_BSS_SIZE, 0x10000)) +#endif -#define SPIRAM_SMALL_SIZE_MAP_VADDR (DRAM0_CACHE_ADDRESS_HIGH - spiram_size) -#define SPIRAM_SMALL_SIZE_MAP_PADDR 0 -#define SPIRAM_SMALL_SIZE_MAP_SIZE spiram_size +#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY +#define SPIRAM_MAP_PADDR_START EXT_BSS_PAGE_ALIGN_SIZE +#define FREE_DRAM0_DRAM1_DPORT_CACHE_START (DPORT_CACHE_ADDRESS_LOW + EXT_BSS_PAGE_ALIGN_SIZE) +#define FREE_DRAM0_DRAM1_DPORT_CACHE_SIZE (DRAM0_DRAM1_DPORT_CACHE_SIZE - EXT_BSS_PAGE_ALIGN_SIZE) +#else +#define SPIRAM_MAP_PADDR_START 0 +#define FREE_DRAM0_DRAM1_DPORT_CACHE_START (DPORT_CACHE_ADDRESS_LOW) +#define FREE_DRAM0_DRAM1_DPORT_CACHE_SIZE (DRAM0_DRAM1_DPORT_CACHE_SIZE) +#endif // if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY -#define SPIRAM_MID_SIZE_MAP_VADDR (AHB_DBUS3_ADDRESS_HIGH - SPIRAM_SIZE_EXC_DRAM0_DRAM1_DPORT) -#define SPIRAM_MID_SIZE_MAP_PADDR 0 -#define SPIRAM_MID_SIZE_MAP_SIZE (SPIRAM_SIZE_EXC_DRAM0_DRAM1_DPORT) +#define SPIRAM_MAP_VADDR_START (DRAM0_CACHE_ADDRESS_HIGH - spiram_map_size) +#define SPIRAM_MAP_SIZE spiram_map_size -#define SPIRAM_BIG_SIZE_MAP_VADDR AHB_DBUS3_ADDRESS_LOW -#define SPIRAM_BIG_SIZE_MAP_PADDR (AHB_DBUS3_ADDRESS_HIGH - DRAM0_DRAM1_DPORT_DBUS3_CACHE_SIZE) -#define SPIRAM_BIG_SIZE_MAP_SIZE DBUS3_ONLY_CACHE_SIZE - -#define SPIRAM_MID_BIG_SIZE_MAP_VADDR DPORT_CACHE_ADDRESS_LOW -#define SPIRAM_MID_BIG_SIZE_MAP_PADDR SPIRAM_SIZE_EXC_DRAM0_DRAM1_DPORT -#define SPIRAM_MID_BIG_SIZE_MAP_SIZE DRAM0_DRAM1_DPORT_DBUS3_CACHE_SIZE - -void IRAM_ATTR esp_spiram_init_cache(void) -{ - size_t spiram_size = esp_spiram_get_size(); - Cache_Suspend_DCache(); - /* map the address from SPIRAM end to the start, map the address in order: DRAM1, DRAM1, DPORT, DBUS3 */ - if (spiram_size <= DRAM0_ONLY_CACHE_SIZE) { - /* cache size <= 3MB + 512 KB, only map DRAM0 bus */ - Cache_Dbus_MMU_Set(MMU_ACCESS_SPIRAM, SPIRAM_SMALL_SIZE_MAP_VADDR, SPIRAM_SMALL_SIZE_MAP_PADDR, 64, SPIRAM_SMALL_SIZE_MAP_SIZE >> 16, 0); - REG_CLR_BIT(EXTMEM_PRO_DCACHE_CTRL1_REG, EXTMEM_PRO_DCACHE_MASK_DRAM0); - } else if (spiram_size <= DRAM0_DRAM1_CACHE_SIZE) { - /* cache size <= 7MB + 512KB, only map DRAM0 and DRAM1 bus */ - Cache_Dbus_MMU_Set(MMU_ACCESS_SPIRAM, SPIRAM_SMALL_SIZE_MAP_VADDR, SPIRAM_SMALL_SIZE_MAP_PADDR, 64, SPIRAM_SMALL_SIZE_MAP_SIZE >> 16, 0); - REG_CLR_BIT(EXTMEM_PRO_DCACHE_CTRL1_REG, EXTMEM_PRO_DCACHE_MASK_DRAM1 | EXTMEM_PRO_DCACHE_MASK_DRAM0); - } else if (spiram_size <= DRAM0_DRAM1_DPORT_CACHE_SIZE) { - /* cache size <= 10MB + 512KB, map DRAM0, DRAM1, DPORT bus */ - Cache_Dbus_MMU_Set(MMU_ACCESS_SPIRAM, SPIRAM_SMALL_SIZE_MAP_VADDR, SPIRAM_SMALL_SIZE_MAP_PADDR, 64, SPIRAM_SMALL_SIZE_MAP_SIZE >> 16, 0); - REG_CLR_BIT(EXTMEM_PRO_DCACHE_CTRL1_REG, EXTMEM_PRO_DCACHE_MASK_DRAM1 | EXTMEM_PRO_DCACHE_MASK_DRAM0 | EXTMEM_PRO_DCACHE_MASK_DPORT); - } else { - /* cache size > 10MB + 512KB, map DRAM0, DRAM1, DPORT bus , only remap 0x3f500000 ~ 0x3ff90000*/ - Cache_Dbus_MMU_Set(MMU_ACCESS_SPIRAM, DPORT_CACHE_ADDRESS_LOW, SPIRAM_SMALL_SIZE_MAP_PADDR, 64, DRAM0_DRAM1_DPORT_CACHE_SIZE >> 16, 0); - REG_CLR_BIT(EXTMEM_PRO_DCACHE_CTRL1_REG, EXTMEM_PRO_DCACHE_MASK_DRAM1 | EXTMEM_PRO_DCACHE_MASK_DRAM0 | EXTMEM_PRO_DCACHE_MASK_DPORT); - } - Cache_Resume_DCache(0); -} - -static uint32_t pages_for_flash = 0; -static uint32_t instrcution_in_spiram = 0; +static uint32_t next_map_page_num = 0; +static uint32_t instruction_in_spiram = 0; static uint32_t rodata_in_spiram = 0; +static size_t spiram_size = 0; +static size_t spiram_map_size = 0; #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS static int instr_flash2spiram_offs = 0; @@ -163,9 +92,44 @@ static uint32_t page0_mapped = 0; static uint32_t page0_page = INVALID_PHY_PAGE; #endif +void IRAM_ATTR esp_spiram_init_cache(void) +{ + spiram_map_size = spiram_size; + Cache_Suspend_DCache(); + +#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY + /*if instruction or rodata in flash will be load to spiram, some subsequent operations require the start + address to be aligned by page, so allocate N pages address space for spiram's bss*/ + Cache_Dbus_MMU_Set(MMU_ACCESS_SPIRAM, DPORT_CACHE_ADDRESS_LOW, 0, 64, EXT_BSS_PAGE_ALIGN_SIZE >> 16, 0); + REG_CLR_BIT(EXTMEM_PRO_DCACHE_CTRL1_REG, EXTMEM_PRO_DCACHE_MASK_DPORT); + next_map_page_num += (EXT_BSS_PAGE_ALIGN_SIZE >> 16); + spiram_map_size -= EXT_BSS_PAGE_ALIGN_SIZE; +#endif + + /* map the address from SPIRAM end to the start, map the address in order: DRAM0, DRAM1, DPORT */ + if (spiram_map_size <= DRAM0_ONLY_CACHE_SIZE) { + /* psram need to be mapped vaddr size <= 3MB + 512 KB, only map DRAM0 bus */ + Cache_Dbus_MMU_Set(MMU_ACCESS_SPIRAM, SPIRAM_MAP_VADDR_START, SPIRAM_MAP_PADDR_START, 64, SPIRAM_MAP_SIZE >> 16, 0); + REG_CLR_BIT(EXTMEM_PRO_DCACHE_CTRL1_REG, EXTMEM_PRO_DCACHE_MASK_DRAM0); + } else if (spiram_map_size <= DRAM0_DRAM1_CACHE_SIZE) { + /* psram need to be mapped vaddr size <= 7MB + 512KB, only map DRAM0 and DRAM1 bus */ + Cache_Dbus_MMU_Set(MMU_ACCESS_SPIRAM, SPIRAM_MAP_VADDR_START, SPIRAM_MAP_PADDR_START, 64, SPIRAM_MAP_SIZE >> 16, 0); + REG_CLR_BIT(EXTMEM_PRO_DCACHE_CTRL1_REG, EXTMEM_PRO_DCACHE_MASK_DRAM1 | EXTMEM_PRO_DCACHE_MASK_DRAM0); + } else if (spiram_size <= DRAM0_DRAM1_DPORT_CACHE_SIZE) { // Equivalent to {spiram_map_size < DRAM0_DRAM1_DPORT_CACHE_SIZE - (spiram_size - spiram_map_size)/*bss size*/} + /* psram need to be mapped vaddr size <= 10MB + 512KB - bss_page_align_size, map DRAM0, DRAM1, DPORT bus */ + Cache_Dbus_MMU_Set(MMU_ACCESS_SPIRAM, SPIRAM_MAP_VADDR_START, SPIRAM_MAP_PADDR_START, 64, SPIRAM_MAP_SIZE >> 16, 0); + REG_CLR_BIT(EXTMEM_PRO_DCACHE_CTRL1_REG, EXTMEM_PRO_DCACHE_MASK_DRAM1 | EXTMEM_PRO_DCACHE_MASK_DRAM0 | EXTMEM_PRO_DCACHE_MASK_DPORT); + } else { + /* psram need to be mapped vaddr size > 10MB + 512KB - bss_page_align_size, map DRAM0, DRAM1, DPORT bus ,discard the memory in the end of spiram */ + Cache_Dbus_MMU_Set(MMU_ACCESS_SPIRAM, FREE_DRAM0_DRAM1_DPORT_CACHE_START, SPIRAM_MAP_PADDR_START, 64, FREE_DRAM0_DRAM1_DPORT_CACHE_SIZE >> 16, 0); + REG_CLR_BIT(EXTMEM_PRO_DCACHE_CTRL1_REG, EXTMEM_PRO_DCACHE_MASK_DRAM1 | EXTMEM_PRO_DCACHE_MASK_DRAM0 | EXTMEM_PRO_DCACHE_MASK_DPORT); + } + Cache_Resume_DCache(0); +} + uint32_t esp_spiram_instruction_access_enabled(void) { - return instrcution_in_spiram; + return instruction_in_spiram; } uint32_t esp_spiram_rodata_access_enabled(void) @@ -176,23 +140,22 @@ uint32_t esp_spiram_rodata_access_enabled(void) #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS esp_err_t esp_spiram_enable_instruction_access(void) { - size_t spiram_size = esp_spiram_get_size(); uint32_t pages_in_flash = 0; pages_in_flash += Cache_Count_Flash_Pages(PRO_CACHE_IBUS0, &page0_mapped); pages_in_flash += Cache_Count_Flash_Pages(PRO_CACHE_IBUS1, &page0_mapped); - if ((pages_in_flash + pages_for_flash) > (spiram_size >> 16)) { - ESP_EARLY_LOGE(TAG, "SPI RAM space not enough for the instructions, has %d pages, need %d pages.", (spiram_size >> 16), (pages_in_flash + pages_for_flash)); + if ((pages_in_flash + next_map_page_num) > (spiram_size >> 16)) { + ESP_EARLY_LOGE(TAG, "SPI RAM space not enough for the instructions, has %d pages, need %d pages.", (spiram_size >> 16), (pages_in_flash + next_map_page_num)); return ESP_FAIL; } ESP_EARLY_LOGI(TAG, "Instructions copied and mapped to SPIRAM"); uint32_t instr_mmu_offset = ((uint32_t)&_instruction_reserved_start & 0xFFFFFF)/MMU_PAGE_SIZE; uint32_t mmu_value = *(volatile uint32_t *)(DR_REG_MMU_TABLE + PRO_CACHE_IBUS0_MMU_START + instr_mmu_offset*sizeof(uint32_t)); mmu_value &= MMU_ADDRESS_MASK; - instr_flash2spiram_offs = mmu_value - pages_for_flash; - ESP_EARLY_LOGV(TAG, "Instructions from flash page%d copy to SPIRAM page%d, Offset: %d", mmu_value, pages_for_flash, instr_flash2spiram_offs); - pages_for_flash = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_IBUS0, IRAM0_ADDRESS_LOW, pages_for_flash, &page0_page); - pages_for_flash = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_IBUS1, IRAM1_ADDRESS_LOW, pages_for_flash, &page0_page); - instrcution_in_spiram = 1; + instr_flash2spiram_offs = mmu_value - next_map_page_num; + ESP_EARLY_LOGV(TAG, "Instructions from flash page%d copy to SPIRAM page%d, Offset: %d", mmu_value, next_map_page_num, instr_flash2spiram_offs); + next_map_page_num = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_IBUS0, IRAM0_ADDRESS_LOW, next_map_page_num, &page0_page); + next_map_page_num = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_IBUS1, IRAM1_ADDRESS_LOW, next_map_page_num, &page0_page); + instruction_in_spiram = 1; return ESP_OK; } #endif @@ -206,7 +169,7 @@ esp_err_t esp_spiram_enable_rodata_access(void) pages_in_flash += Cache_Count_Flash_Pages(PRO_CACHE_DBUS1, &page0_mapped); pages_in_flash += Cache_Count_Flash_Pages(PRO_CACHE_DBUS2, &page0_mapped); - if ((pages_in_flash + pages_for_flash) > (esp_spiram_get_size() >> 16)) { + if ((pages_in_flash + next_map_page_num) > (spiram_size >> 16)) { ESP_EARLY_LOGE(TAG, "SPI RAM space not enough for the read only data."); return ESP_FAIL; } @@ -215,12 +178,12 @@ esp_err_t esp_spiram_enable_rodata_access(void) uint32_t rodata_mmu_offset = ((uint32_t)&_rodata_reserved_start & 0xFFFFFF)/MMU_PAGE_SIZE; uint32_t mmu_value = *(volatile uint32_t *)(DR_REG_MMU_TABLE + PRO_CACHE_IBUS2_MMU_START + rodata_mmu_offset*sizeof(uint32_t)); mmu_value &= MMU_ADDRESS_MASK; - rodata_flash2spiram_offs = mmu_value - pages_for_flash; - ESP_EARLY_LOGV(TAG, "Rodata from flash page%d copy to SPIRAM page%d, Offset: %d", mmu_value, pages_for_flash, rodata_flash2spiram_offs); - pages_for_flash = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_IBUS2, DROM0_ADDRESS_LOW, pages_for_flash, &page0_page); - pages_for_flash = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_DBUS0, DRAM0_ADDRESS_LOW, pages_for_flash, &page0_page); - pages_for_flash = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_DBUS1, DRAM1_ADDRESS_LOW, pages_for_flash, &page0_page); - pages_for_flash = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_DBUS2, DPORT_ADDRESS_LOW, pages_for_flash, &page0_page); + rodata_flash2spiram_offs = mmu_value - next_map_page_num; + ESP_EARLY_LOGV(TAG, "Rodata from flash page%d copy to SPIRAM page%d, Offset: %d", mmu_value, next_map_page_num, rodata_flash2spiram_offs); + next_map_page_num = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_IBUS2, DROM0_ADDRESS_LOW, next_map_page_num, &page0_page); + next_map_page_num = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_DBUS0, DRAM0_ADDRESS_LOW, next_map_page_num, &page0_page); + next_map_page_num = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_DBUS1, DRAM1_ADDRESS_LOW, next_map_page_num, &page0_page); + next_map_page_num = Cache_Flash_To_SPIRAM_Copy(PRO_CACHE_DBUS2, DPORT_ADDRESS_LOW, next_map_page_num, &page0_page); rodata_in_spiram = 1; return ESP_OK; } @@ -293,7 +256,7 @@ esp_err_t esp_spiram_init(void) spiram_inited = true; - size_t spiram_size = esp_spiram_get_size(); + spiram_size = esp_spiram_get_size(); #if (CONFIG_SPIRAM_SIZE != -1) if (spiram_size != CONFIG_SPIRAM_SIZE) { @@ -316,30 +279,58 @@ esp_err_t esp_spiram_init(void) esp_err_t esp_spiram_add_to_heapalloc(void) { - size_t spiram_size = esp_spiram_get_size(); - uint32_t size_for_flash = (pages_for_flash << 16); - intptr_t vaddr; - ESP_EARLY_LOGI(TAG, "Adding pool of %dK of external SPI memory to heap allocator", (spiram_size - (pages_for_flash << 16))/1024); - //Add entire external RAM region to heap allocator. Heap allocator knows the capabilities of this type of memory, so there's - //no need to explicitly specify them. + size_t recycle_pages_size = 0; + size_t map_size = 0; + intptr_t map_vaddr, map_paddr; + ESP_EARLY_LOGI(TAG, "Adding pool of %dK of external SPI memory to heap allocator", (spiram_size - (next_map_page_num << 16))/1024); +#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY + if(EXT_BSS_SIZE){ + ESP_EARLY_LOGI(TAG, "Adding pool of %d Byte(spiram .bss page unused area) of external SPI memory to heap allocator", EXT_BSS_PAGE_ALIGN_SIZE - EXT_BSS_SIZE); + esp_err_t err_status = heap_caps_add_region(DPORT_CACHE_ADDRESS_LOW + EXT_BSS_SIZE, FREE_DRAM0_DRAM1_DPORT_CACHE_START - 1); + if (err_status != ESP_OK){ + return err_status; + } + } +#endif + +#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS || CONFIG_SPIRAM_RODATA + /* Part of the physical address space in spiram is mapped by IRAM0/DROM0, + so the DPORT_DRAM0_DRAM1 address space of the same size can be released */ + uint32_t occupied_pages_size = (next_map_page_num << 16); + recycle_pages_size = occupied_pages_size - SPIRAM_MAP_PADDR_START; +#endif + + // Small size: means DPORT_DRAM0_DRAM1 bus virtrual address space larger than the spiram size if (spiram_size <= DRAM0_DRAM1_DPORT_CACHE_SIZE) { - /* cache size <= 10MB + 512KB, map DRAM0, DRAM1, DPORT bus */ - vaddr = SPIRAM_SMALL_SIZE_MAP_VADDR; - return heap_caps_add_region(vaddr + size_for_flash, vaddr + spiram_size - 1); + map_vaddr = SPIRAM_MAP_VADDR_START; + return heap_caps_add_region(map_vaddr + recycle_pages_size, map_vaddr + spiram_map_size - 1); // pass rodata & instruction section } - vaddr = DPORT_CACHE_ADDRESS_LOW; - Cache_Dbus_MMU_Set(MMU_ACCESS_SPIRAM, vaddr, SPIRAM_SMALL_SIZE_MAP_PADDR, 64, DRAM0_DRAM1_DPORT_CACHE_SIZE >> 16, 0); - if (size_for_flash <= SPIRAM_SIZE_EXC_DRAM0_DRAM1_DPORT) { - return heap_caps_add_region(vaddr, vaddr + DRAM0_DRAM1_DPORT_CACHE_SIZE - 1); + // Middle size: means DPORT_DRAM0_DRAM1 bus virtrual address space less than the + // spiram size, but after releasing the virtual address space mapped + // from the rodata or instruction copied from the flash, the released + // virtual address space is enough to map the abandoned physical address + // space in spiram + if (recycle_pages_size >= SPIRAM_SIZE_EXC_DRAM0_DRAM1_DPORT) { + map_vaddr = SPIRAM_MAP_VADDR_START + recycle_pages_size; + map_paddr = SPIRAM_MAP_PADDR_START + recycle_pages_size; + map_size = SPIRAM_MAP_SIZE - recycle_pages_size; + Cache_Dbus_MMU_Set(MMU_ACCESS_SPIRAM, map_vaddr, map_paddr, 64, map_size >> 16, 0); + return heap_caps_add_region(map_vaddr , map_vaddr + map_size - 1); } - // Largest size - return heap_caps_add_region(vaddr + size_for_flash, vaddr + DRAM0_DRAM1_DPORT_CACHE_SIZE -1); + // Large size: means after releasing the virtual address space mapped from the rodata + // or instruction copied from the flash, the released virtual address space + // still not enough to map the abandoned physical address space in spiram, + // so use all the virtual address space as much as possible + map_vaddr = FREE_DRAM0_DRAM1_DPORT_CACHE_START; + map_paddr = SPIRAM_MAP_PADDR_START + recycle_pages_size; + map_size = FREE_DRAM0_DRAM1_DPORT_CACHE_SIZE; + Cache_Dbus_MMU_Set(MMU_ACCESS_SPIRAM, map_vaddr, map_paddr, 64, map_size >> 16, 0); + return heap_caps_add_region(map_vaddr, map_vaddr + FREE_DRAM0_DRAM1_DPORT_CACHE_SIZE -1); } - static uint8_t *dma_heap; esp_err_t esp_spiram_reserve_dma_pool(size_t size) { @@ -386,4 +377,48 @@ bool esp_spiram_is_initialized(void) return spiram_inited; } +uint8_t esp_spiram_get_cs_io(void) +{ + return psram_get_cs_io(); +} + +/* + Simple RAM test. Writes a word every 32 bytes. Takes about a second to complete for 4MiB. Returns + true when RAM seems OK, false when test fails. WARNING: Do not run this before the 2nd cpu has been + initialized (in a two-core system) or after the heap allocator has taken ownership of the memory. +*/ +bool esp_spiram_test(void) +{ + volatile int *spiram = (volatile int*)(SOC_EXTRAM_DATA_HIGH - spiram_map_size); + size_t p; + size_t s = spiram_map_size; + int errct=0; + int initial_err=-1; + + if (SOC_EXTRAM_DATA_SIZE < spiram_map_size) { + ESP_EARLY_LOGW(TAG, "Only test spiram from %08x to %08x\n", SOC_EXTRAM_DATA_LOW, SOC_EXTRAM_DATA_HIGH); + spiram=(volatile int*)SOC_EXTRAM_DATA_LOW; + s = SOC_EXTRAM_DATA_SIZE; + } + for (p=0; p<(s/sizeof(int)); p+=8) { + spiram[p]=p^0xAAAAAAAA; + } + for (p=0; p<(s/sizeof(int)); p+=8) { + if (spiram[p]!=(p^0xAAAAAAAA)) { + errct++; + if (errct==1) initial_err=p*4; + if (errct < 4) { + ESP_EARLY_LOGE(TAG, "SPI SRAM error@%08x:%08x/%08x \n", &spiram[p], spiram[p], p^0xAAAAAAAA); + } + } + } + if (errct) { + ESP_EARLY_LOGE(TAG, "SPI SRAM memory test fail. %d/%d writes failed, first @ %X\n", errct, s/32, initial_err+SOC_EXTRAM_DATA_LOW); + return false; + } else { + ESP_EARLY_LOGI(TAG, "SPI SRAM memory test OK"); + return true; + } +} + #endif diff --git a/components/esp_hw_support/port/esp32s2/spiram_psram.c b/components/esp_hw_support/port/esp32s2/spiram_psram.c index b6bd73c70a..bb40c9f781 100644 --- a/components/esp_hw_support/port/esp32s2/spiram_psram.c +++ b/components/esp_hw_support/port/esp32s2/spiram_psram.c @@ -2,19 +2,11 @@ Driver bits for PSRAM chips (at the moment only the ESP-PSRAM32 chip). */ -// Copyright 2013-2017 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: 2013-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "sdkconfig.h" @@ -33,7 +25,7 @@ #include "soc/efuse_periph.h" #include "soc/soc_caps.h" #include "soc/io_mux_reg.h" -#include "soc/apb_ctrl_reg.h" +#include "soc/syscon_reg.h" #include "soc/efuse_reg.h" #include "soc/soc.h" #include "driver/gpio.h" @@ -168,6 +160,13 @@ static uint32_t s_psram_id = 0; static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psram_vaddr_mode_t vaddrmode); extern void esp_rom_spi_set_op_mode(int spi_num, esp_rom_spiflash_read_mode_t mode); +static uint8_t s_psram_cs_io = (uint8_t)-1; + +uint8_t psram_get_cs_io(void) +{ + return s_psram_cs_io; +} + static void psram_set_op_mode(int spi_num, psram_cmd_mode_t mode) { if (mode == PSRAM_CMD_QPI) { @@ -375,6 +374,7 @@ static void IRAM_ATTR psram_gpio_config(psram_cache_mode_t mode) psram_io.psram_spiwp_sd3_io = esp_rom_efuse_get_flash_wp_gpio(); } esp_rom_spiflash_select_qio_pins(psram_io.psram_spiwp_sd3_io, spiconfig); + s_psram_cs_io = psram_io.psram_cs_io; } psram_size_t psram_get_size(void) diff --git a/components/esp_hw_support/port/esp32s2/spiram_psram.h b/components/esp_hw_support/port/esp32s2/spiram_psram.h index ea7908f030..819bdc6203 100644 --- a/components/esp_hw_support/port/esp32s2/spiram_psram.h +++ b/components/esp_hw_support/port/esp32s2/spiram_psram.h @@ -1,16 +1,8 @@ -// 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. +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _PSRAM_H @@ -76,5 +68,11 @@ typedef enum { esp_err_t esp_spiram_wrap_set(spiram_wrap_mode_t mode); +/** + * @brief get psram CS IO + * + * @return psram CS IO + */ +uint8_t psram_get_cs_io(void); #endif diff --git a/components/esp_hw_support/port/esp32s3/CMakeLists.txt b/components/esp_hw_support/port/esp32s3/CMakeLists.txt index 5d65ede6e6..e375c6df6d 100644 --- a/components/esp_hw_support/port/esp32s3/CMakeLists.txt +++ b/components/esp_hw_support/port/esp32s3/CMakeLists.txt @@ -10,14 +10,16 @@ set(srcs "rtc_time.c" "rtc_wdt.c" "chip_info.c" - ) + ) if(NOT BOOTLOADER_BUILD) list(APPEND srcs "../async_memcpy_impl_gdma.c" - "dport_access.c" - "esp_crypto_lock.c" - "memprot.c" - "spiram.c") + "dport_access.c" + "esp_hmac.c" + "esp_ds.c" + "esp_crypto_lock.c" + "memprot.c" + "spiram.c") if(CONFIG_SPIRAM_MODE_QUAD) list(APPEND srcs "spiram_psram.c") diff --git a/components/esp_hw_support/port/esp32s3/chip_info.c b/components/esp_hw_support/port/esp32s3/chip_info.c index aaa9c73a18..115a20f561 100644 --- a/components/esp_hw_support/port/esp32s3/chip_info.c +++ b/components/esp_hw_support/port/esp32s3/chip_info.c @@ -1,16 +1,8 @@ -// Copyright 2013-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: 2013-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "esp_chip_info.h" diff --git a/components/esp_hw_support/port/esp32s3/dport_access.c b/components/esp_hw_support/port/esp32s3/dport_access.c index 51bc5b4623..ab24c510a5 100644 --- a/components/esp_hw_support/port/esp32s3/dport_access.c +++ b/components/esp_hw_support/port/esp32s3/dport_access.c @@ -1,16 +1,8 @@ -// Copyright 2010-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: 2010-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include diff --git a/components/esp_hw_support/port/esp32s3/esp_crypto_lock.c b/components/esp_hw_support/port/esp32s3/esp_crypto_lock.c index 98fa6296ce..a8ca5212f1 100644 --- a/components/esp_hw_support/port/esp32s3/esp_crypto_lock.c +++ b/components/esp_hw_support/port/esp32s3/esp_crypto_lock.c @@ -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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include @@ -24,20 +16,44 @@ HMAC: needs SHA DS: needs HMAC (which needs SHA), AES and MPI */ -/* Single lock for SHA and AES, sharing a reserved GDMA channel */ -static _lock_t s_crypto_sha_aes_lock; +/* + * Single lock for SHA, HMAC, DS and AES peripherals. + * SHA and AES share a reserved GDMA channel. + * DS uses HMAC, HMAC uses SHA, so they may also not be used simulaneously. + */ +static _lock_t s_crypto_sha_aes_hmac_ds_lock; /* Lock for the MPI/RSA peripheral, also used by the DS peripheral */ static _lock_t s_crypto_mpi_lock; +void esp_crypto_ds_lock_acquire(void) +{ + _lock_acquire_recursive(&s_crypto_sha_aes_hmac_ds_lock); +} + +void esp_crypto_ds_lock_release(void) +{ + _lock_release_recursive(&s_crypto_sha_aes_hmac_ds_lock); +} + +void esp_crypto_hmac_lock_acquire(void) +{ + _lock_acquire_recursive(&s_crypto_sha_aes_hmac_ds_lock); +} + +void esp_crypto_hmac_lock_release(void) +{ + _lock_release_recursive(&s_crypto_sha_aes_hmac_ds_lock); +} + void esp_crypto_sha_aes_lock_acquire(void) { - _lock_acquire(&s_crypto_sha_aes_lock); + _lock_acquire_recursive(&s_crypto_sha_aes_hmac_ds_lock); } void esp_crypto_sha_aes_lock_release(void) { - _lock_release(&s_crypto_sha_aes_lock); + _lock_release_recursive(&s_crypto_sha_aes_hmac_ds_lock); } void esp_crypto_mpi_lock_acquire(void) diff --git a/components/esp_hw_support/port/esp32s3/esp_ds.c b/components/esp_hw_support/port/esp32s3/esp_ds.c new file mode 100644 index 0000000000..90385de752 --- /dev/null +++ b/components/esp_hw_support/port/esp32s3/esp_ds.c @@ -0,0 +1,228 @@ +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/periph_ctrl.h" +#include "esp_crypto_lock.h" +#include "hal/ds_hal.h" +#include "hal/ds_ll.h" +#include "hal/hmac_hal.h" +#include "esp32s3/rom/digital_signature.h" +#include "esp_timer.h" +#include "esp_ds.h" + +struct esp_ds_context { + const esp_ds_data_t *data; +}; + +/** + * The vtask delay \c esp_ds_sign() is using while waiting for completion of the signing operation. + */ +#define ESP_DS_SIGN_TASK_DELAY_MS 10 + +#define RSA_LEN_MAX 127 + +/* + * esp_digital_signature_length_t is used in esp_ds_data_t in contrast to ets_ds_data_t, where unsigned is used. + * Check esp_digital_signature_length_t's width here because it's converted to unsigned using raw casts. + */ +_Static_assert(sizeof(esp_digital_signature_length_t) == sizeof(unsigned), + "The size of esp_digital_signature_length_t and unsigned has to be the same"); + +/* + * esp_ds_data_t is used in the encryption function but casted to ets_ds_data_t. + * Check esp_ds_data_t's width here because it's converted using raw casts. + */ +_Static_assert(sizeof(esp_ds_data_t) == sizeof(ets_ds_data_t), + "The size of esp_ds_data_t and ets_ds_data_t has to be the same"); + +static void ds_acquire_enable(void) +{ + esp_crypto_ds_lock_acquire(); + esp_crypto_mpi_lock_acquire(); + + // We also enable SHA and HMAC here. SHA is used by HMAC, HMAC is used by DS. + periph_module_enable(PERIPH_HMAC_MODULE); + periph_module_enable(PERIPH_SHA_MODULE); + periph_module_enable(PERIPH_DS_MODULE); + + hmac_hal_start(); +} + +static void ds_disable_release(void) +{ + ds_hal_finish(); + + periph_module_disable(PERIPH_DS_MODULE); + periph_module_disable(PERIPH_SHA_MODULE); + periph_module_disable(PERIPH_HMAC_MODULE); + + esp_crypto_mpi_lock_release(); + esp_crypto_ds_lock_release(); +} + +esp_err_t esp_ds_sign(const void *message, + const esp_ds_data_t *data, + hmac_key_id_t key_id, + void *signature) +{ + // Need to check signature here, otherwise the signature is only checked when the signing has finished and fails + // but the signing isn't uninitialized and the mutex is still locked. + if (!signature) { + return ESP_ERR_INVALID_ARG; + } + + esp_ds_context_t *context; + esp_err_t result = esp_ds_start_sign(message, data, key_id, &context); + if (result != ESP_OK) { + return result; + } + + while (esp_ds_is_busy()) { + vTaskDelay(ESP_DS_SIGN_TASK_DELAY_MS / portTICK_PERIOD_MS); + } + + return esp_ds_finish_sign(signature, context); +} + +esp_err_t esp_ds_start_sign(const void *message, + const esp_ds_data_t *data, + hmac_key_id_t key_id, + esp_ds_context_t **esp_ds_ctx) +{ + if (!message || !data || !esp_ds_ctx) { + return ESP_ERR_INVALID_ARG; + } + + if (key_id >= HMAC_KEY_MAX) { + return ESP_ERR_INVALID_ARG; + } + + if (!(data->rsa_length == ESP_DS_RSA_1024 + || data->rsa_length == ESP_DS_RSA_2048 + || data->rsa_length == ESP_DS_RSA_3072 + || data->rsa_length == ESP_DS_RSA_4096)) { + return ESP_ERR_INVALID_ARG; + } + + ds_acquire_enable(); + + // initiate hmac + uint32_t conf_error = hmac_hal_configure(HMAC_OUTPUT_DS, key_id); + if (conf_error) { + ds_disable_release(); + return ESP32S3_ERR_HW_CRYPTO_DS_HMAC_FAIL; + } + + ds_hal_start(); + + // check encryption key from HMAC + int64_t start_time = esp_timer_get_time(); + while (ds_ll_busy() != 0) { + if ((esp_timer_get_time() - start_time) > SOC_DS_KEY_CHECK_MAX_WAIT_US) { + ds_disable_release(); + return ESP32S3_ERR_HW_CRYPTO_DS_INVALID_KEY; + } + } + + esp_ds_context_t *context = malloc(sizeof(esp_ds_context_t)); + if (!context) { + ds_disable_release(); + return ESP_ERR_NO_MEM; + } + + size_t rsa_len = (data->rsa_length + 1) * 4; + ds_hal_write_private_key_params(data->c); + ds_hal_configure_iv((uint32_t *)data->iv); + ds_hal_write_message(message, rsa_len); + + // initiate signing + ds_hal_start_sign(); + + context->data = data; + *esp_ds_ctx = context; + + return ESP_OK; +} + +bool esp_ds_is_busy(void) +{ + return ds_hal_busy(); +} + +esp_err_t esp_ds_finish_sign(void *signature, esp_ds_context_t *esp_ds_ctx) +{ + if (!signature || !esp_ds_ctx) { + return ESP_ERR_INVALID_ARG; + } + + const esp_ds_data_t *data = esp_ds_ctx->data; + unsigned rsa_len = (data->rsa_length + 1) * 4; + + while (ds_hal_busy()) { } + + ds_signature_check_t sig_check_result = ds_hal_read_result((uint8_t *) signature, (size_t) rsa_len); + + esp_err_t return_value = ESP_OK; + + if (sig_check_result == DS_SIGNATURE_MD_FAIL || sig_check_result == DS_SIGNATURE_PADDING_AND_MD_FAIL) { + return_value = ESP32S3_ERR_HW_CRYPTO_DS_INVALID_DIGEST; + } + + if (sig_check_result == DS_SIGNATURE_PADDING_FAIL) { + return_value = ESP32S3_ERR_HW_CRYPTO_DS_INVALID_PADDING; + } + + free(esp_ds_ctx); + + hmac_hal_clean(); + + ds_disable_release(); + + return return_value; +} + +esp_err_t esp_ds_encrypt_params(esp_ds_data_t *data, + const void *iv, + const esp_ds_p_data_t *p_data, + const void *key) +{ + if (!p_data) { + return ESP_ERR_INVALID_ARG; + } + + esp_err_t result = ESP_OK; + + esp_crypto_ds_lock_acquire(); + periph_module_enable(PERIPH_AES_MODULE); + periph_module_enable(PERIPH_DS_MODULE); + periph_module_enable(PERIPH_SHA_MODULE); + periph_module_enable(PERIPH_HMAC_MODULE); + periph_module_enable(PERIPH_RSA_MODULE); + + ets_ds_data_t *ds_data = (ets_ds_data_t *) data; + const ets_ds_p_data_t *ds_plain_data = (const ets_ds_p_data_t *) p_data; + + ets_ds_result_t ets_result = ets_ds_encrypt_params(ds_data, iv, ds_plain_data, key, ETS_DS_KEY_HMAC); + + if (ets_result == ETS_DS_INVALID_PARAM) { + result = ESP_ERR_INVALID_ARG; + } + + periph_module_disable(PERIPH_RSA_MODULE); + periph_module_disable(PERIPH_HMAC_MODULE); + periph_module_disable(PERIPH_SHA_MODULE); + periph_module_disable(PERIPH_DS_MODULE); + periph_module_disable(PERIPH_AES_MODULE); + esp_crypto_ds_lock_release(); + + return result; +} diff --git a/components/esp_hw_support/port/esp32s3/esp_hmac.c b/components/esp_hw_support/port/esp32s3/esp_hmac.c new file mode 100644 index 0000000000..73c3193a8d --- /dev/null +++ b/components/esp_hw_support/port/esp32s3/esp_hmac.c @@ -0,0 +1,181 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "driver/periph_ctrl.h" +#include "esp32s3/rom/efuse.h" +#include "esp32s3/rom/hmac.h" +#include "esp32s3/rom/ets_sys.h" +#include "esp_efuse.h" +#include "esp_efuse_table.h" +#include "esp_hmac.h" +#include "esp_log.h" +#include "esp_crypto_lock.h" +#include "soc/hwcrypto_reg.h" + +#include "hal/hmac_hal.h" + +#define SHA256_BLOCK_SZ 64 +#define SHA256_PAD_SZ 8 + +static const char *TAG = "esp_hmac"; + +/** + * @brief Apply the HMAC padding without the embedded length. + * + * @note This function does not check the data length, it is the responsibility of the other functions in this + * module to make sure that \c data_len is at most SHA256_BLOCK_SZ - 1 so the padding fits in. + * Otherwise, this function has undefined behavior. + * Note however, that for the actual HMAC implementation on ESP32S3, the length also needs to be applied at the end + * of the block. This function alone deosn't do that. + */ +static void write_and_padd(uint8_t *block, const uint8_t *data, uint16_t data_len) +{ + memcpy(block, data, data_len); + // Apply a one bit, followed by zero bits (refer to the ESP32S3 TRM). + block[data_len] = 0x80; + bzero(block + data_len + 1, SHA256_BLOCK_SZ - data_len - 1); +} + +esp_err_t esp_hmac_calculate(hmac_key_id_t key_id, + const void *message, + size_t message_len, + uint8_t *hmac) +{ + const uint8_t *message_bytes = (const uint8_t *)message; + + if (!message || !hmac) { + return ESP_ERR_INVALID_ARG; + } + if (key_id >= HMAC_KEY_MAX) { + return ESP_ERR_INVALID_ARG; + } + + esp_crypto_hmac_lock_acquire(); + + // We also enable SHA and DS here. SHA is used by HMAC, DS will otherwise hold SHA in reset state. + periph_module_enable(PERIPH_HMAC_MODULE); + periph_module_enable(PERIPH_SHA_MODULE); + periph_module_enable(PERIPH_DS_MODULE); + + hmac_hal_start(); + + uint32_t conf_error = hmac_hal_configure(HMAC_OUTPUT_USER, key_id); + if (conf_error) { + esp_crypto_hmac_lock_release(); + return ESP_FAIL; + } + + if (message_len + 1 + SHA256_PAD_SZ <= SHA256_BLOCK_SZ) { + // If message including padding is only one block... + // Last message block, so apply SHA-256 padding rules in software + uint8_t block[SHA256_BLOCK_SZ]; + uint64_t bit_len = __builtin_bswap64(message_len * 8 + 512); + + write_and_padd(block, message_bytes, message_len); + // Final block: append the bit length in this block and signal padding to peripheral + memcpy(block + SHA256_BLOCK_SZ - sizeof(bit_len), + &bit_len, sizeof(bit_len)); + hmac_hal_write_one_block_512(block); + } else { + // If message including padding is needs more than one block + + // write all blocks without padding except the last one + size_t remaining_blocks = message_len / SHA256_BLOCK_SZ; + for (int i = 1; i < remaining_blocks; i++) { + hmac_hal_write_block_512(message_bytes); + message_bytes += SHA256_BLOCK_SZ; + hmac_hal_next_block_normal(); + } + + // If message fits into one block but without padding, we must not write another block. + if (remaining_blocks) { + hmac_hal_write_block_512(message_bytes); + message_bytes += SHA256_BLOCK_SZ; + } + + size_t remaining = message_len % SHA256_BLOCK_SZ; + // Last message block, so apply SHA-256 padding rules in software + uint8_t block[SHA256_BLOCK_SZ]; + uint64_t bit_len = __builtin_bswap64(message_len * 8 + 512); + + // If the remaining message and appended padding doesn't fit into a single block, we have to write an + // extra block with the rest of the message and potential padding first. + if (remaining >= SHA256_BLOCK_SZ - SHA256_PAD_SZ) { + write_and_padd(block, message_bytes, remaining); + hmac_hal_next_block_normal(); + hmac_hal_write_block_512(block); + bzero(block, SHA256_BLOCK_SZ); + } else { + write_and_padd(block, message_bytes, remaining); + } + memcpy(block + SHA256_BLOCK_SZ - sizeof(bit_len), + &bit_len, sizeof(bit_len)); + hmac_hal_next_block_padding(); + hmac_hal_write_block_512(block); + } + + // Read back result (bit swapped) + hmac_hal_read_result_256(hmac); + + periph_module_disable(PERIPH_DS_MODULE); + periph_module_disable(PERIPH_SHA_MODULE); + periph_module_disable(PERIPH_HMAC_MODULE); + + esp_crypto_hmac_lock_release(); + + return ESP_OK; +} + +static ets_efuse_block_t convert_key_type(hmac_key_id_t key_id) { + return ETS_EFUSE_BLOCK_KEY0 + (ets_efuse_block_t) key_id; +} + +esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token) +{ + int ets_status; + esp_err_t err = ESP_OK; + + if ((!token) || (key_id >= HMAC_KEY_MAX)) + return ESP_ERR_INVALID_ARG; + + /* Check if JTAG is permanently disabled by HW Disable eFuse */ + if (esp_efuse_read_field_bit(ESP_EFUSE_HARD_DIS_JTAG)) { + ESP_LOGE(TAG, "JTAG disabled permanently."); + return ESP_FAIL; + } + + esp_crypto_hmac_lock_acquire(); + + ets_status = ets_jtag_enable_temporarily(token, convert_key_type(key_id)); + + if (ets_status != ETS_OK) { + // ets_jtag_enable_temporarily returns either ETS_OK or ETS_FAIL + err = ESP_FAIL; + ESP_LOGE(TAG, "JTAG re-enabling failed (%d)", err); + } + + ESP_LOGD(TAG, "HMAC computation in downstream mode is completed."); + + ets_hmac_disable(); + + esp_crypto_hmac_lock_release(); + + return err; +} + +esp_err_t esp_hmac_jtag_disable() +{ + esp_crypto_hmac_lock_acquire(); + + REG_SET_BIT(HMAC_SET_INVALIDATE_JTAG_REG, HMAC_INVALIDATE_JTAG); + + esp_crypto_hmac_lock_release(); + + ESP_LOGD(TAG, "Invalidate JTAG result register. JTAG disabled."); + + return ESP_OK; +} diff --git a/components/esp_hw_support/port/esp32s3/memprot.c b/components/esp_hw_support/port/esp32s3/memprot.c index 31f8925f12..3fdbf55b9a 100644 --- a/components/esp_hw_support/port/esp32s3/memprot.c +++ b/components/esp_hw_support/port/esp32s3/memprot.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ /* INTERNAL API * implementation of generic interface to MMU memory protection features diff --git a/components/esp_hw_support/port/esp32s3/opiram_psram.c b/components/esp_hw_support/port/esp32s3/opiram_psram.c index efff2ec4d9..e232ffb797 100644 --- a/components/esp_hw_support/port/esp32s3/opiram_psram.c +++ b/components/esp_hw_support/port/esp32s3/opiram_psram.c @@ -18,7 +18,7 @@ #include "esp32s3/rom/cache.h" #include "soc/io_mux_reg.h" #include "soc/dport_reg.h" -#include "soc/apb_ctrl_reg.h" +#include "soc/syscon_reg.h" #include "soc/gpio_sig_map.h" #include "soc/efuse_reg.h" #include "driver/gpio.h" @@ -38,7 +38,11 @@ #define OCT_PSRAM_ADDR_BITLEN 32 #define OCT_PSRAM_RD_DUMMY_BITLEN (2*(10-1)) #define OCT_PSRAM_WR_DUMMY_BITLEN (2*(5-1)) -#define OCT_PSRAM_CS1_IO 26 +#define OCT_PSRAM_CS1_IO CONFIG_DEFAULT_PSRAM_CS_IO + +#define OCT_PSRAM_CS_SETUP_TIME 3 +#define OCT_PSRAM_CS_HOLD_TIME 3 +#define OCT_PSRAM_CS_HOLD_DELAY 2 typedef struct { union { @@ -96,7 +100,12 @@ typedef struct { static const char* TAG = "opi psram"; static DRAM_ATTR psram_size_t s_psram_size; -static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psram_vaddr_mode_t vaddrmode); +static void IRAM_ATTR s_config_psram_spi_phases(void); + +uint8_t IRAM_ATTR psram_get_cs_io(void) +{ + return OCT_PSRAM_CS1_IO; +} /** * Initialise mode registers of the PSRAM @@ -205,13 +214,33 @@ static void IRAM_ATTR s_print_psram_info(opi_psram_mode_reg_t *reg_val) reg_val->mr0.drive_str == 0x02 ? 4 : 8); } +static void psram_set_cs_timing(void) +{ + //SPI0/1 share the cs_hold / cs_setup, cd_hold_time / cd_setup_time, cs_hold_delay registers for PSRAM, so we only need to set SPI0 related registers here + SET_PERI_REG_MASK(SPI_MEM_SPI_SMEM_AC_REG(0), SPI_MEM_SPI_SMEM_CS_HOLD_M | SPI_MEM_SPI_SMEM_CS_SETUP_M); + SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_AC_REG(0), SPI_MEM_SPI_SMEM_CS_HOLD_TIME_V, OCT_PSRAM_CS_HOLD_TIME, SPI_MEM_SPI_SMEM_CS_HOLD_TIME_S); + SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_AC_REG(0), SPI_MEM_SPI_SMEM_CS_SETUP_TIME_V, OCT_PSRAM_CS_SETUP_TIME, SPI_MEM_SPI_SMEM_CS_SETUP_TIME_S); + //CS1 high time + SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_AC_REG(0), SPI_MEM_SPI_SMEM_CS_HOLD_DELAY_V, OCT_PSRAM_CS_HOLD_DELAY, SPI_MEM_SPI_SMEM_CS_HOLD_DELAY_S); +} + +static void IRAM_ATTR s_init_psram_pins(void) +{ + //Set cs1 pin function + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[OCT_PSRAM_CS1_IO], FUNC_SPICS1_SPICS1); + //Set mspi cs1 drive strength + PIN_SET_DRV(GPIO_PIN_MUX_REG[OCT_PSRAM_CS1_IO], 3); + //Set psram clock pin drive strength + REG_SET_FIELD(SPI_MEM_DATE_REG(0), SPI_MEM_SPI_SMEM_SPICLK_FUN_DRV, 3); +} + esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vaddrmode) { - // enable CS signal - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[OCT_PSRAM_CS1_IO], FUNC_SPICS1_SPICS1); + s_init_psram_pins(); + psram_set_cs_timing(); //enter MSPI slow mode to init PSRAM device registers - spi_timing_enter_mspi_low_speed_mode(); + spi_timing_enter_mspi_low_speed_mode(true); //set to variable dummy mode SET_PERI_REG_MASK(SPI_MEM_DDR_REG(1), SPI_MEM_SPI_FMEM_VAR_DUMMY); @@ -236,10 +265,10 @@ esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vad #if CONFIG_ESPTOOLPY_FLASH_VENDOR_MXIC && CONFIG_ESPTOOLPY_FLASHMODE_OPI_DTR esp_rom_spi_set_dtr_swap_mode(1, true, true); #endif - + //Do PSRAM timing tuning, we use SPI1 to do the tuning, and set the SPI0 PSRAM timing related registers accordingly spi_timing_psram_tuning(); - - spi_timing_enter_mspi_high_speed_mode(); + ////Back to the high speed mode. Flash/PSRAM clocks are set to the clock that user selected. SPI0/1 registers are all set correctly + spi_timing_enter_mspi_high_speed_mode(true); /** * Tuning may change SPI1 regs, whereas legacy spi_flash APIs rely on these regs. @@ -247,12 +276,12 @@ esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vad */ spi_flash_set_rom_required_regs(); - psram_cache_init(mode, vaddrmode); + s_config_psram_spi_phases(); return ESP_OK; } -//register initialization for sram cache params and r/w commands -static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psram_vaddr_mode_t vaddrmode) +//Configure PSRAM SPI0 phase related registers here according to the PSRAM chip requirement +static void IRAM_ATTR s_config_psram_spi_phases(void) { //Config Write CMD phase for SPI0 to access PSRAM SET_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_CACHE_SRAM_USR_WCMD_M); diff --git a/components/esp_hw_support/port/esp32s3/private_include/regi2c_bbpll.h b/components/esp_hw_support/port/esp32s3/private_include/regi2c_bbpll.h index 23b4b86d00..9df0dd12c2 100644 --- a/components/esp_hw_support/port/esp32s3/private_include/regi2c_bbpll.h +++ b/components/esp_hw_support/port/esp32s3/private_include/regi2c_bbpll.h @@ -1,16 +1,8 @@ -// Copyright 2015-2017 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/port/esp32s3/private_include/regi2c_brownout.h b/components/esp_hw_support/port/esp32s3/private_include/regi2c_brownout.h index 0b8b618bba..8073b72a27 100644 --- a/components/esp_hw_support/port/esp32s3/private_include/regi2c_brownout.h +++ b/components/esp_hw_support/port/esp32s3/private_include/regi2c_brownout.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/port/esp32s3/private_include/regi2c_dig_reg.h b/components/esp_hw_support/port/esp32s3/private_include/regi2c_dig_reg.h index 7fca1c0337..146077dcfa 100644 --- a/components/esp_hw_support/port/esp32s3/private_include/regi2c_dig_reg.h +++ b/components/esp_hw_support/port/esp32s3/private_include/regi2c_dig_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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/port/esp32s3/private_include/regi2c_lp_bias.h b/components/esp_hw_support/port/esp32s3/private_include/regi2c_lp_bias.h new file mode 100644 index 0000000000..0a19262dcd --- /dev/null +++ b/components/esp_hw_support/port/esp32s3/private_include/regi2c_lp_bias.h @@ -0,0 +1,21 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +/** + * @file regi2c_lp_bias.h + * @brief Register definitions for analog to calibrate o_code for getting a more precise voltage. + */ + +#define I2C_ULP_IR_FORCE_CODE 5 +#define I2C_ULP_IR_FORCE_CODE_MSB 6 +#define I2C_ULP_IR_FORCE_CODE_LSB 6 + +//register for OCode +#define I2C_ULP_EXT_CODE 6 +#define I2C_ULP_EXT_CODE_MSB 7 +#define I2C_ULP_EXT_CODE_LSB 0 diff --git a/components/esp_hw_support/port/esp32s3/private_include/regi2c_saradc.h b/components/esp_hw_support/port/esp32s3/private_include/regi2c_saradc.h new file mode 100644 index 0000000000..4224e92dcf --- /dev/null +++ b/components/esp_hw_support/port/esp32s3/private_include/regi2c_saradc.h @@ -0,0 +1,55 @@ +/* + * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +/** + * @file regi2c_saradc.h + * @brief Register definitions for analog to calibrate initial code for getting a more precise voltage of SAR ADC. + * + * This file lists register fields of SAR, located on an internal configuration + * bus. These definitions are used via macros defined in regi2c_ctrl.h, by + * function in adc_ll.h. + */ + +#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_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_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_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_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 diff --git a/components/esp_hw_support/port/esp32s3/private_include/regi2c_ulp.h b/components/esp_hw_support/port/esp32s3/private_include/regi2c_ulp.h index fdb5e48f76..898a5bfa8a 100644 --- a/components/esp_hw_support/port/esp32s3/private_include/regi2c_ulp.h +++ b/components/esp_hw_support/port/esp32s3/private_include/regi2c_ulp.h @@ -1,16 +1,8 @@ -// Copyright 2015-2017 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/port/esp32s3/regi2c_ctrl.h b/components/esp_hw_support/port/esp32s3/regi2c_ctrl.h index a944a49f98..e338035fc9 100644 --- a/components/esp_hw_support/port/esp32s3/regi2c_ctrl.h +++ b/components/esp_hw_support/port/esp32s3/regi2c_ctrl.h @@ -1,22 +1,20 @@ -// 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once #include #include "regi2c_bbpll.h" #include "regi2c_dig_reg.h" +#include "regi2c_lp_bias.h" +#include "regi2c_saradc.h" + +#ifdef __cplusplus +extern "C" { +#endif /* Analog function control register */ #define I2C_MST_ANA_CONF0_REG 0x6000E040 @@ -81,3 +79,8 @@ void regi2c_ctrl_write_reg_mask(uint8_t block, uint8_t host_id, uint8_t reg_add, #define REGI2C_READ(block, reg_add) \ regi2c_ctrl_read_reg(block, block##_HOSTID, reg_add) + + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/port/esp32s3/rtc_clk.c b/components/esp_hw_support/port/esp32s3/rtc_clk.c index 5ce98e24f0..d1e5956eb1 100644 --- a/components/esp_hw_support/port/esp32s3/rtc_clk.c +++ b/components/esp_hw_support/port/esp32s3/rtc_clk.c @@ -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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include diff --git a/components/esp_hw_support/port/esp32s3/rtc_clk_common.h b/components/esp_hw_support/port/esp32s3/rtc_clk_common.h index 93e328874c..01b3c1cea2 100644 --- a/components/esp_hw_support/port/esp32s3/rtc_clk_common.h +++ b/components/esp_hw_support/port/esp32s3/rtc_clk_common.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once diff --git a/components/esp_hw_support/port/esp32s3/rtc_clk_init.c b/components/esp_hw_support/port/esp32s3/rtc_clk_init.c index 013ccfc7f4..bbc878e966 100644 --- a/components/esp_hw_support/port/esp32s3/rtc_clk_init.c +++ b/components/esp_hw_support/port/esp32s3/rtc_clk_init.c @@ -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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -20,7 +12,7 @@ #include "esp32s3/rom/rtc.h" #include "soc/rtc.h" #include "soc/rtc_cntl_reg.h" -#include "soc/apb_ctrl_reg.h" +#include "soc/syscon_reg.h" #include "hal/cpu_hal.h" #include "regi2c_ctrl.h" #include "soc_log.h" diff --git a/components/esp_hw_support/port/esp32s3/rtc_init.c b/components/esp_hw_support/port/esp32s3/rtc_init.c index 1d4a88833d..575e07a60b 100644 --- a/components/esp_hw_support/port/esp32s3/rtc_init.c +++ b/components/esp_hw_support/port/esp32s3/rtc_init.c @@ -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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "soc/soc.h" @@ -18,18 +10,24 @@ #include "soc/rtc_cntl_reg.h" #include "soc/dport_reg.h" #include "soc/gpio_reg.h" -#include "soc/apb_ctrl_reg.h" +#include "soc/syscon_reg.h" #include "soc/spi_mem_reg.h" #include "soc/extmem_reg.h" #include "soc/syscon_reg.h" #include "regi2c_ctrl.h" #include "regi2c_ulp.h" #include "soc_log.h" +#include "esp_err.h" +#include "esp_efuse.h" +#include "esp_efuse_table.h" #define RTC_CNTL_MEM_FORCE_NOISO (RTC_CNTL_SLOWMEM_FORCE_NOISO | RTC_CNTL_FASTMEM_FORCE_NOISO) static const char *TAG = "rtcinit"; +static void set_ocode_by_efuse(int calib_version); +static void calibrate_ocode(void); + void rtc_init(rtc_config_t cfg) { REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_RTC_REG, 0); @@ -67,11 +65,36 @@ void rtc_init(rtc_config_t cfg) REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG_SLEEP, RTC_CNTL_DBIAS_1V10); REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG, RTC_CNTL_DBIAS_1V10); + if (cfg.cali_ocode) { + uint32_t blk1_version = 0; + uint32_t blk2_version = 0; + esp_err_t err = esp_efuse_read_field_blob(ESP_EFUSE_BLOCK1_VERSION, &blk1_version, 3); + if (err != ESP_OK) { + blk1_version = 0; + SOC_LOGW(TAG, "efuse read fail, set default blk1_version: %d\n", blk1_version); + } + err = esp_efuse_read_field_blob(ESP_EFUSE_BLOCK2_VERSION, &blk2_version, 4); + if (err != ESP_OK) { + blk2_version = 0; + SOC_LOGW(TAG, "efuse read fail, set default blk2_version: %d\n", blk2_version); + } + if (blk1_version != blk2_version) { + blk1_version = 0; + blk2_version = 0; + SOC_LOGW(TAG, "calibration efuse version does not match, set default version: %d\n", 0); + } + if (blk2_version == 1) { + set_ocode_by_efuse(blk2_version); + } else { + calibrate_ocode(); + } + } + if (cfg.clkctl_init) { //clear CMMU clock force on CLEAR_PERI_REG_MASK(EXTMEM_CACHE_MMU_POWER_CTRL_REG, EXTMEM_CACHE_MMU_MEM_FORCE_ON); //clear clkgate force on - REG_WRITE(APB_CTRL_CLKGATE_FORCE_ON_REG, 0); + REG_WRITE(SYSCON_CLKGATE_FORCE_ON_REG, 0); //clear tag clock force on CLEAR_PERI_REG_MASK(EXTMEM_DCACHE_TAG_POWER_CTRL_REG, EXTMEM_DCACHE_TAG_MEM_FORCE_ON); CLEAR_PERI_REG_MASK(EXTMEM_ICACHE_TAG_POWER_CTRL_REG, EXTMEM_ICACHE_TAG_MEM_FORCE_ON); @@ -155,55 +178,6 @@ void rtc_init(rtc_config_t cfg) CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD); CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_NOISO); } - if (cfg.cali_ocode) { - /* - Bangap output voltage is not precise when calibrate o-code by hardware sometimes, so need software o-code calibration(must close PLL). - Method: - 1. read current cpu config, save in old_config; - 2. switch cpu to xtal because PLL will be closed when o-code calibration; - 3. begin o-code calibration; - 4. wait o-code calibration done flag(odone_flag & bg_odone_flag) or timeout; - 5. set cpu to old-config. - */ - rtc_slow_freq_t slow_clk_freq = rtc_clk_slow_freq_get(); - rtc_slow_freq_t rtc_slow_freq_x32k = RTC_SLOW_FREQ_32K_XTAL; - rtc_slow_freq_t rtc_slow_freq_8MD256 = RTC_SLOW_FREQ_8MD256; - rtc_cal_sel_t cal_clk = RTC_CAL_RTC_MUX; - if (slow_clk_freq == (rtc_slow_freq_x32k)) { - cal_clk = RTC_CAL_32K_XTAL; - } else if (slow_clk_freq == rtc_slow_freq_8MD256) { - cal_clk = RTC_CAL_8MD256; - } - - uint64_t max_delay_time_us = 30000; - uint32_t slow_clk_period = rtc_clk_cal(cal_clk, 100); - uint64_t max_delay_cycle = rtc_time_us_to_slowclk(max_delay_time_us, slow_clk_period); - uint64_t cycle0 = rtc_time_get(); - uint64_t timeout_cycle = cycle0 + max_delay_cycle; - uint64_t cycle1 = 0; - - rtc_cpu_freq_config_t old_config; - rtc_clk_cpu_freq_get_config(&old_config); - rtc_clk_cpu_freq_set_xtal(); - - REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_RESETB, 0); - REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_RESETB, 1); - bool odone_flag = 0; - bool bg_odone_flag = 0; - while (1) { - odone_flag = REGI2C_READ_MASK(I2C_ULP, I2C_ULP_O_DONE_FLAG); - bg_odone_flag = REGI2C_READ_MASK(I2C_ULP, I2C_ULP_BG_O_DONE_FLAG); - cycle1 = rtc_time_get(); - if (odone_flag && bg_odone_flag) { - break; - } - if (cycle1 >= timeout_cycle) { - SOC_LOGW(TAG, "o_code calibration fail\n"); - break; - } - } - rtc_clk_cpu_freq_set_config(&old_config); - } REG_WRITE(RTC_CNTL_INT_ENA_REG, 0); REG_WRITE(RTC_CNTL_INT_CLR_REG, UINT32_MAX); @@ -244,3 +218,66 @@ void rtc_vddsdio_set_config(rtc_vddsdio_config_t config) val |= RTC_CNTL_SDIO_PD_EN; REG_WRITE(RTC_CNTL_SDIO_CONF_REG, val); } + +static void set_ocode_by_efuse(int calib_version) +{ + assert(calib_version == 1); + // use efuse ocode. + uint32_t ocode; + esp_err_t err = esp_efuse_read_field_blob(ESP_EFUSE_OCODE, &ocode, 8); + assert(err == ESP_OK); + (void) err; + REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_EXT_CODE, ocode); + REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_FORCE_CODE, 1); +} + +static void calibrate_ocode(void) +{ + /* + Bandgap output voltage is not precise when calibrate o-code by hardware sometimes, so need software o-code calibration (must turn off PLL). + Method: + 1. read current cpu config, save in old_config; + 2. switch cpu to xtal because PLL will be closed when o-code calibration; + 3. begin o-code calibration; + 4. wait o-code calibration done flag(odone_flag & bg_odone_flag) or timeout; + 5. set cpu to old-config. + */ + rtc_slow_freq_t slow_clk_freq = rtc_clk_slow_freq_get(); + rtc_slow_freq_t rtc_slow_freq_x32k = RTC_SLOW_FREQ_32K_XTAL; + rtc_slow_freq_t rtc_slow_freq_8MD256 = RTC_SLOW_FREQ_8MD256; + rtc_cal_sel_t cal_clk = RTC_CAL_RTC_MUX; + if (slow_clk_freq == (rtc_slow_freq_x32k)) { + cal_clk = RTC_CAL_32K_XTAL; + } else if (slow_clk_freq == rtc_slow_freq_8MD256) { + cal_clk = RTC_CAL_8MD256; + } + + uint64_t max_delay_time_us = 10000; + uint32_t slow_clk_period = rtc_clk_cal(cal_clk, 100); + uint64_t max_delay_cycle = rtc_time_us_to_slowclk(max_delay_time_us, slow_clk_period); + uint64_t cycle0 = rtc_time_get(); + uint64_t timeout_cycle = cycle0 + max_delay_cycle; + uint64_t cycle1 = 0; + + rtc_cpu_freq_config_t old_config; + rtc_clk_cpu_freq_get_config(&old_config); + rtc_clk_cpu_freq_set_xtal(); + + REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_RESETB, 0); + REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_RESETB, 1); + bool odone_flag = 0; + bool bg_odone_flag = 0; + while (1) { + odone_flag = REGI2C_READ_MASK(I2C_ULP, I2C_ULP_O_DONE_FLAG); + bg_odone_flag = REGI2C_READ_MASK(I2C_ULP, I2C_ULP_BG_O_DONE_FLAG); + cycle1 = rtc_time_get(); + if (odone_flag && bg_odone_flag) { + break; + } + if (cycle1 >= timeout_cycle) { + SOC_LOGW(TAG, "o_code calibration fail\n"); + break; + } + } + rtc_clk_cpu_freq_set_config(&old_config); +} diff --git a/components/esp_hw_support/port/esp32s3/rtc_pm.c b/components/esp_hw_support/port/esp32s3/rtc_pm.c index 8461b3c98c..04c5356c59 100644 --- a/components/esp_hw_support/port/esp32s3/rtc_pm.c +++ b/components/esp_hw_support/port/esp32s3/rtc_pm.c @@ -1,22 +1,14 @@ -// 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include #include "soc/rtc.h" #include "soc/rtc_cntl_reg.h" -#include "soc/apb_ctrl_reg.h" +#include "soc/syscon_reg.h" typedef enum { PM_LIGHT_SLEEP = BIT(2), /*!< WiFi PD, memory in light sleep */ diff --git a/components/esp_hw_support/port/esp32s3/rtc_sleep.c b/components/esp_hw_support/port/esp32s3/rtc_sleep.c index bba00859cd..aa2123ae38 100644 --- a/components/esp_hw_support/port/esp32s3/rtc_sleep.c +++ b/components/esp_hw_support/port/esp32s3/rtc_sleep.c @@ -1,22 +1,14 @@ -// 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "soc/soc.h" #include "soc/rtc.h" #include "soc/rtc_cntl_reg.h" -#include "soc/apb_ctrl_reg.h" +#include "soc/syscon_reg.h" #include "soc/dport_reg.h" #include "soc/rtc.h" #include "soc/i2s_reg.h" @@ -40,9 +32,9 @@ void rtc_sleep_pu(rtc_sleep_pu_config_t cfg) REG_SET_FIELD(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_LSLP_MEM_FORCE_PU, cfg.dig_fpu); REG_SET_FIELD(RTC_CNTL_PWC_REG, RTC_CNTL_FASTMEM_FORCE_LPU, cfg.rtc_fpu); REG_SET_FIELD(RTC_CNTL_PWC_REG, RTC_CNTL_SLOWMEM_FORCE_LPU, cfg.rtc_fpu); - REG_SET_FIELD(APB_CTRL_FRONT_END_MEM_PD_REG, APB_CTRL_DC_MEM_FORCE_PU, cfg.fe_fpu); - REG_SET_FIELD(APB_CTRL_FRONT_END_MEM_PD_REG, APB_CTRL_PBUS_MEM_FORCE_PU, cfg.fe_fpu); - REG_SET_FIELD(APB_CTRL_FRONT_END_MEM_PD_REG, APB_CTRL_AGC_MEM_FORCE_PU, cfg.fe_fpu); + REG_SET_FIELD(SYSCON_FRONT_END_MEM_PD_REG, SYSCON_DC_MEM_FORCE_PU, cfg.fe_fpu); + REG_SET_FIELD(SYSCON_FRONT_END_MEM_PD_REG, SYSCON_PBUS_MEM_FORCE_PU, cfg.fe_fpu); + REG_SET_FIELD(SYSCON_FRONT_END_MEM_PD_REG, SYSCON_AGC_MEM_FORCE_PU, cfg.fe_fpu); REG_SET_FIELD(BBPD_CTRL, BB_FFT_FORCE_PU, cfg.bb_fpu); REG_SET_FIELD(BBPD_CTRL, BB_DC_EST_FORCE_PU, cfg.bb_fpu); REG_SET_FIELD(NRXPD_CTRL, NRX_RX_ROT_FORCE_PU, cfg.nrx_fpu); @@ -52,14 +44,14 @@ void rtc_sleep_pu(rtc_sleep_pu_config_t cfg) REG_SET_FIELD(FE2_TX_INTERP_CTRL, FE2_TX_INF_FORCE_PU, cfg.fe_fpu); #endif if (cfg.sram_fpu) { - REG_SET_FIELD(APB_CTRL_MEM_POWER_UP_REG, APB_CTRL_SRAM_POWER_UP, APB_CTRL_SRAM_POWER_UP); + REG_SET_FIELD(SYSCON_MEM_POWER_UP_REG, SYSCON_SRAM_POWER_UP, SYSCON_SRAM_POWER_UP); } else { - REG_SET_FIELD(APB_CTRL_MEM_POWER_UP_REG, APB_CTRL_SRAM_POWER_UP, 0); + REG_SET_FIELD(SYSCON_MEM_POWER_UP_REG, SYSCON_SRAM_POWER_UP, 0); } if (cfg.rom_ram_fpu) { - REG_SET_FIELD(APB_CTRL_MEM_POWER_UP_REG, APB_CTRL_ROM_POWER_UP, APB_CTRL_ROM_POWER_UP); + REG_SET_FIELD(SYSCON_MEM_POWER_UP_REG, SYSCON_ROM_POWER_UP, SYSCON_ROM_POWER_UP); } else { - REG_SET_FIELD(APB_CTRL_MEM_POWER_UP_REG, APB_CTRL_ROM_POWER_UP, 0); + REG_SET_FIELD(SYSCON_MEM_POWER_UP_REG, SYSCON_ROM_POWER_UP, 0); } } @@ -106,9 +98,11 @@ void rtc_sleep_init(rtc_sleep_config_t cfg) } REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_MONITOR, RTC_CNTL_DBG_ATTEN_MONITOR_DEFAULT); REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_BIAS_SLEEP_MONITOR, RTC_CNTL_BIASSLP_MONITOR_DEFAULT); - REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_BIAS_SLEEP_DEEP_SLP, RTC_CNTL_BIASSLP_SLEEP_DEFAULT); + REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_BIAS_SLEEP_DEEP_SLP, + (!cfg.deep_slp && cfg.xtal_fpu) ? RTC_CNTL_BIASSLP_SLEEP_ON : RTC_CNTL_BIASSLP_SLEEP_DEFAULT); REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_PD_CUR_MONITOR, RTC_CNTL_PD_CUR_MONITOR_DEFAULT); - REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_PD_CUR_DEEP_SLP, RTC_CNTL_PD_CUR_SLEEP_DEFAULT); + REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_PD_CUR_DEEP_SLP, + (!cfg.deep_slp && cfg.xtal_fpu) ? RTC_CNTL_PD_CUR_SLEEP_ON : RTC_CNTL_PD_CUR_SLEEP_DEFAULT); if (cfg.deep_slp) { CLEAR_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU); REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_DEEP_SLP, RTC_CNTL_DBG_ATTEN_DEEPSLEEP_DEFAULT); @@ -121,11 +115,20 @@ void rtc_sleep_init(rtc_sleep_config_t cfg) REG_SET_FIELD(RTC_CNTL_REGULATOR_DRV_CTRL_REG, RTC_CNTL_DG_VDD_DRV_B_SLP, RTC_CNTL_DG_VDD_DRV_B_SLP_DEFAULT); SET_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU); CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_WRAP_PD_EN); - REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_DEEP_SLP, RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_DEFAULT); + REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_DEEP_SLP, + cfg.int_8m_pd_en ? RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_DEFAULT : RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_NODROP); } /* mem pd */ CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_LSLP_MEM_FORCE_PU); + //Keep the RTC8M_CLK on in light_sleep mode if the ledc low-speed channel is clocked by RTC8M_CLK. + if (!cfg.int_8m_pd_en && GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M)) { + REG_CLR_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PD); + REG_SET_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU); + } else { + REG_CLR_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU); + } + /* enable VDDSDIO control by state machine */ REG_CLR_BIT(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_FORCE); REG_SET_FIELD(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_PD_EN, cfg.vddsdio_pd_en); @@ -138,8 +141,8 @@ void rtc_sleep_init(rtc_sleep_config_t cfg) REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_DEEP_SLP_REJECT_EN, cfg.deep_slp_reject); REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_LIGHT_SLP_REJECT_EN, cfg.light_slp_reject); - /* gating XTAL clock */ - REG_CLR_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_XTAL_GLOBAL_FORCE_NOGATING); + REG_SET_FIELD(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_XTL_FORCE_PU, cfg.xtal_fpu); + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_XTAL_GLOBAL_FORCE_NOGATING, cfg.xtal_fpu); } void rtc_sleep_low_init(uint32_t slowclk_period) diff --git a/components/esp_hw_support/port/esp32s3/rtc_time.c b/components/esp_hw_support/port/esp32s3/rtc_time.c index 2aa925fda2..3668a9eaa1 100644 --- a/components/esp_hw_support/port/esp32s3/rtc_time.c +++ b/components/esp_hw_support/port/esp32s3/rtc_time.c @@ -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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "esp_rom_sys.h" @@ -50,7 +42,10 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) } else if (slow_freq == RTC_SLOW_FREQ_8MD256) { cal_clk = RTC_CAL_8MD256; } + } else if (cal_clk == RTC_CAL_INTERNAL_OSC) { + cal_clk = RTC_CAL_RTC_MUX; } + /* Enable requested clock (150k clock is always on) */ int dig_32k_xtal_state = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN); if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_state) { diff --git a/components/esp_hw_support/port/esp32s3/rtc_wdt.c b/components/esp_hw_support/port/esp32s3/rtc_wdt.c index d95ec54695..b2251506a4 100644 --- a/components/esp_hw_support/port/esp32s3/rtc_wdt.c +++ b/components/esp_hw_support/port/esp32s3/rtc_wdt.c @@ -1,13 +1,5 @@ -// Copyright 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: 2018-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ diff --git a/components/esp_hw_support/port/esp32s3/spiram.c b/components/esp_hw_support/port/esp32s3/spiram.c index 9d60dcedcf..d0fa5f09af 100644 --- a/components/esp_hw_support/port/esp32s3/spiram.c +++ b/components/esp_hw_support/port/esp32s3/spiram.c @@ -3,19 +3,11 @@ Abstraction layer for spi-ram. For now, it's no more than a stub for the spiram_ we add more types of external RAM memory, this can be made into a more intelligent dispatcher. */ -// Copyright 2015-2017 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -44,10 +36,8 @@ static const char *TAG = "spiram"; #if CONFIG_SPIRAM_SPEED_40M #define PSRAM_SPEED PSRAM_CACHE_S40M -#elif CONFIG_SPIRAM_SPEED_80M +#else //#if CONFIG_SPIRAM_SPEED_80M #define PSRAM_SPEED PSRAM_CACHE_S80M -#else -#define PSRAM_SPEED PSRAM_CACHE_S20M #endif static bool s_spiram_inited = false; @@ -112,7 +102,7 @@ void IRAM_ATTR esp_spiram_init_cache(void) } static uint32_t pages_for_flash = 0; -static uint32_t instrcution_in_spiram = 0; +static uint32_t instruction_in_spiram = 0; static uint32_t rodata_in_spiram = 0; #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS @@ -134,7 +124,7 @@ static uint32_t page0_page = INVALID_PHY_PAGE; uint32_t esp_spiram_instruction_access_enabled(void) { - return instrcution_in_spiram; + return instruction_in_spiram; } uint32_t esp_spiram_rodata_access_enabled(void) @@ -157,7 +147,7 @@ esp_err_t esp_spiram_enable_instruction_access(void) instr_flash2spiram_offs = mmu_value - pages_for_flash; ESP_EARLY_LOGV(TAG, "Instructions from flash page%d copy to SPIRAM page%d, Offset: %d", mmu_value, pages_for_flash, instr_flash2spiram_offs); pages_for_flash = Cache_Flash_To_SPIRAM_Copy(CACHE_IBUS, IRAM0_CACHE_ADDRESS_LOW, pages_for_flash, &page0_page); - instrcution_in_spiram = 1; + instruction_in_spiram = 1; return ESP_OK; } #endif @@ -255,8 +245,7 @@ esp_err_t esp_spiram_init(void) ESP_EARLY_LOGI(TAG, "Found %dMBit SPI RAM device", (esp_spiram_get_size() * 8) / (1024 * 1024)); - ESP_EARLY_LOGI(TAG, "SPI RAM mode: %s", PSRAM_SPEED == PSRAM_CACHE_S40M ? "sram 40m" : \ - PSRAM_SPEED == PSRAM_CACHE_S80M ? "sram 80m" : "sram 20m"); + ESP_EARLY_LOGI(TAG, "SPI RAM mode: %s", PSRAM_SPEED == PSRAM_CACHE_S40M ? "sram 40m" : "sram 80m"); ESP_EARLY_LOGI(TAG, "PSRAM initialized, cache is in %s mode.", \ (PSRAM_MODE == PSRAM_VADDR_MODE_EVENODD) ? "even/odd (2-core)" : \ (PSRAM_MODE == PSRAM_VADDR_MODE_LOWHIGH) ? "low/high (2-core)" : \ @@ -340,4 +329,9 @@ bool esp_spiram_is_initialized(void) return s_spiram_inited; } +uint8_t esp_spiram_get_cs_io(void) +{ + return psram_get_cs_io(); +} + #endif diff --git a/components/esp_hw_support/port/esp32s3/spiram_psram.c b/components/esp_hw_support/port/esp32s3/spiram_psram.c index 42d22f24af..1c36d0a74c 100644 --- a/components/esp_hw_support/port/esp32s3/spiram_psram.c +++ b/components/esp_hw_support/port/esp32s3/spiram_psram.c @@ -2,19 +2,11 @@ Driver bits for PSRAM chips (at the moment only the ESP-PSRAM32 chip). */ -// Copyright 2013-2017 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: 2013-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "sdkconfig.h" @@ -34,7 +26,7 @@ #include "soc/efuse_periph.h" #include "soc/soc_caps.h" #include "soc/io_mux_reg.h" -#include "soc/apb_ctrl_reg.h" +#include "soc/syscon_reg.h" #include "soc/efuse_reg.h" #include "soc/soc.h" #include "soc/io_mux_reg.h" @@ -47,15 +39,14 @@ #if CONFIG_SPIRAM_MODE_QUAD #include "soc/rtc.h" +#include "spi_flash_private.h" static const char* TAG = "psram"; //Commands for PSRAM chip #define PSRAM_READ 0x03 #define PSRAM_FAST_READ 0x0B -#define PSRAM_FAST_READ_DUMMY 0x3 #define PSRAM_FAST_READ_QUAD 0xEB -#define PSRAM_FAST_READ_QUAD_DUMMY 0x5 #define PSRAM_WRITE 0x02 #define PSRAM_QUAD_WRITE 0x38 #define PSRAM_ENTER_QMODE 0x35 @@ -64,6 +55,10 @@ static const char* TAG = "psram"; #define PSRAM_RESET 0x99 #define PSRAM_SET_BURST_LEN 0xC0 #define PSRAM_DEVICE_ID 0x9F + +#define PSRAM_FAST_READ_DUMMY 4 +#define PSRAM_FAST_READ_QUAD_DUMMY 6 + // ID #define PSRAM_ID_KGD_M 0xff #define PSRAM_ID_KGD_S 8 @@ -86,8 +81,6 @@ static const char* TAG = "psram"; #define PSRAM_SIZE_ID(id) ((PSRAM_EID(id) >> PSRAM_EID_SIZE_S) & PSRAM_EID_SIZE_M) #define PSRAM_IS_VALID(id) (PSRAM_KGD(id) == PSRAM_ID_KGD) -// For the old version 32Mbit psram, using the spicial driver */ -#define PSRAM_IS_32MBIT_VER0(id) (PSRAM_EID(id) == 0x20) #define PSRAM_IS_64MBIT_TRIAL(id) (PSRAM_EID(id) == 0x26) // IO-pins for PSRAM. @@ -107,22 +100,8 @@ static const char* TAG = "psram"; #define CS_PSRAM_SEL SPI_MEM_CS1_DIS_M #define CS_FLASH_SEL SPI_MEM_CS0_DIS_M -#define PSRAM_IO_MATRIX_DUMMY_20M 0 -#define PSRAM_IO_MATRIX_DUMMY_40M 0 -#define PSRAM_IO_MATRIX_DUMMY_80M 0 -#define _SPI_CACHE_PORT 0 -#define _SPI_FLASH_PORT 1 -#define _SPI_80M_CLK_DIV 1 -#define _SPI_40M_CLK_DIV 2 -#define _SPI_20M_CLK_DIV 4 - -typedef enum { - PSRAM_CLK_MODE_NORM = 0, /*!< Normal SPI mode */ - PSRAM_CLK_MODE_A1C, /*!< ONE extra clock cycles after CS is set high level */ - PSRAM_CLK_MODE_A2C, /*!< Two extra clock cycles after CS is set high level */ - PSRAM_CLK_MODE_ALON, /*!< clock always on */ - PSRAM_CLK_MODE_MAX, -} psram_clk_mode_t; +#define SPI1_NUM 1 +#define SPI0_NUM 0 typedef enum { @@ -131,35 +110,6 @@ typedef enum { PSRAM_EID_SIZE_64MBITS = 2, } psram_eid_size_t; -typedef struct { - uint8_t flash_clk_io; - uint8_t flash_cs_io; - uint8_t psram_clk_io; - uint8_t psram_cs_io; - uint8_t psram_spiq_sd0_io; - uint8_t psram_spid_sd1_io; - uint8_t psram_spiwp_sd3_io; - uint8_t psram_spihd_sd2_io; -} psram_io_t; - -#define PSRAM_IO_CONF_DEFAULT() { \ - .flash_clk_io = FLASH_CLK_IO, \ - .flash_cs_io = FLASH_CS_IO, \ - .psram_clk_io = PSRAM_CLK_IO, \ - .psram_cs_io = PSRAM_CS_IO, \ - .psram_spiq_sd0_io = PSRAM_SPIQ_SD0_IO, \ - .psram_spid_sd1_io = PSRAM_SPID_SD1_IO, \ - .psram_spiwp_sd3_io = PSRAM_SPIWP_SD3_IO, \ - .psram_spihd_sd2_io = PSRAM_SPIHD_SD2_IO, \ -} - -typedef enum { - PSRAM_SPI_1 = 0x1, - /* PSRAM_SPI_2, */ - /* PSRAM_SPI_3, */ - PSRAM_SPI_MAX , -} psram_spi_num_t; - typedef enum { PSRAM_CMD_QPI, PSRAM_CMD_SPI, @@ -168,9 +118,16 @@ typedef enum { typedef esp_rom_spi_cmd_t psram_cmd_t; static uint32_t s_psram_id = 0; -static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psram_vaddr_mode_t vaddrmode); +static void IRAM_ATTR config_psram_spi_phases(void); extern void esp_rom_spi_set_op_mode(int spi_num, esp_rom_spiflash_read_mode_t mode); +static uint8_t s_psram_cs_io = (uint8_t)-1; + +uint8_t psram_get_cs_io(void) +{ + return s_psram_cs_io; +} + static void psram_set_op_mode(int spi_num, psram_cmd_mode_t mode) { if (mode == PSRAM_CMD_QPI) { @@ -283,7 +240,7 @@ esp_err_t psram_enable_wrap(uint32_t wrap_size) switch (wrap_size) { case 32: case 0: - psram_set_wrap_burst_length(PSRAM_SPI_1, PSRAM_CMD_QPI); + psram_set_wrap_burst_length(1, PSRAM_CMD_QPI); current_wrap_size = wrap_size; return ESP_OK; case 16: @@ -307,7 +264,7 @@ bool psram_support_wrap_size(uint32_t wrap_size) } -//read psram id, should issue `psram_disable_qio_mode` before calling this +//Read ID operation only supports SPI CMD and mode, should issue `psram_disable_qio_mode` before calling this static void psram_read_id(int spi_num, uint32_t* dev_id) { psram_exec_cmd(spi_num, PSRAM_CMD_SPI, @@ -333,58 +290,37 @@ static void IRAM_ATTR psram_enable_qio_mode(int spi_num) false); /* whether is program/erase operation */ } -static void psram_set_spi1_cmd_cs_timing(psram_clk_mode_t clk_mode) +static void psram_set_cs_timing(void) { - if (clk_mode == PSRAM_CLK_MODE_NORM) { - // SPI1 Flash Operation port - SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(_SPI_FLASH_PORT), SPI_MEM_CS_HOLD_TIME_V, 1, SPI_MEM_CS_HOLD_TIME_S); - SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(_SPI_FLASH_PORT), SPI_MEM_CS_SETUP_TIME_V, 0, SPI_MEM_CS_SETUP_TIME_S); - SET_PERI_REG_MASK(SPI_MEM_USER_REG(_SPI_FLASH_PORT), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M); - } else { - SET_PERI_REG_MASK(SPI_MEM_USER_REG(_SPI_FLASH_PORT), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M); - } + //SPI0/1 share the cs_hold / cs_setup, cd_hold_time / cd_setup_time registers for PSRAM, so we only need to set SPI0 related registers here + SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_AC_REG(0), SPI_MEM_SPI_SMEM_CS_HOLD_TIME_V, 0, SPI_MEM_SPI_SMEM_CS_HOLD_TIME_S); + SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_AC_REG(0), SPI_MEM_SPI_SMEM_CS_SETUP_TIME_V, 0, SPI_MEM_SPI_SMEM_CS_SETUP_TIME_S); + SET_PERI_REG_MASK(SPI_MEM_SPI_SMEM_AC_REG(0), SPI_MEM_SPI_SMEM_CS_HOLD_M | SPI_MEM_SPI_SMEM_CS_SETUP_M); } -static void psram_set_spi0_cache_cs_timing(psram_clk_mode_t clk_mode) +static void IRAM_ATTR psram_gpio_config(void) { - if (clk_mode == PSRAM_CLK_MODE_NORM) { - // SPI0 SRAM Cache port - SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_AC_REG(_SPI_CACHE_PORT), SPI_MEM_SPI_SMEM_CS_HOLD_TIME_V, 1, SPI_MEM_SPI_SMEM_CS_HOLD_TIME_S); - SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_AC_REG(_SPI_CACHE_PORT), SPI_MEM_SPI_SMEM_CS_SETUP_TIME_V, 0, SPI_MEM_SPI_SMEM_CS_SETUP_TIME_S); - SET_PERI_REG_MASK(SPI_MEM_SPI_SMEM_AC_REG(_SPI_CACHE_PORT), SPI_MEM_SPI_SMEM_CS_HOLD_M | SPI_MEM_SPI_SMEM_CS_SETUP_M); - // SPI0 Flash Cache port - SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(_SPI_CACHE_PORT), SPI_MEM_CS_HOLD_TIME_V, 0, SPI_MEM_CS_HOLD_TIME_S); - SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(_SPI_CACHE_PORT), SPI_MEM_CS_SETUP_TIME_V, 0, SPI_MEM_CS_SETUP_TIME_S); - SET_PERI_REG_MASK(SPI_MEM_USER_REG(_SPI_CACHE_PORT), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M); + //CS1 + uint8_t cs1_io = PSRAM_CS_IO; + if (cs1_io == SPI_CS1_GPIO_NUM) { + gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[cs1_io], FUNC_SPICS1_SPICS1); } else { - CLEAR_PERI_REG_MASK(SPI_MEM_USER_REG(_SPI_CACHE_PORT), SPI_CS_HOLD_M | SPI_CS_SETUP_M); + esp_rom_gpio_connect_out_signal(cs1_io, SPICS1_OUT_IDX, 0, 0); + gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[cs1_io], PIN_FUNC_GPIO); } -} + s_psram_cs_io = cs1_io; -//psram gpio init , different working frequency we have different solutions -static void IRAM_ATTR psram_gpio_config(psram_cache_mode_t mode) -{ - psram_io_t psram_io = PSRAM_IO_CONF_DEFAULT(); + //WP HD + uint8_t wp_io = PSRAM_SPIWP_SD3_IO; const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info(); if (spiconfig == ESP_ROM_EFUSE_FLASH_DEFAULT_SPI) { - /* FLASH pins(except wp / hd) are all configured via IO_MUX in rom. */ + // MSPI pins (except wp / hd) are all configured via IO_MUX in 1st bootloader. } else { - // FLASH pins are all configured via GPIO matrix in ROM. - psram_io.flash_clk_io = EFUSE_SPICONFIG_RET_SPICLK(spiconfig); - psram_io.flash_cs_io = EFUSE_SPICONFIG_RET_SPICS0(spiconfig); - psram_io.psram_spiq_sd0_io = EFUSE_SPICONFIG_RET_SPIQ(spiconfig); - psram_io.psram_spid_sd1_io = EFUSE_SPICONFIG_RET_SPID(spiconfig); - psram_io.psram_spihd_sd2_io = EFUSE_SPICONFIG_RET_SPIHD(spiconfig); - psram_io.psram_spiwp_sd3_io = esp_rom_efuse_get_flash_wp_gpio(); - } - esp_rom_spiflash_select_qio_pins(psram_io.psram_spiwp_sd3_io, spiconfig); - - if (psram_io.psram_cs_io == SPI_CS1_GPIO_NUM) { - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[psram_io.psram_cs_io], FUNC_SPICS1_SPICS1); - } else { - esp_rom_gpio_connect_out_signal(psram_io.psram_cs_io, SPICS1_OUT_IDX, 0, 0); - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[psram_io.psram_cs_io], PIN_FUNC_GPIO); + // MSPI pins (except wp / hd) are all configured via GPIO matrix in 1st bootloader. + wp_io = esp_rom_efuse_get_flash_wp_gpio(); } + //This ROM function will init both WP and HD pins. + esp_rom_spiflash_select_qio_pins(wp_io, spiconfig); } psram_size_t psram_get_size(void) @@ -401,21 +337,6 @@ psram_size_t psram_get_size(void) return PSRAM_SIZE_MAX; } -//used in UT only -bool psram_is_32mbit_ver0(void) -{ - return PSRAM_IS_32MBIT_VER0(s_psram_id); -} - -static void psram_set_clk_mode(int spi_num, psram_clk_mode_t clk_mode) -{ - if (spi_num == _SPI_CACHE_PORT) { - REG_SET_FIELD(SPI_MEM_SRAM_CMD_REG(0), SPI_MEM_SCLK_MODE, clk_mode); - } else if (spi_num == _SPI_FLASH_PORT) { - REG_SET_FIELD(SPI_MEM_CTRL1_REG(1), SPI_MEM_CLK_MODE, clk_mode); - } -} - /* * Psram mode init will overwrite original flash speed mode, so that it is possible to change psram and flash speed after OTA. * Flash read mode(QIO/QOUT/DIO/DOUT) will not be changed in app bin. It is decided by bootloader, OTA can not change this mode. @@ -423,119 +344,67 @@ static void psram_set_clk_mode(int spi_num, psram_clk_mode_t clk_mode) esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vaddrmode) //psram init { assert(mode < PSRAM_CACHE_MAX && "we don't support any other mode for now."); - // GPIO related settings - psram_gpio_config(mode); - /* SPI1: set spi1 clk mode, in order to send commands on SPI1 */ - /* SPI1: set cs timing(hold time) in order to send commands on SPI1 */ - psram_set_clk_mode(_SPI_FLASH_PORT, PSRAM_CLK_MODE_A1C); - psram_set_spi1_cmd_cs_timing(PSRAM_CLK_MODE_A1C); + psram_gpio_config(); + psram_set_cs_timing(); - int spi_num = PSRAM_SPI_1; - psram_disable_qio_mode(spi_num); - psram_read_id(spi_num, &s_psram_id); + //enter MSPI slow mode to init PSRAM device registers + spi_timing_enter_mspi_low_speed_mode(true); + + //We use SPI1 to init PSRAM + psram_disable_qio_mode(SPI1_NUM); + psram_read_id(SPI1_NUM, &s_psram_id); if (!PSRAM_IS_VALID(s_psram_id)) { /* 16Mbit psram ID read error workaround: * treat the first read id as a dummy one as the pre-condition, * Send Read ID command again */ - psram_read_id(spi_num, &s_psram_id); + psram_read_id(SPI1_NUM, &s_psram_id); if (!PSRAM_IS_VALID(s_psram_id)) { ESP_EARLY_LOGE(TAG, "PSRAM ID read error: 0x%08x", s_psram_id); return ESP_FAIL; } } - psram_clk_mode_t clk_mode = PSRAM_CLK_MODE_MAX; - if (psram_is_32mbit_ver0()) { - clk_mode = PSRAM_CLK_MODE_A1C; - // SPI1: keep clock mode and cs timing for spi1 - } else { - // For other psram, we don't need any extra clock cycles after cs get back to high level - clk_mode = PSRAM_CLK_MODE_NORM; - // SPI1: set clock mode and cs timing to normal mode - psram_set_clk_mode(_SPI_FLASH_PORT, PSRAM_CLK_MODE_NORM); - psram_set_spi1_cmd_cs_timing(PSRAM_CLK_MODE_NORM); - } + //SPI1: send psram reset command + psram_reset_mode(SPI1_NUM); + //SPI1: send QPI enable command + psram_enable_qio_mode(SPI1_NUM); - /* SPI1: send psram reset command */ - /* SPI1: send QPI enable command */ - psram_reset_mode(PSRAM_SPI_1); - psram_enable_qio_mode(PSRAM_SPI_1); + //Do PSRAM timing tuning, we use SPI1 to do the tuning, and set the SPI0 PSRAM timing related registers accordingly + spi_timing_psram_tuning(); - // after sending commands, set spi1 clock mode and cs timing to normal mode. - // since all the operations are sent via SPI0 Cache - /* SPI1: set clock mode to normal mode. */ - /* SPI1: set cs timing to normal */ - psram_set_clk_mode(_SPI_FLASH_PORT, PSRAM_CLK_MODE_NORM); - psram_set_spi1_cmd_cs_timing(PSRAM_CLK_MODE_NORM); - - /* SPI0: set spi0 clock mode */ - /* SPI0: set spi0 flash/cache cs timing */ - psram_set_clk_mode(_SPI_CACHE_PORT, clk_mode); - psram_set_spi0_cache_cs_timing(clk_mode); - - // SPI0: init SPI commands for Cache - psram_cache_init(mode, vaddrmode); + //Configure SPI0 PSRAM related SPI Phases + config_psram_spi_phases(); + //Back to the high speed mode. Flash/PSRAM clocks are set to the clock that user selected. SPI0/1 registers are all set correctly + spi_timing_enter_mspi_high_speed_mode(true); return ESP_OK; } -static void IRAM_ATTR psram_clock_set(int spi_num, int8_t freqdiv) +//Configure PSRAM SPI0 phase related registers here according to the PSRAM chip requirement +static void IRAM_ATTR config_psram_spi_phases(void) { - uint32_t freqbits; - if (1 >= freqdiv) { - WRITE_PERI_REG(SPI_MEM_SRAM_CLK_REG(spi_num), SPI_MEM_SCLK_EQU_SYSCLK); - } else { - freqbits = (((freqdiv-1)< diff --git a/components/esp_hw_support/sleep_gpio.c b/components/esp_hw_support/sleep_gpio.c new file mode 100644 index 0000000000..b9f874c3c6 --- /dev/null +++ b/components/esp_hw_support/sleep_gpio.c @@ -0,0 +1,87 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include "esp_attr.h" +#include "esp_sleep.h" +#include "esp_log.h" +#include "soc/soc_caps.h" + +#include "sdkconfig.h" + +#include "driver/gpio.h" +#include "esp_private/gpio.h" +#include "esp_private/sleep_gpio.h" +#include "bootloader_common.h" + +#ifdef CONFIG_IDF_TARGET_ESP32 +#include "esp32/spiram.h" +#elif CONFIG_IDF_TARGET_ESP32S2 +#include "esp32s2/spiram.h" +#elif CONFIG_IDF_TARGET_ESP32S3 +#include "esp32s3/spiram.h" +#endif + +static const char *TAG = "sleep"; + +#if SOC_GPIO_SUPPORT_SLP_SWITCH + +#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL +void gpio_sleep_mode_config_apply(void) +{ + for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) { + if (GPIO_IS_VALID_GPIO(gpio_num)) { + gpio_sleep_pupd_config_apply(gpio_num); + } + } +} + +IRAM_ATTR void gpio_sleep_mode_config_unapply(void) +{ + for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) { + if (GPIO_IS_VALID_GPIO(gpio_num)) { + gpio_sleep_pupd_config_unapply(gpio_num); + } + } +} +#endif + +void esp_sleep_config_gpio_isolate(void) +{ + ESP_LOGI(TAG, "Configure to isolate all GPIO pins in sleep state"); + for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) { + if (GPIO_IS_VALID_GPIO(gpio_num)) { + gpio_sleep_set_direction(gpio_num, GPIO_MODE_DISABLE); + gpio_sleep_set_pull_mode(gpio_num, GPIO_FLOATING); + } + } +#if CONFIG_ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND && CONFIG_SPIRAM + gpio_sleep_set_pull_mode(esp_spiram_get_cs_io(), GPIO_PULLUP_ONLY); +#endif +#if CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND + gpio_sleep_set_pull_mode(bootloader_flash_get_cs_io(), GPIO_PULLUP_ONLY); +#endif +} + +void esp_sleep_enable_gpio_switch(bool enable) +{ + ESP_LOGI(TAG, "%s automatic switching of GPIO sleep configuration", enable ? "Enable" : "Disable"); + for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) { + if (GPIO_IS_VALID_GPIO(gpio_num)) { + if (enable) { + gpio_sleep_sel_en(gpio_num); + } else { + gpio_sleep_sel_dis(gpio_num); + } + } + } +} + +#endif // SOC_GPIO_SUPPORT_SLP_SWITCH diff --git a/components/esp_hw_support/sleep_mac_bb.c b/components/esp_hw_support/sleep_mac_bb.c new file mode 100644 index 0000000000..4c53852070 --- /dev/null +++ b/components/esp_hw_support/sleep_mac_bb.c @@ -0,0 +1,108 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include "esp_attr.h" +#include "esp_sleep.h" +#include "soc/soc_caps.h" +#include "esp_private/sleep_mac_bb.h" +#include "sdkconfig.h" + +#if CONFIG_MAC_BB_PD + +#define MAC_BB_POWER_DOWN_CB_NO (2) +#define MAC_BB_POWER_UP_CB_NO (2) + +static DRAM_ATTR mac_bb_power_down_cb_t s_mac_bb_power_down_cb[MAC_BB_POWER_DOWN_CB_NO]; +static DRAM_ATTR mac_bb_power_up_cb_t s_mac_bb_power_up_cb[MAC_BB_POWER_UP_CB_NO]; + +esp_err_t esp_register_mac_bb_pd_callback(mac_bb_power_down_cb_t cb) +{ + int index = MAC_BB_POWER_DOWN_CB_NO; + for (int i = MAC_BB_POWER_DOWN_CB_NO - 1; i >= 0; i--) { + if (s_mac_bb_power_down_cb[i] == cb) { + return ESP_OK; + } + + if (s_mac_bb_power_down_cb[i] == NULL) { + index = i; + } + } + + if (index < MAC_BB_POWER_DOWN_CB_NO) { + s_mac_bb_power_down_cb[index] = cb; + return ESP_OK; + } + + return ESP_ERR_NO_MEM; +} + +esp_err_t esp_unregister_mac_bb_pd_callback(mac_bb_power_down_cb_t cb) +{ + for (int i = MAC_BB_POWER_DOWN_CB_NO - 1; i >= 0; i--) { + if (s_mac_bb_power_down_cb[i] == cb) { + s_mac_bb_power_down_cb[i] = NULL; + return ESP_OK; + } + } + return ESP_ERR_INVALID_STATE; +} + +void IRAM_ATTR mac_bb_power_down_cb_execute(void) +{ + for (int i = 0; i < MAC_BB_POWER_DOWN_CB_NO; i++) { + if (s_mac_bb_power_down_cb[i]) { + s_mac_bb_power_down_cb[i](); + } + } +} + +esp_err_t esp_register_mac_bb_pu_callback(mac_bb_power_up_cb_t cb) +{ + int index = MAC_BB_POWER_UP_CB_NO; + for (int i = MAC_BB_POWER_UP_CB_NO - 1; i >= 0; i--) { + if (s_mac_bb_power_up_cb[i] == cb) { + return ESP_OK; + } + + if (s_mac_bb_power_up_cb[i] == NULL) { + index = i; + } + } + + if (index < MAC_BB_POWER_UP_CB_NO) { + s_mac_bb_power_up_cb[index] = cb; + return ESP_OK; + } + + return ESP_ERR_NO_MEM; +} + +esp_err_t esp_unregister_mac_bb_pu_callback(mac_bb_power_up_cb_t cb) +{ + for (int i = MAC_BB_POWER_UP_CB_NO - 1; i >= 0; i--) { + if (s_mac_bb_power_up_cb[i] == cb) { + s_mac_bb_power_up_cb[i] = NULL; + return ESP_OK; + } + } + return ESP_ERR_INVALID_STATE; +} + +void IRAM_ATTR mac_bb_power_up_cb_execute(void) +{ + for (int i = 0; i < MAC_BB_POWER_UP_CB_NO; i++) { + if (s_mac_bb_power_up_cb[i]) { + s_mac_bb_power_up_cb[i](); + } + } +} + +#endif ///CONFIG_MAC_BB_PD diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 92870b6641..0b88d4c8ec 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -1,16 +1,8 @@ -// Copyright 2015-2017 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -24,6 +16,7 @@ #include "esp_log.h" #include "esp_newlib.h" #include "esp_timer.h" +#include "esp_ipc_isr.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "soc/soc_caps.h" @@ -50,12 +43,14 @@ #include "esp_rom_uart.h" #include "esp_rom_sys.h" #include "brownout.h" +#include "esp_private/sleep_retention.h" #ifdef CONFIG_IDF_TARGET_ESP32 #include "esp32/rom/cache.h" #include "esp32/rom/rtc.h" #include "esp32/clk.h" #include "esp_private/gpio.h" +#include "esp_private/sleep_gpio.h" #elif CONFIG_IDF_TARGET_ESP32S2 #include "esp32s2/clk.h" #include "esp32s2/rom/cache.h" @@ -67,18 +62,18 @@ #include "esp32s3/rom/cache.h" #include "esp32s3/rom/rtc.h" #include "soc/extmem_reg.h" +#include "esp_private/sleep_mac_bb.h" #elif CONFIG_IDF_TARGET_ESP32C3 #include "esp32c3/clk.h" #include "esp32c3/rom/cache.h" #include "esp32c3/rom/rtc.h" #include "soc/extmem_reg.h" -#include "esp_heap_caps.h" +#include "esp_private/sleep_mac_bb.h" #elif CONFIG_IDF_TARGET_ESP32H2 #include "esp32h2/clk.h" #include "esp32h2/rom/cache.h" #include "esp32h2/rom/rtc.h" #include "soc/extmem_reg.h" -#include "esp_heap_caps.h" #endif // If light sleep time is less than that, don't power down flash @@ -155,13 +150,16 @@ typedef struct { uint32_t sleep_time_overhead_out; uint32_t rtc_clk_cal_period; uint64_t rtc_ticks_at_sleep_start; -#if SOC_PM_SUPPORT_CPU_PD - void *cpu_pd_mem; -#endif } sleep_config_t; static sleep_config_t s_config = { - .pd_options = { ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO }, + .pd_options = { + ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, +#if SOC_PM_SUPPORT_CPU_PD + ESP_PD_OPTION_AUTO, +#endif + ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO + }, .ccount_ticks_record = 0, .sleep_time_overhead_out = DEFAULT_SLEEP_OUT_OVERHEAD_US, .wakeup_triggers = 0 @@ -190,95 +188,6 @@ static void touch_wakeup_prepare(void); static void esp_deep_sleep_wakeup_prepare(void); #endif -#if CONFIG_MAC_BB_PD -#define MAC_BB_POWER_DOWN_CB_NO 2 -#define MAC_BB_POWER_UP_CB_NO 2 -static DRAM_ATTR mac_bb_power_down_cb_t s_mac_bb_power_down_cb[MAC_BB_POWER_DOWN_CB_NO]; -static DRAM_ATTR mac_bb_power_up_cb_t s_mac_bb_power_up_cb[MAC_BB_POWER_UP_CB_NO]; - -esp_err_t esp_register_mac_bb_pd_callback(mac_bb_power_down_cb_t cb) -{ - int index = MAC_BB_POWER_DOWN_CB_NO; - for (int i = MAC_BB_POWER_DOWN_CB_NO - 1; i >= 0; i--) { - if (s_mac_bb_power_down_cb[i] == cb) { - return ESP_OK; - } - - if (s_mac_bb_power_down_cb[i] == NULL) { - index = i; - } - } - - if (index < MAC_BB_POWER_DOWN_CB_NO) { - s_mac_bb_power_down_cb[index] = cb; - return ESP_OK; - } - - return ESP_ERR_NO_MEM; -} - -esp_err_t esp_unregister_mac_bb_pd_callback(mac_bb_power_down_cb_t cb) -{ - for (int i = MAC_BB_POWER_DOWN_CB_NO - 1; i >= 0; i--) { - if (s_mac_bb_power_down_cb[i] == cb) { - s_mac_bb_power_down_cb[i] = NULL; - return ESP_OK; - } - } - return ESP_ERR_INVALID_STATE; -} - -static IRAM_ATTR void mac_bb_power_down_cb_execute(void) -{ - for (int i = 0; i < MAC_BB_POWER_DOWN_CB_NO; i++) { - if (s_mac_bb_power_down_cb[i]) { - s_mac_bb_power_down_cb[i](); - } - } -} - -esp_err_t esp_register_mac_bb_pu_callback(mac_bb_power_up_cb_t cb) -{ - int index = MAC_BB_POWER_UP_CB_NO; - for (int i = MAC_BB_POWER_UP_CB_NO - 1; i >= 0; i--) { - if (s_mac_bb_power_up_cb[i] == cb) { - return ESP_OK; - } - - if (s_mac_bb_power_up_cb[i] == NULL) { - index = i; - } - } - - if (index < MAC_BB_POWER_UP_CB_NO) { - s_mac_bb_power_up_cb[index] = cb; - return ESP_OK; - } - - return ESP_ERR_NO_MEM; -} - -esp_err_t esp_unregister_mac_bb_pu_callback(mac_bb_power_up_cb_t cb) -{ - for (int i = MAC_BB_POWER_UP_CB_NO - 1; i >= 0; i--) { - if (s_mac_bb_power_up_cb[i] == cb) { - s_mac_bb_power_up_cb[i] = NULL; - return ESP_OK; - } - } - return ESP_ERR_INVALID_STATE; -} - -static IRAM_ATTR void mac_bb_power_up_cb_execute(void) -{ - for (int i = 0; i < MAC_BB_POWER_UP_CB_NO; i++) { - if (s_mac_bb_power_up_cb[i]) { - s_mac_bb_power_up_cb[i](); - } - } -} -#endif ///CONFIG_MAC_BB_PD - /* Wake from deep sleep stub See esp_deepsleep.h esp_wake_deep_sleep() comments for details. */ @@ -371,81 +280,33 @@ static void IRAM_ATTR resume_uarts(void) } } -inline static uint32_t IRAM_ATTR call_rtc_sleep_start(uint32_t reject_triggers, uint32_t lslp_mem_inf_fpu); - -#if SOC_PM_SUPPORT_CPU_PD -esp_err_t esp_sleep_cpu_pd_low_init(bool enable) +inline static void IRAM_ATTR misc_modules_sleep_prepare(void) { - if (enable) { - if (s_config.cpu_pd_mem == NULL) { - void *buf = heap_caps_aligned_alloc(SOC_RTC_CNTL_CPU_PD_DMA_ADDR_ALIGN, - SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE, - MALLOC_CAP_RETENTION | MALLOC_CAP_DEFAULT); - if (buf) { - memset(buf, 0, SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE); - s_config.cpu_pd_mem = rtc_cntl_hal_dma_link_init(buf, - buf + RTC_HAL_DMA_LINK_NODE_SIZE, SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE, NULL); - } else { - return ESP_ERR_NO_MEM; - } - } - } else { - if (s_config.cpu_pd_mem) { - heap_caps_free(s_config.cpu_pd_mem); - s_config.cpu_pd_mem = NULL; - } - } - return ESP_OK; -} -#endif // SOC_PM_SUPPORT_CPU_PD - -#if SOC_GPIO_SUPPORT_SLP_SWITCH -#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL -static inline void gpio_sleep_mode_config_apply(void) -{ - for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) { - if (GPIO_IS_VALID_GPIO(gpio_num)) { - gpio_sleep_pupd_config_apply(gpio_num); - } - } -} - -static inline void gpio_sleep_mode_config_unapply(void) -{ - for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) { - if (GPIO_IS_VALID_GPIO(gpio_num)) { - gpio_sleep_pupd_config_unapply(gpio_num); - } - } -} +#if CONFIG_MAC_BB_PD + mac_bb_power_down_cb_execute(); +#endif +#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL + gpio_sleep_mode_config_apply(); +#endif +#if SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD + sleep_enable_memory_retention(); #endif - -void esp_sleep_config_gpio_isolate(void) -{ - ESP_LOGI(TAG, "Configure to isolate all GPIO pins in sleep state"); - for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) { - if (GPIO_IS_VALID_GPIO(gpio_num)) { - gpio_sleep_set_direction(gpio_num, GPIO_MODE_DISABLE); - gpio_sleep_set_pull_mode(gpio_num, GPIO_FLOATING); - } - } } -void esp_sleep_enable_gpio_switch(bool enable) +inline static void IRAM_ATTR misc_modules_wake_prepare(void) { - ESP_LOGI(TAG, "%s automatic switching of GPIO sleep configuration", enable ? "Enable" : "Disable"); - for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) { - if (GPIO_IS_VALID_GPIO(gpio_num)) { - if (enable) { - gpio_sleep_sel_en(gpio_num); - } else { - gpio_sleep_sel_dis(gpio_num); - } - } - } +#if SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD + sleep_disable_memory_retention(); +#endif +#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL + gpio_sleep_mode_config_unapply(); +#endif +#if CONFIG_MAC_BB_PD + mac_bb_power_up_cb_execute(); +#endif } -#endif // SOC_GPIO_SUPPORT_SLP_SWITCH +inline static uint32_t IRAM_ATTR call_rtc_sleep_start(uint32_t reject_triggers, uint32_t lslp_mem_inf_fpu); static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) { @@ -474,10 +335,6 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) rtc_clk_cpu_freq_get_config(&cpu_freq_config); rtc_clk_cpu_freq_set_xtal(); -#if CONFIG_MAC_BB_PD - mac_bb_power_down_cb_execute(); -#endif - #if SOC_PM_SUPPORT_EXT_WAKEUP // Configure pins for external wakeup if (s_config.wakeup_triggers & RTC_EXT0_TRIG_EN) { @@ -499,11 +356,10 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) if (s_config.wakeup_triggers & RTC_ULP_TRIG_EN) { rtc_hal_ulp_wakeup_enable(); } -#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL - gpio_sleep_mode_config_apply(); -#endif #endif + misc_modules_sleep_prepare(); + #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 if (deep_sleep) { if (s_config.wakeup_triggers & RTC_TOUCH_TRIG_EN) { @@ -544,8 +400,7 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) } // Configure timer wakeup - if ((s_config.wakeup_triggers & RTC_TIMER_TRIG_EN) && - s_config.sleep_duration > 0) { + if (s_config.wakeup_triggers & RTC_TIMER_TRIG_EN) { timer_wakeup_prepare(); } @@ -584,17 +439,8 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) s_config.ccount_ticks_record = cpu_ll_get_cycle_count(); } -#if SOC_PM_SUPPORT_CPU_PD - rtc_cntl_hal_disable_cpu_retention(); -#endif + misc_modules_wake_prepare(); -#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL - gpio_sleep_mode_config_unapply(); -#endif - -#if CONFIG_MAC_BB_PD - mac_bb_power_up_cb_execute(); -#endif // re-enable UART output resume_uarts(); @@ -701,11 +547,15 @@ esp_err_t esp_light_sleep_start(void) uint64_t frc_time_at_start = esp_system_get_time(); uint32_t sleep_time_overhead_in = (ccount_at_sleep_start - s_config.ccount_ticks_record) / (esp_clk_cpu_freq() / 1000000ULL); - DPORT_STALL_OTHER_CPU_START(); + esp_ipc_isr_stall_other_cpu(); // Decide which power domains can be powered down uint32_t pd_flags = get_power_down_flags(); +#ifdef CONFIG_ESP_SLEEP_RTC_BUS_ISO_WORKAROUND + pd_flags &= ~RTC_SLEEP_PD_RTC_PERIPH; +#endif + // Re-calibrate the RTC Timer clock #ifdef CONFIG_ESP_SYSTEM_RTC_EXT_XTAL uint64_t time_per_us = 1000000ULL; @@ -774,10 +624,6 @@ esp_err_t esp_light_sleep_start(void) periph_inform_out_light_sleep_overhead(s_config.sleep_time_adjustment - sleep_time_overhead_in); -#if SOC_PM_SUPPORT_CPU_PD - rtc_cntl_hal_enable_cpu_retention(s_config.cpu_pd_mem); -#endif - rtc_vddsdio_config_t vddsdio_config = rtc_vddsdio_get_config(); // Safety net: enable WDT in case exit from light sleep fails @@ -825,7 +671,7 @@ esp_err_t esp_light_sleep_start(void) esp_set_time_from_rtc(); esp_timer_private_unlock(); - DPORT_STALL_OTHER_CPU_END(); + esp_ipc_isr_release_other_cpu(); if (!wdt_was_enabled) { wdt_hal_write_protect_disable(&rtc_wdt_ctx); wdt_hal_disable(&rtc_wdt_ctx); @@ -1313,18 +1159,14 @@ static uint32_t get_power_down_flags(void) } #if SOC_PM_SUPPORT_CPU_PD - if (s_config.cpu_pd_mem == NULL) { - s_config.pd_options[ESP_PD_DOMAIN_CPU] = ESP_PD_OPTION_ON; - } -#else - if (s_config.pd_options[ESP_PD_DOMAIN_CPU] != ESP_PD_OPTION_ON) { + if (!cpu_domain_pd_allowed()) { s_config.pd_options[ESP_PD_DOMAIN_CPU] = ESP_PD_OPTION_ON; } #endif - if (s_config.pd_options[ESP_PD_DOMAIN_XTAL] == ESP_PD_OPTION_AUTO) { - s_config.pd_options[ESP_PD_DOMAIN_XTAL] = ESP_PD_OPTION_OFF; - } +#ifdef CONFIG_IDF_TARGET_ESP32 + s_config.pd_options[ESP_PD_DOMAIN_XTAL] = ESP_PD_OPTION_OFF; +#endif const char *option_str[] = {"OFF", "ON", "AUTO(OFF)" /* Auto works as OFF */}; ESP_LOGD(TAG, "RTC_PERIPH: %s", option_str[s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH]]); @@ -1352,10 +1194,12 @@ static uint32_t get_power_down_flags(void) pd_flags |= RTC_SLEEP_PD_CPU; } #endif - -#ifdef CONFIG_IDF_TARGET_ESP32 - pd_flags |= RTC_SLEEP_PD_XTAL; -#endif + if (s_config.pd_options[ESP_PD_DOMAIN_RTC8M] != ESP_PD_OPTION_ON) { + pd_flags |= RTC_SLEEP_PD_INT_8M; + } + if (s_config.pd_options[ESP_PD_DOMAIN_XTAL] != ESP_PD_OPTION_ON) { + pd_flags |= RTC_SLEEP_PD_XTAL; + } /** * VDD_SDIO power domain shall be kept on during the light sleep diff --git a/components/esp_hw_support/sleep_retention.c b/components/esp_hw_support/sleep_retention.c new file mode 100644 index 0000000000..86a4d84b4d --- /dev/null +++ b/components/esp_hw_support/sleep_retention.c @@ -0,0 +1,227 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include "esp_attr.h" +#include "esp_sleep.h" +#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_heap_caps.h" +#include "soc/soc_caps.h" +#include "hal/rtc_hal.h" +#include "esp_private/sleep_retention.h" +#include "sdkconfig.h" + +#ifdef CONFIG_IDF_TARGET_ESP32S3 +#include "esp32s3/rom/cache.h" +#endif + +static __attribute__((unused)) const char *TAG = "sleep"; + +/** + * Internal structure which holds all requested light sleep memory retention parameters + */ +typedef struct { + rtc_cntl_sleep_retent_t retent; +} sleep_retention_t; + +static DRAM_ATTR sleep_retention_t s_retention; + +#if SOC_PM_SUPPORT_TAGMEM_PD + +#define TAGMEM_PD_MEM_TYPE_CAPS (MALLOC_CAP_DMA | MALLOC_CAP_DEFAULT) + +#if CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP +static int cache_tagmem_retention_setup(uint32_t code_seg_vaddr, uint32_t code_seg_size, uint32_t data_seg_vaddr, uint32_t data_seg_size) +{ + int sets; /* i/d-cache total set counts */ + int index; /* virtual address mapping i/d-cache row offset */ + int waysgrp; + int icache_tagmem_blk_gs, dcache_tagmem_blk_gs; + struct cache_mode imode = { .icache = 1 }; + struct cache_mode dmode = { .icache = 0 }; + + /* calculate/prepare i-cache tag memory retention parameters */ + Cache_Get_Mode(&imode); + sets = imode.cache_size / imode.cache_ways / imode.cache_line_size; + index = (code_seg_vaddr / imode.cache_line_size) % sets; + waysgrp = imode.cache_ways >> 2; + + code_seg_size = ALIGNUP(imode.cache_line_size, code_seg_size); + + s_retention.retent.tagmem.icache.start_point = index; + s_retention.retent.tagmem.icache.size = (sets * waysgrp) & 0xff; + s_retention.retent.tagmem.icache.vld_size = s_retention.retent.tagmem.icache.size; + if (code_seg_size < imode.cache_size / imode.cache_ways) { + s_retention.retent.tagmem.icache.vld_size = (code_seg_size / imode.cache_line_size) * waysgrp; + } + s_retention.retent.tagmem.icache.enable = (code_seg_size != 0) ? 1 : 0; + icache_tagmem_blk_gs = s_retention.retent.tagmem.icache.vld_size ? s_retention.retent.tagmem.icache.vld_size : sets * waysgrp; + icache_tagmem_blk_gs = ALIGNUP(4, icache_tagmem_blk_gs); + ESP_LOGD(TAG, "I-cache size:%d KiB, line size:%d B, ways:%d, sets:%d, index:%d, tag block groups:%d", (imode.cache_size>>10), + imode.cache_line_size, imode.cache_ways, sets, index, icache_tagmem_blk_gs); + + /* calculate/prepare d-cache tag memory retention parameters */ + Cache_Get_Mode(&dmode); + sets = dmode.cache_size / dmode.cache_ways / dmode.cache_line_size; + index = (data_seg_vaddr / dmode.cache_line_size) % sets; + waysgrp = dmode.cache_ways >> 2; + + data_seg_size = ALIGNUP(dmode.cache_line_size, data_seg_size); + + s_retention.retent.tagmem.dcache.start_point = index; + s_retention.retent.tagmem.dcache.size = (sets * waysgrp) & 0x1ff; + s_retention.retent.tagmem.dcache.vld_size = s_retention.retent.tagmem.dcache.size; +#ifndef CONFIG_ESP32S3_DATA_CACHE_16KB + if (data_seg_size < dmode.cache_size / dmode.cache_ways) { + s_retention.retent.tagmem.dcache.vld_size = (data_seg_size / dmode.cache_line_size) * waysgrp; + } + s_retention.retent.tagmem.dcache.enable = (data_seg_size != 0) ? 1 : 0; +#else + s_retention.retent.tagmem.dcache.enable = 1; +#endif + dcache_tagmem_blk_gs = s_retention.retent.tagmem.dcache.vld_size ? s_retention.retent.tagmem.dcache.vld_size : sets * waysgrp; + dcache_tagmem_blk_gs = ALIGNUP(4, dcache_tagmem_blk_gs); + ESP_LOGD(TAG, "D-cache size:%d KiB, line size:%d B, ways:%d, sets:%d, index:%d, tag block groups:%d", (dmode.cache_size>>10), + dmode.cache_line_size, dmode.cache_ways, sets, index, dcache_tagmem_blk_gs); + + /* For I or D cache tagmem retention, backup and restore are performed through + * RTC DMA (its bus width is 128 bits), For I/D Cache tagmem blocks (i-cache + * tagmem blocks = 92 bits, d-cache tagmem blocks = 88 bits), RTC DMA automatically + * aligns its bit width to 96 bits, therefore, 3 times RTC DMA can transfer 4 + * i/d-cache tagmem blocks (128 bits * 3 = 96 bits * 4) */ + return (((icache_tagmem_blk_gs + dcache_tagmem_blk_gs) << 2) * 3); +} +#endif // CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP + +static esp_err_t esp_sleep_tagmem_pd_low_init(bool enable) +{ + if (enable) { +#if CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP + if (s_retention.retent.tagmem.link_addr == NULL) { + extern char _stext[], _etext[]; + uint32_t code_start = (uint32_t)_stext; + uint32_t code_size = (uint32_t)(_etext - _stext); +#if !CONFIG_ESP32S3_SPIRAM_SUPPORT + extern char _rodata_start[], _rodata_reserved_end[]; + uint32_t data_start = (uint32_t)_rodata_start; + uint32_t data_size = (uint32_t)(_rodata_reserved_end - _rodata_start); +#else + uint32_t data_start = SOC_DROM_LOW; + uint32_t data_size = (SOC_EXTRAM_DATA_HIGH-SOC_EXTRAM_DATA_LOW) + (SOC_DROM_HIGH-SOC_DROM_LOW); +#endif + ESP_LOGI(TAG, "Code start at %08x, total %.2f KiB, data start at %08x, total %.2f KiB", + code_start, (float)code_size/1024, data_start, (float)data_size/1024); + int tagmem_sz = cache_tagmem_retention_setup(code_start, code_size, data_start, data_size); + void *buf = heap_caps_aligned_alloc(SOC_RTC_CNTL_TAGMEM_PD_DMA_ADDR_ALIGN, + tagmem_sz + RTC_HAL_DMA_LINK_NODE_SIZE, + TAGMEM_PD_MEM_TYPE_CAPS); + if (buf) { + memset(buf, 0, tagmem_sz + RTC_HAL_DMA_LINK_NODE_SIZE); + s_retention.retent.tagmem.link_addr = rtc_cntl_hal_dma_link_init(buf, + buf + RTC_HAL_DMA_LINK_NODE_SIZE, tagmem_sz, NULL); + } else { + s_retention.retent.tagmem.icache.enable = 0; + s_retention.retent.tagmem.dcache.enable = 0; + s_retention.retent.tagmem.link_addr = NULL; + return ESP_ERR_NO_MEM; + } + } +#else // CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP + s_retention.retent.tagmem.icache.enable = 0; + s_retention.retent.tagmem.dcache.enable = 0; + s_retention.retent.tagmem.link_addr = NULL; +#endif // CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP + } else { +#if SOC_PM_SUPPORT_TAGMEM_PD + if (s_retention.retent.tagmem.link_addr) { + heap_caps_free(s_retention.retent.tagmem.link_addr); + s_retention.retent.tagmem.icache.enable = 0; + s_retention.retent.tagmem.dcache.enable = 0; + s_retention.retent.tagmem.link_addr = NULL; + } +#endif + } + return ESP_OK; +} + +#endif // SOC_PM_SUPPORT_TAGMEM_PD + +#if SOC_PM_SUPPORT_CPU_PD + +#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 +#define CPU_PD_MEM_TYPE_CAPS (MALLOC_CAP_RETENTION | MALLOC_CAP_DEFAULT) +#else +#define CPU_PD_MEM_TYPE_CAPS (MALLOC_CAP_DMA | MALLOC_CAP_DEFAULT) +#endif + +esp_err_t esp_sleep_cpu_pd_low_init(bool enable) +{ + if (enable) { + if (s_retention.retent.cpu_pd_mem == NULL) { + void *buf = heap_caps_aligned_alloc(SOC_RTC_CNTL_CPU_PD_DMA_ADDR_ALIGN, + SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE, + CPU_PD_MEM_TYPE_CAPS); + if (buf) { + memset(buf, 0, SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE); + s_retention.retent.cpu_pd_mem = rtc_cntl_hal_dma_link_init(buf, + buf + RTC_HAL_DMA_LINK_NODE_SIZE, SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE, NULL); + } else { + return ESP_ERR_NO_MEM; + } + } + } else { + if (s_retention.retent.cpu_pd_mem) { + heap_caps_free(s_retention.retent.cpu_pd_mem); + s_retention.retent.cpu_pd_mem = NULL; + } + } +#if SOC_PM_SUPPORT_TAGMEM_PD + if (esp_sleep_tagmem_pd_low_init(enable) != ESP_OK) { +#ifdef CONFIG_ESP32S3_DATA_CACHE_16KB + esp_sleep_cpu_pd_low_init(false); + return ESP_ERR_NO_MEM; +#endif + } +#endif + return ESP_OK; +} + +bool cpu_domain_pd_allowed(void) +{ + return (s_retention.retent.cpu_pd_mem != NULL); +} + +#endif // SOC_PM_SUPPORT_CPU_PD + +#if SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD + +void sleep_enable_memory_retention(void) +{ +#if SOC_PM_SUPPORT_CPU_PD + rtc_cntl_hal_enable_cpu_retention(&s_retention.retent); +#endif +#if SOC_PM_SUPPORT_TAGMEM_PD + rtc_cntl_hal_enable_tagmem_retention(&s_retention.retent); +#endif +} + +void IRAM_ATTR sleep_disable_memory_retention(void) +{ +#if SOC_PM_SUPPORT_CPU_PD + rtc_cntl_hal_disable_cpu_retention(&s_retention.retent); +#endif +#if SOC_PM_SUPPORT_TAGMEM_PD + rtc_cntl_hal_disable_tagmem_retention(&s_retention.retent); +#endif +} + +#endif // SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD diff --git a/components/esp_hw_support/test/digital_signature_test_cases_3072.h b/components/esp_hw_support/test/digital_signature_test_cases_3072.h index c3f792a703..b06c0d9441 100644 --- a/components/esp_hw_support/test/digital_signature_test_cases_3072.h +++ b/components/esp_hw_support/test/digital_signature_test_cases_3072.h @@ -1,5 +1,10 @@ -/* File generated by gen_digital_signature_tests.py */ - +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + * + * File generated by gen_digital_signature_tests.py + */ #define NUM_HMAC_KEYS 3 static const uint8_t test_hmac_keys[NUM_HMAC_KEYS][32] = { diff --git a/components/esp_hw_support/test/digital_signature_test_cases_4096.h b/components/esp_hw_support/test/digital_signature_test_cases_4096.h index 1aa62760ba..af7705e22e 100644 --- a/components/esp_hw_support/test/digital_signature_test_cases_4096.h +++ b/components/esp_hw_support/test/digital_signature_test_cases_4096.h @@ -1,5 +1,10 @@ -/* File generated by gen_digital_signature_tests.py */ - +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + * + * File generated by gen_digital_signature_tests.py + */ #define NUM_HMAC_KEYS 3 static const uint8_t test_hmac_keys[NUM_HMAC_KEYS][32] = { diff --git a/components/esp_hw_support/test/gen_digital_signature_tests.py b/components/esp_hw_support/test/gen_digital_signature_tests.py index d9ceee5476..75682db418 100644 --- a/components/esp_hw_support/test/gen_digital_signature_tests.py +++ b/components/esp_hw_support/test/gen_digital_signature_tests.py @@ -1,5 +1,8 @@ #!/usr/bin/env python3 +# SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 +import datetime import hashlib import hmac import os @@ -52,7 +55,14 @@ hmac_keys = [os.urandom(32) for x in range(NUM_HMAC_KEYS)] messages = [random.randrange(0, 1 << 4096) for x in range(NUM_MESSAGES)] with open('digital_signature_test_cases.h', 'w') as f: - f.write('/* File generated by gen_digital_signature_tests.py */\n\n') + f.write('/*\n') + year = datetime.datetime.now().year + f.write(' * SPDX-FileCopyrightText: {year} Espressif Systems (Shanghai) CO LTD\n'.format(year=year)) + f.write(' *\n') + f.write(' * SPDX-License-Identifier: Apache-2.0\n') + f.write(' *\n') + f.write(' * File generated by gen_digital_signature_tests.py\n') + f.write(' */\n') # Write out HMAC keys f.write('#define NUM_HMAC_KEYS %d\n\n' % NUM_HMAC_KEYS) diff --git a/components/esp_hw_support/test/test_async_memcpy.c b/components/esp_hw_support/test/test_async_memcpy.c index 19c2251b33..60e84cca79 100644 --- a/components/esp_hw_support/test/test_async_memcpy.c +++ b/components/esp_hw_support/test/test_async_memcpy.c @@ -1,3 +1,8 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include #include diff --git a/components/esp_hw_support/test/test_dport_xt_highint5.S b/components/esp_hw_support/test/test_dport_xt_highint5.S index 223a2a8924..197d7c8cc4 100644 --- a/components/esp_hw_support/test/test_dport_xt_highint5.S +++ b/components/esp_hw_support/test/test_dport_xt_highint5.S @@ -10,6 +10,7 @@ #include "soc/dport_reg.h" #ifndef CONFIG_FREERTOS_UNICORE +#ifndef CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_5 #define L5_INTR_STACK_SIZE 12 #define L5_INTR_A2_OFFSET 0 @@ -77,6 +78,8 @@ xt_highint5: .global ld_include_test_dport_xt_highint5 ld_include_test_dport_xt_highint5: + +#endif // CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_5 #endif // CONFIG_FREERTOS_UNICORE #endif // CONFIG_IDF_TARGET_ESP32 diff --git a/components/esp_hw_support/test/test_ds.c b/components/esp_hw_support/test/test_ds.c index 5e43bc7e55..2a69e1e8dc 100644 --- a/components/esp_hw_support/test/test_ds.c +++ b/components/esp_hw_support/test/test_ds.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "unity.h" @@ -27,13 +19,18 @@ #include "esp32c3/rom/efuse.h" #include "esp32c3/rom/digital_signature.h" #include "esp32c3/rom/hmac.h" +#elif CONFIG_IDF_TARGET_ESP32S3 +#include "esp32s3/rom/efuse.h" +#include "esp32s3/rom/digital_signature.h" +#include "esp32s3/rom/aes.h" +#include "esp32s3/rom/sha.h" #endif #include "esp_ds.h" #define NUM_RESULTS 10 -#if CONFIG_IDF_TARGET_ESP32S2 +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 #define DS_MAX_BITS (4096) #elif CONFIG_IDF_TARGET_ESP32C3 #define DS_MAX_BITS (ETS_DS_MAX_BITS) @@ -44,17 +41,17 @@ typedef struct { ets_ds_p_data_t p_data; uint8_t expected_c[ETS_DS_C_LEN]; uint8_t hmac_key_idx; - uint32_t expected_results[NUM_RESULTS][DS_MAX_BITS/32]; + uint32_t expected_results[NUM_RESULTS][DS_MAX_BITS / 32]; } encrypt_testcase_t; // Generated header digital_signature_test_cases_.h (by gen_digital_signature_tests.py) defines // NUM_HMAC_KEYS, test_hmac_keys, NUM_MESSAGES, NUM_CASES, test_messages[], test_cases[] // Some adaptations were made: removed the 512 bit case and changed RSA lengths to the enums from esp_ds.h #if DS_MAX_BITS == 4096 -#define RSA_LEN (ESP_DS_RSA_4096) +#define RSA_LEN (ESP_DS_RSA_4096) #include "digital_signature_test_cases_4096.h" #elif DS_MAX_BITS == 3072 -#define RSA_LEN (ESP_DS_RSA_3072) +#define RSA_LEN (ESP_DS_RSA_3072) #include "digital_signature_test_cases_3072.h" #endif @@ -104,14 +101,14 @@ TEST_CASE("Digital Signature Parameter Encryption", "[hw_crypto] [ds]") esp_ds_data_t result = { }; esp_ds_p_data_t p_data; - memcpy(p_data.Y, t->p_data.Y, DS_MAX_BITS/8); - memcpy(p_data.M, t->p_data.M, DS_MAX_BITS/8); - memcpy(p_data.Rb, t->p_data.Rb, DS_MAX_BITS/8); + memcpy(p_data.Y, t->p_data.Y, DS_MAX_BITS / 8); + memcpy(p_data.M, t->p_data.M, DS_MAX_BITS / 8); + memcpy(p_data.Rb, t->p_data.Rb, DS_MAX_BITS / 8); p_data.M_prime = t->p_data.M_prime; p_data.length = t->p_data.length; esp_err_t r = esp_ds_encrypt_params(&result, t->iv, &p_data, - test_hmac_keys[t->hmac_key_idx]); + test_hmac_keys[t->hmac_key_idx]); printf("Encrypting test case %d done\n", i); TEST_ASSERT_EQUAL(ESP_OK, r); TEST_ASSERT_EQUAL(t->p_data.length, result.rsa_length); @@ -257,9 +254,10 @@ static void burn_hmac_keys(void) // starting from block 1, block 0 occupied with HMAC upstream test key int __attribute__((unused)) ets_status = ets_efuse_write_key(ETS_EFUSE_BLOCK_KEY1 + i, - purpose, - test_hmac_keys[i], 32); -#if CONFIG_IDF_TARGET_ESP32S2 + purpose, + test_hmac_keys[i], 32); + +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 if (ets_status == ESP_OK) { printf("written DS test key to block [%d]!\n", ETS_EFUSE_BLOCK_KEY1 + i); } else { @@ -288,7 +286,7 @@ TEST_CASE("Digital Signature wrong HMAC key purpose (FPGA only)", "[hw_crypto] [ const char *message = "test"; // HMAC fails in that case because it checks for the correct purpose -#if CONFIG_IDF_TARGET_ESP32S2 +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 TEST_ASSERT_EQUAL(ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL, esp_ds_start_sign(message, &ds_data, HMAC_KEY0, &ctx)); #elif CONFIG_IDF_TARGET_ESP32C3 TEST_ASSERT_EQUAL(ESP32C3_ERR_HW_CRYPTO_DS_HMAC_FAIL, esp_ds_start_sign(message, &ds_data, HMAC_KEY0, &ctx)); @@ -305,7 +303,7 @@ TEST_CASE("Digital Signature Blocking wrong HMAC key purpose (FPGA only)", "[hw_ uint8_t signature_data [128 * 4]; // HMAC fails in that case because it checks for the correct purpose -#if CONFIG_IDF_TARGET_ESP32S2 +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 TEST_ASSERT_EQUAL(ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL, esp_ds_sign(message, &ds_data, HMAC_KEY0, signature_data)); #elif CONFIG_IDF_TARGET_ESP32C3 TEST_ASSERT_EQUAL(ESP32C3_ERR_HW_CRYPTO_DS_HMAC_FAIL, esp_ds_sign(message, &ds_data, HMAC_KEY0, signature_data)); @@ -327,15 +325,15 @@ TEST_CASE("Digital Signature Operation (FPGA only)", "[hw_crypto] [ds]") ds_data.rsa_length = t->p_data.length; for (int j = 0; j < NUM_MESSAGES; j++) { - uint8_t signature[DS_MAX_BITS/8] = { 0 }; + uint8_t signature[DS_MAX_BITS / 8] = { 0 }; printf(" ... message %d\n", j); esp_ds_context_t *esp_ds_ctx; esp_err_t ds_r = esp_ds_start_sign(test_messages[j], - &ds_data, - t->hmac_key_idx + 1, - &esp_ds_ctx); + &ds_data, + t->hmac_key_idx + 1, + &esp_ds_ctx); TEST_ASSERT_EQUAL(ESP_OK, ds_r); ds_r = esp_ds_finish_sign(signature, esp_ds_ctx); @@ -363,23 +361,23 @@ TEST_CASE("Digital Signature Blocking Operation (FPGA only)", "[hw_crypto] [ds]" memcpy(ds_data.c, t->expected_c, ETS_DS_C_LEN); ds_data.rsa_length = t->p_data.length; - uint8_t signature[DS_MAX_BITS/8] = { 0 }; -#if CONFIG_IDF_TARGET_ESP32S2 + uint8_t signature[DS_MAX_BITS / 8] = { 0 }; +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 esp_ds_context_t *esp_ds_ctx; esp_err_t ds_r = esp_ds_start_sign(test_messages[0], - &ds_data, - t->hmac_key_idx + 1, - &esp_ds_ctx); + &ds_data, + t->hmac_key_idx + 1, + &esp_ds_ctx); TEST_ASSERT_EQUAL(ESP_OK, ds_r); ds_r = esp_ds_finish_sign(signature, esp_ds_ctx); TEST_ASSERT_EQUAL(ESP_OK, ds_r); #elif CONFIG_IDF_TARGET_ESP32C3 esp_err_t ds_r = esp_ds_sign(test_messages[0], - &ds_data, - t->hmac_key_idx + 1, - signature); + &ds_data, + t->hmac_key_idx + 1, + signature); TEST_ASSERT_EQUAL(ESP_OK, ds_r); #endif @@ -398,8 +396,8 @@ TEST_CASE("Digital Signature Invalid Data (FPGA only)", "[hw_crypto] [ds]") memcpy(ds_data.c, t->expected_c, ETS_DS_C_LEN); ds_data.rsa_length = t->p_data.length; - uint8_t signature[DS_MAX_BITS/8] = { 0 }; - const uint8_t zero[DS_MAX_BITS/8] = { 0 }; + uint8_t signature[DS_MAX_BITS / 8] = { 0 }; + const uint8_t zero[DS_MAX_BITS / 8] = { 0 }; // Corrupt the IV one bit at a time, rerun and expect failure for (int bit = 0; bit < 128; bit++) { @@ -410,12 +408,12 @@ TEST_CASE("Digital Signature Invalid Data (FPGA only)", "[hw_crypto] [ds]") esp_err_t ds_r = esp_ds_start_sign(test_messages[0], &ds_data, t->hmac_key_idx + 1, &esp_ds_ctx); TEST_ASSERT_EQUAL(ESP_OK, ds_r); ds_r = esp_ds_finish_sign(signature, esp_ds_ctx); -#if CONFIG_IDF_TARGET_ESP32S2 +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 TEST_ASSERT_EQUAL(ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST, ds_r); #elif CONFIG_IDF_TARGET_ESP32C3 TEST_ASSERT_EQUAL(ESP32C3_ERR_HW_CRYPTO_DS_INVALID_DIGEST, ds_r); #endif - TEST_ASSERT_EQUAL_HEX8_ARRAY(zero, signature, DS_MAX_BITS/8); + TEST_ASSERT_EQUAL_HEX8_ARRAY(zero, signature, DS_MAX_BITS / 8); ds_data.iv[bit / 8] ^= 1 << (bit % 8); } @@ -430,12 +428,12 @@ TEST_CASE("Digital Signature Invalid Data (FPGA only)", "[hw_crypto] [ds]") esp_err_t ds_r = esp_ds_start_sign(test_messages[0], &ds_data, t->hmac_key_idx + 1, &esp_ds_ctx); TEST_ASSERT_EQUAL(ESP_OK, ds_r); ds_r = esp_ds_finish_sign(signature, esp_ds_ctx); -#if CONFIG_IDF_TARGET_ESP32S2 +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 TEST_ASSERT_EQUAL(ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST, ds_r); #elif CONFIG_IDF_TARGET_ESP32C3 TEST_ASSERT_EQUAL(ESP32C3_ERR_HW_CRYPTO_DS_INVALID_DIGEST, ds_r); #endif - TEST_ASSERT_EQUAL_HEX8_ARRAY(zero, signature, DS_MAX_BITS/8); + TEST_ASSERT_EQUAL_HEX8_ARRAY(zero, signature, DS_MAX_BITS / 8); ds_data.c[bit / 8] ^= 1 << (bit % 8); } diff --git a/components/esp_hw_support/test/test_hmac.c b/components/esp_hw_support/test/test_hmac.c index 85ce63c54e..cf49bc19e3 100644 --- a/components/esp_hw_support/test/test_hmac.c +++ b/components/esp_hw_support/test/test_hmac.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "unity.h" #include "esp_efuse.h" @@ -22,8 +14,6 @@ #if CONFIG_IDF_ENV_FPGA -#include "esp32s2/rom/efuse.h" - /* Allow testing varying message lengths (truncating the same message) for various results */ typedef struct { @@ -31,22 +21,19 @@ typedef struct { uint8_t result[32]; } hmac_result; -static const ets_efuse_block_t key_block = ETS_EFUSE_BLOCK_KEY4; -static const char *TAG = "test_hmac"; - -static void setup_keyblock(void) { +static void setup_keyblock(esp_efuse_block_t key_block, esp_efuse_purpose_t purpose) { const uint8_t key_data[32] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, 25,26,27,28,29,30,31,32 }; - int ets_status = ets_efuse_write_key(key_block, - ETS_EFUSE_KEY_PURPOSE_HMAC_UP, - key_data, sizeof(key_data)); + esp_err_t status = esp_efuse_write_key(key_block, purpose, key_data, sizeof(key_data)); - if (ets_status == ESP_OK) { - printf("written key!\n"); + if (status == ESP_OK) { + printf("Written key!\n"); + } else if (ESP_ERR_EFUSE_REPEATED_PROG) { + printf("Key written already.\n"); } else { - printf("writing key failed, maybe written already\n"); + printf("ERROR while writing key.\n"); } } @@ -54,10 +41,7 @@ TEST_CASE("HMAC 'downstream' JTAG Enable mode", "[hw_crypto]") { int ets_status; - const uint8_t key_data[32] = { - 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, - 25,26,27,28,29,30,31,32 - }; + setup_keyblock(EFUSE_BLK_KEY3, ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG); // Results calculated with Python: // @@ -69,31 +53,13 @@ TEST_CASE("HMAC 'downstream' JTAG Enable mode", "[hw_crypto]") 0x8e, 0x6c, 0x3e, 0x8e, 0x6e, 0x17, 0x62, 0x5c, 0x50, 0xac, 0x66, 0xa9, 0xa8, 0x57, 0x94, 0x9b }; - ets_status = ets_efuse_write_key(ETS_EFUSE_BLOCK_KEY3, - ETS_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG, - key_data, sizeof(key_data)); - - if (ets_status == ESP_OK) { - ESP_LOGI(TAG, "HMAC_DOWN_JTAG key programmed!"); - } else { - ESP_LOGW(TAG, "HMAC_DOWN_JTAG key programming failed, \ - maybe written already. Continuing"); - } - TEST_ASSERT_MESSAGE(ESP_OK == esp_efuse_batch_write_begin(), "Error programming security efuse.\n"); - ets_status = esp_efuse_set_read_protect(ETS_EFUSE_BLOCK_KEY3); - if (ets_status != ESP_OK) { - ESP_LOGW(TAG, "EFUSE_BLOCK read protect setting failed. \ - Not a must prerequisite to run this test case. Continuing"); - } + ets_status = esp_efuse_write_field_cnt(ESP_EFUSE_SOFT_DIS_JTAG, ESP_EFUSE_SOFT_DIS_JTAG[0]->bit_count); - ets_status = esp_efuse_write_field_bit(ESP_EFUSE_SOFT_DIS_JTAG); - if (ets_status != ESP_OK) { - ESP_LOGI(TAG, "JTAG Disable temporarily failed. \ - May be disabled already. Continuing the test."); - } + TEST_ASSERT_MESSAGE(ets_status == ESP_OK || ets_status == ESP_ERR_EFUSE_CNT_IS_FULL, + "JTAG Disable temporarily failed.\n"); TEST_ASSERT_MESSAGE(ESP_OK == esp_efuse_batch_write_commit(), "Error programming security efuse.\n"); @@ -112,7 +78,7 @@ TEST_CASE("HMAC 'upstream' MAC generation with zeroes", "[hw_crypto]") { uint8_t hmac[32]; - setup_keyblock(); + setup_keyblock(EFUSE_BLK_KEY4, ESP_EFUSE_KEY_PURPOSE_HMAC_UP); const uint8_t zeroes[128] = { }; // Produce the HMAC of various numbers of zeroes @@ -207,7 +173,7 @@ TEST_CASE("HMAC 'upstream' MAC generation from data", "[hw_crypto]") { uint8_t hmac[32]; - setup_keyblock(); + setup_keyblock(EFUSE_BLK_KEY4, ESP_EFUSE_KEY_PURPOSE_HMAC_UP); // 257 characters of pseudo-Latin from lipsum.com (not Copyright) const char *message = "Deleniti voluptas explicabo et assumenda. Sed et aliquid minus quis. Praesentium cupiditate quia nemo est. Laboriosam pariatur ut distinctio tenetur. Sunt architecto iure aspernatur soluta ut recusandae. Ut quibusdam occaecati ut qui sit dignissimos eaque.."; @@ -1007,7 +973,8 @@ TEST_CASE("HMAC 'upstream' wait lock", "[hw_crypto]") // 257 characters of pseudo-Latin from lipsum.com (not Copyright) const char *message = "Deleniti voluptas explicabo et assumenda. Sed et aliquid minus quis. Praesentium cupiditate quia nemo est. Laboriosam pariatur ut distinctio tenetur. Sunt architecto iure aspernatur soluta ut recusandae. Ut quibusdam occaecati ut qui sit dignissimos eaque.."; - setup_keyblock(); + setup_keyblock(EFUSE_BLK_KEY4, ESP_EFUSE_KEY_PURPOSE_HMAC_UP); + static const hmac_result results[] = { { .msglen = 255, .result = { 0x59, 0x52, 0x50, 0x4, 0xb6, 0x28, 0xf9, 0x28, 0x7f, 0x6c, 0x37, 0xba, 0xfb, 0xb2, 0x58, 0xe7, 0xa, 0xac, 0x6c, 0x4a, 0xef, 0x66, 0x6, 0x7b, 0x1, 0x1f, 0x4c, 0xa4, 0xe5, 0xe5, 0x29, 0x5d }, @@ -1023,6 +990,12 @@ TEST_CASE("HMAC 'upstream' wait lock", "[hw_crypto]") } } +#endif // CONFIG_IDF_ENV_FPGA + +/** + * This test is just a parameter test and does not write any keys to efuse. + * It can be done safely on any chip which supports HMAC. + */ TEST_CASE("HMAC key out of range", "[hw_crypto]") { uint8_t hmac[32]; @@ -1034,6 +1007,4 @@ TEST_CASE("HMAC key out of range", "[hw_crypto]") TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_hmac_calculate(HMAC_KEY5 + 1, message, 47, hmac)); } -#endif // CONFIG_IDF_ENV_FPGA - #endif // SOC_HMAC_SUPPORTED diff --git a/components/esp_hw_support/test/test_intr_alloc.c b/components/esp_hw_support/test/test_intr_alloc.c index 8ddeffc827..33d40bbbce 100644 --- a/components/esp_hw_support/test/test_intr_alloc.c +++ b/components/esp_hw_support/test/test_intr_alloc.c @@ -1,3 +1,8 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ /* Tests for the interrupt allocator. */ diff --git a/components/esp_hw_support/test/test_random.c b/components/esp_hw_support/test/test_random.c index 083c791246..58aed599b9 100644 --- a/components/esp_hw_support/test/test_random.c +++ b/components/esp_hw_support/test/test_random.c @@ -1,3 +1,8 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include #include "unity.h" diff --git a/components/esp_hw_support/test/test_rtc_clk.c b/components/esp_hw_support/test/test_rtc_clk.c index 22912ad2da..10fa7cc114 100644 --- a/components/esp_hw_support/test/test_rtc_clk.c +++ b/components/esp_hw_support/test/test_rtc_clk.c @@ -1,3 +1,8 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "unity.h" @@ -5,7 +10,7 @@ #include "soc/soc_caps.h" #include "soc/rtc.h" #include "soc/rtc_periph.h" -#if SOC_ADC_SUPPORT_RTC_CTRL +#if SOC_ADC_RTC_CTRL_SUPPORTED #include "soc/sens_periph.h" #endif #include "soc/gpio_periph.h" diff --git a/components/esp_ipc/CMakeLists.txt b/components/esp_ipc/CMakeLists.txt index ecfdaceda4..b164a765d0 100644 --- a/components/esp_ipc/CMakeLists.txt +++ b/components/esp_ipc/CMakeLists.txt @@ -1,2 +1,10 @@ -idf_component_register(SRCS "ipc.c" +set(srcs "src/esp_ipc.c") + +if(CONFIG_ESP_IPC_ISR_ENABLE) + list(APPEND srcs "src/esp_ipc_isr/esp_ipc_isr.c" + "src/esp_ipc_isr/esp_ipc_isr_handler.S" + "src/esp_ipc_isr/esp_ipc_isr_routines.S") +endif() + +idf_component_register(SRCS "${srcs}" INCLUDE_DIRS "include") diff --git a/components/esp_ipc/Kconfig b/components/esp_ipc/Kconfig new file mode 100644 index 0000000000..b97f978007 --- /dev/null +++ b/components/esp_ipc/Kconfig @@ -0,0 +1,39 @@ +menu "IPC (Inter-Processor Call)" + + config ESP_IPC_TASK_STACK_SIZE + int "Inter-Processor Call (IPC) task stack size" + range 512 65536 if !APPTRACE_ENABLE + range 2048 65536 if APPTRACE_ENABLE + default 2048 if APPTRACE_ENABLE + default 1024 + help + Configure the IPC tasks stack size. One IPC task runs on each core + (in dual core mode), and allows for cross-core function calls. + + See IPC documentation for more details. + + The default stack size should be enough for most common use cases. + It can be shrunk if you are sure that you do not use any custom + IPC functionality. + + config ESP_IPC_USES_CALLERS_PRIORITY + bool "IPC runs at caller's priority" + default y + depends on !FREERTOS_UNICORE + help + If this option is not enabled then the IPC task will keep behavior + same as prior to that of ESP-IDF v4.0, and hence IPC task will run + at (configMAX_PRIORITIES - 1) priority. + + config ESP_IPC_ISR_ENABLE + bool + default y if !FREERTOS_UNICORE + help + This feature servers a similar purpose to the IPC except that the callback function is run + in the context of a level 4 interrupt (i.e., high priority/level interrupt). The IPC ISR + feature is intended for low latency execution of simple functions written in assembly on + another CPU. Due to being run in higher level interrupt context, the assembly functions + should be written in a particular way (see esp_test_ipc_isr_asm() and the "High-Level Interrupts" + chapter in hlinterrupts.rst for more details). + +endmenu # "IPC (Inter-Processor Call) diff --git a/components/esp_ipc/component.mk b/components/esp_ipc/component.mk index ebd7a7d59b..4e2e89bb30 100644 --- a/components/esp_ipc/component.mk +++ b/components/esp_ipc/component.mk @@ -1,3 +1,9 @@ # # Component Makefile # + +COMPONENT_SRCDIRS := src +ifdef CONFIG_ESP_IPC_ISR_ENABLE + COMPONENT_SRCDIRS += src/esp_ipc_isr +endif +COMPONENT_ADD_INCLUDEDIRS := include diff --git a/components/esp_ipc/include/esp_ipc.h b/components/esp_ipc/include/esp_ipc.h index 477b3d0af4..5e02c460bc 100644 --- a/components/esp_ipc/include/esp_ipc.h +++ b/components/esp_ipc/include/esp_ipc.h @@ -20,6 +20,9 @@ #ifdef __cplusplus extern "C" { #endif + +#if !defined(CONFIG_FREERTOS_UNICORE) || defined(CONFIG_APPTRACE_GCOV_ENABLE) + /** @cond */ typedef void (*esp_ipc_func_t)(void* arg); /** @endcond */ @@ -85,6 +88,7 @@ esp_err_t esp_ipc_call(uint32_t cpu_id, esp_ipc_func_t func, void* arg); */ esp_err_t esp_ipc_call_blocking(uint32_t cpu_id, esp_ipc_func_t func, void* arg); +#endif // not CONFIG_FREERTOS_UNICORE or CONFIG_APPTRACE_GCOV_ENABLE #ifdef __cplusplus } diff --git a/components/esp_ipc/include/esp_ipc_isr.h b/components/esp_ipc/include/esp_ipc_isr.h new file mode 100644 index 0000000000..7b6e060f1d --- /dev/null +++ b/components/esp_ipc/include/esp_ipc_isr.h @@ -0,0 +1,117 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "sdkconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef CONFIG_ESP_IPC_ISR_ENABLE + +/** @cond */ +typedef void (*esp_ipc_isr_func_t)(void* arg); +/** @endcond */ + +/** + * @brief Initialize inter-processor call module which based on #4 high-interrupt. + * + * This function is called on CPU start and should not be called from the application. + * + * This function starts two tasks, one on each CPU. These tasks register + * #4 High-interrupt and after that, the tasks are deleted. + * The next API functions work with this functionality: + * esp_ipc_isr_asm_call + * esp_ipc_isr_asm_call_blocking + * They allow to run an asm function on other CPU. + */ +void esp_ipc_isr_init(void); + +/** + * @brief Execute an asm function on the other CPU (uses the #4 high-priority interrupt) + * + * @note In single-core mode, it is not available. + * This function calls the #4 high-priority interrupt on the other CPU. + * The given function is called in the context of the interrupt by CALLX0 command and + * operates with registers a2, a3, a4. + * + * @param[in] func Pointer to a function of type void func(void* arg) to be executed + * @param[in] arg Arbitrary argument of type void* to be passed into the function + */ +void esp_ipc_isr_asm_call(esp_ipc_isr_func_t func, void* arg); + +/** + * @brief Execute an asm function on the other CPU and blocks until it completes (uses the #4 high-priority interrupt) + * + * @note In single-core mode, it is not available. + * This function calls the #4 high-priority interrupt on the other CPU. + * The given function is called in the context of the interrupt by CALLX0 command. + * + * @param[in] func Pointer to a function of type void func(void* arg) to be executed + * @param[in] arg Arbitrary argument of type void* to be passed into the function + */ +void esp_ipc_isr_asm_call_blocking(esp_ipc_isr_func_t func, void* arg); + +/** + * @brief Stall the other CPU and the current CPU disables interrupts with level 3 and lower. + * + * @note In single-core mode, it is not available. + * This function calls the #4 high-priority interrupt on the other CPU. + * The esp_ipc_isr_finish_cmd() function is called on the other CPU in the context of the #4 high-priority interrupt. + * The esp_ipc_isr_finish_cmd is called by CALLX0 command. + * It is waiting for the end command. The command will be sent by esp_ipc_isr_release_other_cpu(). + * This function is used for DPORT workaround. + * + * This function blocks other CPU until the release call esp_ipc_isr_release_other_cpu(). + * + * This fucntion is used for the DPORT workaround: stall other cpu that this cpu is pending to access dport register start. + */ +void esp_ipc_isr_stall_other_cpu(void); + +/** + * @brief Release the other CPU + * + * @note In single-core mode, it is not available. + * This function will send the end command to release the stall other CPU. + * This function is used for DPORT workaround: stall other cpu that this cpu is pending to access dport register end. + * + */ +void esp_ipc_isr_release_other_cpu(void); + +/** + * @brief Pause stall the other CPU + */ +void esp_ipc_isr_stall_pause(void); + +/** + * @brief Abort stall the other CPU + * + * This routine does not stop the stall routines in any way that is recoverable. + * Please only call in case of panic(). + * Used in panic code: the enter_critical stuff may be messed up so we just stop everything without checking the mux. + */ +void esp_ipc_isr_stall_abort(void); + +/** + * @brief Resume stall the other CPU + */ +void esp_ipc_isr_stall_resume(void); + +#else // not CONFIG_ESP_IPC_ISR_ENABLE + +#define esp_ipc_isr_stall_other_cpu() +#define esp_ipc_isr_release_other_cpu() +#define esp_ipc_isr_stall_pause() +#define esp_ipc_isr_stall_abort() +#define esp_ipc_isr_stall_resume() + +#endif // CONFIG_ESP_IPC_ISR_ENABLE + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_ipc/ipc.c b/components/esp_ipc/src/esp_ipc.c similarity index 78% rename from components/esp_ipc/ipc.c rename to components/esp_ipc/src/esp_ipc.c index 7d63d6f87f..2b31d09770 100644 --- a/components/esp_ipc/ipc.c +++ b/components/esp_ipc/src/esp_ipc.c @@ -18,17 +18,20 @@ #include #include "esp_err.h" #include "esp_ipc.h" +#include "esp_ipc_isr.h" #include "esp_attr.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/semphr.h" +#if !defined(CONFIG_FREERTOS_UNICORE) || defined(CONFIG_APPTRACE_GCOV_ENABLE) + static TaskHandle_t s_ipc_task_handle[portNUM_PROCESSORS]; static SemaphoreHandle_t s_ipc_mutex[portNUM_PROCESSORS]; // This mutex is used as a global lock for esp_ipc_* APIs static SemaphoreHandle_t s_ipc_sem[portNUM_PROCESSORS]; // Two semaphores used to wake each of ipc tasks static SemaphoreHandle_t s_ipc_ack[portNUM_PROCESSORS]; // Semaphore used to acknowledge that task was woken up, - // or function has finished running + // or function has finished running static volatile esp_ipc_func_t s_func[portNUM_PROCESSORS]; // Function which should be called by high priority task static void * volatile s_func_arg[portNUM_PROCESSORS]; // Argument to pass into s_func typedef enum { @@ -40,6 +43,11 @@ static volatile esp_ipc_wait_t s_ipc_wait[portNUM_PROCESSORS];// This variable t // s_ipc_ack semaphore: before s_func is called, or // after it returns +#if CONFIG_APPTRACE_GCOV_ENABLE +static volatile esp_ipc_func_t s_gcov_func = NULL; // Gcov dump starter function which should be called by high priority task +static void * volatile s_gcov_func_arg; // Argument to pass into s_gcov_func +#endif + static void IRAM_ATTR ipc_task(void* arg) { const int cpuid = (int) arg; @@ -53,16 +61,25 @@ static void IRAM_ATTR ipc_task(void* arg) abort(); } - esp_ipc_func_t func = s_func[cpuid]; - void* arg = s_func_arg[cpuid]; +#if CONFIG_APPTRACE_GCOV_ENABLE + if (s_gcov_func) { + (*s_gcov_func)(s_gcov_func_arg); + s_gcov_func = NULL; + } +#endif + if (s_func[cpuid]) { + esp_ipc_func_t func = s_func[cpuid]; + void* arg = s_func_arg[cpuid]; - if (s_ipc_wait[cpuid] == IPC_WAIT_FOR_START) { - xSemaphoreGive(s_ipc_ack[cpuid]); - } - (*func)(arg); - if (s_ipc_wait[cpuid] == IPC_WAIT_FOR_END) { - xSemaphoreGive(s_ipc_ack[cpuid]); + if (s_ipc_wait[cpuid] == IPC_WAIT_FOR_START) { + xSemaphoreGive(s_ipc_ack[cpuid]); + } + (*func)(arg); + if (s_ipc_wait[cpuid] == IPC_WAIT_FOR_END) { + xSemaphoreGive(s_ipc_ack[cpuid]); + } } + } // TODO: currently this is unreachable code. Introduce esp_ipc_uninit // function which will signal to both tasks that they can shut down. @@ -86,7 +103,11 @@ static void esp_ipc_init(void) __attribute__((constructor)); static void esp_ipc_init(void) { +#ifdef CONFIG_ESP_IPC_ISR_ENABLE + esp_ipc_isr_init(); +#endif char task_name[15]; + for (int i = 0; i < portNUM_PROCESSORS; ++i) { snprintf(task_name, sizeof(task_name), "ipc%d", i); s_ipc_mutex[i] = xSemaphoreCreateMutex(); @@ -127,6 +148,7 @@ static esp_err_t esp_ipc_call_and_wait(uint32_t cpu_id, esp_ipc_func_t func, voi s_ipc_wait[cpu_id] = wait_for; xSemaphoreGive(s_ipc_sem[cpu_id]); xSemaphoreTake(s_ipc_ack[cpu_id], portMAX_DELAY); + s_func[cpu_id] = NULL; #ifdef CONFIG_ESP_IPC_USES_CALLERS_PRIORITY xSemaphoreGive(s_ipc_mutex[cpu_id]); #else @@ -144,3 +166,20 @@ esp_err_t esp_ipc_call_blocking(uint32_t cpu_id, esp_ipc_func_t func, void* arg) { return esp_ipc_call_and_wait(cpu_id, func, arg, IPC_WAIT_FOR_END); } + +// currently this is only called from gcov component +#if CONFIG_APPTRACE_GCOV_ENABLE +esp_err_t esp_ipc_start_gcov_from_isr(uint32_t cpu_id, esp_ipc_func_t func, void* arg) +{ + if (xTaskGetSchedulerState() != taskSCHEDULER_RUNNING) { + return ESP_ERR_INVALID_STATE; + } + s_gcov_func = func; + s_gcov_func_arg = arg; + xSemaphoreGiveFromISR(s_ipc_sem[cpu_id], NULL); + + return ESP_OK; +} +#endif + +#endif // not CONFIG_FREERTOS_UNICORE or CONFIG_APPTRACE_GCOV_ENABLE diff --git a/components/esp_ipc/src/esp_ipc_isr/esp_ipc_isr.c b/components/esp_ipc/src/esp_ipc_isr/esp_ipc_isr.c new file mode 100644 index 0000000000..a893713e8b --- /dev/null +++ b/components/esp_ipc/src/esp_ipc_isr/esp_ipc_isr.c @@ -0,0 +1,215 @@ +/* + * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include "esp_err.h" +#include "esp_attr.h" +#include "soc/cpu.h" +#include "soc/soc.h" +#include "soc/dport_access.h" +#ifdef CONFIG_IDF_TARGET_ESP32 +#include "soc/dport_reg.h" +#else +#include "soc/periph_defs.h" +#include "soc/system_reg.h" +#endif +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/portmacro.h" +#include "esp_intr_alloc.h" +#include "esp_ipc_isr.h" +#include "xtensa/core-macros.h" +#include "sdkconfig.h" + +static portMUX_TYPE s_ipc_isr_mux = portMUX_INITIALIZER_UNLOCKED; +uint32_t volatile esp_ipc_isr_start_fl; // the flag shows that it is about to run esp_ipc_func() +uint32_t volatile esp_ipc_isr_end_fl = 1; // the flag shows that esp_ipc_func() is done +esp_ipc_isr_func_t volatile esp_ipc_func; // the function which will be run in the ipc_isr context +void * volatile esp_ipc_func_arg; // the argument of esp_ipc_func() + +typedef enum { + STALL_STATE_IDLE = 0, + STALL_STATE_RUNNING = 1, +} stall_state_t; + +static stall_state_t volatile s_stall_state = STALL_STATE_IDLE; +static int32_t volatile s_count_of_nested_calls[portNUM_PROCESSORS] = { 0 }; +static BaseType_t s_stored_interrupt_level; +static uint32_t volatile esp_ipc_isr_finish_cmd; + + +/** + * @brief Type of calling + */ +typedef enum { + IPC_ISR_WAIT_FOR_START = 0, /*!< The caller is waiting for the start */ + IPC_ISR_WAIT_FOR_END = 1, /*!< The caller is waiting for the end */ +} esp_ipc_isr_wait_t; + +#define IPC_ISR_ENTER_CRITICAL() portENTER_CRITICAL_SAFE(&s_ipc_isr_mux) +#define IPC_ISR_EXIT_CRITICAL() portEXIT_CRITICAL_SAFE(&s_ipc_isr_mux) + +static void esp_ipc_isr_call_and_wait(esp_ipc_isr_func_t func, void* arg, esp_ipc_isr_wait_t wait_for); + + +/* Initializing IPC_ISR */ + +static void esp_ipc_isr_init_cpu(void* arg) +{ + (void) arg; + const uint32_t cpuid = xPortGetCoreID(); + uint32_t intr_source = ETS_FROM_CPU_INTR2_SOURCE + cpuid; // ETS_FROM_CPU_INTR2_SOURCE and ETS_FROM_CPU_INTR3_SOURCE + ESP_INTR_DISABLE(ETS_IPC_ISR_INUM); + intr_matrix_set(cpuid, intr_source, ETS_IPC_ISR_INUM); + ESP_INTR_ENABLE(ETS_IPC_ISR_INUM); + + /* If this fails then the minimum stack size for this config is too close to running out */ + assert(uxTaskGetStackHighWaterMark(NULL) > 128); + + if (cpuid != 0) { + s_stall_state = STALL_STATE_RUNNING; + } + vTaskDelete(NULL); +} + +void esp_ipc_isr_init(void) +{ + for (unsigned i = 0; i < portNUM_PROCESSORS; ++i) { + portBASE_TYPE res = xTaskCreatePinnedToCore(esp_ipc_isr_init_cpu, "ipc_isr_init", configMINIMAL_STACK_SIZE, NULL, 5, NULL, i); + assert(res == pdTRUE); + (void)res; + } +} + +/* End initializing IPC_ISR */ + + +/* Public API functions */ + +void IRAM_ATTR esp_ipc_isr_asm_call(esp_ipc_isr_func_t func, void* arg) +{ + IPC_ISR_ENTER_CRITICAL(); + esp_ipc_isr_call_and_wait(func, arg, IPC_ISR_WAIT_FOR_START); + IPC_ISR_EXIT_CRITICAL(); +} + +void IRAM_ATTR esp_ipc_isr_asm_call_blocking(esp_ipc_isr_func_t func, void* arg) +{ + IPC_ISR_ENTER_CRITICAL(); + esp_ipc_isr_call_and_wait(func, arg, IPC_ISR_WAIT_FOR_END); + IPC_ISR_EXIT_CRITICAL(); +} + +// This asm function is from esp_ipc_isr_routines.S. +// It is waiting for the finish_cmd command in a loop. +void esp_ipc_isr_waiting_for_finish_cmd(void* finish_cmd); + +/* + * esp_ipc_isr_stall_other_cpu is used for: + * - stall other CPU, + * - do protection when dual core access DPORT internal register and APB register via DPORT simultaneously. + * This function will be initialize after FreeRTOS startup. + * When cpu0 wants to access DPORT register, it should notify cpu1 enter in high-priority interrupt for be mute. + * When cpu1 already in high-priority interrupt, cpu0 can access DPORT register. + * Currently, cpu1 will wait for cpu0 finish access and exit high-priority interrupt. + */ +void IRAM_ATTR esp_ipc_isr_stall_other_cpu(void) +{ + if (s_stall_state == STALL_STATE_RUNNING) { + BaseType_t intLvl = portENTER_CRITICAL_NESTED(); + const uint32_t cpu_id = xPortGetCoreID(); + if (s_count_of_nested_calls[cpu_id]++ == 0) { + IPC_ISR_ENTER_CRITICAL(); + s_stored_interrupt_level = intLvl; + esp_ipc_isr_finish_cmd = 0; + esp_ipc_isr_call_and_wait(&esp_ipc_isr_waiting_for_finish_cmd, (void*)&esp_ipc_isr_finish_cmd, IPC_ISR_WAIT_FOR_START); + return; + } + + /* Interrupts are already disabled by the parent, we're nested here. */ + portEXIT_CRITICAL_NESTED(intLvl); + } +} + +void IRAM_ATTR esp_ipc_isr_release_other_cpu(void) +{ + if (s_stall_state == STALL_STATE_RUNNING) { + const uint32_t cpu_id = xPortGetCoreID(); + if (--s_count_of_nested_calls[cpu_id] == 0) { + esp_ipc_isr_finish_cmd = 1; + IPC_ISR_EXIT_CRITICAL(); + portEXIT_CRITICAL_NESTED(s_stored_interrupt_level); + } else if (s_count_of_nested_calls[cpu_id] < 0) { + assert(0); + } + } +} + +void IRAM_ATTR esp_ipc_isr_stall_pause(void) +{ + IPC_ISR_ENTER_CRITICAL(); + s_stall_state = STALL_STATE_IDLE; + IPC_ISR_EXIT_CRITICAL(); +} + +void IRAM_ATTR esp_ipc_isr_stall_abort(void) +{ + s_stall_state = STALL_STATE_IDLE; +} + +void IRAM_ATTR esp_ipc_isr_stall_resume(void) +{ + IPC_ISR_ENTER_CRITICAL(); + s_stall_state = STALL_STATE_RUNNING; + IPC_ISR_EXIT_CRITICAL(); +} + +void esp_dport_access_stall_other_cpu_start(void) __attribute__((alias("esp_ipc_isr_stall_other_cpu"))); +void esp_dport_access_stall_other_cpu_end(void) __attribute__((alias("esp_ipc_isr_release_other_cpu"))); +void esp_dport_access_int_pause(void) __attribute__((alias("esp_ipc_isr_stall_pause"))); +void esp_dport_access_int_abort(void) __attribute__((alias("esp_ipc_isr_stall_abort"))); +void esp_dport_access_int_resume(void) __attribute__((alias("esp_ipc_isr_stall_resume"))); + +/* End public API functions */ + + +/* Private functions*/ + +static void IRAM_ATTR esp_ipc_isr_call_and_wait(esp_ipc_isr_func_t func, void* arg, esp_ipc_isr_wait_t wait_for) +{ + const uint32_t cpu_id = xPortGetCoreID(); + + // waiting for the end of the previous call + while (!esp_ipc_isr_end_fl) {}; + + esp_ipc_func = func; + esp_ipc_func_arg = arg; + + esp_ipc_isr_start_fl = 0; + esp_ipc_isr_end_fl = 0; + + if (cpu_id == 0) { + // it runs an interrupt on cpu1 + DPORT_REG_WRITE(SYSTEM_CPU_INTR_FROM_CPU_3_REG, SYSTEM_CPU_INTR_FROM_CPU_3); + } else { + // it runs an interrupt on cpu0 + DPORT_REG_WRITE(SYSTEM_CPU_INTR_FROM_CPU_2_REG, SYSTEM_CPU_INTR_FROM_CPU_2); + } + + // IPC_ISR handler will be called and `...isr_start` and `...isr_end` will be updated there + + if (wait_for == IPC_ISR_WAIT_FOR_START) { + while (!esp_ipc_isr_start_fl) {}; + } else { + // IPC_ISR_WAIT_FOR_END + while (!esp_ipc_isr_end_fl) {}; + } +} + +/* End private functions*/ diff --git a/components/esp_ipc/src/esp_ipc_isr/esp_ipc_isr_handler.S b/components/esp_ipc/src/esp_ipc_isr/esp_ipc_isr_handler.S new file mode 100644 index 0000000000..0fb4ae676a --- /dev/null +++ b/components/esp_ipc/src/esp_ipc_isr/esp_ipc_isr_handler.S @@ -0,0 +1,121 @@ +/* + * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "freertos/xtensa_context.h" +#include "esp_private/panic_reason.h" +#include "sdkconfig.h" +#include "soc/soc.h" +#include "soc/dport_reg.h" + +/* High-priority interrupt - IPC_ISR handler */ + +#if CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_5 +#define LX_INTR_STACK_SIZE 16 +#define LX_INTR_A0_OFFSET 0 +#define LX_INTR_A2_OFFSET 4 +#define LX_INTR_A3_OFFSET 8 +#define LX_INTR_A4_OFFSET 12 +#define EXCSAVE_X EXCSAVE_5 +#define RFI_X 5 + +#elif CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4 + +#define LX_INTR_STACK_SIZE 16 +#define LX_INTR_A0_OFFSET 0 +#define LX_INTR_A2_OFFSET 4 +#define LX_INTR_A3_OFFSET 8 +#define LX_INTR_A4_OFFSET 12 +#define EXCSAVE_X EXCSAVE_4 +#define RFI_X 4 + +#endif /* CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_5 */ + + .data +_lx_intr_stack: + .space LX_INTR_STACK_SIZE + .section .iram1,"ax" + .global esp_ipc_isr_handler + .type esp_ipc_isr_handler,@function + .align 4 +esp_ipc_isr_handler: + /* Allocate exception frame and save minimal context. */ + /* Because the interrupt cause code has protection that only + allows one cpu to enter in the IPC_ISR section of the LX + interrupt at one time, there's no need to have two + _lx_intr_stack for each cpu */ + + /* Save A0, A2, A3, A4 so we can use those registers further*/ + movi a0, _lx_intr_stack + s32i a2, a0, LX_INTR_A2_OFFSET + s32i a3, a0, LX_INTR_A3_OFFSET + s32i a4, a0, LX_INTR_A4_OFFSET + rsr a2, EXCSAVE_X + s32i a2, a0, LX_INTR_A0_OFFSET + + /* disable nested iterrupts */ + /* PS.EXCM is changed from 1 to 0 . It allows using usually exception handler instead of the Double exception handler. */ + /* PS_UM = 1 */ + movi a0, PS_INTLEVEL(5) | PS_UM + wsr a0, PS + rsync + /* restore PS will be done by rfi the end */ + + /* + * Reset isr interrupt flags + */ +#if CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_5 + /* This int is level-triggered and doesn't need clearing. + Do nothing here and clear int status by peripheral register later.*/ +#elif CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4 + /* This int is edge-triggered and needs clearing. */ + movi a3, (1 << ETS_IPC_ISR_INUM) + wsr a3, INTCLEAR +#endif /* CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_5 */ + + /* get CORE_ID */ + getcoreid a3 + beqz a3, 1f + + /* current cpu is 1 */ + movi a3, SYSTEM_CPU_INTR_FROM_CPU_3_REG + movi a4, 0 + s32i a4, a3, 0 /* clear intr */ + j 2f +1: + /* current cpu is 0 */ + movi a3, SYSTEM_CPU_INTR_FROM_CPU_2_REG + movi a4, 0 + s32i a4, a3, 0 /* clear intr */ +2: + + /* set the start flag */ + movi a0, esp_ipc_isr_start_fl + s32i a0, a0, 0 + + /* Call the esp_ipc_function(void* arg) */ + movi a0, esp_ipc_func + l32i a0, a0, 0 + movi a2, esp_ipc_func_arg + l32i a2, a2, 0 + callx0 a0 + + /* Done. Restore registers and return. */ + movi a0, _lx_intr_stack + l32i a2, a0, LX_INTR_A2_OFFSET + l32i a3, a0, LX_INTR_A3_OFFSET + l32i a4, a0, LX_INTR_A4_OFFSET + + /* set the end flag */ + movi a0, esp_ipc_isr_end_fl + s32i a0, a0, 0 + + /* restore a0 */ + rsr a0, EXCSAVE_X + /* restores PS from EPS[X] and jumps to the address in EPC[X] */ + rfi RFI_X diff --git a/components/esp_ipc/src/esp_ipc_isr/esp_ipc_isr_routines.S b/components/esp_ipc/src/esp_ipc_isr/esp_ipc_isr_routines.S new file mode 100644 index 0000000000..77b6b0406b --- /dev/null +++ b/components/esp_ipc/src/esp_ipc_isr/esp_ipc_isr_routines.S @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +/* esp_ipc_isr_waiting_for_finish_cmd(void* finish_cmd) + * + * It should be called by the CALLX0 command from the handler of High-priority interrupt (4 lvl). + * Only these registers [a2, a3, a4] can be used here. + */ + .section .iram1, "ax" + .align 4 + .global esp_ipc_isr_waiting_for_finish_cmd + .type esp_ipc_isr_waiting_for_finish_cmd, @function +// Args: +// a2 - finish_cmd (pointer on esp_ipc_isr_finish_cmd) +esp_ipc_isr_waiting_for_finish_cmd: + /* waiting for the finish command */ +.check_finish_cmd: + l32i a3, a2, 0 + beqz a3, .check_finish_cmd + ret diff --git a/components/esp_ipc/test/CMakeLists.txt b/components/esp_ipc/test/CMakeLists.txt index 24591e199b..7a1793d816 100644 --- a/components/esp_ipc/test/CMakeLists.txt +++ b/components/esp_ipc/test/CMakeLists.txt @@ -1,4 +1,4 @@ -if(IDF_TARGET STREQUAL "esp32") +if(IDF_TARGET STREQUAL "esp32" OR IDF_TARGET STREQUAL "esp32s3") idf_component_register(SRC_DIRS "." PRIV_INCLUDE_DIRS "." PRIV_REQUIRES cmock test_utils esp_ipc) diff --git a/components/esp_ipc/test/component.mk b/components/esp_ipc/test/component.mk index ce464a212a..ed5fa25e2e 100644 --- a/components/esp_ipc/test/component.mk +++ b/components/esp_ipc/test/component.mk @@ -1 +1,2 @@ +COMPONENT_SRCDIRS := . COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive diff --git a/components/esp_ipc/test/test_ipc_isr.S b/components/esp_ipc/test/test_ipc_isr.S new file mode 100644 index 0000000000..a448e38997 --- /dev/null +++ b/components/esp_ipc/test/test_ipc_isr.S @@ -0,0 +1,61 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +/* esp_test_ipc_isr_asm(void *arg) + * + * It should be called by the CALLX0 command from the handler of High-priority interrupt (4 lvl). + * Only these registers [a2, a3, a4] can be used here. + */ + .section .iram1, "ax" + .align 4 + .global esp_test_ipc_isr_asm + .type esp_test_ipc_isr_asm, @function +// Args: +// a2 - void* arg +esp_test_ipc_isr_asm: + movi a3, 0xa5a5 + s32i a3, a2, 0 + ret + + +/* esp_test_ipc_isr_get_other_core_id(void *arg) + * + * this function puts the core_id of the other CPU in the arg. + * use only a2, a3 and a4 regs here. +*/ + .section .iram1, "ax" + .align 4 + .global esp_test_ipc_isr_get_other_core_id + .type esp_test_ipc_isr_get_other_core_id, @function + // Args: + // a2 - void* arg + esp_test_ipc_isr_get_other_core_id: + rsr.prid a3 + extui a3, a3, 13, 1 + s32i a3, a2, 0 + ret + + +/* esp_test_ipc_isr_get_cycle_count_other_cpu(void *arg) + * + * this function puts CCOUNT of the other CPU in the arg. + * use only a2, a3 and a4 regs here. +*/ + .section .iram1, "ax" + .align 4 + .global esp_test_ipc_isr_get_cycle_count_other_cpu + .type esp_test_ipc_isr_get_cycle_count_other_cpu, @function + // Args: + // a2 - void* arg + esp_test_ipc_isr_get_cycle_count_other_cpu: + rsr.ccount a3 + s32i a3, a2, 0 + ret diff --git a/components/esp_ipc/test/test_ipc_isr.c b/components/esp_ipc/test/test_ipc_isr.c new file mode 100644 index 0000000000..cad29e814c --- /dev/null +++ b/components/esp_ipc/test/test_ipc_isr.c @@ -0,0 +1,85 @@ +#include +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "unity.h" +#include "test_utils.h" +#include "esp_rom_sys.h" +#include "esp_ipc_isr.h" + +#ifdef CONFIG_ESP_IPC_ISR_ENABLE + +void esp_test_ipc_isr_asm(void* arg); + +TEST_CASE("Test ipc_isr blocking IPC function calls a ASM function", "[ipc]") +{ + int val = 0x5a5a; + esp_ipc_isr_asm_call_blocking(esp_test_ipc_isr_asm, &val); + TEST_ASSERT_EQUAL_HEX(val, 0xa5a5); +} + +void esp_test_ipc_isr_get_other_core_id(void* arg); + + +TEST_CASE("Test ipc_isr blocking IPC function calls get_other_core_id", "[ipc]") +{ + int val = 0x5a5a; + esp_ipc_isr_asm_call_blocking(esp_test_ipc_isr_get_other_core_id, &val); + TEST_ASSERT_EQUAL_HEX(val, 1); +} + +TEST_CASE("Test ipc_isr exception in asm func leads to StoreProhibited not to Unhandled debug exception", "[ipc][reset=StoreProhibited,SW_CPU_RESET]") +{ + esp_ipc_isr_asm_call_blocking(esp_test_ipc_isr_asm, NULL); +} + +void esp_test_ipc_isr_get_cycle_count_other_cpu(void* arg); + +TEST_CASE("Test ipc_isr blocking IPC function calls get_cycle_count_other_cpu", "[ipc]") +{ + int val = 0x5a5a; + esp_ipc_isr_asm_call_blocking(esp_test_ipc_isr_get_cycle_count_other_cpu, &val); + esp_rom_printf("CCOUNT CPU0 = %d\n", cpu_ll_get_cycle_count()); + esp_rom_printf("CCOUNT CPU1 = %d\n", val); +} + +static bool volatile s_stop; + +static void task_asm(void *arg) +{ + xSemaphoreHandle *sema = (xSemaphoreHandle *) arg; + int val; + int counter = 0; + printf("task_asm\n"); + while (s_stop == false) { + val = 0x5a5a; + esp_ipc_isr_asm_call_blocking(esp_test_ipc_isr_asm, &val); + TEST_ASSERT_EQUAL_HEX(val, 0xa5a5); + ++counter; + } + printf("task_asm counter = %d\n", counter); + TEST_ASSERT_GREATER_THAN(1000000, counter); + xSemaphoreGive(*sema); + vTaskDelete(NULL); +} + +TEST_CASE("Test ipc_isr two tasks use IPC function calls", "[ipc]") +{ + xSemaphoreHandle exit_sema[2]; + exit_sema[0] = xSemaphoreCreateBinary(); + exit_sema[1] = xSemaphoreCreateBinary(); + s_stop = false; + printf("Test start\n"); + xTaskCreatePinnedToCore(task_asm, "task_asm", 2048, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, NULL, 0); + xTaskCreatePinnedToCore(task_asm, "task_asm", 2048, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, NULL, 1); + vTaskDelay(5000 / portTICK_PERIOD_MS); + s_stop = true; + xSemaphoreTake(exit_sema[0], portMAX_DELAY); + xSemaphoreTake(exit_sema[1], portMAX_DELAY); + printf("Test end\n"); + + vSemaphoreDelete(exit_sema[0]); + vSemaphoreDelete(exit_sema[1]); +} +#endif /* CONFIG_ESP_IPC_ISR_ENABLE */ diff --git a/components/esp_lcd/CMakeLists.txt b/components/esp_lcd/CMakeLists.txt index 31dc623873..ffc0cd5119 100644 --- a/components/esp_lcd/CMakeLists.txt +++ b/components/esp_lcd/CMakeLists.txt @@ -1,14 +1,17 @@ set(srcs "src/esp_lcd_common.c" "src/esp_lcd_panel_io.c" "src/esp_lcd_panel_io_i2c.c" + "src/esp_lcd_panel_io_i2s.c" "src/esp_lcd_panel_io_spi.c" "src/esp_lcd_panel_io_i80.c" + "src/esp_lcd_panel_nt35510.c" "src/esp_lcd_panel_ssd1306.c" "src/esp_lcd_panel_st7789.c" "src/esp_lcd_panel_ops.c" "src/esp_lcd_rgb_panel.c") set(includes "include" "interface") +set(priv_requires "driver") idf_component_register(SRCS ${srcs} INCLUDE_DIRS ${includes} - PRIV_INCLUDE_DIRS ${priv_includes}) + PRIV_REQUIRES ${priv_requires}) diff --git a/components/esp_lcd/Kconfig b/components/esp_lcd/Kconfig index d7ca5dc1c2..02a47a09c4 100644 --- a/components/esp_lcd/Kconfig +++ b/components/esp_lcd/Kconfig @@ -1,20 +1,10 @@ menu "LCD and Touch Panel" menu "LCD Peripheral Configuration" - depends on IDF_TARGET_ESP32S3 - choice LCD_PERIPH_CLK_SRC - prompt "Select clock source for LCD peripheral" - default LCD_PERIPH_CLK_SRC_XTAL if PM_ENABLE - default LCD_PERIPH_CLK_SRC_PLL160M + config LCD_PANEL_IO_FORMAT_BUF_SIZE + int "LCD panel io format buffer size" + default 32 help - The peripheral clock is where LCD bus clock derives from. - Each clock source has its unique feature, e.g. - 1. XTAL clock can help LCD work stable when DFS is enabled - 2. PLL160M can achieve higher pixel clock resolution - - config LCD_PERIPH_CLK_SRC_PLL160M - bool "PLL_160M clock" - config LCD_PERIPH_CLK_SRC_XTAL - bool "XTAL clock" - endchoice # LCD_PERIPH_CLK_SRC + LCD driver allocates an internal buffer to transform the data into a proper format, because of + the endian order mismatch. This option is to set the size of the buffer, in bytes. endmenu endmenu diff --git a/components/esp_lcd/include/esp_lcd_panel_io.h b/components/esp_lcd/include/esp_lcd_panel_io.h index c362180f53..eebcabf42b 100644 --- a/components/esp_lcd/include/esp_lcd_panel_io.h +++ b/components/esp_lcd/include/esp_lcd_panel_io.h @@ -9,6 +9,7 @@ #include "esp_err.h" #include "esp_lcd_types.h" #include "soc/soc_caps.h" +#include "hal/lcd_types.h" #ifdef __cplusplus extern "C" { @@ -28,14 +29,13 @@ typedef struct esp_lcd_i80_bus_t *esp_lcd_i80_bus_handle_t; /*!< Type of LCD i * * @param[in] io LCD panel IO handle, which is created by other factory API like `esp_lcd_new_panel_io_spi()` * @param[in] lcd_cmd The specific LCD command - * @param[in] lcd_cmd_bits Length of LCD command, in bits (e.g. 8 bits or 16 bits) * @param[in] param Buffer that holds the command specific parameters, set to NULL if no parameter is needed for the command * @param[in] param_size Size of `param` in memory, in bytes, set to zero if no parameter is needed for the command * @return * - ESP_ERR_INVALID_ARG if parameter is invalid * - ESP_OK on success */ -esp_err_t esp_lcd_panel_io_tx_param(esp_lcd_panel_io_handle_t io, int lcd_cmd, int lcd_cmd_bits, const void *param, size_t param_size); +esp_err_t esp_lcd_panel_io_tx_param(esp_lcd_panel_io_handle_t io, int lcd_cmd, const void *param, size_t param_size); /** * @brief Transmit LCD RGB data @@ -47,14 +47,13 @@ esp_err_t esp_lcd_panel_io_tx_param(esp_lcd_panel_io_handle_t io, int lcd_cmd, i * * @param[in] io LCD panel IO handle, which is created by factory API like `esp_lcd_new_panel_io_spi()` * @param[in] lcd_cmd The specific LCD command - * @param[in] lcd_cmd_bits Length of LCD command, in bits (e.g. 8 bits or 16 bits) * @param[in] color Buffer that holds the RGB color data * @param[in] color_size Size of `color` in memory, in bytes * @return * - ESP_ERR_INVALID_ARG if parameter is invalid * - ESP_OK on success */ -esp_err_t esp_lcd_panel_io_tx_color(esp_lcd_panel_io_handle_t io, int lcd_cmd, int lcd_cmd_bits, const void *color, size_t color_size); +esp_err_t esp_lcd_panel_io_tx_color(esp_lcd_panel_io_handle_t io, int lcd_cmd, const void *color, size_t color_size); /** * @brief Destory LCD panel IO handle (deinitialize panel and free all corresponding resource) @@ -76,10 +75,13 @@ typedef struct { unsigned int pclk_hz; /*!< Frequency of pixel clock */ size_t trans_queue_depth; /*!< Size of internal transaction queue */ bool (*on_color_trans_done)(esp_lcd_panel_io_handle_t panel_io, void *user_data, void *event_data); /*!< Callback, invoked when color data transfer has finished */ - void *user_data; /*!< User private data, passed directly to on_trans_frame_done's user_data */ + void *user_data; /*!< User private data, passed directly to on_trans_frame_done's user_data */ + int lcd_cmd_bits; /*!< Bit-width of LCD command */ + int lcd_param_bits; /*!< Bit-width of LCD parameter */ struct { unsigned int dc_as_cmd_phase: 1; /*!< D/C line value is encoded into SPI transaction command phase */ unsigned int dc_low_on_data: 1; /*!< If this flag is enabled, DC line = 0 means transfer data, DC line = 1 means transfer command; vice versa */ + unsigned int octal_mode: 1; /*!< transmit with octal mode (8 data lines), this mode is used to simulate Intel 8080 timing */ } flags; } esp_lcd_panel_io_spi_config_t; @@ -102,6 +104,8 @@ typedef struct { void *user_data; /*!< User private data, passed directly to on_trans_frame_done's user_data */ size_t control_phase_bytes; /*!< I2C LCD panel will encode control information (e.g. D/C seclection) into control phase, in several bytes */ unsigned int dc_bit_offset; /*!< Offset of the D/C selection bit in control phase */ + int lcd_cmd_bits; /*!< Bit-width of LCD command */ + int lcd_param_bits; /*!< Bit-width of LCD parameter */ struct { unsigned int dc_low_on_data: 1; /*!< If this flag is enabled, DC line = 0 means transfer data, DC line = 1 means transfer command; vice versa */ } flags; @@ -127,8 +131,9 @@ esp_err_t esp_lcd_new_panel_io_i2c(esp_lcd_i2c_bus_handle_t bus, const esp_lcd_p typedef struct { int dc_gpio_num; /*!< GPIO used for D/C line */ int wr_gpio_num; /*!< GPIO used for WR line */ + lcd_clock_source_t clk_src; /*!< Clock source for the I80 LCD peripheral */ int data_gpio_nums[SOC_LCD_I80_BUS_WIDTH]; /*!< GPIOs used for data lines */ - size_t data_width; /*!< Number of data lines, 8 or 16 */ + 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 */ } esp_lcd_i80_bus_config_t; @@ -160,11 +165,13 @@ esp_err_t esp_lcd_del_i80_bus(esp_lcd_i80_bus_handle_t bus); * @brief Panel IO configuration structure, for intel 8080 interface */ typedef struct { - int cs_gpio_num; /*!< GPIO used for CS line */ + int cs_gpio_num; /*!< GPIO used for CS line, set to -1 will declaim exclusively use of I80 bus */ unsigned int pclk_hz; /*!< Frequency of pixel clock */ size_t trans_queue_depth; /*!< Transaction queue size, larger queue, higher throughput */ bool (*on_color_trans_done)(esp_lcd_panel_io_handle_t panel_io, void *user_data, void *event_data); /*!< Callback, invoked when color data was tranferred done */ - void *user_data; /*!< User private data, passed directly to on_trans_done's user_data */ + void *user_data; /*!< User private data, passed directly to on_trans_done's user_data */ + int lcd_cmd_bits; /*!< Bit-width of LCD command */ + int lcd_param_bits; /*!< Bit-width of LCD parameter */ struct { unsigned int dc_idle_level: 1; /*!< Level of DC line in IDLE phase */ unsigned int dc_cmd_level: 1; /*!< Level of DC line in CMD phase */ @@ -172,7 +179,7 @@ typedef struct { unsigned int dc_data_level: 1; /*!< Level of DC line in DATA phase */ } dc_levels; /*!< Each i80 device might have its own D/C control logic */ struct { - unsigned int invert_cs: 1; /*!< Whether to invert the CS line */ + unsigned int cs_active_high: 1; /*!< If set, a high level of CS line will select the device, otherwise, CS line is low level active */ unsigned int reverse_color_bits: 1; /*!< Reverse the data bits, D[N:0] -> D[0:N] */ unsigned int swap_color_bytes: 1; /*!< Swap adjacent two color bytes */ unsigned int pclk_active_neg: 1; /*!< The display will write data lines when there's a falling edge on WR signal (a.k.a the PCLK) */ diff --git a/components/esp_lcd/include/esp_lcd_panel_rgb.h b/components/esp_lcd/include/esp_lcd_panel_rgb.h index 6493292460..2ddd2b6b9a 100644 --- a/components/esp_lcd/include/esp_lcd_panel_rgb.h +++ b/components/esp_lcd/include/esp_lcd_panel_rgb.h @@ -9,6 +9,7 @@ #include "esp_err.h" #include "esp_lcd_types.h" #include "soc/soc_caps.h" +#include "hal/lcd_types.h" #ifdef __cplusplus extern "C" { @@ -41,6 +42,7 @@ typedef struct { * @brief LCD RGB panel configuration structure */ typedef struct { + lcd_clock_source_t clk_src; /*!< Clock source for the RGB LCD peripheral */ esp_lcd_rgb_timing_t timings; /*!< RGB timing parameters */ size_t data_width; /*!< Number of data lines */ int hsync_gpio_num; /*!< GPIO used for HSYNC signal */ diff --git a/components/esp_lcd/include/esp_lcd_panel_vendor.h b/components/esp_lcd/include/esp_lcd_panel_vendor.h index ac98cc3913..dde8be68d3 100644 --- a/components/esp_lcd/include/esp_lcd_panel_vendor.h +++ b/components/esp_lcd/include/esp_lcd_panel_vendor.h @@ -39,6 +39,19 @@ typedef struct { */ esp_err_t esp_lcd_new_panel_st7789(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel); +/** + * @brief Create LCD panel for model NT35510 + * + * @param[in] io LCD panel IO handle + * @param[in] panel_dev_config general panel device configuration + * @param[out] ret_panel Returned LCD panel handle + * @return + * - ESP_ERR_INVALID_ARG if parameter is invalid + * - ESP_ERR_NO_MEM if out of memory + * - ESP_OK on success + */ +esp_err_t esp_lcd_new_panel_nt35510(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel); + /** * @brief Create LCD panel for model SSD1306 * 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 b6b85564cd..2faa6fab26 100644 --- a/components/esp_lcd/interface/esp_lcd_panel_io_interface.h +++ b/components/esp_lcd/interface/esp_lcd_panel_io_interface.h @@ -25,14 +25,13 @@ struct esp_lcd_panel_io_t { * * @param[in] io LCD panel IO handle, which is created by other factory API like `esp_lcd_new_panel_io_spi()` * @param[in] lcd_cmd The specific LCD command - * @param[in] lcd_cmd_bits Length of LCD command, in bits (e.g. 8 bits or 16 bits) * @param[in] param Buffer that holds the command specific parameters, set to NULL if no parameter is needed for the command * @param[in] param_size Size of `param` in memory, in bytes, set to zero if no parameter is needed for the command * @return * - ESP_ERR_INVALID_ARG if parameter is invalid * - ESP_OK on success */ - esp_err_t (*tx_param)(esp_lcd_panel_io_t *io, int lcd_cmd, int lcd_cmd_bits, const void *param, size_t param_size); + esp_err_t (*tx_param)(esp_lcd_panel_io_t *io, int lcd_cmd, const void *param, size_t param_size); /** * @brief Transmit LCD RGB data @@ -41,14 +40,13 @@ struct esp_lcd_panel_io_t { * * @param[in] io LCD panel IO handle, which is created by other factory API like `esp_lcd_new_panel_io_spi()` * @param[in] lcd_cmd The specific LCD command - * @param[in] lcd_cmd_bits Length of LCD command, in bits (e.g. 8 bits or 16 bits) * @param[in] color Buffer that holds the RGB color data * @param[in] color_size Size of `color` in memory, in bytes * @return * - ESP_ERR_INVALID_ARG if parameter is invalid * - ESP_OK on success */ - esp_err_t (*tx_color)(esp_lcd_panel_io_t *io, int lcd_cmd, int lcd_cmd_bits, const void *color, size_t color_size); + esp_err_t (*tx_color)(esp_lcd_panel_io_t *io, int lcd_cmd, const void *color, size_t color_size); /** * @brief Destory LCD panel IO handle (deinitialize all and free resource) diff --git a/components/esp_lcd/src/esp_lcd_common.c b/components/esp_lcd/src/esp_lcd_common.c index 5d2d59e460..8aa364ac8c 100644 --- a/components/esp_lcd/src/esp_lcd_common.c +++ b/components/esp_lcd/src/esp_lcd_common.c @@ -5,10 +5,9 @@ */ #include "freertos/FreeRTOS.h" -#include "soc/rtc.h" // for querying XTAL clock #include "soc/soc_caps.h" -#if SOC_LCDCAM_SUPPORTED #include "esp_lcd_common.h" +#if SOC_LCDCAM_SUPPORTED #include "hal/lcd_ll.h" #include "hal/lcd_hal.h" @@ -78,24 +77,7 @@ void lcd_com_remove_device(lcd_com_device_type_t device_type, int member_id) break; } } - -unsigned long lcd_com_select_periph_clock(lcd_hal_context_t *hal) -{ - unsigned long resolution_hz = 0; - int clock_source = -1; -#if CONFIG_LCD_PERIPH_CLK_SRC_PLL160M - resolution_hz = 160000000 / LCD_PERIPH_CLOCK_PRE_SCALE; - clock_source = LCD_LL_CLOCK_SRC_PLL160M; -#elif CONFIG_LCD_PERIPH_CLK_SRC_XTAL - resolution_hz = rtc_clk_xtal_freq_get() * 1000000 / LCD_PERIPH_CLOCK_PRE_SCALE; - clock_source = LCD_LL_CLOCK_SRC_XTAL; -#else -#error "invalid LCD peripheral clock source" -#endif - - lcd_ll_set_group_clock_src(hal->dev, clock_source, LCD_PERIPH_CLOCK_PRE_SCALE, 1, 0); - return resolution_hz; -} +#endif // SOC_LCDCAM_SUPPORTED void lcd_com_mount_dma_data(dma_descriptor_t *desc_head, const void *buffer, size_t len) { @@ -122,5 +104,3 @@ void lcd_com_mount_dma_data(dma_descriptor_t *desc_head, const void *buffer, siz prepared_length += len; } } - -#endif // SOC_LCDCAM_SUPPORTED diff --git a/components/esp_lcd/src/esp_lcd_common.h b/components/esp_lcd/src/esp_lcd_common.h index 08cac613bd..a6e97ba70b 100644 --- a/components/esp_lcd/src/esp_lcd_common.h +++ b/components/esp_lcd/src/esp_lcd_common.h @@ -5,22 +5,21 @@ */ #pragma once +#include #include "soc/soc_caps.h" +#include "hal/dma_types.h" #if SOC_LCDCAM_SUPPORTED #include "hal/lcd_hal.h" -#include "hal/dma_types.h" -#else -#error "lcd peripheral is not supported on this chip" #endif #ifdef __cplusplus extern "C" { #endif -#if SOC_LCDCAM_SUPPORTED - #define LCD_PERIPH_CLOCK_PRE_SCALE (2) // This is the minimum divider that can be applied to LCD peripheral +#if SOC_LCDCAM_SUPPORTED + typedef enum { LCD_COM_DEVICE_TYPE_I80, LCD_COM_DEVICE_TYPE_RGB @@ -42,17 +41,7 @@ int lcd_com_register_device(lcd_com_device_type_t device_type, void *device_obj) * @param member_id member ID */ void lcd_com_remove_device(lcd_com_device_type_t device_type, int member_id); - -/** - * @brief Select clock source and return peripheral clock resolution (in Hz) - * - * @note The clock source selection is injected by the Kconfig system, - * dynamic switching peripheral clock source is not supported in driver. - * - * @param hal HAL object - * @return Peripheral clock resolution, in Hz - */ -unsigned long lcd_com_select_periph_clock(lcd_hal_context_t *hal); +#endif // SOC_LCDCAM_SUPPORTED /** * @brief Mount data to DMA descriptors @@ -63,7 +52,28 @@ unsigned long lcd_com_select_periph_clock(lcd_hal_context_t *hal); */ void lcd_com_mount_dma_data(dma_descriptor_t *desc_head, const void *buffer, size_t len); -#endif // SOC_LCDCAM_SUPPORTED +/** + * @brief Reverse the bytes in the buffer + * + * @note LCD is big-endian, e.g. to send command 0x1234, byte 0x12 should appear on the bus first + * However, the low level peripheral (like i80, i2s) will send 0x34 first. + * This helper function is used to reverse the bytes order + * + * @param buf buffer address + * @param start start index of the buffer + * @param end end index of the buffer + */ +static inline void lcd_com_reverse_buffer_bytes(uint8_t *buf, int start, int end) +{ + uint8_t temp = 0; + while (start < end) { + temp = buf[start]; + buf[start] = buf[end]; + buf[end] = temp; + start++; + end--; + } +} #ifdef __cplusplus } diff --git a/components/esp_lcd/src/esp_lcd_panel_commands.h b/components/esp_lcd/src/esp_lcd_panel_commands.h index c2ae3933b3..091ef1cffe 100644 --- a/components/esp_lcd/src/esp_lcd_panel_commands.h +++ b/components/esp_lcd/src/esp_lcd_panel_commands.h @@ -45,7 +45,7 @@ #define LCD_CMD_VSCSAD 0x37 // Vertical scroll start address #define LCD_CMD_IDMOFF 0x38 // Recover from IDLE mode #define LCD_CMD_IDMON 0x39 // Fall into IDLE mode (8 color depth is displayed) -#define LCD_CMD_COLMOD 0x3A // Defines the format of RGB picture data, which is to be transferred via the MCU interface +#define LCD_CMD_COLMOD 0x3A // Defines the format of RGB picture data #define LCD_CMD_RAMWRC 0x3C // Memory write continue #define LCD_CMD_RAMRDC 0x3E // Memory read continue #define LCD_CMD_STE 0x44 // Set tear scanline, tearing effect output signal when display module reaches line N diff --git a/components/esp_lcd/src/esp_lcd_panel_io.c b/components/esp_lcd/src/esp_lcd_panel_io.c index 4c80eaf8da..1c45c65a0a 100644 --- a/components/esp_lcd/src/esp_lcd_panel_io.c +++ b/components/esp_lcd/src/esp_lcd_panel_io.c @@ -10,16 +10,16 @@ static const char *TAG = "lcd_panel.io"; -esp_err_t esp_lcd_panel_io_tx_param(esp_lcd_panel_io_handle_t io, int lcd_cmd, int lcd_cmd_bits, const void *param, size_t param_size) +esp_err_t esp_lcd_panel_io_tx_param(esp_lcd_panel_io_handle_t io, int lcd_cmd, const void *param, size_t param_size) { ESP_RETURN_ON_FALSE(io, ESP_ERR_INVALID_ARG, TAG, "invalid panel io handle"); - return io->tx_param(io, lcd_cmd, lcd_cmd_bits, param, param_size); + return io->tx_param(io, lcd_cmd, param, param_size); } -esp_err_t esp_lcd_panel_io_tx_color(esp_lcd_panel_io_handle_t io, int lcd_cmd, int lcd_cmd_bits, const void *color, size_t color_size) +esp_err_t esp_lcd_panel_io_tx_color(esp_lcd_panel_io_handle_t io, int lcd_cmd, const void *color, size_t color_size) { ESP_RETURN_ON_FALSE(io, ESP_ERR_INVALID_ARG, TAG, "invalid panel io handle"); - return io->tx_color(io, lcd_cmd, lcd_cmd_bits, color, color_size); + return io->tx_color(io, lcd_cmd, color, color_size); } esp_err_t esp_lcd_panel_io_del(esp_lcd_panel_io_handle_t io) diff --git a/components/esp_lcd/src/esp_lcd_panel_io_i2c.c b/components/esp_lcd/src/esp_lcd_panel_io_i2c.c index 1453e245f2..037fddedee 100644 --- a/components/esp_lcd/src/esp_lcd_panel_io_i2c.c +++ b/components/esp_lcd/src/esp_lcd_panel_io_i2c.c @@ -22,13 +22,15 @@ static const char *TAG = "lcd_panel.io.i2c"; #define BYTESHIFT(VAR, IDX) (((VAR) >> ((IDX) * 8)) & 0xFF) static esp_err_t panel_io_i2c_del(esp_lcd_panel_io_t *io); -static esp_err_t panel_io_i2c_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, int lcd_cmd_bits, const void *param, size_t param_size); -static esp_err_t panel_io_i2c_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, int lcd_cmd_bits, const void *color, size_t color_size); +static esp_err_t panel_io_i2c_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, const void *param, size_t param_size); +static esp_err_t panel_io_i2c_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, const void *color, size_t color_size); typedef struct { esp_lcd_panel_io_t base; // Base class of generic lcd panel io uint32_t i2c_bus_id; // I2C bus id, indicating which I2C port uint32_t dev_addr; // Device address + int lcd_cmd_bits; // Bit width of LCD command + int lcd_param_bits; // Bit width of LCD parameter uint32_t control_phase_cmd; // control byte when transferring command uint32_t control_phase_data; // control byte when transferring data bool (*on_color_trans_done)(esp_lcd_panel_io_handle_t panel_io, void *user_data, void *event_data); // User register's callback, invoked when color data trans done @@ -46,6 +48,8 @@ esp_err_t esp_lcd_new_panel_io_i2c(esp_lcd_i2c_bus_handle_t bus, const esp_lcd_p ESP_GOTO_ON_FALSE(i2c_panel_io, ESP_ERR_NO_MEM, err, TAG, "no mem for i2c panel io"); i2c_panel_io->i2c_bus_id = (uint32_t)bus; + i2c_panel_io->lcd_cmd_bits = io_config->lcd_cmd_bits; + i2c_panel_io->lcd_param_bits = io_config->lcd_param_bits; i2c_panel_io->on_color_trans_done = io_config->on_color_trans_done; i2c_panel_io->control_phase_data = (!io_config->flags.dc_low_on_data) << (io_config->dc_bit_offset); i2c_panel_io->control_phase_cmd = (io_config->flags.dc_low_on_data) << (io_config->dc_bit_offset); @@ -72,7 +76,7 @@ static esp_err_t panel_io_i2c_del(esp_lcd_panel_io_t *io) return ret; } -static esp_err_t panel_io_i2c_tx_buffer(esp_lcd_panel_io_t *io, int lcd_cmd, int lcd_cmd_bits, const void *buffer, size_t buffer_size, bool is_param) +static esp_err_t panel_io_i2c_tx_buffer(esp_lcd_panel_io_t *io, int lcd_cmd, const void *buffer, size_t buffer_size, bool is_param) { esp_err_t ret = ESP_OK; lcd_panel_io_i2c_t *i2c_panel_io = __containerof(io, lcd_panel_io_i2c_t, base); @@ -81,14 +85,12 @@ static esp_err_t panel_io_i2c_tx_buffer(esp_lcd_panel_io_t *io, int lcd_cmd, int ESP_GOTO_ON_FALSE(cmd_link, ESP_ERR_NO_MEM, err, TAG, "no mem for i2c cmd link"); ESP_GOTO_ON_ERROR(i2c_master_start(cmd_link), err, TAG, "issue start failed"); // start phase ESP_GOTO_ON_ERROR(i2c_master_write_byte(cmd_link, (i2c_panel_io->dev_addr << 1) | I2C_MASTER_WRITE, true), err, TAG, "write address failed"); // address phase - ESP_GOTO_ON_ERROR( - i2c_master_write_byte(cmd_link, is_param ? i2c_panel_io->control_phase_cmd : i2c_panel_io->control_phase_data, true), - err, TAG, "write control phase failed"); // control phase + ESP_GOTO_ON_ERROR(i2c_master_write_byte(cmd_link, is_param ? i2c_panel_io->control_phase_cmd : i2c_panel_io->control_phase_data, true), + err, TAG, "write control phase failed"); // control phase uint8_t cmds[4] = {BYTESHIFT(lcd_cmd, 3), BYTESHIFT(lcd_cmd, 2), BYTESHIFT(lcd_cmd, 1), BYTESHIFT(lcd_cmd, 0)}; - size_t cmds_size = lcd_cmd_bits / 8; + size_t cmds_size = i2c_panel_io->lcd_cmd_bits / 8; if (cmds_size > 0 && cmds_size <= sizeof(cmds)) { - ESP_GOTO_ON_ERROR(i2c_master_write(cmd_link, cmds + (sizeof(cmds) - cmds_size), cmds_size, true), err, TAG, - "write LCD cmd failed"); + ESP_GOTO_ON_ERROR(i2c_master_write(cmd_link, cmds + (sizeof(cmds) - cmds_size), cmds_size, true), err, TAG, "write LCD cmd failed"); } if (buffer) { @@ -114,12 +116,12 @@ err: return ret; } -static esp_err_t panel_io_i2c_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, int lcd_cmd_bits, const void *param, size_t param_size) +static esp_err_t panel_io_i2c_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, const void *param, size_t param_size) { - return panel_io_i2c_tx_buffer(io, lcd_cmd, lcd_cmd_bits, param, param_size, true); + return panel_io_i2c_tx_buffer(io, lcd_cmd, param, param_size, true); } -static esp_err_t panel_io_i2c_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, int lcd_cmd_bits, const void *color, size_t color_size) +static esp_err_t panel_io_i2c_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, const void *color, size_t color_size) { - return panel_io_i2c_tx_buffer(io, lcd_cmd, lcd_cmd_bits, color, color_size, false); + return panel_io_i2c_tx_buffer(io, lcd_cmd, color, color_size, false); } diff --git a/components/esp_lcd/src/esp_lcd_panel_io_i2s.c b/components/esp_lcd/src/esp_lcd_panel_io_i2s.c new file mode 100644 index 0000000000..cea58f71fa --- /dev/null +++ b/components/esp_lcd/src/esp_lcd_panel_io_i2s.c @@ -0,0 +1,752 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// #define LOG_LOCAL_LEVEL ESP_LOG_DEBUG + +///////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Although we're manipulating I2S peripheral (on esp32/s2 target), it has nothing to do with the AUDIO BUS. +// In fact, we're simulating the Intel 8080 bus with I2S peripheral, in a special parallel mode. +///////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "esp_attr.h" +#include "esp_check.h" +#include "esp_intr_alloc.h" +#include "esp_heap_caps.h" +#include "esp_pm.h" +#include "esp_lcd_panel_io_interface.h" +#include "esp_lcd_panel_io.h" +#include "esp_lcd_common.h" +#include "esp_rom_gpio.h" +#include "soc/soc_caps.h" +#include "hal/dma_types.h" +#include "hal/gpio_hal.h" +#include "driver/gpio.h" +#include "driver/periph_ctrl.h" +#if SOC_I2S_LCD_I80_VARIANT +#include "esp_private/i2s_platform.h" +#include "soc/lcd_periph.h" +#include "hal/i2s_hal.h" +#include "hal/i2s_ll.h" +#include "hal/i2s_types.h" + +static const char *TAG = "lcd_panel.io.i80"; + +typedef struct esp_lcd_i80_bus_t esp_lcd_i80_bus_t; +typedef struct lcd_panel_io_i80_t lcd_panel_io_i80_t; +typedef struct lcd_i80_trans_descriptor_t lcd_i80_trans_descriptor_t; + +static esp_err_t panel_io_i80_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, const void *param, size_t param_size); +static esp_err_t panel_io_i80_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, const void *color, size_t color_size); +static esp_err_t panel_io_i80_del(esp_lcd_panel_io_t *io); +static esp_err_t i2s_lcd_select_periph_clock(esp_lcd_i80_bus_handle_t bus, lcd_clock_source_t src); +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 IRAM_ATTR void lcd_default_isr_handler(void *args); + +struct esp_lcd_i80_bus_t { + int bus_id; // Bus ID, index from 0 + portMUX_TYPE spinlock; // spinlock used to protect i80 bus members(hal, device_list, cur_trans) + i2s_hal_context_t hal; // Hal object + size_t bus_width; // Number of data lines + int dc_gpio_num; // GPIO used for DC line + int wr_gpio_num; // GPIO used for WR line + intr_handle_t intr; // LCD peripheral interrupt handle + esp_pm_lock_handle_t pm_lock; // lock APB frequency when necessary + size_t num_dma_nodes; // Number of DMA descriptors + uint8_t *format_buffer;// The driver allocates an internal buffer for DMA to do data format transformer + unsigned long resolution_hz; // LCD_CLK resolution, determined by selected clock source + lcd_i80_trans_descriptor_t *cur_trans; // Current transaction + lcd_panel_io_i80_t *cur_device; // Current working device + LIST_HEAD(i80_device_list, lcd_panel_io_i80_t) device_list; // Head of i80 device list + struct { + unsigned int exclusive: 1; // Indicate whether the I80 bus is owned by one device (whose CS GPIO is not assigned) exclusively + } flags; + dma_descriptor_t dma_nodes[]; // DMA descriptor pool, the descriptors are shared by all i80 devices +}; + +struct lcd_i80_trans_descriptor_t { + lcd_panel_io_i80_t *i80_device; // i80 device issuing this transaction + const void *data; // Data buffer + uint32_t data_length; // Data buffer size + void *cb_user_data; // private data used by trans_done_cb + bool (*trans_done_cb)(esp_lcd_panel_io_handle_t panel_io, void *user_data, void *event_data); // transaction done callback + struct { + unsigned int dc_level: 1; // Level of DC line for this transaction + } flags; +}; + +struct lcd_panel_io_i80_t { + esp_lcd_panel_io_t base; // Base class of generic lcd panel io + esp_lcd_i80_bus_t *bus; // Which bus the device is attached to + int cs_gpio_num; // GPIO used for CS line + unsigned int pclk_hz; // PCLK clock frequency + size_t clock_prescale; // Prescaler coefficient, determined by user's configured PCLK frequency + QueueHandle_t trans_queue; // Transaction queue, transactions in this queue are pending for scheduler to dispatch + QueueHandle_t done_queue; // Transaction done queue, transactions in this queue are finished but not recycled by the caller + size_t queue_size; // Size of transaction queue + size_t num_trans_inflight; // Number of transactions that are undergoing (the descriptor not recycled yet) + int lcd_cmd_bits; // Bit width of LCD command + int lcd_param_bits; // Bit width of LCD parameter + void *cb_user_data; // private data used when transfer color data + bool (*on_color_trans_done)(esp_lcd_panel_io_handle_t panel_io, void *user_data, void *event_data); // color data trans done callback + LIST_ENTRY(lcd_panel_io_i80_t) device_list_entry; // Entry of i80 device list + struct { + unsigned int dc_cmd_level: 1; // Level of DC line in CMD phase + unsigned int dc_data_level: 1; // Level of DC line in DATA phase + } dc_levels; + struct { + unsigned int cs_active_high: 1; // Whether the CS line is active on high level + unsigned int swap_color_bytes: 1; // Swap adjacent two data bytes before sending out + unsigned int pclk_idle_low: 1; // The WR line keeps at low level in IDLE phase + } flags; + lcd_i80_trans_descriptor_t trans_pool[]; // Transaction pool +}; + +esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lcd_i80_bus_handle_t *ret_bus) +{ + esp_err_t ret = ESP_OK; + esp_lcd_i80_bus_t *bus = NULL; + ESP_GOTO_ON_FALSE(bus_config && ret_bus, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); + // although I2S bus supports up to 24 parallel data lines, we restrict users to only use 8 or 16 bit width, due to limited GPIO numbers + ESP_GOTO_ON_FALSE(bus_config->bus_width == 8 || bus_config->bus_width == 16, ESP_ERR_INVALID_ARG, err, + TAG, "invalid bus width:%d", bus_config->bus_width); + size_t max_transfer_bytes = (bus_config->max_transfer_bytes + 3) & ~0x03; // align up to 4 bytes +#if SOC_I2S_TRANS_SIZE_ALIGN_WORD + // double the size of the internal DMA buffer if bus_width is 8, + // because one I2S FIFO (4 bytes) will only contain two bytes of valid data + max_transfer_bytes = max_transfer_bytes * 16 / bus_config->bus_width + 4; +#endif + size_t num_dma_nodes = max_transfer_bytes / DMA_DESCRIPTOR_BUFFER_MAX_SIZE + 1; + // DMA descriptors must be placed in internal SRAM + bus = heap_caps_calloc(1, sizeof(esp_lcd_i80_bus_t) + num_dma_nodes * sizeof(dma_descriptor_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); + ESP_GOTO_ON_FALSE(bus, ESP_ERR_NO_MEM, err, TAG, "no mem for i80 bus"); + bus->num_dma_nodes = num_dma_nodes; + bus->bus_id = -1; +#if SOC_I2S_TRANS_SIZE_ALIGN_WORD + // transform format for LCD commands, parameters and color data, so we need a big buffer + bus->format_buffer = heap_caps_calloc(1, max_transfer_bytes, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); +#else + // only transform format for LCD parameters, buffer size depends on specific LCD, set at compile time + bus->format_buffer = heap_caps_calloc(1, CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); +#endif // SOC_I2S_TRANS_SIZE_ALIGN_WORD + ESP_GOTO_ON_FALSE(bus->format_buffer, ESP_ERR_NO_MEM, err, TAG, "no mem for format buffer"); + // I2S0 has the LCD mode, but the LCD mode can't work with other modes at the same time, we need to register the driver object to the I2S platform + ESP_GOTO_ON_ERROR(i2s_priv_register_object(bus, 0), err, TAG, "register to I2S platform failed"); + bus->bus_id = 0; + // initialize HAL layer + i2s_hal_init(&bus->hal, bus->bus_id); + // set peripheral clock resolution + ret = i2s_lcd_select_periph_clock(bus, bus_config->clk_src); + ESP_GOTO_ON_ERROR(ret, err, TAG, "select periph clock failed"); + // reset peripheral, DMA channel and FIFO + i2s_ll_tx_reset(bus->hal.dev); + i2s_ll_tx_reset_dma(bus->hal.dev); + i2s_ll_tx_reset_fifo(bus->hal.dev); + // install interrupt service, (I2S LCD mode only uses the "TX Unit", which leaves "RX Unit" for other purpose) + // So the interrupt should also be able to share with other functionality + int isr_flags = ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_SHARED; + ret = esp_intr_alloc_intrstatus(lcd_periph_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); + 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 + // initialize DMA link + i2s_lcd_init_dma_link(bus); + // enable I2S LCD master mode (refer to I2S TRM) + i2s_ll_enable_lcd(bus->hal.dev, true); + i2s_ll_tx_stop_on_fifo_empty(bus->hal.dev, true); + i2s_ll_tx_bypass_pcm(bus->hal.dev, true); + i2s_ll_tx_set_slave_mod(bus->hal.dev, false); + i2s_ll_tx_set_bits_mod(bus->hal.dev, bus_config->bus_width); + i2s_ll_tx_set_chan_mod(bus->hal.dev, 1); // mono + bus->bus_width = bus_config->bus_width; + i2s_ll_tx_enable_right_first(bus->hal.dev, true); +#if SOC_I2S_SUPPORTS_DMA_EQUAL + i2s_ll_tx_enable_dma_equal(bus->hal.dev, true); +#endif + // enable trans done interrupt + i2s_ll_enable_intr(bus->hal.dev, I2S_LL_EVENT_TX_EOF, true); + // trigger a quick "trans done" event, and wait for the interrupt line goes active + // this could ensure we go into ISR handler next time we call `esp_intr_enable` + i2s_lcd_trigger_quick_trans_done_event(bus); + // configure GPIO + ret = i2s_lcd_configure_gpio(bus, bus_config); + ESP_GOTO_ON_ERROR(ret, err, TAG, "configure GPIO failed"); + // fill other i80 bus runtime parameters + LIST_INIT(&bus->device_list); // initialize device list head + bus->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED; + bus->dc_gpio_num = bus_config->dc_gpio_num; + bus->wr_gpio_num = bus_config->wr_gpio_num; + *ret_bus = bus; + ESP_LOGD(TAG, "new i80 bus(%d) @%p, %zu dma nodes, resolution %luHz", bus->bus_id, bus, bus->num_dma_nodes, bus->resolution_hz); + return ESP_OK; + +err: + if (bus) { + if (bus->intr) { + esp_intr_free(bus->intr); + } + if (bus->bus_id >= 0) { + i2s_priv_deregister_object(bus->bus_id); + } + if (bus->format_buffer) { + free(bus->format_buffer); + } + if (bus->pm_lock) { + esp_pm_lock_delete(bus->pm_lock); + } + free(bus); + } + return ret; +} + +esp_err_t esp_lcd_del_i80_bus(esp_lcd_i80_bus_handle_t bus) +{ + esp_err_t ret = ESP_OK; + ESP_GOTO_ON_FALSE(bus, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); + ESP_GOTO_ON_FALSE(LIST_EMPTY(&bus->device_list), ESP_ERR_INVALID_STATE, err, TAG, "device list not empty"); + int bus_id = bus->bus_id; + i2s_priv_deregister_object(bus_id); + esp_intr_free(bus->intr); + if (bus->pm_lock) { + esp_pm_lock_delete(bus->pm_lock); + } + free(bus->format_buffer); + free(bus); + ESP_LOGD(TAG, "del i80 bus(%d)", bus_id); +err: + return ret; +} + +esp_err_t esp_lcd_new_panel_io_i80(esp_lcd_i80_bus_handle_t bus, const esp_lcd_panel_io_i80_config_t *io_config, esp_lcd_panel_io_handle_t *ret_io) +{ + esp_err_t ret = ESP_OK; + lcd_panel_io_i80_t *i80_device = NULL; + bool bus_exclusive = false; + ESP_GOTO_ON_FALSE(bus && io_config && ret_io, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); + // check if the bus has been configured as exclusive + portENTER_CRITICAL(&bus->spinlock); + if (!bus->flags.exclusive) { + bus->flags.exclusive = io_config->cs_gpio_num < 0; + } else { + bus_exclusive = true; + } + portEXIT_CRITICAL(&bus->spinlock); + ESP_GOTO_ON_FALSE(!bus_exclusive, ESP_ERR_INVALID_STATE, err, TAG, "bus has been exclusively owned by device"); + // because we set the I2S's left channel data same to right channel, so f_pclk = f_i2s/pclk_div/2 + uint32_t pclk_prescale = bus->resolution_hz / 2 / io_config->pclk_hz; + ESP_GOTO_ON_FALSE(pclk_prescale > 0 && pclk_prescale <= I2S_LL_BCK_MAX_PRESCALE, ESP_ERR_NOT_SUPPORTED, err, TAG, + "prescaler can't satisfy PCLK clock %u", io_config->pclk_hz); + i80_device = calloc(1, sizeof(lcd_panel_io_i80_t) + io_config->trans_queue_depth * sizeof(lcd_i80_trans_descriptor_t)); + ESP_GOTO_ON_FALSE(i80_device, ESP_ERR_NO_MEM, err, TAG, "no mem for i80 panel io"); + // create two queues for i80 device + i80_device->trans_queue = xQueueCreate(io_config->trans_queue_depth, sizeof(lcd_i80_trans_descriptor_t *)); + ESP_GOTO_ON_FALSE(i80_device->trans_queue, ESP_ERR_NO_MEM, err, TAG, "create trans queue failed"); + i80_device->done_queue = xQueueCreate(io_config->trans_queue_depth, sizeof(lcd_i80_trans_descriptor_t *)); + ESP_GOTO_ON_FALSE(i80_device->done_queue, ESP_ERR_NO_MEM, err, TAG, "create done queue failed"); + // adding device to list + portENTER_CRITICAL(&bus->spinlock); + LIST_INSERT_HEAD(&bus->device_list, i80_device, device_list_entry); + portEXIT_CRITICAL(&bus->spinlock); + // we don't initialize the i80 bus at the memont, but initialize the bus when start a transaction for a new device + // so save these as i80 device runtime parameters + i80_device->bus = bus; + i80_device->queue_size = io_config->trans_queue_depth; + i80_device->clock_prescale = pclk_prescale; + i80_device->lcd_cmd_bits = io_config->lcd_cmd_bits; + i80_device->lcd_param_bits = io_config->lcd_param_bits; + i80_device->pclk_hz = bus->resolution_hz / pclk_prescale / 2; + i80_device->dc_levels.dc_cmd_level = io_config->dc_levels.dc_cmd_level; + i80_device->dc_levels.dc_data_level = io_config->dc_levels.dc_data_level; + i80_device->cs_gpio_num = io_config->cs_gpio_num; + i80_device->on_color_trans_done = io_config->on_color_trans_done; + i80_device->cb_user_data = io_config->user_data; + i80_device->flags.cs_active_high = io_config->flags.cs_active_high; + i80_device->flags.swap_color_bytes = io_config->flags.swap_color_bytes; + i80_device->flags.pclk_idle_low = io_config->flags.pclk_idle_low; + // fill panel io function table + i80_device->base.del = panel_io_i80_del; + i80_device->base.tx_param = panel_io_i80_tx_param; + i80_device->base.tx_color = panel_io_i80_tx_color; + 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); + } + *ret_io = &(i80_device->base); + ESP_LOGD(TAG, "new i80 lcd panel io @%p on bus(%d), pclk=%uHz", i80_device, bus->bus_id, i80_device->pclk_hz); + return ESP_OK; + +err: + if (i80_device) { + if (i80_device->trans_queue) { + vQueueDelete(i80_device->trans_queue); + } + if (i80_device->done_queue) { + vQueueDelete(i80_device->done_queue); + } + free(i80_device); + } + return ret; +} + +static esp_err_t panel_io_i80_del(esp_lcd_panel_io_t *io) +{ + lcd_panel_io_i80_t *i80_device = __containerof(io, lcd_panel_io_i80_t, base); + esp_lcd_i80_bus_t *bus = i80_device->bus; + lcd_i80_trans_descriptor_t *trans_desc = NULL; + // wait all pending transaction to finish + for (size_t i = 0; i < i80_device->num_trans_inflight; i++) { + xQueueReceive(i80_device->done_queue, &trans_desc, portMAX_DELAY); + } + // remove from device list + portENTER_CRITICAL(&bus->spinlock); + LIST_REMOVE(i80_device, device_list_entry); + portEXIT_CRITICAL(&bus->spinlock); + + ESP_LOGD(TAG, "del i80 lcd panel io @%p", i80_device); + vQueueDelete(i80_device->trans_queue); + vQueueDelete(i80_device->done_queue); + free(i80_device); + return ESP_OK; +} + +static void i2s_lcd_prepare_cmd_buffer(lcd_i80_trans_descriptor_t *trans_desc, const void *cmd) +{ + lcd_panel_io_i80_t *i80_device = trans_desc->i80_device; + esp_lcd_i80_bus_t *bus = i80_device->bus; + uint8_t *from = (uint8_t *)cmd; + // LCD is big-endian, e.g. to send command 0x1234, byte 0x12 should appear on the data bus first + // However, the I2S peripheral will send 0x34 first, so we reversed the order below + if (bus->bus_width < i80_device->lcd_cmd_bits) { + int start = 0; + int end = i80_device->lcd_cmd_bits / 8 - 1; + lcd_com_reverse_buffer_bytes(from, start, end); + } +#if SOC_I2S_TRANS_SIZE_ALIGN_WORD + uint8_t *to = bus->format_buffer; + int cmd_cycle = i80_device->lcd_cmd_bits / bus->bus_width; + if (cmd_cycle * bus->bus_width < i80_device->lcd_cmd_bits) { + cmd_cycle++; + } + int bytes_to_copy = MIN(bus->bus_width, i80_device->lcd_cmd_bits) / 8; + int cnt_from = 0; + // format command buffer + for (int i = 0; i < cmd_cycle; i++) { + for (int j = 0; j < bytes_to_copy; j++) { + to[2 + j] = from[cnt_from++]; + } + to += 4; + } + trans_desc->data = bus->format_buffer; + trans_desc->data_length = cmd_cycle * 4; +#else + trans_desc->data = cmd; + trans_desc->data_length = MAX(i80_device->lcd_cmd_bits, bus->bus_width) / 8; +#endif +} + +static void i2s_lcd_prepare_param_buffer(lcd_i80_trans_descriptor_t *trans_desc, const void *param, size_t param_num) +{ + lcd_panel_io_i80_t *i80_device = trans_desc->i80_device; + esp_lcd_i80_bus_t *bus = i80_device->bus; + uint8_t *from = (uint8_t *)param; + int param_size = i80_device->lcd_param_bits / 8; + // LCD is big-endian, e.g. to send param 0x1234, byte 0x12 should appear on the data bus first + // However, the I2S peripheral will send 0x34 first, so we reversed the order below + if (bus->bus_width < i80_device->lcd_param_bits) { + for (size_t i = 0; i < param_num; i++) { + int start = i * param_size; + int end = start + param_size - 1; + lcd_com_reverse_buffer_bytes(from, start, end); + } + } +#if SOC_I2S_TRANS_SIZE_ALIGN_WORD + uint8_t *to = bus->format_buffer; + int param_cycle = i80_device->lcd_param_bits / bus->bus_width; + if (param_cycle * bus->bus_width < i80_device->lcd_param_bits) { + param_cycle++; + } + int ele_cycles = param_cycle * param_num; + int bytes_to_copy = MIN(bus->bus_width, i80_device->lcd_param_bits) / 8; + int cnt_from = 0; + // format parameter buffer + for (int i = 0; i < ele_cycles; i++) { + for (int j = 0; j < bytes_to_copy; j++) { + to[2 + j] = from[cnt_from++]; + } + to += 4; + } + trans_desc->data = bus->format_buffer; + trans_desc->data_length = ele_cycles * 4; +#else + uint8_t *to = bus->format_buffer; + uint8_t step = bus->bus_width / 8; + int param_cycle = i80_device->lcd_param_bits / bus->bus_width; + if (param_cycle * bus->bus_width < i80_device->lcd_param_bits) { + param_cycle++; + } + int ele_cycles = param_cycle * param_num; + int bytes_to_copy = MIN(bus->bus_width, i80_device->lcd_param_bits) / 8; + int cnt_from = 0; + // format parameter buffer + for (int i = 0; i < ele_cycles; i++) { + for (int j = 0; j < bytes_to_copy; j++) { + to[j] = from[cnt_from++]; + } + to += step; + } + trans_desc->data = bus->format_buffer; + trans_desc->data_length = to - bus->format_buffer; +#endif +} + +static void i2s_lcd_prepare_color_buffer(lcd_i80_trans_descriptor_t *trans_desc, const void *color, size_t color_size) +{ +#if SOC_I2S_TRANS_SIZE_ALIGN_WORD + lcd_panel_io_i80_t *i80_device = trans_desc->i80_device; + esp_lcd_i80_bus_t *bus = i80_device->bus; + uint8_t *from = (uint8_t *)color; + uint8_t *to = bus->format_buffer; + int bytes_to_copy = bus->bus_width / 8; + int cnt_from = 0; + int first_half = i80_device->flags.swap_color_bytes ? 0 : 2; + int second_half = i80_device->flags.swap_color_bytes ? 2 : 0; + // format color buffer + while (cnt_from < color_size) { + for (int i = 0; i < bytes_to_copy; i++) { + to[first_half + i] = from[cnt_from++]; + } + for (int i = 0; i < bytes_to_copy; i++) { + to[second_half + i] = from[cnt_from++]; + } + to += 4; + } + trans_desc->data = bus->format_buffer; + trans_desc->data_length = to - bus->format_buffer; +#else + trans_desc->data = color; + trans_desc->data_length = color_size; +#endif +} + +static esp_err_t panel_io_i80_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, const void *param, size_t param_size) +{ + lcd_panel_io_i80_t *next_device = __containerof(io, lcd_panel_io_i80_t, base); + esp_lcd_i80_bus_t *bus = next_device->bus; + lcd_panel_io_i80_t *cur_device = bus->cur_device; + lcd_i80_trans_descriptor_t *trans_desc = NULL; + assert(param_size <= (bus->num_dma_nodes * DMA_DESCRIPTOR_BUFFER_MAX_SIZE) && "parameter bytes too long, enlarge max_transfer_bytes"); + assert(param_size <= CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE && "format buffer too small, increase CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE"); + + // before issue a polling transaction, need to wait queued transactions finished + for (size_t i = 0; i < next_device->num_trans_inflight; i++) { + xQueueReceive(next_device->done_queue, &trans_desc, portMAX_DELAY); + } + next_device->num_trans_inflight = 0; + + i2s_ll_clear_intr_status(bus->hal.dev, I2S_LL_EVENT_TX_EOF); + // switch devices if necessary + lcd_i80_switch_devices(cur_device, next_device); + trans_desc = &next_device->trans_pool[0]; + trans_desc->i80_device = next_device; + trans_desc->trans_done_cb = NULL; // no callback for command transfer + bus->cur_trans = trans_desc; +#if SOC_I2S_TRANS_SIZE_ALIGN_WORD + // switch to I2S 32bits mode, one WS cycle <=> one I2S FIFO + i2s_ll_tx_set_bits_mod(bus->hal.dev, 32); +#endif + i2s_lcd_prepare_cmd_buffer(trans_desc, &lcd_cmd); + lcd_com_mount_dma_data(bus->dma_nodes, trans_desc->data, trans_desc->data_length); + gpio_set_level(bus->dc_gpio_num, next_device->dc_levels.dc_cmd_level); + i2s_ll_tx_stop(bus->hal.dev); + i2s_ll_tx_reset(bus->hal.dev); // reset TX engine first + i2s_ll_start_out_link(bus->hal.dev); + // delay a while, wait for DMA data beeing feed to I2S FIFO + // in fact, this is only needed when LCD pixel clock is set too high + esp_rom_delay_us(1); + // increase the pm lock reference count before starting a new transaction + if (bus->pm_lock) { + esp_pm_lock_acquire(bus->pm_lock); + } + i2s_ll_tx_start(bus->hal.dev); + // polling the trans done event + while (!(i2s_ll_get_intr_status(bus->hal.dev) & I2S_LL_EVENT_TX_EOF)) {} + + // parameter is usually short, using polling mode + if (param && param_size) { + i2s_ll_clear_intr_status(bus->hal.dev, I2S_LL_EVENT_TX_EOF); + i2s_lcd_prepare_param_buffer(trans_desc, param, param_size * 8 / next_device->lcd_param_bits); + lcd_com_mount_dma_data(bus->dma_nodes, trans_desc->data, trans_desc->data_length); + gpio_set_level(bus->dc_gpio_num, next_device->dc_levels.dc_data_level); + i2s_ll_tx_stop(bus->hal.dev); + i2s_ll_tx_reset(bus->hal.dev); // reset TX engine first + i2s_ll_start_out_link(bus->hal.dev); + esp_rom_delay_us(1); + i2s_ll_tx_start(bus->hal.dev); + // polling the trans done event, but don't clear the event status + while (!(i2s_ll_get_intr_status(bus->hal.dev) & I2S_LL_EVENT_TX_EOF)) {} + } + // decrease pm lock reference count + if (bus->pm_lock) { + esp_pm_lock_release(bus->pm_lock); + } + bus->cur_trans = NULL; + return ESP_OK; +} + +static esp_err_t panel_io_i80_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, const void *color, size_t color_size) +{ + lcd_panel_io_i80_t *next_device = __containerof(io, lcd_panel_io_i80_t, base); + esp_lcd_i80_bus_t *bus = next_device->bus; + lcd_panel_io_i80_t *cur_device = bus->cur_device; + lcd_i80_trans_descriptor_t *trans_desc = NULL; + assert(color_size <= (bus->num_dma_nodes * DMA_DESCRIPTOR_BUFFER_MAX_SIZE) && "color bytes too long, enlarge max_transfer_bytes"); + + // before issue a polling transaction, need to wait queued transactions finished + for (size_t i = 0; i < next_device->num_trans_inflight; i++) { + xQueueReceive(next_device->done_queue, &trans_desc, portMAX_DELAY); + } + next_device->num_trans_inflight = 0; + + i2s_ll_clear_intr_status(bus->hal.dev, I2S_LL_EVENT_TX_EOF); + // switch devices if necessary + lcd_i80_switch_devices(cur_device, next_device); + trans_desc = &next_device->trans_pool[0]; + trans_desc->i80_device = next_device; + trans_desc->trans_done_cb = NULL; // no callback for command transfer + bus->cur_trans = trans_desc; +#if SOC_I2S_TRANS_SIZE_ALIGN_WORD + // switch to I2S 32bits mode, one WS cycle <=> one I2S FIFO + i2s_ll_tx_set_bits_mod(bus->hal.dev, 32); +#endif + i2s_lcd_prepare_cmd_buffer(trans_desc, &lcd_cmd); + lcd_com_mount_dma_data(bus->dma_nodes, trans_desc->data, trans_desc->data_length); + gpio_set_level(bus->dc_gpio_num, next_device->dc_levels.dc_cmd_level); + i2s_ll_tx_stop(bus->hal.dev); + i2s_ll_tx_reset(bus->hal.dev); // reset TX engine first + i2s_ll_start_out_link(bus->hal.dev); + esp_rom_delay_us(1); + // increase the pm lock reference count before starting a new transaction + if (bus->pm_lock) { + esp_pm_lock_acquire(bus->pm_lock); + } + i2s_ll_tx_start(bus->hal.dev); + // polling the trans done event + while (!(i2s_ll_get_intr_status(bus->hal.dev) & I2S_LL_EVENT_TX_EOF)) {} + // decrease pm lock reference count + if (bus->pm_lock) { + esp_pm_lock_release(bus->pm_lock); + } + bus->cur_trans = NULL; + + // sending LCD color data to queue + trans_desc->trans_done_cb = next_device->on_color_trans_done; + trans_desc->cb_user_data = next_device->cb_user_data; + trans_desc->flags.dc_level = next_device->dc_levels.dc_data_level; // DC level for data transaction + i2s_lcd_prepare_color_buffer(trans_desc, color, color_size); + // send transaction to trans_queue + 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 + esp_intr_enable(bus->intr); + return ESP_OK; +} + +static esp_err_t i2s_lcd_select_periph_clock(esp_lcd_i80_bus_handle_t bus, lcd_clock_source_t src) +{ + esp_err_t ret = ESP_OK; + switch (src) { + case LCD_CLK_SRC_PLL160M: + bus->resolution_hz = 160000000 / LCD_PERIPH_CLOCK_PRE_SCALE; + i2s_ll_tx_clk_set_src(bus->hal.dev, I2S_CLK_D2CLK); +#if CONFIG_PM_ENABLE + ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "i2s_bus_lcd", &bus->pm_lock); + ESP_RETURN_ON_ERROR(ret, TAG, "create ESP_PM_APB_FREQ_MAX lock failed"); + ESP_LOGD(TAG, "installed ESP_PM_APB_FREQ_MAX lock"); +#endif + break; + default: + ESP_RETURN_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, TAG, "unsupported clock source: %d", src); + break; + } + i2s_ll_mclk_div_t clk_cal_config = { + .mclk_div = LCD_PERIPH_CLOCK_PRE_SCALE, + .a = 1, + .b = 0, + }; + i2s_ll_tx_set_clk(bus->hal.dev, &clk_cal_config); + return ret; +} + +static esp_err_t i2s_lcd_init_dma_link(esp_lcd_i80_bus_handle_t bus) +{ + for (int i = 0; i < bus->num_dma_nodes; i++) { + bus->dma_nodes[i].dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_CPU; + bus->dma_nodes[i].next = &bus->dma_nodes[i + 1]; + } + bus->dma_nodes[bus->num_dma_nodes - 1].next = NULL; // one-off DMA chain + i2s_ll_dma_enable_eof_on_fifo_empty(bus->hal.dev, true); + i2s_ll_dma_enable_owner_check(bus->hal.dev, true); + i2s_ll_dma_enable_auto_write_back(bus->hal.dev, true); + i2s_ll_set_out_link_addr(bus->hal.dev, (uint32_t)bus->dma_nodes); + i2s_ll_enable_dma(bus->hal.dev, true); + return ESP_OK; +} + +static esp_err_t i2s_lcd_configure_gpio(esp_lcd_i80_bus_handle_t bus, const esp_lcd_i80_bus_config_t *bus_config) +{ + int bus_id = bus->bus_id; + // check validation of GPIO number + bool valid_gpio = (bus_config->wr_gpio_num >= 0) && (bus_config->dc_gpio_num >= 0); + for (size_t i = 0; i < bus_config->bus_width; i++) { + valid_gpio = valid_gpio && (bus_config->data_gpio_nums[i] >= 0); + } + if (!valid_gpio) { + return ESP_ERR_INVALID_ARG; + } + // 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); +#if SOC_I2S_TRANS_SIZE_ALIGN_WORD + esp_rom_gpio_connect_out_signal(bus_config->data_gpio_nums[i], lcd_periph_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_signals.buses[bus_id].data_sigs[i + SOC_LCD_I80_BUS_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); + esp_rom_gpio_connect_out_signal(bus_config->wr_gpio_num, lcd_periph_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); + return ESP_OK; +} + +static void i2s_lcd_trigger_quick_trans_done_event(esp_lcd_i80_bus_handle_t bus) +{ + // trigger a quick interrupt event by a dummy transaction, wait the LCD interrupt line goes active + // next time when esp_intr_enable is invoked, we can go into interrupt handler immediately + // where we dispatch transactions for i80 devices + static uint32_t fake_trigger = 0; + lcd_com_mount_dma_data(bus->dma_nodes, &fake_trigger, 4); + i2s_ll_start_out_link(bus->hal.dev); + i2s_ll_tx_start(bus->hal.dev); + while (!(i2s_ll_get_intr_status(bus->hal.dev) & I2S_LL_EVENT_TX_EOF)) {} +} + +static void lcd_i80_switch_devices(lcd_panel_io_i80_t *cur_device, lcd_panel_io_i80_t *next_device) +{ + // the caller should make sure the next_device and cur_device are attached to the same bus + esp_lcd_i80_bus_t *bus = next_device->bus; + if (next_device != cur_device) { + // reconfigure PCLK for the new device + i2s_ll_tx_set_bck_div_num(bus->hal.dev, next_device->clock_prescale); + if (cur_device && cur_device->cs_gpio_num >= 0) { // de-assert current device + gpio_set_level(cur_device->cs_gpio_num, !cur_device->flags.cs_active_high); + } + if (next_device->cs_gpio_num >= 0) { + gpio_set_level(next_device->cs_gpio_num, next_device->flags.cs_active_high); // select the next device + } + // the WR signal (a.k.a the PCLK) generated by I2S is low level in idle stage + // but most of 8080 LCDs require the WR line to be in high level during idle stage + esp_rom_gpio_connect_out_signal(bus->wr_gpio_num, lcd_periph_signals.buses[bus->bus_id].wr_sig, !next_device->flags.pclk_idle_low, false); + } + bus->cur_device = next_device; +} + +static IRAM_ATTR void 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; + lcd_panel_io_i80_t *cur_device = NULL; + lcd_panel_io_i80_t *next_device = NULL; + BaseType_t high_task_woken = pdFALSE; + bool need_yield = false; + uint32_t intr_status = i2s_ll_get_intr_status(bus->hal.dev); + if (intr_status & I2S_LL_EVENT_TX_EOF) { // trans done event + // disable interrupt temporarily, only re-enable when there be remained transaction in the queue + esp_intr_disable(bus->intr); + trans_desc = bus->cur_trans; // the finished transaction + cur_device = bus->cur_device;// the working device + // process finished transaction + if (trans_desc) { + assert(trans_desc->i80_device == cur_device && "transaction device mismatch"); + // decrease pm lock reference count + if (bus->pm_lock) { + esp_pm_lock_release(bus->pm_lock); + } + // device callback + if (trans_desc->trans_done_cb) { + if (trans_desc->trans_done_cb(&cur_device->base, trans_desc->cb_user_data, NULL)) { + need_yield = true; + } + } + // move transaction to done_queue + high_task_woken = pdFALSE; + xQueueSendFromISR(cur_device->done_queue, &trans_desc, &high_task_woken); + if (high_task_woken == pdTRUE) { + need_yield = true; + } + bus->cur_trans = NULL; + } + // fetch transactions from devices' trans_queue + // Note: the first registered device will have the highest priority to be scheduled + LIST_FOREACH(next_device, &bus->device_list, device_list_entry) { + high_task_woken = pdFALSE; + if (xQueueReceiveFromISR(next_device->trans_queue, &trans_desc, &high_task_woken) == pdTRUE) { + if (high_task_woken == pdTRUE) { + need_yield = true; + } + // only clear the interrupt status when we're sure there still remains transaction to handle + i2s_ll_clear_intr_status(bus->hal.dev, I2S_LL_EVENT_TX_EOF); + // switch devices if necessary + lcd_i80_switch_devices(cur_device, next_device); + bus->cur_trans = trans_desc; + gpio_set_level(bus->dc_gpio_num, trans_desc->flags.dc_level); + // mount data to DMA links + lcd_com_mount_dma_data(bus->dma_nodes, trans_desc->data, trans_desc->data_length); +#if SOC_I2S_TRANS_SIZE_ALIGN_WORD + // switch to I2S 16bits mode, two WS cycle <=> one I2S FIFO + i2s_ll_tx_set_bits_mod(bus->hal.dev, 16); +#endif + // enable interrupt again, because the new transaction can trigger new trans done event + esp_intr_enable(bus->intr); + i2s_ll_tx_stop(bus->hal.dev); + i2s_ll_tx_reset(bus->hal.dev); // reset TX engine first + i2s_ll_start_out_link(bus->hal.dev); + esp_rom_delay_us(1); + // increase the pm lock reference count before starting a new transaction + if (bus->pm_lock) { + esp_pm_lock_acquire(bus->pm_lock); + } + i2s_ll_tx_start(bus->hal.dev); + break; // exit for-each loop + } + } + } + if (need_yield) { + portYIELD_FROM_ISR(); + } +} + +#endif // SOC_I2S_LCD_I80_VARIANT diff --git a/components/esp_lcd/src/esp_lcd_panel_io_i80.c b/components/esp_lcd/src/esp_lcd_panel_io_i80.c index d2a0981ccd..58138fa768 100644 --- a/components/esp_lcd/src/esp_lcd_panel_io_i80.c +++ b/components/esp_lcd/src/esp_lcd_panel_io_i80.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" @@ -17,6 +18,7 @@ #include "esp_check.h" #include "esp_intr_alloc.h" #include "esp_heap_caps.h" +#include "esp_pm.h" #include "esp_lcd_panel_io_interface.h" #include "esp_lcd_panel_io.h" #include "esp_rom_gpio.h" @@ -38,11 +40,12 @@ typedef struct esp_lcd_i80_bus_t esp_lcd_i80_bus_t; typedef struct lcd_panel_io_i80_t lcd_panel_io_i80_t; typedef struct lcd_i80_trans_descriptor_t lcd_i80_trans_descriptor_t; -static esp_err_t panel_io_i80_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, int lcd_cmd_bits, const void *param, size_t param_size); -static esp_err_t panel_io_i80_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, int lcd_cmd_bits, const void *color, size_t color_size); +static esp_err_t panel_io_i80_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, const void *param, size_t param_size); +static esp_err_t panel_io_i80_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, const void *color, size_t color_size); static esp_err_t panel_io_i80_del(esp_lcd_panel_io_t *io); -static esp_err_t lcd_i80_bus_create_trans_link(esp_lcd_i80_bus_handle_t bus); +static esp_err_t lcd_i80_init_dma_link(esp_lcd_i80_bus_handle_t bus); static void lcd_periph_trigger_quick_trans_done_event(esp_lcd_i80_bus_handle_t bus); +static esp_err_t lcd_i80_select_periph_clock(esp_lcd_i80_bus_handle_t bus, lcd_clock_source_t clk_src); 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); @@ -52,15 +55,20 @@ struct esp_lcd_i80_bus_t { int bus_id; // Bus ID, index from 0 portMUX_TYPE spinlock; // spinlock used to protect i80 bus members(hal, device_list, cur_trans) lcd_hal_context_t hal; // Hal object - size_t data_width; // Number of data lines + size_t bus_width; // Number of data lines 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 + uint8_t *format_buffer; // The driver allocates an internal buffer for DMA to do data format transformer size_t resolution_hz; // LCD_CLK resolution, determined by selected clock source gdma_channel_handle_t dma_chan; // DMA channel handle lcd_i80_trans_descriptor_t *cur_trans; // Current transaction lcd_panel_io_i80_t *cur_device; // Current working device LIST_HEAD(i80_device_list, lcd_panel_io_i80_t) device_list; // Head of i80 device list - dma_descriptor_t dma_nodes[0]; // DMA descriptor pool, the descriptors are shared by all i80 devices + struct { + unsigned int exclusive: 1; // Indicate whether the I80 bus is owned by one device (whose CS GPIO is not assigned) exclusively + } flags; + dma_descriptor_t dma_nodes[]; // DMA descriptor pool, the descriptors are shared by all i80 devices }; struct lcd_i80_trans_descriptor_t { @@ -82,39 +90,44 @@ struct lcd_panel_io_i80_t { QueueHandle_t trans_queue; // Transaction queue, transactions in this queue are pending for scheduler to dispatch QueueHandle_t done_queue; // Transaction done queue, transactions in this queue are finished but not recycled by the caller size_t queue_size; // Size of transaction queue - size_t num_trans_working; // Number of transactions that are undergoing (the descriptor not recycled yet) + size_t num_trans_inflight; // Number of transactions that are undergoing (the descriptor not recycled yet) + int lcd_cmd_bits; // Bit width of LCD command + int lcd_param_bits; // Bit width of LCD parameter void *cb_user_data; // private data used when transfer color data bool (*on_color_trans_done)(esp_lcd_panel_io_handle_t panel_io, void *user_data, void *event_data); // color data trans done callback LIST_ENTRY(lcd_panel_io_i80_t) device_list_entry; // Entry of i80 device list struct { - int dc_idle_level: 1; // Level of DC line in IDLE phase - int dc_cmd_level: 1; // Level of DC line in CMD phase - int dc_dummy_level: 1; // Level of DC line in DUMMY phase - int dc_data_level: 1; // Level of DC line in DATA phase + unsigned int dc_idle_level: 1; // Level of DC line in IDLE phase + unsigned int dc_cmd_level: 1; // Level of DC line in CMD phase + unsigned int dc_dummy_level: 1; // Level of DC line in DUMMY phase + unsigned int dc_data_level: 1; // Level of DC line in DATA phase } dc_levels; struct { - int invert_cs: 1; // Whether to invert the CS line - int reverse_color_bits: 1; // Reverse the data bits, D[N:0] -> D[0:N] - int swap_color_bytes: 1; // Swap adjacent two data bytes before sending out - int pclk_active_neg: 1; // The display will write data lines when there's a falling edge on WR line - int pclk_idle_low: 1; // The WR line keeps at low level in IDLE phase + unsigned int cs_active_high: 1; // Whether the CS line is active on high level + unsigned int reverse_color_bits: 1; // Reverse the data bits, D[N:0] -> D[0:N] + unsigned int swap_color_bytes: 1; // Swap adjacent two data bytes before sending out + unsigned int pclk_active_neg: 1; // The display will write data lines when there's a falling edge on WR line + unsigned int pclk_idle_low: 1; // The WR line keeps at low level in IDLE phase } flags; - lcd_i80_trans_descriptor_t trans_pool[0]; // Transaction pool + lcd_i80_trans_descriptor_t trans_pool[]; // Transaction pool }; esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lcd_i80_bus_handle_t *ret_bus) { esp_err_t ret = ESP_OK; esp_lcd_i80_bus_t *bus = NULL; - ESP_GOTO_ON_FALSE(bus_config && ret_bus, ESP_ERR_INVALID_ARG, err_arg, TAG, "invalid argument"); + ESP_GOTO_ON_FALSE(bus_config && ret_bus, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); size_t num_dma_nodes = bus_config->max_transfer_bytes / DMA_DESCRIPTOR_BUFFER_MAX_SIZE + 1; // DMA descriptors must be placed in internal SRAM bus = heap_caps_calloc(1, sizeof(esp_lcd_i80_bus_t) + num_dma_nodes * sizeof(dma_descriptor_t), MALLOC_CAP_DMA); - ESP_GOTO_ON_FALSE(bus, ESP_ERR_NO_MEM, no_mem_bus, TAG, "no mem for i80 bus"); + ESP_GOTO_ON_FALSE(bus, ESP_ERR_NO_MEM, err, TAG, "no mem for i80 bus"); bus->num_dma_nodes = num_dma_nodes; + bus->bus_id = -1; + bus->format_buffer = heap_caps_calloc(1, CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE, MALLOC_CAP_DMA); + ESP_GOTO_ON_FALSE(bus->format_buffer, ESP_ERR_NO_MEM, err, TAG, "no mem for format buffer"); // register to platform int bus_id = lcd_com_register_device(LCD_COM_DEVICE_TYPE_I80, bus); - ESP_GOTO_ON_FALSE(bus_id >= 0, ESP_ERR_NOT_FOUND, no_slot, TAG, "no free i80 bus slot"); + ESP_GOTO_ON_FALSE(bus_id >= 0, ESP_ERR_NOT_FOUND, err, TAG, "no free i80 bus slot"); bus->bus_id = bus_id; // enable APB to access LCD registers periph_module_enable(lcd_periph_signals.buses[bus_id].module); @@ -124,23 +137,25 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc lcd_ll_reset(bus->hal.dev); lcd_ll_fifo_reset(bus->hal.dev); lcd_ll_enable_clock(bus->hal.dev, true); + // set peripheral clock resolution + ret = lcd_i80_select_periph_clock(bus, bus_config->clk_src); + ESP_GOTO_ON_ERROR(ret, err, TAG, "select periph clock %d failed", bus_config->clk_src); // install interrupt service, (LCD peripheral shares the same interrupt source with Camera peripheral with different mask) // interrupt is disabled by default - int isr_flags = ESP_INTR_FLAG_INTRDISABLED; + int isr_flags = ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_SHARED; ret = esp_intr_alloc_intrstatus(lcd_periph_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); - ESP_GOTO_ON_ERROR(ret, no_int, TAG, "install interrupt failed"); + 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 // install DMA service - ret = lcd_i80_bus_create_trans_link(bus); - ESP_GOTO_ON_ERROR(ret, no_dma, TAG, "install DMA failed"); - // set peripheral clock resolution - bus->resolution_hz = lcd_com_select_periph_clock(&bus->hal); - // enable 8080 mode and set data width + ret = lcd_i80_init_dma_link(bus); + ESP_GOTO_ON_ERROR(ret, err, TAG, "install DMA failed"); + // enable 8080 mode and set bus width lcd_ll_enable_rgb_mode(bus->hal.dev, false); - lcd_ll_set_data_width(bus->hal.dev, bus_config->data_width); + lcd_ll_set_data_width(bus->hal.dev, bus_config->bus_width); + bus->bus_width = lcd_ll_get_data_width(bus->hal.dev); // number of data cycles is controlled by DMA buffer size lcd_ll_enable_output_always_on(bus->hal.dev, true); // enable trans done interrupt @@ -150,27 +165,35 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc lcd_periph_trigger_quick_trans_done_event(bus); // configure GPIO ret = lcd_i80_bus_configure_gpio(bus, bus_config); - ESP_GOTO_ON_ERROR(ret, no_gpio, TAG, "configure GPIO failed"); + ESP_GOTO_ON_ERROR(ret, err, TAG, "configure GPIO failed"); // fill other i80 bus runtime parameters LIST_INIT(&bus->device_list); // initialize device list head bus->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED; - bus->data_width = lcd_ll_get_data_width(bus->hal.dev); *ret_bus = bus; ESP_LOGD(TAG, "new i80 bus(%d) @%p, %zu dma nodes", bus_id, bus, bus->num_dma_nodes); return ESP_OK; -no_gpio: - gdma_disconnect(bus->dma_chan); - gdma_del_channel(bus->dma_chan); -no_dma: - esp_intr_free(bus->intr); -no_int: - periph_module_disable(lcd_periph_signals.buses[bus_id].module); - lcd_com_remove_device(LCD_COM_DEVICE_TYPE_I80, bus->bus_id); -no_slot: - free(bus); -no_mem_bus: -err_arg: +err: + if (bus) { + if (bus->intr) { + esp_intr_free(bus->intr); + } + if (bus->dma_chan) { + gdma_disconnect(bus->dma_chan); + gdma_del_channel(bus->dma_chan); + } + if (bus->bus_id >= 0) { + periph_module_disable(lcd_periph_signals.buses[bus->bus_id].module); + lcd_com_remove_device(LCD_COM_DEVICE_TYPE_I80, bus->bus_id); + } + if (bus->format_buffer) { + free(bus->format_buffer); + } + if (bus->pm_lock) { + esp_pm_lock_delete(bus->pm_lock); + } + free(bus); + } return ret; } @@ -180,11 +203,15 @@ esp_err_t esp_lcd_del_i80_bus(esp_lcd_i80_bus_handle_t bus) ESP_GOTO_ON_FALSE(bus, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); ESP_GOTO_ON_FALSE(LIST_EMPTY(&bus->device_list), ESP_ERR_INVALID_STATE, err, TAG, "device list not empty"); int bus_id = bus->bus_id; + lcd_com_remove_device(LCD_COM_DEVICE_TYPE_I80, bus_id); + periph_module_disable(lcd_periph_signals.buses[bus_id].module); gdma_disconnect(bus->dma_chan); gdma_del_channel(bus->dma_chan); esp_intr_free(bus->intr); - periph_module_disable(lcd_periph_signals.buses[bus_id].module); - lcd_com_remove_device(LCD_COM_DEVICE_TYPE_I80, bus_id); + free(bus->format_buffer); + if (bus->pm_lock) { + esp_pm_lock_delete(bus->pm_lock); + } free(bus); ESP_LOGD(TAG, "del i80 bus(%d)", bus_id); err: @@ -195,10 +222,20 @@ esp_err_t esp_lcd_new_panel_io_i80(esp_lcd_i80_bus_handle_t bus, const esp_lcd_p { esp_err_t ret = ESP_OK; lcd_panel_io_i80_t *i80_device = NULL; + bool bus_exclusive = false; ESP_GOTO_ON_FALSE(bus && io_config && ret_io, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); + // check if the bus has been configured as exclusive + portENTER_CRITICAL(&bus->spinlock); + if (!bus->flags.exclusive) { + bus->flags.exclusive = io_config->cs_gpio_num < 0; + } else { + bus_exclusive = true; + } + portEXIT_CRITICAL(&bus->spinlock); + ESP_GOTO_ON_FALSE(!bus_exclusive, ESP_ERR_INVALID_STATE, err, TAG, "bus has been exclusively owned by device"); // check if pixel clock setting is valid uint32_t pclk_prescale = bus->resolution_hz / io_config->pclk_hz; - ESP_GOTO_ON_FALSE(pclk_prescale <= LCD_LL_CLOCK_PRESCALE_MAX, ESP_ERR_NOT_SUPPORTED, err, TAG, + ESP_GOTO_ON_FALSE(pclk_prescale > 0 && pclk_prescale <= LCD_LL_CLOCK_PRESCALE_MAX, ESP_ERR_NOT_SUPPORTED, err, TAG, "prescaler can't satisfy PCLK clock %u", io_config->pclk_hz); i80_device = calloc(1, sizeof(lcd_panel_io_i80_t) + io_config->trans_queue_depth * sizeof(lcd_i80_trans_descriptor_t)); ESP_GOTO_ON_FALSE(i80_device, ESP_ERR_NO_MEM, err, TAG, "no mem for i80 panel io"); @@ -214,6 +251,8 @@ esp_err_t esp_lcd_new_panel_io_i80(esp_lcd_i80_bus_handle_t bus, const esp_lcd_p // we don't initialize the i80 bus at the memont, but initialize the bus when start a transaction for a new device // so save these as i80 device runtime parameters i80_device->bus = bus; + i80_device->lcd_cmd_bits = io_config->lcd_cmd_bits; + i80_device->lcd_param_bits = io_config->lcd_param_bits; i80_device->queue_size = io_config->trans_queue_depth; i80_device->clock_prescale = pclk_prescale; i80_device->pclk_hz = bus->resolution_hz / pclk_prescale; @@ -224,7 +263,7 @@ esp_err_t esp_lcd_new_panel_io_i80(esp_lcd_i80_bus_handle_t bus, const esp_lcd_p i80_device->cs_gpio_num = io_config->cs_gpio_num; i80_device->flags.reverse_color_bits = io_config->flags.reverse_color_bits; i80_device->flags.swap_color_bytes = io_config->flags.swap_color_bytes; - i80_device->flags.invert_cs = io_config->flags.invert_cs; + i80_device->flags.cs_active_high = io_config->flags.cs_active_high; i80_device->flags.pclk_idle_low = io_config->flags.pclk_idle_low; i80_device->flags.pclk_active_neg = io_config->flags.pclk_active_neg; i80_device->on_color_trans_done = io_config->on_color_trans_done; @@ -235,9 +274,11 @@ esp_err_t esp_lcd_new_panel_io_i80(esp_lcd_i80_bus_handle_t bus, const esp_lcd_p i80_device->base.tx_color = panel_io_i80_tx_color; // 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() - gpio_set_level(io_config->cs_gpio_num, !io_config->flags.invert_cs); - 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); + 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); + gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[io_config->cs_gpio_num], PIN_FUNC_GPIO); + } *ret_io = &(i80_device->base); ESP_LOGD(TAG, "new i80 lcd panel io @%p on bus(%d)", i80_device, bus->bus_id); return ESP_OK; @@ -261,7 +302,7 @@ static esp_err_t panel_io_i80_del(esp_lcd_panel_io_t *io) esp_lcd_i80_bus_t *bus = i80_device->bus; lcd_i80_trans_descriptor_t *trans_desc = NULL; // wait all pending transaction to finish - for (size_t i = 0; i < i80_device->num_trans_working; i++) { + for (size_t i = 0; i < i80_device->num_trans_inflight; i++) { xQueueReceive(i80_device->done_queue, &trans_desc, portMAX_DELAY); } // remove from device list @@ -276,31 +317,72 @@ static esp_err_t panel_io_i80_del(esp_lcd_panel_io_t *io) return ESP_OK; } -static esp_err_t panel_io_i80_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, int lcd_cmd_bits, const void *param, size_t param_size) +static void i80_lcd_prepare_cmd_buffer(esp_lcd_i80_bus_t *bus, lcd_panel_io_i80_t *i80_device, void *lcd_cmd) +{ + uint8_t *from = (uint8_t *)lcd_cmd; + if (bus->bus_width < i80_device->lcd_cmd_bits) { + // LCD is big-endian, e.g. to send command 0x1234, byte 0x12 should appear on the bus first + // However, the i80 peripheral will send 0x34 first, so we reversed the order below + int start = 0; + int end = i80_device->lcd_cmd_bits / 8 - 1; + lcd_com_reverse_buffer_bytes(from, start, end); + } +} + +static uint32_t i80_lcd_prepare_param_buffer(esp_lcd_i80_bus_t *bus, lcd_panel_io_i80_t *i80_device, const void *lcd_param, size_t param_size) +{ + int param_per_size = i80_device->lcd_param_bits / 8; + int param_num = param_size / param_per_size; + const uint8_t *from = (const uint8_t *)lcd_param; + uint8_t *to = bus->format_buffer; + uint8_t step = bus->bus_width / 8; + int param_cycle = i80_device->lcd_param_bits / bus->bus_width; + // in case bus_width=16 and param_bits=8, we still need 1 param_cycle + if (param_cycle * bus->bus_width < i80_device->lcd_param_bits) { + param_cycle++; + } + int ele_cycles = param_cycle * param_num; + int bytes_to_copy = MIN(bus->bus_width, i80_device->lcd_param_bits) / 8; + int cnt_from = 0; + // expand the width of parameters when necessary + for (int i = 0; i < ele_cycles; i++) { + for (int j = 0; j < bytes_to_copy; j++) { + to[j] = from[cnt_from++]; + } + to += step; + } + return to - bus->format_buffer; +} + +static esp_err_t panel_io_i80_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, const void *param, size_t param_size) { lcd_panel_io_i80_t *next_device = __containerof(io, lcd_panel_io_i80_t, base); esp_lcd_i80_bus_t *bus = next_device->bus; lcd_panel_io_i80_t *cur_device = bus->cur_device; lcd_i80_trans_descriptor_t *trans_desc = NULL; assert(param_size <= (bus->num_dma_nodes * DMA_DESCRIPTOR_BUFFER_MAX_SIZE) && "parameter bytes too long, enlarge max_transfer_bytes"); - uint32_t cmd_cycles = lcd_cmd_bits / bus->data_width; - // in case data_width=16 and cmd_bits=8, we still need 1 cmd_cycle - if (cmd_cycles * bus->data_width < lcd_cmd_bits) { + assert(param_size <= CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE && "format buffer too small, increase CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE"); + uint32_t cmd_cycles = next_device->lcd_cmd_bits / bus->bus_width; + // in case bus_width=16 and cmd_bits=8, we still need 1 cmd_cycle + if (cmd_cycles * bus->bus_width < next_device->lcd_cmd_bits) { cmd_cycles++; } + i80_lcd_prepare_cmd_buffer(bus, next_device, &lcd_cmd); + uint32_t param_len = i80_lcd_prepare_param_buffer(bus, next_device, param, param_size); // wait all pending transaction in the queue to finish - for (size_t i = 0; i < next_device->num_trans_working; i++) { + for (size_t i = 0; i < next_device->num_trans_inflight; i++) { xQueueReceive(next_device->done_queue, &trans_desc, portMAX_DELAY); } - next_device->num_trans_working = 0; + next_device->num_trans_inflight = 0; uint32_t intr_status = lcd_ll_get_interrupt_status(bus->hal.dev); lcd_ll_clear_interrupt_status(bus->hal.dev, intr_status); // switch devices if necessary lcd_i80_switch_devices(cur_device, next_device); - // don't reverse bit/bytes for parameters + // set data format + lcd_ll_reverse_data_byte_order(bus->hal.dev, false); lcd_ll_reverse_data_bit_order(bus->hal.dev, false); - lcd_ll_reverse_data_byte_order(bus->hal.dev, bus->data_width, false); + lcd_ll_reverse_data_8bits_order(bus->hal.dev, next_device->lcd_param_bits > bus->bus_width); bus->cur_trans = NULL; bus->cur_device = next_device; // package a transaction @@ -308,34 +390,43 @@ static esp_err_t panel_io_i80_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, int trans_desc->i80_device = next_device; trans_desc->cmd_cycles = cmd_cycles; trans_desc->cmd_value = lcd_cmd; - trans_desc->data = param; - trans_desc->data_length = param_size; + trans_desc->data = param ? bus->format_buffer : NULL; + trans_desc->data_length = param ? param_len : 0; trans_desc->trans_done_cb = NULL; // no callback for parameter transaction // mount data to DMA links lcd_com_mount_dma_data(bus->dma_nodes, trans_desc->data, trans_desc->data_length); + // increase the pm lock reference count before starting a new transaction + if (bus->pm_lock) { + esp_pm_lock_acquire(bus->pm_lock); + } lcd_start_transaction(bus, trans_desc); // polling the trans done event, but don't clear the event status - while (!(lcd_ll_get_interrupt_status(bus->hal.dev) & LCD_LL_EVENT_TRANS_DONE)); + while (!(lcd_ll_get_interrupt_status(bus->hal.dev) & LCD_LL_EVENT_TRANS_DONE)) {} + // decrease pm lock reference count + if (bus->pm_lock) { + esp_pm_lock_release(bus->pm_lock); + } return ESP_OK; } -static esp_err_t panel_io_i80_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, int lcd_cmd_bits, const void *color, size_t color_size) +static esp_err_t panel_io_i80_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, const void *color, size_t color_size) { lcd_panel_io_i80_t *i80_device = __containerof(io, lcd_panel_io_i80_t, base); esp_lcd_i80_bus_t *bus = i80_device->bus; lcd_i80_trans_descriptor_t *trans_desc = NULL; assert(color_size <= (bus->num_dma_nodes * DMA_DESCRIPTOR_BUFFER_MAX_SIZE) && "color bytes too long, enlarge max_transfer_bytes"); - // in case data_width=16 and cmd_bits=8, we still need 1 cmd_cycle - uint32_t cmd_cycles = lcd_cmd_bits / bus->data_width; - if (cmd_cycles * bus->data_width < lcd_cmd_bits) { + // in case bus_width=16 and cmd_bits=8, we still need 1 cmd_cycle + uint32_t cmd_cycles = i80_device->lcd_cmd_bits / bus->bus_width; + if (cmd_cycles * bus->bus_width < i80_device->lcd_cmd_bits) { cmd_cycles++; } - if (i80_device->num_trans_working < i80_device->queue_size) { - trans_desc = &i80_device->trans_pool[i80_device->num_trans_working]; + i80_lcd_prepare_cmd_buffer(bus, i80_device, &lcd_cmd); + if (i80_device->num_trans_inflight < i80_device->queue_size) { + trans_desc = &i80_device->trans_pool[i80_device->num_trans_inflight]; } else { // transaction pool has used up, recycle one from done_queue xQueueReceive(i80_device->done_queue, &trans_desc, portMAX_DELAY); - i80_device->num_trans_working--; + i80_device->num_trans_inflight--; } trans_desc->i80_device = i80_device; trans_desc->cmd_cycles = cmd_cycles; @@ -346,14 +437,37 @@ static esp_err_t panel_io_i80_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, int trans_desc->cb_user_data = i80_device->cb_user_data; // send transaction to trans_queue xQueueSend(i80_device->trans_queue, &trans_desc, portMAX_DELAY); - i80_device->num_trans_working++; + 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 esp_intr_enable(bus->intr); return ESP_OK; } -static esp_err_t lcd_i80_bus_create_trans_link(esp_lcd_i80_bus_handle_t bus) +static esp_err_t lcd_i80_select_periph_clock(esp_lcd_i80_bus_handle_t bus, lcd_clock_source_t clk_src) +{ + esp_err_t ret = ESP_OK; + lcd_ll_set_group_clock_src(bus->hal.dev, clk_src, LCD_PERIPH_CLOCK_PRE_SCALE, 1, 0); + switch (clk_src) { + case LCD_CLK_SRC_PLL160M: + bus->resolution_hz = 160000000 / LCD_PERIPH_CLOCK_PRE_SCALE; +#if CONFIG_PM_ENABLE + ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "i80_bus_lcd", &bus->pm_lock); + ESP_RETURN_ON_ERROR(ret, TAG, "create ESP_PM_APB_FREQ_MAX lock failed"); + ESP_LOGD(TAG, "installed ESP_PM_APB_FREQ_MAX lock"); +#endif + break; + case LCD_CLK_SRC_XTAL: + bus->resolution_hz = rtc_clk_xtal_freq_get() * 1000000 / LCD_PERIPH_CLOCK_PRE_SCALE; + break; + default: + ESP_RETURN_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, TAG, "unsupported clock source: %d", clk_src); + break; + } + return ret; +} + +static esp_err_t lcd_i80_init_dma_link(esp_lcd_i80_bus_handle_t bus) { esp_err_t ret = ESP_OK; // chain DMA descriptors @@ -387,24 +501,24 @@ static esp_err_t lcd_i80_bus_configure_gpio(esp_lcd_i80_bus_handle_t bus, const int bus_id = bus->bus_id; // check validation of GPIO number bool valid_gpio = (bus_config->wr_gpio_num >= 0) && (bus_config->dc_gpio_num >= 0); - for (size_t i = 0; i < bus_config->data_width; i++) { + for (size_t i = 0; i < bus_config->bus_width; i++) { valid_gpio = valid_gpio && (bus_config->data_gpio_nums[i] >= 0); } if (!valid_gpio) { return ESP_ERR_INVALID_ARG; } // connect peripheral signals via GPIO matrix - for (size_t i = 0; i < bus_config->data_width; i++) { - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[bus_config->data_gpio_nums[i]], PIN_FUNC_GPIO); + 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_signals.buses[bus_id].data_sigs[i], false, false); + gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[bus_config->data_gpio_nums[i]], PIN_FUNC_GPIO); } - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[bus_config->dc_gpio_num], PIN_FUNC_GPIO); gpio_set_direction(bus_config->dc_gpio_num, GPIO_MODE_OUTPUT); esp_rom_gpio_connect_out_signal(bus_config->dc_gpio_num, lcd_periph_signals.buses[bus_id].dc_sig, false, false); - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[bus_config->wr_gpio_num], PIN_FUNC_GPIO); + gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[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_signals.buses[bus_id].wr_sig, false, false); + gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[bus_config->wr_gpio_num], PIN_FUNC_GPIO); return ESP_OK; } @@ -415,7 +529,7 @@ static void lcd_periph_trigger_quick_trans_done_event(esp_lcd_i80_bus_handle_t b // where we dispatch transactions for i80 devices lcd_ll_set_phase_cycles(bus->hal.dev, 0, 1, 0); lcd_ll_start(bus->hal.dev); - while (!(lcd_ll_get_interrupt_status(bus->hal.dev) & LCD_LL_EVENT_TRANS_DONE)); + while (!(lcd_ll_get_interrupt_status(bus->hal.dev) & LCD_LL_EVENT_TRANS_DONE)) {} } static void lcd_start_transaction(esp_lcd_i80_bus_t *bus, lcd_i80_trans_descriptor_t *trans_desc) @@ -423,7 +537,7 @@ static void lcd_start_transaction(esp_lcd_i80_bus_t *bus, lcd_i80_trans_descript // by default, the dummy phase is disabled because it's not common for most LCDs // Number of data phase cycles are controlled by DMA buffer length, we only need to enable/disable the phase here lcd_ll_set_phase_cycles(bus->hal.dev, trans_desc->cmd_cycles, 0, trans_desc->data ? 1 : 0); - lcd_ll_set_command(bus->hal.dev, bus->data_width, trans_desc->cmd_value); + lcd_ll_set_command(bus->hal.dev, bus->bus_width, trans_desc->cmd_value); if (trans_desc->data) { // some specific LCD commands can have no parameters gdma_start(bus->dma_chan, (intptr_t)(bus->dma_nodes)); } @@ -442,13 +556,15 @@ static void lcd_i80_switch_devices(lcd_panel_io_i80_t *cur_device, lcd_panel_io_ // configure DC line level for the new device 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) { + 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); } - // connect CS signal to the new device - esp_rom_gpio_connect_out_signal(next_device->cs_gpio_num, lcd_periph_signals.buses[bus->bus_id].cs_sig, - next_device->flags.invert_cs, false); + if (next_device->cs_gpio_num >= 0) { + // connect CS signal to the new device + esp_rom_gpio_connect_out_signal(next_device->cs_gpio_num, lcd_periph_signals.buses[bus->bus_id].cs_sig, + next_device->flags.cs_active_high, false); + } } } @@ -469,6 +585,10 @@ IRAM_ATTR static void lcd_default_isr_handler(void *args) // process finished transaction if (trans_desc) { assert(trans_desc->i80_device == cur_device && "transaction device mismatch"); + // decrease pm lock reference count + if (bus->pm_lock) { + esp_pm_lock_release(bus->pm_lock); + } // device callback if (trans_desc->trans_done_cb) { if (trans_desc->trans_done_cb(&cur_device->base, trans_desc->cb_user_data, NULL)) { @@ -498,13 +618,18 @@ IRAM_ATTR static void lcd_default_isr_handler(void *args) lcd_i80_switch_devices(cur_device, next_device); // only reverse data bit/bytes for color data lcd_ll_reverse_data_bit_order(bus->hal.dev, next_device->flags.reverse_color_bits); - lcd_ll_reverse_data_byte_order(bus->hal.dev, bus->data_width, next_device->flags.swap_color_bytes); + lcd_ll_reverse_data_byte_order(bus->hal.dev, next_device->flags.swap_color_bytes); + lcd_ll_reverse_data_8bits_order(bus->hal.dev, false); bus->cur_trans = trans_desc; bus->cur_device = next_device; // mount data to DMA links lcd_com_mount_dma_data(bus->dma_nodes, trans_desc->data, trans_desc->data_length); // enable interrupt again, because the new transaction can trigger new trans done event esp_intr_enable(bus->intr); + // increase the pm lock reference count before starting a new transaction + if (bus->pm_lock) { + esp_pm_lock_acquire(bus->pm_lock); + } lcd_start_transaction(bus, trans_desc); break; // exit for-each loop } diff --git a/components/esp_lcd/src/esp_lcd_panel_io_spi.c b/components/esp_lcd/src/esp_lcd_panel_io_spi.c index f8c2d2baf2..2c054e2ae2 100644 --- a/components/esp_lcd/src/esp_lcd_panel_io_spi.c +++ b/components/esp_lcd/src/esp_lcd_panel_io_spi.c @@ -15,11 +15,12 @@ #include "driver/gpio.h" #include "esp_log.h" #include "esp_check.h" +#include "esp_lcd_common.h" static const char *TAG = "lcd_panel.io.spi"; -static esp_err_t panel_io_spi_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, int lcd_cmd_bits, const void *param, size_t param_size); -static esp_err_t panel_io_spi_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, int lcd_cmd_bits, const void *color, size_t color_size); +static esp_err_t panel_io_spi_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, const void *param, size_t param_size); +static esp_err_t panel_io_spi_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, const void *color, size_t color_size); static esp_err_t panel_io_spi_del(esp_lcd_panel_io_t *io); static void lcd_spi_pre_trans_cb(spi_transaction_t *trans); static void lcd_spi_post_trans_color_cb(spi_transaction_t *trans); @@ -39,12 +40,15 @@ typedef struct { bool (*on_color_trans_done)(esp_lcd_panel_io_handle_t panel_io, void *user_data, void *event_data); // User register's callback, invoked when color data trans done void *user_data; // User's private data, passed directly to callback on_color_trans_done size_t queue_size; // Size of transaction queue - size_t num_trans_working; // Number of transactions that are undergoing (the descriptor not recycled yet) + size_t num_trans_inflight; // Number of transactions that are undergoing (the descriptor not recycled yet) + int lcd_cmd_bits; // Bit width of LCD command + int lcd_param_bits; // Bit width of LCD parameter struct { - int dc_as_cmd_phase: 1; // D/C line value is encoded into SPI transaction command phase - int dc_data_level: 1; // Indicates the level of DC line when tranfering data + unsigned int dc_as_cmd_phase: 1; // D/C line value is encoded into SPI transaction command phase + unsigned int dc_data_level: 1; // Indicates the level of DC line when tranfering data + unsigned int octal_mode: 1; // Indicates whether the transmitting is enabled with octal mode (8 data lines) } flags; - lcd_spi_trans_descriptor_t trans_pool[0]; // Transaction pool + lcd_spi_trans_descriptor_t trans_pool[]; // Transaction pool } esp_lcd_panel_io_spi_t; esp_err_t esp_lcd_new_panel_io_spi(esp_lcd_spi_bus_handle_t bus, const esp_lcd_panel_io_spi_config_t *io_config, esp_lcd_panel_io_handle_t *ret_io) @@ -58,6 +62,7 @@ esp_err_t esp_lcd_new_panel_io_spi(esp_lcd_spi_bus_handle_t bus, const esp_lcd_p ESP_GOTO_ON_FALSE(spi_panel_io, ESP_ERR_NO_MEM, err, TAG, "no mem for spi panel io"); spi_device_interface_config_t devcfg = { + .flags = SPI_DEVICE_HALFDUPLEX, .clock_speed_hz = io_config->pclk_hz, .mode = io_config->spi_mode, .spics_io_num = io_config->cs_gpio_num, @@ -80,7 +85,10 @@ esp_err_t esp_lcd_new_panel_io_spi(esp_lcd_spi_bus_handle_t bus, const esp_lcd_p spi_panel_io->flags.dc_as_cmd_phase = io_config->flags.dc_as_cmd_phase; spi_panel_io->flags.dc_data_level = !io_config->flags.dc_low_on_data; + spi_panel_io->flags.octal_mode = io_config->flags.octal_mode; spi_panel_io->on_color_trans_done = io_config->on_color_trans_done; + spi_panel_io->lcd_cmd_bits = io_config->lcd_cmd_bits; + spi_panel_io->lcd_param_bits = io_config->lcd_param_bits; spi_panel_io->user_data = io_config->user_data; spi_panel_io->dc_gpio_num = io_config->dc_gpio_num; spi_panel_io->queue_size = io_config->trans_queue_depth; @@ -109,7 +117,7 @@ static esp_err_t panel_io_spi_del(esp_lcd_panel_io_t *io) esp_lcd_panel_io_spi_t *spi_panel_io = __containerof(io, esp_lcd_panel_io_spi_t, base); // wait all pending transaction to finish - for (size_t i = 0; i < spi_panel_io->num_trans_working; i++) { + for (size_t i = 0; i < spi_panel_io->num_trans_inflight; i++) { ret = spi_device_get_trans_result(spi_panel_io->spi_dev, &spi_trans, portMAX_DELAY); ESP_GOTO_ON_ERROR(ret, err, TAG, "recycle spi transactions failed"); } @@ -124,7 +132,35 @@ err: return ret; } -static esp_err_t panel_io_spi_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, int lcd_cmd_bits, const void *param, size_t param_size) +static void spi_lcd_prepare_cmd_buffer(esp_lcd_panel_io_spi_t *panel_io, const void *cmd) +{ + uint8_t *from = (uint8_t *)cmd; + // LCD is big-endian, e.g. to send command 0x1234, byte 0x12 should appear on the bus first + // However, the SPI peripheral will send 0x34 first, so we reversed the order below + if (panel_io->lcd_cmd_bits > 8) { + int start = 0; + int end = panel_io->lcd_cmd_bits / 8 - 1; + lcd_com_reverse_buffer_bytes(from, start, end); + } +} + +static void spi_lcd_prepare_param_buffer(esp_lcd_panel_io_spi_t *panel_io, const void *param, size_t param_size) +{ + uint8_t *from = (uint8_t *)param; + int param_width = panel_io->lcd_param_bits / 8; + size_t param_num = param_size / param_width; + // LCD is big-endian, e.g. to send command 0x1234, byte 0x12 should appear on the bus first + // However, the SPI peripheral will send 0x34 first, so we reversed the order below + if (panel_io->lcd_param_bits > 8) { + for (size_t i = 0; i < param_num; i++) { + int start = i * param_width; + int end = start + param_width - 1; + lcd_com_reverse_buffer_bytes(from, start, end); + } + } +} + +static esp_err_t panel_io_spi_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, const void *param, size_t param_size) { esp_err_t ret = ESP_OK; spi_transaction_t *spi_trans = NULL; @@ -132,17 +168,22 @@ static esp_err_t panel_io_spi_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, int esp_lcd_panel_io_spi_t *spi_panel_io = __containerof(io, esp_lcd_panel_io_spi_t, base); // before issue a polling transaction, need to wait queued transactions finished - for (size_t i = 0; i < spi_panel_io->num_trans_working; i++) { + for (size_t i = 0; i < spi_panel_io->num_trans_inflight; i++) { ret = spi_device_get_trans_result(spi_panel_io->spi_dev, &spi_trans, portMAX_DELAY); ESP_GOTO_ON_ERROR(ret, err, TAG, "recycle spi transactions failed"); } - spi_panel_io->num_trans_working = 0; + spi_panel_io->num_trans_inflight = 0; lcd_trans = &spi_panel_io->trans_pool[0]; memset(lcd_trans, 0, sizeof(lcd_spi_trans_descriptor_t)); + spi_lcd_prepare_cmd_buffer(spi_panel_io, &lcd_cmd); lcd_trans->base.user = spi_panel_io; lcd_trans->flags.dc_gpio_level = !spi_panel_io->flags.dc_data_level; // set D/C line to command mode - lcd_trans->base.length = lcd_cmd_bits; + lcd_trans->base.length = spi_panel_io->lcd_cmd_bits; lcd_trans->base.tx_buffer = &lcd_cmd; + if (spi_panel_io->flags.octal_mode) { + // use 8 lines for transmitting command, address and data + lcd_trans->base.flags |= (SPI_TRANS_MULTILINE_CMD | SPI_TRANS_MULTILINE_ADDR | SPI_TRANS_MODE_OCT); + } if (spi_panel_io->flags.dc_as_cmd_phase) { // encoding DC value to SPI command phase when necessary lcd_trans->base.cmd = !spi_panel_io->flags.dc_data_level; } @@ -151,6 +192,7 @@ static esp_err_t panel_io_spi_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, int ESP_GOTO_ON_ERROR(ret, err, TAG, "spi transmit (polling) command failed"); if (param && param_size) { + spi_lcd_prepare_param_buffer(spi_panel_io, param, param_size); lcd_trans->flags.dc_gpio_level = spi_panel_io->flags.dc_data_level; // set D/C line to data mode lcd_trans->base.length = param_size * 8; // transaction length is in bits lcd_trans->base.tx_buffer = param; @@ -166,7 +208,7 @@ err: return ret; } -static esp_err_t panel_io_spi_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, int lcd_cmd_bits, const void *color, size_t color_size) +static esp_err_t panel_io_spi_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, const void *color, size_t color_size) { esp_err_t ret = ESP_OK; spi_transaction_t *spi_trans = NULL; @@ -174,20 +216,25 @@ static esp_err_t panel_io_spi_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, int esp_lcd_panel_io_spi_t *spi_panel_io = __containerof(io, esp_lcd_panel_io_spi_t, base); // before issue a polling transaction, need to wait queued transactions finished - for (size_t i = 0; i < spi_panel_io->num_trans_working; i++) { + for (size_t i = 0; i < spi_panel_io->num_trans_inflight; i++) { ret = spi_device_get_trans_result(spi_panel_io->spi_dev, &spi_trans, portMAX_DELAY); ESP_GOTO_ON_ERROR(ret, err, TAG, "recycle spi transactions failed"); } - spi_panel_io->num_trans_working = 0; + spi_panel_io->num_trans_inflight = 0; lcd_trans = &spi_panel_io->trans_pool[0]; memset(lcd_trans, 0, sizeof(lcd_spi_trans_descriptor_t)); + spi_lcd_prepare_cmd_buffer(spi_panel_io, &lcd_cmd); lcd_trans->base.user = spi_panel_io; lcd_trans->flags.dc_gpio_level = !spi_panel_io->flags.dc_data_level; // set D/C line to command mode - lcd_trans->base.length = lcd_cmd_bits; + lcd_trans->base.length = spi_panel_io->lcd_cmd_bits; lcd_trans->base.tx_buffer = &lcd_cmd; if (spi_panel_io->flags.dc_as_cmd_phase) { // encoding DC value to SPI command phase when necessary lcd_trans->base.cmd = !spi_panel_io->flags.dc_data_level; } + if (spi_panel_io->flags.octal_mode) { + // use 8 lines for transmitting command, address and data + lcd_trans->base.flags |= (SPI_TRANS_MULTILINE_CMD | SPI_TRANS_MULTILINE_ADDR | SPI_TRANS_MODE_OCT); + } // command is short, using polling mode ret = spi_device_polling_transmit(spi_panel_io->spi_dev, &lcd_trans->base); ESP_GOTO_ON_ERROR(ret, err, TAG, "spi transmit (polling) command failed"); @@ -203,7 +250,7 @@ static esp_err_t panel_io_spi_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, int // color data is usually large, using queue+blocking mode ret = spi_device_queue_trans(spi_panel_io->spi_dev, &lcd_trans->base, portMAX_DELAY); ESP_GOTO_ON_ERROR(ret, err, TAG, "spi transmit (queue) color failed"); - spi_panel_io->num_trans_working++; + spi_panel_io->num_trans_inflight++; err: return ret; diff --git a/components/esp_lcd/src/esp_lcd_panel_nt35510.c b/components/esp_lcd/src/esp_lcd_panel_nt35510.c new file mode 100644 index 0000000000..3bae8dae1b --- /dev/null +++ b/components/esp_lcd/src/esp_lcd_panel_nt35510.c @@ -0,0 +1,280 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// #define LOG_LOCAL_LEVEL ESP_LOG_DEBUG + +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_lcd_panel_interface.h" +#include "esp_lcd_panel_io.h" +#include "esp_lcd_panel_vendor.h" +#include "esp_lcd_panel_ops.h" +#include "esp_lcd_panel_commands.h" +#include "driver/gpio.h" +#include "esp_log.h" +#include "esp_check.h" + +static const char *TAG = "lcd_panel.nt35510"; + +static esp_err_t panel_nt35510_del(esp_lcd_panel_t *panel); +static esp_err_t panel_nt35510_reset(esp_lcd_panel_t *panel); +static esp_err_t panel_nt35510_init(esp_lcd_panel_t *panel); +static esp_err_t panel_nt35510_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data); +static esp_err_t panel_nt35510_invert_color(esp_lcd_panel_t *panel, bool invert_color_data); +static esp_err_t panel_nt35510_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y); +static esp_err_t panel_nt35510_swap_xy(esp_lcd_panel_t *panel, bool swap_axes); +static esp_err_t panel_nt35510_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap); +static esp_err_t panel_nt35510_disp_off(esp_lcd_panel_t *panel, bool off); + +typedef struct { + esp_lcd_panel_t base; + esp_lcd_panel_io_handle_t io; + int reset_gpio_num; + bool reset_level; + int x_gap; + int y_gap; + unsigned int bits_per_pixel; + uint8_t madctl_val; // save current value of LCD_CMD_MADCTL register + uint8_t colmod_cal; // save surrent value of LCD_CMD_COLMOD register +} nt35510_panel_t; + +esp_err_t esp_lcd_new_panel_nt35510(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel) +{ + esp_err_t ret = ESP_OK; + nt35510_panel_t *nt35510 = NULL; + ESP_GOTO_ON_FALSE(io && panel_dev_config && ret_panel, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); + nt35510 = calloc(1, sizeof(nt35510_panel_t)); + ESP_GOTO_ON_FALSE(nt35510, ESP_ERR_NO_MEM, err, TAG, "no mem for nt35510 panel"); + + if (panel_dev_config->reset_gpio_num >= 0) { + gpio_config_t io_conf = { + .mode = GPIO_MODE_OUTPUT, + .pin_bit_mask = 1ULL << panel_dev_config->reset_gpio_num, + }; + ESP_GOTO_ON_ERROR(gpio_config(&io_conf), err, TAG, "configure GPIO for RST line failed"); + } + + switch (panel_dev_config->color_space) { + case ESP_LCD_COLOR_SPACE_RGB: + nt35510->madctl_val = 0; + break; + case ESP_LCD_COLOR_SPACE_BGR: + nt35510->madctl_val |= LCD_CMD_BGR_BIT; + break; + default: + ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported color space"); + break; + } + + switch (panel_dev_config->bits_per_pixel) { + case 16: + nt35510->colmod_cal = 0x55; + break; + case 18: + nt35510->colmod_cal = 0x66; + break; + case 24: + nt35510->colmod_cal = 0x77; + break; + default: + ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported pixel width"); + break; + } + + nt35510->io = io; + nt35510->bits_per_pixel = panel_dev_config->bits_per_pixel; + nt35510->reset_gpio_num = panel_dev_config->reset_gpio_num; + nt35510->reset_level = panel_dev_config->flags.reset_active_high; + nt35510->base.del = panel_nt35510_del; + nt35510->base.reset = panel_nt35510_reset; + nt35510->base.init = panel_nt35510_init; + nt35510->base.draw_bitmap = panel_nt35510_draw_bitmap; + nt35510->base.invert_color = panel_nt35510_invert_color; + nt35510->base.set_gap = panel_nt35510_set_gap; + nt35510->base.mirror = panel_nt35510_mirror; + nt35510->base.swap_xy = panel_nt35510_swap_xy; + nt35510->base.disp_off = panel_nt35510_disp_off; + *ret_panel = &(nt35510->base); + ESP_LOGD(TAG, "new nt35510 panel @%p", nt35510); + + return ESP_OK; + +err: + if (nt35510) { + if (panel_dev_config->reset_gpio_num >= 0) { + gpio_reset_pin(panel_dev_config->reset_gpio_num); + } + free(nt35510); + } + return ret; +} + +static esp_err_t panel_nt35510_del(esp_lcd_panel_t *panel) +{ + nt35510_panel_t *nt35510 = __containerof(panel, nt35510_panel_t, base); + + if (nt35510->reset_gpio_num >= 0) { + gpio_reset_pin(nt35510->reset_gpio_num); + } + ESP_LOGD(TAG, "del nt35510 panel @%p", nt35510); + free(nt35510); + return ESP_OK; +} + +static esp_err_t panel_nt35510_reset(esp_lcd_panel_t *panel) +{ + nt35510_panel_t *nt35510 = __containerof(panel, nt35510_panel_t, base); + esp_lcd_panel_io_handle_t io = nt35510->io; + + // perform hardware reset + if (nt35510->reset_gpio_num >= 0) { + gpio_set_level(nt35510->reset_gpio_num, nt35510->reset_level); + vTaskDelay(pdMS_TO_TICKS(10)); + gpio_set_level(nt35510->reset_gpio_num, !nt35510->reset_level); + vTaskDelay(pdMS_TO_TICKS(10)); + } else { + // perform software reset + esp_lcd_panel_io_tx_param(io, LCD_CMD_SWRESET << 8, NULL, 0); + vTaskDelay(pdMS_TO_TICKS(20)); // spec, wait at least 5m before sending new command + } + + return ESP_OK; +} + +static esp_err_t panel_nt35510_init(esp_lcd_panel_t *panel) +{ + nt35510_panel_t *nt35510 = __containerof(panel, nt35510_panel_t, base); + esp_lcd_panel_io_handle_t io = nt35510->io; + // LCD goes into sleep mode and display will be turned off after power on reset, exit sleep mode first + esp_lcd_panel_io_tx_param(io, LCD_CMD_SLPOUT << 8, NULL, 0); + vTaskDelay(pdMS_TO_TICKS(100)); + esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL << 8, (uint16_t[]) { + nt35510->madctl_val, + }, 2); + esp_lcd_panel_io_tx_param(io, LCD_CMD_COLMOD << 8, (uint16_t[]) { + nt35510->colmod_cal, + }, 2); + // turn on display + esp_lcd_panel_io_tx_param(io, LCD_CMD_DISPON << 8, NULL, 0); + + return ESP_OK; +} + +static esp_err_t panel_nt35510_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data) +{ + nt35510_panel_t *nt35510 = __containerof(panel, nt35510_panel_t, base); + assert((x_start < x_end) && (y_start < y_end) && "start position must be smaller than end position"); + esp_lcd_panel_io_handle_t io = nt35510->io; + + x_start += nt35510->x_gap; + x_end += nt35510->x_gap; + y_start += nt35510->y_gap; + y_end += nt35510->y_gap; + + // define an area of frame memory where MCU can access + esp_lcd_panel_io_tx_param(io, (LCD_CMD_CASET << 8) + 0, (uint16_t[]) { + (x_start >> 8) & 0xFF, + }, 2); + esp_lcd_panel_io_tx_param(io, (LCD_CMD_CASET << 8) + 1, (uint16_t[]) { + x_start & 0xFF, + }, 2); + esp_lcd_panel_io_tx_param(io, (LCD_CMD_CASET << 8) + 2, (uint16_t[]) { + ((x_end - 1) >> 8) & 0xFF, + }, 2); + esp_lcd_panel_io_tx_param(io, (LCD_CMD_CASET << 8) + 3, (uint16_t[]) { + (x_end - 1) & 0xFF, + }, 2); + esp_lcd_panel_io_tx_param(io, (LCD_CMD_RASET << 8) + 0, (uint16_t[]) { + (y_start >> 8) & 0xFF, + }, 2); + esp_lcd_panel_io_tx_param(io, (LCD_CMD_RASET << 8) + 1, (uint16_t[]) { + y_start & 0xFF, + }, 2); + esp_lcd_panel_io_tx_param(io, (LCD_CMD_RASET << 8) + 2, (uint16_t[]) { + ((y_end - 1) >> 8) & 0xFF, + }, 2); + esp_lcd_panel_io_tx_param(io, (LCD_CMD_RASET << 8) + 3, (uint16_t[]) { + (y_end - 1) & 0xFF, + }, 2); + // transfer frame buffer + size_t len = (x_end - x_start) * (y_end - y_start) * nt35510->bits_per_pixel / 8; + esp_lcd_panel_io_tx_color(io, LCD_CMD_RAMWR << 8, color_data, len); + + return ESP_OK; +} + +static esp_err_t panel_nt35510_invert_color(esp_lcd_panel_t *panel, bool invert_color_data) +{ + nt35510_panel_t *nt35510 = __containerof(panel, nt35510_panel_t, base); + esp_lcd_panel_io_handle_t io = nt35510->io; + int command = 0; + if (invert_color_data) { + command = LCD_CMD_INVON; + } else { + command = LCD_CMD_INVOFF; + } + esp_lcd_panel_io_tx_param(io, command << 8, NULL, 0); + return ESP_OK; +} + +static esp_err_t panel_nt35510_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y) +{ + nt35510_panel_t *nt35510 = __containerof(panel, nt35510_panel_t, base); + esp_lcd_panel_io_handle_t io = nt35510->io; + if (mirror_x) { + nt35510->madctl_val |= LCD_CMD_MX_BIT; + } else { + nt35510->madctl_val &= ~LCD_CMD_MX_BIT; + } + if (mirror_y) { + nt35510->madctl_val |= LCD_CMD_MY_BIT; + } else { + nt35510->madctl_val &= ~LCD_CMD_MY_BIT; + } + esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL << 8, (uint16_t[]) { + nt35510->madctl_val + }, 2); + return ESP_OK; +} + +static esp_err_t panel_nt35510_swap_xy(esp_lcd_panel_t *panel, bool swap_axes) +{ + nt35510_panel_t *nt35510 = __containerof(panel, nt35510_panel_t, base); + esp_lcd_panel_io_handle_t io = nt35510->io; + if (swap_axes) { + nt35510->madctl_val |= LCD_CMD_MV_BIT; + } else { + nt35510->madctl_val &= ~LCD_CMD_MV_BIT; + } + esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL << 8, (uint16_t[]) { + nt35510->madctl_val + }, 2); + return ESP_OK; +} + +static esp_err_t panel_nt35510_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap) +{ + nt35510_panel_t *nt35510 = __containerof(panel, nt35510_panel_t, base); + nt35510->x_gap = x_gap; + nt35510->y_gap = y_gap; + return ESP_OK; +} + +static esp_err_t panel_nt35510_disp_off(esp_lcd_panel_t *panel, bool off) +{ + nt35510_panel_t *nt35510 = __containerof(panel, nt35510_panel_t, base); + esp_lcd_panel_io_handle_t io = nt35510->io; + int command = 0; + if (off) { + command = LCD_CMD_DISPOFF; + } else { + command = LCD_CMD_DISPON; + } + esp_lcd_panel_io_tx_param(io, command << 8, NULL, 0); + return ESP_OK; +} diff --git a/components/esp_lcd/src/esp_lcd_panel_ssd1306.c b/components/esp_lcd/src/esp_lcd_panel_ssd1306.c index 9481df82dd..9e56a1548b 100644 --- a/components/esp_lcd/src/esp_lcd_panel_ssd1306.c +++ b/components/esp_lcd/src/esp_lcd_panel_ssd1306.c @@ -130,14 +130,14 @@ static esp_err_t panel_ssd1306_init(esp_lcd_panel_t *panel) { ssd1306_panel_t *ssd1306 = __containerof(panel, ssd1306_panel_t, base); esp_lcd_panel_io_handle_t io = ssd1306->io; - esp_lcd_panel_io_tx_param(io, SSD1306_CMD_DISP_OFF, 8, NULL, 0); - esp_lcd_panel_io_tx_param(io, SSD1306_CMD_SET_MEMORY_ADDR_MODE, 8, (uint8_t[]) { + esp_lcd_panel_io_tx_param(io, SSD1306_CMD_DISP_OFF, NULL, 0); + esp_lcd_panel_io_tx_param(io, SSD1306_CMD_SET_MEMORY_ADDR_MODE, (uint8_t[]) { 0x00 // horizontal addressing mode }, 1); - esp_lcd_panel_io_tx_param(io, SSD1306_CMD_SET_CHARGE_PUMP, 8, (uint8_t[]) { + esp_lcd_panel_io_tx_param(io, SSD1306_CMD_SET_CHARGE_PUMP, (uint8_t[]) { 0x14 // enable charge pump }, 1); - esp_lcd_panel_io_tx_param(io, SSD1306_CMD_DISP_ON, 8, NULL, 0); + esp_lcd_panel_io_tx_param(io, SSD1306_CMD_DISP_ON, NULL, 0); // SEG/COM will be ON after 100ms after sending DISP_ON command vTaskDelay(pdMS_TO_TICKS(100)); return ESP_OK; @@ -157,17 +157,17 @@ static esp_err_t panel_ssd1306_draw_bitmap(esp_lcd_panel_t *panel, int x_start, uint8_t page_start = y_start / 8; uint8_t page_end = (y_end - 1) / 8; // define an area of frame memory where MCU can access - esp_lcd_panel_io_tx_param(io, SSD1306_CMD_SET_COLUMN_RANGE, 8, (uint8_t[]) { + esp_lcd_panel_io_tx_param(io, SSD1306_CMD_SET_COLUMN_RANGE, (uint8_t[]) { (x_start & 0x7F), ((x_end - 1) & 0x7F), }, 2); - esp_lcd_panel_io_tx_param(io, SSD1306_CMD_SET_PAGE_RANGE, 8, (uint8_t[]) { + esp_lcd_panel_io_tx_param(io, SSD1306_CMD_SET_PAGE_RANGE, (uint8_t[]) { (page_start & 0x07), (page_end & 0x07), }, 2); // transfer frame buffer size_t len = (y_end - y_start) * (x_end - x_start) * ssd1306->bits_per_pixel / 8; - esp_lcd_panel_io_tx_color(io, 0, 0, color_data, len); + esp_lcd_panel_io_tx_color(io, 0, color_data, len); return ESP_OK; } @@ -182,7 +182,7 @@ static esp_err_t panel_ssd1306_invert_color(esp_lcd_panel_t *panel, bool invert_ } else { command = SSD1306_CMD_INVERT_OFF; } - esp_lcd_panel_io_tx_param(io, command, 8, NULL, 0); + esp_lcd_panel_io_tx_param(io, command, NULL, 0); return ESP_OK; } @@ -197,13 +197,13 @@ static esp_err_t panel_ssd1306_mirror(esp_lcd_panel_t *panel, bool mirror_x, boo } else { command = SSD1306_CMD_MIRROR_X_OFF; } - esp_lcd_panel_io_tx_param(io, command, 8, NULL, 0); + esp_lcd_panel_io_tx_param(io, command, NULL, 0); if (mirror_y) { command = SSD1306_CMD_MIRROR_Y_ON; } else { command = SSD1306_CMD_MIRROR_X_OFF; } - esp_lcd_panel_io_tx_param(io, command, 8, NULL, 0); + esp_lcd_panel_io_tx_param(io, command, NULL, 0); return ESP_OK; } @@ -230,6 +230,6 @@ static esp_err_t panel_ssd1306_disp_off(esp_lcd_panel_t *panel, bool off) } else { command = SSD1306_CMD_DISP_ON; } - esp_lcd_panel_io_tx_param(io, command, 8, NULL, 0); + esp_lcd_panel_io_tx_param(io, command, NULL, 0); return ESP_OK; } diff --git a/components/esp_lcd/src/esp_lcd_panel_st7789.c b/components/esp_lcd/src/esp_lcd_panel_st7789.c index 1bddafebfd..e182f969c8 100644 --- a/components/esp_lcd/src/esp_lcd_panel_st7789.c +++ b/components/esp_lcd/src/esp_lcd_panel_st7789.c @@ -82,6 +82,7 @@ esp_err_t esp_lcd_new_panel_st7789(const esp_lcd_panel_io_handle_t io, const esp ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported pixel width"); break; } + st7789->io = io; st7789->bits_per_pixel = panel_dev_config->bits_per_pixel; st7789->reset_gpio_num = panel_dev_config->reset_gpio_num; @@ -134,8 +135,8 @@ static esp_err_t panel_st7789_reset(esp_lcd_panel_t *panel) gpio_set_level(st7789->reset_gpio_num, !st7789->reset_level); vTaskDelay(pdMS_TO_TICKS(10)); } else { // perform software reset - esp_lcd_panel_io_tx_param(io, LCD_CMD_SWRESET, 8, NULL, 0); - vTaskDelay(pdMS_TO_TICKS(10)); // spec, wait at least 5m before sending new command + esp_lcd_panel_io_tx_param(io, LCD_CMD_SWRESET, NULL, 0); + vTaskDelay(pdMS_TO_TICKS(20)); // spec, wait at least 5m before sending new command } return ESP_OK; @@ -146,16 +147,16 @@ static esp_err_t panel_st7789_init(esp_lcd_panel_t *panel) st7789_panel_t *st7789 = __containerof(panel, st7789_panel_t, base); esp_lcd_panel_io_handle_t io = st7789->io; // LCD goes into sleep mode and display will be turned off after power on reset, exit sleep mode first - esp_lcd_panel_io_tx_param(io, LCD_CMD_SLPOUT, 8, NULL, 0); + esp_lcd_panel_io_tx_param(io, LCD_CMD_SLPOUT, NULL, 0); vTaskDelay(pdMS_TO_TICKS(100)); - esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, 8, (uint8_t[]) { - 0 + esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]) { + st7789->madctl_val, }, 1); - esp_lcd_panel_io_tx_param(io, LCD_CMD_COLMOD, 8, (uint8_t[]) { + esp_lcd_panel_io_tx_param(io, LCD_CMD_COLMOD, (uint8_t[]) { st7789->colmod_cal, }, 1); // turn on display - esp_lcd_panel_io_tx_param(io, LCD_CMD_DISPON, 8, NULL, 0); + esp_lcd_panel_io_tx_param(io, LCD_CMD_DISPON, NULL, 0); return ESP_OK; } @@ -172,13 +173,13 @@ static esp_err_t panel_st7789_draw_bitmap(esp_lcd_panel_t *panel, int x_start, i y_end += st7789->y_gap; // define an area of frame memory where MCU can access - esp_lcd_panel_io_tx_param(io, LCD_CMD_CASET, 8, (uint8_t[]) { + esp_lcd_panel_io_tx_param(io, LCD_CMD_CASET, (uint8_t[]) { (x_start >> 8) & 0xFF, x_start & 0xFF, ((x_end - 1) >> 8) & 0xFF, (x_end - 1) & 0xFF, }, 4); - esp_lcd_panel_io_tx_param(io, LCD_CMD_RASET, 8, (uint8_t[]) { + esp_lcd_panel_io_tx_param(io, LCD_CMD_RASET, (uint8_t[]) { (y_start >> 8) & 0xFF, y_start & 0xFF, ((y_end - 1) >> 8) & 0xFF, @@ -186,7 +187,7 @@ static esp_err_t panel_st7789_draw_bitmap(esp_lcd_panel_t *panel, int x_start, i }, 4); // transfer frame buffer size_t len = (x_end - x_start) * (y_end - y_start) * st7789->bits_per_pixel / 8; - esp_lcd_panel_io_tx_color(io, LCD_CMD_RAMWR, 8, color_data, len); + esp_lcd_panel_io_tx_color(io, LCD_CMD_RAMWR, color_data, len); return ESP_OK; } @@ -201,7 +202,7 @@ static esp_err_t panel_st7789_invert_color(esp_lcd_panel_t *panel, bool invert_c } else { command = LCD_CMD_INVOFF; } - esp_lcd_panel_io_tx_param(io, command, 8, NULL, 0); + esp_lcd_panel_io_tx_param(io, command, NULL, 0); return ESP_OK; } @@ -219,7 +220,7 @@ static esp_err_t panel_st7789_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool } else { st7789->madctl_val &= ~LCD_CMD_MY_BIT; } - esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, 8, (uint8_t[]) { + esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]) { st7789->madctl_val }, 1); return ESP_OK; @@ -234,7 +235,7 @@ static esp_err_t panel_st7789_swap_xy(esp_lcd_panel_t *panel, bool swap_axes) } else { st7789->madctl_val &= ~LCD_CMD_MV_BIT; } - esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, 8, (uint8_t[]) { + esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]) { st7789->madctl_val }, 1); return ESP_OK; @@ -258,6 +259,6 @@ static esp_err_t panel_st7789_disp_off(esp_lcd_panel_t *panel, bool off) } else { command = LCD_CMD_DISPON; } - esp_lcd_panel_io_tx_param(io, command, 8, NULL, 0); + esp_lcd_panel_io_tx_param(io, command, NULL, 0); return ESP_OK; } diff --git a/components/esp_lcd/src/esp_lcd_rgb_panel.c b/components/esp_lcd/src/esp_lcd_rgb_panel.c index b62daf9481..3145ec5afe 100644 --- a/components/esp_lcd/src/esp_lcd_rgb_panel.c +++ b/components/esp_lcd/src/esp_lcd_rgb_panel.c @@ -18,11 +18,13 @@ #include "esp_check.h" #include "esp_intr_alloc.h" #include "esp_heap_caps.h" +#include "esp_pm.h" #include "esp_lcd_panel_interface.h" #include "esp_lcd_panel_rgb.h" #include "esp_lcd_panel_ops.h" #include "esp_rom_gpio.h" #include "soc/soc_caps.h" +#include "soc/rtc.h" // for querying XTAL clock #include "hal/dma_types.h" #include "hal/gpio_hal.h" #include "esp_private/gdma.h" @@ -53,6 +55,7 @@ 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_off(esp_lcd_panel_t *panel, bool off); +static esp_err_t lcd_rgb_panel_select_periph_clock(esp_rgb_panel_t *panel, lcd_clock_source_t clk_src); static esp_err_t lcd_rgb_panel_create_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 IRAM_ATTR void lcd_default_isr_handler(void *args); @@ -64,6 +67,7 @@ struct esp_rgb_panel_t { size_t data_width; // Number of data lines (e.g. for RGB565, the data width is 16) int disp_gpio_num; // Display control GPIO, which is used to perform action like "disp_off" 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 uint8_t *fb; // Frame buffer size_t fb_size; // Size of frame buffer @@ -91,8 +95,8 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf { esp_err_t ret = ESP_OK; esp_rgb_panel_t *rgb_panel = NULL; - ESP_GOTO_ON_FALSE(rgb_panel_config && ret_panel, ESP_ERR_INVALID_ARG, err_arg, TAG, "invalid parameter"); - ESP_GOTO_ON_FALSE(rgb_panel_config->data_width == 16, ESP_ERR_NOT_SUPPORTED, err_arg, TAG, + ESP_GOTO_ON_FALSE(rgb_panel_config && ret_panel, ESP_ERR_INVALID_ARG, err, TAG, "invalid parameter"); + ESP_GOTO_ON_FALSE(rgb_panel_config->data_width == 16, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported data width %d", rgb_panel_config->data_width); // calculate the number of DMA descriptors size_t fb_size = rgb_panel_config->timings.h_res * rgb_panel_config->timings.v_res * rgb_panel_config->data_width / 8; @@ -102,8 +106,15 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf } // 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), MALLOC_CAP_DMA); - ESP_GOTO_ON_FALSE(rgb_panel, ESP_ERR_NO_MEM, no_mem_panel, TAG, "no mem for rgb panel"); + ESP_GOTO_ON_FALSE(rgb_panel, ESP_ERR_NO_MEM, err, TAG, "no mem for rgb panel"); rgb_panel->num_dma_nodes = num_dma_nodes; + 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"); + rgb_panel->panel_id = panel_id; + // enable APB to access LCD registers + periph_module_enable(lcd_periph_signals.panels[panel_id].module); // alloc frame buffer bool alloc_from_psram = false; // fb_in_psram is only an option, if there's no PSRAM on board, we still alloc from SRAM @@ -117,38 +128,35 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf if (alloc_from_psram) { rgb_panel->fb = heap_caps_calloc(1, fb_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); } else { - rgb_panel->fb = heap_caps_calloc(1, fb_size, MALLOC_CAP_INTERNAL); + rgb_panel->fb = heap_caps_calloc(1, fb_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); } - ESP_GOTO_ON_FALSE(rgb_panel->fb, ESP_ERR_NO_MEM, no_mem_fb, TAG, "no mem for frame buffer"); + ESP_GOTO_ON_FALSE(rgb_panel->fb, ESP_ERR_NO_MEM, err, TAG, "no mem for frame buffer"); rgb_panel->fb_size = fb_size; rgb_panel->flags.fb_in_psram = alloc_from_psram; // semaphore indicates new frame trans done rgb_panel->done_sem = xSemaphoreCreateBinary(); - ESP_GOTO_ON_FALSE(rgb_panel->done_sem, ESP_ERR_NO_MEM, no_mem_sem, TAG, "create done sem failed"); + ESP_GOTO_ON_FALSE(rgb_panel->done_sem, ESP_ERR_NO_MEM, err, TAG, "create done sem failed"); xSemaphoreGive(rgb_panel->done_sem); // initialize the semaphore count to 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, no_slot, TAG, "no free rgb panel slot"); - rgb_panel->panel_id = panel_id; - // enable APB to access LCD registers - periph_module_enable(lcd_periph_signals.panels[panel_id].module); // initialize HAL layer, so we can call LL APIs later lcd_hal_init(&rgb_panel->hal, panel_id); + // set peripheral clock resolution + ret = lcd_rgb_panel_select_periph_clock(rgb_panel, rgb_panel_config->clk_src); + ESP_GOTO_ON_ERROR(ret, err, TAG, "select periph clock failed"); // install interrupt service, (LCD peripheral shares the interrupt source with Camera by different mask) int isr_flags = ESP_INTR_FLAG_SHARED; ret = esp_intr_alloc_intrstatus(lcd_periph_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); - ESP_GOTO_ON_ERROR(ret, no_int, TAG, "install interrupt failed"); + 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.relax_on_idle; ret = lcd_rgb_panel_create_trans_link(rgb_panel); - ESP_GOTO_ON_ERROR(ret, no_dma, TAG, "install DMA failed"); + ESP_GOTO_ON_ERROR(ret, err, TAG, "install DMA failed"); // configure GPIO ret = lcd_rgb_panel_configure_gpio(rgb_panel, rgb_panel_config); - ESP_GOTO_ON_ERROR(ret, no_gpio, TAG, "configure GPIO failed"); + ESP_GOTO_ON_ERROR(ret, err, TAG, "configure GPIO failed"); // fill other rgb panel runtime parameters memcpy(rgb_panel->data_gpio_nums, rgb_panel_config->data_gpio_nums, SOC_LCD_RGB_DATA_WIDTH); rgb_panel->timings = rgb_panel_config->timings; @@ -172,22 +180,31 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf ESP_LOGD(TAG, "new rgb panel(%d) @%p, fb_size=%zu", rgb_panel->panel_id, rgb_panel, rgb_panel->fb_size); return ESP_OK; -no_gpio: - gdma_disconnect(rgb_panel->dma_chan); - gdma_del_channel(rgb_panel->dma_chan); -no_dma: - esp_intr_free(rgb_panel->intr); -no_int: - periph_module_disable(lcd_periph_signals.panels[rgb_panel->panel_id].module); - lcd_com_remove_device(LCD_COM_DEVICE_TYPE_RGB, rgb_panel->panel_id); -no_slot: - vSemaphoreDelete(rgb_panel->done_sem); -no_mem_sem: - free(rgb_panel->fb); -no_mem_fb: - free(rgb_panel); -no_mem_panel: -err_arg: +err: + if (rgb_panel) { + if (rgb_panel->panel_id >= 0) { + periph_module_disable(lcd_periph_signals.panels[rgb_panel->panel_id].module); + lcd_com_remove_device(LCD_COM_DEVICE_TYPE_RGB, rgb_panel->panel_id); + } + if (rgb_panel->fb) { + free(rgb_panel->fb); + } + if (rgb_panel->done_sem) { + vSemaphoreDelete(rgb_panel->done_sem); + } + if (rgb_panel->dma_chan) { + gdma_disconnect(rgb_panel->dma_chan); + gdma_del_channel(rgb_panel->dma_chan); + } + if (rgb_panel->intr) { + esp_intr_free(rgb_panel->intr); + } + if (rgb_panel->pm_lock) { + esp_pm_lock_release(rgb_panel->pm_lock); + esp_pm_lock_delete(rgb_panel->pm_lock); + } + free(rgb_panel); + } return ret; } @@ -203,6 +220,10 @@ static esp_err_t rgb_panel_del(esp_lcd_panel_t *panel) lcd_com_remove_device(LCD_COM_DEVICE_TYPE_RGB, rgb_panel->panel_id); vSemaphoreDelete(rgb_panel->done_sem); free(rgb_panel->fb); + if (rgb_panel->pm_lock) { + esp_pm_lock_release(rgb_panel->pm_lock); + esp_pm_lock_delete(rgb_panel->pm_lock); + } free(rgb_panel); ESP_LOGD(TAG, "del rgb panel(%d)", panel_id); return ESP_OK; @@ -222,8 +243,6 @@ static esp_err_t rgb_panel_init(esp_lcd_panel_t *panel) esp_rgb_panel_t *rgb_panel = __containerof(panel, esp_rgb_panel_t, base); // configure clock lcd_ll_enable_clock(rgb_panel->hal.dev, true); - // set peripheral clock resolution - rgb_panel->resolution_hz = lcd_com_select_periph_clock(&rgb_panel->hal); // set PCLK frequency uint32_t pclk_prescale = rgb_panel->resolution_hz / rgb_panel->timings.pclk_hz; ESP_GOTO_ON_FALSE(pclk_prescale <= LCD_LL_CLOCK_PRESCALE_MAX, ESP_ERR_NOT_SUPPORTED, err, TAG, @@ -403,6 +422,31 @@ static esp_err_t lcd_rgb_panel_configure_gpio(esp_rgb_panel_t *panel, const esp_ return ESP_OK; } +static esp_err_t lcd_rgb_panel_select_periph_clock(esp_rgb_panel_t *panel, lcd_clock_source_t clk_src) +{ + esp_err_t ret = ESP_OK; + lcd_ll_set_group_clock_src(panel->hal.dev, clk_src, LCD_PERIPH_CLOCK_PRE_SCALE, 1, 0); + switch (clk_src) { + case LCD_CLK_SRC_PLL160M: + panel->resolution_hz = 160000000 / LCD_PERIPH_CLOCK_PRE_SCALE; +#if CONFIG_PM_ENABLE + ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "rgb_panel", &panel->pm_lock); + ESP_RETURN_ON_ERROR(ret, TAG, "create ESP_PM_APB_FREQ_MAX lock failed"); + // hold the lock during the whole lifecycle of RGB panel + esp_pm_lock_acquire(panel->pm_lock); + ESP_LOGD(TAG, "installed ESP_PM_APB_FREQ_MAX lock and hold the lock during the whole panel lifecycle"); +#endif + break; + case LCD_CLK_SRC_XTAL: + panel->resolution_hz = rtc_clk_xtal_freq_get() * 1000000 / LCD_PERIPH_CLOCK_PRE_SCALE; + break; + default: + ESP_RETURN_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, TAG, "unsupported clock source: %d", clk_src); + break; + } + return ret; +} + static esp_err_t lcd_rgb_panel_create_trans_link(esp_rgb_panel_t *panel) { esp_err_t ret = ESP_OK; diff --git a/components/esp_lcd/test/test_i2c_lcd_panel.c b/components/esp_lcd/test/test_i2c_lcd_panel.c index 188d6797ac..204b7eeae4 100644 --- a/components/esp_lcd/test/test_i2c_lcd_panel.c +++ b/components/esp_lcd/test/test_i2c_lcd_panel.c @@ -46,6 +46,8 @@ TEST_CASE("lcd panel with i2c interface (ssd1306)", "[lcd]") .dev_addr = TEST_I2C_DEV_ADDR, .control_phase_bytes = 1, // According to SSD1306 datasheet .dc_bit_offset = 6, // According to SSD1306 datasheet + .lcd_cmd_bits = 8, // According to SSD1306 datasheet + .lcd_param_bits = 8, // According to SSD1306 datasheet }; TEST_ESP_OK(esp_lcd_new_panel_io_i2c((esp_lcd_i2c_bus_handle_t)TEST_I2C_HOST_ID, &io_config, &io_handle)); @@ -104,6 +106,8 @@ TEST_CASE("lvgl gui with i2c interface (ssd1306)", "[lcd][lvgl][ignore]") .dev_addr = TEST_I2C_DEV_ADDR, .control_phase_bytes = 1, // According to SSD1306 datasheet .dc_bit_offset = 6, // According to SSD1306 datasheet + .lcd_cmd_bits = 8, // According to SSD1306 datasheet + .lcd_param_bits = 8, // According to SSD1306 datasheet .on_color_trans_done = notify_lvgl_ready_to_flush, .user_data = &disp, }; diff --git a/components/esp_lcd/test/test_i80_board.h b/components/esp_lcd/test/test_i80_board.h new file mode 100644 index 0000000000..088adad2f8 --- /dev/null +++ b/components/esp_lcd/test/test_i80_board.h @@ -0,0 +1,72 @@ +#include "sdkconfig.h" + +#define TEST_LCD_H_RES (240) +#define TEST_LCD_V_RES (280) + +#if CONFIG_IDF_TARGET_ESP32S3 +#define TEST_LCD_BK_LIGHT_GPIO (1) +#define TEST_LCD_RST_GPIO (2) +#define TEST_LCD_CS_GPIO (3) +#define TEST_LCD_DC_GPIO (4) +#define TEST_LCD_PCLK_GPIO (5) +#define TEST_LCD_DATA0_GPIO (6) +#define TEST_LCD_DATA1_GPIO (7) +#define TEST_LCD_DATA2_GPIO (8) +#define TEST_LCD_DATA3_GPIO (9) +#define TEST_LCD_DATA4_GPIO (10) +#define TEST_LCD_DATA5_GPIO (11) +#define TEST_LCD_DATA6_GPIO (12) +#define TEST_LCD_DATA7_GPIO (13) +#define TEST_LCD_DATA8_GPIO (14) +#define TEST_LCD_DATA9_GPIO (15) +#define TEST_LCD_DATA10_GPIO (16) +#define TEST_LCD_DATA11_GPIO (17) +#define TEST_LCD_DATA12_GPIO (18) +#define TEST_LCD_DATA13_GPIO (19) +#define TEST_LCD_DATA14_GPIO (20) +#define TEST_LCD_DATA15_GPIO (21) +#elif CONFIG_IDF_TARGET_ESP32S2 +#define TEST_LCD_BK_LIGHT_GPIO (0) +#define TEST_LCD_RST_GPIO (18) +#define TEST_LCD_CS_GPIO (19) +#define TEST_LCD_DC_GPIO (38) +#define TEST_LCD_PCLK_GPIO (33) +#define TEST_LCD_DATA0_GPIO (1) +#define TEST_LCD_DATA1_GPIO (10) +#define TEST_LCD_DATA2_GPIO (2) +#define TEST_LCD_DATA3_GPIO (11) +#define TEST_LCD_DATA4_GPIO (3) +#define TEST_LCD_DATA5_GPIO (12) +#define TEST_LCD_DATA6_GPIO (4) +#define TEST_LCD_DATA7_GPIO (13) +#define TEST_LCD_DATA8_GPIO (5) +#define TEST_LCD_DATA9_GPIO (14) +#define TEST_LCD_DATA10_GPIO (6) +#define TEST_LCD_DATA11_GPIO (15) +#define TEST_LCD_DATA12_GPIO (7) +#define TEST_LCD_DATA13_GPIO (16) +#define TEST_LCD_DATA14_GPIO (8) +#define TEST_LCD_DATA15_GPIO (17) +#elif CONFIG_IDF_TARGET_ESP32 +#define TEST_LCD_BK_LIGHT_GPIO (2) +#define TEST_LCD_RST_GPIO (-1) +#define TEST_LCD_CS_GPIO (4) +#define TEST_LCD_DC_GPIO (5) +#define TEST_LCD_PCLK_GPIO (18) +#define TEST_LCD_DATA0_GPIO (19) +#define TEST_LCD_DATA1_GPIO (21) +#define TEST_LCD_DATA2_GPIO (0) +#define TEST_LCD_DATA3_GPIO (22) +#define TEST_LCD_DATA4_GPIO (23) +#define TEST_LCD_DATA5_GPIO (33) +#define TEST_LCD_DATA6_GPIO (32) +#define TEST_LCD_DATA7_GPIO (27) +#define TEST_LCD_DATA8_GPIO (12) +#define TEST_LCD_DATA9_GPIO (13) +#define TEST_LCD_DATA10_GPIO (14) +#define TEST_LCD_DATA11_GPIO (15) +#define TEST_LCD_DATA12_GPIO (26) +#define TEST_LCD_DATA13_GPIO (25) +#define TEST_LCD_DATA14_GPIO (16) +#define TEST_LCD_DATA15_GPIO (17) +#endif diff --git a/components/esp_lcd/test/test_i80_lcd_panel.c b/components/esp_lcd/test/test_i80_lcd_panel.c index ea7d8d531f..8474f82729 100644 --- a/components/esp_lcd/test/test_i80_lcd_panel.c +++ b/components/esp_lcd/test/test_i80_lcd_panel.c @@ -7,74 +7,9 @@ #include "esp_lcd_panel_ops.h" #include "soc/soc_caps.h" #include "driver/gpio.h" +#include "test_i80_board.h" -#define TEST_LCD_H_RES (240) -#define TEST_LCD_V_RES (280) -#define TEST_LCD_BK_LIGHT_GPIO (1) -#define TEST_LCD_RST_GPIO (2) -#define TEST_LCD_CS_GPIO (4) -#define TEST_LCD_DC_GPIO (5) -#define TEST_LCD_PCLK_GPIO (6) -#define TEST_LCD_DATA0_GPIO (33) -#define TEST_LCD_DATA1_GPIO (34) -#define TEST_LCD_DATA2_GPIO (35) -#define TEST_LCD_DATA3_GPIO (36) -#define TEST_LCD_DATA4_GPIO (37) -#define TEST_LCD_DATA5_GPIO (38) -#define TEST_LCD_DATA6_GPIO (39) -#define TEST_LCD_DATA7_GPIO (40) -#define TEST_LCD_DATA8_GPIO (41) -#define TEST_LCD_DATA9_GPIO (42) -#define TEST_LCD_DATA10_GPIO (15) -#define TEST_LCD_DATA11_GPIO (16) -#define TEST_LCD_DATA12_GPIO (17) -#define TEST_LCD_DATA13_GPIO (18) -#define TEST_LCD_DATA14_GPIO (19) -#define TEST_LCD_DATA15_GPIO (20) - -#if SOC_LCD_I80_SUPPORTED -TEST_CASE("lcd i80 bus and device allocation", "[lcd]") -{ - esp_lcd_i80_bus_handle_t i80_buses[SOC_LCD_I80_BUSES] = {}; - esp_lcd_i80_bus_config_t bus_config = { - .dc_gpio_num = TEST_LCD_DC_GPIO, - .wr_gpio_num = TEST_LCD_PCLK_GPIO, - .data_gpio_nums = { - TEST_LCD_DATA0_GPIO, - TEST_LCD_DATA1_GPIO, - TEST_LCD_DATA2_GPIO, - TEST_LCD_DATA3_GPIO, - TEST_LCD_DATA4_GPIO, - TEST_LCD_DATA5_GPIO, - TEST_LCD_DATA6_GPIO, - TEST_LCD_DATA7_GPIO, - }, - .data_width = 8, - .max_transfer_bytes = TEST_LCD_H_RES * 40 * sizeof(uint16_t) - }; - for (int i = 0; i < SOC_LCD_I80_BUSES; i++) { - TEST_ESP_OK(esp_lcd_new_i80_bus(&bus_config, &i80_buses[i])); - } - TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, esp_lcd_new_i80_bus(&bus_config, &i80_buses[0])); - esp_lcd_panel_io_handle_t io_handles[10] = {}; - esp_lcd_panel_io_i80_config_t io_config = { - .cs_gpio_num = TEST_LCD_CS_GPIO, - .pclk_hz = 5000000, - .trans_queue_depth = 4, - }; - for (int i = 0; i < 10; i++) { - TEST_ESP_OK(esp_lcd_new_panel_io_i80(i80_buses[0], &io_config, &io_handles[i])); - } - // can't delete bus handle before we delete all devices - TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, esp_lcd_del_i80_bus(i80_buses[0])); - for (int i = 0; i < 10; i++) { - TEST_ESP_OK(esp_lcd_panel_io_del(io_handles[i])); - } - for (int i = 0; i < SOC_LCD_I80_BUSES; i++) { - TEST_ESP_OK(esp_lcd_del_i80_bus(i80_buses[i])); - } -} - +#if SOC_LCDCAM_SUPPORTED TEST_CASE("lcd i80 device swap color bytes", "[lcd]") { esp_lcd_i80_bus_handle_t i80_bus = NULL; @@ -91,7 +26,7 @@ TEST_CASE("lcd i80 device swap color bytes", "[lcd]") TEST_LCD_DATA6_GPIO, TEST_LCD_DATA7_GPIO, }, - .data_width = 8, + .bus_width = 8, .max_transfer_bytes = 20, }; TEST_ESP_OK(esp_lcd_new_i80_bus(&bus_config, &i80_bus)); @@ -107,6 +42,8 @@ TEST_CASE("lcd i80 device swap color bytes", "[lcd]") .dc_dummy_level = 0, .dc_data_level = 1, }, + .lcd_cmd_bits = 8, + .lcd_param_bits = 8, }; io_config.flags.reverse_color_bits = 0; @@ -123,10 +60,10 @@ TEST_CASE("lcd i80 device swap color bytes", "[lcd]") TEST_ESP_OK(esp_lcd_new_panel_io_i80(i80_bus, &io_config, &io_handles[3])); for (int i = 0; i < 4; i++) { - esp_lcd_panel_io_tx_param(io_handles[i], 0xA5, 8, (uint8_t[]) { + esp_lcd_panel_io_tx_param(io_handles[i], 0xA5, (uint8_t[]) { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }, 6); - esp_lcd_panel_io_tx_color(io_handles[i], 0x5A, 8, (uint8_t[]) { + esp_lcd_panel_io_tx_color(io_handles[i], 0x5A, (uint8_t[]) { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }, 6); TEST_ESP_OK(esp_lcd_panel_io_del(io_handles[i])); @@ -151,7 +88,7 @@ TEST_CASE("lcd i80 device clock mode", "[lcd]") TEST_LCD_DATA6_GPIO, TEST_LCD_DATA7_GPIO, }, - .data_width = 8, + .bus_width = 8, .max_transfer_bytes = 20, }; TEST_ESP_OK(esp_lcd_new_i80_bus(&bus_config, &i80_bus)); @@ -167,6 +104,8 @@ TEST_CASE("lcd i80 device clock mode", "[lcd]") .dc_dummy_level = 0, .dc_data_level = 1, }, + .lcd_cmd_bits = 8, + .lcd_param_bits = 8, }; io_config.flags.pclk_idle_low = 0; @@ -183,15 +122,212 @@ TEST_CASE("lcd i80 device clock mode", "[lcd]") TEST_ESP_OK(esp_lcd_new_panel_io_i80(i80_bus, &io_config, &io_handles[3])); for (int i = 0; i < 4; i++) { - esp_lcd_panel_io_tx_param(io_handles[i], 0xA5, 8, (uint8_t[]) { + esp_lcd_panel_io_tx_param(io_handles[i], 0xA5, (uint8_t[]) { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }, 6); TEST_ESP_OK(esp_lcd_panel_io_del(io_handles[i])); } TEST_ESP_OK(esp_lcd_del_i80_bus(i80_bus)); } +#endif // SOC_LCDCAM_SUPPORTED -TEST_CASE("lcd panel with i80 interface (st7789)", "[lcd]") +#if SOC_LCD_I80_SUPPORTED +TEST_CASE("lcd i80 bus and device allocation", "[lcd]") +{ + esp_lcd_i80_bus_handle_t i80_buses[SOC_LCD_I80_BUSES] = {}; + esp_lcd_i80_bus_config_t bus_config = { + .dc_gpio_num = TEST_LCD_DC_GPIO, + .wr_gpio_num = TEST_LCD_PCLK_GPIO, + .data_gpio_nums = { + TEST_LCD_DATA0_GPIO, + TEST_LCD_DATA1_GPIO, + TEST_LCD_DATA2_GPIO, + TEST_LCD_DATA3_GPIO, + TEST_LCD_DATA4_GPIO, + TEST_LCD_DATA5_GPIO, + TEST_LCD_DATA6_GPIO, + TEST_LCD_DATA7_GPIO, + }, + .bus_width = 8, + .max_transfer_bytes = TEST_LCD_H_RES * 40 * sizeof(uint16_t) + }; + for (int i = 0; i < SOC_LCD_I80_BUSES; i++) { + TEST_ESP_OK(esp_lcd_new_i80_bus(&bus_config, &i80_buses[i])); + } + TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, esp_lcd_new_i80_bus(&bus_config, &i80_buses[0])); + esp_lcd_panel_io_handle_t io_handles[10] = {}; + esp_lcd_panel_io_i80_config_t io_config = { + .cs_gpio_num = TEST_LCD_CS_GPIO, + .pclk_hz = 5000000, + .trans_queue_depth = 4, + .lcd_cmd_bits = 8, + .lcd_param_bits = 8, + }; + for (int i = 0; i < 10; i++) { + TEST_ESP_OK(esp_lcd_new_panel_io_i80(i80_buses[0], &io_config, &io_handles[i])); + } + // can't delete bus handle before we delete all devices + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, esp_lcd_del_i80_bus(i80_buses[0])); + for (int i = 0; i < 10; i++) { + TEST_ESP_OK(esp_lcd_panel_io_del(io_handles[i])); + } + for (int i = 0; i < SOC_LCD_I80_BUSES; i++) { + TEST_ESP_OK(esp_lcd_del_i80_bus(i80_buses[i])); + } +} + +TEST_CASE("lcd i80 bus exclusively owned by one device", "[lcd]") +{ + esp_lcd_i80_bus_handle_t i80_bus_handle = NULL; + esp_lcd_i80_bus_config_t bus_config = { + .dc_gpio_num = TEST_LCD_DC_GPIO, + .wr_gpio_num = TEST_LCD_PCLK_GPIO, + .data_gpio_nums = { + TEST_LCD_DATA0_GPIO, + TEST_LCD_DATA1_GPIO, + TEST_LCD_DATA2_GPIO, + TEST_LCD_DATA3_GPIO, + TEST_LCD_DATA4_GPIO, + TEST_LCD_DATA5_GPIO, + TEST_LCD_DATA6_GPIO, + TEST_LCD_DATA7_GPIO, + }, + .bus_width = 8, + .max_transfer_bytes = TEST_LCD_H_RES * 40 * sizeof(uint16_t) + }; + TEST_ESP_OK(esp_lcd_new_i80_bus(&bus_config, &i80_bus_handle)); + esp_lcd_panel_io_handle_t io_handle = NULL; + esp_lcd_panel_io_i80_config_t io_config = { + .cs_gpio_num = -1, // own the bus exclusively + .pclk_hz = 5000000, + .trans_queue_depth = 4, + .lcd_cmd_bits = 8, + .lcd_param_bits = 8, + }; + TEST_ESP_OK(esp_lcd_new_panel_io_i80(i80_bus_handle, &io_config, &io_handle)); + io_config.cs_gpio_num = 0; + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, esp_lcd_new_panel_io_i80(i80_bus_handle, &io_config, &io_handle)); + TEST_ESP_OK(esp_lcd_panel_io_del(io_handle)); + TEST_ESP_OK(esp_lcd_del_i80_bus(i80_bus_handle)); +} + +TEST_CASE("lcd panel i80 io test", "[lcd]") +{ + esp_lcd_i80_bus_handle_t i80_bus = NULL; + esp_lcd_i80_bus_config_t bus_config = { + .dc_gpio_num = TEST_LCD_DC_GPIO, + .wr_gpio_num = TEST_LCD_PCLK_GPIO, + .data_gpio_nums = { + TEST_LCD_DATA0_GPIO, + TEST_LCD_DATA1_GPIO, + TEST_LCD_DATA2_GPIO, + TEST_LCD_DATA3_GPIO, + TEST_LCD_DATA4_GPIO, + TEST_LCD_DATA5_GPIO, + TEST_LCD_DATA6_GPIO, + TEST_LCD_DATA7_GPIO, + TEST_LCD_DATA8_GPIO, + TEST_LCD_DATA9_GPIO, + TEST_LCD_DATA10_GPIO, + TEST_LCD_DATA11_GPIO, + TEST_LCD_DATA12_GPIO, + TEST_LCD_DATA13_GPIO, + TEST_LCD_DATA14_GPIO, + TEST_LCD_DATA15_GPIO, + }, + .bus_width = 16, + .max_transfer_bytes = 100, + }; + esp_lcd_panel_io_handle_t io_handle = NULL; + esp_lcd_panel_io_i80_config_t io_config = { + .cs_gpio_num = TEST_LCD_CS_GPIO, + .pclk_hz = 8000000, // 8MHz + .trans_queue_depth = 10, + .dc_levels = { + .dc_idle_level = 0, + .dc_cmd_level = 0, + .dc_dummy_level = 0, + .dc_data_level = 1, + }, + }; + esp_lcd_panel_handle_t panel_handle = NULL; + esp_lcd_panel_dev_config_t panel_config = { + .reset_gpio_num = TEST_LCD_RST_GPIO, + .color_space = ESP_LCD_COLOR_SPACE_RGB, + .bits_per_pixel = 16, + }; + +// On esp32, GPIO16 and GPIO17 are connected to PSRAM, and we don't have other spare GPIOs can be used in the test +// so we skip the 16bit test on esp32 when PSRAM is enabled +#if !CONFIG_ESP32_SPIRAM_SUPPORT + printf("testing bus-width=16bit, cmd/param bit-width=8bit\r\n"); + bus_config.bus_width = 16; + TEST_ESP_OK(esp_lcd_new_i80_bus(&bus_config, &i80_bus)); + io_config.lcd_cmd_bits = 8; + io_config.lcd_param_bits = 8; + TEST_ESP_OK(esp_lcd_new_panel_io_i80(i80_bus, &io_config, &io_handle)); + TEST_ESP_OK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle)); + + esp_lcd_panel_io_tx_param(io_handle, 0x1A, NULL, 0); + esp_lcd_panel_io_tx_param(io_handle, 0x1B, (uint8_t[]) { + 0x11, 0x22, 0x33 + }, 3); + esp_lcd_panel_io_tx_param(io_handle, 0x1C, NULL, 0); + TEST_ESP_OK(esp_lcd_panel_del(panel_handle)); + TEST_ESP_OK(esp_lcd_panel_io_del(io_handle)); + TEST_ESP_OK(esp_lcd_del_i80_bus(i80_bus)); + + printf("testing bus-width=16bit, cmd/param bit-width=16bit\r\n"); + bus_config.bus_width = 16; + TEST_ESP_OK(esp_lcd_new_i80_bus(&bus_config, &i80_bus)); + io_config.lcd_cmd_bits = 16; + io_config.lcd_param_bits = 16; + TEST_ESP_OK(esp_lcd_new_panel_io_i80(i80_bus, &io_config, &io_handle)); + TEST_ESP_OK(esp_lcd_new_panel_nt35510(io_handle, &panel_config, &panel_handle)); + esp_lcd_panel_io_tx_param(io_handle, 0x1A01, NULL, 0); + esp_lcd_panel_io_tx_param(io_handle, 0x1B02, (uint16_t[]) { + 0x11, 0x22, 0x33 + }, 6); + esp_lcd_panel_io_tx_param(io_handle, 0x1C03, NULL, 0); + TEST_ESP_OK(esp_lcd_panel_del(panel_handle)); + TEST_ESP_OK(esp_lcd_panel_io_del(io_handle)); + TEST_ESP_OK(esp_lcd_del_i80_bus(i80_bus)); +#endif + + printf("testing bus-width=8bit, cmd/param bit-width=8bit\r\n"); + bus_config.bus_width = 8; + TEST_ESP_OK(esp_lcd_new_i80_bus(&bus_config, &i80_bus)); + io_config.lcd_cmd_bits = 8; + io_config.lcd_param_bits = 8; + TEST_ESP_OK(esp_lcd_new_panel_io_i80(i80_bus, &io_config, &io_handle)); + TEST_ESP_OK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle)); + esp_lcd_panel_io_tx_param(io_handle, 0x1A, NULL, 0); + esp_lcd_panel_io_tx_param(io_handle, 0x1B, (uint8_t[]) { + 0x11, 0x22, 0x33 + }, 3); + esp_lcd_panel_io_tx_param(io_handle, 0x1C, NULL, 0); + TEST_ESP_OK(esp_lcd_panel_del(panel_handle)); + TEST_ESP_OK(esp_lcd_panel_io_del(io_handle)); + TEST_ESP_OK(esp_lcd_del_i80_bus(i80_bus)); + + printf("testing bus-width=8bit, cmd/param bit-width=16bit\r\n"); + bus_config.bus_width = 8; + TEST_ESP_OK(esp_lcd_new_i80_bus(&bus_config, &i80_bus)); + io_config.lcd_cmd_bits = 16; + io_config.lcd_param_bits = 16; + TEST_ESP_OK(esp_lcd_new_panel_io_i80(i80_bus, &io_config, &io_handle)); + TEST_ESP_OK(esp_lcd_new_panel_nt35510(io_handle, &panel_config, &panel_handle)); + esp_lcd_panel_io_tx_param(io_handle, 0x1A01, NULL, 0); + esp_lcd_panel_io_tx_param(io_handle, 0x1B02, (uint16_t[]) { + 0x11, 0x22, 0x33 + }, 6); + esp_lcd_panel_io_tx_param(io_handle, 0x1C03, NULL, 0); + TEST_ESP_OK(esp_lcd_panel_del(panel_handle)); + TEST_ESP_OK(esp_lcd_panel_io_del(io_handle)); + TEST_ESP_OK(esp_lcd_del_i80_bus(i80_bus)); +} + +TEST_CASE("lcd panel with i80 interface (st7789, 8bits)", "[lcd]") { #define TEST_IMG_SIZE (100 * 100 * sizeof(uint16_t)) uint8_t *img = heap_caps_malloc(TEST_IMG_SIZE, MALLOC_CAP_DMA); @@ -217,14 +353,14 @@ TEST_CASE("lcd panel with i80 interface (st7789)", "[lcd]") TEST_LCD_DATA6_GPIO, TEST_LCD_DATA7_GPIO, }, - .data_width = 8, + .bus_width = 8, .max_transfer_bytes = TEST_IMG_SIZE + 10, }; TEST_ESP_OK(esp_lcd_new_i80_bus(&bus_config, &i80_bus)); esp_lcd_panel_io_handle_t io_handle = NULL; esp_lcd_panel_io_i80_config_t io_config = { .cs_gpio_num = TEST_LCD_CS_GPIO, - .pclk_hz = 5000000, + .pclk_hz = 8000000, // 8MHz .trans_queue_depth = 10, .dc_levels = { .dc_idle_level = 0, @@ -232,6 +368,8 @@ TEST_CASE("lcd panel with i80 interface (st7789)", "[lcd]") .dc_dummy_level = 0, .dc_data_level = 1, }, + .lcd_cmd_bits = 8, + .lcd_param_bits = 8, }; TEST_ESP_OK(esp_lcd_new_panel_io_i80(i80_bus, &io_config, &io_handle)); @@ -282,7 +420,7 @@ static bool notify_lvgl_ready_to_flush(esp_lcd_panel_io_handle_t panel_io, void return false; } -TEST_CASE("lvgl gui with i80 interface (st7789)", "[lcd][lvgl][ignore]") +TEST_CASE("lvgl gui with i80 interface (st7789, 8bits)", "[lcd][lvgl][ignore]") { // initialize LVGL graphics library lv_disp_t *disp = NULL; @@ -308,14 +446,14 @@ TEST_CASE("lvgl gui with i80 interface (st7789)", "[lcd][lvgl][ignore]") TEST_LCD_DATA6_GPIO, TEST_LCD_DATA7_GPIO, }, - .data_width = 8, + .bus_width = 8, .max_transfer_bytes = TEST_LCD_H_RES * 40 * sizeof(uint16_t) }; TEST_ESP_OK(esp_lcd_new_i80_bus(&bus_config, &i80_bus)); esp_lcd_panel_io_handle_t io_handle = NULL; esp_lcd_panel_io_i80_config_t io_config = { .cs_gpio_num = TEST_LCD_CS_GPIO, - .pclk_hz = 8000000, + .pclk_hz = 10000000, // 10MHz .trans_queue_depth = 10, .dc_levels = { .dc_idle_level = 0, @@ -327,7 +465,9 @@ TEST_CASE("lvgl gui with i80 interface (st7789)", "[lcd][lvgl][ignore]") .swap_color_bytes = 1, }, .on_color_trans_done = notify_lvgl_ready_to_flush, - .user_data = &disp + .user_data = &disp, + .lcd_cmd_bits = 8, + .lcd_param_bits = 8, }; TEST_ESP_OK(esp_lcd_new_panel_io_i80(i80_bus, &io_config, &io_handle)); @@ -351,5 +491,111 @@ TEST_CASE("lvgl gui with i80 interface (st7789)", "[lcd][lvgl][ignore]") test_lvgl_task_loop(panel_handle, TEST_LCD_H_RES, TEST_LCD_V_RES, &disp); } + +#define TEST_NT35510_DATA_WIDTH (8) // change this to 16 when NT35510 is configured to 16bit in length +TEST_CASE("lvgl gui with i80 interface (nt35510, 8/16bits)", "[lcd][lvgl][ignore]") +{ + // initialize LVGL graphics library + lv_disp_t *disp = NULL; + lv_init(); + + esp_lcd_i80_bus_handle_t i80_bus = NULL; + esp_lcd_i80_bus_config_t bus_config = { + .dc_gpio_num = TEST_LCD_DC_GPIO, + .wr_gpio_num = TEST_LCD_PCLK_GPIO, + .data_gpio_nums = { + TEST_LCD_DATA0_GPIO, + TEST_LCD_DATA1_GPIO, + TEST_LCD_DATA2_GPIO, + TEST_LCD_DATA3_GPIO, + TEST_LCD_DATA4_GPIO, + TEST_LCD_DATA5_GPIO, + TEST_LCD_DATA6_GPIO, + TEST_LCD_DATA7_GPIO, + TEST_LCD_DATA8_GPIO, + TEST_LCD_DATA9_GPIO, + TEST_LCD_DATA10_GPIO, + TEST_LCD_DATA11_GPIO, + TEST_LCD_DATA12_GPIO, + TEST_LCD_DATA13_GPIO, + TEST_LCD_DATA14_GPIO, + TEST_LCD_DATA15_GPIO, + }, + .bus_width = TEST_NT35510_DATA_WIDTH, + .max_transfer_bytes = TEST_LCD_H_RES * 40 * sizeof(uint16_t) + }; + TEST_ESP_OK(esp_lcd_new_i80_bus(&bus_config, &i80_bus)); + esp_lcd_panel_io_handle_t io_handle = NULL; + esp_lcd_panel_io_i80_config_t io_config = { + .cs_gpio_num = TEST_LCD_CS_GPIO, + .pclk_hz = 10000000, // 10MHz + .trans_queue_depth = 4, + .dc_levels = { + .dc_idle_level = 0, + .dc_cmd_level = 0, + .dc_dummy_level = 0, + .dc_data_level = 1, + }, + .on_color_trans_done = notify_lvgl_ready_to_flush, + .user_data = &disp, + .lcd_cmd_bits = 16, + .lcd_param_bits = 16, + }; + TEST_ESP_OK(esp_lcd_new_panel_io_i80(i80_bus, &io_config, &io_handle)); + + esp_lcd_panel_handle_t panel_handle = NULL; + esp_lcd_panel_dev_config_t panel_config = { + .reset_gpio_num = -1, + .color_space = ESP_LCD_COLOR_SPACE_RGB, + .bits_per_pixel = 16, + }; + TEST_ESP_OK(esp_lcd_new_panel_nt35510(io_handle, &panel_config, &panel_handle)); + + esp_lcd_panel_reset(panel_handle); + esp_lcd_panel_init(panel_handle); + esp_lcd_panel_swap_xy(panel_handle, true); + esp_lcd_panel_mirror(panel_handle, true, false); + + test_lvgl_task_loop(panel_handle, TEST_LCD_H_RES, TEST_LCD_V_RES, &disp); +} #endif // CONFIG_LV_USE_USER_DATA #endif // SOC_LCD_I80_SUPPORTED + +#if SOC_I2S_LCD_I80_VARIANT +#include "driver/i2s.h" + +TEST_CASE("i80 and i2s driver coexistance", "[lcd][i2s]") +{ + esp_lcd_i80_bus_handle_t i80_bus = NULL; + esp_lcd_i80_bus_config_t bus_config = { + .dc_gpio_num = TEST_LCD_DC_GPIO, + .wr_gpio_num = TEST_LCD_PCLK_GPIO, + .data_gpio_nums = { + TEST_LCD_DATA0_GPIO, + TEST_LCD_DATA1_GPIO, + TEST_LCD_DATA2_GPIO, + TEST_LCD_DATA3_GPIO, + TEST_LCD_DATA4_GPIO, + TEST_LCD_DATA5_GPIO, + TEST_LCD_DATA6_GPIO, + TEST_LCD_DATA7_GPIO, + }, + .bus_width = 8, + .max_transfer_bytes = 20, + }; + TEST_ESP_OK(esp_lcd_new_i80_bus(&bus_config, &i80_bus)); + + i2s_config_t i2s_config = { + .mode = I2S_MODE_MASTER | I2S_MODE_TX, + .sample_rate = 36000, + .bits_per_sample = 16, + .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, + .communication_format = I2S_COMM_FORMAT_STAND_I2S, + .dma_buf_count = 6, + .dma_buf_len = 60, + }; + // I2S driver won't be installed as the same I2S port has been used by LCD + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, i2s_driver_install(0, &i2s_config, 0, NULL)); + TEST_ESP_OK(esp_lcd_del_i80_bus(i80_bus)); +} +#endif // SOC_I2S_LCD_I80_VARIANT diff --git a/components/esp_lcd/test/test_lvgl_port.c b/components/esp_lcd/test/test_lvgl_port_v7.c similarity index 100% rename from components/esp_lcd/test/test_lvgl_port.c rename to components/esp_lcd/test/test_lvgl_port_v7.c diff --git a/components/esp_lcd/test/test_rgb_panel.c b/components/esp_lcd/test/test_rgb_panel.c index 6aa1da2969..36c182ee06 100644 --- a/components/esp_lcd/test/test_rgb_panel.c +++ b/components/esp_lcd/test/test_rgb_panel.c @@ -8,27 +8,28 @@ #define TEST_LCD_H_RES (480) #define TEST_LCD_V_RES (272) -#define TEST_LCD_VSYNC_GPIO (1) -#define TEST_LCD_HSYNC_GPIO (2) -#define TEST_LCD_DE_GPIO (-1) -#define TEST_LCD_PCLK_GPIO (3) -#define TEST_LCD_DATA0_GPIO (4) // B0 -#define TEST_LCD_DATA1_GPIO (5) // B1 -#define TEST_LCD_DATA2_GPIO (6) // B2 -#define TEST_LCD_DATA3_GPIO (7) // B3 -#define TEST_LCD_DATA4_GPIO (8) // B4 -#define TEST_LCD_DATA5_GPIO (9) // G0 -#define TEST_LCD_DATA6_GPIO (10) // G1 -#define TEST_LCD_DATA7_GPIO (11) // G2 -#define TEST_LCD_DATA8_GPIO (12) // G3 -#define TEST_LCD_DATA9_GPIO (13) // G4 -#define TEST_LCD_DATA10_GPIO (14) // G5 -#define TEST_LCD_DATA11_GPIO (15) // R0 -#define TEST_LCD_DATA12_GPIO (16) // R1 -#define TEST_LCD_DATA13_GPIO (17) // R2 -#define TEST_LCD_DATA14_GPIO (18) // R3 -#define TEST_LCD_DATA15_GPIO (19) // R4 -#define TEST_LCD_DISP_EN_GPIO (-1) + +#define TEST_LCD_VSYNC_GPIO (48) +#define TEST_LCD_HSYNC_GPIO (47) +#define TEST_LCD_DE_GPIO (45) +#define TEST_LCD_PCLK_GPIO (21) +#define TEST_LCD_DATA0_GPIO (3) // B0 +#define TEST_LCD_DATA1_GPIO (4) // B1 +#define TEST_LCD_DATA2_GPIO (5) // B2 +#define TEST_LCD_DATA3_GPIO (6) // B3 +#define TEST_LCD_DATA4_GPIO (7) // B4 +#define TEST_LCD_DATA5_GPIO (8) // G0 +#define TEST_LCD_DATA6_GPIO (9) // G1 +#define TEST_LCD_DATA7_GPIO (10) // G2 +#define TEST_LCD_DATA8_GPIO (11) // G3 +#define TEST_LCD_DATA9_GPIO (12) // G4 +#define TEST_LCD_DATA10_GPIO (13) // G5 +#define TEST_LCD_DATA11_GPIO (14) // R0 +#define TEST_LCD_DATA12_GPIO (15) // R1 +#define TEST_LCD_DATA13_GPIO (16) // R2 +#define TEST_LCD_DATA14_GPIO (17) // R3 +#define TEST_LCD_DATA15_GPIO (18) // R4 +#define TEST_LCD_DISP_EN_GPIO (39) #if SOC_LCD_RGB_SUPPORTED // RGB driver consumes a huge memory to save frame buffer, only test it with PSRAM enabled @@ -66,7 +67,7 @@ TEST_CASE("lcd rgb lcd panel", "[lcd]") TEST_LCD_DATA15_GPIO, }, .timings = { - .pclk_hz = 6000000, + .pclk_hz = 12000000, .h_res = TEST_LCD_H_RES, .v_res = TEST_LCD_V_RES, .hsync_back_porch = 43, diff --git a/components/esp_lcd/test/test_spi_board.h b/components/esp_lcd/test/test_spi_board.h new file mode 100644 index 0000000000..b862683db9 --- /dev/null +++ b/components/esp_lcd/test/test_spi_board.h @@ -0,0 +1,18 @@ +#include "sdkconfig.h" + +#define TEST_LCD_H_RES (240) +#define TEST_LCD_V_RES (280) + +#define TEST_LCD_BK_LIGHT_GPIO (18) +#define TEST_LCD_RST_GPIO (5) +#define TEST_LCD_CS_GPIO (0) +#define TEST_LCD_DC_GPIO (19) +#define TEST_LCD_PCLK_GPIO (2) +#define TEST_LCD_DATA0_GPIO (4) +#define TEST_LCD_DATA1_GPIO (7) +#define TEST_LCD_DATA2_GPIO (8) +#define TEST_LCD_DATA3_GPIO (9) +#define TEST_LCD_DATA4_GPIO (10) +#define TEST_LCD_DATA5_GPIO (11) +#define TEST_LCD_DATA6_GPIO (12) +#define TEST_LCD_DATA7_GPIO (13) diff --git a/components/esp_lcd/test/test_spi_lcd_panel.c b/components/esp_lcd/test/test_spi_lcd_panel.c index 1eaa67a63f..1a46ff1c9b 100644 --- a/components/esp_lcd/test/test_spi_lcd_panel.c +++ b/components/esp_lcd/test/test_spi_lcd_panel.c @@ -9,24 +9,16 @@ #include "esp_lcd_panel_vendor.h" #include "esp_lcd_panel_ops.h" #include "esp_system.h" +#include "soc/soc_caps.h" +#include "test_spi_board.h" -#define TEST_LCD_H_RES (240) -#define TEST_LCD_V_RES (280) -#define TEST_SPI_CLK_GPIO (2) -#define TEST_SPI_MOSI_GPIO (4) -#define TEST_LCD_RST_GPIO (5) -#define TEST_LCD_DC_GPIO (18) -#define TEST_LCD_BK_LIGHT_GPIO (19) -#define TEST_SPI_CS_GPIO (0) #define TEST_SPI_HOST_ID (1) -#define TEST_LCD_PIXEL_CLOCK_HZ (20 * 1000 * 1000) +#define TEST_LCD_PIXEL_CLOCK_HZ (20 * 1000 * 1000) // 20MHz -TEST_CASE("lcd panel with spi interface (st7789)", "[lcd]") +typedef bool (*trans_done_callback_t)(esp_lcd_panel_io_handle_t, void *, void *); + +static void lcd_initialize_spi(esp_lcd_panel_io_handle_t *io_handle, trans_done_callback_t on_color_trans_done, void *user_data, int cmd_bits, int param_bits, bool oct_mode) { -#define TEST_IMG_SIZE (100 * 100 * sizeof(uint16_t)) - uint8_t *img = heap_caps_malloc(TEST_IMG_SIZE, MALLOC_CAP_DMA); - TEST_ASSERT_NOT_NULL(img); - gpio_config_t bk_gpio_config = { .mode = GPIO_MODE_OUTPUT, .pin_bit_mask = 1ULL << TEST_LCD_BK_LIGHT_GPIO @@ -34,32 +26,48 @@ TEST_CASE("lcd panel with spi interface (st7789)", "[lcd]") TEST_ESP_OK(gpio_config(&bk_gpio_config)); spi_bus_config_t buscfg = { + .sclk_io_num = TEST_LCD_PCLK_GPIO, + .mosi_io_num = TEST_LCD_DATA0_GPIO, .miso_io_num = -1, - .mosi_io_num = TEST_SPI_MOSI_GPIO, - .sclk_io_num = TEST_SPI_CLK_GPIO, .quadwp_io_num = -1, .quadhd_io_num = -1, .max_transfer_sz = TEST_LCD_H_RES * TEST_LCD_V_RES * sizeof(uint16_t) }; + if (oct_mode) { + buscfg.data1_io_num = TEST_LCD_DATA1_GPIO; + buscfg.data2_io_num = TEST_LCD_DATA2_GPIO; + buscfg.data3_io_num = TEST_LCD_DATA3_GPIO; + buscfg.data4_io_num = TEST_LCD_DATA4_GPIO; + buscfg.data5_io_num = TEST_LCD_DATA5_GPIO; + buscfg.data6_io_num = TEST_LCD_DATA6_GPIO; + buscfg.data7_io_num = TEST_LCD_DATA7_GPIO; + buscfg.flags = SPICOMMON_BUSFLAG_OCTAL; + } TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST_ID, &buscfg, SPI_DMA_CH_AUTO)); - esp_lcd_panel_io_handle_t io_handle = NULL; esp_lcd_panel_io_spi_config_t io_config = { .dc_gpio_num = TEST_LCD_DC_GPIO, - .cs_gpio_num = TEST_SPI_CS_GPIO, + .cs_gpio_num = TEST_LCD_CS_GPIO, .pclk_hz = TEST_LCD_PIXEL_CLOCK_HZ, .spi_mode = 0, .trans_queue_depth = 10, + .lcd_cmd_bits = cmd_bits, + .lcd_param_bits = param_bits, + .on_color_trans_done = on_color_trans_done, + .user_data = user_data }; - TEST_ESP_OK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)TEST_SPI_HOST_ID, &io_config, &io_handle)); + if (oct_mode) { + io_config.flags.octal_mode = 1; + io_config.spi_mode = 3; + } + TEST_ESP_OK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)TEST_SPI_HOST_ID, &io_config, io_handle)); +} - esp_lcd_panel_handle_t panel_handle = NULL; - esp_lcd_panel_dev_config_t panel_config = { - .reset_gpio_num = TEST_LCD_RST_GPIO, - .color_space = ESP_LCD_COLOR_SPACE_RGB, - .bits_per_pixel = 16, - }; - TEST_ESP_OK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle)); +static void lcd_panel_test(esp_lcd_panel_io_handle_t io_handle, esp_lcd_panel_handle_t panel_handle) +{ +#define TEST_IMG_SIZE (100 * 100 * sizeof(uint16_t)) + uint8_t *img = heap_caps_malloc(TEST_IMG_SIZE, MALLOC_CAP_DMA); + TEST_ASSERT_NOT_NULL(img); // turn off backlight gpio_set_level(TEST_LCD_BK_LIGHT_GPIO, 0); @@ -78,7 +86,8 @@ TEST_CASE("lcd panel with spi interface (st7789)", "[lcd]") 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); } - esp_lcd_panel_disp_off(panel_handle, true); // turn off screen + // turn off screen + esp_lcd_panel_disp_off(panel_handle, true); TEST_ESP_OK(esp_lcd_panel_del(panel_handle)); TEST_ESP_OK(esp_lcd_panel_io_del(io_handle)); TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST_ID)); @@ -87,6 +96,92 @@ TEST_CASE("lcd panel with spi interface (st7789)", "[lcd]") #undef TEST_IMG_SIZE } +TEST_CASE("lcd panel spi io test", "[lcd]") +{ + esp_lcd_panel_io_handle_t io_handle = NULL; + lcd_initialize_spi(&io_handle, NULL, NULL, 8, 8, false); + esp_lcd_panel_io_tx_param(io_handle, 0x1A, NULL, 0); + esp_lcd_panel_io_tx_param(io_handle, 0x1B, (uint8_t[]) { + 0x11, 0x22, 0x33 + }, 3); + esp_lcd_panel_io_tx_param(io_handle, 0x1C, NULL, 0); + TEST_ESP_OK(esp_lcd_panel_io_del(io_handle)); + TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST_ID)); + + lcd_initialize_spi(&io_handle, NULL, NULL, 16, 16, false); + esp_lcd_panel_io_tx_param(io_handle, 0x1A01, NULL, 0); + esp_lcd_panel_io_tx_param(io_handle, 0x1B02, (uint16_t[]) { + 0x11, 0x22, 0x33 + }, 6); + esp_lcd_panel_io_tx_param(io_handle, 0x1C03, NULL, 0); + TEST_ESP_OK(esp_lcd_panel_io_del(io_handle)); + TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST_ID)); + +#if SOC_SPI_SUPPORT_OCT + lcd_initialize_spi(&io_handle, NULL, NULL, 8, 8, true); + esp_lcd_panel_io_tx_param(io_handle, 0x1A, NULL, 0); + esp_lcd_panel_io_tx_param(io_handle, 0x1B, (uint8_t[]) { + 0x11, 0x22, 0x33 + }, 3); + esp_lcd_panel_io_tx_param(io_handle, 0x1C, NULL, 0); + TEST_ESP_OK(esp_lcd_panel_io_del(io_handle)); + TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST_ID)); + + lcd_initialize_spi(&io_handle, NULL, NULL, 16, 16, true); + esp_lcd_panel_io_tx_param(io_handle, 0x1A01, NULL, 0); + esp_lcd_panel_io_tx_param(io_handle, 0x1B02, (uint16_t[]) { + 0x11, 0x22, 0x33 + }, 6); + esp_lcd_panel_io_tx_param(io_handle, 0x1C03, NULL, 0); + TEST_ESP_OK(esp_lcd_panel_io_del(io_handle)); + TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST_ID)); +#endif // SOC_SPI_SUPPORT_OCT +} + +#if SOC_SPI_SUPPORT_OCT +TEST_CASE("lcd panel with 8-line spi interface (st7789)", "[lcd]") +{ + esp_lcd_panel_io_handle_t io_handle = NULL; + esp_lcd_panel_handle_t panel_handle = NULL; + lcd_initialize_spi(&io_handle, NULL, NULL, 8, 8, true); + esp_lcd_panel_dev_config_t panel_config = { + .reset_gpio_num = TEST_LCD_RST_GPIO, + .color_space = ESP_LCD_COLOR_SPACE_RGB, + .bits_per_pixel = 16, + }; + TEST_ESP_OK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle)); + lcd_panel_test(io_handle, panel_handle); +} + +TEST_CASE("lcd panel with 8-line spi interface (nt35510)", "[lcd]") +{ + esp_lcd_panel_io_handle_t io_handle = NULL; + esp_lcd_panel_handle_t panel_handle = NULL; + lcd_initialize_spi(&io_handle, NULL, NULL, 16, 16, true); + esp_lcd_panel_dev_config_t panel_config = { + .reset_gpio_num = TEST_LCD_RST_GPIO, + .color_space = ESP_LCD_COLOR_SPACE_RGB, + .bits_per_pixel = 16, + }; + TEST_ESP_OK(esp_lcd_new_panel_nt35510(io_handle, &panel_config, &panel_handle)); + lcd_panel_test(io_handle, panel_handle); +} +#endif // SOC_SPI_SUPPORT_OCT + +TEST_CASE("lcd panel with 1-line spi interface (st7789)", "[lcd]") +{ + esp_lcd_panel_io_handle_t io_handle = NULL; + esp_lcd_panel_handle_t panel_handle = NULL; + lcd_initialize_spi(&io_handle, NULL, NULL, 8, 8, false); + esp_lcd_panel_dev_config_t panel_config = { + .reset_gpio_num = TEST_LCD_RST_GPIO, + .color_space = ESP_LCD_COLOR_SPACE_RGB, + .bits_per_pixel = 16, + }; + TEST_ESP_OK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle)); + lcd_panel_test(io_handle, panel_handle); +} + // The following test shows a porting example of LVGL GUI library // To run the LVGL tests, you need to clone the LVGL library into components directory firstly #if CONFIG_LV_USE_USER_DATA @@ -99,48 +194,10 @@ static bool notify_lvgl_ready_to_flush(esp_lcd_panel_io_handle_t panel_io, void return false; } -TEST_CASE("lvgl gui with spi interface (st7789)", "[lcd][lvgl][ignore]") +static void lvgl_gui_test(esp_lcd_panel_io_handle_t io_handle, esp_lcd_panel_handle_t panel_handle, lv_disp_t **disp) { // initialize LVGL graphics library - lv_disp_t *disp = NULL; lv_init(); - - gpio_config_t bk_gpio_config = { - .mode = GPIO_MODE_OUTPUT, - .pin_bit_mask = 1ULL << TEST_LCD_BK_LIGHT_GPIO - }; - TEST_ESP_OK(gpio_config(&bk_gpio_config)); - - spi_bus_config_t buscfg = { - .miso_io_num = -1, - .mosi_io_num = TEST_SPI_MOSI_GPIO, - .sclk_io_num = TEST_SPI_CLK_GPIO, - .quadwp_io_num = -1, - .quadhd_io_num = -1, - .max_transfer_sz = TEST_LCD_H_RES * TEST_LCD_V_RES * 2 - }; - TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST_ID, &buscfg, 1)); - - esp_lcd_panel_io_handle_t io_handle = NULL; - esp_lcd_panel_io_spi_config_t io_config = { - .dc_gpio_num = TEST_LCD_DC_GPIO, - .cs_gpio_num = TEST_SPI_CS_GPIO, - .pclk_hz = TEST_LCD_PIXEL_CLOCK_HZ, - .spi_mode = 0, - .trans_queue_depth = 10, - .on_color_trans_done = notify_lvgl_ready_to_flush, - .user_data = &disp // we must use "address of disp" here, since the disp object has not been allocated - }; - TEST_ESP_OK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)TEST_SPI_HOST_ID, &io_config, &io_handle)); - - esp_lcd_panel_handle_t panel_handle = NULL; - esp_lcd_panel_dev_config_t panel_config = { - .reset_gpio_num = TEST_LCD_RST_GPIO, - .color_space = ESP_LCD_COLOR_SPACE_RGB, - .bits_per_pixel = 16, - }; - TEST_ESP_OK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle)); - // turn off backlight gpio_set_level(TEST_LCD_BK_LIGHT_GPIO, 0); esp_lcd_panel_reset(panel_handle); @@ -151,7 +208,54 @@ TEST_CASE("lvgl gui with spi interface (st7789)", "[lcd][lvgl][ignore]") // turn on backlight gpio_set_level(TEST_LCD_BK_LIGHT_GPIO, 1); - test_lvgl_task_loop(panel_handle, TEST_LCD_H_RES, TEST_LCD_V_RES, &disp); + test_lvgl_task_loop(panel_handle, TEST_LCD_H_RES, TEST_LCD_V_RES, disp); +} + +#if SOC_SPI_SUPPORT_OCT +TEST_CASE("lvgl gui with 8-line spi interface (st7789)", "[lcd][lvgl][ignore]") +{ + lv_disp_t *disp = NULL; + esp_lcd_panel_io_handle_t io_handle = NULL; + esp_lcd_panel_handle_t panel_handle = NULL; + lcd_initialize_spi(&io_handle, notify_lvgl_ready_to_flush, &disp, 8, 8, true); + esp_lcd_panel_dev_config_t panel_config = { + .reset_gpio_num = TEST_LCD_RST_GPIO, + .color_space = ESP_LCD_COLOR_SPACE_RGB, + .bits_per_pixel = 16, + }; + TEST_ESP_OK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle)); + lvgl_gui_test(io_handle, panel_handle, &disp); +} + +TEST_CASE("lvgl gui with 8-line spi interface (nt35510)", "[lcd][lvgl][ignore]") +{ + lv_disp_t *disp = NULL; + esp_lcd_panel_io_handle_t io_handle = NULL; + esp_lcd_panel_handle_t panel_handle = NULL; + lcd_initialize_spi(&io_handle, notify_lvgl_ready_to_flush, &disp, 16, 16, true); + esp_lcd_panel_dev_config_t panel_config = { + .reset_gpio_num = TEST_LCD_RST_GPIO, + .color_space = ESP_LCD_COLOR_SPACE_RGB, + .bits_per_pixel = 16, + }; + TEST_ESP_OK(esp_lcd_new_panel_nt35510(io_handle, &panel_config, &panel_handle)); + lvgl_gui_test(io_handle, panel_handle, &disp); +} +#endif // SOC_SPI_SUPPORT_OCT + +TEST_CASE("lvgl gui with 1-line spi interface (st7789)", "[lcd][lvgl][ignore]") +{ + lv_disp_t *disp = NULL; + esp_lcd_panel_io_handle_t io_handle = NULL; + esp_lcd_panel_handle_t panel_handle = NULL; + lcd_initialize_spi(&io_handle, notify_lvgl_ready_to_flush, &disp, 8, 8, false); + esp_lcd_panel_dev_config_t panel_config = { + .reset_gpio_num = TEST_LCD_RST_GPIO, + .color_space = ESP_LCD_COLOR_SPACE_RGB, + .bits_per_pixel = 16, + }; + TEST_ESP_OK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle)); + lvgl_gui_test(io_handle, panel_handle, &disp); } #endif // CONFIG_LV_USE_USER_DATA diff --git a/components/esp_local_ctrl/include/esp_local_ctrl.h b/components/esp_local_ctrl/include/esp_local_ctrl.h index 9f4f89daa3..8322412eb3 100644 --- a/components/esp_local_ctrl/include/esp_local_ctrl.h +++ b/components/esp_local_ctrl/include/esp_local_ctrl.h @@ -228,6 +228,37 @@ typedef union { esp_local_ctrl_transport_config_httpd_t *httpd; } esp_local_ctrl_transport_config_t; +/** + * @brief Security types for esp_local_control + */ +typedef enum esp_local_ctrl_proto_sec { + PROTOCOM_SEC0 = 0, + PROTOCOM_SEC1, + PROTOCOM_SEC_CUSTOM, +} esp_local_ctrl_proto_sec_t; + +/** + * Protocom security configs + */ +typedef struct esp_local_ctrl_proto_sec_cfg { + /** + * This sets protocom security version, sec0/sec1 or custom + * If custom, user must provide handle via `proto_sec_custom_handle` below + */ + esp_local_ctrl_proto_sec_t version; + + /** + * Custom security handle if security is set custom via `proto_sec` above + * This handle must follow `protocomm_security_t` signature + */ + void *custom_handle; + + /** + * Proof of possession to be used for local control. Could be NULL. + */ + void *pop; +} esp_local_ctrl_proto_sec_cfg_t; + /** * @brief Configuration structure to pass to `esp_local_ctrl_start()` */ @@ -242,6 +273,11 @@ typedef struct esp_local_ctrl_config { */ esp_local_ctrl_transport_config_t transport_config; + /** + * Security version and POP + */ + esp_local_ctrl_proto_sec_cfg_t proto_sec; + /** * Register handlers for responding to get/set requests on properties */ diff --git a/components/esp_local_ctrl/src/esp_local_ctrl.c b/components/esp_local_ctrl/src/esp_local_ctrl.c index 1eead4d7c1..c99b96782b 100644 --- a/components/esp_local_ctrl/src/esp_local_ctrl.c +++ b/components/esp_local_ctrl/src/esp_local_ctrl.c @@ -19,6 +19,7 @@ #include #include +#include #include #include "esp_local_ctrl_priv.h" @@ -149,8 +150,21 @@ esp_err_t esp_local_ctrl_start(const esp_local_ctrl_config_t *config) return ret; } + protocomm_security_t *proto_sec_handle; + switch (local_ctrl_inst_ctx->config.proto_sec.version) { + case PROTOCOM_SEC_CUSTOM: + proto_sec_handle = local_ctrl_inst_ctx->config.proto_sec.custom_handle; + break; + case PROTOCOM_SEC1: + proto_sec_handle = (protocomm_security_t *) &protocomm_security1; + break; + case PROTOCOM_SEC0: + default: + proto_sec_handle = (protocomm_security_t *) &protocomm_security0; + break; + } ret = protocomm_set_security(local_ctrl_inst_ctx->pc, "esp_local_ctrl/session", - &protocomm_security0, NULL); + proto_sec_handle, local_ctrl_inst_ctx->config.proto_sec.pop); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to set session endpoint"); esp_local_ctrl_stop(); diff --git a/components/esp_netif/CMakeLists.txt b/components/esp_netif/CMakeLists.txt index e3f4871e8a..a78a3116ce 100644 --- a/components/esp_netif/CMakeLists.txt +++ b/components/esp_netif/CMakeLists.txt @@ -1,3 +1,11 @@ +idf_build_get_property(target IDF_TARGET) + +if(${target} STREQUAL "linux") + # Header only library for linux + idf_component_register(INCLUDE_DIRS include) + return() +endif() + set(srcs "esp_netif_handlers.c" "esp_netif_objects.c" diff --git a/components/esp_netif/include/esp_netif_ppp.h b/components/esp_netif/include/esp_netif_ppp.h index 413910c433..159388e80e 100644 --- a/components/esp_netif/include/esp_netif_ppp.h +++ b/components/esp_netif/include/esp_netif_ppp.h @@ -38,6 +38,11 @@ typedef struct esp_netif_ppp_config { */ #define NETIF_PP_PHASE_OFFSET (0x100) +/** @brief event id offset for internal errors + * + */ +#define NETIF_PPP_INTERNAL_ERR_OFFSET (0x200) + /** @brief event ids for different PPP related events * */ @@ -68,6 +73,7 @@ typedef enum { NETIF_PPP_PHASE_RUNNING = NETIF_PP_PHASE_OFFSET + 10, NETIF_PPP_PHASE_TERMINATE = NETIF_PP_PHASE_OFFSET + 11, NETIF_PPP_PHASE_DISCONNECT = NETIF_PP_PHASE_OFFSET + 12, + NETIF_PPP_CONNECT_FAILED = NETIF_PPP_INTERNAL_ERR_OFFSET + 0, } esp_netif_ppp_status_event_t; /** @brief definitions of different authorisation types @@ -89,7 +95,8 @@ typedef enum { * @param[in] user User name * @param[in] passwd Password * - * @return ESP_OK on success, ESP_ERR_ESP_NETIF_INVALID_PARAMS if netif null or not PPP + * @return ESP_OK on success, + * ESP_ERR_ESP_NETIF_INVALID_PARAMS if the supplied netif is not of PPP type, or netif is null */ esp_err_t esp_netif_ppp_set_auth(esp_netif_t *netif, esp_netif_auth_type_t authtype, const char *user, const char *passwd); @@ -98,10 +105,20 @@ esp_err_t esp_netif_ppp_set_auth(esp_netif_t *netif, esp_netif_auth_type_t autht * @param[in] esp_netif Handle to esp-netif instance * @param[in] config Pointer to PPP netif configuration structure * - * @return ESP_OK on success, ESP_ERR_ESP_NETIF_INVALID_PARAMS if netif null or not PPP + * @return ESP_OK on success, + * ESP_ERR_ESP_NETIF_INVALID_PARAMS if the supplied netif is not of PPP type, or netif is null */ esp_err_t esp_netif_ppp_set_params(esp_netif_t *netif, const esp_netif_ppp_config_t *config); +/** @brief Gets parameters configured in the supplied esp-netif. + * + * @param[in] esp_netif Handle to esp-netif instance + * @param[out] config Pointer to PPP netif configuration structure + * + * @return ESP_OK on success, + * ESP_ERR_ESP_NETIF_INVALID_PARAMS if the supplied netif is not of PPP type, or netif is null + */ +esp_err_t esp_netif_ppp_get_params(esp_netif_t *netif, esp_netif_ppp_config_t *config); #ifdef __cplusplus } diff --git a/components/esp_netif/lwip/esp_netif_lwip.c b/components/esp_netif/lwip/esp_netif_lwip.c index 1ec5669b92..2e847146fe 100644 --- a/components/esp_netif/lwip/esp_netif_lwip.c +++ b/components/esp_netif/lwip/esp_netif_lwip.c @@ -101,11 +101,13 @@ extern sys_thread_t g_lwip_task; static const char *TAG = "esp_netif_lwip"; -static sys_sem_t api_sync_sem = NULL; -static sys_sem_t api_lock_sem = NULL; static bool tcpip_initialized = false; static esp_netif_t *s_last_default_esp_netif = NULL; +#if !LWIP_TCPIP_CORE_LOCKING +static sys_sem_t api_sync_sem = NULL; +static sys_sem_t api_lock_sem = NULL; + /** * @brief Api callback from tcpip thread used to call esp-netif * function in lwip task context @@ -124,6 +126,7 @@ static void esp_netif_api_cb(void *api_msg) sys_sem_signal(&api_sync_sem); } +#endif /** * @brief Initiates a tcpip remote call if called from another task @@ -136,6 +139,7 @@ static inline esp_err_t esp_netif_lwip_ipc_call(esp_netif_api_fn fn, esp_netif_t .data = data, .api_fn = fn }; +#if !LWIP_TCPIP_CORE_LOCKING if (g_lwip_task != xTaskGetCurrentTaskHandle()) { ESP_LOGD(TAG, "check: remote, if=%p fn=%p\n", netif, fn); sys_arch_sem_wait(&api_lock_sem, 0); @@ -143,6 +147,7 @@ static inline esp_err_t esp_netif_lwip_ipc_call(esp_netif_api_fn fn, esp_netif_t sys_sem_signal(&api_lock_sem); return msg.ret; } +#endif /* !LWIP_TCPIP_CORE_LOCKING */ ESP_LOGD(TAG, "check: local, if=%p fn=%p\n", netif, fn); return fn(&msg); } @@ -178,7 +183,7 @@ static void esp_netif_set_default_netif(esp_netif_t *esp_netif) esp_netif_ppp_set_default_netif(esp_netif->netif_handle); #endif } else { - netif_set_default(esp_netif->netif_handle); + netif_set_default(esp_netif->lwip_netif); } } @@ -324,6 +329,7 @@ esp_err_t esp_netif_init(void) ESP_LOGD(TAG, "LwIP stack has been initialized"); } +#if !LWIP_TCPIP_CORE_LOCKING if (!api_sync_sem) { if (ERR_OK != sys_sem_new(&api_sync_sem, 0)) { ESP_LOGE(TAG, "esp netif api sync sem init fail"); @@ -337,6 +343,7 @@ esp_err_t esp_netif_init(void) return ESP_FAIL; } } +#endif ESP_LOGD(TAG, "esp-netif has been successfully initialized"); return ESP_OK; @@ -779,7 +786,7 @@ esp_err_t esp_netif_start(esp_netif_t *esp_netif) if (_IS_NETIF_POINT2POINT_TYPE(esp_netif, PPP_LWIP_NETIF)) { #if CONFIG_PPP_SUPPORT // No need to start PPP interface in lwip thread - esp_err_t ret = esp_netif_start_ppp(esp_netif->related_data); + esp_err_t ret = esp_netif_start_ppp(esp_netif); if (ret == ESP_OK) { esp_netif_update_default_netif(esp_netif, ESP_NETIF_STARTED); } diff --git a/components/esp_netif/lwip/esp_netif_lwip_ppp.c b/components/esp_netif/lwip/esp_netif_lwip_ppp.c index a0d711e84a..21385f479f 100644 --- a/components/esp_netif/lwip/esp_netif_lwip_ppp.c +++ b/components/esp_netif/lwip/esp_netif_lwip_ppp.c @@ -296,8 +296,9 @@ netif_related_data_t * esp_netif_new_ppp(esp_netif_t *esp_netif, const esp_netif return (netif_related_data_t *)ppp_obj; } -esp_err_t esp_netif_start_ppp(netif_related_data_t *netif_related) +esp_err_t esp_netif_start_ppp(esp_netif_t *esp_netif) { + netif_related_data_t *netif_related = esp_netif->related_data; lwip_peer2peer_ctx_t *ppp_ctx = (lwip_peer2peer_ctx_t *)netif_related; assert(ppp_ctx->base.netif_type == PPP_LWIP_NETIF); @@ -305,6 +306,9 @@ esp_err_t esp_netif_start_ppp(netif_related_data_t *netif_related) esp_err_t err = pppapi_connect(ppp_ctx->ppp, 0); if (err != ESP_OK) { ESP_LOGE(TAG, "%s: PPP connection cannot be started", __func__); + if (ppp_ctx->ppp_error_event_enabled) { + esp_event_post(NETIF_PPP_STATUS, NETIF_PPP_CONNECT_FAILED, esp_netif, sizeof(esp_netif), 0); + } return ESP_FAIL; } return ESP_OK; @@ -343,10 +347,26 @@ void esp_netif_destroy_ppp(netif_related_data_t *netif_related) esp_err_t esp_netif_ppp_set_params(esp_netif_t *netif, const esp_netif_ppp_config_t *config) { + if (netif == NULL || netif->related_data == NULL || config == NULL || + ((struct lwip_peer2peer_ctx *)netif->related_data)->base.netif_type != PPP_LWIP_NETIF) { + return ESP_ERR_INVALID_ARG; + } struct lwip_peer2peer_ctx *obj = (struct lwip_peer2peer_ctx *)netif->related_data; obj->ppp_phase_event_enabled = config->ppp_phase_event_enabled; obj->ppp_error_event_enabled = config->ppp_error_event_enabled; return ESP_OK; } +esp_err_t esp_netif_ppp_get_params(esp_netif_t *netif, esp_netif_ppp_config_t *config) +{ + if (netif == NULL || netif->related_data == NULL || config == NULL || + ((struct lwip_peer2peer_ctx *)netif->related_data)->base.netif_type != PPP_LWIP_NETIF) { + return ESP_ERR_INVALID_ARG; + } + struct lwip_peer2peer_ctx *obj = (struct lwip_peer2peer_ctx *)netif->related_data; + config->ppp_phase_event_enabled = obj->ppp_phase_event_enabled; + config->ppp_error_event_enabled = obj->ppp_error_event_enabled; + return ESP_OK; +} + #endif /* CONFIG_ESP_NETIF_TCPIP_LWIP */ diff --git a/components/esp_netif/lwip/esp_netif_lwip_ppp.h b/components/esp_netif/lwip/esp_netif_lwip_ppp.h index 1d3b7061d5..b579eb80a8 100644 --- a/components/esp_netif/lwip/esp_netif_lwip_ppp.h +++ b/components/esp_netif/lwip/esp_netif_lwip_ppp.h @@ -32,12 +32,12 @@ netif_related_data_t * esp_netif_new_ppp(esp_netif_t *esp_netif, const esp_netif /** * @brief Creates new PPP related structure * - * @param[in] netif_related pointer to internal ppp context instance + * @param[in] esp_netif pointer esp-netif instance * * @return * - ESP_OK on success */ -esp_err_t esp_netif_start_ppp(netif_related_data_t *netif_related); +esp_err_t esp_netif_start_ppp(esp_netif_t *esp_netif); /** * @brief Data path API to input incoming packets to PPP diff --git a/components/esp_phy/CMakeLists.txt b/components/esp_phy/CMakeLists.txt index 8a92c477f7..2ca1e68101 100644 --- a/components/esp_phy/CMakeLists.txt +++ b/components/esp_phy/CMakeLists.txt @@ -9,7 +9,7 @@ else() endif() if(IDF_TARGET STREQUAL "esp32h2") - set(srcs "src/esp32h2/phy_init.c") + set(srcs "src/phy_init_esp32hxx.c") else() set(srcs "src/phy_init.c") endif() @@ -28,15 +28,22 @@ if(link_binary_libs) target_link_libraries(${COMPONENT_LIB} PUBLIC phy) idf_component_get_property(esp_phy_lib esp_phy COMPONENT_LIB) - target_link_libraries(${COMPONENT_LIB} INTERFACE $ libphy.a - $) if(CONFIG_IDF_TARGET_ESP32) target_link_libraries(${COMPONENT_LIB} PUBLIC rtc) + target_link_libraries(${COMPONENT_LIB} INTERFACE $ libphy.a librtc.a + $) endif() - if(CONFIG_IDF_TARGET_ESP32C3 OR CONFIG_IDF_TARGET_ESP32S3) + if(CONFIG_IDF_TARGET_ESP32S2) + target_link_libraries(${COMPONENT_LIB} INTERFACE $ libphy.a + $) + endif() + + if(CONFIG_IDF_TARGET_ESP32C3 OR CONFIG_IDF_TARGET_ESP32S3 OR CONFIG_IDF_TARGET_ESP32H2) target_link_libraries(${COMPONENT_LIB} PUBLIC btbb) + target_link_libraries(${COMPONENT_LIB} INTERFACE $ libphy.a libbtbb.a + $) endif() endif() diff --git a/components/esp_phy/Kconfig b/components/esp_phy/Kconfig index 19e969170d..e3bb40f3db 100644 --- a/components/esp_phy/Kconfig +++ b/components/esp_phy/Kconfig @@ -81,7 +81,7 @@ menu "PHY" config ESP32_PHY_MAC_BB_PD bool "Power down MAC and baseband of Wi-Fi and Bluetooth when PHY is disabled" - depends on (IDF_TARGET_ESP32C3 && FREERTOS_USE_TICKLESS_IDLE) + depends on ((IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3) && FREERTOS_USE_TICKLESS_IDLE) default n help If enabled, the MAC and baseband of Wi-Fi and Bluetooth will be powered diff --git a/components/esp_phy/esp32h2/include/phy_init_data.h b/components/esp_phy/esp32h2/include/phy_init_data.h index c29eab08ec..7330d7e371 100644 --- a/components/esp_phy/esp32h2/include/phy_init_data.h +++ b/components/esp_phy/esp32h2/include/phy_init_data.h @@ -21,7 +21,7 @@ extern "C" { #endif -// ESP32H2-TODO: IDF-3398 +// There is no init data for H2 right now, could be added when necessary. #ifdef __cplusplus } diff --git a/components/esp_phy/include/phy.h b/components/esp_phy/include/phy.h index c0eadbf2ba..51b972bb6c 100644 --- a/components/esp_phy/include/phy.h +++ b/components/esp_phy/include/phy.h @@ -69,7 +69,7 @@ void phy_wakeup_init(void); */ void phy_close_rf(void); -#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2 +#if !CONFIG_IDF_TARGET_ESP32 /** * @brief Disable PHY temperature sensor. */ diff --git a/components/esp_phy/lib b/components/esp_phy/lib index 8b1137c35c..0ae4bb88c0 160000 --- a/components/esp_phy/lib +++ b/components/esp_phy/lib @@ -1 +1 @@ -Subproject commit 8b1137c35cc3d2b1085e7f857c2530efb115d3a3 +Subproject commit 0ae4bb88c00faa641be5d2a613184735f484edb8 diff --git a/components/esp_phy/src/phy_init.c b/components/esp_phy/src/phy_init.c index e7e7c15638..86e9925374 100644 --- a/components/esp_phy/src/phy_init.c +++ b/components/esp_phy/src/phy_init.c @@ -262,7 +262,7 @@ void esp_phy_disable(void) phy_digital_regs_store(); // Disable PHY and RF. phy_close_rf(); -#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2 +#if !CONFIG_IDF_TARGET_ESP32 // Disable PHY temperature sensor phy_xpd_tsens(); #endif diff --git a/components/esp_phy/src/phy_init_esp32hxx.c b/components/esp_phy/src/phy_init_esp32hxx.c new file mode 100644 index 0000000000..dce1fd672e --- /dev/null +++ b/components/esp_phy/src/phy_init_esp32hxx.c @@ -0,0 +1,72 @@ +// 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 "esp_attr.h" +#include "freertos/portmacro.h" +#include "esp_phy_init.h" +#include "phy.h" + +#define PHY_ENABLE_VERSION_PRINT 1 + +static DRAM_ATTR portMUX_TYPE s_phy_int_mux = portMUX_INITIALIZER_UNLOCKED; +extern void phy_version_print(void); + +static _lock_t s_phy_access_lock; + +/* Reference count of enabling PHY */ +static uint8_t s_phy_access_ref = 0; + +extern void bt_bb_v2_init_cmplx(int print_version); + +uint32_t IRAM_ATTR phy_enter_critical(void) +{ + if (xPortInIsrContext()) { + portENTER_CRITICAL_ISR(&s_phy_int_mux); + + } else { + portENTER_CRITICAL(&s_phy_int_mux); + } + // Interrupt level will be stored in current tcb, so always return zero. + return 0; +} + +void IRAM_ATTR phy_exit_critical(uint32_t level) +{ + // Param level don't need any more, ignore it. + if (xPortInIsrContext()) { + portEXIT_CRITICAL_ISR(&s_phy_int_mux); + } else { + portEXIT_CRITICAL(&s_phy_int_mux); + } +} + +void esp_phy_enable(void) +{ + _lock_acquire(&s_phy_access_lock); + if (s_phy_access_ref == 0) { + register_chipv7_phy(NULL, NULL, PHY_RF_CAL_FULL); + bt_bb_v2_init_cmplx(PHY_ENABLE_VERSION_PRINT); + phy_version_print(); + } + + s_phy_access_ref++; + + _lock_release(&s_phy_access_lock); + // ESP32H2-TODO: enable common clk. +} + +void esp_phy_disable(void) +{ + // ESP32H2-TODO: close rf and disable clk for modem sleep and light sleep +} diff --git a/components/esp_pm/Kconfig b/components/esp_pm/Kconfig index dc0e14422f..f10e888746 100644 --- a/components/esp_pm/Kconfig +++ b/components/esp_pm/Kconfig @@ -96,10 +96,21 @@ menu "Power Management" config PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP bool "Power down CPU in light sleep" - depends on IDF_TARGET_ESP32C3 + depends on IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 + select PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP if ESP32S3_DATA_CACHE_16KB default y help - If enabled, the CPU will be powered down in light sleep. Enabling this option will consume - 1.68 KB of internal RAM and will reduce sleep current consumption by about 100 uA. + If enabled, the CPU will be powered down in light sleep. On esp32c3 soc, enabling this + option will consume 1.68 KB of internal RAM and will reduce sleep current consumption + by about 100 uA. On esp32s3 soc, enabling this option will consume 8.58 KB of internal + RAM and will reduce sleep current consumption by about 650 uA. + + config PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP + bool "Power down I/D-cache tag memory in light sleep" + depends on IDF_TARGET_ESP32S3 && PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP + default y + help + If enabled, the I/D-cache tag memory will be retained in light sleep. Depending on the the + cache configuration, if this option is enabled, it will consume up to 9 KB of internal RAM. endmenu # "Power Management" diff --git a/components/esp_pm/linker.lf b/components/esp_pm/linker.lf index 2abbeab151..91237ef1b5 100644 --- a/components/esp_pm/linker.lf +++ b/components/esp_pm/linker.lf @@ -19,6 +19,11 @@ entries: esp_clk:esp_clk_slowclk_cal_set (noflash) esp_clk:esp_clk_slowclk_cal_get (noflash) esp_clk:esp_rtc_get_time_us (noflash) + if GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL = y: + sleep_gpio:gpio_sleep_mode_config_apply (noflash) + if IDF_TARGET_ESP32 = n && IDF_TARGET_ESP32S2 = n: + sleep_retention:sleep_enable_memory_retention (noflash) + sleep_retention:cpu_domain_pd_allowed (noflash) [mapping:esp_system_pm] archive: libesp_system.a @@ -72,3 +77,5 @@ entries: gpio_hal_workaround:gpio_hal_fun_pupd_restore (noflash) if PM_SLP_IRAM_OPT = y && PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP = y: rtc_cntl_hal:rtc_cntl_hal_enable_cpu_retention (noflash) + if PM_SLP_IRAM_OPT = y && PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP = y: + rtc_cntl_hal:rtc_cntl_hal_enable_tagmem_retention (noflash) diff --git a/components/esp_pm/pm_impl.c b/components/esp_pm/pm_impl.c index 6cc2c4b698..55c7a47ea0 100644 --- a/components/esp_pm/pm_impl.c +++ b/components/esp_pm/pm_impl.c @@ -31,7 +31,7 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#if __XTENSA__ +#if CONFIG_FREERTOS_SYSTICK_USES_CCOUNT #include "freertos/xtensa_timer.h" #include "xtensa/core-macros.h" #endif @@ -68,7 +68,7 @@ #define MHZ (1000000) -#if __XTENSA__ +#ifdef CONFIG_FREERTOS_SYSTICK_USES_CCOUNT /* CCOMPARE update timeout, in CPU cycles. Any value above ~600 cycles will work * for the purpose of detecting a deadlock. */ @@ -78,7 +78,7 @@ * than this. This is to prevent setting CCOMPARE below CCOUNT. */ #define CCOMPARE_MIN_CYCLES_IN_FUTURE 1000 -#endif +#endif // CONFIG_FREERTOS_SYSTICK_USES_CCOUNT /* When light sleep is used, wake this number of microseconds earlier than * the next tick. @@ -115,8 +115,6 @@ static portMUX_TYPE s_switch_lock = portMUX_INITIALIZER_UNLOCKED; static pm_mode_t s_mode = PM_MODE_CPU_MAX; /* True when switch is in progress */ static volatile bool s_is_switching; -/* When switch is in progress, this is the mode we are switching into */ -static pm_mode_t s_new_mode = PM_MODE_CPU_MAX; /* Number of times each mode was locked */ static size_t s_mode_lock_counts[PM_MODE_COUNT]; /* Bit mask of locked modes. BIT(i) is set iff s_mode_lock_counts[i] > 0. */ @@ -184,7 +182,7 @@ static const char* s_mode_names[] = { }; #endif // WITH_PROFILING -#if __XTENSA__ +#ifdef CONFIG_FREERTOS_SYSTICK_USES_CCOUNT /* Indicates to the ISR hook that CCOMPARE needs to be updated on the given CPU. * Used in conjunction with cross-core interrupt to update CCOMPARE on the other CPU. */ @@ -197,7 +195,7 @@ static uint32_t s_ccount_div; static uint32_t s_ccount_mul; static void update_ccompare(void); -#endif // __XTENSA__ +#endif // CONFIG_FREERTOS_SYSTICK_USES_CCOUNT static const char* TAG = "pm"; @@ -405,7 +403,7 @@ void IRAM_ATTR esp_pm_impl_switch_mode(pm_mode_t mode, #endif // WITH_PROFILING } portEXIT_CRITICAL_SAFE(&s_switch_lock); - if (need_switch && new_mode != s_mode) { + if (need_switch) { do_switch(new_mode); } } @@ -425,7 +423,7 @@ static void IRAM_ATTR on_freq_update(uint32_t old_ticks_per_us, uint32_t ticks_p esp_timer_private_update_apb_freq(apb_ticks_per_us); } -#if __XTENSA__ +#ifdef CONFIG_FREERTOS_SYSTICK_USES_CCOUNT #ifdef XT_RTOS_TIMER_INT /* Calculate new tick divisor */ _xt_tick_divisor = ticks_per_us * MHZ / XT_TICK_PER_SEC; @@ -462,7 +460,7 @@ static void IRAM_ATTR on_freq_update(uint32_t old_ticks_per_us, uint32_t ticks_p s_ccount_div = 0; ESP_PM_TRACE_EXIT(CCOMPARE_UPDATE, core_id); } -#endif // __XTENSA__ +#endif // CONFIG_FREERTOS_SYSTICK_USES_CCOUNT } /** @@ -480,18 +478,17 @@ static void IRAM_ATTR do_switch(pm_mode_t new_mode) if (!s_is_switching) { break; } - if (s_new_mode <= new_mode) { - portEXIT_CRITICAL_ISR(&s_switch_lock); - return; - } -#if __XTENSA__ +#ifdef CONFIG_FREERTOS_SYSTICK_USES_CCOUNT if (s_need_update_ccompare[core_id]) { s_need_update_ccompare[core_id] = false; } #endif portEXIT_CRITICAL_ISR(&s_switch_lock); } while (true); - s_new_mode = new_mode; + if (new_mode == s_mode) { + portEXIT_CRITICAL_ISR(&s_switch_lock); + return; + } s_is_switching = true; bool config_changed = s_config_changed; s_config_changed = false; @@ -529,7 +526,7 @@ static void IRAM_ATTR do_switch(pm_mode_t new_mode) portEXIT_CRITICAL_ISR(&s_switch_lock); } -#if __XTENSA__ +#ifdef CONFIG_FREERTOS_SYSTICK_USES_CCOUNT /** * @brief Calculate new CCOMPARE value based on s_ccount_{mul,div} * @@ -550,7 +547,7 @@ static void IRAM_ATTR update_ccompare(void) } } } -#endif // __XTENSA__ +#endif // CONFIG_FREERTOS_SYSTICK_USES_CCOUNT static void IRAM_ATTR leave_idle(void) { @@ -656,7 +653,7 @@ void IRAM_ATTR vApplicationSleep( TickType_t xExpectedIdleTime ) /* Adjust RTOS tick count based on the amount of time spent in sleep */ vTaskStepTick(slept_ticks); -#if __XTENSA__ +#ifdef CONFIG_FREERTOS_SYSTICK_USES_CCOUNT /* Trigger tick interrupt, since sleep time was longer * than portTICK_PERIOD_MS. Note that setting INTSET does not * work for timer interrupt, and changing CCOMPARE would clear @@ -666,7 +663,7 @@ void IRAM_ATTR vApplicationSleep( TickType_t xExpectedIdleTime ) while (!(XTHAL_GET_INTERRUPT() & BIT(XT_TIMER_INTNUM))) { ; } -#elif __riscv +#else portYIELD_WITHIN_API(); #endif } @@ -810,7 +807,7 @@ void IRAM_ATTR esp_pm_impl_isr_hook(void) * from happening in this section, since they will also call into esp_pm_impl_isr_hook. */ uint32_t state = portENTER_CRITICAL_NESTED(); -#if __XTENSA__ && (portNUM_PROCESSORS == 2) +#if defined(CONFIG_FREERTOS_SYSTICK_USES_CCOUNT) && (portNUM_PROCESSORS == 2) if (s_need_update_ccompare[core_id]) { update_ccompare(); s_need_update_ccompare[core_id] = false; @@ -819,7 +816,7 @@ void IRAM_ATTR esp_pm_impl_isr_hook(void) } #else leave_idle(); -#endif // portNUM_PROCESSORS == 2 +#endif // CONFIG_FREERTOS_SYSTICK_USES_CCOUNT && portNUM_PROCESSORS == 2 portEXIT_CRITICAL_NESTED(state); ESP_PM_TRACE_EXIT(ISR_HOOK, core_id); } diff --git a/components/esp_rom/CMakeLists.txt b/components/esp_rom/CMakeLists.txt index 1e1cbb1534..b66eb7b4f4 100644 --- a/components/esp_rom/CMakeLists.txt +++ b/components/esp_rom/CMakeLists.txt @@ -1,16 +1,32 @@ idf_build_get_property(target IDF_TARGET) -set(sources "patches/esp_rom_crc.c" - "patches/esp_rom_sys.c" - "patches/esp_rom_uart.c") +set(include_dirs "include" "include/${target}") + +set(private_required_comp "") + +set(sources "") + +if(target STREQUAL "linux") + list(APPEND sources "${target}/esp_rom_sys.c" + "${target}/esp_rom_crc.c" + "${target}/esp_rom_md5.c" + "${target}/esp_rom_efuse.c") +else() + list(APPEND include_dirs "${target}") + list(APPEND sources "patches/esp_rom_crc.c" + "patches/esp_rom_sys.c" + "patches/esp_rom_uart.c" + "patches/esp_rom_tjpgd.c") + list(APPEND private_required_comp soc hal) +endif() if(CONFIG_IDF_TARGET_ARCH_XTENSA) list(APPEND sources "patches/esp_rom_longjmp.S") endif() idf_component_register(SRCS ${sources} - INCLUDE_DIRS include "${target}" "include/${target}" - PRIV_REQUIRES soc hal) + INCLUDE_DIRS ${include_dirs} + PRIV_REQUIRES ${private_required_comp}) # Append a target linker script at the target-specific path, # only the 'name' part is different for each script @@ -18,13 +34,23 @@ function(rom_linker_script name) target_linker_script(${COMPONENT_LIB} INTERFACE "${target}/ld/${target}.rom.${name}.ld") endfunction() -target_linker_script(${COMPONENT_LIB} INTERFACE "${target}/ld/${target}.rom.ld") -rom_linker_script("api") -rom_linker_script("libgcc") +if(target STREQUAL "linux") + # We need to disable some warnings due to the ROM code's printf implementation + if(${CMAKE_CXX_COMPILER_VERSION} GREATER "7.0.0") # TODO: clang compatibility + target_compile_options(${COMPONENT_LIB} PUBLIC -Wimplicit-fallthrough=0 -Wno-shift-count-overflow) + endif() +else() + target_linker_script(${COMPONENT_LIB} INTERFACE "${target}/ld/${target}.rom.ld") + rom_linker_script("api") + rom_linker_script("libgcc") +endif() if(BOOTLOADER_BUILD) if(target STREQUAL "esp32") rom_linker_script("newlib-funcs") + if(NOT CONFIG_SPI_FLASH_ROM_DRIVER_PATCH) + rom_linker_script("spiflash") + endif() if(CONFIG_ESP32_REV_MIN_3) rom_linker_script("eco3") endif() diff --git a/components/esp_rom/esp32/ld/esp32.rom.api.ld b/components/esp_rom/esp32/ld/esp32.rom.api.ld index be023b85d3..afd3cc04eb 100644 --- a/components/esp_rom/esp32/ld/esp32.rom.api.ld +++ b/components/esp_rom/esp32/ld/esp32.rom.api.ld @@ -2,6 +2,11 @@ * ROM APIs */ +/* user may provide newer version of tjpgd */ +/* so here directly assign the symbols with the ROM API address to make sure one from rom is correctly linked */ +PROVIDE ( esp_rom_tjpgd_decomp = 0x400613e8 ); +PROVIDE ( esp_rom_tjpgd_prepare = 0x40060fa8 ); + PROVIDE ( esp_rom_crc32_le = crc32_le ); PROVIDE ( esp_rom_crc16_le = crc16_le ); PROVIDE ( esp_rom_crc8_le = crc8_le ); diff --git a/components/esp_rom/esp32c3/ld/esp32c3.rom.api.ld b/components/esp_rom/esp32c3/ld/esp32c3.rom.api.ld index 5530bf0dce..e05d9b8aa4 100644 --- a/components/esp_rom/esp32c3/ld/esp32c3.rom.api.ld +++ b/components/esp_rom/esp32c3/ld/esp32c3.rom.api.ld @@ -1,5 +1,11 @@ /** ROM APIs */ + +/* user may provide newer version of tjpgd */ +/* so here directly assign the symbols with the ROM API address to make sure one from rom is correctly linked */ +PROVIDE ( esp_rom_tjpgd_decomp = 0x40000108 ); +PROVIDE ( esp_rom_tjpgd_prepare = 0x40000104 ); + PROVIDE ( esp_rom_crc32_le = crc32_le ); PROVIDE ( esp_rom_crc16_le = crc16_le ); PROVIDE ( esp_rom_crc8_le = crc8_le ); diff --git a/components/esp_rom/esp32c3/ld/esp32c3.rom.ld b/components/esp_rom/esp32c3/ld/esp32c3.rom.ld index a146d8f39d..4b42f866e5 100644 --- a/components/esp_rom/esp32c3/ld/esp32c3.rom.ld +++ b/components/esp_rom/esp32c3/ld/esp32c3.rom.ld @@ -89,8 +89,8 @@ tinfl_decompress_mem_to_mem = 0x40000100; ***************************************/ /* Functions */ -jd_prepare = 0x40000104; -jd_decomp = 0x40000108; +PROVIDE( jd_prepare = 0x40000104 ); +PROVIDE( jd_decomp = 0x40000108 ); /*************************************** diff --git a/components/esp_rom/esp32h2/ld/esp32h2.rom.api.ld b/components/esp_rom/esp32h2/ld/esp32h2.rom.api.ld index 5530bf0dce..588ac6b179 100644 --- a/components/esp_rom/esp32h2/ld/esp32h2.rom.api.ld +++ b/components/esp_rom/esp32h2/ld/esp32h2.rom.api.ld @@ -1,5 +1,8 @@ /** ROM APIs */ +PROVIDE ( esp_rom_tjpgd_decomp = 0x40000104 ); +PROVIDE ( esp_rom_tjpgd_prepare = 0x40000100 ); + PROVIDE ( esp_rom_crc32_le = crc32_le ); PROVIDE ( esp_rom_crc16_le = crc16_le ); PROVIDE ( esp_rom_crc8_le = crc8_le ); diff --git a/components/esp_rom/esp32h2/ld/esp32h2.rom.ld b/components/esp_rom/esp32h2/ld/esp32h2.rom.ld index acd5821d5a..fefad99c3d 100644 --- a/components/esp_rom/esp32h2/ld/esp32h2.rom.ld +++ b/components/esp_rom/esp32h2/ld/esp32h2.rom.ld @@ -88,8 +88,8 @@ tinfl_decompress_mem_to_mem = 0x400000fc; ***************************************/ /* Functions */ -jd_prepare = 0x40000100; -jd_decomp = 0x40000104; +PROVIDE( jd_prepare = 0x40000100 ); +PROVIDE( jd_decomp = 0x40000104 ); /*************************************** diff --git a/components/esp_rom/esp32s2/ld/esp32s2.rom.newlib-funcs.ld b/components/esp_rom/esp32s2/ld/esp32s2.rom.newlib-funcs.ld index c859f655b4..fc976bbbaf 100644 --- a/components/esp_rom/esp32s2/ld/esp32s2.rom.newlib-funcs.ld +++ b/components/esp_rom/esp32s2/ld/esp32s2.rom.newlib-funcs.ld @@ -10,8 +10,8 @@ abs = 0x40000618; __ascii_mbtowc = 0x40007a04; __ascii_wctomb = 0x400018d0; -__assert = 0x4001a430; -__assert_func = 0x4001a408; +PROVIDE ( __assert = 0x4001a430 ); +PROVIDE ( __assert_func = 0x4001a408 ); bzero = 0x400078c8; _cleanup_r = 0x4001a480; creat = 0x4000788c; diff --git a/components/esp_rom/esp32s3/ld/esp32s3.rom.api.ld b/components/esp_rom/esp32s3/ld/esp32s3.rom.api.ld index 6d3b6d1b9f..4d45188393 100644 --- a/components/esp_rom/esp32s3/ld/esp32s3.rom.api.ld +++ b/components/esp_rom/esp32s3/ld/esp32s3.rom.api.ld @@ -2,6 +2,11 @@ * ROM APIs */ +/* user may provide newer version of tjpgd */ +/* so here directly assign the symbols with the ROM API address to make sure one from rom is correctly linked */ +PROVIDE ( esp_rom_tjpgd_decomp = 0x40000864 ); +PROVIDE ( esp_rom_tjpgd_prepare = 0x40000858 ); + PROVIDE ( esp_rom_crc32_le = crc32_le ); PROVIDE ( esp_rom_crc16_le = crc16_le ); PROVIDE ( esp_rom_crc8_le = crc8_le ); diff --git a/components/esp_rom/esp32s3/ld/esp32s3.rom.ld b/components/esp_rom/esp32s3/ld/esp32s3.rom.ld index 556b3eecc0..f78625b3b8 100644 --- a/components/esp_rom/esp32s3/ld/esp32s3.rom.ld +++ b/components/esp_rom/esp32s3/ld/esp32s3.rom.ld @@ -91,8 +91,8 @@ tinfl_decompress_mem_to_mem = 0x4000084c; ***************************************/ /* Functions */ -jd_prepare = 0x40000858; -jd_decomp = 0x40000864; +PROVIDE( jd_prepare = 0x40000858 ); +PROVIDE (jd_decomp = 0x40000864 ); /*************************************** diff --git a/components/esp_rom/host_test/rom_test/CMakeLists.txt b/components/esp_rom/host_test/rom_test/CMakeLists.txt new file mode 100644 index 0000000000..c84747fef4 --- /dev/null +++ b/components/esp_rom/host_test/rom_test/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +set(COMPONENTS main) +list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/mocks/freertos/") +project(test_rom_host) diff --git a/components/esp_rom/host_test/rom_test/README.md b/components/esp_rom/host_test/rom_test/README.md new file mode 100644 index 0000000000..4e99101c90 --- /dev/null +++ b/components/esp_rom/host_test/rom_test/README.md @@ -0,0 +1,37 @@ +| Supported Targets | Linux | +| ----------------- | ----- | + +# Simplest rom test on Linux target + +This unit test tests only if some of the supplied Linux functions seem to work correctly. The test framework is CATCH. + +## Requirements + +* A Linux system +* The usual IDF requirements for Linux system, as described in the [Getting Started Guides](../../../../docs/en/get-started/index.rst). +* The host's gcc/g++ + +This application has been tested on Ubuntu 20.04 with `gcc` version *9.3.0*. + +## Build + +First, make sure that the target is set to Linux. Run `idf.py --preview set-target linux` if you are not sure. Then do a normal IDF build: `idf.py build`. + +## Run + +IDF monitor doesn't work yet for Linux. You have to run the app manually: + +```bash +./build/test_rom_host.elf +``` + +## Example Output + +Ideally, all tests pass, which is indicated by "All tests passed" in the last line: + +```bash +$ ./build/test_rom_host.elf +test +=============================================================================== +All tests passed (8 assertions in 6 test cases) +``` diff --git a/components/esp_rom/host_test/rom_test/main/CMakeLists.txt b/components/esp_rom/host_test/rom_test/main/CMakeLists.txt new file mode 100644 index 0000000000..f0f082fde3 --- /dev/null +++ b/components/esp_rom/host_test/rom_test/main/CMakeLists.txt @@ -0,0 +1,5 @@ +idf_component_register(SRCS "rom_test.cpp" + INCLUDE_DIRS + "." + $ENV{IDF_PATH}/tools/catch + REQUIRES esp_rom) diff --git a/components/esp_rom/host_test/rom_test/main/rom_test.cpp b/components/esp_rom/host_test/rom_test/main/rom_test.cpp new file mode 100644 index 0000000000..3b9bd6a9d9 --- /dev/null +++ b/components/esp_rom/host_test/rom_test/main/rom_test.cpp @@ -0,0 +1,95 @@ +/* LOG unit tests + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. + + This is a very basic test to see whether the supplied linux functions appear to work correctly. + + Note that the printf function is roughly tested in the log host test. +*/ +#define CATCH_CONFIG_MAIN +#include +#include +#include +#include "esp_rom_sys.h" +#include "esp_rom_efuse.h" +#include "esp_rom_crc.h" +#include "esp_rom_md5.h" + +#include "catch.hpp" + +using namespace std; + +static const char *TEST_TAG = "test"; + +// ESP_LOG_EARLY functions are tested in the log host tests and also test rom printf. +TEST_CASE("esp_rom printf returns correct char num") +{ + CHECK(esp_rom_printf("test\n") == 5); +} + +TEST_CASE("delay works") +{ + const uint64_t DELAY = 100u; + struct timespec current_time; + CHECK(clock_gettime(CLOCK_MONOTONIC, ¤t_time) == 0); + uint64_t start_us = current_time.tv_sec * 1000000 + current_time.tv_nsec / 1000; + + esp_rom_delay_us(DELAY); + + CHECK(clock_gettime(CLOCK_MONOTONIC, ¤t_time) == 0); + uint64_t end_us = current_time.tv_sec * 1000000 + current_time.tv_nsec / 1000; + + CHECK(start_us + DELAY <= end_us); +} + +TEST_CASE("crc quick check") +{ + uint32_t expected_result = 0xd4dc5010; + uint32_t result; + const uint8_t original [] = {0x01, 0x21, 0x09, 0xff, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0x00, 0xff, 0xff, 0x06, 0xba, 0xe7, 0xa1}; + + result = esp_rom_crc32_le(0xffffffff, original, sizeof(original)); + + CHECK(result == expected_result); +} + +TEST_CASE("reset reason basic check") +{ + CHECK(esp_rom_get_reset_reason(0) == RESET_REASON_CHIP_POWER_ON); +} + +TEST_CASE("flash gpio info") +{ + CHECK(esp_rom_efuse_get_flash_gpio_info() == 0); +} + +TEST_CASE("get flash wp gpio") +{ + CHECK(esp_rom_efuse_get_flash_wp_gpio() == 0); +} + +TEST_CASE("secure boot always disabled on Linux") +{ + CHECK(esp_rom_efuse_is_secure_boot_enabled() == false); +} + +TEST_CASE("md5") +{ + md5_context_t context; + const uint8_t expected_result [16] = {0x00, 0x2e, 0x17, 0x69, 0x17, 0x24, 0x32, 0x78, 0x72, 0xf1, 0xaf, 0x42, 0x9f, 0x1c, 0xe4, 0xd9}; + uint8_t result [16] = {}; + const std::string MD5_TEST_STRING("This is an MD5 test"); + + esp_rom_md5_init(&context); + esp_rom_md5_update(&context, MD5_TEST_STRING.c_str(), MD5_TEST_STRING.size()); + esp_rom_md5_final(result, &context); + + for (int i = 0; i < 16; i++) { + CHECK(result[i] == expected_result[i]); + } +} diff --git a/components/esp_rom/host_test/rom_test/sdkconfig.defaults b/components/esp_rom/host_test/rom_test/sdkconfig.defaults new file mode 100644 index 0000000000..89c65632c9 --- /dev/null +++ b/components/esp_rom/host_test/rom_test/sdkconfig.defaults @@ -0,0 +1,3 @@ +CONFIG_IDF_TARGET="linux" +CONFIG_COMPILER_CXX_EXCEPTIONS=y +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=n diff --git a/components/esp_rom/include/esp32c3/rom/newlib.h b/components/esp_rom/include/esp32c3/rom/newlib.h deleted file mode 100644 index a852bdb7f5..0000000000 --- a/components/esp_rom/include/esp32c3/rom/newlib.h +++ /dev/null @@ -1,50 +0,0 @@ -// 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. -#pragma once - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* Global variables used by newlib in ROM - - Note that any of these symbols which are used by both ROM & IDF will have duplicate copies - in each "side" of the memory. However they're all pointers, and the pointers will be to the same - thing, so it's not a big memory waste and functionality is the same. - - Some variables which look like they should be here, but aren't: - - - __sf_fake_stdin, __sf_fake_stdout, __sf_fake_stderr - These are defined in ROM because ROM includes findfp.c, - but only used if _REENT_INIT or _REENT_INIT_PTR are ever called and ROM doesn't use these macros anywhere unless - printf() or similar is called without initializing reent first. ESP-IDF sets up its own minimal reent structures. - - - __lock___sinit_recursive_mutex, etc. - these are combined into common_recursive_mutex & common_mutex to save space -*/ -typedef struct { - _LOCK_T common_recursive_mutex; - _LOCK_T common_mutex; - struct _reent *global_reent; -} esp_rom_newlib_global_data_t; - -/* Called from IDF newlib component setup - to initialize common data shared between ROM and IDF -*/ -void esp_rom_newlib_init_global_data(const esp_rom_newlib_global_data_t *data); - -#ifdef __cplusplus -} -#endif diff --git a/components/esp_rom/include/esp32c3/rom/rtc.h b/components/esp_rom/include/esp32c3/rom/rtc.h index 76ece7e819..2a7f6cb614 100644 --- a/components/esp_rom/include/esp32c3/rom/rtc.h +++ b/components/esp_rom/include/esp32c3/rom/rtc.h @@ -85,8 +85,7 @@ typedef enum { NO_MEAN = 0, POWERON_RESET = 1, /**<1, Vbat power on reset*/ RTC_SW_SYS_RESET = 3, /**<3, Software reset digital core*/ - DEEPSLEEP_RESET = 5, /**<3, Deep Sleep reset digital core*/ - SDIO_RESET = 6, /**<6, Reset by SLC module, reset digital core*/ + DEEPSLEEP_RESET = 5, /**<5, Deep Sleep reset digital core*/ TG0WDT_SYS_RESET = 7, /**<7, Timer Group0 Watch dog reset digital core*/ TG1WDT_SYS_RESET = 8, /**<8, Timer Group1 Watch dog reset digital core*/ RTCWDT_SYS_RESET = 9, /**<9, RTC Watch dog Reset digital core*/ @@ -96,8 +95,13 @@ typedef enum { RTCWDT_CPU_RESET = 13, /**<13, RTC Watch dog Reset CPU*/ RTCWDT_BROWN_OUT_RESET = 15, /**<15, Reset when the vdd voltage is not stable*/ RTCWDT_RTC_RESET = 16, /**<16, RTC Watch dog reset digital core and rtc module*/ - TG1WDT_CPU_RESET = 17, /**<11, Time Group1 reset CPU*/ - SUPER_WDT_RESET = 18, /**<11, super watchdog reset digital core and rtc module*/ + TG1WDT_CPU_RESET = 17, /**<17, Time Group1 reset CPU*/ + SUPER_WDT_RESET = 18, /**<18, super watchdog reset digital core and rtc module*/ + GLITCH_RTC_RESET = 19, /**<19, glitch reset digital core and rtc module*/ + EFUSE_RESET = 20, /**<20, efuse reset digital core*/ + USB_UART_CHIP_RESET = 21, /**<21, usb uart reset digital core */ + USB_JTAG_CHIP_RESET = 22, /**<22, usb jtag reset digital core */ + POWER_GLITCH_RESET = 23, /**<23, power glitch reset digital core and rtc module*/ } RESET_REASON; // Check if the reset reason defined in ROM is compatible with soc/reset_reasons.h @@ -112,7 +116,13 @@ _Static_assert((soc_reset_reason_t)RTC_SW_CPU_RESET == RESET_REASON_CPU0_SW, "RT _Static_assert((soc_reset_reason_t)RTCWDT_CPU_RESET == RESET_REASON_CPU0_RTC_WDT, "RTCWDT_CPU_RESET != RESET_REASON_CPU0_RTC_WDT"); _Static_assert((soc_reset_reason_t)RTCWDT_BROWN_OUT_RESET == RESET_REASON_SYS_BROWN_OUT, "RTCWDT_BROWN_OUT_RESET != RESET_REASON_SYS_BROWN_OUT"); _Static_assert((soc_reset_reason_t)RTCWDT_RTC_RESET == RESET_REASON_SYS_RTC_WDT, "RTCWDT_RTC_RESET != RESET_REASON_SYS_RTC_WDT"); +_Static_assert((soc_reset_reason_t)TG1WDT_CPU_RESET == RESET_REASON_CPU0_MWDT1, "TG1WDT_CPU_RESET != RESET_REASON_CPU0_MWDT1"); _Static_assert((soc_reset_reason_t)SUPER_WDT_RESET == RESET_REASON_SYS_SUPER_WDT, "SUPER_WDT_RESET != RESET_REASON_SYS_SUPER_WDT"); +_Static_assert((soc_reset_reason_t)GLITCH_RTC_RESET == RESET_REASON_SYS_CLK_GLITCH, "GLITCH_RTC_RESET != RESET_REASON_SYS_CLK_GLITCH"); +_Static_assert((soc_reset_reason_t)EFUSE_RESET == RESET_REASON_CORE_EFUSE_CRC, "EFUSE_RESET != RESET_REASON_CORE_EFUSE_CRC"); +_Static_assert((soc_reset_reason_t)USB_UART_CHIP_RESET == RESET_REASON_CORE_USB_UART, "USB_UART_CHIP_RESET != RESET_REASON_CORE_USB_UART"); +_Static_assert((soc_reset_reason_t)USB_JTAG_CHIP_RESET == RESET_REASON_CORE_USB_JTAG, "USB_JTAG_CHIP_RESET != RESET_REASON_CORE_USB_JTAG"); +_Static_assert((soc_reset_reason_t)POWER_GLITCH_RESET == RESET_REASON_CORE_PWR_GLITCH, "POWER_GLITCH_RESET != RESET_REASON_CORE_PWR_GLITCH"); typedef enum { NO_SLEEP = 0, diff --git a/components/esp_rom/include/esp32h2/rom/newlib.h b/components/esp_rom/include/esp32h2/rom/newlib.h deleted file mode 100644 index a852bdb7f5..0000000000 --- a/components/esp_rom/include/esp32h2/rom/newlib.h +++ /dev/null @@ -1,50 +0,0 @@ -// 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. -#pragma once - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* Global variables used by newlib in ROM - - Note that any of these symbols which are used by both ROM & IDF will have duplicate copies - in each "side" of the memory. However they're all pointers, and the pointers will be to the same - thing, so it's not a big memory waste and functionality is the same. - - Some variables which look like they should be here, but aren't: - - - __sf_fake_stdin, __sf_fake_stdout, __sf_fake_stderr - These are defined in ROM because ROM includes findfp.c, - but only used if _REENT_INIT or _REENT_INIT_PTR are ever called and ROM doesn't use these macros anywhere unless - printf() or similar is called without initializing reent first. ESP-IDF sets up its own minimal reent structures. - - - __lock___sinit_recursive_mutex, etc. - these are combined into common_recursive_mutex & common_mutex to save space -*/ -typedef struct { - _LOCK_T common_recursive_mutex; - _LOCK_T common_mutex; - struct _reent *global_reent; -} esp_rom_newlib_global_data_t; - -/* Called from IDF newlib component setup - to initialize common data shared between ROM and IDF -*/ -void esp_rom_newlib_init_global_data(const esp_rom_newlib_global_data_t *data); - -#ifdef __cplusplus -} -#endif diff --git a/components/esp_rom/include/esp32h2/rom/rtc.h b/components/esp_rom/include/esp32h2/rom/rtc.h index 76ece7e819..ad4f45c2ca 100644 --- a/components/esp_rom/include/esp32h2/rom/rtc.h +++ b/components/esp_rom/include/esp32h2/rom/rtc.h @@ -85,8 +85,7 @@ typedef enum { NO_MEAN = 0, POWERON_RESET = 1, /**<1, Vbat power on reset*/ RTC_SW_SYS_RESET = 3, /**<3, Software reset digital core*/ - DEEPSLEEP_RESET = 5, /**<3, Deep Sleep reset digital core*/ - SDIO_RESET = 6, /**<6, Reset by SLC module, reset digital core*/ + DEEPSLEEP_RESET = 5, /**<5, Deep Sleep reset digital core*/ TG0WDT_SYS_RESET = 7, /**<7, Timer Group0 Watch dog reset digital core*/ TG1WDT_SYS_RESET = 8, /**<8, Timer Group1 Watch dog reset digital core*/ RTCWDT_SYS_RESET = 9, /**<9, RTC Watch dog Reset digital core*/ @@ -96,8 +95,14 @@ typedef enum { RTCWDT_CPU_RESET = 13, /**<13, RTC Watch dog Reset CPU*/ RTCWDT_BROWN_OUT_RESET = 15, /**<15, Reset when the vdd voltage is not stable*/ RTCWDT_RTC_RESET = 16, /**<16, RTC Watch dog reset digital core and rtc module*/ - TG1WDT_CPU_RESET = 17, /**<11, Time Group1 reset CPU*/ - SUPER_WDT_RESET = 18, /**<11, super watchdog reset digital core and rtc module*/ + TG1WDT_CPU_RESET = 17, /**<17, Time Group1 reset CPU*/ + SUPER_WDT_RESET = 18, /**<18, super watchdog reset digital core and rtc module*/ + GLITCH_RTC_RESET = 19, /**<19, glitch reset digital core and rtc module*/ + EFUSE_RESET = 20, /**<20, efuse reset digital core*/ + USB_UART_CHIP_RESET = 21, /**<21, usb uart reset digital core */ + USB_JTAG_CHIP_RESET = 22, /**<22, usb jtag reset digital core */ + POWER_GLITCH_RESET = 23, /**<23, power glitch reset digital core and rtc module*/ + JTAG_RESET = 24, /**<24, jtag reset CPU*/ } RESET_REASON; // Check if the reset reason defined in ROM is compatible with soc/reset_reasons.h @@ -112,7 +117,14 @@ _Static_assert((soc_reset_reason_t)RTC_SW_CPU_RESET == RESET_REASON_CPU0_SW, "RT _Static_assert((soc_reset_reason_t)RTCWDT_CPU_RESET == RESET_REASON_CPU0_RTC_WDT, "RTCWDT_CPU_RESET != RESET_REASON_CPU0_RTC_WDT"); _Static_assert((soc_reset_reason_t)RTCWDT_BROWN_OUT_RESET == RESET_REASON_SYS_BROWN_OUT, "RTCWDT_BROWN_OUT_RESET != RESET_REASON_SYS_BROWN_OUT"); _Static_assert((soc_reset_reason_t)RTCWDT_RTC_RESET == RESET_REASON_SYS_RTC_WDT, "RTCWDT_RTC_RESET != RESET_REASON_SYS_RTC_WDT"); +_Static_assert((soc_reset_reason_t)TG1WDT_CPU_RESET == RESET_REASON_CPU0_MWDT1, "TG1WDT_CPU_RESET != RESET_REASON_CPU0_MWDT1"); _Static_assert((soc_reset_reason_t)SUPER_WDT_RESET == RESET_REASON_SYS_SUPER_WDT, "SUPER_WDT_RESET != RESET_REASON_SYS_SUPER_WDT"); +_Static_assert((soc_reset_reason_t)GLITCH_RTC_RESET == RESET_REASON_SYS_CLK_GLITCH, "GLITCH_RTC_RESET != RESET_REASON_SYS_CLK_GLITCH"); +_Static_assert((soc_reset_reason_t)EFUSE_RESET == RESET_REASON_CORE_EFUSE_CRC, "EFUSE_RESET != RESET_REASON_CORE_EFUSE_CRC"); +_Static_assert((soc_reset_reason_t)USB_UART_CHIP_RESET == RESET_REASON_CORE_USB_UART, "USB_UART_CHIP_RESET != RESET_REASON_CORE_USB_UART"); +_Static_assert((soc_reset_reason_t)USB_JTAG_CHIP_RESET == RESET_REASON_CORE_USB_JTAG, "USB_JTAG_CHIP_RESET != RESET_REASON_CORE_USB_JTAG"); +_Static_assert((soc_reset_reason_t)POWER_GLITCH_RESET == RESET_REASON_CORE_PWR_GLITCH, "POWER_GLITCH_RESET != RESET_REASON_CORE_PWR_GLITCH"); +_Static_assert((soc_reset_reason_t)JTAG_RESET == RESET_REASON_CPU_JTAG, "JTAG_RESET != RESET_REASON_CPU_JTAG"); typedef enum { NO_SLEEP = 0, diff --git a/components/esp_rom/include/esp32s3/rom/apb_backup_dma.h b/components/esp_rom/include/esp32s3/rom/apb_backup_dma.h new file mode 100644 index 0000000000..324135cb83 --- /dev/null +++ b/components/esp_rom/include/esp32s3/rom/apb_backup_dma.h @@ -0,0 +1,17 @@ +/* + * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +void ets_apb_backup_init_lock_func(void(* _apb_backup_lock)(void), void(* _apb_backup_unlock)(void)); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_rom/include/esp32s3/rom/cache.h b/components/esp_rom/include/esp32s3/rom/cache.h index 0ec6308f7c..27780446fe 100644 --- a/components/esp_rom/include/esp32s3/rom/cache.h +++ b/components/esp_rom/include/esp32s3/rom/cache.h @@ -103,6 +103,11 @@ typedef enum { CACHE_AUTOLOAD_NEGATIVE = 1, /*!< cache autoload step is negative */ } cache_autoload_order_t; +typedef enum { + CACHE_AUTOLOAD_REGION0 = 0, /*!< cache autoload region0 */ + CACHE_AUTOLOAD_REGION1 = 1, /*!< cache autoload region1 */ +} cache_autoload_region_t; + #define CACHE_AUTOLOAD_STEP(i) ((i) - 1) typedef enum { @@ -144,14 +149,17 @@ struct dcache_tag_item { }; struct autoload_config { + uint8_t ena; /*!< autoload enable */ uint8_t order; /*!< autoload step is positive or negative */ uint8_t trigger; /*!< autoload trigger */ - uint8_t ena0; /*!< autoload region0 enable */ - uint8_t ena1; /*!< autoload region1 enable */ - uint32_t addr0; /*!< autoload region0 start address */ - uint32_t size0; /*!< autoload region0 size */ - uint32_t addr1; /*!< autoload region1 start address */ - uint32_t size1; /*!< autoload region1 size */ + uint8_t size; /*!< autoload size */ +}; + +struct autoload_region_config { + uint8_t region; /*!< autoload region*/ + uint8_t ena; /*!< autoload region enable */ + uint32_t addr; /*!< autoload region start address */ + uint32_t size; /*!< autoload region size */ }; struct tag_group_info { @@ -160,6 +168,7 @@ struct tag_group_info { uint32_t vaddr_offset; /*!< virtual address offset of the cache ways */ uint32_t tag_addr[MAX_CACHE_WAYS]; /*!< tag memory address, only [0~mode.ways-1] is valid to use */ uint32_t cache_memory_offset[MAX_CACHE_WAYS]; /*!< cache memory address, only [0~mode.ways-1] is valid to use */ + uint8_t use_legacy; /*!< 1 for using legacy tag api, 0 for using 2rd tag api */ }; struct lock_config { @@ -168,6 +177,39 @@ struct lock_config { uint16_t group; /*!< manual lock group, 0 or 1*/ }; +struct cache_internal_stub_table { + uint32_t (* icache_line_size)(void); + uint32_t (* dcache_line_size)(void); + uint32_t (* icache_addr)(uint32_t addr); + uint32_t (* dcache_addr)(uint32_t addr); + void (* invalidate_icache_items)(uint32_t addr, uint32_t items); + void (* invalidate_dcache_items)(uint32_t addr, uint32_t items); + void (* clean_items)(uint32_t addr, uint32_t items); + void (* writeback_items)(uint32_t addr, uint32_t items); + void (* lock_icache_items)(uint32_t addr, uint32_t items); + void (* lock_dcache_items)(uint32_t addr, uint32_t items); + void (* unlock_icache_items)(uint32_t addr, uint32_t items); + void (* unlock_dcache_items)(uint32_t addr, uint32_t items); + void (* occupy_items)(uint32_t addr, uint32_t items); + uint32_t (* suspend_icache_autoload)(void); + void (* resume_icache_autoload)(uint32_t autoload); + uint32_t (* suspend_dcache_autoload)(void); + void (* resume_dcache_autoload)(uint32_t autoload); + void (* freeze_icache_enable)(cache_freeze_mode_t mode); + void (* freeze_icache_disable)(void); + void (* freeze_dcache_enable)(cache_freeze_mode_t mode); + void (* freeze_dcache_disable)(void); + int (* op_addr)(uint32_t op_icache, uint32_t start_addr, uint32_t size, uint32_t cache_line_size, uint32_t max_sync_num, void(* cache_Iop)(uint32_t, uint32_t), void(* cache_Dop)(uint32_t, uint32_t)); +}; + +typedef void (* cache_op_start)(void); +typedef void (* cache_op_end)(void); + +typedef struct { + cache_op_start start; + cache_op_end end; +} cache_op_cb_t; + #define ESP_ROM_ERR_INVALID_ARG 1 #define MMU_SET_ADDR_ALIGNED_ERROR 2 #define MMU_SET_PASE_SIZE_ERROR 3 @@ -190,7 +232,7 @@ void Cache_MMU_Init(void); * @brief Set ICache mmu mapping. * Please do not call this function in your SDK application. * - * @param uint32_t ext_ram : DPORT_MMU_ACCESS_FLASH for flash, DPORT_MMU_ACCESS_SPIRAM for spiram, DPORT_MMU_INVALID for invalid. + * @param uint32_t ext_ram : MMU_ACCESS_FLASH for flash, MMU_ACCESS_SPIRAM for spiram, MMU_INVALID for invalid. * * @param uint32_t vaddr : virtual address in CPU address space. * Can be Iram0,Iram1,Irom0,Drom0 and AHB buses address. @@ -217,7 +259,7 @@ int Cache_Ibus_MMU_Set(uint32_t ext_ram, uint32_t vaddr, uint32_t paddr, uint32 * @brief Set DCache mmu mapping. * Please do not call this function in your SDK application. * - * @param uint32_t ext_ram : DPORT_MMU_ACCESS_FLASH for flash, DPORT_MMU_ACCESS_SPIRAM for spiram, DPORT_MMU_INVALID for invalid. + * @param uint32_t ext_ram : MMU_ACCESS_FLASH for flash, MMU_ACCESS_SPIRAM for spiram, MMU_INVALID for invalid. * * @param uint32_t vaddr : virtual address in CPU address space. * Can be DRam0, DRam1, DRom0, DPort and AHB buses address. @@ -272,9 +314,9 @@ uint32_t Cache_Flash_To_SPIRAM_Copy(uint32_t bus, uint32_t bus_start_addr, uint3 * @brief allocate memory to used by ICache. * Please do not call this function in your SDK application. * - * @param cache_array_t icache_low : the data array bank used by icache low part, can be CACHE_MEMORY_INVALID, CACHE_MEMORY_IBANK0, CACHE_MEMORY_IBANK1 + * @param cache_array_t icache_low : the data array bank used by icache low part. Due to timing constraint, can only be CACHE_MEMORY_INVALID, CACHE_MEMORY_IBANK0 * - * @param cache_array_t icache_high : the data array bank used by icache high part, can be CACHE_MEMORY_INVALID, CACHE_MEMORY_IBANK0, CACHE_MEMORY_IBANK1 only if icache_low and icache_high is not CACHE_MEMORY_INVALID + * @param cache_array_t icache_high : the data array bank used by icache high part. Due to timing constraint, can only be CACHE_MEMORY_INVALID, or CACHE_MEMORY_IBANK1 only if icache_low and icache_high is CACHE_MEMORY_IBANK0 * * return none */ @@ -284,9 +326,9 @@ void Cache_Occupy_ICache_MEMORY(cache_array_t icache_low, cache_array_t icache_h * @brief allocate memory to used by DCache. * Please do not call this function in your SDK application. * - * @param cache_array_t dcache_low : the data array bank used by dcache low part, can be CACHE_MEMORY_INVALID, CACHE_MEMORY_DBANK0, CACHE_MEMORY_DBANK1 + * @param cache_array_t dcache_low : the data array bank used by dcache low part. Due to timing constraint, can only be CACHE_MEMORY_INVALID, CACHE_MEMORY_DBANK1 * - * @param cache_array_t dcache1_high : the data array bank used by dcache high part, can be CACHE_MEMORY_INVALID, CACHE_MEMORY_DBANK0, CACHE_MEMORY_DBANK1 only if dcache_low0 and dcache_low1 is not CACHE_MEMORY_INVALID + * @param cache_array_t dcache1_high : the data array bank used by dcache high part. Due to timing constraint, can only be CACHE_MEMORY_INVALID, or CACHE_MEMORY_DBANK0 only if dcache_low0 and dcache_low1 is CACHE_MEMORY_DBANK1 * * return none */ @@ -310,7 +352,7 @@ void Cache_Get_Mode(struct cache_mode *mode); * * @param cache_ways_t ways : the associate ways of cache, can be CACHE_4WAYS_ASSOC and CACHE_8WAYS_ASSOC * - * @param cache_line_size_t cache_line_size : the cache line size, can be CACHE_LINE_SIZE_16B, CACHE_LINE_SIZE_32B and CACHE_LINE_SIZE_64B + * @param cache_line_size_t cache_line_size : the cache line size, can be CACHE_LINE_SIZE_16B and CACHE_LINE_SIZE_32B * * return none */ @@ -320,9 +362,9 @@ void Cache_Set_ICache_Mode(cache_size_t cache_size, cache_ways_t ways, cache_lin * @brief set DCache modes: cache size, associate ways and cache line size. * Please do not call this function in your SDK application. * - * @param cache_size_t cache_size : the cache size, can be CACHE_SIZE_8KB and CACHE_SIZE_16KB + * @param cache_size_t cache_size : the cache size, can be CACHE_SIZE_HALF and CACHE_SIZE_FULL * - * @param cache_ways_t ways : the associate ways of cache, can be CACHE_4WAYS_ASSOC and CACHE_8WAYS_ASSOC + * @param cache_ways_t ways : the associate ways of cache, can be CACHE_4WAYS_ASSOC and CACHE_8WAYS_ASSOC, only CACHE_4WAYS_ASSOC works * * @param cache_line_size_t cache_line_size : the cache line size, can be CACHE_LINE_SIZE_16B, CACHE_LINE_SIZE_32B and CACHE_LINE_SIZE_64B * @@ -351,7 +393,7 @@ uint32_t Cache_Address_Through_ICache(uint32_t addr); uint32_t Cache_Address_Through_DCache(uint32_t addr); /** - * @brief Init mmu owner register to make i/d cache use half mmu entries. + * @brief Init Cache for ROM boot, including resetting the Dcache, initializing Owner, MMU, setting DCache mode, Enabling DCache, unmasking bus. * * @param None * @@ -636,6 +678,16 @@ void Cache_End_DCache_Preload(uint32_t autoload); */ void Cache_Config_ICache_Autoload(const struct autoload_config *config); +/** + * @brief Config region autoload parameters of ICache. + * Please do not call this function in your SDK application. + * + * @param struct autoload_region_config * config : region autoload parameters. + * + * @return ESP_ROM_ERR_INVALID_ARG : invalid param, 0 : success + */ +int Cache_Config_ICache_Region_Autoload(const struct autoload_region_config *config); + /** * @brief Enable auto preload for ICache. * Please do not call this function in your SDK application. @@ -666,6 +718,16 @@ void Cache_Disable_ICache_Autoload(void); */ void Cache_Config_DCache_Autoload(const struct autoload_config *config); +/** + * @brief Config region autoload parameters of DCache. + * Please do not call this function in your SDK application. + * + * @param struct autoload_region_config * config : region autoload parameters. + * + * @return ESP_ROM_ERR_INVALID_ARG : invalid param, 0 : success + */ +int Cache_Config_DCache_Region_Autoload(const struct autoload_region_config *config); + /** * @brief Enable auto preload for DCache. * Please do not call this function in your SDK application. @@ -1008,7 +1070,24 @@ void Cache_Freeze_DCache_Disable(void); * * @return None */ -void Cache_Travel_Tag_Memory(struct cache_mode *mode, uint32_t filter_addr, void (* process)(struct tag_group_info *)); +void Cache_Travel_Tag_Memory(struct cache_mode * mode, uint32_t filter_addr, void (* process)(struct tag_group_info *)); + +/** + * @brief Travel tag memory to run a call back function, using 2nd tag registers. + * ICache and DCache are suspend when doing this. + * The callback will get the parameter tag_group_info, which will include a group of tag memory addresses and cache memory addresses. + * Please do not call this function in your SDK application. + * + * @param struct cache_mode * mode : the cache to check and the cache mode. + * + * @param uint32_t filter_addr : only the cache lines which may include the filter_address will be returned to the call back function. + * 0 for do not filter, all cache lines will be returned. + * + * @param void (* process)(struct tag_group_info *) : call back function, which may be called many times, a group(the addresses in the group are in the same position in the cache ways) a time. + * + * @return None + */ +void Cache_Travel_Tag_Memory2(struct cache_mode * mode, uint32_t filter_addr, void (* process)(struct tag_group_info *)); /** * @brief Get the virtual address from cache mode, cache tag and the virtual address offset of cache ways. @@ -1092,6 +1171,8 @@ int flash2spiram_rodata_offset(void); uint32_t flash_instr_rodata_start_page(uint32_t bus); uint32_t flash_instr_rodata_end_page(uint32_t bus); +extern struct cache_internal_stub_table* rom_cache_internal_table_ptr; +extern cache_op_cb_t rom_cache_op_cb; #ifdef __cplusplus } #endif diff --git a/components/esp_rom/include/esp32s3/rom/rsa_pss.h b/components/esp_rom/include/esp32s3/rom/rsa_pss.h index b9ced67a1a..71ae589226 100644 --- a/components/esp_rom/include/esp32s3/rom/rsa_pss.h +++ b/components/esp_rom/include/esp32s3/rom/rsa_pss.h @@ -32,7 +32,7 @@ typedef struct { uint32_t mdash; } ets_rsa_pubkey_t; -bool ets_rsa_pss_verify(const ets_rsa_pubkey_t *key, const uint8_t *sig, const uint8_t *digest); +bool ets_rsa_pss_verify(const ets_rsa_pubkey_t *key, const uint8_t *sig, const uint8_t *digest, uint8_t *verified_digest); void ets_mgf1_sha256(const uint8_t *mgfSeed, size_t seedLen, size_t maskLen, uint8_t *mask); diff --git a/components/esp_rom/include/esp32s3/rom/rtc.h b/components/esp_rom/include/esp32s3/rom/rtc.h index 09d2376ef3..d928c4dee4 100644 --- a/components/esp_rom/include/esp32s3/rom/rtc.h +++ b/components/esp_rom/include/esp32s3/rom/rtc.h @@ -92,6 +92,9 @@ typedef enum { SUPER_WDT_RESET = 18, /**<18, super watchdog reset digital core and rtc module*/ GLITCH_RTC_RESET = 19, /**<19, glitch reset digital core and rtc module*/ EFUSE_RESET = 20, /**<20, efuse reset digital core*/ + USB_UART_CHIP_RESET = 21, /**<21, usb uart reset digital core */ + USB_JTAG_CHIP_RESET = 22, /**<22, usb jtag reset digital core */ + POWER_GLITCH_RESET = 23, /**<23, power glitch reset digital core and rtc module*/ } RESET_REASON; // Check if the reset reason defined in ROM is compatible with soc/reset_reasons.h @@ -106,9 +109,13 @@ _Static_assert((soc_reset_reason_t)RTC_SW_CPU_RESET == RESET_REASON_CPU0_SW, "RT _Static_assert((soc_reset_reason_t)RTCWDT_CPU_RESET == RESET_REASON_CPU0_RTC_WDT, "RTCWDT_CPU_RESET != RESET_REASON_CPU0_RTC_WDT"); _Static_assert((soc_reset_reason_t)RTCWDT_BROWN_OUT_RESET == RESET_REASON_SYS_BROWN_OUT, "RTCWDT_BROWN_OUT_RESET != RESET_REASON_SYS_BROWN_OUT"); _Static_assert((soc_reset_reason_t)RTCWDT_RTC_RESET == RESET_REASON_SYS_RTC_WDT, "RTCWDT_RTC_RESET != RESET_REASON_SYS_RTC_WDT"); +_Static_assert((soc_reset_reason_t)TG1WDT_CPU_RESET == RESET_REASON_CPU0_MWDT1, "TG1WDT_CPU_RESET != RESET_REASON_CPU0_MWDT1"); _Static_assert((soc_reset_reason_t)SUPER_WDT_RESET == RESET_REASON_SYS_SUPER_WDT, "SUPER_WDT_RESET != RESET_REASON_SYS_SUPER_WDT"); _Static_assert((soc_reset_reason_t)GLITCH_RTC_RESET == RESET_REASON_SYS_CLK_GLITCH, "GLITCH_RTC_RESET != RESET_REASON_SYS_CLK_GLITCH"); _Static_assert((soc_reset_reason_t)EFUSE_RESET == RESET_REASON_CORE_EFUSE_CRC, "EFUSE_RESET != RESET_REASON_CORE_EFUSE_CRC"); +_Static_assert((soc_reset_reason_t)USB_UART_CHIP_RESET == RESET_REASON_CORE_USB_UART, "USB_UART_CHIP_RESET != RESET_REASON_CORE_USB_UART"); +_Static_assert((soc_reset_reason_t)USB_JTAG_CHIP_RESET == RESET_REASON_CORE_USB_JTAG, "USB_JTAG_CHIP_RESET != RESET_REASON_CORE_USB_JTAG"); +_Static_assert((soc_reset_reason_t)POWER_GLITCH_RESET == RESET_REASON_CORE_PWR_GLITCH, "POWER_GLITCH_RESET != RESET_REASON_CORE_PWR_GLITCH"); typedef enum { NO_SLEEP = 0, diff --git a/components/esp_rom/include/esp_rom_sys.h b/components/esp_rom/include/esp_rom_sys.h index 9bf73adea5..946cb7af79 100644 --- a/components/esp_rom/include/esp_rom_sys.h +++ b/components/esp_rom/include/esp_rom_sys.h @@ -13,7 +13,7 @@ // limitations under the License. #pragma once - +#include "sdkconfig.h" #include #include "soc/reset_reasons.h" diff --git a/components/esp_rom/include/esp_rom_tjpgd.h b/components/esp_rom/include/esp_rom_tjpgd.h new file mode 100644 index 0000000000..318519ba74 --- /dev/null +++ b/components/esp_rom/include/esp_rom_tjpgd.h @@ -0,0 +1,152 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/*-----------------------------------------------------------------------------/ +/ TJpgDec - Tiny JPEG Decompressor R0.01b (C)ChaN, 2012 +/-----------------------------------------------------------------------------/ +/ The TJpgDec is a generic JPEG decompressor module for tiny embedded systems. +/ This is a free software that opened for education, research and commercial +/ developments under license policy of following terms. +/ +/ Copyright (C) 2012, ChaN, all right reserved. +/ +/ * The TJpgDec module is a free software and there is NO WARRANTY. +/ * No restriction on use. You can use, modify and redistribute it for +/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY. +/ * Redistributions of source code must retain the above copyright notice. +/ +/-----------------------------------------------------------------------------*/ + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Error code */ +typedef enum { + JDR_OK = 0, /* 0: Succeeded */ + JDR_INTR, /* 1: Interrupted by output function */ + JDR_INP, /* 2: Device error or wrong termination of input stream */ + JDR_MEM1, /* 3: Insufficient memory pool for the image */ + JDR_MEM2, /* 4: Insufficient stream input buffer */ + JDR_PAR, /* 5: Parameter error */ + JDR_FMT1, /* 6: Data format error (may be damaged data) */ + JDR_FMT2, /* 7: Right format but not supported */ + JDR_FMT3 /* 8: Not supported JPEG standard */ +} esp_rom_tjpgd_result_t; + +/* Rectangular structure */ +typedef struct { + uint16_t left; /* Left end */ + uint16_t right; /* Right end */ + uint16_t top; /* Top end */ + uint16_t bottom;/* Bottom end */ +} esp_rom_tjpgd_rect_t; + +typedef struct JDEC_s esp_rom_tjpgd_dec_t; + +/** + * @brief Type of user defined input function to read data from input stream + * @param dec Specifies the decompression object of the decompression session + * @param buffer Specifies the pointer to the read buffer to store the read data. A NULL specifies to remove the data from input stream + * @param ndata Specifies number of bytes to read/remove from the input stream + * + * @return number of bytes read/removed. When a zero is returned, the esp_rom_tjpgd_prepare and esp_rom_tjpgd_decomp function aborts with JDR_INP + */ +typedef uint32_t (*esp_rom_tjpgd_input_function_t)(esp_rom_tjpgd_dec_t *dec, uint8_t *buffer, uint32_t ndata); + +/** + * @brief User defined output function to write decompressed pixels to the output device + * + * This function is the data output interface of the TJpgDec module. + * The corresponding decompression session can be identified by the pointer to the device identifier jdec->device passed to the 5th argument of jd_prepare function. + * The bitmap is sent to the frame buffer or display device in this function. + * The first pixel in the bitmap is the left-top of the rectangular, the second one is next right and last pixel is the bottom-right of the rectangular. + * The size of rectangular varies from 1x1 to 16x16 depends on clipping, scaling and sampling factor of the image. + * If the rectangular is out of the frame buffer, it should be clipped in this function. + * + * The pixel format is currently configured to RGB888 + * + * @param dec Specifies the decompression object of the decompression session + * @param bitmap Specifies the RGB bitmap to be output + * @param rect Specifies rectangular region in the image to output the RGB bitmap + * + * @return Normally returns 1. It lets TJpgDec to continue the decompressing process. + * When a 0 is returned, the esp_rom_tjpgd_decomp function aborts with JDR_INTR. + * This is useful to interrupt the decompression process + */ +typedef uint32_t (*esp_rom_tjpgd_output_function_t)(esp_rom_tjpgd_dec_t *dec, void *bitmap, esp_rom_tjpgd_rect_t *rect); + +struct JDEC_s { + uint32_t dctr; /* Number of bytes available in the input buffer */ + uint8_t *dptr; /* Current data read ptr */ + uint8_t *inbuf; /* Bit stream input buffer */ + uint8_t dmsk; /* Current bit in the current read byte */ + uint8_t scale; /* Output scaling ratio */ + uint8_t msx, msy; /* MCU size in unit of block (width, height) */ + uint8_t qtid[3]; /* Quantization table ID of each component */ + int16_t dcv[3]; /* Previous DC element of each component */ + uint16_t nrst; /* Restart inverval */ + uint32_t width, height; /* Size of the input image (pixel) */ + uint8_t *huffbits[2][2]; /* Huffman bit distribution tables [id][dcac] */ + uint16_t *huffcode[2][2]; /* Huffman code word tables [id][dcac] */ + uint8_t *huffdata[2][2]; /* Huffman decoded data tables [id][dcac] */ + int32_t *qttbl[4]; /* Dequaitizer tables [id] */ + void *workbuf; /* Working buffer for IDCT and RGB output */ + uint8_t *mcubuf; /* Working buffer for the MCU */ + void *pool; /* Pointer to available memory pool */ + uint32_t sz_pool; /* Size of momory pool (bytes available) */ + esp_rom_tjpgd_input_function_t infunc; /* Pointer to jpeg stream input function */ + void *device; /* Pointer to I/O device identifiler for the session */ +}; + +/* TJpgDec API functions */ + +/** + * @brief Analyzes the JPEG data and create a decompression object for subsequent decompression process. + * @param dec Specifies the decompression object to be initialized. The decompression object is used for subsequent decompression process. + * @param infunc Specifies the user defined data input function. + * @param work Specifies pointer to the work area for this session. It should be aligned to word boundary or it can result an exception. + * @param sz_work Specifies size of the work area in unit of byte. + * TJpgDec requires upto 3092 bytes of work area depends on the built-in parameter tables of the JPEG image. + * Thus 3092 bytes of work area is sufficient for most case. + * @param dev Specifies pointer to the user defined device identifier for this session. + * It is stored to the member device in the decompression object. It can be referred by I/O functions to identify the current session. + * When I/O device is fixed in the project or this feature is not needed, set NULL and do not care about this. + * + * @return + * - JDR_OK Function succeeded and decompression object is valid. + * - JDR_INP An error occurred in input function due to hard error or wrong stream termination. + * - JDR_MEM1 Insufficient work area for this JPEG image. + * - JDR_MEM2 Insufficient input buffer for this JPEG image. JD_SZBUF may be too small. + * - JDR_PAR Parameter error. Given pointer to the work area is NULL. + * - JDR_FMT1 Data format error. The JPEG data can be collapsed. + * - JDR_FMT2 Right format but not supported. May be a grayscale image. + * - JDR_FMT3 Not supported JPEG standard. May be a progressive JPEG image. + */ +esp_rom_tjpgd_result_t esp_rom_tjpgd_prepare(esp_rom_tjpgd_dec_t *dec, esp_rom_tjpgd_input_function_t infunc, void *work, uint32_t sz_work, void *dev); + +/** + * @brief Decompress the JPEG image and output it as RGB data. + * @param dec Specifies the valid decompressor object. + * @param outfunc Specifies the user defined data output function. The esp_rom_tjpgd_decomp function calls this function to output the decompressed JPEG image in RGB form. + * @param scale Specifies scaling factor N for output. The output image is descaled to 1 / 2 ^ N (N = 0 to 3). + * + * @return + * - JDR_OK Function succeeded. + * - JDR_INTR The decompression process is interrupted by output function. + * - JDR_INP An error occured in input function due to hard error or wrong stream termination. + * - JDR_PAR Parameter error. Given scale factor is invalid. + * - JDR_FMT1 Data format error. The JPEG data can be collapted. + */ +esp_rom_tjpgd_result_t esp_rom_tjpgd_decomp(esp_rom_tjpgd_dec_t *dec, esp_rom_tjpgd_output_function_t outfunc, uint8_t scale); + +#ifdef __cplusplus +} +#endif diff --git a/components/nvs_flash/mock/int/crc.h b/components/esp_rom/include/linux/soc/reset_reasons.h similarity index 60% rename from components/nvs_flash/mock/int/crc.h rename to components/esp_rom/include/linux/soc/reset_reasons.h index bbb581f436..7cc86ffddf 100644 --- a/components/nvs_flash/mock/int/crc.h +++ b/components/esp_rom/include/linux/soc/reset_reasons.h @@ -1,9 +1,9 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// Copyright 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 @@ -11,24 +11,21 @@ // 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. -#ifndef crc_h -#define crc_h -#include +#pragma once #ifdef __cplusplus extern "C" { #endif /** - * Mock function to replace ESP ROM function used in IDF with a Linux implementation. - * Note: the name MUST have the prefix esp_rom_* since tools/ci/check_api_violation.sh checks and complains otherwise. + * @brief Dummy to satisfy the requirement for this type on Linux targets. + * Look at other reset_reasons.h files in IDF. */ -uint32_t esp_rom_crc32_le(uint32_t crc, const uint8_t* buf, size_t len); +typedef enum { + RESET_REASON_CHIP_POWER_ON = 0x01, // Power on reset +} soc_reset_reason_t; #ifdef __cplusplus } #endif - - -#endif /* crc_h */ diff --git a/components/esp_rom/linux/esp_rom_crc.c b/components/esp_rom/linux/esp_rom_crc.c new file mode 100644 index 0000000000..2454118fe0 --- /dev/null +++ b/components/esp_rom/linux/esp_rom_crc.c @@ -0,0 +1,226 @@ +// 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. + +#include "esp_rom_crc.h" + +static const uint32_t crc32_le_table[256] = { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, + 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, + 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, + 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L, + 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, + 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL, + 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, + 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L, + 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, + 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L, + 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, + 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, + 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, + + 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L, + 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, + 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, + 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, + 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L, + 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, + 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL, + 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, + 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L, + 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, + 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, + 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, + 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL +}; + +static uint32_t crc32_be_table[256] = { + 0x00000000L, 0x04c11db7L, 0x09823b6eL, 0x0d4326d9L, 0x130476dcL, 0x17c56b6bL, 0x1a864db2L, 0x1e475005L, + 0x2608edb8L, 0x22c9f00fL, 0x2f8ad6d6L, 0x2b4bcb61L, 0x350c9b64L, 0x31cd86d3L, 0x3c8ea00aL, 0x384fbdbdL, + 0x4c11db70L, 0x48d0c6c7L, 0x4593e01eL, 0x4152fda9L, 0x5f15adacL, 0x5bd4b01bL, 0x569796c2L, 0x52568b75L, + 0x6a1936c8L, 0x6ed82b7fL, 0x639b0da6L, 0x675a1011L, 0x791d4014L, 0x7ddc5da3L, 0x709f7b7aL, 0x745e66cdL, + 0x9823b6e0L, 0x9ce2ab57L, 0x91a18d8eL, 0x95609039L, 0x8b27c03cL, 0x8fe6dd8bL, 0x82a5fb52L, 0x8664e6e5L, + 0xbe2b5b58L, 0xbaea46efL, 0xb7a96036L, 0xb3687d81L, 0xad2f2d84L, 0xa9ee3033L, 0xa4ad16eaL, 0xa06c0b5dL, + 0xd4326d90L, 0xd0f37027L, 0xddb056feL, 0xd9714b49L, 0xc7361b4cL, 0xc3f706fbL, 0xceb42022L, 0xca753d95L, + 0xf23a8028L, 0xf6fb9d9fL, 0xfbb8bb46L, 0xff79a6f1L, 0xe13ef6f4L, 0xe5ffeb43L, 0xe8bccd9aL, 0xec7dd02dL, + 0x34867077L, 0x30476dc0L, 0x3d044b19L, 0x39c556aeL, 0x278206abL, 0x23431b1cL, 0x2e003dc5L, 0x2ac12072L, + 0x128e9dcfL, 0x164f8078L, 0x1b0ca6a1L, 0x1fcdbb16L, 0x018aeb13L, 0x054bf6a4L, 0x0808d07dL, 0x0cc9cdcaL, + 0x7897ab07L, 0x7c56b6b0L, 0x71159069L, 0x75d48ddeL, 0x6b93dddbL, 0x6f52c06cL, 0x6211e6b5L, 0x66d0fb02L, + 0x5e9f46bfL, 0x5a5e5b08L, 0x571d7dd1L, 0x53dc6066L, 0x4d9b3063L, 0x495a2dd4L, 0x44190b0dL, 0x40d816baL, + 0xaca5c697L, 0xa864db20L, 0xa527fdf9L, 0xa1e6e04eL, 0xbfa1b04bL, 0xbb60adfcL, 0xb6238b25L, 0xb2e29692L, + 0x8aad2b2fL, 0x8e6c3698L, 0x832f1041L, 0x87ee0df6L, 0x99a95df3L, 0x9d684044L, 0x902b669dL, 0x94ea7b2aL, + 0xe0b41de7L, 0xe4750050L, 0xe9362689L, 0xedf73b3eL, 0xf3b06b3bL, 0xf771768cL, 0xfa325055L, 0xfef34de2L, + 0xc6bcf05fL, 0xc27dede8L, 0xcf3ecb31L, 0xcbffd686L, 0xd5b88683L, 0xd1799b34L, 0xdc3abdedL, 0xd8fba05aL, + 0x690ce0eeL, 0x6dcdfd59L, 0x608edb80L, 0x644fc637L, 0x7a089632L, 0x7ec98b85L, 0x738aad5cL, 0x774bb0ebL, + 0x4f040d56L, 0x4bc510e1L, 0x46863638L, 0x42472b8fL, 0x5c007b8aL, 0x58c1663dL, 0x558240e4L, 0x51435d53L, + 0x251d3b9eL, 0x21dc2629L, 0x2c9f00f0L, 0x285e1d47L, 0x36194d42L, 0x32d850f5L, 0x3f9b762cL, 0x3b5a6b9bL, + 0x0315d626L, 0x07d4cb91L, 0x0a97ed48L, 0x0e56f0ffL, 0x1011a0faL, 0x14d0bd4dL, 0x19939b94L, 0x1d528623L, + 0xf12f560eL, 0xf5ee4bb9L, 0xf8ad6d60L, 0xfc6c70d7L, 0xe22b20d2L, 0xe6ea3d65L, 0xeba91bbcL, 0xef68060bL, + 0xd727bbb6L, 0xd3e6a601L, 0xdea580d8L, 0xda649d6fL, 0xc423cd6aL, 0xc0e2d0ddL, 0xcda1f604L, 0xc960ebb3L, + 0xbd3e8d7eL, 0xb9ff90c9L, 0xb4bcb610L, 0xb07daba7L, 0xae3afba2L, 0xaafbe615L, 0xa7b8c0ccL, 0xa379dd7bL, + 0x9b3660c6L, 0x9ff77d71L, 0x92b45ba8L, 0x9675461fL, 0x8832161aL, 0x8cf30badL, 0x81b02d74L, 0x857130c3L, + 0x5d8a9099L, 0x594b8d2eL, 0x5408abf7L, 0x50c9b640L, 0x4e8ee645L, 0x4a4ffbf2L, 0x470cdd2bL, 0x43cdc09cL, + 0x7b827d21L, 0x7f436096L, 0x7200464fL, 0x76c15bf8L, 0x68860bfdL, 0x6c47164aL, 0x61043093L, 0x65c52d24L, + 0x119b4be9L, 0x155a565eL, 0x18197087L, 0x1cd86d30L, 0x029f3d35L, 0x065e2082L, 0x0b1d065bL, 0x0fdc1becL, + 0x3793a651L, 0x3352bbe6L, 0x3e119d3fL, 0x3ad08088L, 0x2497d08dL, 0x2056cd3aL, 0x2d15ebe3L, 0x29d4f654L, + 0xc5a92679L, 0xc1683bceL, 0xcc2b1d17L, 0xc8ea00a0L, 0xd6ad50a5L, 0xd26c4d12L, 0xdf2f6bcbL, 0xdbee767cL, + 0xe3a1cbc1L, 0xe760d676L, 0xea23f0afL, 0xeee2ed18L, 0xf0a5bd1dL, 0xf464a0aaL, 0xf9278673L, 0xfde69bc4L, + 0x89b8fd09L, 0x8d79e0beL, 0x803ac667L, 0x84fbdbd0L, 0x9abc8bd5L, 0x9e7d9662L, 0x933eb0bbL, 0x97ffad0cL, + 0xafb010b1L, 0xab710d06L, 0xa6322bdfL, 0xa2f33668L, 0xbcb4666dL, 0xb8757bdaL, 0xb5365d03L, 0xb1f740b4L +}; + +static uint16_t crc16_le_table[256] = { + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48, 0x9dc1,0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 0x9cc9, 0x8d40,0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 0xad4a, 0xbcc3,0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 0xbdcb, 0xac42,0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 0xce4c, 0xdfc5,0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 0xdecd, 0xcf44,0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 0xef4e, 0xfec7,0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 0xffcf, 0xee46,0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 0x0840, 0x19c9,0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 0x18c1, 0x0948,0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 0x2942, 0x38cb,0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 0x39c3, 0x284a,0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 0x4a44, 0x5bcd,0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 0x5ac5, 0x4b4c,0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 0x6b46, 0x7acf,0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 0x7bc7, 0x6a4e,0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; + +static uint16_t crc16_be_table[256] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129,0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318,0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b,0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a,0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, + 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed,0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, + 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc,0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, + 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f,0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, + 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe,0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, + 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1,0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290,0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3,0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2,0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865,0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, + 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54,0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, + 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07,0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, + 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36,0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 +}; + +static uint8_t crc8_le_table[256] = { + 0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75, 0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b, + 0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69, 0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67, + 0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d, 0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43, + 0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51, 0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f, + 0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05, 0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b, + 0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19, 0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17, + 0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d, 0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33, + 0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21, 0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f, + + 0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95, 0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b, + 0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89, 0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87, + 0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad, 0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3, + 0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1, 0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf, + 0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5, 0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb, + 0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9, 0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7, + 0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd, 0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3, + 0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1, 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf +}; + +static uint8_t crc8_be_table[256] = { + 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d, + 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65, 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d, + 0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5, 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd, + 0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, 0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd, + 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2, 0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea, + 0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2, 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a, + 0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, 0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a, + 0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42, 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a, + 0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c, 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4, + 0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, 0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4, + 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c, 0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44, + 0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c, 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34, + 0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, 0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63, + 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b, 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13, + 0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb, 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83, + 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3 +}; + +uint32_t esp_rom_crc32_le(uint32_t crc, uint8_t const * buf,uint32_t len) +{ + uint32_t i; + crc = ~crc; + for(i=0;i>8); + } + return ~crc; +} + +uint32_t esp_rom_crc32_be(uint32_t crc, uint8_t const * buf,uint32_t len) +{ + uint32_t i; + crc = ~crc; + for(i=0;i>24)^buf[i]]^(crc<<8); + } + return ~crc; +} + +uint16_t esp_rom_crc16_le(uint16_t crc, uint8_t const * buf, uint32_t len) +{ + uint32_t i; + crc = ~crc; + for(i = 0; i < len; i++) + { + crc = crc16_le_table[(crc^buf[i])&0xff]^(crc>>8); + } + return ~crc; +} + +uint16_t esp_rom_crc16_be(uint16_t crc, uint8_t const * buf,uint32_t len) +{ + uint32_t i; + crc = ~crc; + for(i=0;i>8)^buf[i]]^(crc<<8); + } + return ~crc; +} + +uint8_t esp_rom_crc8_le(uint8_t crc, uint8_t const * buf, uint32_t len) +{ + uint32_t i; + crc = ~crc; + for(i = 0; i < len; i++) + { + crc = crc8_le_table[crc^buf[i]]; + } + return ~crc; +} + +uint8_t esp_rom_crc8_be(uint8_t crc, uint8_t const * buf,uint32_t len) +{ + uint32_t i; + crc = ~crc; + for(i=0;i> 1) ^ (0x8c) ; + } else { + crc = crc >> 1; + } + } + } + + return (crc); +} + +uint8_t esp_rom_efuse_mac_address_crc8(const uint8_t *data, uint32_t len) +{ + return esp_crc8(data, len); +} + +uint32_t esp_rom_efuse_get_flash_gpio_info(void) +{ + return 0; +} + +uint32_t esp_rom_efuse_get_flash_wp_gpio(void) +{ + return 0; +} + +bool esp_rom_efuse_is_secure_boot_enabled(void) +{ + return false; +} diff --git a/components/esp_rom/linux/esp_rom_md5.c b/components/esp_rom/linux/esp_rom_md5.c new file mode 100644 index 0000000000..ba8847f0ef --- /dev/null +++ b/components/esp_rom/linux/esp_rom_md5.c @@ -0,0 +1,246 @@ +/* + * MD5 hash implementation and interface functions + * Copyright (c) 2003-2005, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include +#include +#include "esp_rom_md5.h" + +static void byteReverse(unsigned char *buf, unsigned longs); +static void MD5Transform(uint32_t buf[4], uint32_t const in[16]); + +/* ===== start - public domain MD5 implementation ===== */ +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + */ + +void esp_rom_md5_init(md5_context_t *context) +{ + context->buf[0] = 0x67452301; + context->buf[1] = 0xefcdab89; + context->buf[2] = 0x98badcfe; + context->buf[3] = 0x10325476; + + context->bits[0] = 0; + context->bits[1] = 0; +} + +void esp_rom_md5_update(md5_context_t *context, const void *buf, uint32_t len) +{ + uint32_t t; + + /* Update bitcount */ + + t = context->bits[0]; + if ((context->bits[0] = t + ((uint32_t) len << 3)) < t) + context->bits[1]++; /* Carry from low to high */ + context->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + + if (t) { + unsigned char *p = (unsigned char *) context->in + t; + + t = 64 - t; + if (len < t) { + memcpy(p, buf, len); + return; + } + memcpy(p, buf, t); + byteReverse(context->in, 16); + MD5Transform(context->buf, (uint32_t *) context->in); + buf += t; + len -= t; + } + /* Process data in 64-byte chunks */ + + while (len >= 64) { + memcpy(context->in, buf, 64); + byteReverse(context->in, 16); + MD5Transform(context->buf, (uint32_t *) context->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + + memcpy(context->in, buf, len); +} + +void esp_rom_md5_final(uint8_t *digest, md5_context_t *context) +{ + unsigned count; + unsigned char *p; + + /* Compute number of bytes mod 64 */ + count = (context->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = context->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset(p, 0, count); + byteReverse(context->in, 16); + MD5Transform(context->buf, (uint32_t *) context->in); + + /* Now fill the next block with 56 bytes */ + memset(context->in, 0, 56); + } else { + /* Pad block to 56 bytes */ + memset(p, 0, count - 8); + } + byteReverse(context->in, 14); + + /* Append length in bits and transform */ + ((uint32_t *) context->in)[14] = context->bits[0]; + ((uint32_t *) context->in)[15] = context->bits[1]; + + MD5Transform(context->buf, (uint32_t *) context->in); + byteReverse((unsigned char *) context->buf, 4); + memcpy(digest, context->buf, 16); + memset(context, 0, sizeof(*context)); /* In case it's sensitive */ +} + +static void byteReverse(unsigned char *buf, unsigned longs) +{ + uint32_t t; + do { + t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 | + ((unsigned) buf[1] << 8 | buf[0]); + *(uint32_t *) buf = t; + buf += 4; + } while (--longs); +} + +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +static void MD5Transform(uint32_t buf[4], uint32_t const in[16]) +{ + register uint32_t a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} +/* ===== end - public domain MD5 implementation ===== */ diff --git a/components/esp_rom/linux/esp_rom_sys.c b/components/esp_rom/linux/esp_rom_sys.c new file mode 100644 index 0000000000..026e195cfe --- /dev/null +++ b/components/esp_rom/linux/esp_rom_sys.c @@ -0,0 +1,295 @@ +// 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. + +#include +#include +#include +#include +#include +#include +#include "esp_rom_sys.h" + +static void call_linux_putc(char c); + +static void (*s_esp_rom_putc)(char c) = call_linux_putc; + +static void call_linux_putc(char c) { + putc(c, stdout); +} + +#define is_digit(c) ((c >= '0') && (c <= '9')) + +static int _cvt(unsigned long long val, char *buf, long radix, char *digits) +{ +#ifdef SUPPORT_LITTLE_RADIX + char temp[64]; +#else + char temp[32]; +#endif + char *cp = temp; + int length = 0; + + if (val == 0) { + /* Special case */ + *cp++ = '0'; + } else { + while (val) { + *cp++ = digits[val % radix]; + val /= radix; + } + } + while (cp != temp) { + *buf++ = *--cp; + length++; + } + *buf = '\0'; + return (length); +} + +static int esp_rom_vprintf(void (*putc)(char c), const char *fmt, va_list ap) +{ +#ifdef BINARY_SUPPORT + char buf[sizeof(long long)*8]; + int i; +#else + char buf[32]; +#endif + char c, sign, *cp=buf; + int left_prec, right_prec, zero_fill, pad, pad_on_right, + islong, islonglong; + long long val = 0; + int res = 0, length = 0; + + while ((c = *fmt++) != '\0') { + if (c == '%') { + c = *fmt++; + left_prec = right_prec = pad_on_right = islong = islonglong = 0; + if (c == '-') { + c = *fmt++; + pad_on_right++; + } + if (c == '0') { + zero_fill = true; + c = *fmt++; + } else { + zero_fill = false; + } + while (is_digit(c)) { + left_prec = (left_prec * 10) + (c - '0'); + c = *fmt++; + } + if (c == '.') { + c = *fmt++; + zero_fill++; + while (is_digit(c)) { + right_prec = (right_prec * 10) + (c - '0'); + c = *fmt++; + } + } else { + right_prec = left_prec; + } + sign = '\0'; + if (c == 'l') { + c = *fmt++; + islong = 1; + if (c == 'l') { + c = *fmt++; + islonglong = 1; + } + } + switch (c) { + case 'p': + islong = 1; + case 'd': + case 'D': + case 'x': + case 'X': + case 'u': + case 'U': +#ifdef BINARY_SUPPORT + case 'b': + case 'B': +#endif + if (islonglong) { + val = va_arg(ap, long long); + } else if (islong) { + val = (long long)va_arg(ap, long); + } else{ + val = (long long)va_arg(ap, int); + } + if ((c == 'd') || (c == 'D')) { + if (val < 0) { + sign = '-'; + val = -val; + } + } else { + if (islong) { + val &= (((long long)1) << (sizeof(long) * 8)) - 1; + } else{ + val &= (((long long)1) << (sizeof(int) * 8)) - 1; + } + } + break; + default: + break; + } + + switch (c) { + case 'p': + (*putc)('0'); + (*putc)('x'); + zero_fill = true; + left_prec = sizeof(unsigned long)*2; + case 'd': + case 'D': + case 'u': + case 'U': + case 'x': + case 'X': + switch (c) { + case 'd': + case 'D': + case 'u': + case 'U': + length = _cvt(val, buf, 10, "0123456789"); + break; + case 'p': + case 'x': + length = _cvt(val, buf, 16, "0123456789abcdef"); + break; + case 'X': + length = _cvt(val, buf, 16, "0123456789ABCDEF"); + break; + } + cp = buf; + break; + case 's': + case 'S': + cp = va_arg(ap, char *); + if (cp == NULL) { + cp = ""; + } + length = 0; + while (cp[length] != '\0') length++; + break; + case 'c': + case 'C': + c = va_arg(ap, int /*char*/); + (*putc)(c); + res++; + continue; +#ifdef BINARY_SUPPORT + case 'b': + case 'B': + length = left_prec; + if (left_prec == 0) { + if (islonglong) + length = sizeof(long long)*8; + else if (islong) + length = sizeof(long)*8; + else + length = sizeof(int)*8; + } + for (i = 0; i < length-1; i++) { + buf[i] = ((val & ((long long)1< 0) { + (*putc)(c); + res++; + } + } + if (sign != '\0') { + (*putc)(sign); + res++; + } + while (length-- > 0) { + c = *cp++; + (*putc)(c); + res++; + } + if (pad_on_right) { + while (pad-- > 0) { + (*putc)(' '); + res++; + } + } + } else { + (*putc)(c); + res++; + } + } + return (res); +} + +int esp_rom_printf(const char *fmt, ...) +{ + + va_list list; + va_start(list, fmt); + int result = esp_rom_vprintf(s_esp_rom_putc, fmt, list); + va_end(list); + return result; +} + +void esp_rom_delay_us(uint32_t us) +{ + int sleep_result = usleep(us); + assert(sleep_result == 0); + (void)sleep_result; // Prevents compiler from optimizing out usleep() due to unused result. Also prevents warning. +} + +void esp_rom_install_channel_putc(int channel, void (*putc)(char c)) +{ + if (putc != NULL) { + s_esp_rom_putc = putc; + } +} + +void esp_rom_install_uart_printf(void) +{ + // Since this is the linux implementation, we don't set any "UART" putc function, but the one which delegates to + // the Linux libc version of putc. + s_esp_rom_putc = call_linux_putc; +} + +soc_reset_reason_t esp_rom_get_reset_reason(int cpu_no) +{ + return RESET_REASON_CHIP_POWER_ON; +} diff --git a/examples/peripherals/lcd/tjpgd/components/tjpgd/src/tjpgd.c b/components/esp_rom/patches/esp_rom_tjpgd.c similarity index 84% rename from examples/peripherals/lcd/tjpgd/components/tjpgd/src/tjpgd.c rename to components/esp_rom/patches/esp_rom_tjpgd.c index 276dc1932c..8e0b8d2713 100644 --- a/examples/peripherals/lcd/tjpgd/components/tjpgd/src/tjpgd.c +++ b/components/esp_rom/patches/esp_rom_tjpgd.c @@ -1,11 +1,11 @@ /*----------------------------------------------------------------------------/ -/ TJpgDec - Tiny JPEG Decompressor R0.01c (C)ChaN, 2019 +/ TJpgDec - Tiny JPEG Decompressor R0.01b (C)ChaN, 2012 /-----------------------------------------------------------------------------/ / The TJpgDec is a generic JPEG decompressor module for tiny embedded systems. / This is a free software that opened for education, research and commercial / developments under license policy of following terms. / -/ Copyright (C) 2019, ChaN, all right reserved. +/ Copyright (C) 2012, ChaN, all right reserved. / / * The TJpgDec module is a free software and there is NO WARRANTY. / * No restriction on use. You can use, modify and redistribute it for @@ -13,13 +13,21 @@ / * Redistributions of source code must retain the above copyright notice. / /-----------------------------------------------------------------------------/ -/ Oct 04, 2011 R0.01 First release. -/ Feb 19, 2012 R0.01a Fixed decompression fails when scan starts with an escape seq. -/ Sep 03, 2012 R0.01b Added JD_TBLCLIP option. -/ Mar 16, 2019 R0.01c Supprted stdint.h. +/ Oct 04,'11 R0.01 First release. +/ Feb 19,'12 R0.01a Fixed decompression fails when scan starts with an escape seq. +/ Sep 03,'12 R0.01b Added JD_TBLCLIP option. /----------------------------------------------------------------------------*/ -#include "tjpgd.h" +#include "esp_rom_caps.h" + +#if !ESP_ROM_HAS_JPEG_DECODE + +#include "esp_rom_tjpgd.h" + +#define JD_SZBUF 512 /* Size of stream input buffer */ +#define JD_FORMAT 0 /* Output pixel format 0:RGB888 (3 BYTE/pix), 1:RGB565 (1 WORD/pix) */ +#define JD_USE_SCALE 1 /* Use descaling feature for output */ +#define JD_TBLCLIP 1 /* Use table for saturation (might be a bit faster but increases 1K bytes of code size) */ /*-----------------------------------------------*/ @@ -28,7 +36,8 @@ #define ZIG(n) Zig[n] -static const uint8_t Zig[64] = { /* Zigzag-order to raster-order conversion table */ +static +const uint8_t Zig[64] = { /* Zigzag-order to raster-order conversion table */ 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, @@ -44,7 +53,8 @@ static const uint8_t Zig[64] = { /* Zigzag-order to raster-order conversion tabl #define IPSF(n) Ipsf[n] -static const uint16_t Ipsf[64] = { /* See also aa_idct.png */ +static +const uint16_t Ipsf[64] = { /* See also aa_idct.png */ (uint16_t)(1.00000*8192), (uint16_t)(1.38704*8192), (uint16_t)(1.30656*8192), (uint16_t)(1.17588*8192), (uint16_t)(1.00000*8192), (uint16_t)(0.78570*8192), (uint16_t)(0.54120*8192), (uint16_t)(0.27590*8192), (uint16_t)(1.38704*8192), (uint16_t)(1.92388*8192), (uint16_t)(1.81226*8192), (uint16_t)(1.63099*8192), (uint16_t)(1.38704*8192), (uint16_t)(1.08979*8192), (uint16_t)(0.75066*8192), (uint16_t)(0.38268*8192), (uint16_t)(1.30656*8192), (uint16_t)(1.81226*8192), (uint16_t)(1.70711*8192), (uint16_t)(1.53636*8192), (uint16_t)(1.30656*8192), (uint16_t)(1.02656*8192), (uint16_t)(0.70711*8192), (uint16_t)(0.36048*8192), @@ -63,9 +73,10 @@ static const uint16_t Ipsf[64] = { /* See also aa_idct.png */ #if JD_TBLCLIP -#define BYTECLIP(v) Clip8[(uint16_t)(v) & 0x3FF] +#define BYTECLIP(v) Clip8[(uint32_t)(v) & 0x3FF] -static const uint8_t Clip8[1024] = { +static +const uint8_t Clip8[1024] = { /* 0..255 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, @@ -106,8 +117,9 @@ static const uint8_t Clip8[1024] = { #else /* JD_TBLCLIP */ -inline uint8_t BYTECLIP ( - int16_t val +inline +uint8_t BYTECLIP ( + int32_t val ) { if (val < 0) val = 0; @@ -124,9 +136,10 @@ inline uint8_t BYTECLIP ( /* Allocate a memory block from memory pool */ /*-----------------------------------------------------------------------*/ -static void* alloc_pool ( /* Pointer to allocated memory block (NULL:no memory available) */ - JDEC* jd, /* Pointer to the decompressor object */ - uint16_t nd /* Number of bytes to allocate */ +static +void* alloc_pool ( /* Pointer to allocated memory block (NULL:no memory available) */ + esp_rom_tjpgd_dec_t* jd, /* Pointer to the decompressor object */ + uint32_t nd /* Number of bytes to allocate */ ) { char *rp = 0; @@ -150,13 +163,14 @@ static void* alloc_pool ( /* Pointer to allocated memory block (NULL:no memory a /* Create de-quantization and prescaling tables with a DQT segment */ /*-----------------------------------------------------------------------*/ -static int create_qt_tbl ( /* 0:OK, !0:Failed */ - JDEC* jd, /* Pointer to the decompressor object */ +static +uint32_t create_qt_tbl ( /* 0:OK, !0:Failed */ + esp_rom_tjpgd_dec_t* jd, /* Pointer to the decompressor object */ const uint8_t* data, /* Pointer to the quantizer tables */ - uint16_t ndata /* Size of input data */ + uint32_t ndata /* Size of input data */ ) { - uint16_t i; + uint32_t i; uint8_t d, z; int32_t *pb; @@ -186,13 +200,14 @@ static int create_qt_tbl ( /* 0:OK, !0:Failed */ /* Create huffman code tables with a DHT segment */ /*-----------------------------------------------------------------------*/ -static int create_huffman_tbl ( /* 0:OK, !0:Failed */ - JDEC* jd, /* Pointer to the decompressor object */ +static +uint32_t create_huffman_tbl ( /* 0:OK, !0:Failed */ + esp_rom_tjpgd_dec_t* jd, /* Pointer to the decompressor object */ const uint8_t* data, /* Pointer to the packed huffman tables */ - uint16_t ndata /* Size of input data */ + uint32_t ndata /* Size of input data */ ) { - uint16_t i, j, b, np, cls, num; + uint32_t i, j, b, np, cls, num; uint8_t d, *pb, *pd; uint16_t hc, *ph; @@ -201,15 +216,17 @@ static int create_huffman_tbl ( /* 0:OK, !0:Failed */ if (ndata < 17) return JDR_FMT1; /* Err: wrong data size */ ndata -= 17; d = *data++; /* Get table number and class */ + cls = (d >> 4); num = d & 0x0F; /* class = dc(0)/ac(1), table number = 0/1 */ if (d & 0xEE) return JDR_FMT1; /* Err: invalid class/number */ - cls = d >> 4; num = d & 0x0F; /* class = dc(0)/ac(1), table number = 0/1 */ pb = alloc_pool(jd, 16); /* Allocate a memory block for the bit distribution table */ if (!pb) return JDR_MEM1; /* Err: not enough memory */ jd->huffbits[num][cls] = pb; for (np = i = 0; i < 16; i++) { /* Load number of patterns for 1 to 16-bit code */ - np += (pb[i] = *data++); /* Get sum of code words for each code */ + pb[i] = b = *data++; + np += b; /* Get sum of code words for each code */ } - ph = alloc_pool(jd, (uint16_t)(np * sizeof (uint16_t)));/* Allocate a memory block for the code word table */ + + ph = alloc_pool(jd, np * sizeof (uint16_t));/* Allocate a memory block for the code word table */ if (!ph) return JDR_MEM1; /* Err: not enough memory */ jd->huffcode[num][cls] = ph; hc = 0; @@ -241,13 +258,14 @@ static int create_huffman_tbl ( /* 0:OK, !0:Failed */ /* Extract N bits from input stream */ /*-----------------------------------------------------------------------*/ -static int bitext ( /* >=0: extracted data, <0: error code */ - JDEC* jd, /* Pointer to the decompressor object */ - int nbit /* Number of bits to extract (1 to 11) */ +static +int32_t bitext ( /* >=0: extracted data, <0: error code */ + esp_rom_tjpgd_dec_t* jd, /* Pointer to the decompressor object */ + uint32_t nbit /* Number of bits to extract (1 to 11) */ ) { uint8_t msk, s, *dp; - uint16_t dc, v, f; + uint32_t dc, v, f; msk = jd->dmsk; dc = jd->dctr; dp = jd->dptr; /* Bit mask, number of data available, read ptr */ @@ -257,14 +275,14 @@ static int bitext ( /* >=0: extracted data, <0: error code */ if (!dc) { /* No input data is available, re-fill input buffer */ dp = jd->inbuf; /* Top of input buffer */ dc = jd->infunc(jd, dp, JD_SZBUF); - if (!dc) return 0 - (int16_t)JDR_INP; /* Err: read error or wrong stream termination */ + if (!dc) return 0 - (int32_t)JDR_INP; /* Err: read error or wrong stream termination */ } else { dp++; /* Next data ptr */ } dc--; /* Decrement number of available bytes */ if (f) { /* In flag sequence? */ f = 0; /* Exit flag sequence */ - if (*dp != 0) return 0 - (int16_t)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */ + if (*dp != 0) return 0 - (int32_t)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */ *dp = s = 0xFF; /* The flag is a data 0xFF */ } else { s = *dp; /* Get next data byte */ @@ -281,7 +299,7 @@ static int bitext ( /* >=0: extracted data, <0: error code */ } while (nbit); jd->dmsk = msk; jd->dctr = dc; jd->dptr = dp; - return (int)v; + return (int32_t)v; } @@ -291,15 +309,16 @@ static int bitext ( /* >=0: extracted data, <0: error code */ /* Extract a huffman decoded data from input stream */ /*-----------------------------------------------------------------------*/ -static int16_t huffext ( /* >=0: decoded data, <0: error code */ - JDEC* jd, /* Pointer to the decompressor object */ +static +int32_t huffext ( /* >=0: decoded data, <0: error code */ + esp_rom_tjpgd_dec_t* jd, /* Pointer to the decompressor object */ const uint8_t* hbits, /* Pointer to the bit distribution table */ const uint16_t* hcode, /* Pointer to the code word table */ const uint8_t* hdata /* Pointer to the data table */ ) { uint8_t msk, s, *dp; - uint16_t dc, v, f, bl, nd; + uint32_t dc, v, f, bl, nd; msk = jd->dmsk; dc = jd->dctr; dp = jd->dptr; /* Bit mask, number of data available, read ptr */ @@ -310,14 +329,15 @@ static int16_t huffext ( /* >=0: decoded data, <0: error code */ if (!dc) { /* No input data is available, re-fill input buffer */ dp = jd->inbuf; /* Top of input buffer */ dc = jd->infunc(jd, dp, JD_SZBUF); - if (!dc) return 0 - (int16_t)JDR_INP; /* Err: read error or wrong stream termination */ + if (!dc) return 0 - (int32_t)JDR_INP; /* Err: read error or wrong stream termination */ } else { dp++; /* Next data ptr */ } dc--; /* Decrement number of available bytes */ if (f) { /* In flag sequence? */ f = 0; /* Exit flag sequence */ - if (*dp != 0) return 0 - (int16_t)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */ + if (*dp != 0) + return 0 - (int32_t)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */ *dp = s = 0xFF; /* The flag is a data 0xFF */ } else { s = *dp; /* Get next data byte */ @@ -341,7 +361,7 @@ static int16_t huffext ( /* >=0: decoded data, <0: error code */ bl--; } while (bl); - return 0 - (int16_t)JDR_FMT1; /* Err: code not found (may be collapted data) */ + return 0 - (int32_t)JDR_FMT1; /* Err: code not found (may be collapted data) */ } @@ -351,7 +371,8 @@ static int16_t huffext ( /* >=0: decoded data, <0: error code */ /* Apply Inverse-DCT in Arai Algorithm (see also aa_idct.png) */ /*-----------------------------------------------------------------------*/ -static void block_idct ( +static +void block_idct ( int32_t* src, /* Input block data (de-quantized and pre-scaled for Arai Algorithm) */ uint8_t* dst /* Pointer to the destination to store the block as byte array */ ) @@ -359,7 +380,7 @@ static void block_idct ( const int32_t M13 = (int32_t)(1.41421*4096), M2 = (int32_t)(1.08239*4096), M4 = (int32_t)(2.61313*4096), M5 = (int32_t)(1.84776*4096); int32_t v0, v1, v2, v3, v4, v5, v6, v7; int32_t t10, t11, t12, t13; - uint16_t i; + uint32_t i; /* Process columns */ for (i = 0; i < 8; i++) { @@ -463,13 +484,14 @@ static void block_idct ( /* Load all blocks in the MCU into working buffer */ /*-----------------------------------------------------------------------*/ -static JRESULT mcu_load ( - JDEC* jd /* Pointer to the decompressor object */ +static +esp_rom_tjpgd_result_t mcu_load ( + esp_rom_tjpgd_dec_t* jd /* Pointer to the decompressor object */ ) { int32_t *tmp = (int32_t*)jd->workbuf; /* Block working buffer for de-quantize and IDCT */ - int b, d, e; - uint16_t blk, nby, nbc, i, z, id, cmp; + uint32_t blk, nby, nbc, i, z, id, cmp; + int32_t b, d, e; uint8_t *bp; const uint8_t *hb, *hd; const uint16_t *hc; @@ -503,7 +525,7 @@ static JRESULT mcu_load ( tmp[0] = d * dqf[0] >> 8; /* De-quantize, apply scale factor of Arai algorithm and descale 8 bits */ /* Extract following 63 AC elements from input stream */ - for (i = 1; i < 64; tmp[i++] = 0) ; /* Clear rest of elements */ + for (i = 1; i < 64; i++) tmp[i] = 0; /* Clear rest of elements */ hb = jd->huffbits[id][1]; /* Huffman table for the AC elements */ hc = jd->huffcode[id][1]; hd = jd->huffdata[id][1]; @@ -512,7 +534,7 @@ static JRESULT mcu_load ( b = huffext(jd, hb, hc, hd); /* Extract a huffman coded value (zero runs and bit length) */ if (b == 0) break; /* EOB? */ if (b < 0) return 0 - b; /* Err: invalid code or input error */ - z = (uint16_t)b >> 4; /* Number of leading zero elements */ + z = (uint32_t)b >> 4; /* Number of leading zero elements */ if (z) { i += z; /* Skip zero elements */ if (i >= 64) return JDR_FMT1; /* Too long zero run */ @@ -527,11 +549,10 @@ static JRESULT mcu_load ( } } while (++i < 64); /* Next AC element */ - if (JD_USE_SCALE && jd->scale == 3) { - *bp = (uint8_t)((*tmp / 256) + 128); /* If scale ratio is 1/8, IDCT can be ommited and only DC element is used */ - } else { + if (JD_USE_SCALE && jd->scale == 3) + *bp = (*tmp / 256) + 128; /* If scale ratio is 1/8, IDCT can be ommited and only DC element is used */ + else block_idct(tmp, bp); /* Apply IDCT and store the block to the MCU buffer */ - } bp += 64; /* Next block */ } @@ -546,18 +567,19 @@ static JRESULT mcu_load ( /* Output an MCU: Convert YCrCb to RGB and output it in RGB form */ /*-----------------------------------------------------------------------*/ -static JRESULT mcu_output ( - JDEC* jd, /* Pointer to the decompressor object */ - uint16_t (*outfunc)(JDEC*, void*, JRECT*), /* RGB output function */ - uint16_t x, /* MCU position in the image (left of the MCU) */ - uint16_t y /* MCU position in the image (top of the MCU) */ +static +esp_rom_tjpgd_result_t mcu_output ( + esp_rom_tjpgd_dec_t* jd, /* Pointer to the decompressor object */ + uint32_t (*outfunc)(esp_rom_tjpgd_dec_t*, void*, esp_rom_tjpgd_rect_t*), /* RGB output function */ + uint32_t x, /* MCU position in the image (left of the MCU) */ + uint32_t y /* MCU position in the image (top of the MCU) */ ) { - const int16_t CVACC = (sizeof (int16_t) > 2) ? 1024 : 128; - uint16_t ix, iy, mx, my, rx, ry; - int16_t yy, cb, cr; + const int32_t CVACC = (sizeof (int32_t) > 2) ? 1024 : 128; + uint32_t ix, iy, mx, my, rx, ry; + int32_t yy, cb, cr; uint8_t *py, *pc, *rgb24; - JRECT rect; + esp_rom_tjpgd_rect_t rect; mx = jd->msx * 8; my = jd->msy * 8; /* MCU size (pixel) */ @@ -597,15 +619,15 @@ static JRESULT mcu_output ( yy = *py++; /* Get Y component */ /* Convert YCbCr to RGB */ - *rgb24++ = /* R */ BYTECLIP(yy + ((int16_t)(1.402 * CVACC) * cr) / CVACC); - *rgb24++ = /* G */ BYTECLIP(yy - ((int16_t)(0.344 * CVACC) * cb + (int16_t)(0.714 * CVACC) * cr) / CVACC); - *rgb24++ = /* B */ BYTECLIP(yy + ((int16_t)(1.772 * CVACC) * cb) / CVACC); + *rgb24++ = /* R */ BYTECLIP(yy + ((int32_t)(1.402 * CVACC) * cr) / CVACC); + *rgb24++ = /* G */ BYTECLIP(yy - ((int32_t)(0.344 * CVACC) * cb + (int32_t)(0.714 * CVACC) * cr) / CVACC); + *rgb24++ = /* B */ BYTECLIP(yy + ((int32_t)(1.772 * CVACC) * cb) / CVACC); } } /* Descale the MCU rectangular if needed */ if (JD_USE_SCALE && jd->scale) { - uint16_t x, y, r, g, b, s, w, a; + uint32_t x, y, r, g, b, s, w, a; uint8_t *op; /* Get averaged RGB value of each square correcponds to a pixel */ @@ -647,9 +669,9 @@ static JRESULT mcu_output ( py += 64; /* Convert YCbCr to RGB */ - *rgb24++ = /* R */ BYTECLIP(yy + ((int16_t)(1.402 * CVACC) * cr / CVACC)); - *rgb24++ = /* G */ BYTECLIP(yy - ((int16_t)(0.344 * CVACC) * cb + (int16_t)(0.714 * CVACC) * cr) / CVACC); - *rgb24++ = /* B */ BYTECLIP(yy + ((int16_t)(1.772 * CVACC) * cb / CVACC)); + *rgb24++ = /* R */ BYTECLIP(yy + ((int32_t)(1.402 * CVACC) * cr / CVACC)); + *rgb24++ = /* G */ BYTECLIP(yy - ((int32_t)(0.344 * CVACC) * cb + (int32_t)(0.714 * CVACC) * cr) / CVACC); + *rgb24++ = /* B */ BYTECLIP(yy + ((int32_t)(1.772 * CVACC) * cb / CVACC)); } } } @@ -658,7 +680,7 @@ static JRESULT mcu_output ( mx >>= jd->scale; if (rx < mx) { uint8_t *s, *d; - uint16_t x, y; + uint32_t x, y; s = d = (uint8_t*)jd->workbuf; for (y = 0; y < ry; y++) { @@ -675,7 +697,7 @@ static JRESULT mcu_output ( if (JD_FORMAT == 1) { uint8_t *s = (uint8_t*)jd->workbuf; uint16_t w, *d = (uint16_t*)s; - uint16_t n = rx * ry; + uint32_t n = rx * ry; do { w = (*s++ & 0xF8) << 8; /* RRRRR----------- */ @@ -696,12 +718,13 @@ static JRESULT mcu_output ( /* Process restart interval */ /*-----------------------------------------------------------------------*/ -static JRESULT restart ( - JDEC* jd, /* Pointer to the decompressor object */ +static +esp_rom_tjpgd_result_t restart ( + esp_rom_tjpgd_dec_t* jd, /* Pointer to the decompressor object */ uint16_t rstn /* Expected restert sequense number */ ) { - uint16_t i, dc; + uint32_t i, dc; uint16_t d; uint8_t *dp; @@ -723,9 +746,8 @@ static JRESULT restart ( jd->dptr = dp; jd->dctr = dc; jd->dmsk = 0; /* Check the marker */ - if ((d & 0xFFD8) != 0xFFD0 || (d & 7) != (rstn & 7)) { + if ((d & 0xFFD8) != 0xFFD0 || (d & 7) != (rstn & 7)) return JDR_FMT1; /* Err: expected RSTn marker is not detected (may be collapted data) */ - } /* Reset DC offset */ jd->dcv[2] = jd->dcv[1] = jd->dcv[0] = 0; @@ -743,19 +765,19 @@ static JRESULT restart ( #define LDB_WORD(ptr) (uint16_t)(((uint16_t)*((uint8_t*)(ptr))<<8)|(uint16_t)*(uint8_t*)((ptr)+1)) -JRESULT jd_prepare ( - JDEC* jd, /* Blank decompressor object */ - uint16_t (*infunc)(JDEC*, uint8_t*, uint16_t), /* JPEG strem input function */ +esp_rom_tjpgd_result_t esp_rom_tjpgd_prepare ( + esp_rom_tjpgd_dec_t* jd, /* Blank decompressor object */ + uint32_t (*infunc)(esp_rom_tjpgd_dec_t*, uint8_t*, uint32_t), /* JPEG strem input function */ void* pool, /* Working buffer for the decompression session */ - uint16_t sz_pool, /* Size of working buffer */ + uint32_t sz_pool, /* Size of working buffer */ void* dev /* I/O device identifier for the session */ ) { uint8_t *seg, b; uint16_t marker; uint32_t ofs; - uint16_t n, i, j, len; - JRESULT rc; + uint32_t n, i, j, len; + esp_rom_tjpgd_result_t rc; if (!pool) return JDR_PAR; @@ -773,7 +795,7 @@ JRESULT jd_prepare ( jd->huffdata[i][j] = 0; } } - for (i = 0; i < 4; jd->qttbl[i++] = 0) ; + for (i = 0; i < 4; i++) jd->qttbl[i] = 0; jd->inbuf = seg = alloc_pool(jd, JD_SZBUF); /* Allocate stream input buffer */ if (!seg) return JDR_MEM1; @@ -805,9 +827,8 @@ JRESULT jd_prepare ( for (i = 0; i < 3; i++) { b = seg[7 + 3 * i]; /* Get sampling factor */ if (!i) { /* Y component */ - if (b != 0x11 && b != 0x22 && b != 0x21) { /* Check sampling factor */ + if (b != 0x11 && b != 0x22 && b != 0x21)/* Check sampling factor */ return JDR_FMT3; /* Err: Supports only 4:4:4, 4:2:0 or 4:2:2 */ - } jd->msx = b >> 4; jd->msy = b & 15; /* Size of MCU [blocks] */ } else { /* Cb/Cr component */ if (b != 0x11) return JDR_FMT3; /* Err: Sampling factor of Cr/Cb must be 1 */ @@ -861,12 +882,9 @@ JRESULT jd_prepare ( b = seg[2 + 2 * i]; /* Get huffman table ID */ if (b != 0x00 && b != 0x11) return JDR_FMT3; /* Err: Different table number for DC/AC element */ b = i ? 1 : 0; - if (!jd->huffbits[b][0] || !jd->huffbits[b][1]) { /* Check dc/ac huffman table for this component */ - return JDR_FMT1; /* Err: Nnot loaded */ - } - if (!jd->qttbl[jd->qtid[i]]) { /* Check dequantizer table for this component */ - return JDR_FMT1; /* Err: Not loaded */ - } + if (!jd->huffbits[b][0] || !jd->huffbits[b][1]) /* Check huffman table for this component */ + return JDR_FMT1; /* Err: Huffman table not loaded */ + if (!jd->qttbl[jd->qtid[i]]) return JDR_FMT1; /* Err: Dequantizer table not loaded */ } /* Allocate working buffer for MCU and RGB */ @@ -876,13 +894,13 @@ JRESULT jd_prepare ( if (len < 256) len = 256; /* but at least 256 byte is required for IDCT */ jd->workbuf = alloc_pool(jd, len); /* and it may occupy a part of following MCU working buffer for RGB output */ if (!jd->workbuf) return JDR_MEM1; /* Err: not enough memory */ - jd->mcubuf = (uint8_t*)alloc_pool(jd, (uint16_t)((n + 2) * 64)); /* Allocate MCU working buffer */ + jd->mcubuf = alloc_pool(jd, (n + 2) * 64); /* Allocate MCU working buffer */ if (!jd->mcubuf) return JDR_MEM1; /* Err: not enough memory */ /* Pre-load the JPEG data to extract it from the bit stream */ jd->dptr = seg; jd->dctr = 0; jd->dmsk = 0; /* Prepare to read bit stream */ if (ofs %= JD_SZBUF) { /* Align read offset to JD_SZBUF */ - jd->dctr = jd->infunc(jd, seg + ofs, (uint16_t)(JD_SZBUF - ofs)); + jd->dctr = jd->infunc(jd, seg + ofs, JD_SZBUF - (uint32_t)ofs); jd->dptr = seg + ofs - 1; } @@ -905,9 +923,8 @@ JRESULT jd_prepare ( default: /* Unknown segment (comment, exif or etc..) */ /* Skip segment data */ - if (jd->infunc(jd, 0, len) != len) { /* Null pointer specifies to skip bytes of stream */ + if (jd->infunc(jd, 0, len) != len) /* Null pointer specifies to skip bytes of stream */ return JDR_INP; - } } } } @@ -919,15 +936,15 @@ JRESULT jd_prepare ( /* Start to decompress the JPEG picture */ /*-----------------------------------------------------------------------*/ -JRESULT jd_decomp ( - JDEC* jd, /* Initialized decompression object */ - uint16_t (*outfunc)(JDEC*, void*, JRECT*), /* RGB output function */ - uint8_t scale /* Output de-scaling factor (0 to 3) */ +esp_rom_tjpgd_result_t esp_rom_tjpgd_decomp ( + esp_rom_tjpgd_dec_t* jd, /* Initialized decompression object */ + uint32_t (*outfunc)(esp_rom_tjpgd_dec_t*, void*, esp_rom_tjpgd_rect_t*), /* RGB output function */ + uint8_t scale /* Output de-scaling factor (0 to 3) */ ) { - uint16_t x, y, mx, my; + uint32_t x, y, mx, my; uint16_t rst, rsc; - JRESULT rc; + esp_rom_tjpgd_result_t rc; if (scale > (JD_USE_SCALE ? 3 : 0)) return JDR_PAR; @@ -955,3 +972,5 @@ JRESULT jd_decomp ( return rc; } + +#endif // ESP_ROM_HAS_JPEG_DECODE diff --git a/components/esp_rom/test/CMakeLists.txt b/components/esp_rom/test/CMakeLists.txt index 82049b5644..00ab63e913 100644 --- a/components/esp_rom/test/CMakeLists.txt +++ b/components/esp_rom/test/CMakeLists.txt @@ -2,11 +2,9 @@ idf_component_register(SRC_DIRS . PRIV_INCLUDE_DIRS . ${CMAKE_CURRENT_BINARY_DIR} PRIV_REQUIRES cmock test_utils) -if(IDF_TARGET STREQUAL "esp32") - add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/test_tjpgd_logo.h" - COMMAND xxd -i "logo.jpg" "${CMAKE_CURRENT_BINARY_DIR}/test_tjpgd_logo.h" - WORKING_DIRECTORY ${COMPONENT_DIR} - DEPENDS "${CMAKE_CURRENT_LIST_DIR}/logo.jpg") - add_custom_target(test_logo DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/test_tjpgd_logo.h") - add_dependencies(${COMPONENT_LIB} test_logo) -endif() +add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/test_tjpgd_logo.h" + COMMAND xxd -i "logo.jpg" "${CMAKE_CURRENT_BINARY_DIR}/test_tjpgd_logo.h" + WORKING_DIRECTORY ${COMPONENT_DIR} + DEPENDS "${CMAKE_CURRENT_LIST_DIR}/logo.jpg") +add_custom_target(test_logo DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/test_tjpgd_logo.h") +add_dependencies(${COMPONENT_LIB} test_logo) diff --git a/components/esp_rom/test/test_tjpgd.c b/components/esp_rom/test/test_tjpgd.c index 7a0439c0d0..673d91a358 100644 --- a/components/esp_rom/test/test_tjpgd.c +++ b/components/esp_rom/test/test_tjpgd.c @@ -5,9 +5,7 @@ #include "sdkconfig.h" #include "unity.h" -#if CONFIG_IDF_TARGET_ESP32 - -#include "esp32/rom/tjpgd.h" +#include "esp_rom_tjpgd.h" #include "test_tjpgd_logo.h" typedef struct { @@ -18,7 +16,7 @@ typedef struct { int outH; } JpegDev; -static UINT infunc(JDEC *decoder, BYTE *buf, UINT len) +static uint32_t infunc(esp_rom_tjpgd_dec_t *decoder, uint8_t *buf, uint32_t len) { JpegDev *jd = (JpegDev *)decoder->device; printf("Reading %d bytes from pos %d\n", len, jd->inPos); @@ -29,7 +27,7 @@ static UINT infunc(JDEC *decoder, BYTE *buf, UINT len) return len; } -static UINT outfunc(JDEC *decoder, void *bitmap, JRECT *rect) +static uint32_t outfunc(esp_rom_tjpgd_dec_t *decoder, void *bitmap, esp_rom_tjpgd_rect_t *rect) { unsigned char *in = (unsigned char *)bitmap; unsigned char *out; @@ -55,10 +53,10 @@ TEST_CASE("Test JPEG decompression library", "[rom][tjpgd]") char *work; int r; int x, y, v; - JDEC decoder; + esp_rom_tjpgd_dec_t decoder; JpegDev jd; - decoded = malloc(48 * 48 * 3); - for (x = 0; x < 48 * 48 * 3; x += 2) { + decoded = malloc(TESTW * TESTH * 3); + for (x = 0; x < TESTW * TESTH * 3; x += 2) { decoded[x] = 0; decoded[x + 1] = 0xff; } @@ -71,9 +69,9 @@ TEST_CASE("Test JPEG decompression library", "[rom][tjpgd]") jd.outW = TESTW; jd.outH = TESTH; - r = jd_prepare(&decoder, infunc, work, WORKSZ, (void *)&jd); + r = esp_rom_tjpgd_prepare(&decoder, infunc, work, WORKSZ, (void *)&jd); TEST_ASSERT_EQUAL(r, JDR_OK); - r = jd_decomp(&decoder, outfunc, 0); + r = esp_rom_tjpgd_decomp(&decoder, outfunc, 0); TEST_ASSERT_EQUAL(r, JDR_OK); p = decoded + 2; @@ -89,5 +87,3 @@ TEST_CASE("Test JPEG decompression library", "[rom][tjpgd]") free(work); free(decoded); } - -#endif // #if CONFIG_IDF_TARGET_ESP32 diff --git a/components/esp_system/CMakeLists.txt b/components/esp_system/CMakeLists.txt index b99447fbc3..0aa60f72a7 100644 --- a/components/esp_system/CMakeLists.txt +++ b/components/esp_system/CMakeLists.txt @@ -21,7 +21,8 @@ else() "system_time.c" "stack_check.c" "task_wdt.c" - "ubsan.c") + "ubsan.c" + "xt_wdt.c") if(NOT (${target} STREQUAL "esp32c3") AND NOT (${target} STREQUAL "esp32h2")) list(APPEND srcs "dbg_stubs.c") @@ -38,7 +39,7 @@ else() # should be removable once using component init functions # link-time registration is used. esp_pm app_update nvs_flash pthread app_trace esp_gdbstub - espcoredump esp_phy efuse + espcoredump esp_phy efuse esp_ipc LDFRAGMENTS "linker.lf" "app.lf") add_subdirectory(port) diff --git a/components/esp_system/Kconfig b/components/esp_system/Kconfig index 509fbbb4aa..adc769a13d 100644 --- a/components/esp_system/Kconfig +++ b/components/esp_system/Kconfig @@ -53,6 +53,12 @@ menu "ESP System Settings" bool default n + config ESP_SYSTEM_RTC_EXT_OSC + # This is a High Layer Kconfig option, invisible, can be selected by other Kconfig option + # e.g. It will be selected on when ESPX_RTC_CLK_SRC_EXT_OSC is on + bool + default n + config ESP_SYSTEM_RTC_EXT_XTAL_BOOTSTRAP_CYCLES int "Bootstrap cycles for external 32kHz crystal" depends on ESP_SYSTEM_RTC_EXT_XTAL @@ -107,9 +113,15 @@ menu "ESP System Settings" menu "Memory protection" + config ESP_SYSTEM_MEMPROT_DEPCHECK + bool + default y if IDF_TARGET_ESP32S2 + default y if IDF_TARGET_ESP32C3 + default y if IDF_TARGET_ESP32H2 + config ESP_SYSTEM_MEMPROT_FEATURE bool "Enable memory protection" - depends on IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32H2 + depends on ESP_SYSTEM_MEMPROT_DEPCHECK default "y" help If enabled, the permission control module watches all the memory access and fires the panic handler @@ -127,6 +139,20 @@ menu "ESP System Settings" Once locked, memory protection settings cannot be changed anymore. The lock is reset only on the chip startup. + config ESP_SYSTEM_MEMPROT_CPU_PREFETCH_PAD_SIZE + # Hidden option for linker script usage + int + depends on ESP_SYSTEM_MEMPROT_DEPCHECK + default 16 + + config ESP_SYSTEM_MEMPROT_MEM_ALIGN_SIZE + # Hidden option for linker script usage + int + depends on ESP_SYSTEM_MEMPROT_DEPCHECK + default 4 if IDF_TARGET_ESP32S2 + default 256 if IDF_TARGET_ESP32S3 + default 512 + endmenu # Memory protection config ESP_SYSTEM_EVENT_QUEUE_SIZE @@ -389,30 +415,30 @@ menu "ESP System Settings" If this option is enabled, the Task Wtachdog Timer will wach the CPU1 Idle Task. - config ESP_IPC_TASK_STACK_SIZE - int "Inter-Processor Call (IPC) task stack size" - range 512 65536 if !APPTRACE_ENABLE - range 2048 65536 if APPTRACE_ENABLE - default 2048 if APPTRACE_ENABLE - default 1024 + config ESP_XT_WDT + bool "Initialize XTAL32K watchdog timer on startup" + depends on !IDF_TARGET_ESP32 && (ESP_SYSTEM_RTC_EXT_OSC || ESP_SYSTEM_RTC_EXT_XTAL) + default n help - Configure the IPC tasks stack size. One IPC task runs on each core - (in dual core mode), and allows for cross-core function calls. + This watchdog timer can detect oscillation failure of the XTAL32K_CLK. When such a failure + is detected the hardware can be set up to automatically switch to BACKUP32K_CLK and generate + an interrupt. - See IPC documentation for more details. + config ESP_XT_WDT_TIMEOUT + int "XTAL32K watchdog timeout period" + depends on ESP_XT_WDT + range 1 255 + default 200 + help + Timeout period configuration for the XTAL32K watchdog timer based on RTC_CLK. - The default stack size should be enough for most common use cases. - It can be shrunk if you are sure that you do not use any custom - IPC functionality. - - config ESP_IPC_USES_CALLERS_PRIORITY - bool "IPC runs at caller's priority" + config ESP_XT_WDT_BACKUP_CLK_ENABLE + bool "Automatically switch to BACKUP32K_CLK when timer expires" + depends on ESP_XT_WDT default y - depends on !FREERTOS_UNICORE help - If this option is not enabled then the IPC task will keep behavior - same as prior to that of ESP-IDF v4.0, and hence IPC task will run - at (configMAX_PRIORITIES - 1) priority. + Enable this to automatically switch to BACKUP32K_CLK as the source of RTC_SLOW_CLK when + the watchdog timer expires. config ESP_PANIC_HANDLER_IRAM bool "Place panic handler code in IRAM" @@ -436,5 +462,23 @@ 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. + choice ESP_SYSTEM_CHECK_INT_LEVEL + prompt "Interrupt level to use for Interrupt Watchdog and other system checks" + default ESP_SYSTEM_CHECK_INT_LEVEL_4 + help + Interrupt level to use for Interrupt Watchdog and other system checks. + + config ESP_SYSTEM_CHECK_INT_LEVEL_5 + bool "Level 5 interrupt" + depends on IDF_TARGET_ESP32 + help + Using level 5 interrupt for Interrupt Watchdog and other system checks. + + config ESP_SYSTEM_CHECK_INT_LEVEL_4 + bool "Level 4 interrupt" + depends on !BTDM_CTRL_HLI + help + Using level 4 interrupt for Interrupt Watchdog and other system checks. + endchoice endmenu # ESP System Settings diff --git a/components/esp_system/component.mk b/components/esp_system/component.mk index 6f603f880b..c67e3064e1 100644 --- a/components/esp_system/component.mk +++ b/components/esp_system/component.mk @@ -53,7 +53,7 @@ $(COMPONENT_LIBRARY): $(ld_output) $(ld_output): $(ld_input) ../include/sdkconfig.h mkdir -p $(COMPONENT_BUILD_DIR)/ld - $(CC) -I ../include -C -P -x c -E $< -o $@ + $(CC) -I ../include -I $(COMPONENT_PATH)/ld -C -P -x c -E $< -o $@ COMPONENT_EXTRA_CLEAN := $(ld_output) $(sections_ld) endif diff --git a/components/esp_system/dbg_stubs.c b/components/esp_system/dbg_stubs.c index ef49c5524d..b564c5b6f2 100644 --- a/components/esp_system/dbg_stubs.c +++ b/components/esp_system/dbg_stubs.c @@ -75,11 +75,14 @@ void esp_dbg_stubs_init(void) s_dbg_stubs_ctl_data.data_alloc = (uint32_t)esp_dbg_stubs_data_alloc; s_dbg_stubs_ctl_data.data_free = (uint32_t)esp_dbg_stubs_data_free; + s_stub_entry[ESP_DBG_STUB_MAGIC_NUM] = ESP_DBG_STUB_MAGIC_NUM_VAL; + s_stub_entry[ESP_DBG_STUB_TABLE_SIZE] = ESP_DBG_STUB_ENTRY_MAX; s_stub_entry[ESP_DBG_STUB_CONTROL_DATA] = (uint32_t)&s_dbg_stubs_ctl_data; eri_write(ESP_DBG_STUBS_TRAX_REG, (uint32_t)s_stub_entry); ESP_LOGV(TAG, "%s stubs %x", __func__, eri_read(ESP_DBG_STUBS_TRAX_REG)); } +// TODO: add lock mechanism. Not now but in the future ESP_DBG_STUB_ENTRY_CAPABILITIES can be set from different places. esp_err_t esp_dbg_stub_entry_set(esp_dbg_stub_id_t id, uint32_t entry) { if (id < ESP_DBG_STUB_ENTRY_FIRST || id >= ESP_DBG_STUB_ENTRY_MAX) { @@ -91,4 +94,15 @@ esp_err_t esp_dbg_stub_entry_set(esp_dbg_stub_id_t id, uint32_t entry) return ESP_OK; } +esp_err_t esp_dbg_stub_entry_get(esp_dbg_stub_id_t id, uint32_t *entry) +{ + if (id < ESP_DBG_STUB_ENTRY_FIRST || id >= ESP_DBG_STUB_ENTRY_MAX) { + ESP_LOGE(TAG, "Invalid stub id %d!", id); + return ESP_ERR_INVALID_ARG; + } + *entry = s_stub_entry[id]; + + return ESP_OK; +} + #endif diff --git a/components/esp_system/include/esp_private/dbg_stubs.h b/components/esp_system/include/esp_private/dbg_stubs.h index f3f5fba3b7..ead23447bc 100644 --- a/components/esp_system/include/esp_private/dbg_stubs.h +++ b/components/esp_system/include/esp_private/dbg_stubs.h @@ -24,13 +24,19 @@ extern "C" { * Debug stubs entries IDs */ typedef enum { - ESP_DBG_STUB_CONTROL_DATA, ///< stubs descriptor entry + ESP_DBG_STUB_MAGIC_NUM, + ESP_DBG_STUB_TABLE_SIZE, + ESP_DBG_STUB_CONTROL_DATA, ///< stubs descriptor entry ESP_DBG_STUB_ENTRY_FIRST, - ESP_DBG_STUB_ENTRY_GCOV ///< GCOV entry - = ESP_DBG_STUB_ENTRY_FIRST, + ESP_DBG_STUB_ENTRY_GCOV ///< GCOV entry + = ESP_DBG_STUB_ENTRY_FIRST, + ESP_DBG_STUB_ENTRY_CAPABILITIES, ESP_DBG_STUB_ENTRY_MAX } esp_dbg_stub_id_t; +#define ESP_DBG_STUB_MAGIC_NUM_VAL 0xFEEDBEEF +#define ESP_DBG_STUB_CAP_GCOV_TASK (1 << 0) + /** * @brief Initializes debug stubs. * @@ -45,12 +51,24 @@ void esp_dbg_stubs_init(void); * * @param id Stub ID. * @param entry Stub entry. Usually it is stub entry function address, - * but can be any value meaningfull for OpenOCD command/code. - * + * but can be any value meaningfull for OpenOCD command/code + * such as capabilities * @return ESP_OK on success, otherwise see esp_err_t */ esp_err_t esp_dbg_stub_entry_set(esp_dbg_stub_id_t id, uint32_t entry); +/** + * @brief Retrives the corresponding stub entry + * + * @param id Stub ID. + * @param entry Stub entry. Usually it is stub entry function address, + * but can be any value meaningfull for OpenOCD command/code + * such as capabilities + * + * @return ESP_OK on success, otherwise see esp_err_t + */ +esp_err_t esp_dbg_stub_entry_get(esp_dbg_stub_id_t id, uint32_t *entry); + #ifdef __cplusplus } #endif diff --git a/components/esp_system/include/esp_task.h b/components/esp_system/include/esp_task.h index 37d78bca6e..adca9cde6b 100644 --- a/components/esp_system/include/esp_task.h +++ b/components/esp_system/include/esp_task.h @@ -52,7 +52,11 @@ #define ESP_TASK_TIMER_PRIO (ESP_TASK_PRIO_MAX - 3) #define ESP_TASK_TIMER_STACK (CONFIG_ESP_TIMER_TASK_STACK_SIZE + TASK_EXTRA_STACK_SIZE) #define ESP_TASKD_EVENT_PRIO (ESP_TASK_PRIO_MAX - 5) +#if CONFIG_LWIP_TCPIP_CORE_LOCKING +#define ESP_TASKD_EVENT_STACK (CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE + TASK_EXTRA_STACK_SIZE + 2048) +#else #define ESP_TASKD_EVENT_STACK (CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE + TASK_EXTRA_STACK_SIZE) +#endif /* CONFIG_LWIP_TCPIP_CORE_LOCKING */ #define ESP_TASK_TCPIP_PRIO (ESP_TASK_PRIO_MAX - 7) #define ESP_TASK_TCPIP_STACK (CONFIG_LWIP_TCPIP_TASK_STACK_SIZE + TASK_EXTRA_STACK_SIZE) #define ESP_TASK_MAIN_PRIO (ESP_TASK_PRIO_MIN + 1) diff --git a/components/esp_system/include/esp_xt_wdt.h b/components/esp_system/include/esp_xt_wdt.h new file mode 100644 index 0000000000..3b39d8056d --- /dev/null +++ b/components/esp_system/include/esp_xt_wdt.h @@ -0,0 +1,63 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include + +#include "esp_err.h" +#include "esp_intr_alloc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief esp_xt_wdt configuration struct + * + */ +typedef struct { + uint8_t timeout; /*!< Watchdog timeout */ + bool auto_backup_clk_enable; /*!< Enable automatic switch to backup clock at timeout */ +} esp_xt_wdt_config_t; + +/* Callback function for WDT interrupt*/ +typedef void (*esp_xt_callback_t)(void *arg); + +/** + * @brief Initializes the xtal32k watchdog timer + * + * @param cfg Pointer to configuration struct + * @return esp_err_t + * - ESP_OK: XTWDT was successfully enabled + * - ESP_ERR_NO_MEM: Failed to allocate ISR + */ +esp_err_t esp_xt_wdt_init(const esp_xt_wdt_config_t *cfg); + +/** + * @brief Register a callback function that will be called when the watchdog + * times out. + * + * @note This function will be called from an interrupt context where the cache might be disabled. + * Thus the function should be placed in IRAM and must not perform any blocking operations. + * + * Only one callback function can be registered, any call to esp_xt_wdt_register_callback + * will override the previous callback function. + * + * @param func The callback function to register + * @param arg Pointer to argument that will be passed to the callback function + */ +void esp_xt_wdt_register_callback(esp_xt_callback_t func, void *arg); + +/** + * @brief Restores the xtal32k clock and re-enables the WDT + * + */ +void esp_xt_wdt_restore_clk(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_system/int_wdt.c b/components/esp_system/int_wdt.c index da2f880cc1..3205422af2 100644 --- a/components/esp_system/int_wdt.c +++ b/components/esp_system/int_wdt.c @@ -51,7 +51,7 @@ static wdt_hal_context_t iwdt_context; */ #define IWDT_LIVELOCK_TIMEOUT_MS (20) -extern uint32_t _l4_intr_livelock_counter, _l4_intr_livelock_max; +extern uint32_t _lx_intr_livelock_counter, _lx_intr_livelock_max; #endif //Take care: the tick hook can also be called before esp_int_wdt_init() is called. @@ -70,9 +70,9 @@ static void IRAM_ATTR tick_hook(void) wdt_hal_write_protect_disable(&iwdt_context); //Reconfigure stage timeouts #if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX - _l4_intr_livelock_counter = 0; + _lx_intr_livelock_counter = 0; wdt_hal_config_stage(&iwdt_context, WDT_STAGE0, - CONFIG_ESP_INT_WDT_TIMEOUT_MS * 1000 / IWDT_TICKS_PER_US / (_l4_intr_livelock_max + 1), WDT_STAGE_ACTION_INT); //Set timeout before interrupt + CONFIG_ESP_INT_WDT_TIMEOUT_MS * 1000 / IWDT_TICKS_PER_US / (_lx_intr_livelock_max + 1), WDT_STAGE_ACTION_INT); //Set timeout before interrupt #else wdt_hal_config_stage(&iwdt_context, WDT_STAGE0, CONFIG_ESP_INT_WDT_TIMEOUT_MS * 1000 / IWDT_TICKS_PER_US, WDT_STAGE_ACTION_INT); //Set timeout before interrupt #endif @@ -116,6 +116,38 @@ void esp_int_wdt_init(void) //Enable WDT wdt_hal_enable(&iwdt_context); wdt_hal_write_protect_enable(&iwdt_context); + + +#if (CONFIG_ESP32_ECO3_CACHE_LOCK_FIX && CONFIG_BTDM_CTRL_HLI) + +#define APB_DCRSET (0x200c) +#define APB_ITCTRL (0x3f00) + +#define ERI_ADDR(APB) (0x100000 + (APB)) + +#define _SYM2STR(x) # x +#define SYM2STR(x) _SYM2STR(x) + uint32_t eriadrs, scratch = 0, immediate = 0; + if (soc_has_cache_lock_bug()) { + if (xPortGetCoreID() != CONFIG_BTDM_CTRL_PINNED_TO_CORE) { + __asm__ __volatile__ ( + /* Enable Xtensa Debug Module Integration Mode */ + "movi %[ERI], " SYM2STR(ERI_ADDR(APB_ITCTRL)) "\n" + "rer %[REG], %[ERI]\n" + "movi %[IMM], 1\n" + "or %[REG], %[IMM], %[REG]\n" + "wer %[REG], %[ERI]\n" + /* Enable Xtensa Debug Module BreakIn signal */ + "movi %[ERI], " SYM2STR(ERI_ADDR(APB_DCRSET)) "\n" + "rer %[REG], %[ERI]\n" + "movi %[IMM], 0x10000\n" + "or %[REG], %[IMM], %[REG]\n" + "wer %[REG], %[ERI]\n" + : [ERI] "=r" (eriadrs), [REG] "+r" (scratch), [IMM] "+r" (immediate) + ); + } + } +#endif } void esp_int_wdt_cpu_init(void) @@ -136,11 +168,11 @@ void esp_int_wdt_cpu_init(void) * This is a workaround for issue 3.15 in "ESP32 ECO and workarounds for * Bugs" document. */ - _l4_intr_livelock_counter = 0; + _lx_intr_livelock_counter = 0; if (soc_has_cache_lock_bug()) { assert((portTICK_PERIOD_MS << 1) <= IWDT_LIVELOCK_TIMEOUT_MS); assert(CONFIG_ESP_INT_WDT_TIMEOUT_MS >= (IWDT_LIVELOCK_TIMEOUT_MS * 3)); - _l4_intr_livelock_max = CONFIG_ESP_INT_WDT_TIMEOUT_MS / IWDT_LIVELOCK_TIMEOUT_MS - 1; + _lx_intr_livelock_max = CONFIG_ESP_INT_WDT_TIMEOUT_MS / IWDT_LIVELOCK_TIMEOUT_MS - 1; } #endif diff --git a/components/esp_system/ld/esp32/memory.ld.in b/components/esp_system/ld/esp32/memory.ld.in index 49b2bc3be5..34f0aa7b5c 100644 --- a/components/esp_system/ld/esp32/memory.ld.in +++ b/components/esp_system/ld/esp32/memory.ld.in @@ -20,10 +20,11 @@ to simple macros with numeric values, and/or #if/#endif blocks. */ #include "sdkconfig.h" +#include "ld.common" /* If BT is not built at all */ -#ifndef CONFIG_BT_RESERVE_DRAM -#define CONFIG_BT_RESERVE_DRAM 0 +#ifndef CONFIG_BTDM_RESERVE_DRAM +#define CONFIG_BTDM_RESERVE_DRAM 0 #endif #ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC @@ -78,8 +79,8 @@ MEMORY in heap at runtime. However due to static ROM memory usage at this 176KB mark, the additional static memory temporarily cannot be used. */ - dram0_0_seg (RW) : org = 0x3FFB0000 + CONFIG_BT_RESERVE_DRAM, - len = DRAM0_0_SEG_LEN - CONFIG_BT_RESERVE_DRAM + dram0_0_seg (RW) : org = 0x3FFB0000 + CONFIG_BTDM_RESERVE_DRAM, + len = DRAM0_0_SEG_LEN - CONFIG_BTDM_RESERVE_DRAM #ifdef CONFIG_APP_BUILD_USE_FLASH_SECTIONS /* Flash mapped constant data */ @@ -102,7 +103,7 @@ MEMORY rtc_slow_seg(RW) : org = 0x50000000 + CONFIG_ESP32_ULP_COPROC_RESERVE_MEM, len = 0x2000 - CONFIG_ESP32_ULP_COPROC_RESERVE_MEM - /* external memory ,including data and text */ + /* external memory */ extern_ram_seg(RWX) : org = 0x3F800000, len = 0x400000 } diff --git a/components/esp_system/ld/esp32/sections.ld.in b/components/esp_system/ld/esp32/sections.ld.in index f3fb5026dd..c2a6c66c5b 100644 --- a/components/esp_system/ld/esp32/sections.ld.in +++ b/components/esp_system/ld/esp32/sections.ld.in @@ -201,10 +201,10 @@ SECTIONS * This section holds data that won't be initialised when startup. * This section locates in External RAM region. */ - .ext_ram.noinit (NOLOAD) : + .ext_ram_noinit (NOLOAD) : { _ext_ram_noinit_start = ABSOLUTE(.); - *(.ext_ram.noinit*) + *(.ext_ram_noinit*) . = ALIGN(4); _ext_ram_noinit_end = ABSOLUTE(.); } > extern_ram_seg @@ -349,7 +349,7 @@ SECTIONS * safe access to up to 16 bytes after the last real instruction, add * dummy bytes to ensure this */ - . += 16; + . += _esp_flash_mmap_prefetch_pad_size; _text_end = ABSOLUTE(.); _etext = .; diff --git a/components/esp_system/ld/esp32c3/memory.ld.in b/components/esp_system/ld/esp32c3/memory.ld.in index 66bf5d9ac4..d387915f93 100644 --- a/components/esp_system/ld/esp32c3/memory.ld.in +++ b/components/esp_system/ld/esp32c3/memory.ld.in @@ -1,3 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + /** * ESP32-C3 Linker Script Memory Layout * This file describes the memory layout (memory blocks) by virtual memory addresses. @@ -7,6 +13,7 @@ */ #include "sdkconfig.h" +#include "ld.common" #ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC #define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE + CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE) diff --git a/components/esp_system/ld/esp32c3/sections.ld.in b/components/esp_system/ld/esp32c3/sections.ld.in index a4e41e7123..96b0bdd346 100644 --- a/components/esp_system/ld/esp32c3/sections.ld.in +++ b/components/esp_system/ld/esp32c3/sections.ld.in @@ -1,3 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + /* Default entry point */ ENTRY(call_start_cpu0); @@ -228,7 +234,7 @@ SECTIONS * safe access to up to 16 bytes after the last real instruction, add * dummy bytes to ensure this */ - . += 16; + . += _esp_flash_mmap_prefetch_pad_size; _text_end = ABSOLUTE(.); _instruction_reserved_end = ABSOLUTE(.); @@ -368,9 +374,9 @@ SECTIONS /* Marks the end of IRAM code segment */ .iram0.text_end (NOLOAD) : { - /* C3 memprot requires 16B padding for possible CPU prefetch and 512B alignment for PMS split lines */ - . += 16; - . = ALIGN (0x200); + /* ESP32-C3 memprot requires 16B padding for possible CPU prefetch and 512B alignment for PMS split lines */ + . += _esp_memprot_prefetch_pad_size; + . = ALIGN(_esp_memprot_align_size); /* iram_end_test section exists for use by memprot unit tests only */ *(.iram_end_test) _iram_text_end = ABSOLUTE(.); diff --git a/components/esp_system/ld/esp32h2/memory.ld.in b/components/esp_system/ld/esp32h2/memory.ld.in index 9672a4783b..03f45cabd9 100644 --- a/components/esp_system/ld/esp32h2/memory.ld.in +++ b/components/esp_system/ld/esp32h2/memory.ld.in @@ -1,3 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + /** * ESP32-H2 Linker Script Memory Layout * This file describes the memory layout (memory blocks) by virtual memory addresses. @@ -7,6 +13,7 @@ */ #include "sdkconfig.h" +#include "ld.common" #ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC #define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE + CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE) @@ -46,7 +53,7 @@ MEMORY #if CONFIG_APP_BUILD_USE_FLASH_SECTIONS /* Flash mapped instruction data */ - iram0_2_seg (RX) : org = 0x42000020, len = 0x8000000-0x20 + iram0_2_seg (RX) : org = 0x42000020, len = 0x800000-0x20 /** * (0x20 offset above is a convenience for the app binary image generation. @@ -65,7 +72,7 @@ MEMORY #if CONFIG_APP_BUILD_USE_FLASH_SECTIONS /* Flash mapped constant data */ - drom0_0_seg (R) : org = 0x3C000020, len = 0x8000000-0x20 + drom0_0_seg (R) : org = 0x3C000020, len = 0x800000-0x20 /* (See iram0_2_seg for meaning of 0x20 offset in the above.) */ #endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS diff --git a/components/esp_system/ld/esp32h2/sections.ld.in b/components/esp_system/ld/esp32h2/sections.ld.in index 65eb17b45c..eaf8a5a41b 100644 --- a/components/esp_system/ld/esp32h2/sections.ld.in +++ b/components/esp_system/ld/esp32h2/sections.ld.in @@ -1,3 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + /* Default entry point */ ENTRY(call_start_cpu0); @@ -365,8 +371,9 @@ SECTIONS /* Marks the end of IRAM code segment */ .iram0.text_end (NOLOAD) : { - /* C3 memprot requires 512 B alignment for split lines */ - . = ALIGN (0x200); + /* ESP32-H2 memprot requires 16B padding for possible CPU prefetch and 512B alignment for PMS split lines */ + . += _esp_memprot_prefetch_pad_size; + . = ALIGN(_esp_memprot_align_size); /* iram_end_test section exists for use by memprot unit tests only */ *(.iram_end_test) _iram_text_end = ABSOLUTE(.); diff --git a/components/esp_system/ld/esp32s2/memory.ld.in b/components/esp_system/ld/esp32s2/memory.ld.in index 668d6fce6a..f40fca87a4 100644 --- a/components/esp_system/ld/esp32s2/memory.ld.in +++ b/components/esp_system/ld/esp32s2/memory.ld.in @@ -1,3 +1,8 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ /* ESP32S2 Linker Script Memory Layout This file describes the memory layout (memory blocks) by virtual memory addresses. @@ -8,6 +13,7 @@ Restrict to simple macros with numeric values, and/or #if/#endif blocks. */ #include "sdkconfig.h" +#include "ld.common" #ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC #define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE + CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE) @@ -102,6 +108,10 @@ MEMORY /* RTC fast memory (same block as above), viewed from data bus */ rtc_data_seg(RW) : org = 0x3ff9e000, len = 0x2000 - ESP_BOOTLOADER_RESERVE_RTC + + /* external memory, covers the dport, dram0, dram1 cacheable address space */ + extern_ram_seg(RWX) : org = 0x3F500000, + len = 0xA80000 } #if defined(CONFIG_ESP32S2_USE_FIXED_STATIC_RAM_SIZE) diff --git a/components/esp_system/ld/esp32s2/sections.ld.in b/components/esp_system/ld/esp32s2/sections.ld.in index e4cd142753..2bbfdad5ce 100644 --- a/components/esp_system/ld/esp32s2/sections.ld.in +++ b/components/esp_system/ld/esp32s2/sections.ld.in @@ -1,3 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + /* Default entry point: */ ENTRY(call_start_cpu0); @@ -177,7 +183,7 @@ SECTIONS _coredump_iram_end = 0; /* align + add 16B for CPU dummy speculative instr. fetch */ - . = ALIGN(4) + 16; + . = ALIGN(_esp_memprot_align_size) + _esp_memprot_prefetch_pad_size; /* iram_end_test section exists for use by memprot unit tests only */ *(.iram_end_test) _iram_text_end = ABSOLUTE(.); @@ -226,6 +232,17 @@ SECTIONS _noinit_end = ABSOLUTE(.); } > dram0_0_seg + /* external memory bss, from any global variable with EXT_RAM_ATTR attribute*/ + .ext_ram.bss (NOLOAD) : + { + _ext_ram_bss_start = ABSOLUTE(.); + + mapping[extern_ram] + + . = ALIGN(4); + _ext_ram_bss_end = ABSOLUTE(.); + } > extern_ram_seg + /* Shared RAM */ .dram0.bss (NOLOAD) : { @@ -352,7 +369,7 @@ SECTIONS * safe access to up to 16 bytes after the last real instruction, add * dummy bytes to ensure this */ - . += 16; + . += _esp_flash_mmap_prefetch_pad_size; _text_end = ABSOLUTE(.); _instruction_reserved_end = ABSOLUTE(.); diff --git a/components/esp_system/ld/esp32s3/memory.ld.in b/components/esp_system/ld/esp32s3/memory.ld.in index a1e4e153d2..4f6b70d490 100644 --- a/components/esp_system/ld/esp32s3/memory.ld.in +++ b/components/esp_system/ld/esp32s3/memory.ld.in @@ -1,3 +1,8 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ /** * ESP32-S3 Linker Script Memory Layout * This file describes the memory layout (memory blocks) by virtual memory addresses. @@ -7,6 +12,7 @@ */ #include "sdkconfig.h" +#include "ld.common" #ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC #define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE + CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE) @@ -16,15 +22,34 @@ #define ESP_BOOTLOADER_RESERVE_RTC 0 #endif +/* + * 40370000 <- IRAM/Icache -> 40378000 <- D/IRAM (I) -> 403E0000 + * 3FC88000 <- D/IRAM (D) -> 3FCF0000 <- DRAM/DCache -> 3FD00000 + * + * Startup code uses the IRAM from 0x403BA000 to 0x403E0000, which is not available for static + * memory, but can only be used after app starts. + * + * D cache use the memory from high address, so when it's configured to 16K/32K, the region + * 0x3FCF000 ~ (3FD00000 - DATA_CACHE_SIZE) should be available. This region is not used as + * static memory, leaving to the heap. + */ + #define SRAM_IRAM_START 0x40370000 -#define SRAM_DRAM_START 0x3FC80000 -#define I_D_SRAM_OFFSET (SRAM_IRAM_START - SRAM_DRAM_START) -#define SRAM_DRAM_END 0x403BA000 - I_D_SRAM_OFFSET /* 2nd stage bootloader iram_loader_seg start address */ +#define SRAM_DIRAM_I_START 0x40378000 +#define SRAM_IRAM_END 0x403BA000 +#define I_D_SRAM_OFFSET (SRAM_DIRAM_I_START - SRAM_DRAM_START) +#define SRAM_DRAM_START 0x3FC88000 +#define SRAM_DRAM_END (SRAM_IRAM_END - I_D_SRAM_OFFSET) /* 2nd stage bootloader iram_loader_seg start address */ +#define I_D_SRAM_SIZE (SRAM_DRAM_END - SRAM_DRAM_START) + + +#define ICACHE_SIZE 0x8000 #define SRAM_IRAM_ORG (SRAM_IRAM_START + CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE) -#define SRAM_DRAM_ORG (SRAM_DRAM_START + CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE) +#define SRAM_IRAM_SIZE (I_D_SRAM_SIZE + ICACHE_SIZE - CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE) -#define I_D_SRAM_SIZE SRAM_DRAM_END - SRAM_DRAM_ORG +#define DCACHE_SIZE 0x10000 +#define SRAM_DRAM_ORG (SRAM_DRAM_START) #if CONFIG_ESP32S3_USE_FIXED_STATIC_RAM_SIZE ASSERT((CONFIG_ESP32S3_FIXED_STATIC_RAM_SIZE <= I_D_SRAM_SIZE), "Fixed static ram data does not fit.") @@ -42,11 +67,11 @@ MEMORY */ /* IRAM for PRO CPU. */ - iram0_0_seg (RX) : org = SRAM_IRAM_ORG, len = I_D_SRAM_SIZE + iram0_0_seg (RX) : org = SRAM_IRAM_ORG, len = SRAM_IRAM_SIZE #if CONFIG_APP_BUILD_USE_FLASH_SECTIONS /* Flash mapped instruction data */ - iram0_2_seg (RX) : org = 0x42000020, len = 0x2000000-0x20 + iram0_2_seg (RX) : org = 0x42000020, len = 0x800000-0x20 /** * (0x20 offset above is a convenience for the app binary image generation. @@ -65,7 +90,7 @@ MEMORY #if CONFIG_APP_BUILD_USE_FLASH_SECTIONS /* Flash mapped constant data */ - drom0_0_seg (R) : org = 0x3C000020, len = 0x2000000-0x20 + drom0_0_seg (R) : org = 0x3C000020, len = 0x800000-0x20 /* (See iram0_2_seg for meaning of 0x20 offset in the above.) */ #endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS diff --git a/components/esp_system/ld/esp32s3/sections.ld.in b/components/esp_system/ld/esp32s3/sections.ld.in index 50ca055298..7ef4075a31 100644 --- a/components/esp_system/ld/esp32s3/sections.ld.in +++ b/components/esp_system/ld/esp32s3/sections.ld.in @@ -1,6 +1,14 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + /* Default entry point */ ENTRY(call_start_cpu0); +_diram_i_start = 0x40378000; + SECTIONS { /** @@ -175,7 +183,7 @@ SECTIONS */ .dram0.dummy (NOLOAD): { - . = ORIGIN(dram0_0_seg) + _iram_end - _iram_start; + . = ORIGIN(dram0_0_seg) + MAX(_iram_end - _diram_i_start, 0); } > dram0_0_seg .dram0.data : @@ -262,7 +270,7 @@ SECTIONS * safe access to up to 16 bytes after the last real instruction, add * dummy bytes to ensure this */ - . += 16; + . += _esp_flash_mmap_prefetch_pad_size; _text_end = ABSOLUTE(.); _instruction_reserved_end = ABSOLUTE(.); @@ -374,7 +382,11 @@ SECTIONS /* Marks the end of IRAM code segment */ .iram0.text_end (NOLOAD) : { - . = ALIGN (4); + /* ESP32-S3 memprot requires 16B padding for possible CPU prefetch and 256B alignment for PMS split lines */ + . += _esp_memprot_prefetch_pad_size; + . = ALIGN(_esp_memprot_align_size); + /* iram_end_test section exists for use by memprot unit tests only */ + *(.iram_end_test) _iram_text_end = ABSOLUTE(.); } > iram0_0_seg diff --git a/components/esp_system/ld/ld.cmake b/components/esp_system/ld/ld.cmake index 93376b69c1..5e80268da7 100644 --- a/components/esp_system/ld/ld.cmake +++ b/components/esp_system/ld/ld.cmake @@ -22,7 +22,8 @@ idf_build_get_property(config_dir CONFIG_DIR) # Preprocess memory.ld.in linker script to include configuration, becomes memory.ld add_custom_command( OUTPUT ${ld_output} - COMMAND "${CMAKE_C_COMPILER}" -C -P -x c -E -o ${ld_output} -I ${config_dir} ${ld_input} + COMMAND "${CMAKE_C_COMPILER}" -C -P -x c -E -o ${ld_output} -I ${config_dir} + -I "${CMAKE_CURRENT_LIST_DIR}" ${ld_input} MAIN_DEPENDENCY ${ld_input} DEPENDS ${sdkconfig_header} COMMENT "Generating memory.ld linker script..." diff --git a/components/esp_system/ld/ld.common b/components/esp_system/ld/ld.common new file mode 100644 index 0000000000..974cafe5d4 --- /dev/null +++ b/components/esp_system/ld/ld.common @@ -0,0 +1,24 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "sdkconfig.h" + +/* CPU instruction prefetch padding size for flash mmap scenario */ +_esp_flash_mmap_prefetch_pad_size = 16; + +/* CPU instruction prefetch padding size for memory protection scenario */ +#ifdef CONFIG_ESP_SYSTEM_MEMPROT_CPU_PREFETCH_PAD_SIZE +_esp_memprot_prefetch_pad_size = CONFIG_ESP_SYSTEM_MEMPROT_CPU_PREFETCH_PAD_SIZE; +#else +_esp_memprot_prefetch_pad_size = 0; +#endif + +/* Memory alignment size for PMS */ +#ifdef CONFIG_ESP_SYSTEM_MEMPROT_MEM_ALIGN_SIZE +_esp_memprot_align_size = CONFIG_ESP_SYSTEM_MEMPROT_MEM_ALIGN_SIZE; +#else +_esp_memprot_align_size = 0; +#endif diff --git a/components/esp_system/panic.c b/components/esp_system/panic.c index 72d57f5616..722975b7c7 100644 --- a/components/esp_system/panic.c +++ b/components/esp_system/panic.c @@ -385,7 +385,7 @@ void esp_panic_handler(panic_info_t *info) } -void __attribute__((noreturn, no_sanitize_undefined)) panic_abort(const char *details) +void IRAM_ATTR __attribute__((noreturn, no_sanitize_undefined)) panic_abort(const char *details) { g_panic_abort = true; s_panic_abort_details = (char *) details; @@ -399,7 +399,7 @@ void __attribute__((noreturn, no_sanitize_undefined)) panic_abort(const char *de #endif #endif - *((int *) 0) = 0; // NOLINT(clang-analyzer-core.NullDereference) should be an invalid operation on targets + *((volatile int *) 0) = 0; // NOLINT(clang-analyzer-core.NullDereference) should be an invalid operation on targets while (1); } diff --git a/components/esp_system/port/arch/xtensa/panic_arch.c b/components/esp_system/port/arch/xtensa/panic_arch.c index fb1e021df0..0eadb67c97 100644 --- a/components/esp_system/port/arch/xtensa/panic_arch.c +++ b/components/esp_system/port/arch/xtensa/panic_arch.c @@ -76,7 +76,7 @@ void panic_print_registers(const void *f, int core) && ((core == 0 && frame->exccause == PANIC_RSN_INTWDT_CPU0) || (core == 1 && frame->exccause == PANIC_RSN_INTWDT_CPU1)) #endif //!CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE - ) { + ) { panic_print_str("\r\n"); @@ -264,27 +264,46 @@ static inline void print_cache_err_details(const void *f) } #if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE +#define MEMPROT_OP_INVALID 0xFFFFFFFF static inline void print_memprot_err_details(const void *f) { uint32_t *fault_addr; uint32_t op_type, op_subtype; - mem_type_prot_t mem_type = esp_memprot_get_active_intr_memtype(); - esp_memprot_get_fault_status( mem_type, &fault_addr, &op_type, &op_subtype ); + const char *operation_type; - char *operation_type = "Write"; - if ( op_type == 0 ) { - operation_type = (mem_type == MEMPROT_IRAM0_SRAM && op_subtype == 0) ? "Instruction fetch" : "Read"; + mem_type_prot_t mem_type = esp_memprot_get_active_intr_memtype(); + if (mem_type != MEMPROT_NONE) { +#if CONFIG_IDF_TARGET_ESP32S2 //specific for ESP32S2 unless IDF-3024 is merged + if (esp_memprot_get_fault_status(mem_type, &fault_addr, &op_type, &op_subtype) != ESP_OK) { + op_type = MEMPROT_OP_INVALID; + } +#else + esp_memprot_get_fault_status(mem_type, &fault_addr, &op_type, &op_subtype); +#endif } - panic_print_str( operation_type ); - panic_print_str( " operation at address 0x" ); - panic_print_hex( (uint32_t)fault_addr ); - panic_print_str(" not permitted.\r\n"); + if (op_type == MEMPROT_OP_INVALID) { + operation_type = "Unknown"; + fault_addr = (uint32_t *)MEMPROT_OP_INVALID; + } else { + if (op_type == 0) { + operation_type = (mem_type == MEMPROT_IRAM0_SRAM && op_subtype == 0) ? "Instruction fetch" : "Read"; + } else { + operation_type = "Write"; + } + } + + panic_print_str(operation_type); + panic_print_str(" operation at address 0x"); + panic_print_hex((uint32_t)fault_addr); + panic_print_str(" not permitted ("); + panic_print_str(esp_memprot_type_to_str(mem_type)); + panic_print_str(")\r\n"); } #endif #elif CONFIG_IDF_TARGET_ESP32S3 -static inline void print_cache_err_details(const void* f) +static inline void print_cache_err_details(const void *f) { uint32_t vaddr = 0, size = 0; uint32_t status; @@ -355,7 +374,7 @@ static inline void print_cache_err_details(const void* f) void panic_arch_fill_info(void *f, panic_info_t *info) { - XtExcFrame *frame = (XtExcFrame*) f; + XtExcFrame *frame = (XtExcFrame *) f; static const char *reason[] = { "IllegalInstruction", "Syscall", "InstructionFetchError", "LoadStoreError", "Level1Interrupt", "Alloca", "IntegerDivideByZero", "PCValue", @@ -388,7 +407,7 @@ void panic_soc_fill_info(void *f, panic_info_t *info) { // [refactor-todo] this should be in the common port panic_handler.c, once // these special exceptions are supported in there. - XtExcFrame *frame = (XtExcFrame*) f; + XtExcFrame *frame = (XtExcFrame *) f; if (frame->exccause == PANIC_RSN_INTWDT_CPU0) { info->core = 0; info->exception = PANIC_EXCEPTION_IWDT; @@ -442,19 +461,19 @@ void panic_soc_fill_info(void *f, panic_info_t *info) #endif } -uint32_t panic_get_address(const void* f) +uint32_t panic_get_address(const void *f) { - return ((XtExcFrame*)f)->pc; + return ((XtExcFrame *)f)->pc; } -uint32_t panic_get_cause(const void* f) +uint32_t panic_get_cause(const void *f) { - return ((XtExcFrame*)f)->exccause; + return ((XtExcFrame *)f)->exccause; } void panic_set_address(void *f, uint32_t addr) { - ((XtExcFrame*)f)->pc = addr; + ((XtExcFrame *)f)->pc = addr; } void panic_print_backtrace(const void *f, int core) diff --git a/components/esp_system/port/arch/xtensa/panic_handler_asm.S b/components/esp_system/port/arch/xtensa/panic_handler_asm.S index b0a5754271..3328f55537 100644 --- a/components/esp_system/port/arch/xtensa/panic_handler_asm.S +++ b/components/esp_system/port/arch/xtensa/panic_handler_asm.S @@ -54,7 +54,7 @@ _xt_panic: s32i a0, sp, XT_STK_A0 /* Set up PS for C, disable all interrupts except NMI and debug, and clear EXCM. */ - movi a0, PS_INTLEVEL(5) | PS_UM | PS_WOE + movi a0, PS_INTLEVEL(XCHAL_DEBUGLEVEL - 2) | PS_UM | PS_WOE wsr a0, PS //Call panic handler diff --git a/components/esp_system/port/cpu_start.c b/components/esp_system/port/cpu_start.c index 023f1a943e..dc2f51a5e0 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -125,16 +125,15 @@ extern int _vector_table; static const char *TAG = "cpu_start"; -#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY extern int _ext_ram_bss_start; extern int _ext_ram_bss_end; #endif + #ifdef CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY extern int _iram_bss_start; extern int _iram_bss_end; #endif -#endif // CONFIG_IDF_TARGET_ESP32 #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE static volatile bool s_cpu_up[SOC_CPU_CORES_NUM] = { false }; @@ -306,7 +305,7 @@ void IRAM_ATTR call_start_cpu0(void) // from panic handler we can be reset by RWDT or TG0WDT if (rst_reas[0] == RESET_REASON_CORE_RTC_WDT || rst_reas[0] == RESET_REASON_CORE_MWDT0 #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE - || rst_reas[1] == RESET_REASON_CORE_RTC_WDT || rst_reas[1] == RESET_REASON_CORE_MWDT0 + || rst_reas[1] == RESET_REASON_CORE_RTC_WDT || rst_reas[1] == RESET_REASON_CORE_MWDT0 #endif ) { wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &RTCCNTL}; @@ -363,9 +362,19 @@ void IRAM_ATTR call_start_cpu0(void) extern int _rodata_reserved_start; uint32_t rodata_reserved_start_align = (uint32_t)&_rodata_reserved_start & ~(MMU_PAGE_SIZE - 1); uint32_t cache_mmu_irom_size = ((rodata_reserved_start_align - SOC_DROM_LOW) / MMU_PAGE_SIZE) * sizeof(uint32_t); + +#if CONFIG_IDF_TARGET_ESP32S3 + extern int _rodata_reserved_end; + uint32_t cache_mmu_drom_size = (((uint32_t)&_rodata_reserved_end - rodata_reserved_start_align + MMU_PAGE_SIZE - 1)/MMU_PAGE_SIZE)*sizeof(uint32_t); +#endif + Cache_Set_IDROM_MMU_Size(cache_mmu_irom_size, CACHE_DROM_MMU_MAX_END - cache_mmu_irom_size); #endif // CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 + esp_mspi_pin_init(); + // For Octal flash, it's hard to implement a read_id function in OPI mode for all vendors. + // So we have to read it here in SPI mode, before entering the OPI mode. + bootloader_flash_update_id(); #if CONFIG_ESPTOOLPY_OCT_FLASH bool efuse_opflash_en = REG_GET_FIELD(EFUSE_RD_REPEAT_DATA3_REG, EFUSE_FLASH_TYPE); if (!efuse_opflash_en) { @@ -373,13 +382,16 @@ void IRAM_ATTR call_start_cpu0(void) abort(); } esp_opiflash_init(); +#endif +#if CONFIG_IDF_TARGET_ESP32S3 + //On other chips, this feature is not provided by HW, or hasn't been tested yet. spi_timing_flash_tuning(); #endif bootloader_init_mem(); #if CONFIG_SPIRAM_BOOT_INIT if (esp_spiram_init() != ESP_OK) { -#if CONFIG_IDF_TARGET_ESP32 +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 #if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY ESP_EARLY_LOGE(TAG, "Failed to init external RAM, needed for external .bss segment"); abort(); @@ -452,18 +464,43 @@ void IRAM_ATTR call_start_cpu0(void) esp_spiram_enable_rodata_access(); #endif -#if CONFIG_ESP32S2_INSTRUCTION_CACHE_WRAP || CONFIG_ESP32S2_DATA_CACHE_WRAP +#if CONFIG_IDF_TARGET_ESP32S3 + int s_instr_flash2spiram_off = 0; + int s_rodata_flash2spiram_off = 0; +#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS + s_instr_flash2spiram_off = instruction_flash2spiram_offset(); +#endif +#if CONFIG_SPIRAM_RODATA + s_rodata_flash2spiram_off = rodata_flash2spiram_offset(); +#endif + + extern void Cache_Set_IDROM_MMU_Info(uint32_t instr_page_num, uint32_t rodata_page_num, uint32_t rodata_start, uint32_t rodata_end, int i_off, int ro_off); + Cache_Set_IDROM_MMU_Info(cache_mmu_irom_size/sizeof(uint32_t), \ + cache_mmu_drom_size/sizeof(uint32_t), \ + (uint32_t)&_rodata_reserved_start, \ + (uint32_t)&_rodata_reserved_end, \ + s_instr_flash2spiram_off, \ + s_rodata_flash2spiram_off); +#endif + +#if CONFIG_ESP32S2_INSTRUCTION_CACHE_WRAP || CONFIG_ESP32S2_DATA_CACHE_WRAP || \ + CONFIG_ESP32S3_INSTRUCTION_CACHE_WRAP || CONFIG_ESP32S3_DATA_CACHE_WRAP uint32_t icache_wrap_enable = 0, dcache_wrap_enable = 0; -#if CONFIG_ESP32S2_INSTRUCTION_CACHE_WRAP +#if CONFIG_ESP32S2_INSTRUCTION_CACHE_WRAP || CONFIG_ESP32S3_INSTRUCTION_CACHE_WRAP icache_wrap_enable = 1; #endif -#if CONFIG_ESP32S2_DATA_CACHE_WRAP +#if CONFIG_ESP32S2_DATA_CACHE_WRAP || CONFIG_ESP32S3_DATA_CACHE_WRAP dcache_wrap_enable = 1; #endif extern void esp_enable_cache_wrap(uint32_t icache_wrap_enable, uint32_t dcache_wrap_enable); esp_enable_cache_wrap(icache_wrap_enable, dcache_wrap_enable); #endif +#if CONFIG_ESP32S3_DATA_CACHE_16KB + Cache_Invalidate_DCache_All(); + Cache_Occupy_Addr(SOC_DROM_LOW, 0x4000); +#endif + #if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY memset(&_ext_ram_bss_start, 0, (&_ext_ram_bss_end - &_ext_ram_bss_start) * sizeof(_ext_ram_bss_start)); #endif @@ -513,18 +550,30 @@ void IRAM_ATTR call_start_cpu0(void) #if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE // Memprot cannot be locked during OS startup as the lock-on prevents any PMS changes until a next reboot // If such a situation appears, it is likely an malicious attempt to bypass the system safety setup -> print error & reset - if ( esp_memprot_is_locked_any() ) { + if (esp_memprot_is_locked_any()) { ESP_EARLY_LOGE(TAG, "Memprot feature locked after the system reset! Potential safety corruption, rebooting."); esp_restart_noos_dig(); } + esp_err_t memp_err = ESP_OK; #if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK +#if CONFIG_IDF_TARGET_ESP32S2 //specific for ESP32S2 unless IDF-3024 is merged + memp_err = esp_memprot_set_prot(true, true, NULL); +#else esp_memprot_set_prot(true, true, NULL); +#endif +#else +#if CONFIG_IDF_TARGET_ESP32S2 //specific for ESP32S2 unless IDF-3024 is merged + memp_err = esp_memprot_set_prot(true, false, NULL); #else esp_memprot_set_prot(true, false, NULL); #endif +#endif + if (memp_err != ESP_OK) { + ESP_EARLY_LOGE(TAG, "Failed to set Memprot feature (error 0x%08X), rebooting.", memp_err); + esp_restart_noos_dig(); + } #endif - bootloader_flash_update_id(); // 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}; #ifdef CONFIG_APP_BUILD_TYPE_ELF_RAM diff --git a/components/esp_system/port/panic_handler.c b/components/esp_system/port/panic_handler.c index d8993f8721..58c27e76dc 100644 --- a/components/esp_system/port/panic_handler.c +++ b/components/esp_system/port/panic_handler.c @@ -14,7 +14,7 @@ #include #include "esp_spi_flash.h" - +#include "esp_ipc_isr.h" #include "esp_private/system_internal.h" #include "soc/soc_memory_layout.h" @@ -165,9 +165,7 @@ static void panic_handler(void *frame, bool pseudo_excause) SOC_HAL_STALL_OTHER_CORES(); #endif -#if CONFIG_IDF_TARGET_ESP32 - esp_dport_access_int_abort(); -#endif + esp_ipc_isr_stall_abort(); if (esp_cpu_in_ocd_debug_mode()) { #if __XTENSA__ @@ -205,9 +203,7 @@ static void IRAM_ATTR panic_enable_cache(void) { int core_id = cpu_hal_get_core_id(); if (!spi_flash_cache_enabled()) { -#ifdef CONFIG_IDF_TARGET_ESP32 - esp_dport_access_int_abort(); -#endif + esp_ipc_isr_stall_abort(); spi_flash_enable_cache(core_id); } } diff --git a/components/esp_system/port/soc/esp32/CMakeLists.txt b/components/esp_system/port/soc/esp32/CMakeLists.txt index 570dbc4b97..e66f3d9234 100644 --- a/components/esp_system/port/soc/esp32/CMakeLists.txt +++ b/components/esp_system/port/soc/esp32/CMakeLists.txt @@ -1,4 +1,4 @@ -set(srcs "dport_panic_highint_hdl.S" +set(srcs "highint_hdl.S" "clk.c" "reset_reason.c" "system_internal.c" @@ -15,7 +15,7 @@ add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs}) target_sources(${COMPONENT_LIB} PRIVATE ${srcs}) -#ld_include_panic_highint_hdl is added as an undefined symbol because otherwise the +#ld_include_highint_hdl is added as an undefined symbol because otherwise the #linker will ignore panic_highint_hdl.S as it has no other files depending on any #symbols in it. -set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u ld_include_panic_highint_hdl") +set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u ld_include_highint_hdl") diff --git a/components/esp_system/port/soc/esp32/dport_panic_highint_hdl.S b/components/esp_system/port/soc/esp32/highint_hdl.S similarity index 65% rename from components/esp_system/port/soc/esp32/dport_panic_highint_hdl.S rename to components/esp_system/port/soc/esp32/highint_hdl.S index 35e7508b05..3ae31686d2 100644 --- a/components/esp_system/port/soc/esp32/dport_panic_highint_hdl.S +++ b/components/esp_system/port/soc/esp32/highint_hdl.S @@ -27,162 +27,35 @@ /* Interrupt , a high-priority interrupt, is used for several things: -- Dport access mediation +- IPC_ISR handler - Cache error panic handler - Interrupt watchdog panic handler */ -#define L4_INTR_STACK_SIZE 12 -#define L4_INTR_A2_OFFSET 0 -#define L4_INTR_A3_OFFSET 4 -#define L4_INTR_A4_OFFSET 8 - .data -_l4_intr_stack: - .space L4_INTR_STACK_SIZE*portNUM_PROCESSORS /* This allocates stacks for each individual CPU. */ +#if CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_5 -#if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX && CONFIG_ESP_INT_WDT - .global _l4_intr_livelock_counter - .global _l4_intr_livelock_max - .align 16 -_l4_intr_livelock_counter: - .word 0 -_l4_intr_livelock_max: - .word 0 -_l4_intr_livelock_sync: - .word 0, 0 -_l4_intr_livelock_app: - .word 0 -_l4_intr_livelock_pro: - .word 0 -#endif +#define LX_INTR_STACK_SIZE 12 +#define LX_INTR_A2_OFFSET 0 +#define LX_INTR_A3_OFFSET 4 +#define LX_INTR_A4_OFFSET 8 +#define EPC_X EPC_5 +#define EXCSAVE_X EXCSAVE_5 +#define RFI_X 5 +#define xt_highintx xt_highint5 - .section .iram1,"ax" - .global xt_highint4 - .type xt_highint4,@function - .align 4 -xt_highint4: +#elif CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4 -#ifndef CONFIG_FREERTOS_UNICORE - /* See if we're here for the dport access interrupt */ - rsr a0, INTERRUPT - extui a0, a0, ETS_DPORT_INUM, 1 - bnez a0, .handle_dport_access_int -#endif // CONFIG_FREERTOS_UNICORE +#define LX_INTR_STACK_SIZE 12 +#define LX_INTR_A2_OFFSET 0 +#define LX_INTR_A3_OFFSET 4 +#define LX_INTR_A4_OFFSET 8 +#define EPC_X EPC_4 +#define EXCSAVE_X EXCSAVE_4 +#define RFI_X 4 +#define xt_highintx xt_highint4 -#if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX && CONFIG_ESP_INT_WDT - /* See if we're here for the tg1 watchdog interrupt */ - rsr a0, INTERRUPT - extui a0, a0, ETS_T1_WDT_INUM, 1 - beqz a0, 1f - - wsr a5, depc /* use DEPC as temp storage */ - movi a0, _l4_intr_livelock_counter - l32i a0, a0, 0 - movi a5, _l4_intr_livelock_max - l32i a5, a5, 0 - bltu a0, a5, .handle_livelock_int /* _l4_intr_livelock_counter < _l4_intr_livelock_max */ - - rsr a5, depc /* restore a5 */ -#endif - - /* Allocate exception frame and save minimal context. */ -1: mov a0, sp - addi sp, sp, -XT_STK_FRMSZ - s32i a0, sp, XT_STK_A1 - #if XCHAL_HAVE_WINDOWED - s32e a0, sp, -12 /* for debug backtrace */ - #endif - rsr a0, PS /* save interruptee's PS */ - s32i a0, sp, XT_STK_PS - rsr a0, EPC_4 /* save interruptee's PC */ - s32i a0, sp, XT_STK_PC - #if XCHAL_HAVE_WINDOWED - s32e a0, sp, -16 /* for debug backtrace */ - #endif - s32i a12, sp, XT_STK_A12 /* _xt_context_save requires A12- */ - s32i a13, sp, XT_STK_A13 /* A13 to have already been saved */ - call0 _xt_context_save - - /* Save vaddr into exception frame */ - rsr a0, EXCVADDR - s32i a0, sp, XT_STK_EXCVADDR - - /* Figure out reason, save into EXCCAUSE reg */ - - rsr a0, INTERRUPT - extui a0, a0, ETS_MEMACCESS_ERR_INUM, 1 /* get cacheerr int bit */ - beqz a0, 1f - /* Kill this interrupt; we cannot reset it. */ - rsr a0, INTENABLE - movi a4, ~(1<= RESET_REASON_CPU0_MWDT0 && rst_reason <= RESET_REASON_CPU0_RTC_WDT && rst_reason != RESET_REASON_SYS_BROWN_OUT) { + if ((rst_reas[0] >= RESET_REASON_CPU0_MWDT0 && rst_reas[0] <= RESET_REASON_CPU0_RTC_WDT && rst_reas[0] != RESET_REASON_SYS_BROWN_OUT)) { common_perip_clk = ~READ_PERI_REG(SYSTEM_PERIP_CLK_EN0_REG); hwcrypto_perip_clk = ~READ_PERI_REG(SYSTEM_PERIP_CLK_EN1_REG); } else { diff --git a/components/esp_system/port/soc/esp32h2/system_internal.c b/components/esp_system/port/soc/esp32h2/system_internal.c index e280343136..d3b451bd53 100644 --- a/components/esp_system/port/soc/esp32h2/system_internal.c +++ b/components/esp_system/port/soc/esp32h2/system_internal.c @@ -94,7 +94,7 @@ void IRAM_ATTR esp_restart_noos(void) // Reset timer/spi/uart SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG, - SYSTEM_TIMERS_RST | SYSTEM_SPI01_RST | SYSTEM_UART_RST); + SYSTEM_TIMERS_RST | SYSTEM_SPI01_RST | SYSTEM_UART_RST | SYSTEM_SYSTIMER_RST); REG_WRITE(SYSTEM_PERIP_RST_EN0_REG, 0); // Reset dma SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST); diff --git a/components/esp_system/port/soc/esp32s2/CMakeLists.txt b/components/esp_system/port/soc/esp32s2/CMakeLists.txt index e8af06695e..d606f3e661 100644 --- a/components/esp_system/port/soc/esp32s2/CMakeLists.txt +++ b/components/esp_system/port/soc/esp32s2/CMakeLists.txt @@ -1,4 +1,4 @@ -set(srcs "dport_panic_highint_hdl.S" +set(srcs "highint_hdl.S" "clk.c" "reset_reason.c" "system_internal.c" @@ -18,7 +18,7 @@ if(CONFIG_ESP_CONSOLE_USB_CDC) target_sources(${COMPONENT_LIB} PRIVATE "${CMAKE_CURRENT_LIST_DIR}/usb_console.c") endif() -#ld_include_panic_highint_hdl is added as an undefined symbol because otherwise the -#linker will ignore panic_highint_hdl.S as it has no other files depending on any +#ld_include_highint_hdl is added as an undefined symbol because otherwise the +#linker will ignore highint_hdl.S as it has no other files depending on any #symbols in it. -set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u ld_include_panic_highint_hdl") +set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u ld_include_highint_hdl") diff --git a/components/esp_system/port/soc/esp32s2/dport_panic_highint_hdl.S b/components/esp_system/port/soc/esp32s2/highint_hdl.S similarity index 98% rename from components/esp_system/port/soc/esp32s2/dport_panic_highint_hdl.S rename to components/esp_system/port/soc/esp32s2/highint_hdl.S index 73cd4fc9d7..845a50a440 100644 --- a/components/esp_system/port/soc/esp32s2/dport_panic_highint_hdl.S +++ b/components/esp_system/port/soc/esp32s2/highint_hdl.S @@ -106,5 +106,5 @@ xt_highint4: (weakly!) in the default int handler. Define a symbol here so we can use it to have the linker inspect this anyway. */ - .global ld_include_panic_highint_hdl -ld_include_panic_highint_hdl: + .global ld_include_highint_hdl +ld_include_highint_hdl: diff --git a/components/esp_system/port/soc/esp32s3/CMakeLists.txt b/components/esp_system/port/soc/esp32s3/CMakeLists.txt index e8af06695e..b944b7f875 100644 --- a/components/esp_system/port/soc/esp32s3/CMakeLists.txt +++ b/components/esp_system/port/soc/esp32s3/CMakeLists.txt @@ -1,8 +1,9 @@ -set(srcs "dport_panic_highint_hdl.S" +set(srcs "highint_hdl.S" "clk.c" "reset_reason.c" "system_internal.c" "cache_err_int.c" + "apb_backup_dma.c" "../../arch/xtensa/panic_arch.c" "../../arch/xtensa/panic_handler_asm.S" "../../arch/xtensa/expression_with_stack.c" @@ -18,7 +19,7 @@ if(CONFIG_ESP_CONSOLE_USB_CDC) target_sources(${COMPONENT_LIB} PRIVATE "${CMAKE_CURRENT_LIST_DIR}/usb_console.c") endif() -#ld_include_panic_highint_hdl is added as an undefined symbol because otherwise the +#ld_include_highint_hdl is added as an undefined symbol because otherwise the #linker will ignore panic_highint_hdl.S as it has no other files depending on any #symbols in it. -set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u ld_include_panic_highint_hdl") +set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u ld_include_highint_hdl") diff --git a/components/esp_system/port/soc/esp32s3/apb_backup_dma.c b/components/esp_system/port/soc/esp32s3/apb_backup_dma.c new file mode 100644 index 0000000000..ef4d2558ad --- /dev/null +++ b/components/esp_system/port/soc/esp32s3/apb_backup_dma.c @@ -0,0 +1,36 @@ +/* + * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/soc_caps.h" +#include "esp_attr.h" +#include "freertos/FreeRTOS.h" +#include "freertos/portmacro.h" +#include "esp32s3/rom/apb_backup_dma.h" + +static portMUX_TYPE s_apb_backup_dma_mutex = portMUX_INITIALIZER_UNLOCKED; + +static void IRAM_ATTR apb_backup_dma_lock(void) +{ + if (xPortInIsrContext()) { + portENTER_CRITICAL_ISR(&s_apb_backup_dma_mutex); + } else { + portENTER_CRITICAL(&s_apb_backup_dma_mutex); + } +} + +static void IRAM_ATTR apb_backup_dma_unlock(void) +{ + if (xPortInIsrContext()) { + portEXIT_CRITICAL_ISR(&s_apb_backup_dma_mutex); + } else { + portEXIT_CRITICAL(&s_apb_backup_dma_mutex); + } +} + +void esp_apb_backup_dma_lock_init(void) +{ + ets_apb_backup_init_lock_func(apb_backup_dma_lock, apb_backup_dma_unlock); +} diff --git a/components/esp_system/port/soc/esp32s3/clk.c b/components/esp_system/port/soc/esp32s3/clk.c index 34639b44ee..79b125cc04 100644 --- a/components/esp_system/port/soc/esp32s3/clk.c +++ b/components/esp_system/port/soc/esp32s3/clk.c @@ -76,6 +76,12 @@ static void select_rtc_slow_clk(slow_clk_sel_t slow_clk); __attribute__((weak)) void esp_clk_init(void) { rtc_config_t cfg = RTC_CONFIG_DEFAULT(); + soc_reset_reason_t rst_reas; + rst_reas = esp_rom_get_reset_reason(0); + //When power on, we need to set `cali_ocode` to 1, to do a OCode calibration, which will calibrate the rtc reference voltage to a tested value + if (rst_reas == RESET_REASON_CHIP_POWER_ON) { + cfg.cali_ocode = 1; + } rtc_init(cfg); assert(rtc_clk_xtal_freq_get() == RTC_XTAL_FREQ_40M); @@ -311,6 +317,11 @@ __attribute__((weak)) void esp_perip_clk_init(void) CLEAR_PERI_REG_MASK(SYSTEM_WIFI_CLK_EN_REG, wifi_bt_sdio_clk); SET_PERI_REG_MASK(SYSTEM_WIFI_CLK_EN_REG, SYSTEM_WIFI_CLK_EN); + /* Set WiFi light sleep clock source to RTC slow clock */ + REG_SET_FIELD(SYSTEM_BT_LPCK_DIV_INT_REG, SYSTEM_BT_LPCK_DIV_NUM, 0); + CLEAR_PERI_REG_MASK(SYSTEM_BT_LPCK_DIV_FRAC_REG, SYSTEM_LPCLK_SEL_8M); + SET_PERI_REG_MASK(SYSTEM_BT_LPCK_DIV_FRAC_REG, SYSTEM_LPCLK_SEL_RTC_SLOW); + /* Enable RNG clock. */ periph_module_enable(PERIPH_RNG_MODULE); } diff --git a/components/esp_system/port/soc/esp32s3/dport_panic_highint_hdl.S b/components/esp_system/port/soc/esp32s3/highint_hdl.S similarity index 93% rename from components/esp_system/port/soc/esp32s3/dport_panic_highint_hdl.S rename to components/esp_system/port/soc/esp32s3/highint_hdl.S index 45f21c29f2..91916e2cef 100644 --- a/components/esp_system/port/soc/esp32s3/dport_panic_highint_hdl.S +++ b/components/esp_system/port/soc/esp32s3/highint_hdl.S @@ -26,6 +26,7 @@ /* Interrupt , a high-priority interrupt, is used for several things: +- IPC_ISR handler - Cache error panic handler - Interrupt watchdog panic handler @@ -44,6 +45,13 @@ _l4_intr_stack: .align 4 xt_highint4: +#ifndef CONFIG_FREERTOS_UNICORE + /* See if we're here for the IPC_ISR interrupt */ + rsr a0, INTERRUPT + extui a0, a0, ETS_IPC_ISR_INUM, 1 + bnez a0, esp_ipc_isr_handler +#endif // not CONFIG_FREERTOS_UNICORE + /* Allocate exception frame and save minimal context. */ mov a0, sp addi sp, sp, -XT_STK_FRMSZ @@ -126,5 +134,5 @@ xt_highint4: (weakly!) in the default int handler. Define a symbol here so we can use it to have the linker inspect this anyway. */ - .global ld_include_panic_highint_hdl -ld_include_panic_highint_hdl: + .global ld_include_highint_hdl +ld_include_highint_hdl: diff --git a/components/esp_system/port/soc/esp32s3/system_internal.c b/components/esp_system/port/soc/esp32s3/system_internal.c index 18dad4005a..551e90e724 100644 --- a/components/esp_system/port/soc/esp32s3/system_internal.c +++ b/components/esp_system/port/soc/esp32s3/system_internal.c @@ -103,7 +103,7 @@ void IRAM_ATTR esp_restart_noos(void) // Reset timer/spi/uart SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG, - SYSTEM_TIMERS_RST | SYSTEM_SPI01_RST | SYSTEM_UART_RST); + SYSTEM_TIMERS_RST | SYSTEM_SPI01_RST | SYSTEM_UART_RST | SYSTEM_SYSTIMER_RST); REG_WRITE(SYSTEM_PERIP_RST_EN0_REG, 0); // Reset dma diff --git a/components/esp_system/startup.c b/components/esp_system/startup.c index 8afc43087f..ddf6c82b77 100644 --- a/components/esp_system/startup.c +++ b/components/esp_system/startup.c @@ -41,6 +41,7 @@ #include "esp_flash_encrypt.h" #include "esp_secure_boot.h" #include "esp_sleep.h" +#include "esp_xt_wdt.h" /***********************************************/ // Headers for other components init functions @@ -344,6 +345,15 @@ static void do_core_init(void) // Note: in some configs this may read flash, so placed after flash init esp_secure_boot_init_checks(); #endif + +#if CONFIG_ESP_XT_WDT + esp_xt_wdt_config_t cfg = { + .timeout = CONFIG_ESP_XT_WDT_TIMEOUT, + .auto_backup_clk_enable = CONFIG_ESP_XT_WDT_BACKUP_CLK_ENABLE, + }; + err = esp_xt_wdt_init(&cfg); + assert(err == ESP_OK && "Failed to init xtwdt"); +#endif } static void do_secondary_init(void) diff --git a/components/esp_system/test/test_sleep.c b/components/esp_system/test/test_sleep.c index 8e85187d38..b742e6486e 100644 --- a/components/esp_system/test/test_sleep.c +++ b/components/esp_system/test/test_sleep.c @@ -111,13 +111,13 @@ TEST_CASE("light sleep stress test", "[deepsleep]") vSemaphoreDelete(done); } +static void timer_func(void* arg) +{ + esp_rom_delay_us(50); +} + TEST_CASE("light sleep stress test with periodic esp_timer", "[deepsleep]") { - void timer_func(void* arg) - { - esp_rom_delay_us(50); - } - SemaphoreHandle_t done = xSemaphoreCreateCounting(2, 0); esp_sleep_enable_timer_wakeup(1000); esp_timer_handle_t timer; diff --git a/components/esp_system/xt_wdt.c b/components/esp_system/xt_wdt.c new file mode 100644 index 0000000000..d3828df47c --- /dev/null +++ b/components/esp_system/xt_wdt.c @@ -0,0 +1,95 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp_xt_wdt.h" +#include "sdkconfig.h" +#include "soc/soc_caps.h" + +#include "esp_log.h" +#include "esp_check.h" +#include "esp_attr.h" +#include "esp_intr_alloc.h" +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" + +#if SOC_XT_WDT_SUPPORTED + +#include "driver/rtc_cntl.h" +#include "hal/xt_wdt_hal.h" +#include "hal/xt_wdt_ll.h" +#include "soc/rtc.h" + +#define RTC_CLK_CAL_CYCLES 500 + +const static char *TAG = "esp_xt_wdt"; + +static xt_wdt_hal_context_t s_hal_ctx; + +static esp_xt_callback_t s_callback_func; +static void *s_callback_arg; + +portMUX_TYPE s_xt_wdt_lock = portMUX_INITIALIZER_UNLOCKED; + +static IRAM_ATTR void rtc_xt_wdt_default_isr_handler(void *arg) +{ + ESP_EARLY_LOGE(TAG, "XTAL32K watchdog timer got triggered"); + + portENTER_CRITICAL_ISR(&s_xt_wdt_lock); + if (s_callback_func) { + (*s_callback_func)(s_callback_arg); + } + portEXIT_CRITICAL_ISR(&s_xt_wdt_lock); +} + +esp_err_t esp_xt_wdt_init(const esp_xt_wdt_config_t *cfg) +{ + esp_err_t ret = ESP_OK; + + xt_wdt_hal_config_t hal_config = { + .timeout = cfg->timeout, + }; + + xt_wdt_hal_init(&s_hal_ctx, &hal_config); + + if (cfg->auto_backup_clk_enable) { + /* Estimate frequency of internal RTC oscillator */ + uint32_t rtc_clk_frequency_khz = rtc_clk_freq_cal(rtc_clk_cal(RTC_CAL_INTERNAL_OSC, RTC_CLK_CAL_CYCLES)) / 1000; + ESP_LOGD(TAG, "Calibrating backup clock from rtc clock with frequency %d", rtc_clk_frequency_khz); + + xt_wdt_hal_enable_backup_clk(&s_hal_ctx, rtc_clk_frequency_khz); + } + + ESP_GOTO_ON_ERROR(rtc_isr_register(rtc_xt_wdt_default_isr_handler, NULL, XT_WDT_LL_XTAL32_DEAD_INTR_MASK), err, TAG, "Failed to register isr"); + + xt_wdt_hal_enable(&s_hal_ctx, 1); + + return ESP_OK; +err: + return ret; +} + +void esp_xt_wdt_restore_clk(void) +{ + xt_wdt_hal_enable(&s_hal_ctx, false); + + REG_CLR_BIT(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XPD_XTAL_32K); + REG_SET_BIT(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XPD_XTAL_32K); + + /* Needs some time after switching to 32khz XTAL before turning on WDT again */ + esp_rom_delay_us(300); + + xt_wdt_hal_enable(&s_hal_ctx, true); +} + +void esp_xt_wdt_register_callback(esp_xt_callback_t func, void *arg) +{ + portENTER_CRITICAL(&s_xt_wdt_lock); + s_callback_func = func; + s_callback_arg = arg; + portEXIT_CRITICAL(&s_xt_wdt_lock); +} + +#endif //SOC_XT_WDT_SUPPORTED diff --git a/components/esp_timer/src/esp_timer_impl_systimer.c b/components/esp_timer/src/esp_timer_impl_systimer.c index ead5d24cab..28bdb07212 100644 --- a/components/esp_timer/src/esp_timer_impl_systimer.c +++ b/components/esp_timer/src/esp_timer_impl_systimer.c @@ -133,7 +133,7 @@ esp_err_t esp_timer_impl_init(intr_handler_t alarm_handler) &timer_alarm_isr, NULL, &s_timer_interrupt_handle); if (err != ESP_OK) { - ESP_EARLY_LOGE(TAG, "esp_intr_alloc failed (%#x)", err); + ESP_EARLY_LOGE(TAG, "esp_intr_alloc failed (0x%x)", err); goto err_intr_alloc; } @@ -155,7 +155,7 @@ esp_err_t esp_timer_impl_init(intr_handler_t alarm_handler) err = esp_intr_enable(s_timer_interrupt_handle); if (err != ESP_OK) { - ESP_EARLY_LOGE(TAG, "esp_intr_enable failed (%#x)", err); + ESP_EARLY_LOGE(TAG, "esp_intr_enable failed (0x%x)", err); goto err_intr_en; } return ESP_OK; diff --git a/components/esp_timer/test/test_esp_timer.c b/components/esp_timer/test/test_esp_timer.c index bd0150331c..3ac57d848c 100644 --- a/components/esp_timer/test/test_esp_timer.c +++ b/components/esp_timer/test/test_esp_timer.c @@ -57,12 +57,12 @@ static void teardown_overflow(void) #endif // CONFIG_ESP_TIMER_IMPL_FRC2 +static void dummy_cb(void* arg) +{ +} + TEST_CASE("esp_timer orders timers correctly", "[esp_timer]") { - void dummy_cb(void* arg) - { - } - uint64_t timeouts[] = { 10000, 1000, 10000, 5000, 20000, 1000 }; size_t indices[] = { 3, 0, 4, 2, 5, 1 }; const size_t num_timers = sizeof(timeouts)/sizeof(timeouts[0]); @@ -116,28 +116,28 @@ TEST_CASE("esp_timer orders timers correctly", "[esp_timer]") fclose(stream); } +static const int test_time_sec = 10; + +static void set_alarm_task(void* arg) +{ + SemaphoreHandle_t done = (SemaphoreHandle_t) arg; + + int64_t start = esp_timer_impl_get_time(); + int64_t now = start; + int count = 0; + const int delays[] = {50, 5000, 10000000}; + const int delays_count = sizeof(delays)/sizeof(delays[0]); + while (now - start < test_time_sec * 1000000) { + now = esp_timer_impl_get_time(); + esp_timer_impl_set_alarm(now + delays[count % delays_count]); + ++count; + } + xSemaphoreGive(done); + vTaskDelete(NULL); +} + TEST_CASE("esp_timer_impl_set_alarm stress test", "[esp_timer]") { - const int test_time_sec = 10; - - void set_alarm_task(void* arg) - { - SemaphoreHandle_t done = (SemaphoreHandle_t) arg; - - int64_t start = esp_timer_impl_get_time(); - int64_t now = start; - int count = 0; - const int delays[] = {50, 5000, 10000000}; - const int delays_count = sizeof(delays)/sizeof(delays[0]); - while (now - start < test_time_sec * 1000000) { - now = esp_timer_impl_get_time(); - esp_timer_impl_set_alarm(now + delays[count % delays_count]); - ++count; - } - xSemaphoreGive(done); - vTaskDelete(NULL); - } - SemaphoreHandle_t done = xSemaphoreCreateCounting(portNUM_PROCESSORS, 0); setup_overflow(); xTaskCreatePinnedToCore(&set_alarm_task, "set_alarm_0", 4096, done, UNITY_FREERTOS_PRIORITY, NULL, 0); @@ -153,18 +153,18 @@ TEST_CASE("esp_timer_impl_set_alarm stress test", "[esp_timer]") vSemaphoreDelete(done); } +static void test_correct_delay_timer_func(void* arg) +{ + int64_t* p_end = (int64_t*) arg; + *p_end = ref_clock_get(); +} + TEST_CASE("esp_timer produces correct delay", "[esp_timer]") { - void timer_func(void* arg) - { - int64_t* p_end = (int64_t*) arg; - *p_end = ref_clock_get(); - } - int64_t t_end; esp_timer_handle_t timer1; esp_timer_create_args_t args = { - .callback = &timer_func, + .callback = &test_correct_delay_timer_func, .arg = &t_end, .name = "timer1" }; @@ -196,41 +196,41 @@ TEST_CASE("esp_timer produces correct delay", "[esp_timer]") esp_timer_delete(timer1); } -TEST_CASE("periodic esp_timer produces correct delays", "[esp_timer]") -{ - // no, we can't make this a const size_t (§6.7.5.2) +// no, we can't make this a const size_t (§6.7.5.2) #define NUM_INTERVALS 16 - typedef struct { - esp_timer_handle_t timer; - size_t cur_interval; - int intervals[NUM_INTERVALS]; - int64_t t_start; - SemaphoreHandle_t done; - } test_args_t; +typedef struct { + esp_timer_handle_t timer; + size_t cur_interval; + int intervals[NUM_INTERVALS]; + int64_t t_start; + SemaphoreHandle_t done; +} test_periodic_correct_delays_args_t; - void timer_func(void* arg) - { - test_args_t* p_args = (test_args_t*) arg; - int64_t t_end = ref_clock_get(); - int32_t ms_diff = (t_end - p_args->t_start) / 1000; - printf("timer #%d %dms\n", p_args->cur_interval, ms_diff); - p_args->intervals[p_args->cur_interval++] = ms_diff; - // Deliberately make timer handler run longer. - // We check that this doesn't affect the result. - esp_rom_delay_us(10*1000); - if (p_args->cur_interval == NUM_INTERVALS) { - printf("done\n"); - TEST_ESP_OK(esp_timer_stop(p_args->timer)); - xSemaphoreGive(p_args->done); - } +static void test_periodic_correct_delays_timer_func(void* arg) +{ + test_periodic_correct_delays_args_t* p_args = (test_periodic_correct_delays_args_t*) arg; + int64_t t_end = ref_clock_get(); + int32_t ms_diff = (t_end - p_args->t_start) / 1000; + printf("timer #%d %dms\n", p_args->cur_interval, ms_diff); + p_args->intervals[p_args->cur_interval++] = ms_diff; + // Deliberately make timer handler run longer. + // We check that this doesn't affect the result. + esp_rom_delay_us(10*1000); + if (p_args->cur_interval == NUM_INTERVALS) { + printf("done\n"); + TEST_ESP_OK(esp_timer_stop(p_args->timer)); + xSemaphoreGive(p_args->done); } +} +TEST_CASE("periodic esp_timer produces correct delays", "[esp_timer]") +{ const int delay_ms = 100; - test_args_t args = {0}; + test_periodic_correct_delays_args_t args = {0}; esp_timer_handle_t timer1; esp_timer_create_args_t create_args = { - .callback = &timer_func, + .callback = &test_periodic_correct_delays_timer_func, .arg = &args, .name = "timer1", }; @@ -254,58 +254,58 @@ TEST_CASE("periodic esp_timer produces correct delays", "[esp_timer]") TEST_ESP_OK( esp_timer_delete(timer1) ); vSemaphoreDelete(args.done); +} #undef NUM_INTERVALS + + +#define N 5 + +typedef struct { + const int order[N * 3]; + size_t count; +} test_timers_ordered_correctly_common_t; + +typedef struct { + int timer_index; + const int intervals[N]; + size_t intervals_count; + esp_timer_handle_t timer; + test_timers_ordered_correctly_common_t* common; + bool pass; + SemaphoreHandle_t done; + int64_t t_start; +} test_timers_ordered_correctly_args_t; + +static void test_timers_ordered_correctly_timer_func(void* arg) +{ + test_timers_ordered_correctly_args_t* p_args = (test_timers_ordered_correctly_args_t*) arg; + // check order + size_t count = p_args->common->count; + int expected_index = p_args->common->order[count]; + int ms_since_start = (ref_clock_get() - p_args->t_start) / 1000; + printf("Time %dms, at count %d, expected timer %d, got timer %d\n", + ms_since_start, count, expected_index, p_args->timer_index); + if (expected_index != p_args->timer_index) { + p_args->pass = false; + esp_timer_stop(p_args->timer); + xSemaphoreGive(p_args->done); + return; + } + p_args->common->count++; + if (++p_args->intervals_count == N) { + esp_timer_stop(p_args->timer); + xSemaphoreGive(p_args->done); + return; + } + int next_interval = p_args->intervals[p_args->intervals_count]; + printf("starting timer %d interval #%d, %d ms\n", + p_args->timer_index, p_args->intervals_count, next_interval); + esp_timer_start_once(p_args->timer, next_interval * 1000); } TEST_CASE("multiple timers are ordered correctly", "[esp_timer]") { -#define N 5 - - typedef struct { - const int order[N * 3]; - size_t count; - } test_common_t; - - typedef struct { - int timer_index; - const int intervals[N]; - size_t intervals_count; - esp_timer_handle_t timer; - test_common_t* common; - bool pass; - SemaphoreHandle_t done; - int64_t t_start; - } test_args_t; - - void timer_func(void* arg) - { - test_args_t* p_args = (test_args_t*) arg; - // check order - size_t count = p_args->common->count; - int expected_index = p_args->common->order[count]; - int ms_since_start = (ref_clock_get() - p_args->t_start) / 1000; - printf("Time %dms, at count %d, expected timer %d, got timer %d\n", - ms_since_start, count, expected_index, p_args->timer_index); - if (expected_index != p_args->timer_index) { - p_args->pass = false; - esp_timer_stop(p_args->timer); - xSemaphoreGive(p_args->done); - return; - } - p_args->common->count++; - if (++p_args->intervals_count == N) { - esp_timer_stop(p_args->timer); - xSemaphoreGive(p_args->done); - return; - } - int next_interval = p_args->intervals[p_args->intervals_count]; - printf("starting timer %d interval #%d, %d ms\n", - p_args->timer_index, p_args->intervals_count, next_interval); - esp_timer_start_once(p_args->timer, next_interval * 1000); - } - - - test_common_t common = { + test_timers_ordered_correctly_common_t common = { .order = {1, 2, 3, 2, 1, 3, 1, 2, 1, 3, 2, 1, 3, 3, 2}, .count = 0 }; @@ -315,7 +315,7 @@ TEST_CASE("multiple timers are ordered correctly", "[esp_timer]") ref_clock_init(); int64_t now = ref_clock_get(); - test_args_t args1 = { + test_timers_ordered_correctly_args_t args1 = { .timer_index = 1, .intervals = {10, 40, 20, 40, 30}, .common = &common, @@ -324,7 +324,7 @@ TEST_CASE("multiple timers are ordered correctly", "[esp_timer]") .t_start = now }; - test_args_t args2 = { + test_timers_ordered_correctly_args_t args2 = { .timer_index = 2, .intervals = {20, 20, 60, 30, 40}, .common = &common, @@ -333,7 +333,7 @@ TEST_CASE("multiple timers are ordered correctly", "[esp_timer]") .t_start = now }; - test_args_t args3 = { + test_timers_ordered_correctly_args_t args3 = { .timer_index = 3, .intervals = {30, 30, 60, 30, 10}, .common = &common, @@ -344,7 +344,7 @@ TEST_CASE("multiple timers are ordered correctly", "[esp_timer]") esp_timer_create_args_t create_args = { - .callback = &timer_func, + .callback = &test_timers_ordered_correctly_timer_func, .arg = &args1, .name = "1" }; @@ -378,8 +378,14 @@ TEST_CASE("multiple timers are ordered correctly", "[esp_timer]") TEST_ESP_OK( esp_timer_delete(args1.timer) ); TEST_ESP_OK( esp_timer_delete(args2.timer) ); TEST_ESP_OK( esp_timer_delete(args3.timer) ); - +} #undef N + + +static void test_short_intervals_timer_func(void* arg) { + SemaphoreHandle_t done = (SemaphoreHandle_t) arg; + xSemaphoreGive(done); + printf("."); } /* Create two timers, start them around the same time, and search through @@ -390,14 +396,8 @@ TEST_CASE("esp_timer for very short intervals", "[esp_timer]") { SemaphoreHandle_t semaphore = xSemaphoreCreateCounting(2, 0); - void timer_func(void* arg) { - SemaphoreHandle_t done = (SemaphoreHandle_t) arg; - xSemaphoreGive(done); - printf("."); - } - esp_timer_create_args_t timer_args = { - .callback = &timer_func, + .callback = &test_short_intervals_timer_func, .arg = (void*) semaphore, .name = "foo" }; @@ -444,68 +444,68 @@ static int64_t IRAM_ATTR __attribute__((noinline)) get_clock_diff(void) return hs_time - ref_time; } +typedef struct { + SemaphoreHandle_t done; + bool pass; + int test_cnt; + int error_cnt; + int64_t max_error; + int64_t avg_diff; + int64_t dummy; +} test_monotonic_values_state_t; + +static void timer_test_monotonic_values_task(void* arg) { + test_monotonic_values_state_t* state = (test_monotonic_values_state_t*) arg; + state->pass = true; + + /* make sure both functions are in cache */ + state->dummy = get_clock_diff(); + + /* calculate the difference between the two clocks */ + portDISABLE_INTERRUPTS(); + int64_t delta = get_clock_diff(); + portENABLE_INTERRUPTS(); + int64_t start_time = ref_clock_get(); + int error_repeat_cnt = 0; + while (ref_clock_get() - start_time < 10000000) { /* 10 seconds */ + /* Get values of both clocks again, and check that they are close to 'delta'. + * We don't disable interrupts here, because esp_timer_get_time doesn't lock + * interrupts internally, so we check if it can get "broken" by a well placed + * interrupt. + */ + int64_t diff = get_clock_diff() - delta; + /* Allow some difference due to rtos tick interrupting task between + * getting 'hs_now' and 'now'. + */ + if (abs(diff) > 100) { + error_repeat_cnt++; + state->error_cnt++; + } else { + error_repeat_cnt = 0; + } + if (error_repeat_cnt > 2) { + printf("diff=%lld\n", diff); + state->pass = false; + } + state->avg_diff += diff; + state->max_error = MAX(state->max_error, abs(diff)); + state->test_cnt++; + } + state->avg_diff /= state->test_cnt; + xSemaphoreGive(state->done); + vTaskDelete(NULL); + } + TEST_CASE("esp_timer_get_time returns monotonic values", "[esp_timer]") { - typedef struct { - SemaphoreHandle_t done; - bool pass; - int test_cnt; - int error_cnt; - int64_t max_error; - int64_t avg_diff; - int64_t dummy; - } test_state_t; - - void timer_test_task(void* arg) { - test_state_t* state = (test_state_t*) arg; - state->pass = true; - - /* make sure both functions are in cache */ - state->dummy = get_clock_diff(); - - /* calculate the difference between the two clocks */ - portDISABLE_INTERRUPTS(); - int64_t delta = get_clock_diff(); - portENABLE_INTERRUPTS(); - int64_t start_time = ref_clock_get(); - int error_repeat_cnt = 0; - while (ref_clock_get() - start_time < 10000000) { /* 10 seconds */ - /* Get values of both clocks again, and check that they are close to 'delta'. - * We don't disable interrupts here, because esp_timer_get_time doesn't lock - * interrupts internally, so we check if it can get "broken" by a well placed - * interrupt. - */ - int64_t diff = get_clock_diff() - delta; - /* Allow some difference due to rtos tick interrupting task between - * getting 'hs_now' and 'now'. - */ - if (abs(diff) > 100) { - error_repeat_cnt++; - state->error_cnt++; - } else { - error_repeat_cnt = 0; - } - if (error_repeat_cnt > 2) { - printf("diff=%lld\n", diff); - state->pass = false; - } - state->avg_diff += diff; - state->max_error = MAX(state->max_error, abs(diff)); - state->test_cnt++; - } - state->avg_diff /= state->test_cnt; - xSemaphoreGive(state->done); - vTaskDelete(NULL); - } - ref_clock_init(); setup_overflow(); - test_state_t states[portNUM_PROCESSORS] = {0}; + test_monotonic_values_state_t states[portNUM_PROCESSORS] = {0}; SemaphoreHandle_t done = xSemaphoreCreateCounting(portNUM_PROCESSORS, 0); for (int i = 0; i < portNUM_PROCESSORS; ++i) { states[i].done = done; - xTaskCreatePinnedToCore(&timer_test_task, "test", 4096, &states[i], 6, NULL, i); + xTaskCreatePinnedToCore(&timer_test_monotonic_values_task, "test", 4096, &states[i], 6, NULL, i); } for (int i = 0; i < portNUM_PROCESSORS; ++i) { @@ -530,27 +530,27 @@ TEST_CASE("Can dump esp_timer stats", "[esp_timer]") esp_timer_dump(stdout); } +typedef struct { + SemaphoreHandle_t notify_from_timer_cb; + esp_timer_handle_t timer; +} test_delete_from_callback_arg_t; + +static void test_delete_from_callback_timer_func(void* varg) +{ + test_delete_from_callback_arg_t arg = *(test_delete_from_callback_arg_t*) varg; + esp_timer_delete(arg.timer); + printf("Timer %p is deleted\n", arg.timer); + xSemaphoreGive(arg.notify_from_timer_cb); +} + TEST_CASE("Can delete timer from callback", "[esp_timer]") { - typedef struct { - SemaphoreHandle_t notify_from_timer_cb; - esp_timer_handle_t timer; - } test_arg_t; - - void timer_func(void* varg) - { - test_arg_t arg = *(test_arg_t*) varg; - esp_timer_delete(arg.timer); - printf("Timer %p is deleted\n", arg.timer); - xSemaphoreGive(arg.notify_from_timer_cb); - } - - test_arg_t args = { + test_delete_from_callback_arg_t args = { .notify_from_timer_cb = xSemaphoreCreateBinary(), }; esp_timer_create_args_t timer_args = { - .callback = &timer_func, + .callback = &test_delete_from_callback_timer_func, .arg = &args, .name = "self_deleter" }; @@ -630,24 +630,23 @@ TEST_CASE("esp_timer_impl_advance moves time base correctly", "[esp_timer]") TEST_ASSERT_INT_WITHIN(1000, diff_us, (int) t_delta); } +typedef struct { + int64_t cb_time; +} test_run_when_expected_state_t; + +static void test_run_when_expected_timer_func(void* varg) { + test_run_when_expected_state_t* arg = (test_run_when_expected_state_t*) varg; + arg->cb_time = ref_clock_get(); +} TEST_CASE("after esp_timer_impl_advance, timers run when expected", "[esp_timer]") { - typedef struct { - int64_t cb_time; - } test_state_t; - - void timer_func(void* varg) { - test_state_t* arg = (test_state_t*) varg; - arg->cb_time = ref_clock_get(); - } - ref_clock_init(); - test_state_t state = { 0 }; + test_run_when_expected_state_t state = { 0 }; esp_timer_create_args_t timer_args = { - .callback = &timer_func, + .callback = &test_run_when_expected_timer_func, .arg = &state }; esp_timer_handle_t timer; @@ -695,15 +694,15 @@ static void IRAM_ATTR test_tick_hook(void) } } +static void test_start_stop_timer_func(void* arg) +{ + printf("timer cb\n"); +} + TEST_CASE("Can start/stop timer from ISR context", "[esp_timer]") { - void timer_func(void* arg) - { - printf("timer cb\n"); - } - esp_timer_create_args_t create_args = { - .callback = &timer_func, + .callback = &test_start_stop_timer_func, }; TEST_ESP_OK(esp_timer_create(&create_args, &timer1)); sem = xSemaphoreCreateBinary(); diff --git a/components/esp_timer/test/test_ets_timer.c b/components/esp_timer/test/test_ets_timer.c index e32077024b..ac266dcca6 100644 --- a/components/esp_timer/test/test_ets_timer.c +++ b/components/esp_timer/test/test_ets_timer.c @@ -20,14 +20,14 @@ #include "esp32h2/rom/ets_sys.h" #endif +static void test_correct_delay_timer_func(void* arg) +{ + struct timeval* ptv = (struct timeval*) arg; + gettimeofday(ptv, NULL); +} + TEST_CASE("ets_timer produces correct delay", "[ets_timer]") { - void timer_func(void* arg) - { - struct timeval* ptv = (struct timeval*) arg; - gettimeofday(ptv, NULL); - } - ETSTimer timer1 = {0}; const int delays_ms[] = {20, 100, 200, 250}; @@ -36,7 +36,7 @@ TEST_CASE("ets_timer produces correct delay", "[ets_timer]") for (size_t i = 0; i < delays_count; ++i) { struct timeval tv_end = {0}; - ets_timer_setfn(&timer1, &timer_func, &tv_end); + ets_timer_setfn(&timer1, &test_correct_delay_timer_func, &tv_end); struct timeval tv_start; gettimeofday(&tv_start, NULL); @@ -54,42 +54,43 @@ TEST_CASE("ets_timer produces correct delay", "[ets_timer]") ets_timer_done(&timer1); } -TEST_CASE("periodic ets_timer produces correct delays", "[ets_timer]") -{ - // no, we can't make this a const size_t (§6.7.5.2) +// no, we can't make this a const size_t (§6.7.5.2) #define NUM_INTERVALS 16 - typedef struct { - ETSTimer *timer; - size_t cur_interval; - int intervals[NUM_INTERVALS]; - struct timeval tv_start; - } test_args_t; +typedef struct { + ETSTimer *timer; + size_t cur_interval; + int intervals[NUM_INTERVALS]; + struct timeval tv_start; +} test_periodic_correct_delays_args_t; - void timer_func(void *arg) { - test_args_t *p_args = (test_args_t *) arg; - struct timeval tv_now; - gettimeofday(&tv_now, NULL); - int32_t ms_diff = (tv_now.tv_sec - p_args->tv_start.tv_sec) * 1000 + - (tv_now.tv_usec - p_args->tv_start.tv_usec) / 1000; - printf("timer #%d %dms\n", p_args->cur_interval, ms_diff); - p_args->intervals[p_args->cur_interval++] = ms_diff; - // Deliberately make timer handler run longer. - // We check that this doesn't affect the result. - esp_rom_delay_us(10 * 1000); - if (p_args->cur_interval == NUM_INTERVALS) { - printf("done\n"); - ets_timer_disarm(p_args->timer); - } +static void test_periodic_correct_delays_timer_func(void* arg) +{ + test_periodic_correct_delays_args_t *p_args = (test_periodic_correct_delays_args_t *) arg; + struct timeval tv_now; + gettimeofday(&tv_now, NULL); + int32_t ms_diff = (tv_now.tv_sec - p_args->tv_start.tv_sec) * 1000 + + (tv_now.tv_usec - p_args->tv_start.tv_usec) / 1000; + printf("timer #%d %dms\n", p_args->cur_interval, ms_diff); + p_args->intervals[p_args->cur_interval++] = ms_diff; + // Deliberately make timer handler run longer. + // We check that this doesn't affect the result. + esp_rom_delay_us(10 * 1000); + if (p_args->cur_interval == NUM_INTERVALS) { + printf("done\n"); + ets_timer_disarm(p_args->timer); } +} +TEST_CASE("periodic ets_timer produces correct delays", "[ets_timer]") +{ const int delay_ms = 100; ETSTimer timer1 = {0}; - test_args_t args = {0}; + test_periodic_correct_delays_args_t args = {0}; args.timer = &timer1; gettimeofday(&args.tv_start, NULL); - ets_timer_setfn(&timer1, &timer_func, &args); + ets_timer_setfn(&timer1, &test_periodic_correct_delays_timer_func, &args); ets_timer_arm(&timer1, delay_ms, true); vTaskDelay(delay_ms * (NUM_INTERVALS + 1)); @@ -98,67 +99,66 @@ TEST_CASE("periodic ets_timer produces correct delays", "[ets_timer]") TEST_ASSERT_INT32_WITHIN(portTICK_PERIOD_MS, (i + 1) * delay_ms, args.intervals[i]); } ets_timer_done(&timer1); - +} #undef NUM_INTERVALS + +#define N 5 + +typedef struct { + const int order[N * 3]; + size_t count; +} test_timers_ordered_correctly_common_t; + +typedef struct { + int timer_index; + const int intervals[N]; + size_t intervals_count; + ETSTimer* timer; + test_timers_ordered_correctly_common_t* common; + bool pass; + SemaphoreHandle_t done; +} test_timers_ordered_correctly_args_t; + +static void test_timers_ordered_correctly_timer_func(void* arg) +{ + test_timers_ordered_correctly_args_t* p_args = (test_timers_ordered_correctly_args_t*) arg; + // check order + size_t count = p_args->common->count; + int expected_index = p_args->common->order[count]; + printf("At count %d, expected timer %d, got timer %d\n", + count, expected_index, p_args->timer_index); + if (expected_index != p_args->timer_index) { + p_args->pass = false; + ets_timer_disarm(p_args->timer); + xSemaphoreGive(p_args->done); + return; + } + p_args->common->count++; + if (++p_args->intervals_count == N) { + ets_timer_disarm(p_args->timer); + xSemaphoreGive(p_args->done); + return; + } + int next_interval = p_args->intervals[p_args->intervals_count]; + printf("timer %d interval #%d, %d ms\n", + p_args->timer_index, p_args->intervals_count, next_interval); + ets_timer_arm(p_args->timer, next_interval, false); } TEST_CASE("multiple ETSTimers are ordered correctly", "[ets_timer]") { -#define N 5 - - typedef struct { - const int order[N * 3]; - size_t count; - } test_common_t; - - typedef struct { - int timer_index; - const int intervals[N]; - size_t intervals_count; - ETSTimer* timer; - test_common_t* common; - bool pass; - SemaphoreHandle_t done; - } test_args_t; - - void timer_func(void* arg) - { - test_args_t* p_args = (test_args_t*) arg; - // check order - size_t count = p_args->common->count; - int expected_index = p_args->common->order[count]; - printf("At count %d, expected timer %d, got timer %d\n", - count, expected_index, p_args->timer_index); - if (expected_index != p_args->timer_index) { - p_args->pass = false; - ets_timer_disarm(p_args->timer); - xSemaphoreGive(p_args->done); - return; - } - p_args->common->count++; - if (++p_args->intervals_count == N) { - ets_timer_disarm(p_args->timer); - xSemaphoreGive(p_args->done); - return; - } - int next_interval = p_args->intervals[p_args->intervals_count]; - printf("timer %d interval #%d, %d ms\n", - p_args->timer_index, p_args->intervals_count, next_interval); - ets_timer_arm(p_args->timer, next_interval, false); - } - ETSTimer timer1; ETSTimer timer2; ETSTimer timer3; - test_common_t common = { + test_timers_ordered_correctly_common_t common = { .order = {1, 2, 3, 2, 1, 3, 1, 2, 1, 3, 2, 1, 3, 3, 2}, .count = 0 }; SemaphoreHandle_t done = xSemaphoreCreateCounting(3, 0); - test_args_t args1 = { + test_timers_ordered_correctly_args_t args1 = { .timer_index = 1, .intervals = {10, 40, 20, 40, 30}, .timer = &timer1, @@ -167,7 +167,7 @@ TEST_CASE("multiple ETSTimers are ordered correctly", "[ets_timer]") .done = done }; - test_args_t args2 = { + test_timers_ordered_correctly_args_t args2 = { .timer_index = 2, .intervals = {20, 20, 60, 30, 40}, .timer = &timer2, @@ -176,7 +176,7 @@ TEST_CASE("multiple ETSTimers are ordered correctly", "[ets_timer]") .done = done }; - test_args_t args3 = { + test_timers_ordered_correctly_args_t args3 = { .timer_index = 3, .intervals = {30, 30, 60, 30, 10}, .timer = &timer3, @@ -185,9 +185,9 @@ TEST_CASE("multiple ETSTimers are ordered correctly", "[ets_timer]") .done = done }; - ets_timer_setfn(&timer1, &timer_func, &args1); - ets_timer_setfn(&timer2, &timer_func, &args2); - ets_timer_setfn(&timer3, &timer_func, &args3); + ets_timer_setfn(&timer1, &test_timers_ordered_correctly_timer_func, &args1); + ets_timer_setfn(&timer2, &test_timers_ordered_correctly_timer_func, &args2); + ets_timer_setfn(&timer3, &test_timers_ordered_correctly_timer_func, &args3); ets_timer_arm(&timer1, args1.intervals[0], false); ets_timer_arm(&timer2, args2.intervals[0], false); @@ -204,25 +204,24 @@ TEST_CASE("multiple ETSTimers are ordered correctly", "[ets_timer]") ets_timer_done(&timer1); ets_timer_done(&timer2); ets_timer_done(&timer3); - +} #undef N + +static void IRAM_ATTR test_iram_timer_func(void* arg) +{ + volatile bool *b = (volatile bool *)arg; + *b = true; } /* WiFi/BT coexistence will sometimes arm/disarm timers from an ISR where flash may be disabled. */ IRAM_ATTR TEST_CASE("ETSTimers arm & disarm run from IRAM", "[ets_timer]") { - void timer_func(void* arg) - { - volatile bool *b = (volatile bool *)arg; - *b = true; - } - volatile bool flag = false; ETSTimer timer1; const int INTERVAL = 5; - ets_timer_setfn(&timer1, &timer_func, (void *)&flag); + ets_timer_setfn(&timer1, &test_iram_timer_func, (void *)&flag); /* arm a disabled timer, then disarm a live timer */ diff --git a/components/esp_wifi/include/esp_wifi_default.h b/components/esp_wifi/include/esp_wifi_default.h index 958977bf25..908ea2c113 100644 --- a/components/esp_wifi/include/esp_wifi_default.h +++ b/components/esp_wifi/include/esp_wifi_default.h @@ -50,7 +50,7 @@ esp_err_t esp_netif_attach_wifi_ap(esp_netif_t *esp_netif); esp_err_t esp_wifi_set_default_wifi_sta_handlers(void); /** - * @brief Sets default wifi event handlers for STA interface + * @brief Sets default wifi event handlers for AP interface * * @return * - ESP_OK on success, error returned from esp_event_handler_register if failed diff --git a/components/esp_wifi/lib b/components/esp_wifi/lib index 0a82aeac1f..4e1c7a8114 160000 --- a/components/esp_wifi/lib +++ b/components/esp_wifi/lib @@ -1 +1 @@ -Subproject commit 0a82aeac1f8ca7837ce642b8778f652c072e1904 +Subproject commit 4e1c7a8114fd03b9841f78a218f579799cb61a0a diff --git a/components/espcoredump/Kconfig b/components/espcoredump/Kconfig index 28a54a02a6..a9d7843e50 100644 --- a/components/espcoredump/Kconfig +++ b/components/espcoredump/Kconfig @@ -15,9 +15,11 @@ menu "Core dump" config ESP_COREDUMP_ENABLE_TO_FLASH bool "Flash" depends on !SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY + select FREERTOS_ENABLE_TASK_SNAPSHOT select ESP_COREDUMP_ENABLE config ESP_COREDUMP_ENABLE_TO_UART bool "UART" + select FREERTOS_ENABLE_TASK_SNAPSHOT select ESP_COREDUMP_ENABLE config ESP_COREDUMP_ENABLE_TO_NONE bool "None" diff --git a/components/espcoredump/corefile/__init__.py b/components/espcoredump/corefile/__init__.py index ae523c796c..710cf81688 100644 --- a/components/espcoredump/corefile/__init__.py +++ b/components/espcoredump/corefile/__init__.py @@ -29,7 +29,7 @@ except ImportError: pass IDF_PATH = os.path.normpath(os.getenv('IDF_PATH', '.')) -XTENSA_TARGETS = ['esp32', 'esp32s2'] +XTENSA_TARGETS = ['esp32', 'esp32s2', 'esp32s3'] RISCV_TARGETS = ['esp32c3'] SUPPORTED_TARGETS = XTENSA_TARGETS + RISCV_TARGETS diff --git a/components/espcoredump/corefile/loader.py b/components/espcoredump/corefile/loader.py index 2cd3e47408..144a350826 100644 --- a/components/espcoredump/corefile/loader.py +++ b/components/espcoredump/corefile/loader.py @@ -29,7 +29,7 @@ from . import ESPCoreDumpLoaderError from .elf import (TASK_STATUS_CORRECT, TASK_STATUS_TCB_CORRUPTED, ElfFile, ElfSegment, ESPCoreDumpElfFile, EspTaskStatus, NoteSection) from .riscv import Esp32c3Methods -from .xtensa import Esp32Methods, Esp32S2Methods +from .xtensa import Esp32Methods, Esp32S2Methods, Esp32S3Methods try: from typing import Optional, Tuple @@ -75,12 +75,13 @@ MemSegmentHeader = Struct( class EspCoreDumpVersion(object): - """Core dump version class + """Core dump version class, it contains all version-dependent params """ - # This class contains all version-dependent params + # Chip IDs should be in sync with components/esp_hw_support/include/esp_chip_info.h ESP32 = 0 ESP32S2 = 2 - XTENSA_CHIPS = [ESP32, ESP32S2] + ESP32S3 = 9 + XTENSA_CHIPS = [ESP32, ESP32S2, ESP32S3] ESP32C3 = 5 RISCV_CHIPS = [ESP32C3] @@ -195,6 +196,8 @@ class EspCoreDumpLoader(EspCoreDumpVersion): self.target_methods = Esp32S2Methods() # type: ignore elif self.chip_ver == self.ESP32C3: self.target_methods = Esp32c3Methods() # type: ignore + elif self.chip_ver == self.ESP32S3: + self.target_methods = Esp32S3Methods() # type: ignore else: raise NotImplementedError else: diff --git a/components/espcoredump/corefile/soc_headers/esp32s3.py b/components/espcoredump/corefile/soc_headers/esp32s3.py new file mode 100644 index 0000000000..d0d5679cda --- /dev/null +++ b/components/espcoredump/corefile/soc_headers/esp32s3.py @@ -0,0 +1,8 @@ +SOC_DRAM_LOW = 0x3FC88000 +SOC_DRAM_HIGH = 0x3FD00000 +SOC_IRAM_LOW = 0x40370000 +SOC_IRAM_HIGH = 0x403E0000 +SOC_RTC_DRAM_LOW = 0x600FE000 +SOC_RTC_DRAM_HIGH = 0x60100000 +SOC_RTC_DATA_LOW = 0x50000000 +SOC_RTC_DATA_HIGH = 0x50002000 diff --git a/components/espcoredump/corefile/xtensa.py b/components/espcoredump/corefile/xtensa.py index 1c038e3819..d2fa810f91 100644 --- a/components/espcoredump/corefile/xtensa.py +++ b/components/espcoredump/corefile/xtensa.py @@ -275,3 +275,7 @@ class Esp32Methods(BaseTargetMethods, XtensaMethodsMixin): class Esp32S2Methods(BaseTargetMethods, XtensaMethodsMixin): TARGET = 'esp32s2' + + +class Esp32S3Methods(BaseTargetMethods, XtensaMethodsMixin): + TARGET = 'esp32s3' diff --git a/components/espcoredump/src/core_dump_common.c b/components/espcoredump/src/core_dump_common.c index b5cf5bdd34..ca995a6260 100644 --- a/components/espcoredump/src/core_dump_common.c +++ b/components/espcoredump/src/core_dump_common.c @@ -16,7 +16,7 @@ #include "sdkconfig.h" #include "soc/soc_memory_layout.h" #include "freertos/FreeRTOS.h" -#include "freertos/task.h" +#include "freertos/task_snapshot.h" #include "esp_rom_sys.h" #include "esp_core_dump_port.h" #include "esp_core_dump_common.h" diff --git a/components/espcoredump/src/port/riscv/core_dump_port.c b/components/espcoredump/src/port/riscv/core_dump_port.c index 3336cbbc37..3b2a4f63ea 100644 --- a/components/espcoredump/src/port/riscv/core_dump_port.c +++ b/components/espcoredump/src/port/riscv/core_dump_port.c @@ -34,8 +34,8 @@ const static DRAM_ATTR char TAG[] __attribute__((unused)) = "esp_core_dump_port" #define COREDUMP_EM_RISCV 0xF3 #define COREDUMP_INVALID_CAUSE_VALUE 0xFFFF -#define COREDUMP_FAKE_STACK_START 0x20000000 -#define COREDUMP_FAKE_STACK_LIMIT 0x30000000 +#define COREDUMP_FAKE_STACK_START 0x20000000U +#define COREDUMP_FAKE_STACK_LIMIT 0x30000000U #if CONFIG_ESP_COREDUMP_ENABLE @@ -424,7 +424,7 @@ void esp_core_dump_summary_parse_backtrace_info(esp_core_dump_bt_info_t *bt_info /* Check whether the stack is a fake stack created during coredump generation * If its a fake stack, we don't have any actual stack dump */ - if (vaddr >= COREDUMP_FAKE_STACK_START && vaddr < COREDUMP_FAKE_STACK_LIMIT) { + if (vaddr >= (void*) COREDUMP_FAKE_STACK_START && vaddr < (void*) COREDUMP_FAKE_STACK_LIMIT) { bt_info->dump_size = 0; return; } diff --git a/components/espcoredump/src/port/xtensa/core_dump_port.c b/components/espcoredump/src/port/xtensa/core_dump_port.c index 8fdaacb73a..a96117a99f 100644 --- a/components/espcoredump/src/port/xtensa/core_dump_port.c +++ b/components/espcoredump/src/port/xtensa/core_dump_port.c @@ -1,16 +1,8 @@ -// Copyright 2015-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: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ /** * @file @@ -228,7 +220,7 @@ static esp_err_t esp_core_dump_get_regs_from_stack(void* stack_addr, regs->ar[i] = stack_arr[XT_STK_AR_START + i]; } regs->sar = exc_frame->sar; -#if CONFIG_IDF_TARGET_ESP32 +#if XCHAL_HAVE_LOOPS regs->lbeg = exc_frame->lbeg; regs->lend = exc_frame->lend; regs->lcount = exc_frame->lcount; @@ -531,7 +523,8 @@ void esp_core_dump_summary_parse_backtrace_info(esp_core_dump_bt_info_t *bt_info frame.next_pc = stack->a0; corrupted = !(esp_stack_ptr_is_sane(frame.sp) && - esp_ptr_executable((void *)esp_cpu_process_stack_pc(frame.pc))); + (esp_ptr_executable((void *)esp_cpu_process_stack_pc(frame.pc)) || + stack->exccause == EXCCAUSE_INSTR_PROHIBITED)); /* Ignore the first corrupted PC in case of InstrFetchProhibited */ /* vaddr is actual stack address when crash occurred. However that stack is now saved * in the flash at a different location. Hence for each SP, we need to adjust the offset diff --git a/components/espcoredump/test/esp32/coredump.b64 b/components/espcoredump/test/esp32/coredump.b64 index 94be30a4e2..56a38c6a4a 100644 --- a/components/espcoredump/test/esp32/coredump.b64 +++ b/components/espcoredump/test/esp32/coredump.b64 @@ -1,34 +1,34 @@ -QC8AAAABAAAAAAAAAAAAAAAAAAA= +XC8AAAABAAAAAAAAAAAAAAAAAAA= f0VMRgEBAQAAAAAAAAAAAAQAXgABAAAAAAAAADQAAAAAAAAAAAAAADQAIAASACgA AAAAAA== BAAAAHQCAAAAAAAAAAAAAAATAAAAEwAABgAAAAAAAAA= -AQAAAHQVAABMjvs/TI77P1gBAABYAQAABgAAAAAAAAA= -AQAAAMwWAABQjPs/UIz7P/QBAAD0AQAABgAAAAAAAAA= -AQAAAMAYAADMcPs/zHD7P1gBAABYAQAABgAAAAAAAAA= -AQAAABgaAAAgb/s/IG/7P6QBAACkAQAABgAAAAAAAAA= -AQAAALwbAAAsePs/LHj7P1gBAABYAQAABgAAAAAAAAA= -AQAAABQdAACAdvs/gHb7P6QBAACkAQAABgAAAAAAAAA= -AQAAALgeAACsl/s/rJf7P1gBAABYAQAABgAAAAAAAAA= -AQAAABAgAAAAlvs/AJb7P6QBAACkAQAABgAAAAAAAAA= -AQAAALQhAADshPs/7IT7P1gBAABYAQAABgAAAAAAAAA= -AQAAAAwjAABAg/s/QIP7P6QBAACkAQAABgAAAAAAAAA= -AQAAALAkAABo+Po/aPj6P1gBAABYAQAABgAAAAAAAAA= -AQAAAAgmAACA9vo/gPb6P+ABAADgAQAABgAAAAAAAAA= -AQAAAOgnAACsU/s/rFP7P1gBAABYAQAABgAAAAAAAAA= -AQAAAEApAADwUfs/8FH7P7QBAAC0AQAABgAAAAAAAAA= -AQAAAPQqAABMQvs/TEL7P1gBAABYAQAABgAAAAAAAAA= -AQAAAEwsAAAA/fo/AP36P8gBAADIAQAABgAAAAAAAAA= -BAAAABQuAAAAAAAAAAAAABQBAAAUAQAABgAAAAAAAAA= +AQAAAHQVAAC0jvs/tI77P1gBAABYAQAABgAAAAAAAAA= +AQAAAMwWAACwjPs/sIz7P/wBAAD8AQAABgAAAAAAAAA= +AQAAAMgYAACUdPs/lHT7P1gBAABYAQAABgAAAAAAAAA= +AQAAACAaAADgcvs/4HL7P6wBAACsAQAABgAAAAAAAAA= +AQAAAMwbAAD0e/s/9Hv7P1gBAABYAQAABgAAAAAAAAA= +AQAAACQdAABAevs/QHr7P6wBAACsAQAABgAAAAAAAAA= +AQAAANAeAAAUmPs/FJj7P1gBAABYAQAABgAAAAAAAAA= +AQAAACggAABglvs/YJb7P6wBAACsAQAABgAAAAAAAAA= +AQAAANQhAABUhfs/VIX7P1gBAABYAQAABgAAAAAAAAA= +AQAAACwjAACgg/s/oIP7P6wBAACsAQAABgAAAAAAAAA= +AQAAANgkAAAk/fo/JP36P1gBAABYAQAABgAAAAAAAAA= +AQAAADAmAACgRPs/oET7P8gBAADIAQAABgAAAAAAAAA= +AQAAAPgnAADUW/s/1Fv7P1gBAABYAQAABgAAAAAAAAA= +AQAAAFApAAAQWvs/EFr7P7wBAAC8AQAABgAAAAAAAAA= +AQAAAAwrAAB0Svs/dEr7P1gBAABYAQAABgAAAAAAAAA= +AQAAAGQsAACgSPs/oEj7P8wBAADMAQAABgAAAAAAAAA= +BAAAADAuAAAAAAAAAAAAABQBAAAUAQAABgAAAAAAAAA= CAAAAEwCAAABAAAA Q09SRQAAAAA= -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATI77PwAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsVYNQCAABgD9FABADRUAQP////8aAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtI77PwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2UsNQCACBgD9FABADRUAQP////8aAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIxWDYAQjfs/ -AgAAAFyN+z9Qjfs/bO/6PwAAAAAAAAAABQAAAK3///8gAAAArI77PwEAAACAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALRLDYBwjfs/ +AgAAALyN+z+wjfs/bO/6PwAAAAAAAAAABQAAAK3///8gAAAAFI/7PwEAAACAAAAA AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA @@ -36,14 +36,14 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAA CAAAAEwCAAABAAAA Q09SRQAAAAA= -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzHD7PwAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGngOQCALBgAAAAAAAAAAAAAAAAAVAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlHT7PwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALnsOQCAFBgAAAAAAAAAAAAAAAAAeAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADoaDYDgb/s/ -AAAAAAEAAAABAAAAAQAAgAAAgAAcAPQ/WpoNgLBv+z8AAAAASB0AQCAHBgAjBwYA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEIaDYCgc/s/ +AAAAAAEAAAABAAAAAQAAgAAAgAAcAPQ/zpwNgHBz+z8AAAAASB0AQCABBgAjAQYA AQAAABwA9D8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA @@ -51,14 +51,14 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAA CAAAAEwCAAABAAAA Q09SRQAAAAA= -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALHj7PwAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGngOQCAKBgAAAAAAAAAAAAAAAAAYAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9Hv7PwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALnsOQCAKBgAAAAAAAAAAAAAAAAAeAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADoaDYBAd/s/ -AAAAAAAAAAABAAAAAQAAgAMAAAAjAAYAWpoNgBB3+z8AAAAAIwoGACAKBgAjCgYA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEIaDYAAe/s/ +AAAAAAAAAAABAAAAAQAAgAMAAAAjAAYAzpwNgNB6+z8AAAAAIwoGACAKBgAjCgYA AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA @@ -66,14 +66,14 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAA CAAAAEwCAAABAAAA Q09SRQAAAAA= -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArJf7PwAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhD4IQCAJBgD9FABADRUAQPj///8AAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFJj7PwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfEIIQCAFBgD9FABADRUAQPj///8AAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApgCIDAlvs/ -AAAAAMkAAACUNPs/QGj7PwAIAAAAAAAAhD4IgKCW+z/cAPA/AQAAANgX+z8jCQYA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIplCIAgl/s/ +AAAAAMkAAABsNPs/AGz7PwAIAAAAAAAAfEIIgACX+z/cAPA/AQAAAMwX+z8jBQYA AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA @@ -81,14 +81,14 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAA CAAAAEwCAAABAAAA Q09SRQAAAAA= -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7IT7PwAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhD4IQCALBgD9FABADRUAQPn///8AAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVIX7PwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfEIIQCAHBgD9FABADRUAQPn///8AAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApgCIAAhPs/ -AAAAAMkAAACUNPs/iDT7P0xC+z8AAAAAhD4IgOCD+z/cAPA/AQAAANgX+z8jCwYA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIplCIBghPs/ +AAAAAMkAAABsNPs/YDT7P3RK+z8AAAAAfEIIgECE+z/cAPA/AQAAAMwX+z8jBwYA AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA @@ -96,198 +96,198 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAA CAAAAEwCAAABAAAA Q09SRQAAAAA= -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaPj6PwAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIz4IQCAMBgAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJP36PwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfEIIQCAMBgAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIQ+CIBA9/o/ -3ADwPwEAAADYF/s/IwAGAAEAAAAEAAAACj4IgCD3+j+4Mfs/AAAAACMKBgAjCgYA -AQAAANACQD8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADVeCIBgRfs/ +AAAAAP////8Y/fo/EDv+PwMAAAAjDwYAfEIIgEBF+z/cAPA/AQAAAMwX+z8jAAYA +AQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAA CAAAAEwCAAABAAAA Q09SRQAAAAA= -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArFP7PwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1Fv7PwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8L8AQCAABgAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMJ3CICwUvs/ -AAAAACMABgAgAAYAIwAGAAEAAAAAAAAACj4IgIBS+z/AMfs/AQAAAMD3+j+A9/o/ -DPT6P1j0+j8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO5+CIDQWvs/ +AAAAACMABgAgAAYAIwAGAAEAAAAAAAAAVUIIgKBa+z+YMfs/AAAAAOBF+z/ARfs/ +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAA CAAAAEwCAAABAAAA Q09SRQAAAAA= -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATEL7PwAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhD4IQCAKBgAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdEr7PwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfEIIQCAKBgAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPVYCIDA/fo/ -AQAAAP/////A+vo/dGn7PwEAAAAcAPQ/hD4IgKD9+j/gAPA/AQAAANgX+z8jCgYA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADVeCIBgSfs/ +AQAAAP////98//o/PG37PwEAAAAcAPQ/fEIIgEBJ+z/gAPA/AQAAAMwX+z8jCgYA AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAA -oIz7P+CN+z9lAAAANDP7PzQz+z9Mjvs/LDP7PxIAAABSCwAsfipi8UyO+z8AAAAA -BwAAAEiG+z91bmFsaWduZWRfcHRyX3QAAQAAAESO+z8HAAAAAAAAAAAAAAAAAAAA +II37P0CO+z9lAAAADDP7Pwwz+z+0jvs/BDP7PxIAAADqRaoAIG065LSO+z8AAAAA +BwAAALCG+z91bmFsaWduZWRfcHRyX3QAAQAAAKyO+z8HAAAAAAAAAAAAAAAAAAAA AAAAAATv+j9s7/o/1O/6PwAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAEgdAEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAA+z8= -776t3rFWDUAwAAYAjFYNgBCN+z8CAAAAXI37P1CN+z9s7/o/AAAAAAAAAAAFAAAA -rf///yAAAACsjvs/AQAAAIAAAAABAAAAAAAAABoAAAAdAAAABQAAAP0UAEANFQBA -/////wEAAACAAAAAnCAIQERY+z8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAEAAACAAAAAAQAAAAAAAACMVg2AQI37PwEAAABs7/o/ -AwAAAAAAAAABAAAAAQAAAFCN+z9s7/o/AAAAAAAAAADUVg2AcI37PwoAAACIFvs/ -AwAAAB4AAAACMkA/AQAAAJQ0+z8jAAYAAQAAAAAAAAC8dQiAoI37PwAAAAAAAAAA -AwAAAKCN+z8AAAAAAAAAACEABgAjAAYAAQAAAAAAAAAAAAAAwI37P7xWDUAAAAAA -IwAGADQz+z9Mjvs/AAAAAAAAAADgjfs/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7I37PwAAAAAAAAAAAAAAAAAAAAAAAAAA +776t3tlLDUAwAgYAtEsNgHCN+z8CAAAAvI37P7CN+z9s7/o/AAAAAAAAAAAFAAAA +rf///yAAAAAUj/s/AQAAAIAAAAABAAAAAAAAABoAAAAdAAAABQAAAP0UAEANFQBA +/////wEAAACAAAAAkB8IQChY+z8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAEAAACAAAAAAQAAAAAAAAC0Sw2AoI37PwEAAABs7/o/ +AwAAAKWlpaUBAAAAAQAAALCN+z9s7/o/AAAAAAAAAAD8Sw2A0I37PwoAAAAYFvs/ +AwAAAB4AAABwI0A/AQAAAGw0+z/AhPs/aEsNQAAAAADcfAiAAI77PwAAAAAAAAAA +AwAAAACO+z8AAAAAAAAAACEABgAjAAYAAQAAAAAAAAAAAAAAII77P+RLDUAAAAAA +IwAGAAwz+z+0jvs/AAAAAAAAAABAjvs/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATI77PwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAA= -IG/7P2Bw+z825LZwNHj7P6gy+z/McPs/oDL7PxkAAAAxouASF+cBTsxw+z8AAAAA -AAAAAMhq+z9JRExFAOBDvnHT/sEOutQAAAAAAMRw+z8AAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +4HL7PyB0+z91NHWB/Hv7P4Ay+z+UdPs/eDL7PxkAAAAlop84JddN9pR0+z8AAAAA +AAAAAJBu+z9JRExFAIySOLz4HKxBkIoAAAAAAIx0+z8AAAAAAAAAAAAAAAAAAAAA AAAAAATv+j9s7/o/1O/6PwAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAEgdAEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAA+z8= -ACEIQBp4DkAwCwYAOhoNgOBv+z8AAAAAAQAAAAEAAAABAACAAACAABwA9D9amg2A -sG/7PwAAAABIHQBAIAcGACMHBgABAAAAHAD0PxUAAAD//wAAAAAAAAAAAAAAAAAA -AAAAAAQjCEAjBwYAYE0IQMQ6+z8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAC0XQhAAAAAAAAAAAC9XQiAAHD7PwgAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAALx1CIAgcPs/AAAAAAAAAAABAAAAIwAGAAEAAAAjBAYA -AAAAAEBw+z+0XQhAAAAAACMABgCoMvs/LHj7PwAAAAAAAAAAYHD7PwAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGxw+z8AAAAA +9B8IQC57DkAwBQYAQhoNgKBz+z8AAAAAAQAAAAEAAAABAACAAACAABwA9D/OnA2A +cHP7PwAAAABIHQBAIAEGACMBBgABAAAAHAD0Px4AAAD//wAAAAAAAAAAAAAAAAAA +AAAAAPghCEAjAQYAwFEIQAg++z8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAoYwhAAAAAAAAAAAAxYwiAwHP7PwgAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAANx8CIDgc/s/AAAAAAAAAAABAAAAIwAGAAEAAAAjDgYA +AAAAAAB0+z8oYwhAAAAAACMABgCAMvs/9Hv7PwAAAAAAAAAAIHT7PwAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACx0+z8AAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -gHb7P8B3+z/VLZInqDL7P9Rw+z8sePs/oDL7PxkAAADQDnUJWS5znCx4+z8AAAAA -AAAAAChy+z9JRExFAF71C3f47ueHKmsAAQAAACR4+z8AAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= +QHr7P4B7+z9o3+higDL7P5x0+z/0e/s/eDL7PxkAAABx1gshKjkyAvR7+z8AAAAA +AAAAAPB1+z9JRExFAGB4ZT8EuKN7Y/8AAQAAAOx7+z8AAAAAAAAAAAAAAAAAAAAA AAAAAATv+j9s7/o/1O/6PwAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAEgdAEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAA+z8= -ACEIQBp4DkAwCgYAOhoNgEB3+z8AAAAAAAAAAAEAAAABAACAAwAAACMABgBamg2A -EHf7PwAAAAAjCgYAIAoGACMKBgABAAAAAAAAABgAAAD//wAAAAAAAAAAAAAAAAAA -AAAAAAQjCEAjCgYAYE0IQCRC+z8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAC0XQhAAAAAAAAAAAC9XQiAYHf7PwgAAAABAAAA -AAAAAAAAAAAAAAAAAAAAALx1CICAd/s/AAAAAAAAAAABAAAAIwAGAAEAAAAAAAAA -AAAAAKB3+z+0XQhAAAAAACMABgCoMvs/zHD7PwAAAAAAAAAAwHf7PwAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMx3+z8AAAAA +9B8IQC57DkAwCgYAQhoNgAB7+z8AAAAAAAAAAAEAAAABAACAAwAAACMABgDOnA2A +0Hr7PwAAAAAjCgYAIAoGACMKBgABAAAAAAAAAB4AAAD//wAAAAAAAAAAAAAAAAAA +AAAAAPghCEAjCgYAwFEIQGhF+z8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAoYwhAAAAAAAAAAAAxYwiAIHv7PwgAAAABAAAA +AAAAAAAAAAAAAAAAAAAAANx8CIBAe/s/AAAAAAAAAAABAAAAIwAGAAEAAAAAAAAA +AAAAAGB7+z8oYwhAAAAAACMABgCAMvs/lHT7PwAAAAAAAAAAgHv7PwAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIx7+z8AAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AJb7P0CX+z/JAAAA9IT7P5Qy+z+sl/s/jDL7Pw8AAAAIhfs/LPH6P6yX+z8AAAAA -CgAAAKiP+z9mYWlsZWRfYXNzZXJ0X3QAAAAAAKSX+z8KAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= +YJb7P6CX+z/JAAAAXIX7P2wy+z8UmPs/ZDL7Pw8AAABwhfs/LPH6PxSY+z8AAAAA +CgAAABCQ+z9mYWlsZWRfYXNzZXJ0X3QAAAAAAAyY+z8KAAAAAAAAAAAAAAAAAAAA AAAAAATv+j9s7/o/1O/6PwAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAEgdAEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAA+z8= -ACEIQIQ+CEAwCQYACmAIgMCW+z8AAAAAyQAAAJQ0+z9AaPs/AAgAAAAAAACEPgiA -oJb7P9wA8D8BAAAA2Bf7PyMJBgABAAAAAAAAAAAAAAD//wAAAAAAAP0UAEANFQBA -+P///wQjCEAjCQYAYE0IQKRh+z8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAwWQD8eAAAAAjJAPwEAAACXVQ2A4Jb7P2QAAACIFvs/ -lDT7P0Bo+z8ACAAAAAAAALx1CIAAl/s/AAAAAAAAAAAhAAYAIwAGAAEAAAAAAAAA -AAAAACCX+z+IVQ1AAAAAACMABgBwM/s/rJf7PwAAAAAAAAAAQJf7PwAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEyX+z8AAAAA +9B8IQHxCCEAwBQYAimUIgCCX+z8AAAAAyQAAAGw0+z8AbPs/AAgAAAAAAAB8QgiA +AJf7P9wA8D8BAAAAzBf7PyMFBgABAAAAAAAAAAAAAAD//wAAAAAAAP0UAEANFQBA ++P////ghCEAjBQYAwFEIQIhh+z8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAIwUQD8eAAAAcCNAPwEAAAC3Sg2AQJf7P2QAAAAYFvs/ +bDT7PwBs+z8ACAAAAAAAANx8CIBgl/s/AAAAAAAAAAAhAAYAIwAGAAEAAAAAAAAA +AAAAAICX+z+oSg1AAAAAACMABgBIM/s/FJj7PwAAAAAAAAAAoJf7PwAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKyX+z8AAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -QIP7P4CE+z/JAAAAlDL7P7SX+z/shPs/jDL7PxQAAAAs8fo/LPH6P+yE+z8AAAAA -BQAAAOh8+z9iYWRfcHRyX3Rhc2sAsOEA////f+SE+z8FAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= +oIP7P+CE+z/JAAAAbDL7PxyY+z9Uhfs/ZDL7PxQAAAAs8fo/LPH6P1SF+z8AAAAA +BQAAAFB9+z9iYWRfcHRyX3Rhc2sArRIA////f0yF+z8FAAAAAAAAAAAAAAAAAAAA AAAAAATv+j9s7/o/1O/6PwAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAEgdAEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAA+z8= -ACEIQIQ+CEAwCwYACmAIgACE+z8AAAAAyQAAAJQ0+z+INPs/TEL7PwAAAACEPgiA -4IP7P9wA8D8BAAAA2Bf7PyMLBgABAAAAAAAAAAAAAAD//wAAAAAAAP0UAEANFQBA -+f///wQjCEAjCwYAYE0IQORO+z8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAKgWQD8YAAAAAjJAPwEAAABPVg2AIIT7P2QAAACIFvs/ -lDT7P4g0+z9MQvs/AAAAALx1CIBAhPs/AAAAAAAAAAAhAAYAIwAGAAEAAAAjCgYA -AAAAAGCE+z9AVg1AAAAAACMABgAMM/s/7IT7PwAAAAAAAAAAgIT7PwAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIyE+z8AAAAA +9B8IQHxCCEAwBwYAimUIgGCE+z8AAAAAyQAAAGw0+z9gNPs/dEr7PwAAAAB8QgiA +QIT7P9wA8D8BAAAAzBf7PyMHBgABAAAAAAAAAAAAAAD//wAAAAAAAP0UAEANFQBA ++f////ghCEAjBwYAwFEIQMhO+z8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAACgVQD8YAAAAcCNAPwEAAAB3Sw2AgIT7P2QAAAAYFvs/ +bDT7P2A0+z90Svs/AAAAANx8CICghPs/AAAAAAAAAAAhAAYAIwAGAAEAAAAjCgYA +AAAAAMCE+z9oSw1AAAAAACMABgDkMvs/VIX7PwAAAAAAAAAA4IT7PwAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOyE+z8AAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -gPb6PwD4+j/iqgEItFP7PyQy+z9o+Po/HDL7PwEAAAA49Po/OPT6P2j4+j8w9Po/ -GAAAAGT0+j9pcGMwACtsMbetm+FBj1oAAAAAAGD4+j8YAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= +oET7PwBG+z/KIQdR3Fv7P/wx+z8k/fo/9DH7PwEAAAD4/Po/+Pz6PyT9+j/w/Po/ +GAAAAGxC+z9pcGMwAGf+W42PJLqDIg4AAAAAAGhG+z8YAAAAAAAAAAAAAAAAAAAA AAAAAATv+j9s7/o/1O/6PwAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAEgdAEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAA+j8= -ACEIQCM+CEAwDAYAhD4IgED3+j/cAPA/AQAAANgX+z8jAAYAAQAAAAQAAAAKPgiA -IPf6P7gx+z8AAAAAIwoGACMKBgABAAAA0AJAPwAAAAD//wAAAAAAAAAAAAAAAAAA -AAAAAAQjCEAjCgYAYE0IQGTC+j8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAKWlpaWlpaWlpaWlpaWlpaX1WAiAYPf6PwAAAAD///// -ACEIQLR1CEAwAAUAAAAAACsrCICA9/o/DPT6P1j0+j9Y9Po/EDv+PwMAAAAjDwYA -vHUIgMD3+j8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////AAAAAAAAAAAAAAAA -AQAAAAEAAAAAAAAAIw8GAAAAAADg9/o/DCsIQAAAAAAjDwYAiDT7P2j4+j8BAAAA -AAAAAAD4+j8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADffw6AwDv+PxQy+z8AAAAA -AAAAAAAAAAAM+Po/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +9B8IQHxCCEAwDAYANV4IgGBF+z8AAAAA/////xj9+j8QO/4/AwAAACMPBgB8QgiA +QEX7P9wA8D8BAAAAzBf7PyMABgABAAAABAAAAAAAAAD//wAAAAAAAAAAAAAAAAAA +AAAAAPghCEAjAAYAwFEIQOgP+z8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAPQfCEDUfAhAMAAFAAAAAADvJgiAgEX7P8z8+j8Y/fo/ +AAAAAMQmCEAAAAAAAAAAANx8CIDARfs/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +/////wAAAAAAAAAAAAAAAAEAAAABAAAAAAAAACMPBgAAAAAA4EX7P8QmCEAAAAAA +Iw8GAGA0+z8k/fo/AQAAAAAAAAAARvs/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +J4IOgMA7/j/sMfs/AAAAAAAAAAAAAAAADEb7PwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -8FH7P0BT+z/2HasIVEL7P3D4+j+sU/s/HDL7PwMAAACvrmDFgSvFvKxT+z8AAAAA -FgAAAKhD+z9lc3BfdGltZXIAeE/mj3EAAAAAAKRT+z8WAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +EFr7P2Bb+z93NIJCfEr7Pyz9+j/UW/s/9DH7PwMAAAD+MW+qiUF6WdRb+z8AAAAA +FgAAANBL+z9lc3BfdGltZXIAgpLTBF4AAAAAAMxb+z8WAAAAAAAAAAAAAAAAAAAA AAAAAATv+j9s7/o/1O/6PwAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAEgdAEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEA+z8= -ACEIQPC/AEAwAAYAwncIgLBS+z8AAAAAIwAGACAABgAjAAYAAQAAAAAAAAAKPgiA -gFL7P8Ax+z8BAAAAwPf6P4D3+j8M9Po/WPT6PwAAAAD//wAAAAAAAAAAAAAAAAAA -AAAAAAQjCECA9/o/YE0IQKQd+z8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAEBT+z8AAAAAAAAAAAAAAAAucAiAwFL7P7gx+z8AAAAA -SFENgOBS+z+IFvs//////wAAAADg9/o/DCsIQAAAAAC8dQiAAFP7PwAAAAAAAAAA -AQAAACMABgABAAAAkDv+PwAAAAAgU/s/PFENQAAAAAAjAAYAYDT7P6xT+z8AAAAA -AAAAAEBT+z8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAABMU/s/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +9B8IQPC/AEAwAAYA7n4IgNBa+z8AAAAAIwAGACAABgAjAAYAAQAAAAAAAABVQgiA +oFr7P5gx+z8AAAAA4EX7P8BF+z8AAAAAAAAAAAAAAAD//wAAAAAAAAAAAAAAAAAA +AAAAAPghCEDARfs/wFEIQEgl+z8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAGBb+z8AAAAAAAAAAAAAAABydgiA4Fr7P5Ax+z8AAAAA +V0UNgABb+z8AAAAAAQAAAAAAAADPAAAAIAFAP5A7/j/cfAiAIFv7PwAAAAAAAAAA +GBb7PyMABgABAAAAIwwGAAAAAABAW/s/SEUNQAAAAAAjAAYAODT7P9Rb+z8AAAAA +AAAAAGBb+z8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAABsW/s/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAA== -AP36P2D++j8vG6MTJDL7P7RT+z9MQvs/HDL7PwEAAACg+vo/oPr6P0xC+z+Y+vo/ -GAAAAMz6+j9pcGMxAHqrpPxnrHN+FewAAQAAAMj++j8YAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAA +oEj7PwBK+z/09Aju/DH7P9xb+z90Svs/9DH7PwEAAABc//o/XP/6P3RK+z9U//o/ +GAAAAHBG+z9pcGMxAJM/cFah0FSaKN4AAQAAAGxK+z8YAAAAAAAAAAAAAAAAAAAA AAAAAATv+j9s7/o/1O/6PwAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAEgdAEAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAA+z8= -ACEIQIQ+CEAwCgYA9VgIgMD9+j8BAAAA/////8D6+j90afs/AQAAABwA9D+EPgiA -oP36P+AA8D8BAAAA2Bf7PyMKBgABAAAAAQAAAAAAAAD//wAAAAAAAAAAAAAAAAAA -AAAAAAQjCEAjCgYAYE0IQMTI+j8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAP//P7MAAAAAAAAAAAAAAAArKwiA4P36P3T6+j/A+vo/ -RAAAEyMKBgABAAAAAQAAALx1CIAg/vo/AQAAAAAAAAAAAAAAAQAAAAEAAAAcAPQ/ -/////yD++j8BAAAA/CsIQAEAAAABAAAAAAAAAAEAAAAAAAAAQP76PwwrCEABAAAA -AQAAAIg0+z9MQvs/AAAAAAAAAABg/vo/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -bw8IgGB9/j+APgAAvQT6AAAAAAAAAAAAbP76PwAAAAAAAAAAAAAAAAAAAAAAAAAA +9B8IQHxCCEAwCgYANV4IgGBJ+z8BAAAA/////3z/+j88bfs/AQAAABwA9D98QgiA +QEn7P+AA8D8BAAAAzBf7PyMKBgABAAAAAQAAAAAAAAD//wAAAAAAAAAAAAAAAAAA +AAAAAPghCEAjCgYAwFEIQOgT+z8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAL5pCIBgSfs/kDH7P0QAABPvJgiAgEn7PzD/+j98//o/ +RAAAEyMKBgABAAAAAQAAANx8CIDASfs/AQAAAAAAAAAAAAAAAQAAAAEAAAAcAPQ/ +/////8BJ+z8BAAAAYC8IQAEAAAABAAAAAAAAAAEAAAAAAAAA4En7P8QmCEABAAAA +AQAAAGA0+z90Svs/AAAAAAAAAAAASvs/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +Mw8IgGB9/j+APgAAtwD6AAAAAAAAAAAADEr7PwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== FAAAAEgAAABKIAAA RVNQX0NPUkVfRFVNUF9JTkZPAAA= -AAEAAGM4MDk4NWI3Njg3OTdmYjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAEAADNmMzZhYjc2MjI1ZWVjMDUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA DAAAAJQAAAClAgAA RVhUUkFfSU5GTwAA -TI77P+gAAAAdAAAA7gAAAAUAAADCAAAAAAAAAMMAAAAAAAAAxAAAACAKBgDFAAAA -AAAAAMYAAAAAAAAAsQAAANOTDUCyAAAAAAAAALMAAAAAAAAAtAAAAB0sCEC1AAAA +tI77P+gAAAAdAAAA7gAAAAUAAADCAAAAAAAAAMMAAAAAAAAAxAAAACAKBgDFAAAA +AAAAAMYAAAAAAAAAsQAAACuWDUCyAAAAAAAAALMAAAAAAAAAtAAAAIcvCEC1AAAA AAAAALYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAA== -YtCItg== +a69dOQ== diff --git a/components/espcoredump/test/esp32/expected_output b/components/espcoredump/test/esp32/expected_output index c069671cdc..013b30d2d5 100644 --- a/components/espcoredump/test/esp32/expected_output +++ b/components/espcoredump/test/esp32/expected_output @@ -2,15 +2,15 @@ espcoredump.py v0.4-dev =============================================================== ==================== ESP32 CORE DUMP START ==================== -Crashed task handle: 0x3ffb8e4c, name: 'unaligned_ptr_t', GDB name: 'process 1073450572' +Crashed task handle: 0x3ffb8eb4, name: 'unaligned_ptr_t', GDB name: 'process 1073450676' ================== CURRENT THREAD REGISTERS =================== exccause 0x1d (StoreProhibitedCause) excvaddr 0x5 -epc1 0x400d93d3 +epc1 0x400d962b epc2 0x0 epc3 0x0 -epc4 0x40082c1d +epc4 0x40082f87 epc5 0x0 epc6 0x0 eps2 0x0 @@ -18,12 +18,12 @@ eps3 0x0 eps4 0x60a20 eps5 0x0 eps6 0x0 -pc 0x400d56b1 0x400d56b1 +pc 0x400d4bd9 0x400d4bd9 lbeg 0x400014fd 1073747197 lend 0x4000150d 1073747213 lcount 0xffffffff 4294967295 sar 0x1a 26 -ps 0x60020 393248 +ps 0x60220 393760 threadptr br scompare1 @@ -39,91 +39,90 @@ f64r_hi f64s fcr fsr -a0 0x800d568c -2146609524 -a1 0x3ffb8d10 1073450256 +a0 0x800d4bb4 -2146612300 +a1 0x3ffb8d70 1073450352 a2 0x2 2 -a3 0x3ffb8d5c 1073450332 -a4 0x3ffb8d50 1073450320 +a3 0x3ffb8dbc 1073450428 +a4 0x3ffb8db0 1073450416 a5 0x3ffaef6c 1073409900 a6 0x0 0 a7 0x0 0 a8 0x5 5 a9 0xffffffad -83 a10 0x20 32 -a11 0x3ffb8eac 1073450668 +a11 0x3ffb8f14 1073450772 a12 0x1 1 a13 0x80 128 a14 0x1 1 a15 0x0 0 ==================== CURRENT THREAD STACK ===================== -#0 0x400d56b1 in UnityPrintNumberUnsigned (number=2) at /builds/espressif/esp-idf/components/unity/unity/src/unity.c:204 -#1 0x400d568c in UnityPrintNumberUnsigned (number=1) at /builds/espressif/esp-idf/components/unity/unity/src/unity.c:198 -#2 0x400d568c in UnityPrintNumberUnsigned (number=10) at /builds/espressif/esp-idf/components/unity/unity/src/unity.c:198 -#3 0x400d56d4 in UnityPrintNumber (number_to_print=0) at /builds/espressif/esp-idf/components/unity/unity/src/unity.c:178 -#4 0x400875bc in vPortTaskWrapper (pxCode=0x400d56bc , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:168 +#0 0x400d4bd9 in recur_func () at ../main/test_core_dump.c:70 +#1 0x400d4bb4 in recur_func () at ../main/test_core_dump.c:63 +#2 0x400d4bb4 in recur_func () at ../main/test_core_dump.c:63 +#3 0x400d4bfc in unaligned_ptr_task (pvParameter=0x0) at ../main/test_core_dump.c:80 +#4 0x40087cdc in vPortTaskWrapper (pxCode=0x400d4be4 , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:159 ======================== THREADS INFO ========================= Id Target Id Frame -* 1 process 1073450572 0x400d56b1 in UnityPrintNumberUnsigned (number=2) at /builds/espressif/esp-idf/components/unity/unity/src/unity.c:204 - 2 process 1073443020 0x400e781a in get_mask (bit_count=, shift=1) at /builds/espressif/esp-idf/components/efuse/src/esp_efuse_utility.c:293 - 3 process 1073444908 0x400e781a in get_mask (bit_count=, shift=0) at /builds/espressif/esp-idf/components/efuse/src/esp_efuse_utility.c:293 - 4 process 1073452972 0x40083e84 in esp_crosscore_int_send_yield (core_id=0) at /builds/espressif/esp-idf/components/esp_system/crosscore_int.c:144 - 5 process 1073448172 0x40083e84 in esp_crosscore_int_send_yield (core_id=0) at /builds/espressif/esp-idf/components/esp_system/crosscore_int.c:144 - 6 process 1073412200 0x40083e23 in esp_crosscore_int_send (core_id=, reason_mask=) at /builds/espressif/esp-idf/components/esp_system/crosscore_int.c:127 - 7 process 1073435564 0x4000bff0 in ?? () - 8 process 1073431116 0x40083e84 in esp_crosscore_int_send_yield (core_id=1) at /builds/espressif/esp-idf/components/esp_system/crosscore_int.c:144 +* 1 process 1073450676 0x400d4bd9 in recur_func () at ../main/test_core_dump.c:70 + 2 process 1073443988 0x400e7b2e in esp_pm_impl_waiti () at ../../../hal/esp32/include/hal/cpu_ll.h:183 + 3 process 1073445876 0x400e7b2e in esp_pm_impl_waiti () at ../../../hal/esp32/include/hal/cpu_ll.h:183 + 4 process 1073453076 0x4008427c in esp_crosscore_int_send_yield (core_id=0) at /builds/espressif/esp-idf/components/esp_system/crosscore_int.c:144 + 5 process 1073448276 0x4008427c in esp_crosscore_int_send_yield (core_id=0) at /builds/espressif/esp-idf/components/esp_system/crosscore_int.c:144 + 6 process 1073413412 0x4008427c in esp_crosscore_int_send_yield (core_id=0) at /builds/espressif/esp-idf/components/esp_system/crosscore_int.c:144 + 7 process 1073437652 0x4000bff0 in ?? () + 8 process 1073433204 0x4008427c in esp_crosscore_int_send_yield (core_id=1) at /builds/espressif/esp-idf/components/esp_system/crosscore_int.c:144 -==================== THREAD 1 (TCB: 0x3ffb8e4c, name: 'unaligned_ptr_t') ===================== -#0 0x400d56b1 in UnityPrintNumberUnsigned (number=2) at /builds/espressif/esp-idf/components/unity/unity/src/unity.c:204 -#1 0x400d568c in UnityPrintNumberUnsigned (number=1) at /builds/espressif/esp-idf/components/unity/unity/src/unity.c:198 -#2 0x400d568c in UnityPrintNumberUnsigned (number=10) at /builds/espressif/esp-idf/components/unity/unity/src/unity.c:198 -#3 0x400d56d4 in UnityPrintNumber (number_to_print=0) at /builds/espressif/esp-idf/components/unity/unity/src/unity.c:178 -#4 0x400875bc in vPortTaskWrapper (pxCode=0x400d56bc , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:168 +==================== THREAD 1 (TCB: 0x3ffb8eb4, name: 'unaligned_ptr_t') ===================== +#0 0x400d4bd9 in recur_func () at ../main/test_core_dump.c:70 +#1 0x400d4bb4 in recur_func () at ../main/test_core_dump.c:63 +#2 0x400d4bb4 in recur_func () at ../main/test_core_dump.c:63 +#3 0x400d4bfc in unaligned_ptr_task (pvParameter=0x0) at ../main/test_core_dump.c:80 +#4 0x40087cdc in vPortTaskWrapper (pxCode=0x400d4be4 , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:159 -==================== THREAD 2 (TCB: 0x3ffb70cc, name: 'IDLE') ===================== -#0 0x400e781a in get_mask (bit_count=, shift=1) at /builds/espressif/esp-idf/components/efuse/src/esp_efuse_utility.c:293 -#1 0x400d1a3a in esp_register_freertos_idle_hook_for_cpu (new_idle_cb=0x8, cpuid=0) at /builds/espressif/esp-idf/components/esp_system/freertos_hooks.c:67 -#2 0x40085dbd in prvIdleTask (pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/tasks.c:3823 -#3 0x400875bc in vPortTaskWrapper (pxCode=0x40085db4 , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:168 +==================== THREAD 2 (TCB: 0x3ffb7494, name: 'IDLE') ===================== +#0 0x400e7b2e in esp_pm_impl_waiti () at ../../../hal/esp32/include/hal/cpu_ll.h:183 +#1 0x400d1a42 in esp_vApplicationIdleHook () at /builds/espressif/esp-idf/components/esp_system/freertos_hooks.c:63 +#2 0x40086331 in prvIdleTask (pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/tasks.c:3909 +#3 0x40087cdc in vPortTaskWrapper (pxCode=0x40086328 , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:159 -==================== THREAD 3 (TCB: 0x3ffb782c, name: 'IDLE') ===================== -#0 0x400e781a in get_mask (bit_count=, shift=0) at /builds/espressif/esp-idf/components/efuse/src/esp_efuse_utility.c:293 -#1 0x400d1a3a in esp_register_freertos_idle_hook_for_cpu (new_idle_cb=0x8, cpuid=1) at /builds/espressif/esp-idf/components/esp_system/freertos_hooks.c:67 -#2 0x40085dbd in prvIdleTask (pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/tasks.c:3823 -#3 0x400875bc in vPortTaskWrapper (pxCode=0x40085db4 , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:168 +==================== THREAD 3 (TCB: 0x3ffb7bf4, name: 'IDLE') ===================== +#0 0x400e7b2e in esp_pm_impl_waiti () at ../../../hal/esp32/include/hal/cpu_ll.h:183 +#1 0x400d1a42 in esp_vApplicationIdleHook () at /builds/espressif/esp-idf/components/esp_system/freertos_hooks.c:63 +#2 0x40086331 in prvIdleTask (pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/tasks.c:3909 +#3 0x40087cdc in vPortTaskWrapper (pxCode=0x40086328 , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:159 -==================== THREAD 4 (TCB: 0x3ffb97ac, name: 'failed_assert_t') ===================== -#0 0x40083e84 in esp_crosscore_int_send_yield (core_id=0) at /builds/espressif/esp-idf/components/esp_system/crosscore_int.c:144 -#1 0x4008600a in vTaskDelay (xTicksToDelay=100) at ../../../hal/esp32/include/hal/cpu_ll.h:39 -#2 0x400d5597 in bad_ptr_func () at ../main/test_core_dump.c:29 -#3 0x400875bc in vPortTaskWrapper (pxCode=0x400d5588 , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:168 +==================== THREAD 4 (TCB: 0x3ffb9814, name: 'failed_assert_t') ===================== +#0 0x4008427c in esp_crosscore_int_send_yield (core_id=0) at /builds/espressif/esp-idf/components/esp_system/crosscore_int.c:144 +#1 0x4008658a in vTaskDelay (xTicksToDelay=100) at ../../../hal/esp32/include/hal/cpu_ll.h:39 +#2 0x400d4ab7 in failed_assert_task (pvParameter=0x0) at ../main/test_core_dump.c:89 +#3 0x40087cdc in vPortTaskWrapper (pxCode=0x400d4aa8 , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:159 -==================== THREAD 5 (TCB: 0x3ffb84ec, name: 'bad_ptr_task') ===================== -#0 0x40083e84 in esp_crosscore_int_send_yield (core_id=0) at /builds/espressif/esp-idf/components/esp_system/crosscore_int.c:144 -#1 0x4008600a in vTaskDelay (xTicksToDelay=100) at ../../../hal/esp32/include/hal/cpu_ll.h:39 -#2 0x400d564f in unaligned_ptr_task (pvParameter=0x0) at ../main/test_core_dump.c:76 -#3 0x400875bc in vPortTaskWrapper (pxCode=0x400d5640 , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:168 +==================== THREAD 5 (TCB: 0x3ffb8554, name: 'bad_ptr_task') ===================== +#0 0x4008427c in esp_crosscore_int_send_yield (core_id=0) at /builds/espressif/esp-idf/components/esp_system/crosscore_int.c:144 +#1 0x4008658a in vTaskDelay (xTicksToDelay=100) at ../../../hal/esp32/include/hal/cpu_ll.h:39 +#2 0x400d4b77 in bad_ptr_task (pvParameter=0x0) at ../main/test_core_dump.c:43 +#3 0x40087cdc in vPortTaskWrapper (pxCode=0x400d4b68 , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:159 -==================== THREAD 6 (TCB: 0x3ffaf868, name: 'ipc0') ===================== -#0 0x40083e23 in esp_crosscore_int_send (core_id=, reason_mask=) at /builds/espressif/esp-idf/components/esp_system/crosscore_int.c:127 -#1 0x40083e84 in esp_crosscore_int_send_yield (core_id=0) at /builds/espressif/esp-idf/components/esp_system/crosscore_int.c:144 -#2 0x400858f5 in xQueueSemaphoreTake (xQueue=0x3ffaf40c, xTicksToWait=) at ../../../hal/esp32/include/hal/cpu_ll.h:39 -#3 0x40082b2b in ipc_task (arg=0x0) at /builds/espressif/esp-idf/components/esp_ipc/ipc.c:51 -#4 0x400875bc in vPortTaskWrapper (pxCode=0x40082b0c , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:168 +==================== THREAD 6 (TCB: 0x3ffafd24, name: 'ipc0') ===================== +#0 0x4008427c in esp_crosscore_int_send_yield (core_id=0) at /builds/espressif/esp-idf/components/esp_system/crosscore_int.c:144 +#1 0x40085e35 in xQueueSemaphoreTake (xQueue=0x3ffafccc, xTicksToWait=) at ../../../hal/esp32/include/hal/cpu_ll.h:39 +#2 0x400826ef in ipc_task (arg=0x0) at /builds/espressif/esp-idf/components/esp_ipc/src/esp_ipc.c:59 +#3 0x40087cdc in vPortTaskWrapper (pxCode=0x400826c4 , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:159 -==================== THREAD 7 (TCB: 0x3ffb53ac, name: 'esp_timer') ===================== +==================== THREAD 7 (TCB: 0x3ffb5bd4, name: 'esp_timer') ===================== #0 0x4000bff0 in ?? () -#1 0x400877c2 in vPortExitCritical (mux=) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:473 -#2 0x4008702e in ulTaskNotifyTake (xClearCountOnExit=1, xTicksToWait=4294967295) at /builds/espressif/esp-idf/components/freertos/tasks.c:5187 -#3 0x400d5148 in esp_timer_impl_init_system_time () at /builds/espressif/esp-idf/components/esp_timer/src/system_time.c:43 -#4 0x400875bc in vPortTaskWrapper (pxCode=0x400d513c , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:168 +#1 0x40087eee in vPortExitCritical (mux=) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:447 +#2 0x40087672 in ulTaskGenericNotifyTake (uxIndexToWait=0, xClearCountOnExit=1, xTicksToWait=) at /builds/espressif/esp-idf/components/freertos/tasks.c:5303 +#3 0x400d4557 in timer_task (arg=0x0) at /builds/espressif/esp-idf/components/esp_timer/src/esp_timer.c:392 +#4 0x40087cdc in vPortTaskWrapper (pxCode=0x400d4548 , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:159 -==================== THREAD 8 (TCB: 0x3ffb424c, name: 'ipc1') ===================== -#0 0x40083e84 in esp_crosscore_int_send_yield (core_id=1) at /builds/espressif/esp-idf/components/esp_system/crosscore_int.c:144 -#1 0x400858f5 in xQueueSemaphoreTake (xQueue=0x3ffafa74, xTicksToWait=) at ../../../hal/esp32/include/hal/cpu_ll.h:39 -#2 0x40082b2b in ipc_task (arg=0x1) at /builds/espressif/esp-idf/components/esp_ipc/ipc.c:51 -#3 0x400875bc in vPortTaskWrapper (pxCode=0x40082b0c , pvParameters=0x1) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:168 +==================== THREAD 8 (TCB: 0x3ffb4a74, name: 'ipc1') ===================== +#0 0x4008427c in esp_crosscore_int_send_yield (core_id=1) at /builds/espressif/esp-idf/components/esp_system/crosscore_int.c:144 +#1 0x40085e35 in xQueueSemaphoreTake (xQueue=0x3ffaff30, xTicksToWait=) at ../../../hal/esp32/include/hal/cpu_ll.h:39 +#2 0x400826ef in ipc_task (arg=0x1) at /builds/espressif/esp-idf/components/esp_ipc/src/esp_ipc.c:59 +#3 0x40087cdc in vPortTaskWrapper (pxCode=0x400826c4 , pvParameters=0x1) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:159 ======================= ALL MEMORY REGIONS ======================== @@ -135,454 +134,454 @@ Name Address Size Attrs .rtc_noinit 0x50000010 0x0 RW .rtc.force_slow 0x50000010 0x0 RW .iram0.vectors 0x40080000 0x403 R XA -.iram0.text 0x40080404 0xa457 R XA -.dram0.data 0x3ffb0000 0x2f18 RW A -.noinit 0x3ffb2f18 0x0 RW +.iram0.text 0x40080404 0xadc3 R XA +.dram0.data 0x3ffb0000 0x2f28 RW A +.ext_ram_noinit 0x3f800000 0x0 RW +.noinit 0x3ffb2f28 0x0 RW .ext_ram.bss 0x3f800000 0x0 RW .flash.appdesc 0x3f400020 0x100 R A -.flash.rodata 0x3f400120 0x35dc RW A -.flash.rodata_noload 0x3f4036fc 0x0 RW -.flash.text 0x400d0020 0x181a7 R XA -.iram0.data 0x4008a85c 0x0 RW -.iram0.bss 0x4008a85c 0x0 RW -.dram0.heap_start 0x3ffb3bf0 0x0 RW -.coredump.tasks.data 0x3ffb8e4c 0x158 RW -.coredump.tasks.data 0x3ffb8c50 0x1f4 RW -.coredump.tasks.data 0x3ffb70cc 0x158 RW -.coredump.tasks.data 0x3ffb6f20 0x1a4 RW -.coredump.tasks.data 0x3ffb782c 0x158 RW -.coredump.tasks.data 0x3ffb7680 0x1a4 RW -.coredump.tasks.data 0x3ffb97ac 0x158 RW -.coredump.tasks.data 0x3ffb9600 0x1a4 RW -.coredump.tasks.data 0x3ffb84ec 0x158 RW -.coredump.tasks.data 0x3ffb8340 0x1a4 RW -.coredump.tasks.data 0x3ffaf868 0x158 RW -.coredump.tasks.data 0x3ffaf680 0x1e0 RW -.coredump.tasks.data 0x3ffb53ac 0x158 RW -.coredump.tasks.data 0x3ffb51f0 0x1b4 RW -.coredump.tasks.data 0x3ffb424c 0x158 RW -.coredump.tasks.data 0x3ffafd00 0x1c8 RW +.flash.rodata 0x3f400120 0x3608 RW A +.flash.rodata_noload 0x3f403728 0x0 RW +.flash.text 0x400d0020 0x18467 R XA +.iram0.data 0x4008b1c8 0x0 RW +.iram0.bss 0x4008b1c8 0x0 RW +.dram0.heap_start 0x3ffb3c10 0x0 RW +.coredump.tasks.data 0x3ffb8eb4 0x158 RW +.coredump.tasks.data 0x3ffb8cb0 0x1fc RW +.coredump.tasks.data 0x3ffb7494 0x158 RW +.coredump.tasks.data 0x3ffb72e0 0x1ac RW +.coredump.tasks.data 0x3ffb7bf4 0x158 RW +.coredump.tasks.data 0x3ffb7a40 0x1ac RW +.coredump.tasks.data 0x3ffb9814 0x158 RW +.coredump.tasks.data 0x3ffb9660 0x1ac RW +.coredump.tasks.data 0x3ffb8554 0x158 RW +.coredump.tasks.data 0x3ffb83a0 0x1ac RW +.coredump.tasks.data 0x3ffafd24 0x158 RW +.coredump.tasks.data 0x3ffb44a0 0x1c8 RW +.coredump.tasks.data 0x3ffb5bd4 0x158 RW +.coredump.tasks.data 0x3ffb5a10 0x1bc RW +.coredump.tasks.data 0x3ffb4a74 0x158 RW +.coredump.tasks.data 0x3ffb48a0 0x1cc RW ====================== CORE DUMP MEMORY CONTENTS ======================== -.coredump.tasks.data 0x3ffb8e4c 0x158 RW -0x3ffb8e4c: 0x3ffb8ca0 0x3ffb8de0 0x00000065 0x3ffb3334 -0x3ffb8e5c: 0x3ffb3334 0x3ffb8e4c 0x3ffb332c 0x00000012 -0x3ffb8e6c: 0x2c000b52 0xf1622a7e 0x3ffb8e4c 0x00000000 -0x3ffb8e7c: 0x00000007 0x3ffb8648 0x6c616e75 0x656e6769 -0x3ffb8e8c: 0x74705f64 0x00745f72 0x00000001 0x3ffb8e44 -0x3ffb8e9c: 0x00000007 0x00000000 0x00000000 0x00000000 -0x3ffb8eac: 0x00000000 0x3ffaef04 0x3ffaef6c 0x3ffaefd4 -0x3ffb8ebc: 0x00000000 0x00000000 0x00000001 0x00000000 -0x3ffb8ecc: 0x00000000 0x00000000 0x40001d48 0x00000000 -0x3ffb8edc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb8eec: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb8efc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb8f0c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb8f1c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb8f2c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb8f3c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb8f4c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb8f5c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb8f6c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb8f7c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb8f8c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb8f9c: 0x00000000 0x3ffb0000 -.coredump.tasks.data 0x3ffb8c50 0x1f4 RW -0x3ffb8c50: 0xdeadbeef 0x400d56b1 0x00060030 0x800d568c -0x3ffb8c60: 0x3ffb8d10 0x00000002 0x3ffb8d5c 0x3ffb8d50 -0x3ffb8c70: 0x3ffaef6c 0x00000000 0x00000000 0x00000005 -0x3ffb8c80: 0xffffffad 0x00000020 0x3ffb8eac 0x00000001 -0x3ffb8c90: 0x00000080 0x00000001 0x00000000 0x0000001a -0x3ffb8ca0: 0x0000001d 0x00000005 0x400014fd 0x4000150d -0x3ffb8cb0: 0xffffffff 0x00000001 0x00000080 0x4008209c -0x3ffb8cc0: 0x3ffb5844 0x00000000 0x00000000 0x00000000 -0x3ffb8cd0: 0xb33fffff 0x00000000 0x00000000 0x00000000 -0x3ffb8ce0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb8cf0: 0x00000001 0x00000080 0x00000001 0x00000000 -0x3ffb8d00: 0x800d568c 0x3ffb8d40 0x00000001 0x3ffaef6c -0x3ffb8d10: 0x00000003 0x00000000 0x00000001 0x00000001 -0x3ffb8d20: 0x3ffb8d50 0x3ffaef6c 0x00000000 0x00000000 -0x3ffb8d30: 0x800d56d4 0x3ffb8d70 0x0000000a 0x3ffb1688 -0x3ffb8d40: 0x00000003 0x0000001e 0x3f403202 0x00000001 -0x3ffb8d50: 0x3ffb3494 0x00060023 0x00000001 0x00000000 -0x3ffb8d60: 0x800875bc 0x3ffb8da0 0x00000000 0x00000000 -0x3ffb8d70: 0x00000003 0x3ffb8da0 0x00000000 0x00000000 -0x3ffb8d80: 0x00060021 0x00060023 0x00000001 0x00000000 -0x3ffb8d90: 0x00000000 0x3ffb8dc0 0x400d56bc 0x00000000 -0x3ffb8da0: 0x00060023 0x3ffb3334 0x3ffb8e4c 0x00000000 -0x3ffb8db0: 0x00000000 0x3ffb8de0 0x00000000 0x00000000 -0x3ffb8dc0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb8dd0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb8de0: 0x00000000 0x00000000 0x3ffb8dec 0x00000000 -0x3ffb8df0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb8e00: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb8e10: 0x00000000 0x00000000 0x00000000 0x00000000 +.coredump.tasks.data 0x3ffb8eb4 0x158 RW +0x3ffb8eb4: 0x3ffb8d20 0x3ffb8e40 0x00000065 0x3ffb330c +0x3ffb8ec4: 0x3ffb330c 0x3ffb8eb4 0x3ffb3304 0x00000012 +0x3ffb8ed4: 0x00aa45ea 0xe43a6d20 0x3ffb8eb4 0x00000000 +0x3ffb8ee4: 0x00000007 0x3ffb86b0 0x6c616e75 0x656e6769 +0x3ffb8ef4: 0x74705f64 0x00745f72 0x00000001 0x3ffb8eac +0x3ffb8f04: 0x00000007 0x00000000 0x00000000 0x00000000 +0x3ffb8f14: 0x00000000 0x3ffaef04 0x3ffaef6c 0x3ffaefd4 +0x3ffb8f24: 0x00000000 0x00000000 0x00000001 0x00000000 +0x3ffb8f34: 0x00000000 0x00000000 0x40001d48 0x00000000 +0x3ffb8f44: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8f54: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8f64: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8f74: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8f84: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8f94: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8fa4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8fb4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8fc4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8fd4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8fe4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8ff4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb9004: 0x00000000 0x3ffb0000 +.coredump.tasks.data 0x3ffb8cb0 0x1fc RW +0x3ffb8cb0: 0xdeadbeef 0x400d4bd9 0x00060230 0x800d4bb4 +0x3ffb8cc0: 0x3ffb8d70 0x00000002 0x3ffb8dbc 0x3ffb8db0 +0x3ffb8cd0: 0x3ffaef6c 0x00000000 0x00000000 0x00000005 +0x3ffb8ce0: 0xffffffad 0x00000020 0x3ffb8f14 0x00000001 +0x3ffb8cf0: 0x00000080 0x00000001 0x00000000 0x0000001a +0x3ffb8d00: 0x0000001d 0x00000005 0x400014fd 0x4000150d +0x3ffb8d10: 0xffffffff 0x00000001 0x00000080 0x40081f90 +0x3ffb8d20: 0x3ffb5828 0x00000000 0x00000000 0x00000000 +0x3ffb8d30: 0xb33fffff 0x00000000 0x00000000 0x00000000 +0x3ffb8d40: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8d50: 0x00000001 0x00000080 0x00000001 0x00000000 +0x3ffb8d60: 0x800d4bb4 0x3ffb8da0 0x00000001 0x3ffaef6c +0x3ffb8d70: 0x00000003 0xa5a5a5a5 0x00000001 0x00000001 +0x3ffb8d80: 0x3ffb8db0 0x3ffaef6c 0x00000000 0x00000000 +0x3ffb8d90: 0x800d4bfc 0x3ffb8dd0 0x0000000a 0x3ffb1618 +0x3ffb8da0: 0x00000003 0x0000001e 0x3f402370 0x00000001 +0x3ffb8db0: 0x3ffb346c 0x3ffb84c0 0x400d4b68 0x00000000 +0x3ffb8dc0: 0x80087cdc 0x3ffb8e00 0x00000000 0x00000000 +0x3ffb8dd0: 0x00000003 0x3ffb8e00 0x00000000 0x00000000 +0x3ffb8de0: 0x00060021 0x00060023 0x00000001 0x00000000 +0x3ffb8df0: 0x00000000 0x3ffb8e20 0x400d4be4 0x00000000 +0x3ffb8e00: 0x00060023 0x3ffb330c 0x3ffb8eb4 0x00000000 +0x3ffb8e10: 0x00000000 0x3ffb8e40 0x00000000 0x00000000 0x3ffb8e20: 0x00000000 0x00000000 0x00000000 0x00000000 0x3ffb8e30: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb8e40: 0x00000000 -.coredump.tasks.data 0x3ffb70cc 0x158 RW -0x3ffb70cc: 0x3ffb6f20 0x3ffb7060 0x70b6e436 0x3ffb7834 -0x3ffb70dc: 0x3ffb32a8 0x3ffb70cc 0x3ffb32a0 0x00000019 -0x3ffb70ec: 0x12e0a231 0x4e01e717 0x3ffb70cc 0x00000000 -0x3ffb70fc: 0x00000000 0x3ffb6ac8 0x454c4449 0xbe43e000 -0x3ffb710c: 0xc1fed371 0x00d4ba0e 0x00000000 0x3ffb70c4 -0x3ffb711c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb712c: 0x00000000 0x3ffaef04 0x3ffaef6c 0x3ffaefd4 -0x3ffb713c: 0x00000000 0x00000000 0x00000001 0x00000000 -0x3ffb714c: 0x00000000 0x00000000 0x40001d48 0x00000000 -0x3ffb715c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb716c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb717c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb718c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb719c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb71ac: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb71bc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb71cc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb71dc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb71ec: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb71fc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb720c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb721c: 0x00000000 0x3ffb0000 -.coredump.tasks.data 0x3ffb6f20 0x1a4 RW -0x3ffb6f20: 0x40082100 0x400e781a 0x00060b30 0x800d1a3a -0x3ffb6f30: 0x3ffb6fe0 0x00000000 0x00000001 0x00000001 -0x3ffb6f40: 0x80000001 0x00800000 0x3ff4001c 0x800d9a5a -0x3ffb6f50: 0x3ffb6fb0 0x00000000 0x40001d48 0x00060720 -0x3ffb6f60: 0x00060723 0x00000001 0x3ff4001c 0x00000015 -0x3ffb6f70: 0x0000ffff 0x00000000 0x00000000 0x00000000 -0x3ffb6f80: 0x00000000 0x40082304 0x00060723 0x40084d60 -0x3ffb6f90: 0x3ffb3ac4 0x00000000 0x00000000 0x00000000 -0x3ffb6fa0: 0xb33fffff 0x00000000 0x00000000 0x00000000 -0x3ffb6fb0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb6fc0: 0x00000000 0x40085db4 0x00000000 0x00000000 -0x3ffb6fd0: 0x80085dbd 0x3ffb7000 0x00000008 0x00000000 -0x3ffb6fe0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb6ff0: 0x800875bc 0x3ffb7020 0x00000000 0x00000000 -0x3ffb7000: 0x00000001 0x00060023 0x00000001 0x00060423 -0x3ffb7010: 0x00000000 0x3ffb7040 0x40085db4 0x00000000 -0x3ffb7020: 0x00060023 0x3ffb32a8 0x3ffb782c 0x00000000 -0x3ffb7030: 0x00000000 0x3ffb7060 0x00000000 0x00000000 -0x3ffb7040: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb7050: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb7060: 0x00000000 0x00000000 0x3ffb706c 0x00000000 -0x3ffb7070: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb7080: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb7090: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb70a0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb70b0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb70c0: 0x00000000 -.coredump.tasks.data 0x3ffb782c 0x158 RW -0x3ffb782c: 0x3ffb7680 0x3ffb77c0 0x27922dd5 0x3ffb32a8 -0x3ffb783c: 0x3ffb70d4 0x3ffb782c 0x3ffb32a0 0x00000019 -0x3ffb784c: 0x09750ed0 0x9c732e59 0x3ffb782c 0x00000000 -0x3ffb785c: 0x00000000 0x3ffb7228 0x454c4449 0x0bf55e00 -0x3ffb786c: 0xe7eef877 0x006b2a87 0x00000001 0x3ffb7824 -0x3ffb787c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb788c: 0x00000000 0x3ffaef04 0x3ffaef6c 0x3ffaefd4 -0x3ffb789c: 0x00000000 0x00000000 0x00000001 0x00000000 -0x3ffb78ac: 0x00000000 0x00000000 0x40001d48 0x00000000 -0x3ffb78bc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb78cc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb78dc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb78ec: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb78fc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb790c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb791c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb792c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb793c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb794c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb795c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb796c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb797c: 0x00000000 0x3ffb0000 -.coredump.tasks.data 0x3ffb7680 0x1a4 RW -0x3ffb7680: 0x40082100 0x400e781a 0x00060a30 0x800d1a3a -0x3ffb7690: 0x3ffb7740 0x00000000 0x00000000 0x00000001 -0x3ffb76a0: 0x80000001 0x00000003 0x00060023 0x800d9a5a -0x3ffb76b0: 0x3ffb7710 0x00000000 0x00060a23 0x00060a20 -0x3ffb76c0: 0x00060a23 0x00000001 0x00000000 0x00000018 -0x3ffb76d0: 0x0000ffff 0x00000000 0x00000000 0x00000000 -0x3ffb76e0: 0x00000000 0x40082304 0x00060a23 0x40084d60 -0x3ffb76f0: 0x3ffb4224 0x00000000 0x00000000 0x00000000 -0x3ffb7700: 0xb33fffff 0x00000000 0x00000000 0x00000000 -0x3ffb7710: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb7720: 0x00000000 0x40085db4 0x00000000 0x00000000 -0x3ffb7730: 0x80085dbd 0x3ffb7760 0x00000008 0x00000001 -0x3ffb7740: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb7750: 0x800875bc 0x3ffb7780 0x00000000 0x00000000 -0x3ffb7760: 0x00000001 0x00060023 0x00000001 0x00000000 -0x3ffb7770: 0x00000000 0x3ffb77a0 0x40085db4 0x00000000 -0x3ffb7780: 0x00060023 0x3ffb32a8 0x3ffb70cc 0x00000000 -0x3ffb7790: 0x00000000 0x3ffb77c0 0x00000000 0x00000000 -0x3ffb77a0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb77b0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb77c0: 0x00000000 0x00000000 0x3ffb77cc 0x00000000 -0x3ffb77d0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb77e0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb77f0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb7800: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb7810: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb7820: 0x00000000 -.coredump.tasks.data 0x3ffb97ac 0x158 RW -0x3ffb97ac: 0x3ffb9600 0x3ffb9740 0x000000c9 0x3ffb84f4 -0x3ffb97bc: 0x3ffb3294 0x3ffb97ac 0x3ffb328c 0x0000000f -0x3ffb97cc: 0x3ffb8508 0x3ffaf12c 0x3ffb97ac 0x00000000 -0x3ffb97dc: 0x0000000a 0x3ffb8fa8 0x6c696166 0x615f6465 -0x3ffb97ec: 0x72657373 0x00745f74 0x00000000 0x3ffb97a4 -0x3ffb97fc: 0x0000000a 0x00000000 0x00000000 0x00000000 -0x3ffb980c: 0x00000000 0x3ffaef04 0x3ffaef6c 0x3ffaefd4 -0x3ffb981c: 0x00000000 0x00000000 0x00000001 0x00000000 -0x3ffb982c: 0x00000000 0x00000000 0x40001d48 0x00000000 -0x3ffb983c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb984c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb985c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb986c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb987c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb988c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb989c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb98ac: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb98bc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb98cc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb98dc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb98ec: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb98fc: 0x00000000 0x3ffb0000 -.coredump.tasks.data 0x3ffb9600 0x1a4 RW -0x3ffb9600: 0x40082100 0x40083e84 0x00060930 0x8008600a -0x3ffb9610: 0x3ffb96c0 0x00000000 0x000000c9 0x3ffb3494 -0x3ffb9620: 0x3ffb6840 0x00000800 0x00000000 0x80083e84 -0x3ffb9630: 0x3ffb96a0 0x3ff000dc 0x00000001 0x3ffb17d8 -0x3ffb9640: 0x00060923 0x00000001 0x00000000 0x00000000 -0x3ffb9650: 0x0000ffff 0x00000000 0x400014fd 0x4000150d -0x3ffb9660: 0xfffffff8 0x40082304 0x00060923 0x40084d60 -0x3ffb9670: 0x3ffb61a4 0x00000000 0x00000000 0x00000000 -0x3ffb9680: 0xb33fffff 0x00000000 0x00000000 0x00000000 -0x3ffb9690: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb96a0: 0x3f40160c 0x0000001e 0x3f403202 0x00000001 -0x3ffb96b0: 0x800d5597 0x3ffb96e0 0x00000064 0x3ffb1688 -0x3ffb96c0: 0x3ffb3494 0x3ffb6840 0x00000800 0x00000000 -0x3ffb96d0: 0x800875bc 0x3ffb9700 0x00000000 0x00000000 -0x3ffb96e0: 0x00060021 0x00060023 0x00000001 0x00000000 -0x3ffb96f0: 0x00000000 0x3ffb9720 0x400d5588 0x00000000 -0x3ffb9700: 0x00060023 0x3ffb3370 0x3ffb97ac 0x00000000 -0x3ffb9710: 0x00000000 0x3ffb9740 0x00000000 0x00000000 -0x3ffb9720: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb9730: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb9740: 0x00000000 0x00000000 0x3ffb974c 0x00000000 -0x3ffb9750: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb9760: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb9770: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8e40: 0x00000000 0x00000000 0x3ffb8e4c 0x00000000 +0x3ffb8e50: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8e60: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8e70: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8e80: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8e90: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8ea0: 0x00000000 0x00000000 0x00000000 +.coredump.tasks.data 0x3ffb7494 0x158 RW +0x3ffb7494: 0x3ffb72e0 0x3ffb7420 0x81753475 0x3ffb7bfc +0x3ffb74a4: 0x3ffb3280 0x3ffb7494 0x3ffb3278 0x00000019 +0x3ffb74b4: 0x389fa225 0xf64dd725 0x3ffb7494 0x00000000 +0x3ffb74c4: 0x00000000 0x3ffb6e90 0x454c4449 0x38928c00 +0x3ffb74d4: 0xac1cf8bc 0x008a9041 0x00000000 0x3ffb748c +0x3ffb74e4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb74f4: 0x00000000 0x3ffaef04 0x3ffaef6c 0x3ffaefd4 +0x3ffb7504: 0x00000000 0x00000000 0x00000001 0x00000000 +0x3ffb7514: 0x00000000 0x00000000 0x40001d48 0x00000000 +0x3ffb7524: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7534: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7544: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7554: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7564: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7574: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7584: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7594: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb75a4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb75b4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb75c4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb75d4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb75e4: 0x00000000 0x3ffb0000 +.coredump.tasks.data 0x3ffb72e0 0x1ac RW +0x3ffb72e0: 0x40081ff4 0x400e7b2e 0x00060530 0x800d1a42 +0x3ffb72f0: 0x3ffb73a0 0x00000000 0x00000001 0x00000001 +0x3ffb7300: 0x80000001 0x00800000 0x3ff4001c 0x800d9cce +0x3ffb7310: 0x3ffb7370 0x00000000 0x40001d48 0x00060120 +0x3ffb7320: 0x00060123 0x00000001 0x3ff4001c 0x0000001e +0x3ffb7330: 0x0000ffff 0x00000000 0x00000000 0x00000000 +0x3ffb7340: 0x00000000 0x400821f8 0x00060123 0x400851c0 +0x3ffb7350: 0x3ffb3e08 0x00000000 0x00000000 0x00000000 +0x3ffb7360: 0xb33fffff 0x00000000 0x00000000 0x00000000 +0x3ffb7370: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7380: 0x00000000 0x40086328 0x00000000 0x00000000 +0x3ffb7390: 0x80086331 0x3ffb73c0 0x00000008 0x00000000 +0x3ffb73a0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb73b0: 0x80087cdc 0x3ffb73e0 0x00000000 0x00000000 +0x3ffb73c0: 0x00000001 0x00060023 0x00000001 0x00060e23 +0x3ffb73d0: 0x00000000 0x3ffb7400 0x40086328 0x00000000 +0x3ffb73e0: 0x00060023 0x3ffb3280 0x3ffb7bf4 0x00000000 +0x3ffb73f0: 0x00000000 0x3ffb7420 0x00000000 0x00000000 +0x3ffb7400: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7410: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7420: 0x00000000 0x00000000 0x3ffb742c 0x00000000 +0x3ffb7430: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7440: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7450: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7460: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7470: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7480: 0x00000000 0x00000000 0x00000000 +.coredump.tasks.data 0x3ffb7bf4 0x158 RW +0x3ffb7bf4: 0x3ffb7a40 0x3ffb7b80 0x62e8df68 0x3ffb3280 +0x3ffb7c04: 0x3ffb749c 0x3ffb7bf4 0x3ffb3278 0x00000019 +0x3ffb7c14: 0x210bd671 0x0232392a 0x3ffb7bf4 0x00000000 +0x3ffb7c24: 0x00000000 0x3ffb75f0 0x454c4449 0x65786000 +0x3ffb7c34: 0xa3b8043f 0x00ff637b 0x00000001 0x3ffb7bec +0x3ffb7c44: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7c54: 0x00000000 0x3ffaef04 0x3ffaef6c 0x3ffaefd4 +0x3ffb7c64: 0x00000000 0x00000000 0x00000001 0x00000000 +0x3ffb7c74: 0x00000000 0x00000000 0x40001d48 0x00000000 +0x3ffb7c84: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7c94: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7ca4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7cb4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7cc4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7cd4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7ce4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7cf4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7d04: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7d14: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7d24: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7d34: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7d44: 0x00000000 0x3ffb0000 +.coredump.tasks.data 0x3ffb7a40 0x1ac RW +0x3ffb7a40: 0x40081ff4 0x400e7b2e 0x00060a30 0x800d1a42 +0x3ffb7a50: 0x3ffb7b00 0x00000000 0x00000000 0x00000001 +0x3ffb7a60: 0x80000001 0x00000003 0x00060023 0x800d9cce +0x3ffb7a70: 0x3ffb7ad0 0x00000000 0x00060a23 0x00060a20 +0x3ffb7a80: 0x00060a23 0x00000001 0x00000000 0x0000001e +0x3ffb7a90: 0x0000ffff 0x00000000 0x00000000 0x00000000 +0x3ffb7aa0: 0x00000000 0x400821f8 0x00060a23 0x400851c0 +0x3ffb7ab0: 0x3ffb4568 0x00000000 0x00000000 0x00000000 +0x3ffb7ac0: 0xb33fffff 0x00000000 0x00000000 0x00000000 +0x3ffb7ad0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7ae0: 0x00000000 0x40086328 0x00000000 0x00000000 +0x3ffb7af0: 0x80086331 0x3ffb7b20 0x00000008 0x00000001 +0x3ffb7b00: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7b10: 0x80087cdc 0x3ffb7b40 0x00000000 0x00000000 +0x3ffb7b20: 0x00000001 0x00060023 0x00000001 0x00000000 +0x3ffb7b30: 0x00000000 0x3ffb7b60 0x40086328 0x00000000 +0x3ffb7b40: 0x00060023 0x3ffb3280 0x3ffb7494 0x00000000 +0x3ffb7b50: 0x00000000 0x3ffb7b80 0x00000000 0x00000000 +0x3ffb7b60: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7b70: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7b80: 0x00000000 0x00000000 0x3ffb7b8c 0x00000000 +0x3ffb7b90: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7ba0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7bb0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7bc0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7bd0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7be0: 0x00000000 0x00000000 0x00000000 +.coredump.tasks.data 0x3ffb9814 0x158 RW +0x3ffb9814: 0x3ffb9660 0x3ffb97a0 0x000000c9 0x3ffb855c +0x3ffb9824: 0x3ffb326c 0x3ffb9814 0x3ffb3264 0x0000000f +0x3ffb9834: 0x3ffb8570 0x3ffaf12c 0x3ffb9814 0x00000000 +0x3ffb9844: 0x0000000a 0x3ffb9010 0x6c696166 0x615f6465 +0x3ffb9854: 0x72657373 0x00745f74 0x00000000 0x3ffb980c +0x3ffb9864: 0x0000000a 0x00000000 0x00000000 0x00000000 +0x3ffb9874: 0x00000000 0x3ffaef04 0x3ffaef6c 0x3ffaefd4 +0x3ffb9884: 0x00000000 0x00000000 0x00000001 0x00000000 +0x3ffb9894: 0x00000000 0x00000000 0x40001d48 0x00000000 +0x3ffb98a4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb98b4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb98c4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb98d4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb98e4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb98f4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb9904: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb9914: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb9924: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb9934: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb9944: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb9954: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb9964: 0x00000000 0x3ffb0000 +.coredump.tasks.data 0x3ffb9660 0x1ac RW +0x3ffb9660: 0x40081ff4 0x4008427c 0x00060530 0x8008658a +0x3ffb9670: 0x3ffb9720 0x00000000 0x000000c9 0x3ffb346c +0x3ffb9680: 0x3ffb6c00 0x00000800 0x00000000 0x8008427c +0x3ffb9690: 0x3ffb9700 0x3ff000dc 0x00000001 0x3ffb17cc +0x3ffb96a0: 0x00060523 0x00000001 0x00000000 0x00000000 +0x3ffb96b0: 0x0000ffff 0x00000000 0x400014fd 0x4000150d +0x3ffb96c0: 0xfffffff8 0x400821f8 0x00060523 0x400851c0 +0x3ffb96d0: 0x3ffb6188 0x00000000 0x00000000 0x00000000 +0x3ffb96e0: 0xb33fffff 0x00000000 0x00000000 0x00000000 +0x3ffb96f0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb9700: 0x3f40148c 0x0000001e 0x3f402370 0x00000001 +0x3ffb9710: 0x800d4ab7 0x3ffb9740 0x00000064 0x3ffb1618 +0x3ffb9720: 0x3ffb346c 0x3ffb6c00 0x00000800 0x00000000 +0x3ffb9730: 0x80087cdc 0x3ffb9760 0x00000000 0x00000000 +0x3ffb9740: 0x00060021 0x00060023 0x00000001 0x00000000 +0x3ffb9750: 0x00000000 0x3ffb9780 0x400d4aa8 0x00000000 +0x3ffb9760: 0x00060023 0x3ffb3348 0x3ffb9814 0x00000000 +0x3ffb9770: 0x00000000 0x3ffb97a0 0x00000000 0x00000000 0x3ffb9780: 0x00000000 0x00000000 0x00000000 0x00000000 0x3ffb9790: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb97a0: 0x00000000 -.coredump.tasks.data 0x3ffb84ec 0x158 RW -0x3ffb84ec: 0x3ffb8340 0x3ffb8480 0x000000c9 0x3ffb3294 -0x3ffb84fc: 0x3ffb97b4 0x3ffb84ec 0x3ffb328c 0x00000014 -0x3ffb850c: 0x3ffaf12c 0x3ffaf12c 0x3ffb84ec 0x00000000 -0x3ffb851c: 0x00000005 0x3ffb7ce8 0x5f646162 0x5f727470 -0x3ffb852c: 0x6b736174 0x00e1b000 0x7fffffff 0x3ffb84e4 -0x3ffb853c: 0x00000005 0x00000000 0x00000000 0x00000000 -0x3ffb854c: 0x00000000 0x3ffaef04 0x3ffaef6c 0x3ffaefd4 -0x3ffb855c: 0x00000000 0x00000000 0x00000001 0x00000000 -0x3ffb856c: 0x00000000 0x00000000 0x40001d48 0x00000000 -0x3ffb857c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb858c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb859c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb85ac: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb85bc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb85cc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb85dc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb85ec: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb85fc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb860c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb861c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb862c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb863c: 0x00000000 0x3ffb0000 -.coredump.tasks.data 0x3ffb8340 0x1a4 RW -0x3ffb8340: 0x40082100 0x40083e84 0x00060b30 0x8008600a -0x3ffb8350: 0x3ffb8400 0x00000000 0x000000c9 0x3ffb3494 -0x3ffb8360: 0x3ffb3488 0x3ffb424c 0x00000000 0x80083e84 -0x3ffb8370: 0x3ffb83e0 0x3ff000dc 0x00000001 0x3ffb17d8 -0x3ffb8380: 0x00060b23 0x00000001 0x00000000 0x00000000 -0x3ffb8390: 0x0000ffff 0x00000000 0x400014fd 0x4000150d -0x3ffb83a0: 0xfffffff9 0x40082304 0x00060b23 0x40084d60 -0x3ffb83b0: 0x3ffb4ee4 0x00000000 0x00000000 0x00000000 -0x3ffb83c0: 0xb33fffff 0x00000000 0x00000000 0x00000000 -0x3ffb83d0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb83e0: 0x3f4016a8 0x00000018 0x3f403202 0x00000001 -0x3ffb83f0: 0x800d564f 0x3ffb8420 0x00000064 0x3ffb1688 -0x3ffb8400: 0x3ffb3494 0x3ffb3488 0x3ffb424c 0x00000000 -0x3ffb8410: 0x800875bc 0x3ffb8440 0x00000000 0x00000000 -0x3ffb8420: 0x00060021 0x00060023 0x00000001 0x00060a23 -0x3ffb8430: 0x00000000 0x3ffb8460 0x400d5640 0x00000000 -0x3ffb8440: 0x00060023 0x3ffb330c 0x3ffb84ec 0x00000000 -0x3ffb8450: 0x00000000 0x3ffb8480 0x00000000 0x00000000 -0x3ffb8460: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb8470: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb8480: 0x00000000 0x00000000 0x3ffb848c 0x00000000 -0x3ffb8490: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb84a0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb84b0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb97a0: 0x00000000 0x00000000 0x3ffb97ac 0x00000000 +0x3ffb97b0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb97c0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb97d0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb97e0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb97f0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb9800: 0x00000000 0x00000000 0x00000000 +.coredump.tasks.data 0x3ffb8554 0x158 RW +0x3ffb8554: 0x3ffb83a0 0x3ffb84e0 0x000000c9 0x3ffb326c +0x3ffb8564: 0x3ffb981c 0x3ffb8554 0x3ffb3264 0x00000014 +0x3ffb8574: 0x3ffaf12c 0x3ffaf12c 0x3ffb8554 0x00000000 +0x3ffb8584: 0x00000005 0x3ffb7d50 0x5f646162 0x5f727470 +0x3ffb8594: 0x6b736174 0x0012ad00 0x7fffffff 0x3ffb854c +0x3ffb85a4: 0x00000005 0x00000000 0x00000000 0x00000000 +0x3ffb85b4: 0x00000000 0x3ffaef04 0x3ffaef6c 0x3ffaefd4 +0x3ffb85c4: 0x00000000 0x00000000 0x00000001 0x00000000 +0x3ffb85d4: 0x00000000 0x00000000 0x40001d48 0x00000000 +0x3ffb85e4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb85f4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8604: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8614: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8624: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8634: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8644: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8654: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8664: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8674: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8684: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8694: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb86a4: 0x00000000 0x3ffb0000 +.coredump.tasks.data 0x3ffb83a0 0x1ac RW +0x3ffb83a0: 0x40081ff4 0x4008427c 0x00060730 0x8008658a +0x3ffb83b0: 0x3ffb8460 0x00000000 0x000000c9 0x3ffb346c +0x3ffb83c0: 0x3ffb3460 0x3ffb4a74 0x00000000 0x8008427c +0x3ffb83d0: 0x3ffb8440 0x3ff000dc 0x00000001 0x3ffb17cc +0x3ffb83e0: 0x00060723 0x00000001 0x00000000 0x00000000 +0x3ffb83f0: 0x0000ffff 0x00000000 0x400014fd 0x4000150d +0x3ffb8400: 0xfffffff9 0x400821f8 0x00060723 0x400851c0 +0x3ffb8410: 0x3ffb4ec8 0x00000000 0x00000000 0x00000000 +0x3ffb8420: 0xb33fffff 0x00000000 0x00000000 0x00000000 +0x3ffb8430: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8440: 0x3f401528 0x00000018 0x3f402370 0x00000001 +0x3ffb8450: 0x800d4b77 0x3ffb8480 0x00000064 0x3ffb1618 +0x3ffb8460: 0x3ffb346c 0x3ffb3460 0x3ffb4a74 0x00000000 +0x3ffb8470: 0x80087cdc 0x3ffb84a0 0x00000000 0x00000000 +0x3ffb8480: 0x00060021 0x00060023 0x00000001 0x00060a23 +0x3ffb8490: 0x00000000 0x3ffb84c0 0x400d4b68 0x00000000 +0x3ffb84a0: 0x00060023 0x3ffb32e4 0x3ffb8554 0x00000000 +0x3ffb84b0: 0x00000000 0x3ffb84e0 0x00000000 0x00000000 0x3ffb84c0: 0x00000000 0x00000000 0x00000000 0x00000000 0x3ffb84d0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb84e0: 0x00000000 -.coredump.tasks.data 0x3ffaf868 0x158 RW -0x3ffaf868: 0x3ffaf680 0x3ffaf800 0x0801aae2 0x3ffb53b4 -0x3ffaf878: 0x3ffb3224 0x3ffaf868 0x3ffb321c 0x00000001 -0x3ffaf888: 0x3ffaf438 0x3ffaf438 0x3ffaf868 0x3ffaf430 -0x3ffaf898: 0x00000018 0x3ffaf464 0x30637069 0x316c2b00 -0x3ffaf8a8: 0xe19badb7 0x005a8f41 0x00000000 0x3ffaf860 -0x3ffaf8b8: 0x00000018 0x00000000 0x00000000 0x00000000 -0x3ffaf8c8: 0x00000000 0x3ffaef04 0x3ffaef6c 0x3ffaefd4 -0x3ffaf8d8: 0x00000000 0x00000000 0x00000001 0x00000000 -0x3ffaf8e8: 0x00000000 0x00000000 0x40001d48 0x00000000 -0x3ffaf8f8: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffaf908: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffaf918: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffaf928: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffaf938: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffaf948: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffaf958: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffaf968: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffaf978: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffaf988: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffaf998: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffaf9a8: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffaf9b8: 0x00000000 0x3ffa0000 -.coredump.tasks.data 0x3ffaf680 0x1e0 RW -0x3ffaf680: 0x40082100 0x40083e23 0x00060c30 0x80083e84 -0x3ffaf690: 0x3ffaf740 0x3ff000dc 0x00000001 0x3ffb17d8 -0x3ffaf6a0: 0x00060023 0x00000001 0x00000004 0x80083e0a -0x3ffaf6b0: 0x3ffaf720 0x3ffb31b8 0x00000000 0x00060a23 -0x3ffaf6c0: 0x00060a23 0x00000001 0x3f4002d0 0x00000000 -0x3ffaf6d0: 0x0000ffff 0x00000000 0x00000000 0x00000000 -0x3ffaf6e0: 0x00000000 0x40082304 0x00060a23 0x40084d60 -0x3ffaf6f0: 0x3ffac264 0x00000000 0x00000000 0x00000000 -0x3ffaf700: 0xb33fffff 0x00000000 0x00000000 0x00000000 -0x3ffaf710: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffaf720: 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 -0x3ffaf730: 0x800858f5 0x3ffaf760 0x00000000 0xffffffff -0x3ffaf740: 0x40082100 0x400875b4 0x00050030 0x00000000 -0x3ffaf750: 0x80082b2b 0x3ffaf780 0x3ffaf40c 0x3ffaf458 -0x3ffaf760: 0x3ffaf458 0x3ffe3b10 0x00000003 0x00060f23 -0x3ffaf770: 0x800875bc 0x3ffaf7c0 0x00000000 0x00000000 -0x3ffaf780: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffaf790: 0xffffffff 0x00000000 0x00000000 0x00000000 -0x3ffaf7a0: 0x00000001 0x00000001 0x00000000 0x00060f23 -0x3ffaf7b0: 0x00000000 0x3ffaf7e0 0x40082b0c 0x00000000 -0x3ffaf7c0: 0x00060f23 0x3ffb3488 0x3ffaf868 0x00000001 -0x3ffaf7d0: 0x00000000 0x3ffaf800 0x00000000 0x00000000 -0x3ffaf7e0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffaf7f0: 0x800e7fdf 0x3ffe3bc0 0x3ffb3214 0x00000000 -0x3ffaf800: 0x00000000 0x00000000 0x3ffaf80c 0x00000000 -0x3ffaf810: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffaf820: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffaf830: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffaf840: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffaf850: 0x00000000 0x00000000 0x00000000 0x00000000 -.coredump.tasks.data 0x3ffb53ac 0x158 RW -0x3ffb53ac: 0x3ffb51f0 0x3ffb5340 0x08ab1df6 0x3ffb4254 -0x3ffb53bc: 0x3ffaf870 0x3ffb53ac 0x3ffb321c 0x00000003 -0x3ffb53cc: 0xc560aeaf 0xbcc52b81 0x3ffb53ac 0x00000000 -0x3ffb53dc: 0x00000016 0x3ffb43a8 0x5f707365 0x656d6974 -0x3ffb53ec: 0x4f780072 0x00718fe6 0x00000000 0x3ffb53a4 -0x3ffb53fc: 0x00000016 0x00000000 0x00000000 0x00000000 -0x3ffb540c: 0x00000000 0x3ffaef04 0x3ffaef6c 0x3ffaefd4 -0x3ffb541c: 0x00000000 0x00000000 0x00000001 0x00000000 -0x3ffb542c: 0x00000000 0x00000000 0x40001d48 0x00000000 -0x3ffb543c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb544c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb545c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb546c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb547c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb548c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb549c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb54ac: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb54bc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb54cc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb54dc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb54ec: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb54fc: 0x00000000 0x3ffb0001 -.coredump.tasks.data 0x3ffb51f0 0x1b4 RW -0x3ffb51f0: 0x40082100 0x4000bff0 0x00060030 0x800877c2 -0x3ffb5200: 0x3ffb52b0 0x00000000 0x00060023 0x00060020 -0x3ffb5210: 0x00060023 0x00000001 0x00000000 0x80083e0a -0x3ffb5220: 0x3ffb5280 0x3ffb31c0 0x00000001 0x3ffaf7c0 -0x3ffb5230: 0x3ffaf780 0x3ffaf40c 0x3ffaf458 0x00000000 -0x3ffb5240: 0x0000ffff 0x00000000 0x00000000 0x00000000 -0x3ffb5250: 0x00000000 0x40082304 0x3ffaf780 0x40084d60 -0x3ffb5260: 0x3ffb1da4 0x00000000 0x00000000 0x00000000 -0x3ffb5270: 0xb33fffff 0x00000000 0x00000000 0x00000000 -0x3ffb5280: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb5290: 0x3ffb5340 0x00000000 0x00000000 0x00000000 -0x3ffb52a0: 0x8008702e 0x3ffb52c0 0x3ffb31b8 0x00000000 -0x3ffb52b0: 0x800d5148 0x3ffb52e0 0x3ffb1688 0xffffffff -0x3ffb52c0: 0x00000000 0x3ffaf7e0 0x40082b0c 0x00000000 -0x3ffb52d0: 0x800875bc 0x3ffb5300 0x00000000 0x00000000 -0x3ffb52e0: 0x00000001 0x00060023 0x00000001 0x3ffe3b90 -0x3ffb52f0: 0x00000000 0x3ffb5320 0x400d513c 0x00000000 -0x3ffb5300: 0x00060023 0x3ffb3460 0x3ffb53ac 0x00000000 -0x3ffb5310: 0x00000000 0x3ffb5340 0x00000000 0x00000000 -0x3ffb5320: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb5330: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb5340: 0x00000000 0x00000000 0x3ffb534c 0x00000000 -0x3ffb5350: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb5360: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb5370: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb5380: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb5390: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb53a0: 0x00000000 -.coredump.tasks.data 0x3ffb424c 0x158 RW -0x3ffb424c: 0x3ffafd00 0x3ffafe60 0x13a31b2f 0x3ffb3224 -0x3ffb425c: 0x3ffb53b4 0x3ffb424c 0x3ffb321c 0x00000001 -0x3ffb426c: 0x3ffafaa0 0x3ffafaa0 0x3ffb424c 0x3ffafa98 -0x3ffb427c: 0x00000018 0x3ffafacc 0x31637069 0xa4ab7a00 -0x3ffb428c: 0x73ac67fc 0x00ec157e 0x00000001 0x3ffafec8 -0x3ffb429c: 0x00000018 0x00000000 0x00000000 0x00000000 -0x3ffb42ac: 0x00000000 0x3ffaef04 0x3ffaef6c 0x3ffaefd4 -0x3ffb42bc: 0x00000000 0x00000000 0x00000001 0x00000000 -0x3ffb42cc: 0x00000000 0x00000000 0x40001d48 0x00000000 -0x3ffb42dc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb42ec: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb42fc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb430c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb431c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb432c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb433c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb434c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb435c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb436c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb437c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb438c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb439c: 0x00000000 0x3ffb0000 -.coredump.tasks.data 0x3ffafd00 0x1c8 RW -0x3ffafd00: 0x40082100 0x40083e84 0x00060a30 0x800858f5 -0x3ffafd10: 0x3ffafdc0 0x00000001 0xffffffff 0x3ffafac0 -0x3ffafd20: 0x3ffb6974 0x00000001 0x3ff4001c 0x80083e84 -0x3ffafd30: 0x3ffafda0 0x3ff000e0 0x00000001 0x3ffb17d8 -0x3ffafd40: 0x00060a23 0x00000001 0x00000001 0x00000000 -0x3ffafd50: 0x0000ffff 0x00000000 0x00000000 0x00000000 -0x3ffafd60: 0x00000000 0x40082304 0x00060a23 0x40084d60 -0x3ffafd70: 0x3ffac8c4 0x00000000 0x00000000 0x00000000 -0x3ffafd80: 0xb33fffff 0x00000000 0x00000000 0x00000000 -0x3ffafd90: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffafda0: 0xb33fffff 0x00000000 0x00000000 0x00000000 -0x3ffafdb0: 0x80082b2b 0x3ffafde0 0x3ffafa74 0x3ffafac0 -0x3ffafdc0: 0x13000044 0x00060a23 0x00000001 0x00000001 -0x3ffafdd0: 0x800875bc 0x3ffafe20 0x00000001 0x00000000 -0x3ffafde0: 0x00000000 0x00000001 0x00000001 0x3ff4001c -0x3ffafdf0: 0xffffffff 0x3ffafe20 0x00000001 0x40082bfc -0x3ffafe00: 0x00000001 0x00000001 0x00000000 0x00000001 -0x3ffafe10: 0x00000000 0x3ffafe40 0x40082b0c 0x00000001 -0x3ffafe20: 0x00000001 0x3ffb3488 0x3ffb424c 0x00000000 -0x3ffafe30: 0x00000000 0x3ffafe60 0x00000000 0x00000000 -0x3ffafe40: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffafe50: 0x80080f6f 0x3ffe7d60 0x00003e80 0x00fa04bd -0x3ffafe60: 0x00000000 0x00000000 0x3ffafe6c 0x00000000 -0x3ffafe70: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffafe80: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffafe90: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffafea0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffafeb0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffafec0: 0x00000000 0x00000000 +0x3ffb84e0: 0x00000000 0x00000000 0x3ffb84ec 0x00000000 +0x3ffb84f0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8500: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8510: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8520: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8530: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8540: 0x00000000 0x00000000 0x00000000 +.coredump.tasks.data 0x3ffafd24 0x158 RW +0x3ffafd24: 0x3ffb44a0 0x3ffb4600 0x510721ca 0x3ffb5bdc +0x3ffafd34: 0x3ffb31fc 0x3ffafd24 0x3ffb31f4 0x00000001 +0x3ffafd44: 0x3ffafcf8 0x3ffafcf8 0x3ffafd24 0x3ffafcf0 +0x3ffafd54: 0x00000018 0x3ffb426c 0x30637069 0x5bfe6700 +0x3ffafd64: 0xba248f8d 0x000e2283 0x00000000 0x3ffb4668 +0x3ffafd74: 0x00000018 0x00000000 0x00000000 0x00000000 +0x3ffafd84: 0x00000000 0x3ffaef04 0x3ffaef6c 0x3ffaefd4 +0x3ffafd94: 0x00000000 0x00000000 0x00000001 0x00000000 +0x3ffafda4: 0x00000000 0x00000000 0x40001d48 0x00000000 +0x3ffafdb4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffafdc4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffafdd4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffafde4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffafdf4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffafe04: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffafe14: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffafe24: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffafe34: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffafe44: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffafe54: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffafe64: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffafe74: 0x00000000 0x3ffa0000 +.coredump.tasks.data 0x3ffb44a0 0x1c8 RW +0x3ffb44a0: 0x40081ff4 0x4008427c 0x00060c30 0x80085e35 +0x3ffb44b0: 0x3ffb4560 0x00000000 0xffffffff 0x3ffafd18 +0x3ffb44c0: 0x3ffe3b10 0x00000003 0x00060f23 0x8008427c +0x3ffb44d0: 0x3ffb4540 0x3ff000dc 0x00000001 0x3ffb17cc +0x3ffb44e0: 0x00060023 0x00000001 0x00000004 0x00000000 +0x3ffb44f0: 0x0000ffff 0x00000000 0x00000000 0x00000000 +0x3ffb4500: 0x00000000 0x400821f8 0x00060023 0x400851c0 +0x3ffb4510: 0x3ffb0fe8 0x00000000 0x00000000 0x00000000 +0x3ffb4520: 0xb33fffff 0x00000000 0x00000000 0x00000000 +0x3ffb4530: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb4540: 0x40081ff4 0x40087cd4 0x00050030 0x00000000 +0x3ffb4550: 0x800826ef 0x3ffb4580 0x3ffafccc 0x3ffafd18 +0x3ffb4560: 0x00000000 0x400826c4 0x00000000 0x00000000 +0x3ffb4570: 0x80087cdc 0x3ffb45c0 0x00000000 0x00000000 +0x3ffb4580: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb4590: 0xffffffff 0x00000000 0x00000000 0x00000000 +0x3ffb45a0: 0x00000001 0x00000001 0x00000000 0x00060f23 +0x3ffb45b0: 0x00000000 0x3ffb45e0 0x400826c4 0x00000000 +0x3ffb45c0: 0x00060f23 0x3ffb3460 0x3ffafd24 0x00000001 +0x3ffb45d0: 0x00000000 0x3ffb4600 0x00000000 0x00000000 +0x3ffb45e0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb45f0: 0x800e8227 0x3ffe3bc0 0x3ffb31ec 0x00000000 +0x3ffb4600: 0x00000000 0x00000000 0x3ffb460c 0x00000000 +0x3ffb4610: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb4620: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb4630: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb4640: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb4650: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb4660: 0x00000000 0x00000000 +.coredump.tasks.data 0x3ffb5bd4 0x158 RW +0x3ffb5bd4: 0x3ffb5a10 0x3ffb5b60 0x42823477 0x3ffb4a7c +0x3ffb5be4: 0x3ffafd2c 0x3ffb5bd4 0x3ffb31f4 0x00000003 +0x3ffb5bf4: 0xaa6f31fe 0x597a4189 0x3ffb5bd4 0x00000000 +0x3ffb5c04: 0x00000016 0x3ffb4bd0 0x5f707365 0x656d6974 +0x3ffb5c14: 0x92820072 0x005e04d3 0x00000000 0x3ffb5bcc +0x3ffb5c24: 0x00000016 0x00000000 0x00000000 0x00000000 +0x3ffb5c34: 0x00000000 0x3ffaef04 0x3ffaef6c 0x3ffaefd4 +0x3ffb5c44: 0x00000000 0x00000000 0x00000001 0x00000000 +0x3ffb5c54: 0x00000000 0x00000000 0x40001d48 0x00000000 +0x3ffb5c64: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5c74: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5c84: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5c94: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5ca4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5cb4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5cc4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5cd4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5ce4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5cf4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5d04: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5d14: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5d24: 0x00000000 0x3ffb0001 +.coredump.tasks.data 0x3ffb5a10 0x1bc RW +0x3ffb5a10: 0x40081ff4 0x4000bff0 0x00060030 0x80087eee +0x3ffb5a20: 0x3ffb5ad0 0x00000000 0x00060023 0x00060020 +0x3ffb5a30: 0x00060023 0x00000001 0x00000000 0x80084255 +0x3ffb5a40: 0x3ffb5aa0 0x3ffb3198 0x00000000 0x3ffb45e0 +0x3ffb5a50: 0x3ffb45c0 0x00000000 0x00000000 0x00000000 +0x3ffb5a60: 0x0000ffff 0x00000000 0x00000000 0x00000000 +0x3ffb5a70: 0x00000000 0x400821f8 0x3ffb45c0 0x400851c0 +0x3ffb5a80: 0x3ffb2548 0x00000000 0x00000000 0x00000000 +0x3ffb5a90: 0xb33fffff 0x00000000 0x00000000 0x00000000 +0x3ffb5aa0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5ab0: 0x3ffb5b60 0x00000000 0x00000000 0x00000000 +0x3ffb5ac0: 0x80087672 0x3ffb5ae0 0x3ffb3190 0x00000000 +0x3ffb5ad0: 0x800d4557 0x3ffb5b00 0x00000000 0x00000001 +0x3ffb5ae0: 0x00000000 0x000000cf 0x3f400120 0x3ffe3b90 +0x3ffb5af0: 0x80087cdc 0x3ffb5b20 0x00000000 0x00000000 +0x3ffb5b00: 0x3ffb1618 0x00060023 0x00000001 0x00060c23 +0x3ffb5b10: 0x00000000 0x3ffb5b40 0x400d4548 0x00000000 +0x3ffb5b20: 0x00060023 0x3ffb3438 0x3ffb5bd4 0x00000000 +0x3ffb5b30: 0x00000000 0x3ffb5b60 0x00000000 0x00000000 +0x3ffb5b40: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5b50: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5b60: 0x00000000 0x00000000 0x3ffb5b6c 0x00000000 +0x3ffb5b70: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5b80: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5b90: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5ba0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5bb0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5bc0: 0x00000000 0x00000000 0x00000000 +.coredump.tasks.data 0x3ffb4a74 0x158 RW +0x3ffb4a74: 0x3ffb48a0 0x3ffb4a00 0xee08f4f4 0x3ffb31fc +0x3ffb4a84: 0x3ffb5bdc 0x3ffb4a74 0x3ffb31f4 0x00000001 +0x3ffb4a94: 0x3ffaff5c 0x3ffaff5c 0x3ffb4a74 0x3ffaff54 +0x3ffb4aa4: 0x00000018 0x3ffb4670 0x31637069 0x703f9300 +0x3ffb4ab4: 0x54d0a156 0x00de289a 0x00000001 0x3ffb4a6c +0x3ffb4ac4: 0x00000018 0x00000000 0x00000000 0x00000000 +0x3ffb4ad4: 0x00000000 0x3ffaef04 0x3ffaef6c 0x3ffaefd4 +0x3ffb4ae4: 0x00000000 0x00000000 0x00000001 0x00000000 +0x3ffb4af4: 0x00000000 0x00000000 0x40001d48 0x00000000 +0x3ffb4b04: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb4b14: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb4b24: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb4b34: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb4b44: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb4b54: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb4b64: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb4b74: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb4b84: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb4b94: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb4ba4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb4bb4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb4bc4: 0x00000000 0x3ffb0000 +.coredump.tasks.data 0x3ffb48a0 0x1cc RW +0x3ffb48a0: 0x40081ff4 0x4008427c 0x00060a30 0x80085e35 +0x3ffb48b0: 0x3ffb4960 0x00000001 0xffffffff 0x3ffaff7c +0x3ffb48c0: 0x3ffb6d3c 0x00000001 0x3ff4001c 0x8008427c +0x3ffb48d0: 0x3ffb4940 0x3ff000e0 0x00000001 0x3ffb17cc +0x3ffb48e0: 0x00060a23 0x00000001 0x00000001 0x00000000 +0x3ffb48f0: 0x0000ffff 0x00000000 0x00000000 0x00000000 +0x3ffb4900: 0x00000000 0x400821f8 0x00060a23 0x400851c0 +0x3ffb4910: 0x3ffb13e8 0x00000000 0x00000000 0x00000000 +0x3ffb4920: 0xb33fffff 0x00000000 0x00000000 0x00000000 +0x3ffb4930: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb4940: 0x800869be 0x3ffb4960 0x3ffb3190 0x13000044 +0x3ffb4950: 0x800826ef 0x3ffb4980 0x3ffaff30 0x3ffaff7c +0x3ffb4960: 0x13000044 0x00060a23 0x00000001 0x00000001 +0x3ffb4970: 0x80087cdc 0x3ffb49c0 0x00000001 0x00000000 +0x3ffb4980: 0x00000000 0x00000001 0x00000001 0x3ff4001c +0x3ffb4990: 0xffffffff 0x3ffb49c0 0x00000001 0x40082f60 +0x3ffb49a0: 0x00000001 0x00000001 0x00000000 0x00000001 +0x3ffb49b0: 0x00000000 0x3ffb49e0 0x400826c4 0x00000001 +0x3ffb49c0: 0x00000001 0x3ffb3460 0x3ffb4a74 0x00000000 +0x3ffb49d0: 0x00000000 0x3ffb4a00 0x00000000 0x00000000 +0x3ffb49e0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb49f0: 0x80080f33 0x3ffe7d60 0x00003e80 0x00fa00b7 +0x3ffb4a00: 0x00000000 0x00000000 0x3ffb4a0c 0x00000000 +0x3ffb4a10: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb4a20: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb4a30: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb4a40: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb4a50: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb4a60: 0x00000000 0x00000000 0x00000000 ===================== ESP32 CORE DUMP END ===================== =============================================================== diff --git a/components/espcoredump/test/esp32c3/coredump.b64 b/components/espcoredump/test/esp32c3/coredump.b64 index 4c361ab5ba..a28efd0200 100644 --- a/components/espcoredump/test/esp32c3/coredump.b64 +++ b/components/espcoredump/test/esp32c3/coredump.b64 @@ -2,281 +2,134 @@ NBQAAAABBQAAAAAAAAAAAAAAAAA= f0VMRgEBAQAAAAAAAAAAAAQA8wABAAAAAAAAADQAAAAAAAAAAAAAADQAIAAMACgA AAAAAA== BAAAALQBAAAAAAAAAAAAAGAEAABgBAAABgAAAAAAAAA= -AQAAABQGAACgEMk/oBDJP1QBAABUAQAABgAAAAAAAAA= -AQAAAGgHAADgDsk/4A7JP7ABAACwAQAABgAAAAAAAAA= -AQAAABgJAADsBsk/7AbJP1QBAABUAQAABgAAAAAAAAA= -AQAAAGwKAACQBck/kAXJP1ABAABQAQAABgAAAAAAAAA= -AQAAALwLAABA+cg/QPnIP1QBAABUAQAABgAAAAAAAAA= -AQAAABANAADw98g/8PfIP0ABAABAAQAABgAAAAAAAAA= -AQAAAFAOAAD8Gck//BnJP1QBAABUAQAABgAAAAAAAAA= -AQAAAKQPAACgGMk/oBjJP1ABAABQAQAABgAAAAAAAAA= -AQAAAPQQAABI4Mg/SODIP1QBAABUAQAABgAAAAAAAAA= -AQAAAEgSAADw3sg/8N7IP1ABAABQAQAABgAAAAAAAAA= +AQAAABQGAADAGsk/wBrJP1QBAABUAQAABgAAAAAAAAA= +AQAAAGgHAAAAGck/ABnJP7ABAACwAQAABgAAAAAAAAA= +AQAAABgJAAAMEck/DBHJP1QBAABUAQAABgAAAAAAAAA= +AQAAAGwKAACwD8k/sA/JP1ABAABQAQAABgAAAAAAAAA= +AQAAALwLAABgA8k/YAPJP1QBAABUAQAABgAAAAAAAAA= +AQAAABANAAAQAsk/EALJP0ABAABAAQAABgAAAAAAAAA= +AQAAAFAOAAAcJMk/HCTJP1QBAABUAQAABgAAAAAAAAA= +AQAAAKQPAADAIsk/wCLJP1ABAABQAQAABgAAAAAAAAA= +AQAAAPQQAABo6sg/aOrIP1QBAABUAQAABgAAAAAAAAA= +AQAAAEgSAAAQ6cg/EOnIP1ABAABQAQAABgAAAAAAAAA= BAAAAJgTAAAAAAAAAAAAAIQAAACEAAAABgAAAAAAAAA= CAAAAMwAAAABAAAA Q09SRQAAAAA= -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoBDJPwAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAymoAQsRqAEKAD8k/AJzIP4jPyD8AAAAA -3AvJPwAAAAAAAAAAAAAAACAAAAC4C8k/AAAAAAcAAACt////BQAAAHwtAEIAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwBrJPwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPFgAQjZYAEKgGck/AKbIP4ToyD8AAAAA +/BXJPwAAAAAAAAAAAAAAACAAAADYFck/AAAAAAcAAACt////BQAAADAuAEIAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAA CAAAAMwAAAABAAAA Q09SRQAAAAA= -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7AbJPwAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOCo4QJZZOEDcBck/dhU4QNjFyD8AAAAA -AAAAAAAAAABkAAAAAAAAAAEAAAABAAAAZAAAAAQAAAABAAAAAAAMYHwtAEIAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADBHJPwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAri04QBJgOED8D8k/VhY4QNTeyD8AAAAA +AAAAAAAAAABkAAAAAAAAAAEAAAABAAAAZAAAAAQAAAABAAAAAAAMYDAuAEIAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAA CAAAAMwAAAABAAAA Q09SRQAAAAA= -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQPnIPwAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqD8AQliyAEKlpaWlpaWlpSi4yD8AAAAA -AAAAAAAAAAAIAAAAAQAAAAEAAABP+Mg/AAAAAED5yD94v8g/AAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAPJPwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEsAAQm60AEKlpaWlpaWlpSTRyD8AAAAA +AAAAAAAAAAAIAAAAAQAAAAEAAABvAsk/AAAAAGADyT+kycg/AAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAA CAAAAMwAAAABAAAA Q09SRQAAAAA= -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/BnJPwAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOCo4QJZZOEDsGMk/dhU4QOjYyD8AAAAA -AAAAAAAAAABkAAAAAAAAAAEAAAABAAAAyAAAAAQAAAABAAAAAAAMYHwtAEIAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHCTJPwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAri04QBJgOEAMI8k/VhY4QOTxyD8AAAAA +AAAAAAAAAABkAAAAAAAAAAEAAAABAAAAyAAAAAQAAAABAAAAAAAMYDAuAEIAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAA CAAAAMwAAAABAAAA Q09SRQAAAAA= -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASODIPwAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANFg4QF5YOEClpaWlpaWlpTifyD8AAAAA -AAAAAAAAAAD/////AQAAAAEAAAABAAAAAAAAAAQAAAAAwMg/ACAMYAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaOrIPwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqF44QNJeOEClpaWlpaWlpTS4yD8AAAAA +AAAAAAAAAAAAAAAA/////wEAAAABAAAA/////wQAAAAA0Mg/ACAMYAAAAAAAAAAA +AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAA -QA/JP2QAAABEusg/RLrIP6AQyT88usg/EgAAAGIQEzEa0cbIoBDJPwAAAAAHAAAA -nAjJP3VuYWxpZ25lZF9wdHJfdAAAAAAAkBDJPwcAAAAAAAAAAAAAAAAAAAAAAAAA -DMvIP3TLyD/cy8g/AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAjM8AQgAAAAAAAAAA +YBnJP2QAAABUxMg/VMTIP8AayT9MxMg/EgAAAOfttLbngBoXwBrJPwAAAAAHAAAA +vBLJP3VuYWxpZ25lZF9wdHJfdAAAAAAAsBrJPwcAAAAAAAAAAAAAAAAAAAAAAAAA +LNXIP5TVyD/81cg/AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAYNEAQgAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AADJPw== -ymoAQsRqAEKAD8k/AJzIP4jPyD8AAAAA3AvJPwAAAAAAAAAAAAAAACAAAAC4C8k/ -AAAAAAcAAACt////BQAAAHwtAEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +PFgAQjZYAEKgGck/AKbIP4ToyD8AAAAA/BXJPwAAAAAAAAAAAAAAACAAAADYFck/ +AAAAAAcAAACt////BQAAADAuAEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACBGAAAAQA4QAcAAAAFAAAA -AAAAAAIAAAB8LQBCAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAA/BDJP3TLyD+oagBC -AAAAAAAAAAAAAAAAAwAAAAAAAADAD8k/AgAAAKhqAEKcFgI8HgAAADgFAjwDAAAA -AAAAAAAAAAAAAAAAAmsAQgAAAAAAAAAAAAAAAKpYOEAAAAAAAAAAAAAAAAAAAAAA -AAAAAKWlpaWlpaWlpaWlpRRkFCcHAQEBAQAAAAAAAAD////////vfwAAAAAAAMA/ -AAAAAAAAMEAAAAAAAADgPwAAAAAAAPg/YUNvY6eH0j+zyGCLKIrGP/t5n1ATRNM/ -AAAAAAAA8D8AAAAAAAAkQAAAAAAAABxAAAAAAAAAFEAAAAAAAABQQwCUyD9AGwAA -kAXJP2QAAAAcusg/HLrIP+wGyT8Uusg/FAAAANewOJfPktX/7AbJPwAAAAAFAAAA -6P7IP2JhZF9wdHJfdGFzawD5OAAAAAAA4AbJPwUAAAAAAAAAAAAAAAAAAAAAAAAA -DMvIP3TLyD/cy8g/AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAjM8AQgAAAAAAAAAA +AAAAAAIAAAAwLgBCAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAHBvJP5TVyD8aWABC +AAAAAAAAAAAAAAAAAwAAAAAAAADgGck/AgAAABpYAEJoEwI8HgAAADgFAjwDAAAA +AAAAAAAAAAAAAAAAdFgAQgAAAAAAAAAAAAAAAB5fOEAAAAAAAAAAAAAAAAAAAAAA +AAAAAKWlpaWlpaWlpaWlpRRkFCcHAQEBAQAAAP///////+9/AAAAAAAAwD8AAAAA +AAAwQAAAAAAAAOA/AAAAAAAA+D9hQ29jp4fSP7PIYIsoisY/+3mfUBNE0z8AAAAA +AADwPwAAAAAAACRAAAAAAAAAHEAAAAAAAAAUQAAAAAAAAFBDGAAAAAAAAAADelBM +sA/JP2QAAAAsxMg/LMTIPwwRyT8kxMg/FAAAAODyDOBCshDBDBHJPwAAAAAFAAAA +CAnJP2JhZF9wdHJfdGFzawDyMAAAAAAAABHJPwUAAAAAAAAAAAAAAAAAAAAAAAAA +LNXIP5TVyD/81cg/AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAYNEAQgAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AADJPw== -OCo4QJZZOEDcBck/dhU4QNjFyD8AAAAAAAAAAAAAAABkAAAAAAAAAAEAAAABAAAA -ZAAAAAQAAAABAAAAAAAMYHwtAEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGQAAACaRzhA -AAAAAAAAAAAAAAAAYmoAQgAAAAAAAAAAAAAAAKpYOEAAAAAAAAAAAAAAAAAAAAAA -AAAAAKWlpaWlpaWlpaWlpRRkFCcHAQEBAQAAAAAAAAD////////vfwAAAAAAAMA/ -AAAAAAAAMEAAAAAAAADgPwAAAAAAAPg/YUNvY6eH0j+zyGCLKIrGP/t5n1ATRNM/ -AAAAAAAA8D8AAAAAAAAkQAAAAAAAABxAAAAAAAAAFEAAAAAAAABQQwCUyD9AGwAA -8PfIP/TCyD+4ucg/uLnIP0D5yD+wucg/GQAAAIwKyNKJhBWKQPnIPwAAAAAAAAAA -PPPIP0lETEUADJCFIppzVXdfJQAAAAAAMPnIPwAAAAAAAAAAAAAAAAAAAAAAAAAA -DMvIP3TLyD/cy8g/AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAjM8AQgAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AADIPw== -qD8AQliyAEKlpaWlpaWlpSi4yD8AAAAAAAAAAAAAAAAIAAAAAQAAAAEAAABP+Mg/ -AAAAAED5yD94v8g/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACKRjhA -AAAAAAAAAAAAAAAAqlg4QAAAAAAAAAAAAAAAAAAAAAAAAAAApaWlpaWlpaWlpaWl -FGQUJwcBAQEBAAAAAAAAAP///////+9/AAAAAAAAwD8AAAAAAAAwQAAAAAAAAOA/ -AAAAAAAA+D9hQ29jp4fSP7PIYIsoisY/+3mfUBNE0z8AAAAAAADwPwAAAAAAACRA -AAAAAAAAHEAAAAAAAAAUQAAAAAAAAFBDAJTIP0AbAAA= -oBjJP8gAAACsu8g/rLvIP/wZyT+ku8g/DwAAAD3SLcsmQCJz/BnJPwAAAAAKAAAA -+BHJP2ZhaWxlZF9hc3NlcnRfdAAAAAAA8BnJPwoAAAAAAAAAAAAAAAAAAAAAAAAA -DMvIP3TLyD/cy8g/AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAjM8AQgAAAAAAAAAA +ri04QBJgOED8D8k/VhY4QNTeyD8AAAAAAAAAAAAAAABkAAAAAAAAAAEAAAABAAAA +ZAAAAAQAAAABAAAAAAAMYDAuAEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGQAAAAiTThA +AAAAAAAAAAAAAAAA1FcAQgAAAAAAAAAAAAAAAB5fOEAAAAAAAAAAAAAAAAAAAAAA +AAAAAKWlpaWlpaWlpaWlpRRkFCcHAQEBAQAAAP///////+9/AAAAAAAAwD8AAAAA +AAAwQAAAAAAAAOA/AAAAAAAA+D9hQ29jp4fSP7PIYIsoisY/+3mfUBNE0z8AAAAA +AADwPwAAAAAAACRAAAAAAAAAHEAAAAAAAAAUQAAAAAAAAFBDGAAAAAAAAAADelBM +EALJPxTNyD/Iw8g/yMPIP2ADyT/Aw8g/GQAAADvW+C6EV+igYAPJPwAAAAAAAAAA +XP3IP0lETEUAz6tiXF5dCfprbAAAAAAAUAPJPwAAAAAAAAAAAAAAAAAAAAAAAAAA +LNXIP5TVyD/81cg/AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAYNEAQgAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AADJPw== -OCo4QJZZOEDsGMk/dhU4QOjYyD8AAAAAAAAAAAAAAABkAAAAAAAAAAEAAAABAAAA -yAAAAAQAAAABAAAAAAAMYHwtAEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGQAAACaRzhA -AAAAAAAAAAAAAAAAVGkAQgAAAAAAAAAAAAAAAKpYOEAAAAAAAAAAAAAAAAAAAAAA -AAAAAKWlpaWlpaWlpaWlpRRkFCcHAQEBAQAAAAAAAAD////////vfwAAAAAAAMA/ -AAAAAAAAMEAAAAAAAADgPwAAAAAAAPg/YUNvY6eH0j+zyGCLKIrGP/t5n1ATRNM/ -AAAAAAAA8D8AAAAAAAAkQAAAAAAAABxAAAAAAAAAFEAAAAAAAABQQwCUyD9AGwAA -8N7IP/TCyD/ou8g/6LvIP0jgyD/gu8g/AwAAAMC3id9g1HkuSODIPwAAAAAWAAAA -RNDIP2VzcF90aW1lcgCr4jobxAAAAAAAQODIPxYAAAAAAAAAAAAAAAAAAAAAAAAA -DMvIP3TLyD/cy8g/AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAjM8AQgAAAAAAAAAA +EsAAQm60AEKlpaWlpaWlpSTRyD8AAAAAAAAAAAAAAAAIAAAAAQAAAAEAAABvAsk/ +AAAAAGADyT+kycg/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASTDhA +AAAAAAAAAAAAAAAAHl84QAAAAAAAAAAAAAAAAAAAAAAAAAAApaWlpaWlpaWlpaWl +FGQUJwcBAQEBAAAA////////738AAAAAAADAPwAAAAAAADBAAAAAAAAA4D8AAAAA +AAD4P2FDb2Onh9I/s8hgiyiKxj/7eZ9QE0TTPwAAAAAAAPA/AAAAAAAAJEAAAAAA +AAAcQAAAAAAAABRAAAAAAAAAUEMYAAAAAAAAAAN6UEw= +wCLJP8gAAAC8xcg/vMXIPxwkyT+0xcg/DwAAAHY27H+0w6sOHCTJPwAAAAAKAAAA +GBzJP2ZhaWxlZF9hc3NlcnRfdAAAAAAAECTJPwoAAAAAAAAAAAAAAAAAAAAAAAAA +LNXIP5TVyD/81cg/AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAYNEAQgAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AADJPw== +ri04QBJgOEAMI8k/VhY4QOTxyD8AAAAAAAAAAAAAAABkAAAAAAAAAAEAAAABAAAA +yAAAAAQAAAABAAAAAAAMYDAuAEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGQAAAAiTThA +AAAAAAAAAAAAAAAAvlYAQgAAAAAAAAAAAAAAAB5fOEAAAAAAAAAAAAAAAAAAAAAA +AAAAAKWlpaWlpaWlpaWlpRRkFCcHAQEBAQAAAP///////+9/AAAAAAAAwD8AAAAA +AAAwQAAAAAAAAOA/AAAAAAAA+D9hQ29jp4fSP7PIYIsoisY/+3mfUBNE0z8AAAAA +AADwPwAAAAAAACRAAAAAAAAAHEAAAAAAAAAUQAAAAAAAAFBDGAAAAAAAAAADelBM +EOnIPxTNyD/4xcg/+MXIP2jqyD/wxcg/AwAAADW8jtOEIaMTaOrIPwAAAAAWAAAA +ZNrIP2VzcF90aW1lcgA5wkMEhwAAAAAAYOrIPxYAAAAAAAAAAAAAAAAAAAAAAAAA +LNXIP5TVyD/81cg/AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAYNEAQgAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AQDIPw== -NFg4QF5YOEClpaWlpaWlpTifyD8AAAAAAAAAAAAAAAD/////AQAAAAEAAAABAAAA -AAAAAAQAAAAAwMg/ACAMYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAP////+eUzhA -AAAAAAAAAAAAAAAAomAAQgAAAAAAAAAAAAAAAKpYOEAAAAAAAAAAAAAAAAAAAAAA -AAAAAKWlpaWlpaWlpaWlpRRkFCcHAQEBAQAAAAAAAAD////////vfwAAAAAAAMA/ -AAAAAAAAMEAAAAAAAADgPwAAAAAAAPg/YUNvY6eH0j+zyGCLKIrGP/t5n1ATRNM/ -AAAAAAAA8D8AAAAAAAAkQAAAAAAAABxAAAAAAAAAFEAAAAAAAABQQwCUyD9AGwAA +qF44QNJeOEClpaWlpaWlpTS4yD8AAAAAAAAAAAAAAAAAAAAA/////wEAAAABAAAA +/////wQAAAAA0Mg/ACAMYAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA/////wAAAACuWThA +AAAAAAAAAAAAAAAAVkwAQgAAAAAAAAAAAAAAAB5fOEAAAAAAAAAAAAAAAAAAAAAA +AAAAAKWlpaWlpaWlpaWlpRRkFCcHAQEBAQAAAP///////+9/AAAAAAAAwD8AAAAA +AAAwQAAAAAAAAOA/AAAAAAAA+D9hQ29jp4fSP7PIYIsoisY/+3mfUBNE0z8AAAAA +AADwPwAAAAAAACRAAAAAAAAAHEAAAAAAAAAUQAAAAAAAAFBDGAAAAAAAAAADelBM FAAAAEgAAABKIAAA RVNQX0NPUkVfRFVNUF9JTkZPAAA= -AAEFAGYxYzNjMWYwMDQ3NmVlZTIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAEFADU1ZTdiYjQ5ZjkyMjQ4NjIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA DAAAAAQAAAClAgAA RVhUUkFfSU5GTwAA -oBDJPw== -vaoAKQ== - -AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAA -CAAAAEwCAAABAAAA -Q09SRQAAAAA= -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqCL8PwAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM3cCQCACBgAAAAAAAAAAAAAAAAAbAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKdfCIBAIvw/ -ZAAAAPjP+z8hAAYAUOv7PyMLBgBZAAAAM3cCgCAi/D8AAAAAZAAAAPTt+z8QDPw/ -AAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAA -CAAAAEwCAAABAAAA -Q09SRQAAAAA= -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBT8PwAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7lQJQCAFBgAAAAAAAAAAAAAAAAAeAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADadCICwE/w/ -AAAAAAEAAAABAAAAAQAAgCMABgAAAAAAHqIIgIAT/D8AAAAAgKQBQCAABgAAwABg -AAAAAEsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAA -CAAAAEwCAAABAAAA -Q09SRQAAAAA= -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuDX8PwAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM3cCQCAHBgAAAAAAAAAAAAAAAAAWAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO9eCIBQNfw/ -ZAAAAPjP+z8hAAYAkCv8PzDR+z9kAAAAM3cCgDA1/D8AAAAAyAAAAPTt+z8QDPw/ -AAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAA -CAAAAEwCAAABAAAA -Q09SRQAAAAA= -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaP35PwAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1KgBQCAOBgAAAAAAAAAAAAAAAAAKAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAByJAoDQ/Pk/ -Iw4GAAAAAAAgDgYAcN7/P8De/z8EAAAAOVMCgKD8+T8w0fs/AAAAANDi/z+w4v8/ -AIBAPyACAD8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAA -YCv8P2QAAACU7Ps/lOz7P1ws/D+M7Ps/EgAAALV8Zvp19PO8XCz8PwAAAAAHAAAA -WCT8P3VuYWxpZ25lZF9wdHJfdAAAAAAAVCz8PwcAAAAAAAAAAAAAAAAAAAAAAAAA -LOj5P5To+T/86Pk/AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAgKQBQAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAD8Pw== -776t3glgCEAwDQYA5F8IgIAr/D8CAAAAzCv8P8Ar/D8AAAAAlOj5PwAAAAAFAAAA -rf///yAAAAC4LPw/t+v5P4AAAAABAAAAAAAAABkAAAAdAAAABQAAALfr+T+AAAAA -PT4CQDT1+z8o6vk/AAAAALfr+T+AAAAAAQAAAAAAAADkXwiAsCv8PwEAAACU6Pk/ -AwAAADDR+z8BAAAAAQAAAMAr/D8AAAAAlOj5PwAAAAAsYAiA4Cv8PwoAAAD4z/s/ -AwAAAB4AAABcIwA/AQAAAPTt+z8QDPw/AAgAAAAAAADshwKAECz8PwAAAAAAAAAA -AwAAABAs/D8AAAAAAAAAACEABgDgIfw/MNH7P2QAAAAAAAAAMCz8PxRgCEAAAAAA -IwAGAFDr+z8jDAYAAQAAAAAAAABQLPw/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAA= -sCH8P2QAAABs7Ps/bOz7P6gi/D9k7Ps/FAAAAOaYhZH9xHrvqCL8PwAAAAAFAAAA -pBr8P2JhZF9wdHJfdGFzawCjEAAAAAAAoCL8PwUAAAAAAAAAAAAAAAAAAAAAAAAA -LOj5P5To+T/86Pk/AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAgKQBQAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAD8Pw== -mD4CQDN3AkAwAgYAp18IgEAi/D9kAAAA+M/7PyEABgBQ6/s/IwsGAFkAAAAzdwKA -ICL8PwAAAABkAAAA9O37PxAM/D8ACAAAAAAAABsAAAD//wAAAAAAAAA/AkAQDPw/ -cGYCQITr+z8AAAAAAAAAAEAM/D8QDPw/AAgAAAAAAADshwKAYCL8PwAAAAAAAAAA -IQAGAFDr+z8jCwYAWQAAAAAAAACAIvw/mF8IQAAAAAAjAAYAUOv7PyMHBgAwC/w/ -AAAAAKAi/D8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -IBP8PxT2+z8I7Ps/COz7P0AU/D8A7Ps/GQAAAI4HwjbIC/+pQBT8PwAAAAAAAAAA -PA78P0lETEUA7gxhMfMFcqcHvwAAAAAAOBT8PwAAAAAAAAAAAAAAAAAAAAAAAAAA -LOj5P5To+T/86Pk/AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAgKQBQAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAD8Pw== -mD4CQO5UCUAwBQYANp0IgLAT/D8AAAAAAQAAAAEAAAABAACAIwAGAAAAAAAeogiA -gBP8PwAAAACApAFAIAAGAADAAGAAAAAASwAAAB4AAAD//wAAAAAAAAA/AkAAwABg -cGYCQBTd+z+lpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaVFdgKA0BP8PwgAAAABAAAA -MBT8PwAAAAAAAAAAAAAAAOyHAoDwE/w/AAAAAAAAAAAhAAYAEAz8PzDR+z8BAAAA -AAAAABAU/D88dgJAAAAAACMABgAwDPw/WABMPwEAAAAAAAAAMBT8PwAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== -wDT8P8gAAAD06/s/9Ov7P7g1/D/s6/s/DwAAAHjELjhoP6d7uDX8PwAAAAAKAAAA -tC38P2ZhaWxlZF9hc3NlcnRfdAAAAAAAsDX8PwoAAAAAAAAAAAAAAAAAAAAAAAAA -LOj5P5To+T/86Pk/AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAgKQBQAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAD8Pw== -mD4CQDN3AkAwBwYA714IgFA1/D9kAAAA+M/7PyEABgCQK/w/MNH7P2QAAAAzdwKA -MDX8PwAAAADIAAAA9O37PxAM/D8ACAAAAAAAABYAAAD//wAAAAAAAAA/AkAQDPw/ -cGYCQJT++z8AAAAAAAAAAPTt+z8QDPw/AAgAAAAAAADshwKAcDX8PwAAAAAAAAAA -IQAGAJAr/D8w0fs/ZAAAAAAAAACQNfw/4F4IQAAAAAAjAAYAUOv7PyMBBgABAAAA -AAAAALA1/D8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -QPz5PxTg+T+Y6/s/mOv7P2j9+T+Q6/s/AwAAAIsLh01IIfbtaP35PwAAAAAWAAAA -ZO35P2VzcF90aW1lcgCSDgdicwAAAAAAYP35PxYAAAAAAAAAAAAAAAAAAAAAAAAA -LOj5P5To+T/86Pk/AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAgKQBQAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AQD5Pw== -mD4CQNSoAUAwDgYAHIkCgND8+T8jDgYAAAAAACAOBgBw3v8/wN7/PwQAAAA5UwKA -oPz5PzDR+z8AAAAA0OL/P7Di/z8AgEA/IAIAPwoAAAD//wAAAAAAAAA/AkCw4v8/ -cGYCQETG+T+lpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaUmggKA4Pz5P/jP+z8AAAAA -bFgIgAD9+T9o/vk/+M/7PwAAAADQ4f8/IwEGAAAAAADshwKAIP35PwAAAAAAAAAA -AQAAAPDh/z8jAQYAAAAAAAAAAABA/fk/YFgIQAAAAAAjAQYAWOv7PwAAAAABAAAA -AAAAAGD9+T8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3WwmAgOL/P4jr+z8AAAAA -FAAAAEgAAABKIAAA -RVNQX0NPUkVfRFVNUF9JTkZPAAA= -AAECADE5YmNmZTg5Y2RjMmNmNTYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -DAAAAJQAAAClAgAA -RVhUUkFfSU5GTwAA -XCz8P+gAAAAdAAAA7gAAAAUAAADCAAAAAAAAAMMAAAAAAAAAxAAAAAAAAADFAAAA -AAAAAMYAAAAAAAAAsQAAAKOaCECyAAAAAAAAALMAAAAAAAAAtAAAAAAAAAC1AAAA -AAAAALYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAA== -K7mejA== +wBrJPw== +c/sxtw== diff --git a/components/espcoredump/test/esp32c3/expected_output b/components/espcoredump/test/esp32c3/expected_output index bf0a61c237..4970d3b51a 100644 --- a/components/espcoredump/test/esp32c3/expected_output +++ b/components/espcoredump/test/esp32c3/expected_output @@ -2,25 +2,25 @@ espcoredump.py v0.4-dev =============================================================== ==================== ESP32 CORE DUMP START ==================== -Crashed task handle: 0x3fc910a0, name: 'unaligned_ptr_t', GDB name: 'process 1070141600' +Crashed task handle: 0x3fc91ac0, name: 'unaligned_ptr_t', GDB name: 'process 1070144192' ================== CURRENT THREAD REGISTERS =================== -ra 0x42006ac4 0x42006ac4 -sp 0x3fc90f80 0x3fc90f80 -gp 0x3fc89c00 0x3fc89c00 <__c.5475+36> -tp 0x3fc8cf88 0x3fc8cf88 +ra 0x42005836 0x42005836 +sp 0x3fc919a0 0x3fc919a0 +gp 0x3fc8a600 0x3fc8a600 <__c.5454+36> +tp 0x3fc8e884 0x3fc8e884 t0 0x0 0 -t1 0x3fc90bdc 1070140380 +t1 0x3fc915fc 1070142972 t2 0x0 0 fp 0x0 0x0 s1 0x0 0 a0 0x20 32 -a1 0x3fc90bb8 1070140344 +a1 0x3fc915d8 1070142936 a2 0x0 0 a3 0x7 7 a4 0xffffffad -83 a5 0x5 5 -a6 0x42002d7c 1107307900 +a6 0x42002e30 1107308080 a7 0x0 0 s2 0x0 0 s3 0x0 0 @@ -36,45 +36,54 @@ t3 0x0 0 t4 0x0 0 t5 0x0 0 t6 0x0 0 -pc 0x42006aca 0x42006aca +pc 0x4200583c 0x4200583c ==================== CURRENT THREAD STACK ===================== -#0 0x42006aca in UnityPrintNumberUnsigned (number=32) at /builds/espressif/esp-idf/components/unity/unity/src/unity.c:196 -#1 0x00000003 in ?? () +#0 0x4200583c in recur_func () at ../main/test_core_dump.c:70 +#1 0x4200581a in recur_func () at ../main/test_core_dump.c:63 +#2 0x4200581a in recur_func () at ../main/test_core_dump.c:63 +#3 0x42005874 in unaligned_ptr_task (pvParameter=) at ../main/test_core_dump.c:80 +#4 0x40385f1e in vPortEnterCritical () at /builds/espressif/esp-idf/components/freertos/port/riscv/port.c:129 +#5 0x00000000 in ?? () +Backtrace stopped: frame did not save the PC ======================== THREADS INFO ========================= Id Target Id Frame -* 1 process 1070141600 0x42006aca in UnityPrintNumberUnsigned (number=32) at /builds/espressif/esp-idf/components/unity/unity/src/unity.c:196 - 2 process 1070139116 0x40382a38 in esp_crosscore_int_send_yield (core_id=core_id@entry=0) at /builds/espressif/esp-idf/components/esp_system/crosscore_int.c:144 - 3 process 1070135616 0x42003fa8 in cpu_ll_waiti () at ../../../hal/esp32c3/include/hal/cpu_ll.h:158 - 4 process 1070143996 0x40382a38 in esp_crosscore_int_send_yield (core_id=core_id@entry=0) at /builds/espressif/esp-idf/components/esp_system/crosscore_int.c:144 - 5 process 1070129224 0x40385834 in vPortClearInterruptMask (mask=1) at /builds/espressif/esp-idf/components/freertos/port/riscv/port.c:199 +* 1 process 1070144192 0x4200583c in recur_func () at ../main/test_core_dump.c:70 + 2 process 1070141708 0x40382dae in esp_crosscore_int_send_yield (core_id=core_id@entry=0) at /builds/espressif/esp-idf/components/esp_system/crosscore_int.c:144 + 3 process 1070138208 0x4200c012 in esp_pm_impl_waiti () at ../../../hal/esp32c3/include/hal/cpu_ll.h:163 + 4 process 1070146588 0x40382dae in esp_crosscore_int_send_yield (core_id=core_id@entry=0) at /builds/espressif/esp-idf/components/esp_system/crosscore_int.c:144 + 5 process 1070131816 0x40385ea8 in vPortClearInterruptMask (mask=1) at /builds/espressif/esp-idf/components/freertos/port/riscv/port.c:177 -==================== THREAD 1 (TCB: 0x3fc910a0, name: 'unaligned_ptr_t') ===================== -#0 0x42006aca in UnityPrintNumberUnsigned (number=32) at /builds/espressif/esp-idf/components/unity/unity/src/unity.c:196 -#1 0x00000003 in ?? () +==================== THREAD 1 (TCB: 0x3fc91ac0, name: 'unaligned_ptr_t') ===================== +#0 0x4200583c in recur_func () at ../main/test_core_dump.c:70 +#1 0x4200581a in recur_func () at ../main/test_core_dump.c:63 +#2 0x4200581a in recur_func () at ../main/test_core_dump.c:63 +#3 0x42005874 in unaligned_ptr_task (pvParameter=) at ../main/test_core_dump.c:80 +#4 0x40385f1e in vPortEnterCritical () at /builds/espressif/esp-idf/components/freertos/port/riscv/port.c:129 +#5 0x00000000 in ?? () +Backtrace stopped: frame did not save the PC -==================== THREAD 2 (TCB: 0x3fc906ec, name: 'bad_ptr_task') ===================== -#0 0x40382a38 in esp_crosscore_int_send_yield (core_id=core_id@entry=0) at /builds/espressif/esp-idf/components/esp_system/crosscore_int.c:144 -#1 0x40385996 in vPortYield () at /builds/espressif/esp-idf/components/freertos/port/riscv/port.c:360 +==================== THREAD 2 (TCB: 0x3fc9110c, name: 'bad_ptr_task') ===================== +#0 0x40382dae in esp_crosscore_int_send_yield (core_id=core_id@entry=0) at /builds/espressif/esp-idf/components/esp_system/crosscore_int.c:144 +#1 0x40386012 in vPortYield () at /builds/espressif/esp-idf/components/freertos/port/riscv/port.c:316 #2 0x00000000 in ?? () Backtrace stopped: frame did not save the PC -==================== THREAD 3 (TCB: 0x3fc8f940, name: 'IDLE') ===================== -#0 0x42003fa8 in cpu_ll_waiti () at ../../../hal/esp32c3/include/hal/cpu_ll.h:158 -#1 esp_pm_impl_waiti () at /builds/espressif/esp-idf/components/esp_pm/pm_impl.c:841 -#2 0x4200b258 in esp_register_freertos_tick_hook_for_cpu (new_tick_cb=0x1, cpuid=1070135375) at /builds/espressif/esp-idf/components/esp_system/freertos_hooks.c:90 +==================== THREAD 3 (TCB: 0x3fc90360, name: 'IDLE') ===================== +#0 0x4200c012 in esp_pm_impl_waiti () at ../../../hal/esp32c3/include/hal/cpu_ll.h:163 +#1 0x4200b46e in esp_vApplicationIdleHook () at /builds/espressif/esp-idf/components/esp_system/freertos_hooks.c:63 Backtrace stopped: Cannot access memory at address 0xa5a5a5b1 -==================== THREAD 4 (TCB: 0x3fc919fc, name: 'failed_assert_t') ===================== -#0 0x40382a38 in esp_crosscore_int_send_yield (core_id=core_id@entry=0) at /builds/espressif/esp-idf/components/esp_system/crosscore_int.c:144 -#1 0x40385996 in vPortYield () at /builds/espressif/esp-idf/components/freertos/port/riscv/port.c:360 +==================== THREAD 4 (TCB: 0x3fc9241c, name: 'failed_assert_t') ===================== +#0 0x40382dae in esp_crosscore_int_send_yield (core_id=core_id@entry=0) at /builds/espressif/esp-idf/components/esp_system/crosscore_int.c:144 +#1 0x40386012 in vPortYield () at /builds/espressif/esp-idf/components/freertos/port/riscv/port.c:316 #2 0x00000000 in ?? () Backtrace stopped: frame did not save the PC -==================== THREAD 5 (TCB: 0x3fc8e048, name: 'esp_timer') ===================== -#0 0x40385834 in vPortClearInterruptMask (mask=1) at /builds/espressif/esp-idf/components/freertos/port/riscv/port.c:199 -#1 0x4038585e in vPortExitCritical () at /builds/espressif/esp-idf/components/freertos/port/riscv/port.c:139 +==================== THREAD 5 (TCB: 0x3fc8ea68, name: 'esp_timer') ===================== +#0 0x40385ea8 in vPortClearInterruptMask (mask=1) at /builds/espressif/esp-idf/components/freertos/port/riscv/port.c:177 +#1 0x40385ed2 in vPortExitCritical () at /builds/espressif/esp-idf/components/freertos/port/riscv/port.c:138 Backtrace stopped: Cannot access memory at address 0xa5a5a5b1 @@ -86,258 +95,259 @@ Name Address Size Attrs .rtc.data 0x50000000 0x10 RW A .rtc_noinit 0x50000010 0x0 RW .rtc.force_slow 0x50000010 0x0 RW -.iram0.text 0x40380000 0x939a R XA -.dram0.data 0x3fc89400 0x1b40 RW A -.noinit 0x3fc8af40 0x0 RW -.flash.text 0x42000020 0x1ada0 R XA +.iram0.text 0x40380000 0x9c7e R XA +.dram0.data 0x3fc89e00 0x1b5c RW A +.noinit 0x3fc8b95c 0x0 RW +.flash.text 0x42000020 0x1b028 R XA .flash.appdesc 0x3c020020 0x100 R A -.flash.rodata 0x3c020120 0x3218 RW A -.eh_frame 0x3c023338 0x728 R A -.flash.rodata_noload 0x3c023a60 0x0 RW -.iram0.data 0x40389400 0x0 RW -.iram0.bss 0x40389400 0x0 RW -.coredump.tasks.data 0x3fc910a0 0x154 RW -.coredump.tasks.data 0x3fc90ee0 0x1b0 RW -.coredump.tasks.data 0x3fc906ec 0x154 RW -.coredump.tasks.data 0x3fc90590 0x150 RW -.coredump.tasks.data 0x3fc8f940 0x154 RW -.coredump.tasks.data 0x3fc8f7f0 0x140 RW -.coredump.tasks.data 0x3fc919fc 0x154 RW -.coredump.tasks.data 0x3fc918a0 0x150 RW -.coredump.tasks.data 0x3fc8e048 0x154 RW -.coredump.tasks.data 0x3fc8def0 0x150 RW +.flash.rodata 0x3c020120 0x3220 RW A +.eh_frame 0x3c023340 0x728 R A +.flash.rodata_noload 0x3c023a68 0x0 RW +.iram0.data 0x40389e00 0x0 RW +.iram0.bss 0x40389e00 0x0 RW +.dram0.heap_start 0x3fc8cd00 0x0 RW +.coredump.tasks.data 0x3fc91ac0 0x154 RW +.coredump.tasks.data 0x3fc91900 0x1b0 RW +.coredump.tasks.data 0x3fc9110c 0x154 RW +.coredump.tasks.data 0x3fc90fb0 0x150 RW +.coredump.tasks.data 0x3fc90360 0x154 RW +.coredump.tasks.data 0x3fc90210 0x140 RW +.coredump.tasks.data 0x3fc9241c 0x154 RW +.coredump.tasks.data 0x3fc922c0 0x150 RW +.coredump.tasks.data 0x3fc8ea68 0x154 RW +.coredump.tasks.data 0x3fc8e910 0x150 RW ====================== CORE DUMP MEMORY CONTENTS ======================== -.coredump.tasks.data 0x3fc910a0 0x154 RW -0x3fc910a0: 0x3fc90f40 0x00000064 0x3fc8ba44 0x3fc8ba44 -0x3fc910b0: 0x3fc910a0 0x3fc8ba3c 0x00000012 0x31131062 -0x3fc910c0: 0xc8c6d11a 0x3fc910a0 0x00000000 0x00000007 -0x3fc910d0: 0x3fc9089c 0x6c616e75 0x656e6769 0x74705f64 -0x3fc910e0: 0x00745f72 0x00000000 0x3fc91090 0x00000007 -0x3fc910f0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc91100: 0x3fc8cb0c 0x3fc8cb74 0x3fc8cbdc 0x00000000 -0x3fc91110: 0x00000000 0x00000001 0x00000000 0x00000000 -0x3fc91120: 0x00000000 0x4200cf8c 0x00000000 0x00000000 -0x3fc91130: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc91140: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc91150: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc91160: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc91170: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc91180: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc91190: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc911a0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc911b0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc911c0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc911d0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc911e0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc911f0: 0x3fc90000 -.coredump.tasks.data 0x3fc90ee0 0x1b0 RW -0x3fc90ee0: 0x42006aca 0x42006ac4 0x3fc90f80 0x3fc89c00 -0x3fc90ef0: 0x3fc8cf88 0x00000000 0x3fc90bdc 0x00000000 -0x3fc90f00: 0x00000000 0x00000000 0x00000020 0x3fc90bb8 -0x3fc90f10: 0x00000000 0x00000007 0xffffffad 0x00000005 -0x3fc90f20: 0x42002d7c 0x00000000 0x00000000 0x00000000 -0x3fc90f30: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc90f40: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc90f50: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc90f60: 0x00001881 0x40380001 0x00000007 0x00000005 -0x3fc90f70: 0x00000000 0x00000002 0x42002d7c 0x00000000 -0x3fc90f80: 0x00000000 0x00000000 0x00000000 0x00000003 -0x3fc90f90: 0x00000000 0x3fc910fc 0x3fc8cb74 0x42006aa8 -0x3fc90fa0: 0x00000000 0x00000000 0x00000000 0x00000003 -0x3fc90fb0: 0x00000000 0x3fc90fc0 0x00000002 0x42006aa8 -0x3fc90fc0: 0x3c02169c 0x0000001e 0x3c020538 0x00000003 -0x3fc90fd0: 0x00000000 0x00000000 0x00000000 0x42006b02 -0x3fc90fe0: 0x00000000 0x00000000 0x00000000 0x403858aa -0x3fc90ff0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc91000: 0x00000000 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 -0x3fc91010: 0x27146414 0x01010107 0x00000001 0x00000000 -0x3fc91020: 0xffffffff 0x7fefffff 0x00000000 0x3fc00000 -0x3fc91030: 0x00000000 0x40300000 0x00000000 0x3fe00000 -0x3fc91040: 0x00000000 0x3ff80000 0x636f4361 0x3fd287a7 -0x3fc91050: 0x8b60c8b3 0x3fc68a28 0x509f79fb 0x3fd34413 -0x3fc91060: 0x00000000 0x3ff00000 0x00000000 0x40240000 -0x3fc91070: 0x00000000 0x401c0000 0x00000000 0x40140000 -0x3fc91080: 0x00000000 0x43500000 0x3fc89400 0x00001b40 -.coredump.tasks.data 0x3fc906ec 0x154 RW -0x3fc906ec: 0x3fc90590 0x00000064 0x3fc8ba1c 0x3fc8ba1c -0x3fc906fc: 0x3fc906ec 0x3fc8ba14 0x00000014 0x9738b0d7 -0x3fc9070c: 0xffd592cf 0x3fc906ec 0x00000000 0x00000005 -0x3fc9071c: 0x3fc8fee8 0x5f646162 0x5f727470 0x6b736174 -0x3fc9072c: 0x0038f900 0x00000000 0x3fc906e0 0x00000005 -0x3fc9073c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc9074c: 0x3fc8cb0c 0x3fc8cb74 0x3fc8cbdc 0x00000000 -0x3fc9075c: 0x00000000 0x00000001 0x00000000 0x00000000 -0x3fc9076c: 0x00000000 0x4200cf8c 0x00000000 0x00000000 -0x3fc9077c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc9078c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc9079c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc907ac: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc907bc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc907cc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc907dc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc907ec: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc907fc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc9080c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc9081c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc9082c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc9083c: 0x3fc90000 -.coredump.tasks.data 0x3fc90590 0x150 RW -0x3fc90590: 0x40382a38 0x40385996 0x3fc905dc 0x40381576 -0x3fc905a0: 0x3fc8c5d8 0x00000000 0x00000000 0x00000000 -0x3fc905b0: 0x00000064 0x00000000 0x00000001 0x00000001 -0x3fc905c0: 0x00000064 0x00000004 0x00000001 0x600c0000 -0x3fc905d0: 0x42002d7c 0x00000000 0x00000000 0x00000000 -0x3fc905e0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc905f0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc90600: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc90610: 0x00000000 0x00000000 0x00000064 0x4038479a -0x3fc90620: 0x00000000 0x00000000 0x00000000 0x42006a62 -0x3fc90630: 0x00000000 0x00000000 0x00000000 0x403858aa -0x3fc90640: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc90650: 0x00000000 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 -0x3fc90660: 0x27146414 0x01010107 0x00000001 0x00000000 -0x3fc90670: 0xffffffff 0x7fefffff 0x00000000 0x3fc00000 -0x3fc90680: 0x00000000 0x40300000 0x00000000 0x3fe00000 -0x3fc90690: 0x00000000 0x3ff80000 0x636f4361 0x3fd287a7 -0x3fc906a0: 0x8b60c8b3 0x3fc68a28 0x509f79fb 0x3fd34413 -0x3fc906b0: 0x00000000 0x3ff00000 0x00000000 0x40240000 -0x3fc906c0: 0x00000000 0x401c0000 0x00000000 0x40140000 -0x3fc906d0: 0x00000000 0x43500000 0x3fc89400 0x00001b40 -.coredump.tasks.data 0x3fc8f940 0x154 RW -0x3fc8f940: 0x3fc8f7f0 0x3fc8c2f4 0x3fc8b9b8 0x3fc8b9b8 -0x3fc8f950: 0x3fc8f940 0x3fc8b9b0 0x00000019 0xd2c80a8c -0x3fc8f960: 0x8a158489 0x3fc8f940 0x00000000 0x00000000 -0x3fc8f970: 0x3fc8f33c 0x454c4449 0x85900c00 0x55739a22 -0x3fc8f980: 0x00255f77 0x00000000 0x3fc8f930 0x00000000 -0x3fc8f990: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8f9a0: 0x3fc8cb0c 0x3fc8cb74 0x3fc8cbdc 0x00000000 -0x3fc8f9b0: 0x00000000 0x00000001 0x00000000 0x00000000 -0x3fc8f9c0: 0x00000000 0x4200cf8c 0x00000000 0x00000000 -0x3fc8f9d0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8f9e0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8f9f0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8fa00: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8fa10: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8fa20: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8fa30: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8fa40: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8fa50: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8fa60: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8fa70: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8fa80: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8fa90: 0x3fc80000 -.coredump.tasks.data 0x3fc8f7f0 0x140 RW -0x3fc8f7f0: 0x42003fa8 0x4200b258 0xa5a5a5a5 0xa5a5a5a5 -0x3fc8f800: 0x3fc8b828 0x00000000 0x00000000 0x00000000 -0x3fc8f810: 0x00000008 0x00000001 0x00000001 0x3fc8f84f -0x3fc8f820: 0x00000000 0x3fc8f940 0x3fc8bf78 0x00000000 -0x3fc8f830: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8f840: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8f850: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8f860: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8f870: 0x00000000 0x00000000 0x00000000 0x4038468a -0x3fc8f880: 0x00000000 0x00000000 0x00000000 0x403858aa -0x3fc8f890: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8f8a0: 0x00000000 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 -0x3fc8f8b0: 0x27146414 0x01010107 0x00000001 0x00000000 -0x3fc8f8c0: 0xffffffff 0x7fefffff 0x00000000 0x3fc00000 -0x3fc8f8d0: 0x00000000 0x40300000 0x00000000 0x3fe00000 -0x3fc8f8e0: 0x00000000 0x3ff80000 0x636f4361 0x3fd287a7 -0x3fc8f8f0: 0x8b60c8b3 0x3fc68a28 0x509f79fb 0x3fd34413 -0x3fc8f900: 0x00000000 0x3ff00000 0x00000000 0x40240000 -0x3fc8f910: 0x00000000 0x401c0000 0x00000000 0x40140000 -0x3fc8f920: 0x00000000 0x43500000 0x3fc89400 0x00001b40 -.coredump.tasks.data 0x3fc919fc 0x154 RW -0x3fc919fc: 0x3fc918a0 0x000000c8 0x3fc8bbac 0x3fc8bbac -0x3fc91a0c: 0x3fc919fc 0x3fc8bba4 0x0000000f 0xcb2dd23d -0x3fc91a1c: 0x73224026 0x3fc919fc 0x00000000 0x0000000a -0x3fc91a2c: 0x3fc911f8 0x6c696166 0x615f6465 0x72657373 -0x3fc91a3c: 0x00745f74 0x00000000 0x3fc919f0 0x0000000a -0x3fc91a4c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc91a5c: 0x3fc8cb0c 0x3fc8cb74 0x3fc8cbdc 0x00000000 -0x3fc91a6c: 0x00000000 0x00000001 0x00000000 0x00000000 -0x3fc91a7c: 0x00000000 0x4200cf8c 0x00000000 0x00000000 -0x3fc91a8c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc91a9c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc91aac: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc91abc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc91acc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc91adc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc91aec: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc91afc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc91b0c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc91b1c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc91b2c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc91b3c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc91b4c: 0x3fc90000 -.coredump.tasks.data 0x3fc918a0 0x150 RW -0x3fc918a0: 0x40382a38 0x40385996 0x3fc918ec 0x40381576 -0x3fc918b0: 0x3fc8d8e8 0x00000000 0x00000000 0x00000000 -0x3fc918c0: 0x00000064 0x00000000 0x00000001 0x00000001 -0x3fc918d0: 0x000000c8 0x00000004 0x00000001 0x600c0000 -0x3fc918e0: 0x42002d7c 0x00000000 0x00000000 0x00000000 -0x3fc918f0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc91900: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc91910: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc91920: 0x00000000 0x00000000 0x00000064 0x4038479a -0x3fc91930: 0x00000000 0x00000000 0x00000000 0x42006954 -0x3fc91940: 0x00000000 0x00000000 0x00000000 0x403858aa +.coredump.tasks.data 0x3fc91ac0 0x154 RW +0x3fc91ac0: 0x3fc91960 0x00000064 0x3fc8c454 0x3fc8c454 +0x3fc91ad0: 0x3fc91ac0 0x3fc8c44c 0x00000012 0xb6b4ede7 +0x3fc91ae0: 0x171a80e7 0x3fc91ac0 0x00000000 0x00000007 +0x3fc91af0: 0x3fc912bc 0x6c616e75 0x656e6769 0x74705f64 +0x3fc91b00: 0x00745f72 0x00000000 0x3fc91ab0 0x00000007 +0x3fc91b10: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc91b20: 0x3fc8d52c 0x3fc8d594 0x3fc8d5fc 0x00000000 +0x3fc91b30: 0x00000000 0x00000001 0x00000000 0x00000000 +0x3fc91b40: 0x00000000 0x4200d160 0x00000000 0x00000000 +0x3fc91b50: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc91b60: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc91b70: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc91b80: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc91b90: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc91ba0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc91bb0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc91bc0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc91bd0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc91be0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc91bf0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc91c00: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc91c10: 0x3fc90000 +.coredump.tasks.data 0x3fc91900 0x1b0 RW +0x3fc91900: 0x4200583c 0x42005836 0x3fc919a0 0x3fc8a600 +0x3fc91910: 0x3fc8e884 0x00000000 0x3fc915fc 0x00000000 +0x3fc91920: 0x00000000 0x00000000 0x00000020 0x3fc915d8 +0x3fc91930: 0x00000000 0x00000007 0xffffffad 0x00000005 +0x3fc91940: 0x42002e30 0x00000000 0x00000000 0x00000000 0x3fc91950: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc91960: 0x00000000 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 -0x3fc91970: 0x27146414 0x01010107 0x00000001 0x00000000 -0x3fc91980: 0xffffffff 0x7fefffff 0x00000000 0x3fc00000 -0x3fc91990: 0x00000000 0x40300000 0x00000000 0x3fe00000 -0x3fc919a0: 0x00000000 0x3ff80000 0x636f4361 0x3fd287a7 -0x3fc919b0: 0x8b60c8b3 0x3fc68a28 0x509f79fb 0x3fd34413 -0x3fc919c0: 0x00000000 0x3ff00000 0x00000000 0x40240000 -0x3fc919d0: 0x00000000 0x401c0000 0x00000000 0x40140000 -0x3fc919e0: 0x00000000 0x43500000 0x3fc89400 0x00001b40 -.coredump.tasks.data 0x3fc8e048 0x154 RW -0x3fc8e048: 0x3fc8def0 0x3fc8c2f4 0x3fc8bbe8 0x3fc8bbe8 -0x3fc8e058: 0x3fc8e048 0x3fc8bbe0 0x00000003 0xdf89b7c0 -0x3fc8e068: 0x2e79d460 0x3fc8e048 0x00000000 0x00000016 -0x3fc8e078: 0x3fc8d044 0x5f707365 0x656d6974 0xe2ab0072 -0x3fc8e088: 0x00c41b3a 0x00000000 0x3fc8e040 0x00000016 -0x3fc8e098: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8e0a8: 0x3fc8cb0c 0x3fc8cb74 0x3fc8cbdc 0x00000000 -0x3fc8e0b8: 0x00000000 0x00000001 0x00000000 0x00000000 -0x3fc8e0c8: 0x00000000 0x4200cf8c 0x00000000 0x00000000 -0x3fc8e0d8: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8e0e8: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8e0f8: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8e108: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8e118: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8e128: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8e138: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8e148: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8e158: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8e168: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8e178: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8e188: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8e198: 0x3fc80001 -.coredump.tasks.data 0x3fc8def0 0x150 RW -0x3fc8def0: 0x40385834 0x4038585e 0xa5a5a5a5 0xa5a5a5a5 -0x3fc8df00: 0x3fc89f38 0x00000000 0x00000000 0x00000000 -0x3fc8df10: 0xffffffff 0x00000001 0x00000001 0x00000001 -0x3fc8df20: 0x00000000 0x00000004 0x3fc8c000 0x600c2000 -0x3fc8df30: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8df40: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8df50: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8df60: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8df70: 0x00000000 0x00000001 0xffffffff 0x4038539e -0x3fc8df80: 0x00000000 0x00000000 0x00000000 0x420060a2 -0x3fc8df90: 0x00000000 0x00000000 0x00000000 0x403858aa -0x3fc8dfa0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3fc8dfb0: 0x00000000 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 -0x3fc8dfc0: 0x27146414 0x01010107 0x00000001 0x00000000 -0x3fc8dfd0: 0xffffffff 0x7fefffff 0x00000000 0x3fc00000 -0x3fc8dfe0: 0x00000000 0x40300000 0x00000000 0x3fe00000 -0x3fc8dff0: 0x00000000 0x3ff80000 0x636f4361 0x3fd287a7 -0x3fc8e000: 0x8b60c8b3 0x3fc68a28 0x509f79fb 0x3fd34413 -0x3fc8e010: 0x00000000 0x3ff00000 0x00000000 0x40240000 -0x3fc8e020: 0x00000000 0x401c0000 0x00000000 0x40140000 -0x3fc8e030: 0x00000000 0x43500000 0x3fc89400 0x00001b40 +0x3fc91960: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc91970: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc91980: 0x00001881 0x40380001 0x00000007 0x00000005 +0x3fc91990: 0x00000000 0x00000002 0x42002e30 0x00000000 +0x3fc919a0: 0x00000000 0x00000000 0x00000000 0x00000003 +0x3fc919b0: 0x00000000 0x3fc91b1c 0x3fc8d594 0x4200581a +0x3fc919c0: 0x00000000 0x00000000 0x00000000 0x00000003 +0x3fc919d0: 0x00000000 0x3fc919e0 0x00000002 0x4200581a +0x3fc919e0: 0x3c021368 0x0000001e 0x3c020538 0x00000003 +0x3fc919f0: 0x00000000 0x00000000 0x00000000 0x42005874 +0x3fc91a00: 0x00000000 0x00000000 0x00000000 0x40385f1e +0x3fc91a10: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc91a20: 0x00000000 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 +0x3fc91a30: 0x27146414 0x01010107 0x00000001 0xffffffff +0x3fc91a40: 0x7fefffff 0x00000000 0x3fc00000 0x00000000 +0x3fc91a50: 0x40300000 0x00000000 0x3fe00000 0x00000000 +0x3fc91a60: 0x3ff80000 0x636f4361 0x3fd287a7 0x8b60c8b3 +0x3fc91a70: 0x3fc68a28 0x509f79fb 0x3fd34413 0x00000000 +0x3fc91a80: 0x3ff00000 0x00000000 0x40240000 0x00000000 +0x3fc91a90: 0x401c0000 0x00000000 0x40140000 0x00000000 +0x3fc91aa0: 0x43500000 0x00000018 0x00000000 0x4c507a03 +.coredump.tasks.data 0x3fc9110c 0x154 RW +0x3fc9110c: 0x3fc90fb0 0x00000064 0x3fc8c42c 0x3fc8c42c +0x3fc9111c: 0x3fc9110c 0x3fc8c424 0x00000014 0xe00cf2e0 +0x3fc9112c: 0xc110b242 0x3fc9110c 0x00000000 0x00000005 +0x3fc9113c: 0x3fc90908 0x5f646162 0x5f727470 0x6b736174 +0x3fc9114c: 0x0030f200 0x00000000 0x3fc91100 0x00000005 +0x3fc9115c: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc9116c: 0x3fc8d52c 0x3fc8d594 0x3fc8d5fc 0x00000000 +0x3fc9117c: 0x00000000 0x00000001 0x00000000 0x00000000 +0x3fc9118c: 0x00000000 0x4200d160 0x00000000 0x00000000 +0x3fc9119c: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc911ac: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc911bc: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc911cc: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc911dc: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc911ec: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc911fc: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc9120c: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc9121c: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc9122c: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc9123c: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc9124c: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc9125c: 0x3fc90000 +.coredump.tasks.data 0x3fc90fb0 0x150 RW +0x3fc90fb0: 0x40382dae 0x40386012 0x3fc90ffc 0x40381656 +0x3fc90fc0: 0x3fc8ded4 0x00000000 0x00000000 0x00000000 +0x3fc90fd0: 0x00000064 0x00000000 0x00000001 0x00000001 +0x3fc90fe0: 0x00000064 0x00000004 0x00000001 0x600c0000 +0x3fc90ff0: 0x42002e30 0x00000000 0x00000000 0x00000000 +0x3fc91000: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc91010: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc91020: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc91030: 0x00000000 0x00000000 0x00000064 0x40384d22 +0x3fc91040: 0x00000000 0x00000000 0x00000000 0x420057d4 +0x3fc91050: 0x00000000 0x00000000 0x00000000 0x40385f1e +0x3fc91060: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc91070: 0x00000000 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 +0x3fc91080: 0x27146414 0x01010107 0x00000001 0xffffffff +0x3fc91090: 0x7fefffff 0x00000000 0x3fc00000 0x00000000 +0x3fc910a0: 0x40300000 0x00000000 0x3fe00000 0x00000000 +0x3fc910b0: 0x3ff80000 0x636f4361 0x3fd287a7 0x8b60c8b3 +0x3fc910c0: 0x3fc68a28 0x509f79fb 0x3fd34413 0x00000000 +0x3fc910d0: 0x3ff00000 0x00000000 0x40240000 0x00000000 +0x3fc910e0: 0x401c0000 0x00000000 0x40140000 0x00000000 +0x3fc910f0: 0x43500000 0x00000018 0x00000000 0x4c507a03 +.coredump.tasks.data 0x3fc90360 0x154 RW +0x3fc90360: 0x3fc90210 0x3fc8cd14 0x3fc8c3c8 0x3fc8c3c8 +0x3fc90370: 0x3fc90360 0x3fc8c3c0 0x00000019 0x2ef8d63b +0x3fc90380: 0xa0e85784 0x3fc90360 0x00000000 0x00000000 +0x3fc90390: 0x3fc8fd5c 0x454c4449 0x62abcf00 0x095d5e5c +0x3fc903a0: 0x006c6bfa 0x00000000 0x3fc90350 0x00000000 +0x3fc903b0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc903c0: 0x3fc8d52c 0x3fc8d594 0x3fc8d5fc 0x00000000 +0x3fc903d0: 0x00000000 0x00000001 0x00000000 0x00000000 +0x3fc903e0: 0x00000000 0x4200d160 0x00000000 0x00000000 +0x3fc903f0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc90400: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc90410: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc90420: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc90430: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc90440: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc90450: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc90460: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc90470: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc90480: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc90490: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc904a0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc904b0: 0x3fc90000 +.coredump.tasks.data 0x3fc90210 0x140 RW +0x3fc90210: 0x4200c012 0x4200b46e 0xa5a5a5a5 0xa5a5a5a5 +0x3fc90220: 0x3fc8d124 0x00000000 0x00000000 0x00000000 +0x3fc90230: 0x00000008 0x00000001 0x00000001 0x3fc9026f +0x3fc90240: 0x00000000 0x3fc90360 0x3fc8c9a4 0x00000000 +0x3fc90250: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc90260: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc90270: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc90280: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc90290: 0x00000000 0x00000000 0x00000000 0x40384c12 +0x3fc902a0: 0x00000000 0x00000000 0x00000000 0x40385f1e +0x3fc902b0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc902c0: 0x00000000 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 +0x3fc902d0: 0x27146414 0x01010107 0x00000001 0xffffffff +0x3fc902e0: 0x7fefffff 0x00000000 0x3fc00000 0x00000000 +0x3fc902f0: 0x40300000 0x00000000 0x3fe00000 0x00000000 +0x3fc90300: 0x3ff80000 0x636f4361 0x3fd287a7 0x8b60c8b3 +0x3fc90310: 0x3fc68a28 0x509f79fb 0x3fd34413 0x00000000 +0x3fc90320: 0x3ff00000 0x00000000 0x40240000 0x00000000 +0x3fc90330: 0x401c0000 0x00000000 0x40140000 0x00000000 +0x3fc90340: 0x43500000 0x00000018 0x00000000 0x4c507a03 +.coredump.tasks.data 0x3fc9241c 0x154 RW +0x3fc9241c: 0x3fc922c0 0x000000c8 0x3fc8c5bc 0x3fc8c5bc +0x3fc9242c: 0x3fc9241c 0x3fc8c5b4 0x0000000f 0x7fec3676 +0x3fc9243c: 0x0eabc3b4 0x3fc9241c 0x00000000 0x0000000a +0x3fc9244c: 0x3fc91c18 0x6c696166 0x615f6465 0x72657373 +0x3fc9245c: 0x00745f74 0x00000000 0x3fc92410 0x0000000a +0x3fc9246c: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc9247c: 0x3fc8d52c 0x3fc8d594 0x3fc8d5fc 0x00000000 +0x3fc9248c: 0x00000000 0x00000001 0x00000000 0x00000000 +0x3fc9249c: 0x00000000 0x4200d160 0x00000000 0x00000000 +0x3fc924ac: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc924bc: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc924cc: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc924dc: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc924ec: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc924fc: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc9250c: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc9251c: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc9252c: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc9253c: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc9254c: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc9255c: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc9256c: 0x3fc90000 +.coredump.tasks.data 0x3fc922c0 0x150 RW +0x3fc922c0: 0x40382dae 0x40386012 0x3fc9230c 0x40381656 +0x3fc922d0: 0x3fc8f1e4 0x00000000 0x00000000 0x00000000 +0x3fc922e0: 0x00000064 0x00000000 0x00000001 0x00000001 +0x3fc922f0: 0x000000c8 0x00000004 0x00000001 0x600c0000 +0x3fc92300: 0x42002e30 0x00000000 0x00000000 0x00000000 +0x3fc92310: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc92320: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc92330: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc92340: 0x00000000 0x00000000 0x00000064 0x40384d22 +0x3fc92350: 0x00000000 0x00000000 0x00000000 0x420056be +0x3fc92360: 0x00000000 0x00000000 0x00000000 0x40385f1e +0x3fc92370: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc92380: 0x00000000 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 +0x3fc92390: 0x27146414 0x01010107 0x00000001 0xffffffff +0x3fc923a0: 0x7fefffff 0x00000000 0x3fc00000 0x00000000 +0x3fc923b0: 0x40300000 0x00000000 0x3fe00000 0x00000000 +0x3fc923c0: 0x3ff80000 0x636f4361 0x3fd287a7 0x8b60c8b3 +0x3fc923d0: 0x3fc68a28 0x509f79fb 0x3fd34413 0x00000000 +0x3fc923e0: 0x3ff00000 0x00000000 0x40240000 0x00000000 +0x3fc923f0: 0x401c0000 0x00000000 0x40140000 0x00000000 +0x3fc92400: 0x43500000 0x00000018 0x00000000 0x4c507a03 +.coredump.tasks.data 0x3fc8ea68 0x154 RW +0x3fc8ea68: 0x3fc8e910 0x3fc8cd14 0x3fc8c5f8 0x3fc8c5f8 +0x3fc8ea78: 0x3fc8ea68 0x3fc8c5f0 0x00000003 0xd38ebc35 +0x3fc8ea88: 0x13a32184 0x3fc8ea68 0x00000000 0x00000016 +0x3fc8ea98: 0x3fc8da64 0x5f707365 0x656d6974 0xc2390072 +0x3fc8eaa8: 0x00870443 0x00000000 0x3fc8ea60 0x00000016 +0x3fc8eab8: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc8eac8: 0x3fc8d52c 0x3fc8d594 0x3fc8d5fc 0x00000000 +0x3fc8ead8: 0x00000000 0x00000001 0x00000000 0x00000000 +0x3fc8eae8: 0x00000000 0x4200d160 0x00000000 0x00000000 +0x3fc8eaf8: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc8eb08: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc8eb18: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc8eb28: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc8eb38: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc8eb48: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc8eb58: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc8eb68: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc8eb78: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc8eb88: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc8eb98: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc8eba8: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc8ebb8: 0x3fc80001 +.coredump.tasks.data 0x3fc8e910 0x150 RW +0x3fc8e910: 0x40385ea8 0x40385ed2 0xa5a5a5a5 0xa5a5a5a5 +0x3fc8e920: 0x3fc8b834 0x00000000 0x00000000 0x00000000 +0x3fc8e930: 0x00000000 0xffffffff 0x00000001 0x00000001 +0x3fc8e940: 0xffffffff 0x00000004 0x3fc8d000 0x600c2000 +0x3fc8e950: 0x00000000 0x00000000 0x00000001 0x00000000 +0x3fc8e960: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc8e970: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc8e980: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc8e990: 0x00000001 0xffffffff 0x00000000 0x403859ae +0x3fc8e9a0: 0x00000000 0x00000000 0x00000000 0x42004c56 +0x3fc8e9b0: 0x00000000 0x00000000 0x00000000 0x40385f1e +0x3fc8e9c0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fc8e9d0: 0x00000000 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 +0x3fc8e9e0: 0x27146414 0x01010107 0x00000001 0xffffffff +0x3fc8e9f0: 0x7fefffff 0x00000000 0x3fc00000 0x00000000 +0x3fc8ea00: 0x40300000 0x00000000 0x3fe00000 0x00000000 +0x3fc8ea10: 0x3ff80000 0x636f4361 0x3fd287a7 0x8b60c8b3 +0x3fc8ea20: 0x3fc68a28 0x509f79fb 0x3fd34413 0x00000000 +0x3fc8ea30: 0x3ff00000 0x00000000 0x40240000 0x00000000 +0x3fc8ea40: 0x401c0000 0x00000000 0x40140000 0x00000000 +0x3fc8ea50: 0x43500000 0x00000018 0x00000000 0x4c507a03 ===================== ESP32 CORE DUMP END ===================== =============================================================== diff --git a/components/espcoredump/test/esp32s2/coredump.b64 b/components/espcoredump/test/esp32s2/coredump.b64 index 4d7a632f0d..816f56345b 100644 --- a/components/espcoredump/test/esp32s2/coredump.b64 +++ b/components/espcoredump/test/esp32s2/coredump.b64 @@ -1,28 +1,28 @@ -4BoAAAABAgAAAAAAAAAAAAAAAAA= +8BoAAAABAgAAAAAAAAAAAAAAAAA= f0VMRgEBAQAAAAAAAAAAAAQAXgABAAAAAAAAADQAAAAAAAAAAAAAADQAIAAMACgA AAAAAA== BAAAALQBAAAAAAAAAAAAAOALAADgCwAABgAAAAAAAAA= -AQAAAJQNAABcLPw/XCz8P1QBAABUAQAABgAAAAAAAAA= -AQAAAOgOAADwKvw/8Cr8P2QBAABkAQAABgAAAAAAAAA= -AQAAAEwQAACoIvw/qCL8P1QBAABUAQAABgAAAAAAAAA= -AQAAAKARAACwIfw/sCH8P/AAAADwAAAABgAAAAAAAAA= -AQAAAJASAABAFPw/QBT8P1QBAABUAQAABgAAAAAAAAA= -AQAAAOQTAAAgE/w/IBP8PxgBAAAYAQAABgAAAAAAAAA= -AQAAAPwUAAC4Nfw/uDX8P1QBAABUAQAABgAAAAAAAAA= -AQAAAFAWAADANPw/wDT8P/AAAADwAAAABgAAAAAAAAA= -AQAAAEAXAABo/fk/aP35P1QBAABUAQAABgAAAAAAAAA= -AQAAAJQYAABA/Pk/QPz5PyABAAAgAQAABgAAAAAAAAA= -BAAAALQZAAAAAAAAAAAAABQBAAAUAQAABgAAAAAAAAA= +AQAAAJQNAAC0Nfw/tDX8P1QBAABUAQAABgAAAAAAAAA= +AQAAAOgOAABANPw/QDT8P2wBAABsAQAABgAAAAAAAAA= +AQAAAFQQAAAALPw/ACz8P1QBAABUAQAABgAAAAAAAAA= +AQAAAKgRAAAAK/w/ACv8P/gAAAD4AAAABgAAAAAAAAA= +AQAAAKASAAB4Hfw/eB38P1QBAABUAQAABgAAAAAAAAA= +AQAAAPQTAABgHPw/YBz8PxABAAAQAQAABgAAAAAAAAA= +AQAAAAQVAAAQP/w/ED/8P1QBAABUAQAABgAAAAAAAAA= +AQAAAFgWAAAQPvw/ED78P/gAAAD4AAAABgAAAAAAAAA= +AQAAAFAXAABo/fk/aP35P1QBAABUAQAABgAAAAAAAAA= +AQAAAKQYAABA/Pk/QPz5PyABAAAgAQAABgAAAAAAAAA= +BAAAAMQZAAAAAAAAAAAAABQBAAAUAQAABgAAAAAAAAA= CAAAAEwCAAABAAAA Q09SRQAAAAA= -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXCz8PwAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACWAIQCANBgAAAAAAAAAAAAAAAAAZAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtDX8PwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJVgIQCANBgAAAAAAAAAAAAAAAAAZAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAORfCICAK/w/ -AgAAAMwr/D/AK/w/AAAAAJTo+T8AAAAABQAAAK3///8gAAAAuCz8P7fr+T+AAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYCIDQNPw/ +AgAAABw1/D8QNfw/AAAAAJTo+T8AAAAABQAAAK3///8gAAAAEDb8P7fr+T+AAAAA AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA @@ -30,14 +30,14 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAA CAAAAEwCAAABAAAA Q09SRQAAAAA= -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqCL8PwAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM3cCQCACBgAAAAAAAAAAAAAAAAAbAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACz8PwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAd3wCQCACBgAAAAAAAAAAAAAAAAAbAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKdfCIBAIvw/ -ZAAAAPjP+z8hAAYAUOv7PyMLBgBZAAAAM3cCgCAi/D8AAAAAZAAAAPTt+z8QDPw/ +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMNXCICQK/w/ +ZAAAABjZ+z8hAAYAYNj7PwAAQj8AwD+4d3wCgHAr/D8AAAAAZQAAAAT3+z9QFfw/ AAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA @@ -45,14 +45,14 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAA CAAAAEwCAAABAAAA Q09SRQAAAAA= -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQBT8PwAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7lQJQCAFBgAAAAAAAAAAAAAAAAAeAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeB38PwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAslgJQCAFBgAAAAAAAAAAAAAAAAAeAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADadCICwE/w/ -AAAAAAEAAAABAAAAAQAAgCMABgAAAAAAHqIIgIAT/D8AAAAAgKQBQCAABgAAwABg +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPKgCIDwHPw/ +AAAAAAEAAAABAAAAAQAAgCMABgAAAAAA2qUIgMAc/D8AAAAAgKQBQCAABgAAwABg AAAAAEsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA @@ -60,14 +60,14 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAA CAAAAEwCAAABAAAA Q09SRQAAAAA= -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuDX8PwAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM3cCQCAHBgAAAAAAAAAAAAAAAAAWAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAED/8PwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAd3wCQCAHBgAAAAAAAAAAAAAAAAAWAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO9eCIBQNfw/ -ZAAAAPjP+z8hAAYAkCv8PzDR+z9kAAAAM3cCgDA1/D8AAAAAyAAAAPTt+z8QDPw/ +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANXCICgPvw/ +ZAAAABjZ+z8hAAYA4DT8P4Da+z9lAAAAd3wCgIA+/D8AAAAAyQAAAAT3+z9QFfw/ AAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA @@ -81,91 +81,93 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAByJAoDQ/Pk/ -Iw4GAAAAAAAgDgYAcN7/P8De/z8EAAAAOVMCgKD8+T8w0fs/AAAAANDi/z+w4v8/ -AIBAPyACAD8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKiPAoDQ/Pk/ +Iw4GAAAAAAAgDgYAcN7/P8De/z8EAAAARVcCgKD8+T+A2vs/AAAAANDi/z+w4v8/ +AIBAP3ACAD8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAA -YCv8P2QAAACU7Ps/lOz7P1ws/D+M7Ps/EgAAALV8Zvp19PO8XCz8PwAAAAAHAAAA -WCT8P3VuYWxpZ25lZF9wdHJfdAAAAAAAVCz8PwcAAAAAAAAAAAAAAAAAAAAAAAAA +sDT8P2UAAACk9fs/pPX7P7Q1/D+c9fs/EgAAAOYO0FnZtglStDX8PwAAAAAHAAAA +sC38P3VuYWxpZ25lZF9wdHJfdAAAAAAArDX8PwcAAAAAAAAAAAAAAAAAAAAAAAAA LOj5P5To+T/86Pk/AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAgKQBQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAD8Pw== -776t3glgCEAwDQYA5F8IgIAr/D8CAAAAzCv8P8Ar/D8AAAAAlOj5PwAAAAAFAAAA -rf///yAAAAC4LPw/t+v5P4AAAAABAAAAAAAAABkAAAAdAAAABQAAALfr+T+AAAAA -PT4CQDT1+z8o6vk/AAAAALfr+T+AAAAAAQAAAAAAAADkXwiAsCv8PwEAAACU6Pk/ -AwAAADDR+z8BAAAAAQAAAMAr/D8AAAAAlOj5PwAAAAAsYAiA4Cv8PwoAAAD4z/s/ -AwAAAB4AAABcIwA/AQAAAPTt+z8QDPw/AAgAAAAAAADshwKAECz8PwAAAAAAAAAA -AwAAABAs/D8AAAAAAAAAACEABgDgIfw/MNH7P2QAAAAAAAAAMCz8PxRgCEAAAAAA -IwAGAFDr+z8jDAYAAQAAAAAAAABQLPw/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAA= -sCH8P2QAAABs7Ps/bOz7P6gi/D9k7Ps/FAAAAOaYhZH9xHrvqCL8PwAAAAAFAAAA -pBr8P2JhZF9wdHJfdGFzawCjEAAAAAAAoCL8PwUAAAAAAAAAAAAAAAAAAAAAAAAA +776t3iVYCEAwDQYAAFgIgNA0/D8CAAAAHDX8PxA1/D8AAAAAlOj5PwAAAAAFAAAA +rf///yAAAAAQNvw/t+v5P4AAAAABAAAAAAAAABkAAAAdAAAABQAAALfr+T+AAAAA +LT8CQLT9+z8o6vk/AAAAALfr+T+AAAAAAQAAAAAAAAAAWAiAADX8PwEAAACU6Pk/ +AwAAAIDa+z8BAAAAAQAAABA1/D8AAAAAlOj5PwAAAABIWAiAMDX8PwoAAAAY2fs/ +AwAAAB4AAAAwJAA/AQAAAAT3+z9QFfw/AAgAAAAAAACQjgKAYDX8PwAAAAAAAAAA +AwAAAGA1/D8AAAAAAAAAACEABgAwK/w/gNr7P2UAAAAAAAAAgDX8PzBYCEAAAAAA +IwAGAGD0+z8jDAYAAQAAAAAAAACgNfw/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +ACv8P2UAAAB89fs/fPX7PwAs/D909fs/FAAAALKGBZUJfuh/ACz8PwAAAAAFAAAA +/CP8P2JhZF9wdHJfdGFzawBMugAAAAAA+Cv8PwUAAAAAAAAAAAAAAAAAAAAAAAAA LOj5P5To+T/86Pk/AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAgKQBQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAD8Pw== -mD4CQDN3AkAwAgYAp18IgEAi/D9kAAAA+M/7PyEABgBQ6/s/IwsGAFkAAAAzdwKA -ICL8PwAAAABkAAAA9O37PxAM/D8ACAAAAAAAABsAAAD//wAAAAAAAAA/AkAQDPw/ -cGYCQITr+z8AAAAAAAAAAEAM/D8QDPw/AAgAAAAAAADshwKAYCL8PwAAAAAAAAAA -IQAGAFDr+z8jCwYAWQAAAAAAAACAIvw/mF8IQAAAAAAjAAYAUOv7PyMHBgAwC/w/ -AAAAAKAi/D8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -IBP8PxT2+z8I7Ps/COz7P0AU/D8A7Ps/GQAAAI4HwjbIC/+pQBT8PwAAAAAAAAAA -PA78P0lETEUA7gxhMfMFcqcHvwAAAAAAOBT8PwAAAAAAAAAAAAAAAAAAAAAAAAAA +iD8CQHd8AkAwAgYAw1cIgJAr/D9kAAAAGNn7PyEABgBg2Ps/AABCPwDAP7h3fAKA +cCv8PwAAAABlAAAABPf7P1AV/D8ACAAAAAAAABsAAAD//wAAAAAAAPA/AkBQFfw/ +gGoCQAT0+z8AAAAAAAAAAAAAAABQFfw/AAgAAAAAAACQjgKAsCv8PwAAAAAAAAAA +IQAGAGDY+z8AAEI/AMA/uAAAAADQK/w/tFcIQAAAAAAjAAYAYPT7PyMJBgABAAAA +AAAAAPAr/D8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAA= +YBz8P0z/+z8Y9fs/GPX7P3gd/D8Q9fs/GQAAAP+8pIL+kQuueB38PwAAAAAAAAAA +dBf8P0lETEUAepz6z4gsR8SsuAAAAAAAcB38PwAAAAAAAAAAAAAAAAAAAAAAAAAA LOj5P5To+T/86Pk/AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAgKQBQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAD8Pw== -mD4CQO5UCUAwBQYANp0IgLAT/D8AAAAAAQAAAAEAAAABAACAIwAGAAAAAAAeogiA -gBP8PwAAAACApAFAIAAGAADAAGAAAAAASwAAAB4AAAD//wAAAAAAAAA/AkAAwABg -cGYCQBTd+z+lpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaVFdgKA0BP8PwgAAAABAAAA -MBT8PwAAAAAAAAAAAAAAAOyHAoDwE/w/AAAAAAAAAAAhAAYAEAz8PzDR+z8BAAAA -AAAAABAU/D88dgJAAAAAACMABgAwDPw/WABMPwEAAAAAAAAAMBT8PwAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== -wDT8P8gAAAD06/s/9Ov7P7g1/D/s6/s/DwAAAHjELjhoP6d7uDX8PwAAAAAKAAAA -tC38P2ZhaWxlZF9hc3NlcnRfdAAAAAAAsDX8PwoAAAAAAAAAAAAAAAAAAAAAAAAA +iD8CQLJYCUAwBQYA8qAIgPAc/D8AAAAAAQAAAAEAAAABAACAIwAGAAAAAADapQiA +wBz8PwAAAACApAFAIAAGAADAAGAAAAAASwAAAB4AAAD//wAAAAAAAPA/AkAAwABg +gGoCQITl+z+lpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWBewKAEB38PwgAAAABAAAA +cB38PwAAAAAAAAAAAAAAAJCOAoAwHfw/AAAAAAAAAAAhAAYAUBX8P4Da+z8BAAAA +AAAAAFAd/D94ewJAAAAAACMABgBwFfw/WABMPwEAAAAAAAAAcB38PwAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= +ED78P8kAAAAE9fs/BPX7PxA//D/89Ps/DwAAAHWqESiki9KrED/8PwAAAAAKAAAA +DDf8P2ZhaWxlZF9hc3NlcnRfdAAAAAAACD/8PwoAAAAAAAAAAAAAAAAAAAAAAAAA LOj5P5To+T/86Pk/AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAgKQBQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAD8Pw== -mD4CQDN3AkAwBwYA714IgFA1/D9kAAAA+M/7PyEABgCQK/w/MNH7P2QAAAAzdwKA -MDX8PwAAAADIAAAA9O37PxAM/D8ACAAAAAAAABYAAAD//wAAAAAAAAA/AkAQDPw/ -cGYCQJT++z8AAAAAAAAAAPTt+z8QDPw/AAgAAAAAAADshwKAcDX8PwAAAAAAAAAA -IQAGAJAr/D8w0fs/ZAAAAAAAAACQNfw/4F4IQAAAAAAjAAYAUOv7PyMBBgABAAAA -AAAAALA1/D8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -QPz5PxTg+T+Y6/s/mOv7P2j9+T+Q6/s/AwAAAIsLh01IIfbtaP35PwAAAAAWAAAA -ZO35P2VzcF90aW1lcgCSDgdicwAAAAAAYP35PxYAAAAAAAAAAAAAAAAAAAAAAAAA +iD8CQHd8AkAwBwYAA1cIgKA+/D9kAAAAGNn7PyEABgDgNPw/gNr7P2UAAAB3fAKA +gD78PwAAAADJAAAABPf7P1AV/D8ACAAAAAAAABYAAAD//wAAAAAAAPA/AkBQFfw/ +gGoCQBQH/D8AAAAAAAAAAAT3+z9QFfw/AAgAAAAAAACQjgKAwD78PwAAAAAAAAAA +IQAGAOA0/D+A2vs/ZQAAAAAAAADgPvw/9FYIQAAAAAAjAAYAYPT7PyMBBgABAAAA +AAAAAAA//D8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAA= +QPz5PxTg+T+o9Ps/qPT7P2j9+T+g9Ps/AwAAABGPfE4uwcARaP35PwAAAAAWAAAA +ZO35P2VzcF90aW1lcgBUDFOoSgAAAAAAYP35PxYAAAAAAAAAAAAAAAAAAAAAAAAA LOj5P5To+T/86Pk/AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAgKQBQAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AQD5Pw== -mD4CQNSoAUAwDgYAHIkCgND8+T8jDgYAAAAAACAOBgBw3v8/wN7/PwQAAAA5UwKA -oPz5PzDR+z8AAAAA0OL/P7Di/z8AgEA/IAIAPwoAAAD//wAAAAAAAAA/AkCw4v8/ -cGYCQETG+T+lpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaUmggKA4Pz5P/jP+z8AAAAA -bFgIgAD9+T9o/vk/+M/7PwAAAADQ4f8/IwEGAAAAAADshwKAIP35PwAAAAAAAAAA -AQAAAPDh/z8jAQYAAAAAAAAAAABA/fk/YFgIQAAAAAAjAQYAWOv7PwAAAAABAAAA -AAAAAGD9+T8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3WwmAgOL/P4jr+z8AAAAA +iD8CQNSoAUAwDgYAqI8CgND8+T8jDgYAAAAAACAOBgBw3v8/wN7/PwQAAABFVwKA +oPz5P4Da+z8AAAAA0OL/P7Di/z8AgEA/cAIAPwoAAAD//wAAAAAAAPA/AkCw4v8/ +gGoCQHTF+T+lpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaX+hwKA4Pz5PxjZ+z8AAAAA +C08IgAD9+T8AAAAAAQAAAAAAAADQ4f8/IwEGAAAAAACQjgKAIP35PwAAAAAAAAAA +GNn7P2j0+z8AAAAAAAAAAAAAAABA/fk//E4IQAAAAAAjAQYAMOL/P1bDogEYzQJA +AAAAAGD9+T8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/XwmAgOL/P5j0+z8AAAAA FAAAAEgAAABKIAAA RVNQX0NPUkVfRFVNUF9JTkZPAAA= -AAECADE5YmNmZTg5Y2RjMmNmNTYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAECADBhOGM1OWYwNjYwNTBjOTMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA DAAAAJQAAAClAgAA RVhUUkFfSU5GTwAA -XCz8P+gAAAAdAAAA7gAAAAUAAADCAAAAAAAAAMMAAAAAAAAAxAAAAAAAAADFAAAA -AAAAAMYAAAAAAAAAsQAAAKOaCECyAAAAAAAAALMAAAAAAAAAtAAAAAAAAAC1AAAA +tDX8P+gAAAAdAAAA7gAAAAUAAADCAAAAAAAAAMMAAAAAAAAAxAAAAAAAAADFAAAA +AAAAAMYAAAAAAAAAsQAAAEOeCECyAAAAAAAAALMAAAAAAAAAtAAAAAAAAAC1AAAA AAAAALYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAA== -K7mejA== +o64IXA== diff --git a/components/espcoredump/test/esp32s2/expected_output b/components/espcoredump/test/esp32s2/expected_output index 8816d3f71d..3f0b3d82fe 100644 --- a/components/espcoredump/test/esp32s2/expected_output +++ b/components/espcoredump/test/esp32s2/expected_output @@ -2,12 +2,12 @@ espcoredump.py v0.4-dev =============================================================== ==================== ESP32 CORE DUMP START ==================== -Crashed task handle: 0x3ffc2c5c, name: 'unaligned_ptr_t', GDB name: 'process 1073491036' +Crashed task handle: 0x3ffc35b4, name: 'unaligned_ptr_t', GDB name: 'process 1073493428' ================== CURRENT THREAD REGISTERS =================== exccause 0x1d (StoreProhibitedCause) excvaddr 0x5 -epc1 0x40089aa3 +epc1 0x40089e43 epc2 0x0 epc3 0x0 epc4 0x0 @@ -18,7 +18,7 @@ eps3 0x0 eps4 0x0 eps5 0x0 eps6 0x0 -pc 0x40086009 0x40086009 +pc 0x40085825 0x40085825 lbeg 0x0 0 lend 0x0 0 lcount 0x0 0 @@ -39,67 +39,67 @@ f64r_hi f64s fcr fsr -a0 0x80085fe4 -2146934812 -a1 0x3ffc2b80 1073490816 +a0 0x80085800 -2146936832 +a1 0x3ffc34d0 1073493200 a2 0x2 2 -a3 0x3ffc2bcc 1073490892 -a4 0x3ffc2bc0 1073490880 +a3 0x3ffc351c 1073493276 +a4 0x3ffc3510 1073493264 a5 0x0 0 a6 0x3ff9e894 1073342612 a7 0x0 0 a8 0x5 5 a9 0xffffffad -83 a10 0x20 32 -a11 0x3ffc2cb8 1073491128 +a11 0x3ffc3610 1073493520 a12 0x3ff9ebb7 1073343415 a13 0x80 128 a14 0x1 1 a15 0x0 0 ==================== CURRENT THREAD STACK ===================== -#0 0x40086009 in UnityPrintNumberUnsigned (number=2) at /builds/espressif/esp-idf/components/unity/unity/src/unity.c:204 -#1 0x40085fe4 in UnityPrintNumberUnsigned (number=1) at /builds/espressif/esp-idf/components/unity/unity/src/unity.c:196 -#2 0x40085fe4 in UnityPrintNumberUnsigned (number=10) at /builds/espressif/esp-idf/components/unity/unity/src/unity.c:196 -#3 0x4008602c in ?? () at /builds/espressif/esp-idf/components/unity/unity/src/unity.c:206 -Backtrace stopped: previous frame identical to this frame (corrupt stack?) +#0 0x40085825 in recur_func () at ../main/test_core_dump.c:70 +#1 0x40085800 in recur_func () at ../main/test_core_dump.c:63 +#2 0x40085800 in recur_func () at ../main/test_core_dump.c:63 +#3 0x40085848 in unaligned_ptr_task (pvParameter=0x0) at ../main/test_core_dump.c:80 +#4 0x40028e90 in vPortTaskWrapper (pxCode=0x40085830 , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:159 ======================== THREADS INFO ========================= Id Target Id Frame -* 1 process 1073491036 0x40086009 in UnityPrintNumberUnsigned (number=2) at /builds/espressif/esp-idf/components/unity/unity/src/unity.c:204 - 2 process 1073488552 0x40027733 in vTaskDelay (xTicksToDelay=100) at ../../../hal/esp32s2/include/hal/cpu_ll.h:33 - 3 process 1073484864 set_ocode_by_efuse (calib_version=0) at /builds/espressif/esp-idf/components/esp_hw_support/port/esp32s2/rtc_init.c:226 - 4 process 1073493432 0x40027733 in vTaskDelay (xTicksToDelay=100) at ../../../hal/esp32s2/include/hal/cpu_ll.h:33 +* 1 process 1073493428 0x40085825 in recur_func () at ../main/test_core_dump.c:70 + 2 process 1073490944 0x40027c77 in vTaskDelay (xTicksToDelay=100) at ../../../hal/esp32s2/include/hal/cpu_ll.h:33 + 3 process 1073487224 0x400958b2 in esp_pm_impl_waiti () at ../../../hal/esp32s2/include/hal/cpu_ll.h:202 + 4 process 1073495824 0x40027c77 in vTaskDelay (xTicksToDelay=100) at ../../../hal/esp32s2/include/hal/cpu_ll.h:33 5 process 1073347944 0x4001a8d4 in ?? () -==================== THREAD 1 (TCB: 0x3ffc2c5c, name: 'unaligned_ptr_t') ===================== -#0 0x40086009 in UnityPrintNumberUnsigned (number=2) at /builds/espressif/esp-idf/components/unity/unity/src/unity.c:204 -#1 0x40085fe4 in UnityPrintNumberUnsigned (number=1) at /builds/espressif/esp-idf/components/unity/unity/src/unity.c:196 -#2 0x40085fe4 in UnityPrintNumberUnsigned (number=10) at /builds/espressif/esp-idf/components/unity/unity/src/unity.c:196 -#3 0x4008602c in ?? () at /builds/espressif/esp-idf/components/unity/unity/src/unity.c:206 -Backtrace stopped: previous frame identical to this frame (corrupt stack?) +==================== THREAD 1 (TCB: 0x3ffc35b4, name: 'unaligned_ptr_t') ===================== +#0 0x40085825 in recur_func () at ../main/test_core_dump.c:70 +#1 0x40085800 in recur_func () at ../main/test_core_dump.c:63 +#2 0x40085800 in recur_func () at ../main/test_core_dump.c:63 +#3 0x40085848 in unaligned_ptr_task (pvParameter=0x0) at ../main/test_core_dump.c:80 +#4 0x40028e90 in vPortTaskWrapper (pxCode=0x40085830 , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:159 -==================== THREAD 2 (TCB: 0x3ffc22a8, name: 'bad_ptr_task') ===================== -#0 0x40027733 in vTaskDelay (xTicksToDelay=100) at ../../../hal/esp32s2/include/hal/cpu_ll.h:33 -#1 0x40085fa7 in unaligned_ptr_task (pvParameter=0x0) at ../main/test_core_dump.c:75 -#2 0x400287ec in vPortTaskWrapper (pxCode=0x40085f98 , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:168 +==================== THREAD 2 (TCB: 0x3ffc2c00, name: 'bad_ptr_task') ===================== +#0 0x40027c77 in vTaskDelay (xTicksToDelay=100) at ../../../hal/esp32s2/include/hal/cpu_ll.h:33 +#1 0x400857c3 in bad_ptr_task (pvParameter=0x0) at ../main/test_core_dump.c:43 +#2 0x40028e90 in vPortTaskWrapper (pxCode=0x400857b4 , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:159 -==================== THREAD 3 (TCB: 0x3ffc1440, name: 'IDLE') ===================== -#0 set_ocode_by_efuse (calib_version=0) at /builds/espressif/esp-idf/components/esp_hw_support/port/esp32s2/rtc_init.c:226 -#1 0x40089d36 in esp_register_freertos_tick_hook_for_cpu (new_tick_cb=0x8, cpuid=1) at /builds/espressif/esp-idf/components/esp_system/freertos_hooks.c:94 -#2 0x40027645 in prvIdleTask (pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/tasks.c:3823 -#3 0x400287ec in vPortTaskWrapper (pxCode=0x4002763c , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:168 +==================== THREAD 3 (TCB: 0x3ffc1d78, name: 'IDLE') ===================== +#0 0x400958b2 in esp_pm_impl_waiti () at ../../../hal/esp32s2/include/hal/cpu_ll.h:202 +#1 0x4008a0f2 in esp_vApplicationIdleHook () at /builds/espressif/esp-idf/components/esp_system/freertos_hooks.c:63 +#2 0x40027b81 in prvIdleTask (pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/tasks.c:3909 +#3 0x40028e90 in vPortTaskWrapper (pxCode=0x40027b78 , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:159 -==================== THREAD 4 (TCB: 0x3ffc35b8, name: 'failed_assert_t') ===================== -#0 0x40027733 in vTaskDelay (xTicksToDelay=100) at ../../../hal/esp32s2/include/hal/cpu_ll.h:33 -#1 0x40085eef in bad_ptr_func () at ../main/test_core_dump.c:26 -#2 0x400287ec in vPortTaskWrapper (pxCode=0x40085ee0 , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:168 +==================== THREAD 4 (TCB: 0x3ffc3f10, name: 'failed_assert_t') ===================== +#0 0x40027c77 in vTaskDelay (xTicksToDelay=100) at ../../../hal/esp32s2/include/hal/cpu_ll.h:33 +#1 0x40085703 in failed_assert_task (pvParameter=0x0) at ../main/test_core_dump.c:89 +#2 0x40028e90 in vPortTaskWrapper (pxCode=0x400856f4 , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:159 ==================== THREAD 5 (TCB: 0x3ff9fd68, name: 'esp_timer') ===================== #0 0x4001a8d4 in ?? () -#1 0x4002891c in vPortExitCritical (mux=0x3ffbcff8) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:473 -#2 0x40028226 in ulTaskNotifyTake (xClearCountOnExit=1, xTicksToWait=) at /builds/espressif/esp-idf/components/freertos/tasks.c:5187 -#3 0x4008586c in esp_timer_impl_init_system_time () at /builds/espressif/esp-idf/components/esp_timer/src/system_time.c:43 -#4 0x400287ec in vPortTaskWrapper (pxCode=0x40085860 , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:168 +#1 0x40028fa8 in vPortExitCritical (mux=0x3ffbd918 ) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:447 +#2 0x400287fe in ulTaskGenericNotifyTake (uxIndexToWait=0, xClearCountOnExit=1, xTicksToWait=) at /builds/espressif/esp-idf/components/freertos/tasks.c:5303 +#3 0x40084f0b in timer_task (arg=0x0) at /builds/espressif/esp-idf/components/esp_timer/src/esp_timer.c:392 +#4 0x40028e90 in vPortTaskWrapper (pxCode=0x40084efc , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:159 ======================= ALL MEMORY REGIONS ======================== @@ -111,200 +111,202 @@ Name Address Size Attrs .rtc_noinit 0x50000010 0x0 RW .rtc.force_slow 0x50000010 0x0 RW .iram0.vectors 0x40022000 0x403 R XA -.iram0.text 0x40022404 0xa014 R XA -.dram0.data 0x3ffbc420 0x256c RW A -.noinit 0x3ffbe98c 0x0 RW +.iram0.text 0x40022404 0xa958 R XA +.dram0.data 0x3ffbcd60 0x2548 RW A +.noinit 0x3ffbf2a8 0x0 RW +.ext_ram.bss 0x3f500000 0x0 RW .flash.appdesc 0x3f000020 0x100 R A -.flash.rodata 0x3f000120 0x3764 RW A -.flash.rodata_noload 0x3f003884 0x0 RW -.flash.text 0x40080020 0x15ca3 R XA -.iram0.text_end 0x4002c418 0x0 RW -.dram0.heap_start 0x3ffbf610 0x0 RW -.coredump.tasks.data 0x3ffc2c5c 0x154 RW -.coredump.tasks.data 0x3ffc2af0 0x164 RW -.coredump.tasks.data 0x3ffc22a8 0x154 RW -.coredump.tasks.data 0x3ffc21b0 0xf0 RW -.coredump.tasks.data 0x3ffc1440 0x154 RW -.coredump.tasks.data 0x3ffc1320 0x118 RW -.coredump.tasks.data 0x3ffc35b8 0x154 RW -.coredump.tasks.data 0x3ffc34c0 0xf0 RW +.flash.rodata 0x3f000120 0x37dc RW A +.flash.rodata_noload 0x3f0038fc 0x0 RW +.flash.text 0x40080020 0x1611f R XA +.iram0.text_end 0x4002cd5c 0x0 RW +.dram0.heap_start 0x3ffbff38 0x0 RW +.coredump.tasks.data 0x3ffc35b4 0x154 RW +.coredump.tasks.data 0x3ffc3440 0x16c RW +.coredump.tasks.data 0x3ffc2c00 0x154 RW +.coredump.tasks.data 0x3ffc2b00 0xf8 RW +.coredump.tasks.data 0x3ffc1d78 0x154 RW +.coredump.tasks.data 0x3ffc1c60 0x110 RW +.coredump.tasks.data 0x3ffc3f10 0x154 RW +.coredump.tasks.data 0x3ffc3e10 0xf8 RW .coredump.tasks.data 0x3ff9fd68 0x154 RW .coredump.tasks.data 0x3ff9fc40 0x120 RW ====================== CORE DUMP MEMORY CONTENTS ======================== -.coredump.tasks.data 0x3ffc2c5c 0x154 RW -0x3ffc2c5c: 0x3ffc2b60 0x00000064 0x3ffbec94 0x3ffbec94 -0x3ffc2c6c: 0x3ffc2c5c 0x3ffbec8c 0x00000012 0xfa667cb5 -0x3ffc2c7c: 0xbcf3f475 0x3ffc2c5c 0x00000000 0x00000007 -0x3ffc2c8c: 0x3ffc2458 0x6c616e75 0x656e6769 0x74705f64 -0x3ffc2c9c: 0x00745f72 0x00000000 0x3ffc2c54 0x00000007 -0x3ffc2cac: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc2cbc: 0x3ff9e82c 0x3ff9e894 0x3ff9e8fc 0x00000000 -0x3ffc2ccc: 0x00000000 0x00000001 0x00000000 0x00000000 -0x3ffc2cdc: 0x00000000 0x4001a480 0x00000000 0x00000000 -0x3ffc2cec: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc2cfc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc2d0c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc2d1c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc2d2c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc2d3c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc2d4c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc2d5c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc2d6c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc2d7c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc2d8c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc2d9c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc2dac: 0x3ffc0000 -.coredump.tasks.data 0x3ffc2af0 0x164 RW -0x3ffc2af0: 0xdeadbeef 0x40086009 0x00060d30 0x80085fe4 -0x3ffc2b00: 0x3ffc2b80 0x00000002 0x3ffc2bcc 0x3ffc2bc0 -0x3ffc2b10: 0x00000000 0x3ff9e894 0x00000000 0x00000005 -0x3ffc2b20: 0xffffffad 0x00000020 0x3ffc2cb8 0x3ff9ebb7 -0x3ffc2b30: 0x00000080 0x00000001 0x00000000 0x00000019 -0x3ffc2b40: 0x0000001d 0x00000005 0x3ff9ebb7 0x00000080 -0x3ffc2b50: 0x40023e3d 0x3ffbf534 0x3ff9ea28 0x00000000 -0x3ffc2b60: 0x3ff9ebb7 0x00000080 0x00000001 0x00000000 -0x3ffc2b70: 0x80085fe4 0x3ffc2bb0 0x00000001 0x3ff9e894 -0x3ffc2b80: 0x00000003 0x3ffbd130 0x00000001 0x00000001 -0x3ffc2b90: 0x3ffc2bc0 0x00000000 0x3ff9e894 0x00000000 -0x3ffc2ba0: 0x8008602c 0x3ffc2be0 0x0000000a 0x3ffbcff8 -0x3ffc2bb0: 0x00000003 0x0000001e 0x3f00235c 0x00000001 -0x3ffc2bc0: 0x3ffbedf4 0x3ffc0c10 0x00000800 0x00000000 -0x3ffc2bd0: 0x800287ec 0x3ffc2c10 0x00000000 0x00000000 -0x3ffc2be0: 0x00000003 0x3ffc2c10 0x00000000 0x00000000 -0x3ffc2bf0: 0x00060021 0x3ffc21e0 0x3ffbd130 0x00000064 -0x3ffc2c00: 0x00000000 0x3ffc2c30 0x40086014 0x00000000 -0x3ffc2c10: 0x00060023 0x3ffbeb50 0x00060c23 0x00000001 -0x3ffc2c20: 0x00000000 0x3ffc2c50 0x00000000 0x00000000 -0x3ffc2c30: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc2c40: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc2c50: 0x00000000 -.coredump.tasks.data 0x3ffc22a8 0x154 RW -0x3ffc22a8: 0x3ffc21b0 0x00000064 0x3ffbec6c 0x3ffbec6c -0x3ffc22b8: 0x3ffc22a8 0x3ffbec64 0x00000014 0x918598e6 -0x3ffc22c8: 0xef7ac4fd 0x3ffc22a8 0x00000000 0x00000005 -0x3ffc22d8: 0x3ffc1aa4 0x5f646162 0x5f727470 0x6b736174 -0x3ffc22e8: 0x0010a300 0x00000000 0x3ffc22a0 0x00000005 -0x3ffc22f8: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc2308: 0x3ff9e82c 0x3ff9e894 0x3ff9e8fc 0x00000000 -0x3ffc2318: 0x00000000 0x00000001 0x00000000 0x00000000 -0x3ffc2328: 0x00000000 0x4001a480 0x00000000 0x00000000 -0x3ffc2338: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc2348: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc2358: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc2368: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc2378: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc2388: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc2398: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc23a8: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc23b8: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc23c8: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc23d8: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc23e8: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc23f8: 0x3ffc0000 -.coredump.tasks.data 0x3ffc21b0 0xf0 RW -0x3ffc21b0: 0x40023e98 0x40027733 0x00060230 0x80085fa7 -0x3ffc21c0: 0x3ffc2240 0x00000064 0x3ffbcff8 0x00060021 -0x3ffc21d0: 0x3ffbeb50 0x00060b23 0x00000059 0x80027733 -0x3ffc21e0: 0x3ffc2220 0x00000000 0x00000064 0x3ffbedf4 -0x3ffc21f0: 0x3ffc0c10 0x00000800 0x00000000 0x0000001b -0x3ffc2200: 0x0000ffff 0x00000000 0x40023f00 0x3ffc0c10 -0x3ffc2210: 0x40026670 0x3ffbeb84 0x00000000 0x00000000 -0x3ffc2220: 0x3ffc0c40 0x3ffc0c10 0x00000800 0x00000000 -0x3ffc2230: 0x800287ec 0x3ffc2260 0x00000000 0x00000000 -0x3ffc2240: 0x00060021 0x3ffbeb50 0x00060b23 0x00000059 -0x3ffc2250: 0x00000000 0x3ffc2280 0x40085f98 0x00000000 -0x3ffc2260: 0x00060023 0x3ffbeb50 0x00060723 0x3ffc0b30 -0x3ffc2270: 0x00000000 0x3ffc22a0 0x00000000 0x00000000 -0x3ffc2280: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc2290: 0x00000000 0x00000000 0x00000000 0x00000000 -.coredump.tasks.data 0x3ffc1440 0x154 RW -0x3ffc1440: 0x3ffc1320 0x3ffbf614 0x3ffbec08 0x3ffbec08 -0x3ffc1450: 0x3ffc1440 0x3ffbec00 0x00000019 0x36c2078e -0x3ffc1460: 0xa9ff0bc8 0x3ffc1440 0x00000000 0x00000000 -0x3ffc1470: 0x3ffc0e3c 0x454c4449 0x610cee00 0x7205f331 -0x3ffc1480: 0x00bf07a7 0x00000000 0x3ffc1438 0x00000000 -0x3ffc1490: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc14a0: 0x3ff9e82c 0x3ff9e894 0x3ff9e8fc 0x00000000 -0x3ffc14b0: 0x00000000 0x00000001 0x00000000 0x00000000 -0x3ffc14c0: 0x00000000 0x4001a480 0x00000000 0x00000000 -0x3ffc14d0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc14e0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc14f0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc1500: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc1510: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc1520: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc1530: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc1540: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc1550: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc1560: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc1570: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc1580: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc1590: 0x3ffc0000 -.coredump.tasks.data 0x3ffc1320 0x118 RW -0x3ffc1320: 0x40023e98 0x400954ee 0x00060530 0x80089d36 -0x3ffc1330: 0x3ffc13b0 0x00000000 0x00000001 0x00000001 -0x3ffc1340: 0x80000001 0x00060023 0x00000000 0x8008a21e -0x3ffc1350: 0x3ffc1380 0x00000000 0x4001a480 0x00060020 -0x3ffc1360: 0x6000c000 0x00000000 0x0000004b 0x0000001e -0x3ffc1370: 0x0000ffff 0x00000000 0x40023f00 0x6000c000 -0x3ffc1380: 0x40026670 0x3ffbdd14 0xa5a5a5a5 0xa5a5a5a5 -0x3ffc1390: 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 -0x3ffc13a0: 0x80027645 0x3ffc13d0 0x00000008 0x00000001 -0x3ffc13b0: 0x3ffc1430 0x00000000 0x00000000 0x00000000 -0x3ffc13c0: 0x800287ec 0x3ffc13f0 0x00000000 0x00000000 -0x3ffc13d0: 0x00060021 0x3ffc0c10 0x3ffbd130 0x00000001 -0x3ffc13e0: 0x00000000 0x3ffc1410 0x4002763c 0x00000000 -0x3ffc13f0: 0x00060023 0x3ffc0c30 0x3f4c0058 0x00000001 -0x3ffc1400: 0x00000000 0x3ffc1430 0x00000000 0x00000000 -0x3ffc1410: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc1420: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc1430: 0x00000000 0x00000000 -.coredump.tasks.data 0x3ffc35b8 0x154 RW -0x3ffc35b8: 0x3ffc34c0 0x000000c8 0x3ffbebf4 0x3ffbebf4 -0x3ffc35c8: 0x3ffc35b8 0x3ffbebec 0x0000000f 0x382ec478 -0x3ffc35d8: 0x7ba73f68 0x3ffc35b8 0x00000000 0x0000000a -0x3ffc35e8: 0x3ffc2db4 0x6c696166 0x615f6465 0x72657373 -0x3ffc35f8: 0x00745f74 0x00000000 0x3ffc35b0 0x0000000a -0x3ffc3608: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc3618: 0x3ff9e82c 0x3ff9e894 0x3ff9e8fc 0x00000000 -0x3ffc3628: 0x00000000 0x00000001 0x00000000 0x00000000 -0x3ffc3638: 0x00000000 0x4001a480 0x00000000 0x00000000 -0x3ffc3648: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc3658: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc3668: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc3678: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc3688: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc3698: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc36a8: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc36b8: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc36c8: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc36d8: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc36e8: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc36f8: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc3708: 0x3ffc0000 -.coredump.tasks.data 0x3ffc34c0 0xf0 RW -0x3ffc34c0: 0x40023e98 0x40027733 0x00060730 0x80085eef -0x3ffc34d0: 0x3ffc3550 0x00000064 0x3ffbcff8 0x00060021 -0x3ffc34e0: 0x3ffc2b90 0x3ffbd130 0x00000064 0x80027733 -0x3ffc34f0: 0x3ffc3530 0x00000000 0x000000c8 0x3ffbedf4 -0x3ffc3500: 0x3ffc0c10 0x00000800 0x00000000 0x00000016 -0x3ffc3510: 0x0000ffff 0x00000000 0x40023f00 0x3ffc0c10 -0x3ffc3520: 0x40026670 0x3ffbfe94 0x00000000 0x00000000 -0x3ffc3530: 0x3ffbedf4 0x3ffc0c10 0x00000800 0x00000000 -0x3ffc3540: 0x800287ec 0x3ffc3570 0x00000000 0x00000000 -0x3ffc3550: 0x00060021 0x3ffc2b90 0x3ffbd130 0x00000064 -0x3ffc3560: 0x00000000 0x3ffc3590 0x40085ee0 0x00000000 -0x3ffc3570: 0x00060023 0x3ffbeb50 0x00060123 0x00000001 -0x3ffc3580: 0x00000000 0x3ffc35b0 0x00000000 0x00000000 +.coredump.tasks.data 0x3ffc35b4 0x154 RW +0x3ffc35b4: 0x3ffc34b0 0x00000065 0x3ffbf5a4 0x3ffbf5a4 +0x3ffc35c4: 0x3ffc35b4 0x3ffbf59c 0x00000012 0x59d00ee6 +0x3ffc35d4: 0x5209b6d9 0x3ffc35b4 0x00000000 0x00000007 +0x3ffc35e4: 0x3ffc2db0 0x6c616e75 0x656e6769 0x74705f64 +0x3ffc35f4: 0x00745f72 0x00000000 0x3ffc35ac 0x00000007 +0x3ffc3604: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc3614: 0x3ff9e82c 0x3ff9e894 0x3ff9e8fc 0x00000000 +0x3ffc3624: 0x00000000 0x00000001 0x00000000 0x00000000 +0x3ffc3634: 0x00000000 0x4001a480 0x00000000 0x00000000 +0x3ffc3644: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc3654: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc3664: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc3674: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc3684: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc3694: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc36a4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc36b4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc36c4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc36d4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc36e4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc36f4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc3704: 0x3ffc0000 +.coredump.tasks.data 0x3ffc3440 0x16c RW +0x3ffc3440: 0xdeadbeef 0x40085825 0x00060d30 0x80085800 +0x3ffc3450: 0x3ffc34d0 0x00000002 0x3ffc351c 0x3ffc3510 +0x3ffc3460: 0x00000000 0x3ff9e894 0x00000000 0x00000005 +0x3ffc3470: 0xffffffad 0x00000020 0x3ffc3610 0x3ff9ebb7 +0x3ffc3480: 0x00000080 0x00000001 0x00000000 0x00000019 +0x3ffc3490: 0x0000001d 0x00000005 0x3ff9ebb7 0x00000080 +0x3ffc34a0: 0x40023f2d 0x3ffbfdb4 0x3ff9ea28 0x00000000 +0x3ffc34b0: 0x3ff9ebb7 0x00000080 0x00000001 0x00000000 +0x3ffc34c0: 0x80085800 0x3ffc3500 0x00000001 0x3ff9e894 +0x3ffc34d0: 0x00000003 0x3ffbda80 0x00000001 0x00000001 +0x3ffc34e0: 0x3ffc3510 0x00000000 0x3ff9e894 0x00000000 +0x3ffc34f0: 0x80085848 0x3ffc3530 0x0000000a 0x3ffbd918 +0x3ffc3500: 0x00000003 0x0000001e 0x3f002430 0x00000001 +0x3ffc3510: 0x3ffbf704 0x3ffc1550 0x00000800 0x00000000 +0x3ffc3520: 0x80028e90 0x3ffc3560 0x00000000 0x00000000 +0x3ffc3530: 0x00000003 0x3ffc3560 0x00000000 0x00000000 +0x3ffc3540: 0x00060021 0x3ffc2b30 0x3ffbda80 0x00000065 +0x3ffc3550: 0x00000000 0x3ffc3580 0x40085830 0x00000000 +0x3ffc3560: 0x00060023 0x3ffbf460 0x00060c23 0x00000001 +0x3ffc3570: 0x00000000 0x3ffc35a0 0x00000000 0x00000000 +0x3ffc3580: 0x00000000 0x00000000 0x00000000 0x00000000 0x3ffc3590: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffc35a0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc35a0: 0x00000000 0x00000000 0x00000000 +.coredump.tasks.data 0x3ffc2c00 0x154 RW +0x3ffc2c00: 0x3ffc2b00 0x00000065 0x3ffbf57c 0x3ffbf57c +0x3ffc2c10: 0x3ffc2c00 0x3ffbf574 0x00000014 0x950586b2 +0x3ffc2c20: 0x7fe87e09 0x3ffc2c00 0x00000000 0x00000005 +0x3ffc2c30: 0x3ffc23fc 0x5f646162 0x5f727470 0x6b736174 +0x3ffc2c40: 0x00ba4c00 0x00000000 0x3ffc2bf8 0x00000005 +0x3ffc2c50: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc2c60: 0x3ff9e82c 0x3ff9e894 0x3ff9e8fc 0x00000000 +0x3ffc2c70: 0x00000000 0x00000001 0x00000000 0x00000000 +0x3ffc2c80: 0x00000000 0x4001a480 0x00000000 0x00000000 +0x3ffc2c90: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc2ca0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc2cb0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc2cc0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc2cd0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc2ce0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc2cf0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc2d00: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc2d10: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc2d20: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc2d30: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc2d40: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc2d50: 0x3ffc0000 +.coredump.tasks.data 0x3ffc2b00 0xf8 RW +0x3ffc2b00: 0x40023f88 0x40027c77 0x00060230 0x800857c3 +0x3ffc2b10: 0x3ffc2b90 0x00000064 0x3ffbd918 0x00060021 +0x3ffc2b20: 0x3ffbd860 0x3f420000 0xb83fc000 0x80027c77 +0x3ffc2b30: 0x3ffc2b70 0x00000000 0x00000065 0x3ffbf704 +0x3ffc2b40: 0x3ffc1550 0x00000800 0x00000000 0x0000001b +0x3ffc2b50: 0x0000ffff 0x00000000 0x40023ff0 0x3ffc1550 +0x3ffc2b60: 0x40026a80 0x3ffbf404 0x00000000 0x00000000 +0x3ffc2b70: 0x00000000 0x3ffc1550 0x00000800 0x00000000 +0x3ffc2b80: 0x80028e90 0x3ffc2bb0 0x00000000 0x00000000 +0x3ffc2b90: 0x00060021 0x3ffbd860 0x3f420000 0xb83fc000 +0x3ffc2ba0: 0x00000000 0x3ffc2bd0 0x400857b4 0x00000000 +0x3ffc2bb0: 0x00060023 0x3ffbf460 0x00060923 0x00000001 +0x3ffc2bc0: 0x00000000 0x3ffc2bf0 0x00000000 0x00000000 +0x3ffc2bd0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc2be0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc2bf0: 0x00000000 0x00000000 +.coredump.tasks.data 0x3ffc1d78 0x154 RW +0x3ffc1d78: 0x3ffc1c60 0x3ffbff4c 0x3ffbf518 0x3ffbf518 +0x3ffc1d88: 0x3ffc1d78 0x3ffbf510 0x00000019 0x82a4bcff +0x3ffc1d98: 0xae0b91fe 0x3ffc1d78 0x00000000 0x00000000 +0x3ffc1da8: 0x3ffc1774 0x454c4449 0xfa9c7a00 0x472c88cf +0x3ffc1db8: 0x00b8acc4 0x00000000 0x3ffc1d70 0x00000000 +0x3ffc1dc8: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc1dd8: 0x3ff9e82c 0x3ff9e894 0x3ff9e8fc 0x00000000 +0x3ffc1de8: 0x00000000 0x00000001 0x00000000 0x00000000 +0x3ffc1df8: 0x00000000 0x4001a480 0x00000000 0x00000000 +0x3ffc1e08: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc1e18: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc1e28: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc1e38: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc1e48: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc1e58: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc1e68: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc1e78: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc1e88: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc1e98: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc1ea8: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc1eb8: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc1ec8: 0x3ffc0000 +.coredump.tasks.data 0x3ffc1c60 0x110 RW +0x3ffc1c60: 0x40023f88 0x400958b2 0x00060530 0x8008a0f2 +0x3ffc1c70: 0x3ffc1cf0 0x00000000 0x00000001 0x00000001 +0x3ffc1c80: 0x80000001 0x00060023 0x00000000 0x8008a5da +0x3ffc1c90: 0x3ffc1cc0 0x00000000 0x4001a480 0x00060020 +0x3ffc1ca0: 0x6000c000 0x00000000 0x0000004b 0x0000001e +0x3ffc1cb0: 0x0000ffff 0x00000000 0x40023ff0 0x6000c000 +0x3ffc1cc0: 0x40026a80 0x3ffbe584 0xa5a5a5a5 0xa5a5a5a5 +0x3ffc1cd0: 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 +0x3ffc1ce0: 0x80027b81 0x3ffc1d10 0x00000008 0x00000001 +0x3ffc1cf0: 0x3ffc1d70 0x00000000 0x00000000 0x00000000 +0x3ffc1d00: 0x80028e90 0x3ffc1d30 0x00000000 0x00000000 +0x3ffc1d10: 0x00060021 0x3ffc1550 0x3ffbda80 0x00000001 +0x3ffc1d20: 0x00000000 0x3ffc1d50 0x40027b78 0x00000000 +0x3ffc1d30: 0x00060023 0x3ffc1570 0x3f4c0058 0x00000001 +0x3ffc1d40: 0x00000000 0x3ffc1d70 0x00000000 0x00000000 +0x3ffc1d50: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc1d60: 0x00000000 0x00000000 0x00000000 0x00000000 +.coredump.tasks.data 0x3ffc3f10 0x154 RW +0x3ffc3f10: 0x3ffc3e10 0x000000c9 0x3ffbf504 0x3ffbf504 +0x3ffc3f20: 0x3ffc3f10 0x3ffbf4fc 0x0000000f 0x2811aa75 +0x3ffc3f30: 0xabd28ba4 0x3ffc3f10 0x00000000 0x0000000a +0x3ffc3f40: 0x3ffc370c 0x6c696166 0x615f6465 0x72657373 +0x3ffc3f50: 0x00745f74 0x00000000 0x3ffc3f08 0x0000000a +0x3ffc3f60: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc3f70: 0x3ff9e82c 0x3ff9e894 0x3ff9e8fc 0x00000000 +0x3ffc3f80: 0x00000000 0x00000001 0x00000000 0x00000000 +0x3ffc3f90: 0x00000000 0x4001a480 0x00000000 0x00000000 +0x3ffc3fa0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc3fb0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc3fc0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc3fd0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc3fe0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc3ff0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc4000: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc4010: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc4020: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc4030: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc4040: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc4050: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc4060: 0x3ffc0000 +.coredump.tasks.data 0x3ffc3e10 0xf8 RW +0x3ffc3e10: 0x40023f88 0x40027c77 0x00060730 0x80085703 +0x3ffc3e20: 0x3ffc3ea0 0x00000064 0x3ffbd918 0x00060021 +0x3ffc3e30: 0x3ffc34e0 0x3ffbda80 0x00000065 0x80027c77 +0x3ffc3e40: 0x3ffc3e80 0x00000000 0x000000c9 0x3ffbf704 +0x3ffc3e50: 0x3ffc1550 0x00000800 0x00000000 0x00000016 +0x3ffc3e60: 0x0000ffff 0x00000000 0x40023ff0 0x3ffc1550 +0x3ffc3e70: 0x40026a80 0x3ffc0714 0x00000000 0x00000000 +0x3ffc3e80: 0x3ffbf704 0x3ffc1550 0x00000800 0x00000000 +0x3ffc3e90: 0x80028e90 0x3ffc3ec0 0x00000000 0x00000000 +0x3ffc3ea0: 0x00060021 0x3ffc34e0 0x3ffbda80 0x00000065 +0x3ffc3eb0: 0x00000000 0x3ffc3ee0 0x400856f4 0x00000000 +0x3ffc3ec0: 0x00060023 0x3ffbf460 0x00060123 0x00000001 +0x3ffc3ed0: 0x00000000 0x3ffc3f00 0x00000000 0x00000000 +0x3ffc3ee0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc3ef0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffc3f00: 0x00000000 0x00000000 .coredump.tasks.data 0x3ff9fd68 0x154 RW -0x3ff9fd68: 0x3ff9fc40 0x3ff9e014 0x3ffbeb98 0x3ffbeb98 -0x3ff9fd78: 0x3ff9fd68 0x3ffbeb90 0x00000003 0x4d870b8b -0x3ff9fd88: 0xedf62148 0x3ff9fd68 0x00000000 0x00000016 -0x3ff9fd98: 0x3ff9ed64 0x5f707365 0x656d6974 0x0e920072 -0x3ff9fda8: 0x00736207 0x00000000 0x3ff9fd60 0x00000016 +0x3ff9fd68: 0x3ff9fc40 0x3ff9e014 0x3ffbf4a8 0x3ffbf4a8 +0x3ff9fd78: 0x3ff9fd68 0x3ffbf4a0 0x00000003 0x4e7c8f11 +0x3ff9fd88: 0x11c0c12e 0x3ff9fd68 0x00000000 0x00000016 +0x3ff9fd98: 0x3ff9ed64 0x5f707365 0x656d6974 0x0c540072 +0x3ff9fda8: 0x004aa853 0x00000000 0x3ff9fd60 0x00000016 0x3ff9fdb8: 0x00000000 0x00000000 0x00000000 0x00000000 0x3ff9fdc8: 0x3ff9e82c 0x3ff9e894 0x3ff9e8fc 0x00000000 0x3ff9fdd8: 0x00000000 0x00000001 0x00000000 0x00000000 @@ -323,24 +325,24 @@ Name Address Size Attrs 0x3ff9fea8: 0x00000000 0x00000000 0x00000000 0x00000000 0x3ff9feb8: 0x3ff90001 .coredump.tasks.data 0x3ff9fc40 0x120 RW -0x3ff9fc40: 0x40023e98 0x4001a8d4 0x00060e30 0x8002891c +0x3ff9fc40: 0x40023f88 0x4001a8d4 0x00060e30 0x80028fa8 0x3ff9fc50: 0x3ff9fcd0 0x00060e23 0x00000000 0x00060e20 -0x3ff9fc60: 0x3fffde70 0x3fffdec0 0x00000004 0x80025339 -0x3ff9fc70: 0x3ff9fca0 0x3ffbd130 0x00000000 0x3fffe2d0 -0x3ff9fc80: 0x3fffe2b0 0x3f408000 0x3f000220 0x0000000a -0x3ff9fc90: 0x0000ffff 0x00000000 0x40023f00 0x3fffe2b0 -0x3ff9fca0: 0x40026670 0x3ff9c644 0xa5a5a5a5 0xa5a5a5a5 +0x3ff9fc60: 0x3fffde70 0x3fffdec0 0x00000004 0x80025745 +0x3ff9fc70: 0x3ff9fca0 0x3ffbda80 0x00000000 0x3fffe2d0 +0x3ff9fc80: 0x3fffe2b0 0x3f408000 0x3f000270 0x0000000a +0x3ff9fc90: 0x0000ffff 0x00000000 0x40023ff0 0x3fffe2b0 +0x3ff9fca0: 0x40026a80 0x3ff9c574 0xa5a5a5a5 0xa5a5a5a5 0x3ff9fcb0: 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 -0x3ff9fcc0: 0x80028226 0x3ff9fce0 0x3ffbcff8 0x00000000 -0x3ff9fcd0: 0x8008586c 0x3ff9fd00 0x3ff9fe68 0x3ffbcff8 +0x3ff9fcc0: 0x800287fe 0x3ff9fce0 0x3ffbd918 0x00000000 +0x3ff9fcd0: 0x80084f0b 0x3ff9fd00 0x00000000 0x00000001 0x3ff9fce0: 0x00000000 0x3fffe1d0 0x00060123 0x00000000 -0x3ff9fcf0: 0x800287ec 0x3ff9fd20 0x00000000 0x00000000 -0x3ff9fd00: 0x00000001 0x3fffe1f0 0x00060123 0x00000000 -0x3ff9fd10: 0x00000000 0x3ff9fd40 0x40085860 0x00000000 -0x3ff9fd20: 0x00060123 0x3ffbeb58 0x00000000 0x00000001 +0x3ff9fcf0: 0x80028e90 0x3ff9fd20 0x00000000 0x00000000 +0x3ff9fd00: 0x3ffbd918 0x3ffbf468 0x00000000 0x00000000 +0x3ff9fd10: 0x00000000 0x3ff9fd40 0x40084efc 0x00000000 +0x3ff9fd20: 0x00060123 0x3fffe230 0x01a2c356 0x4002cd18 0x3ff9fd30: 0x00000000 0x3ff9fd60 0x00000000 0x00000000 0x3ff9fd40: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ff9fd50: 0x80095b37 0x3fffe280 0x3ffbeb88 0x00000000 +0x3ff9fd50: 0x80095f3f 0x3fffe280 0x3ffbf498 0x00000000 ===================== ESP32 CORE DUMP END ===================== =============================================================== diff --git a/components/espcoredump/test/esp32s3/core.elf b/components/espcoredump/test/esp32s3/core.elf new file mode 100644 index 0000000000..f8d17b9442 Binary files /dev/null and b/components/espcoredump/test/esp32s3/core.elf differ diff --git a/components/espcoredump/test/esp32s3/coredump.b64 b/components/espcoredump/test/esp32s3/coredump.b64 new file mode 100644 index 0000000000..79e4ba94b9 --- /dev/null +++ b/components/espcoredump/test/esp32s3/coredump.b64 @@ -0,0 +1,327 @@ +fDUAAAABCQAAAAAAAAAAAAAAAAA= +f0VMRgEBAQAAAAAAAAAAAAQAXgABAAAAAAAAADQAAAAAAAAAAAAAADQAIAASACgA +AAAAAA== +BAAAAHQCAAAAAAAAAAAAAAATAAAAEwAABgAAAAAAAAA= +AQAAAHQVAACUHM4/lBzOP1gBAABYAQAABgAAAAAAAAA= +AQAAAMwWAADAGc4/wBnOP8wCAADMAgAABgAAAAAAAAA= +AQAAAJgZAACoSs8/qErPP1gBAABYAQAABgAAAAAAAAA= +AQAAAPAaAAAgSM8/IEjPP4ACAACAAgAABgAAAAAAAAA= +AQAAAHAdAAAIUs8/CFLPP1gBAABYAQAABgAAAAAAAAA= +AQAAAMgeAACAT88/gE/PP4ACAACAAgAABgAAAAAAAAA= +AQAAAEghAAD0Jc4/9CXOP1gBAABYAQAABgAAAAAAAAA= +AQAAAKAiAACQI84/kCPOP1wCAABcAgAABgAAAAAAAAA= +AQAAAPwkAAA0E84/NBPOP1gBAABYAQAABgAAAAAAAAA= +AQAAAFQmAADQEM4/0BDOP1wCAABcAgAABgAAAAAAAAA= +AQAAALAoAADgGc8/4BnPP1gBAABYAQAABgAAAAAAAAA= +AQAAAAgqAABQF88/UBfPP4gCAACIAgAABgAAAAAAAAA= +AQAAAJAsAACoMc8/qDHPP1gBAABYAQAABgAAAAAAAAA= +AQAAAOgtAAAQL88/EC/PP5ACAACQAgAABgAAAAAAAAA= +AQAAAHgwAABIIM8/SCDPP1gBAABYAQAABgAAAAAAAAA= +AQAAANAxAADAHc8/wB3PP4ACAACAAgAABgAAAAAAAAA= +BAAAAFA0AAAAAAAAAAAAABQBAAAUAQAABgAAAAAAAAA= +CAAAAEwCAAABAAAA +Q09SRQAAAAA= +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlBzOPwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeU4AQiAGBgDVVgVA5VYFQPj///8AAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFROAIKAGs4/ +AgAAAMwazj/AGs4/AAAAACQIzz8BAAAABQAAAK3///8gAAAA9BzOPwEAAACAAAAA +AAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAA +CAAAAEwCAAABAAAA +Q09SRQAAAAA= +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqErPPwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApogBQiAFBgAAAAAAAAAAAAAAAAAeAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKocAILgSM8/ +AAAAAAEAAAABAAAAAQAAgCMABgAAAAAAjp4AgrBIzz8AAAAATKYAQiABBgAjAQYA +AQAAABwAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAA +CAAAAEwCAAABAAAA +Q09SRQAAAAA= +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACFLPPwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApogBQiAMBgAAAAAAAAAAAAAAAAAeAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKocAIJAUM8/ +AAAAAAAAAAABAAAAAQAAgOQtyT8AAAAAjp4AghBQzz8AAAAAAAAAACAMBgAjDAYA +AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAA +CAAAAEwCAAABAAAA +Q09SRQAAAAA= +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9CXOPwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIqI3QCAHBgDVVgVA5VYFQPj///8AAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEpNAIJQJM4/ +ZAAAAKARyT8hAAYAIwAGAAEAAAAAAAAAIqI3gDAkzj8AAAAAygAAAMgwyT9AQc8/ +AAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAA +CAAAAEwCAAABAAAA +Q09SRQAAAAA= +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBPOPwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIqI3QCAJBgDVVgVA5VYFQPn///8PAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABZOAIKQEc4/ +ZAAAAKARyT8hAAYAIwAGAAEAAAAAAAAAIqI3gHARzj8AAAAAygAAAMgwyT+lpaWl +paWlpQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAA +CAAAAEwCAAABAAAA +Q09SRQAAAAA= +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4BnPPwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxZo3QCAABgAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9oN4AQGM8/ +hBXPP9AVzz8BAAAAAQAAAAAAAAAAAACAxZo3gPAXzz8AAAAA/////9AVzz8AAAAA +ADACYP//DwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAA +CAAAAEwCAAABAAAA +Q09SRQAAAAA= +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqDHPPwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4FkFQCAABgAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIq7N4DQL88/ +IwAGAAAAAAAgAAYAIwAGAAEAAABgss4/PX03gKAvzz/sLck/AAAAAJAYzz9wGM8/ +5Gc3QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAA +CAAAAEwCAAABAAAA +Q09SRQAAAAA= +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASCDPPwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1Jk3QCAIBgAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9oN4CAHs8/ +7BvPPzgczz8BAAAAAQAAAAAAAAABAAAAxZo3gGAezz8BAAAA/////zgczz9QQ88/ +AQAAAOgoDGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAA +UBrOP1Abzj9mAAAAaC/JP2gvyT+UHM4/YC/JPxIAAADkCc8/5AnPP5Qczj8AAAAA +BwAAAJAUzj91bmFsaWduZWRfcHRyX3QAAQAAAIwczj8HAAAAAAAAAAAAAAAAAAAA +AAAAALwHzz8kCM8/jAjPPwAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAEymAEIAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAzj8= +776t3nlOAEIwBgYAVE4AgoAazj8CAAAAzBrOP8Aazj8AAAAAJAjPPwEAAAAFAAAA +rf///yAAAAD0HM4/AQAAAIAAAAAAAAAAAQAAAAAAAAAdAAAABQAAANVWBUDlVgVA ++P///wEAAACAAAAApF43QOznzT8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA +AAAAAAEAAAC4Cc8/AAAAAAEAAACAAAAAAAAAAAEAAABUTgCCsBrOPwEAAAAkCM8/ +AwAAAGQAAAABAAAAAAAAAMAazj8AAAAAJAjPPwEAAACfTgCC4BrOPwoAAACgEck/ +AwAAAB4AAADcHwI8AQAAAAAAAAClpaWlpaWlpWUAAAB0uTeAEBvOPwAAAAAAAAAA +AwAAABAbzj8AAAAAAAAAACEABgAjAAYAAQAAAAEAAAAAAAAAMBvOP4ROAEIAAAAA +IwAGAGgvyT+UHM4/AAAAAAAAAABQG84/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYBvOPwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= +IEjPP2BJzz8ZE8oSEFLPP9wuyT+oSs8/1C7JPxkAAABOOGu2TF9PNKhKzz8AAAAA +AAAAAKREzz9JRExFANi+vtYXz7bHi9gAAAAAAKBKzz8AAAAAAAAAAAAAAAAAAAAA +AAAAALwHzz8kCM8/jAjPPwAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAEymAEIAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAzz8= +CF83QKaIAUIwBQYAqhwAguBIzz8AAAAAAQAAAAEAAAABAACAIwAGAAAAAACOngCC +sEjPPwAAAABMpgBCIAEGACMBBgABAAAAHAAAYB4AAAD//wAAAAAAAAAAAAAAAAAA +AAAAABBiN0AjAQYA2I03QPwVzz8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAC8nzdAAAAAAAAAAADInzeAAEnPPwgAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAHS5N4AgSc8/AAAAAAAAAAABAAAAIwAGAAEAAAAKAAAA +AAAAAEBJzz+8nzdAAAAAACMABgDcLsk/CFLPPwAAAAAAAAAAYEnPPwAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBJzz8AAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAA== +gE/PP8BQzz+ajnuM3C7JP7BKzz8IUs8/1C7JPxkAAAAi7aG5MPHYgwhSzz8AAAAA +AAAAAARMzz9JRExFAHXx9YtsRN/cEk8AAQAAAABSzz8AAAAAAAAAAAAAAAAAAAAA +AAAAALwHzz8kCM8/jAjPPwAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAEymAEIAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAzz8= +CF83QKaIAUIwDAYAqhwAgkBQzz8AAAAAAAAAAAEAAAABAACA5C3JPwAAAACOngCC +EFDPPwAAAAAAAAAAIAwGACMMBgABAAAAAAAAAB4AAAD//wAAAAAAAAAAAAAAAAAA +AAAAABBiN0AjDAYA2I03QFwdzz8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAC8nzdAAAAAAAAAAADInzeAYFDPPwgAAAABAAAA +AAAAAAAAAAAAAAAAAAAAAHS5N4CAUM8/AAAAAAAAAAABAAAAIwAGAAEAAAABAAAA +AAAAAKBQzz+8nzdAAAAAACMABgDcLsk/qErPPwAAAAAAAAAAwFDPPwAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBQzz8AAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAA== +kCPOP7Akzj/KAAAAPBPOP8guyT/0Jc4/wC7JPw8AAACwHM4/5AnPP/Qlzj8AAAAA +CgAAAPAdzj9mYWlsZWRfYXNzZXJ0X3QAAAAAAOwlzj8KAAAAAAAAAAAAAAAAAAAA +AAAAALwHzz8kCM8/jAjPPwAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAEymAEIAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAzj8= +CF83QCKiN0AwBwYASk0AglAkzj9kAAAAoBHJPyEABgAjAAYAAQAAAAAAAAAiojeA +MCTOPwAAAADKAAAAyDDJP0BBzz8ACAAAAAAAAAAAAAD//wAAAAAAANVWBUDlVgVA ++P///xBiN0BAQc8/2I03QEzxzT8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA +AAAAAAIAAAAAAAAAAAAAAMgwyT9AQc8/AAgAAAAAAAB0uTeAcCTOPwAAAAAAAAAA +IQAGACMABgABAAAAAAAAAAAAAACQJM4/OE0AQgAAAAAjAAYApC/JP/Qlzj8AAAAA +AAAAALAkzj8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAADAJM4/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +0BDOP/ARzj/KAAAAyC7JP/wlzj80E84/wC7JPxQAAAC0FQg4DGkwtTQTzj8AAAAA +BQAAADALzj9iYWRfcHRyX3Rhc2sA0YIA////fywTzj8FAAAAAAAAAAAAAAAAAAAA +AAAAALwHzz8kCM8/jAjPPwAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAEymAEIAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAzj8= +CF83QCKiN0AwCQYAFk4AgpARzj9kAAAAoBHJPyEABgAjAAYAAQAAAAAAAAAiojeA +cBHOPwAAAADKAAAAyDDJP6WlpaWlpaWlAQAAAA8AAAD//wAAAAAAANVWBUDlVgVA ++f///xBiN0ClpaWl2I03QIzezT8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA +AAAAAAIAAAAAAAAAAAAAAAAAAAClpaWlpaWlpQEAAAB0uTeAsBHOPwAAAAAAAAAA +IQAGACMABgABAAAAAAAAAAAAAADQEc4/BE4AQgAAAAAjAAYAQC/JPzQTzj8AAAAA +AAAAAPARzj8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAEs4/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +UBfPP5AYzz/u1sPesDHPP1guyT/gGc8/UC7JPwEAAACwFc8/sBXPP+AZzz+oFc8/ +GAAAANwVzz9pcGMwANYZW0TaWLfwhgkAAAAAANgZzz8YAAAAAAAAAAAAAAAAAAAA +AAAAALwHzz8kCM8/jAjPPwAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAEymAEIAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAzz8= +CF83QMWaN0AwAAYAD2g3gBAYzz+EFc8/0BXPPwEAAAABAAAAAAAAAAAAAIDFmjeA +8BfPPwAAAAD/////0BXPPwAAAAAAMAJg//8PAAAAAAD//wAAAAAAAAAAAAAAAAAA +AAAAABBiN0AAAAAA2I03QCzlzj8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAADkZzdAAAAAAAAAAAB0uTeAUBjPPwAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAP////8AAAAAAAAAAAAAAAAAAAAAEGI3QAAAAADYjTdA +AAAAAHAYzz/kZzdAAAAAAAAAAAAAAAAA4BnPPwEAAAAAAAAAkBjPPwAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAYzz8AAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +EC/PP2Awzz/f1lxGUCDPP+gZzz+oMc8/UC7JPwMAAABPw9jncFiNf6gxzz8AAAAA +FgAAAKQhzz9lc3BfdGltZXIASV/uw80AAAAAAKAxzz8WAAAAAAAAAAAAAAAAAAAA +AAAAALwHzz8kCM8/jAjPPwAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAEymAEIAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAEAzz8= +CF83QOBZBUAwAAYAirs3gNAvzz8jAAYAAAAAACAABgAjAAYAAQAAAGCyzj89fTeA +oC/PP+wtyT8AAAAAkBjPP3AYzz/kZzdAAAAAAAAAAAD//wAAAAAAAAAAAAAAAAAA +AAAAABBiN0BwGM8/2I03QPz8zj8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA +AAAAAGy5N0AwAAUAAAAAAGAwzz8AAAAAAAAAAAAAAAAKszeA4C/PP+QtyT8AAAAA +z0cAggAwzz8AAAAAAQAAAAAAAACgF88/IwAGAAAAAAB0uTeAIDDPPwAAAAAAAAAA +oBHJPyMABgABAAAAAAAAAAAAAABAMM8/wEcAQgAAAAAjAAYAlDDJP6gxzz8AAAAA +AAAAAGAwzz8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAABwMM8/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= +wB3PPwAfzz/MCnr9WC7JP7Axzz9IIM8/UC7JPwEAAAAYHM8/GBzPP0ggzz8QHM8/ +GAAAAEQczz9pcGMxAEzHCPUTC3I+gMAAAQAAAEAgzz8YAAAAAAAAAAAAAAAAAAAA +AAAAALwHzz8kCM8/jAjPPwAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAEymAEIAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAzz8= +CF83QNSZN0AwCAYAD2g3gIAezz/sG88/OBzPPwEAAAABAAAAAAAAAAEAAADFmjeA +YB7PPwEAAAD/////OBzPP1BDzz8BAAAA6CgMYAAAAAD//wAAAAAAAAAAAAAAAAAA +AAAAABBiN0BQQ88/2I03QJzrzj8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAP//P7MAAAAAAAAAAAAAAAB0uTeAwB7PPwEAAAAAAAAA +AAAAAAIAAAAAAAAAAAAAAP/////AHs8/AQAAAGBrN0AAAAAAAAAAAAAAAAAAAAAA +AAAAAOAezz/kZzdAAQAAAAEAAAC8MMk/SCDPPwAAAAAAAAAAAB/PPwAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAfzz8AAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAA== +FAAAAEgAAABKIAAA +RVNQX0NPUkVfRFVNUF9JTkZPAAA= +AAEJAGM1NDg2NTdmMGViZDE3ZDQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +DAAAAJQAAAClAgAA +RVhUUkFfSU5GTwAA +lBzOP+gAAAAdAAAA7gAAAAUAAADCAAAAAAAAAMMAAAAAAAAAxAAAAAAAAADFAAAA +AAAAAMYAAAAAAAAAsQAAACeXAEKyAAAAAAAAALMAAAAAAAAAtAAAAAAAAAC1AAAA +AAAAALYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAA== +fv6QZA== diff --git a/components/espcoredump/test/esp32s3/expected_output b/components/espcoredump/test/esp32s3/expected_output new file mode 100644 index 0000000000..cc41f6ed6b --- /dev/null +++ b/components/espcoredump/test/esp32s3/expected_output @@ -0,0 +1,679 @@ +espcoredump.py v0.4-dev +=============================================================== +==================== ESP32 CORE DUMP START ==================== + +Crashed task handle: 0x3fce1c94, name: 'unaligned_ptr_t', GDB name: 'process 1070472340' + +================== CURRENT THREAD REGISTERS =================== +exccause 0x1d (StoreProhibitedCause) +excvaddr 0x5 +epc1 0x42009727 +epc2 0x0 +epc3 0x0 +epc4 0x0 +epc5 0x0 +epc6 0x0 +eps2 0x0 +eps3 0x0 +eps4 0x0 +eps5 0x0 +eps6 0x0 +pc 0x42004e79 0x42004e79 +lbeg 0x400556d5 1074091733 +lend 0x400556e5 1074091749 +lcount 0xfffffff8 4294967288 +sar 0x0 0 +ps 0x60620 394784 +threadptr +br +scompare1 +acclo +acchi +m0 +m1 +m2 +m3 +expstate +f64r_lo +f64r_hi +f64s +fcr +fsr +a0 0x82004e54 -2113909164 +a1 0x3fce1a80 1070471808 +a2 0x2 2 +a3 0x3fce1acc 1070471884 +a4 0x3fce1ac0 1070471872 +a5 0x0 0 +a6 0x3fcf0824 1070532644 +a7 0x1 1 +a8 0x5 5 +a9 0xffffffad -83 +a10 0x20 32 +a11 0x3fce1cf4 1070472436 +a12 0x1 1 +a13 0x80 128 +a14 0x0 0 +a15 0x1 1 + +==================== CURRENT THREAD STACK ===================== +#0 0x42004e79 in recur_func () at ../main/test_core_dump.c:70 +#1 0x42004e54 in recur_func () at ../main/test_core_dump.c:63 +#2 0x42004e54 in recur_func () at ../main/test_core_dump.c:63 +#3 0x42004e9f in unaligned_ptr_task (pvParameter=0x0) at ../main/test_core_dump.c:80 +#4 0x4037b974 in vPortTaskWrapper (pxCode=0x42004e84 , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:159 + +======================== THREADS INFO ========================= + Id Target Id Frame +* 1 process 1070472340 0x42004e79 in recur_func () at ../main/test_core_dump.c:70 + 2 process 1070549672 0x420188a6 in esp_pm_impl_waiti () at ../../../hal/esp32s3/include/hal/cpu_ll.h:182 + 3 process 1070551560 0x420188a6 in esp_pm_impl_waiti () at ../../../hal/esp32s3/include/hal/cpu_ll.h:182 + 4 process 1070474740 0x4037a222 in vTaskDelay (xTicksToDelay=100) at ../../../hal/esp32s3/include/hal/cpu_ll.h:38 + 5 process 1070469940 0x4037a222 in vTaskDelay (xTicksToDelay=100) at ../../../hal/esp32s3/include/hal/cpu_ll.h:38 + 6 process 1070537184 0x40379ac5 in xQueueSemaphoreTake (xQueue=0x3fcf1584, xTicksToWait=) at ../../../hal/esp32s3/include/hal/cpu_ll.h:38 + 7 process 1070543272 0x400559e0 in ?? () + 8 process 1070538824 xQueueSemaphoreTake (xQueue=0x3fcf1bec, xTicksToWait=) at /builds/espressif/esp-idf/components/freertos/queue.c:1518 + +==================== THREAD 1 (TCB: 0x3fce1c94, name: 'unaligned_ptr_t') ===================== +#0 0x42004e79 in recur_func () at ../main/test_core_dump.c:70 +#1 0x42004e54 in recur_func () at ../main/test_core_dump.c:63 +#2 0x42004e54 in recur_func () at ../main/test_core_dump.c:63 +#3 0x42004e9f in unaligned_ptr_task (pvParameter=0x0) at ../main/test_core_dump.c:80 +#4 0x4037b974 in vPortTaskWrapper (pxCode=0x42004e84 , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:159 + +==================== THREAD 2 (TCB: 0x3fcf4aa8, name: 'IDLE') ===================== +#0 0x420188a6 in esp_pm_impl_waiti () at ../../../hal/esp32s3/include/hal/cpu_ll.h:182 +#1 0x42001caa in esp_vApplicationIdleHook () at /builds/espressif/esp-idf/components/esp_system/freertos_hooks.c:63 +#2 0x40379fc8 in prvIdleTask (pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/tasks.c:3909 +#3 0x4037b974 in vPortTaskWrapper (pxCode=0x40379fbc , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:159 + +==================== THREAD 3 (TCB: 0x3fcf5208, name: 'IDLE') ===================== +#0 0x420188a6 in esp_pm_impl_waiti () at ../../../hal/esp32s3/include/hal/cpu_ll.h:182 +#1 0x42001caa in esp_vApplicationIdleHook () at /builds/espressif/esp-idf/components/esp_system/freertos_hooks.c:63 +#2 0x40379fc8 in prvIdleTask (pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/tasks.c:3909 +#3 0x4037b974 in vPortTaskWrapper (pxCode=0x40379fbc , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:159 + +==================== THREAD 4 (TCB: 0x3fce25f4, name: 'failed_assert_t') ===================== +#0 0x4037a222 in vTaskDelay (xTicksToDelay=100) at ../../../hal/esp32s3/include/hal/cpu_ll.h:38 +#1 0x42004d4a in failed_assert_task (pvParameter=0x0) at ../main/test_core_dump.c:89 +#2 0x4037b974 in vPortTaskWrapper (pxCode=0x42004d38 , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:159 + +==================== THREAD 5 (TCB: 0x3fce1334, name: 'bad_ptr_task') ===================== +#0 0x4037a222 in vTaskDelay (xTicksToDelay=100) at ../../../hal/esp32s3/include/hal/cpu_ll.h:38 +#1 0x42004e16 in bad_ptr_task (pvParameter=0x0) at ../main/test_core_dump.c:43 +#2 0x4037b974 in vPortTaskWrapper (pxCode=0x42004e04 , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:159 + +==================== THREAD 6 (TCB: 0x3fcf19e0, name: 'ipc0') ===================== +#0 0x40379ac5 in xQueueSemaphoreTake (xQueue=0x3fcf1584, xTicksToWait=) at ../../../hal/esp32s3/include/hal/cpu_ll.h:38 +#1 0x4037680f in ipc_task (arg=0x0) at /builds/espressif/esp-idf/components/esp_ipc/src/esp_ipc.c:59 +#2 0x4037b974 in vPortTaskWrapper (pxCode=0x403767e4 , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:159 + +==================== THREAD 7 (TCB: 0x3fcf31a8, name: 'esp_timer') ===================== +#0 0x400559e0 in ?? () +#1 0x4037bb8a in vPortExitCritical (mux=) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:447 +#2 0x4037b30a in ulTaskGenericNotifyTake (uxIndexToWait=0, xClearCountOnExit=1, xTicksToWait=) at /builds/espressif/esp-idf/components/freertos/tasks.c:5303 +#3 0x420047cf in timer_task (arg=0x0) at /builds/espressif/esp-idf/components/esp_timer/src/esp_timer.c:392 +#4 0x4037b974 in vPortTaskWrapper (pxCode=0x420047c0 , pvParameters=0x0) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:159 + +==================== THREAD 8 (TCB: 0x3fcf2048, name: 'ipc1') ===================== +#0 xQueueSemaphoreTake (xQueue=0x3fcf1bec, xTicksToWait=) at /builds/espressif/esp-idf/components/freertos/queue.c:1518 +#1 0x4037680f in ipc_task (arg=0x1) at /builds/espressif/esp-idf/components/esp_ipc/src/esp_ipc.c:59 +#2 0x4037b974 in vPortTaskWrapper (pxCode=0x403767e4 , pvParameters=0x1) at /builds/espressif/esp-idf/components/freertos/port/xtensa/port.c:159 + + +======================= ALL MEMORY REGIONS ======================== +Name Address Size Attrs +.rtc.text 0x600fe000 0x0 RW +.rtc.dummy 0x600fe000 0x0 RW +.rtc.force_fast 0x600fe000 0x0 RW +.rtc.data 0x50000000 0x10 RW A +.rtc_noinit 0x50000010 0x0 RW +.rtc.force_slow 0x50000010 0x0 RW +.iram0.vectors 0x40374000 0x403 R XA +.iram0.text 0x40374404 0xb75b R XA +.dram0.data 0x3fc8fb60 0x3018 RW A +.noinit 0x3fc92b78 0x0 RW +.flash.text 0x42000020 0x194bf R XA +.flash.appdesc 0x3c020020 0x100 R A +.flash.rodata 0x3c020120 0x3354 RW A +.flash.rodata_noload 0x3c023474 0x0 RW +.iram0.text_end 0x4037fb5f 0x0 RW +.iram0.bss 0x4037fb60 0x0 RW +.dram0.heap_start 0x3fc93960 0x0 RW +.coredump.tasks.data 0x3fce1c94 0x158 RW +.coredump.tasks.data 0x3fce19c0 0x2cc RW +.coredump.tasks.data 0x3fcf4aa8 0x158 RW +.coredump.tasks.data 0x3fcf4820 0x280 RW +.coredump.tasks.data 0x3fcf5208 0x158 RW +.coredump.tasks.data 0x3fcf4f80 0x280 RW +.coredump.tasks.data 0x3fce25f4 0x158 RW +.coredump.tasks.data 0x3fce2390 0x25c RW +.coredump.tasks.data 0x3fce1334 0x158 RW +.coredump.tasks.data 0x3fce10d0 0x25c RW +.coredump.tasks.data 0x3fcf19e0 0x158 RW +.coredump.tasks.data 0x3fcf1750 0x288 RW +.coredump.tasks.data 0x3fcf31a8 0x158 RW +.coredump.tasks.data 0x3fcf2f10 0x290 RW +.coredump.tasks.data 0x3fcf2048 0x158 RW +.coredump.tasks.data 0x3fcf1dc0 0x280 RW + +====================== CORE DUMP MEMORY CONTENTS ======================== +.coredump.tasks.data 0x3fce1c94 0x158 RW +0x3fce1c94: 0x3fce1a50 0x3fce1b50 0x00000066 0x3fc92f68 +0x3fce1ca4: 0x3fc92f68 0x3fce1c94 0x3fc92f60 0x00000012 +0x3fce1cb4: 0x3fcf09e4 0x3fcf09e4 0x3fce1c94 0x00000000 +0x3fce1cc4: 0x00000007 0x3fce1490 0x6c616e75 0x656e6769 +0x3fce1cd4: 0x74705f64 0x00745f72 0x00000001 0x3fce1c8c +0x3fce1ce4: 0x00000007 0x00000000 0x00000000 0x00000000 +0x3fce1cf4: 0x00000000 0x3fcf07bc 0x3fcf0824 0x3fcf088c +0x3fce1d04: 0x00000000 0x00000000 0x00000001 0x00000000 +0x3fce1d14: 0x00000000 0x00000000 0x4200a64c 0x00000000 +0x3fce1d24: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1d34: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1d44: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1d54: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1d64: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1d74: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1d84: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1d94: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1da4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1db4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1dc4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1dd4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1de4: 0x00000000 0x3fce0000 +.coredump.tasks.data 0x3fce19c0 0x2cc RW +0x3fce19c0: 0xdeadbeef 0x42004e79 0x00060630 0x82004e54 +0x3fce19d0: 0x3fce1a80 0x00000002 0x3fce1acc 0x3fce1ac0 +0x3fce19e0: 0x00000000 0x3fcf0824 0x00000001 0x00000005 +0x3fce19f0: 0xffffffad 0x00000020 0x3fce1cf4 0x00000001 +0x3fce1a00: 0x00000080 0x00000000 0x00000001 0x00000000 +0x3fce1a10: 0x0000001d 0x00000005 0x400556d5 0x400556e5 +0x3fce1a20: 0xfffffff8 0x00000001 0x00000080 0x40375ea4 +0x3fce1a30: 0x3fcde7ec 0x00000000 0x00000000 0x00000000 +0x3fce1a40: 0xb33fffff 0x00000000 0x00000000 0x00000000 +0x3fce1a50: 0x00000000 0x00000001 0x3fcf09b8 0x00000000 +0x3fce1a60: 0x00000001 0x00000080 0x00000000 0x00000001 +0x3fce1a70: 0x82004e54 0x3fce1ab0 0x00000001 0x3fcf0824 +0x3fce1a80: 0x00000003 0x00000064 0x00000001 0x00000000 +0x3fce1a90: 0x3fce1ac0 0x00000000 0x3fcf0824 0x00000001 +0x3fce1aa0: 0x82004e9f 0x3fce1ae0 0x0000000a 0x3fc911a0 +0x3fce1ab0: 0x00000003 0x0000001e 0x3c021fdc 0x00000001 +0x3fce1ac0: 0x00000000 0xa5a5a5a5 0xa5a5a5a5 0x00000065 +0x3fce1ad0: 0x8037b974 0x3fce1b10 0x00000000 0x00000000 +0x3fce1ae0: 0x00000003 0x3fce1b10 0x00000000 0x00000000 +0x3fce1af0: 0x00060021 0x00060023 0x00000001 0x00000001 +0x3fce1b00: 0x00000000 0x3fce1b30 0x42004e84 0x00000000 +0x3fce1b10: 0x00060023 0x3fc92f68 0x3fce1c94 0x00000000 +0x3fce1b20: 0x00000000 0x3fce1b50 0x00000000 0x00000000 +0x3fce1b30: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1b40: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1b50: 0x00000000 0x00000000 0x3fce1b60 0x00000000 +0x3fce1b60: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1b70: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1b80: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1b90: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1ba0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1bb0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1bc0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1bd0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1be0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1bf0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1c00: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1c10: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1c20: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1c30: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1c40: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1c50: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1c60: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1c70: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1c80: 0x00000000 0x00000000 0x00000000 +.coredump.tasks.data 0x3fcf4aa8 0x158 RW +0x3fcf4aa8: 0x3fcf4820 0x3fcf4960 0x12ca1319 0x3fcf5210 +0x3fcf4ab8: 0x3fc92edc 0x3fcf4aa8 0x3fc92ed4 0x00000019 +0x3fcf4ac8: 0xb66b384e 0x344f5f4c 0x3fcf4aa8 0x00000000 +0x3fcf4ad8: 0x00000000 0x3fcf44a4 0x454c4449 0xbebed800 +0x3fcf4ae8: 0xb6cf17d6 0x00d88bc7 0x00000000 0x3fcf4aa0 +0x3fcf4af8: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf4b08: 0x00000000 0x3fcf07bc 0x3fcf0824 0x3fcf088c +0x3fcf4b18: 0x00000000 0x00000000 0x00000001 0x00000000 +0x3fcf4b28: 0x00000000 0x00000000 0x4200a64c 0x00000000 +0x3fcf4b38: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf4b48: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf4b58: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf4b68: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf4b78: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf4b88: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf4b98: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf4ba8: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf4bb8: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf4bc8: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf4bd8: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf4be8: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf4bf8: 0x00000000 0x3fcf0000 +.coredump.tasks.data 0x3fcf4820 0x280 RW +0x3fcf4820: 0x40375f08 0x420188a6 0x00060530 0x82001caa +0x3fcf4830: 0x3fcf48e0 0x00000000 0x00000001 0x00000001 +0x3fcf4840: 0x80000001 0x00060023 0x00000000 0x82009e8e +0x3fcf4850: 0x3fcf48b0 0x00000000 0x4200a64c 0x00060120 +0x3fcf4860: 0x00060123 0x00000001 0x6000001c 0x0000001e +0x3fcf4870: 0x0000ffff 0x00000000 0x00000000 0x00000000 +0x3fcf4880: 0x00000000 0x40376210 0x00060123 0x40378dd8 +0x3fcf4890: 0x3fcf15fc 0x00000000 0x00000000 0x00000000 +0x3fcf48a0: 0xb33fffff 0x00000000 0x00000000 0x00000000 +0x3fcf48b0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf48c0: 0x00000000 0x40379fbc 0x00000000 0x00000000 +0x3fcf48d0: 0x80379fc8 0x3fcf4900 0x00000008 0x00000000 +0x3fcf48e0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf48f0: 0x8037b974 0x3fcf4920 0x00000000 0x00000000 +0x3fcf4900: 0x00000001 0x00060023 0x00000001 0x0000000a +0x3fcf4910: 0x00000000 0x3fcf4940 0x40379fbc 0x00000000 +0x3fcf4920: 0x00060023 0x3fc92edc 0x3fcf5208 0x00000000 +0x3fcf4930: 0x00000000 0x3fcf4960 0x00000000 0x00000000 +0x3fcf4940: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf4950: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf4960: 0x00000000 0x00000000 0x3fcf4970 0x00000000 +0x3fcf4970: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf4980: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf4990: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf49a0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf49b0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf49c0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf49d0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf49e0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf49f0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf4a00: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf4a10: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf4a20: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf4a30: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf4a40: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf4a50: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf4a60: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf4a70: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf4a80: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf4a90: 0x00000000 0x00000000 0x00000000 0x00000000 +.coredump.tasks.data 0x3fcf5208 0x158 RW +0x3fcf5208: 0x3fcf4f80 0x3fcf50c0 0x8c7b8e9a 0x3fc92edc +0x3fcf5218: 0x3fcf4ab0 0x3fcf5208 0x3fc92ed4 0x00000019 +0x3fcf5228: 0xb9a1ed22 0x83d8f130 0x3fcf5208 0x00000000 +0x3fcf5238: 0x00000000 0x3fcf4c04 0x454c4449 0xf5f17500 +0x3fcf5248: 0xdf446c8b 0x004f12dc 0x00000001 0x3fcf5200 +0x3fcf5258: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf5268: 0x00000000 0x3fcf07bc 0x3fcf0824 0x3fcf088c +0x3fcf5278: 0x00000000 0x00000000 0x00000001 0x00000000 +0x3fcf5288: 0x00000000 0x00000000 0x4200a64c 0x00000000 +0x3fcf5298: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf52a8: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf52b8: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf52c8: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf52d8: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf52e8: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf52f8: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf5308: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf5318: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf5328: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf5338: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf5348: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf5358: 0x00000000 0x3fcf0000 +.coredump.tasks.data 0x3fcf4f80 0x280 RW +0x3fcf4f80: 0x40375f08 0x420188a6 0x00060c30 0x82001caa +0x3fcf4f90: 0x3fcf5040 0x00000000 0x00000000 0x00000001 +0x3fcf4fa0: 0x80000001 0x3fc92de4 0x00000000 0x82009e8e +0x3fcf4fb0: 0x3fcf5010 0x00000000 0x00000000 0x00060c20 +0x3fcf4fc0: 0x00060c23 0x00000001 0x00000000 0x0000001e +0x3fcf4fd0: 0x0000ffff 0x00000000 0x00000000 0x00000000 +0x3fcf4fe0: 0x00000000 0x40376210 0x00060c23 0x40378dd8 +0x3fcf4ff0: 0x3fcf1d5c 0x00000000 0x00000000 0x00000000 +0x3fcf5000: 0xb33fffff 0x00000000 0x00000000 0x00000000 +0x3fcf5010: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf5020: 0x00000000 0x40379fbc 0x00000000 0x00000000 +0x3fcf5030: 0x80379fc8 0x3fcf5060 0x00000008 0x00000001 +0x3fcf5040: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf5050: 0x8037b974 0x3fcf5080 0x00000000 0x00000000 +0x3fcf5060: 0x00000001 0x00060023 0x00000001 0x00000001 +0x3fcf5070: 0x00000000 0x3fcf50a0 0x40379fbc 0x00000000 +0x3fcf5080: 0x00060023 0x3fc92edc 0x3fcf4aa8 0x00000000 +0x3fcf5090: 0x00000000 0x3fcf50c0 0x00000000 0x00000000 +0x3fcf50a0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf50b0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf50c0: 0x00000000 0x00000000 0x3fcf50d0 0x00000000 +0x3fcf50d0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf50e0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf50f0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf5100: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf5110: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf5120: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf5130: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf5140: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf5150: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf5160: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf5170: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf5180: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf5190: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf51a0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf51b0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf51c0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf51d0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf51e0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf51f0: 0x00000000 0x00000000 0x00000000 0x00000000 +.coredump.tasks.data 0x3fce25f4 0x158 RW +0x3fce25f4: 0x3fce2390 0x3fce24b0 0x000000ca 0x3fce133c +0x3fce2604: 0x3fc92ec8 0x3fce25f4 0x3fc92ec0 0x0000000f +0x3fce2614: 0x3fce1cb0 0x3fcf09e4 0x3fce25f4 0x00000000 +0x3fce2624: 0x0000000a 0x3fce1df0 0x6c696166 0x615f6465 +0x3fce2634: 0x72657373 0x00745f74 0x00000000 0x3fce25ec +0x3fce2644: 0x0000000a 0x00000000 0x00000000 0x00000000 +0x3fce2654: 0x00000000 0x3fcf07bc 0x3fcf0824 0x3fcf088c +0x3fce2664: 0x00000000 0x00000000 0x00000001 0x00000000 +0x3fce2674: 0x00000000 0x00000000 0x4200a64c 0x00000000 +0x3fce2684: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce2694: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce26a4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce26b4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce26c4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce26d4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce26e4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce26f4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce2704: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce2714: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce2724: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce2734: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce2744: 0x00000000 0x3fce0000 +.coredump.tasks.data 0x3fce2390 0x25c RW +0x3fce2390: 0x40375f08 0x4037a222 0x00060730 0x82004d4a +0x3fce23a0: 0x3fce2450 0x00000064 0x3fc911a0 0x00060021 +0x3fce23b0: 0x00060023 0x00000001 0x00000000 0x8037a222 +0x3fce23c0: 0x3fce2430 0x00000000 0x000000ca 0x3fc930c8 +0x3fce23d0: 0x3fcf4140 0x00000800 0x00000000 0x00000000 +0x3fce23e0: 0x0000ffff 0x00000000 0x400556d5 0x400556e5 +0x3fce23f0: 0xfffffff8 0x40376210 0x3fcf4140 0x40378dd8 +0x3fce2400: 0x3fcdf14c 0x00000000 0x00000000 0x00000000 +0x3fce2410: 0xb33fffff 0x00000000 0x00000000 0x00000000 +0x3fce2420: 0x00000000 0x00000002 0x00000000 0x00000000 +0x3fce2430: 0x3fc930c8 0x3fcf4140 0x00000800 0x00000000 +0x3fce2440: 0x8037b974 0x3fce2470 0x00000000 0x00000000 +0x3fce2450: 0x00060021 0x00060023 0x00000001 0x00000000 +0x3fce2460: 0x00000000 0x3fce2490 0x42004d38 0x00000000 +0x3fce2470: 0x00060023 0x3fc92fa4 0x3fce25f4 0x00000000 +0x3fce2480: 0x00000000 0x3fce24b0 0x00000000 0x00000000 +0x3fce2490: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce24a0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce24b0: 0x00000000 0x00000000 0x3fce24c0 0x00000000 +0x3fce24c0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce24d0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce24e0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce24f0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce2500: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce2510: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce2520: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce2530: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce2540: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce2550: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce2560: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce2570: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce2580: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce2590: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce25a0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce25b0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce25c0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce25d0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce25e0: 0x00000000 0x00000000 0x00000000 +.coredump.tasks.data 0x3fce1334 0x158 RW +0x3fce1334: 0x3fce10d0 0x3fce11f0 0x000000ca 0x3fc92ec8 +0x3fce1344: 0x3fce25fc 0x3fce1334 0x3fc92ec0 0x00000014 +0x3fce1354: 0x380815b4 0xb530690c 0x3fce1334 0x00000000 +0x3fce1364: 0x00000005 0x3fce0b30 0x5f646162 0x5f727470 +0x3fce1374: 0x6b736174 0x0082d100 0x7fffffff 0x3fce132c +0x3fce1384: 0x00000005 0x00000000 0x00000000 0x00000000 +0x3fce1394: 0x00000000 0x3fcf07bc 0x3fcf0824 0x3fcf088c +0x3fce13a4: 0x00000000 0x00000000 0x00000001 0x00000000 +0x3fce13b4: 0x00000000 0x00000000 0x4200a64c 0x00000000 +0x3fce13c4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce13d4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce13e4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce13f4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1404: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1414: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1424: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1434: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1444: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1454: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1464: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1474: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1484: 0x00000000 0x3fce0000 +.coredump.tasks.data 0x3fce10d0 0x25c RW +0x3fce10d0: 0x40375f08 0x4037a222 0x00060930 0x82004e16 +0x3fce10e0: 0x3fce1190 0x00000064 0x3fc911a0 0x00060021 +0x3fce10f0: 0x00060023 0x00000001 0x00000000 0x8037a222 +0x3fce1100: 0x3fce1170 0x00000000 0x000000ca 0x3fc930c8 +0x3fce1110: 0xa5a5a5a5 0xa5a5a5a5 0x00000001 0x0000000f +0x3fce1120: 0x0000ffff 0x00000000 0x400556d5 0x400556e5 +0x3fce1130: 0xfffffff9 0x40376210 0xa5a5a5a5 0x40378dd8 +0x3fce1140: 0x3fcdde8c 0x00000000 0x00000000 0x00000000 +0x3fce1150: 0xb33fffff 0x00000000 0x00000000 0x00000000 +0x3fce1160: 0x00000000 0x00000002 0x00000000 0x00000000 +0x3fce1170: 0x00000000 0xa5a5a5a5 0xa5a5a5a5 0x00000001 +0x3fce1180: 0x8037b974 0x3fce11b0 0x00000000 0x00000000 +0x3fce1190: 0x00060021 0x00060023 0x00000001 0x00000000 +0x3fce11a0: 0x00000000 0x3fce11d0 0x42004e04 0x00000000 +0x3fce11b0: 0x00060023 0x3fc92f40 0x3fce1334 0x00000000 +0x3fce11c0: 0x00000000 0x3fce11f0 0x00000000 0x00000000 +0x3fce11d0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce11e0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce11f0: 0x00000000 0x00000000 0x3fce1200 0x00000000 +0x3fce1200: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1210: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1220: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1230: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1240: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1250: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1260: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1270: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1280: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1290: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce12a0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce12b0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce12c0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce12d0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce12e0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce12f0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1300: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1310: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fce1320: 0x00000000 0x00000000 0x00000000 +.coredump.tasks.data 0x3fcf19e0 0x158 RW +0x3fcf19e0: 0x3fcf1750 0x3fcf1890 0xdec3d6ee 0x3fcf31b0 +0x3fcf19f0: 0x3fc92e58 0x3fcf19e0 0x3fc92e50 0x00000001 +0x3fcf1a00: 0x3fcf15b0 0x3fcf15b0 0x3fcf19e0 0x3fcf15a8 +0x3fcf1a10: 0x00000018 0x3fcf15dc 0x30637069 0x5b19d600 +0x3fcf1a20: 0xb758da44 0x000986f0 0x00000000 0x3fcf19d8 +0x3fcf1a30: 0x00000018 0x00000000 0x00000000 0x00000000 +0x3fcf1a40: 0x00000000 0x3fcf07bc 0x3fcf0824 0x3fcf088c +0x3fcf1a50: 0x00000000 0x00000000 0x00000001 0x00000000 +0x3fcf1a60: 0x00000000 0x00000000 0x4200a64c 0x00000000 +0x3fcf1a70: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1a80: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1a90: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1aa0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1ab0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1ac0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1ad0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1ae0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1af0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1b00: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1b10: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1b20: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1b30: 0x00000000 0x3fcf0000 +.coredump.tasks.data 0x3fcf1750 0x288 RW +0x3fcf1750: 0x40375f08 0x40379ac5 0x00060030 0x8037680f +0x3fcf1760: 0x3fcf1810 0x3fcf1584 0x3fcf15d0 0x00000001 +0x3fcf1770: 0x00000001 0x00000000 0x80000000 0x80379ac5 +0x3fcf1780: 0x3fcf17f0 0x00000000 0xffffffff 0x3fcf15d0 +0x3fcf1790: 0x00000000 0x60023000 0x000fffff 0x00000000 +0x3fcf17a0: 0x0000ffff 0x00000000 0x00000000 0x00000000 +0x3fcf17b0: 0x00000000 0x40376210 0x00000000 0x40378dd8 +0x3fcf17c0: 0x3fcee52c 0x00000000 0x00000000 0x00000000 +0x3fcf17d0: 0xb33fffff 0x00000000 0x00000000 0x00000000 +0x3fcf17e0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf17f0: 0x00000000 0x403767e4 0x00000000 0x00000000 +0x3fcf1800: 0x8037b974 0x3fcf1850 0x00000000 0x00000000 +0x3fcf1810: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1820: 0xffffffff 0x00000000 0x00000000 0x00000000 +0x3fcf1830: 0x00000000 0x40376210 0x00000000 0x40378dd8 +0x3fcf1840: 0x00000000 0x3fcf1870 0x403767e4 0x00000000 +0x3fcf1850: 0x00000000 0x00000000 0x3fcf19e0 0x00000001 +0x3fcf1860: 0x00000000 0x3fcf1890 0x00000000 0x00000000 +0x3fcf1870: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1880: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1890: 0x00000000 0x00000000 0x3fcf18a0 0x00000000 +0x3fcf18a0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf18b0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf18c0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf18d0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf18e0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf18f0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1900: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1910: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1920: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1930: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1940: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1950: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1960: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1970: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1980: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1990: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf19a0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf19b0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf19c0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf19d0: 0x00000000 0x00000000 +.coredump.tasks.data 0x3fcf31a8 0x158 RW +0x3fcf31a8: 0x3fcf2f10 0x3fcf3060 0x465cd6df 0x3fcf2050 +0x3fcf31b8: 0x3fcf19e8 0x3fcf31a8 0x3fc92e50 0x00000003 +0x3fcf31c8: 0xe7d8c34f 0x7f8d5870 0x3fcf31a8 0x00000000 +0x3fcf31d8: 0x00000016 0x3fcf21a4 0x5f707365 0x656d6974 +0x3fcf31e8: 0x5f490072 0x00cdc3ee 0x00000000 0x3fcf31a0 +0x3fcf31f8: 0x00000016 0x00000000 0x00000000 0x00000000 +0x3fcf3208: 0x00000000 0x3fcf07bc 0x3fcf0824 0x3fcf088c +0x3fcf3218: 0x00000000 0x00000000 0x00000001 0x00000000 +0x3fcf3228: 0x00000000 0x00000000 0x4200a64c 0x00000000 +0x3fcf3238: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf3248: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf3258: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf3268: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf3278: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf3288: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf3298: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf32a8: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf32b8: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf32c8: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf32d8: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf32e8: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf32f8: 0x00000000 0x3fcf0001 +.coredump.tasks.data 0x3fcf2f10 0x290 RW +0x3fcf2f10: 0x40375f08 0x400559e0 0x00060030 0x8037bb8a +0x3fcf2f20: 0x3fcf2fd0 0x00060023 0x00000000 0x00060020 +0x3fcf2f30: 0x00060023 0x00000001 0x3fceb260 0x80377d3d +0x3fcf2f40: 0x3fcf2fa0 0x3fc92dec 0x00000000 0x3fcf1890 +0x3fcf2f50: 0x3fcf1870 0x403767e4 0x00000000 0x00000000 +0x3fcf2f60: 0x0000ffff 0x00000000 0x00000000 0x00000000 +0x3fcf2f70: 0x00000000 0x40376210 0x3fcf1870 0x40378dd8 +0x3fcf2f80: 0x3fcefcfc 0x00000000 0x00000000 0x00000000 +0x3fcf2f90: 0xb33fffff 0x00000000 0x00000000 0x00000000 +0x3fcf2fa0: 0x00000000 0x4037b96c 0x00050030 0x00000000 +0x3fcf2fb0: 0x3fcf3060 0x00000000 0x00000000 0x00000000 +0x3fcf2fc0: 0x8037b30a 0x3fcf2fe0 0x3fc92de4 0x00000000 +0x3fcf2fd0: 0x820047cf 0x3fcf3000 0x00000000 0x00000001 +0x3fcf2fe0: 0x00000000 0x3fcf17a0 0x00060023 0x00000000 +0x3fcf2ff0: 0x8037b974 0x3fcf3020 0x00000000 0x00000000 +0x3fcf3000: 0x3fc911a0 0x00060023 0x00000001 0x00000000 +0x3fcf3010: 0x00000000 0x3fcf3040 0x420047c0 0x00000000 +0x3fcf3020: 0x00060023 0x3fc93094 0x3fcf31a8 0x00000000 +0x3fcf3030: 0x00000000 0x3fcf3060 0x00000000 0x00000000 +0x3fcf3040: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf3050: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf3060: 0x00000000 0x00000000 0x3fcf3070 0x00000000 +0x3fcf3070: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf3080: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf3090: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf30a0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf30b0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf30c0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf30d0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf30e0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf30f0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf3100: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf3110: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf3120: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf3130: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf3140: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf3150: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf3160: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf3170: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf3180: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf3190: 0x00000000 0x00000000 0x00000000 0x00000000 +.coredump.tasks.data 0x3fcf2048 0x158 RW +0x3fcf2048: 0x3fcf1dc0 0x3fcf1f00 0xfd7a0acc 0x3fc92e58 +0x3fcf2058: 0x3fcf31b0 0x3fcf2048 0x3fc92e50 0x00000001 +0x3fcf2068: 0x3fcf1c18 0x3fcf1c18 0x3fcf2048 0x3fcf1c10 +0x3fcf2078: 0x00000018 0x3fcf1c44 0x31637069 0x08c74c00 +0x3fcf2088: 0x720b13f5 0x00c0803e 0x00000001 0x3fcf2040 +0x3fcf2098: 0x00000018 0x00000000 0x00000000 0x00000000 +0x3fcf20a8: 0x00000000 0x3fcf07bc 0x3fcf0824 0x3fcf088c +0x3fcf20b8: 0x00000000 0x00000000 0x00000001 0x00000000 +0x3fcf20c8: 0x00000000 0x00000000 0x4200a64c 0x00000000 +0x3fcf20d8: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf20e8: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf20f8: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf2108: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf2118: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf2128: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf2138: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf2148: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf2158: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf2168: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf2178: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf2188: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf2198: 0x00000000 0x3fcf0000 +.coredump.tasks.data 0x3fcf1dc0 0x280 RW +0x3fcf1dc0: 0x40375f08 0x403799d4 0x00060830 0x8037680f +0x3fcf1dd0: 0x3fcf1e80 0x3fcf1bec 0x3fcf1c38 0x00000001 +0x3fcf1de0: 0x00000001 0x00000000 0x00000001 0x80379ac5 +0x3fcf1df0: 0x3fcf1e60 0x00000001 0xffffffff 0x3fcf1c38 +0x3fcf1e00: 0x3fcf4350 0x00000001 0x600c28e8 0x00000000 +0x3fcf1e10: 0x0000ffff 0x00000000 0x00000000 0x00000000 +0x3fcf1e20: 0x00000000 0x40376210 0x3fcf4350 0x40378dd8 +0x3fcf1e30: 0x3fceeb9c 0x00000000 0x00000000 0x00000000 +0x3fcf1e40: 0xb33fffff 0x00000000 0x00000000 0x00000000 +0x3fcf1e50: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1e60: 0xb33fffff 0x00000000 0x00000000 0x00000000 +0x3fcf1e70: 0x8037b974 0x3fcf1ec0 0x00000001 0x00000000 +0x3fcf1e80: 0x00000000 0x00000002 0x00000000 0x00000000 +0x3fcf1e90: 0xffffffff 0x3fcf1ec0 0x00000001 0x40376b60 +0x3fcf1ea0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1eb0: 0x00000000 0x3fcf1ee0 0x403767e4 0x00000001 +0x3fcf1ec0: 0x00000001 0x3fc930bc 0x3fcf2048 0x00000000 +0x3fcf1ed0: 0x00000000 0x3fcf1f00 0x00000000 0x00000000 +0x3fcf1ee0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1ef0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1f00: 0x00000000 0x00000000 0x3fcf1f10 0x00000000 +0x3fcf1f10: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1f20: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1f30: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1f40: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1f50: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1f60: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1f70: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1f80: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1f90: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1fa0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1fb0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1fc0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1fd0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1fe0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf1ff0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf2000: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf2010: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf2020: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3fcf2030: 0x00000000 0x00000000 0x00000000 0x00000000 + +===================== ESP32 CORE DUMP END ===================== +=============================================================== +Done! diff --git a/components/espcoredump/test/test_espcoredump.sh b/components/espcoredump/test/test_espcoredump.sh index 8eed51b2cd..1c092a9658 100755 --- a/components/espcoredump/test/test_espcoredump.sh +++ b/components/espcoredump/test/test_espcoredump.sh @@ -11,7 +11,7 @@ else elf_dir=$1 fi -SUPPORTED_TARGETS=("esp32" "esp32s2" "esp32c3") +SUPPORTED_TARGETS=("esp32" "esp32s2" "esp32c3" "esp32s3" ) res=0 coverage erase for chip in "${SUPPORTED_TARGETS[@]}"; do diff --git a/components/espcoredump/test_apps/build_espcoredump.sh b/components/espcoredump/test_apps/build_espcoredump.sh index d39d4780a4..9f7ac84d3f 100755 --- a/components/espcoredump/test_apps/build_espcoredump.sh +++ b/components/espcoredump/test_apps/build_espcoredump.sh @@ -11,7 +11,7 @@ else output_dir=$1 fi -SUPPORTED_TARGETS=("esp32" "esp32s2" "esp32c3") +SUPPORTED_TARGETS=("esp32" "esp32s2" "esp32c3" "esp32s3") for chip in "${SUPPORTED_TARGETS[@]}"; do { echo "--------------------------" diff --git a/components/esptool_py/Kconfig.projbuild b/components/esptool_py/Kconfig.projbuild index ae78307fe3..1e0b35beb8 100644 --- a/components/esptool_py/Kconfig.projbuild +++ b/components/esptool_py/Kconfig.projbuild @@ -56,7 +56,6 @@ menu "Serial flasher config" config ESPTOOLPY_NO_STUB bool "Disable download stub" - default "y" if IDF_TARGET_ESP32H2 # ESP32H2-TODO: IDF-3378 default "n" help The flasher tool sends a precompiled download stub first by default. That stub allows things @@ -76,8 +75,33 @@ menu "Serial flasher config" bool "MXIC OPI FLASH(MX25UM25645G)" endchoice + choice ESPTOOLPY_FLASHMODE + prompt "Flash SPI mode" + default ESPTOOLPY_FLASHMODE_DIO + default ESPTOOLPY_FLASHMODE_OPI if ESPTOOLPY_OCT_FLASH + help + Mode the flash chip is flashed in, as well as the default mode for the + binary to run in. + + config ESPTOOLPY_FLASHMODE_QIO + depends on !ESPTOOLPY_OCT_FLASH + bool "QIO" + config ESPTOOLPY_FLASHMODE_QOUT + depends on !ESPTOOLPY_OCT_FLASH + bool "QOUT" + config ESPTOOLPY_FLASHMODE_DIO + depends on !ESPTOOLPY_OCT_FLASH + bool "DIO" + config ESPTOOLPY_FLASHMODE_DOUT + depends on !ESPTOOLPY_OCT_FLASH + bool "DOUT" + config ESPTOOLPY_FLASHMODE_OPI + depends on ESPTOOLPY_OCT_FLASH + bool "OPI" + endchoice + choice ESPTOOLPY_FLASHMODE_OCT - depends on ESPTOOLPY_OCT_FLASH + depends on ESPTOOLPY_FLASHMODE_OPI prompt "Flash OPI mode" default ESPTOOLPY_FLASHMODE_OPI_DTR @@ -89,23 +113,6 @@ menu "Serial flasher config" bool "OPI_DTR" endchoice - choice ESPTOOLPY_FLASHMODE - prompt "Flash SPI mode" - default ESPTOOLPY_FLASHMODE_DIO - help - Mode the flash chip is flashed in, as well as the default mode for the - binary to run in. - - config ESPTOOLPY_FLASHMODE_QIO - bool "QIO" - config ESPTOOLPY_FLASHMODE_QOUT - bool "QOUT" - config ESPTOOLPY_FLASHMODE_DIO - bool "DIO" - config ESPTOOLPY_FLASHMODE_DOUT - bool "DOUT" - endchoice - # Note: we use esptool.py to flash bootloader in # dio mode for QIO/QOUT, bootloader then upgrades # itself to quad mode during initialisation @@ -115,6 +122,11 @@ menu "Serial flasher config" default "dio" if ESPTOOLPY_FLASHMODE_QOUT default "dio" if ESPTOOLPY_FLASHMODE_DIO default "dout" if ESPTOOLPY_FLASHMODE_DOUT + # The 1st and 2nd bootloader doesn't support opi mode, + # using fastrd instead. For now the ESPTOOL doesn't support + # fasted (see ESPTOOL-274), using dout instead. In ROM the flash mode + # information get from efuse, so don't care this dout choice. + default "dout" if ESPTOOLPY_FLASHMODE_OPI choice ESPTOOLPY_FLASHFREQ prompt "Flash SPI speed" @@ -123,6 +135,9 @@ menu "Serial flasher config" help The SPI flash frequency to be used. + config ESPTOOLPY_FLASHFREQ_120M + depends on ESPTOOLPY_FLASHMODE_OPI_STR || !ESPTOOLPY_OCT_FLASH + bool "120 MHz" config ESPTOOLPY_FLASHFREQ_80M bool "80 MHz" config ESPTOOLPY_FLASHFREQ_40M @@ -136,6 +151,9 @@ menu "Serial flasher config" config ESPTOOLPY_FLASHFREQ string + # On some of the ESP chips, max boot frequency would be equal to (or even lower than) 80m. + # We currently define this to `80m`. + default "80m" if ESPTOOLPY_FLASHFREQ_120M default "80m" if ESPTOOLPY_FLASHFREQ_80M default "40m" if ESPTOOLPY_FLASHFREQ_40M default "26m" if ESPTOOLPY_FLASHFREQ_26M diff --git a/components/esptool_py/esptool b/components/esptool_py/esptool index 5b6c6574a2..b082b0ed2d 160000 --- a/components/esptool_py/esptool +++ b/components/esptool_py/esptool @@ -1 +1 @@ -Subproject commit 5b6c6574a2c4b7dfa6dc07e17e68461dd2a2c145 +Subproject commit b082b0ed2d86b3330134c4854a021dfd14c29b08 diff --git a/components/fatfs/test/test_fatfs_sdmmc.c b/components/fatfs/test/test_fatfs_sdmmc.c index d4d0e8b77c..8cfb446199 100644 --- a/components/fatfs/test/test_fatfs_sdmmc.c +++ b/components/fatfs/test/test_fatfs_sdmmc.c @@ -83,14 +83,14 @@ TEST_CASE("Mount fails cleanly without card inserted", "[fatfs][sd][ignore]") HEAP_SIZE_CHECK(heap_size, 0); } -TEST_CASE("(SD) can create and write file", "[fatfs][sd][test_env=UT_T1_SDMODE]") +TEST_CASE("(SD) can create and write file", "[fatfs][sd][test_env=UT_T1_SDMODE][timeout=60]") { test_setup(); test_fatfs_create_file_with_text(test_filename, fatfs_test_hello_str); test_teardown(); } -TEST_CASE("(SD) can read file", "[fatfs][test_env=UT_T1_SDMODE]") +TEST_CASE("(SD) can read file", "[fatfs][test_env=UT_T1_SDMODE][timeout=60]") { test_setup(); test_fatfs_create_file_with_text(test_filename, fatfs_test_hello_str); @@ -98,7 +98,7 @@ TEST_CASE("(SD) can read file", "[fatfs][test_env=UT_T1_SDMODE]") test_teardown(); } -TEST_CASE("(SD) can read file with pread()", "[fatfs][test_env=UT_T1_SDMODE]") +TEST_CASE("(SD) can read file with pread()", "[fatfs][test_env=UT_T1_SDMODE][timeout=60]") { test_setup(); test_fatfs_create_file_with_text(test_filename, fatfs_test_hello_str); @@ -106,84 +106,84 @@ TEST_CASE("(SD) can read file with pread()", "[fatfs][test_env=UT_T1_SDMODE]") test_teardown(); } -TEST_CASE("(SD) pwrite() works well", "[fatfs][test_env=UT_T1_SDMODE]") +TEST_CASE("(SD) pwrite() works well", "[fatfs][test_env=UT_T1_SDMODE][timeout=60]") { test_setup(); test_fatfs_pwrite_file(test_filename); test_teardown(); } -TEST_CASE("(SD) overwrite and append file", "[fatfs][sd][test_env=UT_T1_SDMODE]") +TEST_CASE("(SD) overwrite and append file", "[fatfs][sd][test_env=UT_T1_SDMODE][timeout=60]") { test_setup(); test_fatfs_overwrite_append(test_filename); test_teardown(); } -TEST_CASE("(SD) can lseek", "[fatfs][sd][test_env=UT_T1_SDMODE]") +TEST_CASE("(SD) can lseek", "[fatfs][sd][test_env=UT_T1_SDMODE][timeout=60]") { test_setup(); test_fatfs_lseek("/sdcard/seek.txt"); test_teardown(); } -TEST_CASE("(SD) can truncate", "[fatfs][sd][test_env=UT_T1_SDMODE]") +TEST_CASE("(SD) can truncate", "[fatfs][sd][test_env=UT_T1_SDMODE][timeout=60]") { test_setup(); test_fatfs_truncate_file("/sdcard/truncate.txt"); test_teardown(); } -TEST_CASE("(SD) stat returns correct values", "[fatfs][test_env=UT_T1_SDMODE]") +TEST_CASE("(SD) stat returns correct values", "[fatfs][test_env=UT_T1_SDMODE][timeout=60]") { test_setup(); test_fatfs_stat("/sdcard/stat.txt", "/sdcard"); test_teardown(); } -TEST_CASE("(SD) utime sets modification time", "[fatfs][test_env=UT_T1_SDMODE]") +TEST_CASE("(SD) utime sets modification time", "[fatfs][test_env=UT_T1_SDMODE][timeout=60]") { test_setup(); test_fatfs_utime("/sdcard/utime.txt", "/sdcard"); test_teardown(); } -TEST_CASE("(SD) unlink removes a file", "[fatfs][test_env=UT_T1_SDMODE]") +TEST_CASE("(SD) unlink removes a file", "[fatfs][test_env=UT_T1_SDMODE][timeout=60]") { test_setup(); test_fatfs_unlink("/sdcard/unlink.txt"); test_teardown(); } -TEST_CASE("(SD) link copies a file, rename moves a file", "[fatfs][test_env=UT_T1_SDMODE]") +TEST_CASE("(SD) link copies a file, rename moves a file", "[fatfs][test_env=UT_T1_SDMODE][timeout=60]") { test_setup(); test_fatfs_link_rename("/sdcard/link"); test_teardown(); } -TEST_CASE("(SD) can create and remove directories", "[fatfs][test_env=UT_T1_SDMODE]") +TEST_CASE("(SD) can create and remove directories", "[fatfs][test_env=UT_T1_SDMODE][timeout=60]") { test_setup(); test_fatfs_mkdir_rmdir("/sdcard/dir"); test_teardown(); } -TEST_CASE("(SD) can opendir root directory of FS", "[fatfs][test_env=UT_T1_SDMODE]") +TEST_CASE("(SD) can opendir root directory of FS", "[fatfs][test_env=UT_T1_SDMODE][timeout=60]") { test_setup(); test_fatfs_can_opendir("/sdcard"); test_teardown(); } -TEST_CASE("(SD) opendir, readdir, rewinddir, seekdir work as expected", "[fatfs][test_env=UT_T1_SDMODE]") +TEST_CASE("(SD) opendir, readdir, rewinddir, seekdir work as expected", "[fatfs][test_env=UT_T1_SDMODE][timeout=60]") { test_setup(); test_fatfs_opendir_readdir_rewinddir("/sdcard/dir"); test_teardown(); } -TEST_CASE("(SD) multiple tasks can use same volume", "[fatfs][test_env=UT_T1_SDMODE]") +TEST_CASE("(SD) multiple tasks can use same volume", "[fatfs][test_env=UT_T1_SDMODE][timeout=60]") { test_setup(); test_fatfs_concurrent("/sdcard/f"); @@ -232,7 +232,7 @@ static void sdmmc_speed_test(void *buf, size_t buf_size, size_t file_size, bool TEST_ESP_OK(esp_vfs_fat_sdmmc_unmount()); } -TEST_CASE("(SD) mount two FAT partitions, SDMMC and WL, at the same time", "[fatfs][sd][test_env=UT_T1_SDMODE]") +TEST_CASE("(SD) mount two FAT partitions, SDMMC and WL, at the same time", "[fatfs][sd][test_env=UT_T1_SDMODE][timeout=60]") { esp_vfs_fat_sdmmc_mount_config_t mount_config = { .format_if_mount_failed = true, diff --git a/components/freemodbus/Kconfig b/components/freemodbus/Kconfig index cbdba581fa..a28e5f498a 100644 --- a/components/freemodbus/Kconfig +++ b/components/freemodbus/Kconfig @@ -187,25 +187,40 @@ menu "Modbus configuration" Modbus stack event processing time. config FMB_TIMER_PORT_ENABLED - bool "Modbus slave stack use timer for 3.5T symbol time measurement" + bool "Modbus stack use timer for 3.5T symbol time measurement" default n help If this option is set the Modbus stack uses timer for T3.5 time measurement. Else the internal UART TOUT timeout is used for 3.5T symbol time measurement. config FMB_TIMER_GROUP - int "Modbus Timer group number" + int "Slave Timer group number" range 0 1 default 0 help - Modbus Timer group number that is used for timeout measurement. + Modbus slave Timer group number that is used for timeout measurement. config FMB_TIMER_INDEX - int "Modbus Timer index in the group" + int "Slave Timer index in the group" range 0 1 default 0 help - Modbus Timer Index in the group that is used for timeout measurement. + Modbus slave Timer Index in the group that is used for timeout measurement. + + config FMB_MASTER_TIMER_GROUP + int "Master Timer group number" + range 0 1 + default FMB_TIMER_GROUP + help + Modbus master Timer group number that is used for timeout measurement. + + config FMB_MASTER_TIMER_INDEX + int "Master Timer index" + range 0 1 + default FMB_TIMER_INDEX + help + Modbus master Timer Index in the group that is used for timeout measurement. + Note: Modbus master and slave should have different timer index to be able to work simultaneously. config FMB_TIMER_ISR_IN_IRAM bool "Place timer interrupt handler into IRAM" diff --git a/components/freemodbus/common/include/esp_modbus_master.h b/components/freemodbus/common/include/esp_modbus_master.h index 621348e193..5d7539b08d 100644 --- a/components/freemodbus/common/include/esp_modbus_master.h +++ b/components/freemodbus/common/include/esp_modbus_master.h @@ -232,7 +232,7 @@ esp_err_t mbc_master_get_cid_info(uint16_t cid, const mb_parameter_descriptor_t* * @return * - esp_err_t ESP_OK - request was successful and value buffer contains * representation of actual parameter data from slave - * - esp_err_t ESP_ERR_INVALID_ARG - invalid argument of function + * - esp_err_t ESP_ERR_INVALID_ARG - invalid argument of function or parameter descriptor * - esp_err_t ESP_ERR_INVALID_RESPONSE - an invalid response from slave * - esp_err_t ESP_ERR_INVALID_STATE - invalid state during data processing or allocation failure * - esp_err_t ESP_ERR_TIMEOUT - operation timed out and no response from slave @@ -253,7 +253,7 @@ esp_err_t mbc_master_get_parameter(uint16_t cid, char* name, uint8_t* value, uin * * @return * - esp_err_t ESP_OK - request was successful and value was saved in the slave device registers - * - esp_err_t ESP_ERR_INVALID_ARG - invalid argument of function + * - esp_err_t ESP_ERR_INVALID_ARG - invalid argument of function or parameter descriptor * - esp_err_t ESP_ERR_INVALID_RESPONSE - an invalid response from slave during processing of parameter * - esp_err_t ESP_ERR_INVALID_STATE - invalid state during data processing or allocation failure * - esp_err_t ESP_ERR_TIMEOUT - operation timed out and no response from slave diff --git a/components/freemodbus/modbus/mb.c b/components/freemodbus/modbus/mb.c index be00e55c64..25722011a9 100644 --- a/components/freemodbus/modbus/mb.c +++ b/components/freemodbus/modbus/mb.c @@ -54,7 +54,7 @@ #endif #ifndef MB_PORT_HAS_CLOSE -#define MB_PORT_HAS_CLOSE 0 +#define MB_PORT_HAS_CLOSE 1 #endif /* ----------------------- Static variables ---------------------------------*/ diff --git a/components/freemodbus/modbus/tcp/mbtcp_m.c b/components/freemodbus/modbus/tcp/mbtcp_m.c index 18359d66d4..05eca0d407 100644 --- a/components/freemodbus/modbus/tcp/mbtcp_m.c +++ b/components/freemodbus/modbus/tcp/mbtcp_m.c @@ -91,8 +91,6 @@ eMBMasterTCPStart( void ) void eMBMasterTCPStop( void ) { - /* Make sure that no more clients are connected. */ - vMBMasterTCPPortDisable( ); } eMBErrorCode diff --git a/components/freemodbus/port/port.h b/components/freemodbus/port/port.h index 79fb0075ed..e67f56c140 100644 --- a/components/freemodbus/port/port.h +++ b/components/freemodbus/port/port.h @@ -61,6 +61,8 @@ #define MB_TCP_FRAME_LOG_BUFSIZE (256) +#define MB_PORT_HAS_CLOSE (1) // Define to explicitly close port on destroy + // Define number of timer reloads per 1 mS #define MB_TIMER_TICS_PER_MS (20UL) diff --git a/components/freemodbus/port/porttimer.c b/components/freemodbus/port/porttimer.c index 35371ad238..565d58ed02 100644 --- a/components/freemodbus/port/porttimer.c +++ b/components/freemodbus/port/porttimer.c @@ -147,8 +147,7 @@ vMBPortTimersDisable(void) void vMBPortTimerClose(void) { #ifdef CONFIG_FMB_TIMER_PORT_ENABLED - ESP_ERROR_CHECK(timer_pause(usTimerGroupIndex, usTimerIndex)); - ESP_ERROR_CHECK(timer_disable_intr(usTimerGroupIndex, usTimerIndex)); + ESP_ERROR_CHECK(timer_deinit(usTimerGroupIndex, usTimerIndex)); ESP_ERROR_CHECK(esp_intr_free(xTimerIntHandle)); #endif } diff --git a/components/freemodbus/port/porttimer_m.c b/components/freemodbus/port/porttimer_m.c index 9d70336327..e473195ef3 100644 --- a/components/freemodbus/port/porttimer_m.c +++ b/components/freemodbus/port/porttimer_m.c @@ -50,16 +50,13 @@ #define MB_TIMER_DIVIDER ((TIMER_BASE_CLK / 1000000UL) * MB_TICK_TIME_US - 1) // divider for 50uS #define MB_TIMER_WITH_RELOAD (1) -// Timer group and timer number to measure time (configurable in KConfig) -#define MB_TIMER_INDEX (CONFIG_FMB_TIMER_INDEX) -#define MB_TIMER_GROUP (CONFIG_FMB_TIMER_GROUP) - /* ----------------------- Variables ----------------------------------------*/ static USHORT usT35TimeOut50us; -static const USHORT usTimerIndex = MB_TIMER_INDEX; // Initialize Modbus Timer index used by stack, -static const USHORT usTimerGroupIndex = MB_TIMER_GROUP; // Timer group index used by stack -static timer_isr_handle_t xTimerIntHandle; // Timer interrupt handle +// Initialize Modbus Timer group and index used by stack +static const USHORT usTimerIndex = CONFIG_FMB_MASTER_TIMER_INDEX; +static const USHORT usTimerGroupIndex = CONFIG_FMB_MASTER_TIMER_GROUP; +static timer_isr_handle_t xTimerIntHandle; // Timer interrupt handle /* ----------------------- static functions ---------------------------------*/ static void IRAM_ATTR vTimerGroupIsr(void *param) @@ -193,7 +190,6 @@ vMBMasterPortTimersDisable() void vMBMasterPortTimerClose(void) { - ESP_ERROR_CHECK(timer_pause(usTimerGroupIndex, usTimerIndex)); - ESP_ERROR_CHECK(timer_disable_intr(usTimerGroupIndex, usTimerIndex)); + ESP_ERROR_CHECK(timer_deinit(usTimerGroupIndex, usTimerIndex)); ESP_ERROR_CHECK(esp_intr_free(xTimerIntHandle)); } diff --git a/components/freemodbus/serial_master/modbus_controller/mbc_serial_master.c b/components/freemodbus/serial_master/modbus_controller/mbc_serial_master.c index 4711630383..ebd38ee15a 100644 --- a/components/freemodbus/serial_master/modbus_controller/mbc_serial_master.c +++ b/components/freemodbus/serial_master/modbus_controller/mbc_serial_master.c @@ -410,8 +410,9 @@ static esp_err_t mbc_serial_master_get_parameter(uint16_t cid, char* name, // Set the type of parameter found in the table *type = reg_info.param_type; } else { - ESP_LOGD(MB_MASTER_TAG, "%s: The cid(%u) not found in the data dictionary.", + ESP_LOGE(MB_MASTER_TAG, "%s: The cid(%u) not found in the data dictionary.", __FUNCTION__, reg_info.cid); + error = ESP_ERR_INVALID_ARG; } return error; } @@ -446,6 +447,7 @@ static esp_err_t mbc_serial_master_set_parameter(uint16_t cid, char* name, } else { ESP_LOGE(MB_MASTER_TAG, "%s: The requested cid(%u) not found in the data dictionary.", __FUNCTION__, reg_info.cid); + error = ESP_ERR_INVALID_ARG; } return error; } diff --git a/components/freemodbus/serial_slave/modbus_controller/mbc_serial_slave.c b/components/freemodbus/serial_slave/modbus_controller/mbc_serial_slave.c index cf45730f40..b45e83980c 100644 --- a/components/freemodbus/serial_slave/modbus_controller/mbc_serial_slave.c +++ b/components/freemodbus/serial_slave/modbus_controller/mbc_serial_slave.c @@ -173,7 +173,7 @@ static esp_err_t mbc_serial_slave_destroy(void) mb_error = eMBClose(); MB_SLAVE_CHECK((mb_error == MB_ENOERR), ESP_ERR_INVALID_STATE, "mb stack close failure returned (0x%x).", (uint32_t)mb_error); - + mbs_interface_ptr = NULL; vMBPortSetMode((UCHAR)MB_PORT_INACTIVE); return ESP_OK; } diff --git a/components/freemodbus/tcp_master/modbus_controller/mbc_tcp_master.c b/components/freemodbus/tcp_master/modbus_controller/mbc_tcp_master.c index ab8964e5cc..1b7f3eb92a 100644 --- a/components/freemodbus/tcp_master/modbus_controller/mbc_tcp_master.c +++ b/components/freemodbus/tcp_master/modbus_controller/mbc_tcp_master.c @@ -33,10 +33,13 @@ #include "mbc_tcp_master.h" // for tcp master create function and types #include "port_tcp_master.h" // for tcp master port defines and types +#if MB_MASTER_TCP_ENABLED + /*-----------------------Master mode use these variables----------------------*/ // The response time is average processing time + data transmission #define MB_RESPONSE_TIMEOUT pdMS_TO_TICKS(CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND) +#define MB_TCP_CONNECTION_TOUT pdMS_TO_TICKS(CONFIG_FMB_TCP_CONNECTION_TOUT_SEC * 1000) static mb_master_interface_t* mbm_interface_ptr = NULL; @@ -116,15 +119,23 @@ static esp_err_t mbc_tcp_master_start(void) result = (BOOL)xMBTCPPortMasterAddSlaveIp(*comm_ip_table); MB_MASTER_CHECK(result, ESP_ERR_INVALID_STATE, "mb stack add slave IP failed: %s.", *comm_ip_table); } - // Add end of list condition - (void)xMBTCPPortMasterAddSlaveIp(NULL); + // Init polling event handlers and wait before start polling + xMBTCPPortMasterWaitEvent(mbm_opts->mbm_event_group, (EventBits_t)MB_EVENT_STACK_STARTED, 1); status = eMBMasterEnable(); MB_MASTER_CHECK((status == MB_ENOERR), ESP_ERR_INVALID_STATE, "mb stack set slave ID failure, eMBMasterEnable() returned (0x%x).", (uint32_t)status); - bool start = (bool)xMBTCPPortMasterWaitEvent(mbm_opts->mbm_event_group, (EventBits_t)MB_EVENT_STACK_STARTED); - MB_MASTER_CHECK((start), ESP_ERR_INVALID_STATE, "mb stack start failed."); + // Send end of list condition to start connection phase + (void)xMBTCPPortMasterAddSlaveIp(NULL); + + // Wait for connection done event + bool start = (bool)xMBTCPPortMasterWaitEvent(mbm_opts->mbm_event_group, + (EventBits_t)MB_EVENT_STACK_STARTED, MB_TCP_CONNECTION_TOUT); + MB_MASTER_CHECK((start), ESP_ERR_INVALID_STATE, + "mb stack could not connect to slaves for %d seconds.", + CONFIG_FMB_TCP_CONNECTION_TOUT_SEC); + return ESP_OK; } @@ -136,17 +147,19 @@ static esp_err_t mbc_tcp_master_destroy(void) MB_MASTER_CHECK((mbm_opts != NULL), ESP_ERR_INVALID_ARG, "mb incorrect options pointer."); eMBErrorCode mb_error = MB_ENOERR; - // Stop polling by clearing correspondent bit in the event group - xEventGroupClearBits(mbm_opts->mbm_event_group, - (EventBits_t)MB_EVENT_STACK_STARTED); // Disable and then destroy the Modbus stack mb_error = eMBMasterDisable(); MB_MASTER_CHECK((mb_error == MB_ENOERR), ESP_ERR_INVALID_STATE, "mb stack disable failure."); - (void)vTaskDelete(mbm_opts->mbm_task_handle); - (void)vEventGroupDelete(mbm_opts->mbm_event_group); mb_error = eMBMasterClose(); MB_MASTER_CHECK((mb_error == MB_ENOERR), ESP_ERR_INVALID_STATE, "mb stack close failure returned (0x%x).", (uint32_t)mb_error); + // Stop polling by clearing correspondent bit in the event group + xEventGroupClearBits(mbm_opts->mbm_event_group, + (EventBits_t)MB_EVENT_STACK_STARTED); + (void)vTaskDelete(mbm_opts->mbm_task_handle); + mbm_opts->mbm_task_handle = NULL; + (void)vEventGroupDelete(mbm_opts->mbm_event_group); + mbm_opts->mbm_event_group = NULL; free(mbm_interface_ptr); // free the memory allocated for options vMBPortSetMode((UCHAR)MB_PORT_INACTIVE); mbm_interface_ptr = NULL; @@ -431,8 +444,9 @@ static esp_err_t mbc_tcp_master_get_parameter(uint16_t cid, char* name, uint8_t* // Set the type of parameter found in the table *type = reg_info.param_type; } else { - ESP_LOGD(MB_MASTER_TAG, "%s: The cid(%u) not found in the data dictionary.", + ESP_LOGE(MB_MASTER_TAG, "%s: The cid(%u) not found in the data dictionary.", __FUNCTION__, reg_info.cid); + error = ESP_ERR_INVALID_ARG; } return error; } @@ -469,6 +483,7 @@ static esp_err_t mbc_tcp_master_set_parameter(uint16_t cid, char* name, uint8_t* } else { ESP_LOGE(MB_MASTER_TAG, "%s: The requested cid(%u) not found in the data dictionary.", __FUNCTION__, reg_info.cid); + error = ESP_ERR_INVALID_ARG; } return error; } @@ -714,3 +729,5 @@ esp_err_t mbc_tcp_master_create(void** handler) return ESP_OK; } + +#endif //#if MB_MASTER_TCP_ENABLED diff --git a/components/freemodbus/tcp_master/port/port_tcp_master.c b/components/freemodbus/tcp_master/port/port_tcp_master.c index 2c72882e16..f4ace753b7 100644 --- a/components/freemodbus/tcp_master/port/port_tcp_master.c +++ b/components/freemodbus/tcp_master/port/port_tcp_master.c @@ -52,6 +52,8 @@ #include "mbframe.h" #include "port_tcp_master.h" +#if MB_MASTER_TCP_ENABLED + /* ----------------------- Defines -----------------------------------------*/ #define MB_TCP_CONNECTION_TIMEOUT_MS ( 20 ) // Connection timeout in mS #define MB_TCP_RECONNECT_TIMEOUT ( 5000000 ) // Connection timeout in uS @@ -64,7 +66,7 @@ #define MB_EVENT_REQ_ERR_MASK ( EV_MASTER_PROCESS_SUCCESS ) -#define MB_EVENT_WAIT_TOUT_MS ( 2000 ) +#define MB_EVENT_WAIT_TOUT_MS ( 3000 ) #define MB_TCP_READ_TICK_MS ( 1 ) #define MB_TCP_READ_BUF_RETRY_CNT ( 4 ) @@ -76,6 +78,7 @@ void vMBPortEventClose( void ); /* ----------------------- Static variables ---------------------------------*/ static MbPortConfig_t xMbPortConfig; static EventGroupHandle_t xMasterEventHandle = NULL; +static SemaphoreHandle_t xShutdownSemaphore = NULL; static EventBits_t xMasterEvent = 0; /* ----------------------- Static functions ---------------------------------*/ @@ -84,7 +87,7 @@ static void vMBTCPPortMasterTask(void *pvParameters); /* ----------------------- Begin implementation -----------------------------*/ // Waits for stack start event to start Modbus event processing -BOOL xMBTCPPortMasterWaitEvent(EventGroupHandle_t xEventHandle, EventBits_t xEvent) +BOOL xMBTCPPortMasterWaitEvent(EventGroupHandle_t xEventHandle, EventBits_t xEvent, USHORT usTimeout) { xMasterEventHandle = xEventHandle; xMasterEvent = xEvent; @@ -92,7 +95,7 @@ BOOL xMBTCPPortMasterWaitEvent(EventGroupHandle_t xEventHandle, EventBits_t xEve (BaseType_t)(xEvent), pdFALSE, // do not clear start bit pdFALSE, - portMAX_DELAY); + usTimeout); return (BOOL)(status & xEvent); } @@ -157,6 +160,8 @@ static void vMBTCPPortMasterStartPoll(void) if (!(xFlags & xMasterEvent)) { ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Fail to start TCP stack."); } + } else { + ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Fail to start polling. Incorrect event handle..."); } } @@ -170,6 +175,8 @@ static void vMBTCPPortMasterStopPoll(void) if (!(xFlags & xMasterEvent)) { ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Fail to stop polling."); } + } else { + ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Fail to stop polling. Incorrect event handle..."); } } @@ -186,6 +193,14 @@ static void vMBTCPPortMasterMStoTimeVal(USHORT usTimeoutMs, struct timeval *tv) tv->tv_usec = (usTimeoutMs - (tv->tv_sec * 1000)) * 1000; } +static void xMBTCPPortMasterCheckShutdown(void) { + // First check if the task is not flagged for shutdown + if (xShutdownSemaphore) { + xSemaphoreGive(xShutdownSemaphore); + vTaskDelete(NULL); + } +} + static BOOL xMBTCPPortMasterCloseConnection(MbSlaveInfo_t* pxInfo) { if (!pxInfo) { @@ -257,6 +272,7 @@ static int xMBTCPPortMasterGetBuf(MbSlaveInfo_t* pxInfo, UCHAR* pucDstBuf, USHOR // Receive data from connected client while (usBytesLeft > 0) { + xMBTCPPortMasterCheckShutdown(); // none blocking read from socket with timeout xLength = recv(pxInfo->xSockId, pucBuf, usBytesLeft, MSG_DONTWAIT); if (xLength < 0) { @@ -342,6 +358,9 @@ static int vMBTCPPortMasterReadPacket(MbSlaveInfo_t* pxInfo) static err_t xMBTCPPortMasterSetNonBlocking(MbSlaveInfo_t* pxInfo) { + if (!pxInfo) { + return ERR_CONN; + } // Set non blocking attribute for socket ULONG ulFlags = fcntl(pxInfo->xSockId, F_GETFL); if (fcntl(pxInfo->xSockId, F_SETFL, ulFlags | O_NONBLOCK) == -1) { @@ -466,6 +485,10 @@ BOOL xMBTCPPortMasterAddSlaveIp(const CHAR* pcIpStr) // Unblocking connect function static err_t xMBTCPPortMasterConnect(MbSlaveInfo_t* pxInfo) { + if (!pxInfo) { + return ERR_CONN; + } + err_t xErr = ERR_OK; CHAR cStr[128]; CHAR* pcStr = NULL; @@ -624,7 +647,8 @@ static void vMBTCPPortMasterTask(void *pvParameters) // Register each slave in the connection info structure while (1) { - BaseType_t xStatus = xQueueReceive(xMbPortConfig.xConnectQueue, (void*)&pcAddrStr, portMAX_DELAY); + BaseType_t xStatus = xQueueReceive(xMbPortConfig.xConnectQueue, (void*)&pcAddrStr, pdMS_TO_TICKS(MB_EVENT_WAIT_TOUT_MS)); + xMBTCPPortMasterCheckShutdown(); if (xStatus != pdTRUE) { ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Fail to register slave IP."); } else { @@ -725,10 +749,14 @@ static void vMBTCPPortMasterTask(void *pvParameters) pxInfo->pcIpAddr, xErr); break; } - pxInfo->xError = xErr; + if (pxInfo) { + pxInfo->xError = xErr; + } + xMBTCPPortMasterCheckShutdown(); } } ESP_LOGI(MB_TCP_MASTER_PORT_TAG, "Connected %d slaves, start polling...", usSlaveConnCnt); + vMBTCPPortMasterStartPoll(); // Send event to start stack // Slave receive data loop @@ -746,6 +774,7 @@ static void vMBTCPPortMasterTask(void *pvParameters) ESP_LOGE(MB_TCP_MASTER_PORT_TAG, "Incorrect connection options for slave index: %d.", xMbPortConfig.ucCurSlaveIndex); vMBTCPPortMasterStopPoll(); + xMBTCPPortMasterCheckShutdown(); break; // incorrect slave descriptor, reconnect. } xTime = xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo); @@ -761,6 +790,7 @@ static void vMBTCPPortMasterTask(void *pvParameters) xTime = xMBTCPPortMasterGetRespTimeLeft(pxCurrInfo); // Wait completion of last transaction xMBMasterPortFsmWaitConfirmation(MB_EVENT_REQ_DONE_MASK, pdMS_TO_TICKS(xTime + 1)); + xMBTCPPortMasterCheckShutdown(); continue; } else if (xRes < 0) { // Select error (slave connection or r/w failure). @@ -771,6 +801,7 @@ static void vMBTCPPortMasterTask(void *pvParameters) xMBMasterPortFsmWaitConfirmation(MB_EVENT_REQ_DONE_MASK, pdMS_TO_TICKS(xTime)); // Stop polling process vMBTCPPortMasterStopPoll(); + xMBTCPPortMasterCheckShutdown(); // Check disconnected slaves, do not need a result just to print information. xMBTCPPortMasterCheckConnState(&xConnSet); break; @@ -803,6 +834,7 @@ static void vMBTCPPortMasterTask(void *pvParameters) pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr, xErr); // Stop polling process vMBTCPPortMasterStopPoll(); + xMBTCPPortMasterCheckShutdown(); // Check disconnected slaves, do not need a result just to print information. xMBTCPPortMasterCheckConnState(&xConnSet); break; @@ -819,6 +851,7 @@ static void vMBTCPPortMasterTask(void *pvParameters) pxCurrInfo->xIndex, pxCurrInfo->xSockId, pxCurrInfo->pcIpAddr, xTime); } } + xMBTCPPortMasterCheckShutdown(); } // while(usMbSlaveInfoCount) } // while (1) vTaskDelete(NULL); @@ -827,18 +860,6 @@ static void vMBTCPPortMasterTask(void *pvParameters) extern void vMBMasterPortEventClose(void); extern void vMBMasterPortTimerClose(void); -void -vMBMasterTCPPortClose(void) -{ - (void)vTaskDelete(xMbPortConfig.xMbTcpTaskHandle); - (void)vMBMasterTCPPortDisable(); - free(xMbPortConfig.pxMbSlaveInfo); - vQueueDelete(xMbPortConfig.xConnectQueue); - vMBMasterPortTimerClose(); - // Release resources for the event queue. - vMBMasterPortEventClose(); -} - void vMBMasterTCPPortDisable(void) { @@ -855,6 +876,29 @@ vMBMasterTCPPortDisable(void) } } +void +vMBMasterTCPPortClose(void) +{ + // Try to exit the task gracefully, so select could release its internal callbacks + // that were allocated on the stack of the task we're going to delete + xShutdownSemaphore = xSemaphoreCreateBinary(); + // if no semaphore (alloc issues) or couldn't acquire it, just delete the task + if (xShutdownSemaphore == NULL || xSemaphoreTake(xShutdownSemaphore, pdMS_TO_TICKS(MB_EVENT_WAIT_TOUT_MS)) != pdTRUE) { + ESP_LOGW(MB_TCP_MASTER_PORT_TAG, "Modbus port task couldn't exit gracefully within timeout -> abruptly deleting the task."); + vTaskDelete(xMbPortConfig.xMbTcpTaskHandle); + } + if (xShutdownSemaphore) { + vSemaphoreDelete(xShutdownSemaphore); + xShutdownSemaphore = NULL; + } + vMBMasterTCPPortDisable(); + free(xMbPortConfig.pxMbSlaveInfo); + vQueueDelete(xMbPortConfig.xConnectQueue); + vMBMasterPortTimerClose(); + // Release resources for the event queue. + vMBMasterPortEventClose(); +} + BOOL xMBMasterTCPPortGetRequest( UCHAR ** ppucMBTCPFrame, USHORT * usTCPLength ) { @@ -945,3 +989,5 @@ xMBMasterTCPTimerExpired(void) return xNeedPoll; } + +#endif //#if MB_MASTER_TCP_ENABLED diff --git a/components/freemodbus/tcp_master/port/port_tcp_master.h b/components/freemodbus/tcp_master/port/port_tcp_master.h index c1b0b816e5..c6a72fb2ee 100644 --- a/components/freemodbus/tcp_master/port/port_tcp_master.h +++ b/components/freemodbus/tcp_master/port/port_tcp_master.h @@ -104,10 +104,11 @@ BOOL xMBTCPPortMasterAddSlaveIp(const CHAR* pcIpStr); * * @param xEventHandle Master event handle * @param xEvent event mask to start Modbus stack FSM + * @param usTimeout - timeout in ticks to wait for stack to start * * @return TRUE if stack started, else FALSE */ -BOOL xMBTCPPortMasterWaitEvent(EventGroupHandle_t xEventHandle, EventBits_t xEvent); +BOOL xMBTCPPortMasterWaitEvent(EventGroupHandle_t xEventHandle, EventBits_t xEvent, USHORT usTimeout); /** * Set network options for Master port diff --git a/components/freemodbus/tcp_slave/modbus_controller/mbc_tcp_slave.c b/components/freemodbus/tcp_slave/modbus_controller/mbc_tcp_slave.c index 3b39e4e47d..e02a24a064 100644 --- a/components/freemodbus/tcp_slave/modbus_controller/mbc_tcp_slave.c +++ b/components/freemodbus/tcp_slave/modbus_controller/mbc_tcp_slave.c @@ -28,6 +28,8 @@ #include "mbc_tcp_slave.h" // for tcp slave mb controller defines #include "port_tcp_slave.h" // for tcp slave port defines +#if MB_TCP_ENABLED + // Shared pointer to interface structure static mb_slave_interface_t* mbs_interface_ptr = NULL; @@ -221,3 +223,5 @@ esp_err_t mbc_tcp_slave_create(void** handler) return ESP_OK; } + +#endif //#if MB_TCP_ENABLED diff --git a/components/freemodbus/tcp_slave/port/port_tcp_slave.c b/components/freemodbus/tcp_slave/port/port_tcp_slave.c index d5d83e7fef..3c4df63cf8 100644 --- a/components/freemodbus/tcp_slave/port/port_tcp_slave.c +++ b/components/freemodbus/tcp_slave/port/port_tcp_slave.c @@ -55,6 +55,8 @@ #include "port_tcp_slave.h" #include "esp_modbus_common.h" // for common types for network options +#if MB_TCP_ENABLED + /* ----------------------- Defines -----------------------------------------*/ #define MB_TCP_DISCONNECT_TIMEOUT ( CONFIG_FMB_TCP_CONNECTION_TOUT_SEC * 1000000 ) // disconnect timeout in uS #define MB_TCP_RESP_TIMEOUT_MS ( MB_MASTER_TIMEOUT_MS_RESPOND - 2 ) // slave response time limit @@ -728,3 +730,5 @@ xMBTCPPortSendResponse( UCHAR * pucMBTCPFrame, USHORT usTCPLength ) } return bFrameSent; } + +#endif //#if MB_TCP_ENABLED diff --git a/components/freertos/CMakeLists.txt b/components/freertos/CMakeLists.txt index a91ad72674..bd5acf5a2f 100644 --- a/components/freertos/CMakeLists.txt +++ b/components/freertos/CMakeLists.txt @@ -6,8 +6,7 @@ endif() idf_build_get_property(target IDF_TARGET) -# should test arch here not target, TODO ESP32-C3 IDF-1754 -if(NOT "${target}" STREQUAL "esp32c3" AND NOT "${target}" STREQUAL "esp32h2") +if(CONFIG_IDF_TARGET_ARCH_XTENSA) set(srcs "port/xtensa/port.c" "port/xtensa/portasm.S" @@ -19,35 +18,39 @@ if(NOT "${target}" STREQUAL "esp32c3" AND NOT "${target}" STREQUAL "esp32h2") set(include_dirs include - port/xtensa/include) + include/esp_additions/freertos # For files with #include "FreeRTOSConfig.h" + port/xtensa/include # For including arch-specific FreeRTOSConfig_arch.h in port//include + include/esp_additions) # For files with #include "freertos/FreeRTOSConfig.h" set(private_include_dirs - include/freertos port/xtensa/include/freertos port/xtensa + port/priv_include .) - set(required_components app_trace esp_timer) -else() # RISC-V +elseif(CONFIG_IDF_TARGET_ARCH_RISCV) set(srcs "port/riscv/port.c" "port/riscv/portasm.S") set(include_dirs include - port/riscv/include) + include/esp_additions/freertos # For files with #include "FreeRTOSConfig.h" + port/riscv/include # For including arch-specific FreeRTOSConfig_arch.h in port//include + include/esp_additions) # For files with #include "freertos/FreeRTOSConfig.h" set(private_include_dirs - include/freertos port/riscv/include/freertos port/riscv + port/priv_include .) - set(required_components app_trace esp_timer) endif() list(APPEND srcs + "esp_additions/task_snapshot.c" "port/port_common.c" + "port/port_systick.c" "croutine.c" "event_groups.c" "list.c" @@ -58,12 +61,18 @@ list(APPEND srcs "FreeRTOS-openocd.c" "freertos_v8_compat.c") +list(APPEND private_include_dirs + "include/freertos") + if(CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY) list(APPEND srcs "port/xtensa/xtensa_loadstore_handler.S") endif() +# esp_timer is required by FreeRTOS because we use esp_tiemr_get_time() to do profiling # app_trace is required by FreeRTOS headers only when CONFIG_APPTRACE_SV_ENABLE=y, -# but requirements can't depend on config options, so always require it. +# REQUIRES can't depend on config options, so always require it. +set(required_components app_trace esp_timer) + idf_component_register(SRCS "${srcs}" INCLUDE_DIRS ${include_dirs} PRIV_INCLUDE_DIRS ${private_include_dirs} diff --git a/components/freertos/GitHub-FreeRTOS-Kernel-Home.url b/components/freertos/GitHub-FreeRTOS-Kernel-Home.url new file mode 100644 index 0000000000..87d25ce02f --- /dev/null +++ b/components/freertos/GitHub-FreeRTOS-Kernel-Home.url @@ -0,0 +1,7 @@ +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,2 +[InternetShortcut] +URL=https://github.com/FreeRTOS/FreeRTOS-Kernel +IconIndex=0 +IDList= +HotKey=0 diff --git a/components/freertos/History.txt b/components/freertos/History.txt index 8caaf23ffe..32d391cea9 100644 --- a/components/freertos/History.txt +++ b/components/freertos/History.txt @@ -1,4 +1,4 @@ -Documentation and download available at http://www.FreeRTOS.org/ +Documentation and download available at https://www.FreeRTOS.org/ Changes since the last release: + Added xTaskCatchUpTicks() which corrects the tick count value after the @@ -19,6 +19,147 @@ Changes since the last release: configISR_STACK_SIZE_WORDS is defined to a non zero value. +Changes between FreeRTOS V10.4.2 and FreeRTOS V10.4.3 released December 14 2020 + + V10.4.3 is included in the 202012.00 LTS release. Learn more at https:/freertos.org/lts-libraries.html + + See https://www.FreeRTOS.org/FreeRTOS-V10.4.x.html + + + Changes to improve robustness and consistency for buffer allocation in + the heap, queue and stream buffer. + + The following functions can no longer be called from unprivileged code. + - xTaskCreateRestricted + - xTaskCreateRestrictedStatic + - vTaskAllocateMPURegions + + +Changes between FreeRTOS V10.4.1 and FreeRTOS V10.4.2 released November 10 2020 + + See https://www.FreeRTOS.org/FreeRTOS-V10.4.x.html + + + Fix an issue in the ARMv8-M ports that caused BASEPRI to be masked + between the first task starting to execute and that task making + a FreeRTOS API call. + + Introduced xTaskDelayUntil(), which is functionally equivalent to + vTaskDelayUntil(), with the addition of returning a value to + indicating whether or not the function placed the calling task into + the Blocked state or not. + + Update WolfSSL to 4.5.0 and add the FIPS ready demo. + + Add support for ESP IDF 4.2 to ThirdParty Xtensa port. + + Re-introduce uxTopUsedPriority to support OpenOCD debugging. + + Convert most dependent libraries in FreeRTOS/FreeRTOS to submodules. + + Various general maintenance and improvements to MISRA compliance. + + +Changes between FreeRTOS V10.4.0 and FreeRTOS V10.4.1 released September 17 2020 + + See https://www.FreeRTOS.org/FreeRTOS-V10.4.x.html + + + Fixed an incorrectly named parameter that prevented the + ulTaskNotifyTakeIndexed macro compiling, and the name space clash in the + test code that prevented this error causing test failures. + + +Changes between FreeRTOS V10.3.1 and FreeRTOS V10.4.0 released September 10 2020 + + See https://www.FreeRTOS.org/FreeRTOS-V10.4.x.html + + Major enhancements: + + + Task notifications: Prior to FreeRTOS V10.4.0 each created task had a + single direct to task notification. From FreeRTOS V10.4.0 each task has + an array of notifications. The direct to task notification API has been + extended with API functions postfixed with "Indexed" to enable the API to + operate on a task notification at any array index. See + https://www.freertos.org/RTOS-task-notifications.html for more information. + + Kernel ports that support memory protection units (MPUs): The ARMv7-M and + ARMv8-M MPU ports now support a privilege access only heap. The ARMv7-M + MPU ports now support devices that have 16 MPU regions, have the ability + to override default memory attributes for privileged code and data + regions, and have the ability to place the FreeRTOS kernel code outside of + the Flash memory. The ARMv8-M MPU ports now support tickless idle mode. + See https://www.freertos.org/FreeRTOS-MPU-memory-protection-unit.html + for more information. + + Additional noteworthy updates: + + + Code formatting is now automated to facilitate the increase in + collaborative development in Git. The auto-formated code is not identical + to the original formatting conventions. Most notably spaces are now used + in place of tabs. + + The prototypes for callback functions (those that start with "Application", + such as vApplicationStackOverflowHook()) are now in the FreeRTOS header + files, removing the need for application writers to add prototypes into + the C files in which they define the functions. + + New Renesas RXv3 port layer. + + Updates to the Synopsys ARC code, including support for EM and HS cores, + and updated BSP. + + Added new POSIX port layer that allows FreeRTOS to run on Linux hosts in + the same way the Windows port layer enables FreeRTOS to run on Windows + hosts. + + Many other minor optimisations and enhancements. For full details + see https://github.com/FreeRTOS/FreeRTOS-Kernel/commits/master + + +Changes between FreeRTOS V10.3.0 and FreeRTOS V10.3.1 released February 18 2020 + + See https://www.FreeRTOS.org/FreeRTOS-V10.3.x.html + + + ./FreeRTOS-Labs directory was removed from this file. The libraries it + contained are now available as a separate download. + +Changes between FreeRTOS V10.2.1 and FreeRTOS V10.3.0 released February 7 2020 + + See https://www.FreeRTOS.org/FreeRTOS-V10.3.x.html + + New and updated kernel ports: + + + Added RISC-V port for the IAR compiler. + + Update the Windows simulator port to use a synchronous object to prevent + a user reported error whereby a task continues to run for a short time + after being moved to the Blocked state. Note we were not able to + replicate the reported issue and it likely depends on your CPU model. + + Correct alignment of stack top in RISC-V port when + configISR_STACK_SIZE_WORDS is defined to a non zero value, which causes + the interrupt stack to be statically allocated. + + The RISC-V machine timer compare register can now be for any HART, whereas + previously it was always assumed FreeRTOS was running on HART 0. + + Update the sequence used to update the 64-bit machine timer + compare register on 32-bit cores to match that suggested in RISC-V + documentation. + + Added tickless low power modes into the ARM, IAR and GCC Cortex-M0 compiler + ports. + + Updated the behaviour of the ARMv7-M MPU (Memory Protection Unit) ports to + match that of the ARMv8-M ports whereby privilege escalations can only + originate from within the kernel's own memory segment. Added + configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY configuration constant. + + Update existing MPU ports to correctly disable the MPU before it is + updated. + + Added contributed port and demo application for a T-Head (formally C-SKY) + microcontroller. + + New API functions: + + + Added the vPortGetHeapStats() API function which returns information on + the heap_4 and heap_5 state. + + Added xTaskCatchUpTicks(), which corrects the tick count value after the + application code has held interrupts disabled for an extended period. + + Added xTaskNotifyValueClear() API function. + + Added uxTimerGetReloadMode() API function. + + Other miscellaneous changes: + + Change type of uxPendedTicks from UBaseType_t to TickType_t to ensure it + has the same type as variables with which it is compared to, and therefore + also renamed the variable xPendingTicks. + + Update Keil projects that use the MPU so memory regions come from linker + script (scatter file) variables instead of being hard coded. + + Added LPC51U68 Cortex-M0+ demos for GCC (MCUXpresso), Keil and IAR + compilers. + + Added CORTEX_MPU_STM32L4_Discovery_Keil_STM32Cube demo. + + Added LPC54018 MPU demo. + + Rename xTaskGetIdleRunTimeCounter() to ulTaskGetIdleRunTimeCounter(). + + Changes between FreeRTOS V10.2.1 and FreeRTOS V10.2.0 released May 13 2019: + Added ARM Cortex-M23 port layer to complement the pre-existing ARM @@ -163,8 +304,8 @@ Changes between FreeRTOS V9.0.1 and FreeRTOS V10.0.0: New Features and components: - + Stream Buffers - see http://www.FreeRTOS.org/RTOS-stream-buffer-example.html - + Message Buffers - see http://www.FreeRTOS.org//RTOS-message-buffer-example.html + + Stream Buffers - see https://www.FreeRTOS.org/RTOS-stream-buffer-example.html + + Message Buffers - see https://www.FreeRTOS.org//RTOS-message-buffer-example.html + Move FreeRTOS+TCP into the main repository, along with the basic Win32 TCP demo FreeRTOS_Plus_TCP_Minimal_Windows_Simulator. @@ -266,7 +407,7 @@ Changes since FreeRTOS V9.0.0: Changes between FreeRTOS V9.0.0 and FreeRTOS V9.0.0rc2 released May 25 2016: - See http://www.FreeRTOS.org/FreeRTOS-V9.html + See https://www.FreeRTOS.org/FreeRTOS-V9.html RTOS kernel updates: @@ -275,7 +416,7 @@ Changes between FreeRTOS V9.0.0 and FreeRTOS V9.0.0rc2 released May 25 2016: "CreateStatic()" API functions. The stack size parameter in xTaskCreateStatic() is now uint32_t, which changes the prototype of the callback functions. See the following URL: - http://www.freertos.org/xTaskCreateStatic.html + https://www.FreeRTOS.org/xTaskCreateStatic.html + GCC ARM Cortex-A port: Introduced the configUSE_TASK_FPU_SUPPORT constant. When configUSE_TASK_FPU_SUPPORT is set to 2 every task is automatically given a floating point (FPU) context. @@ -324,7 +465,7 @@ Changes between FreeRTOS V9.0.0 and FreeRTOS V9.0.0rc2 released May 25 2016: Changes between FreeRTOS V9.0.0rc1 and FreeRTOS V9.0.0rc2 (release candidate 2) released March 30 2016: - NOTE - See http://www.FreeRTOS.org/FreeRTOS-V9.html for details + NOTE - See https://www.FreeRTOS.org/FreeRTOS-V9.html for details + The functions that create RTOS objects using static memory allocation have been simplified and will not revert to using dynamic allocation if a @@ -515,6 +656,8 @@ Changes between V8.2.0 and V8.2.1 released 24th March 2015. Windows port. + Update the PIC32 port to remove deprecation warnings output by the latest XC32 compilers. + + Fix bug when xQueueOverwrite() and xQueueOverwrite() from ISR are used to + overwrite items in two queues that are part of the same set. Demo application updates: @@ -535,7 +678,7 @@ Changes between V8.1.2 and V8.2.0 released 16th January 2015 Significant RTOS kernel updates: + MAJOR NEW FEATURE! Task notifications. Please see the following URL for - details: http://www.FreeRTOS.org/RTOS-task-notifications.html + details: https://www.FreeRTOS.org/RTOS-task-notifications.html + NEW HEADER FILE REQUIRED! Obsolete definitions have been separated into a new header file called FreeRTOS/Source/include/deprecated_definitions.h. This header file must be present to build. Note some of the obsolete @@ -699,21 +842,21 @@ Changes between V8.0.0 and V8.0.1 released 2nd May 2014 Changes between V7.6.0 and V8.0.0 released 19th Feb 2014 - http://www.freertos.org/upgrading-to-FreeRTOS-V8.html + https://www.FreeRTOS.org/upgrading-to-FreeRTOS-V8.html FreeRTOS V8.x.x is a drop-in compatible replacement for FreeRTOS V7.x.x, although a change to the type used to reference character strings may result in application code generating a few (easily clearable) compiler warnings after the upgrade, and an updated typedef naming convention means use of the old typedef names is now discouraged. - See http://www.freertos.org/upgrading-to-FreeRTOS-V8.html for full + See https://www.FreeRTOS.org/upgrading-to-FreeRTOS-V8.html for full information. New features and functionality: - + Event groups - see http://www.freertos.org/FreeRTOS-Event-Groups.html + + Event groups - see https://www.FreeRTOS.org/FreeRTOS-Event-Groups.html + Centralised deferred interrupt processing - see - http://www.freertos.org/xTimerPendFunctionCallFromISR.html + https://www.FreeRTOS.org/xTimerPendFunctionCallFromISR.html Other updates: @@ -724,7 +867,7 @@ Changes between V7.6.0 and V8.0.0 released 19th Feb 2014 priority of the Running task. + New low power tickless demonstration project that targets the ST STM32L microcontroller - see - http://www.freertos.org/STM32L-discovery-low-power-tickless-RTOS-demo.html + https://www.FreeRTOS.org/STM32L-discovery-low-power-tickless-RTOS-demo.html + Add xPortGetMinimumEverFreeHeapSize() to heap_4.c. + Small change to the tickless low power implementation on the SAM4L to ensure the alarm value (compare match value) cannot be set to zero when a @@ -874,8 +1017,8 @@ Changes between V7.4.2 and V7.5.0 released July 19 2013 New API functions: - + uxTaskGetSystemState() http://www.freertos.org/uxTaskGetSystemState.html - + xQueueOverwrite() http://www.freertos.org/xQueueOverwrite.html + + uxTaskGetSystemState() https://www.FreeRTOS.org/uxTaskGetSystemState.html + + xQueueOverwrite() https://www.FreeRTOS.org/xQueueOverwrite.html + xQueueOverwriteFromISR() + xQueuePeekFromISR() @@ -888,7 +1031,7 @@ Changes between V7.4.2 and V7.5.0 released July 19 2013 + Microsemi SmartFusion2 New FreeRTOSConfig.h settings - http://shop.freertos.org/FreeRTOS_API_and_Configuration_Reference_s/1822.htm + https://freertos.org/a00110.html + configUSE_TIME_SLICING + configUSE_NEWLIB_REENTRANT @@ -925,7 +1068,7 @@ Changes between V7.4.1 and V7.4.2 released May 1 2013 + Added FreeRTOS+FAT SL source code and demo project. The demo project runs in the FreeRTOS Windows simulator for easy and hardware independent - experimentation and evaluation. See http://www.FreeRTOS.org/fat_sl + experimentation and evaluation. See https://www.FreeRTOS.org/fat_sl Changes between V7.4.0 and V7.4.1 released April 18 2013 @@ -954,7 +1097,7 @@ Changes between V7.4.0 and V7.4.1 released April 18 2013 Changes between V7.3.0 and V7.4.0 released February 20 2013 + New feature: Queue sets. See: - http://www.FreeRTOS.org/Pend-on-multiple-rtos-objects.html + https://www.FreeRTOS.org/Pend-on-multiple-rtos-objects.html + Overhauled the default tickless idle mode implementation provided with the ARM Cortex-M3 port layers. + Enhanced tickless support in the core kernel code with the introduction of @@ -1101,7 +1244,7 @@ Changes between V7.1.0 and V7.1.1 released May 1 2012 + Introduced the portSETUP_TCB() macro to remove the requirement for the Windows simulator to use the traceTASK_CREATE() macro, leaving the trace - macro available for use by FreeRTOS+Trace (http://www.FreeRTOS.org/trace). + macro available for use by FreeRTOS+Trace (https://www.FreeRTOS.org/trace). + Added a new trace macro, traceMOVE_TASK_TO_READY_STATE(), to allow future FreeRTOS+Trace versions to provide even more information to users. + Updated the FreeRTOS MPU port to be correct for changes that were @@ -1129,7 +1272,7 @@ Changes between V7.1.0 and V7.1.1 released May 1 2012 + The command interpreter has now been formally released as FreeRTOS+CLI, and been moved out of the main FreeRTOS download, to instead be available - from the FreeRTOS+ Ecosystem site http://www.FreeRTOS.org/plus. + from the FreeRTOS+ Ecosystem site https://www.FreeRTOS.org/plus. + flash_timer.c/h has been added to the list of standard demo tasks. This performs the same functionality as the flash.c tasks, but using software timers in place of tasks. @@ -1411,7 +1554,7 @@ Changes between V6.0.3 and V6.0.4 released March 14 2010 + All the contributed files that were located in the Demo/Unsupported_Demos directory have been removed. These files are instead now available in the new Community Contributions section of the FreeRTOS website. See - http://www.freertos.org/RTOS-contributed-ports.html + https://www.FreeRTOS.org/RTOS-contributed-ports.html + The project file located in the Demo/CORTEX_STM32F107_GCC_Rowley directory has been upgraded to use V2.x of the Rowley Crossworks STM32 support package. @@ -1704,9 +1847,6 @@ Changes between V4.8.0 and V5.0.0 released April 15, 2008 compiler might not issue any type mismatch warnings! - See http://www.FreeRTOS.org/upgrading.html for full information. - - Other changes: + Support added for the new Luminary Micro LM3S3768 and LM3S3748 Cortex-M3 @@ -1960,7 +2100,7 @@ Changes between V4.0.1 and V4.0.2 released May 28, 2006 it was also called when the tick function was called during the scheduler unlocking process. + The EMAC driver in the SAM7X lwIP demo has been made more robust as per - the thread: http://sourceforge.net/forum/message.php?msg_id=3714405 + the thread: https://sourceforge.net/forum/message.php?msg_id=3714405 + In the PC ports: Add function prvSetTickFrequencyDefault() to set the DOS tick back to its proper value when the scheduler exits. Thanks Raynald! diff --git a/components/freertos/Kconfig b/components/freertos/Kconfig index ffe2f4987e..0c66f9af8f 100644 --- a/components/freertos/Kconfig +++ b/components/freertos/Kconfig @@ -18,9 +18,23 @@ menu "FreeRTOS" hex default 0x7FFFFFFF + config FREERTOS_TICK_SUPPORT_CORETIMER + bool + default y if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 + + config FREERTOS_TICK_SUPPORT_SYSTIMER + bool + default y if !FREERTOS_TICK_SUPPORT_CORETIMER + # ESP32-S3, ESP32-C3 and ESP32-H2 can use Systimer for FreeRTOS SysTick + # ESP32S2 also has SYSTIMER but it can not be used for the FreeRTOS SysTick because: + # - It has only one counter, which already in use esp_timer. + # A counter for SysTick should be stall in debug mode but work esp_timer. + # - It is not possible to allocate two handlers for esp_timer and SysTick. + choice FREERTOS_CORETIMER prompt "Xtensa timer to use as the FreeRTOS tick source" - default FREERTOS_CORETIMER_0 + default FREERTOS_CORETIMER_0 if FREERTOS_TICK_SUPPORT_CORETIMER + default FREERTOS_CORETIMER_SYSTIMER_LVL1 if FREERTOS_TICK_SUPPORT_SYSTIMER help FreeRTOS needs a timer with an associated interrupt to use as the main tick source to increase counters, run timers and do @@ -29,16 +43,38 @@ menu "FreeRTOS" config FREERTOS_CORETIMER_0 bool "Timer 0 (int 6, level 1)" + depends on FREERTOS_TICK_SUPPORT_CORETIMER help Select this to use timer 0 config FREERTOS_CORETIMER_1 bool "Timer 1 (int 15, level 3)" + depends on FREERTOS_TICK_SUPPORT_CORETIMER help Select this to use timer 1 + config FREERTOS_CORETIMER_SYSTIMER_LVL1 + bool "SYSTIMER 0 (level 1)" + depends on FREERTOS_TICK_SUPPORT_SYSTIMER + help + Select this to use systimer with the 1 interrupt priority. + + config FREERTOS_CORETIMER_SYSTIMER_LVL3 + bool "SYSTIMER 0 (level 3)" + depends on FREERTOS_TICK_SUPPORT_SYSTIMER + help + Select this to use systimer with the 3 interrupt priority. + endchoice + config FREERTOS_SYSTICK_USES_SYSTIMER + bool + default y if FREERTOS_CORETIMER_SYSTIMER_LVL1 || FREERTOS_CORETIMER_SYSTIMER_LVL3 + + config FREERTOS_SYSTICK_USES_CCOUNT + bool + default y if FREERTOS_CORETIMER_0 || FREERTOS_CORETIMER_1 + config FREERTOS_OPTIMIZED_SCHEDULER bool "Enable FreeRTOS pĺatform optimized scheduler" depends on FREERTOS_UNICORE @@ -343,6 +379,7 @@ menu "FreeRTOS" config FREERTOS_RUN_TIME_STATS_USING_CPU_CLK bool "Use CPU Clock for run time stats" + depends on FREERTOS_SYSTICK_USES_CCOUNT help CPU Clock will be used as the clock source for the generation of run time stats. The CPU Clock has a frequency dependent on @@ -428,4 +465,18 @@ menu "FreeRTOS" When enabled, the usage of float type is allowed inside Level 1 ISRs. + config FREERTOS_ENABLE_TASK_SNAPSHOT + bool "Enable task snapshot functions" + default y + help + When enabled, the functions related to snapshots, such as vTaskGetSnapshot or uxTaskGetSnapshotAll, + are compiled and linked. + + config FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH + bool "Place task snapshot functions into flash" + default n + depends on FREERTOS_ENABLE_TASK_SNAPSHOT && !ESP_PANIC_HANDLER_IRAM + help + When enabled, the functions related to snapshots, such as vTaskGetSnapshot or uxTaskGetSnapshotAll, + will be placed in flash. Note that if enabled, these functions cannot be called when cache is disabled. endmenu diff --git a/components/freertos/license.txt b/components/freertos/LICENSE.md similarity index 92% rename from components/freertos/license.txt rename to components/freertos/LICENSE.md index 9e2f3185f2..9cf106272a 100644 --- a/components/freertos/license.txt +++ b/components/freertos/LICENSE.md @@ -1,7 +1,5 @@ MIT License -Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. - 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 the Software without restriction, including without limitation the rights diff --git a/components/freertos/Quick_Start_Guide.url b/components/freertos/Quick_Start_Guide.url new file mode 100644 index 0000000000..ebefebd612 --- /dev/null +++ b/components/freertos/Quick_Start_Guide.url @@ -0,0 +1,5 @@ +[InternetShortcut] +URL=https://www.FreeRTOS.org/FreeRTOS-quick-start-guide.html +IDList= +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,2 diff --git a/components/freertos/component.mk b/components/freertos/component.mk index e72576cbcd..2fd40c90ac 100644 --- a/components/freertos/component.mk +++ b/components/freertos/component.mk @@ -6,9 +6,9 @@ ifdef CONFIG_FREERTOS_DEBUG_OCDAWARE COMPONENT_ADD_LDFLAGS += -Wl,--undefined=uxTopUsedPriority endif -COMPONENT_ADD_INCLUDEDIRS := include port/xtensa/include -COMPONENT_PRIV_INCLUDEDIRS := include/freertos port/xtensa/include/freertos port/xtensa . -COMPONENT_SRCDIRS += port port/xtensa +COMPONENT_ADD_INCLUDEDIRS := include include/esp_additions include/esp_additions/freertos port/xtensa/include +COMPONENT_PRIV_INCLUDEDIRS := include/esp_additions include/esp_additions/freertos include/freertos port/xtensa/include/freertos port/xtensa port/priv_include . +COMPONENT_SRCDIRS += port port/xtensa esp_additions/ ifndef CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY COMPONENT_OBJEXCLUDE := xtensa/xtensa_loadstore_handler.o diff --git a/components/freertos/croutine.c b/components/freertos/croutine.c index f8e24ee7d3..c4c0fab422 100644 --- a/components/freertos/croutine.c +++ b/components/freertos/croutine.c @@ -1,6 +1,6 @@ /* - * FreeRTOS Kernel V10.2.1 - * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V10.4.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * 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 @@ -19,10 +19,9 @@ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS * - * 1 tab == 4 spaces! */ #include "FreeRTOS.h" @@ -30,32 +29,32 @@ #include "croutine.h" /* Remove the whole file is co-routines are not being used. */ -#if( configUSE_CO_ROUTINES != 0 ) +#if ( configUSE_CO_ROUTINES != 0 ) /* * Some kernel aware debuggers require data to be viewed to be global, rather * than file scope. */ -#ifdef portREMOVE_STATIC_QUALIFIER - #define static -#endif + #ifdef portREMOVE_STATIC_QUALIFIER + #define static + #endif /* Lists for ready and blocked co-routines. --------------------*/ -static List_t pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ]; /*< Prioritised ready co-routines. */ -static List_t xDelayedCoRoutineList1; /*< Delayed co-routines. */ -static List_t xDelayedCoRoutineList2; /*< Delayed co-routines (two lists are used - one for delays that have overflowed the current tick count. */ -static List_t * pxDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used. */ -static List_t * pxOverflowDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used to hold co-routines that have overflowed the current tick count. */ -static List_t xPendingReadyCoRoutineList; /*< Holds co-routines that have been readied by an external event. They cannot be added directly to the ready lists as the ready lists cannot be accessed by interrupts. */ + static List_t pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ]; /*< Prioritised ready co-routines. */ + static List_t xDelayedCoRoutineList1; /*< Delayed co-routines. */ + static List_t xDelayedCoRoutineList2; /*< Delayed co-routines (two lists are used - one for delays that have overflowed the current tick count. */ + static List_t * pxDelayedCoRoutineList = NULL; /*< Points to the delayed co-routine list currently being used. */ + static List_t * pxOverflowDelayedCoRoutineList = NULL; /*< Points to the delayed co-routine list currently being used to hold co-routines that have overflowed the current tick count. */ + static List_t xPendingReadyCoRoutineList; /*< Holds co-routines that have been readied by an external event. They cannot be added directly to the ready lists as the ready lists cannot be accessed by interrupts. */ /* Other file private variables. --------------------------------*/ -CRCB_t * pxCurrentCoRoutine = NULL; -static UBaseType_t uxTopCoRoutineReadyPriority = 0; -static TickType_t xCoRoutineTickCount = 0, xLastTickCount = 0, xPassedTicks = 0; + CRCB_t * pxCurrentCoRoutine = NULL; + static UBaseType_t uxTopCoRoutineReadyPriority = 0; + static TickType_t xCoRoutineTickCount = 0, xLastTickCount = 0, xPassedTicks = 0; /* The initial state of the co-routine when it is created. */ -#define corINITIAL_STATE ( 0 ) + #define corINITIAL_STATE ( 0 ) /* * Place the co-routine represented by pxCRCB into the appropriate ready queue @@ -64,20 +63,20 @@ static TickType_t xCoRoutineTickCount = 0, xLastTickCount = 0, xPassedTicks = 0; * This macro accesses the co-routine ready lists and therefore must not be * used from within an ISR. */ -#define prvAddCoRoutineToReadyQueue( pxCRCB ) \ -{ \ - if( pxCRCB->uxPriority > uxTopCoRoutineReadyPriority ) \ - { \ - uxTopCoRoutineReadyPriority = pxCRCB->uxPriority; \ - } \ - vListInsertEnd( ( List_t * ) &( pxReadyCoRoutineLists[ pxCRCB->uxPriority ] ), &( pxCRCB->xGenericListItem ) ); \ -} + #define prvAddCoRoutineToReadyQueue( pxCRCB ) \ + { \ + if( pxCRCB->uxPriority > uxTopCoRoutineReadyPriority ) \ + { \ + uxTopCoRoutineReadyPriority = pxCRCB->uxPriority; \ + } \ + vListInsertEnd( ( List_t * ) &( pxReadyCoRoutineLists[ pxCRCB->uxPriority ] ), &( pxCRCB->xGenericListItem ) ); \ + } /* * Utility to ready all the lists used by the scheduler. This is called * automatically upon the creation of the first co-routine. */ -static void prvInitialiseCoRoutineLists( void ); + static void prvInitialiseCoRoutineLists( void ); /* * Co-routines that are readied by an interrupt cannot be placed directly into @@ -85,7 +84,7 @@ static void prvInitialiseCoRoutineLists( void ); * in the pending ready list in order that they can later be moved to the ready * list by the co-routine scheduler. */ -static void prvCheckPendingReadyList( void ); + static void prvCheckPendingReadyList( void ); /* * Macro that looks at the list of co-routines that are currently delayed to @@ -95,258 +94,268 @@ static void prvCheckPendingReadyList( void ); * meaning once one co-routine has been found whose timer has not expired * we need not look any further down the list. */ -static void prvCheckDelayedList( void ); + static void prvCheckDelayedList( void ); /*-----------------------------------------------------------*/ -BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPriority, UBaseType_t uxIndex ) -{ -BaseType_t xReturn; -CRCB_t *pxCoRoutine; + BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, + UBaseType_t uxPriority, + UBaseType_t uxIndex ) + { + BaseType_t xReturn; + CRCB_t * pxCoRoutine; - /* Allocate the memory that will store the co-routine control block. */ - pxCoRoutine = ( CRCB_t * ) pvPortMalloc( sizeof( CRCB_t ) ); - if( pxCoRoutine ) - { - /* If pxCurrentCoRoutine is NULL then this is the first co-routine to - be created and the co-routine data structures need initialising. */ - if( pxCurrentCoRoutine == NULL ) - { - pxCurrentCoRoutine = pxCoRoutine; - prvInitialiseCoRoutineLists(); - } + /* Allocate the memory that will store the co-routine control block. */ + pxCoRoutine = ( CRCB_t * ) pvPortMalloc( sizeof( CRCB_t ) ); - /* Check the priority is within limits. */ - if( uxPriority >= configMAX_CO_ROUTINE_PRIORITIES ) - { - uxPriority = configMAX_CO_ROUTINE_PRIORITIES - 1; - } + if( pxCoRoutine ) + { + /* If pxCurrentCoRoutine is NULL then this is the first co-routine to + * be created and the co-routine data structures need initialising. */ + if( pxCurrentCoRoutine == NULL ) + { + pxCurrentCoRoutine = pxCoRoutine; + prvInitialiseCoRoutineLists(); + } - /* Fill out the co-routine control block from the function parameters. */ - pxCoRoutine->uxState = corINITIAL_STATE; - pxCoRoutine->uxPriority = uxPriority; - pxCoRoutine->uxIndex = uxIndex; - pxCoRoutine->pxCoRoutineFunction = pxCoRoutineCode; + /* Check the priority is within limits. */ + if( uxPriority >= configMAX_CO_ROUTINE_PRIORITIES ) + { + uxPriority = configMAX_CO_ROUTINE_PRIORITIES - 1; + } - /* Initialise all the other co-routine control block parameters. */ - vListInitialiseItem( &( pxCoRoutine->xGenericListItem ) ); - vListInitialiseItem( &( pxCoRoutine->xEventListItem ) ); + /* Fill out the co-routine control block from the function parameters. */ + pxCoRoutine->uxState = corINITIAL_STATE; + pxCoRoutine->uxPriority = uxPriority; + pxCoRoutine->uxIndex = uxIndex; + pxCoRoutine->pxCoRoutineFunction = pxCoRoutineCode; - /* Set the co-routine control block as a link back from the ListItem_t. - This is so we can get back to the containing CRCB from a generic item - in a list. */ - listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xGenericListItem ), pxCoRoutine ); - listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xEventListItem ), pxCoRoutine ); + /* Initialise all the other co-routine control block parameters. */ + vListInitialiseItem( &( pxCoRoutine->xGenericListItem ) ); + vListInitialiseItem( &( pxCoRoutine->xEventListItem ) ); - /* Event lists are always in priority order. */ - listSET_LIST_ITEM_VALUE( &( pxCoRoutine->xEventListItem ), ( ( TickType_t ) configMAX_CO_ROUTINE_PRIORITIES - ( TickType_t ) uxPriority ) ); + /* Set the co-routine control block as a link back from the ListItem_t. + * This is so we can get back to the containing CRCB from a generic item + * in a list. */ + listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xGenericListItem ), pxCoRoutine ); + listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xEventListItem ), pxCoRoutine ); - /* Now the co-routine has been initialised it can be added to the ready - list at the correct priority. */ - prvAddCoRoutineToReadyQueue( pxCoRoutine ); + /* Event lists are always in priority order. */ + listSET_LIST_ITEM_VALUE( &( pxCoRoutine->xEventListItem ), ( ( TickType_t ) configMAX_CO_ROUTINE_PRIORITIES - ( TickType_t ) uxPriority ) ); - xReturn = pdPASS; - } - else - { - xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; - } + /* Now the co-routine has been initialised it can be added to the ready + * list at the correct priority. */ + prvAddCoRoutineToReadyQueue( pxCoRoutine ); - return xReturn; -} + xReturn = pdPASS; + } + else + { + xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; + } + + return xReturn; + } /*-----------------------------------------------------------*/ -void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, List_t *pxEventList ) -{ -TickType_t xTimeToWake; + void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, + List_t * pxEventList ) + { + TickType_t xTimeToWake; - /* Calculate the time to wake - this may overflow but this is - not a problem. */ - xTimeToWake = xCoRoutineTickCount + xTicksToDelay; + /* Calculate the time to wake - this may overflow but this is + * not a problem. */ + xTimeToWake = xCoRoutineTickCount + xTicksToDelay; - /* We must remove ourselves from the ready list before adding - ourselves to the blocked list as the same list item is used for - both lists. */ - ( void ) uxListRemove( ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) ); + /* We must remove ourselves from the ready list before adding + * ourselves to the blocked list as the same list item is used for + * both lists. */ + ( void ) uxListRemove( ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) ); - /* The list item will be inserted in wake time order. */ - listSET_LIST_ITEM_VALUE( &( pxCurrentCoRoutine->xGenericListItem ), xTimeToWake ); + /* The list item will be inserted in wake time order. */ + listSET_LIST_ITEM_VALUE( &( pxCurrentCoRoutine->xGenericListItem ), xTimeToWake ); - if( xTimeToWake < xCoRoutineTickCount ) - { - /* Wake time has overflowed. Place this item in the - overflow list. */ - vListInsert( ( List_t * ) pxOverflowDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) ); - } - else - { - /* The wake time has not overflowed, so we can use the - current block list. */ - vListInsert( ( List_t * ) pxDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) ); - } + if( xTimeToWake < xCoRoutineTickCount ) + { + /* Wake time has overflowed. Place this item in the + * overflow list. */ + vListInsert( ( List_t * ) pxOverflowDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) ); + } + else + { + /* The wake time has not overflowed, so we can use the + * current block list. */ + vListInsert( ( List_t * ) pxDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) ); + } - if( pxEventList ) - { - /* Also add the co-routine to an event list. If this is done then the - function must be called with interrupts disabled. */ - vListInsert( pxEventList, &( pxCurrentCoRoutine->xEventListItem ) ); - } -} + if( pxEventList ) + { + /* Also add the co-routine to an event list. If this is done then the + * function must be called with interrupts disabled. */ + vListInsert( pxEventList, &( pxCurrentCoRoutine->xEventListItem ) ); + } + } /*-----------------------------------------------------------*/ -static void prvCheckPendingReadyList( void ) -{ - /* Are there any co-routines waiting to get moved to the ready list? These - are co-routines that have been readied by an ISR. The ISR cannot access - the ready lists itself. */ - while( listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) == pdFALSE ) - { - CRCB_t *pxUnblockedCRCB; + static void prvCheckPendingReadyList( void ) + { + /* Are there any co-routines waiting to get moved to the ready list? These + * are co-routines that have been readied by an ISR. The ISR cannot access + * the ready lists itself. */ + while( listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) == pdFALSE ) + { + CRCB_t * pxUnblockedCRCB; - /* The pending ready list can be accessed by an ISR. */ - portDISABLE_INTERRUPTS(); - { - pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( (&xPendingReadyCoRoutineList) ); - ( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) ); - } - portENABLE_INTERRUPTS(); + /* The pending ready list can be accessed by an ISR. */ + portDISABLE_INTERRUPTS(); + { + pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyCoRoutineList ) ); + ( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) ); + } + portENABLE_INTERRUPTS(); - ( void ) uxListRemove( &( pxUnblockedCRCB->xGenericListItem ) ); - prvAddCoRoutineToReadyQueue( pxUnblockedCRCB ); - } -} + ( void ) uxListRemove( &( pxUnblockedCRCB->xGenericListItem ) ); + prvAddCoRoutineToReadyQueue( pxUnblockedCRCB ); + } + } /*-----------------------------------------------------------*/ -static void prvCheckDelayedList( void ) -{ -CRCB_t *pxCRCB; + static void prvCheckDelayedList( void ) + { + CRCB_t * pxCRCB; - xPassedTicks = xTaskGetTickCount() - xLastTickCount; - while( xPassedTicks ) - { - xCoRoutineTickCount++; - xPassedTicks--; + xPassedTicks = xTaskGetTickCount() - xLastTickCount; - /* If the tick count has overflowed we need to swap the ready lists. */ - if( xCoRoutineTickCount == 0 ) - { - List_t * pxTemp; + while( xPassedTicks ) + { + xCoRoutineTickCount++; + xPassedTicks--; - /* Tick count has overflowed so we need to swap the delay lists. If there are - any items in pxDelayedCoRoutineList here then there is an error! */ - pxTemp = pxDelayedCoRoutineList; - pxDelayedCoRoutineList = pxOverflowDelayedCoRoutineList; - pxOverflowDelayedCoRoutineList = pxTemp; - } + /* If the tick count has overflowed we need to swap the ready lists. */ + if( xCoRoutineTickCount == 0 ) + { + List_t * pxTemp; - /* See if this tick has made a timeout expire. */ - while( listLIST_IS_EMPTY( pxDelayedCoRoutineList ) == pdFALSE ) - { - pxCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedCoRoutineList ); + /* Tick count has overflowed so we need to swap the delay lists. If there are + * any items in pxDelayedCoRoutineList here then there is an error! */ + pxTemp = pxDelayedCoRoutineList; + pxDelayedCoRoutineList = pxOverflowDelayedCoRoutineList; + pxOverflowDelayedCoRoutineList = pxTemp; + } - if( xCoRoutineTickCount < listGET_LIST_ITEM_VALUE( &( pxCRCB->xGenericListItem ) ) ) - { - /* Timeout not yet expired. */ - break; - } + /* See if this tick has made a timeout expire. */ + while( listLIST_IS_EMPTY( pxDelayedCoRoutineList ) == pdFALSE ) + { + pxCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedCoRoutineList ); - portDISABLE_INTERRUPTS(); - { - /* The event could have occurred just before this critical - section. If this is the case then the generic list item will - have been moved to the pending ready list and the following - line is still valid. Also the pvContainer parameter will have - been set to NULL so the following lines are also valid. */ - ( void ) uxListRemove( &( pxCRCB->xGenericListItem ) ); + if( xCoRoutineTickCount < listGET_LIST_ITEM_VALUE( &( pxCRCB->xGenericListItem ) ) ) + { + /* Timeout not yet expired. */ + break; + } - /* Is the co-routine waiting on an event also? */ - if( pxCRCB->xEventListItem.pxContainer ) - { - ( void ) uxListRemove( &( pxCRCB->xEventListItem ) ); - } - } - portENABLE_INTERRUPTS(); + portDISABLE_INTERRUPTS(); + { + /* The event could have occurred just before this critical + * section. If this is the case then the generic list item will + * have been moved to the pending ready list and the following + * line is still valid. Also the pvContainer parameter will have + * been set to NULL so the following lines are also valid. */ + ( void ) uxListRemove( &( pxCRCB->xGenericListItem ) ); - prvAddCoRoutineToReadyQueue( pxCRCB ); - } - } + /* Is the co-routine waiting on an event also? */ + if( pxCRCB->xEventListItem.pxContainer ) + { + ( void ) uxListRemove( &( pxCRCB->xEventListItem ) ); + } + } + portENABLE_INTERRUPTS(); - xLastTickCount = xCoRoutineTickCount; -} + prvAddCoRoutineToReadyQueue( pxCRCB ); + } + } + + xLastTickCount = xCoRoutineTickCount; + } /*-----------------------------------------------------------*/ -void vCoRoutineSchedule( void ) -{ - /* See if any co-routines readied by events need moving to the ready lists. */ - prvCheckPendingReadyList(); + void vCoRoutineSchedule( void ) + { + /* Only run a co-routine after prvInitialiseCoRoutineLists() has been + * called. prvInitialiseCoRoutineLists() is called automatically when a + * co-routine is created. */ + if( pxDelayedCoRoutineList != NULL ) + { + /* See if any co-routines readied by events need moving to the ready lists. */ + prvCheckPendingReadyList(); - /* See if any delayed co-routines have timed out. */ - prvCheckDelayedList(); + /* See if any delayed co-routines have timed out. */ + prvCheckDelayedList(); - /* Find the highest priority queue that contains ready co-routines. */ - while( listLIST_IS_EMPTY( &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ) ) - { - if( uxTopCoRoutineReadyPriority == 0 ) - { - /* No more co-routines to check. */ - return; - } - --uxTopCoRoutineReadyPriority; - } + /* Find the highest priority queue that contains ready co-routines. */ + while( listLIST_IS_EMPTY( &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ) ) + { + if( uxTopCoRoutineReadyPriority == 0 ) + { + /* No more co-routines to check. */ + return; + } - /* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the co-routines - of the same priority get an equal share of the processor time. */ - listGET_OWNER_OF_NEXT_ENTRY( pxCurrentCoRoutine, &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ); + --uxTopCoRoutineReadyPriority; + } - /* Call the co-routine. */ - ( pxCurrentCoRoutine->pxCoRoutineFunction )( pxCurrentCoRoutine, pxCurrentCoRoutine->uxIndex ); + /* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the co-routines + * of the same priority get an equal share of the processor time. */ + listGET_OWNER_OF_NEXT_ENTRY( pxCurrentCoRoutine, &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ); - return; -} + /* Call the co-routine. */ + ( pxCurrentCoRoutine->pxCoRoutineFunction )( pxCurrentCoRoutine, pxCurrentCoRoutine->uxIndex ); + } + } /*-----------------------------------------------------------*/ -static void prvInitialiseCoRoutineLists( void ) -{ -UBaseType_t uxPriority; + static void prvInitialiseCoRoutineLists( void ) + { + UBaseType_t uxPriority; - for( uxPriority = 0; uxPriority < configMAX_CO_ROUTINE_PRIORITIES; uxPriority++ ) - { - vListInitialise( ( List_t * ) &( pxReadyCoRoutineLists[ uxPriority ] ) ); - } + for( uxPriority = 0; uxPriority < configMAX_CO_ROUTINE_PRIORITIES; uxPriority++ ) + { + vListInitialise( ( List_t * ) &( pxReadyCoRoutineLists[ uxPriority ] ) ); + } - vListInitialise( ( List_t * ) &xDelayedCoRoutineList1 ); - vListInitialise( ( List_t * ) &xDelayedCoRoutineList2 ); - vListInitialise( ( List_t * ) &xPendingReadyCoRoutineList ); + vListInitialise( ( List_t * ) &xDelayedCoRoutineList1 ); + vListInitialise( ( List_t * ) &xDelayedCoRoutineList2 ); + vListInitialise( ( List_t * ) &xPendingReadyCoRoutineList ); - /* Start with pxDelayedCoRoutineList using list1 and the - pxOverflowDelayedCoRoutineList using list2. */ - pxDelayedCoRoutineList = &xDelayedCoRoutineList1; - pxOverflowDelayedCoRoutineList = &xDelayedCoRoutineList2; -} + /* Start with pxDelayedCoRoutineList using list1 and the + * pxOverflowDelayedCoRoutineList using list2. */ + pxDelayedCoRoutineList = &xDelayedCoRoutineList1; + pxOverflowDelayedCoRoutineList = &xDelayedCoRoutineList2; + } /*-----------------------------------------------------------*/ -BaseType_t xCoRoutineRemoveFromEventList( const List_t *pxEventList ) -{ -CRCB_t *pxUnblockedCRCB; -BaseType_t xReturn; + BaseType_t xCoRoutineRemoveFromEventList( const List_t * pxEventList ) + { + CRCB_t * pxUnblockedCRCB; + BaseType_t xReturn; - /* This function is called from within an interrupt. It can only access - event lists and the pending ready list. This function assumes that a - check has already been made to ensure pxEventList is not empty. */ - pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); - ( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) ); - vListInsertEnd( ( List_t * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) ); + /* This function is called from within an interrupt. It can only access + * event lists and the pending ready list. This function assumes that a + * check has already been made to ensure pxEventList is not empty. */ + pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); + ( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) ); + vListInsertEnd( ( List_t * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) ); - if( pxUnblockedCRCB->uxPriority >= pxCurrentCoRoutine->uxPriority ) - { - xReturn = pdTRUE; - } - else - { - xReturn = pdFALSE; - } + if( pxUnblockedCRCB->uxPriority >= pxCurrentCoRoutine->uxPriority ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } - return xReturn; -} + return xReturn; + } #endif /* configUSE_CO_ROUTINES == 0 */ diff --git a/components/freertos/esp_additions/task_snapshot.c b/components/freertos/esp_additions/task_snapshot.c new file mode 100644 index 0000000000..5fb599bbac --- /dev/null +++ b/components/freertos/esp_additions/task_snapshot.c @@ -0,0 +1,220 @@ +// Copyright 2015-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. + +#include "freertos/FreeRTOS.h" +#include "freertos/task_snapshot.h" + +#ifndef DIM +#define DIM(t) (sizeof(t)/ sizeof(*(t))) +#endif + +#if ( configENABLE_TASK_SNAPSHOT == 1 ) + + static void prvTaskGetSnapshot( TaskSnapshot_t *pxTaskSnapshotArray, UBaseType_t *uxTask, void *pxTCB ) + { + if (pxTCB == NULL) { + return; + } + pxTaskSnapshotArray[ *uxTask ].pxTCB = pxTCB; + pxTaskSnapshotArray[ *uxTask ].pxTopOfStack = (StackType_t *) pxTCBGetTopOfStack(pxTCB); + #if( portSTACK_GROWTH < 0 ) + { + pxTaskSnapshotArray[ *uxTask ].pxEndOfStack = pxTCBGetEndOfStack(pxTCB); + } + #else + { + pxTaskSnapshotArray[ *uxTask ].pxEndOfStack = pxTCBGetStartOfStack(pxTCB); + } + #endif + (*uxTask)++; + } + + static void prvTaskGetSnapshotsFromList( TaskSnapshot_t *pxTaskSnapshotArray, UBaseType_t *uxTask, const UBaseType_t uxArraySize, List_t *pxList ) + { + void *pxNextTCB = NULL; + void *pxFirstTCB = NULL; + + if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 ) + { + listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); + do + { + if( *uxTask >= uxArraySize ) { + break; + } + + listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); + prvTaskGetSnapshot( pxTaskSnapshotArray, uxTask, pxNextTCB ); + } while( pxNextTCB != pxFirstTCB ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + UBaseType_t uxTaskGetSnapshotAll( TaskSnapshot_t * const pxTaskSnapshotArray, const UBaseType_t uxArraySize, UBaseType_t * const pxTcbSz ) + { + UBaseType_t uxTask = 0; + UBaseType_t i = 0; + + + *pxTcbSz = pxTCBGetSize(); + /* Fill in an TaskStatus_t structure with information on each + task in the Ready state. */ + i = configMAX_PRIORITIES; + do + { + i--; + prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxListGetReadyTask(i) ); + } while( i > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + + /* Fill in an TaskStatus_t structure with information on each + task in the Blocked state. */ + prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxGetDelayedTaskList() ); + prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxGetOverflowDelayedTaskList() ); + for (i = 0; i < portNUM_PROCESSORS; i++) { + if( uxTask >= uxArraySize ) { + break; + } + prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxListGetReadyPendingTask(i) ); + } + + #if( INCLUDE_vTaskDelete == 1 ) + { + prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxGetTasksWaitingTermination() ); + } + #endif + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxGetSuspendedTaskList() ); + } + #endif + return uxTask; + } + + static void *prvFirstTaskGet( List_t *pxList ) + { + ListItem_t *pxListItem = listGET_HEAD_ENTRY( pxList ); + if( pxListItem != listGET_END_MARKER( pxList ) ) { + return listGET_LIST_ITEM_OWNER( pxListItem ); + } + return NULL; + } + + static void *prvNextTaskGet( void *pxTCB ) + { + List_t *pxList = listLIST_ITEM_CONTAINER( pxTCBGetStateListItem(pxTCB) ); + ListItem_t *pxListItem = listGET_NEXT( pxTCBGetStateListItem(pxTCB) ); + if( pxListItem != listGET_END_MARKER( pxList ) ) { + return listGET_LIST_ITEM_OWNER( pxListItem ); + } + return NULL; + } + + void vTaskGetSnapshot( TaskHandle_t pxTask, TaskSnapshot_t *pxTaskSnapshot ) + { + configASSERT( portVALID_TCB_MEM(pxTask) ); + configASSERT( pxTaskSnapshot != NULL ); + pxTaskSnapshot->pxTCB = (void*) pxTask; + pxTaskSnapshot->pxTopOfStack = pxTCBGetTopOfStack((void*) pxTask); + pxTaskSnapshot->pxEndOfStack = pxTCBGetEndOfStack((void*) pxTask); + } + + TaskHandle_t pxTaskGetNext( TaskHandle_t pxTask ) + { + void *pxTCB = pxTask; + List_t *pxTaskList = NULL; + UBaseType_t i = configMAX_PRIORITIES; + UBaseType_t bCurTaskListFound = pdFALSE; + List_t *task_lists[] = { + pxGetDelayedTaskList(), + pxGetOverflowDelayedTaskList(), + #if( INCLUDE_vTaskDelete == 1 ) + pxGetTasksWaitingTermination(), + #endif + #if( INCLUDE_vTaskSuspend == 1 ) + pxGetSuspendedTaskList() + #endif + }; + + if( pxTask != NULL && !portVALID_TCB_MEM(pxTask) ) { + return NULL; + } + + if( pxTCB != NULL ) { + pxTCB = prvNextTaskGet( pxTCB ); + if( pxTCB != NULL ) { + // take care not to return garbage + return portVALID_TCB_MEM(pxTCB) ? pxTCB : NULL; + } + pxTaskList = listLIST_ITEM_CONTAINER( pxTCBGetStateListItem(pxTask) ); + } + /* ready tasks lists */ + do + { + i--; + List_t *pxList = pxListGetReadyTask(i); + if( bCurTaskListFound == pdFALSE && pxTaskList != NULL ) { + /* need to find list the current task item from */ + if( pxTaskList == pxList ) { + bCurTaskListFound = pdTRUE; + } + continue; /* go to the next 'ready list' */ + } + pxTCB = prvFirstTaskGet( pxList ); + if( pxTCB != NULL ) { + // take care not to return garbage + return portVALID_TCB_MEM(pxTCB) ? pxTCB : NULL; + } + } + while( i > tskIDLE_PRIORITY ); + /* pending ready tasks lists */ + for (i = 0; i < portNUM_PROCESSORS; i++) { + List_t *pxList = pxListGetReadyPendingTask(i); + if( bCurTaskListFound == pdFALSE && pxTaskList != NULL ) { + /* need to find list the current task item from */ + if( pxTaskList == pxList ) { + bCurTaskListFound = pdTRUE; + } + continue; /* go to the next 'ready list' */ + } + pxTCB = prvFirstTaskGet( pxList ); + if( pxTCB != NULL ) { + // take care not to return garbage + return portVALID_TCB_MEM(pxTCB) ? pxTCB : NULL; + } + } + /* other tasks lists */ + for (i = 0; i < DIM(task_lists); i++) { + List_t *pxList = task_lists[ i ]; + if( bCurTaskListFound == pdFALSE && pxTaskList != NULL ) { + /* need to find list the current task item from */ + if( pxTaskList == pxList ) { + bCurTaskListFound = pdTRUE; + } + continue; /* go to the next 'ready list' */ + } + pxTCB = prvFirstTaskGet( pxList ); + if( pxTCB != NULL ) { + // take care not to return garbage + return portVALID_TCB_MEM(pxTCB) ? pxTCB : NULL; + } + } + + return NULL; + } + +#endif diff --git a/components/freertos/event_groups.c b/components/freertos/event_groups.c index f1e1b362e6..6a4dbf886e 100644 --- a/components/freertos/event_groups.c +++ b/components/freertos/event_groups.c @@ -1,6 +1,6 @@ /* - * FreeRTOS Kernel V10.2.1 - * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V10.4.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * 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 @@ -19,18 +19,17 @@ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS * - * 1 tab == 4 spaces! */ /* Standard includes. */ #include /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining -all the API functions to use the MPU wrappers. That should only be done when -task.h is included from an application file. */ + * all the API functions to use the MPU wrappers. That should only be done when + * task.h is included from an application file. */ #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE /* FreeRTOS includes. */ @@ -39,41 +38,55 @@ task.h is included from an application file. */ #include "timers.h" #include "event_groups.h" +#ifdef ESP_PLATFORM +#define taskCRITICAL_MUX &pxEventBits->eventGroupMux +#undef taskENTER_CRITICAL +#undef taskEXIT_CRITICAL +#undef taskENTER_CRITICAL_ISR +#undef taskEXIT_CRITICAL_ISR +#define taskENTER_CRITICAL( ) portENTER_CRITICAL( taskCRITICAL_MUX ) +#define taskEXIT_CRITICAL( ) portEXIT_CRITICAL( taskCRITICAL_MUX ) +#define taskENTER_CRITICAL_ISR( ) portENTER_CRITICAL_ISR( taskCRITICAL_MUX ) +#define taskEXIT_CRITICAL_ISR( ) portEXIT_CRITICAL_ISR( taskCRITICAL_MUX ) +#endif + /* Lint e961, e750 and e9021 are suppressed as a MISRA exception justified -because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined -for the header files above, but not in this file, in order to generate the -correct privileged Vs unprivileged linkage and placement. */ + * because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined + * for the header files above, but not in this file, in order to generate the + * correct privileged Vs unprivileged linkage and placement. */ #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021 See comment above. */ /* The following bit fields convey control information in a task's event list -item value. It is important they don't clash with the -taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */ + * item value. It is important they don't clash with the + * taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */ #if configUSE_16_BIT_TICKS == 1 - #define eventCLEAR_EVENTS_ON_EXIT_BIT 0x0100U - #define eventUNBLOCKED_DUE_TO_BIT_SET 0x0200U - #define eventWAIT_FOR_ALL_BITS 0x0400U - #define eventEVENT_BITS_CONTROL_BYTES 0xff00U + #define eventCLEAR_EVENTS_ON_EXIT_BIT 0x0100U + #define eventUNBLOCKED_DUE_TO_BIT_SET 0x0200U + #define eventWAIT_FOR_ALL_BITS 0x0400U + #define eventEVENT_BITS_CONTROL_BYTES 0xff00U #else - #define eventCLEAR_EVENTS_ON_EXIT_BIT 0x01000000UL - #define eventUNBLOCKED_DUE_TO_BIT_SET 0x02000000UL - #define eventWAIT_FOR_ALL_BITS 0x04000000UL - #define eventEVENT_BITS_CONTROL_BYTES 0xff000000UL + #define eventCLEAR_EVENTS_ON_EXIT_BIT 0x01000000UL + #define eventUNBLOCKED_DUE_TO_BIT_SET 0x02000000UL + #define eventWAIT_FOR_ALL_BITS 0x04000000UL + #define eventEVENT_BITS_CONTROL_BYTES 0xff000000UL #endif typedef struct EventGroupDef_t { - EventBits_t uxEventBits; - List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */ + EventBits_t uxEventBits; + List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */ - #if( configUSE_TRACE_FACILITY == 1 ) - UBaseType_t uxEventGroupNumber; - #endif + #if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxEventGroupNumber; + #endif - #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) - uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */ - #endif + #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */ + #endif - portMUX_TYPE eventGroupMux; //Mutex required due to SMP +#ifdef ESP_PLATFORM + portMUX_TYPE eventGroupMux; //Mutex required due to SMP +#endif // ESP_PLATFORM } EventGroup_t; /*-----------------------------------------------------------*/ @@ -86,660 +99,735 @@ typedef struct EventGroupDef_t * wait condition is met if any of the bits set in uxBitsToWait for are also set * in uxCurrentEventBits. */ -static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits ) PRIVILEGED_FUNCTION; +static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, + const EventBits_t uxBitsToWaitFor, + const BaseType_t xWaitForAllBits ) PRIVILEGED_FUNCTION; /*-----------------------------------------------------------*/ -#if( configSUPPORT_STATIC_ALLOCATION == 1 ) +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) - EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer ) - { - EventGroup_t *pxEventBits; + EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer ) + { + EventGroup_t * pxEventBits; - /* A StaticEventGroup_t object must be provided. */ - configASSERT( pxEventGroupBuffer ); + /* A StaticEventGroup_t object must be provided. */ + configASSERT( pxEventGroupBuffer ); - #if( configASSERT_DEFINED == 1 ) - { - /* Sanity check that the size of the structure used to declare a - variable of type StaticEventGroup_t equals the size of the real - event group structure. */ - volatile size_t xSize = sizeof( StaticEventGroup_t ); - configASSERT( xSize == sizeof( EventGroup_t ) ); - } /*lint !e529 xSize is referenced if configASSERT() is defined. */ - #endif /* configASSERT_DEFINED */ + #if ( configASSERT_DEFINED == 1 ) + { + /* Sanity check that the size of the structure used to declare a + * variable of type StaticEventGroup_t equals the size of the real + * event group structure. */ + volatile size_t xSize = sizeof( StaticEventGroup_t ); + configASSERT( xSize == sizeof( EventGroup_t ) ); + } /*lint !e529 xSize is referenced if configASSERT() is defined. */ + #endif /* configASSERT_DEFINED */ - /* The user has provided a statically allocated event group - use it. */ - pxEventBits = ( EventGroup_t * ) pxEventGroupBuffer; /*lint !e740 !e9087 EventGroup_t and StaticEventGroup_t are deliberately aliased for data hiding purposes and guaranteed to have the same size and alignment requirement - checked by configASSERT(). */ + /* The user has provided a statically allocated event group - use it. */ + pxEventBits = ( EventGroup_t * ) pxEventGroupBuffer; /*lint !e740 !e9087 EventGroup_t and StaticEventGroup_t are deliberately aliased for data hiding purposes and guaranteed to have the same size and alignment requirement - checked by configASSERT(). */ - if( pxEventBits != NULL ) - { - pxEventBits->uxEventBits = 0; - vListInitialise( &( pxEventBits->xTasksWaitingForBits ) ); + if( pxEventBits != NULL ) + { + pxEventBits->uxEventBits = 0; + vListInitialise( &( pxEventBits->xTasksWaitingForBits ) ); - #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) - { - /* Both static and dynamic allocation can be used, so note that - this event group was created statically in case the event group - is later deleted. */ - pxEventBits->ucStaticallyAllocated = pdTRUE; - } - #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ + #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + { + /* Both static and dynamic allocation can be used, so note that + * this event group was created statically in case the event group + * is later deleted. */ + pxEventBits->ucStaticallyAllocated = pdTRUE; + } + #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ - traceEVENT_GROUP_CREATE( pxEventBits ); + traceEVENT_GROUP_CREATE( pxEventBits ); +#ifdef ESP_PLATFORM + vPortCPUInitializeMutex( &pxEventBits->eventGroupMux ); +#endif // ESP_PLATFORM + } + else + { + /* xEventGroupCreateStatic should only ever be called with + * pxEventGroupBuffer pointing to a pre-allocated (compile time + * allocated) StaticEventGroup_t variable. */ + traceEVENT_GROUP_CREATE_FAILED(); + } - vPortCPUInitializeMutex( &pxEventBits->eventGroupMux ); - } - else - { - /* xEventGroupCreateStatic should only ever be called with - pxEventGroupBuffer pointing to a pre-allocated (compile time - allocated) StaticEventGroup_t variable. */ - traceEVENT_GROUP_CREATE_FAILED(); - } - - return pxEventBits; - } + return pxEventBits; + } #endif /* configSUPPORT_STATIC_ALLOCATION */ /*-----------------------------------------------------------*/ -#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) +#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) - EventGroupHandle_t xEventGroupCreate( void ) - { - EventGroup_t *pxEventBits; + EventGroupHandle_t xEventGroupCreate( void ) + { + EventGroup_t * pxEventBits; - /* Allocate the event group. Justification for MISRA deviation as - follows: pvPortMalloc() always ensures returned memory blocks are - aligned per the requirements of the MCU stack. In this case - pvPortMalloc() must return a pointer that is guaranteed to meet the - alignment requirements of the EventGroup_t structure - which (if you - follow it through) is the alignment requirements of the TickType_t type - (EventBits_t being of TickType_t itself). Therefore, whenever the - stack alignment requirements are greater than or equal to the - TickType_t alignment requirements the cast is safe. In other cases, - where the natural word size of the architecture is less than - sizeof( TickType_t ), the TickType_t variables will be accessed in two - or more reads operations, and the alignment requirements is only that - of each individual read. */ - pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) ); /*lint !e9087 !e9079 see comment above. */ + /* Allocate the event group. Justification for MISRA deviation as + * follows: pvPortMalloc() always ensures returned memory blocks are + * aligned per the requirements of the MCU stack. In this case + * pvPortMalloc() must return a pointer that is guaranteed to meet the + * alignment requirements of the EventGroup_t structure - which (if you + * follow it through) is the alignment requirements of the TickType_t type + * (EventBits_t being of TickType_t itself). Therefore, whenever the + * stack alignment requirements are greater than or equal to the + * TickType_t alignment requirements the cast is safe. In other cases, + * where the natural word size of the architecture is less than + * sizeof( TickType_t ), the TickType_t variables will be accessed in two + * or more reads operations, and the alignment requirements is only that + * of each individual read. */ + pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) ); /*lint !e9087 !e9079 see comment above. */ - if( pxEventBits != NULL ) - { - pxEventBits->uxEventBits = 0; - vListInitialise( &( pxEventBits->xTasksWaitingForBits ) ); + if( pxEventBits != NULL ) + { + pxEventBits->uxEventBits = 0; + vListInitialise( &( pxEventBits->xTasksWaitingForBits ) ); - #if( configSUPPORT_STATIC_ALLOCATION == 1 ) - { - /* Both static and dynamic allocation can be used, so note this - event group was allocated statically in case the event group is - later deleted. */ - pxEventBits->ucStaticallyAllocated = pdFALSE; - } - #endif /* configSUPPORT_STATIC_ALLOCATION */ + #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + { + /* Both static and dynamic allocation can be used, so note this + * event group was allocated statically in case the event group is + * later deleted. */ + pxEventBits->ucStaticallyAllocated = pdFALSE; + } + #endif /* configSUPPORT_STATIC_ALLOCATION */ - vPortCPUInitializeMutex( &pxEventBits->eventGroupMux ); +#ifdef ESP_PLATFORM + vPortCPUInitializeMutex( &pxEventBits->eventGroupMux ); +#endif // ESP_PLATFORM - traceEVENT_GROUP_CREATE( pxEventBits ); - } - else - { - traceEVENT_GROUP_CREATE_FAILED(); /*lint !e9063 Else branch only exists to allow tracing and does not generate code if trace macros are not defined. */ - } + traceEVENT_GROUP_CREATE( pxEventBits ); + } + else + { + traceEVENT_GROUP_CREATE_FAILED(); /*lint !e9063 Else branch only exists to allow tracing and does not generate code if trace macros are not defined. */ + } - return pxEventBits; - } + return pxEventBits; + } #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ /*-----------------------------------------------------------*/ -EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait ) +EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, + const EventBits_t uxBitsToSet, + const EventBits_t uxBitsToWaitFor, + TickType_t xTicksToWait ) { -EventBits_t uxOriginalBitValue, uxReturn; -EventGroup_t *pxEventBits = xEventGroup; -BaseType_t xTimeoutOccurred = pdFALSE; + EventBits_t uxOriginalBitValue, uxReturn; + EventGroup_t * pxEventBits = xEventGroup; +#ifndef ESP_PLATFORM + BaseType_t xAlreadyYielded; +#endif // ESP_PLATFORM + BaseType_t xTimeoutOccurred = pdFALSE; - configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); - configASSERT( uxBitsToWaitFor != 0 ); - #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) - { - configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); - } - #endif + configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); + configASSERT( uxBitsToWaitFor != 0 ); + #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) + { + configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); + } + #endif - taskENTER_CRITICAL( &pxEventBits->eventGroupMux ); - { - uxOriginalBitValue = pxEventBits->uxEventBits; +#ifdef ESP_PLATFORM // IDF-3755 + taskENTER_CRITICAL(); +#else + vTaskSuspendAll(); +#endif // ESP_PLATFORM + { + uxOriginalBitValue = pxEventBits->uxEventBits; - ( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet ); + ( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet ); - if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor ) - { - /* All the rendezvous bits are now set - no need to block. */ - uxReturn = ( uxOriginalBitValue | uxBitsToSet ); + if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor ) + { + /* All the rendezvous bits are now set - no need to block. */ + uxReturn = ( uxOriginalBitValue | uxBitsToSet ); - /* Rendezvous always clear the bits. They will have been cleared - already unless this is the only task in the rendezvous. */ - pxEventBits->uxEventBits &= ~uxBitsToWaitFor; + /* Rendezvous always clear the bits. They will have been cleared + * already unless this is the only task in the rendezvous. */ + pxEventBits->uxEventBits &= ~uxBitsToWaitFor; - xTicksToWait = 0; - } - else - { - if( xTicksToWait != ( TickType_t ) 0 ) - { - traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor ); + xTicksToWait = 0; + } + else + { + if( xTicksToWait != ( TickType_t ) 0 ) + { + traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor ); - /* Store the bits that the calling task is waiting for in the - task's event list item so the kernel knows when a match is - found. Then enter the blocked state. */ - vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait ); + /* Store the bits that the calling task is waiting for in the + * task's event list item so the kernel knows when a match is + * found. Then enter the blocked state. */ + vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait ); - /* This assignment is obsolete as uxReturn will get set after - the task unblocks, but some compilers mistakenly generate a - warning about uxReturn being returned without being set if the - assignment is omitted. */ - uxReturn = 0; - } - else - { - /* The rendezvous bits were not set, but no block time was - specified - just return the current event bit value. */ - uxReturn = pxEventBits->uxEventBits; - xTimeoutOccurred = pdTRUE; - } - } - } + /* This assignment is obsolete as uxReturn will get set after + * the task unblocks, but some compilers mistakenly generate a + * warning about uxReturn being returned without being set if the + * assignment is omitted. */ + uxReturn = 0; + } + else + { + /* The rendezvous bits were not set, but no block time was + * specified - just return the current event bit value. */ + uxReturn = pxEventBits->uxEventBits; + xTimeoutOccurred = pdTRUE; + } + } + } +#ifdef ESP_PLATFORM // IDF-3755 + taskEXIT_CRITICAL(); +#else + xAlreadyYielded = xTaskResumeAll(); +#endif // ESP_PLATFORM - taskEXIT_CRITICAL( &pxEventBits->eventGroupMux ); + if( xTicksToWait != ( TickType_t ) 0 ) + { +#ifdef ESP_PLATFORM + portYIELD_WITHIN_API(); +#else + if( xAlreadyYielded == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } +#endif // ESP_PLATFORM - if( xTicksToWait != ( TickType_t ) 0 ) - { - portYIELD_WITHIN_API(); + /* The task blocked to wait for its required bits to be set - at this + * point either the required bits were set or the block time expired. If + * the required bits were set they will have been stored in the task's + * event list item, and they should now be retrieved then cleared. */ + uxReturn = uxTaskResetEventItemValue(); - /* The task blocked to wait for its required bits to be set - at this - point either the required bits were set or the block time expired. If - the required bits were set they will have been stored in the task's - event list item, and they should now be retrieved then cleared. */ - uxReturn = uxTaskResetEventItemValue(); + if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 ) + { + /* The task timed out, just return the current event bit value. */ + taskENTER_CRITICAL(); + { + uxReturn = pxEventBits->uxEventBits; - if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 ) - { - /* The task timed out, just return the current event bit value. */ - taskENTER_CRITICAL( &pxEventBits->eventGroupMux ); - { - uxReturn = pxEventBits->uxEventBits; + /* Although the task got here because it timed out before the + * bits it was waiting for were set, it is possible that since it + * unblocked another task has set the bits. If this is the case + * then it needs to clear the bits before exiting. */ + if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor ) + { + pxEventBits->uxEventBits &= ~uxBitsToWaitFor; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(); - /* Although the task got here because it timed out before the - bits it was waiting for were set, it is possible that since it - unblocked another task has set the bits. If this is the case - then it needs to clear the bits before exiting. */ - if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor ) - { - pxEventBits->uxEventBits &= ~uxBitsToWaitFor; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - taskEXIT_CRITICAL( &pxEventBits->eventGroupMux ); + xTimeoutOccurred = pdTRUE; + } + else + { + /* The task unblocked because the bits were set. */ + } - xTimeoutOccurred = pdTRUE; - } - else - { - /* The task unblocked because the bits were set. */ - } + /* Control bits might be set as the task had blocked should not be + * returned. */ + uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES; + } - /* Control bits might be set as the task had blocked should not be - returned. */ - uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES; - } + traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred ); - traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred ); + /* Prevent compiler warnings when trace macros are not used. */ + ( void ) xTimeoutOccurred; - /* Prevent compiler warnings when trace macros are not used. */ - ( void ) xTimeoutOccurred; - - return uxReturn; + return uxReturn; } /*-----------------------------------------------------------*/ -EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait ) +EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, + const EventBits_t uxBitsToWaitFor, + const BaseType_t xClearOnExit, + const BaseType_t xWaitForAllBits, + TickType_t xTicksToWait ) { -EventGroup_t *pxEventBits = xEventGroup; -EventBits_t uxReturn, uxControlBits = 0; -BaseType_t xWaitConditionMet; -BaseType_t xTimeoutOccurred = pdFALSE; + EventGroup_t * pxEventBits = xEventGroup; + EventBits_t uxReturn, uxControlBits = 0; +#ifdef ESP_PLATFORM + BaseType_t xWaitConditionMet; +#else + BaseType_t xWaitConditionMet, xAlreadyYielded; +#endif // ESP_PLATFORM + BaseType_t xTimeoutOccurred = pdFALSE; - /* Check the user is not attempting to wait on the bits used by the kernel - itself, and that at least one bit is being requested. */ - configASSERT( xEventGroup ); - configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); - configASSERT( uxBitsToWaitFor != 0 ); - #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) - { - configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); - } - #endif + /* Check the user is not attempting to wait on the bits used by the kernel + * itself, and that at least one bit is being requested. */ + configASSERT( xEventGroup ); + configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); + configASSERT( uxBitsToWaitFor != 0 ); + #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) + { + configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); + } + #endif - taskENTER_CRITICAL( &pxEventBits->eventGroupMux ); - { - const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits; +#ifdef ESP_PLATFORM // IDF-3755 + taskENTER_CRITICAL(); +#else + vTaskSuspendAll(); +#endif // ESP_PLATFORM + { + const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits; - /* Check to see if the wait condition is already met or not. */ - xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits ); + /* Check to see if the wait condition is already met or not. */ + xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits ); - if( xWaitConditionMet != pdFALSE ) - { - /* The wait condition has already been met so there is no need to - block. */ - uxReturn = uxCurrentEventBits; - xTicksToWait = ( TickType_t ) 0; + if( xWaitConditionMet != pdFALSE ) + { + /* The wait condition has already been met so there is no need to + * block. */ + uxReturn = uxCurrentEventBits; + xTicksToWait = ( TickType_t ) 0; - /* Clear the wait bits if requested to do so. */ - if( xClearOnExit != pdFALSE ) - { - pxEventBits->uxEventBits &= ~uxBitsToWaitFor; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else if( xTicksToWait == ( TickType_t ) 0 ) - { - /* The wait condition has not been met, but no block time was - specified, so just return the current value. */ - uxReturn = uxCurrentEventBits; - xTimeoutOccurred = pdTRUE; - } - else - { - /* The task is going to block to wait for its required bits to be - set. uxControlBits are used to remember the specified behaviour of - this call to xEventGroupWaitBits() - for use when the event bits - unblock the task. */ - if( xClearOnExit != pdFALSE ) - { - uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* Clear the wait bits if requested to do so. */ + if( xClearOnExit != pdFALSE ) + { + pxEventBits->uxEventBits &= ~uxBitsToWaitFor; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else if( xTicksToWait == ( TickType_t ) 0 ) + { + /* The wait condition has not been met, but no block time was + * specified, so just return the current value. */ + uxReturn = uxCurrentEventBits; + xTimeoutOccurred = pdTRUE; + } + else + { + /* The task is going to block to wait for its required bits to be + * set. uxControlBits are used to remember the specified behaviour of + * this call to xEventGroupWaitBits() - for use when the event bits + * unblock the task. */ + if( xClearOnExit != pdFALSE ) + { + uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - if( xWaitForAllBits != pdFALSE ) - { - uxControlBits |= eventWAIT_FOR_ALL_BITS; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + if( xWaitForAllBits != pdFALSE ) + { + uxControlBits |= eventWAIT_FOR_ALL_BITS; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - /* Store the bits that the calling task is waiting for in the - task's event list item so the kernel knows when a match is - found. Then enter the blocked state. */ - vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait ); + /* Store the bits that the calling task is waiting for in the + * task's event list item so the kernel knows when a match is + * found. Then enter the blocked state. */ + vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait ); - /* This is obsolete as it will get set after the task unblocks, but - some compilers mistakenly generate a warning about the variable - being returned without being set if it is not done. */ - uxReturn = 0; + /* This is obsolete as it will get set after the task unblocks, but + * some compilers mistakenly generate a warning about the variable + * being returned without being set if it is not done. */ + uxReturn = 0; - traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor ); - } - } + traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor ); + } + } +#ifdef ESP_PLATFORM // IDF-3755 + taskEXIT_CRITICAL(); +#else + xAlreadyYielded = xTaskResumeAll(); +#endif // ESP_PLATFORM - taskEXIT_CRITICAL( &pxEventBits->eventGroupMux ); + if( xTicksToWait != ( TickType_t ) 0 ) + { +#ifdef ESP_PLATFORM + portYIELD_WITHIN_API(); +#else + if( xAlreadyYielded == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } +#endif // ESP_PLATFORM - if( xTicksToWait != ( TickType_t ) 0 ) - { - portYIELD_WITHIN_API(); + /* The task blocked to wait for its required bits to be set - at this + * point either the required bits were set or the block time expired. If + * the required bits were set they will have been stored in the task's + * event list item, and they should now be retrieved then cleared. */ + uxReturn = uxTaskResetEventItemValue(); - /* The task blocked to wait for its required bits to be set - at this - point either the required bits were set or the block time expired. If - the required bits were set they will have been stored in the task's - event list item, and they should now be retrieved then cleared. */ - uxReturn = uxTaskResetEventItemValue(); + if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 ) + { + taskENTER_CRITICAL(); + { + /* The task timed out, just return the current event bit value. */ + uxReturn = pxEventBits->uxEventBits; - if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 ) - { - taskENTER_CRITICAL( &pxEventBits->eventGroupMux ); - { - /* The task timed out, just return the current event bit value. */ - uxReturn = pxEventBits->uxEventBits; + /* It is possible that the event bits were updated between this + * task leaving the Blocked state and running again. */ + if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE ) + { + if( xClearOnExit != pdFALSE ) + { + pxEventBits->uxEventBits &= ~uxBitsToWaitFor; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - /* It is possible that the event bits were updated between this - task leaving the Blocked state and running again. */ - if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE ) - { - if( xClearOnExit != pdFALSE ) - { - pxEventBits->uxEventBits &= ~uxBitsToWaitFor; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - xTimeoutOccurred = pdTRUE; - } - taskEXIT_CRITICAL( &pxEventBits->eventGroupMux ); - } - else - { - /* The task unblocked because the bits were set. */ - } + xTimeoutOccurred = pdTRUE; + } + taskEXIT_CRITICAL(); + } + else + { + /* The task unblocked because the bits were set. */ + } - /* The task blocked so control bits may have been set. */ - uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES; - } - traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred ); + /* The task blocked so control bits may have been set. */ + uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES; + } - /* Prevent compiler warnings when trace macros are not used. */ - ( void ) xTimeoutOccurred; + traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred ); - return uxReturn; + /* Prevent compiler warnings when trace macros are not used. */ + ( void ) xTimeoutOccurred; + + return uxReturn; } /*-----------------------------------------------------------*/ -EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) +EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, + const EventBits_t uxBitsToClear ) { -EventGroup_t *pxEventBits = xEventGroup; -EventBits_t uxReturn; + EventGroup_t * pxEventBits = xEventGroup; + EventBits_t uxReturn; - /* Check the user is not attempting to clear the bits used by the kernel - itself. */ - configASSERT( xEventGroup ); - configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); + /* Check the user is not attempting to clear the bits used by the kernel + * itself. */ + configASSERT( xEventGroup ); + configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); - taskENTER_CRITICAL( &pxEventBits->eventGroupMux ); - { - traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear ); + taskENTER_CRITICAL(); + { + traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear ); - /* The value returned is the event group value prior to the bits being - cleared. */ - uxReturn = pxEventBits->uxEventBits; + /* The value returned is the event group value prior to the bits being + * cleared. */ + uxReturn = pxEventBits->uxEventBits; - /* Clear the bits. */ - pxEventBits->uxEventBits &= ~uxBitsToClear; - } - taskEXIT_CRITICAL( &pxEventBits->eventGroupMux ); + /* Clear the bits. */ + pxEventBits->uxEventBits &= ~uxBitsToClear; + } + taskEXIT_CRITICAL(); - return uxReturn; + return uxReturn; } /*-----------------------------------------------------------*/ #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) - BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) - { - BaseType_t xReturn; + BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, + const EventBits_t uxBitsToClear ) + { + BaseType_t xReturn; - traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear ); - xReturn = xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL ); /*lint !e9087 Can't avoid cast to void* as a generic callback function not specific to this use case. Callback casts back to original type so safe. */ + traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear ); + xReturn = xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL ); /*lint !e9087 Can't avoid cast to void* as a generic callback function not specific to this use case. Callback casts back to original type so safe. */ - return xReturn; - } + return xReturn; + } -#endif +#endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */ /*-----------------------------------------------------------*/ EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) { -UBaseType_t uxSavedInterruptStatus; -EventGroup_t const * const pxEventBits = xEventGroup; -EventBits_t uxReturn; + UBaseType_t uxSavedInterruptStatus; + EventGroup_t const * const pxEventBits = xEventGroup; + EventBits_t uxReturn; - uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); - { - uxReturn = pxEventBits->uxEventBits; - } - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + uxReturn = pxEventBits->uxEventBits; + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); - return uxReturn; + return uxReturn; } /*lint !e818 EventGroupHandle_t is a typedef used in other functions to so can't be pointer to const. */ /*-----------------------------------------------------------*/ -EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) +EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, + const EventBits_t uxBitsToSet ) { -ListItem_t *pxListItem, *pxNext; -ListItem_t const *pxListEnd; -List_t const * pxList; -EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits; -EventGroup_t *pxEventBits = xEventGroup; -BaseType_t xMatchFound = pdFALSE; + ListItem_t * pxListItem, * pxNext; + ListItem_t const * pxListEnd; + List_t const * pxList; + EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits; + EventGroup_t * pxEventBits = xEventGroup; + BaseType_t xMatchFound = pdFALSE; - /* Check the user is not attempting to set the bits used by the kernel - itself. */ - configASSERT( xEventGroup ); - configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); + /* Check the user is not attempting to set the bits used by the kernel + * itself. */ + configASSERT( xEventGroup ); + configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); - pxList = &( pxEventBits->xTasksWaitingForBits ); - pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */ + pxList = &( pxEventBits->xTasksWaitingForBits ); + pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */ +#ifdef ESP_PLATFORM // IDF-3755 + taskENTER_CRITICAL(); +#else + vTaskSuspendAll(); +#endif // ESP_PLATFORM + { + traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet ); - taskENTER_CRITICAL( &pxEventBits->eventGroupMux ); - { - traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet ); + pxListItem = listGET_HEAD_ENTRY( pxList ); - pxListItem = listGET_HEAD_ENTRY( pxList ); + /* Set the bits. */ + pxEventBits->uxEventBits |= uxBitsToSet; - /* Set the bits. */ - pxEventBits->uxEventBits |= uxBitsToSet; + /* See if the new bit value should unblock any tasks. */ + while( pxListItem != pxListEnd ) + { + pxNext = listGET_NEXT( pxListItem ); + uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem ); + xMatchFound = pdFALSE; - /* See if the new bit value should unblock any tasks. */ - while( pxListItem != pxListEnd ) - { - pxNext = listGET_NEXT( pxListItem ); - uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem ); - xMatchFound = pdFALSE; + /* Split the bits waited for from the control bits. */ + uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES; + uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES; - /* Split the bits waited for from the control bits. */ - uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES; - uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES; + if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 ) + { + /* Just looking for single bit being set. */ + if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 ) + { + xMatchFound = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor ) + { + /* All bits are set. */ + xMatchFound = pdTRUE; + } + else + { + /* Need all bits to be set, but not all the bits were set. */ + } - if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 ) - { - /* Just looking for single bit being set. */ - if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 ) - { - xMatchFound = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor ) - { - /* All bits are set. */ - xMatchFound = pdTRUE; - } - else - { - /* Need all bits to be set, but not all the bits were set. */ - } + if( xMatchFound != pdFALSE ) + { + /* The bits match. Should the bits be cleared on exit? */ + if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 ) + { + uxBitsToClear |= uxBitsWaitedFor; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - if( xMatchFound != pdFALSE ) - { - /* The bits match. Should the bits be cleared on exit? */ - if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 ) - { - uxBitsToClear |= uxBitsWaitedFor; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* Store the actual event flag value in the task's event list + * item before removing the task from the event list. The + * eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows + * that is was unblocked due to its required bits matching, rather + * than because it timed out. */ + vTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET ); + } - /* Store the actual event flag value in the task's event list - item before removing the task from the event list. The - eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows - that is was unblocked due to its required bits matching, rather - than because it timed out. */ - xTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET ); - } + /* Move onto the next list item. Note pxListItem->pxNext is not + * used here as the list item may have been removed from the event list + * and inserted into the ready/pending reading list. */ + pxListItem = pxNext; + } - /* Move onto the next list item. Note pxListItem->pxNext is not - used here as the list item may have been removed from the event list - and inserted into the ready/pending reading list. */ - pxListItem = pxNext; - } + /* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT + * bit was set in the control word. */ + pxEventBits->uxEventBits &= ~uxBitsToClear; + } +#ifdef ESP_PLATFORM // IDF-3755 + taskEXIT_CRITICAL(); +#else + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM - /* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT - bit was set in the control word. */ - pxEventBits->uxEventBits &= ~uxBitsToClear; - } - taskEXIT_CRITICAL( &pxEventBits->eventGroupMux ); - - return pxEventBits->uxEventBits; + return pxEventBits->uxEventBits; } /*-----------------------------------------------------------*/ void vEventGroupDelete( EventGroupHandle_t xEventGroup ) { -EventGroup_t *pxEventBits = xEventGroup; -const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits ); + EventGroup_t * pxEventBits = xEventGroup; + const List_t * pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits ); - traceEVENT_GROUP_DELETE( xEventGroup ); + traceEVENT_GROUP_DELETE( xEventGroup ); - taskENTER_CRITICAL( &pxEventBits->eventGroupMux ); - { - while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 ) - { - /* Unblock the task, returning 0 as the event list is being deleted - and cannot therefore have any bits set. */ - configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( const ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) ); - xTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET ); - } - } - taskEXIT_CRITICAL( &pxEventBits->eventGroupMux ); + // IDF-3755 + taskENTER_CRITICAL(); + { + while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 ) + { + /* Unblock the task, returning 0 as the event list is being deleted + * and cannot therefore have any bits set. */ + configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( const ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) ); + vTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET ); + } + } + taskEXIT_CRITICAL(); - #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) ) - { - /* The event group can only have been allocated dynamically - free - it again. */ - vPortFree( pxEventBits ); - } - #elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) - { - /* The event group could have been allocated statically or - dynamically, so check before attempting to free the memory. */ - if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE ) - { - vPortFree( pxEventBits ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ + #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) ) + { + /* The event group can only have been allocated dynamically - free + * it again. */ + vPortFree( pxEventBits ); + } + #elif ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) + { + /* The event group could have been allocated statically or + * dynamically, so check before attempting to free the memory. */ + if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE ) + { + vPortFree( pxEventBits ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ } /*-----------------------------------------------------------*/ /* For internal use only - execute a 'set bits' command that was pended from -an interrupt. */ -void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet ) + * an interrupt. */ +void vEventGroupSetBitsCallback( void * pvEventGroup, + const uint32_t ulBitsToSet ) { - ( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet ); /*lint !e9079 Can't avoid cast to void* as a generic timer callback prototype. Callback casts back to original type so safe. */ + ( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet ); /*lint !e9079 Can't avoid cast to void* as a generic timer callback prototype. Callback casts back to original type so safe. */ } /*-----------------------------------------------------------*/ /* For internal use only - execute a 'clear bits' command that was pended from -an interrupt. */ -void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear ) + * an interrupt. */ +void vEventGroupClearBitsCallback( void * pvEventGroup, + const uint32_t ulBitsToClear ) { - ( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear ); /*lint !e9079 Can't avoid cast to void* as a generic timer callback prototype. Callback casts back to original type so safe. */ + ( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear ); /*lint !e9079 Can't avoid cast to void* as a generic timer callback prototype. Callback casts back to original type so safe. */ } /*-----------------------------------------------------------*/ -static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits ) +static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, + const EventBits_t uxBitsToWaitFor, + const BaseType_t xWaitForAllBits ) { -BaseType_t xWaitConditionMet = pdFALSE; + BaseType_t xWaitConditionMet = pdFALSE; - if( xWaitForAllBits == pdFALSE ) - { - /* Task only has to wait for one bit within uxBitsToWaitFor to be - set. Is one already set? */ - if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 ) - { - xWaitConditionMet = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - /* Task has to wait for all the bits in uxBitsToWaitFor to be set. - Are they set already? */ - if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor ) - { - xWaitConditionMet = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } + if( xWaitForAllBits == pdFALSE ) + { + /* Task only has to wait for one bit within uxBitsToWaitFor to be + * set. Is one already set? */ + if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 ) + { + xWaitConditionMet = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* Task has to wait for all the bits in uxBitsToWaitFor to be set. + * Are they set already? */ + if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor ) + { + xWaitConditionMet = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } - return xWaitConditionMet; + return xWaitConditionMet; } /*-----------------------------------------------------------*/ #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) - BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken ) - { - BaseType_t xReturn; + BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, + const EventBits_t uxBitsToSet, + BaseType_t * pxHigherPriorityTaskWoken ) + { + BaseType_t xReturn; - traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet ); - xReturn = xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken ); /*lint !e9087 Can't avoid cast to void* as a generic callback function not specific to this use case. Callback casts back to original type so safe. */ + traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet ); + xReturn = xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken ); /*lint !e9087 Can't avoid cast to void* as a generic callback function not specific to this use case. Callback casts back to original type so safe. */ - return xReturn; - } + return xReturn; + } -#endif +#endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */ /*-----------------------------------------------------------*/ -#if (configUSE_TRACE_FACILITY == 1) +#if ( configUSE_TRACE_FACILITY == 1 ) - UBaseType_t uxEventGroupGetNumber( void* xEventGroup ) - { - UBaseType_t xReturn; - EventGroup_t const *pxEventBits = ( EventGroup_t * ) xEventGroup; /*lint !e9087 !e9079 EventGroupHandle_t is a pointer to an EventGroup_t, but EventGroupHandle_t is kept opaque outside of this file for data hiding purposes. */ + UBaseType_t uxEventGroupGetNumber( void * xEventGroup ) + { + UBaseType_t xReturn; + EventGroup_t const * pxEventBits = ( EventGroup_t * ) xEventGroup; /*lint !e9087 !e9079 EventGroupHandle_t is a pointer to an EventGroup_t, but EventGroupHandle_t is kept opaque outside of this file for data hiding purposes. */ - if( xEventGroup == NULL ) - { - xReturn = 0; - } - else - { - xReturn = pxEventBits->uxEventGroupNumber; - } + if( xEventGroup == NULL ) + { + xReturn = 0; + } + else + { + xReturn = pxEventBits->uxEventGroupNumber; + } - return xReturn; - } + return xReturn; + } #endif /* configUSE_TRACE_FACILITY */ /*-----------------------------------------------------------*/ #if ( configUSE_TRACE_FACILITY == 1 ) - void vEventGroupSetNumber( void * xEventGroup, UBaseType_t uxEventGroupNumber ) - { - ( ( EventGroup_t * ) xEventGroup )->uxEventGroupNumber = uxEventGroupNumber; /*lint !e9087 !e9079 EventGroupHandle_t is a pointer to an EventGroup_t, but EventGroupHandle_t is kept opaque outside of this file for data hiding purposes. */ - } + void vEventGroupSetNumber( void * xEventGroup, + UBaseType_t uxEventGroupNumber ) + { + ( ( EventGroup_t * ) xEventGroup )->uxEventGroupNumber = uxEventGroupNumber; /*lint !e9087 !e9079 EventGroupHandle_t is a pointer to an EventGroup_t, but EventGroupHandle_t is kept opaque outside of this file for data hiding purposes. */ + } #endif /* configUSE_TRACE_FACILITY */ /*-----------------------------------------------------------*/ diff --git a/components/freertos/include/freertos/FreeRTOSConfig.h b/components/freertos/include/esp_additions/freertos/FreeRTOSConfig.h similarity index 94% rename from components/freertos/include/freertos/FreeRTOSConfig.h rename to components/freertos/include/esp_additions/freertos/FreeRTOSConfig.h index c64cb980d8..39ffb5daf5 100644 --- a/components/freertos/include/freertos/FreeRTOSConfig.h +++ b/components/freertos/include/esp_additions/freertos/FreeRTOSConfig.h @@ -71,10 +71,16 @@ #define FREERTOS_CONFIG_H #include "sdkconfig.h" -// The arch-specific FreeRTOSConfig.h in port//include. -#include_next "freertos/FreeRTOSConfig.h" -#if !(defined(FREERTOS_CONFIG_XTENSA_H) || defined(FREERTOS_CONFIG_RISCV_H)) +/* for likely and unlikely */ +#include "esp_compiler.h" + +// The arch-specific FreeRTOSConfig_arch.h in port//include. +#include "freertos/FreeRTOSConfig_arch.h" + +#if !(defined(FREERTOS_CONFIG_XTENSA_H) \ + || defined(FREERTOS_CONFIG_RISCV_H) \ + || defined(FREERTOS_CONFIG_LINUX_H)) #error "Needs architecture-speific FreeRTOSConfig.h!" #endif @@ -84,7 +90,6 @@ #define portNUM_PROCESSORS 1 #endif -#define configASSERT_2 0 #define portUSING_MPU_WRAPPERS 0 #define configUSE_MUTEX 1 @@ -200,7 +205,6 @@ #define configGENERATE_RUN_TIME_STATS 1 /* Used by vTaskGetRunTimeStats() */ #endif -#define configUSE_TRACE_FACILITY_2 0 #define configBENCHMARK 0 #define configUSE_16_BIT_TICKS 0 #define configIDLE_SHOULD_YIELD 0 @@ -244,7 +248,9 @@ kept at 1. */ #define configKERNEL_INTERRUPT_PRIORITY 1 +#if !CONFIG_IDF_TARGET_LINUX #define configUSE_NEWLIB_REENTRANT 1 +#endif #define configSUPPORT_DYNAMIC_ALLOCATION 1 #define configSUPPORT_STATIC_ALLOCATION 1 @@ -273,11 +279,11 @@ extern void vPortCleanUpTCB ( void *pxTCB ); #endif //configUSE_TICKLESS_IDLE -#if CONFIG_ESP_COREDUMP_ENABLE +#if CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT #define configENABLE_TASK_SNAPSHOT 1 #endif #ifndef configENABLE_TASK_SNAPSHOT -#define configENABLE_TASK_SNAPSHOT 1 +#define configENABLE_TASK_SNAPSHOT 0 #endif #if CONFIG_SYSVIEW_ENABLE @@ -293,4 +299,12 @@ extern void vPortCleanUpTCB ( void *pxTCB ); #define configCHECK_MUTEX_GIVEN_BY_OWNER 0 #endif + +#define configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H 1 + +#define configTASK_NOTIFICATION_ARRAY_ENTRIES 1 + +// backward compatibility for 4.4 +#define xTaskRemoveFromUnorderedEventList vTaskRemoveFromUnorderedEventList + #endif /* FREERTOS_CONFIG_H */ diff --git a/components/freertos/include/esp_additions/freertos/task_snapshot.h b/components/freertos/include/esp_additions/freertos/task_snapshot.h new file mode 100644 index 0000000000..1ad04cce69 --- /dev/null +++ b/components/freertos/include/esp_additions/freertos/task_snapshot.h @@ -0,0 +1,90 @@ +// Copyright 2015-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. + +#pragma once + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#if ( configENABLE_TASK_SNAPSHOT == 1 ) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Check `freertos_tasks_c_additions.h` file for more info + * about these functions declaration. + */ +UBaseType_t pxTCBGetSize ( void ); +ListItem_t* pxTCBGetStateListItem ( void *pxTCB ); +StackType_t* pxTCBGetStartOfStack ( void *pxTCB ); +StackType_t* pxTCBGetTopOfStack ( void *pxTCB ); +StackType_t* pxTCBGetEndOfStack ( void *pxTCB ); +List_t* pxListGetReadyTask ( UBaseType_t idx ); +List_t* pxListGetReadyPendingTask ( UBaseType_t idx ); +List_t* pxGetDelayedTaskList ( void ); +List_t* pxGetOverflowDelayedTaskList ( void ); +List_t* pxGetTasksWaitingTermination ( void ); +List_t* pxGetSuspendedTaskList ( void ); + +/** + * Used with the uxTaskGetSnapshotAll() function to save memory snapshot of each task in the system. + * We need this struct because TCB_t is defined (hidden) in tasks.c. + */ +typedef struct xTASK_SNAPSHOT +{ + void *pxTCB; /*!< Address of task control block. */ + StackType_t *pxTopOfStack; /*!< Points to the location of the last item placed on the tasks stack. */ + StackType_t *pxEndOfStack; /*!< Points to the end of the stack. pxTopOfStack < pxEndOfStack, stack grows hi2lo + pxTopOfStack > pxEndOfStack, stack grows lo2hi*/ +} TaskSnapshot_t; + + +/* + * This function fills array with TaskSnapshot_t structures for every task in the system. + * Used by panic handling code to get snapshots of all tasks in the system. + * Only available when configENABLE_TASK_SNAPSHOT is set to 1. + * @param pxTaskSnapshotArray Pointer to array of TaskSnapshot_t structures to store tasks snapshot data. + * @param uxArraySize Size of tasks snapshots array. + * @param pxTcbSz Pointer to store size of TCB. + * @return Number of elements stored in array. + */ +UBaseType_t uxTaskGetSnapshotAll( TaskSnapshot_t * const pxTaskSnapshotArray, const UBaseType_t uxArraySize, UBaseType_t * const pxTcbSz ); + +/* + * This function iterates over all tasks in the system. + * Used by panic handling code to iterate over tasks in the system. + * Only available when configENABLE_TASK_SNAPSHOT is set to 1. + * @note This function should not be used while FreeRTOS is running (as it doesn't acquire any locks). + * @param pxTask task handle. + * @return Handle for the next task. If pxTask is NULL, returns hadnle for the first task. + */ +TaskHandle_t pxTaskGetNext( TaskHandle_t pxTask ); + +/* + * This function fills TaskSnapshot_t structure for specified task. + * Used by panic handling code to get snapshot of a task. + * Only available when configENABLE_TASK_SNAPSHOT is set to 1. + * @note This function should not be used while FreeRTOS is running (as it doesn't acquire any locks). + * @param pxTask task handle. + * @param pxTaskSnapshot address of TaskSnapshot_t structure to fill. + */ +void vTaskGetSnapshot( TaskHandle_t pxTask, TaskSnapshot_t *pxTaskSnapshot ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/freertos/include/esp_additions/freertos_tasks_c_additions.h b/components/freertos/include/esp_additions/freertos_tasks_c_additions.h new file mode 100644 index 0000000000..464c0b3ffb --- /dev/null +++ b/components/freertos/include/esp_additions/freertos_tasks_c_additions.h @@ -0,0 +1,80 @@ +// Copyright 2015-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. + +#pragma once + +/** + * This file will be included in `tasks.c` file, thus, it must NOT be included + * by any (other) file. + * The functions below only consist in getters for the static variables in + * `tasks.c` file. + * The only source files that should call these functions are the ones in + * `/additions` directory. + */ + +#if ( configENABLE_TASK_SNAPSHOT == 1 ) + + UBaseType_t pxTCBGetSize ( void ) + { + return sizeof(TCB_t); + } + + ListItem_t* pxTCBGetStateListItem ( void *pxTCB ) + { + return &(((TCB_t*)pxTCB)->xStateListItem); + } + + StackType_t* pxTCBGetStartOfStack ( void *pxTCB ) + { + return (StackType_t*) ((TCB_t*)pxTCB)->pxStack; + } + + StackType_t* pxTCBGetTopOfStack ( void *pxTCB ) + { + return (StackType_t*) ((TCB_t*)pxTCB)->pxTopOfStack; + } + + StackType_t* pxTCBGetEndOfStack ( void *pxTCB ) + { + return (StackType_t*) ((TCB_t*)pxTCB)->pxEndOfStack; + } + + + List_t* pxListGetReadyTask ( UBaseType_t idx ) + { + return &( pxReadyTasksLists[idx] ); + } + + List_t* pxListGetReadyPendingTask ( UBaseType_t idx ) + { + return &( xPendingReadyList[idx] ); + } + + List_t* pxGetDelayedTaskList ( void ) { + return pxDelayedTaskList; + } + + List_t* pxGetOverflowDelayedTaskList ( void ) { + return pxOverflowDelayedTaskList; + } + + List_t* pxGetTasksWaitingTermination ( void ) { + return &xTasksWaitingTermination; + } + + List_t* pxGetSuspendedTaskList ( void ) { + return &xSuspendedTaskList; + } + +#endif diff --git a/components/freertos/include/freertos/FreeRTOS.h b/components/freertos/include/freertos/FreeRTOS.h index 2c9c5b13d0..eb0ee6be35 100644 --- a/components/freertos/include/freertos/FreeRTOS.h +++ b/components/freertos/include/freertos/FreeRTOS.h @@ -1,6 +1,6 @@ /* - * FreeRTOS Kernel V10.2.1 - * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V10.4.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * 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 @@ -19,10 +19,9 @@ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS * - * 1 tab == 4 spaces! */ #ifndef INC_FREERTOS_H @@ -46,16 +45,16 @@ * contains the typedefs required to build FreeRTOS. Read the instructions * in FreeRTOS/source/stdint.readme for more information. */ -#include /* READ COMMENT ABOVE. */ +#include /* READ COMMENT ABOVE. */ +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif -/* for likely and unlikely */ -#include "esp_compiler.h" +/* *INDENT-ON* */ /* Application specific configuration options. */ -#include "freertos/FreeRTOSConfig.h" +#include "FreeRTOSConfig.h" /* Basic FreeRTOS definitions. */ #include "projdefs.h" @@ -65,13 +64,14 @@ extern "C" { /* Must be defaulted before configUSE_NEWLIB_REENTRANT is used below. */ #ifndef configUSE_NEWLIB_REENTRANT - #define configUSE_NEWLIB_REENTRANT 0 + #define configUSE_NEWLIB_REENTRANT 0 #endif /* Required if struct _reent is used. */ #if ( configUSE_NEWLIB_REENTRANT == 1 ) - #include + #include #endif + /* * Check all the required application specific macros have been defined. * These macros are application specific and (as downloaded) are defined @@ -79,503 +79,545 @@ extern "C" { */ #ifndef configMINIMAL_STACK_SIZE - #error Missing definition: configMINIMAL_STACK_SIZE must be defined in FreeRTOSConfig.h. configMINIMAL_STACK_SIZE defines the size (in words) of the stack allocated to the idle task. Refer to the demo project provided for your port for a suitable value. + #error Missing definition: configMINIMAL_STACK_SIZE must be defined in FreeRTOSConfig.h. configMINIMAL_STACK_SIZE defines the size (in words) of the stack allocated to the idle task. Refer to the demo project provided for your port for a suitable value. #endif #ifndef configMAX_PRIORITIES - #error Missing definition: configMAX_PRIORITIES must be defined in FreeRTOSConfig.h. See the Configuration section of the FreeRTOS API documentation for details. + #error Missing definition: configMAX_PRIORITIES must be defined in FreeRTOSConfig.h. See the Configuration section of the FreeRTOS API documentation for details. #endif #if configMAX_PRIORITIES < 1 - #error configMAX_PRIORITIES must be defined to be greater than or equal to 1. + #error configMAX_PRIORITIES must be defined to be greater than or equal to 1. #endif #ifndef configUSE_PREEMPTION - #error Missing definition: configUSE_PREEMPTION must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. + #error Missing definition: configUSE_PREEMPTION must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. #endif #ifndef configUSE_IDLE_HOOK - #error Missing definition: configUSE_IDLE_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. + #error Missing definition: configUSE_IDLE_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. #endif #ifndef configUSE_TICK_HOOK - #error Missing definition: configUSE_TICK_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. + #error Missing definition: configUSE_TICK_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. #endif #ifndef configUSE_16_BIT_TICKS - #error Missing definition: configUSE_16_BIT_TICKS must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. + #error Missing definition: configUSE_16_BIT_TICKS must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. #endif #ifndef configUSE_CO_ROUTINES - #define configUSE_CO_ROUTINES 0 + #define configUSE_CO_ROUTINES 0 #endif #ifndef INCLUDE_vTaskPrioritySet - #define INCLUDE_vTaskPrioritySet 0 + #define INCLUDE_vTaskPrioritySet 0 #endif #ifndef INCLUDE_uxTaskPriorityGet - #define INCLUDE_uxTaskPriorityGet 0 + #define INCLUDE_uxTaskPriorityGet 0 #endif #ifndef INCLUDE_vTaskDelete - #define INCLUDE_vTaskDelete 0 + #define INCLUDE_vTaskDelete 0 #endif #ifndef INCLUDE_vTaskSuspend - #define INCLUDE_vTaskSuspend 0 + #define INCLUDE_vTaskSuspend 0 #endif -#ifndef INCLUDE_vTaskDelayUntil - #define INCLUDE_vTaskDelayUntil 0 +#ifdef INCLUDE_xTaskDelayUntil + #ifdef INCLUDE_vTaskDelayUntil + /* INCLUDE_vTaskDelayUntil was replaced by INCLUDE_xTaskDelayUntil. Backward + * compatibility is maintained if only one or the other is defined, but + * there is a conflict if both are defined. */ + #error INCLUDE_vTaskDelayUntil and INCLUDE_xTaskDelayUntil are both defined. INCLUDE_vTaskDelayUntil is no longer required and should be removed + #endif +#endif + +#ifndef INCLUDE_xTaskDelayUntil + #ifdef INCLUDE_vTaskDelayUntil + /* If INCLUDE_vTaskDelayUntil is set but INCLUDE_xTaskDelayUntil is not then + * the project's FreeRTOSConfig.h probably pre-dates the introduction of + * xTaskDelayUntil and setting INCLUDE_xTaskDelayUntil to whatever + * INCLUDE_vTaskDelayUntil is set to will ensure backward compatibility. + */ + #define INCLUDE_xTaskDelayUntil INCLUDE_vTaskDelayUntil + #endif +#endif + +#ifndef INCLUDE_xTaskDelayUntil + #define INCLUDE_xTaskDelayUntil 0 #endif #ifndef INCLUDE_vTaskDelay - #define INCLUDE_vTaskDelay 0 + #define INCLUDE_vTaskDelay 0 #endif #ifndef INCLUDE_xTaskGetIdleTaskHandle - #define INCLUDE_xTaskGetIdleTaskHandle 0 + #define INCLUDE_xTaskGetIdleTaskHandle 0 #endif #ifndef INCLUDE_xTaskAbortDelay - #define INCLUDE_xTaskAbortDelay 0 + #define INCLUDE_xTaskAbortDelay 0 #endif #ifndef INCLUDE_xQueueGetMutexHolder - #define INCLUDE_xQueueGetMutexHolder 0 + #define INCLUDE_xQueueGetMutexHolder 0 #endif #ifndef INCLUDE_xSemaphoreGetMutexHolder - #define INCLUDE_xSemaphoreGetMutexHolder INCLUDE_xQueueGetMutexHolder + #define INCLUDE_xSemaphoreGetMutexHolder INCLUDE_xQueueGetMutexHolder #endif #ifndef INCLUDE_xTaskGetHandle - #define INCLUDE_xTaskGetHandle 0 + #define INCLUDE_xTaskGetHandle 0 #endif #ifndef INCLUDE_uxTaskGetStackHighWaterMark - #define INCLUDE_uxTaskGetStackHighWaterMark 0 + #define INCLUDE_uxTaskGetStackHighWaterMark 0 #endif #ifndef INCLUDE_uxTaskGetStackHighWaterMark2 - #define INCLUDE_uxTaskGetStackHighWaterMark2 0 + #define INCLUDE_uxTaskGetStackHighWaterMark2 0 #endif #ifndef INCLUDE_eTaskGetState - #define INCLUDE_eTaskGetState 0 + #define INCLUDE_eTaskGetState 0 #endif #ifndef INCLUDE_xTaskResumeFromISR - #define INCLUDE_xTaskResumeFromISR 1 + #define INCLUDE_xTaskResumeFromISR 1 #endif #ifndef INCLUDE_xTimerPendFunctionCall - #define INCLUDE_xTimerPendFunctionCall 0 + #define INCLUDE_xTimerPendFunctionCall 0 #endif #ifndef INCLUDE_xTaskGetSchedulerState - #define INCLUDE_xTaskGetSchedulerState 0 + #define INCLUDE_xTaskGetSchedulerState 0 #endif #ifndef INCLUDE_xTaskGetCurrentTaskHandle - #define INCLUDE_xTaskGetCurrentTaskHandle 0 + #define INCLUDE_xTaskGetCurrentTaskHandle 0 #endif #if configUSE_CO_ROUTINES != 0 - #ifndef configMAX_CO_ROUTINE_PRIORITIES - #error configMAX_CO_ROUTINE_PRIORITIES must be greater than or equal to 1. - #endif + #ifndef configMAX_CO_ROUTINE_PRIORITIES + #error configMAX_CO_ROUTINE_PRIORITIES must be greater than or equal to 1. + #endif #endif #ifndef configUSE_DAEMON_TASK_STARTUP_HOOK - #define configUSE_DAEMON_TASK_STARTUP_HOOK 0 + #define configUSE_DAEMON_TASK_STARTUP_HOOK 0 #endif #ifndef configUSE_APPLICATION_TASK_TAG - #define configUSE_APPLICATION_TASK_TAG 0 + #define configUSE_APPLICATION_TASK_TAG 0 #endif #ifndef configNUM_THREAD_LOCAL_STORAGE_POINTERS - #define configNUM_THREAD_LOCAL_STORAGE_POINTERS 0 + #define configNUM_THREAD_LOCAL_STORAGE_POINTERS 0 #endif #ifndef configUSE_RECURSIVE_MUTEXES - #define configUSE_RECURSIVE_MUTEXES 0 + #define configUSE_RECURSIVE_MUTEXES 0 #endif #ifndef configUSE_MUTEXES - #define configUSE_MUTEXES 0 + #define configUSE_MUTEXES 0 #endif #ifndef configUSE_TIMERS - #define configUSE_TIMERS 0 + #define configUSE_TIMERS 0 #endif #ifndef configUSE_COUNTING_SEMAPHORES - #define configUSE_COUNTING_SEMAPHORES 0 + #define configUSE_COUNTING_SEMAPHORES 0 #endif #ifndef configUSE_ALTERNATIVE_API - #define configUSE_ALTERNATIVE_API 0 + #define configUSE_ALTERNATIVE_API 0 #endif #ifndef portCRITICAL_NESTING_IN_TCB - #define portCRITICAL_NESTING_IN_TCB 0 + #define portCRITICAL_NESTING_IN_TCB 0 #endif #ifndef configMAX_TASK_NAME_LEN - #define configMAX_TASK_NAME_LEN 16 + #define configMAX_TASK_NAME_LEN 16 #endif #ifndef configIDLE_SHOULD_YIELD - #define configIDLE_SHOULD_YIELD 1 + #define configIDLE_SHOULD_YIELD 1 #endif #if configMAX_TASK_NAME_LEN < 1 - #error configMAX_TASK_NAME_LEN must be set to a minimum of 1 in FreeRTOSConfig.h + #error configMAX_TASK_NAME_LEN must be set to a minimum of 1 in FreeRTOSConfig.h #endif #ifndef configASSERT - #define configASSERT( x ) - #define configASSERT_DEFINED 0 + #define configASSERT( x ) + #define configASSERT_DEFINED 0 #else - #define configASSERT_DEFINED 1 + #define configASSERT_DEFINED 1 #endif -/* configPRECONDITION should be resolve to configASSERT. - The CBMC proofs need a way to track assumptions and assertions. - A configPRECONDITION statement should express an implicit invariant or assumption made. - A configASSERT statement should express an invariant that must hold explicit before calling - the code. */ +/* configPRECONDITION should be defined as configASSERT. + * The CBMC proofs need a way to track assumptions and assertions. + * A configPRECONDITION statement should express an implicit invariant or + * assumption made. A configASSERT statement should express an invariant that must + * hold explicit before calling the code. */ #ifndef configPRECONDITION - #define configPRECONDITION( X ) configASSERT(X) - #define configPRECONDITION_DEFINED 0 + #define configPRECONDITION( X ) configASSERT( X ) + #define configPRECONDITION_DEFINED 0 #else - #define configPRECONDITION_DEFINED 1 + #define configPRECONDITION_DEFINED 1 #endif #ifndef portMEMORY_BARRIER - #define portMEMORY_BARRIER() + #define portMEMORY_BARRIER() +#endif + +#ifndef portSOFTWARE_BARRIER + #define portSOFTWARE_BARRIER() #endif /* The timers module relies on xTaskGetSchedulerState(). */ #if configUSE_TIMERS == 1 - #ifndef configTIMER_TASK_PRIORITY - #error If configUSE_TIMERS is set to 1 then configTIMER_TASK_PRIORITY must also be defined. - #endif /* configTIMER_TASK_PRIORITY */ + #ifndef configTIMER_TASK_PRIORITY + #error If configUSE_TIMERS is set to 1 then configTIMER_TASK_PRIORITY must also be defined. + #endif /* configTIMER_TASK_PRIORITY */ - #ifndef configTIMER_QUEUE_LENGTH - #error If configUSE_TIMERS is set to 1 then configTIMER_QUEUE_LENGTH must also be defined. - #endif /* configTIMER_QUEUE_LENGTH */ + #ifndef configTIMER_QUEUE_LENGTH + #error If configUSE_TIMERS is set to 1 then configTIMER_QUEUE_LENGTH must also be defined. + #endif /* configTIMER_QUEUE_LENGTH */ - #ifndef configTIMER_TASK_STACK_DEPTH - #error If configUSE_TIMERS is set to 1 then configTIMER_TASK_STACK_DEPTH must also be defined. - #endif /* configTIMER_TASK_STACK_DEPTH */ + #ifndef configTIMER_TASK_STACK_DEPTH + #error If configUSE_TIMERS is set to 1 then configTIMER_TASK_STACK_DEPTH must also be defined. + #endif /* configTIMER_TASK_STACK_DEPTH */ #endif /* configUSE_TIMERS */ #ifndef portSET_INTERRUPT_MASK_FROM_ISR - #define portSET_INTERRUPT_MASK_FROM_ISR() 0 + #define portSET_INTERRUPT_MASK_FROM_ISR() 0 #endif #ifndef portCLEAR_INTERRUPT_MASK_FROM_ISR - #define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) ( void ) uxSavedStatusValue + #define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) ( void ) uxSavedStatusValue #endif #ifndef portCLEAN_UP_TCB - #define portCLEAN_UP_TCB( pxTCB ) ( void ) pxTCB + #define portCLEAN_UP_TCB( pxTCB ) ( void ) pxTCB #endif #ifndef portPRE_TASK_DELETE_HOOK - #define portPRE_TASK_DELETE_HOOK( pvTaskToDelete, pxYieldPending ) + #define portPRE_TASK_DELETE_HOOK( pvTaskToDelete, pxYieldPending ) #endif #ifndef portSETUP_TCB - #define portSETUP_TCB( pxTCB ) ( void ) pxTCB + #define portSETUP_TCB( pxTCB ) ( void ) pxTCB #endif #ifndef configQUEUE_REGISTRY_SIZE - #define configQUEUE_REGISTRY_SIZE 0U + #define configQUEUE_REGISTRY_SIZE 0U #endif #if ( configQUEUE_REGISTRY_SIZE < 1 ) - #define vQueueAddToRegistry( xQueue, pcName ) - #define vQueueUnregisterQueue( xQueue ) - #define pcQueueGetName( xQueue ) + #define vQueueAddToRegistry( xQueue, pcName ) + #define vQueueUnregisterQueue( xQueue ) + #define pcQueueGetName( xQueue ) #endif #ifndef portPOINTER_SIZE_TYPE - #define portPOINTER_SIZE_TYPE uint32_t + #define portPOINTER_SIZE_TYPE uint32_t #endif /* Remove any unused trace macros. */ #ifndef traceSTART - /* Used to perform any necessary initialisation - for example, open a file - into which trace is to be written. */ - #define traceSTART() + +/* Used to perform any necessary initialisation - for example, open a file + * into which trace is to be written. */ + #define traceSTART() #endif #ifndef traceEND - /* Use to close a trace, for example close a file into which trace has been - written. */ - #define traceEND() + +/* Use to close a trace, for example close a file into which trace has been + * written. */ + #define traceEND() #endif #ifndef traceTASK_SWITCHED_IN - /* Called after a task has been selected to run. pxCurrentTCB holds a pointer - to the task control block of the selected task. */ - #define traceTASK_SWITCHED_IN() + +/* Called after a task has been selected to run. pxCurrentTCB holds a pointer + * to the task control block of the selected task. */ + #define traceTASK_SWITCHED_IN() #endif #ifndef traceINCREASE_TICK_COUNT - /* Called before stepping the tick count after waking from tickless idle - sleep. */ - #define traceINCREASE_TICK_COUNT( x ) + +/* Called before stepping the tick count after waking from tickless idle + * sleep. */ + #define traceINCREASE_TICK_COUNT( x ) #endif #ifndef traceLOW_POWER_IDLE_BEGIN - /* Called immediately before entering tickless idle. */ - #define traceLOW_POWER_IDLE_BEGIN() + /* Called immediately before entering tickless idle. */ + #define traceLOW_POWER_IDLE_BEGIN() #endif -#ifndef traceLOW_POWER_IDLE_END - /* Called when returning to the Idle task after a tickless idle. */ - #define traceLOW_POWER_IDLE_END() +#ifndef traceLOW_POWER_IDLE_END + /* Called when returning to the Idle task after a tickless idle. */ + #define traceLOW_POWER_IDLE_END() #endif #ifndef traceTASK_SWITCHED_OUT - /* Called before a task has been selected to run. pxCurrentTCB holds a pointer - to the task control block of the task being switched out. */ - #define traceTASK_SWITCHED_OUT() + +/* Called before a task has been selected to run. pxCurrentTCB holds a pointer + * to the task control block of the task being switched out. */ + #define traceTASK_SWITCHED_OUT() #endif #ifndef traceTASK_PRIORITY_INHERIT - /* Called when a task attempts to take a mutex that is already held by a - lower priority task. pxTCBOfMutexHolder is a pointer to the TCB of the task - that holds the mutex. uxInheritedPriority is the priority the mutex holder - will inherit (the priority of the task that is attempting to obtain the - muted. */ - #define traceTASK_PRIORITY_INHERIT( pxTCBOfMutexHolder, uxInheritedPriority ) + +/* Called when a task attempts to take a mutex that is already held by a + * lower priority task. pxTCBOfMutexHolder is a pointer to the TCB of the task + * that holds the mutex. uxInheritedPriority is the priority the mutex holder + * will inherit (the priority of the task that is attempting to obtain the + * muted. */ + #define traceTASK_PRIORITY_INHERIT( pxTCBOfMutexHolder, uxInheritedPriority ) #endif #ifndef traceTASK_PRIORITY_DISINHERIT - /* Called when a task releases a mutex, the holding of which had resulted in - the task inheriting the priority of a higher priority task. - pxTCBOfMutexHolder is a pointer to the TCB of the task that is releasing the - mutex. uxOriginalPriority is the task's configured (base) priority. */ - #define traceTASK_PRIORITY_DISINHERIT( pxTCBOfMutexHolder, uxOriginalPriority ) + +/* Called when a task releases a mutex, the holding of which had resulted in + * the task inheriting the priority of a higher priority task. + * pxTCBOfMutexHolder is a pointer to the TCB of the task that is releasing the + * mutex. uxOriginalPriority is the task's configured (base) priority. */ + #define traceTASK_PRIORITY_DISINHERIT( pxTCBOfMutexHolder, uxOriginalPriority ) #endif #ifndef traceBLOCKING_ON_QUEUE_RECEIVE - /* Task is about to block because it cannot read from a - queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore - upon which the read was attempted. pxCurrentTCB points to the TCB of the - task that attempted the read. */ - #define traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ) + +/* Task is about to block because it cannot read from a + * queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore + * upon which the read was attempted. pxCurrentTCB points to the TCB of the + * task that attempted the read. */ + #define traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ) #endif #ifndef traceBLOCKING_ON_QUEUE_PEEK - /* Task is about to block because it cannot read from a - queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore - upon which the read was attempted. pxCurrentTCB points to the TCB of the - task that attempted the read. */ - #define traceBLOCKING_ON_QUEUE_PEEK( pxQueue ) + +/* Task is about to block because it cannot read from a + * queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore + * upon which the read was attempted. pxCurrentTCB points to the TCB of the + * task that attempted the read. */ + #define traceBLOCKING_ON_QUEUE_PEEK( pxQueue ) #endif #ifndef traceBLOCKING_ON_QUEUE_SEND - /* Task is about to block because it cannot write to a - queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore - upon which the write was attempted. pxCurrentTCB points to the TCB of the - task that attempted the write. */ - #define traceBLOCKING_ON_QUEUE_SEND( pxQueue ) + +/* Task is about to block because it cannot write to a + * queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore + * upon which the write was attempted. pxCurrentTCB points to the TCB of the + * task that attempted the write. */ + #define traceBLOCKING_ON_QUEUE_SEND( pxQueue ) #endif #ifndef configCHECK_FOR_STACK_OVERFLOW - #define configCHECK_FOR_STACK_OVERFLOW 0 + #define configCHECK_FOR_STACK_OVERFLOW 0 #endif #ifndef configRECORD_STACK_HIGH_ADDRESS - #define configRECORD_STACK_HIGH_ADDRESS 0 + #define configRECORD_STACK_HIGH_ADDRESS 0 #endif #ifndef configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H - #define configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H 0 + #define configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H 0 #endif /* The following event macros are embedded in the kernel API calls. */ #ifndef traceMOVED_TASK_TO_READY_STATE - #define traceMOVED_TASK_TO_READY_STATE( pxTCB ) + #define traceMOVED_TASK_TO_READY_STATE( pxTCB ) #endif #ifndef tracePOST_MOVED_TASK_TO_READY_STATE - #define tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB ) + #define tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB ) #endif #ifndef traceQUEUE_CREATE - #define traceQUEUE_CREATE( pxNewQueue ) + #define traceQUEUE_CREATE( pxNewQueue ) #endif #ifndef traceQUEUE_CREATE_FAILED - #define traceQUEUE_CREATE_FAILED( ucQueueType ) + #define traceQUEUE_CREATE_FAILED( ucQueueType ) #endif #ifndef traceCREATE_MUTEX - #define traceCREATE_MUTEX( pxNewQueue ) + #define traceCREATE_MUTEX( pxNewQueue ) #endif #ifndef traceCREATE_MUTEX_FAILED - #define traceCREATE_MUTEX_FAILED() + #define traceCREATE_MUTEX_FAILED() #endif #ifndef traceGIVE_MUTEX_RECURSIVE - #define traceGIVE_MUTEX_RECURSIVE( pxMutex ) + #define traceGIVE_MUTEX_RECURSIVE( pxMutex ) #endif #ifndef traceGIVE_MUTEX_RECURSIVE_FAILED - #define traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ) + #define traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ) #endif #ifndef traceTAKE_MUTEX_RECURSIVE - #define traceTAKE_MUTEX_RECURSIVE( pxMutex ) + #define traceTAKE_MUTEX_RECURSIVE( pxMutex ) #endif #ifndef traceTAKE_MUTEX_RECURSIVE_FAILED - #define traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex ) + #define traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex ) #endif #ifndef traceCREATE_COUNTING_SEMAPHORE - #define traceCREATE_COUNTING_SEMAPHORE() + #define traceCREATE_COUNTING_SEMAPHORE() #endif #ifndef traceCREATE_COUNTING_SEMAPHORE_FAILED - #define traceCREATE_COUNTING_SEMAPHORE_FAILED() + #define traceCREATE_COUNTING_SEMAPHORE_FAILED() #endif -#ifndef traceQUEUE_SEMAPHORE_RECEIVE - #define traceQUEUE_SEMAPHORE_RECEIVE( pxQueue ) +#ifndef traceQUEUE_SET_SEND + #define traceQUEUE_SET_SEND traceQUEUE_SEND #endif +#ifdef ESP_PLATFORM +#ifndef traceQUEUE_SEMAPHORE_RECEIVE + #define traceQUEUE_SEMAPHORE_RECEIVE( pxQueue ) +#endif +#endif // ESP_PLATFORM + #ifndef traceQUEUE_SEND - #define traceQUEUE_SEND( pxQueue ) + #define traceQUEUE_SEND( pxQueue ) #endif #ifndef traceQUEUE_SEND_FAILED - #define traceQUEUE_SEND_FAILED( pxQueue ) + #define traceQUEUE_SEND_FAILED( pxQueue ) #endif #ifndef traceQUEUE_RECEIVE - #define traceQUEUE_RECEIVE( pxQueue ) + #define traceQUEUE_RECEIVE( pxQueue ) #endif #ifndef traceQUEUE_PEEK - #define traceQUEUE_PEEK( pxQueue ) + #define traceQUEUE_PEEK( pxQueue ) #endif #ifndef traceQUEUE_PEEK_FAILED - #define traceQUEUE_PEEK_FAILED( pxQueue ) + #define traceQUEUE_PEEK_FAILED( pxQueue ) #endif #ifndef traceQUEUE_PEEK_FROM_ISR - #define traceQUEUE_PEEK_FROM_ISR( pxQueue ) + #define traceQUEUE_PEEK_FROM_ISR( pxQueue ) #endif #ifndef traceQUEUE_RECEIVE_FAILED - #define traceQUEUE_RECEIVE_FAILED( pxQueue ) + #define traceQUEUE_RECEIVE_FAILED( pxQueue ) #endif #ifndef traceQUEUE_SEND_FROM_ISR - #define traceQUEUE_SEND_FROM_ISR( pxQueue ) + #define traceQUEUE_SEND_FROM_ISR( pxQueue ) #endif #ifndef traceQUEUE_SEND_FROM_ISR_FAILED - #define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ) + #define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ) #endif #ifndef traceQUEUE_RECEIVE_FROM_ISR - #define traceQUEUE_RECEIVE_FROM_ISR( pxQueue ) + #define traceQUEUE_RECEIVE_FROM_ISR( pxQueue ) #endif #ifndef traceQUEUE_RECEIVE_FROM_ISR_FAILED - #define traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ) + #define traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ) #endif #ifndef traceQUEUE_PEEK_FROM_ISR_FAILED - #define traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue ) + #define traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue ) #endif #ifndef traceQUEUE_DELETE - #define traceQUEUE_DELETE( pxQueue ) + #define traceQUEUE_DELETE( pxQueue ) #endif +#ifdef ESP_PLATFORM #ifndef traceQUEUE_GIVE_FROM_ISR - #define traceQUEUE_GIVE_FROM_ISR( pxQueue ) + #define traceQUEUE_GIVE_FROM_ISR( pxQueue ) #endif #ifndef traceQUEUE_GIVE_FROM_ISR_FAILED - #define traceQUEUE_GIVE_FROM_ISR_FAILED( pxQueue ) + #define traceQUEUE_GIVE_FROM_ISR_FAILED( pxQueue ) #endif +#endif // ESP_PLATFORM #ifndef traceTASK_CREATE - #define traceTASK_CREATE( pxNewTCB ) + #define traceTASK_CREATE( pxNewTCB ) #endif #ifndef traceTASK_CREATE_FAILED - #define traceTASK_CREATE_FAILED() + #define traceTASK_CREATE_FAILED() #endif #ifndef traceTASK_DELETE - #define traceTASK_DELETE( pxTaskToDelete ) + #define traceTASK_DELETE( pxTaskToDelete ) #endif #ifndef traceTASK_DELAY_UNTIL - #define traceTASK_DELAY_UNTIL( x ) + #define traceTASK_DELAY_UNTIL( x ) #endif #ifndef traceTASK_DELAY - #define traceTASK_DELAY() + #define traceTASK_DELAY() #endif #ifndef traceTASK_PRIORITY_SET - #define traceTASK_PRIORITY_SET( pxTask, uxNewPriority ) + #define traceTASK_PRIORITY_SET( pxTask, uxNewPriority ) #endif #ifndef traceTASK_SUSPEND - #define traceTASK_SUSPEND( pxTaskToSuspend ) + #define traceTASK_SUSPEND( pxTaskToSuspend ) #endif #ifndef traceTASK_RESUME - #define traceTASK_RESUME( pxTaskToResume ) + #define traceTASK_RESUME( pxTaskToResume ) #endif #ifndef traceTASK_RESUME_FROM_ISR - #define traceTASK_RESUME_FROM_ISR( pxTaskToResume ) + #define traceTASK_RESUME_FROM_ISR( pxTaskToResume ) #endif #ifndef traceTASK_INCREMENT_TICK - #define traceTASK_INCREMENT_TICK( xTickCount ) + #define traceTASK_INCREMENT_TICK( xTickCount ) #endif #ifndef traceTIMER_CREATE - #define traceTIMER_CREATE( pxNewTimer ) + #define traceTIMER_CREATE( pxNewTimer ) #endif #ifndef traceTIMER_CREATE_FAILED - #define traceTIMER_CREATE_FAILED() + #define traceTIMER_CREATE_FAILED() #endif #ifndef traceTIMER_COMMAND_SEND - #define traceTIMER_COMMAND_SEND( xTimer, xMessageID, xMessageValueValue, xReturn ) + #define traceTIMER_COMMAND_SEND( xTimer, xMessageID, xMessageValueValue, xReturn ) #endif #ifndef traceTIMER_EXPIRED - #define traceTIMER_EXPIRED( pxTimer ) + #define traceTIMER_EXPIRED( pxTimer ) #endif #ifndef traceTIMER_COMMAND_RECEIVED - #define traceTIMER_COMMAND_RECEIVED( pxTimer, xMessageID, xMessageValue ) + #define traceTIMER_COMMAND_RECEIVED( pxTimer, xMessageID, xMessageValue ) #endif #ifndef traceMALLOC @@ -587,445 +629,470 @@ extern "C" { #endif #ifndef traceEVENT_GROUP_CREATE - #define traceEVENT_GROUP_CREATE( xEventGroup ) + #define traceEVENT_GROUP_CREATE( xEventGroup ) #endif #ifndef traceEVENT_GROUP_CREATE_FAILED - #define traceEVENT_GROUP_CREATE_FAILED() + #define traceEVENT_GROUP_CREATE_FAILED() #endif #ifndef traceEVENT_GROUP_SYNC_BLOCK - #define traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor ) + #define traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor ) #endif #ifndef traceEVENT_GROUP_SYNC_END - #define traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) xTimeoutOccurred + #define traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) xTimeoutOccurred #endif #ifndef traceEVENT_GROUP_WAIT_BITS_BLOCK - #define traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor ) + #define traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor ) #endif #ifndef traceEVENT_GROUP_WAIT_BITS_END - #define traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) xTimeoutOccurred + #define traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) xTimeoutOccurred #endif #ifndef traceEVENT_GROUP_CLEAR_BITS - #define traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear ) + #define traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear ) #endif #ifndef traceEVENT_GROUP_CLEAR_BITS_FROM_ISR - #define traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear ) + #define traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear ) #endif #ifndef traceEVENT_GROUP_SET_BITS - #define traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet ) + #define traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet ) #endif #ifndef traceEVENT_GROUP_SET_BITS_FROM_ISR - #define traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet ) + #define traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet ) #endif #ifndef traceEVENT_GROUP_DELETE - #define traceEVENT_GROUP_DELETE( xEventGroup ) + #define traceEVENT_GROUP_DELETE( xEventGroup ) #endif #ifndef tracePEND_FUNC_CALL - #define tracePEND_FUNC_CALL(xFunctionToPend, pvParameter1, ulParameter2, ret) + #define tracePEND_FUNC_CALL( xFunctionToPend, pvParameter1, ulParameter2, ret ) #endif #ifndef tracePEND_FUNC_CALL_FROM_ISR - #define tracePEND_FUNC_CALL_FROM_ISR(xFunctionToPend, pvParameter1, ulParameter2, ret) + #define tracePEND_FUNC_CALL_FROM_ISR( xFunctionToPend, pvParameter1, ulParameter2, ret ) #endif #ifndef traceQUEUE_REGISTRY_ADD - #define traceQUEUE_REGISTRY_ADD(xQueue, pcQueueName) + #define traceQUEUE_REGISTRY_ADD( xQueue, pcQueueName ) #endif #ifndef traceTASK_NOTIFY_TAKE_BLOCK - #define traceTASK_NOTIFY_TAKE_BLOCK() + #define traceTASK_NOTIFY_TAKE_BLOCK( uxIndexToWait ) #endif #ifndef traceTASK_NOTIFY_TAKE - #define traceTASK_NOTIFY_TAKE() + #define traceTASK_NOTIFY_TAKE( uxIndexToWait ) #endif #ifndef traceTASK_NOTIFY_WAIT_BLOCK - #define traceTASK_NOTIFY_WAIT_BLOCK() + #define traceTASK_NOTIFY_WAIT_BLOCK( uxIndexToWait ) #endif #ifndef traceTASK_NOTIFY_WAIT - #define traceTASK_NOTIFY_WAIT() + #define traceTASK_NOTIFY_WAIT( uxIndexToWait ) #endif #ifndef traceTASK_NOTIFY - #define traceTASK_NOTIFY() + #define traceTASK_NOTIFY( uxIndexToNotify ) #endif #ifndef traceTASK_NOTIFY_FROM_ISR - #define traceTASK_NOTIFY_FROM_ISR() + #define traceTASK_NOTIFY_FROM_ISR( uxIndexToNotify ) #endif #ifndef traceTASK_NOTIFY_GIVE_FROM_ISR - #define traceTASK_NOTIFY_GIVE_FROM_ISR() + #define traceTASK_NOTIFY_GIVE_FROM_ISR( uxIndexToNotify ) #endif #ifndef traceSTREAM_BUFFER_CREATE_FAILED - #define traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer ) + #define traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer ) #endif #ifndef traceSTREAM_BUFFER_CREATE_STATIC_FAILED - #define traceSTREAM_BUFFER_CREATE_STATIC_FAILED( xReturn, xIsMessageBuffer ) + #define traceSTREAM_BUFFER_CREATE_STATIC_FAILED( xReturn, xIsMessageBuffer ) #endif #ifndef traceSTREAM_BUFFER_CREATE - #define traceSTREAM_BUFFER_CREATE( pxStreamBuffer, xIsMessageBuffer ) + #define traceSTREAM_BUFFER_CREATE( pxStreamBuffer, xIsMessageBuffer ) #endif #ifndef traceSTREAM_BUFFER_DELETE - #define traceSTREAM_BUFFER_DELETE( xStreamBuffer ) + #define traceSTREAM_BUFFER_DELETE( xStreamBuffer ) #endif #ifndef traceSTREAM_BUFFER_RESET - #define traceSTREAM_BUFFER_RESET( xStreamBuffer ) + #define traceSTREAM_BUFFER_RESET( xStreamBuffer ) #endif #ifndef traceBLOCKING_ON_STREAM_BUFFER_SEND - #define traceBLOCKING_ON_STREAM_BUFFER_SEND( xStreamBuffer ) + #define traceBLOCKING_ON_STREAM_BUFFER_SEND( xStreamBuffer ) #endif #ifndef traceSTREAM_BUFFER_SEND - #define traceSTREAM_BUFFER_SEND( xStreamBuffer, xBytesSent ) + #define traceSTREAM_BUFFER_SEND( xStreamBuffer, xBytesSent ) #endif #ifndef traceSTREAM_BUFFER_SEND_FAILED - #define traceSTREAM_BUFFER_SEND_FAILED( xStreamBuffer ) + #define traceSTREAM_BUFFER_SEND_FAILED( xStreamBuffer ) #endif #ifndef traceSTREAM_BUFFER_SEND_FROM_ISR - #define traceSTREAM_BUFFER_SEND_FROM_ISR( xStreamBuffer, xBytesSent ) + #define traceSTREAM_BUFFER_SEND_FROM_ISR( xStreamBuffer, xBytesSent ) #endif #ifndef traceBLOCKING_ON_STREAM_BUFFER_RECEIVE - #define traceBLOCKING_ON_STREAM_BUFFER_RECEIVE( xStreamBuffer ) + #define traceBLOCKING_ON_STREAM_BUFFER_RECEIVE( xStreamBuffer ) #endif #ifndef traceSTREAM_BUFFER_RECEIVE - #define traceSTREAM_BUFFER_RECEIVE( xStreamBuffer, xReceivedLength ) + #define traceSTREAM_BUFFER_RECEIVE( xStreamBuffer, xReceivedLength ) #endif #ifndef traceSTREAM_BUFFER_RECEIVE_FAILED - #define traceSTREAM_BUFFER_RECEIVE_FAILED( xStreamBuffer ) + #define traceSTREAM_BUFFER_RECEIVE_FAILED( xStreamBuffer ) #endif #ifndef traceSTREAM_BUFFER_RECEIVE_FROM_ISR - #define traceSTREAM_BUFFER_RECEIVE_FROM_ISR( xStreamBuffer, xReceivedLength ) + #define traceSTREAM_BUFFER_RECEIVE_FROM_ISR( xStreamBuffer, xReceivedLength ) #endif +#ifdef ESP_PLATFORM #ifndef traceISR_EXIT_TO_SCHEDULER - #define traceISR_EXIT_TO_SCHEDULER() + #define traceISR_EXIT_TO_SCHEDULER() #endif #ifndef traceISR_EXIT - #define traceISR_EXIT() + #define traceISR_EXIT() #endif #ifndef traceISR_ENTER - #define traceISR_ENTER(_n_) + #define traceISR_ENTER(_n_) #endif +#endif // ESP_PLATFORM #ifndef configGENERATE_RUN_TIME_STATS - #define configGENERATE_RUN_TIME_STATS 0 + #define configGENERATE_RUN_TIME_STATS 0 #endif #if ( configGENERATE_RUN_TIME_STATS == 1 ) - #ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS - #error If configGENERATE_RUN_TIME_STATS is defined then portCONFIGURE_TIMER_FOR_RUN_TIME_STATS must also be defined. portCONFIGURE_TIMER_FOR_RUN_TIME_STATS should call a port layer function to setup a peripheral timer/counter that can then be used as the run time counter time base. - #endif /* portCONFIGURE_TIMER_FOR_RUN_TIME_STATS */ + #ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS + #error If configGENERATE_RUN_TIME_STATS is defined then portCONFIGURE_TIMER_FOR_RUN_TIME_STATS must also be defined. portCONFIGURE_TIMER_FOR_RUN_TIME_STATS should call a port layer function to setup a peripheral timer/counter that can then be used as the run time counter time base. + #endif /* portCONFIGURE_TIMER_FOR_RUN_TIME_STATS */ - #ifndef portGET_RUN_TIME_COUNTER_VALUE - #ifndef portALT_GET_RUN_TIME_COUNTER_VALUE - #error If configGENERATE_RUN_TIME_STATS is defined then either portGET_RUN_TIME_COUNTER_VALUE or portALT_GET_RUN_TIME_COUNTER_VALUE must also be defined. See the examples provided and the FreeRTOS web site for more information. - #endif /* portALT_GET_RUN_TIME_COUNTER_VALUE */ - #endif /* portGET_RUN_TIME_COUNTER_VALUE */ + #ifndef portGET_RUN_TIME_COUNTER_VALUE + #ifndef portALT_GET_RUN_TIME_COUNTER_VALUE + #error If configGENERATE_RUN_TIME_STATS is defined then either portGET_RUN_TIME_COUNTER_VALUE or portALT_GET_RUN_TIME_COUNTER_VALUE must also be defined. See the examples provided and the FreeRTOS web site for more information. + #endif /* portALT_GET_RUN_TIME_COUNTER_VALUE */ + #endif /* portGET_RUN_TIME_COUNTER_VALUE */ #endif /* configGENERATE_RUN_TIME_STATS */ #ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS - #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() + #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() #endif #ifndef configUSE_MALLOC_FAILED_HOOK - #define configUSE_MALLOC_FAILED_HOOK 0 + #define configUSE_MALLOC_FAILED_HOOK 0 #endif #ifndef portPRIVILEGE_BIT - #define portPRIVILEGE_BIT ( ( UBaseType_t ) 0x00 ) + #define portPRIVILEGE_BIT ( ( UBaseType_t ) 0x00 ) #endif #ifndef portYIELD_WITHIN_API - #define portYIELD_WITHIN_API portYIELD + #define portYIELD_WITHIN_API portYIELD #endif #ifndef portSUPPRESS_TICKS_AND_SLEEP - #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) #endif #ifndef configEXPECTED_IDLE_TIME_BEFORE_SLEEP - #define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 2 + #define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 2 #endif #if configEXPECTED_IDLE_TIME_BEFORE_SLEEP < 2 - #error configEXPECTED_IDLE_TIME_BEFORE_SLEEP must not be less than 2 + #error configEXPECTED_IDLE_TIME_BEFORE_SLEEP must not be less than 2 #endif #ifndef configUSE_TICKLESS_IDLE - #define configUSE_TICKLESS_IDLE 0 + #define configUSE_TICKLESS_IDLE 0 #endif #ifndef configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING - #define configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING( x ) + #define configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING( x ) #endif #ifndef configPRE_SLEEP_PROCESSING - #define configPRE_SLEEP_PROCESSING( x ) + #define configPRE_SLEEP_PROCESSING( x ) #endif #ifndef configPOST_SLEEP_PROCESSING - #define configPOST_SLEEP_PROCESSING( x ) + #define configPOST_SLEEP_PROCESSING( x ) #endif #ifndef configUSE_QUEUE_SETS - #define configUSE_QUEUE_SETS 0 + #define configUSE_QUEUE_SETS 0 #endif #ifndef portTASK_USES_FLOATING_POINT - #define portTASK_USES_FLOATING_POINT() + #define portTASK_USES_FLOATING_POINT() #endif #ifndef portALLOCATE_SECURE_CONTEXT - #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) + #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) #endif #ifndef portDONT_DISCARD - #define portDONT_DISCARD + #define portDONT_DISCARD #endif #ifndef configUSE_TIME_SLICING - #define configUSE_TIME_SLICING 1 + #define configUSE_TIME_SLICING 1 #endif #ifndef configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS - #define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 0 + #define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 0 #endif #ifndef configUSE_STATS_FORMATTING_FUNCTIONS - #define configUSE_STATS_FORMATTING_FUNCTIONS 0 + #define configUSE_STATS_FORMATTING_FUNCTIONS 0 #endif #ifndef portASSERT_IF_INTERRUPT_PRIORITY_INVALID - #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() #endif #ifndef configUSE_TRACE_FACILITY - #define configUSE_TRACE_FACILITY 0 + #define configUSE_TRACE_FACILITY 0 #endif #ifndef mtCOVERAGE_TEST_MARKER - #define mtCOVERAGE_TEST_MARKER() + #define mtCOVERAGE_TEST_MARKER() #endif #ifndef mtCOVERAGE_TEST_DELAY - #define mtCOVERAGE_TEST_DELAY() + #define mtCOVERAGE_TEST_DELAY() #endif #ifndef portASSERT_IF_IN_ISR - #define portASSERT_IF_IN_ISR() + #define portASSERT_IF_IN_ISR() #endif #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION - #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 #endif #ifndef configAPPLICATION_ALLOCATED_HEAP - #define configAPPLICATION_ALLOCATED_HEAP 0 + #define configAPPLICATION_ALLOCATED_HEAP 0 #endif #ifndef configUSE_TASK_NOTIFICATIONS - #define configUSE_TASK_NOTIFICATIONS 1 + #define configUSE_TASK_NOTIFICATIONS 1 +#endif + +#ifndef configTASK_NOTIFICATION_ARRAY_ENTRIES + #define configTASK_NOTIFICATION_ARRAY_ENTRIES 1 +#endif + +#if configTASK_NOTIFICATION_ARRAY_ENTRIES < 1 + #error configTASK_NOTIFICATION_ARRAY_ENTRIES must be at least 1 #endif #ifndef configUSE_POSIX_ERRNO - #define configUSE_POSIX_ERRNO 0 + #define configUSE_POSIX_ERRNO 0 #endif #ifndef portTICK_TYPE_IS_ATOMIC - #define portTICK_TYPE_IS_ATOMIC 0 + #define portTICK_TYPE_IS_ATOMIC 0 #endif #ifndef configSUPPORT_STATIC_ALLOCATION - /* Defaults to 0 for backward compatibility. */ - #define configSUPPORT_STATIC_ALLOCATION 0 + /* Defaults to 0 for backward compatibility. */ + #define configSUPPORT_STATIC_ALLOCATION 0 #endif #ifndef configSUPPORT_DYNAMIC_ALLOCATION - /* Defaults to 1 for backward compatibility. */ - #define configSUPPORT_DYNAMIC_ALLOCATION 1 + /* Defaults to 1 for backward compatibility. */ + #define configSUPPORT_DYNAMIC_ALLOCATION 1 +#endif + +#ifndef configSTACK_ALLOCATION_FROM_SEPARATE_HEAP + /* Defaults to 0 for backward compatibility. */ + #define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 #endif #ifndef configSTACK_DEPTH_TYPE - /* Defaults to uint16_t for backward compatibility, but can be overridden - in FreeRTOSConfig.h if uint16_t is too restrictive. */ - #define configSTACK_DEPTH_TYPE uint16_t + +/* Defaults to uint16_t for backward compatibility, but can be overridden + * in FreeRTOSConfig.h if uint16_t is too restrictive. */ + #define configSTACK_DEPTH_TYPE uint16_t #endif #ifndef configMESSAGE_BUFFER_LENGTH_TYPE - /* Defaults to size_t for backward compatibility, but can be overridden - in FreeRTOSConfig.h if lengths will always be less than the number of bytes - in a size_t. */ - #define configMESSAGE_BUFFER_LENGTH_TYPE size_t + +/* Defaults to size_t for backward compatibility, but can be overridden + * in FreeRTOSConfig.h if lengths will always be less than the number of bytes + * in a size_t. */ + #define configMESSAGE_BUFFER_LENGTH_TYPE size_t #endif /* Sanity check the configuration. */ -#if( configUSE_TICKLESS_IDLE != 0 ) - #if( INCLUDE_vTaskSuspend != 1 ) - #error INCLUDE_vTaskSuspend must be set to 1 if configUSE_TICKLESS_IDLE is not set to 0 - #endif /* INCLUDE_vTaskSuspend */ +#if ( configUSE_TICKLESS_IDLE != 0 ) + #if ( INCLUDE_vTaskSuspend != 1 ) + #error INCLUDE_vTaskSuspend must be set to 1 if configUSE_TICKLESS_IDLE is not set to 0 + #endif /* INCLUDE_vTaskSuspend */ #endif /* configUSE_TICKLESS_IDLE */ -#if( ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 0 ) ) - #error configSUPPORT_STATIC_ALLOCATION and configSUPPORT_DYNAMIC_ALLOCATION cannot both be 0, but can both be 1. +#if ( ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 0 ) ) + #error configSUPPORT_STATIC_ALLOCATION and configSUPPORT_DYNAMIC_ALLOCATION cannot both be 0, but can both be 1. #endif -#if( ( configUSE_RECURSIVE_MUTEXES == 1 ) && ( configUSE_MUTEXES != 1 ) ) - #error configUSE_MUTEXES must be set to 1 to use recursive mutexes +#if ( ( configUSE_RECURSIVE_MUTEXES == 1 ) && ( configUSE_MUTEXES != 1 ) ) + #error configUSE_MUTEXES must be set to 1 to use recursive mutexes #endif #ifndef configINITIAL_TICK_COUNT - #define configINITIAL_TICK_COUNT 0 + #define configINITIAL_TICK_COUNT 0 #endif -#if( portTICK_TYPE_IS_ATOMIC == 0 ) - /* Either variables of tick type cannot be read atomically, or - portTICK_TYPE_IS_ATOMIC was not set - map the critical sections used when - the tick count is returned to the standard critical section macros. */ - #define portTICK_TYPE_ENTER_CRITICAL(mux) portENTER_CRITICAL(mux) - #define portTICK_TYPE_EXIT_CRITICAL(mux) portEXIT_CRITICAL(mux) - #define portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR() - #define portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( ( x ) ) +#if ( portTICK_TYPE_IS_ATOMIC == 0 ) + +/* Either variables of tick type cannot be read atomically, or + * portTICK_TYPE_IS_ATOMIC was not set - map the critical sections used when + * the tick count is returned to the standard critical section macros. */ + #define portTICK_TYPE_ENTER_CRITICAL(mux) portENTER_CRITICAL(mux) + #define portTICK_TYPE_EXIT_CRITICAL(mux) portEXIT_CRITICAL(mux) + #define portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR() + #define portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( ( x ) ) #else - /* The tick type can be read atomically, so critical sections used when the - tick count is returned can be defined away. */ - #define portTICK_TYPE_ENTER_CRITICAL() - #define portTICK_TYPE_EXIT_CRITICAL() - #define portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR() 0 - #define portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( x ) ( void ) x -#endif + +/* The tick type can be read atomically, so critical sections used when the + * tick count is returned can be defined away. */ + #define portTICK_TYPE_ENTER_CRITICAL() + #define portTICK_TYPE_EXIT_CRITICAL() + #define portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR() 0 + #define portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( x ) ( void ) x +#endif /* if ( portTICK_TYPE_IS_ATOMIC == 0 ) */ /* Definitions to allow backward compatibility with FreeRTOS versions prior to -V8 if desired. */ + * V8 if desired. */ #ifndef configENABLE_BACKWARD_COMPATIBILITY - #define configENABLE_BACKWARD_COMPATIBILITY 1 + #define configENABLE_BACKWARD_COMPATIBILITY 1 #endif #ifndef configPRINTF - /* configPRINTF() was not defined, so define it away to nothing. To use - configPRINTF() then define it as follows (where MyPrintFunction() is - provided by the application writer): - void MyPrintFunction(const char *pcFormat, ... ); - #define configPRINTF( X ) MyPrintFunction X - - Then call like a standard printf() function, but placing brackets around - all parameters so they are passed as a single parameter. For example: - configPRINTF( ("Value = %d", MyVariable) ); */ - #define configPRINTF( X ) +/* configPRINTF() was not defined, so define it away to nothing. To use + * configPRINTF() then define it as follows (where MyPrintFunction() is + * provided by the application writer): + * + * void MyPrintFunction(const char *pcFormat, ... ); + #define configPRINTF( X ) MyPrintFunction X + * + * Then call like a standard printf() function, but placing brackets around + * all parameters so they are passed as a single parameter. For example: + * configPRINTF( ("Value = %d", MyVariable) ); */ + #define configPRINTF( X ) #endif #ifndef configMAX - /* The application writer has not provided their own MAX macro, so define - the following generic implementation. */ - #define configMAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) ) + +/* The application writer has not provided their own MAX macro, so define + * the following generic implementation. */ + #define configMAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) ) #endif #ifndef configMIN - /* The application writer has not provided their own MAX macro, so define - the following generic implementation. */ - #define configMIN( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) ) + +/* The application writer has not provided their own MIN macro, so define + * the following generic implementation. */ + #define configMIN( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) ) #endif #if configENABLE_BACKWARD_COMPATIBILITY == 1 - #define eTaskStateGet eTaskGetState - #define portTickType TickType_t - #define xTaskHandle TaskHandle_t - #define xQueueHandle QueueHandle_t - #define xSemaphoreHandle SemaphoreHandle_t - #define xQueueSetHandle QueueSetHandle_t - #define xQueueSetMemberHandle QueueSetMemberHandle_t - #define xTimeOutType TimeOut_t - #define xMemoryRegion MemoryRegion_t - #define xTaskParameters TaskParameters_t - #define xTaskStatusType TaskStatus_t - #define xTimerHandle TimerHandle_t - #define xCoRoutineHandle CoRoutineHandle_t - #define pdTASK_HOOK_CODE TaskHookFunction_t - #define portTICK_RATE_MS portTICK_PERIOD_MS - #define pcTaskGetTaskName pcTaskGetName - #define pcTimerGetTimerName pcTimerGetName - #define pcQueueGetQueueName pcQueueGetName - #define vTaskGetTaskInfo vTaskGetInfo + #define eTaskStateGet eTaskGetState + #define portTickType TickType_t + #define xTaskHandle TaskHandle_t + #define xQueueHandle QueueHandle_t + #define xSemaphoreHandle SemaphoreHandle_t + #define xQueueSetHandle QueueSetHandle_t + #define xQueueSetMemberHandle QueueSetMemberHandle_t + #define xTimeOutType TimeOut_t + #define xMemoryRegion MemoryRegion_t + #define xTaskParameters TaskParameters_t + #define xTaskStatusType TaskStatus_t + #define xTimerHandle TimerHandle_t + #define xCoRoutineHandle CoRoutineHandle_t + #define pdTASK_HOOK_CODE TaskHookFunction_t + #define portTICK_RATE_MS portTICK_PERIOD_MS + #define pcTaskGetTaskName pcTaskGetName + #define pcTimerGetTimerName pcTimerGetName + #define pcQueueGetQueueName pcQueueGetName + #define vTaskGetTaskInfo vTaskGetInfo + #define xTaskGetIdleRunTimeCounter ulTaskGetIdleRunTimeCounter - /* Backward compatibility within the scheduler code only - these definitions - are not really required but are included for completeness. */ - #define tmrTIMER_CALLBACK TimerCallbackFunction_t - #define pdTASK_CODE TaskFunction_t - #define xListItem ListItem_t - #define xList List_t +/* Backward compatibility within the scheduler code only - these definitions + * are not really required but are included for completeness. */ + #define tmrTIMER_CALLBACK TimerCallbackFunction_t + #define pdTASK_CODE TaskFunction_t + #define xListItem ListItem_t + #define xList List_t - /* For libraries that break the list data hiding, and access list structure - members directly (which is not supposed to be done). */ - #define pxContainer pvContainer +/* For libraries that break the list data hiding, and access list structure + * members directly (which is not supposed to be done). */ + #define pxContainer pvContainer #endif /* configENABLE_BACKWARD_COMPATIBILITY */ +#ifdef ESP_PLATFORM #ifndef configESP32_PER_TASK_DATA - #define configESP32_PER_TASK_DATA 1 + #define configESP32_PER_TASK_DATA 1 #endif +#endif // ESP_PLATFORM -#if( configUSE_ALTERNATIVE_API != 0 ) - #error The alternative API was deprecated some time ago, and was removed in FreeRTOS V9.0 0 +#if ( configUSE_ALTERNATIVE_API != 0 ) + #error The alternative API was deprecated some time ago, and was removed in FreeRTOS V9.0 0 #endif /* Set configUSE_TASK_FPU_SUPPORT to 0 to omit floating point support even -if floating point hardware is otherwise supported by the FreeRTOS port in use. -This constant is not supported by all FreeRTOS ports that include floating -point support. */ + * if floating point hardware is otherwise supported by the FreeRTOS port in use. + * This constant is not supported by all FreeRTOS ports that include floating + * point support. */ #ifndef configUSE_TASK_FPU_SUPPORT - #define configUSE_TASK_FPU_SUPPORT 1 + #define configUSE_TASK_FPU_SUPPORT 1 #endif /* Set configENABLE_MPU to 1 to enable MPU support and 0 to disable it. This is -currently used in ARMv8M ports. */ + * currently used in ARMv8M ports. */ #ifndef configENABLE_MPU - #define configENABLE_MPU 0 + #define configENABLE_MPU 0 #endif /* Set configENABLE_FPU to 1 to enable FPU support and 0 to disable it. This is -currently used in ARMv8M ports. */ + * currently used in ARMv8M ports. */ #ifndef configENABLE_FPU - #define configENABLE_FPU 1 + #define configENABLE_FPU 1 #endif /* Set configENABLE_TRUSTZONE to 1 enable TrustZone support and 0 to disable it. -This is currently used in ARMv8M ports. */ + * This is currently used in ARMv8M ports. */ #ifndef configENABLE_TRUSTZONE - #define configENABLE_TRUSTZONE 1 + #define configENABLE_TRUSTZONE 1 #endif /* Set configRUN_FREERTOS_SECURE_ONLY to 1 to run the FreeRTOS ARMv8M port on -the Secure Side only. */ + * the Secure Side only. */ #ifndef configRUN_FREERTOS_SECURE_ONLY - #define configRUN_FREERTOS_SECURE_ONLY 0 + #define configRUN_FREERTOS_SECURE_ONLY 0 #endif /* Sometimes the FreeRTOSConfig.h settings only allow a task to be created using @@ -1070,55 +1137,56 @@ the Secure Side only. */ * | | | | xTaskCreateRestrictedStatic | | | | * +-----+---------+--------+-----------------------------+-----------------------------------+------------------+-----------+ */ -#define tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE ( ( ( portUSING_MPU_WRAPPERS == 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) || \ - ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) ) +#define tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE \ + ( ( ( portUSING_MPU_WRAPPERS == 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) || \ + ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) ) /* * In line with software engineering best practice, FreeRTOS implements a strict * data hiding policy, so the real structures used by FreeRTOS to maintain the * state of tasks, queues, semaphores, etc. are not accessible to the application * code. However, if the application writer wants to statically allocate such - * an object then the size of the object needs to be know. Dummy structures + * an object then the size of the object needs to be known. Dummy structures * that are guaranteed to have the same size and alignment requirements of the * real objects are used for this purpose. The dummy list and list item * structures below are used for inclusion in such a dummy structure. */ struct xSTATIC_LIST_ITEM { - #if( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 1 ) - TickType_t xDummy1; - #endif - TickType_t xDummy2; - void *pvDummy3[ 4 ]; - #if( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 1 ) - TickType_t xDummy4; - #endif + #if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 1 ) + TickType_t xDummy1; + #endif + TickType_t xDummy2; + void * pvDummy3[ 4 ]; + #if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 1 ) + TickType_t xDummy4; + #endif }; typedef struct xSTATIC_LIST_ITEM StaticListItem_t; /* See the comments above the struct xSTATIC_LIST_ITEM definition. */ struct xSTATIC_MINI_LIST_ITEM { - #if( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 1 ) - TickType_t xDummy1; - #endif - TickType_t xDummy2; - void *pvDummy3[ 2 ]; + #if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 1 ) + TickType_t xDummy1; + #endif + TickType_t xDummy2; + void * pvDummy3[ 2 ]; }; typedef struct xSTATIC_MINI_LIST_ITEM StaticMiniListItem_t; /* See the comments above the struct xSTATIC_LIST_ITEM definition. */ typedef struct xSTATIC_LIST { - #if( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 1 ) - TickType_t xDummy1; - #endif - UBaseType_t uxDummy2; - void *pvDummy3; - StaticMiniListItem_t xDummy4; - #if( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 1 ) - TickType_t xDummy5; - #endif + #if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 1 ) + TickType_t xDummy1; + #endif + UBaseType_t uxDummy2; + void * pvDummy3; + StaticMiniListItem_t xDummy4; + #if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 1 ) + TickType_t xDummy5; + #endif } StaticList_t; /* @@ -1127,7 +1195,7 @@ typedef struct xSTATIC_LIST * strict data hiding policy. This means the Task structure used internally by * FreeRTOS is not accessible to application code. However, if the application * writer wants to statically allocate the memory required to create a task then - * the size of the task object needs to be know. The StaticTask_t structure + * the size of the task object needs to be known. The StaticTask_t structure * below is provided for this purpose. Its sizes and alignment requirements are * guaranteed to match those of the genuine structure, no matter which * architecture is being used, and no matter how the values in FreeRTOSConfig.h @@ -1136,56 +1204,56 @@ typedef struct xSTATIC_LIST */ typedef struct xSTATIC_TCB { - void *pxDummy1; - #if ( portUSING_MPU_WRAPPERS == 1 ) - xMPU_SETTINGS xDummy2; - #endif - StaticListItem_t xDummy3[ 2 ]; - UBaseType_t uxDummy5; - void *pxDummy6; - uint8_t ucDummy7[ configMAX_TASK_NAME_LEN ]; - BaseType_t xDummyCore; - #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) ) - void *pxDummy8; - #endif - #if ( portCRITICAL_NESTING_IN_TCB == 1 ) - UBaseType_t uxDummy9; - #endif - #if ( configUSE_TRACE_FACILITY == 1 ) - UBaseType_t uxDummy10[ 2 ]; - #endif - #if ( configUSE_MUTEXES == 1 ) - UBaseType_t uxDummy12[ 2 ]; - #endif - #if ( configUSE_APPLICATION_TASK_TAG == 1 ) - void *pxDummy14; - #endif - #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) - void *pvDummy15[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ]; - #if ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS ) - void *pvDummyLocalStorageCallBack[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ]; - #endif - #endif - #if ( configGENERATE_RUN_TIME_STATS == 1 ) - uint32_t ulDummy16; - #endif - #if ( configUSE_NEWLIB_REENTRANT == 1 ) - struct _reent xDummy17; - #endif - #if ( configUSE_TASK_NOTIFICATIONS == 1 ) - uint32_t ulDummy18; - uint8_t ucDummy19; - #endif - #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) - uint8_t uxDummy20; - #endif + void * pxDummy1; + #if ( portUSING_MPU_WRAPPERS == 1 ) + xMPU_SETTINGS xDummy2; + #endif + StaticListItem_t xDummy3[ 2 ]; + UBaseType_t uxDummy5; + void * pxDummy6; + uint8_t ucDummy7[ configMAX_TASK_NAME_LEN ]; + BaseType_t xDummyCore; + #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) ) + void * pxDummy8; + #endif + #if ( portCRITICAL_NESTING_IN_TCB == 1 ) + UBaseType_t uxDummy9; + #endif + #if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxDummy10[ 2 ]; + #endif + #if ( configUSE_MUTEXES == 1 ) + UBaseType_t uxDummy12[ 2 ]; + #endif + #if ( configUSE_APPLICATION_TASK_TAG == 1 ) + void * pxDummy14; + #endif + #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) + void * pvDummy15[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ]; + #if ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS ) + void *pvDummyLocalStorageCallBack[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ]; + #endif + #endif + #if ( configGENERATE_RUN_TIME_STATS == 1 ) + uint32_t ulDummy16; + #endif + #if ( configUSE_NEWLIB_REENTRANT == 1 ) + struct _reent xDummy17; + #endif + #if ( configUSE_TASK_NOTIFICATIONS == 1 ) + uint32_t ulDummy18[ configTASK_NOTIFICATION_ARRAY_ENTRIES ]; + uint8_t ucDummy19[ configTASK_NOTIFICATION_ARRAY_ENTRIES ]; + #endif + #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) + uint8_t uxDummy20; + #endif - #if( INCLUDE_xTaskAbortDelay == 1 ) - uint8_t ucDummy21; - #endif - #if ( configUSE_POSIX_ERRNO == 1 ) - int iDummy22; - #endif + #if ( INCLUDE_xTaskAbortDelay == 1 ) + uint8_t ucDummy21; + #endif + #if ( configUSE_POSIX_ERRNO == 1 ) + int iDummy22; + #endif } StaticTask_t; /* @@ -1194,7 +1262,7 @@ typedef struct xSTATIC_TCB * strict data hiding policy. This means the Queue structure used internally by * FreeRTOS is not accessible to application code. However, if the application * writer wants to statically allocate the memory required to create a queue - * then the size of the queue object needs to be know. The StaticQueue_t + * then the size of the queue object needs to be known. The StaticQueue_t * structure below is provided for this purpose. Its sizes and alignment * requirements are guaranteed to match those of the genuine structure, no * matter which architecture is being used, and no matter how the values in @@ -1204,33 +1272,31 @@ typedef struct xSTATIC_TCB */ typedef struct xSTATIC_QUEUE { - void *pvDummy1[ 3 ]; + void * pvDummy1[ 3 ]; - union - { - void *pvDummy2; - UBaseType_t uxDummy2; - } u; + union + { + void * pvDummy2; + UBaseType_t uxDummy2; + } u; - StaticList_t xDummy3[ 2 ]; - UBaseType_t uxDummy4[ 3 ]; - uint8_t ucDummy5[ 2 ]; + StaticList_t xDummy3[ 2 ]; + UBaseType_t uxDummy4[ 3 ]; + uint8_t ucDummy5[ 2 ]; - #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) - uint8_t ucDummy6; - #endif + #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + uint8_t ucDummy6; + #endif - #if ( configUSE_QUEUE_SETS == 1 ) - void *pvDummy7; - #endif - - #if ( configUSE_TRACE_FACILITY == 1 ) - UBaseType_t uxDummy8; - uint8_t ucDummy9; - #endif - - portMUX_TYPE xDummy10; + #if ( configUSE_QUEUE_SETS == 1 ) + void * pvDummy7; + #endif + #if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxDummy8; + uint8_t ucDummy9; + #endif + portMUX_TYPE xDummy10; } StaticQueue_t; typedef StaticQueue_t StaticSemaphore_t; @@ -1250,19 +1316,17 @@ typedef StaticQueue_t StaticSemaphore_t; */ typedef struct xSTATIC_EVENT_GROUP { - TickType_t xDummy1; - StaticList_t xDummy2; + TickType_t xDummy1; + StaticList_t xDummy2; - #if( configUSE_TRACE_FACILITY == 1 ) - UBaseType_t uxDummy3; - #endif - - #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) - uint8_t ucDummy4; - #endif - - portMUX_TYPE xDummy5; + #if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxDummy3; + #endif + #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + uint8_t ucDummy4; + #endif + portMUX_TYPE xDummy5; } StaticEventGroup_t; /* @@ -1271,7 +1335,7 @@ typedef struct xSTATIC_EVENT_GROUP * strict data hiding policy. This means the software timer structure used * internally by FreeRTOS is not accessible to application code. However, if * the application writer wants to statically allocate the memory required to - * create a software timer then the size of the queue object needs to be know. + * create a software timer then the size of the queue object needs to be known. * The StaticTimer_t structure below is provided for this purpose. Its sizes * and alignment requirements are guaranteed to match those of the genuine * structure, no matter which architecture is being used, and no matter how the @@ -1281,49 +1345,49 @@ typedef struct xSTATIC_EVENT_GROUP */ typedef struct xSTATIC_TIMER { - void *pvDummy1; - StaticListItem_t xDummy2; - TickType_t xDummy3; - void *pvDummy5; - TaskFunction_t pvDummy6; - #if( configUSE_TRACE_FACILITY == 1 ) - UBaseType_t uxDummy7; - #endif - uint8_t ucDummy8; + void * pvDummy1; + StaticListItem_t xDummy2; + TickType_t xDummy3; + void * pvDummy5; + TaskFunction_t pvDummy6; + #if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxDummy7; + #endif + uint8_t ucDummy8; } StaticTimer_t; /* -* In line with software engineering best practice, especially when supplying a -* library that is likely to change in future versions, FreeRTOS implements a -* strict data hiding policy. This means the stream buffer structure used -* internally by FreeRTOS is not accessible to application code. However, if -* the application writer wants to statically allocate the memory required to -* create a stream buffer then the size of the stream buffer object needs to be -* know. The StaticStreamBuffer_t structure below is provided for this purpose. -* Its size and alignment requirements are guaranteed to match those of the -* genuine structure, no matter which architecture is being used, and no matter -* how the values in FreeRTOSConfig.h are set. Its contents are somewhat -* obfuscated in the hope users will recognise that it would be unwise to make -* direct use of the structure members. -*/ + * In line with software engineering best practice, especially when supplying a + * library that is likely to change in future versions, FreeRTOS implements a + * strict data hiding policy. This means the stream buffer structure used + * internally by FreeRTOS is not accessible to application code. However, if + * the application writer wants to statically allocate the memory required to + * create a stream buffer then the size of the stream buffer object needs to be + * known. The StaticStreamBuffer_t structure below is provided for this + * purpose. Its size and alignment requirements are guaranteed to match those + * of the genuine structure, no matter which architecture is being used, and + * no matter how the values in FreeRTOSConfig.h are set. Its contents are + * somewhat obfuscated in the hope users will recognise that it would be unwise + * to make direct use of the structure members. + */ typedef struct xSTATIC_STREAM_BUFFER { - size_t uxDummy1[ 4 ]; - void * pvDummy2[ 3 ]; - uint8_t ucDummy3; - #if ( configUSE_TRACE_FACILITY == 1 ) - UBaseType_t uxDummy4; - #endif - - portMUX_TYPE xDummy5; - + size_t uxDummy1[ 4 ]; + void * pvDummy2[ 3 ]; + uint8_t ucDummy3; + #if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxDummy4; + #endif + portMUX_TYPE xDummy5; } StaticStreamBuffer_t; /* Message buffers are built on stream buffers. */ typedef StaticStreamBuffer_t StaticMessageBuffer_t; +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* INC_FREERTOS_H */ diff --git a/components/freertos/include/freertos/StackMacros.h b/components/freertos/include/freertos/StackMacros.h new file mode 100644 index 0000000000..8d09f10cd1 --- /dev/null +++ b/components/freertos/include/freertos/StackMacros.h @@ -0,0 +1,32 @@ +/* + * FreeRTOS Kernel V10.4.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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 + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + + +#ifndef _MSC_VER /* Visual Studio doesn't support #warning. */ + #warning The name of this file has changed to stack_macros.h. Please update your code accordingly. This source file (which has the original name) will be removed in future released. +#endif + +#include "stack_macros.h" diff --git a/components/freertos/include/freertos/atomic.h b/components/freertos/include/freertos/atomic.h index df52a0f01f..a47b96723c 100644 --- a/components/freertos/include/freertos/atomic.h +++ b/components/freertos/include/freertos/atomic.h @@ -1,6 +1,6 @@ /* - * FreeRTOS Kernel V10.2.1 - * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V10.4.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * 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 @@ -19,19 +19,18 @@ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS * - * 1 tab == 4 spaces! */ /** * @file atomic.h * @brief FreeRTOS atomic operation support. * - * This file implements atomic by disabling interrupts globally. - * Implementation with architecture specific atomic instructions - * are to be provided under each compiler directory. + * This file implements atomic functions by disabling interrupts globally. + * Implementations with architecture specific atomic instructions can be + * provided under each compiler directory. */ #ifndef ATOMIC_H @@ -44,45 +43,50 @@ /* Standard includes. */ #include +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ -/* Port specific definitions -- entering/exiting critical section. +/* + * Port specific definitions -- entering/exiting critical section. * Refer template -- ./lib/FreeRTOS/portable/Compiler/Arch/portmacro.h * * Every call to ATOMIC_EXIT_CRITICAL() must be closely paired with * ATOMIC_ENTER_CRITICAL(). - * */ + * + */ #if defined( portSET_INTERRUPT_MASK_FROM_ISR ) - /* Nested interrupt scheme is supported in this port. */ - #define ATOMIC_ENTER_CRITICAL() \ - UBaseType_t uxCriticalSectionType = portSET_INTERRUPT_MASK_FROM_ISR() +/* Nested interrupt scheme is supported in this port. */ + #define ATOMIC_ENTER_CRITICAL() \ + UBaseType_t uxCriticalSectionType = portSET_INTERRUPT_MASK_FROM_ISR() - #define ATOMIC_EXIT_CRITICAL() \ - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxCriticalSectionType ) + #define ATOMIC_EXIT_CRITICAL() \ + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxCriticalSectionType ) #else - /* Nested interrupt scheme is NOT supported in this port. */ - #define ATOMIC_ENTER_CRITICAL() portENTER_CRITICAL() - #define ATOMIC_EXIT_CRITICAL() portEXIT_CRITICAL() +/* Nested interrupt scheme is NOT supported in this port. */ + #define ATOMIC_ENTER_CRITICAL() portENTER_CRITICAL() + #define ATOMIC_EXIT_CRITICAL() portEXIT_CRITICAL() #endif /* portSET_INTERRUPT_MASK_FROM_ISR() */ -/* Port specific definition -- "always inline". - * Inline is compiler specific, and may not always get inlined depending on your optimization level. - * Also, inline is considerred as performance optimization for atomic. - * Thus, if portFORCE_INLINE is not provided by portmacro.h, instead of resulting error, - * simply define it. +/* + * Port specific definition -- "always inline". + * Inline is compiler specific, and may not always get inlined depending on your + * optimization level. Also, inline is considered as performance optimization + * for atomic. Thus, if portFORCE_INLINE is not provided by portmacro.h, + * instead of resulting error, simply define it away. */ #ifndef portFORCE_INLINE #define portFORCE_INLINE #endif -#define ATOMIC_COMPARE_AND_SWAP_SUCCESS 0x1U /**< Compare and swap succeeded, swapped. */ -#define ATOMIC_COMPARE_AND_SWAP_FAILURE 0x0U /**< Compare and swap failed, did not swap. */ +#define ATOMIC_COMPARE_AND_SWAP_SUCCESS 0x1U /**< Compare and swap succeeded, swapped. */ +#define ATOMIC_COMPARE_AND_SWAP_FAILURE 0x0U /**< Compare and swap failed, did not swap. */ /*----------------------------- Swap && CAS ------------------------------*/ @@ -91,66 +95,67 @@ extern "C" { * * @brief Performs an atomic compare-and-swap operation on the specified values. * - * @param[in, out] pDestination Pointer to memory location from where value is + * @param[in, out] pulDestination Pointer to memory location from where value is * to be loaded and checked. * @param[in] ulExchange If condition meets, write this value to memory. * @param[in] ulComparand Swap condition. * * @return Unsigned integer of value 1 or 0. 1 for swapped, 0 for not swapped. * - * @note This function only swaps *pDestination with ulExchange, if previous - * *pDestination value equals ulComparand. + * @note This function only swaps *pulDestination with ulExchange, if previous + * *pulDestination value equals ulComparand. */ -static portFORCE_INLINE uint32_t Atomic_CompareAndSwap_u32( - uint32_t volatile * pDestination, - uint32_t ulExchange, - uint32_t ulComparand ) +static portFORCE_INLINE uint32_t Atomic_CompareAndSwap_u32( uint32_t volatile * pulDestination, + uint32_t ulExchange, + uint32_t ulComparand ) { - - uint32_t ulReturnValue = ATOMIC_COMPARE_AND_SWAP_FAILURE; + uint32_t ulReturnValue; ATOMIC_ENTER_CRITICAL(); - - if ( *pDestination == ulComparand ) { - *pDestination = ulExchange; - ulReturnValue = ATOMIC_COMPARE_AND_SWAP_SUCCESS; + if( *pulDestination == ulComparand ) + { + *pulDestination = ulExchange; + ulReturnValue = ATOMIC_COMPARE_AND_SWAP_SUCCESS; + } + else + { + ulReturnValue = ATOMIC_COMPARE_AND_SWAP_FAILURE; + } } - ATOMIC_EXIT_CRITICAL(); return ulReturnValue; - } +/*-----------------------------------------------------------*/ /** * Atomic swap (pointers) * - * @brief Atomically sets the address pointed to by *ppDestination to the value - * of *pExchange. + * @brief Atomically sets the address pointed to by *ppvDestination to the value + * of *pvExchange. * - * @param[in, out] ppDestination Pointer to memory location from where a pointer - * value is to be loaded and written back to. - * @param[in] pExchange Pointer value to be written to *ppDestination. + * @param[in, out] ppvDestination Pointer to memory location from where a pointer + * value is to be loaded and written back to. + * @param[in] pvExchange Pointer value to be written to *ppvDestination. * - * @return The initial value of *ppDestination. + * @return The initial value of *ppvDestination. */ -static portFORCE_INLINE void * Atomic_SwapPointers_p32( - void * volatile * ppDestination, - void * pExchange ) +static portFORCE_INLINE void * Atomic_SwapPointers_p32( void * volatile * ppvDestination, + void * pvExchange ) { void * pReturnValue; ATOMIC_ENTER_CRITICAL(); - - pReturnValue = *ppDestination; - - *ppDestination = pExchange; - + { + pReturnValue = *ppvDestination; + *ppvDestination = pvExchange; + } ATOMIC_EXIT_CRITICAL(); return pReturnValue; } +/*-----------------------------------------------------------*/ /** * Atomic compare-and-swap (pointers) @@ -158,30 +163,30 @@ static portFORCE_INLINE void * Atomic_SwapPointers_p32( * @brief Performs an atomic compare-and-swap operation on the specified pointer * values. * - * @param[in, out] ppDestination Pointer to memory location from where a pointer - * value is to be loaded and checked. - * @param[in] pExchange If condition meets, write this value to memory. - * @param[in] pComparand Swap condition. + * @param[in, out] ppvDestination Pointer to memory location from where a pointer + * value is to be loaded and checked. + * @param[in] pvExchange If condition meets, write this value to memory. + * @param[in] pvComparand Swap condition. * * @return Unsigned integer of value 1 or 0. 1 for swapped, 0 for not swapped. * - * @note This function only swaps *ppDestination with pExchange, if previous - * *ppDestination value equals pComparand. + * @note This function only swaps *ppvDestination with pvExchange, if previous + * *ppvDestination value equals pvComparand. */ -static portFORCE_INLINE uint32_t Atomic_CompareAndSwapPointers_p32( - void * volatile * ppDestination, - void * pExchange, void * pComparand ) +static portFORCE_INLINE uint32_t Atomic_CompareAndSwapPointers_p32( void * volatile * ppvDestination, + void * pvExchange, + void * pvComparand ) { uint32_t ulReturnValue = ATOMIC_COMPARE_AND_SWAP_FAILURE; ATOMIC_ENTER_CRITICAL(); - - if ( *ppDestination == pComparand ) { - *ppDestination = pExchange; - ulReturnValue = ATOMIC_COMPARE_AND_SWAP_SUCCESS; + if( *ppvDestination == pvComparand ) + { + *ppvDestination = pvExchange; + ulReturnValue = ATOMIC_COMPARE_AND_SWAP_SUCCESS; + } } - ATOMIC_EXIT_CRITICAL(); return ulReturnValue; @@ -195,28 +200,27 @@ static portFORCE_INLINE uint32_t Atomic_CompareAndSwapPointers_p32( * * @brief Atomically adds count to the value of the specified pointer points to. * - * @param[in,out] pAddend Pointer to memory location from where value is to be + * @param[in,out] pulAddend Pointer to memory location from where value is to be * loaded and written back to. - * @param[in] ulCount Value to be added to *pAddend. + * @param[in] ulCount Value to be added to *pulAddend. * - * @return previous *pAddend value. + * @return previous *pulAddend value. */ -static portFORCE_INLINE uint32_t Atomic_Add_u32( - uint32_t volatile * pAddend, - uint32_t ulCount ) +static portFORCE_INLINE uint32_t Atomic_Add_u32( uint32_t volatile * pulAddend, + uint32_t ulCount ) { uint32_t ulCurrent; ATOMIC_ENTER_CRITICAL(); - - ulCurrent = *pAddend; - - *pAddend += ulCount; - + { + ulCurrent = *pulAddend; + *pulAddend += ulCount; + } ATOMIC_EXIT_CRITICAL(); return ulCurrent; } +/*-----------------------------------------------------------*/ /** * Atomic subtract @@ -224,74 +228,72 @@ static portFORCE_INLINE uint32_t Atomic_Add_u32( * @brief Atomically subtracts count from the value of the specified pointer * pointers to. * - * @param[in,out] pAddend Pointer to memory location from where value is to be + * @param[in,out] pulAddend Pointer to memory location from where value is to be * loaded and written back to. - * @param[in] ulCount Value to be subtract from *pAddend. + * @param[in] ulCount Value to be subtract from *pulAddend. * - * @return previous *pAddend value. + * @return previous *pulAddend value. */ -static portFORCE_INLINE uint32_t Atomic_Subtract_u32( - uint32_t volatile * pAddend, - uint32_t ulCount ) +static portFORCE_INLINE uint32_t Atomic_Subtract_u32( uint32_t volatile * pulAddend, + uint32_t ulCount ) { uint32_t ulCurrent; ATOMIC_ENTER_CRITICAL(); - - ulCurrent = *pAddend; - - *pAddend -= ulCount; - + { + ulCurrent = *pulAddend; + *pulAddend -= ulCount; + } ATOMIC_EXIT_CRITICAL(); return ulCurrent; } +/*-----------------------------------------------------------*/ /** * Atomic increment * * @brief Atomically increments the value of the specified pointer points to. * - * @param[in,out] pAddend Pointer to memory location from where value is to be + * @param[in,out] pulAddend Pointer to memory location from where value is to be * loaded and written back to. * - * @return *pAddend value before increment. + * @return *pulAddend value before increment. */ -static portFORCE_INLINE uint32_t Atomic_Increment_u32( uint32_t volatile * pAddend ) +static portFORCE_INLINE uint32_t Atomic_Increment_u32( uint32_t volatile * pulAddend ) { uint32_t ulCurrent; ATOMIC_ENTER_CRITICAL(); - - ulCurrent = *pAddend; - - *pAddend += 1; - + { + ulCurrent = *pulAddend; + *pulAddend += 1; + } ATOMIC_EXIT_CRITICAL(); return ulCurrent; } +/*-----------------------------------------------------------*/ /** * Atomic decrement * * @brief Atomically decrements the value of the specified pointer points to * - * @param[in,out] pAddend Pointer to memory location from where value is to be + * @param[in,out] pulAddend Pointer to memory location from where value is to be * loaded and written back to. * - * @return *pAddend value before decrement. + * @return *pulAddend value before decrement. */ -static portFORCE_INLINE uint32_t Atomic_Decrement_u32( uint32_t volatile * pAddend ) +static portFORCE_INLINE uint32_t Atomic_Decrement_u32( uint32_t volatile * pulAddend ) { uint32_t ulCurrent; ATOMIC_ENTER_CRITICAL(); - - ulCurrent = *pAddend; - - *pAddend -= 1; - + { + ulCurrent = *pulAddend; + *pulAddend -= 1; + } ATOMIC_EXIT_CRITICAL(); return ulCurrent; @@ -304,115 +306,112 @@ static portFORCE_INLINE uint32_t Atomic_Decrement_u32( uint32_t volatile * pAdde * * @brief Performs an atomic OR operation on the specified values. * - * @param [in, out] pDestination Pointer to memory location from where value is + * @param [in, out] pulDestination Pointer to memory location from where value is * to be loaded and written back to. - * @param [in] ulValue Value to be ORed with *pDestination. + * @param [in] ulValue Value to be ORed with *pulDestination. * - * @return The original value of *pDestination. + * @return The original value of *pulDestination. */ -static portFORCE_INLINE uint32_t Atomic_OR_u32( - uint32_t volatile * pDestination, - uint32_t ulValue ) +static portFORCE_INLINE uint32_t Atomic_OR_u32( uint32_t volatile * pulDestination, + uint32_t ulValue ) { uint32_t ulCurrent; ATOMIC_ENTER_CRITICAL(); - - ulCurrent = *pDestination; - - *pDestination |= ulValue; - + { + ulCurrent = *pulDestination; + *pulDestination |= ulValue; + } ATOMIC_EXIT_CRITICAL(); return ulCurrent; } +/*-----------------------------------------------------------*/ /** * Atomic AND * * @brief Performs an atomic AND operation on the specified values. * - * @param [in, out] pDestination Pointer to memory location from where value is + * @param [in, out] pulDestination Pointer to memory location from where value is * to be loaded and written back to. - * @param [in] ulValue Value to be ANDed with *pDestination. + * @param [in] ulValue Value to be ANDed with *pulDestination. * - * @return The original value of *pDestination. + * @return The original value of *pulDestination. */ -static portFORCE_INLINE uint32_t Atomic_AND_u32( - uint32_t volatile * pDestination, - uint32_t ulValue ) +static portFORCE_INLINE uint32_t Atomic_AND_u32( uint32_t volatile * pulDestination, + uint32_t ulValue ) { uint32_t ulCurrent; ATOMIC_ENTER_CRITICAL(); - - ulCurrent = *pDestination; - - *pDestination &= ulValue; - + { + ulCurrent = *pulDestination; + *pulDestination &= ulValue; + } ATOMIC_EXIT_CRITICAL(); return ulCurrent; } +/*-----------------------------------------------------------*/ /** * Atomic NAND * * @brief Performs an atomic NAND operation on the specified values. * - * @param [in, out] pDestination Pointer to memory location from where value is + * @param [in, out] pulDestination Pointer to memory location from where value is * to be loaded and written back to. - * @param [in] ulValue Value to be NANDed with *pDestination. + * @param [in] ulValue Value to be NANDed with *pulDestination. * - * @return The original value of *pDestination. + * @return The original value of *pulDestination. */ -static portFORCE_INLINE uint32_t Atomic_NAND_u32( - uint32_t volatile * pDestination, - uint32_t ulValue ) +static portFORCE_INLINE uint32_t Atomic_NAND_u32( uint32_t volatile * pulDestination, + uint32_t ulValue ) { uint32_t ulCurrent; ATOMIC_ENTER_CRITICAL(); - - ulCurrent = *pDestination; - - *pDestination = ~(ulCurrent & ulValue); - + { + ulCurrent = *pulDestination; + *pulDestination = ~( ulCurrent & ulValue ); + } ATOMIC_EXIT_CRITICAL(); return ulCurrent; } +/*-----------------------------------------------------------*/ /** * Atomic XOR * * @brief Performs an atomic XOR operation on the specified values. * - * @param [in, out] pDestination Pointer to memory location from where value is + * @param [in, out] pulDestination Pointer to memory location from where value is * to be loaded and written back to. - * @param [in] ulValue Value to be XORed with *pDestination. + * @param [in] ulValue Value to be XORed with *pulDestination. * - * @return The original value of *pDestination. + * @return The original value of *pulDestination. */ -static portFORCE_INLINE uint32_t Atomic_XOR_u32( - uint32_t volatile * pDestination, - uint32_t ulValue ) +static portFORCE_INLINE uint32_t Atomic_XOR_u32( uint32_t volatile * pulDestination, + uint32_t ulValue ) { uint32_t ulCurrent; ATOMIC_ENTER_CRITICAL(); - - ulCurrent = *pDestination; - - *pDestination ^= ulValue; - + { + ulCurrent = *pulDestination; + *pulDestination ^= ulValue; + } ATOMIC_EXIT_CRITICAL(); return ulCurrent; } +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* ATOMIC_H */ diff --git a/components/freertos/include/freertos/croutine.h b/components/freertos/include/freertos/croutine.h index 8b3b41b905..99322d219f 100644 --- a/components/freertos/include/freertos/croutine.h +++ b/components/freertos/include/freertos/croutine.h @@ -1,6 +1,6 @@ /* - * FreeRTOS Kernel V10.2.1 - * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V10.4.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * 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 @@ -19,51 +19,56 @@ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS * - * 1 tab == 4 spaces! */ #ifndef CO_ROUTINE_H #define CO_ROUTINE_H #ifndef INC_FREERTOS_H - #error "include FreeRTOS.h must appear in source files before include croutine.h" + #error "include FreeRTOS.h must appear in source files before include croutine.h" #endif #include "list.h" +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /* Used to hide the implementation of the co-routine control block. The -control block structure however has to be included in the header due to -the macro implementation of the co-routine functionality. */ + * control block structure however has to be included in the header due to + * the macro implementation of the co-routine functionality. */ typedef void * CoRoutineHandle_t; /* Defines the prototype to which co-routine functions must conform. */ -typedef void (*crCOROUTINE_CODE)( CoRoutineHandle_t, UBaseType_t ); +typedef void (* crCOROUTINE_CODE)( CoRoutineHandle_t, + UBaseType_t ); typedef struct corCoRoutineControlBlock { - crCOROUTINE_CODE pxCoRoutineFunction; - ListItem_t xGenericListItem; /*< List item used to place the CRCB in ready and blocked queues. */ - ListItem_t xEventListItem; /*< List item used to place the CRCB in event lists. */ - UBaseType_t uxPriority; /*< The priority of the co-routine in relation to other co-routines. */ - UBaseType_t uxIndex; /*< Used to distinguish between co-routines when multiple co-routines use the same co-routine function. */ - uint16_t uxState; /*< Used internally by the co-routine implementation. */ -} CRCB_t; /* Co-routine control block. Note must be identical in size down to uxPriority with TCB_t. */ + crCOROUTINE_CODE pxCoRoutineFunction; + ListItem_t xGenericListItem; /*< List item used to place the CRCB in ready and blocked queues. */ + ListItem_t xEventListItem; /*< List item used to place the CRCB in event lists. */ + UBaseType_t uxPriority; /*< The priority of the co-routine in relation to other co-routines. */ + UBaseType_t uxIndex; /*< Used to distinguish between co-routines when multiple co-routines use the same co-routine function. */ + uint16_t uxState; /*< Used internally by the co-routine implementation. */ +} CRCB_t; /* Co-routine control block. Note must be identical in size down to uxPriority with TCB_t. */ /** + * @cond * croutine. h - *
- BaseType_t xCoRoutineCreate(
-                                 crCOROUTINE_CODE pxCoRoutineCode,
-                                 UBaseType_t uxPriority,
-                                 UBaseType_t uxIndex
-                               );
+ * @code{c} + * BaseType_t xCoRoutineCreate( + * crCOROUTINE_CODE pxCoRoutineCode, + * UBaseType_t uxPriority, + * UBaseType_t uxIndex + * ); + * @endcode + * @endcond * * Create a new co-routine and add it to the list of co-routines that are * ready to run. @@ -83,59 +88,65 @@ typedef struct corCoRoutineControlBlock * list, otherwise an error code defined with ProjDefs.h. * * Example usage: -
- // Co-routine to be created.
- void vFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
- {
- // Variables in co-routines must be declared static if they must maintain value across a blocking call.
- // This may not be necessary for const variables.
- static const char cLedToFlash[ 2 ] = { 5, 6 };
- static const TickType_t uxFlashRates[ 2 ] = { 200, 400 };
-
-     // Must start every co-routine with a call to crSTART();
-     crSTART( xHandle );
-
-     for( ;; )
-     {
-         // This co-routine just delays for a fixed period, then toggles
-         // an LED.  Two co-routines are created using this function, so
-         // the uxIndex parameter is used to tell the co-routine which
-         // LED to flash and how int32_t to delay.  This assumes xQueue has
-         // already been created.
-         vParTestToggleLED( cLedToFlash[ uxIndex ] );
-         crDELAY( xHandle, uxFlashRates[ uxIndex ] );
-     }
-
-     // Must end every co-routine with a call to crEND();
-     crEND();
- }
-
- // Function that creates two co-routines.
- void vOtherFunction( void )
- {
- uint8_t ucParameterToPass;
- TaskHandle_t xHandle;
-
-     // Create two co-routines at priority 0.  The first is given index 0
-     // so (from the code above) toggles LED 5 every 200 ticks.  The second
-     // is given index 1 so toggles LED 6 every 400 ticks.
-     for( uxIndex = 0; uxIndex < 2; uxIndex++ )
-     {
-         xCoRoutineCreate( vFlashCoRoutine, 0, uxIndex );
-     }
- }
-   
+ * @code{c} + * // Co-routine to be created. + * void vFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex ) + * { + * // Variables in co-routines must be declared static if they must maintain value across a blocking call. + * // This may not be necessary for const variables. + * static const char cLedToFlash[ 2 ] = { 5, 6 }; + * static const TickType_t uxFlashRates[ 2 ] = { 200, 400 }; + * + * // Must start every co-routine with a call to crSTART(); + * crSTART( xHandle ); + * + * for( ;; ) + * { + * // This co-routine just delays for a fixed period, then toggles + * // an LED. Two co-routines are created using this function, so + * // the uxIndex parameter is used to tell the co-routine which + * // LED to flash and how int32_t to delay. This assumes xQueue has + * // already been created. + * vParTestToggleLED( cLedToFlash[ uxIndex ] ); + * crDELAY( xHandle, uxFlashRates[ uxIndex ] ); + * } + * + * // Must end every co-routine with a call to crEND(); + * crEND(); + * } + * + * // Function that creates two co-routines. + * void vOtherFunction( void ) + * { + * uint8_t ucParameterToPass; + * TaskHandle_t xHandle; + * + * // Create two co-routines at priority 0. The first is given index 0 + * // so (from the code above) toggles LED 5 every 200 ticks. The second + * // is given index 1 so toggles LED 6 every 400 ticks. + * for( uxIndex = 0; uxIndex < 2; uxIndex++ ) + * { + * xCoRoutineCreate( vFlashCoRoutine, 0, uxIndex ); + * } + * } + * @endcode + * @cond * \defgroup xCoRoutineCreate xCoRoutineCreate + * @endcond * \ingroup Tasks */ -BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPriority, UBaseType_t uxIndex ); +BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, + UBaseType_t uxPriority, + UBaseType_t uxIndex ); /** + * @cond * croutine. h - *
- void vCoRoutineSchedule( void );
- * + * @code{c} + * void vCoRoutineSchedule( void ); + * @endcode + * @endcond * Run a co-routine. * * vCoRoutineSchedule() executes the highest priority co-routine that is able @@ -148,103 +159,127 @@ BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPri * hook). * * Example usage: -
- // This idle task hook will schedule a co-routine each time it is called.
- // The rest of the idle task will execute between co-routine calls.
- void vApplicationIdleHook( void )
- {
-	vCoRoutineSchedule();
- }
-
- // Alternatively, if you do not require any other part of the idle task to
- // execute, the idle task hook can call vCoRoutineScheduler() within an
- // infinite loop.
- void vApplicationIdleHook( void )
- {
-    for( ;; )
-    {
-        vCoRoutineSchedule();
-    }
- }
- 
+ * @code{c} + * // This idle task hook will schedule a co-routine each time it is called. + * // The rest of the idle task will execute between co-routine calls. + * void vApplicationIdleHook( void ) + * { + * vCoRoutineSchedule(); + * } + * + * // Alternatively, if you do not require any other part of the idle task to + * // execute, the idle task hook can call vCoRoutineScheduler() within an + * // infinite loop. + * void vApplicationIdleHook( void ) + * { + * for( ;; ) + * { + * vCoRoutineSchedule(); + * } + * } + * @endcode + * @endcode + * @cond * \defgroup vCoRoutineSchedule vCoRoutineSchedule + * @endcond * \ingroup Tasks */ void vCoRoutineSchedule( void ); /** + * @cond * croutine. h - *
- crSTART( CoRoutineHandle_t xHandle );
+ * @code{c} + * crSTART( CoRoutineHandle_t xHandle ); + * @endcode + * @endcond * * This macro MUST always be called at the start of a co-routine function. * * Example usage: -
- // Co-routine to be created.
- void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
- {
- // Variables in co-routines must be declared static if they must maintain value across a blocking call.
- static int32_t ulAVariable;
-
-     // Must start every co-routine with a call to crSTART();
-     crSTART( xHandle );
-
-     for( ;; )
-     {
-          // Co-routine functionality goes here.
-     }
-
-     // Must end every co-routine with a call to crEND();
-     crEND();
- }
+ * @code{c} + * // Co-routine to be created. + * void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex ) + * { + * // Variables in co-routines must be declared static if they must maintain value across a blocking call. + * static int32_t ulAVariable; + * + * // Must start every co-routine with a call to crSTART(); + * crSTART( xHandle ); + * + * for( ;; ) + * { + * // Co-routine functionality goes here. + * } + * + * // Must end every co-routine with a call to crEND(); + * crEND(); + * } + * @endcode + * @cond * \defgroup crSTART crSTART + * @endcond * \ingroup Tasks */ -#define crSTART( pxCRCB ) switch( ( ( CRCB_t * )( pxCRCB ) )->uxState ) { case 0: +#define crSTART( pxCRCB ) \ + switch( ( ( CRCB_t * ) ( pxCRCB ) )->uxState ) { \ + case 0: /** + * @cond * croutine. h - *
- crEND();
+ * @code{c} + * crEND(); + * @endcode + * @endcond * * This macro MUST always be called at the end of a co-routine function. * * Example usage: -
- // Co-routine to be created.
- void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
- {
- // Variables in co-routines must be declared static if they must maintain value across a blocking call.
- static int32_t ulAVariable;
-
-     // Must start every co-routine with a call to crSTART();
-     crSTART( xHandle );
-
-     for( ;; )
-     {
-          // Co-routine functionality goes here.
-     }
-
-     // Must end every co-routine with a call to crEND();
-     crEND();
- }
+ * @code{c} + * // Co-routine to be created. + * void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex ) + * { + * // Variables in co-routines must be declared static if they must maintain value across a blocking call. + * static int32_t ulAVariable; + * + * // Must start every co-routine with a call to crSTART(); + * crSTART( xHandle ); + * + * for( ;; ) + * { + * // Co-routine functionality goes here. + * } + * + * // Must end every co-routine with a call to crEND(); + * crEND(); + * } + * @endcode + * @cond * \defgroup crSTART crSTART + * @endcond * \ingroup Tasks */ -#define crEND() } +#define crEND() } /* * These macros are intended for internal use by the co-routine implementation * only. The macros should not be used directly by application writers. */ -#define crSET_STATE0( xHandle ) ( ( CRCB_t * )( xHandle ) )->uxState = (__LINE__ * 2); return; case (__LINE__ * 2): -#define crSET_STATE1( xHandle ) ( ( CRCB_t * )( xHandle ) )->uxState = ((__LINE__ * 2)+1); return; case ((__LINE__ * 2)+1): +#define crSET_STATE0( xHandle ) \ + ( ( CRCB_t * ) ( xHandle ) )->uxState = ( __LINE__ * 2 ); return; \ + case ( __LINE__ * 2 ): +#define crSET_STATE1( xHandle ) \ + ( ( CRCB_t * ) ( xHandle ) )->uxState = ( ( __LINE__ * 2 ) + 1 ); return; \ + case ( ( __LINE__ * 2 ) + 1 ): /** + * @cond * croutine. h - *
- crDELAY( CoRoutineHandle_t xHandle, TickType_t xTicksToDelay );
+ * @code{c} + * crDELAY( CoRoutineHandle_t xHandle, TickType_t xTicksToDelay ); + * @endcode + * @endcond * * Delay a co-routine for a fixed period of time. * @@ -261,48 +296,54 @@ void vCoRoutineSchedule( void ); * can be used to convert ticks to milliseconds. * * Example usage: -
- // Co-routine to be created.
- void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
- {
- // Variables in co-routines must be declared static if they must maintain value across a blocking call.
- // This may not be necessary for const variables.
- // We are to delay for 200ms.
- static const xTickType xDelayTime = 200 / portTICK_PERIOD_MS;
-
-     // Must start every co-routine with a call to crSTART();
-     crSTART( xHandle );
-
-     for( ;; )
-     {
-        // Delay for 200ms.
-        crDELAY( xHandle, xDelayTime );
-
-        // Do something here.
-     }
-
-     // Must end every co-routine with a call to crEND();
-     crEND();
- }
+ * @code{c} + * // Co-routine to be created. + * void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex ) + * { + * // Variables in co-routines must be declared static if they must maintain value across a blocking call. + * // This may not be necessary for const variables. + * // We are to delay for 200ms. + * static const xTickType xDelayTime = 200 / portTICK_PERIOD_MS; + * + * // Must start every co-routine with a call to crSTART(); + * crSTART( xHandle ); + * + * for( ;; ) + * { + * // Delay for 200ms. + * crDELAY( xHandle, xDelayTime ); + * + * // Do something here. + * } + * + * // Must end every co-routine with a call to crEND(); + * crEND(); + * } + * @endcode + * @cond * \defgroup crDELAY crDELAY + * @endcond * \ingroup Tasks */ -#define crDELAY( xHandle, xTicksToDelay ) \ - if( ( xTicksToDelay ) > 0 ) \ - { \ - vCoRoutineAddToDelayedList( ( xTicksToDelay ), NULL ); \ - } \ - crSET_STATE0( ( xHandle ) ); +#define crDELAY( xHandle, xTicksToDelay ) \ + if( ( xTicksToDelay ) > 0 ) \ + { \ + vCoRoutineAddToDelayedList( ( xTicksToDelay ), NULL ); \ + } \ + crSET_STATE0( ( xHandle ) ); /** - *
- crQUEUE_SEND(
-                  CoRoutineHandle_t xHandle,
-                  QueueHandle_t pxQueue,
-                  void *pvItemToQueue,
-                  TickType_t xTicksToWait,
-                  BaseType_t *pxResult
-             )
+ * @cond + * @code{c} + * crQUEUE_SEND( + * CoRoutineHandle_t xHandle, + * QueueHandle_t pxQueue, + * void *pvItemToQueue, + * TickType_t xTicksToWait, + * BaseType_t *pxResult + * ) + * @endcode + * @endcond * * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks. @@ -342,66 +383,72 @@ void vCoRoutineSchedule( void ); * error defined within ProjDefs.h. * * Example usage: -
- // Co-routine function that blocks for a fixed period then posts a number onto
- // a queue.
- static void prvCoRoutineFlashTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
- {
- // Variables in co-routines must be declared static if they must maintain value across a blocking call.
- static BaseType_t xNumberToPost = 0;
- static BaseType_t xResult;
-
-    // Co-routines must begin with a call to crSTART().
-    crSTART( xHandle );
-
-    for( ;; )
-    {
-        // This assumes the queue has already been created.
-        crQUEUE_SEND( xHandle, xCoRoutineQueue, &xNumberToPost, NO_DELAY, &xResult );
-
-        if( xResult != pdPASS )
-        {
-            // The message was not posted!
-        }
-
-        // Increment the number to be posted onto the queue.
-        xNumberToPost++;
-
-        // Delay for 100 ticks.
-        crDELAY( xHandle, 100 );
-    }
-
-    // Co-routines must end with a call to crEND().
-    crEND();
- }
+ * @code{c} + * // Co-routine function that blocks for a fixed period then posts a number onto + * // a queue. + * static void prvCoRoutineFlashTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex ) + * { + * // Variables in co-routines must be declared static if they must maintain value across a blocking call. + * static BaseType_t xNumberToPost = 0; + * static BaseType_t xResult; + * + * // Co-routines must begin with a call to crSTART(). + * crSTART( xHandle ); + * + * for( ;; ) + * { + * // This assumes the queue has already been created. + * crQUEUE_SEND( xHandle, xCoRoutineQueue, &xNumberToPost, NO_DELAY, &xResult ); + * + * if( xResult != pdPASS ) + * { + * // The message was not posted! + * } + * + * // Increment the number to be posted onto the queue. + * xNumberToPost++; + * + * // Delay for 100 ticks. + * crDELAY( xHandle, 100 ); + * } + * + * // Co-routines must end with a call to crEND(). + * crEND(); + * } + * @endcode + * @cond * \defgroup crQUEUE_SEND crQUEUE_SEND + * @endcond * \ingroup Tasks */ -#define crQUEUE_SEND( xHandle, pxQueue, pvItemToQueue, xTicksToWait, pxResult ) \ -{ \ - *( pxResult ) = xQueueCRSend( ( pxQueue) , ( pvItemToQueue) , ( xTicksToWait ) ); \ - if( *( pxResult ) == errQUEUE_BLOCKED ) \ - { \ - crSET_STATE0( ( xHandle ) ); \ - *pxResult = xQueueCRSend( ( pxQueue ), ( pvItemToQueue ), 0 ); \ - } \ - if( *pxResult == errQUEUE_YIELD ) \ - { \ - crSET_STATE1( ( xHandle ) ); \ - *pxResult = pdPASS; \ - } \ -} +#define crQUEUE_SEND( xHandle, pxQueue, pvItemToQueue, xTicksToWait, pxResult ) \ + { \ + *( pxResult ) = xQueueCRSend( ( pxQueue ), ( pvItemToQueue ), ( xTicksToWait ) ); \ + if( *( pxResult ) == errQUEUE_BLOCKED ) \ + { \ + crSET_STATE0( ( xHandle ) ); \ + *pxResult = xQueueCRSend( ( pxQueue ), ( pvItemToQueue ), 0 ); \ + } \ + if( *pxResult == errQUEUE_YIELD ) \ + { \ + crSET_STATE1( ( xHandle ) ); \ + *pxResult = pdPASS; \ + } \ + } /** + * @cond * croutine. h - *
-  crQUEUE_RECEIVE(
-                     CoRoutineHandle_t xHandle,
-                     QueueHandle_t pxQueue,
-                     void *pvBuffer,
-                     TickType_t xTicksToWait,
-                     BaseType_t *pxResult
-                 )
+ * @code{c} + * crQUEUE_RECEIVE( + * CoRoutineHandle_t xHandle, + * QueueHandle_t pxQueue, + * void *pvBuffer, + * TickType_t xTicksToWait, + * BaseType_t *pxResult + * ) + * @endcode + * @endcond * * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks. @@ -440,58 +487,64 @@ void vCoRoutineSchedule( void ); * an error code as defined within ProjDefs.h. * * Example usage: -
- // A co-routine receives the number of an LED to flash from a queue.  It
- // blocks on the queue until the number is received.
- static void prvCoRoutineFlashWorkTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
- {
- // Variables in co-routines must be declared static if they must maintain value across a blocking call.
- static BaseType_t xResult;
- static UBaseType_t uxLEDToFlash;
-
-    // All co-routines must start with a call to crSTART().
-    crSTART( xHandle );
-
-    for( ;; )
-    {
-        // Wait for data to become available on the queue.
-        crQUEUE_RECEIVE( xHandle, xCoRoutineQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
-
-        if( xResult == pdPASS )
-        {
-            // We received the LED to flash - flash it!
-            vParTestToggleLED( uxLEDToFlash );
-        }
-    }
-
-    crEND();
- }
+ * @code{c} + * // A co-routine receives the number of an LED to flash from a queue. It + * // blocks on the queue until the number is received. + * static void prvCoRoutineFlashWorkTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex ) + * { + * // Variables in co-routines must be declared static if they must maintain value across a blocking call. + * static BaseType_t xResult; + * static UBaseType_t uxLEDToFlash; + * + * // All co-routines must start with a call to crSTART(). + * crSTART( xHandle ); + * + * for( ;; ) + * { + * // Wait for data to become available on the queue. + * crQUEUE_RECEIVE( xHandle, xCoRoutineQueue, &uxLEDToFlash, portMAX_DELAY, &xResult ); + * + * if( xResult == pdPASS ) + * { + * // We received the LED to flash - flash it! + * vParTestToggleLED( uxLEDToFlash ); + * } + * } + * + * crEND(); + * } + * @endcode + * @cond * \defgroup crQUEUE_RECEIVE crQUEUE_RECEIVE + * @endcond * \ingroup Tasks */ -#define crQUEUE_RECEIVE( xHandle, pxQueue, pvBuffer, xTicksToWait, pxResult ) \ -{ \ - *( pxResult ) = xQueueCRReceive( ( pxQueue) , ( pvBuffer ), ( xTicksToWait ) ); \ - if( *( pxResult ) == errQUEUE_BLOCKED ) \ - { \ - crSET_STATE0( ( xHandle ) ); \ - *( pxResult ) = xQueueCRReceive( ( pxQueue) , ( pvBuffer ), 0 ); \ - } \ - if( *( pxResult ) == errQUEUE_YIELD ) \ - { \ - crSET_STATE1( ( xHandle ) ); \ - *( pxResult ) = pdPASS; \ - } \ -} +#define crQUEUE_RECEIVE( xHandle, pxQueue, pvBuffer, xTicksToWait, pxResult ) \ + { \ + *( pxResult ) = xQueueCRReceive( ( pxQueue ), ( pvBuffer ), ( xTicksToWait ) ); \ + if( *( pxResult ) == errQUEUE_BLOCKED ) \ + { \ + crSET_STATE0( ( xHandle ) ); \ + *( pxResult ) = xQueueCRReceive( ( pxQueue ), ( pvBuffer ), 0 ); \ + } \ + if( *( pxResult ) == errQUEUE_YIELD ) \ + { \ + crSET_STATE1( ( xHandle ) ); \ + *( pxResult ) = pdPASS; \ + } \ + } /** + * @cond * croutine. h - *
-  crQUEUE_SEND_FROM_ISR(
-                            QueueHandle_t pxQueue,
-                            void *pvItemToQueue,
-                            BaseType_t xCoRoutinePreviouslyWoken
-                       )
+ * @code{c} + * crQUEUE_SEND_FROM_ISR( + * QueueHandle_t pxQueue, + * void *pvItemToQueue, + * BaseType_t xCoRoutinePreviouslyWoken + * ) + * @endcode + * @endcond * * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR() @@ -526,69 +579,76 @@ void vCoRoutineSchedule( void ); * the ISR. * * Example usage: -
- // A co-routine that blocks on a queue waiting for characters to be received.
- static void vReceivingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
- {
- char cRxedChar;
- BaseType_t xResult;
-
-     // All co-routines must start with a call to crSTART().
-     crSTART( xHandle );
-
-     for( ;; )
-     {
-         // Wait for data to become available on the queue.  This assumes the
-         // queue xCommsRxQueue has already been created!
-         crQUEUE_RECEIVE( xHandle, xCommsRxQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
-
-         // Was a character received?
-         if( xResult == pdPASS )
-         {
-             // Process the character here.
-         }
-     }
-
-     // All co-routines must end with a call to crEND().
-     crEND();
- }
-
- // An ISR that uses a queue to send characters received on a serial port to
- // a co-routine.
- void vUART_ISR( void )
- {
- char cRxedChar;
- BaseType_t xCRWokenByPost = pdFALSE;
-
-     // We loop around reading characters until there are none left in the UART.
-     while( UART_RX_REG_NOT_EMPTY() )
-     {
-         // Obtain the character from the UART.
-         cRxedChar = UART_RX_REG;
-
-         // Post the character onto a queue.  xCRWokenByPost will be pdFALSE
-         // the first time around the loop.  If the post causes a co-routine
-         // to be woken (unblocked) then xCRWokenByPost will be set to pdTRUE.
-         // In this manner we can ensure that if more than one co-routine is
-         // blocked on the queue only one is woken by this ISR no matter how
-         // many characters are posted to the queue.
-         xCRWokenByPost = crQUEUE_SEND_FROM_ISR( xCommsRxQueue, &cRxedChar, xCRWokenByPost );
-     }
- }
+ * @code{c} + * // A co-routine that blocks on a queue waiting for characters to be received. + * static void vReceivingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex ) + * { + * char cRxedChar; + * BaseType_t xResult; + * + * // All co-routines must start with a call to crSTART(). + * crSTART( xHandle ); + * + * for( ;; ) + * { + * // Wait for data to become available on the queue. This assumes the + * // queue xCommsRxQueue has already been created! + * crQUEUE_RECEIVE( xHandle, xCommsRxQueue, &uxLEDToFlash, portMAX_DELAY, &xResult ); + * + * // Was a character received? + * if( xResult == pdPASS ) + * { + * // Process the character here. + * } + * } + * + * // All co-routines must end with a call to crEND(). + * crEND(); + * } + * + * // An ISR that uses a queue to send characters received on a serial port to + * // a co-routine. + * void vUART_ISR( void ) + * { + * char cRxedChar; + * BaseType_t xCRWokenByPost = pdFALSE; + * + * // We loop around reading characters until there are none left in the UART. + * while( UART_RX_REG_NOT_EMPTY() ) + * { + * // Obtain the character from the UART. + * cRxedChar = UART_RX_REG; + * + * // Post the character onto a queue. xCRWokenByPost will be pdFALSE + * // the first time around the loop. If the post causes a co-routine + * // to be woken (unblocked) then xCRWokenByPost will be set to pdTRUE. + * // In this manner we can ensure that if more than one co-routine is + * // blocked on the queue only one is woken by this ISR no matter how + * // many characters are posted to the queue. + * xCRWokenByPost = crQUEUE_SEND_FROM_ISR( xCommsRxQueue, &cRxedChar, xCRWokenByPost ); + * } + * } + * @endcode + * @cond * \defgroup crQUEUE_SEND_FROM_ISR crQUEUE_SEND_FROM_ISR + * @endcond * \ingroup Tasks */ -#define crQUEUE_SEND_FROM_ISR( pxQueue, pvItemToQueue, xCoRoutinePreviouslyWoken ) xQueueCRSendFromISR( ( pxQueue ), ( pvItemToQueue ), ( xCoRoutinePreviouslyWoken ) ) +#define crQUEUE_SEND_FROM_ISR( pxQueue, pvItemToQueue, xCoRoutinePreviouslyWoken ) \ + xQueueCRSendFromISR( ( pxQueue ), ( pvItemToQueue ), ( xCoRoutinePreviouslyWoken ) ) /** + * @cond * croutine. h - *
-  crQUEUE_SEND_FROM_ISR(
-                            QueueHandle_t pxQueue,
-                            void *pvBuffer,
-                            BaseType_t * pxCoRoutineWoken
-                       )
+ * @code{c} + * crQUEUE_SEND_FROM_ISR( + * QueueHandle_t pxQueue, + * void *pvBuffer, + * BaseType_t * pxCoRoutineWoken + * ) + * @endcode + * @endcond * * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR() @@ -623,75 +683,79 @@ void vCoRoutineSchedule( void ); * pdFALSE. * * Example usage: -
- // A co-routine that posts a character to a queue then blocks for a fixed
- // period.  The character is incremented each time.
- static void vSendingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
- {
- // cChar holds its value while this co-routine is blocked and must therefore
- // be declared static.
- static char cCharToTx = 'a';
- BaseType_t xResult;
-
-     // All co-routines must start with a call to crSTART().
-     crSTART( xHandle );
-
-     for( ;; )
-     {
-         // Send the next character to the queue.
-         crQUEUE_SEND( xHandle, xCoRoutineQueue, &cCharToTx, NO_DELAY, &xResult );
-
-         if( xResult == pdPASS )
-         {
-             // The character was successfully posted to the queue.
-         }
-		 else
-		 {
-			// Could not post the character to the queue.
-		 }
-
-         // Enable the UART Tx interrupt to cause an interrupt in this
-		 // hypothetical UART.  The interrupt will obtain the character
-		 // from the queue and send it.
-		 ENABLE_RX_INTERRUPT();
-
-		 // Increment to the next character then block for a fixed period.
-		 // cCharToTx will maintain its value across the delay as it is
-		 // declared static.
-		 cCharToTx++;
-		 if( cCharToTx > 'x' )
-		 {
-			cCharToTx = 'a';
-		 }
-		 crDELAY( 100 );
-     }
-
-     // All co-routines must end with a call to crEND().
-     crEND();
- }
-
- // An ISR that uses a queue to receive characters to send on a UART.
- void vUART_ISR( void )
- {
- char cCharToTx;
- BaseType_t xCRWokenByPost = pdFALSE;
-
-     while( UART_TX_REG_EMPTY() )
-     {
-         // Are there any characters in the queue waiting to be sent?
-		 // xCRWokenByPost will automatically be set to pdTRUE if a co-routine
-		 // is woken by the post - ensuring that only a single co-routine is
-		 // woken no matter how many times we go around this loop.
-         if( crQUEUE_RECEIVE_FROM_ISR( pxQueue, &cCharToTx, &xCRWokenByPost ) )
-		 {
-			 SEND_CHARACTER( cCharToTx );
-		 }
-     }
- }
+ * @code{c} + * // A co-routine that posts a character to a queue then blocks for a fixed + * // period. The character is incremented each time. + * static void vSendingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex ) + * { + * // cChar holds its value while this co-routine is blocked and must therefore + * // be declared static. + * static char cCharToTx = 'a'; + * BaseType_t xResult; + * + * // All co-routines must start with a call to crSTART(). + * crSTART( xHandle ); + * + * for( ;; ) + * { + * // Send the next character to the queue. + * crQUEUE_SEND( xHandle, xCoRoutineQueue, &cCharToTx, NO_DELAY, &xResult ); + * + * if( xResult == pdPASS ) + * { + * // The character was successfully posted to the queue. + * } + * else + * { + * // Could not post the character to the queue. + * } + * + * // Enable the UART Tx interrupt to cause an interrupt in this + * // hypothetical UART. The interrupt will obtain the character + * // from the queue and send it. + * ENABLE_RX_INTERRUPT(); + * + * // Increment to the next character then block for a fixed period. + * // cCharToTx will maintain its value across the delay as it is + * // declared static. + * cCharToTx++; + * if( cCharToTx > 'x' ) + * { + * cCharToTx = 'a'; + * } + * crDELAY( 100 ); + * } + * + * // All co-routines must end with a call to crEND(). + * crEND(); + * } + * + * // An ISR that uses a queue to receive characters to send on a UART. + * void vUART_ISR( void ) + * { + * char cCharToTx; + * BaseType_t xCRWokenByPost = pdFALSE; + * + * while( UART_TX_REG_EMPTY() ) + * { + * // Are there any characters in the queue waiting to be sent? + * // xCRWokenByPost will automatically be set to pdTRUE if a co-routine + * // is woken by the post - ensuring that only a single co-routine is + * // woken no matter how many times we go around this loop. + * if( crQUEUE_RECEIVE_FROM_ISR( pxQueue, &cCharToTx, &xCRWokenByPost ) ) + * { + * SEND_CHARACTER( cCharToTx ); + * } + * } + * } + * @endcode + * @cond * \defgroup crQUEUE_RECEIVE_FROM_ISR crQUEUE_RECEIVE_FROM_ISR + * @endcond * \ingroup Tasks */ -#define crQUEUE_RECEIVE_FROM_ISR( pxQueue, pvBuffer, pxCoRoutineWoken ) xQueueCRReceiveFromISR( ( pxQueue ), ( pvBuffer ), ( pxCoRoutineWoken ) ) +#define crQUEUE_RECEIVE_FROM_ISR( pxQueue, pvBuffer, pxCoRoutineWoken ) \ + xQueueCRReceiveFromISR( ( pxQueue ), ( pvBuffer ), ( pxCoRoutineWoken ) ) /* * This function is intended for internal use by the co-routine macros only. @@ -702,7 +766,8 @@ void vCoRoutineSchedule( void ); * Removes the current co-routine from its ready list and places it in the * appropriate delayed list. */ -void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, List_t *pxEventList ); +void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, + List_t * pxEventList ); /* * This function is intended for internal use by the queue implementation only. @@ -711,10 +776,12 @@ void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, List_t *pxEventList ) * Removes the highest priority co-routine from the event list and places it in * the pending ready list. */ -BaseType_t xCoRoutineRemoveFromEventList( const List_t *pxEventList ); +BaseType_t xCoRoutineRemoveFromEventList( const List_t * pxEventList ); +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* CO_ROUTINE_H */ diff --git a/components/freertos/include/freertos/deprecated_definitions.h b/components/freertos/include/freertos/deprecated_definitions.h index 70fc403bd2..d3b942666d 100644 --- a/components/freertos/include/freertos/deprecated_definitions.h +++ b/components/freertos/include/freertos/deprecated_definitions.h @@ -1,6 +1,6 @@ /* - * FreeRTOS Kernel V10.2.1 - * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V10.4.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * 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 @@ -19,10 +19,9 @@ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS * - * 1 tab == 4 spaces! */ #ifndef DEPRECATED_DEFINITIONS_H @@ -30,158 +29,158 @@ /* Each FreeRTOS port has a unique portmacro.h header file. Originally a -pre-processor definition was used to ensure the pre-processor found the correct -portmacro.h file for the port being used. That scheme was deprecated in favour -of setting the compiler's include path such that it found the correct -portmacro.h file - removing the need for the constant and allowing the -portmacro.h file to be located anywhere in relation to the port being used. The -definitions below remain in the code for backward compatibility only. New -projects should not use them. */ + * pre-processor definition was used to ensure the pre-processor found the correct + * portmacro.h file for the port being used. That scheme was deprecated in favour + * of setting the compiler's include path such that it found the correct + * portmacro.h file - removing the need for the constant and allowing the + * portmacro.h file to be located anywhere in relation to the port being used. The + * definitions below remain in the code for backward compatibility only. New + * projects should not use them. */ #ifdef OPEN_WATCOM_INDUSTRIAL_PC_PORT - #include "..\..\Source\portable\owatcom\16bitdos\pc\portmacro.h" - typedef void ( __interrupt __far *pxISR )(); + #include "..\..\Source\portable\owatcom\16bitdos\pc\portmacro.h" + typedef void ( __interrupt __far * pxISR )(); #endif #ifdef OPEN_WATCOM_FLASH_LITE_186_PORT - #include "..\..\Source\portable\owatcom\16bitdos\flsh186\portmacro.h" - typedef void ( __interrupt __far *pxISR )(); + #include "..\..\Source\portable\owatcom\16bitdos\flsh186\portmacro.h" + typedef void ( __interrupt __far * pxISR )(); #endif #ifdef GCC_MEGA_AVR - #include "../portable/GCC/ATMega323/portmacro.h" + #include "../portable/GCC/ATMega323/portmacro.h" #endif #ifdef IAR_MEGA_AVR - #include "../portable/IAR/ATMega323/portmacro.h" + #include "../portable/IAR/ATMega323/portmacro.h" #endif #ifdef MPLAB_PIC24_PORT - #include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h" + #include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h" #endif #ifdef MPLAB_DSPIC_PORT - #include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h" + #include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h" #endif #ifdef MPLAB_PIC18F_PORT - #include "../../Source/portable/MPLAB/PIC18F/portmacro.h" + #include "../../Source/portable/MPLAB/PIC18F/portmacro.h" #endif #ifdef MPLAB_PIC32MX_PORT - #include "../../Source/portable/MPLAB/PIC32MX/portmacro.h" + #include "../../Source/portable/MPLAB/PIC32MX/portmacro.h" #endif #ifdef _FEDPICC - #include "libFreeRTOS/Include/portmacro.h" + #include "libFreeRTOS/Include/portmacro.h" #endif #ifdef SDCC_CYGNAL - #include "../../Source/portable/SDCC/Cygnal/portmacro.h" + #include "../../Source/portable/SDCC/Cygnal/portmacro.h" #endif #ifdef GCC_ARM7 - #include "../../Source/portable/GCC/ARM7_LPC2000/portmacro.h" + #include "../../Source/portable/GCC/ARM7_LPC2000/portmacro.h" #endif #ifdef GCC_ARM7_ECLIPSE - #include "portmacro.h" + #include "portmacro.h" #endif #ifdef ROWLEY_LPC23xx - #include "../../Source/portable/GCC/ARM7_LPC23xx/portmacro.h" + #include "../../Source/portable/GCC/ARM7_LPC23xx/portmacro.h" #endif #ifdef IAR_MSP430 - #include "..\..\Source\portable\IAR\MSP430\portmacro.h" + #include "..\..\Source\portable\IAR\MSP430\portmacro.h" #endif #ifdef GCC_MSP430 - #include "../../Source/portable/GCC/MSP430F449/portmacro.h" + #include "../../Source/portable/GCC/MSP430F449/portmacro.h" #endif #ifdef ROWLEY_MSP430 - #include "../../Source/portable/Rowley/MSP430F449/portmacro.h" + #include "../../Source/portable/Rowley/MSP430F449/portmacro.h" #endif #ifdef ARM7_LPC21xx_KEIL_RVDS - #include "..\..\Source\portable\RVDS\ARM7_LPC21xx\portmacro.h" + #include "..\..\Source\portable\RVDS\ARM7_LPC21xx\portmacro.h" #endif #ifdef SAM7_GCC - #include "../../Source/portable/GCC/ARM7_AT91SAM7S/portmacro.h" + #include "../../Source/portable/GCC/ARM7_AT91SAM7S/portmacro.h" #endif #ifdef SAM7_IAR - #include "..\..\Source\portable\IAR\AtmelSAM7S64\portmacro.h" + #include "..\..\Source\portable\IAR\AtmelSAM7S64\portmacro.h" #endif #ifdef SAM9XE_IAR - #include "..\..\Source\portable\IAR\AtmelSAM9XE\portmacro.h" + #include "..\..\Source\portable\IAR\AtmelSAM9XE\portmacro.h" #endif #ifdef LPC2000_IAR - #include "..\..\Source\portable\IAR\LPC2000\portmacro.h" + #include "..\..\Source\portable\IAR\LPC2000\portmacro.h" #endif #ifdef STR71X_IAR - #include "..\..\Source\portable\IAR\STR71x\portmacro.h" + #include "..\..\Source\portable\IAR\STR71x\portmacro.h" #endif #ifdef STR75X_IAR - #include "..\..\Source\portable\IAR\STR75x\portmacro.h" + #include "..\..\Source\portable\IAR\STR75x\portmacro.h" #endif #ifdef STR75X_GCC - #include "..\..\Source\portable\GCC\STR75x\portmacro.h" + #include "..\..\Source\portable\GCC\STR75x\portmacro.h" #endif #ifdef STR91X_IAR - #include "..\..\Source\portable\IAR\STR91x\portmacro.h" + #include "..\..\Source\portable\IAR\STR91x\portmacro.h" #endif #ifdef GCC_H8S - #include "../../Source/portable/GCC/H8S2329/portmacro.h" + #include "../../Source/portable/GCC/H8S2329/portmacro.h" #endif #ifdef GCC_AT91FR40008 - #include "../../Source/portable/GCC/ARM7_AT91FR40008/portmacro.h" + #include "../../Source/portable/GCC/ARM7_AT91FR40008/portmacro.h" #endif #ifdef RVDS_ARMCM3_LM3S102 - #include "../../Source/portable/RVDS/ARM_CM3/portmacro.h" + #include "../../Source/portable/RVDS/ARM_CM3/portmacro.h" #endif #ifdef GCC_ARMCM3_LM3S102 - #include "../../Source/portable/GCC/ARM_CM3/portmacro.h" + #include "../../Source/portable/GCC/ARM_CM3/portmacro.h" #endif #ifdef GCC_ARMCM3 - #include "../../Source/portable/GCC/ARM_CM3/portmacro.h" + #include "../../Source/portable/GCC/ARM_CM3/portmacro.h" #endif #ifdef IAR_ARM_CM3 - #include "../../Source/portable/IAR/ARM_CM3/portmacro.h" + #include "../../Source/portable/IAR/ARM_CM3/portmacro.h" #endif #ifdef IAR_ARMCM3_LM - #include "../../Source/portable/IAR/ARM_CM3/portmacro.h" + #include "../../Source/portable/IAR/ARM_CM3/portmacro.h" #endif #ifdef HCS12_CODE_WARRIOR - #include "../../Source/portable/CodeWarrior/HCS12/portmacro.h" + #include "../../Source/portable/CodeWarrior/HCS12/portmacro.h" #endif #ifdef MICROBLAZE_GCC - #include "../../Source/portable/GCC/MicroBlaze/portmacro.h" + #include "../../Source/portable/GCC/MicroBlaze/portmacro.h" #endif #ifdef TERN_EE - #include "..\..\Source\portable\Paradigm\Tern_EE\small\portmacro.h" + #include "..\..\Source\portable\Paradigm\Tern_EE\small\portmacro.h" #endif #ifdef GCC_HCS12 - #include "../../Source/portable/GCC/HCS12/portmacro.h" + #include "../../Source/portable/GCC/HCS12/portmacro.h" #endif #ifdef GCC_MCF5235 @@ -189,90 +188,92 @@ projects should not use them. */ #endif #ifdef COLDFIRE_V2_GCC - #include "../../../Source/portable/GCC/ColdFire_V2/portmacro.h" + #include "../../../Source/portable/GCC/ColdFire_V2/portmacro.h" #endif #ifdef COLDFIRE_V2_CODEWARRIOR - #include "../../Source/portable/CodeWarrior/ColdFire_V2/portmacro.h" + #include "../../Source/portable/CodeWarrior/ColdFire_V2/portmacro.h" #endif #ifdef GCC_PPC405 - #include "../../Source/portable/GCC/PPC405_Xilinx/portmacro.h" + #include "../../Source/portable/GCC/PPC405_Xilinx/portmacro.h" #endif #ifdef GCC_PPC440 - #include "../../Source/portable/GCC/PPC440_Xilinx/portmacro.h" + #include "../../Source/portable/GCC/PPC440_Xilinx/portmacro.h" #endif #ifdef _16FX_SOFTUNE - #include "..\..\Source\portable\Softune\MB96340\portmacro.h" + #include "..\..\Source\portable\Softune\MB96340\portmacro.h" #endif #ifdef BCC_INDUSTRIAL_PC_PORT - /* A short file name has to be used in place of the normal - FreeRTOSConfig.h when using the Borland compiler. */ - #include "frconfig.h" - #include "..\portable\BCC\16BitDOS\PC\prtmacro.h" - typedef void ( __interrupt __far *pxISR )(); + +/* A short file name has to be used in place of the normal + * FreeRTOSConfig.h when using the Borland compiler. */ + #include "frconfig.h" + #include "..\portable\BCC\16BitDOS\PC\prtmacro.h" + typedef void ( __interrupt __far * pxISR )(); #endif #ifdef BCC_FLASH_LITE_186_PORT - /* A short file name has to be used in place of the normal - FreeRTOSConfig.h when using the Borland compiler. */ - #include "frconfig.h" - #include "..\portable\BCC\16BitDOS\flsh186\prtmacro.h" - typedef void ( __interrupt __far *pxISR )(); + +/* A short file name has to be used in place of the normal + * FreeRTOSConfig.h when using the Borland compiler. */ + #include "frconfig.h" + #include "..\portable\BCC\16BitDOS\flsh186\prtmacro.h" + typedef void ( __interrupt __far * pxISR )(); #endif #ifdef __GNUC__ - #ifdef __AVR32_AVR32A__ - #include "portmacro.h" - #endif + #ifdef __AVR32_AVR32A__ + #include "portmacro.h" + #endif #endif #ifdef __ICCAVR32__ - #ifdef __CORE__ - #if __CORE__ == __AVR32A__ - #include "portmacro.h" - #endif - #endif + #ifdef __CORE__ + #if __CORE__ == __AVR32A__ + #include "portmacro.h" + #endif + #endif #endif #ifdef __91467D - #include "portmacro.h" + #include "portmacro.h" #endif #ifdef __96340 - #include "portmacro.h" + #include "portmacro.h" #endif #ifdef __IAR_V850ES_Fx3__ - #include "../../Source/portable/IAR/V850ES/portmacro.h" + #include "../../Source/portable/IAR/V850ES/portmacro.h" #endif #ifdef __IAR_V850ES_Jx3__ - #include "../../Source/portable/IAR/V850ES/portmacro.h" + #include "../../Source/portable/IAR/V850ES/portmacro.h" #endif #ifdef __IAR_V850ES_Jx3_L__ - #include "../../Source/portable/IAR/V850ES/portmacro.h" + #include "../../Source/portable/IAR/V850ES/portmacro.h" #endif #ifdef __IAR_V850ES_Jx2__ - #include "../../Source/portable/IAR/V850ES/portmacro.h" + #include "../../Source/portable/IAR/V850ES/portmacro.h" #endif #ifdef __IAR_V850ES_Hx2__ - #include "../../Source/portable/IAR/V850ES/portmacro.h" + #include "../../Source/portable/IAR/V850ES/portmacro.h" #endif #ifdef __IAR_78K0R_Kx3__ - #include "../../Source/portable/IAR/78K0R/portmacro.h" + #include "../../Source/portable/IAR/78K0R/portmacro.h" #endif #ifdef __IAR_78K0R_Kx3L__ - #include "../../Source/portable/IAR/78K0R/portmacro.h" + #include "../../Source/portable/IAR/78K0R/portmacro.h" #endif #endif /* DEPRECATED_DEFINITIONS_H */ diff --git a/components/freertos/include/freertos/event_groups.h b/components/freertos/include/freertos/event_groups.h index 3e05d0dc94..84505ddaaa 100644 --- a/components/freertos/include/freertos/event_groups.h +++ b/components/freertos/include/freertos/event_groups.h @@ -1,6 +1,6 @@ /* - * FreeRTOS Kernel V10.2.1 - * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V10.4.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * 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 @@ -19,25 +19,26 @@ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS * - * 1 tab == 4 spaces! */ #ifndef EVENT_GROUPS_H #define EVENT_GROUPS_H #ifndef INC_FREERTOS_H - #error "include FreeRTOS.h" must appear in source files before "include event_groups.h" + #error "include FreeRTOS.h" must appear in source files before "include event_groups.h" #endif /* FreeRTOS includes. */ #include "timers.h" +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /** * An event group is a collection of bits to which an application can assign a @@ -63,6 +64,9 @@ extern "C" { * used to create a synchronisation point between multiple tasks (a * 'rendezvous'). * + * @cond + * \defgroup EventGroup EventGroup + * @endcond */ @@ -74,25 +78,36 @@ extern "C" { * xEventGroupCreate() returns an EventGroupHandle_t variable that can then * be used as a parameter to other event group functions. * + * @cond * \defgroup EventGroupHandle_t EventGroupHandle_t + * @endcond * \ingroup EventGroup */ struct EventGroupDef_t; -//typedef struct EventGroupDef_t * EventGroupHandle_t; +#ifdef ESP_PLATFORM // IDF-3770 typedef void * EventGroupHandle_t; - +#else +typedef struct EventGroupDef_t * EventGroupHandle_t; +#endif // ESP_PLATFORM /* * The type that holds event bits always matches TickType_t - therefore the * number of bits it holds is set by configUSE_16_BIT_TICKS (16 bits if set to 1, * 32 bits if set to 0. * + * @cond * \defgroup EventBits_t EventBits_t + * @endcond * \ingroup EventGroup */ -typedef TickType_t EventBits_t; +typedef TickType_t EventBits_t; /** - * + * @cond + * event_groups.h + * @code{c} + * EventGroupHandle_t xEventGroupCreate( void ); + * @endcode + * @endcond * * Create a new event group. * @@ -100,7 +115,7 @@ typedef TickType_t EventBits_t; * block of memory, in which the event group's structure is stored. If an event * groups is created using xEventGroupCreate() then the required memory is * automatically dynamically allocated inside the xEventGroupCreate() function. - * (see http://www.freertos.org/a00111.html). If an event group is created + * (see https://www.FreeRTOS.org/a00111.html). If an event group is created * using xEventGroupCreateStatic() then the application writer must instead * provide the memory that will get used by the event group. * xEventGroupCreateStatic() therefore allows an event group to be created @@ -116,41 +131,51 @@ typedef TickType_t EventBits_t; * * @return If the event group was created then a handle to the event group is * returned. If there was insufficient FreeRTOS heap available to create the - * event group then NULL is returned. See http://www.freertos.org/a00111.html + * event group then NULL is returned. See https://www.FreeRTOS.org/a00111.html * * Example usage: * @code{c} - * // Declare a variable to hold the created event group. - * EventGroupHandle_t xCreatedEventGroup; + * // Declare a variable to hold the created event group. + * EventGroupHandle_t xCreatedEventGroup; * - * // Attempt to create the event group. - * xCreatedEventGroup = xEventGroupCreate(); + * // Attempt to create the event group. + * xCreatedEventGroup = xEventGroupCreate(); * - * // Was the event group created successfully? - * if( xCreatedEventGroup == NULL ) - * { - * // The event group was not created because there was insufficient - * // FreeRTOS heap available. - * } - * else - * { - * // The event group was created. - * } + * // Was the event group created successfully? + * if( xCreatedEventGroup == NULL ) + * { + * // The event group was not created because there was insufficient + * // FreeRTOS heap available. + * } + * else + * { + * // The event group was created. + * } * @endcode + * @cond + * \defgroup xEventGroupCreate xEventGroupCreate + * @endcond * \ingroup EventGroup */ -#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) - EventGroupHandle_t xEventGroupCreate( void ) PRIVILEGED_FUNCTION; +#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + EventGroupHandle_t xEventGroupCreate( void ) PRIVILEGED_FUNCTION; #endif /** + * @cond + * event_groups.h + * @code{c} + * EventGroupHandle_t xEventGroupCreateStatic( EventGroupHandle_t * pxEventGroupBuffer ); + * @endcode + * @endcond + * * Create a new event group. * * Internally, within the FreeRTOS implementation, event groups use a [small] * block of memory, in which the event group's structure is stored. If an event * groups is created using xEventGroupCreate() then the required memory is * automatically dynamically allocated inside the xEventGroupCreate() function. - * (see http://www.freertos.org/a00111.html). If an event group is created + * (see https://www.FreeRTOS.org/a00111.html). If an event group is created * using xEventGroupCreateStatic() then the application writer must instead * provide the memory that will get used by the event group. * xEventGroupCreateStatic() therefore allows an event group to be created @@ -173,25 +198,36 @@ typedef TickType_t EventBits_t; * * Example usage: * @code{c} - * // StaticEventGroup_t is a publicly accessible structure that has the same - * // size and alignment requirements as the real event group structure. It is - * // provided as a mechanism for applications to know the size of the event - * // group (which is dependent on the architecture and configuration file - * // settings) without breaking the strict data hiding policy by exposing the - * // real event group internals. This StaticEventGroup_t variable is passed - * // into the xSemaphoreCreateEventGroupStatic() function and is used to store - * // the event group's data structures - * StaticEventGroup_t xEventGroupBuffer; + * // StaticEventGroup_t is a publicly accessible structure that has the same + * // size and alignment requirements as the real event group structure. It is + * // provided as a mechanism for applications to know the size of the event + * // group (which is dependent on the architecture and configuration file + * // settings) without breaking the strict data hiding policy by exposing the + * // real event group internals. This StaticEventGroup_t variable is passed + * // into the xSemaphoreCreateEventGroupStatic() function and is used to store + * // the event group's data structures + * StaticEventGroup_t xEventGroupBuffer; * - * // Create the event group without dynamically allocating any memory. - * xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer ); + * // Create the event group without dynamically allocating any memory. + * xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer ); * @endcode */ -#if( configSUPPORT_STATIC_ALLOCATION == 1 ) - EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer ) PRIVILEGED_FUNCTION; +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer ) PRIVILEGED_FUNCTION; #endif /** + * @cond + * event_groups.h + * @code{c} + * EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, + * const EventBits_t uxBitsToWaitFor, + * const BaseType_t xClearOnExit, + * const BaseType_t xWaitForAllBits, + * const TickType_t xTicksToWait ); + * @endcode + * @endcond + * * [Potentially] block to wait for one or more bits to be set within a * previously created event group. * @@ -235,47 +271,60 @@ typedef TickType_t EventBits_t; * * Example usage: * @code{c} - * #define BIT_0 ( 1 << 0 ) - * #define BIT_4 ( 1 << 4 ) + * #define BIT_0 ( 1 << 0 ) + * #define BIT_4 ( 1 << 4 ) * - * void aFunction( EventGroupHandle_t xEventGroup ) - * { - * EventBits_t uxBits; - * const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS; + * void aFunction( EventGroupHandle_t xEventGroup ) + * { + * EventBits_t uxBits; + * const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS; * - * // Wait a maximum of 100ms for either bit 0 or bit 4 to be set within - * // the event group. Clear the bits before exiting. - * uxBits = xEventGroupWaitBits( - * xEventGroup, // The event group being tested. - * BIT_0 | BIT_4, // The bits within the event group to wait for. - * pdTRUE, // BIT_0 and BIT_4 should be cleared before returning. - * pdFALSE, // Don't wait for both bits, either bit will do. - * xTicksToWait ); // Wait a maximum of 100ms for either bit to be set. + * // Wait a maximum of 100ms for either bit 0 or bit 4 to be set within + * // the event group. Clear the bits before exiting. + * uxBits = xEventGroupWaitBits( + * xEventGroup, // The event group being tested. + * BIT_0 | BIT_4, // The bits within the event group to wait for. + * pdTRUE, // BIT_0 and BIT_4 should be cleared before returning. + * pdFALSE, // Don't wait for both bits, either bit will do. + * xTicksToWait ); // Wait a maximum of 100ms for either bit to be set. * - * if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) ) - * { - * // xEventGroupWaitBits() returned because both bits were set. - * } - * else if( ( uxBits & BIT_0 ) != 0 ) - * { - * // xEventGroupWaitBits() returned because just BIT_0 was set. - * } - * else if( ( uxBits & BIT_4 ) != 0 ) - * { - * // xEventGroupWaitBits() returned because just BIT_4 was set. - * } - * else - * { - * // xEventGroupWaitBits() returned because xTicksToWait ticks passed - * // without either BIT_0 or BIT_4 becoming set. - * } - * } - * @endcode{c} + * if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) ) + * { + * // xEventGroupWaitBits() returned because both bits were set. + * } + * else if( ( uxBits & BIT_0 ) != 0 ) + * { + * // xEventGroupWaitBits() returned because just BIT_0 was set. + * } + * else if( ( uxBits & BIT_4 ) != 0 ) + * { + * // xEventGroupWaitBits() returned because just BIT_4 was set. + * } + * else + * { + * // xEventGroupWaitBits() returned because xTicksToWait ticks passed + * // without either BIT_0 or BIT_4 becoming set. + * } + * } + * @endcode + * @cond + * \defgroup xEventGroupWaitBits xEventGroupWaitBits + * @endcond * \ingroup EventGroup */ -EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; +EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, + const EventBits_t uxBitsToWaitFor, + const BaseType_t xClearOnExit, + const BaseType_t xWaitForAllBits, + TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; /** + * @cond + * event_groups.h + * @code{c} + * EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ); + * @endcode + * @endcond * * Clear bits within an event group. This function cannot be called from an * interrupt. @@ -290,44 +339,54 @@ EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits * * Example usage: * @code{c} - * #define BIT_0 ( 1 << 0 ) - * #define BIT_4 ( 1 << 4 ) + * #define BIT_0 ( 1 << 0 ) + * #define BIT_4 ( 1 << 4 ) * - * void aFunction( EventGroupHandle_t xEventGroup ) - * { - * EventBits_t uxBits; + * void aFunction( EventGroupHandle_t xEventGroup ) + * { + * EventBits_t uxBits; * - * // Clear bit 0 and bit 4 in xEventGroup. - * uxBits = xEventGroupClearBits( - * xEventGroup, // The event group being updated. - * BIT_0 | BIT_4 );// The bits being cleared. + * // Clear bit 0 and bit 4 in xEventGroup. + * uxBits = xEventGroupClearBits( + * xEventGroup, // The event group being updated. + * BIT_0 | BIT_4 );// The bits being cleared. * - * if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) ) - * { - * // Both bit 0 and bit 4 were set before xEventGroupClearBits() was - * // called. Both will now be clear (not set). - * } - * else if( ( uxBits & BIT_0 ) != 0 ) - * { - * // Bit 0 was set before xEventGroupClearBits() was called. It will - * // now be clear. - * } - * else if( ( uxBits & BIT_4 ) != 0 ) - * { - * // Bit 4 was set before xEventGroupClearBits() was called. It will - * // now be clear. - * } - * else - * { - * // Neither bit 0 nor bit 4 were set in the first place. - * } - * } + * if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) ) + * { + * // Both bit 0 and bit 4 were set before xEventGroupClearBits() was + * // called. Both will now be clear (not set). + * } + * else if( ( uxBits & BIT_0 ) != 0 ) + * { + * // Bit 0 was set before xEventGroupClearBits() was called. It will + * // now be clear. + * } + * else if( ( uxBits & BIT_4 ) != 0 ) + * { + * // Bit 4 was set before xEventGroupClearBits() was called. It will + * // now be clear. + * } + * else + * { + * // Neither bit 0 nor bit 4 were set in the first place. + * } + * } * @endcode + * @cond + * \defgroup xEventGroupClearBits xEventGroupClearBits + * @endcond * \ingroup EventGroup */ -EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION; +EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, + const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION; /** + * @cond + * event_groups.h + * @code{c} + * BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ); + * @endcode + * @endcond * * A version of xEventGroupClearBits() that can be called from an interrupt. * @@ -353,35 +412,46 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBit * * Example usage: * @code{c} - * #define BIT_0 ( 1 << 0 ) - * #define BIT_4 ( 1 << 4 ) + * #define BIT_0 ( 1 << 0 ) + * #define BIT_4 ( 1 << 4 ) * - * // An event group which it is assumed has already been created by a call to - * // xEventGroupCreate(). - * EventGroupHandle_t xEventGroup; + * // An event group which it is assumed has already been created by a call to + * // xEventGroupCreate(). + * EventGroupHandle_t xEventGroup; * - * void anInterruptHandler( void ) - * { - * // Clear bit 0 and bit 4 in xEventGroup. - * xResult = xEventGroupClearBitsFromISR( - * xEventGroup, // The event group being updated. - * BIT_0 | BIT_4 ); // The bits being set. + * void anInterruptHandler( void ) + * { + * // Clear bit 0 and bit 4 in xEventGroup. + * xResult = xEventGroupClearBitsFromISR( + * xEventGroup, // The event group being updated. + * BIT_0 | BIT_4 ); // The bits being set. * - * if( xResult == pdPASS ) - * { - * // The message was posted successfully. - * } - * } + * if( xResult == pdPASS ) + * { + * // The message was posted successfully. + * } + * } * @endcode + * @cond + * \defgroup xEventGroupClearBitsFromISR xEventGroupClearBitsFromISR + * @endcond * \ingroup EventGroup */ -#if( configUSE_TRACE_FACILITY == 1 ) - BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION; +#if ( configUSE_TRACE_FACILITY == 1 ) + BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, + const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION; #else - #define xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear ) xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL ) + #define xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear ) \ + xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL ) #endif /** + * @cond + * event_groups.h + * @code{c} + * EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ); + * @endcode + * @endcond * * Set bits within an event group. * This function cannot be called from an interrupt. xEventGroupSetBitsFromISR() @@ -408,49 +478,59 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBit * * Example usage: * @code{c} - * #define BIT_0 ( 1 << 0 ) - * #define BIT_4 ( 1 << 4 ) + * #define BIT_0 ( 1 << 0 ) + * #define BIT_4 ( 1 << 4 ) * - * void aFunction( EventGroupHandle_t xEventGroup ) - * { - * EventBits_t uxBits; + * void aFunction( EventGroupHandle_t xEventGroup ) + * { + * EventBits_t uxBits; * - * // Set bit 0 and bit 4 in xEventGroup. - * uxBits = xEventGroupSetBits( - * xEventGroup, // The event group being updated. - * BIT_0 | BIT_4 );// The bits being set. + * // Set bit 0 and bit 4 in xEventGroup. + * uxBits = xEventGroupSetBits( + * xEventGroup, // The event group being updated. + * BIT_0 | BIT_4 );// The bits being set. * - * if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) ) - * { - * // Both bit 0 and bit 4 remained set when the function returned. - * } - * else if( ( uxBits & BIT_0 ) != 0 ) - * { - * // Bit 0 remained set when the function returned, but bit 4 was - * // cleared. It might be that bit 4 was cleared automatically as a - * // task that was waiting for bit 4 was removed from the Blocked - * // state. - * } - * else if( ( uxBits & BIT_4 ) != 0 ) - * { - * // Bit 4 remained set when the function returned, but bit 0 was - * // cleared. It might be that bit 0 was cleared automatically as a - * // task that was waiting for bit 0 was removed from the Blocked - * // state. - * } - * else - * { - * // Neither bit 0 nor bit 4 remained set. It might be that a task - * // was waiting for both of the bits to be set, and the bits were - * // cleared as the task left the Blocked state. - * } - * } - * @endcode{c} + * if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) ) + * { + * // Both bit 0 and bit 4 remained set when the function returned. + * } + * else if( ( uxBits & BIT_0 ) != 0 ) + * { + * // Bit 0 remained set when the function returned, but bit 4 was + * // cleared. It might be that bit 4 was cleared automatically as a + * // task that was waiting for bit 4 was removed from the Blocked + * // state. + * } + * else if( ( uxBits & BIT_4 ) != 0 ) + * { + * // Bit 4 remained set when the function returned, but bit 0 was + * // cleared. It might be that bit 0 was cleared automatically as a + * // task that was waiting for bit 0 was removed from the Blocked + * // state. + * } + * else + * { + * // Neither bit 0 nor bit 4 remained set. It might be that a task + * // was waiting for both of the bits to be set, and the bits were + * // cleared as the task left the Blocked state. + * } + * } + * @endcode + * @cond + * \defgroup xEventGroupSetBits xEventGroupSetBits + * @endcond * \ingroup EventGroup */ -EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) PRIVILEGED_FUNCTION; +EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, + const EventBits_t uxBitsToSet ) PRIVILEGED_FUNCTION; /** + * @cond + * event_groups.h + * @code{c} + * BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken ); + * @endcode + * @endcond * * A version of xEventGroupSetBits() that can be called from an interrupt. * @@ -484,46 +564,61 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_ * * Example usage: * @code{c} - * #define BIT_0 ( 1 << 0 ) - * #define BIT_4 ( 1 << 4 ) + * #define BIT_0 ( 1 << 0 ) + * #define BIT_4 ( 1 << 4 ) * - * // An event group which it is assumed has already been created by a call to - * // xEventGroupCreate(). - * EventGroupHandle_t xEventGroup; + * // An event group which it is assumed has already been created by a call to + * // xEventGroupCreate(). + * EventGroupHandle_t xEventGroup; * - * void anInterruptHandler( void ) - * { - * BaseType_t xHigherPriorityTaskWoken, xResult; + * void anInterruptHandler( void ) + * { + * BaseType_t xHigherPriorityTaskWoken, xResult; * - * // xHigherPriorityTaskWoken must be initialised to pdFALSE. - * xHigherPriorityTaskWoken = pdFALSE; + * // xHigherPriorityTaskWoken must be initialised to pdFALSE. + * xHigherPriorityTaskWoken = pdFALSE; * - * // Set bit 0 and bit 4 in xEventGroup. - * xResult = xEventGroupSetBitsFromISR( - * xEventGroup, // The event group being updated. - * BIT_0 | BIT_4 // The bits being set. - * &xHigherPriorityTaskWoken ); + * // Set bit 0 and bit 4 in xEventGroup. + * xResult = xEventGroupSetBitsFromISR( + * xEventGroup, // The event group being updated. + * BIT_0 | BIT_4 // The bits being set. + * &xHigherPriorityTaskWoken ); * - * // Was the message posted successfully? - * if( xResult == pdPASS ) - * { - * // If xHigherPriorityTaskWoken is now set to pdTRUE then a context - * // switch should be requested. The macro used is port specific and - * // will be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() - - * // refer to the documentation page for the port being used. - * portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); - * } - * } + * // Was the message posted successfully? + * if( xResult == pdPASS ) + * { + * // If xHigherPriorityTaskWoken is now set to pdTRUE then a context + * // switch should be requested. The macro used is port specific and + * // will be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() - + * // refer to the documentation page for the port being used. + * portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); + * } + * } * @endcode + * @cond + * \defgroup xEventGroupSetBitsFromISR xEventGroupSetBitsFromISR + * @endcond * \ingroup EventGroup */ -#if( configUSE_TRACE_FACILITY == 1 ) - BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; +#if ( configUSE_TRACE_FACILITY == 1 ) + BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, + const EventBits_t uxBitsToSet, + BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; #else - #define xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken ) xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken ) + #define xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken ) \ + xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken ) #endif /** + * @cond + * event_groups.h + * @code{c} + * EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, + * const EventBits_t uxBitsToSet, + * const EventBits_t uxBitsToWaitFor, + * TickType_t xTicksToWait ); + * @endcode + * @endcond * * Atomically set bits within an event group, then wait for a combination of * bits to be set within the same event group. This functionality is typically @@ -563,86 +658,98 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_ * * Example usage: * @code{c} - * // Bits used by the three tasks. - * #define TASK_0_BIT ( 1 << 0 ) - * #define TASK_1_BIT ( 1 << 1 ) - * #define TASK_2_BIT ( 1 << 2 ) + * // Bits used by the three tasks. + * #define TASK_0_BIT ( 1 << 0 ) + * #define TASK_1_BIT ( 1 << 1 ) + * #define TASK_2_BIT ( 1 << 2 ) * - * #define ALL_SYNC_BITS ( TASK_0_BIT | TASK_1_BIT | TASK_2_BIT ) + * #define ALL_SYNC_BITS ( TASK_0_BIT | TASK_1_BIT | TASK_2_BIT ) * - * // Use an event group to synchronise three tasks. It is assumed this event - * // group has already been created elsewhere. - * EventGroupHandle_t xEventBits; + * // Use an event group to synchronise three tasks. It is assumed this event + * // group has already been created elsewhere. + * EventGroupHandle_t xEventBits; * - * void vTask0( void *pvParameters ) - * { - * EventBits_t uxReturn; - * TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS; + * void vTask0( void *pvParameters ) + * { + * EventBits_t uxReturn; + * TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS; * - * for( ;; ) - * { - * // Perform task functionality here. + * for( ;; ) + * { + * // Perform task functionality here. * - * // Set bit 0 in the event flag to note this task has reached the - * // sync point. The other two tasks will set the other two bits defined - * // by ALL_SYNC_BITS. All three tasks have reached the synchronisation - * // point when all the ALL_SYNC_BITS are set. Wait a maximum of 100ms - * // for this to happen. - * uxReturn = xEventGroupSync( xEventBits, TASK_0_BIT, ALL_SYNC_BITS, xTicksToWait ); + * // Set bit 0 in the event flag to note this task has reached the + * // sync point. The other two tasks will set the other two bits defined + * // by ALL_SYNC_BITS. All three tasks have reached the synchronisation + * // point when all the ALL_SYNC_BITS are set. Wait a maximum of 100ms + * // for this to happen. + * uxReturn = xEventGroupSync( xEventBits, TASK_0_BIT, ALL_SYNC_BITS, xTicksToWait ); * - * if( ( uxReturn & ALL_SYNC_BITS ) == ALL_SYNC_BITS ) - * { - * // All three tasks reached the synchronisation point before the call - * // to xEventGroupSync() timed out. - * } - * } + * if( ( uxReturn & ALL_SYNC_BITS ) == ALL_SYNC_BITS ) + * { + * // All three tasks reached the synchronisation point before the call + * // to xEventGroupSync() timed out. + * } * } + * } * - * void vTask1( void *pvParameters ) - * { - * for( ;; ) - * { - * // Perform task functionality here. + * void vTask1( void *pvParameters ) + * { + * for( ;; ) + * { + * // Perform task functionality here. * - * // Set bit 1 in the event flag to note this task has reached the - * // synchronisation point. The other two tasks will set the other two - * // bits defined by ALL_SYNC_BITS. All three tasks have reached the - * // synchronisation point when all the ALL_SYNC_BITS are set. Wait - * // indefinitely for this to happen. - * xEventGroupSync( xEventBits, TASK_1_BIT, ALL_SYNC_BITS, portMAX_DELAY ); + * // Set bit 1 in the event flag to note this task has reached the + * // synchronisation point. The other two tasks will set the other two + * // bits defined by ALL_SYNC_BITS. All three tasks have reached the + * // synchronisation point when all the ALL_SYNC_BITS are set. Wait + * // indefinitely for this to happen. + * xEventGroupSync( xEventBits, TASK_1_BIT, ALL_SYNC_BITS, portMAX_DELAY ); * - * // xEventGroupSync() was called with an indefinite block time, so - * // this task will only reach here if the syncrhonisation was made by all - * // three tasks, so there is no need to test the return value. - * } - * } - * - * void vTask2( void *pvParameters ) - * { - * for( ;; ) - * { - * // Perform task functionality here. - * - * // Set bit 2 in the event flag to note this task has reached the - * // synchronisation point. The other two tasks will set the other two - * // bits defined by ALL_SYNC_BITS. All three tasks have reached the - * // synchronisation point when all the ALL_SYNC_BITS are set. Wait - * // indefinitely for this to happen. - * xEventGroupSync( xEventBits, TASK_2_BIT, ALL_SYNC_BITS, portMAX_DELAY ); - * - * // xEventGroupSync() was called with an indefinite block time, so - * // this task will only reach here if the syncrhonisation was made by all - * // three tasks, so there is no need to test the return value. - * } + * // xEventGroupSync() was called with an indefinite block time, so + * // this task will only reach here if the synchronisation was made by all + * // three tasks, so there is no need to test the return value. + * } + * } + * + * void vTask2( void *pvParameters ) + * { + * for( ;; ) + * { + * // Perform task functionality here. + * + * // Set bit 2 in the event flag to note this task has reached the + * // synchronisation point. The other two tasks will set the other two + * // bits defined by ALL_SYNC_BITS. All three tasks have reached the + * // synchronisation point when all the ALL_SYNC_BITS are set. Wait + * // indefinitely for this to happen. + * xEventGroupSync( xEventBits, TASK_2_BIT, ALL_SYNC_BITS, portMAX_DELAY ); + * + * // xEventGroupSync() was called with an indefinite block time, so + * // this task will only reach here if the synchronisation was made by all + * // three tasks, so there is no need to test the return value. * } + * } * * @endcode + * @cond + * \defgroup xEventGroupSync xEventGroupSync + * @endcond * \ingroup EventGroup */ -EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; +EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, + const EventBits_t uxBitsToSet, + const EventBits_t uxBitsToWaitFor, + TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; /** + * @cond + * event_groups.h + * @code{c} + * EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup ); + * @endcode + * @endcond * * Returns the current value of the bits in an event group. This function * cannot be used from an interrupt. @@ -651,11 +758,20 @@ EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t u * * @return The event group bits at the time xEventGroupGetBits() was called. * + * @cond + * \defgroup xEventGroupGetBits xEventGroupGetBits + * @endcond * \ingroup EventGroup */ -#define xEventGroupGetBits( xEventGroup ) xEventGroupClearBits( xEventGroup, 0 ) +#define xEventGroupGetBits( xEventGroup ) xEventGroupClearBits( xEventGroup, 0 ) /** + * @cond + * event_groups.h + * @code{c} + * EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ); + * @endcode + * @endcond * * A version of xEventGroupGetBits() that can be called from an ISR. * @@ -663,11 +779,21 @@ EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t u * * @return The event group bits at the time xEventGroupGetBitsFromISR() was called. * + * @cond + * \defgroup xEventGroupGetBitsFromISR xEventGroupGetBitsFromISR + * @endcond * \ingroup EventGroup */ EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION; /** + * @cond + * event_groups.h + * @code{c} + * void xEventGroupDelete( EventGroupHandle_t xEventGroup ); + * @endcode + * @endcond + * * Delete an event group that was previously created by a call to * xEventGroupCreate(). Tasks that are blocked on the event group will be * unblocked and obtain 0 as the event group's value. @@ -679,19 +805,24 @@ void vEventGroupDelete( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION; /** @cond */ /* For internal use only. */ -void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet ) PRIVILEGED_FUNCTION; -void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear ) PRIVILEGED_FUNCTION; +void vEventGroupSetBitsCallback( void * pvEventGroup, + const uint32_t ulBitsToSet ) PRIVILEGED_FUNCTION; +void vEventGroupClearBitsCallback( void * pvEventGroup, + const uint32_t ulBitsToClear ) PRIVILEGED_FUNCTION; -#if (configUSE_TRACE_FACILITY == 1) - UBaseType_t uxEventGroupGetNumber( void* xEventGroup ) PRIVILEGED_FUNCTION; - void vEventGroupSetNumber( void* xEventGroup, UBaseType_t uxEventGroupNumber ) PRIVILEGED_FUNCTION; +#if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxEventGroupGetNumber( void * xEventGroup ) PRIVILEGED_FUNCTION; + void vEventGroupSetNumber( void * xEventGroup, + UBaseType_t uxEventGroupNumber ) PRIVILEGED_FUNCTION; #endif /** @endcond */ +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* EVENT_GROUPS_H */ diff --git a/components/freertos/include/freertos/list.h b/components/freertos/include/freertos/list.h index d06481e29b..f76328f8e0 100644 --- a/components/freertos/include/freertos/list.h +++ b/components/freertos/include/freertos/list.h @@ -1,6 +1,6 @@ /* - * FreeRTOS Kernel V10.2.1 - * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V10.4.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * 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 @@ -19,10 +19,9 @@ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS * - * 1 tab == 4 spaces! */ /* @@ -54,7 +53,7 @@ */ #ifndef INC_FREERTOS_H - #error FreeRTOS.h must be included before list.h + #error "FreeRTOS.h must be included before list.h" #endif #ifndef LIST_H @@ -89,47 +88,49 @@ * "#define configLIST_VOLATILE volatile" */ #ifndef configLIST_VOLATILE - #define configLIST_VOLATILE + #define configLIST_VOLATILE #endif /* configSUPPORT_CROSS_MODULE_OPTIMISATION */ +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /* Macros that can be used to place known values within the list structures, -then check that the known values do not get corrupted during the execution of -the application. These may catch the list data structures being overwritten in -memory. They will not catch data errors caused by incorrect configuration or -use of FreeRTOS.*/ -#if( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 ) - /* Define the macros to do nothing. */ - #define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE - #define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE - #define listFIRST_LIST_INTEGRITY_CHECK_VALUE - #define listSECOND_LIST_INTEGRITY_CHECK_VALUE - #define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) - #define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) - #define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ) - #define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ) - #define listTEST_LIST_ITEM_INTEGRITY( pxItem ) - #define listTEST_LIST_INTEGRITY( pxList ) -#else - /* Define macros that add new members into the list structures. */ - #define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue1; - #define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue2; - #define listFIRST_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue1; - #define listSECOND_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue2; + * then check that the known values do not get corrupted during the execution of + * the application. These may catch the list data structures being overwritten in + * memory. They will not catch data errors caused by incorrect configuration or + * use of FreeRTOS.*/ +#if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 ) + /* Define the macros to do nothing. */ + #define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE + #define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE + #define listFIRST_LIST_INTEGRITY_CHECK_VALUE + #define listSECOND_LIST_INTEGRITY_CHECK_VALUE + #define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) + #define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) + #define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ) + #define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ) + #define listTEST_LIST_ITEM_INTEGRITY( pxItem ) + #define listTEST_LIST_INTEGRITY( pxList ) +#else /* if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 ) */ + /* Define macros that add new members into the list structures. */ + #define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue1; + #define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue2; + #define listFIRST_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue1; + #define listSECOND_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue2; - /* Define macros that set the new structure members to known values. */ - #define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue1 = pdINTEGRITY_CHECK_VALUE - #define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue2 = pdINTEGRITY_CHECK_VALUE - #define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ) ( pxList )->xListIntegrityValue1 = pdINTEGRITY_CHECK_VALUE - #define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ) ( pxList )->xListIntegrityValue2 = pdINTEGRITY_CHECK_VALUE +/* Define macros that set the new structure members to known values. */ + #define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue1 = pdINTEGRITY_CHECK_VALUE + #define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue2 = pdINTEGRITY_CHECK_VALUE + #define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ) ( pxList )->xListIntegrityValue1 = pdINTEGRITY_CHECK_VALUE + #define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ) ( pxList )->xListIntegrityValue2 = pdINTEGRITY_CHECK_VALUE - /* Define macros that will assert if one of the structure members does not - contain its expected value. */ - #define listTEST_LIST_ITEM_INTEGRITY( pxItem ) configASSERT( ( ( pxItem )->xListItemIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxItem )->xListItemIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) ) - #define listTEST_LIST_INTEGRITY( pxList ) configASSERT( ( ( pxList )->xListIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxList )->xListIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) ) +/* Define macros that will assert if one of the structure members does not + * contain its expected value. */ + #define listTEST_LIST_ITEM_INTEGRITY( pxItem ) configASSERT( ( ( pxItem )->xListItemIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxItem )->xListItemIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) ) + #define listTEST_LIST_INTEGRITY( pxList ) configASSERT( ( ( pxList )->xListIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxList )->xListIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) ) #endif /* configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES */ @@ -139,22 +140,22 @@ use of FreeRTOS.*/ struct xLIST; struct xLIST_ITEM { - listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ - configLIST_VOLATILE TickType_t xItemValue; /*< The value being listed. In most cases this is used to sort the list in descending order. */ - struct xLIST_ITEM * configLIST_VOLATILE pxNext; /*< Pointer to the next ListItem_t in the list. */ - struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /*< Pointer to the previous ListItem_t in the list. */ - void * pvOwner; /*< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */ - struct xLIST * configLIST_VOLATILE pxContainer; /*< Pointer to the list in which this list item is placed (if any). */ - listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ + listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ + configLIST_VOLATILE TickType_t xItemValue; /*< The value being listed. In most cases this is used to sort the list in descending order. */ + struct xLIST_ITEM * configLIST_VOLATILE pxNext; /*< Pointer to the next ListItem_t in the list. */ + struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /*< Pointer to the previous ListItem_t in the list. */ + void * pvOwner; /*< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */ + struct xLIST * configLIST_VOLATILE pxContainer; /*< Pointer to the list in which this list item is placed (if any). */ + listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ }; -typedef struct xLIST_ITEM ListItem_t; /* For some reason lint wants this as two separate definitions. */ +typedef struct xLIST_ITEM ListItem_t; /* For some reason lint wants this as two separate definitions. */ struct xMINI_LIST_ITEM { - listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ - configLIST_VOLATILE TickType_t xItemValue; - struct xLIST_ITEM * configLIST_VOLATILE pxNext; - struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; + listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ + configLIST_VOLATILE TickType_t xItemValue; + struct xLIST_ITEM * configLIST_VOLATILE pxNext; + struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; }; typedef struct xMINI_LIST_ITEM MiniListItem_t; @@ -163,11 +164,11 @@ typedef struct xMINI_LIST_ITEM MiniListItem_t; */ typedef struct xLIST { - listFIRST_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ - volatile UBaseType_t uxNumberOfItems; - ListItem_t * configLIST_VOLATILE pxIndex; /*< Used to walk through the list. Points to the last item returned by a call to listGET_OWNER_OF_NEXT_ENTRY (). */ - MiniListItem_t xListEnd; /*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */ - listSECOND_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ + listFIRST_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ + volatile UBaseType_t uxNumberOfItems; + ListItem_t * configLIST_VOLATILE pxIndex; /*< Used to walk through the list. Points to the last item returned by a call to listGET_OWNER_OF_NEXT_ENTRY (). */ + MiniListItem_t xListEnd; /*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */ + listSECOND_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ } List_t; /* @@ -177,7 +178,7 @@ typedef struct xLIST * \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER * \ingroup LinkedList */ -#define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner ) ( ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) ) +#define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner ) ( ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) ) /* * Access macro to get the owner of a list item. The owner of a list item @@ -186,7 +187,7 @@ typedef struct xLIST * \page listGET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER * \ingroup LinkedList */ -#define listGET_LIST_ITEM_OWNER( pxListItem ) ( ( pxListItem )->pvOwner ) +#define listGET_LIST_ITEM_OWNER( pxListItem ) ( ( pxListItem )->pvOwner ) /* * Access macro to set the value of the list item. In most cases the value is @@ -195,7 +196,7 @@ typedef struct xLIST * \page listSET_LIST_ITEM_VALUE listSET_LIST_ITEM_VALUE * \ingroup LinkedList */ -#define listSET_LIST_ITEM_VALUE( pxListItem, xValue ) ( ( pxListItem )->xItemValue = ( xValue ) ) +#define listSET_LIST_ITEM_VALUE( pxListItem, xValue ) ( ( pxListItem )->xItemValue = ( xValue ) ) /* * Access macro to retrieve the value of the list item. The value can @@ -205,7 +206,7 @@ typedef struct xLIST * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE * \ingroup LinkedList */ -#define listGET_LIST_ITEM_VALUE( pxListItem ) ( ( pxListItem )->xItemValue ) +#define listGET_LIST_ITEM_VALUE( pxListItem ) ( ( pxListItem )->xItemValue ) /* * Access macro to retrieve the value of the list item at the head of a given @@ -214,7 +215,7 @@ typedef struct xLIST * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE * \ingroup LinkedList */ -#define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext->xItemValue ) +#define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext->xItemValue ) /* * Return the list item at the head of the list. @@ -222,7 +223,7 @@ typedef struct xLIST * \page listGET_HEAD_ENTRY listGET_HEAD_ENTRY * \ingroup LinkedList */ -#define listGET_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext ) +#define listGET_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext ) /* * Return the next list item. @@ -230,7 +231,7 @@ typedef struct xLIST * \page listGET_NEXT listGET_NEXT * \ingroup LinkedList */ -#define listGET_NEXT( pxListItem ) ( ( pxListItem )->pxNext ) +#define listGET_NEXT( pxListItem ) ( ( pxListItem )->pxNext ) /* * Return the list item that marks the end of the list @@ -238,7 +239,7 @@ typedef struct xLIST * \page listGET_END_MARKER listGET_END_MARKER * \ingroup LinkedList */ -#define listGET_END_MARKER( pxList ) ( ( ListItem_t const * ) ( &( ( pxList )->xListEnd ) ) ) +#define listGET_END_MARKER( pxList ) ( ( ListItem_t const * ) ( &( ( pxList )->xListEnd ) ) ) /* * Access macro to determine if a list contains any items. The macro will @@ -247,12 +248,12 @@ typedef struct xLIST * \page listLIST_IS_EMPTY listLIST_IS_EMPTY * \ingroup LinkedList */ -#define listLIST_IS_EMPTY( pxList ) ( ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) ? pdTRUE : pdFALSE ) +#define listLIST_IS_EMPTY( pxList ) ( ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) ? pdTRUE : pdFALSE ) /* * Access macro to return the number of items in the list. */ -#define listCURRENT_LIST_LENGTH( pxList ) ( ( pxList )->uxNumberOfItems ) +#define listCURRENT_LIST_LENGTH( pxList ) ( ( pxList )->uxNumberOfItems ) /* * Access function to obtain the owner of the next entry in a list. @@ -274,18 +275,18 @@ typedef struct xLIST * \page listGET_OWNER_OF_NEXT_ENTRY listGET_OWNER_OF_NEXT_ENTRY * \ingroup LinkedList */ -#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \ -{ \ -List_t * const pxConstList = ( pxList ); \ - /* Increment the index to the next item and return the item, ensuring */ \ - /* we don't return the marker used at the end of the list. */ \ - ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ - if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) ) \ - { \ - ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ - } \ - ( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \ -} +#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \ + { \ + List_t * const pxConstList = ( pxList ); \ + /* Increment the index to the next item and return the item, ensuring */ \ + /* we don't return the marker used at the end of the list. */ \ + ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ + if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) ) \ + { \ + ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ + } \ + ( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \ + } /* @@ -304,7 +305,7 @@ List_t * const pxConstList = ( pxList ); \ * \page listGET_OWNER_OF_HEAD_ENTRY listGET_OWNER_OF_HEAD_ENTRY * \ingroup LinkedList */ -#define listGET_OWNER_OF_HEAD_ENTRY( pxList ) ( (&( ( pxList )->xListEnd ))->pxNext->pvOwner ) +#define listGET_OWNER_OF_HEAD_ENTRY( pxList ) ( ( &( ( pxList )->xListEnd ) )->pxNext->pvOwner ) /* * Check to see if a list item is within a list. The list item maintains a @@ -315,7 +316,7 @@ List_t * const pxConstList = ( pxList ); \ * @param pxListItem The list item we want to know if is in the list. * @return pdTRUE if the list item is in the list, otherwise pdFALSE. */ -#define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( ( pxListItem )->pxContainer == ( pxList ) ) ? ( pdTRUE ) : ( pdFALSE ) ) +#define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( ( pxListItem )->pxContainer == ( pxList ) ) ? ( pdTRUE ) : ( pdFALSE ) ) /* * Return the list a list item is contained within (referenced from). @@ -323,14 +324,14 @@ List_t * const pxConstList = ( pxList ); \ * @param pxListItem The list item being queried. * @return A pointer to the List_t object that references the pxListItem */ -#define listLIST_ITEM_CONTAINER( pxListItem ) ( ( pxListItem )->pxContainer ) +#define listLIST_ITEM_CONTAINER( pxListItem ) ( ( pxListItem )->pxContainer ) /* * This provides a crude means of knowing if a list has been initialised, as * pxList->xListEnd.xItemValue is set to portMAX_DELAY by the vListInitialise() * function. */ -#define listLIST_IS_INITIALISED( pxList ) ( ( pxList )->xListEnd.xItemValue == portMAX_DELAY ) +#define listLIST_IS_INITIALISED( pxList ) ( ( pxList )->xListEnd.xItemValue == portMAX_DELAY ) /* * Must be called before a list is used! This initialises all the members @@ -366,7 +367,8 @@ void vListInitialiseItem( ListItem_t * const pxItem ) PRIVILEGED_FUNCTION; * \page vListInsert vListInsert * \ingroup LinkedList */ -void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION; +void vListInsert( List_t * const pxList, + ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION; /* * Insert a list item into a list. The item will be inserted in a position @@ -387,7 +389,8 @@ void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem ) PRIV * \page vListInsertEnd vListInsertEnd * \ingroup LinkedList */ -void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION; +void vListInsertEnd( List_t * const pxList, + ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION; /* * Remove an item from a list. The list item has a pointer to the list that @@ -404,8 +407,10 @@ void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem ) P */ UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) PRIVILEGED_FUNCTION; +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ -#endif +#endif /* ifndef LIST_H */ diff --git a/components/freertos/include/freertos/message_buffer.h b/components/freertos/include/freertos/message_buffer.h index a49324da43..e57c589fba 100644 --- a/components/freertos/include/freertos/message_buffer.h +++ b/components/freertos/include/freertos/message_buffer.h @@ -1,6 +1,6 @@ /* - * FreeRTOS Kernel V10.2.1 - * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V10.4.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * 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 @@ -19,10 +19,9 @@ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS * - * 1 tab == 4 spaces! */ @@ -63,15 +62,17 @@ #define FREERTOS_MESSAGE_BUFFER_H #ifndef INC_FREERTOS_H - #error "include FreeRTOS.h must appear in source files before include message_buffer.h" + #error "include FreeRTOS.h must appear in source files before include message_buffer.h" #endif /* Message buffers are built onto of stream buffers. */ #include "stream_buffer.h" +/* *INDENT-OFF* */ #if defined( __cplusplus ) -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /** * Type by which message buffers are referenced. For example, a call to @@ -84,6 +85,14 @@ typedef void * MessageBufferHandle_t; /*-----------------------------------------------------------*/ /** + * @cond + * message_buffer.h + * + * @code{c} + * MessageBufferHandle_t xMessageBufferCreate( size_t xBufferSizeBytes ); + * @endcode + * @endcond + * * Creates a new message buffer using dynamically allocated memory. See * xMessageBufferCreateStatic() for a version that uses statically allocated * memory (memory that is allocated at compile time). @@ -113,28 +122,41 @@ typedef void * MessageBufferHandle_t; * MessageBufferHandle_t xMessageBuffer; * const size_t xMessageBufferSizeBytes = 100; * - * // Create a message buffer that can hold 100 bytes. The memory used to hold - * // both the message buffer structure and the messages themselves is allocated - * // dynamically. Each message added to the buffer consumes an additional 4 - * // bytes which are used to hold the lengh of the message. - * xMessageBuffer = xMessageBufferCreate( xMessageBufferSizeBytes ); + * // Create a message buffer that can hold 100 bytes. The memory used to hold + * // both the message buffer structure and the messages themselves is allocated + * // dynamically. Each message added to the buffer consumes an additional 4 + * // bytes which are used to hold the lengh of the message. + * xMessageBuffer = xMessageBufferCreate( xMessageBufferSizeBytes ); * - * if( xMessageBuffer == NULL ) - * { - * // There was not enough heap memory space available to create the - * // message buffer. - * } - * else - * { - * // The message buffer was created successfully and can now be used. - * } + * if( xMessageBuffer == NULL ) + * { + * // There was not enough heap memory space available to create the + * // message buffer. + * } + * else + * { + * // The message buffer was created successfully and can now be used. + * } * * @endcode + * @cond + * \defgroup xMessageBufferCreate xMessageBufferCreate + * @endcond * \ingroup MessageBufferManagement */ -#define xMessageBufferCreate( xBufferSizeBytes ) ( MessageBufferHandle_t ) xStreamBufferGenericCreate( xBufferSizeBytes, ( size_t ) 0, pdTRUE ) +#define xMessageBufferCreate( xBufferSizeBytes ) \ + ( MessageBufferHandle_t ) xStreamBufferGenericCreate( xBufferSizeBytes, ( size_t ) 0, pdTRUE ) /** + * @cond + * message_buffer.h + * + * @code{c} + * MessageBufferHandle_t xMessageBufferCreateStatic( size_t xBufferSizeBytes, + * uint8_t *pucMessageBufferStorageArea, + * StaticMessageBuffer_t *pxStaticMessageBuffer ); + * @endcode + * @endcond * Creates a new message buffer using statically allocated memory. See * xMessageBufferCreate() for a version that uses dynamically allocated memory. * @@ -176,23 +198,38 @@ typedef void * MessageBufferHandle_t; * { * MessageBufferHandle_t xMessageBuffer; * - * xMessageBuffer = xMessageBufferCreateStatic( sizeof( ucBufferStorage ), - * ucBufferStorage, - * &xMessageBufferStruct ); + * xMessageBuffer = xMessageBufferCreateStatic( sizeof( ucBufferStorage ), + * ucBufferStorage, + * &xMessageBufferStruct ); * - * // As neither the pucMessageBufferStorageArea or pxStaticMessageBuffer - * // parameters were NULL, xMessageBuffer will not be NULL, and can be used to - * // reference the created message buffer in other message buffer API calls. + * // As neither the pucMessageBufferStorageArea or pxStaticMessageBuffer + * // parameters were NULL, xMessageBuffer will not be NULL, and can be used to + * // reference the created message buffer in other message buffer API calls. * - * // Other code that uses the message buffer can go here. + * // Other code that uses the message buffer can go here. * } * * @endcode + * @cond + * \defgroup xMessageBufferCreateStatic xMessageBufferCreateStatic + * @endcond * \ingroup MessageBufferManagement */ -#define xMessageBufferCreateStatic( xBufferSizeBytes, pucMessageBufferStorageArea, pxStaticMessageBuffer ) ( MessageBufferHandle_t ) xStreamBufferGenericCreateStatic( xBufferSizeBytes, 0, pdTRUE, pucMessageBufferStorageArea, pxStaticMessageBuffer ) +#define xMessageBufferCreateStatic( xBufferSizeBytes, pucMessageBufferStorageArea, pxStaticMessageBuffer ) \ + ( MessageBufferHandle_t ) xStreamBufferGenericCreateStatic( xBufferSizeBytes, 0, pdTRUE, pucMessageBufferStorageArea, pxStaticMessageBuffer ) /** + * @cond + * message_buffer.h + * + * @code{c} + * size_t xMessageBufferSend( MessageBufferHandle_t xMessageBuffer, + * const void *pvTxData, + * size_t xDataLengthBytes, + * TickType_t xTicksToWait ); + * @endcode + * @endcond + * * Sends a discrete message to the message buffer. The message can be any * length that fits within the buffer's free space, and is copied into the * buffer. @@ -256,32 +293,47 @@ typedef void * MessageBufferHandle_t; * char *pcStringToSend = "String to send"; * const TickType_t x100ms = pdMS_TO_TICKS( 100 ); * - * // Send an array to the message buffer, blocking for a maximum of 100ms to - * // wait for enough space to be available in the message buffer. - * xBytesSent = xMessageBufferSend( xMessageBuffer, ( void * ) ucArrayToSend, sizeof( ucArrayToSend ), x100ms ); + * // Send an array to the message buffer, blocking for a maximum of 100ms to + * // wait for enough space to be available in the message buffer. + * xBytesSent = xMessageBufferSend( xMessageBuffer, ( void * ) ucArrayToSend, sizeof( ucArrayToSend ), x100ms ); * - * if( xBytesSent != sizeof( ucArrayToSend ) ) - * { - * // The call to xMessageBufferSend() times out before there was enough - * // space in the buffer for the data to be written. - * } + * if( xBytesSent != sizeof( ucArrayToSend ) ) + * { + * // The call to xMessageBufferSend() times out before there was enough + * // space in the buffer for the data to be written. + * } * - * // Send the string to the message buffer. Return immediately if there is - * // not enough space in the buffer. - * xBytesSent = xMessageBufferSend( xMessageBuffer, ( void * ) pcStringToSend, strlen( pcStringToSend ), 0 ); + * // Send the string to the message buffer. Return immediately if there is + * // not enough space in the buffer. + * xBytesSent = xMessageBufferSend( xMessageBuffer, ( void * ) pcStringToSend, strlen( pcStringToSend ), 0 ); * - * if( xBytesSent != strlen( pcStringToSend ) ) - * { - * // The string could not be added to the message buffer because there was - * // not enough free space in the buffer. - * } + * if( xBytesSent != strlen( pcStringToSend ) ) + * { + * // The string could not be added to the message buffer because there was + * // not enough free space in the buffer. + * } * } * @endcode + * @cond + * \defgroup xMessageBufferSend xMessageBufferSend + * @endcond * \ingroup MessageBufferManagement */ -#define xMessageBufferSend( xMessageBuffer, pvTxData, xDataLengthBytes, xTicksToWait ) xStreamBufferSend( ( StreamBufferHandle_t ) xMessageBuffer, pvTxData, xDataLengthBytes, xTicksToWait ) +#define xMessageBufferSend( xMessageBuffer, pvTxData, xDataLengthBytes, xTicksToWait ) \ + xStreamBufferSend( ( StreamBufferHandle_t ) xMessageBuffer, pvTxData, xDataLengthBytes, xTicksToWait ) /** + * @cond + * message_buffer.h + * + * @code{c} + * size_t xMessageBufferSendFromISR( MessageBufferHandle_t xMessageBuffer, + * const void *pvTxData, + * size_t xDataLengthBytes, + * BaseType_t *pxHigherPriorityTaskWoken ); + * @endcode + * @endcond + * * Interrupt safe version of the API function that sends a discrete message to * the message buffer. The message can be any length that fits within the * buffer's free space, and is copied into the buffer. @@ -348,34 +400,49 @@ typedef void * MessageBufferHandle_t; * char *pcStringToSend = "String to send"; * BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE. * - * // Attempt to send the string to the message buffer. - * xBytesSent = xMessageBufferSendFromISR( xMessageBuffer, - * ( void * ) pcStringToSend, - * strlen( pcStringToSend ), - * &xHigherPriorityTaskWoken ); + * // Attempt to send the string to the message buffer. + * xBytesSent = xMessageBufferSendFromISR( xMessageBuffer, + * ( void * ) pcStringToSend, + * strlen( pcStringToSend ), + * &xHigherPriorityTaskWoken ); * - * if( xBytesSent != strlen( pcStringToSend ) ) - * { - * // The string could not be added to the message buffer because there was - * // not enough free space in the buffer. - * } + * if( xBytesSent != strlen( pcStringToSend ) ) + * { + * // The string could not be added to the message buffer because there was + * // not enough free space in the buffer. + * } * - * // If xHigherPriorityTaskWoken was set to pdTRUE inside - * // xMessageBufferSendFromISR() then a task that has a priority above the - * // priority of the currently executing task was unblocked and a context - * // switch should be performed to ensure the ISR returns to the unblocked - * // task. In most FreeRTOS ports this is done by simply passing - * // xHigherPriorityTaskWoken into portYIELD_FROM_ISR(), which will test the - * // variables value, and perform the context switch if necessary. Check the - * // documentation for the port in use for port specific instructions. - * portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); + * // If xHigherPriorityTaskWoken was set to pdTRUE inside + * // xMessageBufferSendFromISR() then a task that has a priority above the + * // priority of the currently executing task was unblocked and a context + * // switch should be performed to ensure the ISR returns to the unblocked + * // task. In most FreeRTOS ports this is done by simply passing + * // xHigherPriorityTaskWoken into portYIELD_FROM_ISR(), which will test the + * // variables value, and perform the context switch if necessary. Check the + * // documentation for the port in use for port specific instructions. + * portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); * } * @endcode + * @cond + * \defgroup xMessageBufferSendFromISR xMessageBufferSendFromISR + * @endcond * \ingroup MessageBufferManagement */ -#define xMessageBufferSendFromISR( xMessageBuffer, pvTxData, xDataLengthBytes, pxHigherPriorityTaskWoken ) xStreamBufferSendFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pvTxData, xDataLengthBytes, pxHigherPriorityTaskWoken ) +#define xMessageBufferSendFromISR( xMessageBuffer, pvTxData, xDataLengthBytes, pxHigherPriorityTaskWoken ) \ + xStreamBufferSendFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pvTxData, xDataLengthBytes, pxHigherPriorityTaskWoken ) /** + * @cond + * message_buffer.h + * + * @code{c} + * size_t xMessageBufferReceive( MessageBufferHandle_t xMessageBuffer, + * void *pvRxData, + * size_t xBufferLengthBytes, + * TickType_t xTicksToWait ); + * @endcode + * @endcond + * * Receives a discrete message from a message buffer. Messages can be of * variable length and are copied out of the buffer. * @@ -434,27 +501,42 @@ typedef void * MessageBufferHandle_t; * size_t xReceivedBytes; * const TickType_t xBlockTime = pdMS_TO_TICKS( 20 ); * - * // Receive the next message from the message buffer. Wait in the Blocked - * // state (so not using any CPU processing time) for a maximum of 100ms for - * // a message to become available. - * xReceivedBytes = xMessageBufferReceive( xMessageBuffer, - * ( void * ) ucRxData, - * sizeof( ucRxData ), - * xBlockTime ); + * // Receive the next message from the message buffer. Wait in the Blocked + * // state (so not using any CPU processing time) for a maximum of 100ms for + * // a message to become available. + * xReceivedBytes = xMessageBufferReceive( xMessageBuffer, + * ( void * ) ucRxData, + * sizeof( ucRxData ), + * xBlockTime ); * - * if( xReceivedBytes > 0 ) - * { - * // A ucRxData contains a message that is xReceivedBytes long. Process - * // the message here.... - * } + * if( xReceivedBytes > 0 ) + * { + * // A ucRxData contains a message that is xReceivedBytes long. Process + * // the message here.... + * } * } * @endcode + * @cond + * \defgroup xMessageBufferReceive xMessageBufferReceive + * @endcond * \ingroup MessageBufferManagement */ -#define xMessageBufferReceive( xMessageBuffer, pvRxData, xBufferLengthBytes, xTicksToWait ) xStreamBufferReceive( ( StreamBufferHandle_t ) xMessageBuffer, pvRxData, xBufferLengthBytes, xTicksToWait ) +#define xMessageBufferReceive( xMessageBuffer, pvRxData, xBufferLengthBytes, xTicksToWait ) \ + xStreamBufferReceive( ( StreamBufferHandle_t ) xMessageBuffer, pvRxData, xBufferLengthBytes, xTicksToWait ) /** + * @cond + * message_buffer.h + * + * @code{c} + * size_t xMessageBufferReceiveFromISR( MessageBufferHandle_t xMessageBuffer, + * void *pvRxData, + * size_t xBufferLengthBytes, + * BaseType_t *pxHigherPriorityTaskWoken ); + * @endcode + * @endcond + * * An interrupt safe version of the API function that receives a discrete * message from a message buffer. Messages can be of variable length and are * copied out of the buffer. @@ -517,34 +599,46 @@ typedef void * MessageBufferHandle_t; * size_t xReceivedBytes; * BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE. * - * // Receive the next message from the message buffer. - * xReceivedBytes = xMessageBufferReceiveFromISR( xMessageBuffer, - * ( void * ) ucRxData, - * sizeof( ucRxData ), - * &xHigherPriorityTaskWoken ); + * // Receive the next message from the message buffer. + * xReceivedBytes = xMessageBufferReceiveFromISR( xMessageBuffer, + * ( void * ) ucRxData, + * sizeof( ucRxData ), + * &xHigherPriorityTaskWoken ); * - * if( xReceivedBytes > 0 ) - * { - * // A ucRxData contains a message that is xReceivedBytes long. Process - * // the message here.... - * } + * if( xReceivedBytes > 0 ) + * { + * // A ucRxData contains a message that is xReceivedBytes long. Process + * // the message here.... + * } * - * // If xHigherPriorityTaskWoken was set to pdTRUE inside - * // xMessageBufferReceiveFromISR() then a task that has a priority above the - * // priority of the currently executing task was unblocked and a context - * // switch should be performed to ensure the ISR returns to the unblocked - * // task. In most FreeRTOS ports this is done by simply passing - * // xHigherPriorityTaskWoken into portYIELD_FROM_ISR(), which will test the - * // variables value, and perform the context switch if necessary. Check the - * // documentation for the port in use for port specific instructions. - * portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); + * // If xHigherPriorityTaskWoken was set to pdTRUE inside + * // xMessageBufferReceiveFromISR() then a task that has a priority above the + * // priority of the currently executing task was unblocked and a context + * // switch should be performed to ensure the ISR returns to the unblocked + * // task. In most FreeRTOS ports this is done by simply passing + * // xHigherPriorityTaskWoken into portYIELD_FROM_ISR(), which will test the + * // variables value, and perform the context switch if necessary. Check the + * // documentation for the port in use for port specific instructions. + * portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); * } * @endcode + * @cond + * \defgroup xMessageBufferReceiveFromISR xMessageBufferReceiveFromISR + * @endcond * \ingroup MessageBufferManagement */ -#define xMessageBufferReceiveFromISR( xMessageBuffer, pvRxData, xBufferLengthBytes, pxHigherPriorityTaskWoken ) xStreamBufferReceiveFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pvRxData, xBufferLengthBytes, pxHigherPriorityTaskWoken ) +#define xMessageBufferReceiveFromISR( xMessageBuffer, pvRxData, xBufferLengthBytes, pxHigherPriorityTaskWoken ) \ + xStreamBufferReceiveFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pvRxData, xBufferLengthBytes, pxHigherPriorityTaskWoken ) /** + * @cond + * message_buffer.h + * + * @code{c} + * void vMessageBufferDelete( MessageBufferHandle_t xMessageBuffer ); + * @endcode + * @endcond + * * Deletes a message buffer that was previously created using a call to * xMessageBufferCreate() or xMessageBufferCreateStatic(). If the message * buffer was created using dynamic memory (that is, by xMessageBufferCreate()), @@ -556,9 +650,17 @@ typedef void * MessageBufferHandle_t; * @param xMessageBuffer The handle of the message buffer to be deleted. * */ -#define vMessageBufferDelete( xMessageBuffer ) vStreamBufferDelete( ( StreamBufferHandle_t ) xMessageBuffer ) +#define vMessageBufferDelete( xMessageBuffer ) \ + vStreamBufferDelete( ( StreamBufferHandle_t ) xMessageBuffer ) /** + * @cond + * message_buffer.h + * @code{c} + * BaseType_t xMessageBufferIsFull( MessageBufferHandle_t xMessageBuffer ) ); + * @endcode + * @endcond + * * Tests to see if a message buffer is full. A message buffer is full if it * cannot accept any more messages, of any size, until space is made available * by a message being removed from the message buffer. @@ -568,9 +670,17 @@ typedef void * MessageBufferHandle_t; * @return If the message buffer referenced by xMessageBuffer is full then * pdTRUE is returned. Otherwise pdFALSE is returned. */ -#define xMessageBufferIsFull( xMessageBuffer ) xStreamBufferIsFull( ( StreamBufferHandle_t ) xMessageBuffer ) +#define xMessageBufferIsFull( xMessageBuffer ) \ + xStreamBufferIsFull( ( StreamBufferHandle_t ) xMessageBuffer ) /** + * @cond + * message_buffer.h + * @code{c} + * BaseType_t xMessageBufferIsEmpty( MessageBufferHandle_t xMessageBuffer ) ); + * @endcode + * @endcond + * * Tests to see if a message buffer is empty (does not contain any messages). * * @param xMessageBuffer The handle of the message buffer being queried. @@ -579,9 +689,17 @@ typedef void * MessageBufferHandle_t; * pdTRUE is returned. Otherwise pdFALSE is returned. * */ -#define xMessageBufferIsEmpty( xMessageBuffer ) xStreamBufferIsEmpty( ( StreamBufferHandle_t ) xMessageBuffer ) +#define xMessageBufferIsEmpty( xMessageBuffer ) \ + xStreamBufferIsEmpty( ( StreamBufferHandle_t ) xMessageBuffer ) /** + * @cond + * message_buffer.h + * @code{c} + * BaseType_t xMessageBufferReset( MessageBufferHandle_t xMessageBuffer ); + * @endcode + * @endcond + * * Resets a message buffer to its initial empty state, discarding any message it * contained. * @@ -594,12 +712,23 @@ typedef void * MessageBufferHandle_t; * the message queue to wait for space to become available, or to wait for a * a message to be available, then pdFAIL is returned. * + * @cond + * \defgroup xMessageBufferReset xMessageBufferReset + * @endcond * \ingroup MessageBufferManagement */ -#define xMessageBufferReset( xMessageBuffer ) xStreamBufferReset( ( StreamBufferHandle_t ) xMessageBuffer ) +#define xMessageBufferReset( xMessageBuffer ) \ + xStreamBufferReset( ( StreamBufferHandle_t ) xMessageBuffer ) /** + * @cond + * message_buffer.h + * @code{c} + * size_t xMessageBufferSpaceAvailable( MessageBufferHandle_t xMessageBuffer ) ); + * @endcode + * @endcond + * * Returns the number of bytes of free space in the message buffer. * * @param xMessageBuffer The handle of the message buffer being queried. @@ -611,12 +740,24 @@ typedef void * MessageBufferHandle_t; * architecture, so if xMessageBufferSpacesAvailable() returns 10, then the size * of the largest message that can be written to the message buffer is 6 bytes. * + * @cond + * \defgroup xMessageBufferSpaceAvailable xMessageBufferSpaceAvailable + * @endcond * \ingroup MessageBufferManagement */ -#define xMessageBufferSpaceAvailable( xMessageBuffer ) xStreamBufferSpacesAvailable( ( StreamBufferHandle_t ) xMessageBuffer ) -#define xMessageBufferSpacesAvailable( xMessageBuffer ) xStreamBufferSpacesAvailable( ( StreamBufferHandle_t ) xMessageBuffer ) /* Corrects typo in original macro name. */ +#define xMessageBufferSpaceAvailable( xMessageBuffer ) \ + xStreamBufferSpacesAvailable( ( StreamBufferHandle_t ) xMessageBuffer ) +#define xMessageBufferSpacesAvailable( xMessageBuffer ) \ + xStreamBufferSpacesAvailable( ( StreamBufferHandle_t ) xMessageBuffer ) /* Corrects typo in original macro name. */ /** + * @cond + * message_buffer.h + * @code{c} + * size_t xMessageBufferNextLengthBytes( MessageBufferHandle_t xMessageBuffer ) ); + * @endcode + * @endcond + * * Returns the length (in bytes) of the next message in a message buffer. * Useful if xMessageBufferReceive() returned 0 because the size of the buffer * passed into xMessageBufferReceive() was too small to hold the next message. @@ -626,11 +767,23 @@ typedef void * MessageBufferHandle_t; * @return The length (in bytes) of the next message in the message buffer, or 0 * if the message buffer is empty. * + * @cond + * \defgroup xMessageBufferNextLengthBytes xMessageBufferNextLengthBytes + * @endcond * \ingroup MessageBufferManagement */ -#define xMessageBufferNextLengthBytes( xMessageBuffer ) xStreamBufferNextMessageLengthBytes( ( StreamBufferHandle_t ) xMessageBuffer ) PRIVILEGED_FUNCTION; +#define xMessageBufferNextLengthBytes( xMessageBuffer ) \ + xStreamBufferNextMessageLengthBytes( ( StreamBufferHandle_t ) xMessageBuffer ) PRIVILEGED_FUNCTION; /** + * @cond + * message_buffer.h + * + * @code{c} + * BaseType_t xMessageBufferSendCompletedFromISR( MessageBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken ); + * @endcode + * @endcond + * * For advanced users only. * * The sbSEND_COMPLETED() macro is called from within the FreeRTOS APIs when @@ -658,11 +811,23 @@ typedef void * MessageBufferHandle_t; * @return If a task was removed from the Blocked state then pdTRUE is returned. * Otherwise pdFALSE is returned. * + * @cond + * \defgroup xMessageBufferSendCompletedFromISR xMessageBufferSendCompletedFromISR + * @endcond * \ingroup StreamBufferManagement */ -#define xMessageBufferSendCompletedFromISR( xMessageBuffer, pxHigherPriorityTaskWoken ) xStreamBufferSendCompletedFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pxHigherPriorityTaskWoken ) +#define xMessageBufferSendCompletedFromISR( xMessageBuffer, pxHigherPriorityTaskWoken ) \ + xStreamBufferSendCompletedFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pxHigherPriorityTaskWoken ) /** + * @cond + * message_buffer.h + * + * @code{c} + * BaseType_t xMessageBufferReceiveCompletedFromISR( MessageBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken ); + * @endcode + * @endcond + * * For advanced users only. * * The sbRECEIVE_COMPLETED() macro is called from within the FreeRTOS APIs when @@ -691,12 +856,18 @@ typedef void * MessageBufferHandle_t; * @return If a task was removed from the Blocked state then pdTRUE is returned. * Otherwise pdFALSE is returned. * + * @cond + * \defgroup xMessageBufferReceiveCompletedFromISR xMessageBufferReceiveCompletedFromISR + * @endcond * \ingroup StreamBufferManagement */ -#define xMessageBufferReceiveCompletedFromISR( xMessageBuffer, pxHigherPriorityTaskWoken ) xStreamBufferReceiveCompletedFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pxHigherPriorityTaskWoken ) +#define xMessageBufferReceiveCompletedFromISR( xMessageBuffer, pxHigherPriorityTaskWoken ) \ + xStreamBufferReceiveCompletedFromISR( ( StreamBufferHandle_t ) xMessageBuffer, pxHigherPriorityTaskWoken ) +/* *INDENT-OFF* */ #if defined( __cplusplus ) -} /* extern "C" */ + } /* extern "C" */ #endif +/* *INDENT-ON* */ -#endif /* !defined( FREERTOS_MESSAGE_BUFFER_H ) */ +#endif /* !defined( FREERTOS_MESSAGE_BUFFER_H ) */ diff --git a/components/freertos/include/freertos/mpu_prototypes.h b/components/freertos/include/freertos/mpu_prototypes.h new file mode 100644 index 0000000000..ceb74f3e5b --- /dev/null +++ b/components/freertos/include/freertos/mpu_prototypes.h @@ -0,0 +1,257 @@ +/* + * FreeRTOS Kernel V10.4.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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 + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +/* + * When the MPU is used the standard (non MPU) API functions are mapped to + * equivalents that start "MPU_", the prototypes for which are defined in this + * header files. This will cause the application code to call the MPU_ version + * which wraps the non-MPU version with privilege promoting then demoting code, + * so the kernel code always runs will full privileges. + */ + + +#ifndef MPU_PROTOTYPES_H +#define MPU_PROTOTYPES_H + +/* MPU versions of tasks.h API functions. */ +BaseType_t MPU_xTaskCreate( TaskFunction_t pxTaskCode, + const char * const pcName, + const uint16_t usStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + TaskHandle_t * const pxCreatedTask ) FREERTOS_SYSTEM_CALL; +TaskHandle_t MPU_xTaskCreateStatic( TaskFunction_t pxTaskCode, + const char * const pcName, + const uint32_t ulStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + StackType_t * const puxStackBuffer, + StaticTask_t * const pxTaskBuffer ) FREERTOS_SYSTEM_CALL; +void MPU_vTaskDelete( TaskHandle_t xTaskToDelete ) FREERTOS_SYSTEM_CALL; +void MPU_vTaskDelay( const TickType_t xTicksToDelay ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTaskDelayUntil( TickType_t * const pxPreviousWakeTime, + const TickType_t xTimeIncrement ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTaskAbortDelay( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL; +UBaseType_t MPU_uxTaskPriorityGet( const TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL; +eTaskState MPU_eTaskGetState( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL; +void MPU_vTaskGetInfo( TaskHandle_t xTask, + TaskStatus_t * pxTaskStatus, + BaseType_t xGetFreeStackSpace, + eTaskState eState ) FREERTOS_SYSTEM_CALL; +void MPU_vTaskPrioritySet( TaskHandle_t xTask, + UBaseType_t uxNewPriority ) FREERTOS_SYSTEM_CALL; +void MPU_vTaskSuspend( TaskHandle_t xTaskToSuspend ) FREERTOS_SYSTEM_CALL; +void MPU_vTaskResume( TaskHandle_t xTaskToResume ) FREERTOS_SYSTEM_CALL; +void MPU_vTaskStartScheduler( void ) FREERTOS_SYSTEM_CALL; +void MPU_vTaskSuspendAll( void ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTaskResumeAll( void ) FREERTOS_SYSTEM_CALL; +TickType_t MPU_xTaskGetTickCount( void ) FREERTOS_SYSTEM_CALL; +UBaseType_t MPU_uxTaskGetNumberOfTasks( void ) FREERTOS_SYSTEM_CALL; +char * MPU_pcTaskGetName( TaskHandle_t xTaskToQuery ) FREERTOS_SYSTEM_CALL; +TaskHandle_t MPU_xTaskGetHandle( const char * pcNameToQuery ) FREERTOS_SYSTEM_CALL; +UBaseType_t MPU_uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL; +configSTACK_DEPTH_TYPE MPU_uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL; +void MPU_vTaskSetApplicationTaskTag( TaskHandle_t xTask, + TaskHookFunction_t pxHookFunction ) FREERTOS_SYSTEM_CALL; +TaskHookFunction_t MPU_xTaskGetApplicationTaskTag( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL; +void MPU_vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, + BaseType_t xIndex, + void * pvValue ) FREERTOS_SYSTEM_CALL; +void * MPU_pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, + BaseType_t xIndex ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTaskCallApplicationTaskHook( TaskHandle_t xTask, + void * pvParameter ) FREERTOS_SYSTEM_CALL; +TaskHandle_t MPU_xTaskGetIdleTaskHandle( void ) FREERTOS_SYSTEM_CALL; +UBaseType_t MPU_uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, + const UBaseType_t uxArraySize, + uint32_t * const pulTotalRunTime ) FREERTOS_SYSTEM_CALL; +uint32_t MPU_ulTaskGetIdleRunTimeCounter( void ) FREERTOS_SYSTEM_CALL; +void MPU_vTaskList( char * pcWriteBuffer ) FREERTOS_SYSTEM_CALL; +void MPU_vTaskGetRunTimeStats( char * pcWriteBuffer ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTaskGenericNotify( TaskHandle_t xTaskToNotify, + UBaseType_t uxIndexToNotify, + uint32_t ulValue, + eNotifyAction eAction, + uint32_t * pulPreviousNotificationValue ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn, + uint32_t ulBitsToClearOnEntry, + uint32_t ulBitsToClearOnExit, + uint32_t * pulNotificationValue, + TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; +uint32_t MPU_ulTaskGenericNotifyTake( UBaseType_t uxIndexToWaitOn, + BaseType_t xClearCountOnExit, + TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTaskGenericNotifyStateClear( TaskHandle_t xTask, + UBaseType_t uxIndexToClear ) FREERTOS_SYSTEM_CALL; +uint32_t MPU_ulTaskGenericNotifyValueClear( TaskHandle_t xTask, + UBaseType_t uxIndexToClear, + uint32_t ulBitsToClear ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTaskIncrementTick( void ) FREERTOS_SYSTEM_CALL; +TaskHandle_t MPU_xTaskGetCurrentTaskHandle( void ) FREERTOS_SYSTEM_CALL; +void MPU_vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, + TickType_t * const pxTicksToWait ) FREERTOS_SYSTEM_CALL; +void MPU_vTaskMissedYield( void ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTaskGetSchedulerState( void ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) FREERTOS_SYSTEM_CALL; + +/* MPU versions of queue.h API functions. */ +BaseType_t MPU_xQueueGenericSend( QueueHandle_t xQueue, + const void * const pvItemToQueue, + TickType_t xTicksToWait, + const BaseType_t xCopyPosition ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xQueueReceive( QueueHandle_t xQueue, + void * const pvBuffer, + TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xQueuePeek( QueueHandle_t xQueue, + void * const pvBuffer, + TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xQueueSemaphoreTake( QueueHandle_t xQueue, + TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; +UBaseType_t MPU_uxQueueMessagesWaiting( const QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL; +UBaseType_t MPU_uxQueueSpacesAvailable( const QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL; +void MPU_vQueueDelete( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL; +QueueHandle_t MPU_xQueueCreateMutex( const uint8_t ucQueueType ) FREERTOS_SYSTEM_CALL; +QueueHandle_t MPU_xQueueCreateMutexStatic( const uint8_t ucQueueType, + StaticQueue_t * pxStaticQueue ) FREERTOS_SYSTEM_CALL; +QueueHandle_t MPU_xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, + const UBaseType_t uxInitialCount ) FREERTOS_SYSTEM_CALL; +QueueHandle_t MPU_xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, + const UBaseType_t uxInitialCount, + StaticQueue_t * pxStaticQueue ) FREERTOS_SYSTEM_CALL; +TaskHandle_t MPU_xQueueGetMutexHolder( QueueHandle_t xSemaphore ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xQueueTakeMutexRecursive( QueueHandle_t xMutex, + TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xQueueGiveMutexRecursive( QueueHandle_t pxMutex ) FREERTOS_SYSTEM_CALL; +void MPU_vQueueAddToRegistry( QueueHandle_t xQueue, + const char * pcName ) FREERTOS_SYSTEM_CALL; +void MPU_vQueueUnregisterQueue( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL; +const char * MPU_pcQueueGetName( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL; +QueueHandle_t MPU_xQueueGenericCreate( const UBaseType_t uxQueueLength, + const UBaseType_t uxItemSize, + const uint8_t ucQueueType ) FREERTOS_SYSTEM_CALL; +QueueHandle_t MPU_xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, + const UBaseType_t uxItemSize, + uint8_t * pucQueueStorage, + StaticQueue_t * pxStaticQueue, + const uint8_t ucQueueType ) FREERTOS_SYSTEM_CALL; +QueueSetHandle_t MPU_xQueueCreateSet( const UBaseType_t uxEventQueueLength ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, + QueueSetHandle_t xQueueSet ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, + QueueSetHandle_t xQueueSet ) FREERTOS_SYSTEM_CALL; +QueueSetMemberHandle_t MPU_xQueueSelectFromSet( QueueSetHandle_t xQueueSet, + const TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xQueueGenericReset( QueueHandle_t xQueue, + BaseType_t xNewQueue ) FREERTOS_SYSTEM_CALL; +void MPU_vQueueSetQueueNumber( QueueHandle_t xQueue, + UBaseType_t uxQueueNumber ) FREERTOS_SYSTEM_CALL; +UBaseType_t MPU_uxQueueGetQueueNumber( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL; +uint8_t MPU_ucQueueGetQueueType( QueueHandle_t xQueue ) FREERTOS_SYSTEM_CALL; + +/* MPU versions of timers.h API functions. */ +TimerHandle_t MPU_xTimerCreate( const char * const pcTimerName, + const TickType_t xTimerPeriodInTicks, + const UBaseType_t uxAutoReload, + void * const pvTimerID, + TimerCallbackFunction_t pxCallbackFunction ) FREERTOS_SYSTEM_CALL; +TimerHandle_t MPU_xTimerCreateStatic( const char * const pcTimerName, + const TickType_t xTimerPeriodInTicks, + const UBaseType_t uxAutoReload, + void * const pvTimerID, + TimerCallbackFunction_t pxCallbackFunction, + StaticTimer_t * pxTimerBuffer ) FREERTOS_SYSTEM_CALL; +void * MPU_pvTimerGetTimerID( const TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL; +void MPU_vTimerSetTimerID( TimerHandle_t xTimer, + void * pvNewID ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTimerIsTimerActive( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL; +TaskHandle_t MPU_xTimerGetTimerDaemonTaskHandle( void ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, + void * pvParameter1, + uint32_t ulParameter2, + TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; +const char * MPU_pcTimerGetName( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL; +void MPU_vTimerSetReloadMode( TimerHandle_t xTimer, + const UBaseType_t uxAutoReload ) FREERTOS_SYSTEM_CALL; +UBaseType_t MPU_uxTimerGetReloadMode( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL; +TickType_t MPU_xTimerGetPeriod( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL; +TickType_t MPU_xTimerGetExpiryTime( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTimerCreateTimerTask( void ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xTimerGenericCommand( TimerHandle_t xTimer, + const BaseType_t xCommandID, + const TickType_t xOptionalValue, + BaseType_t * const pxHigherPriorityTaskWoken, + const TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; + +/* MPU versions of event_group.h API functions. */ +EventGroupHandle_t MPU_xEventGroupCreate( void ) FREERTOS_SYSTEM_CALL; +EventGroupHandle_t MPU_xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer ) FREERTOS_SYSTEM_CALL; +EventBits_t MPU_xEventGroupWaitBits( EventGroupHandle_t xEventGroup, + const EventBits_t uxBitsToWaitFor, + const BaseType_t xClearOnExit, + const BaseType_t xWaitForAllBits, + TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; +EventBits_t MPU_xEventGroupClearBits( EventGroupHandle_t xEventGroup, + const EventBits_t uxBitsToClear ) FREERTOS_SYSTEM_CALL; +EventBits_t MPU_xEventGroupSetBits( EventGroupHandle_t xEventGroup, + const EventBits_t uxBitsToSet ) FREERTOS_SYSTEM_CALL; +EventBits_t MPU_xEventGroupSync( EventGroupHandle_t xEventGroup, + const EventBits_t uxBitsToSet, + const EventBits_t uxBitsToWaitFor, + TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; +void MPU_vEventGroupDelete( EventGroupHandle_t xEventGroup ) FREERTOS_SYSTEM_CALL; +UBaseType_t MPU_uxEventGroupGetNumber( void * xEventGroup ) FREERTOS_SYSTEM_CALL; + +/* MPU versions of message/stream_buffer.h API functions. */ +size_t MPU_xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, + const void * pvTxData, + size_t xDataLengthBytes, + TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; +size_t MPU_xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer, + void * pvRxData, + size_t xBufferLengthBytes, + TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL; +size_t MPU_xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL; +void MPU_vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL; +size_t MPU_xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL; +size_t MPU_xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer ) FREERTOS_SYSTEM_CALL; +BaseType_t MPU_xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, + size_t xTriggerLevel ) FREERTOS_SYSTEM_CALL; +StreamBufferHandle_t MPU_xStreamBufferGenericCreate( size_t xBufferSizeBytes, + size_t xTriggerLevelBytes, + BaseType_t xIsMessageBuffer ) FREERTOS_SYSTEM_CALL; +StreamBufferHandle_t MPU_xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes, + size_t xTriggerLevelBytes, + BaseType_t xIsMessageBuffer, + uint8_t * const pucStreamBufferStorageArea, + StaticStreamBuffer_t * const pxStaticStreamBuffer ) FREERTOS_SYSTEM_CALL; + + + +#endif /* MPU_PROTOTYPES_H */ diff --git a/components/freertos/include/freertos/mpu_wrappers.h b/components/freertos/include/freertos/mpu_wrappers.h index 7cbad5da08..c02dcd0c41 100644 --- a/components/freertos/include/freertos/mpu_wrappers.h +++ b/components/freertos/include/freertos/mpu_wrappers.h @@ -1,6 +1,6 @@ /* - * FreeRTOS Kernel V10.2.1 - * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V10.4.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * 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 @@ -19,166 +19,165 @@ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS * - * 1 tab == 4 spaces! */ #ifndef MPU_WRAPPERS_H #define MPU_WRAPPERS_H /* This file redefines API functions to be called through a wrapper macro, but -only for ports that are using the MPU. */ + * only for ports that are using the MPU. */ #if portUSING_MPU_WRAPPERS - /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE will be defined when this file is - included from queue.c or task.c to prevent it from having an effect within - those files. */ - #ifndef MPU_WRAPPERS_INCLUDED_FROM_API_FILE +/* MPU_WRAPPERS_INCLUDED_FROM_API_FILE will be defined when this file is + * included from queue.c or task.c to prevent it from having an effect within + * those files. */ + #ifndef MPU_WRAPPERS_INCLUDED_FROM_API_FILE - /* - * Map standard (non MPU) API functions to equivalents that start - * "MPU_". This will cause the application code to call the MPU_ - * version, which wraps the non-MPU version with privilege promoting - * then demoting code, so the kernel code always runs will full - * privileges. - */ +/* + * Map standard (non MPU) API functions to equivalents that start + * "MPU_". This will cause the application code to call the MPU_ + * version, which wraps the non-MPU version with privilege promoting + * then demoting code, so the kernel code always runs will full + * privileges. + */ - /* Map standard tasks.h API functions to the MPU equivalents. */ - #define xTaskCreate MPU_xTaskCreate - #define xTaskCreateStatic MPU_xTaskCreateStatic - #define xTaskCreateRestricted MPU_xTaskCreateRestricted - #define vTaskAllocateMPURegions MPU_vTaskAllocateMPURegions - #define vTaskDelete MPU_vTaskDelete - #define vTaskDelay MPU_vTaskDelay - #define vTaskDelayUntil MPU_vTaskDelayUntil - #define xTaskAbortDelay MPU_xTaskAbortDelay - #define uxTaskPriorityGet MPU_uxTaskPriorityGet - #define eTaskGetState MPU_eTaskGetState - #define vTaskGetInfo MPU_vTaskGetInfo - #define vTaskPrioritySet MPU_vTaskPrioritySet - #define vTaskSuspend MPU_vTaskSuspend - #define vTaskResume MPU_vTaskResume - #define vTaskSuspendAll MPU_vTaskSuspendAll - #define xTaskResumeAll MPU_xTaskResumeAll - #define xTaskGetTickCount MPU_xTaskGetTickCount - #define uxTaskGetNumberOfTasks MPU_uxTaskGetNumberOfTasks - #define pcTaskGetName MPU_pcTaskGetName - #define xTaskGetHandle MPU_xTaskGetHandle - #define uxTaskGetStackHighWaterMark MPU_uxTaskGetStackHighWaterMark - #define uxTaskGetStackHighWaterMark2 MPU_uxTaskGetStackHighWaterMark2 - #define vTaskSetApplicationTaskTag MPU_vTaskSetApplicationTaskTag - #define xTaskGetApplicationTaskTag MPU_xTaskGetApplicationTaskTag - // #define vTaskSetThreadLocalStoragePointer MPU_vTaskSetThreadLocalStoragePointer - // #define pvTaskGetThreadLocalStoragePointer MPU_pvTaskGetThreadLocalStoragePointer - #define xTaskCallApplicationTaskHook MPU_xTaskCallApplicationTaskHook - #define xTaskGetIdleTaskHandle MPU_xTaskGetIdleTaskHandle - #define uxTaskGetSystemState MPU_uxTaskGetSystemState - #define vTaskList MPU_vTaskList - #define vTaskGetRunTimeStats MPU_vTaskGetRunTimeStats - #define ulTaskGetIdleRunTimeCounter MPU_ulTaskGetIdleRunTimeCounter - #define xTaskGenericNotify MPU_xTaskGenericNotify - #define xTaskNotifyWait MPU_xTaskNotifyWait - #define ulTaskNotifyTake MPU_ulTaskNotifyTake - #define xTaskNotifyStateClear MPU_xTaskNotifyStateClear - #define xTaskCatchUpTicks MPU_xTaskCatchUpTicks +/* Map standard tasks.h API functions to the MPU equivalents. */ + #define xTaskCreate MPU_xTaskCreate + #define xTaskCreateStatic MPU_xTaskCreateStatic + #define xTaskCreateRestricted MPU_xTaskCreateRestricted + #define vTaskAllocateMPURegions MPU_vTaskAllocateMPURegions + #define vTaskDelete MPU_vTaskDelete + #define vTaskDelay MPU_vTaskDelay + #define vTaskDelayUntil MPU_vTaskDelayUntil + #define xTaskAbortDelay MPU_xTaskAbortDelay + #define uxTaskPriorityGet MPU_uxTaskPriorityGet + #define eTaskGetState MPU_eTaskGetState + #define vTaskGetInfo MPU_vTaskGetInfo + #define vTaskPrioritySet MPU_vTaskPrioritySet + #define vTaskSuspend MPU_vTaskSuspend + #define vTaskResume MPU_vTaskResume + #define vTaskSuspendAll MPU_vTaskSuspendAll + #define xTaskResumeAll MPU_xTaskResumeAll + #define xTaskGetTickCount MPU_xTaskGetTickCount + #define uxTaskGetNumberOfTasks MPU_uxTaskGetNumberOfTasks + #define pcTaskGetName MPU_pcTaskGetName + #define xTaskGetHandle MPU_xTaskGetHandle + #define uxTaskGetStackHighWaterMark MPU_uxTaskGetStackHighWaterMark + #define uxTaskGetStackHighWaterMark2 MPU_uxTaskGetStackHighWaterMark2 + #define vTaskSetApplicationTaskTag MPU_vTaskSetApplicationTaskTag + #define xTaskGetApplicationTaskTag MPU_xTaskGetApplicationTaskTag + // #define vTaskSetThreadLocalStoragePointer MPU_vTaskSetThreadLocalStoragePointer + // #define pvTaskGetThreadLocalStoragePointer MPU_pvTaskGetThreadLocalStoragePointer + #define xTaskCallApplicationTaskHook MPU_xTaskCallApplicationTaskHook + #define xTaskGetIdleTaskHandle MPU_xTaskGetIdleTaskHandle + #define uxTaskGetSystemState MPU_uxTaskGetSystemState + #define vTaskList MPU_vTaskList + #define vTaskGetRunTimeStats MPU_vTaskGetRunTimeStats + #define ulTaskGetIdleRunTimeCounter MPU_ulTaskGetIdleRunTimeCounter + #define xTaskGenericNotify MPU_xTaskGenericNotify + #define xTaskNotifyWait MPU_xTaskNotifyWait + #define ulTaskNotifyTake MPU_ulTaskNotifyTake + #define xTaskNotifyStateClear MPU_xTaskNotifyStateClear + #define xTaskCatchUpTicks MPU_xTaskCatchUpTicks - #define xTaskGetCurrentTaskHandle MPU_xTaskGetCurrentTaskHandle - #define vTaskSetTimeOutState MPU_vTaskSetTimeOutState - #define xTaskCheckForTimeOut MPU_xTaskCheckForTimeOut - #define xTaskGetSchedulerState MPU_xTaskGetSchedulerState + #define xTaskGetCurrentTaskHandle MPU_xTaskGetCurrentTaskHandle + #define vTaskSetTimeOutState MPU_vTaskSetTimeOutState + #define xTaskCheckForTimeOut MPU_xTaskCheckForTimeOut + #define xTaskGetSchedulerState MPU_xTaskGetSchedulerState - /* Map standard queue.h API functions to the MPU equivalents. */ - #define xQueueGenericSend MPU_xQueueGenericSend - #define xQueueReceive MPU_xQueueReceive - #define xQueuePeek MPU_xQueuePeek - #define xQueueSemaphoreTake MPU_xQueueSemaphoreTake - #define uxQueueMessagesWaiting MPU_uxQueueMessagesWaiting - #define uxQueueSpacesAvailable MPU_uxQueueSpacesAvailable - #define vQueueDelete MPU_vQueueDelete - #define xQueueCreateMutex MPU_xQueueCreateMutex - #define xQueueCreateMutexStatic MPU_xQueueCreateMutexStatic - #define xQueueCreateCountingSemaphore MPU_xQueueCreateCountingSemaphore - #define xQueueCreateCountingSemaphoreStatic MPU_xQueueCreateCountingSemaphoreStatic - #define xQueueGetMutexHolder MPU_xQueueGetMutexHolder - #define xQueueTakeMutexRecursive MPU_xQueueTakeMutexRecursive - #define xQueueGiveMutexRecursive MPU_xQueueGiveMutexRecursive - #define xQueueGenericCreate MPU_xQueueGenericCreate - #define xQueueGenericCreateStatic MPU_xQueueGenericCreateStatic - #define xQueueCreateSet MPU_xQueueCreateSet - #define xQueueAddToSet MPU_xQueueAddToSet - #define xQueueRemoveFromSet MPU_xQueueRemoveFromSet - #define xQueueSelectFromSet MPU_xQueueSelectFromSet - #define xQueueGenericReset MPU_xQueueGenericReset + /* Map standard queue.h API functions to the MPU equivalents. */ + #define xQueueGenericSend MPU_xQueueGenericSend + #define xQueueReceive MPU_xQueueReceive + #define xQueuePeek MPU_xQueuePeek + #define xQueueSemaphoreTake MPU_xQueueSemaphoreTake + #define uxQueueMessagesWaiting MPU_uxQueueMessagesWaiting + #define uxQueueSpacesAvailable MPU_uxQueueSpacesAvailable + #define vQueueDelete MPU_vQueueDelete + #define xQueueCreateMutex MPU_xQueueCreateMutex + #define xQueueCreateMutexStatic MPU_xQueueCreateMutexStatic + #define xQueueCreateCountingSemaphore MPU_xQueueCreateCountingSemaphore + #define xQueueCreateCountingSemaphoreStatic MPU_xQueueCreateCountingSemaphoreStatic + #define xQueueGetMutexHolder MPU_xQueueGetMutexHolder + #define xQueueTakeMutexRecursive MPU_xQueueTakeMutexRecursive + #define xQueueGiveMutexRecursive MPU_xQueueGiveMutexRecursive + #define xQueueGenericCreate MPU_xQueueGenericCreate + #define xQueueGenericCreateStatic MPU_xQueueGenericCreateStatic + #define xQueueCreateSet MPU_xQueueCreateSet + #define xQueueAddToSet MPU_xQueueAddToSet + #define xQueueRemoveFromSet MPU_xQueueRemoveFromSet + #define xQueueSelectFromSet MPU_xQueueSelectFromSet + #define xQueueGenericReset MPU_xQueueGenericReset - #if( configQUEUE_REGISTRY_SIZE > 0 ) - #define vQueueAddToRegistry MPU_vQueueAddToRegistry - #define vQueueUnregisterQueue MPU_vQueueUnregisterQueue - #define pcQueueGetName MPU_pcQueueGetName - #endif + #if ( configQUEUE_REGISTRY_SIZE > 0 ) + #define vQueueAddToRegistry MPU_vQueueAddToRegistry + #define vQueueUnregisterQueue MPU_vQueueUnregisterQueue + #define pcQueueGetName MPU_pcQueueGetName + #endif - /* Map standard timer.h API functions to the MPU equivalents. */ - #define xTimerCreate MPU_xTimerCreate - #define xTimerCreateStatic MPU_xTimerCreateStatic - #define pvTimerGetTimerID MPU_pvTimerGetTimerID - #define vTimerSetTimerID MPU_vTimerSetTimerID - #define xTimerIsTimerActive MPU_xTimerIsTimerActive - #define xTimerGetTimerDaemonTaskHandle MPU_xTimerGetTimerDaemonTaskHandle - #define xTimerPendFunctionCall MPU_xTimerPendFunctionCall - #define pcTimerGetName MPU_pcTimerGetName - #define vTimerSetReloadMode MPU_vTimerSetReloadMode - #define xTimerGetPeriod MPU_xTimerGetPeriod - #define xTimerGetExpiryTime MPU_xTimerGetExpiryTime - #define xTimerGenericCommand MPU_xTimerGenericCommand +/* Map standard timer.h API functions to the MPU equivalents. */ + #define xTimerCreate MPU_xTimerCreate + #define xTimerCreateStatic MPU_xTimerCreateStatic + #define pvTimerGetTimerID MPU_pvTimerGetTimerID + #define vTimerSetTimerID MPU_vTimerSetTimerID + #define xTimerIsTimerActive MPU_xTimerIsTimerActive + #define xTimerGetTimerDaemonTaskHandle MPU_xTimerGetTimerDaemonTaskHandle + #define xTimerPendFunctionCall MPU_xTimerPendFunctionCall + #define pcTimerGetName MPU_pcTimerGetName + #define vTimerSetReloadMode MPU_vTimerSetReloadMode + #define xTimerGetPeriod MPU_xTimerGetPeriod + #define xTimerGetExpiryTime MPU_xTimerGetExpiryTime + #define xTimerGenericCommand MPU_xTimerGenericCommand - /* Map standard event_group.h API functions to the MPU equivalents. */ - #define xEventGroupCreate MPU_xEventGroupCreate - #define xEventGroupCreateStatic MPU_xEventGroupCreateStatic - #define xEventGroupWaitBits MPU_xEventGroupWaitBits - #define xEventGroupClearBits MPU_xEventGroupClearBits - #define xEventGroupSetBits MPU_xEventGroupSetBits - #define xEventGroupSync MPU_xEventGroupSync - #define vEventGroupDelete MPU_vEventGroupDelete +/* Map standard event_group.h API functions to the MPU equivalents. */ + #define xEventGroupCreate MPU_xEventGroupCreate + #define xEventGroupCreateStatic MPU_xEventGroupCreateStatic + #define xEventGroupWaitBits MPU_xEventGroupWaitBits + #define xEventGroupClearBits MPU_xEventGroupClearBits + #define xEventGroupSetBits MPU_xEventGroupSetBits + #define xEventGroupSync MPU_xEventGroupSync + #define vEventGroupDelete MPU_vEventGroupDelete - /* Map standard message/stream_buffer.h API functions to the MPU - equivalents. */ - #define xStreamBufferSend MPU_xStreamBufferSend - #define xStreamBufferReceive MPU_xStreamBufferReceive - #define xStreamBufferNextMessageLengthBytes MPU_xStreamBufferNextMessageLengthBytes - #define vStreamBufferDelete MPU_vStreamBufferDelete - #define xStreamBufferIsFull MPU_xStreamBufferIsFull - #define xStreamBufferIsEmpty MPU_xStreamBufferIsEmpty - #define xStreamBufferReset MPU_xStreamBufferReset - #define xStreamBufferSpacesAvailable MPU_xStreamBufferSpacesAvailable - #define xStreamBufferBytesAvailable MPU_xStreamBufferBytesAvailable - #define xStreamBufferSetTriggerLevel MPU_xStreamBufferSetTriggerLevel - #define xStreamBufferGenericCreate MPU_xStreamBufferGenericCreate - #define xStreamBufferGenericCreateStatic MPU_xStreamBufferGenericCreateStatic +/* Map standard message/stream_buffer.h API functions to the MPU + * equivalents. */ + #define xStreamBufferSend MPU_xStreamBufferSend + #define xStreamBufferReceive MPU_xStreamBufferReceive + #define xStreamBufferNextMessageLengthBytes MPU_xStreamBufferNextMessageLengthBytes + #define vStreamBufferDelete MPU_vStreamBufferDelete + #define xStreamBufferIsFull MPU_xStreamBufferIsFull + #define xStreamBufferIsEmpty MPU_xStreamBufferIsEmpty + #define xStreamBufferReset MPU_xStreamBufferReset + #define xStreamBufferSpacesAvailable MPU_xStreamBufferSpacesAvailable + #define xStreamBufferBytesAvailable MPU_xStreamBufferBytesAvailable + #define xStreamBufferSetTriggerLevel MPU_xStreamBufferSetTriggerLevel + #define xStreamBufferGenericCreate MPU_xStreamBufferGenericCreate + #define xStreamBufferGenericCreateStatic MPU_xStreamBufferGenericCreateStatic - /* Remove the privileged function macro, but keep the PRIVILEGED_DATA - macro so applications can place data in privileged access sections - (useful when using statically allocated objects). */ - #define PRIVILEGED_FUNCTION - #define PRIVILEGED_DATA __attribute__((section("privileged_data"))) - #define FREERTOS_SYSTEM_CALL +/* Remove the privileged function macro, but keep the PRIVILEGED_DATA + * macro so applications can place data in privileged access sections + * (useful when using statically allocated objects). */ + #define PRIVILEGED_FUNCTION + #define PRIVILEGED_DATA __attribute__( ( section( "privileged_data" ) ) ) + #define FREERTOS_SYSTEM_CALL - #else /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */ + #else /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */ - /* Ensure API functions go in the privileged execution section. */ - #define PRIVILEGED_FUNCTION __attribute__((section("privileged_functions"))) - #define PRIVILEGED_DATA __attribute__((section("privileged_data"))) - #define FREERTOS_SYSTEM_CALL __attribute__((section( "freertos_system_calls"))) +/* Ensure API functions go in the privileged execution section. */ + #define PRIVILEGED_FUNCTION __attribute__( ( section( "privileged_functions" ) ) ) + #define PRIVILEGED_DATA __attribute__( ( section( "privileged_data" ) ) ) + #define FREERTOS_SYSTEM_CALL __attribute__( ( section( "freertos_system_calls" ) ) ) - #endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */ + #endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */ #else /* portUSING_MPU_WRAPPERS */ - #define PRIVILEGED_FUNCTION - #define PRIVILEGED_DATA - #define FREERTOS_SYSTEM_CALL - #define portUSING_MPU_WRAPPERS 0 + #define PRIVILEGED_FUNCTION + #define PRIVILEGED_DATA + #define FREERTOS_SYSTEM_CALL + #define portUSING_MPU_WRAPPERS 0 #endif /* portUSING_MPU_WRAPPERS */ diff --git a/components/freertos/include/freertos/portable.h b/components/freertos/include/freertos/portable.h index 0c39bb9f6d..acc337cb96 100644 --- a/components/freertos/include/freertos/portable.h +++ b/components/freertos/include/freertos/portable.h @@ -1,6 +1,6 @@ /* - * FreeRTOS Kernel V10.2.1 - * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V10.4.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * 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 @@ -19,10 +19,9 @@ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS * - * 1 tab == 4 spaces! */ /*----------------------------------------------------------- @@ -33,68 +32,70 @@ #define PORTABLE_H /* Each FreeRTOS port has a unique portmacro.h header file. Originally a -pre-processor definition was used to ensure the pre-processor found the correct -portmacro.h file for the port being used. That scheme was deprecated in favour -of setting the compiler's include path such that it found the correct -portmacro.h file - removing the need for the constant and allowing the -portmacro.h file to be located anywhere in relation to the port being used. -Purely for reasons of backward compatibility the old method is still valid, but -to make it clear that new projects should not use it, support for the port -specific constants has been moved into the deprecated_definitions.h header -file. */ + * pre-processor definition was used to ensure the pre-processor found the correct + * portmacro.h file for the port being used. That scheme was deprecated in favour + * of setting the compiler's include path such that it found the correct + * portmacro.h file - removing the need for the constant and allowing the + * portmacro.h file to be located anywhere in relation to the port being used. + * Purely for reasons of backward compatibility the old method is still valid, but + * to make it clear that new projects should not use it, support for the port + * specific constants has been moved into the deprecated_definitions.h header + * file. */ #include "deprecated_definitions.h" /* If portENTER_CRITICAL is not defined then including deprecated_definitions.h -did not result in a portmacro.h header file being included - and it should be -included here. In this case the path to the correct portmacro.h header file -must be set in the compiler's include path. */ + * did not result in a portmacro.h header file being included - and it should be + * included here. In this case the path to the correct portmacro.h header file + * must be set in the compiler's include path. */ #ifndef portENTER_CRITICAL - #include "freertos/portmacro.h" + #include "freertos/portmacro.h" #endif #if portBYTE_ALIGNMENT == 32 - #define portBYTE_ALIGNMENT_MASK ( 0x001f ) + #define portBYTE_ALIGNMENT_MASK ( 0x001f ) #endif #if portBYTE_ALIGNMENT == 16 - #define portBYTE_ALIGNMENT_MASK ( 0x000f ) + #define portBYTE_ALIGNMENT_MASK ( 0x000f ) #endif #if portBYTE_ALIGNMENT == 8 - #define portBYTE_ALIGNMENT_MASK ( 0x0007 ) + #define portBYTE_ALIGNMENT_MASK ( 0x0007 ) #endif #if portBYTE_ALIGNMENT == 4 - #define portBYTE_ALIGNMENT_MASK ( 0x0003 ) + #define portBYTE_ALIGNMENT_MASK ( 0x0003 ) #endif #if portBYTE_ALIGNMENT == 2 - #define portBYTE_ALIGNMENT_MASK ( 0x0001 ) + #define portBYTE_ALIGNMENT_MASK ( 0x0001 ) #endif #if portBYTE_ALIGNMENT == 1 - #define portBYTE_ALIGNMENT_MASK ( 0x0000 ) + #define portBYTE_ALIGNMENT_MASK ( 0x0000 ) #endif #ifndef portBYTE_ALIGNMENT_MASK - #error "Invalid portBYTE_ALIGNMENT definition" + #error "Invalid portBYTE_ALIGNMENT definition" #endif #ifndef portNUM_CONFIGURABLE_REGIONS - #define portNUM_CONFIGURABLE_REGIONS 1 + #define portNUM_CONFIGURABLE_REGIONS 1 #endif #ifndef portHAS_STACK_OVERFLOW_CHECKING - #define portHAS_STACK_OVERFLOW_CHECKING 0 + #define portHAS_STACK_OVERFLOW_CHECKING 0 #endif #ifndef portARCH_NAME - #define portARCH_NAME NULL + #define portARCH_NAME NULL #endif +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ #include "mpu_wrappers.h" @@ -104,40 +105,52 @@ extern "C" { * the order that the port expects to find them. * */ -#if( portUSING_MPU_WRAPPERS == 1 ) - #if( portHAS_STACK_OVERFLOW_CHECKING == 1 ) - StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, StackType_t *pxEndOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) PRIVILEGED_FUNCTION; - #else - StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) PRIVILEGED_FUNCTION; - #endif -#else - #if( portHAS_STACK_OVERFLOW_CHECKING == 1 ) - StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, StackType_t *pxEndOfStack, TaskFunction_t pxCode, void *pvParameters ) PRIVILEGED_FUNCTION; - #else - StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) PRIVILEGED_FUNCTION; - #endif +#if ( portUSING_MPU_WRAPPERS == 1 ) + #if ( portHAS_STACK_OVERFLOW_CHECKING == 1 ) + StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, + StackType_t * pxEndOfStack, + TaskFunction_t pxCode, + void * pvParameters, + BaseType_t xRunPrivileged ) PRIVILEGED_FUNCTION; + #else + StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, + TaskFunction_t pxCode, + void * pvParameters, + BaseType_t xRunPrivileged ) PRIVILEGED_FUNCTION; + #endif +#else /* if ( portUSING_MPU_WRAPPERS == 1 ) */ + #if ( portHAS_STACK_OVERFLOW_CHECKING == 1 ) + StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, + StackType_t * pxEndOfStack, + TaskFunction_t pxCode, + void * pvParameters ) PRIVILEGED_FUNCTION; + #else + StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, + TaskFunction_t pxCode, + void * pvParameters ) PRIVILEGED_FUNCTION; + #endif #endif #ifdef configUSE_FREERTOS_PROVIDED_HEAP /* Used by heap_5.c to define the start address and size of each memory region -that together comprise the total FreeRTOS heap space. */ + * that together comprise the total FreeRTOS heap space. */ typedef struct HeapRegion { - uint8_t *pucStartAddress; - size_t xSizeInBytes; + uint8_t * pucStartAddress; + size_t xSizeInBytes; } HeapRegion_t; /* Used to pass information about the heap out of vPortGetHeapStats(). */ typedef struct xHeapStats { - size_t xAvailableHeapSpaceInBytes; /* The total heap size currently available - this is the sum of all the free blocks, not the largest block that can be allocated. */ - size_t xSizeOfLargestFreeBlockInBytes; /* The maximum size, in bytes, of all the free blocks within the heap at the time vPortGetHeapStats() is called. */ - size_t xSizeOfSmallestFreeBlockInBytes; /* The minimum size, in bytes, of all the free blocks within the heap at the time vPortGetHeapStats() is called. */ - size_t xNumberOfFreeBlocks; /* The number of free memory blocks within the heap at the time vPortGetHeapStats() is called. */ - size_t xMinimumEverFreeBytesRemaining; /* The minimum amount of total free memory (sum of all free blocks) there has been in the heap since the system booted. */ - size_t xNumberOfSuccessfulAllocations; /* The number of calls to pvPortMalloc() that have returned a valid memory block. */ - size_t xNumberOfSuccessfulFrees; /* The number of calls to vPortFree() that has successfully freed a block of memory. */ + size_t xAvailableHeapSpaceInBytes; /* The total heap size currently available - this is the sum of all the free blocks, not the largest block that can be allocated. */ + size_t xSizeOfLargestFreeBlockInBytes; /* The maximum size, in bytes, of all the free blocks within the heap at the time vPortGetHeapStats() is called. */ + size_t xSizeOfSmallestFreeBlockInBytes; /* The minimum size, in bytes, of all the free blocks within the heap at the time vPortGetHeapStats() is called. */ + size_t xNumberOfFreeBlocks; /* The number of free memory blocks within the heap at the time vPortGetHeapStats() is called. */ + size_t xMinimumEverFreeBytesRemaining; /* The minimum amount of total free memory (sum of all free blocks) there has been in the heap since the system booted. */ + size_t xNumberOfSuccessfulAllocations; /* The number of calls to pvPortMalloc() that have returned a valid memory block. */ + size_t xNumberOfSuccessfulFrees; /* The number of calls to vPortFree() that has successfully freed a block of memory. */ } HeapStats_t; /* @@ -157,16 +170,24 @@ void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ) PRIVILEG * Returns a HeapStats_t structure filled with information about the current * heap state. */ -void vPortGetHeapStats( HeapStats_t *pxHeapStats ); +void vPortGetHeapStats( HeapStats_t * pxHeapStats ); + /* * Map to the memory management routines required for the port. */ -void *pvPortMalloc( size_t xSize ) PRIVILEGED_FUNCTION; -void vPortFree( void *pv ) PRIVILEGED_FUNCTION; +void * pvPortMalloc( size_t xSize ) PRIVILEGED_FUNCTION; +void vPortFree( void * pv ) PRIVILEGED_FUNCTION; void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION; size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION; size_t xPortGetMinimumEverFreeHeapSize( void ) PRIVILEGED_FUNCTION; +#if( configSTACK_ALLOCATION_FROM_SEPARATE_HEAP == 1 ) + void *pvPortMallocStack( size_t xSize ) PRIVILEGED_FUNCTION; + void vPortFreeStack( void *pv ) PRIVILEGED_FUNCTION; +#else + #define pvPortMallocStack pvPortMalloc + #define vPortFreeStack vPortFree +#endif #else // configUSE_FREERTOS_PROVIDED_HEAP /* @@ -196,8 +217,25 @@ BaseType_t xPortStartScheduler( void ) PRIVILEGED_FUNCTION; */ void vPortEndScheduler( void ) PRIVILEGED_FUNCTION; -#ifdef __cplusplus -} +/* + * The structures and methods of manipulating the MPU are contained within the + * port layer. + * + * Fills the xMPUSettings structure with the memory region information + * contained in xRegions. + */ +#if ( portUSING_MPU_WRAPPERS == 1 ) + struct xMEMORY_REGION; + void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings, + const struct xMEMORY_REGION * const xRegions, + StackType_t * pxBottomOfStack, + uint32_t ulStackDepth ) PRIVILEGED_FUNCTION; #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ + #endif /* PORTABLE_H */ diff --git a/components/freertos/include/freertos/projdefs.h b/components/freertos/include/freertos/projdefs.h index ce647fb6fb..ec8022ca0b 100644 --- a/components/freertos/include/freertos/projdefs.h +++ b/components/freertos/include/freertos/projdefs.h @@ -1,6 +1,6 @@ /* - * FreeRTOS Kernel V10.2.1 - * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V10.4.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * 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 @@ -19,10 +19,9 @@ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS * - * 1 tab == 4 spaces! */ #ifndef PROJDEFS_H @@ -32,95 +31,95 @@ * Defines the prototype to which task functions must conform. Defined in this * file to ensure the type is known before portable.h is included. */ -typedef void (*TaskFunction_t)( void * ); +typedef void (* TaskFunction_t)( void * ); /* Converts a time in milliseconds to a time in ticks. This macro can be -overridden by a macro of the same name defined in FreeRTOSConfig.h in case the -definition here is not suitable for your application. */ + * overridden by a macro of the same name defined in FreeRTOSConfig.h in case the + * definition here is not suitable for your application. */ #ifndef pdMS_TO_TICKS - #define pdMS_TO_TICKS( xTimeInMs ) ( ( TickType_t ) ( ( ( TickType_t ) ( xTimeInMs ) * ( TickType_t ) configTICK_RATE_HZ ) / ( TickType_t ) 1000 ) ) + #define pdMS_TO_TICKS( xTimeInMs ) ( ( TickType_t ) ( ( ( TickType_t ) ( xTimeInMs ) * ( TickType_t ) configTICK_RATE_HZ ) / ( TickType_t ) 1000U ) ) #endif - +#ifdef ESP_PLATFORM #ifndef pdTICKS_TO_MS - #define pdTICKS_TO_MS( xTicks ) ( ( uint32_t ) ( xTicks ) * 1000 / configTICK_RATE_HZ ) + #define pdTICKS_TO_MS( xTicks ) ( ( uint32_t ) ( xTicks ) * 1000 / configTICK_RATE_HZ ) #endif +#endif // ESP_PLATFORM +#define pdFALSE ( ( BaseType_t ) 0 ) +#define pdTRUE ( ( BaseType_t ) 1 ) -#define pdFALSE ( ( BaseType_t ) 0 ) -#define pdTRUE ( ( BaseType_t ) 1 ) - -#define pdPASS ( pdTRUE ) -#define pdFAIL ( pdFALSE ) -#define errQUEUE_EMPTY ( ( BaseType_t ) 0 ) -#define errQUEUE_FULL ( ( BaseType_t ) 0 ) +#define pdPASS ( pdTRUE ) +#define pdFAIL ( pdFALSE ) +#define errQUEUE_EMPTY ( ( BaseType_t ) 0 ) +#define errQUEUE_FULL ( ( BaseType_t ) 0 ) /* FreeRTOS error definitions. */ -#define errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ( -1 ) -#define errQUEUE_BLOCKED ( -4 ) -#define errQUEUE_YIELD ( -5 ) +#define errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ( -1 ) +#define errQUEUE_BLOCKED ( -4 ) +#define errQUEUE_YIELD ( -5 ) /* Macros used for basic data corruption checks. */ #ifndef configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES - #define configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES 0 + #define configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES 0 #endif -#if( configUSE_16_BIT_TICKS == 1 ) - #define pdINTEGRITY_CHECK_VALUE 0x5a5a +#if ( configUSE_16_BIT_TICKS == 1 ) + #define pdINTEGRITY_CHECK_VALUE 0x5a5a #else - #define pdINTEGRITY_CHECK_VALUE 0x5a5a5a5aUL + #define pdINTEGRITY_CHECK_VALUE 0x5a5a5a5aUL #endif /* The following errno values are used by FreeRTOS+ components, not FreeRTOS -itself. */ -#define pdFREERTOS_ERRNO_NONE 0 /* No errors */ -#define pdFREERTOS_ERRNO_ENOENT 2 /* No such file or directory */ -#define pdFREERTOS_ERRNO_EINTR 4 /* Interrupted system call */ -#define pdFREERTOS_ERRNO_EIO 5 /* I/O error */ -#define pdFREERTOS_ERRNO_ENXIO 6 /* No such device or address */ -#define pdFREERTOS_ERRNO_EBADF 9 /* Bad file number */ -#define pdFREERTOS_ERRNO_EAGAIN 11 /* No more processes */ -#define pdFREERTOS_ERRNO_EWOULDBLOCK 11 /* Operation would block */ -#define pdFREERTOS_ERRNO_ENOMEM 12 /* Not enough memory */ -#define pdFREERTOS_ERRNO_EACCES 13 /* Permission denied */ -#define pdFREERTOS_ERRNO_EFAULT 14 /* Bad address */ -#define pdFREERTOS_ERRNO_EBUSY 16 /* Mount device busy */ -#define pdFREERTOS_ERRNO_EEXIST 17 /* File exists */ -#define pdFREERTOS_ERRNO_EXDEV 18 /* Cross-device link */ -#define pdFREERTOS_ERRNO_ENODEV 19 /* No such device */ -#define pdFREERTOS_ERRNO_ENOTDIR 20 /* Not a directory */ -#define pdFREERTOS_ERRNO_EISDIR 21 /* Is a directory */ -#define pdFREERTOS_ERRNO_EINVAL 22 /* Invalid argument */ -#define pdFREERTOS_ERRNO_ENOSPC 28 /* No space left on device */ -#define pdFREERTOS_ERRNO_ESPIPE 29 /* Illegal seek */ -#define pdFREERTOS_ERRNO_EROFS 30 /* Read only file system */ -#define pdFREERTOS_ERRNO_EUNATCH 42 /* Protocol driver not attached */ -#define pdFREERTOS_ERRNO_EBADE 50 /* Invalid exchange */ -#define pdFREERTOS_ERRNO_EFTYPE 79 /* Inappropriate file type or format */ -#define pdFREERTOS_ERRNO_ENMFILE 89 /* No more files */ -#define pdFREERTOS_ERRNO_ENOTEMPTY 90 /* Directory not empty */ -#define pdFREERTOS_ERRNO_ENAMETOOLONG 91 /* File or path name too long */ -#define pdFREERTOS_ERRNO_EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ -#define pdFREERTOS_ERRNO_ENOBUFS 105 /* No buffer space available */ -#define pdFREERTOS_ERRNO_ENOPROTOOPT 109 /* Protocol not available */ -#define pdFREERTOS_ERRNO_EADDRINUSE 112 /* Address already in use */ -#define pdFREERTOS_ERRNO_ETIMEDOUT 116 /* Connection timed out */ -#define pdFREERTOS_ERRNO_EINPROGRESS 119 /* Connection already in progress */ -#define pdFREERTOS_ERRNO_EALREADY 120 /* Socket already connected */ -#define pdFREERTOS_ERRNO_EADDRNOTAVAIL 125 /* Address not available */ -#define pdFREERTOS_ERRNO_EISCONN 127 /* Socket is already connected */ -#define pdFREERTOS_ERRNO_ENOTCONN 128 /* Socket is not connected */ -#define pdFREERTOS_ERRNO_ENOMEDIUM 135 /* No medium inserted */ -#define pdFREERTOS_ERRNO_EILSEQ 138 /* An invalid UTF-16 sequence was encountered. */ -#define pdFREERTOS_ERRNO_ECANCELED 140 /* Operation canceled. */ + * itself. */ +#define pdFREERTOS_ERRNO_NONE 0 /* No errors */ +#define pdFREERTOS_ERRNO_ENOENT 2 /* No such file or directory */ +#define pdFREERTOS_ERRNO_EINTR 4 /* Interrupted system call */ +#define pdFREERTOS_ERRNO_EIO 5 /* I/O error */ +#define pdFREERTOS_ERRNO_ENXIO 6 /* No such device or address */ +#define pdFREERTOS_ERRNO_EBADF 9 /* Bad file number */ +#define pdFREERTOS_ERRNO_EAGAIN 11 /* No more processes */ +#define pdFREERTOS_ERRNO_EWOULDBLOCK 11 /* Operation would block */ +#define pdFREERTOS_ERRNO_ENOMEM 12 /* Not enough memory */ +#define pdFREERTOS_ERRNO_EACCES 13 /* Permission denied */ +#define pdFREERTOS_ERRNO_EFAULT 14 /* Bad address */ +#define pdFREERTOS_ERRNO_EBUSY 16 /* Mount device busy */ +#define pdFREERTOS_ERRNO_EEXIST 17 /* File exists */ +#define pdFREERTOS_ERRNO_EXDEV 18 /* Cross-device link */ +#define pdFREERTOS_ERRNO_ENODEV 19 /* No such device */ +#define pdFREERTOS_ERRNO_ENOTDIR 20 /* Not a directory */ +#define pdFREERTOS_ERRNO_EISDIR 21 /* Is a directory */ +#define pdFREERTOS_ERRNO_EINVAL 22 /* Invalid argument */ +#define pdFREERTOS_ERRNO_ENOSPC 28 /* No space left on device */ +#define pdFREERTOS_ERRNO_ESPIPE 29 /* Illegal seek */ +#define pdFREERTOS_ERRNO_EROFS 30 /* Read only file system */ +#define pdFREERTOS_ERRNO_EUNATCH 42 /* Protocol driver not attached */ +#define pdFREERTOS_ERRNO_EBADE 50 /* Invalid exchange */ +#define pdFREERTOS_ERRNO_EFTYPE 79 /* Inappropriate file type or format */ +#define pdFREERTOS_ERRNO_ENMFILE 89 /* No more files */ +#define pdFREERTOS_ERRNO_ENOTEMPTY 90 /* Directory not empty */ +#define pdFREERTOS_ERRNO_ENAMETOOLONG 91 /* File or path name too long */ +#define pdFREERTOS_ERRNO_EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define pdFREERTOS_ERRNO_ENOBUFS 105 /* No buffer space available */ +#define pdFREERTOS_ERRNO_ENOPROTOOPT 109 /* Protocol not available */ +#define pdFREERTOS_ERRNO_EADDRINUSE 112 /* Address already in use */ +#define pdFREERTOS_ERRNO_ETIMEDOUT 116 /* Connection timed out */ +#define pdFREERTOS_ERRNO_EINPROGRESS 119 /* Connection already in progress */ +#define pdFREERTOS_ERRNO_EALREADY 120 /* Socket already connected */ +#define pdFREERTOS_ERRNO_EADDRNOTAVAIL 125 /* Address not available */ +#define pdFREERTOS_ERRNO_EISCONN 127 /* Socket is already connected */ +#define pdFREERTOS_ERRNO_ENOTCONN 128 /* Socket is not connected */ +#define pdFREERTOS_ERRNO_ENOMEDIUM 135 /* No medium inserted */ +#define pdFREERTOS_ERRNO_EILSEQ 138 /* An invalid UTF-16 sequence was encountered. */ +#define pdFREERTOS_ERRNO_ECANCELED 140 /* Operation canceled. */ /* The following endian values are used by FreeRTOS+ components, not FreeRTOS -itself. */ -#define pdFREERTOS_LITTLE_ENDIAN 0 -#define pdFREERTOS_BIG_ENDIAN 1 + * itself. */ +#define pdFREERTOS_LITTLE_ENDIAN 0 +#define pdFREERTOS_BIG_ENDIAN 1 /* Re-defining endian values for generic naming. */ -#define pdLITTLE_ENDIAN pdFREERTOS_LITTLE_ENDIAN -#define pdBIG_ENDIAN pdFREERTOS_BIG_ENDIAN +#define pdLITTLE_ENDIAN pdFREERTOS_LITTLE_ENDIAN +#define pdBIG_ENDIAN pdFREERTOS_BIG_ENDIAN #endif /* PROJDEFS_H */ diff --git a/components/freertos/include/freertos/queue.h b/components/freertos/include/freertos/queue.h index 8c35465316..81cccc05df 100644 --- a/components/freertos/include/freertos/queue.h +++ b/components/freertos/include/freertos/queue.h @@ -1,6 +1,6 @@ /* - * FreeRTOS Kernel V10.2.1 - * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V10.4.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * 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 @@ -19,10 +19,9 @@ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS * - * 1 tab == 4 spaces! */ @@ -30,12 +29,14 @@ #define QUEUE_H #ifndef INC_FREERTOS_H - #error "include FreeRTOS.h" must appear in source files before "include queue.h" + #error "include FreeRTOS.h" must appear in source files before "include queue.h" #endif +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ #include "task.h" @@ -45,42 +46,64 @@ extern "C" { * xQueueSend(), xQueueReceive(), etc. */ struct QueueDefinition; /* Using old naming convention so as not to break kernel aware debuggers. */ -typedef struct QueueDefinition * QueueHandle_t; +typedef struct QueueDefinition * QueueHandle_t; /** * Type by which queue sets are referenced. For example, a call to * xQueueCreateSet() returns an xQueueSet variable that can then be used as a * parameter to xQueueSelectFromSet(), xQueueAddToSet(), etc. */ -typedef struct QueueDefinition * QueueSetHandle_t; +typedef struct QueueDefinition * QueueSetHandle_t; /** * Queue sets can contain both queues and semaphores, so the * QueueSetMemberHandle_t is defined as a type to be used where a parameter or * return value can be either an QueueHandle_t or an SemaphoreHandle_t. */ -typedef struct QueueDefinition * QueueSetMemberHandle_t; +typedef struct QueueDefinition * QueueSetMemberHandle_t; /** @cond */ /* For internal use only. */ -#define queueSEND_TO_BACK ( ( BaseType_t ) 0 ) -#define queueSEND_TO_FRONT ( ( BaseType_t ) 1 ) -#define queueOVERWRITE ( ( BaseType_t ) 2 ) +#define queueSEND_TO_BACK ( ( BaseType_t ) 0 ) +#define queueSEND_TO_FRONT ( ( BaseType_t ) 1 ) +#define queueOVERWRITE ( ( BaseType_t ) 2 ) /* For internal use only. These definitions *must* match those in queue.c. */ -#define queueQUEUE_TYPE_BASE ( ( uint8_t ) 0U ) -#define queueQUEUE_TYPE_SET ( ( uint8_t ) 0U ) -#define queueQUEUE_TYPE_MUTEX ( ( uint8_t ) 1U ) -#define queueQUEUE_TYPE_COUNTING_SEMAPHORE ( ( uint8_t ) 2U ) -#define queueQUEUE_TYPE_BINARY_SEMAPHORE ( ( uint8_t ) 3U ) -#define queueQUEUE_TYPE_RECURSIVE_MUTEX ( ( uint8_t ) 4U ) +#define queueQUEUE_TYPE_BASE ( ( uint8_t ) 0U ) +#define queueQUEUE_TYPE_SET ( ( uint8_t ) 0U ) +#define queueQUEUE_TYPE_MUTEX ( ( uint8_t ) 1U ) +#define queueQUEUE_TYPE_COUNTING_SEMAPHORE ( ( uint8_t ) 2U ) +#define queueQUEUE_TYPE_BINARY_SEMAPHORE ( ( uint8_t ) 3U ) +#define queueQUEUE_TYPE_RECURSIVE_MUTEX ( ( uint8_t ) 4U ) /** @endcond */ /** - * Creates a new queue instance. This allocates the storage required by the - * new queue and returns a handle for the queue. + * @cond + * queue. h + * @code{c} + * QueueHandle_t xQueueCreate( + * UBaseType_t uxQueueLength, + * UBaseType_t uxItemSize + * ); + * @endcode + * @endcond + * + * Creates a new queue instance, and returns a handle by which the new queue + * can be referenced. + * + * Internally, within the FreeRTOS implementation, queues use two blocks of + * memory. The first block is used to hold the queue's data structures. The + * second block is used to hold items placed into the queue. If a queue is + * created using xQueueCreate() then both blocks of memory are automatically + * dynamically allocated inside the xQueueCreate() function. (see + * https://www.FreeRTOS.org/a00111.html). If a queue is created using + * xQueueCreateStatic() then the application writer must provide the memory that + * will get used by the queue. xQueueCreateStatic() therefore allows a queue to + * be created without using any dynamic memory allocation. + * + * https://www.FreeRTOS.org/Embedded-RTOS-Queues.html * * @param uxQueueLength The maximum number of items that the queue can contain. * @@ -95,15 +118,15 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; * * Example usage: * @code{c} - * struct AMessage - * { + * struct AMessage + * { * char ucMessageID; * char ucData[ 20 ]; - * }; + * }; * - * void vATask( void *pvParameters ) - * { - * QueueHandle_t xQueue1, xQueue2; + * void vATask( void *pvParameters ) + * { + * QueueHandle_t xQueue1, xQueue2; * * // Create a queue capable of containing 10 uint32_t values. * xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) ); @@ -121,15 +144,29 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; * } * * // ... Rest of task code. - * } + * } * @endcode + * @cond + * \defgroup xQueueCreate xQueueCreate + * @endcond * \ingroup QueueManagement */ -#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) - #define xQueueCreate( uxQueueLength, uxItemSize ) xQueueGenericCreate( ( uxQueueLength ), ( uxItemSize ), ( queueQUEUE_TYPE_BASE ) ) +#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + #define xQueueCreate( uxQueueLength, uxItemSize ) xQueueGenericCreate( ( uxQueueLength ), ( uxItemSize ), ( queueQUEUE_TYPE_BASE ) ) #endif /** + * @cond + * queue. h + * @code{c} + * QueueHandle_t xQueueCreateStatic( + * UBaseType_t uxQueueLength, + * UBaseType_t uxItemSize, + * uint8_t *pucQueueStorageBuffer, + * StaticQueue_t *pxQueueBuffer + * ); + * @endcode + * @endcond * Creates a new queue instance, and returns a handle by which the new queue * can be referenced. * @@ -138,12 +175,12 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; * second block is used to hold items placed into the queue. If a queue is * created using xQueueCreate() then both blocks of memory are automatically * dynamically allocated inside the xQueueCreate() function. (see - * http://www.freertos.org/a00111.html). If a queue is created using + * https://www.FreeRTOS.org/a00111.html). If a queue is created using * xQueueCreateStatic() then the application writer must provide the memory that * will get used by the queue. xQueueCreateStatic() therefore allows a queue to * be created without using any dynamic memory allocation. * - * http://www.FreeRTOS.org/Embedded-RTOS-Queues.html + * https://www.FreeRTOS.org/Embedded-RTOS-Queues.html * * @param uxQueueLength The maximum number of items that the queue can contain. * @@ -184,7 +221,7 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; * * void vATask( void *pvParameters ) * { - * QueueHandle_t xQueue1; + * QueueHandle_t xQueue1; * * // Create a queue capable of containing 10 uint32_t values. * xQueue1 = xQueueCreate( QUEUE_LENGTH, // The number of items the queue can hold. @@ -198,13 +235,27 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; * // ... Rest of task code. * } * @endcode + * @cond + * \defgroup xQueueCreateStatic xQueueCreateStatic + * @endcond * \ingroup QueueManagement */ -#if( configSUPPORT_STATIC_ALLOCATION == 1 ) - #define xQueueCreateStatic( uxQueueLength, uxItemSize, pucQueueStorage, pxQueueBuffer ) xQueueGenericCreateStatic( ( uxQueueLength ), ( uxItemSize ), ( pucQueueStorage ), ( pxQueueBuffer ), ( queueQUEUE_TYPE_BASE ) ) +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + #define xQueueCreateStatic( uxQueueLength, uxItemSize, pucQueueStorage, pxQueueBuffer ) xQueueGenericCreateStatic( ( uxQueueLength ), ( uxItemSize ), ( pucQueueStorage ), ( pxQueueBuffer ), ( queueQUEUE_TYPE_BASE ) ) #endif /* configSUPPORT_STATIC_ALLOCATION */ /** + * @cond + * queue. h + * @code{c} + * BaseType_t xQueueSendToToFront( + * QueueHandle_t xQueue, + * const void *pvItemToQueue, + * TickType_t xTicksToWait + * ); + * @endcode + * @endcond + * * Post an item to the front of a queue. The item is queued by copy, not by * reference. This function must not be called from an interrupt service * routine. See xQueueSendFromISR () for an alternative which may be used @@ -227,18 +278,18 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; * * Example usage: * @code{c} - * struct AMessage - * { + * struct AMessage + * { * char ucMessageID; * char ucData[ 20 ]; - * } xMessage; + * } xMessage; * - * uint32_t ulVar = 10UL; + * uint32_t ulVar = 10UL; * - * void vATask( void *pvParameters ) - * { - * QueueHandle_t xQueue1, xQueue2; - * struct AMessage *pxMessage; + * void vATask( void *pvParameters ) + * { + * QueueHandle_t xQueue1, xQueue2; + * struct AMessage *pxMessage; * * // Create a queue capable of containing 10 uint32_t values. * xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) ); @@ -268,13 +319,28 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; * } * * // ... Rest of task code. - * } + * } * @endcode + * @cond + * \defgroup xQueueSend xQueueSend + * @endcond * \ingroup QueueManagement */ -#define xQueueSendToFront( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_FRONT ) +#define xQueueSendToFront( xQueue, pvItemToQueue, xTicksToWait ) \ + xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_FRONT ) /** + * @cond + * queue. h + * @code{c} + * BaseType_t xQueueSendToBack( + * QueueHandle_t xQueue, + * const void *pvItemToQueue, + * TickType_t xTicksToWait + * ); + * @endcode + * @endcond + * * This is a macro that calls xQueueGenericSend(). * * Post an item to the back of a queue. The item is queued by copy, not by @@ -299,18 +365,18 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; * * Example usage: * @code{c} - * struct AMessage - * { + * struct AMessage + * { * char ucMessageID; * char ucData[ 20 ]; - * } xMessage; + * } xMessage; * - * uint32_t ulVar = 10UL; + * uint32_t ulVar = 10UL; * - * void vATask( void *pvParameters ) - * { - * QueueHandle_t xQueue1, xQueue2; - * struct AMessage *pxMessage; + * void vATask( void *pvParameters ) + * { + * QueueHandle_t xQueue1, xQueue2; + * struct AMessage *pxMessage; * * // Create a queue capable of containing 10 uint32_t values. * xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) ); @@ -340,13 +406,28 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; * } * * // ... Rest of task code. - * } + * } * @endcode + * @cond + * \defgroup xQueueSend xQueueSend + * @endcond * \ingroup QueueManagement */ -#define xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK ) +#define xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait ) \ + xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK ) /** + * @cond + * queue. h + * @code{c} + * BaseType_t xQueueSend( + * QueueHandle_t xQueue, + * const void * pvItemToQueue, + * TickType_t xTicksToWait + * ); + * @endcode + * @endcond + * * This is a macro that calls xQueueGenericSend(). It is included for * backward compatibility with versions of FreeRTOS.org that did not * include the xQueueSendToFront() and xQueueSendToBack() macros. It is @@ -373,18 +454,18 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; * * Example usage: * @code{c} - * struct AMessage - * { + * struct AMessage + * { * char ucMessageID; * char ucData[ 20 ]; - * } xMessage; + * } xMessage; * - * uint32_t ulVar = 10UL; + * uint32_t ulVar = 10UL; * - * void vATask( void *pvParameters ) - * { - * QueueHandle_t xQueue1, xQueue2; - * struct AMessage *pxMessage; + * void vATask( void *pvParameters ) + * { + * QueueHandle_t xQueue1, xQueue2; + * struct AMessage *pxMessage; * * // Create a queue capable of containing 10 uint32_t values. * xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) ); @@ -414,13 +495,27 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; * } * * // ... Rest of task code. - * } + * } * @endcode + * @cond + * \defgroup xQueueSend xQueueSend + * @endcond * \ingroup QueueManagement */ -#define xQueueSend( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK ) +#define xQueueSend( xQueue, pvItemToQueue, xTicksToWait ) \ + xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK ) /** + * @cond + * queue. h + * @code{c} + * BaseType_t xQueueOverwrite( + * QueueHandle_t xQueue, + * const void * pvItemToQueue + * ); + * @endcode + * @endcond + * * Only for use with queues that have a length of one - so the queue is either * empty or full. * @@ -445,10 +540,10 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; * Example usage: * @code{c} * - * void vFunction( void *pvParameters ) - * { - * QueueHandle_t xQueue; - * uint32_t ulVarToSend, ulValReceived; + * void vFunction( void *pvParameters ) + * { + * QueueHandle_t xQueue; + * uint32_t ulVarToSend, ulValReceived; * * // Create a queue to hold one uint32_t value. It is strongly * // recommended *not* to use xQueueOverwrite() on queues that can @@ -490,12 +585,28 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; * // ... * } * @endcode + * @cond + * \defgroup xQueueOverwrite xQueueOverwrite + * @endcond * \ingroup QueueManagement */ -#define xQueueOverwrite( xQueue, pvItemToQueue ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), 0, queueOVERWRITE ) +#define xQueueOverwrite( xQueue, pvItemToQueue ) \ + xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), 0, queueOVERWRITE ) /** + * @cond + * queue. h + * @code{c} + * BaseType_t xQueueGenericSend( + * QueueHandle_t xQueue, + * const void * pvItemToQueue, + * TickType_t xTicksToWait + * BaseType_t xCopyPosition + * ); + * @endcode + * @endcond + * * It is preferred that the macros xQueueSend(), xQueueSendToFront() and * xQueueSendToBack() are used in place of calling this function directly. * @@ -524,18 +635,18 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; * * Example usage: * @code{c} - * struct AMessage - * { + * struct AMessage + * { * char ucMessageID; * char ucData[ 20 ]; - * } xMessage; + * } xMessage; * - * uint32_t ulVar = 10UL; + * uint32_t ulVar = 10UL; * - * void vATask( void *pvParameters ) - * { - * QueueHandle_t xQueue1, xQueue2; - * struct AMessage *pxMessage; + * void vATask( void *pvParameters ) + * { + * QueueHandle_t xQueue1, xQueue2; + * struct AMessage *pxMessage; * * // Create a queue capable of containing 10 uint32_t values. * xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) ); @@ -565,13 +676,30 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t; * } * * // ... Rest of task code. - * } + * } * @endcode + * @cond + * \defgroup xQueueSend xQueueSend + * @endcond * \ingroup QueueManagement */ -BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION; +BaseType_t xQueueGenericSend( QueueHandle_t xQueue, + const void * const pvItemToQueue, + TickType_t xTicksToWait, + const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION; /** + * @cond + * queue. h + * @code{c} + * BaseType_t xQueuePeek( + * QueueHandle_t xQueue, + * void * const pvBuffer, + * TickType_t xTicksToWait + * ); + * @endcode + * @endcond + * * Receive an item from a queue without removing the item from the queue. * The item is received by copy so a buffer of adequate size must be * provided. The number of bytes copied into the buffer was defined when @@ -592,7 +720,7 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQ * * @param xTicksToWait The maximum amount of time the task should block * waiting for an item to receive should the queue be empty at the time - * of the call. The time is defined in tick periods so the constant + * of the call. The time is defined in tick periods so the constant * portTICK_PERIOD_MS should be used to convert to real time if this is required. * xQueuePeek() will return immediately if xTicksToWait is 0 and the queue * is empty. @@ -602,18 +730,18 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQ * * Example usage: * @code{c} - * struct AMessage - * { + * struct AMessage + * { * char ucMessageID; * char ucData[ 20 ]; - * } xMessage; + * } xMessage; * - * QueueHandle_t xQueue; + * QueueHandle_t xQueue; * - * // Task to create a queue and post a value. - * void vATask( void *pvParameters ) - * { - * struct AMessage *pxMessage; + * // Task to create a queue and post a value. + * void vATask( void *pvParameters ) + * { + * struct AMessage *pxMessage; * * // Create a queue capable of containing 10 pointers to AMessage structures. * // These should be passed by pointer as they contain a lot of data. @@ -631,12 +759,12 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQ * xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 ); * * // ... Rest of task code. - * } + * } * - * // Task to peek the data from the queue. - * void vADifferentTask( void *pvParameters ) - * { - * struct AMessage *pxRxedMessage; + * // Task to peek the data from the queue. + * void vADifferentTask( void *pvParameters ) + * { + * struct AMessage *pxRxedMessage; * * if( xQueue != 0 ) * { @@ -650,13 +778,28 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQ * } * * // ... Rest of task code. - * } + * } * @endcode + * @cond + * \defgroup xQueuePeek xQueuePeek + * @endcond * \ingroup QueueManagement */ -BaseType_t xQueuePeek( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; +BaseType_t xQueuePeek( QueueHandle_t xQueue, + void * const pvBuffer, + TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; /** + * @cond + * queue. h + * @code{c} + * BaseType_t xQueuePeekFromISR( + * QueueHandle_t xQueue, + * void *pvBuffer, + * ); + * @endcode + * @endcond + * * A version of xQueuePeek() that can be called from an interrupt service * routine (ISR). * @@ -677,11 +820,26 @@ BaseType_t xQueuePeek( QueueHandle_t xQueue, void * const pvBuffer, TickType_t x * @return pdTRUE if an item was successfully received from the queue, * otherwise pdFALSE. * + * @cond + * \defgroup xQueuePeekFromISR xQueuePeekFromISR + * @endcond * \ingroup QueueManagement */ -BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, void * const pvBuffer ) PRIVILEGED_FUNCTION; +BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, + void * const pvBuffer ) PRIVILEGED_FUNCTION; /** + * @cond + * queue. h + * @code{c} + * BaseType_t xQueueReceive( + * QueueHandle_t xQueue, + * void *pvBuffer, + * TickType_t xTicksToWait + * ); + * @endcode + * @endcond + * * Receive an item from a queue. The item is received by copy so a buffer of * adequate size must be provided. The number of bytes copied into the buffer * was defined when the queue was created. @@ -699,7 +857,7 @@ BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, void * const pvBuffer ) PRIV * * @param xTicksToWait The maximum amount of time the task should block * waiting for an item to receive should the queue be empty at the time - * of the call. xQueueReceive() will return immediately if xTicksToWait + * of the call. xQueueReceive() will return immediately if xTicksToWait * is zero and the queue is empty. The time is defined in tick periods so the * constant portTICK_PERIOD_MS should be used to convert to real time if this is * required. @@ -709,72 +867,94 @@ BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, void * const pvBuffer ) PRIV * * Example usage: * @code{c} - * struct AMessage + * struct AMessage + * { + * char ucMessageID; + * char ucData[ 20 ]; + * } xMessage; + * + * QueueHandle_t xQueue; + * + * // Task to create a queue and post a value. + * void vATask( void *pvParameters ) + * { + * struct AMessage *pxMessage; + * + * // Create a queue capable of containing 10 pointers to AMessage structures. + * // These should be passed by pointer as they contain a lot of data. + * xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) ); + * if( xQueue == 0 ) * { - * char ucMessageID; - * char ucData[ 20 ]; - * } xMessage; - * - * QueueHandle_t xQueue; - * - * // Task to create a queue and post a value. - * void vATask( void *pvParameters ) - * { - * struct AMessage *pxMessage; - * - * // Create a queue capable of containing 10 pointers to AMessage structures. - * // These should be passed by pointer as they contain a lot of data. - * xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) ); - * if( xQueue == 0 ) - * { - * // Failed to create the queue. - * } - * - * // ... - * - * // Send a pointer to a struct AMessage object. Don't block if the - * // queue is already full. - * pxMessage = & xMessage; - * xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 ); - * - * // ... Rest of task code. + * // Failed to create the queue. * } * - * // Task to receive from the queue. - * void vADifferentTask( void *pvParameters ) + * // ... + * + * // Send a pointer to a struct AMessage object. Don't block if the + * // queue is already full. + * pxMessage = & xMessage; + * xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 ); + * + * // ... Rest of task code. + * } + * + * // Task to receive from the queue. + * void vADifferentTask( void *pvParameters ) + * { + * struct AMessage *pxRxedMessage; + * + * if( xQueue != 0 ) * { - * struct AMessage *pxRxedMessage; - * - * if( xQueue != 0 ) - * { - * // Receive a message on the created queue. Block for 10 ticks if a - * // message is not immediately available. - * if( xQueueReceive( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) ) - * { - * // pcRxedMessage now points to the struct AMessage variable posted - * // by vATask. - * } - * } - * - * // ... Rest of task code. + * // Receive a message on the created queue. Block for 10 ticks if a + * // message is not immediately available. + * if( xQueueReceive( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) ) + * { + * // pcRxedMessage now points to the struct AMessage variable posted + * // by vATask. + * } * } + * + * // ... Rest of task code. + * } * @endcode + * @cond + * \defgroup xQueueReceive xQueueReceive + * @endcond * \ingroup QueueManagement */ -BaseType_t xQueueReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; +BaseType_t xQueueReceive( QueueHandle_t xQueue, + void * const pvBuffer, + TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; /** + * @cond + * queue. h + * @code{c} + * UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue ); + * @endcode + * @endcond + * * Return the number of messages stored in a queue. * * @param xQueue A handle to the queue being queried. * * @return The number of messages available in the queue. * + * @cond + * \defgroup uxQueueMessagesWaiting uxQueueMessagesWaiting + * @endcond * \ingroup QueueManagement */ UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; /** + * @cond + * queue. h + * @code{c} + * UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue ); + * @endcode + * @endcond + * * Return the number of free spaces available in a queue. This is equal to the * number of items that can be sent to the queue before the queue becomes full * if no items are removed. @@ -783,21 +963,45 @@ UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue ) PRIVILEGED_FUNC * * @return The number of spaces available in the queue. * + * @cond + * \defgroup uxQueueMessagesWaiting uxQueueMessagesWaiting + * @endcond * \ingroup QueueManagement */ UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; /** + * @cond + * queue. h + * @code{c} + * void vQueueDelete( QueueHandle_t xQueue ); + * @endcode + * @endcond + * * Delete a queue - freeing all the memory allocated for storing of items * placed on the queue. * * @param xQueue A handle to the queue to be deleted. * + * @cond + * \defgroup vQueueDelete vQueueDelete + * @endcond * \ingroup QueueManagement */ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; /** + * @cond + * queue. h + * @code{c} + * BaseType_t xQueueSendToFrontFromISR( + * QueueHandle_t xQueue, + * const void *pvItemToQueue, + * BaseType_t *pxHigherPriorityTaskWoken + * ); + * @endcode + * @endcond + * * This is a macro that calls xQueueGenericSendFromISR(). * * Post an item to the front of a queue. It is safe to use this macro from @@ -826,38 +1030,54 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; * Example usage for buffered IO (where the ISR can obtain more than one value * per call): * @code{c} - * void vBufferISR( void ) + * void vBufferISR( void ) + * { + * char cIn; + * BaseType_t xHigherPrioritTaskWoken; + * + * // We have not woken a task at the start of the ISR. + * xHigherPriorityTaskWoken = pdFALSE; + * + * // Loop until the buffer is empty. + * do * { - * char cIn; - * BaseType_t xHigherPrioritTaskWoken; + * // Obtain a byte from the buffer. + * cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS ); * - * // We have not woken a task at the start of the ISR. - * xHigherPriorityTaskWoken = pdFALSE; + * // Post the byte. + * xQueueSendToFrontFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken ); * - * // Loop until the buffer is empty. - * do - * { - * // Obtain a byte from the buffer. - * cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS ); + * } while( portINPUT_BYTE( BUFFER_COUNT ) ); * - * // Post the byte. - * xQueueSendToFrontFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken ); - * - * } while( portINPUT_BYTE( BUFFER_COUNT ) ); - * - * // Now the buffer is empty we can switch context if necessary. - * if( xHigherPriorityTaskWoken ) - * { - * portYIELD_FROM_ISR (); - * } + * // Now the buffer is empty we can switch context if necessary. + * if( xHigherPriorityTaskWoken ) + * { + * portYIELD_FROM_ISR (); * } + * } * @endcode + * + * @cond + * \defgroup xQueueSendFromISR xQueueSendFromISR + * @endcond * \ingroup QueueManagement */ -#define xQueueSendToFrontFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_FRONT ) +#define xQueueSendToFrontFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) \ + xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_FRONT ) /** + * @cond + * queue. h + * @code{c} + * BaseType_t xQueueSendToBackFromISR( + * QueueHandle_t xQueue, + * const void *pvItemToQueue, + * BaseType_t *pxHigherPriorityTaskWoken + * ); + * @endcode + * @endcond + * * This is a macro that calls xQueueGenericSendFromISR(). * * Post an item to the back of a queue. It is safe to use this macro from @@ -886,37 +1106,53 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; * Example usage for buffered IO (where the ISR can obtain more than one value * per call): * @code{c} - * void vBufferISR( void ) + * void vBufferISR( void ) + * { + * char cIn; + * BaseType_t xHigherPriorityTaskWoken; + * + * // We have not woken a task at the start of the ISR. + * xHigherPriorityTaskWoken = pdFALSE; + * + * // Loop until the buffer is empty. + * do * { - * char cIn; - * BaseType_t xHigherPriorityTaskWoken; + * // Obtain a byte from the buffer. + * cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS ); * - * // We have not woken a task at the start of the ISR. - * xHigherPriorityTaskWoken = pdFALSE; + * // Post the byte. + * xQueueSendToBackFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken ); * - * // Loop until the buffer is empty. - * do - * { - * // Obtain a byte from the buffer. - * cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS ); + * } while( portINPUT_BYTE( BUFFER_COUNT ) ); * - * // Post the byte. - * xQueueSendToBackFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken ); - * - * } while( portINPUT_BYTE( BUFFER_COUNT ) ); - * - * // Now the buffer is empty we can switch context if necessary. - * if( xHigherPriorityTaskWoken ) - * { - * portYIELD_FROM_ISR (); - * } + * // Now the buffer is empty we can switch context if necessary. + * if( xHigherPriorityTaskWoken ) + * { + * portYIELD_FROM_ISR (); * } + * } * @endcode + * + * @cond + * \defgroup xQueueSendFromISR xQueueSendFromISR + * @endcond * \ingroup QueueManagement */ -#define xQueueSendToBackFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK ) +#define xQueueSendToBackFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) \ + xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK ) /** + * @cond + * queue. h + * @code{c} + * BaseType_t xQueueOverwriteFromISR( + * QueueHandle_t xQueue, + * const void * pvItemToQueue, + * BaseType_t *pxHigherPriorityTaskWoken + * ); + * @endcode + * @endcond + * * A version of xQueueOverwrite() that can be used in an interrupt service * routine (ISR). * @@ -947,15 +1183,16 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; * * Example usage: * @code{c} - * QueueHandle_t xQueue; * - * void vFunction( void *pvParameters ) - * { - * // Create a queue to hold one uint32_t value. It is strongly - * // recommended *not* to use xQueueOverwriteFromISR() on queues that can - * // contain more than one value, and doing so will trigger an assertion - * // if configASSERT() is defined. - * xQueue = xQueueCreate( 1, sizeof( uint32_t ) ); + * QueueHandle_t xQueue; + * + * void vFunction( void *pvParameters ) + * { + * // Create a queue to hold one uint32_t value. It is strongly + * // recommended *not* to use xQueueOverwriteFromISR() on queues that can + * // contain more than one value, and doing so will trigger an assertion + * // if configASSERT() is defined. + * xQueue = xQueueCreate( 1, sizeof( uint32_t ) ); * } * * void vAnInterruptHandler( void ) @@ -964,35 +1201,50 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; * BaseType_t xHigherPriorityTaskWoken = pdFALSE; * uint32_t ulVarToSend, ulValReceived; * - * // Write the value 10 to the queue using xQueueOverwriteFromISR(). - * ulVarToSend = 10; - * xQueueOverwriteFromISR( xQueue, &ulVarToSend, &xHigherPriorityTaskWoken ); + * // Write the value 10 to the queue using xQueueOverwriteFromISR(). + * ulVarToSend = 10; + * xQueueOverwriteFromISR( xQueue, &ulVarToSend, &xHigherPriorityTaskWoken ); * - * // The queue is full, but calling xQueueOverwriteFromISR() again will still - * // pass because the value held in the queue will be overwritten with the - * // new value. - * ulVarToSend = 100; - * xQueueOverwriteFromISR( xQueue, &ulVarToSend, &xHigherPriorityTaskWoken ); + * // The queue is full, but calling xQueueOverwriteFromISR() again will still + * // pass because the value held in the queue will be overwritten with the + * // new value. + * ulVarToSend = 100; + * xQueueOverwriteFromISR( xQueue, &ulVarToSend, &xHigherPriorityTaskWoken ); * - * // Reading from the queue will now return 100. + * // Reading from the queue will now return 100. * - * // ... + * // ... * - * if( xHigherPrioritytaskWoken == pdTRUE ) - * { - * // Writing to the queue caused a task to unblock and the unblocked task - * // has a priority higher than or equal to the priority of the currently - * // executing task (the task this interrupt interrupted). Perform a context - * // switch so this interrupt returns directly to the unblocked task. - * portYIELD_FROM_ISR(); // or portEND_SWITCHING_ISR() depending on the port. - * } + * if( xHigherPrioritytaskWoken == pdTRUE ) + * { + * // Writing to the queue caused a task to unblock and the unblocked task + * // has a priority higher than or equal to the priority of the currently + * // executing task (the task this interrupt interrupted). Perform a context + * // switch so this interrupt returns directly to the unblocked task. + * portYIELD_FROM_ISR(); // or portEND_SWITCHING_ISR() depending on the port. + * } * } * @endcode + * @cond + * \defgroup xQueueOverwriteFromISR xQueueOverwriteFromISR + * @endcond * \ingroup QueueManagement */ -#define xQueueOverwriteFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueOVERWRITE ) +#define xQueueOverwriteFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) \ + xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueOVERWRITE ) /** + * @cond + * queue. h + * @code{c} + * BaseType_t xQueueSendFromISR( + * QueueHandle_t xQueue, + * const void *pvItemToQueue, + * BaseType_t *pxHigherPriorityTaskWoken + * ); + * @endcode + * @endcond + * * This is a macro that calls xQueueGenericSendFromISR(). It is included * for backward compatibility with versions of FreeRTOS.org that did not * include the xQueueSendToBackFromISR() and xQueueSendToFrontFromISR() @@ -1024,40 +1276,57 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; * Example usage for buffered IO (where the ISR can obtain more than one value * per call): * @code{c} - * void vBufferISR( void ) + * void vBufferISR( void ) + * { + * char cIn; + * BaseType_t xHigherPriorityTaskWoken; + * + * // We have not woken a task at the start of the ISR. + * xHigherPriorityTaskWoken = pdFALSE; + * + * // Loop until the buffer is empty. + * do * { - * char cIn; - * BaseType_t xHigherPriorityTaskWoken; + * // Obtain a byte from the buffer. + * cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS ); * - * // We have not woken a task at the start of the ISR. - * xHigherPriorityTaskWoken = pdFALSE; + * // Post the byte. + * xQueueSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken ); * - * // Loop until the buffer is empty. - * do - * { - * // Obtain a byte from the buffer. - * cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS ); + * } while( portINPUT_BYTE( BUFFER_COUNT ) ); * - * // Post the byte. - * xQueueSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken ); - * - * } while( portINPUT_BYTE( BUFFER_COUNT ) ); - * - * // Now the buffer is empty we can switch context if necessary. - * if( xHigherPriorityTaskWoken ) - * { - * // Actual macro used here is port specific. - * portYIELD_FROM_ISR (); - * } + * // Now the buffer is empty we can switch context if necessary. + * if( xHigherPriorityTaskWoken ) + * { + * // Actual macro used here is port specific. + * portYIELD_FROM_ISR (); * } + * } * @endcode * + * @cond + * \defgroup xQueueSendFromISR xQueueSendFromISR + * @endcond * \ingroup QueueManagement */ -#define xQueueSendFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK ) +#define xQueueSendFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) \ + xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK ) +/** @cond */ /**@{*/ /** + * @cond + * queue. h + * @code{c} + * BaseType_t xQueueGenericSendFromISR( + * QueueHandle_t xQueue, + * const void *pvItemToQueue, + * BaseType_t *pxHigherPriorityTaskWoken, + * BaseType_t xCopyPosition + * ); + * @endcode + * @endcond + * * It is preferred that the macros xQueueSendFromISR(), * xQueueSendToFrontFromISR() and xQueueSendToBackFromISR() be used in place * of calling this function directly. xQueueGiveFromISR() is an @@ -1093,40 +1362,57 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; * Example usage for buffered IO (where the ISR can obtain more than one value * per call): * @code{c} - * void vBufferISR( void ) + * void vBufferISR( void ) + * { + * char cIn; + * BaseType_t xHigherPriorityTaskWokenByPost; + * + * // We have not woken a task at the start of the ISR. + * xHigherPriorityTaskWokenByPost = pdFALSE; + * + * // Loop until the buffer is empty. + * do * { - * char cIn; - * BaseType_t xHigherPriorityTaskWokenByPost; + * // Obtain a byte from the buffer. + * cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS ); * - * // We have not woken a task at the start of the ISR. - * xHigherPriorityTaskWokenByPost = pdFALSE; + * // Post each byte. + * xQueueGenericSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWokenByPost, queueSEND_TO_BACK ); * - * // Loop until the buffer is empty. - * do - * { - * // Obtain a byte from the buffer. - * cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS ); + * } while( portINPUT_BYTE( BUFFER_COUNT ) ); * - * // Post each byte. - * xQueueGenericSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWokenByPost, queueSEND_TO_BACK ); - * - * } while( portINPUT_BYTE( BUFFER_COUNT ) ); - * - * // Now the buffer is empty we can switch context if necessary. Note that the - * // name of the yield function required is port specific. - * if( xHigherPriorityTaskWokenByPost ) - * { - * taskYIELD_YIELD_FROM_ISR(); - * } + * // Now the buffer is empty we can switch context if necessary. Note that the + * // name of the yield function required is port specific. + * if( xHigherPriorityTaskWokenByPost ) + * { + * taskYIELD_YIELD_FROM_ISR(); * } + * } * @endcode + * * \ingroup QueueManagement */ -BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, const void * const pvItemToQueue, BaseType_t * const pxHigherPriorityTaskWoken, const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION; -BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; +BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, + const void * const pvItemToQueue, + BaseType_t * const pxHigherPriorityTaskWoken, + const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION; +BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, + BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; /**@}*/ +/** @endcond */ /** + * @cond + * queue. h + * @code{c} + * BaseType_t xQueueReceiveFromISR( + * QueueHandle_t xQueue, + * void *pvBuffer, + * BaseType_t *pxTaskWoken + * ); + * @endcode + * @endcond + * * Receive an item from a queue. It is safe to use this function from within an * interrupt service routine. * @@ -1146,63 +1432,69 @@ BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, BaseType_t * const pxHigherP * * Example usage: * @code{c} - * QueueHandle_t xQueue; * - * // Function to create a queue and post some values. - * void vAFunction( void *pvParameters ) + * QueueHandle_t xQueue; + * + * // Function to create a queue and post some values. + * void vAFunction( void *pvParameters ) + * { + * char cValueToPost; + * const TickType_t xTicksToWait = ( TickType_t )0xff; + * + * // Create a queue capable of containing 10 characters. + * xQueue = xQueueCreate( 10, sizeof( char ) ); + * if( xQueue == 0 ) * { - * char cValueToPost; - * const TickType_t xTicksToWait = ( TickType_t )0xff; - * - * // Create a queue capable of containing 10 characters. - * xQueue = xQueueCreate( 10, sizeof( char ) ); - * if( xQueue == 0 ) - * { - * // Failed to create the queue. - * } - * - * // ... - * - * // Post some characters that will be used within an ISR. If the queue - * // is full then this task will block for xTicksToWait ticks. - * cValueToPost = 'a'; - * xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait ); - * cValueToPost = 'b'; - * xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait ); - * - * // ... keep posting characters ... this task may block when the queue - * // becomes full. - * - * cValueToPost = 'c'; - * xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait ); + * // Failed to create the queue. * } * - * // ISR that outputs all the characters received on the queue. - * void vISR_Routine( void ) + * // ... + * + * // Post some characters that will be used within an ISR. If the queue + * // is full then this task will block for xTicksToWait ticks. + * cValueToPost = 'a'; + * xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait ); + * cValueToPost = 'b'; + * xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait ); + * + * // ... keep posting characters ... this task may block when the queue + * // becomes full. + * + * cValueToPost = 'c'; + * xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait ); + * } + * + * // ISR that outputs all the characters received on the queue. + * void vISR_Routine( void ) + * { + * BaseType_t xTaskWokenByReceive = pdFALSE; + * char cRxedChar; + * + * while( xQueueReceiveFromISR( xQueue, ( void * ) &cRxedChar, &xTaskWokenByReceive) ) * { - * BaseType_t xTaskWokenByReceive = pdFALSE; - * char cRxedChar; + * // A character was received. Output the character now. + * vOutputCharacter( cRxedChar ); * - * while( xQueueReceiveFromISR( xQueue, ( void * ) &cRxedChar, &xTaskWokenByReceive) ) - * { - * // A character was received. Output the character now. - * vOutputCharacter( cRxedChar ); - * - * // If removing the character from the queue woke the task that was - * // posting onto the queue cTaskWokenByReceive will have been set to - * // pdTRUE. No matter how many times this loop iterates only one - * // task will be woken. - * } - * - * if( cTaskWokenByPost != ( char ) pdFALSE; - * { - * taskYIELD (); - * } + * // If removing the character from the queue woke the task that was + * // posting onto the queue cTaskWokenByReceive will have been set to + * // pdTRUE. No matter how many times this loop iterates only one + * // task will be woken. * } + * + * if( cTaskWokenByPost != ( char ) pdFALSE; + * { + * taskYIELD (); + * } + * } * @endcode + * @cond + * \defgroup xQueueReceiveFromISR xQueueReceiveFromISR + * @endcond * \ingroup QueueManagement */ -BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, void * const pvBuffer, BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; +BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, + void * const pvBuffer, + BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; /* * Utilities to query queues that are safe to use from an ISR. These utilities @@ -1213,7 +1505,7 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUN UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; /** @cond */ -/** +/* * The functions defined above are for passing data to and from tasks. The * functions below are the equivalents for passing data to and from * co-routines. @@ -1222,10 +1514,18 @@ UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue ) PRIVILEG * should not be called directly from application code. Instead use the macro * wrappers defined within croutine.h. */ -BaseType_t xQueueCRSendFromISR( QueueHandle_t xQueue, const void *pvItemToQueue, BaseType_t xCoRoutinePreviouslyWoken ); -BaseType_t xQueueCRReceiveFromISR( QueueHandle_t xQueue, void *pvBuffer, BaseType_t *pxTaskWoken ); -BaseType_t xQueueCRSend( QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait ); -BaseType_t xQueueCRReceive( QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait ); +BaseType_t xQueueCRSendFromISR( QueueHandle_t xQueue, + const void * pvItemToQueue, + BaseType_t xCoRoutinePreviouslyWoken ); +BaseType_t xQueueCRReceiveFromISR( QueueHandle_t xQueue, + void * pvBuffer, + BaseType_t * pxTaskWoken ); +BaseType_t xQueueCRSend( QueueHandle_t xQueue, + const void * pvItemToQueue, + TickType_t xTicksToWait ); +BaseType_t xQueueCRReceive( QueueHandle_t xQueue, + void * pvBuffer, + TickType_t xTicksToWait ); /** * For internal use only. Use xSemaphoreCreateMutex(), @@ -1233,10 +1533,15 @@ BaseType_t xQueueCRReceive( QueueHandle_t xQueue, void *pvBuffer, TickType_t xTi * these functions directly. */ QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType ) PRIVILEGED_FUNCTION; -QueueHandle_t xQueueCreateMutexStatic( const uint8_t ucQueueType, StaticQueue_t *pxStaticQueue ) PRIVILEGED_FUNCTION; -QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount ) PRIVILEGED_FUNCTION; -QueueHandle_t xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount, StaticQueue_t *pxStaticQueue ) PRIVILEGED_FUNCTION; -BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; +QueueHandle_t xQueueCreateMutexStatic( const uint8_t ucQueueType, + StaticQueue_t * pxStaticQueue ) PRIVILEGED_FUNCTION; +QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, + const UBaseType_t uxInitialCount ) PRIVILEGED_FUNCTION; +QueueHandle_t xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, + const UBaseType_t uxInitialCount, + StaticQueue_t * pxStaticQueue ) PRIVILEGED_FUNCTION; +BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, + TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; TaskHandle_t xQueueGetMutexHolder( QueueHandle_t xSemaphore ) PRIVILEGED_FUNCTION; TaskHandle_t xQueueGetMutexHolderFromISR( QueueHandle_t xSemaphore ) PRIVILEGED_FUNCTION; @@ -1244,7 +1549,8 @@ TaskHandle_t xQueueGetMutexHolderFromISR( QueueHandle_t xSemaphore ) PRIVILEGED_ * For internal use only. Use xSemaphoreTakeMutexRecursive() or * xSemaphoreGiveMutexRecursive() instead of calling these functions directly. */ -BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; +BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex, + TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ) PRIVILEGED_FUNCTION; /** @endcond */ @@ -1253,7 +1559,7 @@ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ) PRIVILEGED_FUNCTION; * Reset a queue back to its original empty state. The return value is now * obsolete and is always set to pdPASS. */ -#define xQueueReset( xQueue ) xQueueGenericReset( xQueue, pdFALSE ) +#define xQueueReset( xQueue ) xQueueGenericReset( xQueue, pdFALSE ) /** * The registry is provided as a means for kernel aware debuggers to @@ -1277,8 +1583,9 @@ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ) PRIVILEGED_FUNCTION; * stores a pointer to the string - so the string must be persistent (global or * preferably in ROM/Flash), not on the stack. */ -#if( configQUEUE_REGISTRY_SIZE > 0 ) - void vQueueAddToRegistry( QueueHandle_t xQueue, const char *pcQueueName ) PRIVILEGED_FUNCTION; /**lint !e971 Unqualified char types are allowed for strings and single characters only. */ +#if ( configQUEUE_REGISTRY_SIZE > 0 ) + void vQueueAddToRegistry( QueueHandle_t xQueue, + const char * pcQueueName ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ #endif /** @@ -1291,8 +1598,8 @@ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ) PRIVILEGED_FUNCTION; * * @param xQueue The handle of the queue being removed from the registry. */ -#if( configQUEUE_REGISTRY_SIZE > 0 ) - void vQueueUnregisterQueue( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; +#if ( configQUEUE_REGISTRY_SIZE > 0 ) + void vQueueUnregisterQueue( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; #endif /** @@ -1306,26 +1613,32 @@ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ) PRIVILEGED_FUNCTION; * queue is returned. If the queue is not in the registry then NULL is * returned. */ -#if( configQUEUE_REGISTRY_SIZE > 0 ) - const char *pcQueueGetName( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; /**lint !e971 Unqualified char types are allowed for strings and single characters only. */ +#if ( configQUEUE_REGISTRY_SIZE > 0 ) + const char * pcQueueGetName( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ #endif /** - * Generic version of the function used to creaet a queue using dynamic memory + * Generic version of the function used to create a queue using dynamic memory * allocation. This is called by other functions and macros that create other * RTOS objects that use the queue structure as their base. */ -#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) - QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType ) PRIVILEGED_FUNCTION; +#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, + const UBaseType_t uxItemSize, + const uint8_t ucQueueType ) PRIVILEGED_FUNCTION; #endif /** - * Generic version of the function used to creaet a queue using dynamic memory + * Generic version of the function used to create a queue using dynamic memory * allocation. This is called by other functions and macros that create other * RTOS objects that use the queue structure as their base. */ -#if( configSUPPORT_STATIC_ALLOCATION == 1 ) - QueueHandle_t xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, StaticQueue_t *pxStaticQueue, const uint8_t ucQueueType ) PRIVILEGED_FUNCTION; +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + QueueHandle_t xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, + const UBaseType_t uxItemSize, + uint8_t * pucQueueStorage, + StaticQueue_t * pxStaticQueue, + const uint8_t ucQueueType ) PRIVILEGED_FUNCTION; #endif /** @@ -1342,7 +1655,7 @@ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ) PRIVILEGED_FUNCTION; * or semaphores contained in the set is in a state where a queue read or * semaphore take operation would be successful. * - * Note 1: See the documentation on http://wwwFreeRTOS.org/RTOS-queue-sets.html + * Note 1: See the documentation on https://www.FreeRTOS.org/RTOS-queue-sets.html * for reasons why queue sets are very rarely needed in practice as there are * simpler methods of blocking on multiple objects. * @@ -1400,7 +1713,8 @@ QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength ) PRIVILE * queue set because it is already a member of a different queue set then pdFAIL * is returned. */ -BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION; +BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, + QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION; /** * Removes a queue or semaphore from a queue set. A queue or semaphore can only @@ -1419,7 +1733,8 @@ BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHan * then pdPASS is returned. If the queue was not in the queue set, or the * queue (or semaphore) was not empty, then pdFAIL is returned. */ -BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION; +BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, + QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION; /** * xQueueSelectFromSet() selects from the members of a queue set a queue or @@ -1431,7 +1746,7 @@ BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueS * See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this * function. * - * Note 1: See the documentation on http://wwwFreeRTOS.org/RTOS-queue-sets.html + * Note 1: See the documentation on https://www.FreeRTOS.org/RTOS-queue-sets.html * for reasons why queue sets are very rarely needed in practice as there are * simpler methods of blocking on multiple objects. * @@ -1455,7 +1770,8 @@ BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueS * in the queue set that is available, or NULL if no such queue or semaphore * exists before before the specified block time expires. */ -QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; +QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, + const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; /** * A version of xQueueSelectFromSet() that can be used from an ISR. @@ -1465,16 +1781,22 @@ QueueSetMemberHandle_t xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet ) /** @cond */ /* Not public API functions. */ -void vQueueWaitForMessageRestricted( QueueHandle_t xQueue, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely ) PRIVILEGED_FUNCTION; -BaseType_t xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue ) PRIVILEGED_FUNCTION; -void vQueueSetQueueNumber( QueueHandle_t xQueue, UBaseType_t uxQueueNumber ) PRIVILEGED_FUNCTION; +void vQueueWaitForMessageRestricted( QueueHandle_t xQueue, + TickType_t xTicksToWait, + const BaseType_t xWaitIndefinitely ) PRIVILEGED_FUNCTION; +BaseType_t xQueueGenericReset( QueueHandle_t xQueue, + BaseType_t xNewQueue ) PRIVILEGED_FUNCTION; +void vQueueSetQueueNumber( QueueHandle_t xQueue, + UBaseType_t uxQueueNumber ) PRIVILEGED_FUNCTION; UBaseType_t uxQueueGetQueueNumber( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; uint8_t ucQueueGetQueueType( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; /** @endcond */ +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* QUEUE_H */ diff --git a/components/freertos/include/freertos/semphr.h b/components/freertos/include/freertos/semphr.h index 971d74d496..7e99c0b396 100644 --- a/components/freertos/include/freertos/semphr.h +++ b/components/freertos/include/freertos/semphr.h @@ -1,6 +1,6 @@ /* - * FreeRTOS Kernel V10.2.1 - * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V10.4.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * 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 @@ -19,35 +19,36 @@ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS * - * 1 tab == 4 spaces! */ #ifndef SEMAPHORE_H #define SEMAPHORE_H #ifndef INC_FREERTOS_H - #error "include FreeRTOS.h" must appear in source files before "include semphr.h" + #error "include FreeRTOS.h" must appear in source files before "include semphr.h" #endif #include "queue.h" typedef QueueHandle_t SemaphoreHandle_t; -#define semBINARY_SEMAPHORE_QUEUE_LENGTH ( ( uint8_t ) 1U ) -#define semSEMAPHORE_QUEUE_ITEM_LENGTH ( ( uint8_t ) 0U ) -#define semGIVE_BLOCK_TIME ( ( TickType_t ) 0U ) +#define semBINARY_SEMAPHORE_QUEUE_LENGTH ( ( uint8_t ) 1U ) +#define semSEMAPHORE_QUEUE_ITEM_LENGTH ( ( uint8_t ) 0U ) +#define semGIVE_BLOCK_TIME ( ( TickType_t ) 0U ) /** @cond */ /** * semphr. h - *
vSemaphoreCreateBinary( SemaphoreHandle_t xSemaphore )
+ * @code{c} + * vSemaphoreCreateBinary( SemaphoreHandle_t xSemaphore ); + * @endcode * * In many usage scenarios it is faster and more memory efficient to use a * direct to task notification in place of a binary semaphore! - * http://www.freertos.org/RTOS-task-notifications.html + * https://www.FreeRTOS.org/RTOS-task-notifications.html * * This old vSemaphoreCreateBinary() macro is now deprecated in favour of the * xSemaphoreCreateBinary() function. Note that binary semaphores created using @@ -72,48 +73,58 @@ typedef QueueHandle_t SemaphoreHandle_t; * * Example usage: * @code{c} - * SemaphoreHandle_t xSemaphore = NULL; + * SemaphoreHandle_t xSemaphore = NULL; * - * void vATask( void * pvParameters ) + * void vATask( void * pvParameters ) + * { + * // Semaphore cannot be used before a call to vSemaphoreCreateBinary (). + * // This is a macro so pass the variable in directly. + * vSemaphoreCreateBinary( xSemaphore ); + * + * if( xSemaphore != NULL ) * { - * // Semaphore cannot be used before a call to vSemaphoreCreateBinary (). - * // This is a macro so pass the variable in directly. - * vSemaphoreCreateBinary( xSemaphore ); - * - * if( xSemaphore != NULL ) - * { - * // The semaphore was created successfully. - * // The semaphore can now be used. - * } + * // The semaphore was created successfully. + * // The semaphore can now be used. * } + * } * @endcode + * @cond + * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary + * @endcond * \ingroup Semaphores */ -#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) - #define vSemaphoreCreateBinary( xSemaphore ) \ - { \ - ( xSemaphore ) = xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ); \ - if( ( xSemaphore ) != NULL ) \ - { \ - ( void ) xSemaphoreGive( ( xSemaphore ) ); \ - } \ - } +#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + #define vSemaphoreCreateBinary( xSemaphore ) \ + { \ + ( xSemaphore ) = xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ); \ + if( ( xSemaphore ) != NULL ) \ + { \ + ( void ) xSemaphoreGive( ( xSemaphore ) ); \ + } \ + } #endif /** @endcond */ /** + * @cond + * semphr. h + * @code{c} + * SemaphoreHandle_t xSemaphoreCreateBinary( void ); + * @endcode + * @endcond + * * Creates a new binary semaphore instance, and returns a handle by which the * new semaphore can be referenced. * * In many usage scenarios it is faster and more memory efficient to use a * direct to task notification in place of a binary semaphore! - * http://www.freertos.org/RTOS-task-notifications.html + * https://www.FreeRTOS.org/RTOS-task-notifications.html * * Internally, within the FreeRTOS implementation, binary semaphores use a block * of memory, in which the semaphore structure is stored. If a binary semaphore * is created using xSemaphoreCreateBinary() then the required memory is * automatically dynamically allocated inside the xSemaphoreCreateBinary() - * function. (see http://www.freertos.org/a00111.html). If a binary semaphore + * function. (see https://www.FreeRTOS.org/a00111.html). If a binary semaphore * is created using xSemaphoreCreateBinaryStatic() then the application writer * must provide the memory. xSemaphoreCreateBinaryStatic() therefore allows a * binary semaphore to be created without using any dynamic memory allocation. @@ -137,40 +148,50 @@ typedef QueueHandle_t SemaphoreHandle_t; * * Example usage: * @code{c} - * SemaphoreHandle_t xSemaphore = NULL; + * SemaphoreHandle_t xSemaphore = NULL; * - * void vATask( void * pvParameters ) + * void vATask( void * pvParameters ) + * { + * // Semaphore cannot be used before a call to vSemaphoreCreateBinary(). + * // This is a macro so pass the variable in directly. + * xSemaphore = xSemaphoreCreateBinary(); + * + * if( xSemaphore != NULL ) * { - * // Semaphore cannot be used before a call to vSemaphoreCreateBinary (). - * // This is a macro so pass the variable in directly. - * xSemaphore = xSemaphoreCreateBinary(); - * - * if( xSemaphore != NULL ) - * { - * // The semaphore was created successfully. - * // The semaphore can now be used. - * } + * // The semaphore was created successfully. + * // The semaphore can now be used. * } + * } * @endcode + * @cond + * \defgroup xSemaphoreCreateBinary xSemaphoreCreateBinary + * @endcond * \ingroup Semaphores */ -#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) - #define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ) +#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + #define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ) #endif /** + * @cond + * semphr. h + * @code{c} + * SemaphoreHandle_t xSemaphoreCreateBinaryStatic( StaticSemaphore_t *pxSemaphoreBuffer ); + * @endcode + * @endcond + * * Creates a new binary semaphore instance, and returns a handle by which the * new semaphore can be referenced. * * NOTE: In many usage scenarios it is faster and more memory efficient to use a * direct to task notification in place of a binary semaphore! - * http://www.freertos.org/RTOS-task-notifications.html + * https://www.FreeRTOS.org/RTOS-task-notifications.html * * Internally, within the FreeRTOS implementation, binary semaphores use a block * of memory, in which the semaphore structure is stored. If a binary semaphore * is created using xSemaphoreCreateBinary() then the required memory is * automatically dynamically allocated inside the xSemaphoreCreateBinary() - * function. (see http://www.freertos.org/a00111.html). If a binary semaphore + * function. (see https://www.FreeRTOS.org/a00111.html). If a binary semaphore * is created using xSemaphoreCreateBinaryStatic() then the application writer * must provide the memory. xSemaphoreCreateBinaryStatic() therefore allows a * binary semaphore to be created without using any dynamic memory allocation. @@ -191,38 +212,51 @@ typedef QueueHandle_t SemaphoreHandle_t; * * Example usage: * @code{c} - * SemaphoreHandle_t xSemaphore = NULL; - * StaticSemaphore_t xSemaphoreBuffer; + * SemaphoreHandle_t xSemaphore = NULL; + * StaticSemaphore_t xSemaphoreBuffer; * - * void vATask( void * pvParameters ) - * { - * // Semaphore cannot be used before a call to xSemaphoreCreateBinary() or - * // xSemaphoreCreateBinaryStatic(). - * // The semaphore's data structures will be placed in the xSemaphoreBuffer - * // variable, the address of which is passed into the function. The - * // function's parameter is not NULL, so the function will not attempt any - * // dynamic memory allocation, and therefore the function will not return - * // return NULL. - * xSemaphore = xSemaphoreCreateBinaryStatic( &xSemaphoreBuffer ); + * void vATask( void * pvParameters ) + * { + * // Semaphore cannot be used before a call to xSemaphoreCreateBinary() or + * // xSemaphoreCreateBinaryStatic(). + * // The semaphore's data structures will be placed in the xSemaphoreBuffer + * // variable, the address of which is passed into the function. The + * // function's parameter is not NULL, so the function will not attempt any + * // dynamic memory allocation, and therefore the function will not return + * // return NULL. + * xSemaphore = xSemaphoreCreateBinaryStatic( &xSemaphoreBuffer ); * - * // Rest of task code goes here. - * } + * // Rest of task code goes here. + * } * @endcode + * @cond + * \defgroup xSemaphoreCreateBinaryStatic xSemaphoreCreateBinaryStatic + * @endcond * \ingroup Semaphores */ -#if( configSUPPORT_STATIC_ALLOCATION == 1 ) - #define xSemaphoreCreateBinaryStatic( pxStaticSemaphore ) xQueueGenericCreateStatic( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticSemaphore, queueQUEUE_TYPE_BINARY_SEMAPHORE ) +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + #define xSemaphoreCreateBinaryStatic( pxStaticSemaphore ) xQueueGenericCreateStatic( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticSemaphore, queueQUEUE_TYPE_BINARY_SEMAPHORE ) #endif /* configSUPPORT_STATIC_ALLOCATION */ /** + * @cond + * semphr. h + * @code{c} + * xSemaphoreTake( + * SemaphoreHandle_t xSemaphore, + * TickType_t xBlockTime + * ); + * @endcode + * @endcond + * * Macro to obtain a semaphore. The semaphore must have previously been * created with a call to xSemaphoreCreateBinary(), xSemaphoreCreateMutex() or * xSemaphoreCreateCounting(). * - * @param xSemaphore A handle to the semaphore being taken - obtained when + * param xSemaphore A handle to the semaphore being taken - obtained when * the semaphore was created. * - * @param xBlockTime The time in ticks to wait for the semaphore to become + * param xBlockTime The time in ticks to wait for the semaphore to become * available. The macro portTICK_PERIOD_MS can be used to convert this to a * real time. A block time of zero can be used to poll the semaphore. A block * time of portMAX_DELAY can be used to block indefinitely (provided @@ -233,48 +267,61 @@ typedef QueueHandle_t SemaphoreHandle_t; * * Example usage: * @code{c} - * SemaphoreHandle_t xSemaphore = NULL; + * SemaphoreHandle_t xSemaphore = NULL; * - * // A task that creates a semaphore. - * void vATask( void * pvParameters ) + * // A task that creates a semaphore. + * void vATask( void * pvParameters ) + * { + * // Create the semaphore to guard a shared resource. + * vSemaphoreCreateBinary( xSemaphore ); + * } + * + * // A task that uses the semaphore. + * void vAnotherTask( void * pvParameters ) + * { + * // ... Do other things. + * + * if( xSemaphore != NULL ) * { - * // Create the semaphore to guard a shared resource. - * vSemaphoreCreateBinary( xSemaphore ); - * } - * - * // A task that uses the semaphore. - * void vAnotherTask( void * pvParameters ) - * { - * // ... Do other things. - * - * if( xSemaphore != NULL ) - * { - * // See if we can obtain the semaphore. If the semaphore is not available - * // wait 10 ticks to see if it becomes free. - * if( xSemaphoreTake( xSemaphore, ( TickType_t ) 10 ) == pdTRUE ) - * { - * // We were able to obtain the semaphore and can now access the - * // shared resource. - * - * // ... - * - * // We have finished accessing the shared resource. Release the - * // semaphore. - * xSemaphoreGive( xSemaphore ); - * } - * else - * { - * // We could not obtain the semaphore and can therefore not access - * // the shared resource safely. - * } - * } + * // See if we can obtain the semaphore. If the semaphore is not available + * // wait 10 ticks to see if it becomes free. + * if( xSemaphoreTake( xSemaphore, ( TickType_t ) 10 ) == pdTRUE ) + * { + * // We were able to obtain the semaphore and can now access the + * // shared resource. + * + * // ... + * + * // We have finished accessing the shared resource. Release the + * // semaphore. + * xSemaphoreGive( xSemaphore ); + * } + * else + * { + * // We could not obtain the semaphore and can therefore not access + * // the shared resource safely. + * } * } + * } * @endcode + * @cond + * \defgroup xSemaphoreTake xSemaphoreTake + * @endcond * \ingroup Semaphores */ -#define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueSemaphoreTake( ( xSemaphore ), ( xBlockTime ) ) +#define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueSemaphoreTake( ( xSemaphore ), ( xBlockTime ) ) /** + * @cond + * semphr. h + * @code{c} + * xSemaphoreTakeRecursive( + * SemaphoreHandle_t xMutex, + * TickType_t xBlockTime + * ); + * @endcode + * @endcond + * * Macro to recursively obtain, or 'take', a mutex type semaphore. * The mutex must have previously been created using a call to * xSemaphoreCreateRecursiveMutex(); @@ -305,76 +352,63 @@ typedef QueueHandle_t SemaphoreHandle_t; * * Example usage: * @code{c} - * SemaphoreHandle_t xMutex = NULL; + * SemaphoreHandle_t xMutex = NULL; * - * // A task that creates a mutex. - * void vATask( void * pvParameters ) + * // A task that creates a mutex. + * void vATask( void * pvParameters ) + * { + * // Create the mutex to guard a shared resource. + * xMutex = xSemaphoreCreateRecursiveMutex(); + * } + * + * // A task that uses the mutex. + * void vAnotherTask( void * pvParameters ) + * { + * // ... Do other things. + * + * if( xMutex != NULL ) * { - * // Create the mutex to guard a shared resource. - * xMutex = xSemaphoreCreateRecursiveMutex(); - * } - * - * // A task that uses the mutex. - * void vAnotherTask( void * pvParameters ) - * { - * // ... Do other things. - * - * if( xMutex != NULL ) - * { - * // See if we can obtain the mutex. If the mutex is not available - * // wait 10 ticks to see if it becomes free. - * if( xSemaphoreTakeRecursive( xSemaphore, ( TickType_t ) 10 ) == pdTRUE ) - * { - * // We were able to obtain the mutex and can now access the - * // shared resource. - * - * // ... - * // For some reason due to the nature of the code further calls to - * // xSemaphoreTakeRecursive() are made on the same mutex. In real - * // code these would not be just sequential calls as this would make - * // no sense. Instead the calls are likely to be buried inside - * // a more complex call structure. - * xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); - * xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); - * - * // The mutex has now been 'taken' three times, so will not be - * // available to another task until it has also been given back - * // three times. Again it is unlikely that real code would have - * // these calls sequentially, but instead buried in a more complex - * // call structure. This is just for illustrative purposes. - * xSemaphoreGiveRecursive( xMutex ); - * xSemaphoreGiveRecursive( xMutex ); - * xSemaphoreGiveRecursive( xMutex ); - * - * // Now the mutex can be taken by other tasks. - * } - * else - * { - * // We could not obtain the mutex and can therefore not access - * // the shared resource safely. - * } - * } + * // See if we can obtain the mutex. If the mutex is not available + * // wait 10 ticks to see if it becomes free. + * if( xSemaphoreTakeRecursive( xSemaphore, ( TickType_t ) 10 ) == pdTRUE ) + * { + * // We were able to obtain the mutex and can now access the + * // shared resource. + * + * // ... + * // For some reason due to the nature of the code further calls to + * // xSemaphoreTakeRecursive() are made on the same mutex. In real + * // code these would not be just sequential calls as this would make + * // no sense. Instead the calls are likely to be buried inside + * // a more complex call structure. + * xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); + * xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); + * + * // The mutex has now been 'taken' three times, so will not be + * // available to another task until it has also been given back + * // three times. Again it is unlikely that real code would have + * // these calls sequentially, but instead buried in a more complex + * // call structure. This is just for illustrative purposes. + * xSemaphoreGiveRecursive( xMutex ); + * xSemaphoreGiveRecursive( xMutex ); + * xSemaphoreGiveRecursive( xMutex ); + * + * // Now the mutex can be taken by other tasks. + * } + * else + * { + * // We could not obtain the mutex and can therefore not access + * // the shared resource safely. + * } * } + * } * @endcode + * @cond + * \defgroup xSemaphoreTakeRecursive xSemaphoreTakeRecursive + * @endcond * \ingroup Semaphores */ -#define xSemaphoreTakeRecursive( xMutex, xBlockTime ) xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) ) - -/** @cond */ -/* - * xSemaphoreAltTake() is an alternative version of xSemaphoreTake(). - * - * The source code that implements the alternative (Alt) API is much - * simpler because it executes everything from within a critical section. - * This is the approach taken by many other RTOSes, but FreeRTOS.org has the - * preferred fully featured API too. The fully featured API has more - * complex code that takes longer to execute, but makes much less use of - * critical sections. Therefore the alternative API sacrifices interrupt - * responsiveness to gain execution speed, whereas the fully featured API - * sacrifices execution speed to ensure better interrupt responsiveness. - */ -#define xSemaphoreAltTake( xSemaphore, xBlockTime ) xQueueAltGenericReceive( ( QueueHandle_t ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE ) -/** @endcond */ +#define xSemaphoreTakeRecursive( xMutex, xBlockTime ) xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) ) /** * Macro to release a semaphore. The semaphore must have previously been @@ -397,47 +431,54 @@ typedef QueueHandle_t SemaphoreHandle_t; * * Example usage: * @code{c} - * SemaphoreHandle_t xSemaphore = NULL; + * SemaphoreHandle_t xSemaphore = NULL; * - * void vATask( void * pvParameters ) + * void vATask( void * pvParameters ) + * { + * // Create the semaphore to guard a shared resource. + * vSemaphoreCreateBinary( xSemaphore ); + * + * if( xSemaphore != NULL ) * { - * // Create the semaphore to guard a shared resource. - * vSemaphoreCreateBinary( xSemaphore ); + * if( xSemaphoreGive( xSemaphore ) != pdTRUE ) + * { + * // We would expect this call to fail because we cannot give + * // a semaphore without first "taking" it! + * } * - * if( xSemaphore != NULL ) - * { - * if( xSemaphoreGive( xSemaphore ) != pdTRUE ) - * { - * // We would expect this call to fail because we cannot give - * // a semaphore without first "taking" it! - * } + * // Obtain the semaphore - don't block if the semaphore is not + * // immediately available. + * if( xSemaphoreTake( xSemaphore, ( TickType_t ) 0 ) ) + * { + * // We now have the semaphore and can access the shared resource. * - * // Obtain the semaphore - don't block if the semaphore is not - * // immediately available. - * if( xSemaphoreTake( xSemaphore, ( TickType_t ) 0 ) ) - * { - * // We now have the semaphore and can access the shared resource. + * // ... * - * // ... - * - * // We have finished accessing the shared resource so can free the - * // semaphore. - * if( xSemaphoreGive( xSemaphore ) != pdTRUE ) - * { - * // We would not expect this call to fail because we must have - * // obtained the semaphore to get here. - * } - * } - * } + * // We have finished accessing the shared resource so can free the + * // semaphore. + * if( xSemaphoreGive( xSemaphore ) != pdTRUE ) + * { + * // We would not expect this call to fail because we must have + * // obtained the semaphore to get here. + * } + * } * } + * } * @endcode + * @cond + * \defgroup xSemaphoreGive xSemaphoreGive + * @endcond * \ingroup Semaphores */ -#define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK ) +#define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK ) /** + * @cond * semphr. h - *
xSemaphoreGiveRecursive( SemaphoreHandle_t xMutex )
+ * @code{c} + * xSemaphoreGiveRecursive( SemaphoreHandle_t xMutex ); + * @endcode + * @endcond * * Macro to recursively release, or 'give', a mutex type semaphore. * The mutex must have previously been created using a call to @@ -462,78 +503,64 @@ typedef QueueHandle_t SemaphoreHandle_t; * * Example usage: * @code{c} - * SemaphoreHandle_t xMutex = NULL; + * SemaphoreHandle_t xMutex = NULL; * - * // A task that creates a mutex. - * void vATask( void * pvParameters ) + * // A task that creates a mutex. + * void vATask( void * pvParameters ) + * { + * // Create the mutex to guard a shared resource. + * xMutex = xSemaphoreCreateRecursiveMutex(); + * } + * + * // A task that uses the mutex. + * void vAnotherTask( void * pvParameters ) + * { + * // ... Do other things. + * + * if( xMutex != NULL ) * { - * // Create the mutex to guard a shared resource. - * xMutex = xSemaphoreCreateRecursiveMutex(); - * } - * - * // A task that uses the mutex. - * void vAnotherTask( void * pvParameters ) - * { - * // ... Do other things. - * - * if( xMutex != NULL ) - * { - * // See if we can obtain the mutex. If the mutex is not available - * // wait 10 ticks to see if it becomes free. - * if( xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ) == pdTRUE ) - * { - * // We were able to obtain the mutex and can now access the - * // shared resource. - * - * // ... - * // For some reason due to the nature of the code further calls to - * // xSemaphoreTakeRecursive() are made on the same mutex. In real - * // code these would not be just sequential calls as this would make - * // no sense. Instead the calls are likely to be buried inside - * // a more complex call structure. - * xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); - * xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); - * - * // The mutex has now been 'taken' three times, so will not be - * // available to another task until it has also been given back - * // three times. Again it is unlikely that real code would have - * // these calls sequentially, it would be more likely that the calls - * // to xSemaphoreGiveRecursive() would be called as a call stack - * // unwound. This is just for demonstrative purposes. - * xSemaphoreGiveRecursive( xMutex ); - * xSemaphoreGiveRecursive( xMutex ); - * xSemaphoreGiveRecursive( xMutex ); - * - * // Now the mutex can be taken by other tasks. - * } - * else - * { - * // We could not obtain the mutex and can therefore not access - * // the shared resource safely. - * } - * } + * // See if we can obtain the mutex. If the mutex is not available + * // wait 10 ticks to see if it becomes free. + * if( xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ) == pdTRUE ) + * { + * // We were able to obtain the mutex and can now access the + * // shared resource. + * + * // ... + * // For some reason due to the nature of the code further calls to + * // xSemaphoreTakeRecursive() are made on the same mutex. In real + * // code these would not be just sequential calls as this would make + * // no sense. Instead the calls are likely to be buried inside + * // a more complex call structure. + * xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); + * xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); + * + * // The mutex has now been 'taken' three times, so will not be + * // available to another task until it has also been given back + * // three times. Again it is unlikely that real code would have + * // these calls sequentially, it would be more likely that the calls + * // to xSemaphoreGiveRecursive() would be called as a call stack + * // unwound. This is just for demonstrative purposes. + * xSemaphoreGiveRecursive( xMutex ); + * xSemaphoreGiveRecursive( xMutex ); + * xSemaphoreGiveRecursive( xMutex ); + * + * // Now the mutex can be taken by other tasks. + * } + * else + * { + * // We could not obtain the mutex and can therefore not access + * // the shared resource safely. + * } * } + * } * @endcode + * @cond + * \defgroup xSemaphoreGiveRecursive xSemaphoreGiveRecursive + * @endcond * \ingroup Semaphores */ -#define xSemaphoreGiveRecursive( xMutex ) xQueueGiveMutexRecursive( ( xMutex ) ) - -/** @cond */ -/* - * xSemaphoreAltGive() is an alternative version of xSemaphoreGive(). - * - * The source code that implements the alternative (Alt) API is much - * simpler because it executes everything from within a critical section. - * This is the approach taken by many other RTOSes, but FreeRTOS.org has the - * preferred fully featured API too. The fully featured API has more - * complex code that takes longer to execute, but makes much less use of - * critical sections. Therefore the alternative API sacrifices interrupt - * responsiveness to gain execution speed, whereas the fully featured API - * sacrifices execution speed to ensure better interrupt responsiveness. - */ -#define xSemaphoreAltGive( xSemaphore ) xQueueAltGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK ) - -/** @endcond */ +#define xSemaphoreGiveRecursive( xMutex ) xQueueGiveMutexRecursive( ( xMutex ) ) /** * Macro to release a semaphore. The semaphore must have previously been @@ -557,68 +584,81 @@ typedef QueueHandle_t SemaphoreHandle_t; * * Example usage: * @code{c} - * \#define LONG_TIME 0xffff - * \#define TICKS_TO_WAIT 10 - * SemaphoreHandle_t xSemaphore = NULL; + * #define LONG_TIME 0xffff + * #define TICKS_TO_WAIT 10 + * SemaphoreHandle_t xSemaphore = NULL; * - * // Repetitive task. - * void vATask( void * pvParameters ) + * // Repetitive task. + * void vATask( void * pvParameters ) + * { + * for( ;; ) * { - * for( ;; ) - * { - * // We want this task to run every 10 ticks of a timer. The semaphore - * // was created before this task was started. + * // We want this task to run every 10 ticks of a timer. The semaphore + * // was created before this task was started. * - * // Block waiting for the semaphore to become available. - * if( xSemaphoreTake( xSemaphore, LONG_TIME ) == pdTRUE ) - * { - * // It is time to execute. + * // Block waiting for the semaphore to become available. + * if( xSemaphoreTake( xSemaphore, LONG_TIME ) == pdTRUE ) + * { + * // It is time to execute. * - * // ... + * // ... * - * // We have finished our task. Return to the top of the loop where - * // we will block on the semaphore until it is time to execute - * // again. Note when using the semaphore for synchronisation with an - * // ISR in this manner there is no need to 'give' the semaphore back. - * } - * } + * // We have finished our task. Return to the top of the loop where + * // we will block on the semaphore until it is time to execute + * // again. Note when using the semaphore for synchronisation with an + * // ISR in this manner there is no need to 'give' the semaphore back. + * } + * } + * } + * + * // Timer ISR + * void vTimerISR( void * pvParameters ) + * { + * static uint8_t ucLocalTickCount = 0; + * static BaseType_t xHigherPriorityTaskWoken; + * + * // A timer tick has occurred. + * + * // ... Do other time functions. + * + * // Is it time for vATask () to run? + * xHigherPriorityTaskWoken = pdFALSE; + * ucLocalTickCount++; + * if( ucLocalTickCount >= TICKS_TO_WAIT ) + * { + * // Unblock the task by releasing the semaphore. + * xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken ); + * + * // Reset the count so we release the semaphore again in 10 ticks time. + * ucLocalTickCount = 0; * } * - * // Timer ISR - * void vTimerISR( void * pvParameters ) + * if( xHigherPriorityTaskWoken != pdFALSE ) * { - * static uint8_t ucLocalTickCount = 0; - * static BaseType_t xHigherPriorityTaskWoken; - * - * // A timer tick has occurred. - * - * // ... Do other time functions. - * - * // Is it time for vATask () to run? - * xHigherPriorityTaskWoken = pdFALSE; - * ucLocalTickCount++; - * if( ucLocalTickCount >= TICKS_TO_WAIT ) - * { - * // Unblock the task by releasing the semaphore. - * xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken ); - * - * // Reset the count so we release the semaphore again in 10 ticks time. - * ucLocalTickCount = 0; - * } - * - * if( xHigherPriorityTaskWoken != pdFALSE ) - * { - * // We can force a context switch here. Context switching from an - * // ISR uses port specific syntax. Check the demo task for your port - * // to find the syntax required. - * } + * // We can force a context switch here. Context switching from an + * // ISR uses port specific syntax. Check the demo task for your port + * // to find the syntax required. * } + * } * @endcode + * @cond + * \defgroup xSemaphoreGiveFromISR xSemaphoreGiveFromISR + * @endcond * \ingroup Semaphores */ -#define xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueGiveFromISR( ( QueueHandle_t ) ( xSemaphore ), ( pxHigherPriorityTaskWoken ) ) +#define xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueGiveFromISR( ( QueueHandle_t ) ( xSemaphore ), ( pxHigherPriorityTaskWoken ) ) /** + * @cond + * semphr. h + * @code{c} + * xSemaphoreTakeFromISR( + * SemaphoreHandle_t xSemaphore, + * BaseType_t *pxHigherPriorityTaskWoken + * ); + * @endcode + * @endcond + * * Macro to take a semaphore from an ISR. The semaphore must have * previously been created with a call to xSemaphoreCreateBinary() or * xSemaphoreCreateCounting(). @@ -643,17 +683,24 @@ typedef QueueHandle_t SemaphoreHandle_t; * @return pdTRUE if the semaphore was successfully taken, otherwise * pdFALSE */ -#define xSemaphoreTakeFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueReceiveFromISR( ( QueueHandle_t ) ( xSemaphore ), NULL, ( pxHigherPriorityTaskWoken ) ) +#define xSemaphoreTakeFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueReceiveFromISR( ( QueueHandle_t ) ( xSemaphore ), NULL, ( pxHigherPriorityTaskWoken ) ) /** - * Macro that implements a mutex semaphore by using the existing queue - * mechanism. + * @cond + * semphr. h + * @code{c} + * SemaphoreHandle_t xSemaphoreCreateMutex( void ); + * @endcode + * @endcond + * + * Creates a new mutex type semaphore instance, and returns a handle by which + * the new mutex can be referenced. * * Internally, within the FreeRTOS implementation, mutex semaphores use a block * of memory, in which the mutex structure is stored. If a mutex is created * using xSemaphoreCreateMutex() then the required memory is automatically * dynamically allocated inside the xSemaphoreCreateMutex() function. (see - * http://www.freertos.org/a00111.html). If a mutex is created using + * https://www.FreeRTOS.org/a00111.html). If a mutex is created using * xSemaphoreCreateMutexStatic() then the application writer must provided the * memory. xSemaphoreCreateMutexStatic() therefore allows a mutex to be created * without using any dynamic memory allocation. @@ -679,28 +726,38 @@ typedef QueueHandle_t SemaphoreHandle_t; * * Example usage: * @code{c} - * SemaphoreHandle_t xSemaphore; + * SemaphoreHandle_t xSemaphore; * - * void vATask( void * pvParameters ) + * void vATask( void * pvParameters ) + * { + * // Semaphore cannot be used before a call to xSemaphoreCreateMutex(). + * // This is a macro so pass the variable in directly. + * xSemaphore = xSemaphoreCreateMutex(); + * + * if( xSemaphore != NULL ) * { - * // Semaphore cannot be used before a call to xSemaphoreCreateMutex(). - * // This is a macro so pass the variable in directly. - * xSemaphore = xSemaphoreCreateMutex(); - * - * if( xSemaphore != NULL ) - * { - * // The semaphore was created successfully. - * // The semaphore can now be used. - * } + * // The semaphore was created successfully. + * // The semaphore can now be used. * } + * } * @endcode + * @cond + * \defgroup xSemaphoreCreateMutex xSemaphoreCreateMutex + * @endcond * \ingroup Semaphores */ -#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) - #define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX ) +#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + #define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX ) #endif /** + * @cond + * semphr. h + * @code{c} + * SemaphoreHandle_t xSemaphoreCreateMutexStatic( StaticSemaphore_t *pxMutexBuffer ); + * @endcode + * @endcond + * * Creates a new mutex type semaphore instance, and returns a handle by which * the new mutex can be referenced. * @@ -708,7 +765,7 @@ typedef QueueHandle_t SemaphoreHandle_t; * of memory, in which the mutex structure is stored. If a mutex is created * using xSemaphoreCreateMutex() then the required memory is automatically * dynamically allocated inside the xSemaphoreCreateMutex() function. (see - * http://www.freertos.org/a00111.html). If a mutex is created using + * https://www.FreeRTOS.org/a00111.html). If a mutex is created using * xSemaphoreCreateMutexStatic() then the application writer must provided the * memory. xSemaphoreCreateMutexStatic() therefore allows a mutex to be created * without using any dynamic memory allocation. @@ -736,25 +793,28 @@ typedef QueueHandle_t SemaphoreHandle_t; * mutex is returned. If pxMutexBuffer was NULL then NULL is returned. * * Example usage: - * @code - * SemaphoreHandle_t xSemaphore; - * StaticSemaphore_t xMutexBuffer; + * @code{c} + * SemaphoreHandle_t xSemaphore; + * StaticSemaphore_t xMutexBuffer; * - * void vATask( void * pvParameters ) - * { - * // A mutex cannot be used before it has been created. xMutexBuffer is - * // into xSemaphoreCreateMutexStatic() so no dynamic memory allocation is - * // attempted. - * xSemaphore = xSemaphoreCreateMutexStatic( &xMutexBuffer ); + * void vATask( void * pvParameters ) + * { + * // A mutex cannot be used before it has been created. xMutexBuffer is + * // into xSemaphoreCreateMutexStatic() so no dynamic memory allocation is + * // attempted. + * xSemaphore = xSemaphoreCreateMutexStatic( &xMutexBuffer ); * - * // As no dynamic memory allocation was performed, xSemaphore cannot be NULL, - * // so there is no need to check it. - * } + * // As no dynamic memory allocation was performed, xSemaphore cannot be NULL, + * // so there is no need to check it. + * } * @endcode + * @cond + * \defgroup xSemaphoreCreateMutexStatic xSemaphoreCreateMutexStatic + * @endcond * \ingroup Semaphores */ - #if( configSUPPORT_STATIC_ALLOCATION == 1 ) - #define xSemaphoreCreateMutexStatic( pxMutexBuffer ) xQueueCreateMutexStatic( queueQUEUE_TYPE_MUTEX, ( pxMutexBuffer ) ) +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + #define xSemaphoreCreateMutexStatic( pxMutexBuffer ) xQueueCreateMutexStatic( queueQUEUE_TYPE_MUTEX, ( pxMutexBuffer ) ) #endif /* configSUPPORT_STATIC_ALLOCATION */ @@ -796,7 +856,7 @@ typedef QueueHandle_t SemaphoreHandle_t; * service routines. * * @return xSemaphore Handle to the created mutex semaphore. Should be of type - * SemaphoreHandle_t. + * SemaphoreHandle_t. * * Example usage: * @code{c} @@ -818,7 +878,7 @@ typedef QueueHandle_t SemaphoreHandle_t; * \ingroup Semaphores */ #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) ) - #define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX ) + #define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX ) #endif /** @@ -830,7 +890,7 @@ typedef QueueHandle_t SemaphoreHandle_t; * created using xSemaphoreCreateRecursiveMutex() then the required memory is * automatically dynamically allocated inside the * xSemaphoreCreateRecursiveMutex() function. (see - * http://www.freertos.org/a00111.html). If a recursive mutex is created using + * https://www.FreeRTOS.org/a00111.html). If a recursive mutex is created using * xSemaphoreCreateRecursiveMutexStatic() then the application writer must * provide the memory that will get used by the mutex. * xSemaphoreCreateRecursiveMutexStatic() therefore allows a recursive mutex to @@ -867,7 +927,7 @@ typedef QueueHandle_t SemaphoreHandle_t; * returned. * * Example usage: - * @code + * @code{c} * SemaphoreHandle_t xSemaphore; * StaticSemaphore_t xMutexBuffer; * @@ -886,24 +946,31 @@ typedef QueueHandle_t SemaphoreHandle_t; * @endcode * \ingroup Semaphores */ -#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) ) - #define xSemaphoreCreateRecursiveMutexStatic( pxStaticSemaphore ) xQueueCreateMutexStatic( queueQUEUE_TYPE_RECURSIVE_MUTEX, pxStaticSemaphore ) +#if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) ) + #define xSemaphoreCreateRecursiveMutexStatic( pxStaticSemaphore ) xQueueCreateMutexStatic( queueQUEUE_TYPE_RECURSIVE_MUTEX, pxStaticSemaphore ) #endif /* configSUPPORT_STATIC_ALLOCATION */ /** + * @cond + * semphr. h + * @code{c} + * SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount ); + * @endcode + * @endcond + * * Creates a new counting semaphore instance, and returns a handle by which the * new counting semaphore can be referenced. * * In many usage scenarios it is faster and more memory efficient to use a * direct to task notification in place of a counting semaphore! - * http://www.freertos.org/RTOS-task-notifications.html + * https://www.FreeRTOS.org/RTOS-task-notifications.html * * Internally, within the FreeRTOS implementation, counting semaphores use a * block of memory, in which the counting semaphore structure is stored. If a * counting semaphore is created using xSemaphoreCreateCounting() then the * required memory is automatically dynamically allocated inside the * xSemaphoreCreateCounting() function. (see - * http://www.freertos.org/a00111.html). If a counting semaphore is created + * https://www.FreeRTOS.org/a00111.html). If a counting semaphore is created * using xSemaphoreCreateCountingStatic() then the application writer can * instead optionally provide the memory that will get used by the counting * semaphore. xSemaphoreCreateCountingStatic() therefore allows a counting @@ -942,44 +1009,54 @@ typedef QueueHandle_t SemaphoreHandle_t; * * Example usage: * @code{c} - * SemaphoreHandle_t xSemaphore; + * SemaphoreHandle_t xSemaphore; * - * void vATask( void * pvParameters ) + * void vATask( void * pvParameters ) + * { + * SemaphoreHandle_t xSemaphore = NULL; + * + * // Semaphore cannot be used before a call to xSemaphoreCreateCounting(). + * // The max value to which the semaphore can count should be 10, and the + * // initial value assigned to the count should be 0. + * xSemaphore = xSemaphoreCreateCounting( 10, 0 ); + * + * if( xSemaphore != NULL ) * { - * SemaphoreHandle_t xSemaphore = NULL; - * - * // Semaphore cannot be used before a call to xSemaphoreCreateCounting(). - * // The max value to which the semaphore can count should be 10, and the - * // initial value assigned to the count should be 0. - * xSemaphore = xSemaphoreCreateCounting( 10, 0 ); - * - * if( xSemaphore != NULL ) - * { - * // The semaphore was created successfully. - * // The semaphore can now be used. - * } + * // The semaphore was created successfully. + * // The semaphore can now be used. * } + * } * @endcode + * @cond + * \defgroup xSemaphoreCreateCounting xSemaphoreCreateCounting + * @endcond * \ingroup Semaphores */ -#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) - #define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) ) +#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + #define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) ) #endif /** + * @cond + * semphr. h + * @code{c} + * SemaphoreHandle_t xSemaphoreCreateCountingStatic( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount, StaticSemaphore_t *pxSemaphoreBuffer ); + * @endcode + * @endcond + * * Creates a new counting semaphore instance, and returns a handle by which the * new counting semaphore can be referenced. * * In many usage scenarios it is faster and more memory efficient to use a * direct to task notification in place of a counting semaphore! - * http://www.freertos.org/RTOS-task-notifications.html + * https://www.FreeRTOS.org/RTOS-task-notifications.html * * Internally, within the FreeRTOS implementation, counting semaphores use a * block of memory, in which the counting semaphore structure is stored. If a * counting semaphore is created using xSemaphoreCreateCounting() then the * required memory is automatically dynamically allocated inside the * xSemaphoreCreateCounting() function. (see - * http://www.freertos.org/a00111.html). If a counting semaphore is created + * https://www.FreeRTOS.org/a00111.html). If a counting semaphore is created * using xSemaphoreCreateCountingStatic() then the application writer must * provide the memory. xSemaphoreCreateCountingStatic() therefore allows a * counting semaphore to be created without using any dynamic memory allocation. @@ -1022,42 +1099,62 @@ typedef QueueHandle_t SemaphoreHandle_t; * * Example usage: * @code{c} - * SemaphoreHandle_t xSemaphore; - * StaticSemaphore_t xSemaphoreBuffer; + * SemaphoreHandle_t xSemaphore; + * StaticSemaphore_t xSemaphoreBuffer; * - * void vATask( void * pvParameters ) - * { - * SemaphoreHandle_t xSemaphore = NULL; + * void vATask( void * pvParameters ) + * { + * SemaphoreHandle_t xSemaphore = NULL; * - * // Counting semaphore cannot be used before they have been created. Create - * // a counting semaphore using xSemaphoreCreateCountingStatic(). The max - * // value to which the semaphore can count is 10, and the initial value - * // assigned to the count will be 0. The address of xSemaphoreBuffer is - * // passed in and will be used to hold the semaphore structure, so no dynamic - * // memory allocation will be used. - * xSemaphore = xSemaphoreCreateCounting( 10, 0, &xSemaphoreBuffer ); + * // Counting semaphore cannot be used before they have been created. Create + * // a counting semaphore using xSemaphoreCreateCountingStatic(). The max + * // value to which the semaphore can count is 10, and the initial value + * // assigned to the count will be 0. The address of xSemaphoreBuffer is + * // passed in and will be used to hold the semaphore structure, so no dynamic + * // memory allocation will be used. + * xSemaphore = xSemaphoreCreateCounting( 10, 0, &xSemaphoreBuffer ); * - * // No memory allocation was attempted so xSemaphore cannot be NULL, so there - * // is no need to check its value. - * } + * // No memory allocation was attempted so xSemaphore cannot be NULL, so there + * // is no need to check its value. + * } * @endcode + * @cond + * \defgroup xSemaphoreCreateCountingStatic xSemaphoreCreateCountingStatic + * @endcond * \ingroup Semaphores */ -#if( configSUPPORT_STATIC_ALLOCATION == 1 ) - #define xSemaphoreCreateCountingStatic( uxMaxCount, uxInitialCount, pxSemaphoreBuffer ) xQueueCreateCountingSemaphoreStatic( ( uxMaxCount ), ( uxInitialCount ), ( pxSemaphoreBuffer ) ) +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + #define xSemaphoreCreateCountingStatic( uxMaxCount, uxInitialCount, pxSemaphoreBuffer ) xQueueCreateCountingSemaphoreStatic( ( uxMaxCount ), ( uxInitialCount ), ( pxSemaphoreBuffer ) ) #endif /* configSUPPORT_STATIC_ALLOCATION */ /** + * @cond + * semphr. h + * @code{c} + * void vSemaphoreDelete( SemaphoreHandle_t xSemaphore ); + * @endcode + * @endcond + * * Delete a semaphore. This function must be used with care. For example, * do not delete a mutex type semaphore if the mutex is held by a task. * * @param xSemaphore A handle to the semaphore to be deleted. * + * @cond + * \defgroup vSemaphoreDelete vSemaphoreDelete + * @endcond * \ingroup Semaphores */ -#define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) ) +#define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) ) /** + * @cond + * semphr.h + * @code{c} + * TaskHandle_t xSemaphoreGetMutexHolder( SemaphoreHandle_t xMutex ); + * @endcode + * @endcond + * * If xMutex is indeed a mutex type semaphore, return the current mutex holder. * If xMutex is not a mutex type semaphore, or the mutex is available (not held * by a task), return NULL. @@ -1067,20 +1164,30 @@ typedef QueueHandle_t SemaphoreHandle_t; * the holder may change between the function exiting and the returned value * being tested. */ -#define xSemaphoreGetMutexHolder( xSemaphore ) xQueueGetMutexHolder( ( xSemaphore ) ) +#define xSemaphoreGetMutexHolder( xSemaphore ) xQueueGetMutexHolder( ( xSemaphore ) ) /** + * @cond + * semphr.h + * @code{c} + * TaskHandle_t xSemaphoreGetMutexHolderFromISR( SemaphoreHandle_t xMutex ); + * @endcode + * @endcond * * If xMutex is indeed a mutex type semaphore, return the current mutex holder. * If xMutex is not a mutex type semaphore, or the mutex is available (not held * by a task), return NULL. * */ -#define xSemaphoreGetMutexHolderFromISR( xSemaphore ) xQueueGetMutexHolderFromISR( ( xSemaphore ) ) +#define xSemaphoreGetMutexHolderFromISR( xSemaphore ) xQueueGetMutexHolderFromISR( ( xSemaphore ) ) /** + * @cond * semphr.h - *
UBaseType_t uxSemaphoreGetCount( SemaphoreHandle_t xSemaphore );
+ * @code{c} + * UBaseType_t uxSemaphoreGetCount( SemaphoreHandle_t xSemaphore ); + * @endcode + * @endcond * * If the semaphore is a counting semaphore then uxSemaphoreGetCount() returns * its current count value. If the semaphore is a binary semaphore then @@ -1088,6 +1195,6 @@ typedef QueueHandle_t SemaphoreHandle_t; * semaphore is not available. * */ -#define uxSemaphoreGetCount( xSemaphore ) uxQueueMessagesWaiting( ( QueueHandle_t ) ( xSemaphore ) ) +#define uxSemaphoreGetCount( xSemaphore ) uxQueueMessagesWaiting( ( QueueHandle_t ) ( xSemaphore ) ) #endif /* SEMAPHORE_H */ diff --git a/components/freertos/include/freertos/stack_macros.h b/components/freertos/include/freertos/stack_macros.h index b8eca4246f..249c4ef840 100644 --- a/components/freertos/include/freertos/stack_macros.h +++ b/components/freertos/include/freertos/stack_macros.h @@ -1,6 +1,6 @@ /* - * FreeRTOS Kernel V10.2.1 - * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V10.4.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * 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 @@ -19,10 +19,9 @@ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS * - * 1 tab == 4 spaces! */ #ifndef STACK_MACROS_H @@ -46,94 +45,94 @@ #if( configCHECK_FOR_STACK_OVERFLOW == 0 ) - /* FreeRTOSConfig.h is not set to check for stack overflows. */ - #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() - #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() + /* FreeRTOSConfig.h is not set to check for stack overflows. */ + #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() + #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() #endif /* configCHECK_FOR_STACK_OVERFLOW == 0 */ /*-----------------------------------------------------------*/ #if( configCHECK_FOR_STACK_OVERFLOW == 1 ) - /* FreeRTOSConfig.h is only set to use the first method of - overflow checking. */ - #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() + /* FreeRTOSConfig.h is only set to use the first method of + overflow checking. */ + #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() #endif /*-----------------------------------------------------------*/ #if( ( configCHECK_FOR_STACK_OVERFLOW > 0 ) && ( portSTACK_GROWTH < 0 ) ) - /* Only the current stack state is to be checked. */ - #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() \ - { \ - /* Is the currently saved stack pointer within the stack limit? */ \ - if( pxCurrentTCB[ xPortGetCoreID() ]->pxTopOfStack <= pxCurrentTCB[ xPortGetCoreID() ]->pxStack ) \ - { \ - vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB[ xPortGetCoreID() ], pxCurrentTCB[ xPortGetCoreID() ]->pcTaskName ); \ - } \ - } +/* Only the current stack state is to be checked. */ + #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() \ + { \ + /* Is the currently saved stack pointer within the stack limit? */ \ + if( pxCurrentTCB[ xPortGetCoreID() ]->pxTopOfStack <= pxCurrentTCB[ xPortGetCoreID() ]->pxStack ) \ + { \ + vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB[ xPortGetCoreID() ], pxCurrentTCB[ xPortGetCoreID() ]->pcTaskName ); \ + } \ + } #endif /* configCHECK_FOR_STACK_OVERFLOW > 0 */ /*-----------------------------------------------------------*/ #if( ( configCHECK_FOR_STACK_OVERFLOW > 0 ) && ( portSTACK_GROWTH > 0 ) ) - /* Only the current stack state is to be checked. */ - #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() \ - { \ - \ - /* Is the currently saved stack pointer within the stack limit? */ \ - if( pxCurrentTCB[ xPortGetCoreID() ]->pxTopOfStack >= pxCurrentTCB[ xPortGetCoreID() ]->pxEndOfStack ) \ - { \ - vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB[ xPortGetCoreID() ], pxCurrentTCB[ xPortGetCoreID() ]->pcTaskName ); \ - } \ - } +/* Only the current stack state is to be checked. */ + #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() \ + { \ + \ + /* Is the currently saved stack pointer within the stack limit? */ \ + if( pxCurrentTCB[ xPortGetCoreID() ]->pxTopOfStack >= pxCurrentTCB[ xPortGetCoreID() ]->pxEndOfStack ) \ + { \ + vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB[ xPortGetCoreID() ], pxCurrentTCB[ xPortGetCoreID() ]->pcTaskName ); \ + } \ + } #endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */ /*-----------------------------------------------------------*/ -#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) ) +#if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) ) - #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() \ - { \ - static const uint8_t ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ - tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ - tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ - tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ - tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \ - \ - \ - /* Has the extremity of the task stack ever been written over? */ \ - if( memcmp( ( void * ) pxCurrentTCB[ xPortGetCoreID() ]->pxStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \ - { \ - vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB[ xPortGetCoreID() ], pxCurrentTCB[ xPortGetCoreID() ]->pcTaskName ); \ - } \ - } + #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() \ + { \ + static const uint8_t ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \ + \ + \ + /* Has the extremity of the task stack ever been written over? */ \ + if( memcmp( ( void * ) pxCurrentTCB[ xPortGetCoreID() ]->pxStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \ + { \ + vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB[ xPortGetCoreID() ], pxCurrentTCB[ xPortGetCoreID() ]->pcTaskName ); \ + } \ + } #endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ /*-----------------------------------------------------------*/ -#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) ) +#if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) ) - #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() \ - { \ - int8_t *pcEndOfStack = ( int8_t * ) pxCurrentTCB[ xPortGetCoreID() ]->pxEndOfStack; \ - static const uint8_t ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ - tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ - tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ - tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ - tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \ - \ - \ - pcEndOfStack -= sizeof( ucExpectedStackBytes ); \ - \ - /* Has the extremity of the task stack ever been written over? */ \ - if( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \ - { \ - vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB[ xPortGetCoreID() ], pxCurrentTCB[ xPortGetCoreID() ]->pcTaskName ); \ - } \ - } + #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() \ + { \ + int8_t *pcEndOfStack = ( int8_t * ) pxCurrentTCB[ xPortGetCoreID() ]->pxEndOfStack; \ + static const uint8_t ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \ + \ + \ + pcEndOfStack -= sizeof( ucExpectedStackBytes ); \ + \ + /* Has the extremity of the task stack ever been written over? */ \ + if( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \ + { \ + vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB[ xPortGetCoreID() ], pxCurrentTCB[ xPortGetCoreID() ]->pcTaskName ); \ + } \ + } #endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ diff --git a/components/freertos/include/freertos/stdint.readme b/components/freertos/include/freertos/stdint.readme index 4414c29ed2..20a8d663ef 100644 --- a/components/freertos/include/freertos/stdint.readme +++ b/components/freertos/include/freertos/stdint.readme @@ -1,3 +1,28 @@ +/* + * FreeRTOS Kernel V10.4.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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 + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ #ifndef FREERTOS_STDINT #define FREERTOS_STDINT @@ -10,7 +35,7 @@ * To use this file: * * 1) Copy this file into the directory that contains your FreeRTOSConfig.h - * header file, as that directory will already be in the compilers include + * header file, as that directory will already be in the compiler's include * path. * * 2) Rename the copied file stdint.h. diff --git a/components/freertos/include/freertos/stream_buffer.h b/components/freertos/include/freertos/stream_buffer.h index 1a3d8f5190..9e58cff120 100644 --- a/components/freertos/include/freertos/stream_buffer.h +++ b/components/freertos/include/freertos/stream_buffer.h @@ -1,6 +1,6 @@ /* - * FreeRTOS Kernel V10.2.1 - * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V10.4.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * 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 @@ -19,10 +19,9 @@ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS * - * 1 tab == 4 spaces! */ /* @@ -43,7 +42,7 @@ * (such as xStreamBufferSend()) inside a critical section and set the send * block time to 0. Likewise, if there are to be multiple different readers * then the application writer must place each call to a reading API function - * (such as xStreamBufferRead()) inside a critical section section and set the + * (such as xStreamBufferReceive()) inside a critical section section and set the * receive block time to 0. * */ @@ -52,12 +51,14 @@ #define STREAM_BUFFER_H #ifndef INC_FREERTOS_H - #error "include FreeRTOS.h must appear in source files before include stream_buffer.h" + #error "include FreeRTOS.h must appear in source files before include stream_buffer.h" #endif +/* *INDENT-OFF* */ #if defined( __cplusplus ) -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /** * Type by which stream buffers are referenced. For example, a call to @@ -68,7 +69,16 @@ extern "C" { struct StreamBufferDef_t; typedef struct StreamBufferDef_t * StreamBufferHandle_t; + /** + * @cond + * message_buffer.h + * + * @code{c} + * StreamBufferHandle_t xStreamBufferCreate( size_t xBufferSizeBytes, size_t xTriggerLevelBytes ); + * @endcode + * @endcond + * * Creates a new stream buffer using dynamically allocated memory. See * xStreamBufferCreateStatic() for a version that uses statically allocated * memory (memory that is allocated at compile time). @@ -103,32 +113,46 @@ typedef struct StreamBufferDef_t * StreamBufferHandle_t; * Example use: * @code{c} * - * void vAFunction( void ) - * { - * StreamBufferHandle_t xStreamBuffer; - * const size_t xStreamBufferSizeBytes = 100, xTriggerLevel = 10; + * void vAFunction( void ) + * { + * StreamBufferHandle_t xStreamBuffer; + * const size_t xStreamBufferSizeBytes = 100, xTriggerLevel = 10; * - * // Create a stream buffer that can hold 100 bytes. The memory used to hold - * // both the stream buffer structure and the data in the stream buffer is - * // allocated dynamically. - * xStreamBuffer = xStreamBufferCreate( xStreamBufferSizeBytes, xTriggerLevel ); + * // Create a stream buffer that can hold 100 bytes. The memory used to hold + * // both the stream buffer structure and the data in the stream buffer is + * // allocated dynamically. + * xStreamBuffer = xStreamBufferCreate( xStreamBufferSizeBytes, xTriggerLevel ); * - * if( xStreamBuffer == NULL ) - * { - * // There was not enough heap memory space available to create the - * // stream buffer. - * } - * else - * { - * // The stream buffer was created successfully and can now be used. - * } - * } + * if( xStreamBuffer == NULL ) + * { + * // There was not enough heap memory space available to create the + * // stream buffer. + * } + * else + * { + * // The stream buffer was created successfully and can now be used. + * } + * } * @endcode + * @cond + * \defgroup xStreamBufferCreate xStreamBufferCreate + * @endcond * \ingroup StreamBufferManagement */ -#define xStreamBufferCreate( xBufferSizeBytes, xTriggerLevelBytes ) xStreamBufferGenericCreate( xBufferSizeBytes, xTriggerLevelBytes, pdFALSE ) +#define xStreamBufferCreate( xBufferSizeBytes, xTriggerLevelBytes ) xStreamBufferGenericCreate( xBufferSizeBytes, xTriggerLevelBytes, pdFALSE ) /** + * @cond + * stream_buffer.h + * + * @code{c} + * StreamBufferHandle_t xStreamBufferCreateStatic( size_t xBufferSizeBytes, + * size_t xTriggerLevelBytes, + * uint8_t *pucStreamBufferStorageArea, + * StaticStreamBuffer_t *pxStaticStreamBuffer ); + * @endcode + * @endcond + * * Creates a new stream buffer using statically allocated memory. See * xStreamBufferCreate() for a version that uses dynamically allocated memory. * @@ -167,40 +191,55 @@ typedef struct StreamBufferDef_t * StreamBufferHandle_t; * Example use: * @code{c} * - * // Used to dimension the array used to hold the streams. The available space - * // will actually be one less than this, so 999. - * #define STORAGE_SIZE_BYTES 1000 + * // Used to dimension the array used to hold the streams. The available space + * // will actually be one less than this, so 999. + * #define STORAGE_SIZE_BYTES 1000 * - * // Defines the memory that will actually hold the streams within the stream - * // buffer. - * static uint8_t ucStorageBuffer[ STORAGE_SIZE_BYTES ]; + * // Defines the memory that will actually hold the streams within the stream + * // buffer. + * static uint8_t ucStorageBuffer[ STORAGE_SIZE_BYTES ]; * - * // The variable used to hold the stream buffer structure. - * StaticStreamBuffer_t xStreamBufferStruct; + * // The variable used to hold the stream buffer structure. + * StaticStreamBuffer_t xStreamBufferStruct; * - * void MyFunction( void ) - * { - * StreamBufferHandle_t xStreamBuffer; - * const size_t xTriggerLevel = 1; + * void MyFunction( void ) + * { + * StreamBufferHandle_t xStreamBuffer; + * const size_t xTriggerLevel = 1; * - * xStreamBuffer = xStreamBufferCreateStatic( sizeof( ucBufferStorage ), - * xTriggerLevel, - * ucBufferStorage, - * &xStreamBufferStruct ); + * xStreamBuffer = xStreamBufferCreateStatic( sizeof( ucBufferStorage ), + * xTriggerLevel, + * ucBufferStorage, + * &xStreamBufferStruct ); * - * // As neither the pucStreamBufferStorageArea or pxStaticStreamBuffer - * // parameters were NULL, xStreamBuffer will not be NULL, and can be used to - * // reference the created stream buffer in other stream buffer API calls. + * // As neither the pucStreamBufferStorageArea or pxStaticStreamBuffer + * // parameters were NULL, xStreamBuffer will not be NULL, and can be used to + * // reference the created stream buffer in other stream buffer API calls. * - * // Other code that uses the stream buffer can go here. - * } + * // Other code that uses the stream buffer can go here. + * } * * @endcode + * @cond + * \defgroup xStreamBufferCreateStatic xStreamBufferCreateStatic + * @endcond * \ingroup StreamBufferManagement */ -#define xStreamBufferCreateStatic( xBufferSizeBytes, xTriggerLevelBytes, pucStreamBufferStorageArea, pxStaticStreamBuffer ) xStreamBufferGenericCreateStatic( xBufferSizeBytes, xTriggerLevelBytes, pdFALSE, pucStreamBufferStorageArea, pxStaticStreamBuffer ) +#define xStreamBufferCreateStatic( xBufferSizeBytes, xTriggerLevelBytes, pucStreamBufferStorageArea, pxStaticStreamBuffer ) \ + xStreamBufferGenericCreateStatic( xBufferSizeBytes, xTriggerLevelBytes, pdFALSE, pucStreamBufferStorageArea, pxStaticStreamBuffer ) /** + * @cond + * stream_buffer.h + * + * @code{c} + * size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, + * const void *pvTxData, + * size_t xDataLengthBytes, + * TickType_t xTicksToWait ); + * @endcode + * @endcond + * * Sends bytes to a stream buffer. The bytes are copied into the stream buffer. * * ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer @@ -215,7 +254,7 @@ typedef struct StreamBufferDef_t * StreamBufferHandle_t; * (such as xStreamBufferSend()) inside a critical section and set the send * block time to 0. Likewise, if there are to be multiple different readers * then the application writer must place each call to a reading API function - * (such as xStreamBufferRead()) inside a critical section and set the receive + * (such as xStreamBufferReceive()) inside a critical section and set the receive * block time to 0. * * Use xStreamBufferSend() to write to a stream buffer from a task. Use @@ -250,44 +289,58 @@ typedef struct StreamBufferDef_t * StreamBufferHandle_t; * * Example use: * @code{c} - * void vAFunction( StreamBufferHandle_t xStreamBuffer ) - * { - * size_t xBytesSent; - * uint8_t ucArrayToSend[] = { 0, 1, 2, 3 }; - * char *pcStringToSend = "String to send"; - * const TickType_t x100ms = pdMS_TO_TICKS( 100 ); + * void vAFunction( StreamBufferHandle_t xStreamBuffer ) + * { + * size_t xBytesSent; + * uint8_t ucArrayToSend[] = { 0, 1, 2, 3 }; + * char *pcStringToSend = "String to send"; + * const TickType_t x100ms = pdMS_TO_TICKS( 100 ); * - * // Send an array to the stream buffer, blocking for a maximum of 100ms to - * // wait for enough space to be available in the stream buffer. - * xBytesSent = xStreamBufferSend( xStreamBuffer, ( void * ) ucArrayToSend, sizeof( ucArrayToSend ), x100ms ); + * // Send an array to the stream buffer, blocking for a maximum of 100ms to + * // wait for enough space to be available in the stream buffer. + * xBytesSent = xStreamBufferSend( xStreamBuffer, ( void * ) ucArrayToSend, sizeof( ucArrayToSend ), x100ms ); * - * if( xBytesSent != sizeof( ucArrayToSend ) ) - * { - * // The call to xStreamBufferSend() times out before there was enough - * // space in the buffer for the data to be written, but it did - * // successfully write xBytesSent bytes. - * } + * if( xBytesSent != sizeof( ucArrayToSend ) ) + * { + * // The call to xStreamBufferSend() times out before there was enough + * // space in the buffer for the data to be written, but it did + * // successfully write xBytesSent bytes. + * } * - * // Send the string to the stream buffer. Return immediately if there is not - * // enough space in the buffer. - * xBytesSent = xStreamBufferSend( xStreamBuffer, ( void * ) pcStringToSend, strlen( pcStringToSend ), 0 ); + * // Send the string to the stream buffer. Return immediately if there is not + * // enough space in the buffer. + * xBytesSent = xStreamBufferSend( xStreamBuffer, ( void * ) pcStringToSend, strlen( pcStringToSend ), 0 ); * - * if( xBytesSent != strlen( pcStringToSend ) ) - * { - * // The entire string could not be added to the stream buffer because - * // there was not enough free space in the buffer, but xBytesSent bytes - * // were sent. Could try again to send the remaining bytes. - * } - * } + * if( xBytesSent != strlen( pcStringToSend ) ) + * { + * // The entire string could not be added to the stream buffer because + * // there was not enough free space in the buffer, but xBytesSent bytes + * // were sent. Could try again to send the remaining bytes. + * } + * } * @endcode + * @cond + * \defgroup xStreamBufferSend xStreamBufferSend + * @endcond * \ingroup StreamBufferManagement */ size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, - const void *pvTxData, - size_t xDataLengthBytes, - TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; + const void * pvTxData, + size_t xDataLengthBytes, + TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; /** + * @cond + * stream_buffer.h + * + * @code{c} + * size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer, + * const void *pvTxData, + * size_t xDataLengthBytes, + * BaseType_t *pxHigherPriorityTaskWoken ); + * @endcode + * @endcond + * * Interrupt safe version of the API function that sends a stream of bytes to * the stream buffer. * @@ -303,7 +356,7 @@ size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, * (such as xStreamBufferSend()) inside a critical section and set the send * block time to 0. Likewise, if there are to be multiple different readers * then the application writer must place each call to a reading API function - * (such as xStreamBufferRead()) inside a critical section and set the receive + * (such as xStreamBufferReceive()) inside a critical section and set the receive * block time to 0. * * Use xStreamBufferSend() to write to a stream buffer from a task. Use @@ -339,46 +392,60 @@ size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, * * Example use: * @code{c} - * //A stream buffer that has already been created. - * StreamBufferHandle_t xStreamBuffer; + * // A stream buffer that has already been created. + * StreamBufferHandle_t xStreamBuffer; * - * void vAnInterruptServiceRoutine( void ) - * { - * size_t xBytesSent; - * char *pcStringToSend = "String to send"; - * BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE. + * void vAnInterruptServiceRoutine( void ) + * { + * size_t xBytesSent; + * char *pcStringToSend = "String to send"; + * BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE. * - * // Attempt to send the string to the stream buffer. - * xBytesSent = xStreamBufferSendFromISR( xStreamBuffer, - * ( void * ) pcStringToSend, - * strlen( pcStringToSend ), - * &xHigherPriorityTaskWoken ); + * // Attempt to send the string to the stream buffer. + * xBytesSent = xStreamBufferSendFromISR( xStreamBuffer, + * ( void * ) pcStringToSend, + * strlen( pcStringToSend ), + * &xHigherPriorityTaskWoken ); * - * if( xBytesSent != strlen( pcStringToSend ) ) - * { - * // There was not enough free space in the stream buffer for the entire - * // string to be written, ut xBytesSent bytes were written. - * } + * if( xBytesSent != strlen( pcStringToSend ) ) + * { + * // There was not enough free space in the stream buffer for the entire + * // string to be written, ut xBytesSent bytes were written. + * } * - * // If xHigherPriorityTaskWoken was set to pdTRUE inside - * // xStreamBufferSendFromISR() then a task that has a priority above the - * // priority of the currently executing task was unblocked and a context - * // switch should be performed to ensure the ISR returns to the unblocked - * // task. In most FreeRTOS ports this is done by simply passing - * // xHigherPriorityTaskWoken into taskYIELD_FROM_ISR(), which will test the - * // variables value, and perform the context switch if necessary. Check the - * // documentation for the port in use for port specific instructions. - * taskYIELD_FROM_ISR( xHigherPriorityTaskWoken ); - * } + * // If xHigherPriorityTaskWoken was set to pdTRUE inside + * // xStreamBufferSendFromISR() then a task that has a priority above the + * // priority of the currently executing task was unblocked and a context + * // switch should be performed to ensure the ISR returns to the unblocked + * // task. In most FreeRTOS ports this is done by simply passing + * // xHigherPriorityTaskWoken into taskYIELD_FROM_ISR(), which will test the + * // variables value, and perform the context switch if necessary. Check the + * // documentation for the port in use for port specific instructions. + * taskYIELD_FROM_ISR( xHigherPriorityTaskWoken ); + * } * @endcode + * @cond + * \defgroup xStreamBufferSendFromISR xStreamBufferSendFromISR + * @endcond * \ingroup StreamBufferManagement */ size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer, - const void *pvTxData, - size_t xDataLengthBytes, - BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; + const void * pvTxData, + size_t xDataLengthBytes, + BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; /** + * @cond + * stream_buffer.h + * + * @code{c} + * size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer, + * void *pvRxData, + * size_t xBufferLengthBytes, + * TickType_t xTicksToWait ); + * @endcode + * @endcond + * * Receives bytes from a stream buffer. * * ***NOTE***: Uniquely among FreeRTOS objects, the stream buffer @@ -393,7 +460,7 @@ size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer, * (such as xStreamBufferSend()) inside a critical section and set the send * block time to 0. Likewise, if there are to be multiple different readers * then the application writer must place each call to a reading API function - * (such as xStreamBufferRead()) inside a critical section and set the receive + * (such as xStreamBufferReceive()) inside a critical section and set the receive * block time to 0. * * Use xStreamBufferReceive() to read from a stream buffer from a task. Use @@ -428,37 +495,50 @@ size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer, * * Example use: * @code{c} - * void vAFunction( StreamBuffer_t xStreamBuffer ) - * { - * uint8_t ucRxData[ 20 ]; - * size_t xReceivedBytes; - * const TickType_t xBlockTime = pdMS_TO_TICKS( 20 ); + * void vAFunction( StreamBuffer_t xStreamBuffer ) + * { + * uint8_t ucRxData[ 20 ]; + * size_t xReceivedBytes; + * const TickType_t xBlockTime = pdMS_TO_TICKS( 20 ); * - * // Receive up to another sizeof( ucRxData ) bytes from the stream buffer. - * // Wait in the Blocked state (so not using any CPU processing time) for a - * // maximum of 100ms for the full sizeof( ucRxData ) number of bytes to be - * // available. - * xReceivedBytes = xStreamBufferReceive( xStreamBuffer, - * ( void * ) ucRxData, - * sizeof( ucRxData ), - * xBlockTime ); + * // Receive up to another sizeof( ucRxData ) bytes from the stream buffer. + * // Wait in the Blocked state (so not using any CPU processing time) for a + * // maximum of 100ms for the full sizeof( ucRxData ) number of bytes to be + * // available. + * xReceivedBytes = xStreamBufferReceive( xStreamBuffer, + * ( void * ) ucRxData, + * sizeof( ucRxData ), + * xBlockTime ); * - * if( xReceivedBytes > 0 ) - * { - * // A ucRxData contains another xRecievedBytes bytes of data, which can - * // be processed here.... - * } - * } + * if( xReceivedBytes > 0 ) + * { + * // A ucRxData contains another xRecievedBytes bytes of data, which can + * // be processed here.... + * } + * } * @endcode + * @cond + * \defgroup xStreamBufferReceive xStreamBufferReceive + * @endcond * \ingroup StreamBufferManagement */ size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer, - void *pvRxData, - size_t xBufferLengthBytes, - TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; - + void * pvRxData, + size_t xBufferLengthBytes, + TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; /** + * @cond + * stream_buffer.h + * + * @code{c} + * size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer, + * void *pvRxData, + * size_t xBufferLengthBytes, + * BaseType_t *pxHigherPriorityTaskWoken ); + * @endcode + * @endcond + * * An interrupt safe version of the API function that receives bytes from a * stream buffer. * @@ -495,46 +575,57 @@ size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer, * * Example use: * @code{c} - * // A stream buffer that has already been created. - * StreamBuffer_t xStreamBuffer; + * // A stream buffer that has already been created. + * StreamBuffer_t xStreamBuffer; * - * void vAnInterruptServiceRoutine( void ) - * { - * uint8_t ucRxData[ 20 ]; - * size_t xReceivedBytes; - * BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE. + * void vAnInterruptServiceRoutine( void ) + * { + * uint8_t ucRxData[ 20 ]; + * size_t xReceivedBytes; + * BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Initialised to pdFALSE. * - * // Receive the next stream from the stream buffer. - * xReceivedBytes = xStreamBufferReceiveFromISR( xStreamBuffer, - * ( void * ) ucRxData, - * sizeof( ucRxData ), - * &xHigherPriorityTaskWoken ); + * // Receive the next stream from the stream buffer. + * xReceivedBytes = xStreamBufferReceiveFromISR( xStreamBuffer, + * ( void * ) ucRxData, + * sizeof( ucRxData ), + * &xHigherPriorityTaskWoken ); * - * if( xReceivedBytes > 0 ) - * { - * // ucRxData contains xReceivedBytes read from the stream buffer. - * // Process the stream here.... - * } + * if( xReceivedBytes > 0 ) + * { + * // ucRxData contains xReceivedBytes read from the stream buffer. + * // Process the stream here.... + * } * - * // If xHigherPriorityTaskWoken was set to pdTRUE inside - * // xStreamBufferReceiveFromISR() then a task that has a priority above the - * // priority of the currently executing task was unblocked and a context - * // switch should be performed to ensure the ISR returns to the unblocked - * // task. In most FreeRTOS ports this is done by simply passing - * // xHigherPriorityTaskWoken into taskYIELD_FROM_ISR(), which will test the - * // variables value, and perform the context switch if necessary. Check the - * // documentation for the port in use for port specific instructions. - * taskYIELD_FROM_ISR( xHigherPriorityTaskWoken ); - * } + * // If xHigherPriorityTaskWoken was set to pdTRUE inside + * // xStreamBufferReceiveFromISR() then a task that has a priority above the + * // priority of the currently executing task was unblocked and a context + * // switch should be performed to ensure the ISR returns to the unblocked + * // task. In most FreeRTOS ports this is done by simply passing + * // xHigherPriorityTaskWoken into taskYIELD_FROM_ISR(), which will test the + * // variables value, and perform the context switch if necessary. Check the + * // documentation for the port in use for port specific instructions. + * taskYIELD_FROM_ISR( xHigherPriorityTaskWoken ); + * } * @endcode + * @cond + * \defgroup xStreamBufferReceiveFromISR xStreamBufferReceiveFromISR + * @endcond * \ingroup StreamBufferManagement */ size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer, - void *pvRxData, - size_t xBufferLengthBytes, - BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; + void * pvRxData, + size_t xBufferLengthBytes, + BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; /** + * @cond + * stream_buffer.h + * + * @code{c} + * void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ); + * @endcode + * @endcond + * * Deletes a stream buffer that was previously created using a call to * xStreamBufferCreate() or xStreamBufferCreateStatic(). If the stream * buffer was created using dynamic memory (that is, by xStreamBufferCreate()), @@ -545,11 +636,22 @@ size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer, * * @param xStreamBuffer The handle of the stream buffer to be deleted. * + * @cond + * \defgroup vStreamBufferDelete vStreamBufferDelete + * @endcond * \ingroup StreamBufferManagement */ void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; /** + * @cond + * stream_buffer.h + * + * @code{c} + * BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ); + * @endcode + * @endcond + * * Queries a stream buffer to see if it is full. A stream buffer is full if it * does not have any free space, and therefore cannot accept any more data. * @@ -558,11 +660,22 @@ void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTI * @return If the stream buffer is full then pdTRUE is returned. Otherwise * pdFALSE is returned. * + * @cond + * \defgroup xStreamBufferIsFull xStreamBufferIsFull + * @endcond * \ingroup StreamBufferManagement */ BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; /** + * @cond + * stream_buffer.h + * + * @code{c} + * BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer ); + * @endcode + * @endcond + * * Queries a stream buffer to see if it is empty. A stream buffer is empty if * it does not contain any data. * @@ -571,11 +684,22 @@ BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_ * @return If the stream buffer is empty then pdTRUE is returned. Otherwise * pdFALSE is returned. * + * @cond + * \defgroup xStreamBufferIsEmpty xStreamBufferIsEmpty + * @endcond * \ingroup StreamBufferManagement */ BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; /** + * @cond + * stream_buffer.h + * + * @code{c} + * BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ); + * @endcode + * @endcond + * * Resets a stream buffer to its initial, empty, state. Any data that was in * the stream buffer is discarded. A stream buffer can only be reset if there * are no tasks blocked waiting to either send to or receive from the stream @@ -587,11 +711,22 @@ BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED * a task blocked waiting to send to or read from the stream buffer then the * stream buffer is not reset and pdFAIL is returned. * + * @cond + * \defgroup xStreamBufferReset xStreamBufferReset + * @endcond * \ingroup StreamBufferManagement */ BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; /** + * @cond + * stream_buffer.h + * + * @code{c} + * size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer ); + * @endcode + * @endcond + * * Queries a stream buffer to see how much free space it contains, which is * equal to the amount of data that can be sent to the stream buffer before it * is full. @@ -601,12 +736,22 @@ BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_F * @return The number of bytes that can be written to the stream buffer before * the stream buffer would be full. * + * @cond * \defgroup xStreamBufferSpacesAvailable xStreamBufferSpacesAvailable + * @endcond * \ingroup StreamBufferManagement */ size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; /** + * @cond + * stream_buffer.h + * + * @code{c} + * size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer ); + * @endcode + * @endcond + * * Queries a stream buffer to see how much data it contains, which is equal to * the number of bytes that can be read from the stream buffer before the stream * buffer would be empty. @@ -616,12 +761,22 @@ size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer ) PRIVIL * @return The number of bytes that can be read from the stream buffer before * the stream buffer would be empty. * + * @cond * \defgroup xStreamBufferBytesAvailable xStreamBufferBytesAvailable + * @endcond * \ingroup StreamBufferManagement */ size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; /** + * @cond + * stream_buffer.h + * + * @code{c} + * BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, size_t xTriggerLevel ); + * @endcode + * @endcond + * * A stream buffer's trigger level is the number of bytes that must be in the * stream buffer before a task that is blocked on the stream buffer to * wait for data is moved out of the blocked state. For example, if a task is @@ -647,11 +802,23 @@ size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer ) PRIVILE * then the trigger level will be updated and pdTRUE is returned. Otherwise * pdFALSE is returned. * + * @cond + * \defgroup xStreamBufferSetTriggerLevel xStreamBufferSetTriggerLevel + * @endcond * \ingroup StreamBufferManagement */ -BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, size_t xTriggerLevel ) PRIVILEGED_FUNCTION; +BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, + size_t xTriggerLevel ) PRIVILEGED_FUNCTION; /** + * @cond + * stream_buffer.h + * + * @code{c} + * BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken ); + * @endcode + * @endcond + * * For advanced users only. * * The sbSEND_COMPLETED() macro is called from within the FreeRTOS APIs when @@ -679,11 +846,23 @@ BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, siz * @return If a task was removed from the Blocked state then pdTRUE is returned. * Otherwise pdFALSE is returned. * + * @cond + * \defgroup xStreamBufferSendCompletedFromISR xStreamBufferSendCompletedFromISR + * @endcond * \ingroup StreamBufferManagement */ -BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; +BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer, + BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; /** + * @cond + * stream_buffer.h + * + * @code{c} + * BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken ); + * @endcode + * @endcond + * * For advanced users only. * * The sbRECEIVE_COMPLETED() macro is called from within the FreeRTOS APIs when @@ -712,34 +891,41 @@ BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer * @return If a task was removed from the Blocked state then pdTRUE is returned. * Otherwise pdFALSE is returned. * + * @cond + * \defgroup xStreamBufferReceiveCompletedFromISR xStreamBufferReceiveCompletedFromISR + * @endcond * \ingroup StreamBufferManagement */ -BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; +BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer, + BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; /** @cond */ /* Functions below here are not part of the public API. */ StreamBufferHandle_t xStreamBufferGenericCreate( size_t xBufferSizeBytes, - size_t xTriggerLevelBytes, - BaseType_t xIsMessageBuffer ) PRIVILEGED_FUNCTION; + size_t xTriggerLevelBytes, + BaseType_t xIsMessageBuffer ) PRIVILEGED_FUNCTION; StreamBufferHandle_t xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes, - size_t xTriggerLevelBytes, - BaseType_t xIsMessageBuffer, - uint8_t * const pucStreamBufferStorageArea, - StaticStreamBuffer_t * const pxStaticStreamBuffer ) PRIVILEGED_FUNCTION; + size_t xTriggerLevelBytes, + BaseType_t xIsMessageBuffer, + uint8_t * const pucStreamBufferStorageArea, + StaticStreamBuffer_t * const pxStaticStreamBuffer ) PRIVILEGED_FUNCTION; size_t xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; -#if( configUSE_TRACE_FACILITY == 1 ) - void vStreamBufferSetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer, UBaseType_t uxStreamBufferNumber ) PRIVILEGED_FUNCTION; - UBaseType_t uxStreamBufferGetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; - uint8_t ucStreamBufferGetStreamBufferType( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; +#if ( configUSE_TRACE_FACILITY == 1 ) + void vStreamBufferSetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer, + UBaseType_t uxStreamBufferNumber ) PRIVILEGED_FUNCTION; + UBaseType_t uxStreamBufferGetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; + uint8_t ucStreamBufferGetStreamBufferType( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; #endif /** @endcond */ +/* *INDENT-OFF* */ #if defined( __cplusplus ) -} + } #endif +/* *INDENT-ON* */ -#endif /* !defined( STREAM_BUFFER_H ) */ +#endif /* !defined( STREAM_BUFFER_H ) */ diff --git a/components/freertos/include/freertos/task.h b/components/freertos/include/freertos/task.h index 559945805e..df88c074fb 100644 --- a/components/freertos/include/freertos/task.h +++ b/components/freertos/include/freertos/task.h @@ -1,6 +1,6 @@ /* - * FreeRTOS Kernel V10.2.1 - * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V10.4.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * 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 @@ -19,10 +19,9 @@ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS * - * 1 tab == 4 spaces! */ @@ -30,69 +29,89 @@ #define INC_TASK_H #ifndef INC_FREERTOS_H - #error "include FreeRTOS.h must appear in source files before include task.h" + #error "include FreeRTOS.h must appear in source files before include task.h" #endif #include "list.h" +#ifdef ESP_PLATFORM // IDF-3793 #include "freertos/portmacro.h" +#endif // ESP_PLATFORM +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * MACROS AND DEFINITIONS *----------------------------------------------------------*/ -#define tskKERNEL_VERSION_NUMBER "V10.2.1" -#define tskKERNEL_VERSION_MAJOR 10 -#define tskKERNEL_VERSION_MINOR 2 -#define tskKERNEL_VERSION_BUILD 1 +#define tskKERNEL_VERSION_NUMBER "V10.4.3" +#define tskKERNEL_VERSION_MAJOR 10 +#define tskKERNEL_VERSION_MINOR 4 +#define tskKERNEL_VERSION_BUILD 3 /* MPU region parameters passed in ulParameters * of MemoryRegion_t struct. */ -#define tskMPU_REGION_READ_ONLY ( 1UL << 0UL ) -#define tskMPU_REGION_READ_WRITE ( 1UL << 1UL ) -#define tskMPU_REGION_EXECUTE_NEVER ( 1UL << 2UL ) -#define tskMPU_REGION_NORMAL_MEMORY ( 1UL << 3UL ) -#define tskMPU_REGION_DEVICE_MEMORY ( 1UL << 4UL ) +#define tskMPU_REGION_READ_ONLY ( 1UL << 0UL ) +#define tskMPU_REGION_READ_WRITE ( 1UL << 1UL ) +#define tskMPU_REGION_EXECUTE_NEVER ( 1UL << 2UL ) +#define tskMPU_REGION_NORMAL_MEMORY ( 1UL << 3UL ) +#define tskMPU_REGION_DEVICE_MEMORY ( 1UL << 4UL ) + +/* The direct to task notification feature used to have only a single notification + * per task. Now there is an array of notifications per task that is dimensioned by + * configTASK_NOTIFICATION_ARRAY_ENTRIES. For backward compatibility, any use of the + * original direct to task notification defaults to using the first index in the + * array. */ +#define tskDEFAULT_INDEX_TO_NOTIFY ( 0 ) + +#define tskNO_AFFINITY ( 0x7FFFFFFF ) -#define tskNO_AFFINITY ( 0x7FFFFFFF ) /** + * task. h + * * Type by which tasks are referenced. For example, a call to xTaskCreate * returns (via a pointer parameter) an TaskHandle_t variable that can then * be used as a parameter to vTaskDelete to delete the task. * + * @cond + * \defgroup TaskHandle_t TaskHandle_t + * @endcond * \ingroup Tasks */ -struct tskTaskControlBlock; /* The old naming convention is used to prevent breaking kernel aware debuggers. */ -//typedef struct tskTaskControlBlock* TaskHandle_t; +struct tskTaskControlBlock; /* The old naming convention is used to prevent breaking kernel aware debuggers. */ +#ifdef ESP_PLATFORM // IDF-3769 typedef void* TaskHandle_t; +#else +typedef struct tskTaskControlBlock* TaskHandle_t; +#endif // ESP_PLATFORM /** * Defines the prototype to which the application task hook function must * conform. */ -typedef BaseType_t (*TaskHookFunction_t)( void * ); +typedef BaseType_t (* TaskHookFunction_t)( void * ); /** Task states returned by eTaskGetState. */ typedef enum { - eRunning = 0, /* A task is querying the state of itself, so must be running. */ - eReady, /* The task being queried is in a read or pending ready list. */ - eBlocked, /* The task being queried is in the Blocked state. */ - eSuspended, /* The task being queried is in the Suspended state, or is in the Blocked state with an infinite time out. */ - eDeleted, /* The task being queried has been deleted, but its TCB has not yet been freed. */ - eInvalid /* Used as an 'invalid state' value. */ + eRunning = 0, /* A task is querying the state of itself, so must be running. */ + eReady, /* The task being queried is in a read or pending ready list. */ + eBlocked, /* The task being queried is in the Blocked state. */ + eSuspended, /* The task being queried is in the Suspended state, or is in the Blocked state with an infinite time out. */ + eDeleted, /* The task being queried has been deleted, but its TCB has not yet been freed. */ + eInvalid /* Used as an 'invalid state' value. */ } eTaskState; /* Actions that can be performed when vTaskNotify() is called. */ typedef enum { - eNoAction = 0, /* Notify the task without updating its notify value. */ - eSetBits, /* Set bits in the task's notification value. */ - eIncrement, /* Increment the task's notification value. */ - eSetValueWithOverwrite, /* Set the task's notification value to a specific value even if the previous value has not yet been read by the task. */ - eSetValueWithoutOverwrite /* Set the task's notification value if the previous value has been read by the task. */ + eNoAction = 0, /* Notify the task without updating its notify value. */ + eSetBits, /* Set bits in the task's notification value. */ + eIncrement, /* Increment the task's notification value. */ + eSetValueWithOverwrite, /* Set the task's notification value to a specific value even if the previous value has not yet been read by the task. */ + eSetValueWithoutOverwrite /* Set the task's notification value if the previous value has been read by the task. */ } eNotifyAction; /** @cond */ @@ -101,8 +120,8 @@ typedef enum */ typedef struct xTIME_OUT { - BaseType_t xOverflowCount; - TickType_t xTimeOnEntering; + BaseType_t xOverflowCount; + TickType_t xTimeOnEntering; } TimeOut_t; /** @@ -110,9 +129,9 @@ typedef struct xTIME_OUT */ typedef struct xMEMORY_REGION { - void *pvBaseAddress; - uint32_t ulLengthInBytes; - uint32_t ulParameters; + void * pvBaseAddress; + uint32_t ulLengthInBytes; + uint32_t ulParameters; } MemoryRegion_t; /* @@ -120,50 +139,36 @@ typedef struct xMEMORY_REGION */ typedef struct xTASK_PARAMETERS { - TaskFunction_t pvTaskCode; - const char * const pcName; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ - configSTACK_DEPTH_TYPE usStackDepth; - void *pvParameters; - UBaseType_t uxPriority; - StackType_t *puxStackBuffer; - MemoryRegion_t xRegions[ portNUM_CONFIGURABLE_REGIONS ]; - #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) - StaticTask_t * const pxTaskBuffer; - #endif + TaskFunction_t pvTaskCode; + const char * const pcName; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + configSTACK_DEPTH_TYPE usStackDepth; + void * pvParameters; + UBaseType_t uxPriority; + StackType_t * puxStackBuffer; + MemoryRegion_t xRegions[ portNUM_CONFIGURABLE_REGIONS ]; + #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) + StaticTask_t * const pxTaskBuffer; + #endif } TaskParameters_t; - -/* - * Used with the uxTaskGetSystemState() function to return the state of each task in the system. - */ +/* Used with the uxTaskGetSystemState() function to return the state of each task + * in the system. */ typedef struct xTASK_STATUS { - TaskHandle_t xHandle; /* The handle of the task to which the rest of the information in the structure relates. */ - const char *pcTaskName; /* A pointer to the task's name. This value will be invalid if the task was deleted since the structure was populated! */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ - UBaseType_t xTaskNumber; /* A number unique to the task. */ - eTaskState eCurrentState; /* The state in which the task existed when the structure was populated. */ - UBaseType_t uxCurrentPriority; /* The priority at which the task was running (may be inherited) when the structure was populated. */ - UBaseType_t uxBasePriority; /* The priority to which the task will return if the task's current priority has been inherited to avoid unbounded priority inversion when obtaining a mutex. Only valid if configUSE_MUTEXES is defined as 1 in FreeRTOSConfig.h. */ - uint32_t ulRunTimeCounter; /* The total run time allocated to the task so far, as defined by the run time stats clock. See http://www.freertos.org/rtos-run-time-stats.html. Only valid when configGENERATE_RUN_TIME_STATS is defined as 1 in FreeRTOSConfig.h. */ - StackType_t *pxStackBase; /* Points to the lowest address of the task's stack area. */ - configSTACK_DEPTH_TYPE usStackHighWaterMark; /* The minimum amount of stack space that has remained for the task since the task was created. The closer this value is to zero the closer the task has come to overflowing its stack. */ + TaskHandle_t xHandle; /* The handle of the task to which the rest of the information in the structure relates. */ + const char * pcTaskName; /* A pointer to the task's name. This value will be invalid if the task was deleted since the structure was populated! */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + UBaseType_t xTaskNumber; /* A number unique to the task. */ + eTaskState eCurrentState; /* The state in which the task existed when the structure was populated. */ + UBaseType_t uxCurrentPriority; /* The priority at which the task was running (may be inherited) when the structure was populated. */ + UBaseType_t uxBasePriority; /* The priority to which the task will return if the task's current priority has been inherited to avoid unbounded priority inversion when obtaining a mutex. Only valid if configUSE_MUTEXES is defined as 1 in FreeRTOSConfig.h. */ + uint32_t ulRunTimeCounter; /* The total run time allocated to the task so far, as defined by the run time stats clock. See https://www.FreeRTOS.org/rtos-run-time-stats.html. Only valid when configGENERATE_RUN_TIME_STATS is defined as 1 in FreeRTOSConfig.h. */ + StackType_t * pxStackBase; /* Points to the lowest address of the task's stack area. */ + configSTACK_DEPTH_TYPE usStackHighWaterMark; /* The minimum amount of stack space that has remained for the task since the task was created. The closer this value is to zero the closer the task has come to overflowing its stack. */ #if configTASKLIST_INCLUDE_COREID - BaseType_t xCoreID; /*!< Core this task is pinned to (0, 1, or -1 for tskNO_AFFINITY). This field is present if CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID is set. */ + BaseType_t xCoreID; /*!< Core this task is pinned to (0, 1, or -1 for tskNO_AFFINITY). This field is present if CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID is set. */ #endif } TaskStatus_t; -/** - * Used with the uxTaskGetSnapshotAll() function to save memory snapshot of each task in the system. - * We need this struct because TCB_t is defined (hidden) in tasks.c. - */ -typedef struct xTASK_SNAPSHOT -{ - void *pxTCB; /*!< Address of task control block. */ - StackType_t *pxTopOfStack; /*!< Points to the location of the last item placed on the tasks stack. */ - StackType_t *pxEndOfStack; /*!< Points to the end of the stack. pxTopOfStack < pxEndOfStack, stack grows hi2lo - pxTopOfStack > pxEndOfStack, stack grows lo2hi*/ -} TaskSnapshot_t; - /** @endcond */ /** @@ -171,9 +176,9 @@ typedef struct xTASK_SNAPSHOT */ typedef enum { - eAbortSleep = 0, /* A task has been made ready or a context switch pended since portSUPPORESS_TICKS_AND_SLEEP() was called - abort entering a sleep mode. */ - eStandardSleep, /* Enter a sleep mode that will not last any longer than the expected idle time. */ - eNoTasksWaitingTimeout /* No tasks are waiting for a timeout so it is safe to enter a sleep mode that can only be exited by an external interrupt. */ + eAbortSleep = 0, /* A task has been made ready or a context switch pended since portSUPPORESS_TICKS_AND_SLEEP() was called - abort entering a sleep mode. */ + eStandardSleep, /* Enter a sleep mode that will not last any longer than the expected idle time. */ + eNoTasksWaitingTimeout /* No tasks are waiting for a timeout so it is safe to enter a sleep mode that can only be exited by an external interrupt. */ } eSleepModeStatus; /** @@ -181,61 +186,104 @@ typedef enum * * \ingroup TaskUtils */ -#define tskIDLE_PRIORITY ( ( UBaseType_t ) 0U ) +#define tskIDLE_PRIORITY ( ( UBaseType_t ) 0U ) /** + * task. h + * * Macro for forcing a context switch. * + * @cond + * \defgroup taskYIELD taskYIELD + * @endcond * \ingroup SchedulerControl */ -#define taskYIELD() portYIELD() +#define taskYIELD() portYIELD() /** + * task. h + * * Macro to mark the start of a critical code region. Preemptive context * switches cannot occur when in a critical region. * * @note This may alter the stack (depending on the portable implementation) * so must be used with care! * + * @cond + * \defgroup taskENTER_CRITICAL taskENTER_CRITICAL + * @endcond * \ingroup SchedulerControl */ -#define taskENTER_CRITICAL( x ) portENTER_CRITICAL( x ) +#ifdef ESP_PLATFORM +#define taskENTER_CRITICAL( x ) portENTER_CRITICAL( x ) +#else +#define taskENTER_CRITICAL( ) portENTER_CRITICAL( ) +#endif // ESP_PLATFORM #define taskENTER_CRITICAL_FROM_ISR( ) portSET_INTERRUPT_MASK_FROM_ISR() -#define taskENTER_CRITICAL_ISR(mux) portENTER_CRITICAL_ISR(mux) + +#ifdef ESP_PLATFORM +#define taskENTER_CRITICAL_ISR( x ) portENTER_CRITICAL_ISR( x ) +#else +#define taskENTER_CRITICAL_ISR( ) portENTER_CRITICAL_ISR( ) +#endif // ESP_PLATFORM /** + * task. h + * * Macro to mark the end of a critical code region. Preemptive context * switches cannot occur when in a critical region. * * @note This may alter the stack (depending on the portable implementation) * so must be used with care! * + * @cond + * \defgroup taskEXIT_CRITICAL taskEXIT_CRITICAL + * @endcond * \ingroup SchedulerControl */ -#define taskEXIT_CRITICAL( x ) portEXIT_CRITICAL( x ) -#define taskEXIT_CRITICAL_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) -#define taskEXIT_CRITICAL_ISR(mux) portEXIT_CRITICAL_ISR(mux) +#ifdef ESP_PLATFORM +#define taskEXIT_CRITICAL( x ) portEXIT_CRITICAL( x ) +#else +#define taskEXIT_CRITICAL( ) portEXIT_CRITICAL( ) +#endif // ESP_PLATFORM +#define taskEXIT_CRITICAL_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) + +#ifdef ESP_PLATFORM +#define taskEXIT_CRITICAL_ISR( x ) portEXIT_CRITICAL_ISR( x ) +#else +#define taskEXIT_CRITICAL_ISR( ) portEXIT_CRITICAL_ISR( ) +#endif // ESP_PLATFORM /** + * task. h + * * Macro to disable all maskable interrupts. * + * @cond + * \defgroup taskDISABLE_INTERRUPTS taskDISABLE_INTERRUPTS + * @endcond * \ingroup SchedulerControl */ -#define taskDISABLE_INTERRUPTS() portDISABLE_INTERRUPTS() +#define taskDISABLE_INTERRUPTS() portDISABLE_INTERRUPTS() /** + * task. h + * * Macro to enable microcontroller interrupts. * + * @cond + * \defgroup taskENABLE_INTERRUPTS taskENABLE_INTERRUPTS + * @endcond * \ingroup SchedulerControl */ -#define taskENABLE_INTERRUPTS() portENABLE_INTERRUPTS() +#define taskENABLE_INTERRUPTS() portENABLE_INTERRUPTS() /* Definitions returned by xTaskGetSchedulerState(). taskSCHEDULER_SUSPENDED is -0 to generate more optimal code when configASSERT() is defined as the constant -is used in assert() statements. */ -#define taskSCHEDULER_SUSPENDED ( ( BaseType_t ) 0 ) -#define taskSCHEDULER_NOT_STARTED ( ( BaseType_t ) 1 ) -#define taskSCHEDULER_RUNNING ( ( BaseType_t ) 2 ) + * 0 to generate more optimal code when configASSERT() is defined as the constant + * is used in assert() statements. */ +#define taskSCHEDULER_SUSPENDED ( ( BaseType_t ) 0 ) +#define taskSCHEDULER_NOT_STARTED ( ( BaseType_t ) 1 ) +#define taskSCHEDULER_RUNNING ( ( BaseType_t ) 2 ) /*----------------------------------------------------------- @@ -283,13 +331,13 @@ is used in assert() statements. */ * \ingroup Tasks */ #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) - BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pvTaskCode, - const char * const pcName, - const uint32_t usStackDepth, - void * const pvParameters, - UBaseType_t uxPriority, - TaskHandle_t * const pvCreatedTask, - const BaseType_t xCoreID); + BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pvTaskCode, + const char * const pcName, + const uint32_t usStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + TaskHandle_t * const pvCreatedTask, + const BaseType_t xCoreID); #endif @@ -301,7 +349,7 @@ is used in assert() statements. */ * second block is used by the task as its stack. If a task is created using * xTaskCreate() then both blocks of memory are automatically dynamically * allocated inside the xTaskCreate() function. (see - * http://www.freertos.org/a00111.html). If a task is created using + * https://www.FreeRTOS.org/a00111.html). If a task is created using * xTaskCreateStatic() then the application writer must provide the required * memory. xTaskCreateStatic() therefore allows a task to be created without * using any dynamic memory allocation. @@ -345,50 +393,52 @@ is used in assert() statements. */ * * Example usage: * @code{c} - * // Task to be created. - * void vTaskCode( void * pvParameters ) - * { + * // Task to be created. + * void vTaskCode( void * pvParameters ) + * { * for( ;; ) * { * // Task code goes here. * } - * } + * } * - * // Function that creates a task. - * void vOtherFunction( void ) - * { - * static uint8_t ucParameterToPass; - * TaskHandle_t xHandle = NULL; + * // Function that creates a task. + * void vOtherFunction( void ) + * { + * static uint8_t ucParameterToPass; + * TaskHandle_t xHandle = NULL; * * // Create the task, storing the handle. Note that the passed parameter ucParameterToPass * // must exist for the lifetime of the task, so in this case is declared static. If it was just an * // an automatic stack variable it might no longer exist, or at least have been corrupted, by the time * // the new task attempts to access it. * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, &ucParameterToPass, tskIDLE_PRIORITY, &xHandle ); - * configASSERT( xHandle ); + * configASSERT( xHandle ); * * // Use the handle to delete the task. - * if( xHandle != NULL ) - * { - * vTaskDelete( xHandle ); - * } - * } + * if( xHandle != NULL ) + * { + * vTaskDelete( xHandle ); + * } + * } * @endcode + * @cond + * \defgroup xTaskCreate xTaskCreate + * @endcond * \ingroup Tasks */ +#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) -#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) - - static inline IRAM_ATTR BaseType_t xTaskCreate( - TaskFunction_t pvTaskCode, - const char * const pcName, - const uint32_t usStackDepth, - void * const pvParameters, - UBaseType_t uxPriority, - TaskHandle_t * const pvCreatedTask) - { - return xTaskCreatePinnedToCore( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pvCreatedTask, tskNO_AFFINITY ); - } + static inline IRAM_ATTR BaseType_t xTaskCreate( + TaskFunction_t pvTaskCode, + const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + const uint32_t usStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + TaskHandle_t * const pxCreatedTask) PRIVILEGED_FUNCTION + { + return xTaskCreatePinnedToCore( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask, tskNO_AFFINITY ); + } #endif @@ -439,14 +489,14 @@ is used in assert() statements. */ * \ingroup Tasks */ #if( configSUPPORT_STATIC_ALLOCATION == 1 ) - TaskHandle_t xTaskCreateStaticPinnedToCore( TaskFunction_t pvTaskCode, - const char * const pcName, - const uint32_t ulStackDepth, - void * const pvParameters, - UBaseType_t uxPriority, - StackType_t * const pxStackBuffer, - StaticTask_t * const pxTaskBuffer, - const BaseType_t xCoreID ); + TaskHandle_t xTaskCreateStaticPinnedToCore( TaskFunction_t pvTaskCode, + const char * const pcName, + const uint32_t ulStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + StackType_t * const pxStackBuffer, + StaticTask_t * const pxTaskBuffer, + const BaseType_t xCoreID ); #endif /* configSUPPORT_STATIC_ALLOCATION */ /** @@ -497,71 +547,80 @@ is used in assert() statements. */ * Example usage: * @code{c} * - * // Dimensions the buffer that the task being created will use as its stack. - * // NOTE: This is the number of bytes the stack will hold, not the number of - * // words as found in vanilla FreeRTOS. - * #define STACK_SIZE 200 + * // Dimensions the buffer that the task being created will use as its stack. + * // NOTE: This is the number of bytes the stack will hold, not the number of + * // words as found in vanilla FreeRTOS. + * #define STACK_SIZE 200 * - * // Structure that will hold the TCB of the task being created. - * StaticTask_t xTaskBuffer; + * // Structure that will hold the TCB of the task being created. + * StaticTask_t xTaskBuffer; * - * // Buffer that the task being created will use as its stack. Note this is - * // an array of StackType_t variables. The size of StackType_t is dependent on - * // the RTOS port. - * StackType_t xStack[ STACK_SIZE ]; + * // Buffer that the task being created will use as its stack. Note this is + * // an array of StackType_t variables. The size of StackType_t is dependent on + * // the RTOS port. + * StackType_t xStack[ STACK_SIZE ]; * - * // Function that implements the task being created. - * void vTaskCode( void * pvParameters ) - * { - * // The parameter value is expected to be 1 as 1 is passed in the - * // pvParameters value in the call to xTaskCreateStatic(). - * configASSERT( ( uint32_t ) pvParameters == 1UL ); + * // Function that implements the task being created. + * void vTaskCode( void * pvParameters ) + * { + * // The parameter value is expected to be 1 as 1 is passed in the + * // pvParameters value in the call to xTaskCreateStatic(). + * configASSERT( ( uint32_t ) pvParameters == 1UL ); * - * for( ;; ) - * { - * // Task code goes here. - * } - * } + * for( ;; ) + * { + * // Task code goes here. + * } + * } * - * // Function that creates a task. - * void vOtherFunction( void ) - * { - * TaskHandle_t xHandle = NULL; + * // Function that creates a task. + * void vOtherFunction( void ) + * { + * TaskHandle_t xHandle = NULL; * - * // Create the task without using any dynamic memory allocation. - * xHandle = xTaskCreateStatic( - * vTaskCode, // Function that implements the task. - * "NAME", // Text name for the task. - * STACK_SIZE, // Stack size in bytes, not words. - * ( void * ) 1, // Parameter passed into the task. - * tskIDLE_PRIORITY,// Priority at which the task is created. - * xStack, // Array to use as the task's stack. - * &xTaskBuffer ); // Variable to hold the task's data structure. + * // Create the task without using any dynamic memory allocation. + * xHandle = xTaskCreateStatic( + * vTaskCode, // Function that implements the task. + * "NAME", // Text name for the task. + * STACK_SIZE, // Stack size in bytes, not words. + * ( void * ) 1, // Parameter passed into the task. + * tskIDLE_PRIORITY,// Priority at which the task is created. + * xStack, // Array to use as the task's stack. + * &xTaskBuffer ); // Variable to hold the task's data structure. * - * // puxStackBuffer and pxTaskBuffer were not NULL, so the task will have - * // been created, and xHandle will be the task's handle. Use the handle - * // to suspend the task. - * vTaskSuspend( xHandle ); - * } + * // puxStackBuffer and pxTaskBuffer were not NULL, so the task will have + * // been created, and xHandle will be the task's handle. Use the handle + * // to suspend the task. + * vTaskSuspend( xHandle ); + * } * @endcode * \ingroup Tasks */ #if( configSUPPORT_STATIC_ALLOCATION == 1 ) - static inline IRAM_ATTR TaskHandle_t xTaskCreateStatic( - TaskFunction_t pvTaskCode, - const char * const pcName, - const uint32_t ulStackDepth, - void * const pvParameters, - UBaseType_t uxPriority, - StackType_t * const pxStackBuffer, - StaticTask_t * const pxTaskBuffer) - { - return xTaskCreateStaticPinnedToCore( pvTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, pxStackBuffer, pxTaskBuffer, tskNO_AFFINITY ); - } + static inline IRAM_ATTR TaskHandle_t xTaskCreateStatic( + TaskFunction_t pvTaskCode, + const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + const uint32_t ulStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + StackType_t * const puxStackBuffer, + StaticTask_t * const pxTaskBuffer) PRIVILEGED_FUNCTION + { + return xTaskCreateStaticPinnedToCore( pvTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, puxStackBuffer, pxTaskBuffer, tskNO_AFFINITY ); + } #endif /* configSUPPORT_STATIC_ALLOCATION */ -/* +/** + * @cond + * task. h + * @code{c} + * BaseType_t xTaskCreateRestricted( TaskParameters_t *pxTaskDefinition, TaskHandle_t *pxCreatedTask ); + * @endcode + * @endcond + * + * Only available when configSUPPORT_DYNAMIC_ALLOCATION is set to 1. + * * xTaskCreateRestricted() should only be used in systems that include an MPU * implementation. * @@ -572,12 +631,12 @@ is used in assert() statements. */ * See xTaskCreateRestrictedStatic() for a version that does not use any * dynamic memory allocation. * - * param pxTaskDefinition Pointer to a structure that contains a member + * @param pxTaskDefinition Pointer to a structure that contains a member * for each of the normal xTaskCreate() parameters (see the xTaskCreate() API * documentation) plus an optional stack buffer and the memory region * definitions. * - * param pxCreatedTask Used to pass back a handle by which the created task + * @param pxCreatedTask Used to pass back a handle by which the created task * can be referenced. * * return pdPASS if the task was successfully created and added to a ready @@ -588,54 +647,65 @@ is used in assert() statements. */ * // Create an TaskParameters_t structure that defines the task to be created. * static const TaskParameters_t xCheckTaskParameters = * { - * vATask, // pvTaskCode - the function that implements the task. - * "ATask", // pcName - just a text name for the task to assist debugging. - * 100, // usStackDepth - the stack size DEFINED IN WORDS. - * NULL, // pvParameters - passed into the task function as the function parameters. - * ( 1UL | portPRIVILEGE_BIT ),// uxPriority - task priority, set the portPRIVILEGE_BIT if the task should run in a privileged state. - * cStackBuffer,// puxStackBuffer - the buffer to be used as the task stack. + * vATask, // pvTaskCode - the function that implements the task. + * "ATask", // pcName - just a text name for the task to assist debugging. + * 100, // usStackDepth - the stack size DEFINED IN WORDS. + * NULL, // pvParameters - passed into the task function as the function parameters. + * ( 1UL | portPRIVILEGE_BIT ),// uxPriority - task priority, set the portPRIVILEGE_BIT if the task should run in a privileged state. + * cStackBuffer,// puxStackBuffer - the buffer to be used as the task stack. * - * // xRegions - Allocate up to three separate memory regions for access by - * // the task, with appropriate access permissions. Different processors have - * // different memory alignment requirements - refer to the FreeRTOS documentation - * // for full information. - * { - * // Base address Length Parameters - * { cReadWriteArray, 32, portMPU_REGION_READ_WRITE }, - * { cReadOnlyArray, 32, portMPU_REGION_READ_ONLY }, - * { cPrivilegedOnlyAccessArray, 128, portMPU_REGION_PRIVILEGED_READ_WRITE } - * } + * // xRegions - Allocate up to three separate memory regions for access by + * // the task, with appropriate access permissions. Different processors have + * // different memory alignment requirements - refer to the FreeRTOS documentation + * // for full information. + * { + * // Base address Length Parameters + * { cReadWriteArray, 32, portMPU_REGION_READ_WRITE }, + * { cReadOnlyArray, 32, portMPU_REGION_READ_ONLY }, + * { cPrivilegedOnlyAccessArray, 128, portMPU_REGION_PRIVILEGED_READ_WRITE } + * } * }; * * int main( void ) * { * TaskHandle_t xHandle; * - * // Create a task from the const structure defined above. The task handle - * // is requested (the second parameter is not NULL) but in this case just for - * // demonstration purposes as its not actually used. - * xTaskCreateRestricted( &xRegTest1Parameters, &xHandle ); + * // Create a task from the const structure defined above. The task handle + * // is requested (the second parameter is not NULL) but in this case just for + * // demonstration purposes as its not actually used. + * xTaskCreateRestricted( &xRegTest1Parameters, &xHandle ); * - * // Start the scheduler. - * vTaskStartScheduler(); + * // Start the scheduler. + * vTaskStartScheduler(); * - * // Will only get here if there was insufficient memory to create the idle - * // and/or timer task. - * for( ;; ); + * // Will only get here if there was insufficient memory to create the idle + * // and/or timer task. + * for( ;; ); * } * @endcode + * @cond + * \defgroup xTaskCreateRestricted xTaskCreateRestricted + * @endcond * \ingroup Tasks */ -#if( portUSING_MPU_WRAPPERS == 1 ) - BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ); +#if ( portUSING_MPU_WRAPPERS == 1 ) + BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, + TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION; #endif -/* - * xTaskCreateRestrictedStatic() should only be used in systems that include an - * MPU implementation. +/** + * @cond + * task. h + * @code{c} + * BaseType_t xTaskCreateRestrictedStatic( TaskParameters_t *pxTaskDefinition, TaskHandle_t *pxCreatedTask ); + * @endcode + * @endcond * * Only available when configSUPPORT_STATIC_ALLOCATION is set to 1. * + * xTaskCreateRestrictedStatic() should only be used in systems that include an + * MPU implementation. + * * Internally, within the FreeRTOS implementation, tasks use two blocks of * memory. The first block is used to hold the task's data structures. The * second block is used by the task as its stack. If a task is created using @@ -647,14 +717,14 @@ is used in assert() statements. */ * xTaskCreateRestrictedStatic() therefore allows a memory protected task to be * created without using any dynamic memory allocation. * - * param pxTaskDefinition Pointer to a structure that contains a member + * @param pxTaskDefinition Pointer to a structure that contains a member * for each of the normal xTaskCreate() parameters (see the xTaskCreate() API * documentation) plus an optional stack buffer and the memory region * definitions. If configSUPPORT_STATIC_ALLOCATION is set to 1 the structure * contains an additional member, which is used to point to a variable of type * StaticTask_t - which is then used to hold the task's data structure. * - * param pxCreatedTask Used to pass back a handle by which the created task + * @param pxCreatedTask Used to pass back a handle by which the created task * can be referenced. * * return pdPASS if the task was successfully created and added to a ready @@ -669,62 +739,72 @@ is used in assert() statements. */ * static PRIVILEGED_DATA StaticTask_t xTaskBuffer; * static const TaskParameters_t xCheckTaskParameters = * { - * vATask, // pvTaskCode - the function that implements the task. - * "ATask", // pcName - just a text name for the task to assist debugging. - * 100, // usStackDepth - the stack size DEFINED IN BYTES. - * NULL, // pvParameters - passed into the task function as the function parameters. - * ( 1UL | portPRIVILEGE_BIT ),// uxPriority - task priority, set the portPRIVILEGE_BIT if the task should run in a privileged state. - * cStackBuffer,// puxStackBuffer - the buffer to be used as the task stack. + * vATask, // pvTaskCode - the function that implements the task. + * "ATask", // pcName - just a text name for the task to assist debugging. + * 100, // usStackDepth - the stack size DEFINED IN BYTES. + * NULL, // pvParameters - passed into the task function as the function parameters. + * ( 1UL | portPRIVILEGE_BIT ),// uxPriority - task priority, set the portPRIVILEGE_BIT if the task should run in a privileged state. + * cStackBuffer,// puxStackBuffer - the buffer to be used as the task stack. * - * // xRegions - Allocate up to three separate memory regions for access by - * // the task, with appropriate access permissions. Different processors have - * // different memory alignment requirements - refer to the FreeRTOS documentation - * // for full information. - * { - * // Base address Length Parameters - * { cReadWriteArray, 32, portMPU_REGION_READ_WRITE }, - * { cReadOnlyArray, 32, portMPU_REGION_READ_ONLY }, - * { cPrivilegedOnlyAccessArray, 128, portMPU_REGION_PRIVILEGED_READ_WRITE } - * } + * // xRegions - Allocate up to three separate memory regions for access by + * // the task, with appropriate access permissions. Different processors have + * // different memory alignment requirements - refer to the FreeRTOS documentation + * // for full information. + * { + * // Base address Length Parameters + * { cReadWriteArray, 32, portMPU_REGION_READ_WRITE }, + * { cReadOnlyArray, 32, portMPU_REGION_READ_ONLY }, + * { cPrivilegedOnlyAccessArray, 128, portMPU_REGION_PRIVILEGED_READ_WRITE } + * } * - * &xTaskBuffer; // Holds the task's data structure. + * &xTaskBuffer; // Holds the task's data structure. * }; * * int main( void ) * { * TaskHandle_t xHandle; * - * // Create a task from the const structure defined above. The task handle - * // is requested (the second parameter is not NULL) but in this case just for - * // demonstration purposes as its not actually used. - * xTaskCreateRestricted( &xRegTest1Parameters, &xHandle ); + * // Create a task from the const structure defined above. The task handle + * // is requested (the second parameter is not NULL) but in this case just for + * // demonstration purposes as its not actually used. + * xTaskCreateRestricted( &xRegTest1Parameters, &xHandle ); * - * // Start the scheduler. - * vTaskStartScheduler(); + * // Start the scheduler. + * vTaskStartScheduler(); * - * // Will only get here if there was insufficient memory to create the idle - * // and/or timer task. - * for( ;; ); + * // Will only get here if there was insufficient memory to create the idle + * // and/or timer task. + * for( ;; ); * } * @endcode + * @cond + * \defgroup xTaskCreateRestrictedStatic xTaskCreateRestrictedStatic + * @endcond * \ingroup Tasks */ -#if( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) - BaseType_t xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ); +#if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) + BaseType_t xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition, + TaskHandle_t * pxCreatedTask ) PRIVILEGED_FUNCTION; #endif -/* +/** + * @cond + * task. h + * @code{c} + * void vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions ); + * @endcode + * @endcond + * * Memory regions are assigned to a restricted task when the task is created by * a call to xTaskCreateRestricted(). These regions can be redefined using * vTaskAllocateMPURegions(). * - * param xTask The handle of the task being updated. + * @param xTask The handle of the task being updated. * - * param pxRegions A pointer to an MemoryRegion_t structure that contains the + * @param pxRegions A pointer to an MemoryRegion_t structure that contains the * new memory region definitions. * * Example usage: - * * @code{c} * // Define an array of MemoryRegion_t structures that configures an MPU region * // allowing read/write access for 1024 bytes starting at the beginning of the @@ -732,38 +812,49 @@ is used in assert() statements. */ * // unused so set to zero. * static const MemoryRegion_t xAltRegions[ portNUM_CONFIGURABLE_REGIONS ] = * { - * // Base address Length Parameters - * { ucOneKByte, 1024, portMPU_REGION_READ_WRITE }, - * { 0, 0, 0 }, - * { 0, 0, 0 } + * // Base address Length Parameters + * { ucOneKByte, 1024, portMPU_REGION_READ_WRITE }, + * { 0, 0, 0 }, + * { 0, 0, 0 } * }; * * void vATask( void *pvParameters ) * { - * // This task was created such that it has access to certain regions of - * // memory as defined by the MPU configuration. At some point it is - * // desired that these MPU regions are replaced with that defined in the - * // xAltRegions const struct above. Use a call to vTaskAllocateMPURegions() - * // for this purpose. NULL is used as the task handle to indicate that this - * // function should modify the MPU regions of the calling task. - * vTaskAllocateMPURegions( NULL, xAltRegions ); + * // This task was created such that it has access to certain regions of + * // memory as defined by the MPU configuration. At some point it is + * // desired that these MPU regions are replaced with that defined in the + * // xAltRegions const struct above. Use a call to vTaskAllocateMPURegions() + * // for this purpose. NULL is used as the task handle to indicate that this + * // function should modify the MPU regions of the calling task. + * vTaskAllocateMPURegions( NULL, xAltRegions ); * - * // Now the task can continue its function, but from this point on can only - * // access its stack and the ucOneKByte array (unless any other statically - * // defined or shared regions have been declared elsewhere). + * // Now the task can continue its function, but from this point on can only + * // access its stack and the ucOneKByte array (unless any other statically + * // defined or shared regions have been declared elsewhere). * } * @endcode + * @cond + * \defgroup xTaskCreateRestricted xTaskCreateRestricted + * @endcond * \ingroup Tasks */ -void vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions ) PRIVILEGED_FUNCTION; +void vTaskAllocateMPURegions( TaskHandle_t xTask, + const MemoryRegion_t * const pxRegions ) PRIVILEGED_FUNCTION; /** - * Remove a task from the RTOS real time kernel's management. The task being - * deleted will be removed from all ready, blocked, suspended and event lists. + * @cond + * task. h + * @code{c} + * void vTaskDelete( TaskHandle_t xTask ); + * @endcode + * @endcond * * INCLUDE_vTaskDelete must be defined as 1 for this function to be available. * See the configuration section for more information. * + * Remove a task from the RTOS real time kernel's management. The task being + * deleted will be removed from all ready, blocked, suspended and event lists. + * * NOTE: The idle task is responsible for freeing the kernel allocated * memory from tasks that have been deleted. It is therefore important that * the idle task is not starved of microcontroller processing time if your @@ -779,17 +870,20 @@ void vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const p * * Example usage: * @code{c} - * void vOtherFunction( void ) - * { - * TaskHandle_t xHandle; + * void vOtherFunction( void ) + * { + * TaskHandle_t xHandle; * - * // Create the task, storing the handle. - * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle ); + * // Create the task, storing the handle. + * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle ); * - * // Use the handle to delete the task. - * vTaskDelete( xHandle ); - * } + * // Use the handle to delete the task. + * vTaskDelete( xHandle ); + * } * @endcode + * @cond + * \defgroup vTaskDelete vTaskDelete + * @endcond * \ingroup Tasks */ void vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION; @@ -799,7 +893,10 @@ void vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION; *----------------------------------------------------------*/ /** - * Delay a task for a given number of ticks. + * task. h + * @code{c} + * void vTaskDelay( const TickType_t xTicksToDelay ); + * @endcode * * Delay a task for a given number of ticks. The actual time that the * task remains blocked depends on the tick rate. The constant @@ -809,6 +906,7 @@ void vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION; * INCLUDE_vTaskDelay must be defined as 1 for this function to be available. * See the configuration section for more information. * + * * vTaskDelay() specifies a time at which the task wishes to unblock relative to * the time at which vTaskDelay() is called. For example, specifying a block * period of 100 ticks will cause the task to unblock 100 ticks after @@ -816,7 +914,7 @@ void vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION; * of controlling the frequency of a periodic task as the path taken through the * code, as well as other task and interrupt activity, will effect the frequency * at which vTaskDelay() gets called and therefore the time at which the task - * next executes. See vTaskDelayUntil() for an alternative API function designed + * next executes. See xTaskDelayUntil() for an alternative API function designed * to facilitate fixed frequency execution. It does this by specifying an * absolute time (rather than a relative time) at which the calling task should * unblock. @@ -826,27 +924,34 @@ void vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION; * * Example usage: * @code{c} - * void vTaskFunction( void * pvParameters ) - * { - * // Block for 500ms. - * const TickType_t xDelay = 500 / portTICK_PERIOD_MS; + * void vTaskFunction( void * pvParameters ) + * { + * // Block for 500ms. + * const TickType_t xDelay = 500 / portTICK_PERIOD_MS; * - * for( ;; ) - * { - * // Simply toggle the LED every 500ms, blocking between each toggle. - * vToggleLED(); - * vTaskDelay( xDelay ); - * } - * } + * for( ;; ) + * { + * // Simply toggle the LED every 500ms, blocking between each toggle. + * vToggleLED(); + * vTaskDelay( xDelay ); + * } + * } * @endcode + * + * @cond + * \defgroup vTaskDelay vTaskDelay + * @endcond * \ingroup TaskCtrl */ void vTaskDelay( const TickType_t xTicksToDelay ) PRIVILEGED_FUNCTION; /** - * Delay a task until a specified time. + * task. h + * @code{c} + * BaseType_t xTaskDelayUntil( TickType_t *pxPreviousWakeTime, const TickType_t xTimeIncrement ); + * @endcode * - * INCLUDE_vTaskDelayUntil must be defined as 1 for this function to be available. + * INCLUDE_xTaskDelayUntil must be defined as 1 for this function to be available. * See the configuration section for more information. * * Delay a task until a specified time. This function can be used by periodic @@ -861,46 +966,73 @@ void vTaskDelay( const TickType_t xTicksToDelay ) PRIVILEGED_FUNCTION; * each time it executes]. * * Whereas vTaskDelay () specifies a wake time relative to the time at which the function - * is called, vTaskDelayUntil () specifies the absolute (exact) time at which it wishes to + * is called, xTaskDelayUntil () specifies the absolute (exact) time at which it wishes to * unblock. * - * The constant portTICK_PERIOD_MS can be used to calculate real time from the tick - * rate - with the resolution of one tick period. + * The macro pdMS_TO_TICKS() can be used to calculate the number of ticks from a + * time specified in milliseconds with a resolution of one tick period. * * @param pxPreviousWakeTime Pointer to a variable that holds the time at which the * task was last unblocked. The variable must be initialised with the current time * prior to its first use (see the example below). Following this the variable is - * automatically updated within vTaskDelayUntil (). + * automatically updated within xTaskDelayUntil (). * * @param xTimeIncrement The cycle time period. The task will be unblocked at - * time *pxPreviousWakeTime + xTimeIncrement. Calling vTaskDelayUntil with the + * time *pxPreviousWakeTime + xTimeIncrement. Calling xTaskDelayUntil with the * same xTimeIncrement parameter value will cause the task to execute with * a fixed interface period. * + * @return Value which can be used to check whether the task was actually delayed. + * Will be pdTRUE if the task way delayed and pdFALSE otherwise. A task will not + * be delayed if the next expected wake time is in the past. + * * Example usage: * @code{c} - * // Perform an action every 10 ticks. - * void vTaskFunction( void * pvParameters ) - * { - * TickType_t xLastWakeTime; - * const TickType_t xFrequency = 10; + * // Perform an action every 10 ticks. + * void vTaskFunction( void * pvParameters ) + * { + * TickType_t xLastWakeTime; + * const TickType_t xFrequency = 10; + * BaseType_t xWasDelayed; * - * // Initialise the xLastWakeTime variable with the current time. - * xLastWakeTime = xTaskGetTickCount (); - * for( ;; ) - * { - * // Wait for the next cycle. - * vTaskDelayUntil( &xLastWakeTime, xFrequency ); + * // Initialise the xLastWakeTime variable with the current time. + * xLastWakeTime = xTaskGetTickCount (); + * for( ;; ) + * { + * // Wait for the next cycle. + * xWasDelayed = xTaskDelayUntil( &xLastWakeTime, xFrequency ); * - * // Perform action here. - * } - * } + * // Perform action here. xWasDelayed value can be used to determine + * // whether a deadline was missed if the code here took too long. + * } + * } * @endcode + * @cond + * \defgroup xTaskDelayUntil xTaskDelayUntil + * @endcond * \ingroup TaskCtrl */ -void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement ) PRIVILEGED_FUNCTION; +BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime, + const TickType_t xTimeIncrement ) PRIVILEGED_FUNCTION; + +/* + * vTaskDelayUntil() is the older version of xTaskDelayUntil() and does not + * return a value. + */ +#define vTaskDelayUntil( pxPreviousWakeTime, xTimeIncrement ) \ +{ \ + ( void ) xTaskDelayUntil( pxPreviousWakeTime, xTimeIncrement ); \ +} + /** + * @cond + * task. h + * @code{c} + * BaseType_t xTaskAbortDelay( TaskHandle_t xTask ); + * @endcode + * @endcond + * * INCLUDE_xTaskAbortDelay must be defined as 1 in FreeRTOSConfig.h for this * function to be available. * @@ -912,22 +1044,36 @@ void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xT * task will leave the Blocked state, and return from whichever function call * placed the task into the Blocked state. * + * There is no 'FromISR' version of this function as an interrupt would need to + * know which object a task was blocked on in order to know which actions to + * take. For example, if the task was blocked on a queue the interrupt handler + * would then need to know if the queue was locked. + * * @param xTask The handle of the task to remove from the Blocked state. * * @return If the task referenced by xTask was not in the Blocked state then * pdFAIL is returned. Otherwise pdPASS is returned. * + * @cond * \defgroup xTaskAbortDelay xTaskAbortDelay + * @endcond * \ingroup TaskCtrl */ BaseType_t xTaskAbortDelay( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; /** - * Obtain the priority of any task. + * @cond + * task. h + * @code{c} + * UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask ); + * @endcode + * @endcond * * INCLUDE_uxTaskPriorityGet must be defined as 1 for this function to be available. * See the configuration section for more information. * + * Obtain the priority of any task. + * * @param xTask Handle of the task to be queried. Passing a NULL * handle results in the priority of the calling task being returned. * @@ -935,9 +1081,9 @@ BaseType_t xTaskAbortDelay( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; * * Example usage: * @code{c} - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; + * void vAFunction( void ) + * { + * TaskHandle_t xHandle; * * // Create a task, storing the handle. * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle ); @@ -961,23 +1107,39 @@ BaseType_t xTaskAbortDelay( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; * } * } * @endcode + * @cond + * \defgroup uxTaskPriorityGet uxTaskPriorityGet + * @endcond * \ingroup TaskCtrl */ UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION; /** + * @cond + * task. h + * @code{c} + * UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask ); + * @endcode + * @endcond + * * A version of uxTaskPriorityGet() that can be used from an ISR. */ UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION; /** - * Obtain the state of any task. - * - * States are encoded by the eTaskState enumerated type. + * @cond + * task. h + * @code{c} + * eTaskState eTaskGetState( TaskHandle_t xTask ); + * @endcode + * @endcond * * INCLUDE_eTaskGetState must be defined as 1 for this function to be available. * See the configuration section for more information. * + * Obtain the state of any task. States are encoded by the eTaskState + * enumerated type. + * * @param xTask Handle of the task to be queried. * * @return The state of xTask at the time the function was called. Note the @@ -987,11 +1149,17 @@ UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask ) PRIVILEGED_FUNC eTaskState eTaskGetState( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; /** - * Populates a TaskStatus_t structure with information about a task. + * @cond + * task. h + * @code{c} + * void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState ); + * @endcode + * @endcond * * configUSE_TRACE_FACILITY must be defined as 1 for this function to be * available. See the configuration section for more information. * + * Populates a TaskStatus_t structure with information about a task. * * @param xTask Handle of the task being queried. If xTask is NULL then * information will be returned about the calling task. @@ -1022,29 +1190,42 @@ eTaskState eTaskGetState( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; * TaskHandle_t xHandle; * TaskStatus_t xTaskDetails; * - * // Obtain the handle of a task from its name. - * xHandle = xTaskGetHandle( "Task_Name" ); + * // Obtain the handle of a task from its name. + * xHandle = xTaskGetHandle( "Task_Name" ); * - * // Check the handle is not NULL. - * configASSERT( xHandle ); + * // Check the handle is not NULL. + * configASSERT( xHandle ); * - * // Use the handle to obtain further information about the task. - * vTaskGetInfo( xHandle, - * &xTaskDetails, - * pdTRUE, // Include the high water mark in xTaskDetails. - * eInvalid ); // Include the task state in xTaskDetails. + * // Use the handle to obtain further information about the task. + * vTaskGetInfo( xHandle, + * &xTaskDetails, + * pdTRUE, // Include the high water mark in xTaskDetails. + * eInvalid ); // Include the task state in xTaskDetails. * } * @endcode + * @cond + * \defgroup vTaskGetInfo vTaskGetInfo + * @endcond * \ingroup TaskCtrl */ -void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState ) PRIVILEGED_FUNCTION; +void vTaskGetInfo( TaskHandle_t xTask, + TaskStatus_t * pxTaskStatus, + BaseType_t xGetFreeStackSpace, + eTaskState eState ) PRIVILEGED_FUNCTION; /** - * Set the priority of any task. + * @cond + * task. h + * @code{c} + * void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ); + * @endcode + * @endcond * * INCLUDE_vTaskPrioritySet must be defined as 1 for this function to be available. * See the configuration section for more information. * + * Set the priority of any task. + * * A context switch will occur before the function returns if the priority * being set is higher than the currently executing task. * @@ -1055,9 +1236,9 @@ void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xG * * Example usage: * @code{c} - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; + * void vAFunction( void ) + * { + * TaskHandle_t xHandle; * * // Create a task, storing the handle. * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle ); @@ -1071,14 +1252,23 @@ void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xG * * // Use a NULL handle to raise our priority to the same value. * vTaskPrioritySet( NULL, tskIDLE_PRIORITY + 1 ); - * } + * } * @endcode + * @cond + * \defgroup vTaskPrioritySet vTaskPrioritySet + * @endcond * \ingroup TaskCtrl */ -void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ) PRIVILEGED_FUNCTION; +void vTaskPrioritySet( TaskHandle_t xTask, + UBaseType_t uxNewPriority ) PRIVILEGED_FUNCTION; /** - * Suspend a task. + * @cond + * task. h + * @code{c} + * void vTaskSuspend( TaskHandle_t xTaskToSuspend ); + * @endcode + * @endcond * * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. * See the configuration section for more information. @@ -1095,9 +1285,9 @@ void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ) PRIVILEGE * * Example usage: * @code{c} - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; + * void vAFunction( void ) + * { + * TaskHandle_t xHandle; * * // Create a task, storing the handle. * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle ); @@ -1120,18 +1310,28 @@ void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ) PRIVILEGE * * // We cannot get here unless another task calls vTaskResume * // with our handle as the parameter. - * } + * } * @endcode + * @cond + * \defgroup vTaskSuspend vTaskSuspend + * @endcond * \ingroup TaskCtrl */ void vTaskSuspend( TaskHandle_t xTaskToSuspend ) PRIVILEGED_FUNCTION; /** - * Resumes a suspended task. + * @cond + * task. h + * @code{c} + * void vTaskResume( TaskHandle_t xTaskToResume ); + * @endcode + * @endcond * * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. * See the configuration section for more information. * + * Resumes a suspended task. + * * A task that has been suspended by one or more calls to vTaskSuspend () * will be made available for running again by a single call to * vTaskResume (). @@ -1140,9 +1340,9 @@ void vTaskSuspend( TaskHandle_t xTaskToSuspend ) PRIVILEGED_FUNCTION; * * Example usage: * @code{c} - * void vAFunction( void ) - * { - * TaskHandle_t xHandle; + * void vAFunction( void ) + * { + * TaskHandle_t xHandle; * * // Create a task, storing the handle. * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle ); @@ -1165,18 +1365,28 @@ void vTaskSuspend( TaskHandle_t xTaskToSuspend ) PRIVILEGED_FUNCTION; * * // The created task will once again get microcontroller processing * // time in accordance with its priority within the system. - * } + * } * @endcode + * @cond + * \defgroup vTaskResume vTaskResume + * @endcond * \ingroup TaskCtrl */ void vTaskResume( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; /** - * An implementation of vTaskResume() that can be called from within an ISR. + * @cond + * task. h + * @code{c} + * void xTaskResumeFromISR( TaskHandle_t xTaskToResume ); + * @endcode + * @endcond * * INCLUDE_xTaskResumeFromISR must be defined as 1 for this function to be * available. See the configuration section for more information. * + * An implementation of vTaskResume() that can be called from within an ISR. + * * A task that has been suspended by one or more calls to vTaskSuspend () * will be made available for running again by a single call to * xTaskResumeFromISR (). @@ -1192,6 +1402,9 @@ void vTaskResume( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; * otherwise pdFALSE. This is used by the ISR to determine if a context switch * may be required following the ISR. * + * @cond + * \defgroup vTaskResumeFromISR vTaskResumeFromISR + * @endcond * \ingroup TaskCtrl */ BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; @@ -1201,21 +1414,27 @@ BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; *----------------------------------------------------------*/ /** @cond */ /** - * Starts the real time kernel tick processing. + * @cond + * task. h + * @code{c} + * void vTaskStartScheduler( void ); + * @endcode + * @endcond * + * Starts the real time kernel tick processing. After calling the kernel + * has control over which tasks are executed and when. + * NOTE: In ESP-IDF the scheduler is started automatically during * application startup, vTaskStartScheduler() should not be called from * ESP-IDF applications. * - * After calling the kernel has control over which tasks are executed and when. - * * See the demo application file main.c for an example of creating * tasks and starting the kernel. * * Example usage: * @code{c} - * void vAFunction( void ) - * { + * void vAFunction( void ) + * { * // Create at least one task before starting the kernel. * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); * @@ -1223,15 +1442,23 @@ BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION; * vTaskStartScheduler (); * * // Will not get here unless a task calls vTaskEndScheduler () - * } + * } * @endcode * + * @cond + * \defgroup vTaskStartScheduler vTaskStartScheduler + * @endcond * \ingroup SchedulerControl */ void vTaskStartScheduler( void ) PRIVILEGED_FUNCTION; /** - * Stops the real time kernel tick. + * @cond + * task. h + * @code{c} + * void vTaskEndScheduler( void ); + * @endcode + * @endcond * * NOTE: At the time of writing only the x86 real mode port, which runs on a PC * in place of DOS, implements this function. @@ -1254,8 +1481,8 @@ void vTaskStartScheduler( void ) PRIVILEGED_FUNCTION; * * Example usage: * @code{c} - * void vTaskCode( void * pvParameters ) - * { + * void vTaskCode( void * pvParameters ) + * { * for( ;; ) * { * // Task code goes here. @@ -1264,10 +1491,10 @@ void vTaskStartScheduler( void ) PRIVILEGED_FUNCTION; * // so call ... * vTaskEndScheduler (); * } - * } + * } * - * void vAFunction( void ) - * { + * void vAFunction( void ) + * { * // Create at least one task before starting the kernel. * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); * @@ -1277,8 +1504,12 @@ void vTaskStartScheduler( void ) PRIVILEGED_FUNCTION; * // Will only get here when the vTaskCode () task has called * // vTaskEndScheduler (). When we get here we are back to single task * // execution. - * } + * } * @endcode + * + * @cond + * \defgroup vTaskEndScheduler vTaskEndScheduler + * @endcond * \ingroup SchedulerControl */ void vTaskEndScheduler( void ) PRIVILEGED_FUNCTION; @@ -1286,9 +1517,15 @@ void vTaskEndScheduler( void ) PRIVILEGED_FUNCTION; /** @endcond */ /** - * Suspends the scheduler without disabling interrupts. + * @cond + * task. h + * @code{c} + * void vTaskSuspendAll( void ); + * @endcode + * @endcond * - * Context switches will not occur while the scheduler is suspended. + * Suspends the scheduler without disabling interrupts. Context switches will + * not occur while the scheduler is suspended. * * After calling vTaskSuspendAll () the calling task will continue to execute * without risk of being swapped out until a call to xTaskResumeAll () has been @@ -1300,8 +1537,8 @@ void vTaskEndScheduler( void ) PRIVILEGED_FUNCTION; * * Example usage: * @code{c} - * void vTask1( void * pvParameters ) - * { + * void vTask1( void * pvParameters ) + * { * for( ;; ) * { * // Task code goes here. @@ -1327,13 +1564,23 @@ void vTaskEndScheduler( void ) PRIVILEGED_FUNCTION; * // The operation is complete. Restart the kernel. * xTaskResumeAll (); * } - * } + * } * @endcode + * @cond + * \defgroup vTaskSuspendAll vTaskSuspendAll + * @endcond * \ingroup SchedulerControl */ void vTaskSuspendAll( void ) PRIVILEGED_FUNCTION; /** + * @cond + * task. h + * @code{c} + * BaseType_t xTaskResumeAll( void ); + * @endcode + * @endcond + * * Resumes scheduler activity after it was suspended by a call to * vTaskSuspendAll(). * @@ -1341,12 +1588,12 @@ void vTaskSuspendAll( void ) PRIVILEGED_FUNCTION; * that were previously suspended by a call to vTaskSuspend(). * * @return If resuming the scheduler caused a context switch then pdTRUE is - * returned, otherwise pdFALSE is returned. + * returned, otherwise pdFALSE is returned. * * Example usage: * @code{c} - * void vTask1( void * pvParameters ) - * { + * void vTask1( void * pvParameters ) + * { * for( ;; ) * { * // Task code goes here. @@ -1377,8 +1624,11 @@ void vTaskSuspendAll( void ) PRIVILEGED_FUNCTION; * taskYIELD (); * } * } - * } + * } * @endcode + * @cond + * \defgroup xTaskResumeAll xTaskResumeAll + * @endcond * \ingroup SchedulerControl */ BaseType_t xTaskResumeAll( void ) PRIVILEGED_FUNCTION; @@ -1388,16 +1638,29 @@ BaseType_t xTaskResumeAll( void ) PRIVILEGED_FUNCTION; *----------------------------------------------------------*/ /** - * Get tick count + * @cond + * task. h + * @code{c} + * TickType_t xTaskGetTickCount( void ); + * @endcode + * @endcond * * @return The count of ticks since vTaskStartScheduler was called. * + * @cond + * \defgroup xTaskGetTickCount xTaskGetTickCount + * @endcond * \ingroup TaskUtils */ TickType_t xTaskGetTickCount( void ) PRIVILEGED_FUNCTION; /** - * Get tick count from ISR + * @cond + * task. h + * @code{c} + * TickType_t xTaskGetTickCountFromISR( void ); + * @endcode + * @endcond * * @return The count of ticks since vTaskStartScheduler was called. * @@ -1406,44 +1669,73 @@ TickType_t xTaskGetTickCount( void ) PRIVILEGED_FUNCTION; * microcontroller being used or interrupt nesting is either not supported or * not being used. * + * @cond + * \defgroup xTaskGetTickCountFromISR xTaskGetTickCountFromISR + * @endcond * \ingroup TaskUtils */ TickType_t xTaskGetTickCountFromISR( void ) PRIVILEGED_FUNCTION; /** - * Get current number of tasks + * @cond + * task. h + * @code{c} + * uint16_t uxTaskGetNumberOfTasks( void ); + * @endcode + * @endcond * * @return The number of tasks that the real time kernel is currently managing. * This includes all ready, blocked and suspended tasks. A task that * has been deleted but not yet freed by the idle task will also be * included in the count. * + * @cond + * \defgroup uxTaskGetNumberOfTasks uxTaskGetNumberOfTasks + * @endcond * \ingroup TaskUtils */ UBaseType_t uxTaskGetNumberOfTasks( void ) PRIVILEGED_FUNCTION; /** - * Get task name + * @cond + * task. h + * @code{c} + * char *pcTaskGetName( TaskHandle_t xTaskToQuery ); + * @endcode + * @endcond * * @return The text (human readable) name of the task referenced by the handle * xTaskToQuery. A task can query its own name by either passing in its own * handle, or by setting xTaskToQuery to NULL. * + * @cond + * \defgroup pcTaskGetName pcTaskGetName + * @endcond * \ingroup TaskUtils */ -char *pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +char * pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ /** - * @note This function takes a relatively long time to complete and should be + * @cond + * task. h + * @code{c} + * TaskHandle_t xTaskGetHandle( const char *pcNameToQuery ); + * @endcode + * @endcond + * + * NOTE: This function takes a relatively long time to complete and should be * used sparingly. * * @return The handle of the task that has the human readable name pcNameToQuery. * NULL is returned if no matching name is found. INCLUDE_xTaskGetHandle * must be set to 1 in FreeRTOSConfig.h for pcTaskGetHandle() to be available. * + * @cond + * \defgroup pcTaskGetHandle pcTaskGetHandle + * @endcond * \ingroup TaskUtils */ -TaskHandle_t xTaskGetHandle( const char *pcNameToQuery ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +TaskHandle_t xTaskGetHandle( const char * pcNameToQuery ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ /** * Returns the high water mark of the stack associated with xTask. @@ -1513,109 +1805,195 @@ configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) PRIVIL uint8_t* pxTaskGetStackStart( TaskHandle_t xTask) PRIVILEGED_FUNCTION; /* When using trace macros it is sometimes necessary to include task.h before -FreeRTOS.h. When this is done TaskHookFunction_t will not yet have been defined, -so the following two prototypes will cause a compilation error. This can be -fixed by simply guarding against the inclusion of these two prototypes unless -they are explicitly required by the configUSE_APPLICATION_TASK_TAG configuration -constant. */ + * FreeRTOS.h. When this is done TaskHookFunction_t will not yet have been defined, + * so the following two prototypes will cause a compilation error. This can be + * fixed by simply guarding against the inclusion of these two prototypes unless + * they are explicitly required by the configUSE_APPLICATION_TASK_TAG configuration + * constant. */ #ifdef configUSE_APPLICATION_TASK_TAG - #if configUSE_APPLICATION_TASK_TAG == 1 - /** - * Sets pxHookFunction to be the task hook function used by the task xTask. - * @param xTask Handle of the task to set the hook function for - * Passing xTask as NULL has the effect of setting the calling - * tasks hook function. - * @param pxHookFunction Pointer to the hook function. - */ - void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction ) PRIVILEGED_FUNCTION; + #if configUSE_APPLICATION_TASK_TAG == 1 +/** + * @cond + * task.h + * @code{c} + * void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction ); + * @endcode + * @endcond + * + * Sets pxHookFunction to be the task hook function used by the task xTask. + * @param xTask Handle of the task to set the hook function for + * Passing xTask as NULL has the effect of setting the calling + * tasks hook function. + * @param pxHookFunction Pointer to the hook function. + */ + void vTaskSetApplicationTaskTag( TaskHandle_t xTask, + TaskHookFunction_t pxHookFunction ) PRIVILEGED_FUNCTION; - /** - * - * Returns the pxHookFunction value assigned to the task xTask. Do not - * call from an interrupt service routine - call - * xTaskGetApplicationTaskTagFromISR() instead. - */ - TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; +/** + * @cond + * task.h + * @code{c} + * void xTaskGetApplicationTaskTag( TaskHandle_t xTask ); + * @endcode + * @endcond + * + * Returns the pxHookFunction value assigned to the task xTask. Do not + * call from an interrupt service routine - call + * xTaskGetApplicationTaskTagFromISR() instead. + */ + TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; - /** - * - * Returns the pxHookFunction value assigned to the task xTask. Can - * be called from an interrupt service routine. - */ - TaskHookFunction_t xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; - #endif /* configUSE_APPLICATION_TASK_TAG ==1 */ +/** + * @cond + * task.h + * @code{c} + * void xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask ); + * @endcode + * @endcond + * + * Returns the pxHookFunction value assigned to the task xTask. Can + * be called from an interrupt service routine. + */ + TaskHookFunction_t xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; + #endif /* configUSE_APPLICATION_TASK_TAG ==1 */ #endif /* ifdef configUSE_APPLICATION_TASK_TAG */ -#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) +#if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) - /** - * Set local storage pointer specific to the given task. - * - * Each task contains an array of pointers that is dimensioned by the - * configNUM_THREAD_LOCAL_STORAGE_POINTERS setting in FreeRTOSConfig.h. - * The kernel does not use the pointers itself, so the application writer - * can use the pointers for any purpose they wish. - * - * @param xTaskToSet Task to set thread local storage pointer for - * @param xIndex The index of the pointer to set, from 0 to - * configNUM_THREAD_LOCAL_STORAGE_POINTERS - 1. - * @param pvValue Pointer value to set. - */ - void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue ) PRIVILEGED_FUNCTION; + /** + * Set local storage pointer specific to the given task. + * + * Each task contains an array of pointers that is dimensioned by the + * configNUM_THREAD_LOCAL_STORAGE_POINTERS setting in FreeRTOSConfig.h. + * The kernel does not use the pointers itself, so the application writer + * can use the pointers for any purpose they wish. + * + * @param xTaskToSet Task to set thread local storage pointer for + * @param xIndex The index of the pointer to set, from 0 to + * configNUM_THREAD_LOCAL_STORAGE_POINTERS - 1. + * @param pvValue Pointer value to set. + */ + void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, + BaseType_t xIndex, + void * pvValue ) PRIVILEGED_FUNCTION; - /** - * Get local storage pointer specific to the given task. - * - * Each task contains an array of pointers that is dimensioned by the - * configNUM_THREAD_LOCAL_STORAGE_POINTERS setting in FreeRTOSConfig.h. - * The kernel does not use the pointers itself, so the application writer - * can use the pointers for any purpose they wish. - * - * @param xTaskToQuery Task to get thread local storage pointer for - * @param xIndex The index of the pointer to get, from 0 to - * configNUM_THREAD_LOCAL_STORAGE_POINTERS - 1. - * @return Pointer value - */ - void *pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, BaseType_t xIndex ) PRIVILEGED_FUNCTION; + /** + * Get local storage pointer specific to the given task. + * + * Each task contains an array of pointers that is dimensioned by the + * configNUM_THREAD_LOCAL_STORAGE_POINTERS setting in FreeRTOSConfig.h. + * The kernel does not use the pointers itself, so the application writer + * can use the pointers for any purpose they wish. + * + * @param xTaskToQuery Task to get thread local storage pointer for + * @param xIndex The index of the pointer to get, from 0 to + * configNUM_THREAD_LOCAL_STORAGE_POINTERS - 1. + * @return Pointer value + */ + void * pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, + BaseType_t xIndex ) PRIVILEGED_FUNCTION; - #if ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS ) + #if ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS ) - /** - * Prototype of local storage pointer deletion callback. - */ - typedef void (*TlsDeleteCallbackFunction_t)( int, void * ); + /** + * Prototype of local storage pointer deletion callback. + */ + typedef void (*TlsDeleteCallbackFunction_t)( int, void * ); - /** - * Set local storage pointer and deletion callback. - * - * Each task contains an array of pointers that is dimensioned by the - * configNUM_THREAD_LOCAL_STORAGE_POINTERS setting in FreeRTOSConfig.h. - * The kernel does not use the pointers itself, so the application writer - * can use the pointers for any purpose they wish. - * - * Local storage pointers set for a task can reference dynamically - * allocated resources. This function is similar to - * vTaskSetThreadLocalStoragePointer, but provides a way to release - * these resources when the task gets deleted. For each pointer, - * a callback function can be set. This function will be called - * when task is deleted, with the local storage pointer index - * and value as arguments. - * - * @param xTaskToSet Task to set thread local storage pointer for - * @param xIndex The index of the pointer to set, from 0 to - * configNUM_THREAD_LOCAL_STORAGE_POINTERS - 1. - * @param pvValue Pointer value to set. - * @param pvDelCallback Function to call to dispose of the local - * storage pointer when the task is deleted. - */ - void vTaskSetThreadLocalStoragePointerAndDelCallback( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue, TlsDeleteCallbackFunction_t pvDelCallback); - #endif + /** + * Set local storage pointer and deletion callback. + * + * Each task contains an array of pointers that is dimensioned by the + * configNUM_THREAD_LOCAL_STORAGE_POINTERS setting in FreeRTOSConfig.h. + * The kernel does not use the pointers itself, so the application writer + * can use the pointers for any purpose they wish. + * + * Local storage pointers set for a task can reference dynamically + * allocated resources. This function is similar to + * vTaskSetThreadLocalStoragePointer, but provides a way to release + * these resources when the task gets deleted. For each pointer, + * a callback function can be set. This function will be called + * when task is deleted, with the local storage pointer index + * and value as arguments. + * + * @param xTaskToSet Task to set thread local storage pointer for + * @param xIndex The index of the pointer to set, from 0 to + * configNUM_THREAD_LOCAL_STORAGE_POINTERS - 1. + * @param pvValue Pointer value to set. + * @param pvDelCallback Function to call to dispose of the local + * storage pointer when the task is deleted. + */ + void vTaskSetThreadLocalStoragePointerAndDelCallback( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue, TlsDeleteCallbackFunction_t pvDelCallback); + #endif #endif +#if ( configCHECK_FOR_STACK_OVERFLOW > 0 ) + + /** + * @cond + * task.h + * @code{c} + * void vApplicationStackOverflowHook( TaskHandle_t xTask char *pcTaskName); + * @endcode + * @endcond + * The application stack overflow hook is called when a stack overflow is detected for a task. + * + * Details on stack overflow detection can be found here: https://www.FreeRTOS.org/Stacks-and-stack-overflow-checking.html + * + * @param xTask the task that just exceeded its stack boundaries. + * @param pcTaskName A character string containing the name of the offending task. + */ + void vApplicationStackOverflowHook( TaskHandle_t xTask, + char * pcTaskName ); + +#endif + +#if ( configUSE_TICK_HOOK > 0 ) + /** + * @cond + * task.h + * @code{c} + * void vApplicationTickHook( void ); + * @endcode + * @endcond + * + * This hook function is called in the system tick handler after any OS work is completed. + */ + void vApplicationTickHook( void ); /*lint !e526 Symbol not defined as it is an application callback. */ + +#endif + +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + /** + * @cond + * task.h + * @code{c} + * void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, StackType_t ** ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ) + * @endcode + * @endcond + * This function is used to provide a statically allocated block of memory to FreeRTOS to hold the Idle Task TCB. This function is required when + * configSUPPORT_STATIC_ALLOCATION is set. For more information see this URI: https://www.FreeRTOS.org/a00110.html#configSUPPORT_STATIC_ALLOCATION + * + * @param ppxIdleTaskTCBBuffer A handle to a statically allocated TCB buffer + * @param ppxIdleTaskStackBuffer A handle to a statically allocated Stack buffer for thie idle task + * @param pulIdleTaskStackSize A pointer to the number of elements that will fit in the allocated stack buffer + */ + void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, + StackType_t ** ppxIdleTaskStackBuffer, + uint32_t * pulIdleTaskStackSize ); /*lint !e526 Symbol not defined as it is an application callback. */ +#endif + /** - * Calls the hook function associated with xTask. Passing xTask as NULL has + * @cond + * task.h + * @code{c} + * BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter ); + * @endcode + * @endcond + * + * Calls the hook function associated with xTask. Passing xTask as NULL has * the effect of calling the Running tasks (the calling task) hook function. * * @param xTask Handle of the task to call the hook for. @@ -1623,7 +2001,8 @@ constant. */ * wants. The return value is the value returned by the task hook function * registered by the user. */ -BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter ) PRIVILEGED_FUNCTION; +BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, + void * pvParameter ) PRIVILEGED_FUNCTION; /** * xTaskGetIdleTaskHandle() is only available if @@ -1644,7 +2023,7 @@ TaskHandle_t xTaskGetIdleTaskHandle( void ) PRIVILEGED_FUNCTION; * of run time consumed by the task. See the TaskStatus_t structure * definition in this file for the full member list. * - * @note This function is intended for debugging use only as its use results in + * NOTE: This function is intended for debugging use only as its use results in * the scheduler remaining suspended for an extended period. * * @param pxTaskStatusArray A pointer to an array of TaskStatus_t structures. @@ -1660,7 +2039,7 @@ TaskHandle_t xTaskGetIdleTaskHandle( void ) PRIVILEGED_FUNCTION; * @param pulTotalRunTime If configGENERATE_RUN_TIME_STATS is set to 1 in * FreeRTOSConfig.h then *pulTotalRunTime is set by uxTaskGetSystemState() to the * total run time (as defined by the run time stats clock, see - * http://www.freertos.org/rtos-run-time-stats.html) since the target booted. + * https://www.FreeRTOS.org/rtos-run-time-stats.html) since the target booted. * pulTotalRunTime can be set to NULL to omit the total run time information. * * @return The number of TaskStatus_t structures that were populated by @@ -1670,68 +2049,70 @@ TaskHandle_t xTaskGetIdleTaskHandle( void ) PRIVILEGED_FUNCTION; * * Example usage: * @code{c} - * // This example demonstrates how a human readable table of run time stats - * // information is generated from raw data provided by uxTaskGetSystemState(). - * // The human readable table is written to pcWriteBuffer - * void vTaskGetRunTimeStats( char *pcWriteBuffer ) - * { - * TaskStatus_t *pxTaskStatusArray; - * volatile UBaseType_t uxArraySize, x; - * uint32_t ulTotalRunTime, ulStatsAsPercentage; - * - * // Make sure the write buffer does not contain a string. - * *pcWriteBuffer = 0x00; - * - * // Take a snapshot of the number of tasks in case it changes while this - * // function is executing. - * uxArraySize = uxTaskGetNumberOfTasks(); - * - * // Allocate a TaskStatus_t structure for each task. An array could be - * // allocated statically at compile time. - * pxTaskStatusArray = pvPortMalloc( uxArraySize * sizeof( TaskStatus_t ) ); - * - * if( pxTaskStatusArray != NULL ) + * // This example demonstrates how a human readable table of run time stats + * // information is generated from raw data provided by uxTaskGetSystemState(). + * // The human readable table is written to pcWriteBuffer + * void vTaskGetRunTimeStats( char *pcWriteBuffer ) * { - * // Generate raw status information about each task. - * uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalRunTime ); + * TaskStatus_t *pxTaskStatusArray; + * volatile UBaseType_t uxArraySize, x; + * uint32_t ulTotalRunTime, ulStatsAsPercentage; * - * // For percentage calculations. - * ulTotalRunTime /= 100UL; + * // Make sure the write buffer does not contain a string. + * *pcWriteBuffer = 0x00; * - * // Avoid divide by zero errors. - * if( ulTotalRunTime > 0 ) + * // Take a snapshot of the number of tasks in case it changes while this + * // function is executing. + * uxArraySize = uxTaskGetNumberOfTasks(); + * + * // Allocate a TaskStatus_t structure for each task. An array could be + * // allocated statically at compile time. + * pxTaskStatusArray = pvPortMalloc( uxArraySize * sizeof( TaskStatus_t ) ); + * + * if( pxTaskStatusArray != NULL ) * { - * // For each populated position in the pxTaskStatusArray array, - * // format the raw data as human readable ASCII data - * for( x = 0; x < uxArraySize; x++ ) + * // Generate raw status information about each task. + * uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalRunTime ); + * + * // For percentage calculations. + * ulTotalRunTime /= 100UL; + * + * // Avoid divide by zero errors. + * if( ulTotalRunTime > 0 ) * { - * // What percentage of the total run time has the task used? - * // This will always be rounded down to the nearest integer. - * // ulTotalRunTimeDiv100 has already been divided by 100. - * ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalRunTime; - * - * if( ulStatsAsPercentage > 0UL ) + * // For each populated position in the pxTaskStatusArray array, + * // format the raw data as human readable ASCII data + * for( x = 0; x < uxArraySize; x++ ) * { - * sprintf( pcWriteBuffer, "%s\t\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage ); - * } - * else - * { - * // If the percentage is zero here then the task has - * // consumed less than 1% of the total run time. - * sprintf( pcWriteBuffer, "%s\t\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter ); - * } + * // What percentage of the total run time has the task used? + * // This will always be rounded down to the nearest integer. + * // ulTotalRunTimeDiv100 has already been divided by 100. + * ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalRunTime; * - * pcWriteBuffer += strlen( ( char * ) pcWriteBuffer ); + * if( ulStatsAsPercentage > 0UL ) + * { + * sprintf( pcWriteBuffer, "%s\t\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage ); + * } + * else + * { + * // If the percentage is zero here then the task has + * // consumed less than 1% of the total run time. + * sprintf( pcWriteBuffer, "%s\t\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter ); + * } + * + * pcWriteBuffer += strlen( ( char * ) pcWriteBuffer ); + * } * } - * } * - * // The array is no longer needed, free the memory it consumes. - * vPortFree( pxTaskStatusArray ); + * // The array is no longer needed, free the memory it consumes. + * vPortFree( pxTaskStatusArray ); + * } * } - * } - * @endcode + * @endcode */ -UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime ) PRIVILEGED_FUNCTION; +UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, + const UBaseType_t uxArraySize, + uint32_t * const pulTotalRunTime ) PRIVILEGED_FUNCTION; /** * List all the current tasks. @@ -1740,7 +2121,7 @@ UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const * both be defined as 1 for this function to be available. See the * configuration section of the FreeRTOS.org website for more information. * - * @note This function will disable interrupts for its duration. It is + * NOTE 1: This function will disable interrupts for its duration. It is * not intended for normal application runtime use but as a debug aid. * * Lists all the current tasks, along with their current state and stack @@ -1749,7 +2130,9 @@ UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const * Tasks are reported as blocked ('B'), ready ('R'), deleted ('D') or * suspended ('S'). * - * @note This function is provided for convenience only, and is used by many of the + * PLEASE NOTE: + * + * This function is provided for convenience only, and is used by many of the * demo applications. Do not consider it to be part of the scheduler. * * vTaskList() calls uxTaskGetSystemState(), then formats part of the @@ -1772,9 +2155,12 @@ UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const * enough to contain the generated report. Approximately 40 bytes per * task should be sufficient. * + * @cond + * \defgroup vTaskList vTaskList + * @endcond * \ingroup TaskUtils */ -void vTaskList( char * pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +void vTaskList( char * pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ /** * Get the state of running tasks as a string @@ -1787,7 +2173,7 @@ void vTaskList( char * pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unquali * value respectively. The counter should be at least 10 times the frequency of * the tick count. * - * @note This function will disable interrupts for its duration. It is + * NOTE 1: This function will disable interrupts for its duration. It is * not intended for normal application runtime use but as a debug aid. * * Setting configGENERATE_RUN_TIME_STATS to 1 will result in a total @@ -1798,7 +2184,9 @@ void vTaskList( char * pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unquali * task into a buffer, both as an absolute count value and as a percentage * of the total system execution time. * - * @note This function is provided for convenience only, and is used by many of the + * NOTE 2: + * + * This function is provided for convenience only, and is used by many of the * demo applications. Do not consider it to be part of the scheduler. * * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part of the @@ -1822,42 +2210,69 @@ void vTaskList( char * pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unquali * contain the generated report. Approximately 40 bytes per task should * be sufficient. * + * @cond + * \defgroup vTaskGetRunTimeStats vTaskGetRunTimeStats + * @endcond * \ingroup TaskUtils */ -void vTaskGetRunTimeStats( char *pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +void vTaskGetRunTimeStats( char * pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ /** -* configGENERATE_RUN_TIME_STATS and configUSE_STATS_FORMATTING_FUNCTIONS -* must both be defined as 1 for this function to be available. The application -* must also then provide definitions for -* portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and portGET_RUN_TIME_COUNTER_VALUE() -* to configure a peripheral timer/counter and return the timers current count -* value respectively. The counter should be at least 10 times the frequency of -* the tick count. -* -* Setting configGENERATE_RUN_TIME_STATS to 1 will result in a total -* accumulated execution time being stored for each task. The resolution -* of the accumulated time value depends on the frequency of the timer -* configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro. -* While uxTaskGetSystemState() and vTaskGetRunTimeStats() writes the total -* execution time of each task into a buffer, ulTaskGetIdleRunTimeCounter() -* returns the total execution time of just the idle task. -* -* @return The total run time of the idle task. This is the amount of time the -* idle task has actually been executing. The unit of time is dependent on the -* frequency configured using the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and -* portGET_RUN_TIME_COUNTER_VALUE() macros. -* -* \ingroup TaskUtils -*/ + * @cond + * task. h + * @code + * uint32_t ulTaskGetIdleRunTimeCounter( void ); + * @endcode + * @endcond + * + * configGENERATE_RUN_TIME_STATS and configUSE_STATS_FORMATTING_FUNCTIONS + * must both be defined as 1 for this function to be available. The application + * must also then provide definitions for + * portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and portGET_RUN_TIME_COUNTER_VALUE() + * to configure a peripheral timer/counter and return the timers current count + * value respectively. The counter should be at least 10 times the frequency of + * the tick count. + * + * Setting configGENERATE_RUN_TIME_STATS to 1 will result in a total + * accumulated execution time being stored for each task. The resolution + * of the accumulated time value depends on the frequency of the timer + * configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro. + * While uxTaskGetSystemState() and vTaskGetRunTimeStats() writes the total + * execution time of each task into a buffer, ulTaskGetIdleRunTimeCounter() + * returns the total execution time of just the idle task. + * + * @return The total run time of the idle task. This is the amount of time the + * idle task has actually been executing. The unit of time is dependent on the + * frequency configured using the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and + * portGET_RUN_TIME_COUNTER_VALUE() macros. + * + * @cond + * \defgroup ulTaskGetIdleRunTimeCounter ulTaskGetIdleRunTimeCounter + * @endcond + * \ingroup TaskUtils + */ uint32_t ulTaskGetIdleRunTimeCounter( void ) PRIVILEGED_FUNCTION; /** - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this - * function to be available. + * task. h + * @code{c} + * BaseType_t xTaskNotifyIndexed( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction ); + * BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction ); + * @endcode * - * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private - * "notification value", which is a 32-bit unsigned integer (uint32_t). + * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * + * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these + * functions to be available. + * + * Sends a direct to task notification to a task, with an optional value and + * action. + * + * Each task has a private array of "notification values" (or 'notifications'), + * each of which is a 32-bit unsigned integer (uint32_t). The constant + * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the + * array, and (for backward compatibility) defaults to 1 if left undefined. + * Prior to FreeRTOS V10.4.0 there was only one notification value per task. * * Events can be sent to a task using an intermediary object. Examples of such * objects are queues, semaphores, mutexes and event groups. Task notifications @@ -1865,28 +2280,46 @@ uint32_t ulTaskGetIdleRunTimeCounter( void ) PRIVILEGED_FUNCTION; * an intermediary object. * * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment the task's notification value. In that way - * task notifications can be used to send data to a task, or be used as light - * weight and fast binary or counting semaphores. + * update, overwrite or increment one of the task's notification values. In + * that way task notifications can be used to send data to a task, or be used as + * light weight and fast binary or counting semaphores. * - * A notification sent to a task will remain pending until it is cleared by the - * task calling xTaskNotifyWait() or ulTaskNotifyTake(). If the task was - * already in the Blocked state to wait for a notification when the notification - * arrives then the task will automatically be removed from the Blocked state - * (unblocked) and the notification cleared. - * - * A task can use xTaskNotifyWait() to [optionally] block to wait for a - * notification to be pending, or ulTaskNotifyTake() to [optionally] block - * to wait for its notification value to have a non-zero value. The task does + * A task can use xTaskNotifyWaitIndexed() to [optionally] block to wait for a + * notification to be pending, or ulTaskNotifyTakeIndexed() to [optionally] block + * to wait for a notification value to have a non-zero value. The task does * not consume any CPU time while it is in the Blocked state. * - * See http://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * A notification sent to a task will remain pending until it is cleared by the + * task calling xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() (or their + * un-indexed equivalents). If the task was already in the Blocked state to + * wait for a notification when the notification arrives then the task will + * automatically be removed from the Blocked state (unblocked) and the + * notification cleared. + * + * **NOTE** Each notification within the array operates independently - a task + * can only block on one notification within the array at a time and will not be + * unblocked by a notification sent to any other array index. + * + * Backward compatibility information: + * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and + * all task notification API functions operated on that value. Replacing the + * single notification value with an array of notification values necessitated a + * new set of API functions that could address specific notifications within the + * array. xTaskNotify() is the original API function, and remains backward + * compatible by always operating on the notification value at index 0 in the + * array. Calling xTaskNotify() is equivalent to calling xTaskNotifyIndexed() + * with the uxIndexToNotify parameter set to 0. * * @param xTaskToNotify The handle of the task being notified. The handle to a * task can be returned from the xTaskCreate() API function used to create the * task, and the handle of the currently running task can be obtained by calling * xTaskGetCurrentTaskHandle(). * + * @param uxIndexToNotify The index within the target task's array of + * notification values to which the notification is to be sent. uxIndexToNotify + * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotify() does + * not have this parameter and always sends notifications to index 0. + * * @param ulValue Data that can be sent with the notification. How the data is * used depends on the value of the eAction parameter. * @@ -1894,54 +2327,100 @@ uint32_t ulTaskGetIdleRunTimeCounter( void ) PRIVILEGED_FUNCTION; * value, if at all. Valid values for eAction are as follows: * * eSetBits - - * The task's notification value is bitwise ORed with ulValue. xTaskNofify() - * always returns pdPASS in this case. + * The target notification value is bitwise ORed with ulValue. + * xTaskNotifyIndexed() always returns pdPASS in this case. * * eIncrement - - * The task's notification value is incremented. ulValue is not used and - * xTaskNotify() always returns pdPASS in this case. + * The target notification value is incremented. ulValue is not used and + * xTaskNotifyIndexed() always returns pdPASS in this case. * * eSetValueWithOverwrite - - * The task's notification value is set to the value of ulValue, even if the - * task being notified had not yet processed the previous notification (the - * task already had a notification pending). xTaskNotify() always returns - * pdPASS in this case. + * The target notification value is set to the value of ulValue, even if the + * task being notified had not yet processed the previous notification at the + * same array index (the task already had a notification pending at that index). + * xTaskNotifyIndexed() always returns pdPASS in this case. * * eSetValueWithoutOverwrite - - * If the task being notified did not already have a notification pending then - * the task's notification value is set to ulValue and xTaskNotify() will - * return pdPASS. If the task being notified already had a notification - * pending then no action is performed and pdFAIL is returned. + * If the task being notified did not already have a notification pending at the + * same array index then the target notification value is set to ulValue and + * xTaskNotifyIndexed() will return pdPASS. If the task being notified already + * had a notification pending at the same array index then no action is + * performed and pdFAIL is returned. * * eNoAction - - * The task receives a notification without its notification value being - * updated. ulValue is not used and xTaskNotify() always returns pdPASS in - * this case. + * The task receives a notification at the specified array index without the + * notification value at that index being updated. ulValue is not used and + * xTaskNotifyIndexed() always returns pdPASS in this case. * - * @param pulPreviousNotificationValue Can be used to pass out the subject - * task's notification value before any bits are modified by the notify - * function. + * pulPreviousNotificationValue - + * Can be used to pass out the subject task's notification value before any + * bits are modified by the notify function. * * @return Dependent on the value of eAction. See the description of the * eAction parameter. * + * \defgroup xTaskNotifyIndexed xTaskNotifyIndexed * \ingroup TaskNotifications */ -BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue ) PRIVILEGED_FUNCTION; -#define xTaskNotify( xTaskToNotify, ulValue, eAction ) xTaskGenericNotify( ( xTaskToNotify ), ( ulValue ), ( eAction ), NULL ) -#define xTaskNotifyAndQuery( xTaskToNotify, ulValue, eAction, pulPreviousNotifyValue ) xTaskGenericNotify( ( xTaskToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotifyValue ) ) +BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, + UBaseType_t uxIndexToNotify, + uint32_t ulValue, + eNotifyAction eAction, + uint32_t * pulPreviousNotificationValue ) PRIVILEGED_FUNCTION; +#define xTaskNotify( xTaskToNotify, ulValue, eAction ) \ + xTaskGenericNotify( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( ulValue ), ( eAction ), NULL ) +#define xTaskNotifyIndexed( xTaskToNotify, uxIndexToNotify, ulValue, eAction ) \ + xTaskGenericNotify( ( xTaskToNotify ), ( uxIndexToNotify ), ( ulValue ), ( eAction ), NULL ) /** - * Send task notification from an ISR. + * task. h + * @code{c} + * BaseType_t xTaskNotifyAndQueryIndexed( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotifyValue ); + * BaseType_t xTaskNotifyAndQuery( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotifyValue ); + * @endcode * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this - * function to be available. + * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. * - * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private - * "notification value", which is a 32-bit unsigned integer (uint32_t). + * xTaskNotifyAndQueryIndexed() performs the same operation as + * xTaskNotifyIndexed() with the addition that it also returns the subject + * task's prior notification value (the notification value at the time the + * function is called rather than when the function returns) in the additional + * pulPreviousNotifyValue parameter. * - * A version of xTaskNotify() that can be used from an interrupt service routine - * (ISR). + * xTaskNotifyAndQuery() performs the same operation as xTaskNotify() with the + * addition that it also returns the subject task's prior notification value + * (the notification value as it was at the time the function is called, rather + * than when the function returns) in the additional pulPreviousNotifyValue + * parameter. + * + * \defgroup xTaskNotifyAndQueryIndexed xTaskNotifyAndQueryIndexed + * \ingroup TaskNotifications + */ +#define xTaskNotifyAndQuery( xTaskToNotify, ulValue, eAction, pulPreviousNotifyValue ) \ + xTaskGenericNotify( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( ulValue ), ( eAction ), ( pulPreviousNotifyValue ) ) +#define xTaskNotifyAndQueryIndexed( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pulPreviousNotifyValue ) \ + xTaskGenericNotify( ( xTaskToNotify ), ( uxIndexToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotifyValue ) ) + +/** + * task. h + * @code{c} + * BaseType_t xTaskNotifyIndexedFromISR( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken ); + * BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken ); + * @endcode + * + * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * + * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these + * functions to be available. + * + * A version of xTaskNotifyIndexed() that can be used from an interrupt service + * routine (ISR). + * + * Each task has a private array of "notification values" (or 'notifications'), + * each of which is a 32-bit unsigned integer (uint32_t). The constant + * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the + * array, and (for backward compatibility) defaults to 1 if left undefined. + * Prior to FreeRTOS V10.4.0 there was only one notification value per task. * * Events can be sent to a task using an intermediary object. Examples of such * objects are queues, semaphores, mutexes and event groups. Task notifications @@ -1949,22 +2428,40 @@ BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNo * an intermediary object. * * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment the task's notification value. In that way - * task notifications can be used to send data to a task, or be used as light - * weight and fast binary or counting semaphores. + * update, overwrite or increment one of the task's notification values. In + * that way task notifications can be used to send data to a task, or be used as + * light weight and fast binary or counting semaphores. * - * A notification sent to a task will remain pending until it is cleared by the - * task calling xTaskNotifyWait() or ulTaskNotifyTake(). If the task was - * already in the Blocked state to wait for a notification when the notification - * arrives then the task will automatically be removed from the Blocked state - * (unblocked) and the notification cleared. - * - * A task can use xTaskNotifyWait() to [optionally] block to wait for a - * notification to be pending, or ulTaskNotifyTake() to [optionally] block - * to wait for its notification value to have a non-zero value. The task does + * A task can use xTaskNotifyWaitIndexed() to [optionally] block to wait for a + * notification to be pending, or ulTaskNotifyTakeIndexed() to [optionally] block + * to wait for a notification value to have a non-zero value. The task does * not consume any CPU time while it is in the Blocked state. * - * See http://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * A notification sent to a task will remain pending until it is cleared by the + * task calling xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() (or their + * un-indexed equivalents). If the task was already in the Blocked state to + * wait for a notification when the notification arrives then the task will + * automatically be removed from the Blocked state (unblocked) and the + * notification cleared. + * + * **NOTE** Each notification within the array operates independently - a task + * can only block on one notification within the array at a time and will not be + * unblocked by a notification sent to any other array index. + * + * Backward compatibility information: + * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and + * all task notification API functions operated on that value. Replacing the + * single notification value with an array of notification values necessitated a + * new set of API functions that could address specific notifications within the + * array. xTaskNotifyFromISR() is the original API function, and remains + * backward compatible by always operating on the notification value at index 0 + * within the array. Calling xTaskNotifyFromISR() is equivalent to calling + * xTaskNotifyIndexedFromISR() with the uxIndexToNotify parameter set to 0. + * + * @param uxIndexToNotify The index within the target task's array of + * notification values to which the notification is to be sent. uxIndexToNotify + * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyFromISR() + * does not have this parameter and always sends notifications to index 0. * * @param xTaskToNotify The handle of the task being notified. The handle to a * task can be returned from the xTaskCreate() API function used to create the @@ -1978,7 +2475,7 @@ BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNo * value, if at all. Valid values for eAction are as follows: * * eSetBits - - * The task's notification value is bitwise ORed with ulValue. xTaskNofify() + * The task's notification value is bitwise ORed with ulValue. xTaskNotify() * always returns pdPASS in this case. * * eIncrement - @@ -2002,9 +2499,6 @@ BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNo * updated. ulValue is not used and xTaskNotify() always returns pdPASS in * this case. * - * @param pulPreviousNotificationValue Can be used to pass out the subject task's - * notification value before any bits are modified by the notify function. - * * @param pxHigherPriorityTaskWoken xTaskNotifyFromISR() will set * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the * task to which the notification was sent to leave the Blocked state, and the @@ -2017,20 +2511,70 @@ BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNo * @return Dependent on the value of eAction. See the description of the * eAction parameter. * + * \defgroup xTaskNotifyIndexedFromISR xTaskNotifyIndexedFromISR * \ingroup TaskNotifications */ -BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; -#define xTaskNotifyFromISR( xTaskToNotify, ulValue, eAction, pxHigherPriorityTaskWoken ) xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( ulValue ), ( eAction ), NULL, ( pxHigherPriorityTaskWoken ) ) -#define xTaskNotifyAndQueryFromISR( xTaskToNotify, ulValue, eAction, pulPreviousNotificationValue, pxHigherPriorityTaskWoken ) xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotificationValue ), ( pxHigherPriorityTaskWoken ) ) +BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, + UBaseType_t uxIndexToNotify, + uint32_t ulValue, + eNotifyAction eAction, + uint32_t * pulPreviousNotificationValue, + BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; +#define xTaskNotifyFromISR( xTaskToNotify, ulValue, eAction, pxHigherPriorityTaskWoken ) \ + xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( ulValue ), ( eAction ), NULL, ( pxHigherPriorityTaskWoken ) ) +#define xTaskNotifyIndexedFromISR( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pxHigherPriorityTaskWoken ) \ + xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( uxIndexToNotify ), ( ulValue ), ( eAction ), NULL, ( pxHigherPriorityTaskWoken ) ) /** - * Wait for task notification + * task. h + * @code{c} + * BaseType_t xTaskNotifyAndQueryIndexedFromISR( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken ); + * BaseType_t xTaskNotifyAndQueryFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken ); + * @endcode + * + * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * + * xTaskNotifyAndQueryIndexedFromISR() performs the same operation as + * xTaskNotifyIndexedFromISR() with the addition that it also returns the + * subject task's prior notification value (the notification value at the time + * the function is called rather than at the time the function returns) in the + * additional pulPreviousNotifyValue parameter. + * + * xTaskNotifyAndQueryFromISR() performs the same operation as + * xTaskNotifyFromISR() with the addition that it also returns the subject + * task's prior notification value (the notification value at the time the + * function is called rather than at the time the function returns) in the + * additional pulPreviousNotifyValue parameter. + * + * \defgroup xTaskNotifyAndQueryIndexedFromISR xTaskNotifyAndQueryIndexedFromISR + * \ingroup TaskNotifications + */ +#define xTaskNotifyAndQueryIndexedFromISR( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pulPreviousNotificationValue, pxHigherPriorityTaskWoken ) \ + xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( uxIndexToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotificationValue ), ( pxHigherPriorityTaskWoken ) ) +#define xTaskNotifyAndQueryFromISR( xTaskToNotify, ulValue, eAction, pulPreviousNotificationValue, pxHigherPriorityTaskWoken ) \ + xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( ulValue ), ( eAction ), ( pulPreviousNotificationValue ), ( pxHigherPriorityTaskWoken ) ) + +/** + * task. h + * @code{c} + * BaseType_t xTaskNotifyWaitIndexed( UBaseType_t uxIndexToWaitOn, uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ); + * + * BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ); + * @endcode + * + * Waits for a direct to task notification to be pending at a given index within + * an array of direct to task notifications. + * + * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. * * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this * function to be available. * - * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private - * "notification value", which is a 32-bit unsigned integer (uint32_t). + * Each task has a private array of "notification values" (or 'notifications'), + * each of which is a 32-bit unsigned integer (uint32_t). The constant + * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the + * array, and (for backward compatibility) defaults to 1 if left undefined. + * Prior to FreeRTOS V10.4.0 there was only one notification value per task. * * Events can be sent to a task using an intermediary object. Examples of such * objects are queues, semaphores, mutexes and event groups. Task notifications @@ -2038,22 +2582,41 @@ BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulVal * an intermediary object. * * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment the task's notification value. In that way - * task notifications can be used to send data to a task, or be used as light - * weight and fast binary or counting semaphores. + * update, overwrite or increment one of the task's notification values. In + * that way task notifications can be used to send data to a task, or be used as + * light weight and fast binary or counting semaphores. * * A notification sent to a task will remain pending until it is cleared by the - * task calling xTaskNotifyWait() or ulTaskNotifyTake(). If the task was - * already in the Blocked state to wait for a notification when the notification - * arrives then the task will automatically be removed from the Blocked state - * (unblocked) and the notification cleared. + * task calling xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() (or their + * un-indexed equivalents). If the task was already in the Blocked state to + * wait for a notification when the notification arrives then the task will + * automatically be removed from the Blocked state (unblocked) and the + * notification cleared. * - * A task can use xTaskNotifyWait() to [optionally] block to wait for a - * notification to be pending, or ulTaskNotifyTake() to [optionally] block - * to wait for its notification value to have a non-zero value. The task does + * A task can use xTaskNotifyWaitIndexed() to [optionally] block to wait for a + * notification to be pending, or ulTaskNotifyTakeIndexed() to [optionally] block + * to wait for a notification value to have a non-zero value. The task does * not consume any CPU time while it is in the Blocked state. * - * See http://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * **NOTE** Each notification within the array operates independently - a task + * can only block on one notification within the array at a time and will not be + * unblocked by a notification sent to any other array index. + * + * Backward compatibility information: + * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and + * all task notification API functions operated on that value. Replacing the + * single notification value with an array of notification values necessitated a + * new set of API functions that could address specific notifications within the + * array. xTaskNotifyWait() is the original API function, and remains backward + * compatible by always operating on the notification value at index 0 in the + * array. Calling xTaskNotifyWait() is equivalent to calling + * xTaskNotifyWaitIndexed() with the uxIndexToWaitOn parameter set to 0. + * + * @param uxIndexToWaitOn The index within the calling task's array of + * notification values on which the calling task will wait for a notification to + * be received. uxIndexToWaitOn must be less than + * configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyWait() does + * not have this parameter and always waits for notifications on index 0. * * @param ulBitsToClearOnEntry Bits that are set in ulBitsToClearOnEntry value * will be cleared in the calling task's notification value before the task @@ -2092,18 +2655,39 @@ BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulVal * already pending when xTaskNotifyWait was called) then pdPASS is * returned. Otherwise pdFAIL is returned. * + * \defgroup xTaskNotifyWaitIndexed xTaskNotifyWaitIndexed * \ingroup TaskNotifications */ -BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; +BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn, + uint32_t ulBitsToClearOnEntry, + uint32_t ulBitsToClearOnExit, + uint32_t * pulNotificationValue, + TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; +#define xTaskNotifyWait( ulBitsToClearOnEntry, ulBitsToClearOnExit, pulNotificationValue, xTicksToWait ) \ + xTaskGenericNotifyWait( tskDEFAULT_INDEX_TO_NOTIFY, ( ulBitsToClearOnEntry ), ( ulBitsToClearOnExit ), ( pulNotificationValue ), ( xTicksToWait ) ) +#define xTaskNotifyWaitIndexed( uxIndexToWaitOn, ulBitsToClearOnEntry, ulBitsToClearOnExit, pulNotificationValue, xTicksToWait ) \ + xTaskGenericNotifyWait( ( uxIndexToWaitOn ), ( ulBitsToClearOnEntry ), ( ulBitsToClearOnExit ), ( pulNotificationValue ), ( xTicksToWait ) ) /** - * Simplified macro for sending task notification. + * task. h + * @code{c} + * BaseType_t xTaskNotifyGiveIndexed( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify ); + * BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify ); + * @endcode * - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this macro - * to be available. + * Sends a direct to task notification to a particular index in the target + * task's notification array in a manner similar to giving a counting semaphore. * - * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private - * "notification value", which is a 32-bit unsigned integer (uint32_t). + * See https://www.FreeRTOS.org/RTOS-task-notifications.html for more details. + * + * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these + * macros to be available. + * + * Each task has a private array of "notification values" (or 'notifications'), + * each of which is a 32-bit unsigned integer (uint32_t). The constant + * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the + * array, and (for backward compatibility) defaults to 1 if left undefined. + * Prior to FreeRTOS V10.4.0 there was only one notification value per task. * * Events can be sent to a task using an intermediary object. Examples of such * objects are queues, semaphores, mutexes and event groups. Task notifications @@ -2111,46 +2695,76 @@ BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClea * an intermediary object. * * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment the task's notification value. In that way - * task notifications can be used to send data to a task, or be used as light - * weight and fast binary or counting semaphores. + * update, overwrite or increment one of the task's notification values. In + * that way task notifications can be used to send data to a task, or be used as + * light weight and fast binary or counting semaphores. * - * xTaskNotifyGive() is a helper macro intended for use when task notifications - * are used as light weight and faster binary or counting semaphore equivalents. - * Actual FreeRTOS semaphores are given using the xSemaphoreGive() API function, - * the equivalent action that instead uses a task notification is - * xTaskNotifyGive(). + * xTaskNotifyGiveIndexed() is a helper macro intended for use when task + * notifications are used as light weight and faster binary or counting + * semaphore equivalents. Actual FreeRTOS semaphores are given using the + * xSemaphoreGive() API function, the equivalent action that instead uses a task + * notification is xTaskNotifyGiveIndexed(). * * When task notifications are being used as a binary or counting semaphore * equivalent then the task being notified should wait for the notification - * using the ulTaskNotificationTake() API function rather than the - * xTaskNotifyWait() API function. + * using the ulTaskNotificationTakeIndexed() API function rather than the + * xTaskNotifyWaitIndexed() API function. * - * See http://www.FreeRTOS.org/RTOS-task-notifications.html for more details. + * **NOTE** Each notification within the array operates independently - a task + * can only block on one notification within the array at a time and will not be + * unblocked by a notification sent to any other array index. + * + * Backward compatibility information: + * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and + * all task notification API functions operated on that value. Replacing the + * single notification value with an array of notification values necessitated a + * new set of API functions that could address specific notifications within the + * array. xTaskNotifyGive() is the original API function, and remains backward + * compatible by always operating on the notification value at index 0 in the + * array. Calling xTaskNotifyGive() is equivalent to calling + * xTaskNotifyGiveIndexed() with the uxIndexToNotify parameter set to 0. * * @param xTaskToNotify The handle of the task being notified. The handle to a * task can be returned from the xTaskCreate() API function used to create the * task, and the handle of the currently running task can be obtained by calling * xTaskGetCurrentTaskHandle(). * + * @param uxIndexToNotify The index within the target task's array of + * notification values to which the notification is to be sent. uxIndexToNotify + * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyGive() + * does not have this parameter and always sends notifications to index 0. + * * @return xTaskNotifyGive() is a macro that calls xTaskNotify() with the * eAction parameter set to eIncrement - so pdPASS is always returned. * + * \defgroup xTaskNotifyGiveIndexed xTaskNotifyGiveIndexed * \ingroup TaskNotifications */ -#define xTaskNotifyGive( xTaskToNotify ) xTaskGenericNotify( ( xTaskToNotify ), ( 0 ), eIncrement, NULL ) +#define xTaskNotifyGive( xTaskToNotify ) \ + xTaskGenericNotify( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( 0 ), eIncrement, NULL ) +#define xTaskNotifyGiveIndexed( xTaskToNotify, uxIndexToNotify ) \ + xTaskGenericNotify( ( xTaskToNotify ), ( uxIndexToNotify ), ( 0 ), eIncrement, NULL ) /** - * Simplified macro for sending task notification from ISR. + * task. h + * @code{c} + * void vTaskNotifyGiveIndexedFromISR( TaskHandle_t xTaskHandle, UBaseType_t uxIndexToNotify, BaseType_t *pxHigherPriorityTaskWoken ); + * void vTaskNotifyGiveFromISR( TaskHandle_t xTaskHandle, BaseType_t *pxHigherPriorityTaskWoken ); + * @endcode + * + * A version of xTaskNotifyGiveIndexed() that can be called from an interrupt + * service routine (ISR). + * + * See https://www.FreeRTOS.org/RTOS-task-notifications.html for more details. * * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this macro * to be available. * - * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private - * "notification value", which is a 32-bit unsigned integer (uint32_t). - * - * A version of xTaskNotifyGive() that can be called from an interrupt service - * routine (ISR). + * Each task has a private array of "notification values" (or 'notifications'), + * each of which is a 32-bit unsigned integer (uint32_t). The constant + * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the + * array, and (for backward compatibility) defaults to 1 if left undefined. + * Prior to FreeRTOS V10.4.0 there was only one notification value per task. * * Events can be sent to a task using an intermediary object. Examples of such * objects are queues, semaphores, mutexes and event groups. Task notifications @@ -2158,28 +2772,46 @@ BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClea * an intermediary object. * * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment the task's notification value. In that way - * task notifications can be used to send data to a task, or be used as light - * weight and fast binary or counting semaphores. + * update, overwrite or increment one of the task's notification values. In + * that way task notifications can be used to send data to a task, or be used as + * light weight and fast binary or counting semaphores. * - * vTaskNotifyGiveFromISR() is intended for use when task notifications are - * used as light weight and faster binary or counting semaphore equivalents. + * vTaskNotifyGiveIndexedFromISR() is intended for use when task notifications + * are used as light weight and faster binary or counting semaphore equivalents. * Actual FreeRTOS semaphores are given from an ISR using the * xSemaphoreGiveFromISR() API function, the equivalent action that instead uses - * a task notification is vTaskNotifyGiveFromISR(). + * a task notification is vTaskNotifyGiveIndexedFromISR(). * * When task notifications are being used as a binary or counting semaphore * equivalent then the task being notified should wait for the notification - * using the ulTaskNotificationTake() API function rather than the - * xTaskNotifyWait() API function. + * using the ulTaskNotificationTakeIndexed() API function rather than the + * xTaskNotifyWaitIndexed() API function. * - * See http://www.FreeRTOS.org/RTOS-task-notifications.html for more details. + * **NOTE** Each notification within the array operates independently - a task + * can only block on one notification within the array at a time and will not be + * unblocked by a notification sent to any other array index. + * + * Backward compatibility information: + * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and + * all task notification API functions operated on that value. Replacing the + * single notification value with an array of notification values necessitated a + * new set of API functions that could address specific notifications within the + * array. xTaskNotifyFromISR() is the original API function, and remains + * backward compatible by always operating on the notification value at index 0 + * within the array. Calling xTaskNotifyGiveFromISR() is equivalent to calling + * xTaskNotifyGiveIndexedFromISR() with the uxIndexToNotify parameter set to 0. * * @param xTaskToNotify The handle of the task being notified. The handle to a * task can be returned from the xTaskCreate() API function used to create the * task, and the handle of the currently running task can be obtained by calling * xTaskGetCurrentTaskHandle(). * + * @param uxIndexToNotify The index within the target task's array of + * notification values to which the notification is to be sent. uxIndexToNotify + * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. + * xTaskNotifyGiveFromISR() does not have this parameter and always sends + * notifications to index 0. + * * @param pxHigherPriorityTaskWoken vTaskNotifyGiveFromISR() will set * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the * task to which the notification was sent to leave the Blocked state, and the @@ -2189,18 +2821,38 @@ BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClea * requested from an ISR is dependent on the port - see the documentation page * for the port in use. * + * \defgroup vTaskNotifyGiveIndexedFromISR vTaskNotifyGiveIndexedFromISR * \ingroup TaskNotifications */ -void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; +void vTaskGenericNotifyGiveFromISR( TaskHandle_t xTaskToNotify, + UBaseType_t uxIndexToNotify, + BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; +#define vTaskNotifyGiveFromISR( xTaskToNotify, pxHigherPriorityTaskWoken ) \ + vTaskGenericNotifyGiveFromISR( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( pxHigherPriorityTaskWoken ) ); +#define vTaskNotifyGiveIndexedFromISR( xTaskToNotify, uxIndexToNotify, pxHigherPriorityTaskWoken ) \ + vTaskGenericNotifyGiveFromISR( ( xTaskToNotify ), ( uxIndexToNotify ), ( pxHigherPriorityTaskWoken ) ); /** - * Simplified macro for receiving task notification. + * task. h + * @code{c} + * uint32_t ulTaskNotifyTakeIndexed( UBaseType_t uxIndexToWaitOn, BaseType_t xClearCountOnExit, TickType_t xTicksToWait ); + * + * uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait ); + * @endcode + * + * Waits for a direct to task notification on a particular index in the calling + * task's notification array in a manner similar to taking a counting semaphore. + * + * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. * * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this * function to be available. * - * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private - * "notification value", which is a 32-bit unsigned integer (uint32_t). + * Each task has a private array of "notification values" (or 'notifications'), + * each of which is a 32-bit unsigned integer (uint32_t). The constant + * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the + * array, and (for backward compatibility) defaults to 1 if left undefined. + * Prior to FreeRTOS V10.4.0 there was only one notification value per task. * * Events can be sent to a task using an intermediary object. Examples of such * objects are queues, semaphores, mutexes and event groups. Task notifications @@ -2208,35 +2860,54 @@ void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPri * an intermediary object. * * A notification sent to a task can optionally perform an action, such as - * update, overwrite or increment the task's notification value. In that way - * task notifications can be used to send data to a task, or be used as light - * weight and fast binary or counting semaphores. + * update, overwrite or increment one of the task's notification values. In + * that way task notifications can be used to send data to a task, or be used as + * light weight and fast binary or counting semaphores. * - * ulTaskNotifyTake() is intended for use when a task notification is used as a - * faster and lighter weight binary or counting semaphore alternative. Actual - * FreeRTOS semaphores are taken using the xSemaphoreTake() API function, the - * equivalent action that instead uses a task notification is - * ulTaskNotifyTake(). + * ulTaskNotifyTakeIndexed() is intended for use when a task notification is + * used as a faster and lighter weight binary or counting semaphore alternative. + * Actual FreeRTOS semaphores are taken using the xSemaphoreTake() API function, + * the equivalent action that instead uses a task notification is + * ulTaskNotifyTakeIndexed(). * * When a task is using its notification value as a binary or counting semaphore - * other tasks should send notifications to it using the xTaskNotifyGive() - * macro, or xTaskNotify() function with the eAction parameter set to + * other tasks should send notifications to it using the xTaskNotifyGiveIndexed() + * macro, or xTaskNotifyIndex() function with the eAction parameter set to * eIncrement. * - * ulTaskNotifyTake() can either clear the task's notification value to - * zero on exit, in which case the notification value acts like a binary - * semaphore, or decrement the task's notification value on exit, in which case - * the notification value acts like a counting semaphore. + * ulTaskNotifyTakeIndexed() can either clear the task's notification value at + * the array index specified by the uxIndexToWaitOn parameter to zero on exit, + * in which case the notification value acts like a binary semaphore, or + * decrement the notification value on exit, in which case the notification + * value acts like a counting semaphore. * - * A task can use ulTaskNotifyTake() to [optionally] block to wait for a + * A task can use ulTaskNotifyTakeIndexed() to [optionally] block to wait for * the task's notification value to be non-zero. The task does not consume any * CPU time while it is in the Blocked state. * - * Where as xTaskNotifyWait() will return when a notification is pending, - * ulTaskNotifyTake() will return when the task's notification value is + * Where as xTaskNotifyWaitIndexed() will return when a notification is pending, + * ulTaskNotifyTakeIndexed() will return when the task's notification value is * not zero. * - * See http://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * **NOTE** Each notification within the array operates independently - a task + * can only block on one notification within the array at a time and will not be + * unblocked by a notification sent to any other array index. + * + * Backward compatibility information: + * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and + * all task notification API functions operated on that value. Replacing the + * single notification value with an array of notification values necessitated a + * new set of API functions that could address specific notifications within the + * array. ulTaskNotifyTake() is the original API function, and remains backward + * compatible by always operating on the notification value at index 0 in the + * array. Calling ulTaskNotifyTake() is equivalent to calling + * ulTaskNotifyTakeIndexed() with the uxIndexToWaitOn parameter set to 0. + * + * @param uxIndexToWaitOn The index within the calling task's array of + * notification values on which the calling task will wait for a notification to + * be non-zero. uxIndexToWaitOn must be less than + * configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyTake() does + * not have this parameter and always waits for notifications on index 0. * * @param xClearCountOnExit if xClearCountOnExit is pdFALSE then the task's * notification value is decremented when the function exits. In this way the @@ -2256,23 +2927,289 @@ void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPri * @return The task's notification count before it is either cleared to zero or * decremented (see the xClearCountOnExit parameter). * + * \defgroup ulTaskNotifyTakeIndexed ulTaskNotifyTakeIndexed * \ingroup TaskNotifications */ -uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; +uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWaitOn, + BaseType_t xClearCountOnExit, + TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; +#define ulTaskNotifyTake( xClearCountOnExit, xTicksToWait ) \ + ulTaskGenericNotifyTake( ( tskDEFAULT_INDEX_TO_NOTIFY ), ( xClearCountOnExit ), ( xTicksToWait ) ) +#define ulTaskNotifyTakeIndexed( uxIndexToWaitOn, xClearCountOnExit, xTicksToWait ) \ + ulTaskGenericNotifyTake( ( uxIndexToWaitOn ), ( xClearCountOnExit ), ( xTicksToWait ) ) /** + * task. h + * @code{c} + * BaseType_t xTaskNotifyStateClearIndexed( TaskHandle_t xTask, UBaseType_t uxIndexToCLear ); * - * If the notification state of the task referenced by the handle xTask is - * eNotified, then set the task's notification state to eNotWaitingNotification. - * The task's notification value is not altered. Set xTask to NULL to clear the - * notification state of the calling task. + * BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask ); + * @endcode + * + * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * + * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these + * functions to be available. + * + * Each task has a private array of "notification values" (or 'notifications'), + * each of which is a 32-bit unsigned integer (uint32_t). The constant + * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the + * array, and (for backward compatibility) defaults to 1 if left undefined. + * Prior to FreeRTOS V10.4.0 there was only one notification value per task. + * + * If a notification is sent to an index within the array of notifications then + * the notification at that index is said to be 'pending' until it is read or + * explicitly cleared by the receiving task. xTaskNotifyStateClearIndexed() + * is the function that clears a pending notification without reading the + * notification value. The notification value at the same array index is not + * altered. Set xTask to NULL to clear the notification state of the calling + * task. + * + * Backward compatibility information: + * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and + * all task notification API functions operated on that value. Replacing the + * single notification value with an array of notification values necessitated a + * new set of API functions that could address specific notifications within the + * array. xTaskNotifyStateClear() is the original API function, and remains + * backward compatible by always operating on the notification value at index 0 + * within the array. Calling xTaskNotifyStateClear() is equivalent to calling + * xTaskNotifyStateClearIndexed() with the uxIndexToNotify parameter set to 0. + * + * @param xTask The handle of the RTOS task that will have a notification state + * cleared. Set xTask to NULL to clear a notification state in the calling + * task. To obtain a task's handle create the task using xTaskCreate() and + * make use of the pxCreatedTask parameter, or create the task using + * xTaskCreateStatic() and store the returned value, or use the task's name in + * a call to xTaskGetHandle(). + * + * @param uxIndexToClear The index within the target task's array of + * notification values to act upon. For example, setting uxIndexToClear to 1 + * will clear the state of the notification at index 1 within the array. + * uxIndexToClear must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. + * ulTaskNotifyStateClear() does not have this parameter and always acts on the + * notification at index 0. * * @return pdTRUE if the task's notification state was set to * eNotWaitingNotification, otherwise pdFALSE. * + * \defgroup xTaskNotifyStateClearIndexed xTaskNotifyStateClearIndexed * \ingroup TaskNotifications */ -BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask ); +BaseType_t xTaskGenericNotifyStateClear( TaskHandle_t xTask, + UBaseType_t uxIndexToClear ) PRIVILEGED_FUNCTION; +#define xTaskNotifyStateClear( xTask ) \ + xTaskGenericNotifyStateClear( ( xTask ), ( tskDEFAULT_INDEX_TO_NOTIFY ) ) +#define xTaskNotifyStateClearIndexed( xTask, uxIndexToClear ) \ + xTaskGenericNotifyStateClear( ( xTask ), ( uxIndexToClear ) ) + +/** + * task. h + * @code{c} + * uint32_t ulTaskNotifyValueClearIndexed( TaskHandle_t xTask, UBaseType_t uxIndexToClear, uint32_t ulBitsToClear ); + * + * uint32_t ulTaskNotifyValueClear( TaskHandle_t xTask, uint32_t ulBitsToClear ); + * @endcode + * + * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * + * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these + * functions to be available. + * + * Each task has a private array of "notification values" (or 'notifications'), + * each of which is a 32-bit unsigned integer (uint32_t). The constant + * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the + * array, and (for backward compatibility) defaults to 1 if left undefined. + * Prior to FreeRTOS V10.4.0 there was only one notification value per task. + * + * ulTaskNotifyValueClearIndexed() clears the bits specified by the + * ulBitsToClear bit mask in the notification value at array index uxIndexToClear + * of the task referenced by xTask. + * + * Backward compatibility information: + * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and + * all task notification API functions operated on that value. Replacing the + * single notification value with an array of notification values necessitated a + * new set of API functions that could address specific notifications within the + * array. ulTaskNotifyValueClear() is the original API function, and remains + * backward compatible by always operating on the notification value at index 0 + * within the array. Calling ulTaskNotifyValueClear() is equivalent to calling + * ulTaskNotifyValueClearIndexed() with the uxIndexToClear parameter set to 0. + * + * @param xTask The handle of the RTOS task that will have bits in one of its + * notification values cleared. Set xTask to NULL to clear bits in a + * notification value of the calling task. To obtain a task's handle create the + * task using xTaskCreate() and make use of the pxCreatedTask parameter, or + * create the task using xTaskCreateStatic() and store the returned value, or + * use the task's name in a call to xTaskGetHandle(). + * + * @param uxIndexToClear The index within the target task's array of + * notification values in which to clear the bits. uxIndexToClear + * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. + * ulTaskNotifyValueClear() does not have this parameter and always clears bits + * in the notification value at index 0. + * + * @param ulBitsToClear Bit mask of the bits to clear in the notification value of + * xTask. Set a bit to 1 to clear the corresponding bits in the task's notification + * value. Set ulBitsToClear to 0xffffffff (UINT_MAX on 32-bit architectures) to clear + * the notification value to 0. Set ulBitsToClear to 0 to query the task's + * notification value without clearing any bits. + * + * + * @return The value of the target task's notification value before the bits + * specified by ulBitsToClear were cleared. + * \defgroup ulTaskNotifyValueClear ulTaskNotifyValueClear + * \ingroup TaskNotifications + */ +uint32_t ulTaskGenericNotifyValueClear( TaskHandle_t xTask, + UBaseType_t uxIndexToClear, + uint32_t ulBitsToClear ) PRIVILEGED_FUNCTION; +#define ulTaskNotifyValueClear( xTask, ulBitsToClear ) \ + ulTaskGenericNotifyValueClear( ( xTask ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( ulBitsToClear ) ) +#define ulTaskNotifyValueClearIndexed( xTask, uxIndexToClear, ulBitsToClear ) \ + ulTaskGenericNotifyValueClear( ( xTask ), ( uxIndexToClear ), ( ulBitsToClear ) ) + +/** + * @cond + * task.h + * @code{c} + * void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ); + * @endcode + * @endcond + * + * Capture the current time for future use with xTaskCheckForTimeOut(). + * + * @param pxTimeOut Pointer to a timeout object into which the current time + * is to be captured. The captured time includes the tick count and the number + * of times the tick count has overflowed since the system first booted. + * \defgroup vTaskSetTimeOutState vTaskSetTimeOutState + * @cond + * \ingroup TaskCtrl + * @endcond + */ +void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNCTION; + +/** + * @cond + * task.h + * @code + * BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait ); + * @endcode + * @endcond + * + * Determines if pxTicksToWait ticks has passed since a time was captured + * using a call to vTaskSetTimeOutState(). The captured time includes the tick + * count and the number of times the tick count has overflowed. + * + * @param pxTimeOut The time status as captured previously using + * vTaskSetTimeOutState. If the timeout has not yet occurred, it is updated + * to reflect the current time status. + * @param pxTicksToWait The number of ticks to check for timeout i.e. if + * pxTicksToWait ticks have passed since pxTimeOut was last updated (either by + * vTaskSetTimeOutState() or xTaskCheckForTimeOut()), the timeout has occurred. + * If the timeout has not occurred, pxTicksToWait is updated to reflect the + * number of remaining ticks. + * + * @return If timeout has occurred, pdTRUE is returned. Otherwise pdFALSE is + * returned and pxTicksToWait is updated to reflect the number of remaining + * ticks. + * + * @see https://www.FreeRTOS.org/xTaskCheckForTimeOut.html + * + * Example Usage: + * @code + * // Driver library function used to receive uxWantedBytes from an Rx buffer + * // that is filled by a UART interrupt. If there are not enough bytes in the + * // Rx buffer then the task enters the Blocked state until it is notified that + * // more data has been placed into the buffer. If there is still not enough + * // data then the task re-enters the Blocked state, and xTaskCheckForTimeOut() + * // is used to re-calculate the Block time to ensure the total amount of time + * // spent in the Blocked state does not exceed MAX_TIME_TO_WAIT. This + * // continues until either the buffer contains at least uxWantedBytes bytes, + * // or the total amount of time spent in the Blocked state reaches + * // MAX_TIME_TO_WAIT – at which point the task reads however many bytes are + * // available up to a maximum of uxWantedBytes. + * + * size_t xUART_Receive( uint8_t *pucBuffer, size_t uxWantedBytes ) + * { + * size_t uxReceived = 0; + * TickType_t xTicksToWait = MAX_TIME_TO_WAIT; + * TimeOut_t xTimeOut; + * + * // Initialize xTimeOut. This records the time at which this function + * // was entered. + * vTaskSetTimeOutState( &xTimeOut ); + * + * // Loop until the buffer contains the wanted number of bytes, or a + * // timeout occurs. + * while( UART_bytes_in_rx_buffer( pxUARTInstance ) < uxWantedBytes ) + * { + * // The buffer didn't contain enough data so this task is going to + * // enter the Blocked state. Adjusting xTicksToWait to account for + * // any time that has been spent in the Blocked state within this + * // function so far to ensure the total amount of time spent in the + * // Blocked state does not exceed MAX_TIME_TO_WAIT. + * if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) != pdFALSE ) + * { + * //Timed out before the wanted number of bytes were available, + * // exit the loop. + * break; + * } + * + * // Wait for a maximum of xTicksToWait ticks to be notified that the + * // receive interrupt has placed more data into the buffer. + * ulTaskNotifyTake( pdTRUE, xTicksToWait ); + * } + * + * // Attempt to read uxWantedBytes from the receive buffer into pucBuffer. + * // The actual number of bytes read (which might be less than + * // uxWantedBytes) is returned. + * uxReceived = UART_read_from_receive_buffer( pxUARTInstance, + * pucBuffer, + * uxWantedBytes ); + * + * return uxReceived; + * } + * @endcode + * @cond + * \defgroup xTaskCheckForTimeOut xTaskCheckForTimeOut + * @endcond + * \ingroup TaskCtrl + */ +BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, + TickType_t * const pxTicksToWait ) PRIVILEGED_FUNCTION; + +/** + * @cond + * task.h + * @code{c} + * BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ); + * @endcode + * @endcond + * + * This function corrects the tick count value after the application code has held + * interrupts disabled for an extended period resulting in tick interrupts having + * been missed. + * + * This function is similar to vTaskStepTick(), however, unlike + * vTaskStepTick(), xTaskCatchUpTicks() may move the tick count forward past a + * time at which a task should be removed from the blocked state. That means + * tasks may have to be removed from the blocked state as the tick count is + * moved. + * + * @param xTicksToCatchUp The number of tick interrupts that have been missed due to + * interrupts being disabled. Its value is not computed automatically, so must be + * computed by the application writer. + * + * @return pdTRUE if moving the tick count forward resulted in a task leaving the + * blocked state and a context switch being performed. Otherwise pdFALSE. + * + * \defgroup xTaskCatchUpTicks xTaskCatchUpTicks + * @cond + * \ingroup TaskCtrl + * @endcond + */ +BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) PRIVILEGED_FUNCTION; + /*----------------------------------------------------------- * SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES @@ -2299,7 +3236,6 @@ TaskHandle_t xTaskGetCurrentTaskHandleForCPU( BaseType_t cpuid ); */ TaskHandle_t xTaskGetIdleTaskHandleForCPU( UBaseType_t cpuid ); - /* * Get the current core affinity of a task */ @@ -2339,7 +3275,7 @@ BaseType_t xTaskIncrementTick( void ) PRIVILEGED_FUNCTION; * xItemValue value, and inserts the list item at the end of the list. * * The 'ordered' version uses the existing event list item value (which is the - * owning tasks priority) to insert the list item into the event list is task + * owning task's priority) to insert the list item into the event list in task * priority order. * * @param pxEventList The list containing tasks that are blocked waiting @@ -2349,12 +3285,15 @@ BaseType_t xTaskIncrementTick( void ) PRIVILEGED_FUNCTION; * event list is not ordered by task priority. * * @param xTicksToWait The maximum amount of time that the task should wait - * for the event to occur. This is specified in kernel ticks,the constant + * for the event to occur. This is specified in kernel ticks, the constant * portTICK_PERIOD_MS can be used to convert kernel ticks into a real time * period. */ -void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; -void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xItemValue, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; +void vTaskPlaceOnEventList( List_t * const pxEventList, + const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; +void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, + const TickType_t xItemValue, + const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; /* * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN @@ -2367,7 +3306,9 @@ void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xIte * indefinitely, whereas vTaskPlaceOnEventList() does. * */ -void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely ) PRIVILEGED_FUNCTION; +void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, + TickType_t xTicksToWait, + const BaseType_t xWaitIndefinitely ) PRIVILEGED_FUNCTION; /* * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN @@ -2394,7 +3335,8 @@ void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, TickType_t xTi * making the call, otherwise pdFALSE. */ BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList ) PRIVILEGED_FUNCTION; -BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue ) PRIVILEGED_FUNCTION; +void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, + const TickType_t xItemValue ) PRIVILEGED_FUNCTION; /* * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY @@ -2404,7 +3346,7 @@ BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, cons * Sets the pointer to the current TCB to the TCB of the highest priority task * that is ready to run. */ -void vTaskSwitchContext( void ) PRIVILEGED_FUNCTION; +portDONT_DISCARD void vTaskSwitchContext( void ) PRIVILEGED_FUNCTION; /* * THESE FUNCTIONS MUST NOT BE USED FROM APPLICATION CODE. THEY ARE USED BY @@ -2417,17 +3359,6 @@ TickType_t uxTaskResetEventItemValue( void ) PRIVILEGED_FUNCTION; */ TaskHandle_t xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION; -/* - * Capture the current time status for future reference. - */ -void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNCTION; - -/* - * Compare the time status now with that previously captured to see if the - * timeout has expired. - */ -BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait ) PRIVILEGED_FUNCTION; - /* * Shortcut used by the queue implementation to prevent unnecessary call to * taskYIELD(); @@ -2460,23 +3391,20 @@ BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder ) PRIVILEGE * the highest priority task that is still waiting for the mutex (if there were * more than one task waiting for the mutex). */ -void vTaskPriorityDisinheritAfterTimeout( TaskHandle_t const pxMutexHolder, UBaseType_t uxHighestPriorityWaitingTask ) PRIVILEGED_FUNCTION; +void vTaskPriorityDisinheritAfterTimeout( TaskHandle_t const pxMutexHolder, + UBaseType_t uxHighestPriorityWaitingTask ) PRIVILEGED_FUNCTION; /* * Get the uxTCBNumber assigned to the task referenced by the xTask parameter. */ UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; -/* - * Get the current core affinity of a task - */ -BaseType_t xTaskGetAffinity( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; - /* * Set the uxTaskNumber of the task referenced by the xTask parameter to * uxHandle. */ -void vTaskSetTaskNumber( TaskHandle_t xTask, const UBaseType_t uxHandle ) PRIVILEGED_FUNCTION; +void vTaskSetTaskNumber( TaskHandle_t xTask, + const UBaseType_t uxHandle ) PRIVILEGED_FUNCTION; /* * Only available when configUSE_TICKLESS_IDLE is set to 1. @@ -2488,19 +3416,6 @@ void vTaskSetTaskNumber( TaskHandle_t xTask, const UBaseType_t uxHandle ) PRIVIL */ void vTaskStepTick( const TickType_t xTicksToJump ) PRIVILEGED_FUNCTION; -/* Correct the tick count value after the application code has held -interrupts disabled for an extended period. xTicksToCatchUp is the number -of tick interrupts that have been missed due to interrupts being disabled. -Its value is not computed automatically, so must be computed by the -application writer. - -This function is similar to vTaskStepTick(), however, unlike -vTaskStepTick(), xTaskCatchUpTicks() may move the tick count forward past a -time at which a task should be removed from the blocked state. That means -tasks may have to be removed from the blocked state as the tick count is -moved. */ -BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) PRIVILEGED_FUNCTION; - /* * Only available when configUSE_TICKLESS_IDLE is set to 1. * Provided for use within portSUPPRESS_TICKS_AND_SLEEP() to allow the port @@ -2524,44 +3439,20 @@ eSleepModeStatus eTaskConfirmSleepModeStatus( void ) PRIVILEGED_FUNCTION; TaskHandle_t pvTaskIncrementMutexHeldCount( void ) PRIVILEGED_FUNCTION; /* - * For internal use only. Same as vTaskSetTimeOutState(), but without a critial + * For internal use only. Same as vTaskSetTimeOutState(), but without a critical * section. */ void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNCTION; -/* - * This function fills array with TaskSnapshot_t structures for every task in the system. - * Used by panic handling code to get snapshots of all tasks in the system. - * Only available when configENABLE_TASK_SNAPSHOT is set to 1. - * @param pxTaskSnapshotArray Pointer to array of TaskSnapshot_t structures to store tasks snapshot data. - * @param uxArraySize Size of tasks snapshots array. - * @param pxTcbSz Pointer to store size of TCB. - * @return Number of elements stored in array. - */ -UBaseType_t uxTaskGetSnapshotAll( TaskSnapshot_t * const pxTaskSnapshotArray, const UBaseType_t uxArraySize, UBaseType_t * const pxTcbSz ); - -/* - * This function iterates over all tasks in the system. - * Used by panic handling code to iterate over tasks in the system. - * Only available when configENABLE_TASK_SNAPSHOT is set to 1. - * @note This function should not be used while FreeRTOS is running (as it doesn't acquire any locks). - * @param pxTask task handle. - * @return Handle for the next task. If pxTask is NULL, returns hadnle for the first task. - */ -TaskHandle_t pxTaskGetNext( TaskHandle_t pxTask ); - -/* - * This function fills TaskSnapshot_t structure for specified task. - * Used by panic handling code to get snapshot of a task. - * Only available when configENABLE_TASK_SNAPSHOT is set to 1. - * @note This function should not be used while FreeRTOS is running (as it doesn't acquire any locks). - * @param pxTask task handle. - * @param pxTaskSnapshot address of TaskSnapshot_t structure to fill. - */ -void vTaskGetSnapshot( TaskHandle_t pxTask, TaskSnapshot_t *pxTaskSnapshot ); +#ifdef ESP_PLATFORM +/* TODO: IDF-3683 */ +#include "freertos/task_snapshot.h" +#endif // ESP_PLATFORM /** @endcond */ + #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* INC_TASK_H */ diff --git a/components/freertos/include/freertos/timers.h b/components/freertos/include/freertos/timers.h index 9a5e23385f..a8bc4f38c7 100644 --- a/components/freertos/include/freertos/timers.h +++ b/components/freertos/include/freertos/timers.h @@ -1,6 +1,6 @@ /* - * FreeRTOS Kernel V10.2.1 - * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V10.4.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * 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 @@ -19,10 +19,9 @@ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS * - * 1 tab == 4 spaces! */ @@ -30,41 +29,43 @@ #define TIMERS_H #ifndef INC_FREERTOS_H - #error "include FreeRTOS.h must appear in source files before include timers.h" + #error "include FreeRTOS.h must appear in source files before include timers.h" #endif /*lint -save -e537 This headers are only multiply included if the application code -happens to also be including task.h. */ + * happens to also be including task.h. */ #include "task.h" /*lint -restore */ +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * MACROS AND DEFINITIONS *----------------------------------------------------------*/ /* IDs for commands that can be sent/received on the timer queue. These are to -be used solely through the macros that make up the public software timer API, -as defined below. The commands that are sent from interrupts must use the -highest numbers as tmrFIRST_FROM_ISR_COMMAND is used to determine if the task -or interrupt version of the queue send function should be used. */ -#define tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR ( ( BaseType_t ) -2 ) -#define tmrCOMMAND_EXECUTE_CALLBACK ( ( BaseType_t ) -1 ) -#define tmrCOMMAND_START_DONT_TRACE ( ( BaseType_t ) 0 ) -#define tmrCOMMAND_START ( ( BaseType_t ) 1 ) -#define tmrCOMMAND_RESET ( ( BaseType_t ) 2 ) -#define tmrCOMMAND_STOP ( ( BaseType_t ) 3 ) -#define tmrCOMMAND_CHANGE_PERIOD ( ( BaseType_t ) 4 ) -#define tmrCOMMAND_DELETE ( ( BaseType_t ) 5 ) + * be used solely through the macros that make up the public software timer API, + * as defined below. The commands that are sent from interrupts must use the + * highest numbers as tmrFIRST_FROM_ISR_COMMAND is used to determine if the task + * or interrupt version of the queue send function should be used. */ +#define tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR ( ( BaseType_t ) -2 ) +#define tmrCOMMAND_EXECUTE_CALLBACK ( ( BaseType_t ) -1 ) +#define tmrCOMMAND_START_DONT_TRACE ( ( BaseType_t ) 0 ) +#define tmrCOMMAND_START ( ( BaseType_t ) 1 ) +#define tmrCOMMAND_RESET ( ( BaseType_t ) 2 ) +#define tmrCOMMAND_STOP ( ( BaseType_t ) 3 ) +#define tmrCOMMAND_CHANGE_PERIOD ( ( BaseType_t ) 4 ) +#define tmrCOMMAND_DELETE ( ( BaseType_t ) 5 ) -#define tmrFIRST_FROM_ISR_COMMAND ( ( BaseType_t ) 6 ) -#define tmrCOMMAND_START_FROM_ISR ( ( BaseType_t ) 6 ) -#define tmrCOMMAND_RESET_FROM_ISR ( ( BaseType_t ) 7 ) -#define tmrCOMMAND_STOP_FROM_ISR ( ( BaseType_t ) 8 ) -#define tmrCOMMAND_CHANGE_PERIOD_FROM_ISR ( ( BaseType_t ) 9 ) +#define tmrFIRST_FROM_ISR_COMMAND ( ( BaseType_t ) 6 ) +#define tmrCOMMAND_START_FROM_ISR ( ( BaseType_t ) 6 ) +#define tmrCOMMAND_RESET_FROM_ISR ( ( BaseType_t ) 7 ) +#define tmrCOMMAND_STOP_FROM_ISR ( ( BaseType_t ) 8 ) +#define tmrCOMMAND_CHANGE_PERIOD_FROM_ISR ( ( BaseType_t ) 9 ) /** @@ -74,20 +75,30 @@ or interrupt version of the queue send function should be used. */ * (for example, xTimerStart(), xTimerReset(), etc.). */ struct tmrTimerControl; /* The old naming convention is used to prevent breaking kernel aware debuggers. */ -//typedef struct tmrTimerControl * TimerHandle_t; +#ifdef ESP_PLATFORM // IDF-3768 typedef void* TimerHandle_t; +#else +typedef struct tmrTimerControl * TimerHandle_t; +#endif // ESP_PLATFORM /* * Defines the prototype to which timer callback functions must conform. */ -typedef void (*TimerCallbackFunction_t)( TimerHandle_t xTimer ); +typedef void (* TimerCallbackFunction_t)( TimerHandle_t xTimer ); /* * Defines the prototype to which functions used with the * xTimerPendFunctionCallFromISR() function must conform. */ -typedef void (*PendedFunction_t)( void *, uint32_t ); +typedef void (* PendedFunction_t)( void *, + uint32_t ); /** + * TimerHandle_t xTimerCreate( const char * const pcTimerName, + * TickType_t xTimerPeriodInTicks, + * UBaseType_t uxAutoReload, + * void * pvTimerID, + * TimerCallbackFunction_t pxCallbackFunction ); + * * Creates a new software timer instance, and returns a handle by which the * created software timer can be referenced. * @@ -95,7 +106,7 @@ typedef void (*PendedFunction_t)( void *, uint32_t ); * of memory, in which the timer data structure is stored. If a software timer * is created using xTimerCreate() then the required memory is automatically * dynamically allocated inside the xTimerCreate() function. (see - * http://www.freertos.org/a00111.html). If a software timer is created using + * https://www.FreeRTOS.org/a00111.html). If a software timer is created using * xTimerCreateStatic() then the application writer must provide the memory that * will get used by the software timer. xTimerCreateStatic() therefore allows a * software timer to be created without using any dynamic memory allocation. @@ -115,7 +126,7 @@ typedef void (*PendedFunction_t)( void *, uint32_t ); * after 100 ticks, then xTimerPeriodInTicks should be set to 100. * Alternatively, if the timer must expire after 500ms, then xPeriod can be set * to ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than or - * equal to 1000. + * equal to 1000. Time timer period must be greater than 0. * * @param uxAutoReload If uxAutoReload is set to pdTRUE then the timer will * expire repeatedly with a frequency set by the xTimerPeriodInTicks parameter. @@ -129,7 +140,7 @@ typedef void (*PendedFunction_t)( void *, uint32_t ); * * @param pxCallbackFunction The function to call when the timer expires. * Callback functions must have the prototype defined by TimerCallbackFunction_t, - * which is "void vCallbackFunction( TimerHandle_t xTimer );". + * which is "void vCallbackFunction( TimerHandle_t xTimer );". * * @return If the timer is successfully created then a handle to the newly * created timer is returned. If the timer cannot be created (because either @@ -137,7 +148,7 @@ typedef void (*PendedFunction_t)( void *, uint32_t ); * structures, or the timer period was set to 0) then NULL is returned. * * Example usage: - * @code{c} + * @verbatim * #define NUM_TIMERS 5 * * // An array to hold handles to the created timers. @@ -155,8 +166,8 @@ typedef void (*PendedFunction_t)( void *, uint32_t ); * int32_t lArrayIndex; * const int32_t xMaxExpiryCountBeforeStopping = 10; * - * // Optionally do something if the pxTimer parameter is NULL. - * configASSERT( pxTimer ); + * // Optionally do something if the pxTimer parameter is NULL. + * configASSERT( pxTimer ); * * // Which timer expired? * lArrayIndex = ( int32_t ) pvTimerGetTimerID( pxTimer ); @@ -216,138 +227,145 @@ typedef void (*PendedFunction_t)( void *, uint32_t ); * // Should not reach here. * for( ;; ); * } - * @endcode + * @endverbatim */ -#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) - TimerHandle_t xTimerCreate( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ - const TickType_t xTimerPeriodInTicks, - const UBaseType_t uxAutoReload, - void * const pvTimerID, - TimerCallbackFunction_t pxCallbackFunction ) PRIVILEGED_FUNCTION; +#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + TimerHandle_t xTimerCreate( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + const TickType_t xTimerPeriodInTicks, + const UBaseType_t uxAutoReload, + void * const pvTimerID, + TimerCallbackFunction_t pxCallbackFunction ) PRIVILEGED_FUNCTION; #endif - /** - * Creates a new software timer instance, and returns a handle by which the - * created software timer can be referenced. - * - * Internally, within the FreeRTOS implementation, software timers use a block - * of memory, in which the timer data structure is stored. If a software timer - * is created using xTimerCreate() then the required memory is automatically - * dynamically allocated inside the xTimerCreate() function. (see - * http://www.freertos.org/a00111.html). If a software timer is created using - * xTimerCreateStatic() then the application writer must provide the memory that - * will get used by the software timer. xTimerCreateStatic() therefore allows a - * software timer to be created without using any dynamic memory allocation. - * - * Timers are created in the dormant state. The xTimerStart(), xTimerReset(), - * xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and - * xTimerChangePeriodFromISR() API functions can all be used to transition a - * timer into the active state. - * - * @param pcTimerName A text name that is assigned to the timer. This is done - * purely to assist debugging. The kernel itself only ever references a timer - * by its handle, and never by its name. - * - * @param xTimerPeriodInTicks The timer period. The time is defined in tick - * periods so the constant portTICK_PERIOD_MS can be used to convert a time that - * has been specified in milliseconds. For example, if the timer must expire - * after 100 ticks, then xTimerPeriodInTicks should be set to 100. - * Alternatively, if the timer must expire after 500ms, then xPeriod can be set - * to ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than or - * equal to 1000. - * - * @param uxAutoReload If uxAutoReload is set to pdTRUE then the timer will - * expire repeatedly with a frequency set by the xTimerPeriodInTicks parameter. - * If uxAutoReload is set to pdFALSE then the timer will be a one-shot timer and - * enter the dormant state after it expires. - * - * @param pvTimerID An identifier that is assigned to the timer being created. - * Typically this would be used in the timer callback function to identify which - * timer expired when the same callback function is assigned to more than one - * timer. - * - * @param pxCallbackFunction The function to call when the timer expires. - * Callback functions must have the prototype defined by TimerCallbackFunction_t, - * which is "void vCallbackFunction( TimerHandle_t xTimer );". - * - * @param pxTimerBuffer Must point to a variable of type StaticTimer_t, which - * will be then be used to hold the software timer's data structures, removing - * the need for the memory to be allocated dynamically. - * - * @return If the timer is created then a handle to the created timer is - * returned. If pxTimerBuffer was NULL then NULL is returned. - * - * Example usage: - * @code{c} - * - * // The buffer used to hold the software timer's data structure. - * static StaticTimer_t xTimerBuffer; - * - * // A variable that will be incremented by the software timer's callback - * // function. - * UBaseType_t uxVariableToIncrement = 0; - * - * // A software timer callback function that increments a variable passed to - * // it when the software timer was created. After the 5th increment the - * // callback function stops the software timer. - * static void prvTimerCallback( TimerHandle_t xExpiredTimer ) - * { - * UBaseType_t *puxVariableToIncrement; - * BaseType_t xReturned; - * - * // Obtain the address of the variable to increment from the timer ID. - * puxVariableToIncrement = ( UBaseType_t * ) pvTimerGetTimerID( xExpiredTimer ); - * - * // Increment the variable to show the timer callback has executed. - * ( *puxVariableToIncrement )++; - * - * // If this callback has executed the required number of times, stop the - * // timer. - * if( *puxVariableToIncrement == 5 ) - * { - * // This is called from a timer callback so must not block. - * xTimerStop( xExpiredTimer, staticDONT_BLOCK ); - * } - * } - * - * - * void main( void ) - * { - * // Create the software time. xTimerCreateStatic() has an extra parameter - * // than the normal xTimerCreate() API function. The parameter is a pointer - * // to the StaticTimer_t structure that will hold the software timer - * // structure. If the parameter is passed as NULL then the structure will be - * // allocated dynamically, just as if xTimerCreate() had been called. - * xTimer = xTimerCreateStatic( "T1", // Text name for the task. Helps debugging only. Not used by FreeRTOS. - * xTimerPeriod, // The period of the timer in ticks. - * pdTRUE, // This is an auto-reload timer. - * ( void * ) &uxVariableToIncrement, // A variable incremented by the software timer's callback function - * prvTimerCallback, // The function to execute when the timer expires. - * &xTimerBuffer ); // The buffer that will hold the software timer structure. - * - * // The scheduler has not started yet so a block time is not used. - * xReturned = xTimerStart( xTimer, 0 ); - * - * // ... - * // Create tasks here. - * // ... - * - * // Starting the scheduler will start the timers running as they have already - * // been set into the active state. - * vTaskStartScheduler(); - * - * // Should not reach here. - * for( ;; ); - * } - * @endcode - */ - #if( configSUPPORT_STATIC_ALLOCATION == 1 ) - TimerHandle_t xTimerCreateStatic( const char * const pcTimerName, - const TickType_t xTimerPeriodInTicks, - const UBaseType_t uxAutoReload, - void * const pvTimerID, - TimerCallbackFunction_t pxCallbackFunction, - StaticTimer_t *pxTimerBuffer ) PRIVILEGED_FUNCTION; +/** + * TimerHandle_t xTimerCreateStatic(const char * const pcTimerName, + * TickType_t xTimerPeriodInTicks, + * UBaseType_t uxAutoReload, + * void * pvTimerID, + * TimerCallbackFunction_t pxCallbackFunction, + * StaticTimer_t *pxTimerBuffer ); + * + * Creates a new software timer instance, and returns a handle by which the + * created software timer can be referenced. + * + * Internally, within the FreeRTOS implementation, software timers use a block + * of memory, in which the timer data structure is stored. If a software timer + * is created using xTimerCreate() then the required memory is automatically + * dynamically allocated inside the xTimerCreate() function. (see + * https://www.FreeRTOS.org/a00111.html). If a software timer is created using + * xTimerCreateStatic() then the application writer must provide the memory that + * will get used by the software timer. xTimerCreateStatic() therefore allows a + * software timer to be created without using any dynamic memory allocation. + * + * Timers are created in the dormant state. The xTimerStart(), xTimerReset(), + * xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and + * xTimerChangePeriodFromISR() API functions can all be used to transition a + * timer into the active state. + * + * @param pcTimerName A text name that is assigned to the timer. This is done + * purely to assist debugging. The kernel itself only ever references a timer + * by its handle, and never by its name. + * + * @param xTimerPeriodInTicks The timer period. The time is defined in tick + * periods so the constant portTICK_PERIOD_MS can be used to convert a time that + * has been specified in milliseconds. For example, if the timer must expire + * after 100 ticks, then xTimerPeriodInTicks should be set to 100. + * Alternatively, if the timer must expire after 500ms, then xPeriod can be set + * to ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than or + * equal to 1000. The timer period must be greater than 0. + * + * @param uxAutoReload If uxAutoReload is set to pdTRUE then the timer will + * expire repeatedly with a frequency set by the xTimerPeriodInTicks parameter. + * If uxAutoReload is set to pdFALSE then the timer will be a one-shot timer and + * enter the dormant state after it expires. + * + * @param pvTimerID An identifier that is assigned to the timer being created. + * Typically this would be used in the timer callback function to identify which + * timer expired when the same callback function is assigned to more than one + * timer. + * + * @param pxCallbackFunction The function to call when the timer expires. + * Callback functions must have the prototype defined by TimerCallbackFunction_t, + * which is "void vCallbackFunction( TimerHandle_t xTimer );". + * + * @param pxTimerBuffer Must point to a variable of type StaticTimer_t, which + * will be then be used to hold the software timer's data structures, removing + * the need for the memory to be allocated dynamically. + * + * @return If the timer is created then a handle to the created timer is + * returned. If pxTimerBuffer was NULL then NULL is returned. + * + * Example usage: + * @verbatim + * + * // The buffer used to hold the software timer's data structure. + * static StaticTimer_t xTimerBuffer; + * + * // A variable that will be incremented by the software timer's callback + * // function. + * UBaseType_t uxVariableToIncrement = 0; + * + * // A software timer callback function that increments a variable passed to + * // it when the software timer was created. After the 5th increment the + * // callback function stops the software timer. + * static void prvTimerCallback( TimerHandle_t xExpiredTimer ) + * { + * UBaseType_t *puxVariableToIncrement; + * BaseType_t xReturned; + * + * // Obtain the address of the variable to increment from the timer ID. + * puxVariableToIncrement = ( UBaseType_t * ) pvTimerGetTimerID( xExpiredTimer ); + * + * // Increment the variable to show the timer callback has executed. + * ( *puxVariableToIncrement )++; + * + * // If this callback has executed the required number of times, stop the + * // timer. + * if( *puxVariableToIncrement == 5 ) + * { + * // This is called from a timer callback so must not block. + * xTimerStop( xExpiredTimer, staticDONT_BLOCK ); + * } + * } + * + * + * void main( void ) + * { + * // Create the software time. xTimerCreateStatic() has an extra parameter + * // than the normal xTimerCreate() API function. The parameter is a pointer + * // to the StaticTimer_t structure that will hold the software timer + * // structure. If the parameter is passed as NULL then the structure will be + * // allocated dynamically, just as if xTimerCreate() had been called. + * xTimer = xTimerCreateStatic( "T1", // Text name for the task. Helps debugging only. Not used by FreeRTOS. + * xTimerPeriod, // The period of the timer in ticks. + * pdTRUE, // This is an auto-reload timer. + * ( void * ) &uxVariableToIncrement, // A variable incremented by the software timer's callback function + * prvTimerCallback, // The function to execute when the timer expires. + * &xTimerBuffer ); // The buffer that will hold the software timer structure. + * + * // The scheduler has not started yet so a block time is not used. + * xReturned = xTimerStart( xTimer, 0 ); + * + * // ... + * // Create tasks here. + * // ... + * + * // Starting the scheduler will start the timers running as they have already + * // been set into the active state. + * vTaskStartScheduler(); + * + * // Should not reach here. + * for( ;; ); + * } + * @endverbatim + */ +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + TimerHandle_t xTimerCreateStatic( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + const TickType_t xTimerPeriodInTicks, + const UBaseType_t uxAutoReload, + void * const pvTimerID, + TimerCallbackFunction_t pxCallbackFunction, + StaticTimer_t * pxTimerBuffer ) PRIVILEGED_FUNCTION; #endif /* configSUPPORT_STATIC_ALLOCATION */ /** @@ -370,7 +388,7 @@ typedef void (*PendedFunction_t)( void *, uint32_t ); * * See the xTimerCreate() API function example usage scenario. */ -void *pvTimerGetTimerID( const TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; +void * pvTimerGetTimerID( const TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; /** * void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID ); @@ -391,7 +409,8 @@ void *pvTimerGetTimerID( const TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; * * See the xTimerCreate() API function example usage scenario. */ -void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID ) PRIVILEGED_FUNCTION; +void vTimerSetTimerID( TimerHandle_t xTimer, + void * pvNewID ) PRIVILEGED_FUNCTION; /** * BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ); @@ -413,7 +432,7 @@ void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID ) PRIVILEGED_FUNCTION * pdFALSE will be returned if the timer is active. * * Example usage: - * @code{c} + * @verbatim * // This function assumes xTimer has already been created. * void vAFunction( TimerHandle_t xTimer ) * { @@ -426,11 +445,15 @@ void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID ) PRIVILEGED_FUNCTION * // xTimer is not active, do something else. * } * } - * @endcode + * @endverbatim */ BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; /** + * @cond + * TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ); + * @endcond + * * xTimerGetTimerDaemonTaskHandle() is only available if * INCLUDE_xTimerGetTimerDaemonTaskHandle is set to 1 in FreeRTOSConfig.h. * @@ -489,9 +512,12 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION; * See the xTimerCreate() API function example usage scenario. * */ -#define xTimerStart( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) ) +#define xTimerStart( xTimer, xTicksToWait ) \ + xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) ) /** + * BaseType_t xTimerStop( TimerHandle_t xTimer, TickType_t xTicksToWait ); + * * Timer functionality is provided by a timer service/daemon task. Many of the * public FreeRTOS timer API functions send commands to the timer service task * through a queue called the timer command queue. The timer command queue is @@ -529,9 +555,14 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION; * See the xTimerCreate() API function example usage scenario. * */ -#define xTimerStop( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP, 0U, NULL, ( xTicksToWait ) ) +#define xTimerStop( xTimer, xTicksToWait ) \ + xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP, 0U, NULL, ( xTicksToWait ) ) /** + * BaseType_t xTimerChangePeriod( TimerHandle_t xTimer, + * TickType_t xNewPeriod, + * TickType_t xTicksToWait ); + * * Timer functionality is provided by a timer service/daemon task. Many of the * public FreeRTOS timer API functions send commands to the timer service task * through a queue called the timer command queue. The timer command queue is @@ -573,7 +604,7 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION; * configTIMER_TASK_PRIORITY configuration constant. * * Example usage: - * @code{c} + * @verbatim * // This function assumes xTimer has already been created. If the timer * // referenced by xTimer is already active when it is called, then the timer * // is deleted. If the timer referenced by xTimer is not active when it is @@ -603,11 +634,14 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION; * } * } * } - * @endcode + * @endverbatim */ - #define xTimerChangePeriod( xTimer, xNewPeriod, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD, ( xNewPeriod ), NULL, ( xTicksToWait ) ) +#define xTimerChangePeriod( xTimer, xNewPeriod, xTicksToWait ) \ + xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD, ( xNewPeriod ), NULL, ( xTicksToWait ) ) /** + * BaseType_t xTimerDelete( TimerHandle_t xTimer, TickType_t xTicksToWait ); + * * Timer functionality is provided by a timer service/daemon task. Many of the * public FreeRTOS timer API functions send commands to the timer service task * through a queue called the timer command queue. The timer command queue is @@ -641,9 +675,12 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION; * * See the xTimerChangePeriod() API function example usage scenario. */ -#define xTimerDelete( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_DELETE, 0U, NULL, ( xTicksToWait ) ) +#define xTimerDelete( xTimer, xTicksToWait ) \ + xTimerGenericCommand( ( xTimer ), tmrCOMMAND_DELETE, 0U, NULL, ( xTicksToWait ) ) /** + * BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xTicksToWait ); + * * Timer functionality is provided by a timer service/daemon task. Many of the * public FreeRTOS timer API functions send commands to the timer service task * through a queue called the timer command queue. The timer command queue is @@ -689,7 +726,7 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION; * configuration constant. * * Example usage: - * @code{c} + * @verbatim * // When a key is pressed, an LCD back-light is switched on. If 5 seconds pass * // without a key being pressed, then the LCD back-light is switched off. In * // this case, the timer is a one-shot timer. @@ -761,11 +798,15 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION; * // Should not reach here. * for( ;; ); * } - * @endcode + * @endverbatim */ -#define xTimerReset( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_RESET, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) ) +#define xTimerReset( xTimer, xTicksToWait ) \ + xTimerGenericCommand( ( xTimer ), tmrCOMMAND_RESET, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) ) /** + * BaseType_t xTimerStartFromISR( TimerHandle_t xTimer, + * BaseType_t *pxHigherPriorityTaskWoken ); + * * A version of xTimerStart() that can be called from an interrupt service * routine. * @@ -793,7 +834,7 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION; * configuration constant. * * Example usage: - * @code{c} + * @verbatim * // This scenario assumes xBacklightTimer has already been created. When a * // key is pressed, an LCD back-light is switched on. If 5 seconds pass * // without a key being pressed, then the LCD back-light is switched off. In @@ -844,11 +885,15 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION; * // depends on the FreeRTOS port being used). * } * } - * @endcode + * @endverbatim */ -#define xTimerStartFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START_FROM_ISR, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U ) +#define xTimerStartFromISR( xTimer, pxHigherPriorityTaskWoken ) \ + xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START_FROM_ISR, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U ) /** + * BaseType_t xTimerStopFromISR( TimerHandle_t xTimer, + * BaseType_t *pxHigherPriorityTaskWoken ); + * * A version of xTimerStop() that can be called from an interrupt service * routine. * @@ -874,7 +919,7 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION; * priority is set by the configTIMER_TASK_PRIORITY configuration constant. * * Example usage: - * @code{c} + * @verbatim * // This scenario assumes xTimer has already been created and started. When * // an interrupt occurs, the timer should be simply stopped. * @@ -904,11 +949,16 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION; * // depends on the FreeRTOS port being used). * } * } - * @endcode + * @endverbatim */ -#define xTimerStopFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP_FROM_ISR, 0, ( pxHigherPriorityTaskWoken ), 0U ) +#define xTimerStopFromISR( xTimer, pxHigherPriorityTaskWoken ) \ + xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP_FROM_ISR, 0, ( pxHigherPriorityTaskWoken ), 0U ) /** + * BaseType_t xTimerChangePeriodFromISR( TimerHandle_t xTimer, + * TickType_t xNewPeriod, + * BaseType_t *pxHigherPriorityTaskWoken ); + * * A version of xTimerChangePeriod() that can be called from an interrupt * service routine. * @@ -943,7 +993,7 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION; * priority is set by the configTIMER_TASK_PRIORITY configuration constant. * * Example usage: - * @code{c} + * @verbatim * // This scenario assumes xTimer has already been created and started. When * // an interrupt occurs, the period of xTimer should be changed to 500ms. * @@ -973,11 +1023,15 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION; * // depends on the FreeRTOS port being used). * } * } - * @endcode + * @endverbatim */ -#define xTimerChangePeriodFromISR( xTimer, xNewPeriod, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD_FROM_ISR, ( xNewPeriod ), ( pxHigherPriorityTaskWoken ), 0U ) +#define xTimerChangePeriodFromISR( xTimer, xNewPeriod, pxHigherPriorityTaskWoken ) \ + xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD_FROM_ISR, ( xNewPeriod ), ( pxHigherPriorityTaskWoken ), 0U ) /** + * BaseType_t xTimerResetFromISR( TimerHandle_t xTimer, + * BaseType_t *pxHigherPriorityTaskWoken ); + * * A version of xTimerReset() that can be called from an interrupt service * routine. * @@ -1005,7 +1059,7 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION; * task priority is set by the configTIMER_TASK_PRIORITY configuration constant. * * Example usage: - * @code{c} + * @verbatim * // This scenario assumes xBacklightTimer has already been created. When a * // key is pressed, an LCD back-light is switched on. If 5 seconds pass * // without a key being pressed, then the LCD back-light is switched off. In @@ -1056,12 +1110,19 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION; * // depends on the FreeRTOS port being used). * } * } - * @endcode + * @endverbatim */ -#define xTimerResetFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_RESET_FROM_ISR, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U ) +#define xTimerResetFromISR( xTimer, pxHigherPriorityTaskWoken ) \ + xTimerGenericCommand( ( xTimer ), tmrCOMMAND_RESET_FROM_ISR, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U ) /** + * BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, + * void *pvParameter1, + * uint32_t ulParameter2, + * BaseType_t *pxHigherPriorityTaskWoken ); + * + * * Used from application interrupt service routines to defer the execution of a * function to the RTOS daemon task (the timer service task, hence this function * is implemented in timers.c and is prefixed with 'Timer'). @@ -1103,75 +1164,87 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION; * timer daemon task, otherwise pdFALSE is returned. * * Example usage: - * @code{c} + * @verbatim * - * // The callback function that will execute in the context of the daemon task. + * // The callback function that will execute in the context of the daemon task. * // Note callback functions must all use this same prototype. * void vProcessInterface( void *pvParameter1, uint32_t ulParameter2 ) - * { - * BaseType_t xInterfaceToService; + * { + * BaseType_t xInterfaceToService; * - * // The interface that requires servicing is passed in the second + * // The interface that requires servicing is passed in the second * // parameter. The first parameter is not used in this case. - * xInterfaceToService = ( BaseType_t ) ulParameter2; + * xInterfaceToService = ( BaseType_t ) ulParameter2; * - * // ...Perform the processing here... - * } + * // ...Perform the processing here... + * } * - * // An ISR that receives data packets from multiple interfaces + * // An ISR that receives data packets from multiple interfaces * void vAnISR( void ) - * { - * BaseType_t xInterfaceToService, xHigherPriorityTaskWoken; + * { + * BaseType_t xInterfaceToService, xHigherPriorityTaskWoken; * - * // Query the hardware to determine which interface needs processing. - * xInterfaceToService = prvCheckInterfaces(); + * // Query the hardware to determine which interface needs processing. + * xInterfaceToService = prvCheckInterfaces(); * * // The actual processing is to be deferred to a task. Request the * // vProcessInterface() callback function is executed, passing in the - * // number of the interface that needs processing. The interface to - * // service is passed in the second parameter. The first parameter is - * // not used in this case. - * xHigherPriorityTaskWoken = pdFALSE; - * xTimerPendFunctionCallFromISR( vProcessInterface, NULL, ( uint32_t ) xInterfaceToService, &xHigherPriorityTaskWoken ); + * // number of the interface that needs processing. The interface to + * // service is passed in the second parameter. The first parameter is + * // not used in this case. + * xHigherPriorityTaskWoken = pdFALSE; + * xTimerPendFunctionCallFromISR( vProcessInterface, NULL, ( uint32_t ) xInterfaceToService, &xHigherPriorityTaskWoken ); * - * // If xHigherPriorityTaskWoken is now set to pdTRUE then a context - * // switch should be requested. The macro used is port specific and will - * // be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() - refer to - * // the documentation page for the port being used. - * portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); + * // If xHigherPriorityTaskWoken is now set to pdTRUE then a context + * // switch should be requested. The macro used is port specific and will + * // be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() - refer to + * // the documentation page for the port being used. + * portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); * - * } - * @endcode + * } + * @endverbatim */ -BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; +BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, + void * pvParameter1, + uint32_t ulParameter2, + BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; - /** - * Used to defer the execution of a function to the RTOS daemon task (the timer - * service task, hence this function is implemented in timers.c and is prefixed - * with 'Timer'). - * - * @param xFunctionToPend The function to execute from the timer service/ - * daemon task. The function must conform to the PendedFunction_t - * prototype. - * - * @param pvParameter1 The value of the callback function's first parameter. - * The parameter has a void * type to allow it to be used to pass any type. - * For example, unsigned longs can be cast to a void *, or the void * can be - * used to point to a structure. - * - * @param ulParameter2 The value of the callback function's second parameter. - * - * @param xTicksToWait Calling this function will result in a message being - * sent to the timer daemon task on a queue. xTicksToWait is the amount of - * time the calling task should remain in the Blocked state (so not using any - * processing time) for space to become available on the timer queue if the - * queue is found to be full. - * - * @return pdPASS is returned if the message was successfully sent to the - * timer daemon task, otherwise pdFALSE is returned. - * - */ -BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; +/** + * BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, + * void *pvParameter1, + * uint32_t ulParameter2, + * TickType_t xTicksToWait ); + * + * + * Used to defer the execution of a function to the RTOS daemon task (the timer + * service task, hence this function is implemented in timers.c and is prefixed + * with 'Timer'). + * + * @param xFunctionToPend The function to execute from the timer service/ + * daemon task. The function must conform to the PendedFunction_t + * prototype. + * + * @param pvParameter1 The value of the callback function's first parameter. + * The parameter has a void * type to allow it to be used to pass any type. + * For example, unsigned longs can be cast to a void *, or the void * can be + * used to point to a structure. + * + * @param ulParameter2 The value of the callback function's second parameter. + * + * @param xTicksToWait Calling this function will result in a message being + * sent to the timer daemon task on a queue. xTicksToWait is the amount of + * time the calling task should remain in the Blocked state (so not using any + * processing time) for space to become available on the timer queue if the + * queue is found to be full. + * + * @return pdPASS is returned if the message was successfully sent to the + * timer daemon task, otherwise pdFALSE is returned. + * + */ +BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, + void * pvParameter1, + uint32_t ulParameter2, + TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; /** * const char * const pcTimerGetName( TimerHandle_t xTimer ); @@ -1187,8 +1260,8 @@ const char * pcTimerGetName( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; /*lint /** * void vTimerSetReloadMode( TimerHandle_t xTimer, const UBaseType_t uxAutoReload ); * - * Updates a timer to be either an autoreload timer, in which case the timer - * automatically resets itself each time it expires, or a one shot timer, in + * Updates a timer to be either an auto-reload timer, in which case the timer + * automatically resets itself each time it expires, or a one-shot timer, in * which case the timer will only expire once unless it is manually restarted. * * @param xTimer The handle of the timer being updated. @@ -1199,7 +1272,22 @@ const char * pcTimerGetName( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; /*lint * uxAutoReload is set to pdFALSE then the timer will be a one-shot timer and * enter the dormant state after it expires. */ -void vTimerSetReloadMode( TimerHandle_t xTimer, const UBaseType_t uxAutoReload ) PRIVILEGED_FUNCTION; +void vTimerSetReloadMode( TimerHandle_t xTimer, + const UBaseType_t uxAutoReload ) PRIVILEGED_FUNCTION; + +/** + * UBaseType_t uxTimerGetReloadMode( TimerHandle_t xTimer ); + * + * Queries a timer to determine if it is an auto-reload timer, in which case the timer + * automatically resets itself each time it expires, or a one-shot timer, in + * which case the timer will only expire once unless it is manually restarted. + * + * @param xTimer The handle of the timer being queried. + * + * @return If the timer is an auto-reload timer then pdTRUE is returned, otherwise + * pdFALSE is returned. + */ +UBaseType_t uxTimerGetReloadMode( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; /** * TickType_t xTimerGetPeriod( TimerHandle_t xTimer ); @@ -1213,18 +1301,18 @@ void vTimerSetReloadMode( TimerHandle_t xTimer, const UBaseType_t uxAutoReload ) TickType_t xTimerGetPeriod( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; /** -* TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer ); -* -* Returns the time in ticks at which the timer will expire. If this is less -* than the current tick count then the expiry time has overflowed from the -* current time. -* -* @param xTimer The handle of the timer being queried. -* -* @return If the timer is running then the time in ticks at which the timer -* will next expire is returned. If the timer is not running then the return -* value is undefined. -*/ + * TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer ); + * + * Returns the time in ticks at which the timer will expire. If this is less + * than the current tick count then the expiry time has overflowed from the + * current time. + * + * @param xTimer The handle of the timer being queried. + * + * @return If the timer is running then the time in ticks at which the timer + * will next expire is returned. If the timer is not running then the return + * value is undefined. + */ TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; /** @cond */ @@ -1234,16 +1322,46 @@ TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; * for use by the kernel only. */ BaseType_t xTimerCreateTimerTask( void ) PRIVILEGED_FUNCTION; -BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; +BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, + const BaseType_t xCommandID, + const TickType_t xOptionalValue, + BaseType_t * const pxHigherPriorityTaskWoken, + const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; -#if( configUSE_TRACE_FACILITY == 1 ) - void vTimerSetTimerNumber( TimerHandle_t xTimer, UBaseType_t uxTimerNumber ) PRIVILEGED_FUNCTION; - UBaseType_t uxTimerGetTimerNumber( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; +#if ( configUSE_TRACE_FACILITY == 1 ) + void vTimerSetTimerNumber( TimerHandle_t xTimer, + UBaseType_t uxTimerNumber ) PRIVILEGED_FUNCTION; + UBaseType_t uxTimerGetTimerNumber( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; #endif /** @endcond */ -#ifdef __cplusplus -} +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + + /** + * @cond + * task.h + * @code{c} + * void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer, StackType_t ** ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize ) + * @endcode + * @endcond + * + * This function is used to provide a statically allocated block of memory to FreeRTOS to hold the Timer Task TCB. This function is required when + * configSUPPORT_STATIC_ALLOCATION is set. For more information see this URI: https://www.FreeRTOS.org/a00110.html#configSUPPORT_STATIC_ALLOCATION + * + * @param ppxTimerTaskTCBBuffer A handle to a statically allocated TCB buffer + * @param ppxTimerTaskStackBuffer A handle to a statically allocated Stack buffer for thie idle task + * @param pulTimerTaskStackSize A pointer to the number of elements that will fit in the allocated stack buffer + */ + void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer, + StackType_t ** ppxTimerTaskStackBuffer, + uint32_t * pulTimerTaskStackSize ); + #endif + +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* TIMERS_H */ diff --git a/components/freertos/linker.lf b/components/freertos/linker.lf index 155436e8f6..8473d52605 100644 --- a/components/freertos/linker.lf +++ b/components/freertos/linker.lf @@ -2,13 +2,11 @@ archive: libfreertos.a entries: * (noflash_text) + if FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH = y: + task_snapshot (default) if FREERTOS_PLACE_FUNCTIONS_INTO_FLASH = y: port: pxPortInitialiseStack (default) port: xPortStartScheduler (default) - if ESP_PANIC_HANDLER_IRAM != y: - tasks: uxTaskGetSnapshotAll (default) - tasks: prvTaskGetSnapshot (default) - tasks: prvTaskGetSnapshotsFromList (default) if IDF_TARGET_ESP32S2 = n && IDF_TARGET_ESP32C3 = n && IDF_TARGET_ESP32H2 = n : port: vPortReleaseTaskMPUSettings (default) tasks: xTaskCreateRestricted (default) @@ -28,7 +26,7 @@ entries: tasks: vTaskSuspendAll (default) tasks: uxTaskGetNumberOfTasks (default) tasks: xTaskGetIdleTaskHandle (default) - tasks: xTaskRemoveFromUnorderedEventList (default) + tasks: vTaskRemoveFromUnorderedEventList (default) tasks: uxTaskPriorityGet (default) tasks: vTaskPrioritySet (default) tasks: vTaskSetThreadLocalStoragePointerAndDelCallback (default) @@ -36,12 +34,15 @@ entries: tasks: xTaskGetCurrentTaskHandleForCPU (default) tasks: vTaskDelete (default) tasks: vTaskDelayUntil (default) + tasks: xTaskDelayUntil (default) tasks: vTaskDelay (default) tasks: vTaskSuspend (default) tasks: xTaskResumeAll (default) tasks: uxTaskResetEventItemValue (default) tasks: ulTaskNotifyTake (default) + tasks: ulTaskGenericNotifyTake (default) tasks: xTaskNotifyWait (default) + tasks: xTaskGenericNotifyWait (default) tasks: xTaskGenericNotify (default) tasks: eTaskGetState (default) tasks: pxTaskGetStackStart (default) diff --git a/components/freertos/list.c b/components/freertos/list.c index 42e482d36d..5eec523162 100644 --- a/components/freertos/list.c +++ b/components/freertos/list.c @@ -1,6 +1,6 @@ /* - * FreeRTOS Kernel V10.2.1 - * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V10.4.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * 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 @@ -19,180 +19,195 @@ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS * - * 1 tab == 4 spaces! */ #include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining + * all the API functions to use the MPU wrappers. That should only be done when + * task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + #include "FreeRTOS.h" #include "list.h" +/* Lint e9021, e961 and e750 are suppressed as a MISRA exception justified + * because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be + * defined for the header files above, but not in this file, in order to + * generate the correct privileged Vs unprivileged linkage and placement. */ +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021. */ /*----------------------------------------------------------- - * PUBLIC LIST API documented in list.h - *----------------------------------------------------------*/ +* PUBLIC LIST API documented in list.h +*----------------------------------------------------------*/ void vListInitialise( List_t * const pxList ) { - /* The list structure contains a list item which is used to mark the - end of the list. To initialise the list the list end is inserted - as the only list entry. */ - pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */ + /* The list structure contains a list item which is used to mark the + * end of the list. To initialise the list the list end is inserted + * as the only list entry. */ + pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */ - /* The list end value is the highest possible value in the list to - ensure it remains at the end of the list. */ - pxList->xListEnd.xItemValue = portMAX_DELAY; + /* The list end value is the highest possible value in the list to + * ensure it remains at the end of the list. */ + pxList->xListEnd.xItemValue = portMAX_DELAY; - /* The list end next and previous pointers point to itself so we know - when the list is empty. */ - pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */ - pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );/*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */ + /* The list end next and previous pointers point to itself so we know + * when the list is empty. */ + pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */ + pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */ - pxList->uxNumberOfItems = ( UBaseType_t ) 0U; + pxList->uxNumberOfItems = ( UBaseType_t ) 0U; - /* Write known values into the list if - configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ - listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ); - listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ); + /* Write known values into the list if + * configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ + listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ); + listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ); } /*-----------------------------------------------------------*/ void vListInitialiseItem( ListItem_t * const pxItem ) { - /* Make sure the list item is not recorded as being on a list. */ - pxItem->pxContainer = NULL; + /* Make sure the list item is not recorded as being on a list. */ + pxItem->pxContainer = NULL; - /* Write known values into the list item if - configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ - listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ); - listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ); + /* Write known values into the list item if + * configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ + listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ); + listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ); } /*-----------------------------------------------------------*/ -void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem ) +void vListInsertEnd( List_t * const pxList, + ListItem_t * const pxNewListItem ) { -ListItem_t * const pxIndex = pxList->pxIndex; + ListItem_t * const pxIndex = pxList->pxIndex; - /* Only effective when configASSERT() is also defined, these tests may catch - the list data structures being overwritten in memory. They will not catch - data errors caused by incorrect configuration or use of FreeRTOS. */ - listTEST_LIST_INTEGRITY( pxList ); - listTEST_LIST_ITEM_INTEGRITY( pxNewListItem ); + /* Only effective when configASSERT() is also defined, these tests may catch + * the list data structures being overwritten in memory. They will not catch + * data errors caused by incorrect configuration or use of FreeRTOS. */ + listTEST_LIST_INTEGRITY( pxList ); + listTEST_LIST_ITEM_INTEGRITY( pxNewListItem ); - /* Insert a new list item into pxList, but rather than sort the list, - makes the new list item the last item to be removed by a call to - listGET_OWNER_OF_NEXT_ENTRY(). */ - pxNewListItem->pxNext = pxIndex; - pxNewListItem->pxPrevious = pxIndex->pxPrevious; + /* Insert a new list item into pxList, but rather than sort the list, + * makes the new list item the last item to be removed by a call to + * listGET_OWNER_OF_NEXT_ENTRY(). */ + pxNewListItem->pxNext = pxIndex; + pxNewListItem->pxPrevious = pxIndex->pxPrevious; - /* Only used during decision coverage testing. */ - mtCOVERAGE_TEST_DELAY(); + /* Only used during decision coverage testing. */ + mtCOVERAGE_TEST_DELAY(); - pxIndex->pxPrevious->pxNext = pxNewListItem; - pxIndex->pxPrevious = pxNewListItem; + pxIndex->pxPrevious->pxNext = pxNewListItem; + pxIndex->pxPrevious = pxNewListItem; - /* Remember which list the item is in. */ - pxNewListItem->pxContainer = pxList; + /* Remember which list the item is in. */ + pxNewListItem->pxContainer = pxList; - ( pxList->uxNumberOfItems )++; + ( pxList->uxNumberOfItems )++; } /*-----------------------------------------------------------*/ -void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem ) +void vListInsert( List_t * const pxList, + ListItem_t * const pxNewListItem ) { -ListItem_t *pxIterator; -const TickType_t xValueOfInsertion = pxNewListItem->xItemValue; + ListItem_t * pxIterator; + const TickType_t xValueOfInsertion = pxNewListItem->xItemValue; - /* Only effective when configASSERT() is also defined, these tests may catch - the list data structures being overwritten in memory. They will not catch - data errors caused by incorrect configuration or use of FreeRTOS. */ - listTEST_LIST_INTEGRITY( pxList ); - listTEST_LIST_ITEM_INTEGRITY( pxNewListItem ); + /* Only effective when configASSERT() is also defined, these tests may catch + * the list data structures being overwritten in memory. They will not catch + * data errors caused by incorrect configuration or use of FreeRTOS. */ + listTEST_LIST_INTEGRITY( pxList ); + listTEST_LIST_ITEM_INTEGRITY( pxNewListItem ); - /* Insert the new list item into the list, sorted in xItemValue order. + /* Insert the new list item into the list, sorted in xItemValue order. + * + * If the list already contains a list item with the same item value then the + * new list item should be placed after it. This ensures that TCBs which are + * stored in ready lists (all of which have the same xItemValue value) get a + * share of the CPU. However, if the xItemValue is the same as the back marker + * the iteration loop below will not end. Therefore the value is checked + * first, and the algorithm slightly modified if necessary. */ + if( xValueOfInsertion == portMAX_DELAY ) + { + pxIterator = pxList->xListEnd.pxPrevious; + } + else + { + /* *** NOTE *********************************************************** + * If you find your application is crashing here then likely causes are + * listed below. In addition see https://www.FreeRTOS.org/FAQHelp.html for + * more tips, and ensure configASSERT() is defined! + * https://www.FreeRTOS.org/a00110.html#configASSERT + * + * 1) Stack overflow - + * see https://www.FreeRTOS.org/Stacks-and-stack-overflow-checking.html + * 2) Incorrect interrupt priority assignment, especially on Cortex-M + * parts where numerically high priority values denote low actual + * interrupt priorities, which can seem counter intuitive. See + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html and the definition + * of configMAX_SYSCALL_INTERRUPT_PRIORITY on + * https://www.FreeRTOS.org/a00110.html + * 3) Calling an API function from within a critical section or when + * the scheduler is suspended, or calling an API function that does + * not end in "FromISR" from an interrupt. + * 4) Using a queue or semaphore before it has been initialised or + * before the scheduler has been started (are interrupts firing + * before vTaskStartScheduler() has been called?). + * 5) If the FreeRTOS port supports interrupt nesting then ensure that + * the priority of the tick interrupt is at or below + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + **********************************************************************/ - If the list already contains a list item with the same item value then the - new list item should be placed after it. This ensures that TCBs which are - stored in ready lists (all of which have the same xItemValue value) get a - share of the CPU. However, if the xItemValue is the same as the back marker - the iteration loop below will not end. Therefore the value is checked - first, and the algorithm slightly modified if necessary. */ - if( xValueOfInsertion == portMAX_DELAY ) - { - pxIterator = pxList->xListEnd.pxPrevious; - } - else - { - /* *** NOTE *********************************************************** - If you find your application is crashing here then likely causes are - listed below. In addition see https://www.freertos.org/FAQHelp.html for - more tips, and ensure configASSERT() is defined! - https://www.freertos.org/a00110.html#configASSERT + for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. *//*lint !e440 The iterator moves to a different value, not xValueOfInsertion. */ + { + /* There is nothing to do here, just iterating to the wanted + * insertion position. */ + } + } - 1) Stack overflow - - see https://www.freertos.org/Stacks-and-stack-overflow-checking.html - 2) Incorrect interrupt priority assignment, especially on Cortex-M - parts where numerically high priority values denote low actual - interrupt priorities, which can seem counter intuitive. See - https://www.freertos.org/RTOS-Cortex-M3-M4.html and the definition - of configMAX_SYSCALL_INTERRUPT_PRIORITY on - https://www.freertos.org/a00110.html - 3) Calling an API function from within a critical section or when - the scheduler is suspended, or calling an API function that does - not end in "FromISR" from an interrupt. - 4) Using a queue or semaphore before it has been initialised or - before the scheduler has been started (are interrupts firing - before vTaskStartScheduler() has been called?). - **********************************************************************/ + pxNewListItem->pxNext = pxIterator->pxNext; + pxNewListItem->pxNext->pxPrevious = pxNewListItem; + pxNewListItem->pxPrevious = pxIterator; + pxIterator->pxNext = pxNewListItem; - for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. *//*lint !e440 The iterator moves to a different value, not xValueOfInsertion. */ - { - /* There is nothing to do here, just iterating to the wanted - insertion position. */ - } - } + /* Remember which list the item is in. This allows fast removal of the + * item later. */ + pxNewListItem->pxContainer = pxList; - pxNewListItem->pxNext = pxIterator->pxNext; - pxNewListItem->pxNext->pxPrevious = pxNewListItem; - pxNewListItem->pxPrevious = pxIterator; - pxIterator->pxNext = pxNewListItem; - - /* Remember which list the item is in. This allows fast removal of the - item later. */ - pxNewListItem->pxContainer = pxList; - - ( pxList->uxNumberOfItems )++; + ( pxList->uxNumberOfItems )++; } /*-----------------------------------------------------------*/ UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) { /* The list item knows which list it is in. Obtain the list from the list -item. */ -List_t * const pxList = pxItemToRemove->pxContainer; + * item. */ + List_t * const pxList = pxItemToRemove->pxContainer; - pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious; - pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext; + pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious; + pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext; - /* Only used during decision coverage testing. */ - mtCOVERAGE_TEST_DELAY(); + /* Only used during decision coverage testing. */ + mtCOVERAGE_TEST_DELAY(); - /* Make sure the index is left pointing to a valid item. */ - if(pxList->pxIndex == pxItemToRemove) - { - pxList->pxIndex = pxItemToRemove->pxPrevious; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* Make sure the index is left pointing to a valid item. */ + if( pxList->pxIndex == pxItemToRemove ) + { + pxList->pxIndex = pxItemToRemove->pxPrevious; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - pxItemToRemove->pxContainer = NULL; - ( pxList->uxNumberOfItems )--; + pxItemToRemove->pxContainer = NULL; + ( pxList->uxNumberOfItems )--; - return pxList->uxNumberOfItems; + return pxList->uxNumberOfItems; } /*-----------------------------------------------------------*/ diff --git a/components/freertos/port/linux/include/freertos/FreeRTOSConfig_arch.h b/components/freertos/port/linux/include/freertos/FreeRTOSConfig_arch.h new file mode 100644 index 0000000000..273593d86a --- /dev/null +++ b/components/freertos/port/linux/include/freertos/FreeRTOSConfig_arch.h @@ -0,0 +1,75 @@ +/* + FreeRTOS V10 - Copyright (C) 2021 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef FREERTOS_CONFIG_LINUX_H +#define FREERTOS_CONFIG_LINUX_H + +// This file is included in the common FreeRTOSConfig.h. + +#endif // FREERTOS_CONFIG_LINUX_H diff --git a/components/freertos/port/linux/include/freertos/portmacro.h b/components/freertos/port/linux/include/freertos/portmacro.h new file mode 100644 index 0000000000..720f128c80 --- /dev/null +++ b/components/freertos/port/linux/include/freertos/portmacro.h @@ -0,0 +1,32 @@ +#pragma once + +#include "esp_attr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define portBYTE_ALIGNMENT 16 + +/* Type definitions. */ +#define portCHAR uint8_t +#define portFLOAT float +#define portDOUBLE double +#define portLONG int32_t +#define portSHORT int16_t +#define portSTACK_TYPE uint8_t +#define portBASE_TYPE int +// interrupt module will mask interrupt with priority less than threshold +#define RVHAL_EXCM_LEVEL 4 + +typedef portSTACK_TYPE StackType_t; +typedef portBASE_TYPE BaseType_t; +typedef unsigned portBASE_TYPE UBaseType_t; +typedef uint32_t TickType_t; +#define portMAX_DELAY ( TickType_t ) 0xffffffffUL + +typedef int portMUX_TYPE; + +#ifdef __cplusplus +} +#endif diff --git a/components/freertos/port/port_common.c b/components/freertos/port/port_common.c index 9ba5e381a0..5af0e378e7 100644 --- a/components/freertos/port/port_common.c +++ b/components/freertos/port/port_common.c @@ -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: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "FreeRTOS.h" @@ -22,8 +14,9 @@ #include "esp_task_wdt.h" #include "esp_task.h" #include "esp_private/crosscore_int.h" -#include "esp_private/startup_internal.h" +#include "esp_private/startup_internal.h" /* Required by g_spiram_ok. [refactor-todo] for g_spiram_ok */ #include "esp_log.h" +#include "soc/soc_memory_types.h" #include "soc/dport_access.h" #include "sdkconfig.h" @@ -56,7 +49,7 @@ volatile unsigned port_xSchedulerRunning[portNUM_PROCESSORS] = {0}; // // And since this should be true, we can just check for CONFIG_FREERTOS_UNICORE. #if CONFIG_FREERTOS_UNICORE != CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE - #error "FreeRTOS and system configuration mismatch regarding the use of multiple cores." + #error "FreeRTOS and system configuration mismatch regarding the use of multiple cores." #endif static void main_task(void* args); @@ -70,75 +63,85 @@ extern void app_main(void); void esp_startup_start_app_common(void) { #if CONFIG_ESP_INT_WDT - esp_int_wdt_init(); - //Initialize the interrupt watch dog for CPU0. - esp_int_wdt_cpu_init(); + esp_int_wdt_init(); + //Initialize the interrupt watch dog for CPU0. + esp_int_wdt_cpu_init(); #endif - esp_crosscore_int_init(); - -#ifndef CONFIG_FREERTOS_UNICORE -#if CONFIG_IDF_TARGET_ESP32 - esp_dport_access_int_init(); -#endif -#endif + esp_crosscore_int_init(); #ifdef CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME esp_gdbstub_init(); #endif // CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME - portBASE_TYPE res = xTaskCreatePinnedToCore(&main_task, "main", - ESP_TASK_MAIN_STACK, NULL, - ESP_TASK_MAIN_PRIO, NULL, ESP_TASK_MAIN_CORE); - assert(res == pdTRUE); - (void)res; + portBASE_TYPE res = xTaskCreatePinnedToCore(&main_task, "main", + ESP_TASK_MAIN_STACK, NULL, + ESP_TASK_MAIN_PRIO, NULL, ESP_TASK_MAIN_CORE); + assert(res == pdTRUE); + (void)res; } static void main_task(void* args) { #if !CONFIG_FREERTOS_UNICORE - // Wait for FreeRTOS initialization to finish on APP CPU, before replacing its startup stack - while (port_xSchedulerRunning[1] == 0) { - ; - } + // Wait for FreeRTOS initialization to finish on APP CPU, before replacing its startup stack + while (port_xSchedulerRunning[1] == 0) { + ; + } #endif - // [refactor-todo] check if there is a way to move the following block to esp_system startup - heap_caps_enable_nonos_stack_heaps(); + // [refactor-todo] check if there is a way to move the following block to esp_system startup + heap_caps_enable_nonos_stack_heaps(); - // Now we have startup stack RAM available for heap, enable any DMA pool memory + // Now we have startup stack RAM available for heap, enable any DMA pool memory #if CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL - if (g_spiram_ok) { - esp_err_t r = esp_spiram_reserve_dma_pool(CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL); - if (r != ESP_OK) { - ESP_EARLY_LOGE(TAG, "Could not reserve internal/DMA pool (error 0x%x)", r); - abort(); - } - } + if (g_spiram_ok) { + esp_err_t r = esp_spiram_reserve_dma_pool(CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL); + if (r != ESP_OK) { + ESP_EARLY_LOGE(TAG, "Could not reserve internal/DMA pool (error 0x%x)", r); + abort(); + } + } #endif - //Initialize task wdt if configured to do so + //Initialize task wdt if configured to do so #ifdef CONFIG_ESP_TASK_WDT_PANIC - ESP_ERROR_CHECK(esp_task_wdt_init(CONFIG_ESP_TASK_WDT_TIMEOUT_S, true)); + ESP_ERROR_CHECK(esp_task_wdt_init(CONFIG_ESP_TASK_WDT_TIMEOUT_S, true)); #elif CONFIG_ESP_TASK_WDT - ESP_ERROR_CHECK(esp_task_wdt_init(CONFIG_ESP_TASK_WDT_TIMEOUT_S, false)); + ESP_ERROR_CHECK(esp_task_wdt_init(CONFIG_ESP_TASK_WDT_TIMEOUT_S, false)); #endif - //Add IDLE 0 to task wdt + //Add IDLE 0 to task wdt #ifdef CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0 - TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCPU(0); - if(idle_0 != NULL){ - ESP_ERROR_CHECK(esp_task_wdt_add(idle_0)); - } + TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCPU(0); + if(idle_0 != NULL){ + ESP_ERROR_CHECK(esp_task_wdt_add(idle_0)); + } #endif - //Add IDLE 1 to task wdt + //Add IDLE 1 to task wdt #ifdef CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1 - TaskHandle_t idle_1 = xTaskGetIdleTaskHandleForCPU(1); - if(idle_1 != NULL){ - ESP_ERROR_CHECK(esp_task_wdt_add(idle_1)); - } + TaskHandle_t idle_1 = xTaskGetIdleTaskHandleForCPU(1); + if(idle_1 != NULL){ + ESP_ERROR_CHECK(esp_task_wdt_add(idle_1)); + } #endif - app_main(); - vTaskDelete(NULL); + app_main(); + vTaskDelete(NULL); +} + +// -------------------- Heap Related ----------------------- + +bool xPortCheckValidTCBMem(const void *ptr) +{ + return esp_ptr_internal(ptr) && esp_ptr_byte_accessible(ptr); +} + +bool xPortcheckValidStackMem(const void *ptr) +{ +#ifdef CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY + return esp_ptr_byte_accessible(ptr); +#else + return esp_ptr_internal(ptr) && esp_ptr_byte_accessible(ptr); +#endif } diff --git a/components/freertos/port/port_systick.c b/components/freertos/port/port_systick.c new file mode 100644 index 0000000000..0c14a155a1 --- /dev/null +++ b/components/freertos/port/port_systick.c @@ -0,0 +1,170 @@ +/* + * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "soc/cpu.h" +#include "FreeRTOS.h" +#include "task.h" +#include "esp_intr_alloc.h" +#include "esp_err.h" +#include "esp_log.h" +#include "sdkconfig.h" +#ifdef CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER +#include "soc/periph_defs.h" +#include "soc/system_reg.h" +#include "hal/systimer_hal.h" +#include "hal/systimer_ll.h" +#endif + +BaseType_t xPortSysTickHandler(void); + +#ifdef CONFIG_FREERTOS_SYSTICK_USES_CCOUNT +extern void _frxt_tick_timer_init(void); +extern void _xt_tick_divisor_init(void); + +#ifdef CONFIG_FREERTOS_CORETIMER_0 + #define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER0_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF) +#endif +#ifdef CONFIG_FREERTOS_CORETIMER_1 + #define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER1_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF) +#endif + +/** + * @brief Initialize CCONT timer to generate the tick interrupt + * + */ +void vPortSetupTimer(void) +{ + /* Init the tick divisor value */ + _xt_tick_divisor_init(); + + _frxt_tick_timer_init(); +} + + +#elif CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER + +_Static_assert(SOC_CPU_CORES_NUM <= SOC_SYSTIMER_ALARM_NUM - 1, "the number of cores must match the number of core alarms in SYSTIMER"); + +void SysTickIsrHandler(void *arg); + +static uint32_t s_handled_systicks[portNUM_PROCESSORS] = { 0 }; + +#define SYSTICK_INTR_ID (ETS_SYSTIMER_TARGET0_EDGE_INTR_SOURCE) + +/** + * @brief Set up the systimer peripheral to generate the tick interrupt + * + * Both timer alarms are configured in periodic mode. + * It is done at the same time so SysTicks for both CPUs occur at the same time or very close. + * Shifts a time of triggering interrupts for core 0 and core 1. + */ +void vPortSetupTimer(void) +{ + unsigned cpuid = xPortGetCoreID(); +#ifdef CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL3 + const unsigned level = ESP_INTR_FLAG_LEVEL3; +#else + const unsigned level = ESP_INTR_FLAG_LEVEL1; +#endif + /* Systimer HAL layer object */ + static systimer_hal_context_t systimer_hal; + /* set system timer interrupt vector */ + ESP_ERROR_CHECK(esp_intr_alloc(ETS_SYSTIMER_TARGET0_EDGE_INTR_SOURCE + cpuid, ESP_INTR_FLAG_IRAM | level, SysTickIsrHandler, &systimer_hal, NULL)); + + if (cpuid == 0) { + systimer_hal_init(&systimer_hal); + systimer_ll_set_counter_value(systimer_hal.dev, SYSTIMER_LL_COUNTER_OS_TICK, 0); + systimer_ll_apply_counter_value(systimer_hal.dev, SYSTIMER_LL_COUNTER_OS_TICK); + + for (cpuid = 0; cpuid < SOC_CPU_CORES_NUM; cpuid++) { + systimer_hal_counter_can_stall_by_cpu(&systimer_hal, SYSTIMER_LL_COUNTER_OS_TICK, cpuid, false); + } + + for (cpuid = 0; cpuid < portNUM_PROCESSORS; ++cpuid) { + uint32_t alarm_id = SYSTIMER_LL_ALARM_OS_TICK_CORE0 + cpuid; + + /* configure the timer */ + systimer_hal_connect_alarm_counter(&systimer_hal, alarm_id, SYSTIMER_LL_COUNTER_OS_TICK); + systimer_hal_set_alarm_period(&systimer_hal, alarm_id, 1000000UL / CONFIG_FREERTOS_HZ); + systimer_hal_select_alarm_mode(&systimer_hal, alarm_id, SYSTIMER_ALARM_MODE_PERIOD); + systimer_hal_counter_can_stall_by_cpu(&systimer_hal, SYSTIMER_LL_COUNTER_OS_TICK, cpuid, true); + if (cpuid == 0) { + systimer_hal_enable_alarm_int(&systimer_hal, alarm_id); + systimer_hal_enable_counter(&systimer_hal, SYSTIMER_LL_COUNTER_OS_TICK); +#ifndef CONFIG_FREERTOS_UNICORE + // SysTick of core 0 and core 1 are shifted by half of period + systimer_hal_counter_value_advance(&systimer_hal, SYSTIMER_LL_COUNTER_OS_TICK, 1000000UL / CONFIG_FREERTOS_HZ / 2); +#endif + } + } + } else { + uint32_t alarm_id = SYSTIMER_LL_ALARM_OS_TICK_CORE0 + cpuid; + systimer_hal_enable_alarm_int(&systimer_hal, alarm_id); + } +} + +/** + * @brief Systimer interrupt handler. + * + * The Systimer interrupt for SysTick works in periodic mode no need to calc the next alarm. + * If a timer interrupt is ever serviced more than one tick late, it is necessary to process multiple ticks. + */ +IRAM_ATTR void SysTickIsrHandler(void *arg) +{ + uint32_t cpuid = xPortGetCoreID(); + systimer_hal_context_t *systimer_hal = (systimer_hal_context_t *)arg; +#ifdef CONFIG_PM_TRACE + ESP_PM_TRACE_ENTER(TICK, cpuid); +#endif + + uint32_t alarm_id = SYSTIMER_LL_ALARM_OS_TICK_CORE0 + cpuid; + do { + systimer_ll_clear_alarm_int(systimer_hal->dev, alarm_id); + + uint32_t diff = systimer_hal_get_counter_value(systimer_hal, SYSTIMER_LL_COUNTER_OS_TICK) / systimer_ll_get_alarm_period(systimer_hal->dev, alarm_id) - s_handled_systicks[cpuid]; + if (diff > 0) { + if (s_handled_systicks[cpuid] == 0) { + s_handled_systicks[cpuid] = diff; + diff = 1; + } else { + s_handled_systicks[cpuid] += diff; + } + + do { + xPortSysTickHandler(); + } while (--diff); + } + } while (systimer_ll_is_alarm_int_fired(systimer_hal->dev, alarm_id)); + +#ifdef CONFIG_PM_TRACE + ESP_PM_TRACE_EXIT(TICK, cpuid); +#endif +} + +#endif // CONFIG_FREERTOS_SYSTICK_USES_CCOUNT + +/** + * @brief Handler of SysTick + * + * The function is called from: + * - _frxt_timer_int for xtensa with CONFIG_FREERTOS_SYSTICK_USES_CCOUNT + * - SysTickIsrHandler for xtensa with CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER + * - SysTickIsrHandler for riscv + */ +BaseType_t xPortSysTickHandler(void) +{ + portbenchmarkIntLatency(); + traceISR_ENTER(SYSTICK_INTR_ID); + BaseType_t ret = xTaskIncrementTick(); + if(ret != pdFALSE) { + portYIELD_FROM_ISR(); + } else { + traceISR_EXIT(); + } + return ret; +} diff --git a/components/freertos/port/priv_include/port_systick.h b/components/freertos/port/priv_include/port_systick.h new file mode 100644 index 0000000000..a2418823bc --- /dev/null +++ b/components/freertos/port/priv_include/port_systick.h @@ -0,0 +1,20 @@ +/* + * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Set up the SysTick interrupt + */ +void vPortSetupTimer(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/freertos/port/riscv/include/freertos/FreeRTOSConfig.h b/components/freertos/port/riscv/include/freertos/FreeRTOSConfig_arch.h similarity index 100% rename from components/freertos/port/riscv/include/freertos/FreeRTOSConfig.h rename to components/freertos/port/riscv/include/freertos/FreeRTOSConfig_arch.h diff --git a/components/freertos/port/riscv/include/freertos/portmacro.h b/components/freertos/port/riscv/include/freertos/portmacro.h index 9ead3fea26..edfd862f79 100644 --- a/components/freertos/port/riscv/include/freertos/portmacro.h +++ b/components/freertos/port/riscv/include/freertos/portmacro.h @@ -1,5 +1,5 @@ /* - * FreeRTOS Kernel V10.2.1 + * FreeRTOS Kernel V10.4.3 * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of @@ -24,89 +24,466 @@ * * 1 tab == 4 spaces! */ + #ifndef PORTMACRO_H #define PORTMACRO_H +#ifndef __ASSEMBLER__ + +#include "sdkconfig.h" +#include +#include +#include +#include +#include "soc/spinlock.h" +#include "soc/interrupt_core0_reg.h" +#include "soc/cpu.h" +#include "esp_attr.h" +#include "esp_rom_sys.h" +#include "esp_timer.h" /* required for FreeRTOS run time stats */ +#include "esp_heap_caps.h" +#include "esp_system.h" /* required by esp_get_...() functions in portable.h. [refactor-todo] Update portable.h */ +#include "esp_newlib.h" +#include "portbenchmark.h" + +/* [refactor-todo] These includes are not directly used in this file. They are kept into to prevent a breaking change. Remove these. */ +#include +#ifdef CONFIG_LEGACY_INCLUDE_COMMON_HEADERS +#include "soc/soc_memory_layout.h" +#endif + #ifdef __cplusplus extern "C" { #endif -#ifndef __ASSEMBLER__ -#include -#include -#include -#include -#include -#include "esp_timer.h" /* required for FreeRTOS run time stats */ -#include "sdkconfig.h" -#include "esp_attr.h" -#include "esp_heap_caps.h" -#ifdef CONFIG_LEGACY_INCLUDE_COMMON_HEADERS -#include "soc/soc_memory_layout.h" -#endif -#include "soc/spinlock.h" -#include "soc/interrupt_core0_reg.h" -#include "esp_rom_sys.h" -#include "soc/cpu.h" -#include "esp_system.h" -#include "esp_newlib.h" +/* --------------------------------------------------- Port Types ------------------------------------------------------ + * - Port specific types. + * - The settings in this file configure FreeRTOS correctly for the given hardware and compiler. + * - These settings should not be altered. + * - The port types must come first as they are used further down in this file + * ------------------------------------------------------------------------------------------------------------------ */ -/*----------------------------------------------------------- - * Port specific definitions. - * - * The settings in this file configure FreeRTOS correctly for the - * given hardware and compiler. - * - * These settings should not be altered. - *----------------------------------------------------------- - */ +#define portCHAR uint8_t +#define portFLOAT float +#define portDOUBLE double +#define portLONG int32_t +#define portSHORT int16_t +#define portSTACK_TYPE uint8_t +#define portBASE_TYPE int -/* Type definitions. */ -#define portCHAR uint8_t -#define portFLOAT float -#define portDOUBLE double -#define portLONG int32_t -#define portSHORT int16_t -#define portSTACK_TYPE uint8_t -#define portBASE_TYPE int -// interrupt module will mask interrupt with priority less than threshold -#define RVHAL_EXCM_LEVEL 4 +typedef portSTACK_TYPE StackType_t; +typedef portBASE_TYPE BaseType_t; +typedef unsigned portBASE_TYPE UBaseType_t; -typedef portSTACK_TYPE StackType_t; -typedef portBASE_TYPE BaseType_t; -typedef unsigned portBASE_TYPE UBaseType_t; - -#if( configUSE_16_BIT_TICKS == 1 ) - typedef uint16_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffff +#if (configUSE_16_BIT_TICKS == 1) +typedef uint16_t TickType_t; +#define portMAX_DELAY (TickType_t) 0xffff #else - typedef uint32_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +typedef uint32_t TickType_t; +#define portMAX_DELAY (TickType_t) 0xffffffffUL #endif -/*------------------------------------------------------*/ -/* Architecture specifics. */ -#define portSTACK_GROWTH ( -1 ) -#define portTICK_PERIOD_MS ( ( TickType_t ) (1000 / configTICK_RATE_HZ) ) -#define portBYTE_ALIGNMENT 16 -/*-----------------------------------------------------------*/ -#include "portbenchmark.h" +/* Task function macros as described on the FreeRTOS.org WEB site. */ +#define portTASK_FUNCTION_PROTO(vFunction, pvParameters) void vFunction(void *pvParameters) +#define portTASK_FUNCTION(vFunction, pvParameters) void vFunction(void *pvParameters) -static inline BaseType_t IRAM_ATTR xPortGetCoreID(void) { +// interrupt module will mask interrupt with priority less than threshold +#define RVHAL_EXCM_LEVEL 4 + + + +/* ----------------------------------------------- Port Configurations ------------------------------------------------- + * - Configurations values supplied by each port + * - Required by FreeRTOS + * ------------------------------------------------------------------------------------------------------------------ */ + +#define portCRITICAL_NESTING_IN_TCB 0 +#define portSTACK_GROWTH (-1) +#define portTICK_PERIOD_MS ((TickType_t) (1000 / configTICK_RATE_HZ)) +#define portBYTE_ALIGNMENT 16 +#define portNOP() __asm volatile (" nop ") + + + +/* ---------------------------------------------- Forward Declarations ------------------------------------------------- + * - Forward declarations of all the port functions and macros need to implement the FreeRTOS porting interface + * - These must come before definition/declaration of the FreeRTOS porting interface + * ------------------------------------------------------------------------------------------------------------------ */ + +// --------------------- Interrupts ------------------------ + +/** + * @brief Checks if the current core is in an ISR context + * + * - ISR context consist of Low/Mid priority ISR, or time tick ISR + * - High priority ISRs aren't detected here, but they normally cannot call C code, so that should not be an issue anyway. + * + * @note [refactor-todo] Check if this should be inlined + * @return + * - pdTRUE if in ISR + * - pdFALSE otherwise + */ +BaseType_t xPortInIsrContext(void); + +/** + * @brief Check if in ISR context from High priority ISRs + * + * - Called from High priority ISR + * - Checks if the previous context (before high priority interrupt) was in ISR context (meaning low/med priority) + * + * @note [refactor-todo] Check if this should be inlined + * @return + * - pdTRUE if in previous in ISR context + * - pdFALSE otherwise + */ +BaseType_t xPortInterruptedFromISRContext(void); + +/** + * @brief Disable interrupts in a nested manner + * + * - Cleaner solution allows nested interrupts disabling and restoring via local registers or stack. + * - They can be called from interrupts too. + * - WARNING Only applies to current CPU. + * + * @note [refactor-todo] Define this as portSET_INTERRUPT_MASK_FROM_ISR() instead + * @return unsigned Previous interrupt state + */ +static inline unsigned portENTER_CRITICAL_NESTED(void); + +/* ---------------------- Spinlocks ------------------------ + - Spinlocks added to match API with SMP FreeRTOS. Single core RISC-V does not need spin locks + - Because single core does not have a primitive spinlock data type, we have to implement one here + * @note [refactor-todo] Refactor critical section API so that this is no longer required + * ------------------------------------------------------ */ + +/** + * @brief Spinlock object + * Owner: + * - Set to 0 if uninitialized + * - Set to portMUX_FREE_VAL when free + * - Set to CORE_ID_REGVAL_PRO or CORE_ID_REGVAL_AP when locked + * - Any other value indicates corruption + * Count: + * - 0 if unlocked + * - Recursive count if locked + * + * @note Not a true spinlock as single core RISC-V does not have atomic compare and set instruction + * @note Keep portMUX_INITIALIZER_UNLOCKED in sync with this struct + */ +typedef struct { + uint32_t owner; + uint32_t count; +#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG + const char *lastLockedFn; + int lastLockedLine; +#endif +} portMUX_TYPE; +/**< Spinlock initializer */ +#ifndef CONFIG_FREERTOS_PORTMUX_DEBUG +#define portMUX_INITIALIZER_UNLOCKED { \ + .owner = portMUX_FREE_VAL, \ + .count = 0, \ + } +#else +#define portMUX_INITIALIZER_UNLOCKED { \ + .owner = portMUX_FREE_VAL, \ + .count = 0, \ + .lastLockedFn = "(never locked)", \ + .lastLockedLine = -1 \ + } +#endif /* CONFIG_FREERTOS_PORTMUX_DEBUG */ +#define portMUX_FREE_VAL SPINLOCK_FREE /**< Spinlock is free. [refactor-todo] check if this is still required */ +#define portMUX_NO_TIMEOUT SPINLOCK_WAIT_FOREVER /**< When passed for 'timeout_cycles', spin forever if necessary. [refactor-todo] check if this is still required */ +#define portMUX_TRY_LOCK SPINLOCK_NO_WAIT /**< Try to acquire the spinlock a single time only. [refactor-todo] check if this is still required */ + +/** + * @brief Initialize a spinlock + * + * - Initializes a spinlock that is used by FreeRTOS SMP critical sections + * + * @note [refactor-todo] We can make this inline or consider making it a macro + * @param[in] mux Spinlock + */ +void vPortCPUInitializeMutex(portMUX_TYPE *mux); + +/** + * @brief Acquire a spinlock + * + * @note [refactor-todo] check if we still need this + * @note [refactor-todo] Check if this should be inlined + * @param[in] mux Spinlock + */ +void vPortCPUAcquireMutex(portMUX_TYPE *mux); + +/** + * @brief Acquire a spinlock but with a specified timeout + * + * @note [refactor-todo] Check if we still need this + * @note [refactor-todo] Check if this should be inlined + * @note [refactor-todo] Check if this function should be renamed (due to bool return type) + * @param[in] mux Spinlock + * @param[in] timeout Timeout in number of CPU cycles + * @return true Spinlock acquired + * @return false Timed out + */ +bool vPortCPUAcquireMutexTimeout(portMUX_TYPE *mux, int timeout_cycles); + +/** + * @brief Release a spinlock + * + * @note [refactor-todo] check if we still need this + * @note [refactor-todo] Check if this should be inlined + * @param[in] mux Spinlock + */ +void vPortCPUReleaseMutex(portMUX_TYPE *mux); + +/** + * @brief Wrapper for atomic compare-and-set instruction + * + * @note Isn't a real atomic CAS. + * @note [refactor-todo] check if we still need this + * @note [refactor-todo] Check if this function should be renamed (due to void return type) + * + * @param[inout] addr Pointer to target address + * @param[in] compare Compare value + * @param[inout] set Pointer to set value + */ +static inline void __attribute__((always_inline)) uxPortCompareSet(volatile uint32_t *addr, uint32_t compare, uint32_t *set); + +/** + * @brief Wrapper for atomic compare-and-set instruction in external RAM + * + * @note Isn't a real atomic CAS. + * @note [refactor-todo] check if we still need this + * @note [refactor-todo] Check if this function should be renamed (due to void return type) + * + * @param[inout] addr Pointer to target address + * @param[in] compare Compare value + * @param[inout] set Pointer to set value + */ +static inline void uxPortCompareSetExtram(volatile uint32_t *addr, uint32_t compare, uint32_t *set); + +// ------------------ Critical Sections -------------------- + +/** + * @brief Enter a critical section + * + * - Simply disable interrupts + * - Can be nested + */ +void vPortEnterCritical(void); + +/** + * @brief Exit a critical section + * + * - Reenables interrupts + * - Can be nested + */ +void vPortExitCritical(void); + +// ---------------------- Yielding ------------------------- + +/** + * @brief Set interrupt mask and return current interrupt enable register + * + * @note [refactor-todo] Check if this function should be renamed (due to int return type) + * @return int Current interrupt enable register before set + */ +int vPortSetInterruptMask(void); + +/** + * @brief Clear current interrupt mask and set given mask + * + * @param mask Interrupt mask + */ +void vPortClearInterruptMask(int mask); + +/** + * @brief Perform a context switch from a task + * + * @note [refactor-todo] The rest of ESP-IDF should call taskYield() instead + */ +void vPortYield(void); + +/** + * @brief Perform a context switch from an ISR + */ +void vPortYieldFromISR(void); + +/** + * @brief Yields the other core + * + * @note Added to be compatible with SMP API + * @note [refactor-todo] Put this into private macros as its only called from task.c and is not public API + * @param coreid ID of core to yield + */ +void vPortYieldOtherCore(BaseType_t coreid); + +/** + * @brief Checks if the current core can yield + * + * - A core cannot yield if its in an ISR or in a critical section + * + * @note [refactor-todo] See if this can be separated from port macro + * @note [refactor-todo] Check if this function should be renamed (due to bool return type) + * @return true Core can yield + * @return false Core cannot yield + */ +static inline bool IRAM_ATTR xPortCanYield(void); + +// ------------------- Hook Functions ---------------------- + +extern void esp_vApplicationIdleHook(void); +extern void esp_vApplicationTickHook(void); + +/** + * @brief Hook function called on entry to tickless idle + * + * - Implemented in pm_impl.c + * + * @param xExpectedIdleTime Expected idle time + */ +void vApplicationSleep(TickType_t xExpectedIdleTime); + +// ----------------------- System -------------------------- + +/** + * @brief Get the tick rate per second + * + * @note [refactor-todo] make this inline + * @note [refactor-todo] Check if this function should be renamed (due to uint return type) + * @return uint32_t Tick rate in Hz + */ +uint32_t xPortGetTickRateHz(void); + +/** + * @brief Set a watchpoint to watch the last 32 bytes of the stack + * + * Callback to set a watchpoint on the end of the stack. Called every context switch to change the stack watchpoint + * around. + * + * @param pxStackStart Pointer to the start of the stack + */ +void vPortSetStackWatchpoint(void *pxStackStart); + +/** + * @brief Get the current core's ID + * + * @note Added to be compatible with SMP API + * @note [refactor-todo] IDF should call a FreeRTOS like macro instead of port function directly + * @return BaseType_t Core ID + */ +static inline BaseType_t IRAM_ATTR xPortGetCoreID(void) +{ return cpu_hal_get_core_id(); } -static inline bool IRAM_ATTR xPortCanYield(void) + +/* ------------------------------------------- FreeRTOS Porting Interface ---------------------------------------------- + * - Contains all the mappings of the macros required by FreeRTOS + * - Most come after forward declare as porting macros map to declared functions + * - Maps to forward declared functions + * ------------------------------------------------------------------------------------------------------------------ */ + +// ----------------------- Memory -------------------------- + +/** + * @brief Task memory allocation macros + * + * @note Because the ROM routines don't necessarily handle a stack in external RAM correctly, we force the stack + * memory to always be internal. + * @note [refactor-todo] Update portable.h to match v10.4.3 to use new malloc prototypes + */ +#define portTcbMemoryCaps (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT) +#define portStackMemoryCaps (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT) +#define pvPortMallocTcbMem(size) pvPortMalloc(size) +#define pvPortMallocStackMem(size) pvPortMalloc(size) + +// --------------------- Interrupts ------------------------ + +#define portEXIT_CRITICAL_NESTED(state) do { portCLEAR_INTERRUPT_MASK_FROM_ISR(state);} while(0); +#define portDISABLE_INTERRUPTS() portSET_INTERRUPT_MASK_FROM_ISR() +#define portENABLE_INTERRUPTS() portCLEAR_INTERRUPT_MASK_FROM_ISR(1) +#define portSET_INTERRUPT_MASK_FROM_ISR() vPortSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedStatusValue) vPortClearInterruptMask(uxSavedStatusValue) + +// ------------------ Critical Sections -------------------- + +#define portENTER_CRITICAL(mux) {(void)mux; vPortEnterCritical();} +#define portEXIT_CRITICAL(mux) {(void)mux; vPortExitCritical();} +//In single-core RISC-V, we can use the same critical section API +#define portENTER_CRITICAL_ISR(mux) portENTER_CRITICAL(mux) +#define portEXIT_CRITICAL_ISR(mux) portEXIT_CRITICAL(mux) +/* [refactor-todo] on RISC-V, both ISR and non-ISR cases result in the same call. We can redefine this macro */ +#define portENTER_CRITICAL_SAFE(mux) ({ \ + if (xPortInIsrContext()) { \ + portENTER_CRITICAL_ISR(mux); \ + } else { \ + portENTER_CRITICAL(mux); \ + } \ +}) +#define portEXIT_CRITICAL_SAFE(mux) ({ \ + if (xPortInIsrContext()) { \ + portEXIT_CRITICAL_ISR(mux); \ + } else { \ + portEXIT_CRITICAL(mux); \ + } \ +}) + +// ---------------------- Yielding ------------------------- + +#define portYIELD() vPortYield() +#define portYIELD_FROM_ISR() vPortYieldFromISR() +#define portEND_SWITCHING_ISR(xSwitchRequired) if(xSwitchRequired) vPortYield() +/* Yielding within an API call (when interrupts are off), means the yield should be delayed + until interrupts are re-enabled. + To do this, we use the "cross-core" interrupt as a trigger to yield on this core when interrupts are re-enabled.This + is the same interrupt & code path which is used to trigger a yield between CPUs, although in this case the yield is + happening on the same CPU. +*/ +#define portYIELD_WITHIN_API() portYIELD() + +// ------------------- Hook Functions ---------------------- + +#ifndef CONFIG_FREERTOS_LEGACY_HOOKS +#define vApplicationIdleHook esp_vApplicationIdleHook +#define vApplicationTickHook esp_vApplicationTickHook +#endif /* !CONFIG_FREERTOS_LEGACY_HOOKS */ +#define portSUPPRESS_TICKS_AND_SLEEP(idleTime) vApplicationSleep(idleTime) + +// ------------------- Run Time Stats ---------------------- + +#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() +#define portGET_RUN_TIME_COUNTER_VALUE() 0 +#ifdef CONFIG_FREERTOS_RUN_TIME_STATS_USING_ESP_TIMER +/* Coarse resolution time (us) */ +#define portALT_GET_RUN_TIME_COUNTER_VALUE(x) do {x = (uint32_t)esp_timer_get_time();} while(0) +#endif + + + +/* --------------------------------------------- Inline Implementations ------------------------------------------------ + * - Implementation of inline functions of the forward declares + * - Should come after forward declare and FreeRTOS Porting interface, as implementation may use both. + * - For implementation of non-inlined functions, see port.c, port_common.c, or other assembly files + * ------------------------------------------------------------------------------------------------------------------ */ + +// --------------------- Interrupts ------------------------ + +static inline unsigned portENTER_CRITICAL_NESTED(void) { - uint32_t threshold = REG_READ(INTERRUPT_CORE0_CPU_INT_THRESH_REG); - /* when enter critical code, freertos will mask threshold to RVHAL_EXCM_LEVEL - * and exit critical code, will recover threshold value (1). so threshold <= 1 - * means not in critical code - */ - return (threshold <= 1); + unsigned state = portSET_INTERRUPT_MASK_FROM_ISR(); + return state; +} + +// ---------------------- Spinlocks ------------------------ + +static inline void __attribute__((always_inline)) uxPortCompareSet(volatile uint32_t *addr, uint32_t compare, uint32_t *set) +{ + compare_and_set_native(addr, compare, set); } static inline void uxPortCompareSetExtram(volatile uint32_t *addr, uint32_t compare, uint32_t *set) @@ -116,199 +493,56 @@ static inline void uxPortCompareSetExtram(volatile uint32_t *addr, uint32_t comp #endif } -static inline void __attribute__((always_inline)) uxPortCompareSet(volatile uint32_t *addr, uint32_t compare, uint32_t *set) { - compare_and_set_native(addr, compare, set); +// ---------------------- Yielding ------------------------- + +static inline bool IRAM_ATTR xPortCanYield(void) +{ + uint32_t threshold = REG_READ(INTERRUPT_CORE0_CPU_INT_THRESH_REG); + /* when enter critical code, FreeRTOS will mask threshold to RVHAL_EXCM_LEVEL + * and exit critical code, will recover threshold value (1). so threshold <= 1 + * means not in critical code + */ + return (threshold <= 1); } -#define portCRITICAL_NESTING_IN_TCB 0 -/* - * Send an interrupt to another core in order to make the task running - * on it yield for a higher-priority task. + +/* ------------------------------------------------------ Misc --------------------------------------------------------- + * - Miscellaneous porting macros + * - These are not port of the FreeRTOS porting interface, but are used by other FreeRTOS dependent components + * ------------------------------------------------------------------------------------------------------------------ */ + +// -------------------- Heap Related ----------------------- + +/** + * @brief Checks if a given piece of memory can be used to store a task's TCB + * + * - Defined in port_common.c + * + * @param ptr Pointer to memory + * @return true Memory can be used to store a TCB + * @return false Otherwise */ -void vPortYieldOtherCore( BaseType_t coreid); +bool xPortCheckValidTCBMem(const void *ptr); -/* - Callback to set a watchpoint on the end of the stack. Called every context switch to change the stack - watchpoint around. +/** + * @brief Checks if a given piece of memory can be used to store a task's stack + * + * - Defined in port_common.c + * + * @param ptr Pointer to memory + * @return true Memory can be used to store a task stack + * @return false Otherwise */ -void vPortSetStackWatchpoint( void* pxStackStart ); +bool xPortcheckValidStackMem(const void *ptr); -/* - * Returns true if the current core is in ISR context; low prio ISR, med prio ISR or timer tick ISR. High prio ISRs - * aren't detected here, but they normally cannot call C code, so that should not be an issue anyway. - */ -BaseType_t xPortInIsrContext(void); - -/* - * This function will be called in High prio ISRs. Returns true if the current core was in ISR context - * before calling into high prio ISR context. - */ -BaseType_t xPortInterruptedFromISRContext(void); - -/* "mux" data structure (spinlock) */ -typedef struct { - /* owner field values: - * 0 - Uninitialized (invalid) - * portMUX_FREE_VAL - Mux is free, can be locked by either CPU - * CORE_ID_REGVAL_PRO / CORE_ID_REGVAL_APP - Mux is locked to the particular core - * - * - * Any value other than portMUX_FREE_VAL, CORE_ID_REGVAL_PRO, CORE_ID_REGVAL_APP indicates corruption - */ - uint32_t owner; - /* count field: - * If mux is unlocked, count should be zero. - * If mux is locked, count is non-zero & represents the number of recursive locks on the mux. - */ - uint32_t count; -#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG - const char *lastLockedFn; - int lastLockedLine; -#endif -} portMUX_TYPE; - -#define portMUX_FREE_VAL SPINLOCK_FREE - -/* Special constants for vPortCPUAcquireMutexTimeout() */ -#define portMUX_NO_TIMEOUT SPINLOCK_WAIT_FOREVER /* When passed for 'timeout_cycles', spin forever if necessary */ -#define portMUX_TRY_LOCK SPINLOCK_NO_WAIT /* Try to acquire the spinlock a single time only */ - -// Keep this in sync with the portMUX_TYPE struct definition please. -#ifndef CONFIG_FREERTOS_PORTMUX_DEBUG -#define portMUX_INITIALIZER_UNLOCKED { \ - .owner = portMUX_FREE_VAL, \ - .count = 0, \ - } -#else -#define portMUX_INITIALIZER_UNLOCKED { \ - .owner = portMUX_FREE_VAL, \ - .count = 0, \ - .lastLockedFn = "(never locked)", \ - .lastLockedLine = -1 \ - } -#endif - -/* Scheduler utilities. */ -extern void vPortYield( void ); -extern void vPortYieldFromISR( void ); - -#define portYIELD() vPortYield() -#define portYIELD_FROM_ISR() vPortYieldFromISR() - -/* Yielding within an API call (when interrupts are off), means the yield should be delayed - until interrupts are re-enabled. - To do this, we use the "cross-core" interrupt as a trigger to yield on this core when interrupts are re-enabled.This - is the same interrupt & code path which is used to trigger a yield between CPUs, although in this case the yield is - happening on the same CPU. -*/ -#define portYIELD_WITHIN_API() portYIELD() -/*-----------------------------------------------------------*/ - -/* Critical section management. */ -extern int vPortSetInterruptMask(void); -extern void vPortClearInterruptMask( int ); - -void vPortCPUInitializeMutex(portMUX_TYPE *mux); -void vPortCPUAcquireMutex(portMUX_TYPE *mux); -bool vPortCPUAcquireMutexTimeout(portMUX_TYPE *mux, int timeout_cycles); -void vPortCPUReleaseMutex(portMUX_TYPE *mux); - -extern void vPortEnterCritical( void ); -extern void vPortExitCritical( void ); - -#define portDISABLE_INTERRUPTS() portSET_INTERRUPT_MASK_FROM_ISR() -#define portENABLE_INTERRUPTS() portCLEAR_INTERRUPT_MASK_FROM_ISR(1) - -#define portENTER_CRITICAL(mux) {(void)mux; vPortEnterCritical();} -#define portEXIT_CRITICAL(mux) {(void)mux; vPortExitCritical();} - -#define portENTER_CRITICAL_ISR(mux) portENTER_CRITICAL(mux) -#define portEXIT_CRITICAL_ISR(mux) portEXIT_CRITICAL(mux) - -#define portENTER_CRITICAL_SAFE(mux) do { \ - if (xPortInIsrContext()) { \ - portENTER_CRITICAL_ISR(mux); \ - } else { \ - portENTER_CRITICAL(mux); \ - } \ - } while(0) - -#define portEXIT_CRITICAL_SAFE(mux) do { \ - if (xPortInIsrContext()) { \ - portEXIT_CRITICAL_ISR(mux); \ - } else { \ - portEXIT_CRITICAL(mux); \ - } \ - } while(0) - -/*------------------------------------------------------------*/ -#define portSET_INTERRUPT_MASK_FROM_ISR() vPortSetInterruptMask() -#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) vPortClearInterruptMask( uxSavedStatusValue ) -#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYield() - -// Cleaner solution allows nested interrupts disabling and restoring via local registers or stack. -// They can be called from interrupts too. -static inline unsigned portENTER_CRITICAL_NESTED(void) { - unsigned state = portSET_INTERRUPT_MASK_FROM_ISR(); - return state; -} - -#define portEXIT_CRITICAL_NESTED(state) do { portCLEAR_INTERRUPT_MASK_FROM_ISR( state );} while(0); -/*-----------------------------------------------------------*/ - -//Because the ROM routines don't necessarily handle a stack in external RAM correctly, we force -//the stack memory to always be internal. -#define portTcbMemoryCaps (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT) -#define portStackMemoryCaps (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT) - -#define pvPortMallocTcbMem(size) pvPortMalloc(size) -#define pvPortMallocStackMem(size) pvPortMalloc(size) - -/* Fine resolution time */ -#define portGET_RUN_TIME_COUNTER_VALUE() 0 -#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() - -#ifdef CONFIG_FREERTOS_RUN_TIME_STATS_USING_ESP_TIMER -/* Coarse resolution time (us) */ -#define portALT_GET_RUN_TIME_COUNTER_VALUE(x) do {x = (uint32_t)esp_timer_get_time();} while(0) -#endif - -extern void esp_vApplicationIdleHook( void ); -extern void esp_vApplicationTickHook( void ); - -#ifndef CONFIG_FREERTOS_LEGACY_HOOKS -#define vApplicationIdleHook esp_vApplicationIdleHook -#define vApplicationTickHook esp_vApplicationTickHook -#endif /* !CONFIG_FREERTOS_LEGACY_HOOKS */ - -/* Task function macros as described on the FreeRTOS.org WEB site. */ -#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) -#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) - -void vApplicationSleep( TickType_t xExpectedIdleTime ); -#define portSUPPRESS_TICKS_AND_SLEEP( idleTime ) vApplicationSleep( idleTime ) - -#define portNOP() __asm volatile ( " nop " ) - -#define portVALID_TCB_MEM(ptr) esp_ptr_byte_accessible(ptr) -#define portVALID_STACK_MEM(ptr) esp_ptr_byte_accessible(ptr) - -/* Get tick rate per second */ -uint32_t xPortGetTickRateHz(void); - -// configASSERT_2 if requested -#if configASSERT_2 -#include -void exit(int); -#define configASSERT( x ) if (!(x)) { porttracePrint(-1); printf("\nAssertion failed in %s:%d\n", __FILE__, __LINE__); exit(-1); } -#endif - - -#endif //__ASSEMBLER__ +#define portVALID_TCB_MEM(ptr) xPortCheckValidTCBMem(ptr) +#define portVALID_STACK_MEM(ptr) xPortcheckValidStackMem(ptr) #ifdef __cplusplus } #endif +#endif //__ASSEMBLER__ + #endif /* PORTMACRO_H */ diff --git a/components/freertos/port/riscv/port.c b/components/freertos/port/riscv/port.c index 2f9ada3f57..2ca3972098 100644 --- a/components/freertos/port/riscv/port.c +++ b/components/freertos/port/riscv/port.c @@ -74,30 +74,35 @@ * Implementation of functions defined in portable.h for the RISC-V port. *----------------------------------------------------------------------*/ -#include -#include "FreeRTOS.h" -#include "task.h" -#include "portmacro.h" - #include "sdkconfig.h" - +#include #include "soc/soc_caps.h" #include "soc/periph_defs.h" #include "soc/system_reg.h" #include "hal/systimer_hal.h" #include "hal/systimer_ll.h" - #include "riscv/rvruntime-frames.h" #include "riscv/riscv_interrupts.h" #include "riscv/interrupt.h" - +#include "esp_private/crosscore_int.h" +#include "esp_private/pm_trace.h" +#include "esp_attr.h" #include "esp_system.h" #include "esp_intr_alloc.h" -#include "esp_private/crosscore_int.h" -#include "esp_attr.h" #include "esp_debug_helpers.h" #include "esp_log.h" -#include "esp_private/pm_trace.h" +#include "FreeRTOS.h" /* This pulls in portmacro.h */ +#include "task.h" +#include "portmacro.h" +#include "port_systick.h" + + + +/* ---------------------------------------------------- Variables ------------------------------------------------------ + * + * ------------------------------------------------------------------------------------------------------------------ */ + +static const char *TAG = "cpu_start"; // [refactor-todo]: might be appropriate to change in the future, but /** * @brief A variable is used to keep track of the critical section nesting. @@ -113,56 +118,43 @@ BaseType_t xPortSwitchFlag = 0; __attribute__((aligned(16))) static StackType_t xIsrStack[configISR_STACK_SIZE]; StackType_t *xIsrStackTop = &xIsrStack[0] + (configISR_STACK_SIZE & (~((portPOINTER_SIZE_TYPE)portBYTE_ALIGNMENT_MASK))); -static const char *TAG = "cpu_start"; // [refactor-todo]: might be appropriate to change in the future, but -static void vPortSysTickHandler(void *arg); -static void vPortSetupTimer(void); -static void prvTaskExitError(void); + +/* ------------------------------------------------ FreeRTOS Portable -------------------------------------------------- + * - Provides implementation for functions required by FreeRTOS + * - Declared in portable.h + * ------------------------------------------------------------------------------------------------------------------ */ + +// ----------------- Scheduler Start/End ------------------- extern void esprv_intc_int_set_threshold(int); // FIXME, this function is in ROM only - -void vPortEnterCritical(void) +BaseType_t xPortStartScheduler(void) { - BaseType_t state = portENTER_CRITICAL_NESTED(); - uxCriticalNesting++; + uxInterruptNesting = 0; + uxCriticalNesting = 0; + uxSchedulerRunning = 0; - if (uxCriticalNesting == 1) { - uxSavedInterruptState = state; - } + /* Setup the hardware to generate the tick. */ + vPortSetupTimer(); + + esprv_intc_int_set_threshold(1); /* set global INTC masking level */ + riscv_global_interrupts_enable(); + + vPortYield(); + + /*Should not get here*/ + return pdFALSE; } -void vPortExitCritical(void) +void vPortEndScheduler(void) { - if (uxCriticalNesting > 0) { - uxCriticalNesting--; - if (uxCriticalNesting == 0) { - portEXIT_CRITICAL_NESTED(uxSavedInterruptState); - } - } + /* very unlikely this function will be called, so just trap here */ + abort(); } -/** - * @brief Set up the systimer peripheral to generate the tick interrupt - * - */ -void vPortSetupTimer(void) -{ - /* Systimer HAL layer object */ - static systimer_hal_context_t systimer_hal; - /* set system timer interrupt vector */ - ESP_ERROR_CHECK(esp_intr_alloc(ETS_SYSTIMER_TARGET0_EDGE_INTR_SOURCE, ESP_INTR_FLAG_IRAM, vPortSysTickHandler, &systimer_hal, NULL)); +// ------------------------ Stack -------------------------- - /* configure the timer */ - systimer_hal_init(&systimer_hal); - systimer_hal_connect_alarm_counter(&systimer_hal, SYSTIMER_LL_ALARM_OS_TICK_CORE0, SYSTIMER_LL_COUNTER_OS_TICK); - systimer_hal_enable_counter(&systimer_hal, SYSTIMER_LL_COUNTER_OS_TICK); - systimer_hal_counter_can_stall_by_cpu(&systimer_hal, SYSTIMER_LL_COUNTER_OS_TICK, 0, true); - systimer_hal_set_alarm_period(&systimer_hal, SYSTIMER_LL_ALARM_OS_TICK_CORE0, 1000000UL / CONFIG_FREERTOS_HZ); - systimer_hal_select_alarm_mode(&systimer_hal, SYSTIMER_LL_ALARM_OS_TICK_CORE0, SYSTIMER_ALARM_MODE_PERIOD); - systimer_hal_enable_alarm_int(&systimer_hal, SYSTIMER_LL_ALARM_OS_TICK_CORE0); -} - -void prvTaskExitError(void) +static void prvTaskExitError(void) { /* A function that implements a task must not exit or attempt to return to its caller as there is nothing to return to. If a task wants to exit it @@ -175,57 +167,11 @@ void prvTaskExitError(void) abort(); } -/* Clear current interrupt mask and set given mask */ -void vPortClearInterruptMask(int mask) -{ - REG_WRITE(INTERRUPT_CORE0_CPU_INT_THRESH_REG, mask); - /** - * The delay between the moment we unmask the interrupt threshold register - * and the moment the potential requested interrupt is triggered is not - * null: up to three machine cycles/instructions can be executed. - * - * When compilation size optimization is enabled, this function and its - * callers returning void will have NO epilogue, thus the instruction - * following these calls will be executed. - * - * If the requested interrupt is a context switch to a higher priority - * task then the one currently running, we MUST NOT execute any instruction - * before the interrupt effectively happens. - * In order to prevent this, force this routine to have a 3-instruction - * delay before exiting. - */ - asm volatile ( "nop" ); - asm volatile ( "nop" ); - asm volatile ( "nop" ); -} - -/* Set interrupt mask and return current interrupt enable register */ -int vPortSetInterruptMask(void) -{ - int ret; - unsigned old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE); - ret = REG_READ(INTERRUPT_CORE0_CPU_INT_THRESH_REG); - REG_WRITE(INTERRUPT_CORE0_CPU_INT_THRESH_REG, RVHAL_EXCM_LEVEL); - RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE); - /** - * In theory, this function should not return immediately as there is a - * delay between the moment we mask the interrupt threshold register and - * the moment a potential lower-priority interrupt is triggered (as said - * above), it should have a delay of 2 machine cycles/instructions. - * - * However, in practice, this function has an epilogue of one instruction, - * thus the instruction masking the interrupt threshold register is - * followed by two instructions: `ret` and `csrrs` (RV_SET_CSR). - * That's why we don't need any additional nop instructions here. - */ - return ret; -} - StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters) { extern uint32_t __global_pointer$; - uint8_t* task_thread_local_start; - uint8_t* threadptr; + uint8_t *task_thread_local_start; + uint8_t *threadptr; extern char _thread_local_start, _thread_local_end, _flash_rodata_start; /* Byte pointer, so that subsequent calculations don't depend on sizeof(StackType_t). */ @@ -293,100 +239,13 @@ StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxC return (StackType_t *)frame; } -IRAM_ATTR void vPortSysTickHandler(void *arg) -{ - systimer_hal_context_t *systimer_hal = (systimer_hal_context_t *)arg; - systimer_ll_clear_alarm_int(systimer_hal->dev, SYSTIMER_LL_ALARM_OS_TICK_CORE0); -#ifdef CONFIG_PM_TRACE - ESP_PM_TRACE_ENTER(TICK, xPortGetCoreID()); -#endif +/* ---------------------------------------------- Port Implementations ------------------------------------------------- + * + * ------------------------------------------------------------------------------------------------------------------ */ - if (!uxSchedulerRunning) { - return; - } - - if (xTaskIncrementTick() != pdFALSE) { - vPortYieldFromISR(); - } - -#ifdef CONFIG_PM_TRACE - ESP_PM_TRACE_EXIT(TICK, xPortGetCoreID()); -#endif -} - -BaseType_t xPortStartScheduler(void) -{ - uxInterruptNesting = 0; - uxCriticalNesting = 0; - uxSchedulerRunning = 0; - - vPortSetupTimer(); - - esprv_intc_int_set_threshold(1); /* set global INTC masking level */ - riscv_global_interrupts_enable(); - - vPortYield(); - - /*Should not get here*/ - return pdFALSE; -} - -void vPortEndScheduler(void) -{ - /* very unlikely this function will be called, so just trap here */ - abort(); -} - -void vPortYieldOtherCore(BaseType_t coreid) -{ - esp_crosscore_int_send_yield(coreid); -} - -void vPortYieldFromISR( void ) -{ - traceISR_EXIT_TO_SCHEDULER(); - uxSchedulerRunning = 1; - xPortSwitchFlag = 1; -} - -void vPortYield(void) -{ - if (uxInterruptNesting) { - vPortYieldFromISR(); - } else { - - esp_crosscore_int_send_yield(0); - /* There are 3-4 instructions of latency between triggering the software - interrupt and the CPU interrupt happening. Make sure it happened before - we return, otherwise vTaskDelay() may return and execute 1-2 - instructions before the delay actually happens. - - (We could use the WFI instruction here, but there is a chance that - the interrupt will happen while evaluating the other two conditions - for an instant yield, and if that happens then the WFI would be - waiting for the next interrupt to occur...) - */ - while (uxSchedulerRunning && uxCriticalNesting == 0 && REG_READ(SYSTEM_CPU_INTR_FROM_CPU_0_REG) != 0) {} - } - -} - -#define STACK_WATCH_AREA_SIZE 32 -#define STACK_WATCH_POINT_NUMBER (SOC_CPU_WATCHPOINTS_NUM - 1) - -void vPortSetStackWatchpoint(void *pxStackStart) -{ - uint32_t addr = (uint32_t)pxStackStart; - addr = (addr + (STACK_WATCH_AREA_SIZE - 1)) & (~(STACK_WATCH_AREA_SIZE - 1)); - esp_cpu_set_watchpoint(STACK_WATCH_POINT_NUMBER, (char *)addr, STACK_WATCH_AREA_SIZE, ESP_WATCHPOINT_STORE); -} - -uint32_t xPortGetTickRateHz(void) -{ - return (uint32_t)configTICK_RATE_HZ; -} +// --------------------- Interrupts ------------------------ BaseType_t xPortInIsrContext(void) { @@ -399,6 +258,7 @@ BaseType_t IRAM_ATTR xPortInterruptedFromISRContext(void) return uxInterruptNesting; } +// ---------------------- Spinlocks ------------------------ void vPortCPUInitializeMutex(portMUX_TYPE *mux) { @@ -422,6 +282,109 @@ void vPortCPUReleaseMutex(portMUX_TYPE *mux) (void)mux; //TODO: IDF-2393 } +// ------------------ Critical Sections -------------------- + +void vPortEnterCritical(void) +{ + BaseType_t state = portENTER_CRITICAL_NESTED(); + uxCriticalNesting++; + + if (uxCriticalNesting == 1) { + uxSavedInterruptState = state; + } +} + +void vPortExitCritical(void) +{ + if (uxCriticalNesting > 0) { + uxCriticalNesting--; + if (uxCriticalNesting == 0) { + portEXIT_CRITICAL_NESTED(uxSavedInterruptState); + } + } +} + +// ---------------------- Yielding ------------------------- + +int vPortSetInterruptMask(void) +{ + int ret; + unsigned old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE); + ret = REG_READ(INTERRUPT_CORE0_CPU_INT_THRESH_REG); + REG_WRITE(INTERRUPT_CORE0_CPU_INT_THRESH_REG, RVHAL_EXCM_LEVEL); + RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE); + /** + * In theory, this function should not return immediately as there is a + * delay between the moment we mask the interrupt threshold register and + * the moment a potential lower-priority interrupt is triggered (as said + * above), it should have a delay of 2 machine cycles/instructions. + * + * However, in practice, this function has an epilogue of one instruction, + * thus the instruction masking the interrupt threshold register is + * followed by two instructions: `ret` and `csrrs` (RV_SET_CSR). + * That's why we don't need any additional nop instructions here. + */ + return ret; +} + +void vPortClearInterruptMask(int mask) +{ + REG_WRITE(INTERRUPT_CORE0_CPU_INT_THRESH_REG, mask); + /** + * The delay between the moment we unmask the interrupt threshold register + * and the moment the potential requested interrupt is triggered is not + * null: up to three machine cycles/instructions can be executed. + * + * When compilation size optimization is enabled, this function and its + * callers returning void will have NO epilogue, thus the instruction + * following these calls will be executed. + * + * If the requested interrupt is a context switch to a higher priority + * task then the one currently running, we MUST NOT execute any instruction + * before the interrupt effectively happens. + * In order to prevent this, force this routine to have a 3-instruction + * delay before exiting. + */ + asm volatile ( "nop" ); + asm volatile ( "nop" ); + asm volatile ( "nop" ); +} + +void vPortYield(void) +{ + if (uxInterruptNesting) { + vPortYieldFromISR(); + } else { + + esp_crosscore_int_send_yield(0); + /* There are 3-4 instructions of latency between triggering the software + interrupt and the CPU interrupt happening. Make sure it happened before + we return, otherwise vTaskDelay() may return and execute 1-2 + instructions before the delay actually happens. + + (We could use the WFI instruction here, but there is a chance that + the interrupt will happen while evaluating the other two conditions + for an instant yield, and if that happens then the WFI would be + waiting for the next interrupt to occur...) + */ + while (uxSchedulerRunning && uxCriticalNesting == 0 && REG_READ(SYSTEM_CPU_INTR_FROM_CPU_0_REG) != 0) {} + } +} + +void vPortYieldFromISR( void ) +{ + traceISR_EXIT_TO_SCHEDULER(); + uxSchedulerRunning = 1; + xPortSwitchFlag = 1; +} + +void vPortYieldOtherCore(BaseType_t coreid) +{ + esp_crosscore_int_send_yield(coreid); +} + +// ------------------- Hook Functions ---------------------- + void __attribute__((weak)) vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName) { #define ERR_STR1 "***ERROR*** A stack overflow in task " @@ -437,6 +400,32 @@ void __attribute__((weak)) vApplicationStackOverflowHook(TaskHandle_t xTask, cha esp_system_abort(buf); } +// ----------------------- System -------------------------- + +uint32_t xPortGetTickRateHz(void) +{ + return (uint32_t)configTICK_RATE_HZ; +} + +#define STACK_WATCH_AREA_SIZE 32 +#define STACK_WATCH_POINT_NUMBER (SOC_CPU_WATCHPOINTS_NUM - 1) + +void vPortSetStackWatchpoint(void *pxStackStart) +{ + uint32_t addr = (uint32_t)pxStackStart; + addr = (addr + (STACK_WATCH_AREA_SIZE - 1)) & (~(STACK_WATCH_AREA_SIZE - 1)); + esp_cpu_set_watchpoint(STACK_WATCH_POINT_NUMBER, (char *)addr, STACK_WATCH_AREA_SIZE, ESP_WATCHPOINT_STORE); +} + + + +/* ---------------------------------------------- Misc Implementations ------------------------------------------------- + * + * ------------------------------------------------------------------------------------------------------------------ */ + +// --------------------- App Start-up ---------------------- + +/* [refactor-todo]: See if we can include this through a header */ extern void esp_startup_start_app_common(void); void esp_startup_start_app(void) diff --git a/components/freertos/port/xtensa/include/freertos/FreeRTOSConfig.h b/components/freertos/port/xtensa/include/freertos/FreeRTOSConfig_arch.h similarity index 100% rename from components/freertos/port/xtensa/include/freertos/FreeRTOSConfig.h rename to components/freertos/port/xtensa/include/freertos/FreeRTOSConfig_arch.h diff --git a/components/freertos/port/xtensa/include/freertos/portmacro.h b/components/freertos/port/xtensa/include/freertos/portmacro.h index eeabdf786a..f1520b70c2 100644 --- a/components/freertos/port/xtensa/include/freertos/portmacro.h +++ b/components/freertos/port/xtensa/include/freertos/portmacro.h @@ -1,5 +1,5 @@ /* - * FreeRTOS Kernel V10.2.1 + * FreeRTOS Kernel V10.4.3 * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of @@ -24,129 +24,520 @@ * * 1 tab == 4 spaces! */ + #ifndef PORTMACRO_H #define PORTMACRO_H +#ifndef __ASSEMBLER__ + +#include "sdkconfig.h" +#include +#include +#include +#include +#include +#include /* required for xthal_get_ccount. [refactor-todo] use cpu_hal instead */ +#include /* required for XTOS_SET_INTLEVEL. [refactor-todo] add common intr functions to esp_hw_support */ +#include "xt_instr_macros.h" +#include "soc/spinlock.h" +#include "hal/cpu_hal.h" +#include "esp_private/crosscore_int.h" +#include "esp_attr.h" +#include "esp_timer.h" /* required for esp_timer_get_time. [refactor-todo] make this common between archs */ +#include "esp_newlib.h" /* required for esp_reent_init() in tasks.c */ +#include "esp_heap_caps.h" +#include "esp_rom_sys.h" +#include "esp_system.h" /* required by esp_get_...() functions in portable.h. [refactor-todo] Update portable.h */ +#include "portbenchmark.h" + +/* [refactor-todo] These includes are not directly used in this file. They are kept into to prevent a breaking change. Remove these. */ +#include +#include +#include +#include "soc/cpu.h" +#ifdef CONFIG_LEGACY_INCLUDE_COMMON_HEADERS +#include "soc/soc_memory_layout.h" +#endif + #ifdef __cplusplus extern "C" { #endif -#ifndef __ASSEMBLER__ -#include -#include -#include -#include -#include -#include -#include -#include /* required for XSHAL_CLIB */ -#include -#include "esp_private/crosscore_int.h" -#include "esp_timer.h" /* required for FreeRTOS run time stats */ -#include "esp_system.h" -#include "esp_newlib.h" -#include "soc/spinlock.h" -#include -#include "esp_rom_sys.h" -#include "sdkconfig.h" -#include "freertos/xtensa_api.h" -#include "esp_system.h" -#include "soc/cpu.h" -#include -#ifdef CONFIG_LEGACY_INCLUDE_COMMON_HEADERS -#include "soc/soc_memory_layout.h" -#endif +/* --------------------------------------------------- Port Types ------------------------------------------------------ + * - Port specific types. + * - The settings in this file configure FreeRTOS correctly for the given hardware and compiler. + * - These settings should not be altered. + * - The port types must come before first as they are used further down the file + * ------------------------------------------------------------------------------------------------------------------ */ -/*----------------------------------------------------------- - * Port specific definitions. - * - * The settings in this file configure FreeRTOS correctly for the - * given hardware and compiler. - * - * These settings should not be altered. - *----------------------------------------------------------- - */ +#define portCHAR int8_t +#define portFLOAT float +#define portDOUBLE double +#define portLONG int32_t +#define portSHORT int16_t +#define portSTACK_TYPE uint8_t +#define portBASE_TYPE int -#include "esp_system.h" -#include "hal/cpu_hal.h" -#include "xt_instr_macros.h" - -/* Type definitions. */ -#define portCHAR int8_t -#define portFLOAT float -#define portDOUBLE double -#define portLONG int32_t -#define portSHORT int16_t -#define portSTACK_TYPE uint8_t -#define portBASE_TYPE int - -typedef portSTACK_TYPE StackType_t; -typedef portBASE_TYPE BaseType_t; -typedef unsigned portBASE_TYPE UBaseType_t; +typedef portSTACK_TYPE StackType_t; +typedef portBASE_TYPE BaseType_t; +typedef unsigned portBASE_TYPE UBaseType_t; #if( configUSE_16_BIT_TICKS == 1 ) - typedef uint16_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffff +typedef uint16_t TickType_t; +#define portMAX_DELAY ( TickType_t ) 0xffff #else - typedef uint32_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +typedef uint32_t TickType_t; +#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #endif -/*-----------------------------------------------------------*/ -// portbenchmark -#include "portbenchmark.h" +/* Task function macros as described on the FreeRTOS.org WEB site. */ +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) -#include "sdkconfig.h" -#include "esp_attr.h" -#include "portmacro_priv.h" -// Cleaner solution allows nested interrupts disabling and restoring via local registers or stack. -// They can be called from interrupts too. -// WARNING: Only applies to current CPU. See notes above. -static inline unsigned portENTER_CRITICAL_NESTED(void) { - unsigned state = XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL); - portbenchmarkINTERRUPT_DISABLE(); - return state; -} -#define portEXIT_CRITICAL_NESTED(state) do { portbenchmarkINTERRUPT_RESTORE(state); XTOS_RESTORE_JUST_INTLEVEL(state); } while (0) -/* -Modifications to portENTER_CRITICAL. +/* ----------------------------------------------- Port Configurations ------------------------------------------------- + * - Configurations values supplied by each port + * - Required by FreeRTOS + * ------------------------------------------------------------------------------------------------------------------ */ -For an introduction, see "Critical Sections & Disabling Interrupts" in docs/api-guides/freertos-smp.rst +#define portCRITICAL_NESTING_IN_TCB 0 +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 4 +#define portNOP() XT_NOP() -The original portENTER_CRITICAL only disabled the ISRs. This is enough for single-CPU operation: by -disabling the interrupts, there is no task switch so no other tasks can meddle in the data, and because -interrupts are disabled, ISRs can't corrupt data structures either. -For multiprocessing, things get a bit more hairy. First of all, disabling the interrupts doesn't stop -the tasks or ISRs on the other processors meddling with our CPU. For tasks, this is solved by adding -a spinlock to the portENTER_CRITICAL macro. A task running on the other CPU accessing the same data will -spinlock in the portENTER_CRITICAL code until the first CPU is done. -For ISRs, we now also need muxes: while portENTER_CRITICAL disabling interrupts will stop ISRs on the same -CPU from meddling with the data, it does not stop interrupts on the other cores from interfering with the -data. For this, we also use a spinlock in the routines called by the ISR, but these spinlocks -do not disable the interrupts (because they already are). +/* ---------------------------------------------- Forward Declarations ------------------------------------------------- + * - Forward declarations of all the port functions and macros need to implement the FreeRTOS porting interface + * - These must come before definition/declaration of the FreeRTOS porting interface + * ------------------------------------------------------------------------------------------------------------------ */ -This all assumes that interrupts are either entirely disabled or enabled. Interrupt priority levels -will break this scheme. +// --------------------- Interrupts ------------------------ -Remark: For the ESP32, portENTER_CRITICAL and portENTER_CRITICAL_ISR both alias vPortEnterCritical, meaning -that either function can be called both from ISR as well as task context. This is not standard FreeRTOS -behaviour; please keep this in mind if you need any compatibility with other FreeRTOS implementations. +/** + * @brief Checks if the current core is in an ISR context + * + * - ISR context consist of Low/Mid priority ISR, or time tick ISR + * - High priority ISRs aren't detected here, but they normally cannot call C code, so that should not be an issue anyway. + * + * @note [refactor-todo] Check if this should be inlined + * @return + * - pdTRUE if in ISR + * - pdFALSE otherwise + */ +BaseType_t xPortInIsrContext(void); + +/** + * @brief Asserts if in ISR context + * + * - Asserts on xPortInIsrContext() internally + * + * @note [refactor-todo] Check if this API is still required + * @note [refactor-todo] Check if this should be inlined + */ +void vPortAssertIfInISR(void); + +/** + * @brief Check if in ISR context from High priority ISRs + * + * - Called from High priority ISR + * - Checks if the previous context (before high priority interrupt) was in ISR context (meaning low/med priority) + * + * @note [refactor-todo] Check if this should be inlined + * @return + * - pdTRUE if in previous in ISR context + * - pdFALSE otherwise + */ +BaseType_t xPortInterruptedFromISRContext(void); + +/** + * @brief Disable interrupts in a nested manner + * + * - Cleaner solution allows nested interrupts disabling and restoring via local registers or stack. + * - They can be called from interrupts too. + * - WARNING Only applies to current CPU. + * @note [refactor-todo] Define this as portSET_INTERRUPT_MASK_FROM_ISR() instead + * @return unsigned Previous interrupt state + */ +static inline unsigned __attribute__((always_inline)) portENTER_CRITICAL_NESTED(void); + +/* ---------------------- Spinlocks ------------------------ + * - Modifications made to critical sections to support SMP + * - See "Critical Sections & Disabling Interrupts" in docs/api-guides/freertos-smp.rst for more details + * - Remark: For the ESP32, portENTER_CRITICAL and portENTER_CRITICAL_ISR both alias vPortEnterCritical, meaning that + * either function can be called both from ISR as well as task context. This is not standard FreeRTOS + * behaviorr; please keep this in mind if you need any compatibility with other FreeRTOS implementations. + * @note [refactor-todo] Check if these comments are still true + * ------------------------------------------------------ */ + +typedef spinlock_t portMUX_TYPE; /**< Spinlock type used by FreeRTOS critical sections */ +#define portMUX_INITIALIZER_UNLOCKED SPINLOCK_INITIALIZER /**< Spinlock initializer */ +#define portMUX_FREE_VAL SPINLOCK_FREE /**< Spinlock is free. [refactor-todo] check if this is still required */ +#define portMUX_NO_TIMEOUT SPINLOCK_WAIT_FOREVER /**< When passed for 'timeout_cycles', spin forever if necessary. [refactor-todo] check if this is still required */ +#define portMUX_TRY_LOCK SPINLOCK_NO_WAIT /**< Try to acquire the spinlock a single time only. [refactor-todo] check if this is still required */ + +/** + * @brief Initialize a spinlock + * + * - Initializes a spinlock that is used by FreeRTOS SMP critical sections + * + * @param[in] mux Spinlock + */ +static inline void __attribute__((always_inline)) vPortCPUInitializeMutex(portMUX_TYPE *mux); + +/** + * @brief Acquire a spinlock + * + * @note [refactor-todo] check if we still need this + * + * @param[in] mux Spinlock + */ +static inline void __attribute__((always_inline)) vPortCPUAcquireMutex(portMUX_TYPE *mux); + +/** + * @brief Acquire a spinlock but with a specified timeout + * + * @note [refactor-todo] check if we still need this + * @note [refactor-todo] Check if this function should be renamed (due to bool return type) + * + * @param[in] mux Spinlock + * @param timeout + * @return true Spinlock acquired + * @return false Timed out + */ +static inline bool __attribute__((always_inline)) vPortCPUAcquireMutexTimeout(portMUX_TYPE *mux, int timeout); + +/** + * @brief Release a spinlock + * + * @note [refactor-todo] check if we still need this + * + * @param[in] mux Spinlock + */ +static inline void __attribute__((always_inline)) vPortCPUReleaseMutex(portMUX_TYPE *mux); + +/** + * @brief Wrapper for atomic compare-and-set instruction + * + * This subroutine will atomically compare *addr to 'compare'. If *addr == compare, *addr is set to *set. *set is + * updated with the previous value of *addr (either 'compare' or some other value.) + * + * @warning From the ISA docs: in some (unspecified) cases, the s32c1i instruction may return the "bitwise inverse" of + * the old mem if the mem wasn't written. This doesn't seem to happen on the ESP32 (portMUX assertions would + * fail). + * + * @note [refactor-todo] check if we still need this + * @note [refactor-todo] Check if this function should be renamed (due to void return type) + * + * @param[inout] addr Pointer to target address + * @param[in] compare Compare value + * @param[inout] set Pointer to set value + */ +static inline void __attribute__((always_inline)) uxPortCompareSet(volatile uint32_t *addr, uint32_t compare, uint32_t *set); + +/** + * @brief Wrapper for atomic compare-and-set instruction in external RAM + * + * Atomic compare-and-set but the target address is placed in external RAM + * + * @note [refactor-todo] check if we still need this + * + * @param[inout] addr Pointer to target address + * @param[in] compare Compare value + * @param[inout] set Pointer to set value + */ +static inline void uxPortCompareSetExtram(volatile uint32_t *addr, uint32_t compare, uint32_t *set); + +// ------------------ Critical Sections -------------------- + +/** + * @brief Enter a SMP critical section + * + * - Disable interrupts + * - Takes spinlock + * - Can be nested + * + * @param[in] mux Spinlock + */ +void vPortEnterCritical(portMUX_TYPE *mux); + +/** + * @brief Exit a SMP critical section + * + * - Releases spinlock + * - Reenables interrupts + * - Can be nested + * + * @param[in] mux Spinlock + */ +void vPortExitCritical(portMUX_TYPE *mux); + +/** + * @brief FreeRTOS compliant version of enter critical + * + * - Ensures that critical section is only entered from task context + * + * @param[in] mux Spinlock + */ +static inline void __attribute__((always_inline)) vPortEnterCriticalCompliance(portMUX_TYPE *mux); + +/** + * @brief FreeRTOS compliant version of exit critical + * + * @param[in] mux Spinlock + */ +static inline void __attribute__((always_inline)) vPortExitCriticalCompliance(portMUX_TYPE *mux); + +/** + * @brief Safe version of enter critical + * + * - This function can be used to enter a critical section from both task and ISR contexts + * + * @param[in] mux Spinlock + */ +static inline void __attribute__((always_inline)) vPortEnterCriticalSafe(portMUX_TYPE *mux); + +/** + * @brief Safe version of exit critical + * + * @param[in] mux Spinlock + */ +static inline void __attribute__((always_inline)) vPortExitCriticalSafe(portMUX_TYPE *mux); + +// ---------------------- Yielding ------------------------- + +/** + * @brief Perform a solicited context switch + * + * - Defined in portasm.S + * + * @note [refactor-todo] The rest of ESP-IDF should call taskYield() instead + */ +void vPortYield( void ); + +/** + * @brief + * + * @note [refactor-todo] Refactor this to avoid va_args + * @param argc + * @param ... Variable arguments to allow for IDF prototype without arguments, and vanilla version WITH argument + */ +void vPortEvaluateYieldFromISR(int argc, ...); + +/** + * @brief Yields the other core + * + * - Send an interrupt to another core in order to make the task running on it yield for a higher-priority task. + * - Can be used to yield current core as well + * + * @note [refactor-todo] Put this into private macros as its only called from task.c and is not public API + * @param coreid ID of core to yield + */ +void vPortYieldOtherCore(BaseType_t coreid); + +/** + * @brief Checks if the current core can yield + * + * - A core cannot yield if its in an ISR or in a critical section + * + * @note [refactor-todo] See if this can be separated from port macro + * @return true Core can yield + * @return false Core cannot yield + */ +static inline bool IRAM_ATTR xPortCanYield(void); + +// ------------------- Hook Functions ---------------------- + +extern void esp_vApplicationIdleHook(void); /* Required by tasks.c */ +extern void esp_vApplicationTickHook(void); /* Required by tasks.c */ + +/** + * @brief Hook function called on entry to tickless idle + * + * - Implemented in pm_impl.c + * + * @param xExpectedIdleTime Expected idle time + */ +void vApplicationSleep(TickType_t xExpectedIdleTime); + +// ----------------------- System -------------------------- + +/** + * @brief Get the tick rate per second + * + * @note [refactor-todo] make this inline + * @return uint32_t Tick rate in Hz + */ +uint32_t xPortGetTickRateHz(void); + +/** + * @brief Set a watchpoint to watch the last 32 bytes of the stack + * + * Callback to set a watchpoint on the end of the stack. Called every context switch to change the stack watchpoint + * around. + * + * @param pxStackStart Pointer to the start of the stack + */ +void vPortSetStackWatchpoint( void *pxStackStart ); + +/** + * @brief Get the current core's ID + * + * @note [refactor-todo] IDF should call a FreeRTOS like macro instead of port function directly + * @return BaseType_t Core ID + */ +static inline BaseType_t IRAM_ATTR xPortGetCoreID(void); + + + +/* ------------------------------------------- FreeRTOS Porting Interface ---------------------------------------------- + * - Contains all the mappings of the macros required by FreeRTOS + * - Most come after forward declare as porting macros map to declared functions + * - Maps to forward declared functions + * ------------------------------------------------------------------------------------------------------------------ */ + +// ----------------------- Memory -------------------------- + +/** + * @brief Task memory allocation macros + * + * @note Because the ROM routines don't necessarily handle a stack in external RAM correctly, we force the stack + * memory to always be internal. + * @note [refactor-todo] Update portable.h to match v10.4.3 to use new malloc prototypes + */ +#define portTcbMemoryCaps (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT) +#define portStackMemoryCaps (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT) +#define pvPortMallocTcbMem(size) heap_caps_malloc(size, portTcbMemoryCaps) +#define pvPortMallocStackMem(size) heap_caps_malloc(size, portStackMemoryCaps) + +// --------------------- Interrupts ------------------------ + +#define portEXIT_CRITICAL_NESTED(state) do { portbenchmarkINTERRUPT_RESTORE(state); XTOS_RESTORE_JUST_INTLEVEL(state); } while (0) + +/** + * - Only applies to current core + * - These cannot be nested. They should be used with a lot of care and cannot be called from interrupt level. + * + * @note [refactor-todo] replace XTOS_SET_INTLEVEL with more efficient version, if any? + */ +#define portDISABLE_INTERRUPTS() do { XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL); portbenchmarkINTERRUPT_DISABLE(); } while (0) +#define portENABLE_INTERRUPTS() do { portbenchmarkINTERRUPT_RESTORE(0); XTOS_SET_INTLEVEL(0); } while (0) + +/** + * ISR versions to enable/disable interrupts + */ +#define portSET_INTERRUPT_MASK_FROM_ISR() portENTER_CRITICAL_NESTED() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR(state) portEXIT_CRITICAL_NESTED(state) + +#define portASSERT_IF_IN_ISR() vPortAssertIfInISR() + +// ------------------ Critical Sections -------------------- + +/** + * @brief FreeRTOS critical section macros + * + * - Added a spinlock argument for SMP + * - Can be nested + * - Compliance versions will assert if regular critical section API is used in ISR context + * - Safe versions can be called from either contexts + */ +#ifdef CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE +#define portENTER_CRITICAL(mux) vPortEnterCriticalCompliance(mux) +#define portEXIT_CRITICAL(mux) vPortExitCriticalCompliance(mux) +#else +#define portENTER_CRITICAL(mux) vPortEnterCritical(mux) +#define portEXIT_CRITICAL(mux) vPortExitCritical(mux) +#endif /* CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE */ +#define portENTER_CRITICAL_ISR(mux) vPortEnterCritical(mux) +#define portEXIT_CRITICAL_ISR(mux) vPortExitCritical(mux) +#define portENTER_CRITICAL_SAFE(mux) vPortEnterCriticalSafe(mux) +#define portEXIT_CRITICAL_SAFE(mux) vPortExitCriticalSafe(mux) + +// ---------------------- Yielding ------------------------- + +#define portYIELD() vPortYield() + +/** + * @note The macro below could be used when passing a single argument, or without any argument, + * it was developed to support both usages of portYIELD inside of an ISR. Any other usage form + * might result in undesired behavior + * + * @note [refactor-todo] Refactor this to avoid va_args + */ +#if defined(__cplusplus) && (__cplusplus > 201703L) +#define portYIELD_FROM_ISR(...) vPortEvaluateYieldFromISR(portGET_ARGUMENT_COUNT(__VA_ARGS__) __VA_OPT__(,) __VA_ARGS__) +#else +#define portYIELD_FROM_ISR(...) vPortEvaluateYieldFromISR(portGET_ARGUMENT_COUNT(__VA_ARGS__), ##__VA_ARGS__) +#endif + +/* Yielding within an API call (when interrupts are off), means the yield should be delayed + until interrupts are re-enabled. + + To do this, we use the "cross-core" interrupt as a trigger to yield on this core when interrupts are re-enabled.This + is the same interrupt & code path which is used to trigger a yield between CPUs, although in this case the yield is + happening on the same CPU. */ -/* "mux" data structure (spinlock) */ -typedef spinlock_t portMUX_TYPE; +#define portYIELD_WITHIN_API() esp_crosscore_int_send_yield(xPortGetCoreID()) -#define portMUX_FREE_VAL SPINLOCK_FREE -#define portMUX_NO_TIMEOUT SPINLOCK_WAIT_FOREVER /* When passed for 'timeout_cycles', spin forever if necessary */ -#define portMUX_TRY_LOCK SPINLOCK_NO_WAIT /* Try to acquire the spinlock a single time only */ -#define portMUX_INITIALIZER_UNLOCKED SPINLOCK_INITIALIZER +// ------------------- Hook Functions ---------------------- -#define portCRITICAL_NESTING_IN_TCB 0 +#ifndef CONFIG_FREERTOS_LEGACY_HOOKS +#define vApplicationIdleHook esp_vApplicationIdleHook +#define vApplicationTickHook esp_vApplicationTickHook +#endif /* !CONFIG_FREERTOS_LEGACY_HOOKS */ + +#define portSUPPRESS_TICKS_AND_SLEEP(idleTime) vApplicationSleep(idleTime) + +// ------------------- Run Time Stats ---------------------- + +#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() + +/** + * - Fine resolution uses ccount + * - ALT is coarse and uses esp_timer + * @note [refactor-todo] Make fine and alt timers mutually exclusive + */ +#define portGET_RUN_TIME_COUNTER_VALUE() xthal_get_ccount() +#ifdef CONFIG_FREERTOS_RUN_TIME_STATS_USING_ESP_TIMER +#define portALT_GET_RUN_TIME_COUNTER_VALUE(x) do {x = (uint32_t)esp_timer_get_time();} while(0) +#endif + +// -------------- Optimized Task Selection ----------------- + +#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 +/* Check the configuration. */ +#if( configMAX_PRIORITIES > 32 ) +#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 different priorities as tasks that share a priority will time slice. +#endif + +/* Store/clear the ready priorities in a bit map. */ +#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) +#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) +#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __builtin_clz( ( uxReadyPriorities ) ) ) +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ + + + +/* --------------------------------------------- Inline Implementations ------------------------------------------------ + * - Implementation of inline functions of the forward declares + * - Should come after forward declare and FreeRTOS Porting interface, as implementation may use both. + * - For implementation of non-inlined functions, see port.c + * ------------------------------------------------------------------------------------------------------------------ */ + +// --------------------- Interrupts ------------------------ + +static inline unsigned portENTER_CRITICAL_NESTED(void) +{ + unsigned state = XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL); + portbenchmarkINTERRUPT_DISABLE(); + return state; +} + +// ---------------------- Spinlocks ------------------------ static inline void __attribute__((always_inline)) vPortCPUInitializeMutex(portMUX_TYPE *mux) { @@ -168,21 +559,23 @@ static inline void __attribute__((always_inline)) vPortCPUReleaseMutex(portMUX_T spinlock_release(mux); } -void vPortEnterCritical(portMUX_TYPE *mux); -void vPortExitCritical(portMUX_TYPE *mux); +static inline void __attribute__((always_inline)) uxPortCompareSet(volatile uint32_t *addr, uint32_t compare, uint32_t *set) +{ + compare_and_set_native(addr, compare, set); +} -#define portASSERT_IF_IN_ISR() vPortAssertIfInISR() -void vPortAssertIfInISR(void); +static inline void uxPortCompareSetExtram(volatile uint32_t *addr, uint32_t compare, uint32_t *set) +{ +#ifdef CONFIG_SPIRAM + compare_and_set_extram(addr, compare, set); +#endif +} -/* - * Returns true if the current core is in ISR context; low prio ISR, med prio ISR or timer tick ISR. High prio ISRs - * aren't detected here, but they normally cannot call C code, so that should not be an issue anyway. - */ -BaseType_t xPortInIsrContext(void); +// ------------------ Critical Sections -------------------- static inline void __attribute__((always_inline)) vPortEnterCriticalCompliance(portMUX_TYPE *mux) { - if(!xPortInIsrContext()) { + if (!xPortInIsrContext()) { vPortEnterCritical(mux); } else { esp_rom_printf("%s:%d (%s)- port*_CRITICAL called from ISR context!\n", @@ -193,7 +586,7 @@ static inline void __attribute__((always_inline)) vPortEnterCriticalCompliance(p static inline void __attribute__((always_inline)) vPortExitCriticalCompliance(portMUX_TYPE *mux) { - if(!xPortInIsrContext()) { + if (!xPortInIsrContext()) { vPortExitCritical(mux); } else { esp_rom_printf("%s:%d (%s)- port*_CRITICAL called from ISR context!\n", @@ -202,20 +595,6 @@ static inline void __attribute__((always_inline)) vPortExitCriticalCompliance(po } } -#ifdef CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE -/* Calling port*_CRITICAL from ISR context would cause an assert failure. - * If the parent function is called from both ISR and Non-ISR context then call port*_CRITICAL_SAFE - */ -#define portENTER_CRITICAL(mux) vPortEnterCriticalCompliance(mux) -#define portEXIT_CRITICAL(mux) vPortExitCriticalCompliance(mux) -#else -#define portENTER_CRITICAL(mux) vPortEnterCritical(mux) -#define portEXIT_CRITICAL(mux) vPortExitCritical(mux) -#endif - -#define portENTER_CRITICAL_ISR(mux) vPortEnterCritical(mux) -#define portEXIT_CRITICAL_ISR(mux) vPortExitCritical(mux) - static inline void __attribute__((always_inline)) vPortEnterCriticalSafe(portMUX_TYPE *mux) { if (xPortInIsrContext()) { @@ -234,80 +613,82 @@ static inline void __attribute__((always_inline)) vPortExitCriticalSafe(portMUX_ } } -#define portENTER_CRITICAL_SAFE(mux) vPortEnterCriticalSafe(mux) -#define portEXIT_CRITICAL_SAFE(mux) vPortExitCriticalSafe(mux) +// ---------------------- Yielding ------------------------- + +static inline bool IRAM_ATTR xPortCanYield(void) +{ + uint32_t ps_reg = 0; + + //Get the current value of PS (processor status) register + RSR(PS, ps_reg); + + /* + * intlevel = (ps_reg & 0xf); + * excm = (ps_reg >> 4) & 0x1; + * CINTLEVEL is max(excm * EXCMLEVEL, INTLEVEL), where EXCMLEVEL is 3. + * However, just return true, only intlevel is zero. + */ + + return ((ps_reg & PS_INTLEVEL_MASK) == 0); +} + +// ----------------------- System -------------------------- + +static inline BaseType_t IRAM_ATTR xPortGetCoreID(void) +{ + return cpu_hal_get_core_id(); +} + + + +/* ------------------------------------------------------ Misc --------------------------------------------------------- + * - Miscellaneous porting macros + * - These are not port of the FreeRTOS porting interface, but are used by other FreeRTOS dependent components + * - [refactor-todo] Remove dependency on MPU wrappers by modifying TCB + * ------------------------------------------------------------------------------------------------------------------ */ + +// -------------------- Co-Processor ----------------------- + +// When coprocessors are defined, we maintain a pointer to coprocessors area. +// We currently use a hack: redefine field xMPU_SETTINGS in TCB block as a structure that can hold: +// MPU wrappers, coprocessor area pointer, trace code structure, and more if needed. +// The field is normally used for memory protection. FreeRTOS should create another general purpose field. +typedef struct { +#if XCHAL_CP_NUM > 0 + volatile StackType_t *coproc_area; // Pointer to coprocessor save area; MUST BE FIRST +#endif + +#if portUSING_MPU_WRAPPERS + // Define here mpu_settings, which is port dependent + int mpu_setting; // Just a dummy example here; MPU not ported to Xtensa yet +#endif +} xMPU_SETTINGS; + +// Main hack to use MPU_wrappers even when no MPU is defined (warning: mpu_setting should not be accessed; otherwise move this above xMPU_SETTINGS) +#if (XCHAL_CP_NUM > 0) && !portUSING_MPU_WRAPPERS // If MPU wrappers not used, we still need to allocate coproc area +#undef portUSING_MPU_WRAPPERS +#define portUSING_MPU_WRAPPERS 1 // Enable it to allocate coproc area +#define MPU_WRAPPERS_H // Override mpu_wrapper.h to disable unwanted code +#define PRIVILEGED_FUNCTION +#define PRIVILEGED_DATA +#endif + +void _xt_coproc_release(volatile void *coproc_sa_base); /* - * Wrapper for the Xtensa compare-and-set instruction. This subroutine will atomically compare - * *addr to 'compare'. If *addr == compare, *addr is set to *set. *set is updated with the previous - * value of *addr (either 'compare' or some other value.) + * The structures and methods of manipulating the MPU are contained within the + * port layer. * - * Warning: From the ISA docs: in some (unspecified) cases, the s32c1i instruction may return the - * *bitwise inverse* of the old mem if the mem wasn't written. This doesn't seem to happen on the - * ESP32 (portMUX assertions would fail). + * Fills the xMPUSettings structure with the memory region information + * contained in xRegions. */ -static inline void __attribute__((always_inline)) uxPortCompareSet(volatile uint32_t *addr, uint32_t compare, uint32_t *set) { - compare_and_set_native(addr, compare, set); -} - -// Critical section management. NW-TODO: replace XTOS_SET_INTLEVEL with more efficient version, if any? -// These cannot be nested. They should be used with a lot of care and cannot be called from interrupt level. -// -// Only applies to one CPU. See notes above & below for reasons not to use these. -#define portDISABLE_INTERRUPTS() do { XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL); portbenchmarkINTERRUPT_DISABLE(); } while (0) -#define portENABLE_INTERRUPTS() do { portbenchmarkINTERRUPT_RESTORE(0); XTOS_SET_INTLEVEL(0); } while (0) - - -// These FreeRTOS versions are similar to the nested versions above -#define portSET_INTERRUPT_MASK_FROM_ISR() portENTER_CRITICAL_NESTED() -#define portCLEAR_INTERRUPT_MASK_FROM_ISR(state) portEXIT_CRITICAL_NESTED(state) - -//Because the ROM routines don't necessarily handle a stack in external RAM correctly, we force -//the stack memory to always be internal. -#define portTcbMemoryCaps (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT) -#define portStackMemoryCaps (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT) -#define pvPortMallocTcbMem(size) heap_caps_malloc(size, portTcbMemoryCaps) -#define pvPortMallocStackMem(size) heap_caps_malloc(size, portStackMemoryCaps) - -//xTaskCreateStatic uses these functions to check incoming memory. -#define portVALID_TCB_MEM(ptr) (esp_ptr_internal(ptr) && esp_ptr_byte_accessible(ptr)) -#ifdef CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY -#define portVALID_STACK_MEM(ptr) esp_ptr_byte_accessible(ptr) -#else -#define portVALID_STACK_MEM(ptr) (esp_ptr_internal(ptr) && esp_ptr_byte_accessible(ptr)) +#if( portUSING_MPU_WRAPPERS == 1 ) +struct xMEMORY_REGION; +void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION *const xRegions, StackType_t *pxBottomOfStack, uint32_t usStackDepth ) PRIVILEGED_FUNCTION; +void vPortReleaseTaskMPUSettings( xMPU_SETTINGS *xMPUSettings ); #endif - -static inline void uxPortCompareSetExtram(volatile uint32_t *addr, uint32_t compare, uint32_t *set) -{ -#ifdef CONFIG_SPIRAM - compare_and_set_extram(addr, compare, set); -#endif -} - - -/*-----------------------------------------------------------*/ - -/* Architecture specifics. */ -#define portSTACK_GROWTH ( -1 ) -#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) -#define portBYTE_ALIGNMENT 4 -#define portNOP() XT_NOP() -/*-----------------------------------------------------------*/ - -/* Fine resolution time */ -#define portGET_RUN_TIME_COUNTER_VALUE() xthal_get_ccount() -//ccount or esp_timer are initialized elsewhere -#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() - -#ifdef CONFIG_FREERTOS_RUN_TIME_STATS_USING_ESP_TIMER -/* Coarse resolution time (us) */ -#define portALT_GET_RUN_TIME_COUNTER_VALUE(x) do {x = (uint32_t)esp_timer_get_time();} while(0) -#endif - -void vPortYield( void ); -void vPortEvaluateYieldFromISR(int argc, ...); -void _frxt_setup_switch( void ); +// -------------------- VA_ARGS Yield ---------------------- /** * Macro to count number of arguments of a __VA_ARGS__ used to support portYIELD_FROM_ISR with, @@ -329,177 +710,37 @@ void _frxt_setup_switch( void ); _Static_assert(portGET_ARGUMENT_COUNT() == 0, "portGET_ARGUMENT_COUNT() result does not match for 0 arguments"); _Static_assert(portGET_ARGUMENT_COUNT(1) == 1, "portGET_ARGUMENT_COUNT() result does not match for 1 argument"); -#define portYIELD() vPortYield() +// -------------------- Heap Related ----------------------- /** - * @note The macro below could be used when passing a single argument, or without any argument, - * it was developed to support both usages of portYIELD inside of an ISR. Any other usage form - * might result in undesired behaviour - */ -#if defined(__cplusplus) && (__cplusplus > 201703L) -#define portYIELD_FROM_ISR(...) vPortEvaluateYieldFromISR(portGET_ARGUMENT_COUNT(__VA_ARGS__) __VA_OPT__(,) __VA_ARGS__) -#else -#define portYIELD_FROM_ISR(...) vPortEvaluateYieldFromISR(portGET_ARGUMENT_COUNT(__VA_ARGS__), ##__VA_ARGS__) -#endif - -/* Yielding within an API call (when interrupts are off), means the yield should be delayed - until interrupts are re-enabled. - - To do this, we use the "cross-core" interrupt as a trigger to yield on this core when interrupts are re-enabled.This - is the same interrupt & code path which is used to trigger a yield between CPUs, although in this case the yield is - happening on the same CPU. -*/ -#define portYIELD_WITHIN_API() esp_crosscore_int_send_yield(xPortGetCoreID()) - -/*-----------------------------------------------------------*/ - -/* Task function macros as described on the FreeRTOS.org WEB site. */ -#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) -#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) - -// When coprocessors are defined, we to maintain a pointer to coprocessors area. -// We currently use a hack: redefine field xMPU_SETTINGS in TCB block as a structure that can hold: -// MPU wrappers, coprocessor area pointer, trace code structure, and more if needed. -// The field is normally used for memory protection. FreeRTOS should create another general purpose field. -typedef struct { - #if XCHAL_CP_NUM > 0 - volatile StackType_t* coproc_area; // Pointer to coprocessor save area; MUST BE FIRST - #endif - - #if portUSING_MPU_WRAPPERS - // Define here mpu_settings, which is port dependent - int mpu_setting; // Just a dummy example here; MPU not ported to Xtensa yet - #endif - - #if configUSE_TRACE_FACILITY_2 - struct { - // Cf. porttraceStamp() - int taskstamp; /* Stamp from inside task to see where we are */ - int taskstampcount; /* A counter usually incremented when we restart the task's loop */ - } porttrace; - #endif -} xMPU_SETTINGS; - -// Main hack to use MPU_wrappers even when no MPU is defined (warning: mpu_setting should not be accessed; otherwise move this above xMPU_SETTINGS) -#if (XCHAL_CP_NUM > 0 || configUSE_TRACE_FACILITY_2) && !portUSING_MPU_WRAPPERS // If MPU wrappers not used, we still need to allocate coproc area - #undef portUSING_MPU_WRAPPERS - #define portUSING_MPU_WRAPPERS 1 // Enable it to allocate coproc area - #define MPU_WRAPPERS_H // Override mpu_wrapper.h to disable unwanted code - #define PRIVILEGED_FUNCTION - #define PRIVILEGED_DATA -#endif - -extern void esp_vApplicationIdleHook( void ); -extern void esp_vApplicationTickHook( void ); - -#ifndef CONFIG_FREERTOS_LEGACY_HOOKS -#define vApplicationIdleHook esp_vApplicationIdleHook -#define vApplicationTickHook esp_vApplicationTickHook -#endif /* !CONFIG_FREERTOS_LEGACY_HOOKS */ - -void vApplicationSleep( TickType_t xExpectedIdleTime ); - -#define portSUPPRESS_TICKS_AND_SLEEP( idleTime ) vApplicationSleep( idleTime ) - -void _xt_coproc_release(volatile void * coproc_sa_base); - -/* Architecture specific optimisations. */ -#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 - -/* Check the configuration. */ -#if( configMAX_PRIORITIES > 32 ) - #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 different priorities as tasks that share a priority will time slice. -#endif - -/* Store/clear the ready priorities in a bit map. */ -#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) -#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) - -/*-----------------------------------------------------------*/ - -#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __builtin_clz( ( uxReadyPriorities ) ) ) - -#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ - -/* - * Send an interrupt to another core in order to make the task running - * on it yield for a higher-priority task. - */ - -void vPortYieldOtherCore( BaseType_t coreid) ; - -/* - Callback to set a watchpoint on the end of the stack. Called every context switch to change the stack - watchpoint around. - */ -void vPortSetStackWatchpoint( void* pxStackStart ); - -/* - * Returns true if the current core is in ISR context; low prio ISR, med prio ISR or timer tick ISR. High prio ISRs - * aren't detected here, but they normally cannot call C code, so that should not be an issue anyway. - */ -BaseType_t xPortInIsrContext(void); - -/* - * This function will be called in High prio ISRs. Returns true if the current core was in ISR context - * before calling into high prio ISR context. - */ -BaseType_t xPortInterruptedFromISRContext(void); - -/* - * The structures and methods of manipulating the MPU are contained within the - * port layer. + * @brief Checks if a given piece of memory can be used to store a task's TCB * - * Fills the xMPUSettings structure with the memory region information - * contained in xRegions. + * - Defined in port_common.c + * + * @param ptr Pointer to memory + * @return true Memory can be used to store a TCB + * @return false Otherwise */ -#if( portUSING_MPU_WRAPPERS == 1 ) - struct xMEMORY_REGION; - void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint32_t usStackDepth ) PRIVILEGED_FUNCTION; - void vPortReleaseTaskMPUSettings( xMPU_SETTINGS *xMPUSettings ); -#endif +bool xPortCheckValidTCBMem(const void *ptr); -/* Multi-core: get current core ID */ -static inline BaseType_t IRAM_ATTR xPortGetCoreID(void) { - return cpu_hal_get_core_id(); -} +/** + * @brief Checks if a given piece of memory can be used to store a task's stack + * + * - Defined in port_common.c + * + * @param ptr Pointer to memory + * @return true Memory can be used to store a task stack + * @return false Otherwise + */ +bool xPortcheckValidStackMem(const void *ptr); -/* Get tick rate per second */ -uint32_t xPortGetTickRateHz(void); - -static inline bool IRAM_ATTR xPortCanYield(void) -{ - uint32_t ps_reg = 0; - - //Get the current value of PS (processor status) register - RSR(PS, ps_reg); - - /* - * intlevel = (ps_reg & 0xf); - * excm = (ps_reg >> 4) & 0x1; - * CINTLEVEL is max(excm * EXCMLEVEL, INTLEVEL), where EXCMLEVEL is 3. - * However, just return true, only intlevel is zero. - */ - - return ((ps_reg & PS_INTLEVEL_MASK) == 0); -} - -// porttrace -#if configUSE_TRACE_FACILITY_2 -#include "porttrace.h" -#endif - -// configASSERT_2 if requested -#if configASSERT_2 -#include -void exit(int); -#define configASSERT( x ) if (!(x)) { porttracePrint(-1); printf("\nAssertion failed in %s:%d\n", __FILE__, __LINE__); exit(-1); } -#endif - -#endif // __ASSEMBLER__ +#define portVALID_TCB_MEM(ptr) xPortCheckValidTCBMem(ptr) +#define portVALID_STACK_MEM(ptr) xPortcheckValidStackMem(ptr) #ifdef __cplusplus } #endif +#endif // __ASSEMBLER__ + #endif /* PORTMACRO_H */ diff --git a/components/freertos/port/xtensa/include/freertos/portmacro_priv.h b/components/freertos/port/xtensa/include/freertos/portmacro_priv.h deleted file mode 100644 index 843456b5aa..0000000000 --- a/components/freertos/port/xtensa/include/freertos/portmacro_priv.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd. - All rights reserved - - VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. - - *************************************************************************** - * * - * FreeRTOS provides completely free yet professionally developed, * - * robust, strictly quality controlled, supported, and cross * - * platform software that has become a de facto standard. * - * * - * Help yourself get started quickly and support the FreeRTOS * - * project by purchasing a FreeRTOS tutorial book, reference * - * manual, or both from: http://www.FreeRTOS.org/Documentation * - * * - * Thank you! * - * * - *************************************************************************** - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. - - >>! NOTE: The modification to the GPL is included to allow you to !<< - >>! distribute a combined work that includes FreeRTOS without being !<< - >>! obliged to provide the source code for proprietary components !<< - >>! outside of the FreeRTOS kernel. !<< - - FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. Full license text is available from the following - link: http://www.freertos.org/a00114.html - - 1 tab == 4 spaces! - - *************************************************************************** - * * - * Having a problem? Start by reading the FAQ "My application does * - * not run, what could be wrong?" * - * * - * http://www.FreeRTOS.org/FAQHelp.html * - * * - *************************************************************************** - - http://www.FreeRTOS.org - Documentation, books, training, latest versions, - license and Real Time Engineers Ltd. contact details. - - http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, - including FreeRTOS+Trace - an indispensable productivity tool, a DOS - compatible FAT file system, and our tiny thread aware UDP/IP stack. - - http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High - Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS - licenses offer ticketed support, indemnification and middleware. - - http://www.SafeRTOS.com - High Integrity Systems also provide a safety - engineered and independently SIL3 certified version for use in safety and - mission critical applications that require provable dependability. - - 1 tab == 4 spaces! -*/ - - -/* This header holds the macros for porting which should only be used inside FreeRTOS */ - -#pragma once -#include "soc/soc_memory_layout.h" - -//xTaskCreateStatic uses these functions to check incoming memory. -#define portVALID_TCB_MEM(ptr) (esp_ptr_internal(ptr) && esp_ptr_byte_accessible(ptr)) -#ifdef CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY -#define portVALID_STACK_MEM(ptr) esp_ptr_byte_accessible(ptr) -#else -#define portVALID_STACK_MEM(ptr) (esp_ptr_internal(ptr) && esp_ptr_byte_accessible(ptr)) -#endif diff --git a/components/freertos/port/xtensa/include/freertos/xtensa_rtos.h b/components/freertos/port/xtensa/include/freertos/xtensa_rtos.h index d1b4023799..b7793d6803 100644 --- a/components/freertos/port/xtensa/include/freertos/xtensa_rtos.h +++ b/components/freertos/port/xtensa/include/freertos/xtensa_rtos.h @@ -50,6 +50,7 @@ Should be included by all Xtensa generic and RTOS port-specific sources. #include #include +#include "sdkconfig.h" /* Include any RTOS specific definitions that are needed by this header. @@ -145,7 +146,9 @@ May be coded in or called from C or assembly, per ABI conventions. RTOS may optionally define XT_TICK_PER_SEC in its own way (eg. macro). */ // void XT_RTOS_TIMER_INT(void) +#ifdef CONFIG_FREERTOS_SYSTICK_USES_CCOUNT #define XT_RTOS_TIMER_INT _frxt_timer_int +#endif #define XT_TICK_PER_SEC configTICK_RATE_HZ /* diff --git a/components/freertos/port/xtensa/port.c b/components/freertos/port/xtensa/port.c index 41bc826652..778d3b23e6 100644 --- a/components/freertos/port/xtensa/port.c +++ b/components/freertos/port/xtensa/port.c @@ -1,162 +1,124 @@ /* - FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd. - All rights reserved + * FreeRTOS Kernel V10.4.3 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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 + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. If you wish to use our Amazon + * FreeRTOS name, please do so in a fair use way that does not cause confusion. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + * 1 tab == 4 spaces! + */ - VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. +/* + * Copyright (c) 2015-2019 Cadence Design Systems, Inc. + * + * 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 the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. - - *************************************************************************** - >>! NOTE: The modification to the GPL is included to allow you to !<< - >>! distribute a combined work that includes FreeRTOS without being !<< - >>! obliged to provide the source code for proprietary components !<< - >>! outside of the FreeRTOS kernel. !<< - *************************************************************************** - - FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. Full license text is available on the following - link: http://www.freertos.org/a00114.html - - *************************************************************************** - * * - * FreeRTOS provides completely free yet professionally developed, * - * robust, strictly quality controlled, supported, and cross * - * platform software that is more than just the market leader, it * - * is the industry's de facto standard. * - * * - * Help yourself get started quickly while simultaneously helping * - * to support the FreeRTOS project by purchasing a FreeRTOS * - * tutorial book, reference manual, or both: * - * http://www.FreeRTOS.org/Documentation * - * * - *************************************************************************** - - http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading - the FAQ page "My application does not run, what could be wrong?". Have you - defined configASSERT()? - - http://www.FreeRTOS.org/support - In return for receiving this top quality - embedded software for free we request you assist our global community by - participating in the support forum. - - http://www.FreeRTOS.org/training - Investing in training allows your team to - be as productive as possible as early as possible. Now you can receive - FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers - Ltd, and the world's leading authority on the world's leading RTOS. - - http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, - including FreeRTOS+Trace - an indispensable productivity tool, a DOS - compatible FAT file system, and our tiny thread aware UDP/IP stack. - - http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. - Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. - - http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High - Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS - licenses offer ticketed support, indemnification and commercial middleware. - - http://www.SafeRTOS.com - High Integrity Systems also provide a safety - engineered and independently SIL3 certified version for use in safety and - mission critical applications that require provable dependability. - - 1 tab == 4 spaces! -*/ - -/******************************************************************************* -// Copyright (c) 2003-2015 Cadence Design Systems, Inc. -// -// 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 the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------------------------------- -*/ +#include "sdkconfig.h" +#include #include #include +#include #include - -#include "xtensa_rtos.h" - -#include "soc/cpu.h" - -#include "FreeRTOS.h" -#include "task.h" - -#include "esp_debug_helpers.h" -#include "esp_heap_caps.h" -#include "esp_heap_caps_init.h" -#include "esp_private/crosscore_int.h" - -#include "esp_intr_alloc.h" -#include "esp_log.h" -#include "sdkconfig.h" - -#include "esp_task_wdt.h" -#include "esp_task.h" - +#include #include "soc/soc_caps.h" -#include "soc/efuse_reg.h" -#include "soc/dport_access.h" -#include "soc/dport_reg.h" +#include "esp_private/crosscore_int.h" +#include "esp_system.h" +#include "esp_log.h" #include "esp_int_wdt.h" - - -#include "sdkconfig.h" - -#if CONFIG_IDF_TARGET_ESP32 -#include "esp32/spiram.h" -#elif CONFIG_IDF_TARGET_ESP32S2 -#include "esp32s2/spiram.h" -#elif CONFIG_IDF_TARGET_ESP32S3 -#include "esp32s3/spiram.h" -#endif - -#include "esp_private/startup_internal.h" // [refactor-todo] for g_spiram_ok -#include "esp_app_trace.h" // [refactor-todo] for esp_app_trace_init - -/* Defined in portasm.h */ -extern void _frxt_tick_timer_init(void); - -/* Defined in xtensa_context.S */ -extern void _xt_coproc_init(void); - -static const char* TAG = "cpu_start"; // [refactor-todo]: might be appropriate to change in the future, but - // for now maintain the same log output - -#if CONFIG_FREERTOS_CORETIMER_0 - #define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER0_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF) -#endif -#if CONFIG_FREERTOS_CORETIMER_1 - #define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER1_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF) -#endif +#include "esp_app_trace.h" /* Required for esp_apptrace_init. [refactor-todo] */ +#include "FreeRTOS.h" /* This pulls in portmacro.h */ +#include "task.h" /* Required for TaskHandle_t, tskNO_AFFINITY, and vTaskStartScheduler */ +#include "port_systick.h" _Static_assert(tskNO_AFFINITY == CONFIG_FREERTOS_NO_AFFINITY, "incorrect tskNO_AFFINITY value"); -/*-----------------------------------------------------------*/ + +/* ---------------------------------------------------- Variables ------------------------------------------------------ + * + * ------------------------------------------------------------------------------------------------------------------ */ + +static const char *TAG = "cpu_start"; /* [refactor-todo]: might be appropriate to change in the future, but for now maintain the same log output */ extern volatile int port_xSchedulerRunning[portNUM_PROCESSORS]; unsigned port_interruptNesting[portNUM_PROCESSORS] = {0}; // Interrupt nesting level. Increased/decreased in portasm.c, _frxt_int_enter/_frxt_int_exit BaseType_t port_uxCriticalNesting[portNUM_PROCESSORS] = {0}; BaseType_t port_uxOldInterruptState[portNUM_PROCESSORS] = {0}; -/*-----------------------------------------------------------*/ + + +/* ------------------------------------------------ FreeRTOS Portable -------------------------------------------------- + * - Provides implementation for functions required by FreeRTOS + * - Declared in portable.h + * ------------------------------------------------------------------------------------------------------------------ */ + +// ----------------- Scheduler Start/End ------------------- + +/* Defined in xtensa_context.S */ +extern void _xt_coproc_init(void); + +BaseType_t xPortStartScheduler( void ) +{ + // Interrupts are disabled at this point and stack contains PS with enabled interrupts when task context is restored + +#if XCHAL_CP_NUM > 0 + /* Initialize co-processor management for tasks. Leave CPENABLE alone. */ + _xt_coproc_init(); +#endif + + /* Setup the hardware to generate the tick. */ + vPortSetupTimer(); + + port_xSchedulerRunning[xPortGetCoreID()] = 1; + + // Cannot be directly called from C; never returns + __asm__ volatile ("call0 _frxt_dispatch\n"); + + /* Should not get here. */ + return pdTRUE; +} + +void vPortEndScheduler( void ) +{ + /* It is unlikely that the Xtensa port will get stopped. If required simply + disable the tick interrupt here. */ + abort(); +} + +// ------------------------ Stack -------------------------- // User exception dispatcher when exiting void _xt_user_exit(void); @@ -165,239 +127,204 @@ void _xt_user_exit(void); // Wrapper to allow task functions to return (increases stack overhead by 16 bytes) static void vPortTaskWrapper(TaskFunction_t pxCode, void *pvParameters) { - pxCode(pvParameters); - //FreeRTOS tasks should not return. Log the task name and abort. - char * pcTaskName = pcTaskGetTaskName(NULL); - ESP_LOGE("FreeRTOS", "FreeRTOS Task \"%s\" should not return, Aborting now!", pcTaskName); - abort(); + pxCode(pvParameters); + //FreeRTOS tasks should not return. Log the task name and abort. + char *pcTaskName = pcTaskGetTaskName(NULL); + ESP_LOGE("FreeRTOS", "FreeRTOS Task \"%s\" should not return, Aborting now!", pcTaskName); + abort(); } #endif -/* - * Stack initialization - */ #if portUSING_MPU_WRAPPERS StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) #else StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) #endif { - StackType_t *sp, *tp; - XtExcFrame *frame; - #if XCHAL_CP_NUM > 0 - uint32_t *p; - #endif - uint32_t *threadptr; - void *task_thread_local_start; - extern int _thread_local_start, _thread_local_end, _flash_rodata_start, _flash_rodata_align; - // TODO: check that TLS area fits the stack - uint32_t thread_local_sz = (uint8_t *)&_thread_local_end - (uint8_t *)&_thread_local_start; + StackType_t *sp, *tp; + XtExcFrame *frame; +#if XCHAL_CP_NUM > 0 + uint32_t *p; +#endif + uint32_t *threadptr; + void *task_thread_local_start; + extern int _thread_local_start, _thread_local_end, _flash_rodata_start, _flash_rodata_align; + // TODO: check that TLS area fits the stack + uint32_t thread_local_sz = (uint8_t *)&_thread_local_end - (uint8_t *)&_thread_local_start; - thread_local_sz = ALIGNUP(0x10, thread_local_sz); + thread_local_sz = ALIGNUP(0x10, thread_local_sz); - /* Initialize task's stack so that we have the following structure at the top: + /* Initialize task's stack so that we have the following structure at the top: - ----LOW ADDRESSES ----------------------------------------HIGH ADDRESSES---------- - task stack | interrupt stack frame | thread local vars | co-processor save area | - ---------------------------------------------------------------------------------- - | | - SP pxTopOfStack + ----LOW ADDRESSES ----------------------------------------HIGH ADDRESSES---------- + task stack | interrupt stack frame | thread local vars | co-processor save area | + ---------------------------------------------------------------------------------- + | | + SP pxTopOfStack - All parts are aligned to 16 byte boundary. */ - sp = (StackType_t *) (((UBaseType_t)pxTopOfStack - XT_CP_SIZE - thread_local_sz - XT_STK_FRMSZ) & ~0xf); + All parts are aligned to 16 byte boundary. */ + sp = (StackType_t *) (((UBaseType_t)pxTopOfStack - XT_CP_SIZE - thread_local_sz - XT_STK_FRMSZ) & ~0xf); - /* Clear the entire frame (do not use memset() because we don't depend on C library) */ - for (tp = sp; tp <= pxTopOfStack; ++tp) - *tp = 0; + /* Clear the entire frame (do not use memset() because we don't depend on C library) */ + for (tp = sp; tp <= pxTopOfStack; ++tp) { + *tp = 0; + } - frame = (XtExcFrame *) sp; + frame = (XtExcFrame *) sp; - /* Explicitly initialize certain saved registers */ - #if CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER - frame->pc = (UBaseType_t) vPortTaskWrapper; /* task wrapper */ - #else - frame->pc = (UBaseType_t) pxCode; /* task entrypoint */ - #endif - frame->a0 = 0; /* to terminate GDB backtrace */ - frame->a1 = (UBaseType_t) sp + XT_STK_FRMSZ; /* physical top of stack frame */ - frame->exit = (UBaseType_t) _xt_user_exit; /* user exception exit dispatcher */ + /* Explicitly initialize certain saved registers */ +#if CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER + frame->pc = (UBaseType_t) vPortTaskWrapper; /* task wrapper */ +#else + frame->pc = (UBaseType_t) pxCode; /* task entrypoint */ +#endif + frame->a0 = 0; /* to terminate GDB backtrace */ + frame->a1 = (UBaseType_t) sp + XT_STK_FRMSZ; /* physical top of stack frame */ + frame->exit = (UBaseType_t) _xt_user_exit; /* user exception exit dispatcher */ - /* Set initial PS to int level 0, EXCM disabled ('rfe' will enable), user mode. */ - /* Also set entry point argument parameter. */ - #ifdef __XTENSA_CALL0_ABI__ - #if CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER - frame->a2 = (UBaseType_t) pxCode; - frame->a3 = (UBaseType_t) pvParameters; - #else - frame->a2 = (UBaseType_t) pvParameters; - #endif - frame->ps = PS_UM | PS_EXCM; - #else - /* + for windowed ABI also set WOE and CALLINC (pretend task was 'call4'd). */ - #if CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER - frame->a6 = (UBaseType_t) pxCode; - frame->a7 = (UBaseType_t) pvParameters; - #else - frame->a6 = (UBaseType_t) pvParameters; - #endif - frame->ps = PS_UM | PS_EXCM | PS_WOE | PS_CALLINC(1); - #endif - - #ifdef XT_USE_SWPRI - /* Set the initial virtual priority mask value to all 1's. */ - frame->vpri = 0xFFFFFFFF; - #endif - - /* Init threadptr register and set up TLS run-time area. - * The diagram in port/riscv/port.c illustrates the calculations below. - */ - task_thread_local_start = (void *)(((uint32_t)pxTopOfStack - XT_CP_SIZE - thread_local_sz) & ~0xf); - memcpy(task_thread_local_start, &_thread_local_start, thread_local_sz); - threadptr = (uint32_t *)(sp + XT_STK_EXTRA); - /* Calculate THREADPTR value. - * The generated code will add THREADPTR value to a constant value determined at link time, - * to get the address of the TLS variable. - * The constant value is calculated by the linker as follows - * (search for 'tpoff' in elf32-xtensa.c in BFD): - * offset = address - tls_section_vma + align_up(TCB_SIZE, tls_section_alignment) - * where TCB_SIZE is hardcoded to 8. - * Note this is slightly different compared to the RISC-V port, where offset = address - tls_section_vma. - */ - const uint32_t tls_section_alignment = (uint32_t) &_flash_rodata_align; /* ALIGN value of .flash.rodata section */ - const uint32_t tcb_size = 8; /* Unrelated to FreeRTOS, this is the constant from BFD */ - const uint32_t base = (tcb_size + tls_section_alignment - 1) & (~(tls_section_alignment - 1)); - *threadptr = (uint32_t)task_thread_local_start - ((uint32_t)&_thread_local_start - (uint32_t)&_flash_rodata_start) - base; - - #if XCHAL_CP_NUM > 0 - /* Init the coprocessor save area (see xtensa_context.h) */ - /* No access to TCB here, so derive indirectly. Stack growth is top to bottom. - * //p = (uint32_t *) xMPUSettings->coproc_area; - */ - p = (uint32_t *)(((uint32_t) pxTopOfStack - XT_CP_SIZE) & ~0xf); - configASSERT( ( uint32_t ) p >= frame->a1 ); - p[0] = 0; - p[1] = 0; - p[2] = (((uint32_t) p) + 12 + XCHAL_TOTAL_SA_ALIGN - 1) & -XCHAL_TOTAL_SA_ALIGN; - #endif - - return sp; -} - -/*-----------------------------------------------------------*/ - -void vPortEndScheduler( void ) -{ - /* It is unlikely that the Xtensa port will get stopped. If required simply - disable the tick interrupt here. */ - abort(); -} - -/*-----------------------------------------------------------*/ - -BaseType_t xPortStartScheduler( void ) -{ - // Interrupts are disabled at this point and stack contains PS with enabled interrupts when task context is restored - - #if XCHAL_CP_NUM > 0 - /* Initialize co-processor management for tasks. Leave CPENABLE alone. */ - _xt_coproc_init(); - #endif - - /* Init the tick divisor value */ - _xt_tick_divisor_init(); - - /* Setup the hardware to generate the tick. */ - _frxt_tick_timer_init(); - - port_xSchedulerRunning[xPortGetCoreID()] = 1; - - // Cannot be directly called from C; never returns - __asm__ volatile ("call0 _frxt_dispatch\n"); - - /* Should not get here. */ - return pdTRUE; -} -/*-----------------------------------------------------------*/ - -BaseType_t xPortSysTickHandler( void ) -{ - BaseType_t ret; - - portbenchmarkIntLatency(); - traceISR_ENTER(SYSTICK_INTR_ID); - ret = xTaskIncrementTick(); - if( ret != pdFALSE ) - { - portYIELD_FROM_ISR(); - } else { - traceISR_EXIT(); - } - return ret; -} - - -void vPortYieldOtherCore( BaseType_t coreid ) { - esp_crosscore_int_send_yield( coreid ); -} - -/*-----------------------------------------------------------*/ - -/* - * Used to set coprocessor area in stack. Current hack is to reuse MPU pointer for coprocessor area. - */ -#if portUSING_MPU_WRAPPERS -void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint32_t usStackDepth ) -{ - #if XCHAL_CP_NUM > 0 - xMPUSettings->coproc_area = ( StackType_t * ) ( ( uint32_t ) ( pxBottomOfStack + usStackDepth - 1 )); - xMPUSettings->coproc_area = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) xMPUSettings->coproc_area ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); - xMPUSettings->coproc_area = ( StackType_t * ) ( ( ( uint32_t ) xMPUSettings->coproc_area - XT_CP_SIZE ) & ~0xf ); - - - /* NOTE: we cannot initialize the coprocessor save area here because FreeRTOS is going to - * clear the stack area after we return. This is done in pxPortInitialiseStack(). - */ - #endif -} - -void vPortReleaseTaskMPUSettings( xMPU_SETTINGS *xMPUSettings ) -{ - /* If task has live floating point registers somewhere, release them */ - _xt_coproc_release( xMPUSettings->coproc_area ); -} + /* Set initial PS to int level 0, EXCM disabled ('rfe' will enable), user mode. */ + /* Also set entry point argument parameter. */ +#ifdef __XTENSA_CALL0_ABI__ +#if CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER + frame->a2 = (UBaseType_t) pxCode; + frame->a3 = (UBaseType_t) pvParameters; +#else + frame->a2 = (UBaseType_t) pvParameters; +#endif + frame->ps = PS_UM | PS_EXCM; +#else /* __XTENSA_CALL0_ABI__ */ + /* + for windowed ABI also set WOE and CALLINC (pretend task was 'call4'd). */ +#if CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER + frame->a6 = (UBaseType_t) pxCode; + frame->a7 = (UBaseType_t) pvParameters; +#else + frame->a6 = (UBaseType_t) pvParameters; +#endif + frame->ps = PS_UM | PS_EXCM | PS_WOE | PS_CALLINC(1); +#endif /* __XTENSA_CALL0_ABI__ */ +#ifdef XT_USE_SWPRI + /* Set the initial virtual priority mask value to all 1's. */ + frame->vpri = 0xFFFFFFFF; #endif -/* - * Returns true if the current core is in ISR context; low prio ISR, med prio ISR or timer tick ISR. High prio ISRs - * aren't detected here, but they normally cannot call C code, so that should not be an issue anyway. - */ -BaseType_t xPortInIsrContext(void) -{ - unsigned int irqStatus; - BaseType_t ret; - irqStatus=portENTER_CRITICAL_NESTED(); - ret=(port_interruptNesting[xPortGetCoreID()] != 0); - portEXIT_CRITICAL_NESTED(irqStatus); - return ret; + /* Init threadptr register and set up TLS run-time area. + * The diagram in port/riscv/port.c illustrates the calculations below. + */ + task_thread_local_start = (void *)(((uint32_t)pxTopOfStack - XT_CP_SIZE - thread_local_sz) & ~0xf); + memcpy(task_thread_local_start, &_thread_local_start, thread_local_sz); + threadptr = (uint32_t *)(sp + XT_STK_EXTRA); + /* Calculate THREADPTR value. + * The generated code will add THREADPTR value to a constant value determined at link time, + * to get the address of the TLS variable. + * The constant value is calculated by the linker as follows + * (search for 'tpoff' in elf32-xtensa.c in BFD): + * offset = address - tls_section_vma + align_up(TCB_SIZE, tls_section_alignment) + * where TCB_SIZE is hardcoded to 8. + * Note this is slightly different compared to the RISC-V port, where offset = address - tls_section_vma. + */ + const uint32_t tls_section_alignment = (uint32_t) &_flash_rodata_align; /* ALIGN value of .flash.rodata section */ + const uint32_t tcb_size = 8; /* Unrelated to FreeRTOS, this is the constant from BFD */ + const uint32_t base = (tcb_size + tls_section_alignment - 1) & (~(tls_section_alignment - 1)); + *threadptr = (uint32_t)task_thread_local_start - ((uint32_t)&_thread_local_start - (uint32_t)&_flash_rodata_start) - base; + +#if XCHAL_CP_NUM > 0 + /* Init the coprocessor save area (see xtensa_context.h) */ + /* No access to TCB here, so derive indirectly. Stack growth is top to bottom. + * //p = (uint32_t *) xMPUSettings->coproc_area; + */ + p = (uint32_t *)(((uint32_t) pxTopOfStack - XT_CP_SIZE) & ~0xf); + configASSERT( ( uint32_t ) p >= frame->a1 ); + p[0] = 0; + p[1] = 0; + p[2] = (((uint32_t) p) + 12 + XCHAL_TOTAL_SA_ALIGN - 1) & -XCHAL_TOTAL_SA_ALIGN; +#endif /* XCHAL_CP_NUM */ + + return sp; +} + + + +/* ---------------------------------------------- Port Implementations ------------------------------------------------- + * + * ------------------------------------------------------------------------------------------------------------------ */ + +// --------------------- Interrupts ------------------------ + +BaseType_t xPortInIsrContext(void) +{ + unsigned int irqStatus; + BaseType_t ret; + irqStatus = portENTER_CRITICAL_NESTED(); + ret = (port_interruptNesting[xPortGetCoreID()] != 0); + portEXIT_CRITICAL_NESTED(irqStatus); + return ret; +} + +void vPortAssertIfInISR(void) +{ + configASSERT(xPortInIsrContext()); } -/* - * This function will be called in High prio ISRs. Returns true if the current core was in ISR context - * before calling into high prio ISR context. - */ BaseType_t IRAM_ATTR xPortInterruptedFromISRContext(void) { - return (port_interruptNesting[xPortGetCoreID()] != 0); + return (port_interruptNesting[xPortGetCoreID()] != 0); } +// ------------------ Critical Sections -------------------- + +void __attribute__((optimize("-O3"))) vPortEnterCritical(portMUX_TYPE *mux) +{ + BaseType_t oldInterruptLevel = portENTER_CRITICAL_NESTED(); + /* Interrupts may already be disabled (because we're doing this recursively) + * but we can't get the interrupt level after + * vPortCPUAquireMutex, because it also may mess with interrupts. + * Get it here first, then later figure out if we're nesting + * and save for real there. + */ + vPortCPUAcquireMutex( mux ); + BaseType_t coreID = xPortGetCoreID(); + BaseType_t newNesting = port_uxCriticalNesting[coreID] + 1; + port_uxCriticalNesting[coreID] = newNesting; + + if ( newNesting == 1 ) { + //This is the first time we get called. Save original interrupt level. + port_uxOldInterruptState[coreID] = oldInterruptLevel; + } +} + +void __attribute__((optimize("-O3"))) vPortExitCritical(portMUX_TYPE *mux) +{ + vPortCPUReleaseMutex( mux ); + BaseType_t coreID = xPortGetCoreID(); + BaseType_t nesting = port_uxCriticalNesting[coreID]; + + if (nesting > 0) { + nesting--; + port_uxCriticalNesting[coreID] = nesting; + + if ( nesting == 0 ) { + portEXIT_CRITICAL_NESTED(port_uxOldInterruptState[coreID]); + } + } +} + +// ---------------------- Yielding ------------------------- + +void vPortYieldOtherCore( BaseType_t coreid ) +{ + esp_crosscore_int_send_yield( coreid ); +} + +extern void _frxt_setup_switch( void ); //Defined in portasm.S + void IRAM_ATTR vPortEvaluateYieldFromISR(int argc, ...) { BaseType_t xYield; va_list ap; va_start(ap, argc); - if(argc) { + if (argc) { xYield = (BaseType_t)va_arg(ap, int); va_end(ap); } else { @@ -409,122 +336,115 @@ void IRAM_ATTR vPortEvaluateYieldFromISR(int argc, ...) } //Yield exists, so need evaluate it first then switch: - if(xYield == pdTRUE) { + if (xYield == pdTRUE) { traceISR_EXIT_TO_SCHEDULER(); _frxt_setup_switch(); } } -void vPortAssertIfInISR(void) +// ------------------- Hook Functions ---------------------- + +void __attribute__((weak)) vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName ) { - configASSERT(xPortInIsrContext()); +#define ERR_STR1 "***ERROR*** A stack overflow in task " +#define ERR_STR2 " has been detected." + const char *str[] = {ERR_STR1, pcTaskName, ERR_STR2}; + + char buf[sizeof(ERR_STR1) + CONFIG_FREERTOS_MAX_TASK_NAME_LEN + sizeof(ERR_STR2) + 1 /* null char */] = { 0 }; + + char *dest = buf; + for (size_t i = 0 ; i < sizeof(str) / sizeof(str[0]); i++) { + dest = strcat(dest, str[i]); + } + esp_system_abort(buf); } +// ----------------------- System -------------------------- + +uint32_t xPortGetTickRateHz(void) +{ + return (uint32_t)configTICK_RATE_HZ; +} + + #define STACK_WATCH_AREA_SIZE 32 #define STACK_WATCH_POINT_NUMBER (SOC_CPU_WATCHPOINTS_NUM - 1) -void vPortSetStackWatchpoint( void* pxStackStart ) { - //Set watchpoint 1 to watch the last 32 bytes of the stack. - //Unfortunately, the Xtensa watchpoints can't set a watchpoint on a random [base - base+n] region because - //the size works by masking off the lowest address bits. For that reason, we futz a bit and watch the lowest 32 - //bytes of the stack we can actually watch. In general, this can cause the watchpoint to be triggered at most - //28 bytes early. The value 32 is chosen because it's larger than the stack canary, which in FreeRTOS is 20 bytes. - //This way, we make sure we trigger before/when the stack canary is corrupted, not after. - int addr=(int)pxStackStart; - addr=(addr+31)&(~31); - esp_cpu_set_watchpoint(STACK_WATCH_POINT_NUMBER, (char*)addr, 32, ESP_WATCHPOINT_STORE); -} - -uint32_t xPortGetTickRateHz(void) { - return (uint32_t)configTICK_RATE_HZ; -} - -void __attribute__((optimize("-O3"))) vPortEnterCritical(portMUX_TYPE *mux) +void vPortSetStackWatchpoint( void *pxStackStart ) { - BaseType_t oldInterruptLevel = portENTER_CRITICAL_NESTED(); - /* Interrupts may already be disabled (because we're doing this recursively) - * but we can't get the interrupt level after - * vPortCPUAquireMutex, because it also may mess with interrupts. - * Get it here first, then later figure out if we're nesting - * and save for real there. - */ - vPortCPUAcquireMutex( mux ); - BaseType_t coreID = xPortGetCoreID(); - BaseType_t newNesting = port_uxCriticalNesting[coreID] + 1; - port_uxCriticalNesting[coreID] = newNesting; - - if( newNesting == 1 ) - { - //This is the first time we get called. Save original interrupt level. - port_uxOldInterruptState[coreID] = oldInterruptLevel; - } + //Set watchpoint 1 to watch the last 32 bytes of the stack. + //Unfortunately, the Xtensa watchpoints can't set a watchpoint on a random [base - base+n] region because + //the size works by masking off the lowest address bits. For that reason, we futz a bit and watch the lowest 32 + //bytes of the stack we can actually watch. In general, this can cause the watchpoint to be triggered at most + //28 bytes early. The value 32 is chosen because it's larger than the stack canary, which in FreeRTOS is 20 bytes. + //This way, we make sure we trigger before/when the stack canary is corrupted, not after. + int addr = (int)pxStackStart; + addr = (addr + 31) & (~31); + esp_cpu_set_watchpoint(STACK_WATCH_POINT_NUMBER, (char *)addr, 32, ESP_WATCHPOINT_STORE); } -void __attribute__((optimize("-O3"))) vPortExitCritical(portMUX_TYPE *mux) +/* ---------------------------------------------- Misc Implementations ------------------------------------------------- + * + * ------------------------------------------------------------------------------------------------------------------ */ + +// -------------------- Co-Processor ----------------------- + +/* + * Used to set coprocessor area in stack. Current hack is to reuse MPU pointer for coprocessor area. + */ +#if portUSING_MPU_WRAPPERS +void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION *const xRegions, StackType_t *pxBottomOfStack, uint32_t usStackDepth ) { - vPortCPUReleaseMutex( mux ); - BaseType_t coreID = xPortGetCoreID(); - BaseType_t nesting = port_uxCriticalNesting[coreID]; +#if XCHAL_CP_NUM > 0 + xMPUSettings->coproc_area = ( StackType_t * ) ( ( uint32_t ) ( pxBottomOfStack + usStackDepth - 1 )); + xMPUSettings->coproc_area = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) xMPUSettings->coproc_area ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); + xMPUSettings->coproc_area = ( StackType_t * ) ( ( ( uint32_t ) xMPUSettings->coproc_area - XT_CP_SIZE ) & ~0xf ); - if(nesting > 0) - { - nesting--; - port_uxCriticalNesting[coreID] = nesting; - if( nesting == 0 ) - { - portEXIT_CRITICAL_NESTED(port_uxOldInterruptState[coreID]); - } - } + /* NOTE: we cannot initialize the coprocessor save area here because FreeRTOS is going to + * clear the stack area after we return. This is done in pxPortInitialiseStack(). + */ +#endif } -void __attribute__((weak)) vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName ) +void vPortReleaseTaskMPUSettings( xMPU_SETTINGS *xMPUSettings ) { - #define ERR_STR1 "***ERROR*** A stack overflow in task " - #define ERR_STR2 " has been detected." - const char *str[] = {ERR_STR1, pcTaskName, ERR_STR2}; - - char buf[sizeof(ERR_STR1) + CONFIG_FREERTOS_MAX_TASK_NAME_LEN + sizeof(ERR_STR2) + 1 /* null char */] = { 0 }; - - char *dest = buf; - for (size_t i = 0 ; i < sizeof(str)/ sizeof(str[0]); i++) { - dest = strcat(dest, str[i]); - } - esp_system_abort(buf); + /* If task has live floating point registers somewhere, release them */ + _xt_coproc_release( xMPUSettings->coproc_area ); } +#endif /* portUSING_MPU_WRAPPERS */ + +// --------------------- App Start-up ---------------------- #if !CONFIG_FREERTOS_UNICORE void esp_startup_start_app_other_cores(void) { - // For now, we only support up to two core: 0 and 1. - if (xPortGetCoreID() >= 2) { - abort(); - } + // For now, we only support up to two core: 0 and 1. + if (xPortGetCoreID() >= 2) { + abort(); + } - // Wait for FreeRTOS initialization to finish on PRO CPU - while (port_xSchedulerRunning[0] == 0) { - ; - } + // Wait for FreeRTOS initialization to finish on PRO CPU + while (port_xSchedulerRunning[0] == 0) { + ; + } #if CONFIG_APPTRACE_ENABLE - // [refactor-todo] move to esp_system initialization - esp_err_t err = esp_apptrace_init(); - assert(err == ESP_OK && "Failed to init apptrace module on APP CPU!"); + // [refactor-todo] move to esp_system initialization + esp_err_t err = esp_apptrace_init(); + assert(err == ESP_OK && "Failed to init apptrace module on APP CPU!"); #endif #if CONFIG_ESP_INT_WDT - //Initialize the interrupt watch dog for CPU1. - esp_int_wdt_cpu_init(); + //Initialize the interrupt watch dog for CPU1. + esp_int_wdt_cpu_init(); #endif - esp_crosscore_int_init(); -#if CONFIG_IDF_TARGET_ESP32 - esp_dport_access_int_init(); -#endif + esp_crosscore_int_init(); - ESP_EARLY_LOGI(TAG, "Starting scheduler on APP CPU."); - xPortStartScheduler(); - abort(); /* Only get to here if FreeRTOS somehow very broken */ + ESP_EARLY_LOGI(TAG, "Starting scheduler on APP CPU."); + xPortStartScheduler(); + abort(); /* Only get to here if FreeRTOS somehow very broken */ } #endif // !CONFIG_FREERTOS_UNICORE @@ -534,12 +454,12 @@ void esp_startup_start_app(void) { #if !CONFIG_ESP_INT_WDT #if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX - assert(!soc_has_cache_lock_bug() && "ESP32 Rev 3 + Dual Core + PSRAM requires INT WDT enabled in project config!"); + assert(!soc_has_cache_lock_bug() && "ESP32 Rev 3 + Dual Core + PSRAM requires INT WDT enabled in project config!"); #endif #endif - esp_startup_start_app_common(); + esp_startup_start_app_common(); - ESP_LOGI(TAG, "Starting scheduler on PRO CPU."); - vTaskStartScheduler(); + ESP_LOGI(TAG, "Starting scheduler on PRO CPU."); + vTaskStartScheduler(); } diff --git a/components/freertos/port/xtensa/portasm.S b/components/freertos/port/xtensa/portasm.S index 86f452e12f..188454c164 100644 --- a/components/freertos/port/xtensa/portasm.S +++ b/components/freertos/port/xtensa/portasm.S @@ -270,6 +270,7 @@ _frxt_int_exit: * ********************************************************************************************************** */ +#ifdef CONFIG_FREERTOS_SYSTICK_USES_CCOUNT .globl _frxt_timer_int .type _frxt_timer_int,@function .align 4 @@ -321,7 +322,7 @@ _frxt_timer_int: s32i a3, sp, 8 #endif - /* Call the FreeRTOS tick handler (see port.c). */ + /* Call the FreeRTOS tick handler (see port_systick.c). */ #ifdef __XTENSA_CALL0_ABI__ call0 xPortSysTickHandler #else @@ -347,6 +348,7 @@ _frxt_timer_int: #endif // CONFIG_PM_TRACE RET(16) +#endif // CONFIG_FREERTOS_SYSTICK_USES_CCOUNT /* ********************************************************************************************************** @@ -358,6 +360,7 @@ _frxt_timer_int: * ********************************************************************************************************** */ +#ifdef CONFIG_FREERTOS_SYSTICK_USES_CCOUNT .globl _frxt_tick_timer_init .type _frxt_tick_timer_init,@function .align 4 @@ -391,6 +394,7 @@ _frxt_tick_timer_init: #endif RET(16) +#endif // CONFIG_FREERTOS_SYSTICK_USES_CCOUNT /* ********************************************************************************************************** diff --git a/components/freertos/port/xtensa/xtensa_vector_defaults.S b/components/freertos/port/xtensa/xtensa_vector_defaults.S index 59f127b941..791116cfbc 100644 --- a/components/freertos/port/xtensa/xtensa_vector_defaults.S +++ b/components/freertos/port/xtensa/xtensa_vector_defaults.S @@ -32,6 +32,21 @@ The default behaviour is to just exit the interrupt or call the panic handler on .align 4 _xt_debugexception: +#if (CONFIG_ESP32_ECO3_CACHE_LOCK_FIX && CONFIG_BTDM_CTRL_HLI) +#define XT_DEBUGCAUSE_DI (5) + getcoreid a0 +#if (CONFIG_BTDM_CTRL_PINNED_TO_CORE == PRO_CPU_NUM) + beqz a0, 1f +#else + bnez a0, 1f +#endif + + rsr a0, DEBUGCAUSE + extui a0, a0, XT_DEBUGCAUSE_DI, 1 + bnez a0, _xt_debug_di_exc +1: +#endif //(CONFIG_ESP32_ECO3_CACHE_LOCK_FIX && CONFIG_BTDM_CTRL_HLI) + movi a0,PANIC_RSN_DEBUGEXCEPTION wsr a0,EXCCAUSE /* _xt_panic assumes a level 1 exception. As we're @@ -44,6 +59,66 @@ _xt_debugexception: call0 _xt_panic /* does not return */ rfi XCHAL_DEBUGLEVEL +#if (CONFIG_ESP32_ECO3_CACHE_LOCK_FIX && CONFIG_BTDM_CTRL_HLI) + .align 4 +_xt_debug_di_exc: + + /* + The delay time can be calculated by the following formula: + T = ceil(0.25 + max(t1, t2)) us + + t1 = 80 / f1, t2 = (1 + 14/N) * 20 / f2 + + f1: PSRAM access frequency, unit: MHz. + f2: Flash access frequency, unit: MHz. + + When flash is slow/fast read, N = 1. + When flash is DOUT/DIO read, N = 2. + When flash is QOUT/QIO read, N = 4. + + And after testing, when CPU frequency is 240 MHz, it will take 1us to loop 27 times. + */ +#if defined(CONFIG_ESPTOOLPY_FLASHMODE_QIO) || defined(CONFIG_ESPTOOLPY_FLASHMODE_QOUT) + +# if defined(CONFIG_ESPTOOLPY_FLASHFREQ_80M) && defined(CONFIG_SPIRAM_SPEED_80M) + movi a0, 54 +# elif defined(CONFIG_ESPTOOLPY_FLASHFREQ_80M) && defined(CONFIG_SPIRAM_SPEED_40M) + movi a0, 81 +# elif defined(CONFIG_ESPTOOLPY_FLASHFREQ_40M) && defined(CONFIG_SPIRAM_SPEED_40M) + movi a0, 81 +# elif defined(CONFIG_ESPTOOLPY_FLASHFREQ_26M) && defined(CONFIG_SPIRAM_SPEED_40M) + movi a0, 108 +# else + movi a0, 135 +# endif + +#elif defined(CONFIG_ESPTOOLPY_FLASHMODE_DIO) || defined(CONFIG_ESPTOOLPY_FLASHMODE_DOUT) + +# if defined(CONFIG_ESPTOOLPY_FLASHFREQ_80M) && defined(CONFIG_SPIRAM_SPEED_80M) + movi a0, 81 +# elif defined(CONFIG_ESPTOOLPY_FLASHFREQ_80M) && defined(CONFIG_SPIRAM_SPEED_40M) + movi a0, 81 +# elif defined(CONFIG_ESPTOOLPY_FLASHFREQ_40M) && defined(CONFIG_SPIRAM_SPEED_40M) + movi a0, 135 +# elif defined(CONFIG_ESPTOOLPY_FLASHFREQ_26M) && defined(CONFIG_SPIRAM_SPEED_40M) + movi a0, 189 +# else + movi a0, 243 +# endif + +#else + movi a0, 243 +#endif + +1: addi a0, a0, -1 /* delay_us(N) */ + .rept 4 + nop + .endr + bnez a0, 1b + + rsr a0, EXCSAVE+XCHAL_DEBUGLEVEL + rfi XCHAL_DEBUGLEVEL +#endif //(CONFIG_ESP32_ECO3_CACHE_LOCK_FIX && CONFIG_BTDM_CTRL_HLI) #endif /* Debug exception */ diff --git a/components/freertos/port/xtensa/xtensa_vectors.S b/components/freertos/port/xtensa/xtensa_vectors.S index 4fd27e45c0..1560ff27d6 100644 --- a/components/freertos/port/xtensa/xtensa_vectors.S +++ b/components/freertos/port/xtensa/xtensa_vectors.S @@ -289,9 +289,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. rsil a3, \level - 1 /* lower interrupt level by 1 */ #endif + #ifdef XT_RTOS_TIMER_INT movi a3, XT_TIMER_INTEN /* a3 = timer interrupt bit */ wsr a4, INTCLEAR /* clear sw or edge-triggered interrupt */ beq a3, a4, 7f /* if timer interrupt then skip table */ + #else + wsr a4, INTCLEAR /* clear sw or edge-triggered interrupt */ + #endif // XT_RTOS_TIMER_INT find_ms_setbit a3, a4, a3, 0 /* a3 = interrupt number */ @@ -316,6 +320,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. j .L_xt_user_int_&level& /* check for more interrupts */ #endif + #ifdef XT_RTOS_TIMER_INT 7: .ifeq XT_TIMER_INTPRI - \level @@ -335,6 +340,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. call4 XT_RTOS_TIMER_INT #endif .endif + #endif // XT_RTOS_TIMER_INT #ifdef XT_USE_SWPRI j 8f @@ -633,11 +639,11 @@ _xt_user_exc: rsr a0, EXCSAVE_1 /* save interruptee's a0 */ s32i a0, sp, XT_STK_A0 - /* Set up PS for C, reenable hi-pri interrupts, and clear EXCM. */ + /* Set up PS for C, reenable debug and NMI interrupts, and clear EXCM. */ #ifdef __XTENSA_CALL0_ABI__ - movi a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM + movi a0, PS_INTLEVEL(XCHAL_DEBUGLEVEL - 2) | PS_UM #else - movi a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE + movi a0, PS_INTLEVEL(XCHAL_DEBUGLEVEL - 2) | PS_UM | PS_WOE #endif wsr a0, PS diff --git a/components/freertos/queue.c b/components/freertos/queue.c index 81df2db898..4a6973adf8 100644 --- a/components/freertos/queue.c +++ b/components/freertos/queue.c @@ -1,6 +1,6 @@ /* - * FreeRTOS Kernel V10.2.1 - * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V10.4.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * 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 @@ -19,18 +19,17 @@ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS * - * 1 tab == 4 spaces! */ #include #include /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining -all the API functions to use the MPU wrappers. That should only be done when -task.h is included from an application file. */ + * all the API functions to use the MPU wrappers. That should only be done when + * task.h is included from an application file. */ #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE #include "FreeRTOS.h" @@ -38,102 +37,116 @@ task.h is included from an application file. */ #include "queue.h" #if ( configUSE_CO_ROUTINES == 1 ) - #include "croutine.h" + #include "croutine.h" +#endif + +#ifdef ESP_PLATFORM +#define taskCRITICAL_MUX &((Queue_t *)pxQueue)->mux +#undef taskENTER_CRITICAL +#undef taskEXIT_CRITICAL +#undef taskENTER_CRITICAL_ISR +#undef taskEXIT_CRITICAL_ISR +#define taskENTER_CRITICAL( ) portENTER_CRITICAL( taskCRITICAL_MUX ) +#define taskEXIT_CRITICAL( ) portEXIT_CRITICAL( taskCRITICAL_MUX ) +#define taskENTER_CRITICAL_ISR( ) portENTER_CRITICAL_ISR( taskCRITICAL_MUX ) +#define taskEXIT_CRITICAL_ISR( ) portEXIT_CRITICAL_ISR( taskCRITICAL_MUX ) #endif /* Lint e9021, e961 and e750 are suppressed as a MISRA exception justified -because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined -for the header files above, but not in this file, in order to generate the -correct privileged Vs unprivileged linkage and placement. */ + * because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined + * for the header files above, but not in this file, in order to generate the + * correct privileged Vs unprivileged linkage and placement. */ #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021. */ /* Constants used with the cRxLock and cTxLock structure members. */ -#define queueUNLOCKED ( ( int8_t ) -1 ) -#define queueLOCKED_UNMODIFIED ( ( int8_t ) 0 ) +#define queueUNLOCKED ( ( int8_t ) -1 ) +#define queueLOCKED_UNMODIFIED ( ( int8_t ) 0 ) +#define queueINT8_MAX ( ( int8_t ) 127 ) /* When the Queue_t structure is used to represent a base queue its pcHead and -pcTail members are used as pointers into the queue storage area. When the -Queue_t structure is used to represent a mutex pcHead and pcTail pointers are -not necessary, and the pcHead pointer is set to NULL to indicate that the -structure instead holds a pointer to the mutex holder (if any). Map alternative -names to the pcHead and structure member to ensure the readability of the code -is maintained. The QueuePointers_t and SemaphoreData_t types are used to form -a union as their usage is mutually exclusive dependent on what the queue is -being used for. */ -#define uxQueueType pcHead -#define queueQUEUE_IS_MUTEX NULL + * pcTail members are used as pointers into the queue storage area. When the + * Queue_t structure is used to represent a mutex pcHead and pcTail pointers are + * not necessary, and the pcHead pointer is set to NULL to indicate that the + * structure instead holds a pointer to the mutex holder (if any). Map alternative + * names to the pcHead and structure member to ensure the readability of the code + * is maintained. The QueuePointers_t and SemaphoreData_t types are used to form + * a union as their usage is mutually exclusive dependent on what the queue is + * being used for. */ +#define uxQueueType pcHead +#define queueQUEUE_IS_MUTEX NULL typedef struct QueuePointers { - int8_t *pcTail; /*< Points to the byte at the end of the queue storage area. Once more byte is allocated than necessary to store the queue items, this is used as a marker. */ - int8_t *pcReadFrom; /*< Points to the last place that a queued item was read from when the structure is used as a queue. */ + int8_t * pcTail; /*< Points to the byte at the end of the queue storage area. Once more byte is allocated than necessary to store the queue items, this is used as a marker. */ + int8_t * pcReadFrom; /*< Points to the last place that a queued item was read from when the structure is used as a queue. */ } QueuePointers_t; typedef struct SemaphoreData { - TaskHandle_t xMutexHolder; /*< The handle of the task that holds the mutex. */ - UBaseType_t uxRecursiveCallCount;/*< Maintains a count of the number of times a recursive mutex has been recursively 'taken' when the structure is used as a mutex. */ + TaskHandle_t xMutexHolder; /*< The handle of the task that holds the mutex. */ + UBaseType_t uxRecursiveCallCount; /*< Maintains a count of the number of times a recursive mutex has been recursively 'taken' when the structure is used as a mutex. */ } SemaphoreData_t; /* Semaphores do not actually store or copy data, so have an item size of -zero. */ -#define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( ( UBaseType_t ) 0 ) -#define queueMUTEX_GIVE_BLOCK_TIME ( ( TickType_t ) 0U ) + * zero. */ +#define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( ( UBaseType_t ) 0 ) +#define queueMUTEX_GIVE_BLOCK_TIME ( ( TickType_t ) 0U ) -#if( configUSE_PREEMPTION == 0 ) - /* If the cooperative scheduler is being used then a yield should not be - performed just because a higher priority task has been woken. */ - #define queueYIELD_IF_USING_PREEMPTION() +#if ( configUSE_PREEMPTION == 0 ) + +/* If the cooperative scheduler is being used then a yield should not be + * performed just because a higher priority task has been woken. */ + #define queueYIELD_IF_USING_PREEMPTION() #else - #define queueYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API() + #define queueYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API() #endif /* * Definition of the queue used by the scheduler. * Items are queued by copy, not reference. See the following link for the - * rationale: https://www.freertos.org/Embedded-RTOS-Queues.html + * rationale: https://www.FreeRTOS.org/Embedded-RTOS-Queues.html */ -typedef struct QueueDefinition /* The old naming convention is used to prevent breaking kernel aware debuggers. */ +typedef struct QueueDefinition /* The old naming convention is used to prevent breaking kernel aware debuggers. */ { - int8_t *pcHead; /*< Points to the beginning of the queue storage area. */ - int8_t *pcWriteTo; /*< Points to the free next place in the storage area. */ + int8_t * pcHead; /*< Points to the beginning of the queue storage area. */ + int8_t * pcWriteTo; /*< Points to the free next place in the storage area. */ - union - { - QueuePointers_t xQueue; /*< Data required exclusively when this structure is used as a queue. */ - SemaphoreData_t xSemaphore; /*< Data required exclusively when this structure is used as a semaphore. */ - } u; + union + { + QueuePointers_t xQueue; /*< Data required exclusively when this structure is used as a queue. */ + SemaphoreData_t xSemaphore; /*< Data required exclusively when this structure is used as a semaphore. */ + } u; - List_t xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */ - List_t xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */ + List_t xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */ + List_t xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */ - volatile UBaseType_t uxMessagesWaiting;/*< The number of items currently in the queue. */ - UBaseType_t uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */ - UBaseType_t uxItemSize; /*< The size of each items that the queue will hold. */ + volatile UBaseType_t uxMessagesWaiting; /*< The number of items currently in the queue. */ + UBaseType_t uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */ + UBaseType_t uxItemSize; /*< The size of each items that the queue will hold. */ - volatile int8_t cRxLock; /*< Stores the number of items received from the queue (removed from the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ - volatile int8_t cTxLock; /*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ + volatile int8_t cRxLock; /*< Stores the number of items received from the queue (removed from the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ + volatile int8_t cTxLock; /*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ - #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) - uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the memory used by the queue was statically allocated to ensure no attempt is made to free the memory. */ - #endif + #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the memory used by the queue was statically allocated to ensure no attempt is made to free the memory. */ + #endif - #if ( configUSE_QUEUE_SETS == 1 ) - struct QueueDefinition *pxQueueSetContainer; - #endif - - #if ( configUSE_TRACE_FACILITY == 1 ) - UBaseType_t uxQueueNumber; - uint8_t ucQueueType; - #endif - - portMUX_TYPE mux; //Mutex required due to SMP + #if ( configUSE_QUEUE_SETS == 1 ) + struct QueueDefinition * pxQueueSetContainer; + #endif + #if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxQueueNumber; + uint8_t ucQueueType; + #endif +#ifdef ESP_PLATFORM + portMUX_TYPE mux; //Mutex required due to SMP +#endif // ESP_PLATFORM } xQUEUE; /* The old xQUEUE name is maintained above then typedefed to the new Queue_t -name below to enable the use of older kernel aware debuggers. */ + * name below to enable the use of older kernel aware debuggers. */ typedef xQUEUE Queue_t; /*-----------------------------------------------------------*/ @@ -144,28 +157,28 @@ typedef xQUEUE Queue_t; */ #if ( configQUEUE_REGISTRY_SIZE > 0 ) - /* The type stored within the queue registry array. This allows a name - to be assigned to each queue making kernel aware debugging a little - more user friendly. */ - typedef struct QUEUE_REGISTRY_ITEM - { - const char *pcQueueName; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ - QueueHandle_t xHandle; - } xQueueRegistryItem; +/* The type stored within the queue registry array. This allows a name + * to be assigned to each queue making kernel aware debugging a little + * more user friendly. */ + typedef struct QUEUE_REGISTRY_ITEM + { + const char * pcQueueName; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + QueueHandle_t xHandle; + } xQueueRegistryItem; - /* The old xQueueRegistryItem name is maintained above then typedefed to the - new xQueueRegistryItem name below to enable the use of older kernel aware - debuggers. */ - typedef xQueueRegistryItem QueueRegistryItem_t; - - /* The queue registry is simply an array of QueueRegistryItem_t structures. - The pcQueueName member of a structure being NULL is indicative of the - array position being vacant. */ - PRIVILEGED_DATA QueueRegistryItem_t xQueueRegistry[ configQUEUE_REGISTRY_SIZE ]; - - //Need to add queue registry mutex to protect against simultaneous access - static portMUX_TYPE queue_registry_spinlock = portMUX_INITIALIZER_UNLOCKED; +/* The old xQueueRegistryItem name is maintained above then typedefed to the + * new xQueueRegistryItem name below to enable the use of older kernel aware + * debuggers. */ + typedef xQueueRegistryItem QueueRegistryItem_t; +/* The queue registry is simply an array of QueueRegistryItem_t structures. + * The pcQueueName member of a structure being NULL is indicative of the + * array position being vacant. */ + PRIVILEGED_DATA QueueRegistryItem_t xQueueRegistry[ configQUEUE_REGISTRY_SIZE ]; +#ifdef ESP_PLATFORM + //Need to add queue registry mutex to protect against simultaneous access + static portMUX_TYPE queue_registry_spinlock = portMUX_INITIALIZER_UNLOCKED; +#endif // ESP_PLATFORM #endif /* configQUEUE_REGISTRY_SIZE */ /* @@ -183,58 +196,67 @@ static void prvUnlockQueue( Queue_t * const pxQueue ) PRIVILEGED_FUNCTION; * * @return pdTRUE if the queue contains no items, otherwise pdFALSE. */ -static BaseType_t prvIsQueueEmpty( const Queue_t *pxQueue ) PRIVILEGED_FUNCTION; +static BaseType_t prvIsQueueEmpty( const Queue_t * pxQueue ) PRIVILEGED_FUNCTION; /* * Uses a critical section to determine if there is any space in a queue. * * @return pdTRUE if there is no space, otherwise pdFALSE; */ -static BaseType_t prvIsQueueFull( const Queue_t *pxQueue ) PRIVILEGED_FUNCTION; +static BaseType_t prvIsQueueFull( const Queue_t * pxQueue ) PRIVILEGED_FUNCTION; /* * Copies an item into the queue, either at the front of the queue or the * back of the queue. */ -static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueue, const BaseType_t xPosition ) PRIVILEGED_FUNCTION; +static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, + const void * pvItemToQueue, + const BaseType_t xPosition ) PRIVILEGED_FUNCTION; /* * Copies an item out of a queue. */ -static void prvCopyDataFromQueue( Queue_t * const pxQueue, void * const pvBuffer ) PRIVILEGED_FUNCTION; +static void prvCopyDataFromQueue( Queue_t * const pxQueue, + void * const pvBuffer ) PRIVILEGED_FUNCTION; #if ( configUSE_QUEUE_SETS == 1 ) - /* - * Checks to see if a queue is a member of a queue set, and if so, notifies - * the queue set that the queue contains data. - */ - static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue, const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION; + +/* + * Checks to see if a queue is a member of a queue set, and if so, notifies + * the queue set that the queue contains data. + */ + static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue, const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION; #endif /* * Called after a Queue_t structure has been allocated either statically or * dynamically to fill in the structure's members. */ -static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, const uint8_t ucQueueType, Queue_t *pxNewQueue ) PRIVILEGED_FUNCTION; +static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, + const UBaseType_t uxItemSize, + uint8_t * pucQueueStorage, + const uint8_t ucQueueType, + Queue_t * pxNewQueue ) PRIVILEGED_FUNCTION; /* * Mutexes are a special type of queue. When a mutex is created, first the * queue is created, then prvInitialiseMutex() is called to configure the queue * as a mutex. */ -#if( configUSE_MUTEXES == 1 ) - static void prvInitialiseMutex( Queue_t *pxNewQueue ) PRIVILEGED_FUNCTION; +#if ( configUSE_MUTEXES == 1 ) + static void prvInitialiseMutex( Queue_t * pxNewQueue ) PRIVILEGED_FUNCTION; #endif -#if( configUSE_MUTEXES == 1 ) - /* - * If a task waiting for a mutex causes the mutex holder to inherit a - * priority, but the waiting task times out, then the holder should - * disinherit the priority - but only down to the highest priority of any - * other tasks that are waiting for the same mutex. This function returns - * that priority. - */ - static UBaseType_t prvGetDisinheritPriorityAfterTimeout( const Queue_t * const pxQueue ) PRIVILEGED_FUNCTION; +#if ( configUSE_MUTEXES == 1 ) + +/* + * If a task waiting for a mutex causes the mutex holder to inherit a + * priority, but the waiting task times out, then the holder should + * disinherit the priority - but only down to the highest priority of any + * other tasks that are waiting for the same mutex. This function returns + * that priority. + */ + static UBaseType_t prvGetDisinheritPriorityAfterTimeout( const Queue_t * const pxQueue ) PRIVILEGED_FUNCTION; #endif /*-----------------------------------------------------------*/ @@ -242,2715 +264,2884 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, const UBaseT * Macro to mark a queue as locked. Locking a queue prevents an ISR from * accessing the queue event lists. */ -#define prvLockQueue( pxQueue ) \ - taskENTER_CRITICAL( &pxQueue->mux); \ - { \ - if( ( pxQueue )->cRxLock == queueUNLOCKED ) \ - { \ - ( pxQueue )->cRxLock = queueLOCKED_UNMODIFIED; \ - } \ - if( ( pxQueue )->cTxLock == queueUNLOCKED ) \ - { \ - ( pxQueue )->cTxLock = queueLOCKED_UNMODIFIED; \ - } \ - } \ - taskEXIT_CRITICAL( &pxQueue->mux) +#define prvLockQueue( pxQueue ) \ + taskENTER_CRITICAL(); \ + { \ + if( ( pxQueue )->cRxLock == queueUNLOCKED ) \ + { \ + ( pxQueue )->cRxLock = queueLOCKED_UNMODIFIED; \ + } \ + if( ( pxQueue )->cTxLock == queueUNLOCKED ) \ + { \ + ( pxQueue )->cTxLock = queueLOCKED_UNMODIFIED; \ + } \ + } \ + taskEXIT_CRITICAL() /*-----------------------------------------------------------*/ -BaseType_t xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue ) +BaseType_t xQueueGenericReset( QueueHandle_t xQueue, + BaseType_t xNewQueue ) { -Queue_t * const pxQueue = xQueue; + Queue_t * const pxQueue = xQueue; - configASSERT( pxQueue ); + configASSERT( pxQueue ); - if( xNewQueue == pdTRUE ) - { - vPortCPUInitializeMutex(&pxQueue->mux); - } +#ifdef ESP_PLATFORM + if( xNewQueue == pdTRUE ) + { + vPortCPUInitializeMutex(&pxQueue->mux); + } +#endif // ESP_PLATFORM - taskENTER_CRITICAL( &pxQueue->mux); - { - pxQueue->u.xQueue.pcTail = pxQueue->pcHead + ( pxQueue->uxLength * pxQueue->uxItemSize ); /*lint !e9016 Pointer arithmetic allowed on char types, especially when it assists conveying intent. */ - pxQueue->uxMessagesWaiting = ( UBaseType_t ) 0U; - pxQueue->pcWriteTo = pxQueue->pcHead; - pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead + ( ( pxQueue->uxLength - 1U ) * pxQueue->uxItemSize ); /*lint !e9016 Pointer arithmetic allowed on char types, especially when it assists conveying intent. */ - pxQueue->cRxLock = queueUNLOCKED; - pxQueue->cTxLock = queueUNLOCKED; + taskENTER_CRITICAL(); + { + pxQueue->u.xQueue.pcTail = pxQueue->pcHead + ( pxQueue->uxLength * pxQueue->uxItemSize ); /*lint !e9016 Pointer arithmetic allowed on char types, especially when it assists conveying intent. */ + pxQueue->uxMessagesWaiting = ( UBaseType_t ) 0U; + pxQueue->pcWriteTo = pxQueue->pcHead; + pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead + ( ( pxQueue->uxLength - 1U ) * pxQueue->uxItemSize ); /*lint !e9016 Pointer arithmetic allowed on char types, especially when it assists conveying intent. */ + pxQueue->cRxLock = queueUNLOCKED; + pxQueue->cTxLock = queueUNLOCKED; - if( xNewQueue == pdFALSE ) - { - /* If there are tasks blocked waiting to read from the queue, then - the tasks will remain blocked as after this function exits the queue - will still be empty. If there are tasks blocked waiting to write to - the queue, then one should be unblocked as after this function exits - it will be possible to write to it. */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) - { - queueYIELD_IF_USING_PREEMPTION(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - /* Ensure the event queues start in the correct state. */ - vListInitialise( &( pxQueue->xTasksWaitingToSend ) ); - vListInitialise( &( pxQueue->xTasksWaitingToReceive ) ); - } - } - taskEXIT_CRITICAL( &pxQueue->mux); + if( xNewQueue == pdFALSE ) + { + /* If there are tasks blocked waiting to read from the queue, then + * the tasks will remain blocked as after this function exits the queue + * will still be empty. If there are tasks blocked waiting to write to + * the queue, then one should be unblocked as after this function exits + * it will be possible to write to it. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* Ensure the event queues start in the correct state. */ + vListInitialise( &( pxQueue->xTasksWaitingToSend ) ); + vListInitialise( &( pxQueue->xTasksWaitingToReceive ) ); + } + } + taskEXIT_CRITICAL(); - /* A value is returned for calling semantic consistency with previous - versions. */ - return pdPASS; + /* A value is returned for calling semantic consistency with previous + * versions. */ + return pdPASS; } /*-----------------------------------------------------------*/ -#if( configSUPPORT_STATIC_ALLOCATION == 1 ) +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) - QueueHandle_t xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, StaticQueue_t *pxStaticQueue, const uint8_t ucQueueType ) - { - Queue_t *pxNewQueue; + QueueHandle_t xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, + const UBaseType_t uxItemSize, + uint8_t * pucQueueStorage, + StaticQueue_t * pxStaticQueue, + const uint8_t ucQueueType ) + { + Queue_t * pxNewQueue; - configASSERT( uxQueueLength > ( UBaseType_t ) 0 ); + configASSERT( uxQueueLength > ( UBaseType_t ) 0 ); - /* The StaticQueue_t structure and the queue storage area must be - supplied. */ - configASSERT( pxStaticQueue != NULL ); + /* The StaticQueue_t structure and the queue storage area must be + * supplied. */ + configASSERT( pxStaticQueue != NULL ); - /* A queue storage area should be provided if the item size is not 0, and - should not be provided if the item size is 0. */ - configASSERT( !( ( pucQueueStorage != NULL ) && ( uxItemSize == 0 ) ) ); - configASSERT( !( ( pucQueueStorage == NULL ) && ( uxItemSize != 0 ) ) ); + /* A queue storage area should be provided if the item size is not 0, and + * should not be provided if the item size is 0. */ + configASSERT( !( ( pucQueueStorage != NULL ) && ( uxItemSize == 0 ) ) ); + configASSERT( !( ( pucQueueStorage == NULL ) && ( uxItemSize != 0 ) ) ); - #if( configASSERT_DEFINED == 1 ) - { - /* Sanity check that the size of the structure used to declare a - variable of type StaticQueue_t or StaticSemaphore_t equals the size of - the real queue and semaphore structures. */ - volatile size_t xSize = sizeof( StaticQueue_t ); - configASSERT( xSize == sizeof( Queue_t ) ); - ( void ) xSize; /* Keeps lint quiet when configASSERT() is not defined. */ - } - #endif /* configASSERT_DEFINED */ + #if ( configASSERT_DEFINED == 1 ) + { + /* Sanity check that the size of the structure used to declare a + * variable of type StaticQueue_t or StaticSemaphore_t equals the size of + * the real queue and semaphore structures. */ + volatile size_t xSize = sizeof( StaticQueue_t ); - /* The address of a statically allocated queue was passed in, use it. - The address of a statically allocated storage area was also passed in - but is already set. */ - pxNewQueue = ( Queue_t * ) pxStaticQueue; /*lint !e740 !e9087 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */ + /* This assertion cannot be branch covered in unit tests */ + configASSERT( xSize == sizeof( Queue_t ) ); /* LCOV_EXCL_BR_LINE */ + ( void ) xSize; /* Keeps lint quiet when configASSERT() is not defined. */ + } + #endif /* configASSERT_DEFINED */ - if( pxNewQueue != NULL ) - { - #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) - { - /* Queues can be allocated wither statically or dynamically, so - note this queue was allocated statically in case the queue is - later deleted. */ - pxNewQueue->ucStaticallyAllocated = pdTRUE; - } - #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ + /* The address of a statically allocated queue was passed in, use it. + * The address of a statically allocated storage area was also passed in + * but is already set. */ + pxNewQueue = ( Queue_t * ) pxStaticQueue; /*lint !e740 !e9087 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */ - prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue ); - } - else - { - traceQUEUE_CREATE_FAILED( ucQueueType ); - mtCOVERAGE_TEST_MARKER(); - } + if( pxNewQueue != NULL ) + { + #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + { + /* Queues can be allocated wither statically or dynamically, so + * note this queue was allocated statically in case the queue is + * later deleted. */ + pxNewQueue->ucStaticallyAllocated = pdTRUE; + } + #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ - return pxNewQueue; - } + prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue ); + } + else + { + traceQUEUE_CREATE_FAILED( ucQueueType ); + mtCOVERAGE_TEST_MARKER(); + } + + return pxNewQueue; + } #endif /* configSUPPORT_STATIC_ALLOCATION */ /*-----------------------------------------------------------*/ -#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) +#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) - QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType ) - { - Queue_t *pxNewQueue; - size_t xQueueSizeInBytes; - uint8_t *pucQueueStorage; + QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, + const UBaseType_t uxItemSize, + const uint8_t ucQueueType ) + { + Queue_t * pxNewQueue = NULL; + size_t xQueueSizeInBytes; + uint8_t * pucQueueStorage; - configASSERT( uxQueueLength > ( UBaseType_t ) 0 ); + configASSERT( uxQueueLength > ( UBaseType_t ) 0 ); - if( uxItemSize == ( UBaseType_t ) 0 ) - { - /* There is not going to be a queue storage area. */ - xQueueSizeInBytes = ( size_t ) 0; - } - else - { - /* Allocate enough space to hold the maximum number of items that - can be in the queue at any time. */ - xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ - } + if( uxItemSize == ( UBaseType_t ) 0 ) + { + /* There is not going to be a queue storage area. */ + xQueueSizeInBytes = ( size_t ) 0; + } + else + { + /* Allocate enough space to hold the maximum number of items that + * can be in the queue at any time. It is valid for uxItemSize to be + * zero in the case the queue is used as a semaphore. */ + xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + } - /* Check for multiplication overflow. */ - configASSERT( ( uxItemSize == 0 ) || ( uxQueueLength == ( xQueueSizeInBytes / uxItemSize ) ) ); + /* Check for multiplication overflow. */ + configASSERT( ( uxItemSize == 0 ) || ( uxQueueLength == ( xQueueSizeInBytes / uxItemSize ) ) ); - /* Check for addition overflow. */ - configASSERT( ( sizeof( Queue_t ) + xQueueSizeInBytes ) > xQueueSizeInBytes ); + /* Check for addition overflow. */ + configASSERT( ( sizeof( Queue_t ) + xQueueSizeInBytes ) > xQueueSizeInBytes ); - /* Allocate the queue and storage area. Justification for MISRA - deviation as follows: pvPortMalloc() always ensures returned memory - blocks are aligned per the requirements of the MCU stack. In this case - pvPortMalloc() must return a pointer that is guaranteed to meet the - alignment requirements of the Queue_t structure - which in this case - is an int8_t *. Therefore, whenever the stack alignment requirements - are greater than or equal to the pointer to char requirements the cast - is safe. In other cases alignment requirements are not strict (one or - two bytes). */ - pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes ); /*lint !e9087 !e9079 see comment above. */ + /* Allocate the queue and storage area. Justification for MISRA + * deviation as follows: pvPortMalloc() always ensures returned memory + * blocks are aligned per the requirements of the MCU stack. In this case + * pvPortMalloc() must return a pointer that is guaranteed to meet the + * alignment requirements of the Queue_t structure - which in this case + * is an int8_t *. Therefore, whenever the stack alignment requirements + * are greater than or equal to the pointer to char requirements the cast + * is safe. In other cases alignment requirements are not strict (one or + * two bytes). */ + pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes ); /*lint !e9087 !e9079 see comment above. */ - if( pxNewQueue != NULL ) - { - /* Jump past the queue structure to find the location of the queue - storage area. */ - pucQueueStorage = ( uint8_t * ) pxNewQueue; - pucQueueStorage += sizeof( Queue_t ); /*lint !e9016 Pointer arithmetic allowed on char types, especially when it assists conveying intent. */ + if( pxNewQueue != NULL ) + { + /* Jump past the queue structure to find the location of the queue + * storage area. */ + pucQueueStorage = ( uint8_t * ) pxNewQueue; + pucQueueStorage += sizeof( Queue_t ); /*lint !e9016 Pointer arithmetic allowed on char types, especially when it assists conveying intent. */ - #if( configSUPPORT_STATIC_ALLOCATION == 1 ) - { - /* Queues can be created either statically or dynamically, so - note this task was created dynamically in case it is later - deleted. */ - pxNewQueue->ucStaticallyAllocated = pdFALSE; - } - #endif /* configSUPPORT_STATIC_ALLOCATION */ + #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + { + /* Queues can be created either statically or dynamically, so + * note this task was created dynamically in case it is later + * deleted. */ + pxNewQueue->ucStaticallyAllocated = pdFALSE; + } + #endif /* configSUPPORT_STATIC_ALLOCATION */ - prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue ); - } - else - { - traceQUEUE_CREATE_FAILED( ucQueueType ); - mtCOVERAGE_TEST_MARKER(); - } + prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue ); + } + else + { + traceQUEUE_CREATE_FAILED( ucQueueType ); + mtCOVERAGE_TEST_MARKER(); + } - return pxNewQueue; - } + return pxNewQueue; + } #endif /* configSUPPORT_STATIC_ALLOCATION */ /*-----------------------------------------------------------*/ -static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, const uint8_t ucQueueType, Queue_t *pxNewQueue ) +static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, + const UBaseType_t uxItemSize, + uint8_t * pucQueueStorage, + const uint8_t ucQueueType, + Queue_t * pxNewQueue ) { - /* Remove compiler warnings about unused parameters should - configUSE_TRACE_FACILITY not be set to 1. */ - ( void ) ucQueueType; + /* Remove compiler warnings about unused parameters should + * configUSE_TRACE_FACILITY not be set to 1. */ + ( void ) ucQueueType; - if( uxItemSize == ( UBaseType_t ) 0 ) - { - /* No RAM was allocated for the queue storage area, but PC head cannot - be set to NULL because NULL is used as a key to say the queue is used as - a mutex. Therefore just set pcHead to point to the queue as a benign - value that is known to be within the memory map. */ - pxNewQueue->pcHead = ( int8_t * ) pxNewQueue; - } - else - { - /* Set the head to the start of the queue storage area. */ - pxNewQueue->pcHead = ( int8_t * ) pucQueueStorage; - } + if( uxItemSize == ( UBaseType_t ) 0 ) + { + /* No RAM was allocated for the queue storage area, but PC head cannot + * be set to NULL because NULL is used as a key to say the queue is used as + * a mutex. Therefore just set pcHead to point to the queue as a benign + * value that is known to be within the memory map. */ + pxNewQueue->pcHead = ( int8_t * ) pxNewQueue; + } + else + { + /* Set the head to the start of the queue storage area. */ + pxNewQueue->pcHead = ( int8_t * ) pucQueueStorage; + } - /* Initialise the queue members as described where the queue type is - defined. */ - pxNewQueue->uxLength = uxQueueLength; - pxNewQueue->uxItemSize = uxItemSize; - ( void ) xQueueGenericReset( pxNewQueue, pdTRUE ); + /* Initialise the queue members as described where the queue type is + * defined. */ + pxNewQueue->uxLength = uxQueueLength; + pxNewQueue->uxItemSize = uxItemSize; + ( void ) xQueueGenericReset( pxNewQueue, pdTRUE ); - #if ( configUSE_TRACE_FACILITY == 1 ) - { - pxNewQueue->ucQueueType = ucQueueType; - } - #endif /* configUSE_TRACE_FACILITY */ + #if ( configUSE_TRACE_FACILITY == 1 ) + { + pxNewQueue->ucQueueType = ucQueueType; + } + #endif /* configUSE_TRACE_FACILITY */ - #if( configUSE_QUEUE_SETS == 1 ) - { - pxNewQueue->pxQueueSetContainer = NULL; - } - #endif /* configUSE_QUEUE_SETS */ + #if ( configUSE_QUEUE_SETS == 1 ) + { + pxNewQueue->pxQueueSetContainer = NULL; + } + #endif /* configUSE_QUEUE_SETS */ - traceQUEUE_CREATE( pxNewQueue ); + traceQUEUE_CREATE( pxNewQueue ); } /*-----------------------------------------------------------*/ -#if( configUSE_MUTEXES == 1 ) +#if ( configUSE_MUTEXES == 1 ) - static void prvInitialiseMutex( Queue_t *pxNewQueue ) - { - if( pxNewQueue != NULL ) - { - /* The queue create function will set all the queue structure members - correctly for a generic queue, but this function is creating a - mutex. Overwrite those members that need to be set differently - - in particular the information required for priority inheritance. */ - pxNewQueue->u.xSemaphore.xMutexHolder = NULL; - pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX; + static void prvInitialiseMutex( Queue_t * pxNewQueue ) + { + if( pxNewQueue != NULL ) + { + /* The queue create function will set all the queue structure members + * correctly for a generic queue, but this function is creating a + * mutex. Overwrite those members that need to be set differently - + * in particular the information required for priority inheritance. */ + pxNewQueue->u.xSemaphore.xMutexHolder = NULL; + pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX; - /* In case this is a recursive mutex. */ - pxNewQueue->u.xSemaphore.uxRecursiveCallCount = 0; - vPortCPUInitializeMutex(&pxNewQueue->mux); + /* In case this is a recursive mutex. */ + pxNewQueue->u.xSemaphore.uxRecursiveCallCount = 0; +#ifdef ESP_PLATFORM + vPortCPUInitializeMutex(&pxNewQueue->mux); +#endif // ESP_PLATFORM + traceCREATE_MUTEX( pxNewQueue ); - traceCREATE_MUTEX( pxNewQueue ); - - /* Start with the semaphore in the expected state. */ - ( void ) xQueueGenericSend( pxNewQueue, NULL, ( TickType_t ) 0U, queueSEND_TO_BACK ); - } - else - { - traceCREATE_MUTEX_FAILED(); - } - } + /* Start with the semaphore in the expected state. */ + ( void ) xQueueGenericSend( pxNewQueue, NULL, ( TickType_t ) 0U, queueSEND_TO_BACK ); + } + else + { + traceCREATE_MUTEX_FAILED(); + } + } #endif /* configUSE_MUTEXES */ /*-----------------------------------------------------------*/ -#if( ( configUSE_MUTEXES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) +#if ( ( configUSE_MUTEXES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) - QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType ) - { - QueueHandle_t xNewQueue; - const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0; + QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType ) + { + QueueHandle_t xNewQueue; + const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0; - xNewQueue = xQueueGenericCreate( uxMutexLength, uxMutexSize, ucQueueType ); - prvInitialiseMutex( ( Queue_t * ) xNewQueue ); + xNewQueue = xQueueGenericCreate( uxMutexLength, uxMutexSize, ucQueueType ); + prvInitialiseMutex( ( Queue_t * ) xNewQueue ); - return xNewQueue; - } + return xNewQueue; + } #endif /* configUSE_MUTEXES */ /*-----------------------------------------------------------*/ -#if( ( configUSE_MUTEXES == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) +#if ( ( configUSE_MUTEXES == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) - QueueHandle_t xQueueCreateMutexStatic( const uint8_t ucQueueType, StaticQueue_t *pxStaticQueue ) - { - QueueHandle_t xNewQueue; - const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0; + QueueHandle_t xQueueCreateMutexStatic( const uint8_t ucQueueType, + StaticQueue_t * pxStaticQueue ) + { + QueueHandle_t xNewQueue; + const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0; - /* Prevent compiler warnings about unused parameters if - configUSE_TRACE_FACILITY does not equal 1. */ - ( void ) ucQueueType; + /* Prevent compiler warnings about unused parameters if + * configUSE_TRACE_FACILITY does not equal 1. */ + ( void ) ucQueueType; - xNewQueue = xQueueGenericCreateStatic( uxMutexLength, uxMutexSize, NULL, pxStaticQueue, ucQueueType ); - prvInitialiseMutex( ( Queue_t * ) xNewQueue ); + xNewQueue = xQueueGenericCreateStatic( uxMutexLength, uxMutexSize, NULL, pxStaticQueue, ucQueueType ); + prvInitialiseMutex( ( Queue_t * ) xNewQueue ); - return xNewQueue; - } + return xNewQueue; + } #endif /* configUSE_MUTEXES */ /*-----------------------------------------------------------*/ #if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) - TaskHandle_t xQueueGetMutexHolder( QueueHandle_t xSemaphore ) - { - TaskHandle_t pxReturn; - Queue_t * const pxSemaphore = ( Queue_t * ) xSemaphore; - - /* This function is called by xSemaphoreGetMutexHolder(), and should not - be called directly. Note: This is a good way of determining if the - calling task is the mutex holder, but not a good way of determining the - identity of the mutex holder, as the holder may change between the - following critical section exiting and the function returning. */ - taskENTER_CRITICAL( &pxSemaphore->mux); - { - if( pxSemaphore->uxQueueType == queueQUEUE_IS_MUTEX ) - { - pxReturn = pxSemaphore->u.xSemaphore.xMutexHolder; - } - else - { - pxReturn = NULL; - } - } - taskEXIT_CRITICAL( &pxSemaphore->mux); - - return pxReturn; - } /*lint !e818 xSemaphore cannot be a pointer to const because it is a typedef. */ + TaskHandle_t xQueueGetMutexHolder( QueueHandle_t xSemaphore ) + { + TaskHandle_t pxReturn; + Queue_t * const pxSemaphore = ( Queue_t * ) xSemaphore; + /* This function is called by xSemaphoreGetMutexHolder(), and should not + * be called directly. Note: This is a good way of determining if the + * calling task is the mutex holder, but not a good way of determining the + * identity of the mutex holder, as the holder may change between the + * following critical section exiting and the function returning. */ +#ifdef ESP_PLATFORM + Queue_t * const pxQueue = (Queue_t *)pxSemaphore; #endif + taskENTER_CRITICAL(); + { + if( pxSemaphore->uxQueueType == queueQUEUE_IS_MUTEX ) + { + pxReturn = pxSemaphore->u.xSemaphore.xMutexHolder; + } + else + { + pxReturn = NULL; + } + } + taskEXIT_CRITICAL(); + + return pxReturn; + } /*lint !e818 xSemaphore cannot be a pointer to const because it is a typedef. */ + +#endif /* if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) */ /*-----------------------------------------------------------*/ #if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) - TaskHandle_t xQueueGetMutexHolderFromISR( QueueHandle_t xSemaphore ) - { - TaskHandle_t pxReturn; + TaskHandle_t xQueueGetMutexHolderFromISR( QueueHandle_t xSemaphore ) + { + TaskHandle_t pxReturn; - configASSERT( xSemaphore ); + configASSERT( xSemaphore ); - /* Mutexes cannot be used in interrupt service routines, so the mutex - holder should not change in an ISR, and therefore a critical section is - not required here. */ - if( ( ( Queue_t * ) xSemaphore )->uxQueueType == queueQUEUE_IS_MUTEX ) - { - pxReturn = ( ( Queue_t * ) xSemaphore )->u.xSemaphore.xMutexHolder; - } - else - { - pxReturn = NULL; - } + /* Mutexes cannot be used in interrupt service routines, so the mutex + * holder should not change in an ISR, and therefore a critical section is + * not required here. */ + if( ( ( Queue_t * ) xSemaphore )->uxQueueType == queueQUEUE_IS_MUTEX ) + { + pxReturn = ( ( Queue_t * ) xSemaphore )->u.xSemaphore.xMutexHolder; + } + else + { + pxReturn = NULL; + } - return pxReturn; - } /*lint !e818 xSemaphore cannot be a pointer to const because it is a typedef. */ + return pxReturn; + } /*lint !e818 xSemaphore cannot be a pointer to const because it is a typedef. */ -#endif +#endif /* if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) */ /*-----------------------------------------------------------*/ #if ( configUSE_RECURSIVE_MUTEXES == 1 ) - BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ) - { - BaseType_t xReturn; - Queue_t * const pxMutex = ( Queue_t * ) xMutex; + BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ) + { + BaseType_t xReturn; + Queue_t * const pxMutex = ( Queue_t * ) xMutex; - configASSERT( pxMutex ); + configASSERT( pxMutex ); - /* If this is the task that holds the mutex then xMutexHolder will not - change outside of this task. If this task does not hold the mutex then - pxMutexHolder can never coincidentally equal the tasks handle, and as - this is the only condition we are interested in it does not matter if - pxMutexHolder is accessed simultaneously by another task. Therefore no - mutual exclusion is required to test the pxMutexHolder variable. */ - if( pxMutex->u.xSemaphore.xMutexHolder == xTaskGetCurrentTaskHandle() ) - { - traceGIVE_MUTEX_RECURSIVE( pxMutex ); + /* If this is the task that holds the mutex then xMutexHolder will not + * change outside of this task. If this task does not hold the mutex then + * pxMutexHolder can never coincidentally equal the tasks handle, and as + * this is the only condition we are interested in it does not matter if + * pxMutexHolder is accessed simultaneously by another task. Therefore no + * mutual exclusion is required to test the pxMutexHolder variable. */ + if( pxMutex->u.xSemaphore.xMutexHolder == xTaskGetCurrentTaskHandle() ) + { + traceGIVE_MUTEX_RECURSIVE( pxMutex ); - /* uxRecursiveCallCount cannot be zero if xMutexHolder is equal to - the task handle, therefore no underflow check is required. Also, - uxRecursiveCallCount is only modified by the mutex holder, and as - there can only be one, no mutual exclusion is required to modify the - uxRecursiveCallCount member. */ - ( pxMutex->u.xSemaphore.uxRecursiveCallCount )--; + /* uxRecursiveCallCount cannot be zero if xMutexHolder is equal to + * the task handle, therefore no underflow check is required. Also, + * uxRecursiveCallCount is only modified by the mutex holder, and as + * there can only be one, no mutual exclusion is required to modify the + * uxRecursiveCallCount member. */ + ( pxMutex->u.xSemaphore.uxRecursiveCallCount )--; - /* Has the recursive call count unwound to 0? */ - if( pxMutex->u.xSemaphore.uxRecursiveCallCount == ( UBaseType_t ) 0 ) - { - /* Return the mutex. This will automatically unblock any other - task that might be waiting to access the mutex. */ - ( void ) xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* Has the recursive call count unwound to 0? */ + if( pxMutex->u.xSemaphore.uxRecursiveCallCount == ( UBaseType_t ) 0 ) + { + /* Return the mutex. This will automatically unblock any other + * task that might be waiting to access the mutex. */ + ( void ) xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - xReturn = pdPASS; - } - else - { - /* The mutex cannot be given because the calling task is not the - holder. */ - xReturn = pdFAIL; + xReturn = pdPASS; + } + else + { + /* The mutex cannot be given because the calling task is not the + * holder. */ + xReturn = pdFAIL; - traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ); - } + traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ); + } - return xReturn; - } + return xReturn; + } #endif /* configUSE_RECURSIVE_MUTEXES */ /*-----------------------------------------------------------*/ #if ( configUSE_RECURSIVE_MUTEXES == 1 ) - BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xTicksToWait ) - { - BaseType_t xReturn; - Queue_t * const pxMutex = ( Queue_t * ) xMutex; + BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex, + TickType_t xTicksToWait ) + { + BaseType_t xReturn; + Queue_t * const pxMutex = ( Queue_t * ) xMutex; - configASSERT( pxMutex ); + configASSERT( pxMutex ); - /* Comments regarding mutual exclusion as per those within - xQueueGiveMutexRecursive(). */ + /* Comments regarding mutual exclusion as per those within + * xQueueGiveMutexRecursive(). */ - traceTAKE_MUTEX_RECURSIVE( pxMutex ); + traceTAKE_MUTEX_RECURSIVE( pxMutex ); - if( pxMutex->u.xSemaphore.xMutexHolder == xTaskGetCurrentTaskHandle() ) - { - ( pxMutex->u.xSemaphore.uxRecursiveCallCount )++; - xReturn = pdPASS; - } - else - { - xReturn = xQueueSemaphoreTake( pxMutex, xTicksToWait ); + if( pxMutex->u.xSemaphore.xMutexHolder == xTaskGetCurrentTaskHandle() ) + { + ( pxMutex->u.xSemaphore.uxRecursiveCallCount )++; + xReturn = pdPASS; + } + else + { + xReturn = xQueueSemaphoreTake( pxMutex, xTicksToWait ); - /* pdPASS will only be returned if the mutex was successfully - obtained. The calling task may have entered the Blocked state - before reaching here. */ - if( xReturn != pdFAIL ) - { - ( pxMutex->u.xSemaphore.uxRecursiveCallCount )++; - } - else - { - traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex ); - } - } + /* pdPASS will only be returned if the mutex was successfully + * obtained. The calling task may have entered the Blocked state + * before reaching here. */ + if( xReturn != pdFAIL ) + { + ( pxMutex->u.xSemaphore.uxRecursiveCallCount )++; + } + else + { + traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex ); + } + } - return xReturn; - } + return xReturn; + } #endif /* configUSE_RECURSIVE_MUTEXES */ /*-----------------------------------------------------------*/ -#if( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) +#if ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) - QueueHandle_t xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount, StaticQueue_t *pxStaticQueue ) - { - QueueHandle_t xHandle; + QueueHandle_t xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, + const UBaseType_t uxInitialCount, + StaticQueue_t * pxStaticQueue ) + { + QueueHandle_t xHandle = NULL; - configASSERT( uxMaxCount != 0 ); - configASSERT( uxInitialCount <= uxMaxCount ); + configASSERT( uxMaxCount != 0 ); + configASSERT( uxInitialCount <= uxMaxCount ); - xHandle = xQueueGenericCreateStatic( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticQueue, queueQUEUE_TYPE_COUNTING_SEMAPHORE ); + xHandle = xQueueGenericCreateStatic( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticQueue, queueQUEUE_TYPE_COUNTING_SEMAPHORE ); - if( xHandle != NULL ) - { - ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount; + if( xHandle != NULL ) + { + ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount; - traceCREATE_COUNTING_SEMAPHORE(); - } - else - { - traceCREATE_COUNTING_SEMAPHORE_FAILED(); - } + traceCREATE_COUNTING_SEMAPHORE(); + } + else + { + traceCREATE_COUNTING_SEMAPHORE_FAILED(); + } - return xHandle; - } + return xHandle; + } #endif /* ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */ /*-----------------------------------------------------------*/ -#if( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) +#if ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) - QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount ) - { - QueueHandle_t xHandle; + QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, + const UBaseType_t uxInitialCount ) + { + QueueHandle_t xHandle = NULL; - configASSERT( uxMaxCount != 0 ); - configASSERT( uxInitialCount <= uxMaxCount ); + configASSERT( uxMaxCount != 0 ); + configASSERT( uxInitialCount <= uxMaxCount ); - xHandle = xQueueGenericCreate( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE ); + xHandle = xQueueGenericCreate( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE ); - if( xHandle != NULL ) - { - ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount; + if( xHandle != NULL ) + { + ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount; - traceCREATE_COUNTING_SEMAPHORE(); - } - else - { - traceCREATE_COUNTING_SEMAPHORE_FAILED(); - } + traceCREATE_COUNTING_SEMAPHORE(); + } + else + { + traceCREATE_COUNTING_SEMAPHORE_FAILED(); + } - return xHandle; - } + return xHandle; + } #endif /* ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */ /*-----------------------------------------------------------*/ -BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition ) +BaseType_t xQueueGenericSend( QueueHandle_t xQueue, + const void * const pvItemToQueue, + TickType_t xTicksToWait, + const BaseType_t xCopyPosition ) { -BaseType_t xEntryTimeSet = pdFALSE, xYieldRequired; -TimeOut_t xTimeOut; -Queue_t * const pxQueue = xQueue; + BaseType_t xEntryTimeSet = pdFALSE, xYieldRequired; + TimeOut_t xTimeOut; + Queue_t * const pxQueue = xQueue; - configASSERT( pxQueue ); - configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); - configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) ); - #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) - { - configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); - } - #endif + configASSERT( pxQueue ); + configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); + configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) ); + #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) + { + configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); + } + #endif #if ( configUSE_MUTEXES == 1 && configCHECK_MUTEX_GIVEN_BY_OWNER == 1) - configASSERT(pxQueue->uxQueueType != queueQUEUE_IS_MUTEX - || pxQueue->u.xSemaphore.xMutexHolder == NULL - || pxQueue->u.xSemaphore.xMutexHolder == xTaskGetCurrentTaskHandle()); + configASSERT(pxQueue->uxQueueType != queueQUEUE_IS_MUTEX + || pxQueue->u.xSemaphore.xMutexHolder == NULL + || pxQueue->u.xSemaphore.xMutexHolder == xTaskGetCurrentTaskHandle()); #endif - /*lint -save -e904 This function relaxes the coding standard somewhat to - allow return statements within the function itself. This is done in the - interest of execution time efficiency. */ - for( ;; ) - { - taskENTER_CRITICAL( &pxQueue->mux); - { - /* Is there room on the queue now? The running task must be the - highest priority task wanting to access the queue. If the head item - in the queue is to be overwritten then it does not matter if the - queue is full. */ - if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) ) - { - traceQUEUE_SEND( pxQueue ); + /*lint -save -e904 This function relaxes the coding standard somewhat to + * allow return statements within the function itself. This is done in the + * interest of execution time efficiency. */ + for( ; ; ) + { + taskENTER_CRITICAL(); + { + /* Is there room on the queue now? The running task must be the + * highest priority task wanting to access the queue. If the head item + * in the queue is to be overwritten then it does not matter if the + * queue is full. */ + if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) ) + { + traceQUEUE_SEND( pxQueue ); - #if ( configUSE_QUEUE_SETS == 1 ) - { - UBaseType_t uxPreviousMessagesWaiting = pxQueue->uxMessagesWaiting; + #if ( configUSE_QUEUE_SETS == 1 ) + { + UBaseType_t uxPreviousMessagesWaiting = pxQueue->uxMessagesWaiting; - xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); + xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); - if( pxQueue->pxQueueSetContainer != NULL ) - { - if( ( xCopyPosition == queueOVERWRITE ) && ( uxPreviousMessagesWaiting != ( UBaseType_t ) 0 ) ) - { - /* Do not notify the queue set as an existing item - was overwritten in the queue so the number of items - in the queue has not changed. */ - mtCOVERAGE_TEST_MARKER(); - } - else if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) != pdFALSE ) - { - /* The queue is a member of a queue set, and posting - to the queue set caused a higher priority task to - unblock. A context switch is required. */ - queueYIELD_IF_USING_PREEMPTION(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - /* If there was a task waiting for data to arrive on the - queue then unblock it now. */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The unblocked task has a priority higher than - our own so yield immediately. Yes it is ok to - do this from within the critical section - the - kernel takes care of that. */ - queueYIELD_IF_USING_PREEMPTION(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else if(xYieldRequired != pdFALSE) - { - /* This path is a special case that will only get - executed if the task was holding multiple mutexes - and the mutexes were given back in an order that is - different to that in which they were taken. */ - queueYIELD_IF_USING_PREEMPTION(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - } - #else /* configUSE_QUEUE_SETS */ - { - xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); + if( pxQueue->pxQueueSetContainer != NULL ) + { + if( ( xCopyPosition == queueOVERWRITE ) && ( uxPreviousMessagesWaiting != ( UBaseType_t ) 0 ) ) + { + /* Do not notify the queue set as an existing item + * was overwritten in the queue so the number of items + * in the queue has not changed. */ + mtCOVERAGE_TEST_MARKER(); + } + else if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) != pdFALSE ) + { + /* The queue is a member of a queue set, and posting + * to the queue set caused a higher priority task to + * unblock. A context switch is required. */ + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* If there was a task waiting for data to arrive on the + * queue then unblock it now. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The unblocked task has a priority higher than + * our own so yield immediately. Yes it is ok to + * do this from within the critical section - the + * kernel takes care of that. */ + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else if( xYieldRequired != pdFALSE ) + { + /* This path is a special case that will only get + * executed if the task was holding multiple mutexes + * and the mutexes were given back in an order that is + * different to that in which they were taken. */ + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + #else /* configUSE_QUEUE_SETS */ + { + xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); - /* If there was a task waiting for data to arrive on the - queue then unblock it now. */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The unblocked task has a priority higher than - our own so yield immediately. Yes it is ok to do - this from within the critical section - the kernel - takes care of that. */ - queueYIELD_IF_USING_PREEMPTION(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else if(xYieldRequired != pdFALSE) - { - /* This path is a special case that will only get - executed if the task was holding multiple mutexes and - the mutexes were given back in an order that is - different to that in which they were taken. */ - queueYIELD_IF_USING_PREEMPTION(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - #endif /* configUSE_QUEUE_SETS */ + /* If there was a task waiting for data to arrive on the + * queue then unblock it now. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The unblocked task has a priority higher than + * our own so yield immediately. Yes it is ok to do + * this from within the critical section - the kernel + * takes care of that. */ + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else if( xYieldRequired != pdFALSE ) + { + /* This path is a special case that will only get + * executed if the task was holding multiple mutexes and + * the mutexes were given back in an order that is + * different to that in which they were taken. */ + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_QUEUE_SETS */ - taskEXIT_CRITICAL( &pxQueue->mux); - return pdPASS; - } - else - { - if( xTicksToWait == ( TickType_t ) 0 ) - { - /* The queue was full and no block time is specified (or - the block time has expired) so leave now. */ - taskEXIT_CRITICAL( &pxQueue->mux); + taskEXIT_CRITICAL(); + return pdPASS; + } + else + { + if( xTicksToWait == ( TickType_t ) 0 ) + { + /* The queue was full and no block time is specified (or + * the block time has expired) so leave now. */ + taskEXIT_CRITICAL(); - /* Return to the original privilege level before exiting - the function. */ - traceQUEUE_SEND_FAILED( pxQueue ); - return errQUEUE_FULL; - } - else if( xEntryTimeSet == pdFALSE ) - { - /* The queue was full and a block time was specified so - configure the timeout structure. */ - vTaskInternalSetTimeOutState( &xTimeOut ); - xEntryTimeSet = pdTRUE; - } - else - { - /* Entry time was already set. */ - mtCOVERAGE_TEST_MARKER(); - } - } - } - taskEXIT_CRITICAL( &pxQueue->mux); + /* Return to the original privilege level before exiting + * the function. */ + traceQUEUE_SEND_FAILED( pxQueue ); + return errQUEUE_FULL; + } + else if( xEntryTimeSet == pdFALSE ) + { + /* The queue was full and a block time was specified so + * configure the timeout structure. */ + vTaskInternalSetTimeOutState( &xTimeOut ); + xEntryTimeSet = pdTRUE; + } + else + { + /* Entry time was already set. */ + mtCOVERAGE_TEST_MARKER(); + } + } + } + taskEXIT_CRITICAL(); - /* Interrupts and other tasks can send to and receive from the queue - now the critical section has been exited. */ + /* Interrupts and other tasks can send to and receive from the queue + * now the critical section has been exited. */ - taskENTER_CRITICAL( &pxQueue->mux); - prvLockQueue( pxQueue ); +#ifdef ESP_PLATFORM // IDF-3755 + taskENTER_CRITICAL(); +#else + vTaskSuspendAll(); +#endif // ESP_PLATFORM + prvLockQueue( pxQueue ); - /* Update the timeout state to see if it has expired yet. */ - if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) - { - if( prvIsQueueFull( pxQueue ) != pdFALSE ) - { - traceBLOCKING_ON_QUEUE_SEND( pxQueue ); - vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait ); + /* Update the timeout state to see if it has expired yet. */ + if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) + { + if( prvIsQueueFull( pxQueue ) != pdFALSE ) + { + traceBLOCKING_ON_QUEUE_SEND( pxQueue ); + vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait ); - /* Unlocking the queue means queue events can effect the - event list. It is possible that interrupts occurring now - remove this task from the event list again - but as the - scheduler is suspended the task will go onto the pending - ready last instead of the actual ready list. */ - prvUnlockQueue( pxQueue ); + /* Unlocking the queue means queue events can effect the + * event list. It is possible that interrupts occurring now + * remove this task from the event list again - but as the + * scheduler is suspended the task will go onto the pending + * ready list instead of the actual ready list. */ + prvUnlockQueue( pxQueue ); - /* Resuming the scheduler will move tasks from the pending - ready list into the ready list - so it is feasible that this - task is already in a ready list before it yields - in which - case the yield will not cause a context switch unless there - is also a higher priority task in the pending ready list. */ - taskEXIT_CRITICAL( &pxQueue->mux); - portYIELD_WITHIN_API(); + /* Resuming the scheduler will move tasks from the pending + * ready list into the ready list - so it is feasible that this + * task is already in the ready list before it yields - in which + * case the yield will not cause a context switch unless there + * is also a higher priority task in the pending ready list. */ +#ifdef ESP_PLATFORM // IDF-3755 + taskEXIT_CRITICAL(); +#else + if( xTaskResumeAll() == pdFALSE ) +#endif // ESP_PLATFORM + { + portYIELD_WITHIN_API(); + } - } - else - { - /* Try again. */ - prvUnlockQueue( pxQueue ); - taskEXIT_CRITICAL( &pxQueue->mux); - } - } - else - { - /* The timeout has expired. */ - prvUnlockQueue( pxQueue ); - taskEXIT_CRITICAL( &pxQueue->mux); + } + else + { + /* Try again. */ + prvUnlockQueue( pxQueue ); +#ifdef ESP_PLATFORM // IDF-3755 + taskEXIT_CRITICAL(); +#else + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM + } + } + else + { + /* The timeout has expired. */ + prvUnlockQueue( pxQueue ); +#ifdef ESP_PLATFORM // IDF-3755 + taskEXIT_CRITICAL(); +#else + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM - traceQUEUE_SEND_FAILED( pxQueue ); - return errQUEUE_FULL; - } - } /*lint -restore */ + traceQUEUE_SEND_FAILED( pxQueue ); + return errQUEUE_FULL; + } + } /*lint -restore */ } /*-----------------------------------------------------------*/ -BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, const void * const pvItemToQueue, BaseType_t * const pxHigherPriorityTaskWoken, const BaseType_t xCopyPosition ) +BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, + const void * const pvItemToQueue, + BaseType_t * const pxHigherPriorityTaskWoken, + const BaseType_t xCopyPosition ) { -BaseType_t xReturn; -UBaseType_t uxSavedInterruptStatus; -Queue_t * const pxQueue = xQueue; + BaseType_t xReturn; + UBaseType_t uxSavedInterruptStatus; + Queue_t * const pxQueue = xQueue; - configASSERT( pxQueue ); - configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); - configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) ); + configASSERT( pxQueue ); + configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); + configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) ); - /* RTOS ports that support interrupt nesting have the concept of a maximum - system call (or maximum API call) interrupt priority. Interrupts that are - above the maximum system call priority are kept permanently enabled, even - when the RTOS kernel is in a critical section, but cannot make any calls to - FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h - then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion - failure if a FreeRTOS API function is called from an interrupt that has been - assigned a priority above the configured maximum system call priority. - Only FreeRTOS functions that end in FromISR can be called from interrupts - that have been assigned a priority at or (logically) below the maximum - system call interrupt priority. FreeRTOS maintains a separate interrupt - safe API to ensure interrupt entry is as fast and as simple as possible. - More information (albeit Cortex-M specific) is provided on the following - link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ - portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + /* RTOS ports that support interrupt nesting have the concept of a maximum + * system call (or maximum API call) interrupt priority. Interrupts that are + * above the maximum system call priority are kept permanently enabled, even + * when the RTOS kernel is in a critical section, but cannot make any calls to + * FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h + * then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + * failure if a FreeRTOS API function is called from an interrupt that has been + * assigned a priority above the configured maximum system call priority. + * Only FreeRTOS functions that end in FromISR can be called from interrupts + * that have been assigned a priority at or (logically) below the maximum + * system call interrupt priority. FreeRTOS maintains a separate interrupt + * safe API to ensure interrupt entry is as fast and as simple as possible. + * More information (albeit Cortex-M specific) is provided on the following + * link: https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); - /* Similar to xQueueGenericSend, except without blocking if there is no room - in the queue. Also don't directly wake a task that was blocked on a queue - read, instead return a flag to say whether a context switch is required or - not (i.e. has a task with a higher priority than us been woken by this - post). */ - uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); - { - taskENTER_CRITICAL_ISR(&pxQueue->mux); + /* Similar to xQueueGenericSend, except without blocking if there is no room + * in the queue. Also don't directly wake a task that was blocked on a queue + * read, instead return a flag to say whether a context switch is required or + * not (i.e. has a task with a higher priority than us been woken by this + * post). */ + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + taskENTER_CRITICAL_ISR(); - if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) ) - { - const int8_t cTxLock = pxQueue->cTxLock; + if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) ) + { + const int8_t cTxLock = pxQueue->cTxLock; - traceQUEUE_SEND_FROM_ISR( pxQueue ); + traceQUEUE_SEND_FROM_ISR( pxQueue ); - /* Semaphores use xQueueGiveFromISR(), so pxQueue will not be a - semaphore or mutex. That means prvCopyDataToQueue() cannot result - in a task disinheriting a priority and prvCopyDataToQueue() can be - called here even though the disinherit function does not check if - the scheduler is suspended before accessing the ready lists. */ - ( void ) prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); + /* Semaphores use xQueueGiveFromISR(), so pxQueue will not be a + * semaphore or mutex. That means prvCopyDataToQueue() cannot result + * in a task disinheriting a priority and prvCopyDataToQueue() can be + * called here even though the disinherit function does not check if + * the scheduler is suspended before accessing the ready lists. */ + ( void ) prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); - /* The event list is not altered if the queue is locked. This will - be done when the queue is unlocked later. */ - if( cTxLock == queueUNLOCKED ) - { - #if ( configUSE_QUEUE_SETS == 1 ) - { - if( pxQueue->pxQueueSetContainer != NULL ) - { - if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) != pdFALSE ) - { - /* The queue is a member of a queue set, and posting - to the queue set caused a higher priority task to - unblock. A context switch is required. */ - if( pxHigherPriorityTaskWoken != NULL ) - { - *pxHigherPriorityTaskWoken = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The task waiting has a higher priority so - record that a context switch is required. */ - if( pxHigherPriorityTaskWoken != NULL ) - { - *pxHigherPriorityTaskWoken = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - } - #else /* configUSE_QUEUE_SETS */ - { - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The task waiting has a higher priority so record that a - context switch is required. */ - if( pxHigherPriorityTaskWoken != NULL ) - { - *pxHigherPriorityTaskWoken = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - #endif /* configUSE_QUEUE_SETS */ - } - else - { - /* Increment the lock count so the task that unlocks the queue - knows that data was posted while it was locked. */ - pxQueue->cTxLock = ( int8_t ) ( cTxLock + 1 ); - } + /* The event list is not altered if the queue is locked. This will + * be done when the queue is unlocked later. */ + if( cTxLock == queueUNLOCKED ) + { + #if ( configUSE_QUEUE_SETS == 1 ) + { + if( pxQueue->pxQueueSetContainer != NULL ) + { + if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) != pdFALSE ) + { + /* The queue is a member of a queue set, and posting + * to the queue set caused a higher priority task to + * unblock. A context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so + * record that a context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + #else /* configUSE_QUEUE_SETS */ + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so record that a + * context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_QUEUE_SETS */ + } + else + { + /* Increment the lock count so the task that unlocks the queue + * knows that data was posted while it was locked. */ + pxQueue->cTxLock = ( int8_t ) ( cTxLock + 1 ); + } - xReturn = pdPASS; - } - else - { - traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ); - xReturn = errQUEUE_FULL; - } + xReturn = pdPASS; + } + else + { + traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ); + xReturn = errQUEUE_FULL; + } - taskEXIT_CRITICAL_ISR(&pxQueue->mux); - } - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + taskEXIT_CRITICAL_ISR(); + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); - return xReturn; + return xReturn; } /*-----------------------------------------------------------*/ -BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, BaseType_t * const pxHigherPriorityTaskWoken ) +BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, + BaseType_t * const pxHigherPriorityTaskWoken ) { -BaseType_t xReturn; -UBaseType_t uxSavedInterruptStatus; -Queue_t * const pxQueue = xQueue; + BaseType_t xReturn; + UBaseType_t uxSavedInterruptStatus; + Queue_t * const pxQueue = xQueue; - /* Similar to xQueueGenericSendFromISR() but used with semaphores where the - item size is 0. Don't directly wake a task that was blocked on a queue - read, instead return a flag to say whether a context switch is required or - not (i.e. has a task with a higher priority than us been woken by this - post). */ + /* Similar to xQueueGenericSendFromISR() but used with semaphores where the + * item size is 0. Don't directly wake a task that was blocked on a queue + * read, instead return a flag to say whether a context switch is required or + * not (i.e. has a task with a higher priority than us been woken by this + * post). */ - configASSERT( pxQueue ); + configASSERT( pxQueue ); - /* xQueueGenericSendFromISR() should be used instead of xQueueGiveFromISR() - if the item size is not 0. */ - configASSERT( pxQueue->uxItemSize == 0 ); + /* xQueueGenericSendFromISR() should be used instead of xQueueGiveFromISR() + * if the item size is not 0. */ + configASSERT( pxQueue->uxItemSize == 0 ); - /* Normally a mutex would not be given from an interrupt, especially if - there is a mutex holder, as priority inheritance makes no sense for an - interrupts, only tasks. */ - configASSERT( !( ( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) && ( pxQueue->u.xSemaphore.xMutexHolder != NULL ) ) ); + /* Normally a mutex would not be given from an interrupt, especially if + * there is a mutex holder, as priority inheritance makes no sense for an + * interrupts, only tasks. */ + configASSERT( !( ( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) && ( pxQueue->u.xSemaphore.xMutexHolder != NULL ) ) ); - /* RTOS ports that support interrupt nesting have the concept of a maximum - system call (or maximum API call) interrupt priority. Interrupts that are - above the maximum system call priority are kept permanently enabled, even - when the RTOS kernel is in a critical section, but cannot make any calls to - FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h - then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion - failure if a FreeRTOS API function is called from an interrupt that has been - assigned a priority above the configured maximum system call priority. - Only FreeRTOS functions that end in FromISR can be called from interrupts - that have been assigned a priority at or (logically) below the maximum - system call interrupt priority. FreeRTOS maintains a separate interrupt - safe API to ensure interrupt entry is as fast and as simple as possible. - More information (albeit Cortex-M specific) is provided on the following - link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ - portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + /* RTOS ports that support interrupt nesting have the concept of a maximum + * system call (or maximum API call) interrupt priority. Interrupts that are + * above the maximum system call priority are kept permanently enabled, even + * when the RTOS kernel is in a critical section, but cannot make any calls to + * FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h + * then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + * failure if a FreeRTOS API function is called from an interrupt that has been + * assigned a priority above the configured maximum system call priority. + * Only FreeRTOS functions that end in FromISR can be called from interrupts + * that have been assigned a priority at or (logically) below the maximum + * system call interrupt priority. FreeRTOS maintains a separate interrupt + * safe API to ensure interrupt entry is as fast and as simple as possible. + * More information (albeit Cortex-M specific) is provided on the following + * link: https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); - uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); - { - taskENTER_CRITICAL_ISR(&pxQueue->mux); + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + taskENTER_CRITICAL_ISR(); - const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; + const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; - /* When the queue is used to implement a semaphore no data is ever - moved through the queue but it is still valid to see if the queue 'has - space'. */ - if( uxMessagesWaiting < pxQueue->uxLength ) - { - const int8_t cTxLock = pxQueue->cTxLock; + /* When the queue is used to implement a semaphore no data is ever + * moved through the queue but it is still valid to see if the queue 'has + * space'. */ + if( uxMessagesWaiting < pxQueue->uxLength ) + { + const int8_t cTxLock = pxQueue->cTxLock; - traceQUEUE_GIVE_FROM_ISR( pxQueue ); + traceQUEUE_GIVE_FROM_ISR( pxQueue ); - /* A task can only have an inherited priority if it is a mutex - holder - and if there is a mutex holder then the mutex cannot be - given from an ISR. As this is the ISR version of the function it - can be assumed there is no mutex holder and no need to determine if - priority disinheritance is needed. Simply increase the count of - messages (semaphores) available. */ - pxQueue->uxMessagesWaiting = uxMessagesWaiting + ( UBaseType_t ) 1; + /* A task can only have an inherited priority if it is a mutex + * holder - and if there is a mutex holder then the mutex cannot be + * given from an ISR. As this is the ISR version of the function it + * can be assumed there is no mutex holder and no need to determine if + * priority disinheritance is needed. Simply increase the count of + * messages (semaphores) available. */ + pxQueue->uxMessagesWaiting = uxMessagesWaiting + ( UBaseType_t ) 1; - /* The event list is not altered if the queue is locked. This will - be done when the queue is unlocked later. */ - if( cTxLock == queueUNLOCKED ) - { - #if ( configUSE_QUEUE_SETS == 1 ) - { - if( pxQueue->pxQueueSetContainer != NULL ) - { - if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) != pdFALSE ) - { - /* The semaphore is a member of a queue set, and - posting to the queue set caused a higher priority - task to unblock. A context switch is required. */ - if( pxHigherPriorityTaskWoken != NULL ) - { - *pxHigherPriorityTaskWoken = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The task waiting has a higher priority so - record that a context switch is required. */ - if( pxHigherPriorityTaskWoken != NULL ) - { - *pxHigherPriorityTaskWoken = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - } - #else /* configUSE_QUEUE_SETS */ - { - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The task waiting has a higher priority so record that a - context switch is required. */ - if( pxHigherPriorityTaskWoken != NULL ) - { - *pxHigherPriorityTaskWoken = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - #endif /* configUSE_QUEUE_SETS */ - } - else - { - /* Increment the lock count so the task that unlocks the queue - knows that data was posted while it was locked. */ - pxQueue->cTxLock = ( int8_t ) ( cTxLock + 1 ); - } + /* The event list is not altered if the queue is locked. This will + * be done when the queue is unlocked later. */ + if( cTxLock == queueUNLOCKED ) + { + #if ( configUSE_QUEUE_SETS == 1 ) + { + if( pxQueue->pxQueueSetContainer != NULL ) + { + if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) != pdFALSE ) + { + /* The semaphore is a member of a queue set, and + * posting to the queue set caused a higher priority + * task to unblock. A context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so + * record that a context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + #else /* configUSE_QUEUE_SETS */ + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so record that a + * context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_QUEUE_SETS */ + } + else + { + /* Increment the lock count so the task that unlocks the queue + * knows that data was posted while it was locked. */ + pxQueue->cTxLock = ( int8_t ) ( cTxLock + 1 ); + } - xReturn = pdPASS; - } - else - { - traceQUEUE_GIVE_FROM_ISR_FAILED( pxQueue ); - xReturn = errQUEUE_FULL; - } - taskEXIT_CRITICAL_ISR(&pxQueue->mux); - } - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + xReturn = pdPASS; + } + else + { + traceQUEUE_GIVE_FROM_ISR_FAILED( pxQueue ); + xReturn = errQUEUE_FULL; + } + taskEXIT_CRITICAL_ISR(); + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); - return xReturn; + return xReturn; } /*-----------------------------------------------------------*/ -BaseType_t xQueueReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait ) +BaseType_t xQueueReceive( QueueHandle_t xQueue, + void * const pvBuffer, + TickType_t xTicksToWait ) { -BaseType_t xEntryTimeSet = pdFALSE; -TimeOut_t xTimeOut; -Queue_t * const pxQueue = xQueue; + BaseType_t xEntryTimeSet = pdFALSE; + TimeOut_t xTimeOut; + Queue_t * const pxQueue = xQueue; - /* Check the pointer is not NULL. */ - configASSERT( ( pxQueue ) ); + /* Check the pointer is not NULL. */ + configASSERT( ( pxQueue ) ); - /* The buffer into which data is received can only be NULL if the data size - is zero (so no data is copied into the buffer. */ - configASSERT( !( ( ( pvBuffer ) == NULL ) && ( ( pxQueue )->uxItemSize != ( UBaseType_t ) 0U ) ) ); + /* The buffer into which data is received can only be NULL if the data size + * is zero (so no data is copied into the buffer). */ + configASSERT( !( ( ( pvBuffer ) == NULL ) && ( ( pxQueue )->uxItemSize != ( UBaseType_t ) 0U ) ) ); - /* Cannot block if the scheduler is suspended. */ - #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) - { - configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); - } - #endif + /* Cannot block if the scheduler is suspended. */ + #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) + { + configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); + } + #endif + /*lint -save -e904 This function relaxes the coding standard somewhat to + * allow return statements within the function itself. This is done in the + * interest of execution time efficiency. */ + for( ; ; ) + { + taskENTER_CRITICAL(); + { + const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; - /*lint -save -e904 This function relaxes the coding standard somewhat to - allow return statements within the function itself. This is done in the - interest of execution time efficiency. */ - for( ;; ) - { - taskENTER_CRITICAL( &pxQueue->mux); - { - const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; + /* Is there data in the queue now? To be running the calling task + * must be the highest priority task wanting to access the queue. */ + if( uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + /* Data available, remove one item. */ + prvCopyDataFromQueue( pxQueue, pvBuffer ); + traceQUEUE_RECEIVE( pxQueue ); + pxQueue->uxMessagesWaiting = uxMessagesWaiting - ( UBaseType_t ) 1; - /* Is there data in the queue now? To be running the calling task - must be the highest priority task wanting to access the queue. */ - if( uxMessagesWaiting > ( UBaseType_t ) 0 ) - { - /* Data available, remove one item. */ - prvCopyDataFromQueue( pxQueue, pvBuffer ); - traceQUEUE_RECEIVE( pxQueue ); - pxQueue->uxMessagesWaiting = uxMessagesWaiting - ( UBaseType_t ) 1; + /* There is now space in the queue, were any tasks waiting to + * post to the queue? If so, unblock the highest priority waiting + * task. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - /* There is now space in the queue, were any tasks waiting to - post to the queue? If so, unblock the highest priority waiting - task. */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) - { - queueYIELD_IF_USING_PREEMPTION(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + taskEXIT_CRITICAL(); + return pdPASS; + } + else + { + if( xTicksToWait == ( TickType_t ) 0 ) + { + /* The queue was empty and no block time is specified (or + * the block time has expired) so leave now. */ + taskEXIT_CRITICAL(); + traceQUEUE_RECEIVE_FAILED( pxQueue ); + return errQUEUE_EMPTY; + } + else if( xEntryTimeSet == pdFALSE ) + { + /* The queue was empty and a block time was specified so + * configure the timeout structure. */ + vTaskInternalSetTimeOutState( &xTimeOut ); + xEntryTimeSet = pdTRUE; + } + else + { + /* Entry time was already set. */ + mtCOVERAGE_TEST_MARKER(); + } + } + } + taskEXIT_CRITICAL(); - taskEXIT_CRITICAL( &pxQueue->mux); - return pdPASS; - } - else - { - if( xTicksToWait == ( TickType_t ) 0 ) - { - /* The queue was empty and no block time is specified (or - the block time has expired) so leave now. */ - taskEXIT_CRITICAL( &pxQueue->mux); - traceQUEUE_RECEIVE_FAILED( pxQueue ); - return errQUEUE_EMPTY; - } - else if( xEntryTimeSet == pdFALSE ) - { - /* The queue was empty and a block time was specified so - configure the timeout structure. */ - vTaskInternalSetTimeOutState( &xTimeOut ); - xEntryTimeSet = pdTRUE; - } - else - { - /* Entry time was already set. */ - mtCOVERAGE_TEST_MARKER(); - } - } - } - taskEXIT_CRITICAL( &pxQueue->mux); + /* Interrupts and other tasks can send to and receive from the queue + * now the critical section has been exited. */ - /* Interrupts and other tasks can send to and receive from the queue - now the critical section has been exited. */ +#ifdef ESP_PLATFORM // IDF-3755 + taskENTER_CRITICAL(); +#else + vTaskSuspendAll(); +#endif // ESP_PLATFORM + prvLockQueue( pxQueue ); - taskENTER_CRITICAL( &pxQueue->mux); - prvLockQueue( pxQueue ); + /* Update the timeout state to see if it has expired yet. */ + if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) + { + /* The timeout has not expired. If the queue is still empty place + * the task on the list of tasks waiting to receive from the queue. */ + if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) + { + traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ); + vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); + prvUnlockQueue( pxQueue ); +#ifdef ESP_PLATFORM // IDF-3755 + taskEXIT_CRITICAL(); +#else + if( xTaskResumeAll() == pdFALSE ) +#endif // ESP_PLATFORM + { + portYIELD_WITHIN_API(); + } +#ifndef ESP_PLATFORM + else + { + mtCOVERAGE_TEST_MARKER(); + } +#endif // ESP_PLATFORM + } + else + { + /* The queue contains data again. Loop back to try and read the + * data. */ + prvUnlockQueue( pxQueue ); +#ifdef ESP_PLATFORM // IDF-3755 + taskEXIT_CRITICAL(); +#else + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM + } + } + else + { + /* Timed out. If there is no data in the queue exit, otherwise loop + * back and attempt to read the data. */ + prvUnlockQueue( pxQueue ); +#ifdef ESP_PLATFORM // IDF-3755 + taskEXIT_CRITICAL(); +#else + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM - /* Update the timeout state to see if it has expired yet. */ - if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) - { - /* The timeout has not expired. If the queue is still empty place - the task on the list of tasks waiting to receive from the queue. */ - if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) - { - traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ); - vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); - prvUnlockQueue( pxQueue ); - taskEXIT_CRITICAL( &pxQueue->mux); - portYIELD_WITHIN_API(); - } - else - { - /* The queue contains data again. Loop back to try and read the - data. */ - prvUnlockQueue( pxQueue ); - taskEXIT_CRITICAL( &pxQueue->mux); - } - } - else - { - /* Timed out. If there is no data in the queue exit, otherwise loop - back and attempt to read the data. */ - prvUnlockQueue( pxQueue ); - taskEXIT_CRITICAL( &pxQueue->mux); - - if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) - { - traceQUEUE_RECEIVE_FAILED( pxQueue ); - return errQUEUE_EMPTY; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - } /*lint -restore */ + if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) + { + traceQUEUE_RECEIVE_FAILED( pxQueue ); + return errQUEUE_EMPTY; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } /*lint -restore */ } /*-----------------------------------------------------------*/ -BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, TickType_t xTicksToWait ) +BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, + TickType_t xTicksToWait ) { -BaseType_t xEntryTimeSet = pdFALSE; -TimeOut_t xTimeOut; -Queue_t * const pxQueue = xQueue; + BaseType_t xEntryTimeSet = pdFALSE; + TimeOut_t xTimeOut; + Queue_t * const pxQueue = xQueue; -#if( configUSE_MUTEXES == 1 ) - BaseType_t xInheritanceOccurred = pdFALSE; -#endif + #if ( configUSE_MUTEXES == 1 ) + BaseType_t xInheritanceOccurred = pdFALSE; + #endif - /* Check the queue pointer is not NULL. */ - configASSERT( ( pxQueue ) ); + /* Check the queue pointer is not NULL. */ + configASSERT( ( pxQueue ) ); - /* Check this really is a semaphore, in which case the item size will be - 0. */ - configASSERT( pxQueue->uxItemSize == 0 ); + /* Check this really is a semaphore, in which case the item size will be + * 0. */ + configASSERT( pxQueue->uxItemSize == 0 ); - /* Cannot block if the scheduler is suspended. */ - #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) - { - configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); - } - #endif + /* Cannot block if the scheduler is suspended. */ + #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) + { + configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); + } + #endif + /*lint -save -e904 This function relaxes the coding standard somewhat to allow return + * statements within the function itself. This is done in the interest + * of execution time efficiency. */ + for( ; ; ) + { + taskENTER_CRITICAL(); + { + /* Semaphores are queues with an item size of 0, and where the + * number of messages in the queue is the semaphore's count value. */ + const UBaseType_t uxSemaphoreCount = pxQueue->uxMessagesWaiting; - /*lint -save -e904 This function relaxes the coding standard somewhat to allow return - statements within the function itself. This is done in the interest - of execution time efficiency. */ - for( ;; ) - { - taskENTER_CRITICAL( &pxQueue->mux); - { - /* Semaphores are queues with an item size of 0, and where the - number of messages in the queue is the semaphore's count value. */ - const UBaseType_t uxSemaphoreCount = pxQueue->uxMessagesWaiting; + /* Is there data in the queue now? To be running the calling task + * must be the highest priority task wanting to access the queue. */ + if( uxSemaphoreCount > ( UBaseType_t ) 0 ) + { + traceQUEUE_SEMAPHORE_RECEIVE( pxQueue ); - /* Is there data in the queue now? To be running the calling task - must be the highest priority task wanting to access the queue. */ - if( uxSemaphoreCount > ( UBaseType_t ) 0 ) - { - traceQUEUE_SEMAPHORE_RECEIVE( pxQueue ); + /* Semaphores are queues with a data size of zero and where the + * messages waiting is the semaphore's count. Reduce the count. */ + pxQueue->uxMessagesWaiting = uxSemaphoreCount - ( UBaseType_t ) 1; - /* Semaphores are queues with a data size of zero and where the - messages waiting is the semaphore's count. Reduce the count. */ - pxQueue->uxMessagesWaiting = uxSemaphoreCount - ( UBaseType_t ) 1; + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + /* Record the information required to implement + * priority inheritance should it become necessary. */ + pxQueue->u.xSemaphore.xMutexHolder = pvTaskIncrementMutexHeldCount(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_MUTEXES */ - #if ( configUSE_MUTEXES == 1 ) - { - if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) - { - /* Record the information required to implement - priority inheritance should it become necessary. */ - pxQueue->u.xSemaphore.xMutexHolder = pvTaskIncrementMutexHeldCount(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - #endif /* configUSE_MUTEXES */ + /* Check to see if other tasks are blocked waiting to give the + * semaphore, and if so, unblock the highest priority such task. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - /* Check to see if other tasks are blocked waiting to give the - semaphore, and if so, unblock the highest priority such task. */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) - { - queueYIELD_IF_USING_PREEMPTION(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + taskEXIT_CRITICAL(); + return pdPASS; + } + else + { + if( xTicksToWait == ( TickType_t ) 0 ) + { + /* For inheritance to have occurred there must have been an + * initial timeout, and an adjusted timeout cannot become 0, as + * if it were 0 the function would have exited. */ + #if ( configUSE_MUTEXES == 1 ) + { + configASSERT( xInheritanceOccurred == pdFALSE ); + } + #endif /* configUSE_MUTEXES */ - taskEXIT_CRITICAL( &pxQueue->mux); - return pdPASS; - } - else - { - if( xTicksToWait == ( TickType_t ) 0 ) - { - /* For inheritance to have occurred there must have been an - initial timeout, and an adjusted timeout cannot become 0, as - if it were 0 the function would have exited. */ - #if( configUSE_MUTEXES == 1 ) - { - configASSERT( xInheritanceOccurred == pdFALSE ); - } - #endif /* configUSE_MUTEXES */ + /* The semaphore count was 0 and no block time is specified + * (or the block time has expired) so exit now. */ + taskEXIT_CRITICAL(); + traceQUEUE_RECEIVE_FAILED( pxQueue ); + return errQUEUE_EMPTY; + } + else if( xEntryTimeSet == pdFALSE ) + { + /* The semaphore count was 0 and a block time was specified + * so configure the timeout structure ready to block. */ + vTaskInternalSetTimeOutState( &xTimeOut ); + xEntryTimeSet = pdTRUE; + } + else + { + /* Entry time was already set. */ + mtCOVERAGE_TEST_MARKER(); + } + } + } + taskEXIT_CRITICAL(); - /* The semaphore count was 0 and no block time is specified - (or the block time has expired) so exit now. */ - taskEXIT_CRITICAL( &pxQueue->mux); - traceQUEUE_RECEIVE_FAILED( pxQueue ); - return errQUEUE_EMPTY; - } - else if( xEntryTimeSet == pdFALSE ) - { - /* The semaphore count was 0 and a block time was specified - so configure the timeout structure ready to block. */ - vTaskInternalSetTimeOutState( &xTimeOut ); - xEntryTimeSet = pdTRUE; - } - else - { - /* Entry time was already set. */ - mtCOVERAGE_TEST_MARKER(); - } - } - } - taskEXIT_CRITICAL( &pxQueue->mux); + /* Interrupts and other tasks can give to and take from the semaphore + * now the critical section has been exited. */ - /* Interrupts and other tasks can give to and take from the semaphore - now the critical section has been exited. */ +#ifdef ESP_PLATFORM // IDF-3755 + taskENTER_CRITICAL(); +#else + vTaskSuspendAll(); +#endif // ESP_PLATFORM + prvLockQueue( pxQueue ); - taskENTER_CRITICAL( &pxQueue->mux); - prvLockQueue( pxQueue ); + /* Update the timeout state to see if it has expired yet. */ + if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) + { + /* A block time is specified and not expired. If the semaphore + * count is 0 then enter the Blocked state to wait for a semaphore to + * become available. As semaphores are implemented with queues the + * queue being empty is equivalent to the semaphore count being 0. */ + if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) + { + traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ); - /* Update the timeout state to see if it has expired yet. */ - if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) - { - /* A block time is specified and not expired. If the semaphore - count is 0 then enter the Blocked state to wait for a semaphore to - become available. As semaphores are implemented with queues the - queue being empty is equivalent to the semaphore count being 0. */ - if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) - { - traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ); + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + taskENTER_CRITICAL(); + { + xInheritanceOccurred = xTaskPriorityInherit( pxQueue->u.xSemaphore.xMutexHolder ); + } + taskEXIT_CRITICAL(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* if ( configUSE_MUTEXES == 1 ) */ - #if ( configUSE_MUTEXES == 1 ) - { - if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) - { - taskENTER_CRITICAL( &pxQueue->mux); - { - xInheritanceOccurred = xTaskPriorityInherit( pxQueue->u.xSemaphore.xMutexHolder ); - } - taskEXIT_CRITICAL( &pxQueue->mux); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - #endif + vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); + prvUnlockQueue( pxQueue ); +#ifdef ESP_PLATFORM // IDF-3755 + taskEXIT_CRITICAL(); +#else + if( xTaskResumeAll() == pdFALSE ) +#endif // ESP_PLATFORM + { + portYIELD_WITHIN_API(); + } +#ifndef ESP_PLATFORM + else + { + mtCOVERAGE_TEST_MARKER(); + } +#endif // ESP_PLATFORM + } + else + { + /* There was no timeout and the semaphore count was not 0, so + * attempt to take the semaphore again. */ + prvUnlockQueue( pxQueue ); +#ifdef ESP_PLATFORM // IDF-3755 + taskEXIT_CRITICAL(); +#else + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM + } + } + else + { + /* Timed out. */ + prvUnlockQueue( pxQueue ); +#ifdef ESP_PLATFORM // IDF-3755 + taskEXIT_CRITICAL(); +#else + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM - vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); - prvUnlockQueue( pxQueue ); - taskEXIT_CRITICAL( &pxQueue->mux); - portYIELD_WITHIN_API(); - } - else - { - /* There was no timeout and the semaphore count was not 0, so - attempt to take the semaphore again. */ - prvUnlockQueue( pxQueue ); - taskEXIT_CRITICAL( &pxQueue->mux); - } - } - else - { - /* Timed out. */ - prvUnlockQueue( pxQueue ); - taskEXIT_CRITICAL( &pxQueue->mux); + /* If the semaphore count is 0 exit now as the timeout has + * expired. Otherwise return to attempt to take the semaphore that is + * known to be available. As semaphores are implemented by queues the + * queue being empty is equivalent to the semaphore count being 0. */ + if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) + { + #if ( configUSE_MUTEXES == 1 ) + { + /* xInheritanceOccurred could only have be set if + * pxQueue->uxQueueType == queueQUEUE_IS_MUTEX so no need to + * test the mutex type again to check it is actually a mutex. */ + if( xInheritanceOccurred != pdFALSE ) + { + taskENTER_CRITICAL(); + { + UBaseType_t uxHighestWaitingPriority; - /* If the semaphore count is 0 exit now as the timeout has - expired. Otherwise return to attempt to take the semaphore that is - known to be available. As semaphores are implemented by queues the - queue being empty is equivalent to the semaphore count being 0. */ - if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) - { - #if ( configUSE_MUTEXES == 1 ) - { - /* xInheritanceOccurred could only have be set if - pxQueue->uxQueueType == queueQUEUE_IS_MUTEX so no need to - test the mutex type again to check it is actually a mutex. */ - if( xInheritanceOccurred != pdFALSE ) - { - taskENTER_CRITICAL( &pxQueue->mux); - { - UBaseType_t uxHighestWaitingPriority; + /* This task blocking on the mutex caused another + * task to inherit this task's priority. Now this task + * has timed out the priority should be disinherited + * again, but only as low as the next highest priority + * task that is waiting for the same mutex. */ + uxHighestWaitingPriority = prvGetDisinheritPriorityAfterTimeout( pxQueue ); + vTaskPriorityDisinheritAfterTimeout( pxQueue->u.xSemaphore.xMutexHolder, uxHighestWaitingPriority ); + } + taskEXIT_CRITICAL(); + } + } + #endif /* configUSE_MUTEXES */ - /* This task blocking on the mutex caused another - task to inherit this task's priority. Now this task - has timed out the priority should be disinherited - again, but only as low as the next highest priority - task that is waiting for the same mutex. */ - uxHighestWaitingPriority = prvGetDisinheritPriorityAfterTimeout( pxQueue ); - vTaskPriorityDisinheritAfterTimeout( pxQueue->u.xSemaphore.xMutexHolder, uxHighestWaitingPriority ); - } - taskEXIT_CRITICAL( &pxQueue->mux); - } - } - #endif /* configUSE_MUTEXES */ - - traceQUEUE_RECEIVE_FAILED( pxQueue ); - return errQUEUE_EMPTY; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - } /*lint -restore */ + traceQUEUE_RECEIVE_FAILED( pxQueue ); + return errQUEUE_EMPTY; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } /*lint -restore */ } /*-----------------------------------------------------------*/ -BaseType_t xQueuePeek( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait ) +BaseType_t xQueuePeek( QueueHandle_t xQueue, + void * const pvBuffer, + TickType_t xTicksToWait ) { -BaseType_t xEntryTimeSet = pdFALSE; -TimeOut_t xTimeOut; -int8_t *pcOriginalReadPosition; -Queue_t * const pxQueue = xQueue; + BaseType_t xEntryTimeSet = pdFALSE; + TimeOut_t xTimeOut; + int8_t * pcOriginalReadPosition; + Queue_t * const pxQueue = xQueue; - /* Check the pointer is not NULL. */ - configASSERT( ( pxQueue ) ); + /* Check the pointer is not NULL. */ + configASSERT( ( pxQueue ) ); - /* The buffer into which data is received can only be NULL if the data size - is zero (so no data is copied into the buffer. */ - configASSERT( !( ( ( pvBuffer ) == NULL ) && ( ( pxQueue )->uxItemSize != ( UBaseType_t ) 0U ) ) ); + /* The buffer into which data is received can only be NULL if the data size + * is zero (so no data is copied into the buffer. */ + configASSERT( !( ( ( pvBuffer ) == NULL ) && ( ( pxQueue )->uxItemSize != ( UBaseType_t ) 0U ) ) ); - /* Cannot block if the scheduler is suspended. */ - #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) - { - configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); - } - #endif + /* Cannot block if the scheduler is suspended. */ + #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) + { + configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); + } + #endif + /*lint -save -e904 This function relaxes the coding standard somewhat to + * allow return statements within the function itself. This is done in the + * interest of execution time efficiency. */ + for( ; ; ) + { + taskENTER_CRITICAL(); + { + const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; - /*lint -save -e904 This function relaxes the coding standard somewhat to - allow return statements within the function itself. This is done in the - interest of execution time efficiency. */ - for( ;; ) - { - taskENTER_CRITICAL( &pxQueue->mux); - { - const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; + /* Is there data in the queue now? To be running the calling task + * must be the highest priority task wanting to access the queue. */ + if( uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + /* Remember the read position so it can be reset after the data + * is read from the queue as this function is only peeking the + * data, not removing it. */ + pcOriginalReadPosition = pxQueue->u.xQueue.pcReadFrom; - /* Is there data in the queue now? To be running the calling task - must be the highest priority task wanting to access the queue. */ - if( uxMessagesWaiting > ( UBaseType_t ) 0 ) - { - /* Remember the read position so it can be reset after the data - is read from the queue as this function is only peeking the - data, not removing it. */ - pcOriginalReadPosition = pxQueue->u.xQueue.pcReadFrom; + prvCopyDataFromQueue( pxQueue, pvBuffer ); + traceQUEUE_PEEK( pxQueue ); - prvCopyDataFromQueue( pxQueue, pvBuffer ); - traceQUEUE_PEEK( pxQueue ); + /* The data is not being removed, so reset the read pointer. */ + pxQueue->u.xQueue.pcReadFrom = pcOriginalReadPosition; - /* The data is not being removed, so reset the read pointer. */ - pxQueue->u.xQueue.pcReadFrom = pcOriginalReadPosition; + /* The data is being left in the queue, so see if there are + * any other tasks waiting for the data. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority than this task. */ + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - /* The data is being left in the queue, so see if there are - any other tasks waiting for the data. */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The task waiting has a higher priority than this task. */ - queueYIELD_IF_USING_PREEMPTION(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + taskEXIT_CRITICAL(); + return pdPASS; + } + else + { + if( xTicksToWait == ( TickType_t ) 0 ) + { + /* The queue was empty and no block time is specified (or + * the block time has expired) so leave now. */ + taskEXIT_CRITICAL(); + traceQUEUE_PEEK_FAILED( pxQueue ); + return errQUEUE_EMPTY; + } + else if( xEntryTimeSet == pdFALSE ) + { + /* The queue was empty and a block time was specified so + * configure the timeout structure ready to enter the blocked + * state. */ + vTaskInternalSetTimeOutState( &xTimeOut ); + xEntryTimeSet = pdTRUE; + } + else + { + /* Entry time was already set. */ + mtCOVERAGE_TEST_MARKER(); + } + } + } + taskEXIT_CRITICAL(); - taskEXIT_CRITICAL( &pxQueue->mux); - return pdPASS; - } - else - { - if( xTicksToWait == ( TickType_t ) 0 ) - { - /* The queue was empty and no block time is specified (or - the block time has expired) so leave now. */ - taskEXIT_CRITICAL( &pxQueue->mux); - traceQUEUE_PEEK_FAILED( pxQueue ); - return errQUEUE_EMPTY; - } - else if( xEntryTimeSet == pdFALSE ) - { - /* The queue was empty and a block time was specified so - configure the timeout structure ready to enter the blocked - state. */ - vTaskInternalSetTimeOutState( &xTimeOut ); - xEntryTimeSet = pdTRUE; - } - else - { - /* Entry time was already set. */ - mtCOVERAGE_TEST_MARKER(); - } - } - } - taskEXIT_CRITICAL( &pxQueue->mux); + /* Interrupts and other tasks can send to and receive from the queue + * now the critical section has been exited. */ - /* Interrupts and other tasks can send to and receive from the queue - now the critical section has been exited. */ +#ifdef ESP_PLATFORM // IDF-3755 + taskENTER_CRITICAL(); +#else + vTaskSuspendAll(); +#endif // ESP_PLATFORM + prvLockQueue( pxQueue ); - taskENTER_CRITICAL( &pxQueue->mux); - prvLockQueue( pxQueue ); + /* Update the timeout state to see if it has expired yet. */ + if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) + { + /* Timeout has not expired yet, check to see if there is data in the + * queue now, and if not enter the Blocked state to wait for data. */ + if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) + { + traceBLOCKING_ON_QUEUE_PEEK( pxQueue ); + vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); + prvUnlockQueue( pxQueue ); +#ifdef ESP_PLATFORM // IDF-3755 + taskEXIT_CRITICAL(); +#else + if( xTaskResumeAll() == pdFALSE ) +#endif // ESP_PLATFORM + { + portYIELD_WITHIN_API(); + } +#ifndef ESP_PLATFORM + else + { + mtCOVERAGE_TEST_MARKER(); + } +#endif // ESP_PLATFORM + } + else + { + /* There is data in the queue now, so don't enter the blocked + * state, instead return to try and obtain the data. */ + prvUnlockQueue( pxQueue ); +#ifdef ESP_PLATFORM // IDF-3755 + taskEXIT_CRITICAL(); +#else + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM + } + } + else + { + /* The timeout has expired. If there is still no data in the queue + * exit, otherwise go back and try to read the data again. */ + prvUnlockQueue( pxQueue ); +#ifdef ESP_PLATFORM // IDF-3755 + taskEXIT_CRITICAL(); +#else + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM - /* Update the timeout state to see if it has expired yet. */ - if(xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE) - { - /* Timeout has not expired yet, check to see if there is data in the - queue now, and if not enter the Blocked state to wait for data. */ - if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) - { - traceBLOCKING_ON_QUEUE_PEEK( pxQueue ); - vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); - prvUnlockQueue( pxQueue ); - taskEXIT_CRITICAL( &pxQueue->mux); - portYIELD_WITHIN_API(); - } - else - { - /* There is data in the queue now, so don't enter the blocked - state, instead return to try and obtain the data. */ - prvUnlockQueue( pxQueue ); - taskEXIT_CRITICAL( &pxQueue->mux); - } - } - else - { - /* The timeout has expired. If there is still no data in the queue - exit, otherwise go back and try to read the data again. */ - prvUnlockQueue( pxQueue ); - taskEXIT_CRITICAL( &pxQueue->mux); - - if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) - { - traceQUEUE_PEEK_FAILED( pxQueue ); - return errQUEUE_EMPTY; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - } /*lint -restore */ + if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) + { + traceQUEUE_PEEK_FAILED( pxQueue ); + return errQUEUE_EMPTY; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } /*lint -restore */ } /*-----------------------------------------------------------*/ -BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, void * const pvBuffer, BaseType_t * const pxHigherPriorityTaskWoken ) +BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, + void * const pvBuffer, + BaseType_t * const pxHigherPriorityTaskWoken ) { -BaseType_t xReturn; -UBaseType_t uxSavedInterruptStatus; -Queue_t * const pxQueue = xQueue; + BaseType_t xReturn; + UBaseType_t uxSavedInterruptStatus; + Queue_t * const pxQueue = xQueue; - configASSERT( pxQueue ); - configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); + configASSERT( pxQueue ); + configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); - /* RTOS ports that support interrupt nesting have the concept of a maximum - system call (or maximum API call) interrupt priority. Interrupts that are - above the maximum system call priority are kept permanently enabled, even - when the RTOS kernel is in a critical section, but cannot make any calls to - FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h - then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion - failure if a FreeRTOS API function is called from an interrupt that has been - assigned a priority above the configured maximum system call priority. - Only FreeRTOS functions that end in FromISR can be called from interrupts - that have been assigned a priority at or (logically) below the maximum - system call interrupt priority. FreeRTOS maintains a separate interrupt - safe API to ensure interrupt entry is as fast and as simple as possible. - More information (albeit Cortex-M specific) is provided on the following - link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ - portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + /* RTOS ports that support interrupt nesting have the concept of a maximum + * system call (or maximum API call) interrupt priority. Interrupts that are + * above the maximum system call priority are kept permanently enabled, even + * when the RTOS kernel is in a critical section, but cannot make any calls to + * FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h + * then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + * failure if a FreeRTOS API function is called from an interrupt that has been + * assigned a priority above the configured maximum system call priority. + * Only FreeRTOS functions that end in FromISR can be called from interrupts + * that have been assigned a priority at or (logically) below the maximum + * system call interrupt priority. FreeRTOS maintains a separate interrupt + * safe API to ensure interrupt entry is as fast and as simple as possible. + * More information (albeit Cortex-M specific) is provided on the following + * link: https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); - uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); - { - taskENTER_CRITICAL_ISR(&pxQueue->mux); + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + taskENTER_CRITICAL_ISR(); - const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; + const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; - /* Cannot block in an ISR, so check there is data available. */ - if( uxMessagesWaiting > ( UBaseType_t ) 0 ) - { - const int8_t cRxLock = pxQueue->cRxLock; + /* Cannot block in an ISR, so check there is data available. */ + if( uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + const int8_t cRxLock = pxQueue->cRxLock; - traceQUEUE_RECEIVE_FROM_ISR( pxQueue ); + traceQUEUE_RECEIVE_FROM_ISR( pxQueue ); - prvCopyDataFromQueue( pxQueue, pvBuffer ); - pxQueue->uxMessagesWaiting = uxMessagesWaiting - ( UBaseType_t ) 1; + prvCopyDataFromQueue( pxQueue, pvBuffer ); + pxQueue->uxMessagesWaiting = uxMessagesWaiting - ( UBaseType_t ) 1; - /* If the queue is locked the event list will not be modified. - Instead update the lock count so the task that unlocks the queue - will know that an ISR has removed data while the queue was - locked. */ - if( cRxLock == queueUNLOCKED ) - { - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) - { - /* The task waiting has a higher priority than us so - force a context switch. */ - if( pxHigherPriorityTaskWoken != NULL ) - { - *pxHigherPriorityTaskWoken = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - /* Increment the lock count so the task that unlocks the queue - knows that data was removed while it was locked. */ - pxQueue->cRxLock = ( int8_t ) ( cRxLock + 1 ); - } + /* If the queue is locked the event list will not be modified. + * Instead update the lock count so the task that unlocks the queue + * will know that an ISR has removed data while the queue was + * locked. */ + if( cRxLock == queueUNLOCKED ) + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + /* The task waiting has a higher priority than us so + * force a context switch. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* Increment the lock count so the task that unlocks the queue + * knows that data was removed while it was locked. */ + pxQueue->cRxLock = ( int8_t ) ( cRxLock + 1 ); + } - xReturn = pdPASS; - } - else - { - xReturn = pdFAIL; - traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ); - } - taskEXIT_CRITICAL_ISR(&pxQueue->mux); - } - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ); + } + taskEXIT_CRITICAL_ISR(); + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); - return xReturn; + return xReturn; } /*-----------------------------------------------------------*/ -BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, void * const pvBuffer ) +BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, + void * const pvBuffer ) { -BaseType_t xReturn; -UBaseType_t uxSavedInterruptStatus; -int8_t *pcOriginalReadPosition; -Queue_t * const pxQueue = xQueue; + BaseType_t xReturn; + UBaseType_t uxSavedInterruptStatus; + int8_t * pcOriginalReadPosition; + Queue_t * const pxQueue = xQueue; - configASSERT( pxQueue ); - configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); - configASSERT( pxQueue->uxItemSize != 0 ); /* Can't peek a semaphore. */ + configASSERT( pxQueue ); + configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); + configASSERT( pxQueue->uxItemSize != 0 ); /* Can't peek a semaphore. */ - /* RTOS ports that support interrupt nesting have the concept of a maximum - system call (or maximum API call) interrupt priority. Interrupts that are - above the maximum system call priority are kept permanently enabled, even - when the RTOS kernel is in a critical section, but cannot make any calls to - FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h - then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion - failure if a FreeRTOS API function is called from an interrupt that has been - assigned a priority above the configured maximum system call priority. - Only FreeRTOS functions that end in FromISR can be called from interrupts - that have been assigned a priority at or (logically) below the maximum - system call interrupt priority. FreeRTOS maintains a separate interrupt - safe API to ensure interrupt entry is as fast and as simple as possible. - More information (albeit Cortex-M specific) is provided on the following - link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ - portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + /* RTOS ports that support interrupt nesting have the concept of a maximum + * system call (or maximum API call) interrupt priority. Interrupts that are + * above the maximum system call priority are kept permanently enabled, even + * when the RTOS kernel is in a critical section, but cannot make any calls to + * FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h + * then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + * failure if a FreeRTOS API function is called from an interrupt that has been + * assigned a priority above the configured maximum system call priority. + * Only FreeRTOS functions that end in FromISR can be called from interrupts + * that have been assigned a priority at or (logically) below the maximum + * system call interrupt priority. FreeRTOS maintains a separate interrupt + * safe API to ensure interrupt entry is as fast and as simple as possible. + * More information (albeit Cortex-M specific) is provided on the following + * link: https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); - uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); - taskENTER_CRITICAL_ISR(&pxQueue->mux); - { - /* Cannot block in an ISR, so check there is data available. */ - if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) - { - traceQUEUE_PEEK_FROM_ISR( pxQueue ); + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + taskENTER_CRITICAL_ISR(); + { + /* Cannot block in an ISR, so check there is data available. */ + if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + traceQUEUE_PEEK_FROM_ISR( pxQueue ); - /* Remember the read position so it can be reset as nothing is - actually being removed from the queue. */ - pcOriginalReadPosition = pxQueue->u.xQueue.pcReadFrom; - prvCopyDataFromQueue( pxQueue, pvBuffer ); - pxQueue->u.xQueue.pcReadFrom = pcOriginalReadPosition; + /* Remember the read position so it can be reset as nothing is + * actually being removed from the queue. */ + pcOriginalReadPosition = pxQueue->u.xQueue.pcReadFrom; + prvCopyDataFromQueue( pxQueue, pvBuffer ); + pxQueue->u.xQueue.pcReadFrom = pcOriginalReadPosition; - xReturn = pdPASS; - } - else - { - xReturn = pdFAIL; - traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue ); - } - } - taskEXIT_CRITICAL_ISR(&pxQueue->mux); - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue ); + } + } + taskEXIT_CRITICAL_ISR(); + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); - return xReturn; + return xReturn; } /*-----------------------------------------------------------*/ UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue ) { -UBaseType_t uxReturn; -Queue_t * const pxQueue = ( Queue_t * ) xQueue; + UBaseType_t uxReturn; + Queue_t * const pxQueue = ( Queue_t * ) xQueue; - configASSERT( xQueue ); + configASSERT( xQueue ); - taskENTER_CRITICAL( &pxQueue->mux); - { - uxReturn = ( ( Queue_t * ) xQueue )->uxMessagesWaiting; - } - taskEXIT_CRITICAL( &pxQueue->mux); + taskENTER_CRITICAL(); + { + uxReturn = ( ( Queue_t * ) xQueue )->uxMessagesWaiting; + } + taskEXIT_CRITICAL(); - return uxReturn; + return uxReturn; } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ /*-----------------------------------------------------------*/ UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue ) { -UBaseType_t uxReturn; -Queue_t * const pxQueue = xQueue; + UBaseType_t uxReturn; + Queue_t * const pxQueue = xQueue; - configASSERT( pxQueue ); + configASSERT( pxQueue ); - taskENTER_CRITICAL( &pxQueue->mux); - { - uxReturn = pxQueue->uxLength - pxQueue->uxMessagesWaiting; - } - taskEXIT_CRITICAL( &pxQueue->mux); + taskENTER_CRITICAL(); + { + uxReturn = pxQueue->uxLength - pxQueue->uxMessagesWaiting; + } + taskEXIT_CRITICAL(); - return uxReturn; + return uxReturn; } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ /*-----------------------------------------------------------*/ UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue ) { -UBaseType_t uxReturn; -Queue_t * const pxQueue = xQueue; + UBaseType_t uxReturn; + Queue_t * const pxQueue = xQueue; - configASSERT( pxQueue ); - uxReturn = pxQueue->uxMessagesWaiting; + configASSERT( pxQueue ); + uxReturn = pxQueue->uxMessagesWaiting; - return uxReturn; + return uxReturn; } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ /*-----------------------------------------------------------*/ void vQueueDelete( QueueHandle_t xQueue ) { -Queue_t * const pxQueue = xQueue; + Queue_t * const pxQueue = xQueue; - configASSERT( pxQueue ); - traceQUEUE_DELETE( pxQueue ); + configASSERT( pxQueue ); + traceQUEUE_DELETE( pxQueue ); - #if ( configQUEUE_REGISTRY_SIZE > 0 ) - { - vQueueUnregisterQueue( pxQueue ); - } - #endif + #if ( configQUEUE_REGISTRY_SIZE > 0 ) + { + vQueueUnregisterQueue( pxQueue ); + } + #endif - #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) ) - { - /* The queue can only have been allocated dynamically - free it - again. */ - vPortFree( pxQueue ); - } - #elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) - { - /* The queue could have been allocated statically or dynamically, so - check before attempting to free the memory. */ - if( pxQueue->ucStaticallyAllocated == ( uint8_t ) pdFALSE ) - { - vPortFree( pxQueue ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - #else - { - /* The queue must have been statically allocated, so is not going to be - deleted. Avoid compiler warnings about the unused parameter. */ - ( void ) pxQueue; - } - #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ + #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) ) + { + /* The queue can only have been allocated dynamically - free it + * again. */ + vPortFree( pxQueue ); + } + #elif ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) + { + /* The queue could have been allocated statically or dynamically, so + * check before attempting to free the memory. */ + if( pxQueue->ucStaticallyAllocated == ( uint8_t ) pdFALSE ) + { + vPortFree( pxQueue ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #else /* if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) ) */ + { + /* The queue must have been statically allocated, so is not going to be + * deleted. Avoid compiler warnings about the unused parameter. */ + ( void ) pxQueue; + } + #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ } /*-----------------------------------------------------------*/ #if ( configUSE_TRACE_FACILITY == 1 ) - UBaseType_t uxQueueGetQueueNumber( QueueHandle_t xQueue ) - { - return ( ( Queue_t * ) xQueue )->uxQueueNumber; - } + UBaseType_t uxQueueGetQueueNumber( QueueHandle_t xQueue ) + { + return ( ( Queue_t * ) xQueue )->uxQueueNumber; + } #endif /* configUSE_TRACE_FACILITY */ /*-----------------------------------------------------------*/ #if ( configUSE_TRACE_FACILITY == 1 ) - void vQueueSetQueueNumber( QueueHandle_t xQueue, UBaseType_t uxQueueNumber ) - { - ( ( Queue_t * ) xQueue )->uxQueueNumber = uxQueueNumber; - } + void vQueueSetQueueNumber( QueueHandle_t xQueue, + UBaseType_t uxQueueNumber ) + { + ( ( Queue_t * ) xQueue )->uxQueueNumber = uxQueueNumber; + } #endif /* configUSE_TRACE_FACILITY */ /*-----------------------------------------------------------*/ #if ( configUSE_TRACE_FACILITY == 1 ) - uint8_t ucQueueGetQueueType( QueueHandle_t xQueue ) - { - return ( ( Queue_t * ) xQueue )->ucQueueType; - } + uint8_t ucQueueGetQueueType( QueueHandle_t xQueue ) + { + return ( ( Queue_t * ) xQueue )->ucQueueType; + } #endif /* configUSE_TRACE_FACILITY */ /*-----------------------------------------------------------*/ -#if( configUSE_MUTEXES == 1 ) +#if ( configUSE_MUTEXES == 1 ) - static UBaseType_t prvGetDisinheritPriorityAfterTimeout( const Queue_t * const pxQueue ) - { - UBaseType_t uxHighestPriorityOfWaitingTasks; + static UBaseType_t prvGetDisinheritPriorityAfterTimeout( const Queue_t * const pxQueue ) + { + UBaseType_t uxHighestPriorityOfWaitingTasks; - /* If a task waiting for a mutex causes the mutex holder to inherit a - priority, but the waiting task times out, then the holder should - disinherit the priority - but only down to the highest priority of any - other tasks that are waiting for the same mutex. For this purpose, - return the priority of the highest priority task that is waiting for the - mutex. */ - if( listCURRENT_LIST_LENGTH( &( pxQueue->xTasksWaitingToReceive ) ) > 0U ) - { - uxHighestPriorityOfWaitingTasks = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) listGET_ITEM_VALUE_OF_HEAD_ENTRY( &( pxQueue->xTasksWaitingToReceive ) ); - } - else - { - uxHighestPriorityOfWaitingTasks = tskIDLE_PRIORITY; - } + /* If a task waiting for a mutex causes the mutex holder to inherit a + * priority, but the waiting task times out, then the holder should + * disinherit the priority - but only down to the highest priority of any + * other tasks that are waiting for the same mutex. For this purpose, + * return the priority of the highest priority task that is waiting for the + * mutex. */ + if( listCURRENT_LIST_LENGTH( &( pxQueue->xTasksWaitingToReceive ) ) > 0U ) + { + uxHighestPriorityOfWaitingTasks = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) listGET_ITEM_VALUE_OF_HEAD_ENTRY( &( pxQueue->xTasksWaitingToReceive ) ); + } + else + { + uxHighestPriorityOfWaitingTasks = tskIDLE_PRIORITY; + } - return uxHighestPriorityOfWaitingTasks; - } + return uxHighestPriorityOfWaitingTasks; + } #endif /* configUSE_MUTEXES */ /*-----------------------------------------------------------*/ -static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueue, const BaseType_t xPosition ) +static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, + const void * pvItemToQueue, + const BaseType_t xPosition ) { -BaseType_t xReturn = pdFALSE; -UBaseType_t uxMessagesWaiting; + BaseType_t xReturn = pdFALSE; + UBaseType_t uxMessagesWaiting; - /* This function is called from a critical section. */ + /* This function is called from a critical section. */ - uxMessagesWaiting = pxQueue->uxMessagesWaiting; + uxMessagesWaiting = pxQueue->uxMessagesWaiting; - if( pxQueue->uxItemSize == ( UBaseType_t ) 0 ) - { - #if ( configUSE_MUTEXES == 1 ) - { - if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) - { - /* The mutex is no longer being held. */ - xReturn = xTaskPriorityDisinherit( pxQueue->u.xSemaphore.xMutexHolder ); - pxQueue->u.xSemaphore.xMutexHolder = NULL; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - #endif /* configUSE_MUTEXES */ - } - else if( xPosition == queueSEND_TO_BACK ) - { - ( void ) memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 !e9087 MISRA exception as the casts are only redundant for some ports, plus previous logic ensures a null pointer can only be passed to memcpy() if the copy size is 0. Cast to void required by function signature and safe as no alignment requirement and copy length specified in bytes. */ - pxQueue->pcWriteTo += pxQueue->uxItemSize; /*lint !e9016 Pointer arithmetic on char types ok, especially in this use case where it is the clearest way of conveying intent. */ - if( pxQueue->pcWriteTo >= pxQueue->u.xQueue.pcTail ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */ - { - pxQueue->pcWriteTo = pxQueue->pcHead; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - ( void ) memcpy( ( void * ) pxQueue->u.xQueue.pcReadFrom, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e9087 !e418 MISRA exception as the casts are only redundant for some ports. Cast to void required by function signature and safe as no alignment requirement and copy length specified in bytes. Assert checks null pointer only used when length is 0. */ - pxQueue->u.xQueue.pcReadFrom -= pxQueue->uxItemSize; - if( pxQueue->u.xQueue.pcReadFrom < pxQueue->pcHead ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */ - { - pxQueue->u.xQueue.pcReadFrom = ( pxQueue->u.xQueue.pcTail - pxQueue->uxItemSize ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + if( pxQueue->uxItemSize == ( UBaseType_t ) 0 ) + { + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + /* The mutex is no longer being held. */ + xReturn = xTaskPriorityDisinherit( pxQueue->u.xSemaphore.xMutexHolder ); + pxQueue->u.xSemaphore.xMutexHolder = NULL; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_MUTEXES */ + } + else if( xPosition == queueSEND_TO_BACK ) + { + ( void ) memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 !e9087 MISRA exception as the casts are only redundant for some ports, plus previous logic ensures a null pointer can only be passed to memcpy() if the copy size is 0. Cast to void required by function signature and safe as no alignment requirement and copy length specified in bytes. */ + pxQueue->pcWriteTo += pxQueue->uxItemSize; /*lint !e9016 Pointer arithmetic on char types ok, especially in this use case where it is the clearest way of conveying intent. */ - if( xPosition == queueOVERWRITE ) - { - if( uxMessagesWaiting > ( UBaseType_t ) 0 ) - { - /* An item is not being added but overwritten, so subtract - one from the recorded number of items in the queue so when - one is added again below the number of recorded items remains - correct. */ - --uxMessagesWaiting; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } + if( pxQueue->pcWriteTo >= pxQueue->u.xQueue.pcTail ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */ + { + pxQueue->pcWriteTo = pxQueue->pcHead; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + ( void ) memcpy( ( void * ) pxQueue->u.xQueue.pcReadFrom, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e9087 !e418 MISRA exception as the casts are only redundant for some ports. Cast to void required by function signature and safe as no alignment requirement and copy length specified in bytes. Assert checks null pointer only used when length is 0. */ + pxQueue->u.xQueue.pcReadFrom -= pxQueue->uxItemSize; - pxQueue->uxMessagesWaiting = uxMessagesWaiting + ( UBaseType_t ) 1; + if( pxQueue->u.xQueue.pcReadFrom < pxQueue->pcHead ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */ + { + pxQueue->u.xQueue.pcReadFrom = ( pxQueue->u.xQueue.pcTail - pxQueue->uxItemSize ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - return xReturn; + if( xPosition == queueOVERWRITE ) + { + if( uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + /* An item is not being added but overwritten, so subtract + * one from the recorded number of items in the queue so when + * one is added again below the number of recorded items remains + * correct. */ + --uxMessagesWaiting; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + pxQueue->uxMessagesWaiting = uxMessagesWaiting + ( UBaseType_t ) 1; + + return xReturn; } /*-----------------------------------------------------------*/ -static void prvCopyDataFromQueue( Queue_t * const pxQueue, void * const pvBuffer ) +static void prvCopyDataFromQueue( Queue_t * const pxQueue, + void * const pvBuffer ) { - if( pxQueue->uxItemSize != ( UBaseType_t ) 0 ) - { - pxQueue->u.xQueue.pcReadFrom += pxQueue->uxItemSize; /*lint !e9016 Pointer arithmetic on char types ok, especially in this use case where it is the clearest way of conveying intent. */ - if( pxQueue->u.xQueue.pcReadFrom >= pxQueue->u.xQueue.pcTail ) /*lint !e946 MISRA exception justified as use of the relational operator is the cleanest solutions. */ - { - pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.xQueue.pcReadFrom, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 !e9087 MISRA exception as the casts are only redundant for some ports. Also previous logic ensures a null pointer can only be passed to memcpy() when the count is 0. Cast to void required by function signature and safe as no alignment requirement and copy length specified in bytes. */ - } + if( pxQueue->uxItemSize != ( UBaseType_t ) 0 ) + { + pxQueue->u.xQueue.pcReadFrom += pxQueue->uxItemSize; /*lint !e9016 Pointer arithmetic on char types ok, especially in this use case where it is the clearest way of conveying intent. */ + + if( pxQueue->u.xQueue.pcReadFrom >= pxQueue->u.xQueue.pcTail ) /*lint !e946 MISRA exception justified as use of the relational operator is the cleanest solutions. */ + { + pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.xQueue.pcReadFrom, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 !e9087 MISRA exception as the casts are only redundant for some ports. Also previous logic ensures a null pointer can only be passed to memcpy() when the count is 0. Cast to void required by function signature and safe as no alignment requirement and copy length specified in bytes. */ + } } /*-----------------------------------------------------------*/ static void prvUnlockQueue( Queue_t * const pxQueue ) { - /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */ + /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */ - /* The lock counts contains the number of extra data items placed or - removed from the queue while the queue was locked. When a queue is - locked items can be added or removed, but the event lists cannot be - updated. */ - taskENTER_CRITICAL( &pxQueue->mux); - { - int8_t cTxLock = pxQueue->cTxLock; + /* The lock counts contains the number of extra data items placed or + * removed from the queue while the queue was locked. When a queue is + * locked items can be added or removed, but the event lists cannot be + * updated. */ + taskENTER_CRITICAL(); + { + int8_t cTxLock = pxQueue->cTxLock; - /* See if data was added to the queue while it was locked. */ - while( cTxLock > queueLOCKED_UNMODIFIED ) - { - /* Data was posted while the queue was locked. Are any tasks - blocked waiting for data to become available? */ - #if ( configUSE_QUEUE_SETS == 1 ) - { - if( pxQueue->pxQueueSetContainer != NULL ) - { - if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) != pdFALSE ) - { - /* The queue is a member of a queue set, and posting to - the queue set caused a higher priority task to unblock. - A context switch is required. */ - vTaskMissedYield(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - /* Tasks that are removed from the event list will get - added to the pending ready list as the scheduler is still - suspended. */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The task waiting has a higher priority so record that a - context switch is required. */ - vTaskMissedYield(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - break; - } - } - } - #else /* configUSE_QUEUE_SETS */ - { - /* Tasks that are removed from the event list will get added to - the pending ready list as the scheduler is still suspended. */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The task waiting has a higher priority so record that - a context switch is required. */ - vTaskMissedYield(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - break; - } - } - #endif /* configUSE_QUEUE_SETS */ + /* See if data was added to the queue while it was locked. */ + while( cTxLock > queueLOCKED_UNMODIFIED ) + { + /* Data was posted while the queue was locked. Are any tasks + * blocked waiting for data to become available? */ + #if ( configUSE_QUEUE_SETS == 1 ) + { + if( pxQueue->pxQueueSetContainer != NULL ) + { + if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) != pdFALSE ) + { + /* The queue is a member of a queue set, and posting to + * the queue set caused a higher priority task to unblock. + * A context switch is required. */ + vTaskMissedYield(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* Tasks that are removed from the event list will get + * added to the pending ready list as the scheduler is still + * suspended. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so record that a + * context switch is required. */ + vTaskMissedYield(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + break; + } + } + } + #else /* configUSE_QUEUE_SETS */ + { + /* Tasks that are removed from the event list will get added to + * the pending ready list as the scheduler is still suspended. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so record that + * a context switch is required. */ + vTaskMissedYield(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + break; + } + } + #endif /* configUSE_QUEUE_SETS */ - --cTxLock; - } + --cTxLock; + } - pxQueue->cTxLock = queueUNLOCKED; - } - taskEXIT_CRITICAL( &pxQueue->mux); + pxQueue->cTxLock = queueUNLOCKED; + } + taskEXIT_CRITICAL(); - /* Do the same for the Rx lock. */ - taskENTER_CRITICAL( &pxQueue->mux); - { - int8_t cRxLock = pxQueue->cRxLock; + /* Do the same for the Rx lock. */ + taskENTER_CRITICAL(); + { + int8_t cRxLock = pxQueue->cRxLock; - while( cRxLock > queueLOCKED_UNMODIFIED ) - { - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) - { - vTaskMissedYield(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + while( cRxLock > queueLOCKED_UNMODIFIED ) + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + vTaskMissedYield(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - --cRxLock; - } - else - { - break; - } - } + --cRxLock; + } + else + { + break; + } + } - pxQueue->cRxLock = queueUNLOCKED; - } - taskEXIT_CRITICAL( &pxQueue->mux); + pxQueue->cRxLock = queueUNLOCKED; + } + taskEXIT_CRITICAL(); } /*-----------------------------------------------------------*/ -static BaseType_t prvIsQueueEmpty( const Queue_t *pxQueue ) +static BaseType_t prvIsQueueEmpty( const Queue_t * pxQueue ) { -BaseType_t xReturn; -Queue_t *pxQ = (Queue_t *)pxQueue; - taskENTER_CRITICAL( &pxQ->mux ); - { - if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 ) - { - xReturn = pdTRUE; - } - else - { - xReturn = pdFALSE; - } - } - taskEXIT_CRITICAL( &pxQ->mux ); + BaseType_t xReturn; + taskENTER_CRITICAL(); + { + if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + } + taskEXIT_CRITICAL(); - return xReturn; + return xReturn; } /*-----------------------------------------------------------*/ BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue ) { -BaseType_t xReturn; -Queue_t * const pxQueue = xQueue; + BaseType_t xReturn; + Queue_t * const pxQueue = xQueue; - configASSERT( pxQueue ); - if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 ) - { - xReturn = pdTRUE; - } - else - { - xReturn = pdFALSE; - } + configASSERT( pxQueue ); - return xReturn; + if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + + return xReturn; } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */ /*-----------------------------------------------------------*/ -static BaseType_t prvIsQueueFull( const Queue_t *pxQueue ) +static BaseType_t prvIsQueueFull( const Queue_t * pxQueue ) { -BaseType_t xReturn; + BaseType_t xReturn; - { - if( pxQueue->uxMessagesWaiting == pxQueue->uxLength ) - { - xReturn = pdTRUE; - } - else - { - xReturn = pdFALSE; - } - } + { + if( pxQueue->uxMessagesWaiting == pxQueue->uxLength ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + } - return xReturn; + return xReturn; } /*-----------------------------------------------------------*/ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) { -BaseType_t xReturn; -Queue_t * const pxQueue = xQueue; + BaseType_t xReturn; + Queue_t * const pxQueue = xQueue; - configASSERT( pxQueue ); - if( pxQueue->uxMessagesWaiting == pxQueue->uxLength ) - { - xReturn = pdTRUE; - } - else - { - xReturn = pdFALSE; - } + configASSERT( pxQueue ); - return xReturn; + if( pxQueue->uxMessagesWaiting == pxQueue->uxLength ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + + return xReturn; } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */ /*-----------------------------------------------------------*/ #if ( configUSE_CO_ROUTINES == 1 ) - BaseType_t xQueueCRSend( QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait ) - { - BaseType_t xReturn; - Queue_t * const pxQueue = xQueue; + BaseType_t xQueueCRSend( QueueHandle_t xQueue, + const void * pvItemToQueue, + TickType_t xTicksToWait ) + { + BaseType_t xReturn; + Queue_t * const pxQueue = xQueue; - /* If the queue is already full we may have to block. A critical section - is required to prevent an interrupt removing something from the queue - between the check to see if the queue is full and blocking on the queue. */ - portDISABLE_INTERRUPTS(); - { - if( prvIsQueueFull( pxQueue ) != pdFALSE ) - { - /* The queue is full - do we want to block or just leave without - posting? */ - if( xTicksToWait > ( TickType_t ) 0 ) - { - /* As this is called from a coroutine we cannot block directly, but - return indicating that we need to block. */ - vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) ); - portENABLE_INTERRUPTS(); - return errQUEUE_BLOCKED; - } - else - { - portENABLE_INTERRUPTS(); - return errQUEUE_FULL; - } - } - } - portENABLE_INTERRUPTS(); + /* If the queue is already full we may have to block. A critical section + * is required to prevent an interrupt removing something from the queue + * between the check to see if the queue is full and blocking on the queue. */ + portDISABLE_INTERRUPTS(); + { + if( prvIsQueueFull( pxQueue ) != pdFALSE ) + { + /* The queue is full - do we want to block or just leave without + * posting? */ + if( xTicksToWait > ( TickType_t ) 0 ) + { + /* As this is called from a coroutine we cannot block directly, but + * return indicating that we need to block. */ + vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) ); + portENABLE_INTERRUPTS(); + return errQUEUE_BLOCKED; + } + else + { + portENABLE_INTERRUPTS(); + return errQUEUE_FULL; + } + } + } + portENABLE_INTERRUPTS(); - portDISABLE_INTERRUPTS(); - { - if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) - { - /* There is room in the queue, copy the data into the queue. */ - prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK ); - xReturn = pdPASS; + portDISABLE_INTERRUPTS(); + { + if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) + { + /* There is room in the queue, copy the data into the queue. */ + prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK ); + xReturn = pdPASS; - /* Were any co-routines waiting for data to become available? */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - /* In this instance the co-routine could be placed directly - into the ready list as we are within a critical section. - Instead the same pending ready list mechanism is used as if - the event were caused from within an interrupt. */ - if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The co-routine waiting has a higher priority so record - that a yield might be appropriate. */ - xReturn = errQUEUE_YIELD; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - xReturn = errQUEUE_FULL; - } - } - portENABLE_INTERRUPTS(); + /* Were any co-routines waiting for data to become available? */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + /* In this instance the co-routine could be placed directly + * into the ready list as we are within a critical section. + * Instead the same pending ready list mechanism is used as if + * the event were caused from within an interrupt. */ + if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The co-routine waiting has a higher priority so record + * that a yield might be appropriate. */ + xReturn = errQUEUE_YIELD; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + xReturn = errQUEUE_FULL; + } + } + portENABLE_INTERRUPTS(); - return xReturn; - } + return xReturn; + } #endif /* configUSE_CO_ROUTINES */ /*-----------------------------------------------------------*/ #if ( configUSE_CO_ROUTINES == 1 ) - BaseType_t xQueueCRReceive( QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait ) - { - BaseType_t xReturn; - Queue_t * const pxQueue = xQueue; + BaseType_t xQueueCRReceive( QueueHandle_t xQueue, + void * pvBuffer, + TickType_t xTicksToWait ) + { + BaseType_t xReturn; + Queue_t * const pxQueue = xQueue; - /* If the queue is already empty we may have to block. A critical section - is required to prevent an interrupt adding something to the queue - between the check to see if the queue is empty and blocking on the queue. */ - portDISABLE_INTERRUPTS(); - { - if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 ) - { - /* There are no messages in the queue, do we want to block or just - leave with nothing? */ - if( xTicksToWait > ( TickType_t ) 0 ) - { - /* As this is a co-routine we cannot block directly, but return - indicating that we need to block. */ - vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) ); - portENABLE_INTERRUPTS(); - return errQUEUE_BLOCKED; - } - else - { - portENABLE_INTERRUPTS(); - return errQUEUE_FULL; - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - portENABLE_INTERRUPTS(); + /* If the queue is already empty we may have to block. A critical section + * is required to prevent an interrupt adding something to the queue + * between the check to see if the queue is empty and blocking on the queue. */ + portDISABLE_INTERRUPTS(); + { + if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 ) + { + /* There are no messages in the queue, do we want to block or just + * leave with nothing? */ + if( xTicksToWait > ( TickType_t ) 0 ) + { + /* As this is a co-routine we cannot block directly, but return + * indicating that we need to block. */ + vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) ); + portENABLE_INTERRUPTS(); + return errQUEUE_BLOCKED; + } + else + { + portENABLE_INTERRUPTS(); + return errQUEUE_FULL; + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + portENABLE_INTERRUPTS(); - portDISABLE_INTERRUPTS(); - { - if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) - { - /* Data is available from the queue. */ - pxQueue->u.xQueue.pcReadFrom += pxQueue->uxItemSize; - if( pxQueue->u.xQueue.pcReadFrom >= pxQueue->u.xQueue.pcTail ) - { - pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - --( pxQueue->uxMessagesWaiting ); - ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.xQueue.pcReadFrom, ( unsigned ) pxQueue->uxItemSize ); + portDISABLE_INTERRUPTS(); + { + if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + /* Data is available from the queue. */ + pxQueue->u.xQueue.pcReadFrom += pxQueue->uxItemSize; - xReturn = pdPASS; + if( pxQueue->u.xQueue.pcReadFrom >= pxQueue->u.xQueue.pcTail ) + { + pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - /* Were any co-routines waiting for space to become available? */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) - { - /* In this instance the co-routine could be placed directly - into the ready list as we are within a critical section. - Instead the same pending ready list mechanism is used as if - the event were caused from within an interrupt. */ - if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) - { - xReturn = errQUEUE_YIELD; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - xReturn = pdFAIL; - } - } - portENABLE_INTERRUPTS(); + --( pxQueue->uxMessagesWaiting ); + ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.xQueue.pcReadFrom, ( unsigned ) pxQueue->uxItemSize ); - return xReturn; - } + xReturn = pdPASS; + + /* Were any co-routines waiting for space to become available? */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + /* In this instance the co-routine could be placed directly + * into the ready list as we are within a critical section. + * Instead the same pending ready list mechanism is used as if + * the event were caused from within an interrupt. */ + if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + xReturn = errQUEUE_YIELD; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + xReturn = pdFAIL; + } + } + portENABLE_INTERRUPTS(); + + return xReturn; + } #endif /* configUSE_CO_ROUTINES */ /*-----------------------------------------------------------*/ #if ( configUSE_CO_ROUTINES == 1 ) - BaseType_t xQueueCRSendFromISR( QueueHandle_t xQueue, const void *pvItemToQueue, BaseType_t xCoRoutinePreviouslyWoken ) - { - Queue_t * const pxQueue = xQueue; + BaseType_t xQueueCRSendFromISR( QueueHandle_t xQueue, + const void * pvItemToQueue, + BaseType_t xCoRoutinePreviouslyWoken ) + { + Queue_t * const pxQueue = xQueue; - /* Cannot block within an ISR so if there is no space on the queue then - exit without doing anything. */ - if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) - { - prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK ); + /* Cannot block within an ISR so if there is no space on the queue then + * exit without doing anything. */ + if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) + { + prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK ); - /* We only want to wake one co-routine per ISR, so check that a - co-routine has not already been woken. */ - if( xCoRoutinePreviouslyWoken == pdFALSE ) - { - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - return pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* We only want to wake one co-routine per ISR, so check that a + * co-routine has not already been woken. */ + if( xCoRoutinePreviouslyWoken == pdFALSE ) + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + return pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - return xCoRoutinePreviouslyWoken; - } + return xCoRoutinePreviouslyWoken; + } #endif /* configUSE_CO_ROUTINES */ /*-----------------------------------------------------------*/ #if ( configUSE_CO_ROUTINES == 1 ) - BaseType_t xQueueCRReceiveFromISR( QueueHandle_t xQueue, void *pvBuffer, BaseType_t *pxCoRoutineWoken ) - { - BaseType_t xReturn; - Queue_t * const pxQueue = xQueue; + BaseType_t xQueueCRReceiveFromISR( QueueHandle_t xQueue, + void * pvBuffer, + BaseType_t * pxCoRoutineWoken ) + { + BaseType_t xReturn; + Queue_t * const pxQueue = xQueue; - /* We cannot block from an ISR, so check there is data available. If - not then just leave without doing anything. */ - if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) - { - /* Copy the data from the queue. */ - pxQueue->u.xQueue.pcReadFrom += pxQueue->uxItemSize; - if( pxQueue->u.xQueue.pcReadFrom >= pxQueue->u.xQueue.pcTail ) - { - pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - --( pxQueue->uxMessagesWaiting ); - ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.xQueue.pcReadFrom, ( unsigned ) pxQueue->uxItemSize ); + /* We cannot block from an ISR, so check there is data available. If + * not then just leave without doing anything. */ + if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + /* Copy the data from the queue. */ + pxQueue->u.xQueue.pcReadFrom += pxQueue->uxItemSize; - if( ( *pxCoRoutineWoken ) == pdFALSE ) - { - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) - { - if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) - { - *pxCoRoutineWoken = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + if( pxQueue->u.xQueue.pcReadFrom >= pxQueue->u.xQueue.pcTail ) + { + pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - xReturn = pdPASS; - } - else - { - xReturn = pdFAIL; - } + --( pxQueue->uxMessagesWaiting ); + ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.xQueue.pcReadFrom, ( unsigned ) pxQueue->uxItemSize ); - return xReturn; - } + if( ( *pxCoRoutineWoken ) == pdFALSE ) + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + *pxCoRoutineWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + } + + return xReturn; + } #endif /* configUSE_CO_ROUTINES */ /*-----------------------------------------------------------*/ #if ( configQUEUE_REGISTRY_SIZE > 0 ) - void vQueueAddToRegistry( QueueHandle_t xQueue, const char *pcQueueName ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ - { - UBaseType_t ux; + void vQueueAddToRegistry( QueueHandle_t xQueue, + const char * pcQueueName ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + { + UBaseType_t ux; - portENTER_CRITICAL(&queue_registry_spinlock); - /* See if there is an empty space in the registry. A NULL name denotes - a free slot. */ - for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ ) - { - if( xQueueRegistry[ ux ].pcQueueName == NULL ) - { - /* Store the information on this queue. */ - xQueueRegistry[ ux ].pcQueueName = pcQueueName; - xQueueRegistry[ ux ].xHandle = xQueue; + portENTER_CRITICAL(&queue_registry_spinlock); + /* See if there is an empty space in the registry. A NULL name denotes + * a free slot. */ + for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ ) + { + if( xQueueRegistry[ ux ].pcQueueName == NULL ) + { + /* Store the information on this queue. */ + xQueueRegistry[ ux ].pcQueueName = pcQueueName; + xQueueRegistry[ ux ].xHandle = xQueue; - traceQUEUE_REGISTRY_ADD( xQueue, pcQueueName ); - break; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - portEXIT_CRITICAL(&queue_registry_spinlock); - } + traceQUEUE_REGISTRY_ADD( xQueue, pcQueueName ); + break; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + portEXIT_CRITICAL(&queue_registry_spinlock); + } #endif /* configQUEUE_REGISTRY_SIZE */ /*-----------------------------------------------------------*/ #if ( configQUEUE_REGISTRY_SIZE > 0 ) - const char *pcQueueGetName( QueueHandle_t xQueue ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ - { - UBaseType_t ux; - const char *pcReturn = NULL; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + const char * pcQueueGetName( QueueHandle_t xQueue ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + { + UBaseType_t ux; + const char * pcReturn = NULL; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ - portENTER_CRITICAL(&queue_registry_spinlock); - /* Note there is nothing here to protect against another task adding or - removing entries from the registry while it is being searched. */ - for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ ) - { - if( xQueueRegistry[ ux ].xHandle == xQueue ) - { - pcReturn = xQueueRegistry[ ux ].pcQueueName; - break; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - portEXIT_CRITICAL(&queue_registry_spinlock); + portENTER_CRITICAL(&queue_registry_spinlock); - return pcReturn; - } /*lint !e818 xQueue cannot be a pointer to const because it is a typedef. */ + /* Note there is nothing here to protect against another task adding or + * removing entries from the registry while it is being searched. */ + + for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ ) + { + if( xQueueRegistry[ ux ].xHandle == xQueue ) + { + pcReturn = xQueueRegistry[ ux ].pcQueueName; + break; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + portEXIT_CRITICAL(&queue_registry_spinlock); + + return pcReturn; + } /*lint !e818 xQueue cannot be a pointer to const because it is a typedef. */ #endif /* configQUEUE_REGISTRY_SIZE */ /*-----------------------------------------------------------*/ #if ( configQUEUE_REGISTRY_SIZE > 0 ) - void vQueueUnregisterQueue( QueueHandle_t xQueue ) - { - UBaseType_t ux; + void vQueueUnregisterQueue( QueueHandle_t xQueue ) + { + UBaseType_t ux; - portENTER_CRITICAL(&queue_registry_spinlock); - /* See if the handle of the queue being unregistered in actually in the - registry. */ - for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ ) - { - if( xQueueRegistry[ ux ].xHandle == xQueue ) - { - /* Set the name to NULL to show that this slot if free again. */ - xQueueRegistry[ ux ].pcQueueName = NULL; + portENTER_CRITICAL(&queue_registry_spinlock); - /* Set the handle to NULL to ensure the same queue handle cannot - appear in the registry twice if it is added, removed, then - added again. */ - xQueueRegistry[ ux ].xHandle = ( QueueHandle_t ) 0; - break; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - portEXIT_CRITICAL(&queue_registry_spinlock); + /* See if the handle of the queue being unregistered in actually in the + * registry. */ + for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ ) + { + if( xQueueRegistry[ ux ].xHandle == xQueue ) + { + /* Set the name to NULL to show that this slot if free again. */ + xQueueRegistry[ ux ].pcQueueName = NULL; - } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */ + /* Set the handle to NULL to ensure the same queue handle cannot + * appear in the registry twice if it is added, removed, then + * added again. */ + xQueueRegistry[ ux ].xHandle = ( QueueHandle_t ) 0; + break; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + portEXIT_CRITICAL(&queue_registry_spinlock); + + } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */ #endif /* configQUEUE_REGISTRY_SIZE */ /*-----------------------------------------------------------*/ #if ( configUSE_TIMERS == 1 ) - void vQueueWaitForMessageRestricted( QueueHandle_t xQueue, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely ) - { - Queue_t * const pxQueue = xQueue; + void vQueueWaitForMessageRestricted( QueueHandle_t xQueue, + TickType_t xTicksToWait, + const BaseType_t xWaitIndefinitely ) + { + Queue_t * const pxQueue = xQueue; - /* This function should not be called by application code hence the - 'Restricted' in its name. It is not part of the public API. It is - designed for use by kernel code, and has special calling requirements. - It can result in vListInsert() being called on a list that can only - possibly ever have one item in it, so the list will be fast, but even - so it should be called with the scheduler locked and not from a critical - section. */ + /* This function should not be called by application code hence the + * 'Restricted' in its name. It is not part of the public API. It is + * designed for use by kernel code, and has special calling requirements. + * It can result in vListInsert() being called on a list that can only + * possibly ever have one item in it, so the list will be fast, but even + * so it should be called with the scheduler locked and not from a critical + * section. */ - /* Only do anything if there are no messages in the queue. This function - will not actually cause the task to block, just place it on a blocked - list. It will not block until the scheduler is unlocked - at which - time a yield will be performed. If an item is added to the queue while - the queue is locked, and the calling task blocks on the queue, then the - calling task will be immediately unblocked when the queue is unlocked. */ - prvLockQueue( pxQueue ); - if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0U ) - { - /* There is nothing in the queue, block for the specified period. */ - vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait, xWaitIndefinitely ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - prvUnlockQueue( pxQueue ); - } + /* Only do anything if there are no messages in the queue. This function + * will not actually cause the task to block, just place it on a blocked + * list. It will not block until the scheduler is unlocked - at which + * time a yield will be performed. If an item is added to the queue while + * the queue is locked, and the calling task blocks on the queue, then the + * calling task will be immediately unblocked when the queue is unlocked. */ + prvLockQueue( pxQueue ); + + if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0U ) + { + /* There is nothing in the queue, block for the specified period. */ + vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait, xWaitIndefinitely ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + prvUnlockQueue( pxQueue ); + } #endif /* configUSE_TIMERS */ /*-----------------------------------------------------------*/ -#if( ( configUSE_QUEUE_SETS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) +#if ( ( configUSE_QUEUE_SETS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) - QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength ) - { - QueueSetHandle_t pxQueue; + QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength ) + { + QueueSetHandle_t pxQueue; - pxQueue = xQueueGenericCreate( uxEventQueueLength, ( UBaseType_t ) sizeof( Queue_t * ), queueQUEUE_TYPE_SET ); + pxQueue = xQueueGenericCreate( uxEventQueueLength, ( UBaseType_t ) sizeof( Queue_t * ), queueQUEUE_TYPE_SET ); - return pxQueue; - } + return pxQueue; + } #endif /* configUSE_QUEUE_SETS */ /*-----------------------------------------------------------*/ #if ( configUSE_QUEUE_SETS == 1 ) - BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) - { - BaseType_t xReturn; + BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, + QueueSetHandle_t xQueueSet ) + { + BaseType_t xReturn; +#ifdef ESP_PLATFORM + Queue_t * pxQueue = (Queue_t * )xQueueOrSemaphore; +#endif - taskENTER_CRITICAL(&(((Queue_t * )xQueueOrSemaphore)->mux)); - { - if( ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL ) - { - /* Cannot add a queue/semaphore to more than one queue set. */ - xReturn = pdFAIL; - } - else if( ( ( Queue_t * ) xQueueOrSemaphore )->uxMessagesWaiting != ( UBaseType_t ) 0 ) - { - /* Cannot add a queue/semaphore to a queue set if there are already - items in the queue/semaphore. */ - xReturn = pdFAIL; - } - else - { - ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer = xQueueSet; - xReturn = pdPASS; - } - } - taskEXIT_CRITICAL(&(((Queue_t * )xQueueOrSemaphore)->mux)); + taskENTER_CRITICAL(); + { + if( ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL ) + { + /* Cannot add a queue/semaphore to more than one queue set. */ + xReturn = pdFAIL; + } + else if( ( ( Queue_t * ) xQueueOrSemaphore )->uxMessagesWaiting != ( UBaseType_t ) 0 ) + { + /* Cannot add a queue/semaphore to a queue set if there are already + * items in the queue/semaphore. */ + xReturn = pdFAIL; + } + else + { + ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer = xQueueSet; + xReturn = pdPASS; + } + } + taskEXIT_CRITICAL(); - return xReturn; - } + return xReturn; + } #endif /* configUSE_QUEUE_SETS */ /*-----------------------------------------------------------*/ #if ( configUSE_QUEUE_SETS == 1 ) - BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) - { - BaseType_t xReturn; - Queue_t * const pxQueueOrSemaphore = ( Queue_t * ) xQueueOrSemaphore; + BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, + QueueSetHandle_t xQueueSet ) + { + BaseType_t xReturn; + Queue_t * const pxQueueOrSemaphore = ( Queue_t * ) xQueueOrSemaphore; - if( pxQueueOrSemaphore->pxQueueSetContainer != xQueueSet ) - { - /* The queue was not a member of the set. */ - xReturn = pdFAIL; - } - else if( pxQueueOrSemaphore->uxMessagesWaiting != ( UBaseType_t ) 0 ) - { - /* It is dangerous to remove a queue from a set when the queue is - not empty because the queue set will still hold pending events for - the queue. */ - xReturn = pdFAIL; - } - else - { - taskENTER_CRITICAL(&(pxQueueOrSemaphore->mux)); - { - /* The queue is no longer contained in the set. */ - pxQueueOrSemaphore->pxQueueSetContainer = NULL; - } - taskEXIT_CRITICAL(&(pxQueueOrSemaphore->mux)); - xReturn = pdPASS; - } + if( pxQueueOrSemaphore->pxQueueSetContainer != xQueueSet ) + { + /* The queue was not a member of the set. */ + xReturn = pdFAIL; + } + else if( pxQueueOrSemaphore->uxMessagesWaiting != ( UBaseType_t ) 0 ) + { + /* It is dangerous to remove a queue from a set when the queue is + * not empty because the queue set will still hold pending events for + * the queue. */ + xReturn = pdFAIL; + } + else + { +#ifdef ESP_PLATFORM + Queue_t* pxQueue = (Queue_t*)pxQueueOrSemaphore; +#endif + taskENTER_CRITICAL(); + { + /* The queue is no longer contained in the set. */ + pxQueueOrSemaphore->pxQueueSetContainer = NULL; + } + taskEXIT_CRITICAL(); + xReturn = pdPASS; + } - return xReturn; - } /*lint !e818 xQueueSet could not be declared as pointing to const as it is a typedef. */ + return xReturn; + } /*lint !e818 xQueueSet could not be declared as pointing to const as it is a typedef. */ #endif /* configUSE_QUEUE_SETS */ /*-----------------------------------------------------------*/ #if ( configUSE_QUEUE_SETS == 1 ) - QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, TickType_t const xTicksToWait ) - { - QueueSetMemberHandle_t xReturn = NULL; + QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, + TickType_t const xTicksToWait ) + { + QueueSetMemberHandle_t xReturn = NULL; - ( void ) xQueueReceive( ( QueueHandle_t ) xQueueSet, &xReturn, xTicksToWait ); /*lint !e961 Casting from one typedef to another is not redundant. */ - return xReturn; - } + ( void ) xQueueReceive( ( QueueHandle_t ) xQueueSet, &xReturn, xTicksToWait ); /*lint !e961 Casting from one typedef to another is not redundant. */ + return xReturn; + } #endif /* configUSE_QUEUE_SETS */ /*-----------------------------------------------------------*/ #if ( configUSE_QUEUE_SETS == 1 ) - QueueSetMemberHandle_t xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet ) - { - QueueSetMemberHandle_t xReturn = NULL; + QueueSetMemberHandle_t xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet ) + { + QueueSetMemberHandle_t xReturn = NULL; - ( void ) xQueueReceiveFromISR( ( QueueHandle_t ) xQueueSet, &xReturn, NULL ); /*lint !e961 Casting from one typedef to another is not redundant. */ - return xReturn; - } + ( void ) xQueueReceiveFromISR( ( QueueHandle_t ) xQueueSet, &xReturn, NULL ); /*lint !e961 Casting from one typedef to another is not redundant. */ + return xReturn; + } #endif /* configUSE_QUEUE_SETS */ /*-----------------------------------------------------------*/ #if ( configUSE_QUEUE_SETS == 1 ) - static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue, const BaseType_t xCopyPosition ) - { - Queue_t *pxQueueSetContainer = pxQueue->pxQueueSetContainer; - BaseType_t xReturn = pdFALSE; + static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue, + const BaseType_t xCopyPosition ) + { + Queue_t * pxQueueSetContainer = pxQueue->pxQueueSetContainer; + BaseType_t xReturn = pdFALSE; - /* This function must be called form a critical section. */ + /* This function must be called form a critical section. */ - configASSERT( pxQueueSetContainer ); + /* The following line is not reachable in unit tests because every call + * to prvNotifyQueueSetContainer is preceded by a check that + * pxQueueSetContainer != NULL */ + configASSERT( pxQueueSetContainer ); /* LCOV_EXCL_BR_LINE */ - //Acquire the Queue set's spinlock - portENTER_CRITICAL(&(pxQueueSetContainer->mux)); + //Acquire the Queue set's spinlock + portENTER_CRITICAL(&(pxQueueSetContainer->mux)); - configASSERT( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength ); + configASSERT( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength ); - if( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength ) - { - const int8_t cTxLock = pxQueueSetContainer->cTxLock; + if( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength ) + { + const int8_t cTxLock = pxQueueSetContainer->cTxLock; - traceQUEUE_SEND( pxQueueSetContainer ); + traceQUEUE_SEND( pxQueueSetContainer ); - /* The data copied is the handle of the queue that contains data. */ - xReturn = prvCopyDataToQueue( pxQueueSetContainer, &pxQueue, xCopyPosition ); + /* The data copied is the handle of the queue that contains data. */ + xReturn = prvCopyDataToQueue( pxQueueSetContainer, &pxQueue, xCopyPosition ); - if( cTxLock == queueUNLOCKED ) - { - if( listLIST_IS_EMPTY( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The task waiting has a higher priority. */ - xReturn = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - pxQueueSetContainer->cTxLock = ( int8_t ) ( cTxLock + 1 ); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + if( cTxLock == queueUNLOCKED ) + { + if( listLIST_IS_EMPTY( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority. */ + xReturn = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + pxQueueSetContainer->cTxLock = ( int8_t ) ( cTxLock + 1 ); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - //Release the Queue set's spinlock - portEXIT_CRITICAL(&(pxQueueSetContainer->mux)); + //Release the Queue set's spinlock + portEXIT_CRITICAL(&(pxQueueSetContainer->mux)); - return xReturn; - } + return xReturn; + } #endif /* configUSE_QUEUE_SETS */ diff --git a/components/freertos/stream_buffer.c b/components/freertos/stream_buffer.c index d5a21b0876..bc3991bdca 100644 --- a/components/freertos/stream_buffer.c +++ b/components/freertos/stream_buffer.c @@ -1,6 +1,6 @@ /* - * FreeRTOS Kernel V10.2.1 - * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V10.4.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * 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 @@ -19,10 +19,9 @@ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS * - * 1 tab == 4 spaces! */ /* Standard includes. */ @@ -30,8 +29,8 @@ #include /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining -all the API functions to use the MPU wrappers. That should only be done when -task.h is included from an application file. */ + * all the API functions to use the MPU wrappers. That should only be done when + * task.h is included from an application file. */ #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE /* FreeRTOS includes. */ @@ -39,121 +38,165 @@ task.h is included from an application file. */ #include "task.h" #include "stream_buffer.h" -#if( configUSE_TASK_NOTIFICATIONS != 1 ) - #error configUSE_TASK_NOTIFICATIONS must be set to 1 to build stream_buffer.c +#ifdef ESP_PLATFORM +#define taskCRITICAL_MUX &pxStreamBuffer->xStreamBufferMux +#undef taskENTER_CRITICAL +#undef taskEXIT_CRITICAL +#undef taskENTER_CRITICAL_ISR +#undef taskEXIT_CRITICAL_ISR +#define taskENTER_CRITICAL( ) portENTER_CRITICAL( taskCRITICAL_MUX ) +#define taskEXIT_CRITICAL( ) portEXIT_CRITICAL( taskCRITICAL_MUX ) +#define taskENTER_CRITICAL_ISR( ) portENTER_CRITICAL_ISR( taskCRITICAL_MUX ) +#define taskEXIT_CRITICAL_ISR( ) portEXIT_CRITICAL_ISR( taskCRITICAL_MUX ) +#endif + +#if ( configUSE_TASK_NOTIFICATIONS != 1 ) + #error configUSE_TASK_NOTIFICATIONS must be set to 1 to build stream_buffer.c #endif /* Lint e961, e9021 and e750 are suppressed as a MISRA exception justified -because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined -for the header files above, but not in this file, in order to generate the -correct privileged Vs unprivileged linkage and placement. */ + * because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined + * for the header files above, but not in this file, in order to generate the + * correct privileged Vs unprivileged linkage and placement. */ #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021. */ /* If the user has not provided application specific Rx notification macros, -or #defined the notification macros away, them provide default implementations -that uses task notifications. */ -/*lint -save -e9026 Function like macros allowed and needed here so they can be overidden. */ + * or #defined the notification macros away, then provide default implementations + * that uses task notifications. */ +/*lint -save -e9026 Function like macros allowed and needed here so they can be overridden. */ + #ifndef sbRECEIVE_COMPLETED - #define sbRECEIVE_COMPLETED( pxStreamBuffer ) \ - taskENTER_CRITICAL( &pxStreamBuffer->xStreamBufferMux ); \ - { \ - if( ( pxStreamBuffer )->xTaskWaitingToSend != NULL ) \ - { \ - ( void ) xTaskNotify( ( pxStreamBuffer )->xTaskWaitingToSend, \ - ( uint32_t ) 0, \ - eNoAction ); \ - ( pxStreamBuffer )->xTaskWaitingToSend = NULL; \ - } \ - } \ - taskEXIT_CRITICAL( &pxStreamBuffer->xStreamBufferMux ); +#ifdef ESP_PLATFORM // IDF-3775 + #define sbRECEIVE_COMPLETED( pxStreamBuffer ) \ + taskENTER_CRITICAL(); \ + { \ + if( ( pxStreamBuffer )->xTaskWaitingToSend != NULL ) \ + { \ + ( void ) xTaskNotify( ( pxStreamBuffer )->xTaskWaitingToSend, \ + ( uint32_t ) 0, \ + eNoAction ); \ + ( pxStreamBuffer )->xTaskWaitingToSend = NULL; \ + } \ + } \ + taskEXIT_CRITICAL(); +#else + #define sbRECEIVE_COMPLETED( pxStreamBuffer ) \ + vTaskSuspendAll(); \ + { \ + if( ( pxStreamBuffer )->xTaskWaitingToSend != NULL ) \ + { \ + ( void ) xTaskNotify( ( pxStreamBuffer )->xTaskWaitingToSend, \ + ( uint32_t ) 0, \ + eNoAction ); \ + ( pxStreamBuffer )->xTaskWaitingToSend = NULL; \ + } \ + } \ + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM #endif /* sbRECEIVE_COMPLETED */ #ifndef sbRECEIVE_COMPLETED_FROM_ISR - #define sbRECEIVE_COMPLETED_FROM_ISR( pxStreamBuffer, \ - pxHigherPriorityTaskWoken ) \ - { \ - UBaseType_t uxSavedInterruptStatus; \ - \ - uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR(); \ - { \ - if( ( pxStreamBuffer )->xTaskWaitingToSend != NULL ) \ - { \ - ( void ) xTaskNotifyFromISR( ( pxStreamBuffer )->xTaskWaitingToSend, \ - ( uint32_t ) 0, \ - eNoAction, \ - pxHigherPriorityTaskWoken ); \ - ( pxStreamBuffer )->xTaskWaitingToSend = NULL; \ - } \ - } \ - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \ - } + #define sbRECEIVE_COMPLETED_FROM_ISR( pxStreamBuffer, \ + pxHigherPriorityTaskWoken ) \ + { \ + UBaseType_t uxSavedInterruptStatus; \ + \ + uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR(); \ + { \ + if( ( pxStreamBuffer )->xTaskWaitingToSend != NULL ) \ + { \ + ( void ) xTaskNotifyFromISR( ( pxStreamBuffer )->xTaskWaitingToSend, \ + ( uint32_t ) 0, \ + eNoAction, \ + pxHigherPriorityTaskWoken ); \ + ( pxStreamBuffer )->xTaskWaitingToSend = NULL; \ + } \ + } \ + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \ + } #endif /* sbRECEIVE_COMPLETED_FROM_ISR */ /* If the user has not provided an application specific Tx notification macro, -or #defined the notification macro away, them provide a default implementation -that uses task notifications. */ + * or #defined the notification macro away, them provide a default implementation + * that uses task notifications. */ #ifndef sbSEND_COMPLETED - #define sbSEND_COMPLETED( pxStreamBuffer ) \ - taskENTER_CRITICAL( &pxStreamBuffer->xStreamBufferMux ); \ - { \ - if( ( pxStreamBuffer )->xTaskWaitingToReceive != NULL ) \ - { \ - ( void ) xTaskNotify( ( pxStreamBuffer )->xTaskWaitingToReceive, \ - ( uint32_t ) 0, \ - eNoAction ); \ - ( pxStreamBuffer )->xTaskWaitingToReceive = NULL; \ - } \ - } \ - taskEXIT_CRITICAL( &pxStreamBuffer->xStreamBufferMux ); +#ifdef ESP_PLATFORM // IDF-3755 + #define sbSEND_COMPLETED( pxStreamBuffer ) \ + taskENTER_CRITICAL(); \ + { \ + if( ( pxStreamBuffer )->xTaskWaitingToReceive != NULL ) \ + { \ + ( void ) xTaskNotify( ( pxStreamBuffer )->xTaskWaitingToReceive, \ + ( uint32_t ) 0, \ + eNoAction ); \ + ( pxStreamBuffer )->xTaskWaitingToReceive = NULL; \ + } \ + } \ + taskEXIT_CRITICAL(); +#else + #define sbSEND_COMPLETED( pxStreamBuffer ) \ + vTaskSuspendAll(); \ + { \ + if( ( pxStreamBuffer )->xTaskWaitingToReceive != NULL ) \ + { \ + ( void ) xTaskNotify( ( pxStreamBuffer )->xTaskWaitingToReceive, \ + ( uint32_t ) 0, \ + eNoAction ); \ + ( pxStreamBuffer )->xTaskWaitingToReceive = NULL; \ + } \ + } \ + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM #endif /* sbSEND_COMPLETED */ #ifndef sbSEND_COMPLETE_FROM_ISR - #define sbSEND_COMPLETE_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken ) \ - { \ - UBaseType_t uxSavedInterruptStatus; \ - \ - uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR(); \ - { \ - if( ( pxStreamBuffer )->xTaskWaitingToReceive != NULL ) \ - { \ - ( void ) xTaskNotifyFromISR( ( pxStreamBuffer )->xTaskWaitingToReceive, \ - ( uint32_t ) 0, \ - eNoAction, \ - pxHigherPriorityTaskWoken ); \ - ( pxStreamBuffer )->xTaskWaitingToReceive = NULL; \ - } \ - } \ - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \ - } + #define sbSEND_COMPLETE_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken ) \ + { \ + UBaseType_t uxSavedInterruptStatus; \ + \ + uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR(); \ + { \ + if( ( pxStreamBuffer )->xTaskWaitingToReceive != NULL ) \ + { \ + ( void ) xTaskNotifyFromISR( ( pxStreamBuffer )->xTaskWaitingToReceive, \ + ( uint32_t ) 0, \ + eNoAction, \ + pxHigherPriorityTaskWoken ); \ + ( pxStreamBuffer )->xTaskWaitingToReceive = NULL; \ + } \ + } \ + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \ + } #endif /* sbSEND_COMPLETE_FROM_ISR */ /*lint -restore (9026) */ /* The number of bytes used to hold the length of a message in the buffer. */ -#define sbBYTES_TO_STORE_MESSAGE_LENGTH ( sizeof( configMESSAGE_BUFFER_LENGTH_TYPE ) ) +#define sbBYTES_TO_STORE_MESSAGE_LENGTH ( sizeof( configMESSAGE_BUFFER_LENGTH_TYPE ) ) /* Bits stored in the ucFlags field of the stream buffer. */ -#define sbFLAGS_IS_MESSAGE_BUFFER ( ( uint8_t ) 1 ) /* Set if the stream buffer was created as a message buffer, in which case it holds discrete messages rather than a stream. */ -#define sbFLAGS_IS_STATICALLY_ALLOCATED ( ( uint8_t ) 2 ) /* Set if the stream buffer was created using statically allocated memory. */ +#define sbFLAGS_IS_MESSAGE_BUFFER ( ( uint8_t ) 1 ) /* Set if the stream buffer was created as a message buffer, in which case it holds discrete messages rather than a stream. */ +#define sbFLAGS_IS_STATICALLY_ALLOCATED ( ( uint8_t ) 2 ) /* Set if the stream buffer was created using statically allocated memory. */ /*-----------------------------------------------------------*/ /* Structure that hold state information on the buffer. */ -typedef struct StreamBufferDef_t /*lint !e9058 Style convention uses tag. */ +typedef struct StreamBufferDef_t /*lint !e9058 Style convention uses tag. */ { - volatile size_t xTail; /* Index to the next item to read within the buffer. */ - volatile size_t xHead; /* Index to the next item to write within the buffer. */ - size_t xLength; /* The length of the buffer pointed to by pucBuffer. */ - size_t xTriggerLevelBytes; /* The number of bytes that must be in the stream buffer before a task that is waiting for data is unblocked. */ - volatile TaskHandle_t xTaskWaitingToReceive; /* Holds the handle of a task waiting for data, or NULL if no tasks are waiting. */ - volatile TaskHandle_t xTaskWaitingToSend; /* Holds the handle of a task waiting to send data to a message buffer that is full. */ - uint8_t *pucBuffer; /* Points to the buffer itself - that is - the RAM that stores the data passed through the buffer. */ - uint8_t ucFlags; + volatile size_t xTail; /* Index to the next item to read within the buffer. */ + volatile size_t xHead; /* Index to the next item to write within the buffer. */ + size_t xLength; /* The length of the buffer pointed to by pucBuffer. */ + size_t xTriggerLevelBytes; /* The number of bytes that must be in the stream buffer before a task that is waiting for data is unblocked. */ + volatile TaskHandle_t xTaskWaitingToReceive; /* Holds the handle of a task waiting for data, or NULL if no tasks are waiting. */ + volatile TaskHandle_t xTaskWaitingToSend; /* Holds the handle of a task waiting to send data to a message buffer that is full. */ + uint8_t * pucBuffer; /* Points to the buffer itself - that is - the RAM that stores the data passed through the buffer. */ + uint8_t ucFlags; - #if ( configUSE_TRACE_FACILITY == 1 ) - UBaseType_t uxStreamBufferNumber; /* Used for tracing purposes. */ - #endif - - portMUX_TYPE xStreamBufferMux; //Mutex required due to SMP + #if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxStreamBufferNumber; /* Used for tracing purposes. */ + #endif +#ifdef ESP_PLATFORM + portMUX_TYPE xStreamBufferMux; //Mutex required due to SMP +#endif // ESP_PLATFORM } StreamBuffer_t; /* @@ -167,7 +210,9 @@ static size_t prvBytesInBuffer( const StreamBuffer_t * const pxStreamBuffer ) PR * success case, or 0 if there was not enough space in the buffer (in which case * no data is written into the buffer). */ -static size_t prvWriteBytesToBuffer( StreamBuffer_t * const pxStreamBuffer, const uint8_t *pucData, size_t xCount ) PRIVILEGED_FUNCTION; +static size_t prvWriteBytesToBuffer( StreamBuffer_t * const pxStreamBuffer, + const uint8_t * pucData, + size_t xCount ) PRIVILEGED_FUNCTION; /* * If the stream buffer is being used as a message buffer, then reads an entire @@ -176,11 +221,11 @@ static size_t prvWriteBytesToBuffer( StreamBuffer_t * const pxStreamBuffer, cons * prvReadBytesFromBuffer() is called to actually extract the bytes from the * buffer's data storage area. */ -static size_t prvReadMessageFromBuffer( StreamBuffer_t *pxStreamBuffer, - void *pvRxData, - size_t xBufferLengthBytes, - size_t xBytesAvailable, - size_t xBytesToStoreMessageLength ) PRIVILEGED_FUNCTION; +static size_t prvReadMessageFromBuffer( StreamBuffer_t * pxStreamBuffer, + void * pvRxData, + size_t xBufferLengthBytes, + size_t xBytesAvailable, + size_t xBytesToStoreMessageLength ) PRIVILEGED_FUNCTION; /* * If the stream buffer is being used as a message buffer, then writes an entire @@ -189,1084 +234,1130 @@ static size_t prvReadMessageFromBuffer( StreamBuffer_t *pxStreamBuffer, * prvWriteBytestoBuffer() is called to actually send the bytes to the buffer's * data storage area. */ -static size_t prvWriteMessageToBuffer( StreamBuffer_t * const pxStreamBuffer, - const void * pvTxData, - size_t xDataLengthBytes, - size_t xSpace, - size_t xRequiredSpace ) PRIVILEGED_FUNCTION; +static size_t prvWriteMessageToBuffer( StreamBuffer_t * const pxStreamBuffer, + const void * pvTxData, + size_t xDataLengthBytes, + size_t xSpace, + size_t xRequiredSpace ) PRIVILEGED_FUNCTION; /* * Read xMaxCount bytes from the pxStreamBuffer message buffer and write them * to pucData. */ -static size_t prvReadBytesFromBuffer( StreamBuffer_t *pxStreamBuffer, - uint8_t *pucData, - size_t xMaxCount, - size_t xBytesAvailable ) PRIVILEGED_FUNCTION; +static size_t prvReadBytesFromBuffer( StreamBuffer_t * pxStreamBuffer, + uint8_t * pucData, + size_t xMaxCount, + size_t xBytesAvailable ) PRIVILEGED_FUNCTION; /* * Called by both pxStreamBufferCreate() and pxStreamBufferCreateStatic() to * initialise the members of the newly created stream buffer structure. */ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer, - uint8_t * const pucBuffer, - size_t xBufferSizeBytes, - size_t xTriggerLevelBytes, - uint8_t ucFlags ) PRIVILEGED_FUNCTION; + uint8_t * const pucBuffer, + size_t xBufferSizeBytes, + size_t xTriggerLevelBytes, + uint8_t ucFlags ) PRIVILEGED_FUNCTION; /*-----------------------------------------------------------*/ -#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) +#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) - StreamBufferHandle_t xStreamBufferGenericCreate( size_t xBufferSizeBytes, size_t xTriggerLevelBytes, BaseType_t xIsMessageBuffer ) - { - uint8_t *pucAllocatedMemory; - uint8_t ucFlags; + StreamBufferHandle_t xStreamBufferGenericCreate( size_t xBufferSizeBytes, + size_t xTriggerLevelBytes, + BaseType_t xIsMessageBuffer ) + { + uint8_t * pucAllocatedMemory; + uint8_t ucFlags; - /* In case the stream buffer is going to be used as a message buffer - (that is, it will hold discrete messages with a little meta data that - says how big the next message is) check the buffer will be large enough - to hold at least one message. */ - if( xIsMessageBuffer == pdTRUE ) - { - /* Is a message buffer but not statically allocated. */ - ucFlags = sbFLAGS_IS_MESSAGE_BUFFER; - configASSERT( xBufferSizeBytes > sbBYTES_TO_STORE_MESSAGE_LENGTH ); - } - else - { - /* Not a message buffer and not statically allocated. */ - ucFlags = 0; - configASSERT( xBufferSizeBytes > 0 ); - } - configASSERT( xTriggerLevelBytes <= xBufferSizeBytes ); + /* In case the stream buffer is going to be used as a message buffer + * (that is, it will hold discrete messages with a little meta data that + * says how big the next message is) check the buffer will be large enough + * to hold at least one message. */ + if( xIsMessageBuffer == pdTRUE ) + { + /* Is a message buffer but not statically allocated. */ + ucFlags = sbFLAGS_IS_MESSAGE_BUFFER; + configASSERT( xBufferSizeBytes > sbBYTES_TO_STORE_MESSAGE_LENGTH ); + } + else + { + /* Not a message buffer and not statically allocated. */ + ucFlags = 0; + configASSERT( xBufferSizeBytes > 0 ); + } - /* A trigger level of 0 would cause a waiting task to unblock even when - the buffer was empty. */ - if( xTriggerLevelBytes == ( size_t ) 0 ) - { - xTriggerLevelBytes = ( size_t ) 1; - } + configASSERT( xTriggerLevelBytes <= xBufferSizeBytes ); - /* A stream buffer requires a StreamBuffer_t structure and a buffer. - Both are allocated in a single call to pvPortMalloc(). The - StreamBuffer_t structure is placed at the start of the allocated memory - and the buffer follows immediately after. The requested size is - incremented so the free space is returned as the user would expect - - this is a quirk of the implementation that means otherwise the free - space would be reported as one byte smaller than would be logically - expected. */ - if( xBufferSizeBytes < ( xBufferSizeBytes + 1 + sizeof( StreamBuffer_t ) ) ) - { - xBufferSizeBytes++; - pucAllocatedMemory = ( uint8_t * ) pvPortMalloc( xBufferSizeBytes + sizeof( StreamBuffer_t ) ); /*lint !e9079 malloc() only returns void*. */ - } - else - { - pucAllocatedMemory = NULL; - } + /* A trigger level of 0 would cause a waiting task to unblock even when + * the buffer was empty. */ + if( xTriggerLevelBytes == ( size_t ) 0 ) + { + xTriggerLevelBytes = ( size_t ) 1; + } - if( pucAllocatedMemory != NULL ) - { - prvInitialiseNewStreamBuffer( ( StreamBuffer_t * ) pucAllocatedMemory, /* Structure at the start of the allocated memory. */ /*lint !e9087 Safe cast as allocated memory is aligned. */ /*lint !e826 Area is not too small and alignment is guaranteed provided malloc() behaves as expected and returns aligned buffer. */ - pucAllocatedMemory + sizeof( StreamBuffer_t ), /* Storage area follows. */ /*lint !e9016 Indexing past structure valid for uint8_t pointer, also storage area has no alignment requirement. */ - xBufferSizeBytes, - xTriggerLevelBytes, - ucFlags ); + /* A stream buffer requires a StreamBuffer_t structure and a buffer. + * Both are allocated in a single call to pvPortMalloc(). The + * StreamBuffer_t structure is placed at the start of the allocated memory + * and the buffer follows immediately after. The requested size is + * incremented so the free space is returned as the user would expect - + * this is a quirk of the implementation that means otherwise the free + * space would be reported as one byte smaller than would be logically + * expected. */ + if( xBufferSizeBytes < ( xBufferSizeBytes + 1 + sizeof( StreamBuffer_t ) ) ) + { + xBufferSizeBytes++; + pucAllocatedMemory = ( uint8_t * ) pvPortMalloc( xBufferSizeBytes + sizeof( StreamBuffer_t ) ); /*lint !e9079 malloc() only returns void*. */ + } + else + { + pucAllocatedMemory = NULL; + } - traceSTREAM_BUFFER_CREATE( ( ( StreamBuffer_t * ) pucAllocatedMemory ), xIsMessageBuffer ); - } - else - { - traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer ); - } + if( pucAllocatedMemory != NULL ) + { + prvInitialiseNewStreamBuffer( ( StreamBuffer_t * ) pucAllocatedMemory, /* Structure at the start of the allocated memory. */ /*lint !e9087 Safe cast as allocated memory is aligned. */ /*lint !e826 Area is not too small and alignment is guaranteed provided malloc() behaves as expected and returns aligned buffer. */ + pucAllocatedMemory + sizeof( StreamBuffer_t ), /* Storage area follows. */ /*lint !e9016 Indexing past structure valid for uint8_t pointer, also storage area has no alignment requirement. */ + xBufferSizeBytes, + xTriggerLevelBytes, + ucFlags ); - return ( StreamBufferHandle_t ) pucAllocatedMemory; /*lint !e9087 !e826 Safe cast as allocated memory is aligned. */ - } + traceSTREAM_BUFFER_CREATE( ( ( StreamBuffer_t * ) pucAllocatedMemory ), xIsMessageBuffer ); + } + else + { + traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer ); + } + + return ( StreamBufferHandle_t ) pucAllocatedMemory; /*lint !e9087 !e826 Safe cast as allocated memory is aligned. */ + } #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ /*-----------------------------------------------------------*/ -#if( configSUPPORT_STATIC_ALLOCATION == 1 ) +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) - StreamBufferHandle_t xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes, - size_t xTriggerLevelBytes, - BaseType_t xIsMessageBuffer, - uint8_t * const pucStreamBufferStorageArea, - StaticStreamBuffer_t * const pxStaticStreamBuffer ) - { - StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) pxStaticStreamBuffer; /*lint !e740 !e9087 Safe cast as StaticStreamBuffer_t is opaque Streambuffer_t. */ - StreamBufferHandle_t xReturn; - uint8_t ucFlags; + StreamBufferHandle_t xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes, + size_t xTriggerLevelBytes, + BaseType_t xIsMessageBuffer, + uint8_t * const pucStreamBufferStorageArea, + StaticStreamBuffer_t * const pxStaticStreamBuffer ) + { + StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) pxStaticStreamBuffer; /*lint !e740 !e9087 Safe cast as StaticStreamBuffer_t is opaque Streambuffer_t. */ + StreamBufferHandle_t xReturn; + uint8_t ucFlags; - configASSERT( pucStreamBufferStorageArea ); - configASSERT( pxStaticStreamBuffer ); - configASSERT( xTriggerLevelBytes <= xBufferSizeBytes ); + configASSERT( pucStreamBufferStorageArea ); + configASSERT( pxStaticStreamBuffer ); + configASSERT( xTriggerLevelBytes <= xBufferSizeBytes ); - /* A trigger level of 0 would cause a waiting task to unblock even when - the buffer was empty. */ - if( xTriggerLevelBytes == ( size_t ) 0 ) - { - xTriggerLevelBytes = ( size_t ) 1; - } + /* A trigger level of 0 would cause a waiting task to unblock even when + * the buffer was empty. */ + if( xTriggerLevelBytes == ( size_t ) 0 ) + { + xTriggerLevelBytes = ( size_t ) 1; + } - if( xIsMessageBuffer != pdFALSE ) - { - /* Statically allocated message buffer. */ - ucFlags = sbFLAGS_IS_MESSAGE_BUFFER | sbFLAGS_IS_STATICALLY_ALLOCATED; - } - else - { - /* Statically allocated stream buffer. */ - ucFlags = sbFLAGS_IS_STATICALLY_ALLOCATED; - } + if( xIsMessageBuffer != pdFALSE ) + { + /* Statically allocated message buffer. */ + ucFlags = sbFLAGS_IS_MESSAGE_BUFFER | sbFLAGS_IS_STATICALLY_ALLOCATED; + } + else + { + /* Statically allocated stream buffer. */ + ucFlags = sbFLAGS_IS_STATICALLY_ALLOCATED; + } - /* In case the stream buffer is going to be used as a message buffer - (that is, it will hold discrete messages with a little meta data that - says how big the next message is) check the buffer will be large enough - to hold at least one message. */ - configASSERT( xBufferSizeBytes > sbBYTES_TO_STORE_MESSAGE_LENGTH ); + /* In case the stream buffer is going to be used as a message buffer + * (that is, it will hold discrete messages with a little meta data that + * says how big the next message is) check the buffer will be large enough + * to hold at least one message. */ + configASSERT( xBufferSizeBytes > sbBYTES_TO_STORE_MESSAGE_LENGTH ); - #if( configASSERT_DEFINED == 1 ) - { - /* Sanity check that the size of the structure used to declare a - variable of type StaticStreamBuffer_t equals the size of the real - message buffer structure. */ - volatile size_t xSize = sizeof( StaticStreamBuffer_t ); - configASSERT( xSize == sizeof( StreamBuffer_t ) ); - } /*lint !e529 xSize is referenced is configASSERT() is defined. */ - #endif /* configASSERT_DEFINED */ + #if ( configASSERT_DEFINED == 1 ) + { + /* Sanity check that the size of the structure used to declare a + * variable of type StaticStreamBuffer_t equals the size of the real + * message buffer structure. */ + volatile size_t xSize = sizeof( StaticStreamBuffer_t ); + configASSERT( xSize == sizeof( StreamBuffer_t ) ); + } /*lint !e529 xSize is referenced is configASSERT() is defined. */ + #endif /* configASSERT_DEFINED */ - if( ( pucStreamBufferStorageArea != NULL ) && ( pxStaticStreamBuffer != NULL ) ) - { - prvInitialiseNewStreamBuffer( pxStreamBuffer, - pucStreamBufferStorageArea, - xBufferSizeBytes, - xTriggerLevelBytes, - ucFlags ); - /* Remember this was statically allocated in case it is ever deleted - again. */ - pxStreamBuffer->ucFlags |= sbFLAGS_IS_STATICALLY_ALLOCATED; + if( ( pucStreamBufferStorageArea != NULL ) && ( pxStaticStreamBuffer != NULL ) ) + { + prvInitialiseNewStreamBuffer( pxStreamBuffer, + pucStreamBufferStorageArea, + xBufferSizeBytes, + xTriggerLevelBytes, + ucFlags ); - traceSTREAM_BUFFER_CREATE( pxStreamBuffer, xIsMessageBuffer ); + /* Remember this was statically allocated in case it is ever deleted + * again. */ + pxStreamBuffer->ucFlags |= sbFLAGS_IS_STATICALLY_ALLOCATED; - xReturn = ( StreamBufferHandle_t ) pxStaticStreamBuffer; /*lint !e9087 Data hiding requires cast to opaque type. */ - } - else - { - xReturn = NULL; - traceSTREAM_BUFFER_CREATE_STATIC_FAILED( xReturn, xIsMessageBuffer ); - } + traceSTREAM_BUFFER_CREATE( pxStreamBuffer, xIsMessageBuffer ); - return xReturn; - } + xReturn = ( StreamBufferHandle_t ) pxStaticStreamBuffer; /*lint !e9087 Data hiding requires cast to opaque type. */ + } + else + { + xReturn = NULL; + traceSTREAM_BUFFER_CREATE_STATIC_FAILED( xReturn, xIsMessageBuffer ); + } + + return xReturn; + } #endif /* ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ /*-----------------------------------------------------------*/ void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) { -StreamBuffer_t * pxStreamBuffer = xStreamBuffer; + StreamBuffer_t * pxStreamBuffer = xStreamBuffer; - configASSERT( pxStreamBuffer ); + configASSERT( pxStreamBuffer ); - traceSTREAM_BUFFER_DELETE( xStreamBuffer ); + traceSTREAM_BUFFER_DELETE( xStreamBuffer ); - if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_STATICALLY_ALLOCATED ) == ( uint8_t ) pdFALSE ) - { - #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) - { - /* Both the structure and the buffer were allocated using a single call - to pvPortMalloc(), hence only one call to vPortFree() is required. */ - vPortFree( ( void * ) pxStreamBuffer ); /*lint !e9087 Standard free() semantics require void *, plus pxStreamBuffer was allocated by pvPortMalloc(). */ - } - #else - { - /* Should not be possible to get here, ucFlags must be corrupt. - Force an assert. */ - configASSERT( xStreamBuffer == ( StreamBufferHandle_t ) ~0 ); - } - #endif - } - else - { - /* The structure and buffer were not allocated dynamically and cannot be - freed - just scrub the structure so future use will assert. */ - ( void ) memset( pxStreamBuffer, 0x00, sizeof( StreamBuffer_t ) ); - } + if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_STATICALLY_ALLOCATED ) == ( uint8_t ) pdFALSE ) + { + #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + { + /* Both the structure and the buffer were allocated using a single call + * to pvPortMalloc(), hence only one call to vPortFree() is required. */ + vPortFree( ( void * ) pxStreamBuffer ); /*lint !e9087 Standard free() semantics require void *, plus pxStreamBuffer was allocated by pvPortMalloc(). */ + } + #else + { + /* Should not be possible to get here, ucFlags must be corrupt. + * Force an assert. */ + configASSERT( xStreamBuffer == ( StreamBufferHandle_t ) ~0 ); + } + #endif + } + else + { + /* The structure and buffer were not allocated dynamically and cannot be + * freed - just scrub the structure so future use will assert. */ + ( void ) memset( pxStreamBuffer, 0x00, sizeof( StreamBuffer_t ) ); + } } /*-----------------------------------------------------------*/ BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ) { -StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; -BaseType_t xReturn = pdFAIL; + StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; + BaseType_t xReturn = pdFAIL; -#if( configUSE_TRACE_FACILITY == 1 ) - UBaseType_t uxStreamBufferNumber; -#endif + #if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxStreamBufferNumber; + #endif - configASSERT( pxStreamBuffer ); + configASSERT( pxStreamBuffer ); - #if( configUSE_TRACE_FACILITY == 1 ) - { - /* Store the stream buffer number so it can be restored after the - reset. */ - uxStreamBufferNumber = pxStreamBuffer->uxStreamBufferNumber; - } - #endif + #if ( configUSE_TRACE_FACILITY == 1 ) + { + /* Store the stream buffer number so it can be restored after the + * reset. */ + uxStreamBufferNumber = pxStreamBuffer->uxStreamBufferNumber; + } + #endif - /* Can only reset a message buffer if there are no tasks blocked on it. */ - taskENTER_CRITICAL( &pxStreamBuffer->xStreamBufferMux ); - { - if( pxStreamBuffer->xTaskWaitingToReceive == NULL ) - { - if( pxStreamBuffer->xTaskWaitingToSend == NULL ) - { - prvInitialiseNewStreamBuffer( pxStreamBuffer, - pxStreamBuffer->pucBuffer, - pxStreamBuffer->xLength, - pxStreamBuffer->xTriggerLevelBytes, - pxStreamBuffer->ucFlags ); - xReturn = pdPASS; + /* Can only reset a message buffer if there are no tasks blocked on it. */ + taskENTER_CRITICAL(); + { + if( pxStreamBuffer->xTaskWaitingToReceive == NULL ) + { + if( pxStreamBuffer->xTaskWaitingToSend == NULL ) + { + prvInitialiseNewStreamBuffer( pxStreamBuffer, + pxStreamBuffer->pucBuffer, + pxStreamBuffer->xLength, + pxStreamBuffer->xTriggerLevelBytes, + pxStreamBuffer->ucFlags ); + xReturn = pdPASS; - #if( configUSE_TRACE_FACILITY == 1 ) - { - pxStreamBuffer->uxStreamBufferNumber = uxStreamBufferNumber; - } - #endif + #if ( configUSE_TRACE_FACILITY == 1 ) + { + pxStreamBuffer->uxStreamBufferNumber = uxStreamBufferNumber; + } + #endif - traceSTREAM_BUFFER_RESET( xStreamBuffer ); - } - } - } - taskEXIT_CRITICAL( &pxStreamBuffer->xStreamBufferMux ); + traceSTREAM_BUFFER_RESET( xStreamBuffer ); + } + } + } + taskEXIT_CRITICAL(); - return xReturn; + return xReturn; } /*-----------------------------------------------------------*/ -BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, size_t xTriggerLevel ) +BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, + size_t xTriggerLevel ) { -StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; -BaseType_t xReturn; + StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; + BaseType_t xReturn; - configASSERT( pxStreamBuffer ); + configASSERT( pxStreamBuffer ); - /* It is not valid for the trigger level to be 0. */ - if( xTriggerLevel == ( size_t ) 0 ) - { - xTriggerLevel = ( size_t ) 1; - } + /* It is not valid for the trigger level to be 0. */ + if( xTriggerLevel == ( size_t ) 0 ) + { + xTriggerLevel = ( size_t ) 1; + } - /* The trigger level is the number of bytes that must be in the stream - buffer before a task that is waiting for data is unblocked. */ - if( xTriggerLevel <= pxStreamBuffer->xLength ) - { - pxStreamBuffer->xTriggerLevelBytes = xTriggerLevel; - xReturn = pdPASS; - } - else - { - xReturn = pdFALSE; - } + /* The trigger level is the number of bytes that must be in the stream + * buffer before a task that is waiting for data is unblocked. */ + if( xTriggerLevel <= pxStreamBuffer->xLength ) + { + pxStreamBuffer->xTriggerLevelBytes = xTriggerLevel; + xReturn = pdPASS; + } + else + { + xReturn = pdFALSE; + } - return xReturn; + return xReturn; } /*-----------------------------------------------------------*/ size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer ) { -const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; -size_t xSpace; + const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; + size_t xSpace; - configASSERT( pxStreamBuffer ); + configASSERT( pxStreamBuffer ); - xSpace = pxStreamBuffer->xLength + pxStreamBuffer->xTail; - xSpace -= pxStreamBuffer->xHead; - xSpace -= ( size_t ) 1; + xSpace = pxStreamBuffer->xLength + pxStreamBuffer->xTail; + xSpace -= pxStreamBuffer->xHead; + xSpace -= ( size_t ) 1; - if( xSpace >= pxStreamBuffer->xLength ) - { - xSpace -= pxStreamBuffer->xLength; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + if( xSpace >= pxStreamBuffer->xLength ) + { + xSpace -= pxStreamBuffer->xLength; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - return xSpace; + return xSpace; } /*-----------------------------------------------------------*/ size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer ) { -const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; -size_t xReturn; + const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; + size_t xReturn; - configASSERT( pxStreamBuffer ); + configASSERT( pxStreamBuffer ); - xReturn = prvBytesInBuffer( pxStreamBuffer ); - return xReturn; + xReturn = prvBytesInBuffer( pxStreamBuffer ); + return xReturn; } /*-----------------------------------------------------------*/ size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, - const void *pvTxData, - size_t xDataLengthBytes, - TickType_t xTicksToWait ) + const void * pvTxData, + size_t xDataLengthBytes, + TickType_t xTicksToWait ) { -StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; -size_t xReturn, xSpace = 0; -size_t xRequiredSpace = xDataLengthBytes; -TimeOut_t xTimeOut; + StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; + size_t xReturn, xSpace = 0; + size_t xRequiredSpace = xDataLengthBytes; + TimeOut_t xTimeOut; + size_t xMaxReportedSpace = 0; - configASSERT( pvTxData ); - configASSERT( pxStreamBuffer ); + configASSERT( pvTxData ); + configASSERT( pxStreamBuffer ); - /* This send function is used to write to both message buffers and stream - buffers. If this is a message buffer then the space needed must be - increased by the amount of bytes needed to store the length of the - message. */ - if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 ) - { - xRequiredSpace += sbBYTES_TO_STORE_MESSAGE_LENGTH; + /* The maximum amount of space a stream buffer will ever report is its length + * minus 1. */ + xMaxReportedSpace = pxStreamBuffer->xLength - ( size_t ) 1; - /* Overflow? */ - configASSERT( xRequiredSpace > xDataLengthBytes ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* This send function is used to write to both message buffers and stream + * buffers. If this is a message buffer then the space needed must be + * increased by the amount of bytes needed to store the length of the + * message. */ + if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 ) + { + xRequiredSpace += sbBYTES_TO_STORE_MESSAGE_LENGTH; - if( xTicksToWait != ( TickType_t ) 0 ) - { - vTaskSetTimeOutState( &xTimeOut ); + /* Overflow? */ + configASSERT( xRequiredSpace > xDataLengthBytes ); - do - { - /* Wait until the required number of bytes are free in the message - buffer. */ - taskENTER_CRITICAL( &pxStreamBuffer->xStreamBufferMux ); - { - xSpace = xStreamBufferSpacesAvailable( pxStreamBuffer ); + /* If this is a message buffer then it must be possible to write the + * whole message. */ + if( xRequiredSpace > xMaxReportedSpace ) + { + /* The message would not fit even if the entire buffer was empty, + * so don't wait for space. */ + xTicksToWait = ( TickType_t ) 0; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* If this is a stream buffer then it is acceptable to write only part + * of the message to the buffer. Cap the length to the total length of + * the buffer. */ + if( xRequiredSpace > xMaxReportedSpace ) + { + xRequiredSpace = xMaxReportedSpace; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } - if( xSpace < xRequiredSpace ) - { - /* Clear notification state as going to wait for space. */ - ( void ) xTaskNotifyStateClear( NULL ); + if( xTicksToWait != ( TickType_t ) 0 ) + { + vTaskSetTimeOutState( &xTimeOut ); - /* Should only be one writer. */ - configASSERT( pxStreamBuffer->xTaskWaitingToSend == NULL ); - pxStreamBuffer->xTaskWaitingToSend = xTaskGetCurrentTaskHandle(); - } - else - { - taskEXIT_CRITICAL( &pxStreamBuffer->xStreamBufferMux ); - break; - } - } - taskEXIT_CRITICAL( &pxStreamBuffer->xStreamBufferMux ); + do + { + /* Wait until the required number of bytes are free in the message + * buffer. */ + taskENTER_CRITICAL(); + { + xSpace = xStreamBufferSpacesAvailable( pxStreamBuffer ); - traceBLOCKING_ON_STREAM_BUFFER_SEND( xStreamBuffer ); - ( void ) xTaskNotifyWait( ( uint32_t ) 0, ( uint32_t ) 0, NULL, xTicksToWait ); - pxStreamBuffer->xTaskWaitingToSend = NULL; + if( xSpace < xRequiredSpace ) + { + /* Clear notification state as going to wait for space. */ + ( void ) xTaskNotifyStateClear( NULL ); - } while( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* Should only be one writer. */ + configASSERT( pxStreamBuffer->xTaskWaitingToSend == NULL ); + pxStreamBuffer->xTaskWaitingToSend = xTaskGetCurrentTaskHandle(); + } + else + { + taskEXIT_CRITICAL(); + break; + } + } + taskEXIT_CRITICAL(); - if( xSpace == ( size_t ) 0 ) - { - xSpace = xStreamBufferSpacesAvailable( pxStreamBuffer ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + traceBLOCKING_ON_STREAM_BUFFER_SEND( xStreamBuffer ); + ( void ) xTaskNotifyWait( ( uint32_t ) 0, ( uint32_t ) 0, NULL, xTicksToWait ); + pxStreamBuffer->xTaskWaitingToSend = NULL; + } while( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - xReturn = prvWriteMessageToBuffer( pxStreamBuffer, pvTxData, xDataLengthBytes, xSpace, xRequiredSpace ); + if( xSpace == ( size_t ) 0 ) + { + xSpace = xStreamBufferSpacesAvailable( pxStreamBuffer ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - if( xReturn > ( size_t ) 0 ) - { - traceSTREAM_BUFFER_SEND( xStreamBuffer, xReturn ); + xReturn = prvWriteMessageToBuffer( pxStreamBuffer, pvTxData, xDataLengthBytes, xSpace, xRequiredSpace ); - /* Was a task waiting for the data? */ - if( prvBytesInBuffer( pxStreamBuffer ) >= pxStreamBuffer->xTriggerLevelBytes ) - { - sbSEND_COMPLETED( pxStreamBuffer ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - traceSTREAM_BUFFER_SEND_FAILED( xStreamBuffer ); - } + if( xReturn > ( size_t ) 0 ) + { + traceSTREAM_BUFFER_SEND( xStreamBuffer, xReturn ); - return xReturn; + /* Was a task waiting for the data? */ + if( prvBytesInBuffer( pxStreamBuffer ) >= pxStreamBuffer->xTriggerLevelBytes ) + { + sbSEND_COMPLETED( pxStreamBuffer ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + traceSTREAM_BUFFER_SEND_FAILED( xStreamBuffer ); + } + + return xReturn; } /*-----------------------------------------------------------*/ size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer, - const void *pvTxData, - size_t xDataLengthBytes, - BaseType_t * const pxHigherPriorityTaskWoken ) + const void * pvTxData, + size_t xDataLengthBytes, + BaseType_t * const pxHigherPriorityTaskWoken ) { -StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; -size_t xReturn, xSpace; -size_t xRequiredSpace = xDataLengthBytes; + StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; + size_t xReturn, xSpace; + size_t xRequiredSpace = xDataLengthBytes; - configASSERT( pvTxData ); - configASSERT( pxStreamBuffer ); + configASSERT( pvTxData ); + configASSERT( pxStreamBuffer ); - /* This send function is used to write to both message buffers and stream - buffers. If this is a message buffer then the space needed must be - increased by the amount of bytes needed to store the length of the - message. */ - if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 ) - { - xRequiredSpace += sbBYTES_TO_STORE_MESSAGE_LENGTH; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* This send function is used to write to both message buffers and stream + * buffers. If this is a message buffer then the space needed must be + * increased by the amount of bytes needed to store the length of the + * message. */ + if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 ) + { + xRequiredSpace += sbBYTES_TO_STORE_MESSAGE_LENGTH; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - xSpace = xStreamBufferSpacesAvailable( pxStreamBuffer ); - xReturn = prvWriteMessageToBuffer( pxStreamBuffer, pvTxData, xDataLengthBytes, xSpace, xRequiredSpace ); + xSpace = xStreamBufferSpacesAvailable( pxStreamBuffer ); + xReturn = prvWriteMessageToBuffer( pxStreamBuffer, pvTxData, xDataLengthBytes, xSpace, xRequiredSpace ); - if( xReturn > ( size_t ) 0 ) - { - /* Was a task waiting for the data? */ - if( prvBytesInBuffer( pxStreamBuffer ) >= pxStreamBuffer->xTriggerLevelBytes ) - { - sbSEND_COMPLETE_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + if( xReturn > ( size_t ) 0 ) + { + /* Was a task waiting for the data? */ + if( prvBytesInBuffer( pxStreamBuffer ) >= pxStreamBuffer->xTriggerLevelBytes ) + { + sbSEND_COMPLETE_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - traceSTREAM_BUFFER_SEND_FROM_ISR( xStreamBuffer, xReturn ); + traceSTREAM_BUFFER_SEND_FROM_ISR( xStreamBuffer, xReturn ); - return xReturn; + return xReturn; } /*-----------------------------------------------------------*/ static size_t prvWriteMessageToBuffer( StreamBuffer_t * const pxStreamBuffer, - const void * pvTxData, - size_t xDataLengthBytes, - size_t xSpace, - size_t xRequiredSpace ) + const void * pvTxData, + size_t xDataLengthBytes, + size_t xSpace, + size_t xRequiredSpace ) { - BaseType_t xShouldWrite; - size_t xReturn; + BaseType_t xShouldWrite; + size_t xReturn; - if( xSpace == ( size_t ) 0 ) - { - /* Doesn't matter if this is a stream buffer or a message buffer, there - is no space to write. */ - xShouldWrite = pdFALSE; - } - else if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) == ( uint8_t ) 0 ) - { - /* This is a stream buffer, as opposed to a message buffer, so writing a - stream of bytes rather than discrete messages. Write as many bytes as - possible. */ - xShouldWrite = pdTRUE; - xDataLengthBytes = configMIN( xDataLengthBytes, xSpace ); - } - else if( xSpace >= xRequiredSpace ) - { - /* This is a message buffer, as opposed to a stream buffer, and there - is enough space to write both the message length and the message itself - into the buffer. Start by writing the length of the data, the data - itself will be written later in this function. */ - xShouldWrite = pdTRUE; - ( void ) prvWriteBytesToBuffer( pxStreamBuffer, ( const uint8_t * ) &( xDataLengthBytes ), sbBYTES_TO_STORE_MESSAGE_LENGTH ); - } - else - { - /* There is space available, but not enough space. */ - xShouldWrite = pdFALSE; - } + if( xSpace == ( size_t ) 0 ) + { + /* Doesn't matter if this is a stream buffer or a message buffer, there + * is no space to write. */ + xShouldWrite = pdFALSE; + } + else if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) == ( uint8_t ) 0 ) + { + /* This is a stream buffer, as opposed to a message buffer, so writing a + * stream of bytes rather than discrete messages. Write as many bytes as + * possible. */ + xShouldWrite = pdTRUE; + xDataLengthBytes = configMIN( xDataLengthBytes, xSpace ); + } + else if( xSpace >= xRequiredSpace ) + { + /* This is a message buffer, as opposed to a stream buffer, and there + * is enough space to write both the message length and the message itself + * into the buffer. Start by writing the length of the data, the data + * itself will be written later in this function. */ + xShouldWrite = pdTRUE; + ( void ) prvWriteBytesToBuffer( pxStreamBuffer, ( const uint8_t * ) &( xDataLengthBytes ), sbBYTES_TO_STORE_MESSAGE_LENGTH ); + } + else + { + /* There is space available, but not enough space. */ + xShouldWrite = pdFALSE; + } - if( xShouldWrite != pdFALSE ) - { - /* Writes the data itself. */ - xReturn = prvWriteBytesToBuffer( pxStreamBuffer, ( const uint8_t * ) pvTxData, xDataLengthBytes ); /*lint !e9079 Storage buffer is implemented as uint8_t for ease of sizing, alighment and access. */ - } - else - { - xReturn = 0; - } + if( xShouldWrite != pdFALSE ) + { + /* Writes the data itself. */ + xReturn = prvWriteBytesToBuffer( pxStreamBuffer, ( const uint8_t * ) pvTxData, xDataLengthBytes ); /*lint !e9079 Storage buffer is implemented as uint8_t for ease of sizing, alignment and access. */ + } + else + { + xReturn = 0; + } - return xReturn; + return xReturn; } /*-----------------------------------------------------------*/ size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer, - void *pvRxData, - size_t xBufferLengthBytes, - TickType_t xTicksToWait ) + void * pvRxData, + size_t xBufferLengthBytes, + TickType_t xTicksToWait ) { -StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; -size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength; + StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; + size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength; - configASSERT( pvRxData ); - configASSERT( pxStreamBuffer ); + configASSERT( pvRxData ); + configASSERT( pxStreamBuffer ); - /* This receive function is used by both message buffers, which store - discrete messages, and stream buffers, which store a continuous stream of - bytes. Discrete messages include an additional - sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the - message. */ - if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 ) - { - xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH; - } - else - { - xBytesToStoreMessageLength = 0; - } + /* This receive function is used by both message buffers, which store + * discrete messages, and stream buffers, which store a continuous stream of + * bytes. Discrete messages include an additional + * sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the + * message. */ + if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 ) + { + xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH; + } + else + { + xBytesToStoreMessageLength = 0; + } - if( xTicksToWait != ( TickType_t ) 0 ) - { - /* Checking if there is data and clearing the notification state must be - performed atomically. */ - taskENTER_CRITICAL( &pxStreamBuffer->xStreamBufferMux ); - { - xBytesAvailable = prvBytesInBuffer( pxStreamBuffer ); + if( xTicksToWait != ( TickType_t ) 0 ) + { + /* Checking if there is data and clearing the notification state must be + * performed atomically. */ + taskENTER_CRITICAL(); + { + xBytesAvailable = prvBytesInBuffer( pxStreamBuffer ); - /* If this function was invoked by a message buffer read then - xBytesToStoreMessageLength holds the number of bytes used to hold - the length of the next discrete message. If this function was - invoked by a stream buffer read then xBytesToStoreMessageLength will - be 0. */ - if( xBytesAvailable <= xBytesToStoreMessageLength ) - { - /* Clear notification state as going to wait for data. */ - ( void ) xTaskNotifyStateClear( NULL ); + /* If this function was invoked by a message buffer read then + * xBytesToStoreMessageLength holds the number of bytes used to hold + * the length of the next discrete message. If this function was + * invoked by a stream buffer read then xBytesToStoreMessageLength will + * be 0. */ + if( xBytesAvailable <= xBytesToStoreMessageLength ) + { + /* Clear notification state as going to wait for data. */ + ( void ) xTaskNotifyStateClear( NULL ); - /* Should only be one reader. */ - configASSERT( pxStreamBuffer->xTaskWaitingToReceive == NULL ); - pxStreamBuffer->xTaskWaitingToReceive = xTaskGetCurrentTaskHandle(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - taskEXIT_CRITICAL( &pxStreamBuffer->xStreamBufferMux ); + /* Should only be one reader. */ + configASSERT( pxStreamBuffer->xTaskWaitingToReceive == NULL ); + pxStreamBuffer->xTaskWaitingToReceive = xTaskGetCurrentTaskHandle(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(); - if( xBytesAvailable <= xBytesToStoreMessageLength ) - { - /* 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; + if( xBytesAvailable <= xBytesToStoreMessageLength ) + { + /* 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; - /* Recheck the data available after blocking. */ - xBytesAvailable = prvBytesInBuffer( pxStreamBuffer ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - xBytesAvailable = prvBytesInBuffer( pxStreamBuffer ); - } + /* Recheck the data available after blocking. */ + xBytesAvailable = prvBytesInBuffer( pxStreamBuffer ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + xBytesAvailable = prvBytesInBuffer( pxStreamBuffer ); + } - /* Whether receiving a discrete message (where xBytesToStoreMessageLength - holds the number of bytes used to store the message length) or a stream of - bytes (where xBytesToStoreMessageLength is zero), the number of bytes - available must be greater than xBytesToStoreMessageLength to be able to - read bytes from the buffer. */ - if( xBytesAvailable > xBytesToStoreMessageLength ) - { - xReceivedLength = prvReadMessageFromBuffer( pxStreamBuffer, pvRxData, xBufferLengthBytes, xBytesAvailable, xBytesToStoreMessageLength ); + /* Whether receiving a discrete message (where xBytesToStoreMessageLength + * holds the number of bytes used to store the message length) or a stream of + * bytes (where xBytesToStoreMessageLength is zero), the number of bytes + * available must be greater than xBytesToStoreMessageLength to be able to + * read bytes from the buffer. */ + if( xBytesAvailable > xBytesToStoreMessageLength ) + { + xReceivedLength = prvReadMessageFromBuffer( pxStreamBuffer, pvRxData, xBufferLengthBytes, xBytesAvailable, xBytesToStoreMessageLength ); - /* Was a task waiting for space in the buffer? */ - if( xReceivedLength != ( size_t ) 0 ) - { - traceSTREAM_BUFFER_RECEIVE( xStreamBuffer, xReceivedLength ); - sbRECEIVE_COMPLETED( pxStreamBuffer ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - traceSTREAM_BUFFER_RECEIVE_FAILED( xStreamBuffer ); - mtCOVERAGE_TEST_MARKER(); - } + /* Was a task waiting for space in the buffer? */ + if( xReceivedLength != ( size_t ) 0 ) + { + traceSTREAM_BUFFER_RECEIVE( xStreamBuffer, xReceivedLength ); + sbRECEIVE_COMPLETED( pxStreamBuffer ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + traceSTREAM_BUFFER_RECEIVE_FAILED( xStreamBuffer ); + mtCOVERAGE_TEST_MARKER(); + } - return xReceivedLength; + return xReceivedLength; } /*-----------------------------------------------------------*/ size_t xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) { -StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; -size_t xReturn, xBytesAvailable, xOriginalTail; -configMESSAGE_BUFFER_LENGTH_TYPE xTempReturn; + StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; + size_t xReturn, xBytesAvailable, xOriginalTail; + configMESSAGE_BUFFER_LENGTH_TYPE xTempReturn; - configASSERT( pxStreamBuffer ); + configASSERT( pxStreamBuffer ); - /* Ensure the stream buffer is being used as a message buffer. */ - if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 ) - { - xBytesAvailable = prvBytesInBuffer( pxStreamBuffer ); - if( xBytesAvailable > sbBYTES_TO_STORE_MESSAGE_LENGTH ) - { - /* The number of bytes available is greater than the number of bytes - required to hold the length of the next message, so another message - is available. Return its length without removing the length bytes - from the buffer. A copy of the tail is stored so the buffer can be - returned to its prior state as the message is not actually being - removed from the buffer. */ - xOriginalTail = pxStreamBuffer->xTail; - ( void ) prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) &xTempReturn, sbBYTES_TO_STORE_MESSAGE_LENGTH, xBytesAvailable ); - xReturn = ( size_t ) xTempReturn; - pxStreamBuffer->xTail = xOriginalTail; - } - else - { - /* The minimum amount of bytes in a message buffer is - ( sbBYTES_TO_STORE_MESSAGE_LENGTH + 1 ), so if xBytesAvailable is - less than sbBYTES_TO_STORE_MESSAGE_LENGTH the only other valid - value is 0. */ - configASSERT( xBytesAvailable == 0 ); - xReturn = 0; - } - } - else - { - xReturn = 0; - } + /* Ensure the stream buffer is being used as a message buffer. */ + if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 ) + { + xBytesAvailable = prvBytesInBuffer( pxStreamBuffer ); - return xReturn; + if( xBytesAvailable > sbBYTES_TO_STORE_MESSAGE_LENGTH ) + { + /* The number of bytes available is greater than the number of bytes + * required to hold the length of the next message, so another message + * is available. Return its length without removing the length bytes + * from the buffer. A copy of the tail is stored so the buffer can be + * returned to its prior state as the message is not actually being + * removed from the buffer. */ + xOriginalTail = pxStreamBuffer->xTail; + ( void ) prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) &xTempReturn, sbBYTES_TO_STORE_MESSAGE_LENGTH, xBytesAvailable ); + xReturn = ( size_t ) xTempReturn; + pxStreamBuffer->xTail = xOriginalTail; + } + else + { + /* The minimum amount of bytes in a message buffer is + * ( sbBYTES_TO_STORE_MESSAGE_LENGTH + 1 ), so if xBytesAvailable is + * less than sbBYTES_TO_STORE_MESSAGE_LENGTH the only other valid + * value is 0. */ + configASSERT( xBytesAvailable == 0 ); + xReturn = 0; + } + } + else + { + xReturn = 0; + } + + return xReturn; } /*-----------------------------------------------------------*/ size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer, - void *pvRxData, - size_t xBufferLengthBytes, - BaseType_t * const pxHigherPriorityTaskWoken ) + void * pvRxData, + size_t xBufferLengthBytes, + BaseType_t * const pxHigherPriorityTaskWoken ) { -StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; -size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength; + StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; + size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength; - configASSERT( pvRxData ); - configASSERT( pxStreamBuffer ); + configASSERT( pvRxData ); + configASSERT( pxStreamBuffer ); - /* This receive function is used by both message buffers, which store - discrete messages, and stream buffers, which store a continuous stream of - bytes. Discrete messages include an additional - sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the - message. */ - if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 ) - { - xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH; - } - else - { - xBytesToStoreMessageLength = 0; - } + /* This receive function is used by both message buffers, which store + * discrete messages, and stream buffers, which store a continuous stream of + * bytes. Discrete messages include an additional + * sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the + * message. */ + if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 ) + { + xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH; + } + else + { + xBytesToStoreMessageLength = 0; + } - xBytesAvailable = prvBytesInBuffer( pxStreamBuffer ); + xBytesAvailable = prvBytesInBuffer( pxStreamBuffer ); - /* Whether receiving a discrete message (where xBytesToStoreMessageLength - holds the number of bytes used to store the message length) or a stream of - bytes (where xBytesToStoreMessageLength is zero), the number of bytes - available must be greater than xBytesToStoreMessageLength to be able to - read bytes from the buffer. */ - if( xBytesAvailable > xBytesToStoreMessageLength ) - { - xReceivedLength = prvReadMessageFromBuffer( pxStreamBuffer, pvRxData, xBufferLengthBytes, xBytesAvailable, xBytesToStoreMessageLength ); + /* Whether receiving a discrete message (where xBytesToStoreMessageLength + * holds the number of bytes used to store the message length) or a stream of + * bytes (where xBytesToStoreMessageLength is zero), the number of bytes + * available must be greater than xBytesToStoreMessageLength to be able to + * read bytes from the buffer. */ + if( xBytesAvailable > xBytesToStoreMessageLength ) + { + xReceivedLength = prvReadMessageFromBuffer( pxStreamBuffer, pvRxData, xBufferLengthBytes, xBytesAvailable, xBytesToStoreMessageLength ); - /* Was a task waiting for space in the buffer? */ - if( xReceivedLength != ( size_t ) 0 ) - { - sbRECEIVE_COMPLETED_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* Was a task waiting for space in the buffer? */ + if( xReceivedLength != ( size_t ) 0 ) + { + sbRECEIVE_COMPLETED_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - traceSTREAM_BUFFER_RECEIVE_FROM_ISR( xStreamBuffer, xReceivedLength ); + traceSTREAM_BUFFER_RECEIVE_FROM_ISR( xStreamBuffer, xReceivedLength ); - return xReceivedLength; + return xReceivedLength; } /*-----------------------------------------------------------*/ -static size_t prvReadMessageFromBuffer( StreamBuffer_t *pxStreamBuffer, - void *pvRxData, - size_t xBufferLengthBytes, - size_t xBytesAvailable, - size_t xBytesToStoreMessageLength ) +static size_t prvReadMessageFromBuffer( StreamBuffer_t * pxStreamBuffer, + void * pvRxData, + size_t xBufferLengthBytes, + size_t xBytesAvailable, + size_t xBytesToStoreMessageLength ) { -size_t xOriginalTail, xReceivedLength, xNextMessageLength; -configMESSAGE_BUFFER_LENGTH_TYPE xTempNextMessageLength; + size_t xOriginalTail, xReceivedLength, xNextMessageLength; + configMESSAGE_BUFFER_LENGTH_TYPE xTempNextMessageLength; - if( xBytesToStoreMessageLength != ( size_t ) 0 ) - { - /* A discrete message is being received. First receive the length - of the message. A copy of the tail is stored so the buffer can be - returned to its prior state if the length of the message is too - large for the provided buffer. */ - xOriginalTail = pxStreamBuffer->xTail; - ( void ) prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) &xTempNextMessageLength, xBytesToStoreMessageLength, xBytesAvailable ); - xNextMessageLength = ( size_t ) xTempNextMessageLength; + if( xBytesToStoreMessageLength != ( size_t ) 0 ) + { + /* A discrete message is being received. First receive the length + * of the message. A copy of the tail is stored so the buffer can be + * returned to its prior state if the length of the message is too + * large for the provided buffer. */ + xOriginalTail = pxStreamBuffer->xTail; + ( void ) prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) &xTempNextMessageLength, xBytesToStoreMessageLength, xBytesAvailable ); + xNextMessageLength = ( size_t ) xTempNextMessageLength; - /* Reduce the number of bytes available by the number of bytes just - read out. */ - xBytesAvailable -= xBytesToStoreMessageLength; + /* Reduce the number of bytes available by the number of bytes just + * read out. */ + xBytesAvailable -= xBytesToStoreMessageLength; - /* Check there is enough space in the buffer provided by the - user. */ - if( xNextMessageLength > xBufferLengthBytes ) - { - /* The user has provided insufficient space to read the message - so return the buffer to its previous state (so the length of - the message is in the buffer again). */ - pxStreamBuffer->xTail = xOriginalTail; - xNextMessageLength = 0; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - /* A stream of bytes is being received (as opposed to a discrete - message), so read as many bytes as possible. */ - xNextMessageLength = xBufferLengthBytes; - } + /* Check there is enough space in the buffer provided by the + * user. */ + if( xNextMessageLength > xBufferLengthBytes ) + { + /* The user has provided insufficient space to read the message + * so return the buffer to its previous state (so the length of + * the message is in the buffer again). */ + pxStreamBuffer->xTail = xOriginalTail; + xNextMessageLength = 0; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* A stream of bytes is being received (as opposed to a discrete + * message), so read as many bytes as possible. */ + xNextMessageLength = xBufferLengthBytes; + } - /* Read the actual data. */ - xReceivedLength = prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) pvRxData, xNextMessageLength, xBytesAvailable ); /*lint !e9079 Data storage area is implemented as uint8_t array for ease of sizing, indexing and alignment. */ + /* Read the actual data. */ + xReceivedLength = prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) pvRxData, xNextMessageLength, xBytesAvailable ); /*lint !e9079 Data storage area is implemented as uint8_t array for ease of sizing, indexing and alignment. */ - return xReceivedLength; + return xReceivedLength; } /*-----------------------------------------------------------*/ BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer ) { -const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; -BaseType_t xReturn; -size_t xTail; + const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; + BaseType_t xReturn; + size_t xTail; - configASSERT( pxStreamBuffer ); + configASSERT( pxStreamBuffer ); - /* True if no bytes are available. */ - xTail = pxStreamBuffer->xTail; - if( pxStreamBuffer->xHead == xTail ) - { - xReturn = pdTRUE; - } - else - { - xReturn = pdFALSE; - } + /* True if no bytes are available. */ + xTail = pxStreamBuffer->xTail; - return xReturn; + if( pxStreamBuffer->xHead == xTail ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + + return xReturn; } /*-----------------------------------------------------------*/ BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ) { -BaseType_t xReturn; -size_t xBytesToStoreMessageLength; -const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; + BaseType_t xReturn; + size_t xBytesToStoreMessageLength; + const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; - configASSERT( pxStreamBuffer ); + configASSERT( pxStreamBuffer ); - /* This generic version of the receive function is used by both message - buffers, which store discrete messages, and stream buffers, which store a - continuous stream of bytes. Discrete messages include an additional - sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the message. */ - if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 ) - { - xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH; - } - else - { - xBytesToStoreMessageLength = 0; - } + /* This generic version of the receive function is used by both message + * buffers, which store discrete messages, and stream buffers, which store a + * continuous stream of bytes. Discrete messages include an additional + * sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the message. */ + if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 ) + { + xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH; + } + else + { + xBytesToStoreMessageLength = 0; + } - /* True if the available space equals zero. */ - if( xStreamBufferSpacesAvailable( xStreamBuffer ) <= xBytesToStoreMessageLength ) - { - xReturn = pdTRUE; - } - else - { - xReturn = pdFALSE; - } + /* True if the available space equals zero. */ + if( xStreamBufferSpacesAvailable( xStreamBuffer ) <= xBytesToStoreMessageLength ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } - return xReturn; + return xReturn; } /*-----------------------------------------------------------*/ -BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken ) +BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer, + BaseType_t * pxHigherPriorityTaskWoken ) { -StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; -BaseType_t xReturn; -UBaseType_t uxSavedInterruptStatus; + StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; + BaseType_t xReturn; + UBaseType_t uxSavedInterruptStatus; - configASSERT( pxStreamBuffer ); + configASSERT( pxStreamBuffer ); - uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR(); - { - if( ( pxStreamBuffer )->xTaskWaitingToReceive != NULL ) - { - ( void ) xTaskNotifyFromISR( ( pxStreamBuffer )->xTaskWaitingToReceive, - ( uint32_t ) 0, - eNoAction, - pxHigherPriorityTaskWoken ); - ( pxStreamBuffer )->xTaskWaitingToReceive = NULL; - xReturn = pdTRUE; - } - else - { - xReturn = pdFALSE; - } - } - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR(); + { + if( ( pxStreamBuffer )->xTaskWaitingToReceive != NULL ) + { + ( void ) xTaskNotifyFromISR( ( pxStreamBuffer )->xTaskWaitingToReceive, + ( uint32_t ) 0, + eNoAction, + pxHigherPriorityTaskWoken ); + ( pxStreamBuffer )->xTaskWaitingToReceive = NULL; + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); - return xReturn; + return xReturn; } /*-----------------------------------------------------------*/ -BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken ) +BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer, + BaseType_t * pxHigherPriorityTaskWoken ) { -StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; -BaseType_t xReturn; -UBaseType_t uxSavedInterruptStatus; + StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; + BaseType_t xReturn; + UBaseType_t uxSavedInterruptStatus; - configASSERT( pxStreamBuffer ); + configASSERT( pxStreamBuffer ); - uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR(); - { - if( ( pxStreamBuffer )->xTaskWaitingToSend != NULL ) - { - ( void ) xTaskNotifyFromISR( ( pxStreamBuffer )->xTaskWaitingToSend, - ( uint32_t ) 0, - eNoAction, - pxHigherPriorityTaskWoken ); - ( pxStreamBuffer )->xTaskWaitingToSend = NULL; - xReturn = pdTRUE; - } - else - { - xReturn = pdFALSE; - } - } - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR(); + { + if( ( pxStreamBuffer )->xTaskWaitingToSend != NULL ) + { + ( void ) xTaskNotifyFromISR( ( pxStreamBuffer )->xTaskWaitingToSend, + ( uint32_t ) 0, + eNoAction, + pxHigherPriorityTaskWoken ); + ( pxStreamBuffer )->xTaskWaitingToSend = NULL; + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); - return xReturn; + return xReturn; } /*-----------------------------------------------------------*/ -static size_t prvWriteBytesToBuffer( StreamBuffer_t * const pxStreamBuffer, const uint8_t *pucData, size_t xCount ) +static size_t prvWriteBytesToBuffer( StreamBuffer_t * const pxStreamBuffer, + const uint8_t * pucData, + size_t xCount ) { -size_t xNextHead, xFirstLength; + size_t xNextHead, xFirstLength; - configASSERT( xCount > ( size_t ) 0 ); + configASSERT( xCount > ( size_t ) 0 ); - xNextHead = pxStreamBuffer->xHead; + xNextHead = pxStreamBuffer->xHead; - /* Calculate the number of bytes that can be added in the first write - - which may be less than the total number of bytes that need to be added if - the buffer will wrap back to the beginning. */ - xFirstLength = configMIN( pxStreamBuffer->xLength - xNextHead, xCount ); + /* Calculate the number of bytes that can be added in the first write - + * which may be less than the total number of bytes that need to be added if + * the buffer will wrap back to the beginning. */ + xFirstLength = configMIN( pxStreamBuffer->xLength - xNextHead, xCount ); - /* Write as many bytes as can be written in the first write. */ - configASSERT( ( xNextHead + xFirstLength ) <= pxStreamBuffer->xLength ); - ( void ) memcpy( ( void* ) ( &( pxStreamBuffer->pucBuffer[ xNextHead ] ) ), ( const void * ) pucData, xFirstLength ); /*lint !e9087 memcpy() requires void *. */ + /* Write as many bytes as can be written in the first write. */ + configASSERT( ( xNextHead + xFirstLength ) <= pxStreamBuffer->xLength ); + ( void ) memcpy( ( void * ) ( &( pxStreamBuffer->pucBuffer[ xNextHead ] ) ), ( const void * ) pucData, xFirstLength ); /*lint !e9087 memcpy() requires void *. */ - /* If the number of bytes written was less than the number that could be - written in the first write... */ - if( xCount > xFirstLength ) - { - /* ...then write the remaining bytes to the start of the buffer. */ - configASSERT( ( xCount - xFirstLength ) <= pxStreamBuffer->xLength ); - ( void ) memcpy( ( void * ) pxStreamBuffer->pucBuffer, ( const void * ) &( pucData[ xFirstLength ] ), xCount - xFirstLength ); /*lint !e9087 memcpy() requires void *. */ - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* If the number of bytes written was less than the number that could be + * written in the first write... */ + if( xCount > xFirstLength ) + { + /* ...then write the remaining bytes to the start of the buffer. */ + configASSERT( ( xCount - xFirstLength ) <= pxStreamBuffer->xLength ); + ( void ) memcpy( ( void * ) pxStreamBuffer->pucBuffer, ( const void * ) &( pucData[ xFirstLength ] ), xCount - xFirstLength ); /*lint !e9087 memcpy() requires void *. */ + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - xNextHead += xCount; - if( xNextHead >= pxStreamBuffer->xLength ) - { - xNextHead -= pxStreamBuffer->xLength; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + xNextHead += xCount; - pxStreamBuffer->xHead = xNextHead; + if( xNextHead >= pxStreamBuffer->xLength ) + { + xNextHead -= pxStreamBuffer->xLength; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - return xCount; + pxStreamBuffer->xHead = xNextHead; + + return xCount; } /*-----------------------------------------------------------*/ -static size_t prvReadBytesFromBuffer( StreamBuffer_t *pxStreamBuffer, uint8_t *pucData, size_t xMaxCount, size_t xBytesAvailable ) +static size_t prvReadBytesFromBuffer( StreamBuffer_t * pxStreamBuffer, + uint8_t * pucData, + size_t xMaxCount, + size_t xBytesAvailable ) { -size_t xCount, xFirstLength, xNextTail; + size_t xCount, xFirstLength, xNextTail; - /* Use the minimum of the wanted bytes and the available bytes. */ - xCount = configMIN( xBytesAvailable, xMaxCount ); + /* Use the minimum of the wanted bytes and the available bytes. */ + xCount = configMIN( xBytesAvailable, xMaxCount ); - if( xCount > ( size_t ) 0 ) - { - xNextTail = pxStreamBuffer->xTail; + if( xCount > ( size_t ) 0 ) + { + xNextTail = pxStreamBuffer->xTail; - /* Calculate the number of bytes that can be read - which may be - less than the number wanted if the data wraps around to the start of - the buffer. */ - xFirstLength = configMIN( pxStreamBuffer->xLength - xNextTail, xCount ); + /* Calculate the number of bytes that can be read - which may be + * less than the number wanted if the data wraps around to the start of + * the buffer. */ + xFirstLength = configMIN( pxStreamBuffer->xLength - xNextTail, xCount ); - /* Obtain the number of bytes it is possible to obtain in the first - read. Asserts check bounds of read and write. */ - configASSERT( xFirstLength <= xMaxCount ); - configASSERT( ( xNextTail + xFirstLength ) <= pxStreamBuffer->xLength ); - ( void ) memcpy( ( void * ) pucData, ( const void * ) &( pxStreamBuffer->pucBuffer[ xNextTail ] ), xFirstLength ); /*lint !e9087 memcpy() requires void *. */ + /* Obtain the number of bytes it is possible to obtain in the first + * read. Asserts check bounds of read and write. */ + configASSERT( xFirstLength <= xMaxCount ); + configASSERT( ( xNextTail + xFirstLength ) <= pxStreamBuffer->xLength ); + ( void ) memcpy( ( void * ) pucData, ( const void * ) &( pxStreamBuffer->pucBuffer[ xNextTail ] ), xFirstLength ); /*lint !e9087 memcpy() requires void *. */ - /* If the total number of wanted bytes is greater than the number - that could be read in the first read... */ - if( xCount > xFirstLength ) - { - /*...then read the remaining bytes from the start of the buffer. */ - configASSERT( xCount <= xMaxCount ); - ( void ) memcpy( ( void * ) &( pucData[ xFirstLength ] ), ( void * ) ( pxStreamBuffer->pucBuffer ), xCount - xFirstLength ); /*lint !e9087 memcpy() requires void *. */ - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* If the total number of wanted bytes is greater than the number + * that could be read in the first read... */ + if( xCount > xFirstLength ) + { + /*...then read the remaining bytes from the start of the buffer. */ + configASSERT( xCount <= xMaxCount ); + ( void ) memcpy( ( void * ) &( pucData[ xFirstLength ] ), ( void * ) ( pxStreamBuffer->pucBuffer ), xCount - xFirstLength ); /*lint !e9087 memcpy() requires void *. */ + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - /* Move the tail pointer to effectively remove the data read from - the buffer. */ - xNextTail += xCount; + /* Move the tail pointer to effectively remove the data read from + * the buffer. */ + xNextTail += xCount; - if( xNextTail >= pxStreamBuffer->xLength ) - { - xNextTail -= pxStreamBuffer->xLength; - } + if( xNextTail >= pxStreamBuffer->xLength ) + { + xNextTail -= pxStreamBuffer->xLength; + } - pxStreamBuffer->xTail = xNextTail; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + pxStreamBuffer->xTail = xNextTail; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - return xCount; + return xCount; } /*-----------------------------------------------------------*/ static size_t prvBytesInBuffer( const StreamBuffer_t * const pxStreamBuffer ) { /* Returns the distance between xTail and xHead. */ -size_t xCount; + size_t xCount; - xCount = pxStreamBuffer->xLength + pxStreamBuffer->xHead; - xCount -= pxStreamBuffer->xTail; - if ( xCount >= pxStreamBuffer->xLength ) - { - xCount -= pxStreamBuffer->xLength; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + xCount = pxStreamBuffer->xLength + pxStreamBuffer->xHead; + xCount -= pxStreamBuffer->xTail; - return xCount; + if( xCount >= pxStreamBuffer->xLength ) + { + xCount -= pxStreamBuffer->xLength; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + return xCount; } /*-----------------------------------------------------------*/ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer, - uint8_t * const pucBuffer, - size_t xBufferSizeBytes, - size_t xTriggerLevelBytes, - uint8_t ucFlags ) + uint8_t * const pucBuffer, + size_t xBufferSizeBytes, + size_t xTriggerLevelBytes, + uint8_t ucFlags ) { - /* Assert here is deliberately writing to the entire buffer to ensure it can - be written to without generating exceptions, and is setting the buffer to a - known value to assist in development/debugging. */ - #if( configASSERT_DEFINED == 1 ) - { - /* The value written just has to be identifiable when looking at the - memory. Don't use 0xA5 as that is the stack fill value and could - result in confusion as to what is actually being observed. */ - const BaseType_t xWriteValue = 0x55; - configASSERT( memset( pucBuffer, ( int ) xWriteValue, xBufferSizeBytes ) == pucBuffer ); - } /*lint !e529 !e438 xWriteValue is only used if configASSERT() is defined. */ - #endif + /* Assert here is deliberately writing to the entire buffer to ensure it can + * be written to without generating exceptions, and is setting the buffer to a + * known value to assist in development/debugging. */ + #if ( configASSERT_DEFINED == 1 ) + { + /* The value written just has to be identifiable when looking at the + * memory. Don't use 0xA5 as that is the stack fill value and could + * result in confusion as to what is actually being observed. */ + const BaseType_t xWriteValue = 0x55; + configASSERT( memset( pucBuffer, ( int ) xWriteValue, xBufferSizeBytes ) == pucBuffer ); + } /*lint !e529 !e438 xWriteValue is only used if configASSERT() is defined. */ + #endif - ( void ) memset( ( void * ) pxStreamBuffer, 0x00, sizeof( StreamBuffer_t ) ); /*lint !e9087 memset() requires void *. */ - pxStreamBuffer->pucBuffer = pucBuffer; - pxStreamBuffer->xLength = xBufferSizeBytes; - pxStreamBuffer->xTriggerLevelBytes = xTriggerLevelBytes; - pxStreamBuffer->ucFlags = ucFlags; - vPortCPUInitializeMutex( &pxStreamBuffer->xStreamBufferMux ); + ( void ) memset( ( void * ) pxStreamBuffer, 0x00, sizeof( StreamBuffer_t ) ); /*lint !e9087 memset() requires void *. */ + pxStreamBuffer->pucBuffer = pucBuffer; + pxStreamBuffer->xLength = xBufferSizeBytes; + pxStreamBuffer->xTriggerLevelBytes = xTriggerLevelBytes; + pxStreamBuffer->ucFlags = ucFlags; +#ifdef ESP_PLATFORM + vPortCPUInitializeMutex( &pxStreamBuffer->xStreamBufferMux ); +#endif // ESP_PLATFORM } #if ( configUSE_TRACE_FACILITY == 1 ) - UBaseType_t uxStreamBufferGetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer ) - { - return xStreamBuffer->uxStreamBufferNumber; - } + UBaseType_t uxStreamBufferGetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer ) + { + return xStreamBuffer->uxStreamBufferNumber; + } #endif /* configUSE_TRACE_FACILITY */ /*-----------------------------------------------------------*/ #if ( configUSE_TRACE_FACILITY == 1 ) - void vStreamBufferSetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer, UBaseType_t uxStreamBufferNumber ) - { - xStreamBuffer->uxStreamBufferNumber = uxStreamBufferNumber; - } + void vStreamBufferSetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer, + UBaseType_t uxStreamBufferNumber ) + { + xStreamBuffer->uxStreamBufferNumber = uxStreamBufferNumber; + } #endif /* configUSE_TRACE_FACILITY */ /*-----------------------------------------------------------*/ #if ( configUSE_TRACE_FACILITY == 1 ) - uint8_t ucStreamBufferGetStreamBufferType( StreamBufferHandle_t xStreamBuffer ) - { - return ( xStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ); - } + uint8_t ucStreamBufferGetStreamBufferType( StreamBufferHandle_t xStreamBuffer ) + { + return( xStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ); + } #endif /* configUSE_TRACE_FACILITY */ /*-----------------------------------------------------------*/ diff --git a/components/freertos/tasks.c b/components/freertos/tasks.c index 5053c8ba16..01bde4506b 100644 --- a/components/freertos/tasks.c +++ b/components/freertos/tasks.c @@ -1,6 +1,6 @@ /* - * FreeRTOS Kernel V10.2.1 - * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V10.4.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * 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 @@ -19,10 +19,9 @@ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS * - * 1 tab == 4 spaces! */ /* Standard includes. */ @@ -30,185 +29,198 @@ #include /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining -all the API functions to use the MPU wrappers. That should only be done when -task.h is included from an application file. */ + * all the API functions to use the MPU wrappers. That should only be done when + * task.h is included from an application file. */ #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE - /* FreeRTOS includes. */ #include "FreeRTOS.h" #include "task.h" #include "timers.h" #include "stack_macros.h" +#ifdef ESP_PLATFORM +#define taskCRITICAL_MUX &xTaskQueueMutex +#undef taskENTER_CRITICAL +#undef taskEXIT_CRITICAL +#undef taskENTER_CRITICAL_ISR +#undef taskEXIT_CRITICAL_ISR +#define taskENTER_CRITICAL( ) portENTER_CRITICAL( taskCRITICAL_MUX ) +#define taskEXIT_CRITICAL( ) portEXIT_CRITICAL( taskCRITICAL_MUX ) +#define taskENTER_CRITICAL_ISR( ) portENTER_CRITICAL_ISR( taskCRITICAL_MUX ) +#define taskEXIT_CRITICAL_ISR( ) portEXIT_CRITICAL_ISR( taskCRITICAL_MUX ) +#endif + /* Lint e9021, e961 and e750 are suppressed as a MISRA exception justified -because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined -for the header files above, but not in this file, in order to generate the -correct privileged Vs unprivileged linkage and placement. */ + * because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined + * for the header files above, but not in this file, in order to generate the + * correct privileged Vs unprivileged linkage and placement. */ #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021. */ /* Set configUSE_STATS_FORMATTING_FUNCTIONS to 2 to include the stats formatting -functions but without including stdio.h here. */ + * functions but without including stdio.h here. */ #if ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) - /* At the bottom of this file are two optional functions that can be used - to generate human readable text from the raw data generated by the - uxTaskGetSystemState() function. Note the formatting functions are provided - for convenience only, and are NOT considered part of the kernel. */ - #include + +/* At the bottom of this file are two optional functions that can be used + * to generate human readable text from the raw data generated by the + * uxTaskGetSystemState() function. Note the formatting functions are provided + * for convenience only, and are NOT considered part of the kernel. */ + #include #endif /* configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) */ -#if( configUSE_PREEMPTION == 0 ) - /* If the cooperative scheduler is being used then a yield should not be - performed just because a higher priority task has been woken. */ - #define taskYIELD_IF_USING_PREEMPTION() +#if ( configUSE_PREEMPTION == 0 ) + +/* If the cooperative scheduler is being used then a yield should not be + * performed just because a higher priority task has been woken. */ + #define taskYIELD_IF_USING_PREEMPTION() #else - #define taskYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API() + #define taskYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API() #endif /* Values that can be assigned to the ucNotifyState member of the TCB. */ -#define taskNOT_WAITING_NOTIFICATION ( ( uint8_t ) 0 ) -#define taskWAITING_NOTIFICATION ( ( uint8_t ) 1 ) -#define taskNOTIFICATION_RECEIVED ( ( uint8_t ) 2 ) +#define taskNOT_WAITING_NOTIFICATION ( ( uint8_t ) 0 ) /* Must be zero as it is the initialised value. */ +#define taskWAITING_NOTIFICATION ( ( uint8_t ) 1 ) +#define taskNOTIFICATION_RECEIVED ( ( uint8_t ) 2 ) /* * The value used to fill the stack of a task when the task is created. This * is used purely for checking the high water mark for tasks. */ -#define tskSTACK_FILL_BYTE ( 0xa5U ) +#define tskSTACK_FILL_BYTE ( 0xa5U ) -/* Bits used to recored how a task's stack and TCB were allocated. */ -#define tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 0 ) -#define tskSTATICALLY_ALLOCATED_STACK_ONLY ( ( uint8_t ) 1 ) -#define tskSTATICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 2 ) +/* Bits used to record how a task's stack and TCB were allocated. */ +#define tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 0 ) +#define tskSTATICALLY_ALLOCATED_STACK_ONLY ( ( uint8_t ) 1 ) +#define tskSTATICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 2 ) /* If any of the following are set then task stacks are filled with a known -value so the high water mark can be determined. If none of the following are -set then don't fill the stack so there is no unnecessary dependency on memset. */ -#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) ) - #define tskSET_NEW_STACKS_TO_KNOWN_VALUE 1 + * value so the high water mark can be determined. If none of the following are + * set then don't fill the stack so there is no unnecessary dependency on memset. */ +#if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) ) + #define tskSET_NEW_STACKS_TO_KNOWN_VALUE 1 #else - #define tskSET_NEW_STACKS_TO_KNOWN_VALUE 0 + #define tskSET_NEW_STACKS_TO_KNOWN_VALUE 0 #endif /* * Macros used by vListTask to indicate which state a task is in. */ -#define tskRUNNING_CHAR ( 'X' ) -#define tskBLOCKED_CHAR ( 'B' ) -#define tskREADY_CHAR ( 'R' ) -#define tskDELETED_CHAR ( 'D' ) -#define tskSUSPENDED_CHAR ( 'S' ) +#define tskRUNNING_CHAR ( 'X' ) +#define tskBLOCKED_CHAR ( 'B' ) +#define tskREADY_CHAR ( 'R' ) +#define tskDELETED_CHAR ( 'D' ) +#define tskSUSPENDED_CHAR ( 'S' ) /* - * Some kernel aware debuggers require the data the debugger needs access to be - * global, rather than file scope. + * Some kernel aware debuggers require the data the debugger needs access to to + * be global, rather than file scope. */ #ifdef portREMOVE_STATIC_QUALIFIER - #define static + #define static #endif /* The name allocated to the Idle task. This can be overridden by defining -configIDLE_TASK_NAME in FreeRTOSConfig.h. */ + * configIDLE_TASK_NAME in FreeRTOSConfig.h. */ #ifndef configIDLE_TASK_NAME - #define configIDLE_TASK_NAME "IDLE" + #define configIDLE_TASK_NAME "IDLE" #endif #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 ) - /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is - performed in a generic way that is not optimised to any particular - microcontroller architecture. */ +/* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is + * performed in a generic way that is not optimised to any particular + * microcontroller architecture. */ - /* uxTopReadyPriority holds the priority of the highest priority ready - state task. */ - #define taskRECORD_READY_PRIORITY( uxPriority ) \ - { \ - if( ( uxPriority ) > uxTopReadyPriority ) \ - { \ - uxTopReadyPriority = ( uxPriority ); \ - } \ - } /* taskRECORD_READY_PRIORITY */ +/* uxTopReadyPriority holds the priority of the highest priority ready + * state task. */ + #define taskRECORD_READY_PRIORITY( uxPriority ) \ + { \ + if( ( uxPriority ) > uxTopReadyPriority ) \ + { \ + uxTopReadyPriority = ( uxPriority ); \ + } \ + } /* taskRECORD_READY_PRIORITY */ - /*-----------------------------------------------------------*/ +/*-----------------------------------------------------------*/ - #define taskSELECT_HIGHEST_PRIORITY_TASK() \ - { \ - UBaseType_t uxTopPriority = uxTopReadyPriority; \ - \ - /* Find the highest priority queue that contains ready tasks. */ \ - while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopPriority ] ) ) ) \ - { \ - configASSERT( uxTopPriority ); \ - --uxTopPriority; \ - } \ - \ - /* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of \ - the same priority get an equal share of the processor time. */ \ - listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB[xPortGetCoreID()], &( pxReadyTasksLists[ uxTopPriority ] ) ); \ - uxTopReadyPriority = uxTopPriority; \ - } /* taskSELECT_HIGHEST_PRIORITY_TASK */ + #define taskSELECT_HIGHEST_PRIORITY_TASK() \ + { \ + UBaseType_t uxTopPriority = uxTopReadyPriority; \ + \ + /* Find the highest priority queue that contains ready tasks. */ \ + while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopPriority ] ) ) ) \ + { \ + configASSERT( uxTopPriority ); \ + --uxTopPriority; \ + } \ + \ + /* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of \ + * the same priority get an equal share of the processor time. */ \ + listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB[xPortGetCoreID()], &( pxReadyTasksLists[ uxTopPriority ] ) ); \ + uxTopReadyPriority = uxTopPriority; \ + } /* taskSELECT_HIGHEST_PRIORITY_TASK */ - /*-----------------------------------------------------------*/ +/*-----------------------------------------------------------*/ - /* Define away taskRESET_READY_PRIORITY() and portRESET_READY_PRIORITY() as - they are only required when a port optimised method of task selection is - being used. */ - #define taskRESET_READY_PRIORITY( uxPriority ) - #define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority ) +/* Define away taskRESET_READY_PRIORITY() and portRESET_READY_PRIORITY() as + * they are only required when a port optimised method of task selection is + * being used. */ + #define taskRESET_READY_PRIORITY( uxPriority ) + #define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority ) #else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ - /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 1 then task selection is - performed in a way that is tailored to the particular microcontroller - architecture being used. */ +/* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 1 then task selection is + * performed in a way that is tailored to the particular microcontroller + * architecture being used. */ - /* A port optimised version is provided. Call the port defined macros. */ - #define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority ) +/* A port optimised version is provided. Call the port defined macros. */ + #define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority ) - /*-----------------------------------------------------------*/ +/*-----------------------------------------------------------*/ - #define taskSELECT_HIGHEST_PRIORITY_TASK() \ - { \ - UBaseType_t uxTopPriority; \ - \ - /* Find the highest priority list that contains ready tasks. */ \ - portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \ - configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \ - listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB[xPortGetCoreID()], &( pxReadyTasksLists[ uxTopPriority ] ) ); \ - } /* taskSELECT_HIGHEST_PRIORITY_TASK() */ + #define taskSELECT_HIGHEST_PRIORITY_TASK() \ + { \ + UBaseType_t uxTopPriority; \ + \ + /* Find the highest priority list that contains ready tasks. */ \ + portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \ + configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \ + listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB[xPortGetCoreID()], &( pxReadyTasksLists[ uxTopPriority ] ) ); \ + } /* taskSELECT_HIGHEST_PRIORITY_TASK() */ - /*-----------------------------------------------------------*/ +/*-----------------------------------------------------------*/ - /* A port optimised version is provided, call it only if the TCB being reset - is being referenced from a ready list. If it is referenced from a delayed - or suspended list then it won't be in a ready list. */ - #define taskRESET_READY_PRIORITY( uxPriority ) \ - { \ - if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == ( UBaseType_t ) 0 ) \ - { \ - portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) ); \ - } \ - } +/* A port optimised version is provided, call it only if the TCB being reset + * is being referenced from a ready list. If it is referenced from a delayed + * or suspended list then it won't be in a ready list. */ + #define taskRESET_READY_PRIORITY( uxPriority ) \ + { \ + if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == ( UBaseType_t ) 0 ) \ + { \ + portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) ); \ + } \ + } #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ /*-----------------------------------------------------------*/ /* pxDelayedTaskList and pxOverflowDelayedTaskList are switched when the tick -count overflows. */ -#define taskSWITCH_DELAYED_LISTS() \ -{ \ - List_t *pxTemp; \ - \ - /* The delayed tasks list should be empty when the lists are switched. */ \ - configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) ); \ - \ - pxTemp = pxDelayedTaskList; \ - pxDelayedTaskList = pxOverflowDelayedTaskList; \ - pxOverflowDelayedTaskList = pxTemp; \ - xNumOfOverflows++; \ - prvResetNextTaskUnblockTime(); \ -} + * count overflows. */ +#define taskSWITCH_DELAYED_LISTS() \ + { \ + List_t * pxTemp; \ + \ + /* The delayed tasks list should be empty when the lists are switched. */ \ + configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) ); \ + \ + pxTemp = pxDelayedTaskList; \ + pxDelayedTaskList = pxOverflowDelayedTaskList; \ + pxOverflowDelayedTaskList = pxTemp; \ + xNumOfOverflows++; \ + prvResetNextTaskUnblockTime(); \ + } /*-----------------------------------------------------------*/ @@ -216,17 +228,17 @@ count overflows. */ * Place the task represented by pxTCB into the appropriate ready list for * the task. It is inserted at the end of the list. */ -#define prvAddTaskToReadyList( pxTCB ) \ - traceMOVED_TASK_TO_READY_STATE( pxTCB ); \ - taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \ - vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) ); \ - tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB ) +#define prvAddTaskToReadyList( pxTCB ) \ + traceMOVED_TASK_TO_READY_STATE( pxTCB ); \ + taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \ + vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) ); \ + tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB ) /*-----------------------------------------------------------*/ #define tskCAN_RUN_HERE( cpuid ) ( cpuid==xPortGetCoreID() || cpuid==tskNO_AFFINITY ) /* - * Several functions take an TaskHandle_t parameter that can optionally be NULL, + * Several functions take a TaskHandle_t parameter that can optionally be NULL, * where NULL is used to indicate that the handle of the currently executing * task should be used in place of the parameter. This macro simply checks to * see if the parameter is NULL and returns a pointer to the appropriate TCB. @@ -239,17 +251,17 @@ count overflows. */ #endif /* The item value of the event list item is normally used to hold the priority -of the task to which it belongs (coded to allow it to be held in reverse -priority order). However, it is occasionally borrowed for other purposes. It -is important its value is not updated due to a task priority change while it is -being used for another purpose. The following bit definition is used to inform -the scheduler that the value should not be changed - in which case it is the -responsibility of whichever module is using the value to ensure it gets set back -to its original value when it is released. */ -#if( configUSE_16_BIT_TICKS == 1 ) - #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x8000U + * of the task to which it belongs (coded to allow it to be held in reverse + * priority order). However, it is occasionally borrowed for other purposes. It + * is important its value is not updated due to a task priority change while it is + * being used for another purpose. The following bit definition is used to inform + * the scheduler that the value should not be changed - in which case it is the + * responsibility of whichever module is using the value to ensure it gets set back + * to its original value when it is released. */ +#if ( configUSE_16_BIT_TICKS == 1 ) + #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x8000U #else - #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x80000000UL + #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x80000000UL #endif /* @@ -257,153 +269,159 @@ to its original value when it is released. */ * and stores task state information, including a pointer to the task's context * (the task's run time environment, including register values) */ -typedef struct tskTaskControlBlock /* The old naming convention is used to prevent breaking kernel aware debuggers. */ +typedef struct tskTaskControlBlock /* The old naming convention is used to prevent breaking kernel aware debuggers. */ { - volatile StackType_t *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */ + volatile StackType_t * pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */ - #if ( portUSING_MPU_WRAPPERS == 1 ) - xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */ - #endif + #if ( portUSING_MPU_WRAPPERS == 1 ) + xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */ + #endif - ListItem_t xStateListItem; /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */ - ListItem_t xEventListItem; /*< Used to reference a task from an event list. */ - UBaseType_t uxPriority; /*< The priority of the task. 0 is the lowest priority. */ - StackType_t *pxStack; /*< Points to the start of the stack. */ - char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ - BaseType_t xCoreID; /*< Core this task is pinned to */ + ListItem_t xStateListItem; /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */ + ListItem_t xEventListItem; /*< Used to reference a task from an event list. */ + UBaseType_t uxPriority; /*< The priority of the task. 0 is the lowest priority. */ + StackType_t * pxStack; /*< Points to the start of the stack. */ + char pcTaskName[ configMAX_TASK_NAME_LEN ]; /*< Descriptive name given to the task when created. Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + BaseType_t xCoreID; /*< Core this task is pinned to */ - #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) ) - StackType_t *pxEndOfStack; /*< Points to the highest valid address for the stack. */ - #endif + #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) ) + StackType_t * pxEndOfStack; /*< Points to the highest valid address for the stack. */ + #endif - #if ( portCRITICAL_NESTING_IN_TCB == 1 ) - UBaseType_t uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */ - #endif + #if ( portCRITICAL_NESTING_IN_TCB == 1 ) + UBaseType_t uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */ + #endif - #if ( configUSE_TRACE_FACILITY == 1 ) - UBaseType_t uxTCBNumber; /*< Stores a number that increments each time a TCB is created. It allows debuggers to determine when a task has been deleted and then recreated. */ - UBaseType_t uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */ - #endif + #if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxTCBNumber; /*< Stores a number that increments each time a TCB is created. It allows debuggers to determine when a task has been deleted and then recreated. */ + UBaseType_t uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */ + #endif - #if ( configUSE_MUTEXES == 1 ) - UBaseType_t uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */ - UBaseType_t uxMutexesHeld; - #endif + #if ( configUSE_MUTEXES == 1 ) + UBaseType_t uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */ + UBaseType_t uxMutexesHeld; + #endif - #if ( configUSE_APPLICATION_TASK_TAG == 1 ) - TaskHookFunction_t pxTaskTag; - #endif + #if ( configUSE_APPLICATION_TASK_TAG == 1 ) + TaskHookFunction_t pxTaskTag; + #endif - #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) - void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ]; - #if ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS ) - TlsDeleteCallbackFunction_t pvThreadLocalStoragePointersDelCallback[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ]; - #endif - #endif + #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) + void * pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ]; + #if ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS ) + TlsDeleteCallbackFunction_t pvThreadLocalStoragePointersDelCallback[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ]; + #endif + #endif - #if( configGENERATE_RUN_TIME_STATS == 1 ) - uint32_t ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */ - #endif + #if ( configGENERATE_RUN_TIME_STATS == 1 ) + uint32_t ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */ + #endif - #if ( configUSE_NEWLIB_REENTRANT == 1 ) - /* Allocate a Newlib reent structure that is specific to this task. - Note Newlib support has been included by popular demand, but is not - used by the FreeRTOS maintainers themselves. FreeRTOS is not - responsible for resulting newlib operation. User must be familiar with - newlib and must provide system-wide implementations of the necessary - stubs. Be warned that (at the time of writing) the current newlib design - implements a system-wide malloc() that must be provided with locks. */ - struct _reent xNewLib_reent; - #endif + #if ( configUSE_NEWLIB_REENTRANT == 1 ) - #if( configUSE_TASK_NOTIFICATIONS == 1 ) - volatile uint32_t ulNotifiedValue; - volatile uint8_t ucNotifyState; - #endif + /* Allocate a Newlib reent structure that is specific to this task. + * Note Newlib support has been included by popular demand, but is not + * used by the FreeRTOS maintainers themselves. FreeRTOS is not + * responsible for resulting newlib operation. User must be familiar with + * newlib and must provide system-wide implementations of the necessary + * stubs. Be warned that (at the time of writing) the current newlib design + * implements a system-wide malloc() that must be provided with locks. + * + * See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html + * for additional information. */ + struct _reent xNewLib_reent; + #endif - /* See the comments in FreeRTOS.h with the definition of - tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */ - #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */ - uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */ - #endif + #if ( configUSE_TASK_NOTIFICATIONS == 1 ) + volatile uint32_t ulNotifiedValue[ configTASK_NOTIFICATION_ARRAY_ENTRIES ]; + volatile uint8_t ucNotifyState[ configTASK_NOTIFICATION_ARRAY_ENTRIES ]; + #endif - #if( INCLUDE_xTaskAbortDelay == 1 ) - uint8_t ucDelayAborted; - #endif + /* See the comments in FreeRTOS.h with the definition of + * tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */ + #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */ + uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */ + #endif - #if( configUSE_POSIX_ERRNO == 1 ) - int iTaskErrno; - #endif + #if ( INCLUDE_xTaskAbortDelay == 1 ) + uint8_t ucDelayAborted; + #endif + #if ( configUSE_POSIX_ERRNO == 1 ) + int iTaskErrno; + #endif } tskTCB; /* The old tskTCB name is maintained above then typedefed to the new TCB_t name -below to enable the use of older kernel aware debuggers. */ + * below to enable the use of older kernel aware debuggers. */ typedef tskTCB TCB_t; /*lint -save -e956 A manual analysis and inspection has been used to determine -which static variables must be declared volatile. */ + * which static variables must be declared volatile. */ PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB[portNUM_PROCESSORS] = {NULL}; /* Lists for ready and blocked tasks. -------------------- -xDelayedTaskList1 and xDelayedTaskList2 could be move to function scople but -doing so breaks some kernel aware debuggers and debuggers that rely on removing -the static qualifier. */ -PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ];/*< Prioritised ready tasks. */ -PRIVILEGED_DATA static List_t xDelayedTaskList1; /*< Delayed tasks. */ -PRIVILEGED_DATA static List_t xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */ -PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList; /*< Points to the delayed task list currently being used. */ -PRIVILEGED_DATA static List_t * volatile pxOverflowDelayedTaskList; /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */ -PRIVILEGED_DATA static List_t xPendingReadyList[ portNUM_PROCESSORS ]; /*< Tasks that have been readied while the scheduler was suspended. They will be moved to the ready list when the scheduler is resumed. */ + * xDelayedTaskList1 and xDelayedTaskList2 could be moved to function scope but + * doing so breaks some kernel aware debuggers and debuggers that rely on removing + * the static qualifier. */ +PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ]; /*< Prioritised ready tasks. */ +PRIVILEGED_DATA static List_t xDelayedTaskList1; /*< Delayed tasks. */ +PRIVILEGED_DATA static List_t xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */ +PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList; /*< Points to the delayed task list currently being used. */ +PRIVILEGED_DATA static List_t * volatile pxOverflowDelayedTaskList; /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */ +PRIVILEGED_DATA static List_t xPendingReadyList[ portNUM_PROCESSORS ]; /*< Tasks that have been readied while the scheduler was suspended. They will be moved to the ready list when the scheduler is resumed. */ + +#ifdef ESP_PLATFORM PRIVILEGED_DATA static portMUX_TYPE xTaskQueueMutex = portMUX_INITIALIZER_UNLOCKED; +#endif // ESP_PLATFORM -#if( INCLUDE_vTaskDelete == 1 ) +#if ( INCLUDE_vTaskDelete == 1 ) - PRIVILEGED_DATA static List_t xTasksWaitingTermination; /*< Tasks that have been deleted - but their memory not yet freed. */ - PRIVILEGED_DATA static volatile UBaseType_t uxDeletedTasksWaitingCleanUp = ( UBaseType_t ) 0U; + PRIVILEGED_DATA static List_t xTasksWaitingTermination; /*< Tasks that have been deleted - but their memory not yet freed. */ + PRIVILEGED_DATA static volatile UBaseType_t uxDeletedTasksWaitingCleanUp = ( UBaseType_t ) 0U; #endif #if ( INCLUDE_vTaskSuspend == 1 ) - PRIVILEGED_DATA static List_t xSuspendedTaskList; /*< Tasks that are currently suspended. */ + PRIVILEGED_DATA static List_t xSuspendedTaskList; /*< Tasks that are currently suspended. */ #endif /* Global POSIX errno. Its value is changed upon context switching to match -the errno of the currently running task. */ + * the errno of the currently running task. */ #if ( configUSE_POSIX_ERRNO == 1 ) - int FreeRTOS_errno = 0; + int FreeRTOS_errno = 0; #endif /* Other file private variables. --------------------------------*/ -PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks = ( UBaseType_t ) 0U; -PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT; -PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY; -PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE; -PRIVILEGED_DATA static volatile TickType_t xPendedTicks = ( TickType_t ) 0U; +PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks = ( UBaseType_t ) 0U; +PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT; +PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY; +PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE; +PRIVILEGED_DATA static volatile TickType_t xPendedTicks = ( TickType_t ) 0U; PRIVILEGED_DATA static volatile BaseType_t xYieldPending[portNUM_PROCESSORS] = {pdFALSE}; -PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0; -PRIVILEGED_DATA static UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U; -PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime = ( TickType_t ) 0U; /* Initialised to portMAX_DELAY before the scheduler starts. */ -PRIVILEGED_DATA static TaskHandle_t xIdleTaskHandle[portNUM_PROCESSORS] = {NULL}; /*< Holds the handle of the idle task. The idle task is created automatically when the scheduler is started. */ +PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0; +PRIVILEGED_DATA static UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U; +PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime = ( TickType_t ) 0U; /* Initialised to portMAX_DELAY before the scheduler starts. */ +PRIVILEGED_DATA static TaskHandle_t xIdleTaskHandle[portNUM_PROCESSORS] = {NULL}; /*< Holds the handle of the idle task. The idle task is created automatically when the scheduler is started. */ /* Context switches are held pending while the scheduler is suspended. Also, -interrupts must not manipulate the xStateListItem of a TCB, or any of the -lists the xStateListItem can be referenced from, if the scheduler is suspended. -If an interrupt needs to unblock a task while the scheduler is suspended then it -moves the task's event list item into the xPendingReadyList, ready for the -kernel to move the task from the pending ready list into the real ready list -when the scheduler is unsuspended. The pending ready list itself can only be -accessed from a critical section. */ + * interrupts must not manipulate the xStateListItem of a TCB, or any of the + * lists the xStateListItem can be referenced from, if the scheduler is suspended. + * If an interrupt needs to unblock a task while the scheduler is suspended then it + * moves the task's event list item into the xPendingReadyList, ready for the + * kernel to move the task from the pending ready list into the real ready list + * when the scheduler is unsuspended. The pending ready list itself can only be + * accessed from a critical section. */ PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended[portNUM_PROCESSORS] = {( UBaseType_t ) pdFALSE}; #if ( configGENERATE_RUN_TIME_STATS == 1 ) - /* Do not move these variables to function scope as doing so prevents the - code working with debuggers that need to remove the static qualifier. */ - PRIVILEGED_DATA static uint32_t ulTaskSwitchedInTime[portNUM_PROCESSORS] = {0U}; /*< Holds the value of a timer/counter the last time a task was switched in. */ - PRIVILEGED_DATA static uint32_t ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */ +/* Do not move these variables to function scope as doing so prevents the + * code working with debuggers that need to remove the static qualifier. */ + PRIVILEGED_DATA static uint32_t ulTaskSwitchedInTime[portNUM_PROCESSORS] = {0U}; /*< Holds the value of a timer/counter the last time a task was switched in. */ + PRIVILEGED_DATA static uint32_t ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */ #endif @@ -419,19 +437,19 @@ PRIVILEGED_DATA static volatile BaseType_t xSwitchingContext[ portNUM_PROCESSORS /* Callback function prototypes. --------------------------*/ #if( configCHECK_FOR_STACK_OVERFLOW > 0 ) - extern void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName ); + extern void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName ); #endif #if( configUSE_TICK_HOOK > 0 ) - extern void vApplicationTickHook( void ); /*lint !e526 Symbol not defined as it is an application callback. */ + extern void vApplicationTickHook( void ); /*lint !e526 Symbol not defined as it is an application callback. */ #endif #if( configSUPPORT_STATIC_ALLOCATION == 1 ) - extern void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ); /*lint !e526 Symbol not defined as it is an application callback. */ + extern void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ); /*lint !e526 Symbol not defined as it is an application callback. */ #endif @@ -444,7 +462,7 @@ PRIVILEGED_DATA static volatile BaseType_t xSwitchingContext[ portNUM_PROCESSORS */ #if ( INCLUDE_vTaskSuspend == 1 ) - static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION; + static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION; #endif /* INCLUDE_vTaskSuspend */ @@ -465,7 +483,7 @@ static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION; * void prvIdleTask( void *pvParameters ); * */ -static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters ); +static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters ) PRIVILEGED_FUNCTION; /* * Utility to free all memory allocated by the scheduler to hold a TCB, @@ -476,7 +494,7 @@ static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters ); */ #if ( INCLUDE_vTaskDelete == 1 ) - static void prvDeleteTCB( TCB_t *pxTCB ) PRIVILEGED_FUNCTION; + static void prvDeleteTCB( TCB_t * pxTCB ) PRIVILEGED_FUNCTION; #endif @@ -484,7 +502,7 @@ static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters ); * called during task deletion before prvDeleteTCB is called. */ #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) && ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS ) - static void prvDeleteTLS( TCB_t *pxTCB ); + static void prvDeleteTLS( TCB_t *pxTCB ); #endif /* @@ -498,7 +516,8 @@ static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION; * The currently executing task is entering the Blocked state. Add the task to * either the current or the overflow delayed task list. */ -static void prvAddCurrentTaskToDelayedList( const portBASE_TYPE xCoreID, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; +static void prvAddCurrentTaskToDelayedList( const portBASE_TYPE xCoreID, + const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; /* * Fills an TaskStatus_t structure with information on each task that is @@ -510,7 +529,9 @@ static void prvAddCurrentTaskToDelayedList( const portBASE_TYPE xCoreID, const T */ #if ( configUSE_TRACE_FACILITY == 1 ) - static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState ) PRIVILEGED_FUNCTION; + static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t * pxTaskStatusArray, + List_t * pxList, + eTaskState eState ) PRIVILEGED_FUNCTION; #endif @@ -520,7 +541,8 @@ static void prvAddCurrentTaskToDelayedList( const portBASE_TYPE xCoreID, const T */ #if ( INCLUDE_xTaskGetHandle == 1 ) - static TCB_t *prvSearchForNameWithinSingleList( List_t *pxList, const char pcNameToQuery[] ) PRIVILEGED_FUNCTION; + static TCB_t * prvSearchForNameWithinSingleList( List_t * pxList, + const char pcNameToQuery[] ) PRIVILEGED_FUNCTION; #endif @@ -531,7 +553,7 @@ static void prvAddCurrentTaskToDelayedList( const portBASE_TYPE xCoreID, const T */ #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) ) - static configSTACK_DEPTH_TYPE prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) PRIVILEGED_FUNCTION; + static configSTACK_DEPTH_TYPE prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) PRIVILEGED_FUNCTION; #endif @@ -546,7 +568,7 @@ static void prvAddCurrentTaskToDelayedList( const portBASE_TYPE xCoreID, const T */ #if ( configUSE_TICKLESS_IDLE != 0 ) - static TickType_t prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION; + static TickType_t prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION; #endif @@ -554,15 +576,16 @@ static void prvAddCurrentTaskToDelayedList( const portBASE_TYPE xCoreID, const T * Set xNextTaskUnblockTime to the time at which the next Blocked state task * will exit the Blocked state. */ -static void prvResetNextTaskUnblockTime( void ); +static void prvResetNextTaskUnblockTime( void ) PRIVILEGED_FUNCTION; #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) - /* - * Helper function used to pad task names with spaces when printing out - * human readable tables of task information. - */ - static char *prvWriteNameToBuffer( char *pcBuffer, const char *pcTaskName ) PRIVILEGED_FUNCTION; +/* + * Helper function used to pad task names with spaces when printing out + * human readable tables of task information. + */ + static char * prvWriteNameToBuffer( char * pcBuffer, + const char * pcTaskName ) PRIVILEGED_FUNCTION; #endif @@ -570,21 +593,23 @@ static void prvResetNextTaskUnblockTime( void ); * Called after a Task_t structure has been allocated either statically or * dynamically to fill in the structure's members. */ -static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, - const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ - const uint32_t ulStackDepth, - void * const pvParameters, - UBaseType_t uxPriority, - TaskHandle_t * const pxCreatedTask, - TCB_t *pxNewTCB, - const MemoryRegion_t * const xRegions, - BaseType_t xCoreID ) PRIVILEGED_FUNCTION; +static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, + const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + const uint32_t ulStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + TaskHandle_t * const pxCreatedTask, + TCB_t * pxNewTCB, + const MemoryRegion_t * const xRegions, + BaseType_t xCoreID ) PRIVILEGED_FUNCTION; /* * Called after a new task has been created and initialised to place the task * under the control of the scheduler. */ -static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode, BaseType_t xCoreID ) PRIVILEGED_FUNCTION; +static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, + TaskFunction_t pxTaskCode, + BaseType_t xCoreID ) PRIVILEGED_FUNCTION; /* * freertos_tasks_c_additions_init() should only be called if the user definable @@ -593,7 +618,7 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode */ #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT - static void freertos_tasks_c_additions_init( void ) PRIVILEGED_FUNCTION; + static void freertos_tasks_c_additions_init( void ) PRIVILEGED_FUNCTION; #endif @@ -606,1484 +631,1551 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode */ void taskYIELD_OTHER_CORE( BaseType_t xCoreID, UBaseType_t uxPriority ) { - BaseType_t i; + BaseType_t i; - if (xCoreID != tskNO_AFFINITY) { - if ( pxCurrentTCB[ xCoreID ]->uxPriority < uxPriority ) { // NOLINT(clang-analyzer-core.NullDereference) IDF-685 - vPortYieldOtherCore( xCoreID ); - } - } - else - { - /* The task has no affinity. See if we can find a CPU to put it on.*/ - for (i=0; iuxPriority < uxPriority) - { - vPortYieldOtherCore( i ); - break; - } - } - } + if (xCoreID != tskNO_AFFINITY) { + if ( pxCurrentTCB[ xCoreID ]->uxPriority < uxPriority ) { // NOLINT(clang-analyzer-core.NullDereference) IDF-685 + vPortYieldOtherCore( xCoreID ); + } + } + else + { + /* The task has no affinity. See if we can find a CPU to put it on.*/ + for (i=0; iuxPriority < uxPriority) + { + vPortYieldOtherCore( i ); + break; + } + } + } } /*-----------------------------------------------------------*/ -#if( configSUPPORT_STATIC_ALLOCATION == 1 ) +#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) - TaskHandle_t xTaskCreateStaticPinnedToCore( TaskFunction_t pvTaskCode, - const char * const pcName, - const uint32_t ulStackDepth, - void * const pvParameters, - UBaseType_t uxPriority, - StackType_t * const pxStackBuffer, - StaticTask_t * const pxTaskBuffer, - const BaseType_t xCoreID ) - { - TCB_t *pxNewTCB; - TaskHandle_t xReturn; + TaskHandle_t xTaskCreateStaticPinnedToCore( TaskFunction_t pvTaskCode, + const char * const pcName, + const uint32_t ulStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + StackType_t * const pxStackBuffer, + StaticTask_t * const pxTaskBuffer, + const BaseType_t xCoreID ) + { + TCB_t *pxNewTCB; + TaskHandle_t xReturn; - configASSERT( portVALID_TCB_MEM(pxTaskBuffer) ); - configASSERT( portVALID_STACK_MEM(pxStackBuffer) ); - configASSERT( (xCoreID>=0 && xCoreID=0 && xCoreIDpxStack = ( StackType_t * ) pxStackBuffer; + if( ( pxTaskBuffer != NULL ) && ( pxStackBuffer != NULL ) ) + { + /* The memory used for the task's TCB and stack are passed into this + * function - use them. */ + pxNewTCB = ( TCB_t * ) pxTaskBuffer; /*lint !e740 !e9087 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */ + pxNewTCB->pxStack = ( StackType_t * ) pxStackBuffer; - #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */ - { - /* Tasks can be created statically or dynamically, so note this - task was created statically in case the task is later deleted. */ - pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB; - } - #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */ + #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */ + { + /* Tasks can be created statically or dynamically, so note this + * task was created statically in case the task is later deleted. */ + pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB; + } + #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */ - prvInitialiseNewTask( pvTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, &xReturn, pxNewTCB, NULL, xCoreID ); - prvAddNewTaskToReadyList( pxNewTCB, pvTaskCode, xCoreID ); - } - else - { - xReturn = NULL; - } + prvInitialiseNewTask( pvTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, &xReturn, pxNewTCB, NULL, xCoreID ); + prvAddNewTaskToReadyList( pxNewTCB, pvTaskCode, xCoreID ); + } + else + { + xReturn = NULL; + } - return xReturn; - } + return xReturn; + } #endif /* SUPPORT_STATIC_ALLOCATION */ /*-----------------------------------------------------------*/ -#if( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) +#if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) - BaseType_t xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ) - { - TCB_t *pxNewTCB; - BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; + BaseType_t xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition, + TaskHandle_t * pxCreatedTask ) + { + TCB_t * pxNewTCB; + BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; - configASSERT( pxTaskDefinition->puxStackBuffer != NULL ); - configASSERT( pxTaskDefinition->pxTaskBuffer != NULL ); + configASSERT( pxTaskDefinition->puxStackBuffer != NULL ); + configASSERT( pxTaskDefinition->pxTaskBuffer != NULL ); - if( ( pxTaskDefinition->puxStackBuffer != NULL ) && ( pxTaskDefinition->pxTaskBuffer != NULL ) ) - { - /* Allocate space for the TCB. Where the memory comes from depends - on the implementation of the port malloc function and whether or - not static allocation is being used. */ - pxNewTCB = ( TCB_t * ) pxTaskDefinition->pxTaskBuffer; + if( ( pxTaskDefinition->puxStackBuffer != NULL ) && ( pxTaskDefinition->pxTaskBuffer != NULL ) ) + { + /* Allocate space for the TCB. Where the memory comes from depends + * on the implementation of the port malloc function and whether or + * not static allocation is being used. */ + pxNewTCB = ( TCB_t * ) pxTaskDefinition->pxTaskBuffer; - /* Store the stack location in the TCB. */ - pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer; + /* Store the stack location in the TCB. */ + pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer; - #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) - { - /* Tasks can be created statically or dynamically, so note this - task was created statically in case the task is later deleted. */ - pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB; - } - #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */ + #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) + { + /* Tasks can be created statically or dynamically, so note this + * task was created statically in case the task is later deleted. */ + pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB; + } + #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */ - prvInitialiseNewTask( pxTaskDefinition->pvTaskCode, - pxTaskDefinition->pcName, - ( uint32_t ) pxTaskDefinition->usStackDepth, - pxTaskDefinition->pvParameters, - pxTaskDefinition->uxPriority, - pxCreatedTask, pxNewTCB, - pxTaskDefinition->xRegions, - tskNO_AFFINITY ); + prvInitialiseNewTask( pxTaskDefinition->pvTaskCode, + pxTaskDefinition->pcName, + ( uint32_t ) pxTaskDefinition->usStackDepth, + pxTaskDefinition->pvParameters, + pxTaskDefinition->uxPriority, + pxCreatedTask, pxNewTCB, + pxTaskDefinition->xRegions, + tskNO_AFFINITY ); - prvAddNewTaskToReadyList( pxNewTCB, pxTaskDefinition->pvTaskCode, tskNO_AFFINITY); - xReturn = pdPASS; - } + prvAddNewTaskToReadyList( pxNewTCB, pxTaskDefinition->pvTaskCode, tskNO_AFFINITY); + xReturn = pdPASS; + } - return xReturn; - } + return xReturn; + } #endif /* ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ /*-----------------------------------------------------------*/ -#if( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) +#if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) - BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ) - { - TCB_t *pxNewTCB; - BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; + BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, + TaskHandle_t * pxCreatedTask ) + { + TCB_t * pxNewTCB; + BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; - configASSERT( pxTaskDefinition->puxStackBuffer ); + configASSERT( pxTaskDefinition->puxStackBuffer ); - if( pxTaskDefinition->puxStackBuffer != NULL ) - { - /* Allocate space for the TCB. Where the memory comes from depends - on the implementation of the port malloc function and whether or - not static allocation is being used. */ - pxNewTCB = ( TCB_t * ) pvPortMallocTcbMem( sizeof( TCB_t ) ); + if( pxTaskDefinition->puxStackBuffer != NULL ) + { + /* Allocate space for the TCB. Where the memory comes from depends + * on the implementation of the port malloc function and whether or + * not static allocation is being used. */ + pxNewTCB = ( TCB_t * ) pvPortMallocTcbMem( sizeof( TCB_t ) ); - if( pxNewTCB != NULL ) - { - /* Store the stack location in the TCB. */ - pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer; + if( pxNewTCB != NULL ) + { + /* Store the stack location in the TCB. */ + pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer; - #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) - { - /* Tasks can be created statically or dynamically, so note - this task had a statically allocated stack in case it is - later deleted. The TCB was allocated dynamically. */ - pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_ONLY; - } - #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */ + #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) + { + /* Tasks can be created statically or dynamically, so note + * this task had a statically allocated stack in case it is + * later deleted. The TCB was allocated dynamically. */ + pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_ONLY; + } + #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */ - prvInitialiseNewTask( pxTaskDefinition->pvTaskCode, - pxTaskDefinition->pcName, - ( uint32_t ) pxTaskDefinition->usStackDepth, - pxTaskDefinition->pvParameters, - pxTaskDefinition->uxPriority, - pxCreatedTask, pxNewTCB, - pxTaskDefinition->xRegions, - tskNO_AFFINITY ); + prvInitialiseNewTask( pxTaskDefinition->pvTaskCode, + pxTaskDefinition->pcName, + ( uint32_t ) pxTaskDefinition->usStackDepth, + pxTaskDefinition->pvParameters, + pxTaskDefinition->uxPriority, + pxCreatedTask, pxNewTCB, + pxTaskDefinition->xRegions, + tskNO_AFFINITY ); - prvAddNewTaskToReadyList( pxNewTCB, pxTaskDefinition->pvTaskCode, tskNO_AFFINITY); - xReturn = pdPASS; - } - } + prvAddNewTaskToReadyList( pxNewTCB, pxTaskDefinition->pvTaskCode, tskNO_AFFINITY); + xReturn = pdPASS; + } + } - return xReturn; - } + return xReturn; + } #endif /* portUSING_MPU_WRAPPERS */ /*-----------------------------------------------------------*/ -#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) +#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) - BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pvTaskCode, - const char * const pcName, - const uint32_t usStackDepth, - void * const pvParameters, - UBaseType_t uxPriority, - TaskHandle_t * const pvCreatedTask, - const BaseType_t xCoreID) - { - TCB_t *pxNewTCB; - BaseType_t xReturn; + BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pvTaskCode, + const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + const uint32_t usStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + TaskHandle_t * const pvCreatedTask, + const BaseType_t xCoreID) + { + TCB_t * pxNewTCB; + BaseType_t xReturn; - /* If the stack grows down then allocate the stack then the TCB so the stack - does not grow into the TCB. Likewise if the stack grows up then allocate - the TCB then the stack. */ - #if( portSTACK_GROWTH > 0 ) - { - /* Allocate space for the TCB. Where the memory comes from depends on - the implementation of the port malloc function and whether or not static - allocation is being used. */ - pxNewTCB = ( TCB_t * ) pvPortMallocTcbMem( sizeof( TCB_t ) ); + /* If the stack grows down then allocate the stack then the TCB so the stack + * does not grow into the TCB. Likewise if the stack grows up then allocate + * the TCB then the stack. */ + #if ( portSTACK_GROWTH > 0 ) + { + /* Allocate space for the TCB. Where the memory comes from depends on + * the implementation of the port malloc function and whether or not static + * allocation is being used. */ + pxNewTCB = ( TCB_t * ) pvPortMallocTcbMem( sizeof( TCB_t ) ); - if( pxNewTCB != NULL ) - { - /* Allocate space for the stack used by the task being created. - The base of the stack memory stored in the TCB so the task can - be deleted later if required. */ - pxNewTCB->pxStack = ( StackType_t * ) pvPortMallocStackMem( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + if( pxNewTCB != NULL ) + { + /* Allocate space for the stack used by the task being created. + * The base of the stack memory stored in the TCB so the task can + * be deleted later if required. */ + pxNewTCB->pxStack = ( StackType_t * ) pvPortMallocStackMem( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ - if( pxNewTCB->pxStack == NULL ) - { - /* Could not allocate the stack. Delete the allocated TCB. */ - vPortFree( pxNewTCB ); - pxNewTCB = NULL; - } - } - } - #else /* portSTACK_GROWTH */ - { - StackType_t *pxStack; + if( pxNewTCB->pxStack == NULL ) + { + /* Could not allocate the stack. Delete the allocated TCB. */ + vPortFree( pxNewTCB ); + pxNewTCB = NULL; + } + } + } + #else /* portSTACK_GROWTH */ + { + StackType_t * pxStack; - /* Allocate space for the stack used by the task being created. */ - pxStack = pvPortMallocStackMem( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation is the stack. */ + /* Allocate space for the stack used by the task being created. */ + pxStack = pvPortMallocStackMem( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation is the stack. */ - if( pxStack != NULL ) - { - /* Allocate space for the TCB. */ - pxNewTCB = ( TCB_t * ) pvPortMallocTcbMem( sizeof( TCB_t ) ); /*lint !e9087 !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack, and the first member of TCB_t is always a pointer to the task's stack. */ + if( pxStack != NULL ) + { + /* Allocate space for the TCB. */ + pxNewTCB = ( TCB_t * ) pvPortMallocTcbMem( sizeof( TCB_t ) ); /*lint !e9087 !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack, and the first member of TCB_t is always a pointer to the task's stack. */ - if( pxNewTCB != NULL ) - { - /* Store the stack location in the TCB. */ - pxNewTCB->pxStack = pxStack; - } - else - { - /* The stack cannot be used as the TCB was not created. Free - it again. */ - vPortFree( pxStack ); - } - } - else - { - pxNewTCB = NULL; - } - } - #endif /* portSTACK_GROWTH */ + if( pxNewTCB != NULL ) + { + /* Store the stack location in the TCB. */ + pxNewTCB->pxStack = pxStack; + } + else + { + /* The stack cannot be used as the TCB was not created. Free + * it again. */ + vPortFree( pxStack ); + } + } + else + { + pxNewTCB = NULL; + } + } + #endif /* portSTACK_GROWTH */ - if( pxNewTCB != NULL ) - { - #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e9029 !e731 Macro has been consolidated for readability reasons. */ - { - /* Tasks can be created statically or dynamically, so note this - task was created dynamically in case it is later deleted. */ - pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB; - } - #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */ + if( pxNewTCB != NULL ) + { + #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e9029 !e731 Macro has been consolidated for readability reasons. */ + { + /* Tasks can be created statically or dynamically, so note this + * task was created dynamically in case it is later deleted. */ + pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB; + } + #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */ - prvInitialiseNewTask( pvTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pvCreatedTask, pxNewTCB, NULL, xCoreID ); - prvAddNewTaskToReadyList( pxNewTCB, pvTaskCode, xCoreID); - xReturn = pdPASS; - } - else - { - xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; - } + prvInitialiseNewTask( pvTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pvCreatedTask, pxNewTCB, NULL, xCoreID ); + prvAddNewTaskToReadyList( pxNewTCB, pvTaskCode, xCoreID); + xReturn = pdPASS; + } + else + { + xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; + } - return xReturn; - } + return xReturn; + } #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ /*-----------------------------------------------------------*/ -static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, - const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ - const uint32_t ulStackDepth, - void * const pvParameters, - UBaseType_t uxPriority, - TaskHandle_t * const pxCreatedTask, - TCB_t *pxNewTCB, - const MemoryRegion_t * const xRegions, - BaseType_t xCoreID ) +static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, + const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + const uint32_t ulStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + TaskHandle_t * const pxCreatedTask, + TCB_t * pxNewTCB, + const MemoryRegion_t * const xRegions, + BaseType_t xCoreID ) { -StackType_t *pxTopOfStack; -UBaseType_t x; + StackType_t * pxTopOfStack; + UBaseType_t x; - #if (portNUM_PROCESSORS < 2) - xCoreID = 0; - #endif + #if (portNUM_PROCESSORS < 2) + xCoreID = 0; + #endif - #if( portUSING_MPU_WRAPPERS == 1 ) - /* Should the task be created in privileged mode? */ - BaseType_t xRunPrivileged; - if( ( uxPriority & portPRIVILEGE_BIT ) != 0U ) - { - xRunPrivileged = pdTRUE; - } - else - { - xRunPrivileged = pdFALSE; - } - uxPriority &= ~portPRIVILEGE_BIT; - #endif /* portUSING_MPU_WRAPPERS == 1 */ + #if ( portUSING_MPU_WRAPPERS == 1 ) + /* Should the task be created in privileged mode? */ + BaseType_t xRunPrivileged; - /* Avoid dependency on memset() if it is not required. */ - #if( tskSET_NEW_STACKS_TO_KNOWN_VALUE == 1 ) - { - /* Fill the stack with a known value to assist debugging. */ - ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) ulStackDepth * sizeof( StackType_t ) ); - } - #endif /* tskSET_NEW_STACKS_TO_KNOWN_VALUE */ + if( ( uxPriority & portPRIVILEGE_BIT ) != 0U ) + { + xRunPrivileged = pdTRUE; + } + else + { + xRunPrivileged = pdFALSE; + } + uxPriority &= ~portPRIVILEGE_BIT; + #endif /* portUSING_MPU_WRAPPERS == 1 */ - /* Calculate the top of stack address. This depends on whether the stack - grows from high memory to low (as per the 80x86) or vice versa. - portSTACK_GROWTH is used to make the result positive or negative as required - by the port. */ - #if( portSTACK_GROWTH < 0 ) - { - pxTopOfStack = &( pxNewTCB->pxStack[ ulStackDepth - ( uint32_t ) 1 ] ); - pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); /*lint !e923 !e9033 !e9078 MISRA exception. Avoiding casts between pointers and integers is not practical. Size differences accounted for using portPOINTER_SIZE_TYPE type. Checked by assert(). */ + /* Avoid dependency on memset() if it is not required. */ + #if ( tskSET_NEW_STACKS_TO_KNOWN_VALUE == 1 ) + { + /* Fill the stack with a known value to assist debugging. */ + ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) ulStackDepth * sizeof( StackType_t ) ); + } + #endif /* tskSET_NEW_STACKS_TO_KNOWN_VALUE */ - /* Check the alignment of the calculated top of stack is correct. */ - configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); + #if( configUSE_TRACE_FACILITY == 1 ) + { + /* Zero the uxTaskNumber TCB member to avoid random value from dynamically allocated TCBs */ + pxNewTCB->uxTaskNumber = 0; + } + #endif /* ( configUSE_TRACE_FACILITY == 1 ) */ - #if( configRECORD_STACK_HIGH_ADDRESS == 1 ) - { - /* Also record the stack's high address, which may assist - debugging. */ - pxNewTCB->pxEndOfStack = pxTopOfStack; - } - #endif /* configRECORD_STACK_HIGH_ADDRESS */ - } - #else /* portSTACK_GROWTH */ - { - pxTopOfStack = pxNewTCB->pxStack; + /* Calculate the top of stack address. This depends on whether the stack + * grows from high memory to low (as per the 80x86) or vice versa. + * portSTACK_GROWTH is used to make the result positive or negative as required + * by the port. */ + #if ( portSTACK_GROWTH < 0 ) + { + pxTopOfStack = &( pxNewTCB->pxStack[ ulStackDepth - ( uint32_t ) 1 ] ); + pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); /*lint !e923 !e9033 !e9078 MISRA exception. Avoiding casts between pointers and integers is not practical. Size differences accounted for using portPOINTER_SIZE_TYPE type. Checked by assert(). */ - /* Check the alignment of the stack buffer is correct. */ - configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxNewTCB->pxStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); + /* Check the alignment of the calculated top of stack is correct. */ + configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); - /* The other extreme of the stack space is required if stack checking is - performed. */ - pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 ); - } - #endif /* portSTACK_GROWTH */ + #if ( configRECORD_STACK_HIGH_ADDRESS == 1 ) + { + /* Also record the stack's high address, which may assist + * debugging. */ + pxNewTCB->pxEndOfStack = pxTopOfStack; + } + #endif /* configRECORD_STACK_HIGH_ADDRESS */ + } + #else /* portSTACK_GROWTH */ + { + pxTopOfStack = pxNewTCB->pxStack; - /* Store the task name in the TCB. */ - if( pcName != NULL ) - { - for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ ) - { - pxNewTCB->pcTaskName[ x ] = pcName[ x ]; + /* Check the alignment of the stack buffer is correct. */ + configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxNewTCB->pxStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); - /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than - configMAX_TASK_NAME_LEN characters just in case the memory after the - string is not accessible (extremely unlikely). */ - if( pcName[ x ] == ( char ) 0x00 ) - { - break; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } + /* The other extreme of the stack space is required if stack checking is + * performed. */ + pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 ); + } + #endif /* portSTACK_GROWTH */ - /* Ensure the name string is terminated in the case that the string length - was greater or equal to configMAX_TASK_NAME_LEN. */ - pxNewTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0'; - } - else - { - /* The task has not been given a name, so just ensure there is a NULL - terminator when it is read out. */ - pxNewTCB->pcTaskName[ 0 ] = 0x00; - } + /* Store the task name in the TCB. */ + if( pcName != NULL ) + { + for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ ) + { + pxNewTCB->pcTaskName[ x ] = pcName[ x ]; - /* This is used as an array index so must ensure it's not too large. First - remove the privilege bit if one is present. */ - if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES ) - { - uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than + * configMAX_TASK_NAME_LEN characters just in case the memory after the + * string is not accessible (extremely unlikely). */ + if( pcName[ x ] == ( char ) 0x00 ) + { + break; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } - pxNewTCB->uxPriority = uxPriority; - pxNewTCB->xCoreID = xCoreID; - #if ( configUSE_MUTEXES == 1 ) - { - pxNewTCB->uxBasePriority = uxPriority; - pxNewTCB->uxMutexesHeld = 0; - } - #endif /* configUSE_MUTEXES */ + /* Ensure the name string is terminated in the case that the string length + * was greater or equal to configMAX_TASK_NAME_LEN. */ + pxNewTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0'; + } + else + { + /* The task has not been given a name, so just ensure there is a NULL + * terminator when it is read out. */ + pxNewTCB->pcTaskName[ 0 ] = 0x00; + } - vListInitialiseItem( &( pxNewTCB->xStateListItem ) ); - vListInitialiseItem( &( pxNewTCB->xEventListItem ) ); + /* This is used as an array index so must ensure it's not too large. First + * remove the privilege bit if one is present. */ + if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES ) + { + uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - /* Set the pxNewTCB as a link back from the ListItem_t. This is so we can get - back to the containing TCB from a generic item in a list. */ - listSET_LIST_ITEM_OWNER( &( pxNewTCB->xStateListItem ), pxNewTCB ); + pxNewTCB->uxPriority = uxPriority; + pxNewTCB->xCoreID = xCoreID; + #if ( configUSE_MUTEXES == 1 ) + { + pxNewTCB->uxBasePriority = uxPriority; + pxNewTCB->uxMutexesHeld = 0; + } + #endif /* configUSE_MUTEXES */ - /* Event lists are always in priority order. */ - listSET_LIST_ITEM_VALUE( &( pxNewTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ - listSET_LIST_ITEM_OWNER( &( pxNewTCB->xEventListItem ), pxNewTCB ); + vListInitialiseItem( &( pxNewTCB->xStateListItem ) ); + vListInitialiseItem( &( pxNewTCB->xEventListItem ) ); - #if ( portCRITICAL_NESTING_IN_TCB == 1 ) - { - pxNewTCB->uxCriticalNesting = ( UBaseType_t ) 0U; - } - #endif /* portCRITICAL_NESTING_IN_TCB */ + /* Set the pxNewTCB as a link back from the ListItem_t. This is so we can get + * back to the containing TCB from a generic item in a list. */ + listSET_LIST_ITEM_OWNER( &( pxNewTCB->xStateListItem ), pxNewTCB ); - #if ( configUSE_APPLICATION_TASK_TAG == 1 ) - { - pxNewTCB->pxTaskTag = NULL; - } - #endif /* configUSE_APPLICATION_TASK_TAG */ + /* Event lists are always in priority order. */ + listSET_LIST_ITEM_VALUE( &( pxNewTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + listSET_LIST_ITEM_OWNER( &( pxNewTCB->xEventListItem ), pxNewTCB ); - #if ( configGENERATE_RUN_TIME_STATS == 1 ) - { - pxNewTCB->ulRunTimeCounter = 0UL; - } - #endif /* configGENERATE_RUN_TIME_STATS */ + #if ( portCRITICAL_NESTING_IN_TCB == 1 ) + { + pxNewTCB->uxCriticalNesting = ( UBaseType_t ) 0U; + } + #endif /* portCRITICAL_NESTING_IN_TCB */ - #if ( portUSING_MPU_WRAPPERS == 1 ) - { - vPortStoreTaskMPUSettings( &( pxNewTCB->xMPUSettings ), xRegions, pxNewTCB->pxStack, ulStackDepth ); - } - #else - { - /* Avoid compiler warning about unreferenced parameter. */ - ( void ) xRegions; - } - #endif + #if ( configUSE_APPLICATION_TASK_TAG == 1 ) + { + pxNewTCB->pxTaskTag = NULL; + } + #endif /* configUSE_APPLICATION_TASK_TAG */ - #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 ) - { - for( x = 0; x < ( UBaseType_t ) configNUM_THREAD_LOCAL_STORAGE_POINTERS; x++ ) - { - pxNewTCB->pvThreadLocalStoragePointers[ x ] = NULL; - #if ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS == 1) - pxNewTCB->pvThreadLocalStoragePointersDelCallback[ x ] = NULL; - #endif + #if ( configGENERATE_RUN_TIME_STATS == 1 ) + { + pxNewTCB->ulRunTimeCounter = 0UL; + } + #endif /* configGENERATE_RUN_TIME_STATS */ - } - } - #endif + #if ( portUSING_MPU_WRAPPERS == 1 ) + { + vPortStoreTaskMPUSettings( &( pxNewTCB->xMPUSettings ), xRegions, pxNewTCB->pxStack, ulStackDepth ); + } + #else + { + /* Avoid compiler warning about unreferenced parameter. */ + ( void ) xRegions; + } + #endif - #if ( configUSE_TASK_NOTIFICATIONS == 1 ) - { - pxNewTCB->ulNotifiedValue = 0; - pxNewTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION; - } - #endif + #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 ) + { + for( x = 0; x < ( UBaseType_t ) configNUM_THREAD_LOCAL_STORAGE_POINTERS; x++ ) + { + pxNewTCB->pvThreadLocalStoragePointers[ x ] = NULL; + #if ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS == 1) + pxNewTCB->pvThreadLocalStoragePointersDelCallback[ x ] = NULL; + #endif - #if ( configUSE_NEWLIB_REENTRANT == 1 ) - { - // /* Initialise this task's Newlib reent structure. */ - // _REENT_INIT_PTR( ( &( pxNewTCB->xNewLib_reent ) ) ); + } + } + #endif - /* Initialise this task's Newlib reent structure. */ - esp_reent_init(&pxNewTCB->xNewLib_reent); + #if ( configUSE_TASK_NOTIFICATIONS == 1 ) + { + memset( ( void * ) &( pxNewTCB->ulNotifiedValue[ 0 ] ), 0x00, sizeof( pxNewTCB->ulNotifiedValue ) ); + memset( ( void * ) &( pxNewTCB->ucNotifyState[ 0 ] ), 0x00, sizeof( pxNewTCB->ucNotifyState ) ); + } + #endif - } - #endif + #if ( configUSE_NEWLIB_REENTRANT == 1 ) + { + // /* Initialise this task's Newlib reent structure. */ + // _REENT_INIT_PTR( ( &( pxNewTCB->xNewLib_reent ) ) ); - #if( INCLUDE_xTaskAbortDelay == 1 ) - { - pxNewTCB->ucDelayAborted = pdFALSE; - } - #endif + /* Initialise this task's Newlib reent structure. */ + esp_reent_init(&pxNewTCB->xNewLib_reent); + } + #endif - /* Initialize the TCB stack to look as if the task was already running, - but had been interrupted by the scheduler. The return address is set - to the start of the task function. Once the stack has been initialised - the top of stack variable is updated. */ - #if( portUSING_MPU_WRAPPERS == 1 ) - { - /* If the port has capability to detect stack overflow, - pass the stack end address to the stack initialization - function as well. */ - #if( portHAS_STACK_OVERFLOW_CHECKING == 1 ) - { - #if( portSTACK_GROWTH < 0 ) - { - pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxStack, pxTaskCode, pvParameters, xRunPrivileged ); - } - #else /* portSTACK_GROWTH */ - { - pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxEndOfStack, pxTaskCode, pvParameters, xRunPrivileged ); - } - #endif /* portSTACK_GROWTH */ - } - #else /* portHAS_STACK_OVERFLOW_CHECKING */ - { - pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged ); - } - #endif /* portHAS_STACK_OVERFLOW_CHECKING */ - } - #else /* portUSING_MPU_WRAPPERS */ - { - /* If the port has capability to detect stack overflow, - pass the stack end address to the stack initialization - function as well. */ - #if( portHAS_STACK_OVERFLOW_CHECKING == 1 ) - { - #if( portSTACK_GROWTH < 0 ) - { - pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxStack, pxTaskCode, pvParameters ); - } - #else /* portSTACK_GROWTH */ - { - pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxEndOfStack, pxTaskCode, pvParameters ); - } - #endif /* portSTACK_GROWTH */ - } - #else /* portHAS_STACK_OVERFLOW_CHECKING */ - { - pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters ); - } - #endif /* portHAS_STACK_OVERFLOW_CHECKING */ - } - #endif /* portUSING_MPU_WRAPPERS */ + #if ( INCLUDE_xTaskAbortDelay == 1 ) + { + pxNewTCB->ucDelayAborted = pdFALSE; + } + #endif - if( pxCreatedTask != NULL ) - { - /* Pass the handle out in an anonymous way. The handle can be used to - change the created task's priority, delete the created task, etc.*/ - *pxCreatedTask = ( TaskHandle_t ) pxNewTCB; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* Initialize the TCB stack to look as if the task was already running, + * but had been interrupted by the scheduler. The return address is set + * to the start of the task function. Once the stack has been initialised + * the top of stack variable is updated. */ + #if ( portUSING_MPU_WRAPPERS == 1 ) + { + /* If the port has capability to detect stack overflow, + * pass the stack end address to the stack initialization + * function as well. */ + #if ( portHAS_STACK_OVERFLOW_CHECKING == 1 ) + { + #if ( portSTACK_GROWTH < 0 ) + { + pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxStack, pxTaskCode, pvParameters, xRunPrivileged ); + } + #else /* portSTACK_GROWTH */ + { + pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxEndOfStack, pxTaskCode, pvParameters, xRunPrivileged ); + } + #endif /* portSTACK_GROWTH */ + } + #else /* portHAS_STACK_OVERFLOW_CHECKING */ + { + pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged ); + } + #endif /* portHAS_STACK_OVERFLOW_CHECKING */ + } + #else /* portUSING_MPU_WRAPPERS */ + { + /* If the port has capability to detect stack overflow, + * pass the stack end address to the stack initialization + * function as well. */ + #if ( portHAS_STACK_OVERFLOW_CHECKING == 1 ) + { + #if ( portSTACK_GROWTH < 0 ) + { + pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxStack, pxTaskCode, pvParameters ); + } + #else /* portSTACK_GROWTH */ + { + pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxEndOfStack, pxTaskCode, pvParameters ); + } + #endif /* portSTACK_GROWTH */ + } + #else /* portHAS_STACK_OVERFLOW_CHECKING */ + { + pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters ); + } + #endif /* portHAS_STACK_OVERFLOW_CHECKING */ + } + #endif /* portUSING_MPU_WRAPPERS */ + + if( pxCreatedTask != NULL ) + { + /* Pass the handle out in an anonymous way. The handle can be used to + * change the created task's priority, delete the created task, etc.*/ + *pxCreatedTask = ( TaskHandle_t ) pxNewTCB; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } } /*-----------------------------------------------------------*/ -static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode, BaseType_t xCoreID ) +static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, + TaskFunction_t pxTaskCode, + BaseType_t xCoreID ) { - TCB_t *curTCB, *tcb0, *tcb1; + TCB_t *curTCB, *tcb0, *tcb1; - #if (portNUM_PROCESSORS < 2) - xCoreID = 0; - #endif + #if (portNUM_PROCESSORS < 2) + xCoreID = 0; + #endif - /* Ensure interrupts don't access the task lists while the lists are being - updated. */ - taskENTER_CRITICAL( &xTaskQueueMutex ); - { - uxCurrentNumberOfTasks++; + /* Ensure interrupts don't access the task lists while the lists are being + * updated. */ + taskENTER_CRITICAL(); + { + uxCurrentNumberOfTasks++; - if ( xCoreID == tskNO_AFFINITY ) - { - if ( portNUM_PROCESSORS == 1 ) - { - xCoreID = 0; - } - else - { - // if the task has no affinity, put it on either core if nothing is currently scheduled there. Failing that, - // put it on the core where it will preempt the lowest priority running task. If neither of these are true, - // queue it on the currently running core. - tcb0 = pxCurrentTCB[0]; - tcb1 = pxCurrentTCB[1]; - if ( tcb0 == NULL ) - { - xCoreID = 0; - } - else if ( tcb1 == NULL ) - { - xCoreID = 1; - } - else if ( tcb0->uxPriority < pxNewTCB->uxPriority && tcb0->uxPriority < tcb1->uxPriority ) - { - xCoreID = 0; - } - else if ( tcb1->uxPriority < pxNewTCB->uxPriority ) - { - xCoreID = 1; - } - else - { - xCoreID = xPortGetCoreID(); // Both CPU have higher priority tasks running on them, so this won't run yet - } - } - } + if ( xCoreID == tskNO_AFFINITY ) + { + if ( portNUM_PROCESSORS == 1 ) + { + xCoreID = 0; + } + else + { + // if the task has no affinity, put it on either core if nothing is currently scheduled there. Failing that, + // put it on the core where it will preempt the lowest priority running task. If neither of these are true, + // queue it on the currently running core. + tcb0 = pxCurrentTCB[0]; + tcb1 = pxCurrentTCB[1]; + if ( tcb0 == NULL ) + { + xCoreID = 0; + } + else if ( tcb1 == NULL ) + { + xCoreID = 1; + } + else if ( tcb0->uxPriority < pxNewTCB->uxPriority && tcb0->uxPriority < tcb1->uxPriority ) + { + xCoreID = 0; + } + else if ( tcb1->uxPriority < pxNewTCB->uxPriority ) + { + xCoreID = 1; + } + else + { + xCoreID = xPortGetCoreID(); // Both CPU have higher priority tasks running on them, so this won't run yet + } + } + } - if( pxCurrentTCB[xCoreID] == NULL ) - { - /* There are no other tasks, or all the other tasks are in - the suspended state - make this the current task. */ - pxCurrentTCB[xCoreID] = pxNewTCB; + if( pxCurrentTCB[xCoreID] == NULL ) + { + /* There are no other tasks, or all the other tasks are in + * the suspended state - make this the current task. */ + pxCurrentTCB[xCoreID] = pxNewTCB; - if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 ) - { - /* This is the first task to be created so do the preliminary - initialisation required. We will not recover if this call - fails, but we will report the failure. */ - prvInitialiseTaskLists(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - /* If the scheduler is not already running, make this task the - current task if it is the highest priority task to be created - so far. */ - if( xSchedulerRunning == pdFALSE ) - { - if( pxCurrentTCB[xCoreID] == NULL || pxCurrentTCB[xCoreID]->uxPriority <= pxNewTCB->uxPriority ) - { - pxCurrentTCB[xCoreID] = pxNewTCB; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } + if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 ) + { + /* This is the first task to be created so do the preliminary + * initialisation required. We will not recover if this call + * fails, but we will report the failure. */ + prvInitialiseTaskLists(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* If the scheduler is not already running, make this task the + * current task if it is the highest priority task to be created + * so far. */ + if( xSchedulerRunning == pdFALSE ) + { + if( pxCurrentTCB[xCoreID] == NULL || pxCurrentTCB[xCoreID]->uxPriority <= pxNewTCB->uxPriority ) + { + pxCurrentTCB[xCoreID] = pxNewTCB; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } - uxTaskNumber++; + uxTaskNumber++; - #if ( configUSE_TRACE_FACILITY == 1 ) - { - /* Add a counter into the TCB for tracing only. */ - pxNewTCB->uxTCBNumber = uxTaskNumber; - } - #endif /* configUSE_TRACE_FACILITY */ - traceTASK_CREATE( pxNewTCB ); + #if ( configUSE_TRACE_FACILITY == 1 ) + { + /* Add a counter into the TCB for tracing only. */ + pxNewTCB->uxTCBNumber = uxTaskNumber; + } + #endif /* configUSE_TRACE_FACILITY */ + traceTASK_CREATE( pxNewTCB ); - prvAddTaskToReadyList( pxNewTCB ); + prvAddTaskToReadyList( pxNewTCB ); - portSETUP_TCB( pxNewTCB ); - } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + portSETUP_TCB( pxNewTCB ); + } + taskEXIT_CRITICAL(); - if( xSchedulerRunning != pdFALSE ) - { - /* If the created task is of a higher priority than the current task - then it should run now. */ - taskENTER_CRITICAL(&xTaskQueueMutex); + if( xSchedulerRunning != pdFALSE ) + { + /* If the created task is of a higher priority than the current task + * then it should run now. */ + taskENTER_CRITICAL(); - curTCB = pxCurrentTCB[ xCoreID ]; - if( curTCB == NULL || curTCB->uxPriority < pxNewTCB->uxPriority ) - { - if( xCoreID == xPortGetCoreID() ) - { - taskYIELD_IF_USING_PREEMPTION(); - } - else { - taskYIELD_OTHER_CORE(xCoreID, pxNewTCB->uxPriority); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - taskEXIT_CRITICAL(&xTaskQueueMutex); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + curTCB = pxCurrentTCB[ xCoreID ]; + if( curTCB == NULL || curTCB->uxPriority < pxNewTCB->uxPriority ) + { + if( xCoreID == xPortGetCoreID() ) + { + taskYIELD_IF_USING_PREEMPTION(); + } + else { + taskYIELD_OTHER_CORE(xCoreID, pxNewTCB->uxPriority); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + taskEXIT_CRITICAL(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } } /*-----------------------------------------------------------*/ #if ( INCLUDE_vTaskDelete == 1 ) - void vTaskDelete( TaskHandle_t xTaskToDelete ) - { - TCB_t *pxTCB; - TCB_t *curTCB; - BaseType_t core; - BaseType_t xFreeNow = 0; + void vTaskDelete( TaskHandle_t xTaskToDelete ) + { + TCB_t * pxTCB; + TCB_t * curTCB; + BaseType_t core; + BaseType_t xFreeNow = 0; - taskENTER_CRITICAL( &xTaskQueueMutex ); - { - core = xPortGetCoreID(); - curTCB = pxCurrentTCB[core]; + taskENTER_CRITICAL(); + { + core = xPortGetCoreID(); + curTCB = pxCurrentTCB[core]; - /* If null is passed in here then it is the calling task that is - being deleted. */ - pxTCB = prvGetTCBFromHandle( xTaskToDelete ); + /* If null is passed in here then it is the calling task that is + * being deleted. */ + pxTCB = prvGetTCBFromHandle( xTaskToDelete ); - /* Remove task from the ready/delayed list. */ - if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) - { - taskRESET_READY_PRIORITY( pxTCB->uxPriority ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* Remove task from the ready/delayed list. */ + if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) + { + taskRESET_READY_PRIORITY( pxTCB->uxPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - /* Is the task waiting on an event also? */ - if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) - { - ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* Is the task waiting on an event also? */ + if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) + { + ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - /* Increment the uxTaskNumber also so kernel aware debuggers can - detect that the task lists need re-generating. This is done before - portPRE_TASK_DELETE_HOOK() as in the Windows port that macro will - not return. */ - uxTaskNumber++; + /* Increment the uxTaskNumber also so kernel aware debuggers can + * detect that the task lists need re-generating. This is done before + * portPRE_TASK_DELETE_HOOK() as in the Windows port that macro will + * not return. */ + uxTaskNumber++; - if( pxTCB == curTCB || - /* in SMP, we also can't immediately delete the task active on the other core */ - (portNUM_PROCESSORS > 1 && pxTCB == pxCurrentTCB[ !core ]) || - /* ... and we can't delete a non-running task pinned to the other core, as - FPU cleanup has to happen on the same core */ - (portNUM_PROCESSORS > 1 && pxTCB->xCoreID == (!core)) ) - { - /* A task is deleting itself. This cannot complete within the - task itself, as a context switch to another task is required. - Place the task in the termination list. The idle task will - check the termination list and free up any memory allocated by - the scheduler for the TCB and stack of the deleted task. */ - vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xStateListItem ) ); + if( pxTCB == curTCB || + /* in SMP, we also can't immediately delete the task active on the other core */ + (portNUM_PROCESSORS > 1 && pxTCB == pxCurrentTCB[ !core ]) || + /* ... and we can't delete a non-running task pinned to the other core, as + FPU cleanup has to happen on the same core */ + (portNUM_PROCESSORS > 1 && pxTCB->xCoreID == (!core)) ) + { + /* A task is deleting itself. This cannot complete within the + * task itself, as a context switch to another task is required. + * Place the task in the termination list. The idle task will + * check the termination list and free up any memory allocated by + * the scheduler for the TCB and stack of the deleted task. */ + vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xStateListItem ) ); - /* Increment the ucTasksDeleted variable so the idle task knows - there is a task that has been deleted and that it should therefore - check the xTasksWaitingTermination list. */ - ++uxDeletedTasksWaitingCleanUp; + /* Increment the ucTasksDeleted variable so the idle task knows + * there is a task that has been deleted and that it should therefore + * check the xTasksWaitingTermination list. */ + ++uxDeletedTasksWaitingCleanUp; - /* The pre-delete hook is primarily for the Windows simulator, - in which Windows specific clean up operations are performed, - after which it is not possible to yield away from this task - - hence xYieldPending is used to latch that a context switch is - required. */ - portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending[core] ); + /* The pre-delete hook is primarily for the Windows simulator, + * in which Windows specific clean up operations are performed, + * after which it is not possible to yield away from this task - + * hence xYieldPending is used to latch that a context switch is + * required. */ + portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending[core] ); - if (portNUM_PROCESSORS > 1 && pxTCB == pxCurrentTCB[ !core ]) - { - /* SMP case of deleting a task running on a different core. Same issue - as a task deleting itself, but we need to send a yield to this task now - before we release xTaskQueueMutex. + if (portNUM_PROCESSORS > 1 && pxTCB == pxCurrentTCB[ !core ]) + { + /* SMP case of deleting a task running on a different core. Same issue + as a task deleting itself, but we need to send a yield to this task now + before we release xTaskQueueMutex. - Specifically there is a case where the other core may already be spinning on - xTaskQueueMutex waiting to go into a blocked state. A check is added in - prvAddCurrentTaskToDelayedList() to prevent it from removing itself from - xTasksWaitingTermination list in this case (instead it will immediately - release xTaskQueueMutex again and be yielded before the FreeRTOS function - returns.) */ - vPortYieldOtherCore( !core ); - } - } - else - { - --uxCurrentNumberOfTasks; - xFreeNow = pdTRUE; + Specifically there is a case where the other core may already be spinning on + xTaskQueueMutex waiting to go into a blocked state. A check is added in + prvAddCurrentTaskToDelayedList() to prevent it from removing itself from + xTasksWaitingTermination list in this case (instead it will immediately + release xTaskQueueMutex again and be yielded before the FreeRTOS function + returns.) */ + vPortYieldOtherCore( !core ); + } + } + else + { + --uxCurrentNumberOfTasks; + xFreeNow = pdTRUE; - /* Reset the next expected unblock time in case it referred to - the task that has just been deleted. */ - prvResetNextTaskUnblockTime(); - } + /* Reset the next expected unblock time in case it referred to + * the task that has just been deleted. */ + prvResetNextTaskUnblockTime(); + } - traceTASK_DELETE( pxTCB ); - } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + traceTASK_DELETE( pxTCB ); + } + taskEXIT_CRITICAL(); - if(xFreeNow == pdTRUE) { - #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) && ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS ) - prvDeleteTLS( pxTCB ); - #endif + if(xFreeNow == pdTRUE) { + #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) && ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS ) + prvDeleteTLS( pxTCB ); + #endif - prvDeleteTCB( pxTCB ); - } + prvDeleteTCB( pxTCB ); + } - /* Force a reschedule if it is the currently running task that has just - been deleted. */ - if( xSchedulerRunning != pdFALSE ) - { - if( pxTCB == curTCB ) - { - configASSERT( xTaskGetSchedulerState() != taskSCHEDULER_SUSPENDED ); - portYIELD_WITHIN_API(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - } + /* Force a reschedule if it is the currently running task that has just + * been deleted. */ + if( xSchedulerRunning != pdFALSE ) + { + if( pxTCB == curTCB ) + { + configASSERT( xTaskGetSchedulerState() != taskSCHEDULER_SUSPENDED ); + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } #endif /* INCLUDE_vTaskDelete */ /*-----------------------------------------------------------*/ -#if ( INCLUDE_vTaskDelayUntil == 1 ) +#if ( INCLUDE_xTaskDelayUntil == 1 ) +#ifdef ESP_PLATFORM + // backward binary compatibility - remove later + #undef vTaskDelayUntil + void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, + const TickType_t xTimeIncrement ) + { + xTaskDelayUntil(pxPreviousWakeTime, xTimeIncrement); + } +#endif // ESP_PLATFORM - void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement ) - { - TickType_t xTimeToWake; - BaseType_t xShouldDelay = pdFALSE; + BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime, + const TickType_t xTimeIncrement ) + { + TickType_t xTimeToWake; +#ifdef ESP_PLATFORM + BaseType_t xShouldDelay = pdFALSE; +#else + BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE; +#endif // ESP_PLATFORM - configASSERT( pxPreviousWakeTime ); - configASSERT( ( xTimeIncrement > 0U ) ); - configASSERT( uxSchedulerSuspended[xPortGetCoreID()] == 0 ); + configASSERT( pxPreviousWakeTime ); + configASSERT( ( xTimeIncrement > 0U ) ); + configASSERT( uxSchedulerSuspended[xPortGetCoreID()] == 0 ); - taskENTER_CRITICAL( &xTaskQueueMutex ); - { - /* Minor optimisation. The tick count cannot change in this - block. */ - const TickType_t xConstTickCount = xTickCount; +#ifdef ESP_PLATFORM // IDF-3755 + taskENTER_CRITICAL(); +#else + vTaskSuspendAll(); +#endif // ESP_PLATFORM + { + /* Minor optimisation. The tick count cannot change in this + * block. */ + const TickType_t xConstTickCount = xTickCount; - /* Generate the tick time at which the task wants to wake. */ - xTimeToWake = *pxPreviousWakeTime + xTimeIncrement; + /* Generate the tick time at which the task wants to wake. */ + xTimeToWake = *pxPreviousWakeTime + xTimeIncrement; - if( xConstTickCount < *pxPreviousWakeTime ) - { - /* The tick count has overflowed since this function was - lasted called. In this case the only time we should ever - actually delay is if the wake time has also overflowed, - and the wake time is greater than the tick time. When this - is the case it is as if neither time had overflowed. */ - if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) ) - { - xShouldDelay = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - /* The tick time has not overflowed. In this case we will - delay if either the wake time has overflowed, and/or the - tick time is less than the wake time. */ - if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) ) - { - xShouldDelay = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } + if( xConstTickCount < *pxPreviousWakeTime ) + { + /* The tick count has overflowed since this function was + * lasted called. In this case the only time we should ever + * actually delay is if the wake time has also overflowed, + * and the wake time is greater than the tick time. When this + * is the case it is as if neither time had overflowed. */ + if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) ) + { + xShouldDelay = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* The tick time has not overflowed. In this case we will + * delay if either the wake time has overflowed, and/or the + * tick time is less than the wake time. */ + if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) ) + { + xShouldDelay = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } - /* Update the wake time ready for the next call. */ - *pxPreviousWakeTime = xTimeToWake; + /* Update the wake time ready for the next call. */ + *pxPreviousWakeTime = xTimeToWake; - if( xShouldDelay != pdFALSE ) - { - traceTASK_DELAY_UNTIL(); + if( xShouldDelay != pdFALSE ) + { + traceTASK_DELAY_UNTIL(); - /* prvAddCurrentTaskToDelayedList() needs the block time, not - the time to wake, so subtract the current tick count. */ - prvAddCurrentTaskToDelayedList( xPortGetCoreID(), xTimeToWake - xConstTickCount ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + /* prvAddCurrentTaskToDelayedList() needs the block time, not + * the time to wake, so subtract the current tick count. */ + prvAddCurrentTaskToDelayedList( xPortGetCoreID(), xTimeToWake - xConstTickCount ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } +#ifdef ESP_PLATFORM // IDF-3755 + taskEXIT_CRITICAL(); +#else + xAlreadyYielded = xTaskResumeAll(); +#endif // ESP_PLATFORM - /* Force a reschedule, we may have put ourselves to sleep. */ - portYIELD_WITHIN_API(); - } + /* Force a reschedule if xTaskResumeAll has not already done so, we may + * have put ourselves to sleep. */ +#ifdef ESP_PLATFORM + portYIELD_WITHIN_API(); +#else + if( xAlreadyYielded == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } +#endif // ESP_PLATFORM + return xShouldDelay; + } -#endif /* INCLUDE_vTaskDelayUntil */ +#endif /* INCLUDE_xTaskDelayUntil */ /*-----------------------------------------------------------*/ #if ( INCLUDE_vTaskDelay == 1 ) - void vTaskDelay( const TickType_t xTicksToDelay ) - { - /* A delay time of zero just forces a reschedule. */ - if( xTicksToDelay > ( TickType_t ) 0U ) - { - configASSERT( uxSchedulerSuspended[xPortGetCoreID()] == 0 ); - taskENTER_CRITICAL( &xTaskQueueMutex ); - { - traceTASK_DELAY(); + void vTaskDelay( const TickType_t xTicksToDelay ) + { + /* A delay time of zero just forces a reschedule. */ + if( xTicksToDelay > ( TickType_t ) 0U ) + { + configASSERT( uxSchedulerSuspended[xPortGetCoreID()] == 0 ); +#ifdef ESP_PLATFORM // IDF-3755 + taskENTER_CRITICAL(); +#else + vTaskSuspendAll(); +#endif // ESP_PLATFORM + { + traceTASK_DELAY(); - /* A task that is removed from the event list while the - scheduler is suspended will not get placed in the ready - list or removed from the blocked list until the scheduler - is resumed. - - This task cannot be in an event list as it is the currently - executing task. */ - prvAddCurrentTaskToDelayedList( xPortGetCoreID(), xTicksToDelay ); - } - taskEXIT_CRITICAL( &xTaskQueueMutex ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - /* Force a reschedule, we may have put ourselves to sleep. */ - portYIELD_WITHIN_API(); - } + /* A task that is removed from the event list while the + * scheduler is suspended will not get placed in the ready + * list or removed from the blocked list until the scheduler + * is resumed. + * + * This task cannot be in an event list as it is the currently + * executing task. */ + prvAddCurrentTaskToDelayedList( xPortGetCoreID(), xTicksToDelay ); + } +#ifdef ESP_PLATFORM // IDF-3755 + taskEXIT_CRITICAL(); +#else + xAlreadyYielded = xTaskResumeAll(); +#endif // ESP_PLATFORM + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + /* Force a reschedule, we may have put ourselves to sleep. */ + portYIELD_WITHIN_API(); + } #endif /* INCLUDE_vTaskDelay */ /*-----------------------------------------------------------*/ -#if( ( INCLUDE_eTaskGetState == 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_xTaskAbortDelay == 1 ) ) +#if ( ( INCLUDE_eTaskGetState == 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_xTaskAbortDelay == 1 ) ) - eTaskState eTaskGetState( TaskHandle_t xTask ) - { - eTaskState eReturn; - List_t const * pxStateList, *pxDelayedList, *pxOverflowedDelayedList; - const TCB_t * const pxTCB = xTask; + eTaskState eTaskGetState( TaskHandle_t xTask ) + { + eTaskState eReturn; + List_t const * pxStateList, * pxDelayedList, * pxOverflowedDelayedList; + const TCB_t * const pxTCB = xTask; - configASSERT( pxTCB ); + configASSERT( pxTCB ); - taskENTER_CRITICAL( &xTaskQueueMutex ); //Need critical section incase either core context switches in between - if( pxTCB == pxCurrentTCB[xPortGetCoreID()]) - { - /* The task calling this function is querying its own state. */ - eReturn = eRunning; - } - #if (portNUM_PROCESSORS > 1) - else if (pxTCB == pxCurrentTCB[!xPortGetCoreID()]) - { - /* The task calling this function is querying its own state. */ - eReturn = eRunning; - } - #endif - else - { - pxStateList = listLIST_ITEM_CONTAINER( &( pxTCB->xStateListItem ) ); - pxDelayedList = pxDelayedTaskList; - pxOverflowedDelayedList = pxOverflowDelayedTaskList; + taskENTER_CRITICAL(); //Need critical section incase either core context switches in between + if( pxTCB == pxCurrentTCB[xPortGetCoreID()]) + { + /* The task calling this function is querying its own state. */ + eReturn = eRunning; + } + #if (portNUM_PROCESSORS > 1) + else if (pxTCB == pxCurrentTCB[!xPortGetCoreID()]) + { + /* The task calling this function is querying its own state. */ + eReturn = eRunning; + } + #endif + else + { + pxStateList = listLIST_ITEM_CONTAINER( &( pxTCB->xStateListItem ) ); + pxDelayedList = pxDelayedTaskList; + pxOverflowedDelayedList = pxOverflowDelayedTaskList; - if( ( pxStateList == pxDelayedList ) || ( pxStateList == pxOverflowedDelayedList ) ) - { - /* The task being queried is referenced from one of the Blocked - lists. */ - eReturn = eBlocked; - } + if( ( pxStateList == pxDelayedList ) || ( pxStateList == pxOverflowedDelayedList ) ) + { + /* The task being queried is referenced from one of the Blocked + * lists. */ + eReturn = eBlocked; + } - #if ( INCLUDE_vTaskSuspend == 1 ) - else if( pxStateList == &xSuspendedTaskList ) - { - /* The task being queried is referenced from the suspended - list. Is it genuinely suspended or is it blocked - indefinitely? */ - if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ) - { - #if( configUSE_TASK_NOTIFICATIONS == 1 ) - { - /* The task does not appear on the event list item of - and of the RTOS objects, but could still be in the - blocked state if it is waiting on its notification - rather than waiting on an object. */ - if( pxTCB->ucNotifyState == taskWAITING_NOTIFICATION ) - { - eReturn = eBlocked; - } - else - { - eReturn = eSuspended; - } - } - #else - { - eReturn = eSuspended; - } - #endif - } - else - { - eReturn = eBlocked; - } - } - #endif + #if ( INCLUDE_vTaskSuspend == 1 ) + else if( pxStateList == &xSuspendedTaskList ) + { + /* The task being queried is referenced from the suspended + * list. Is it genuinely suspended or is it blocked + * indefinitely? */ + if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ) + { + #if ( configUSE_TASK_NOTIFICATIONS == 1 ) + { + BaseType_t x; - #if ( INCLUDE_vTaskDelete == 1 ) - else if( ( pxStateList == &xTasksWaitingTermination ) || ( pxStateList == NULL ) ) - { - /* The task being queried is referenced from the deleted - tasks list, or it is not referenced from any lists at - all. */ - eReturn = eDeleted; - } - #endif + /* The task does not appear on the event list item of + * and of the RTOS objects, but could still be in the + * blocked state if it is waiting on its notification + * rather than waiting on an object. If not, is + * suspended. */ + eReturn = eSuspended; - else /*lint !e525 Negative indentation is intended to make use of pre-processor clearer. */ - { - /* If the task is not in any other state, it must be in the - Ready (including pending ready) state. */ - eReturn = eReady; - } - } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + for( x = 0; x < configTASK_NOTIFICATION_ARRAY_ENTRIES; x++ ) + { + if( pxTCB->ucNotifyState[ x ] == taskWAITING_NOTIFICATION ) + { + eReturn = eBlocked; + break; + } + } + } + #else /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */ + { + eReturn = eSuspended; + } + #endif /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */ + } + else + { + eReturn = eBlocked; + } + } + #endif /* if ( INCLUDE_vTaskSuspend == 1 ) */ - return eReturn; - } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */ + #if ( INCLUDE_vTaskDelete == 1 ) + else if( ( pxStateList == &xTasksWaitingTermination ) || ( pxStateList == NULL ) ) + { + /* The task being queried is referenced from the deleted + * tasks list, or it is not referenced from any lists at + * all. */ + eReturn = eDeleted; + } + #endif + + else /*lint !e525 Negative indentation is intended to make use of pre-processor clearer. */ + { + /* If the task is not in any other state, it must be in the + * Ready (including pending ready) state. */ + eReturn = eReady; + } + } + taskEXIT_CRITICAL(); + + return eReturn; + } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */ #endif /* INCLUDE_eTaskGetState */ /*-----------------------------------------------------------*/ #if ( INCLUDE_uxTaskPriorityGet == 1 ) - UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask ) - { - TCB_t const *pxTCB; - UBaseType_t uxReturn; + UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask ) + { + TCB_t const * pxTCB; + UBaseType_t uxReturn; - taskENTER_CRITICAL( &xTaskQueueMutex ); - { - /* If null is passed in here then it is the priority of the task - that called uxTaskPriorityGet() that is being queried. */ - pxTCB = prvGetTCBFromHandle( xTask ); - uxReturn = pxTCB->uxPriority; - } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + taskENTER_CRITICAL(); + { + /* If null is passed in here then it is the priority of the task + * that called uxTaskPriorityGet() that is being queried. */ + pxTCB = prvGetTCBFromHandle( xTask ); + uxReturn = pxTCB->uxPriority; + } + taskEXIT_CRITICAL(); - return uxReturn; - } + return uxReturn; + } #endif /* INCLUDE_uxTaskPriorityGet */ /*-----------------------------------------------------------*/ #if ( INCLUDE_uxTaskPriorityGet == 1 ) - UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask ) - { - TCB_t const *pxTCB; - UBaseType_t uxReturn; + UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask ) + { + TCB_t const * pxTCB; + UBaseType_t uxReturn; - /* RTOS ports that support interrupt nesting have the concept of a - maximum system call (or maximum API call) interrupt priority. - Interrupts that are above the maximum system call priority are keep - permanently enabled, even when the RTOS kernel is in a critical section, - but cannot make any calls to FreeRTOS API functions. If configASSERT() - is defined in FreeRTOSConfig.h then - portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion - failure if a FreeRTOS API function is called from an interrupt that has - been assigned a priority above the configured maximum system call - priority. Only FreeRTOS functions that end in FromISR can be called - from interrupts that have been assigned a priority at or (logically) - below the maximum system call interrupt priority. FreeRTOS maintains a - separate interrupt safe API to ensure interrupt entry is as fast and as - simple as possible. More information (albeit Cortex-M specific) is - provided on the following link: - https://www.freertos.org/RTOS-Cortex-M3-M4.html */ - portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + /* RTOS ports that support interrupt nesting have the concept of a + * maximum system call (or maximum API call) interrupt priority. + * Interrupts that are above the maximum system call priority are keep + * permanently enabled, even when the RTOS kernel is in a critical section, + * but cannot make any calls to FreeRTOS API functions. If configASSERT() + * is defined in FreeRTOSConfig.h then + * portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + * failure if a FreeRTOS API function is called from an interrupt that has + * been assigned a priority above the configured maximum system call + * priority. Only FreeRTOS functions that end in FromISR can be called + * from interrupts that have been assigned a priority at or (logically) + * below the maximum system call interrupt priority. FreeRTOS maintains a + * separate interrupt safe API to ensure interrupt entry is as fast and as + * simple as possible. More information (albeit Cortex-M specific) is + * provided on the following link: + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); - portENTER_CRITICAL_ISR(&xTaskQueueMutex ); - { - /* If null is passed in here then it is the priority of the calling - task that is being queried. */ - pxTCB = prvGetTCBFromHandle( xTask ); - uxReturn = pxTCB->uxPriority; - } - portEXIT_CRITICAL_ISR(&xTaskQueueMutex); + portENTER_CRITICAL_ISR(&xTaskQueueMutex ); + { + /* If null is passed in here then it is the priority of the calling + * task that is being queried. */ + pxTCB = prvGetTCBFromHandle( xTask ); + uxReturn = pxTCB->uxPriority; + } + portEXIT_CRITICAL_ISR(&xTaskQueueMutex); - return uxReturn; - } + return uxReturn; + } #endif /* INCLUDE_uxTaskPriorityGet */ /*-----------------------------------------------------------*/ #if ( INCLUDE_vTaskPrioritySet == 1 ) - void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ) - { - TCB_t *pxTCB; - UBaseType_t uxCurrentBasePriority, uxPriorityUsedOnEntry; - BaseType_t xYieldRequired = pdFALSE; + void vTaskPrioritySet( TaskHandle_t xTask, + UBaseType_t uxNewPriority ) + { + TCB_t * pxTCB; + UBaseType_t uxCurrentBasePriority, uxPriorityUsedOnEntry; + BaseType_t xYieldRequired = pdFALSE; - configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) ); + configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) ); - /* Ensure the new priority is valid. */ - if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES ) - { - uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* Ensure the new priority is valid. */ + if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES ) + { + uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - taskENTER_CRITICAL( &xTaskQueueMutex ); - { - /* If null is passed in here then it is the priority of the calling - task that is being changed. */ - pxTCB = prvGetTCBFromHandle( xTask ); + taskENTER_CRITICAL(); + { + /* If null is passed in here then it is the priority of the calling + * task that is being changed. */ + pxTCB = prvGetTCBFromHandle( xTask ); - traceTASK_PRIORITY_SET( pxTCB, uxNewPriority ); + traceTASK_PRIORITY_SET( pxTCB, uxNewPriority ); - #if ( configUSE_MUTEXES == 1 ) - { - uxCurrentBasePriority = pxTCB->uxBasePriority; - } - #else - { - uxCurrentBasePriority = pxTCB->uxPriority; - } - #endif + #if ( configUSE_MUTEXES == 1 ) + { + uxCurrentBasePriority = pxTCB->uxBasePriority; + } + #else + { + uxCurrentBasePriority = pxTCB->uxPriority; + } + #endif - if( uxCurrentBasePriority != uxNewPriority ) - { - /* The priority change may have readied a task of higher - priority than the calling task. */ - if( uxNewPriority > uxCurrentBasePriority ) - { - if( pxTCB != pxCurrentTCB[xPortGetCoreID()] ) - { - /* The priority of a task other than the currently - running task is being raised. Is the priority being - raised above that of the running task? */ - if ( tskCAN_RUN_HERE(pxTCB->xCoreID) && uxNewPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) - { - xYieldRequired = pdTRUE; - } - else if ( pxTCB->xCoreID != xPortGetCoreID() ) - { - taskYIELD_OTHER_CORE( pxTCB->xCoreID, uxNewPriority ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - /* The priority of the running task is being raised, - but the running task must already be the highest - priority task able to run so no yield is required. */ - } - } - else if( pxTCB == pxCurrentTCB[xPortGetCoreID()] ) - { - /* Setting the priority of the running task down means - there may now be another task of higher priority that - is ready to execute. */ - xYieldRequired = pdTRUE; - } - else if( pxTCB != pxCurrentTCB[xPortGetCoreID()] ) - { - /* The priority of a task other than the currently - running task is being raised. Is the priority being - raised above that of the running task? */ - if( uxNewPriority >= pxCurrentTCB[xPortGetCoreID()]->uxPriority ) - { - xYieldRequired = pdTRUE; - } - else if ( pxTCB->xCoreID != xPortGetCoreID() ) //Need to check if not currently running on other core - { - taskYIELD_OTHER_CORE( pxTCB->xCoreID, uxNewPriority ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - /* Setting the priority of any other task down does not - require a yield as the running task must be above the - new priority of the task being modified. */ - } + if( uxCurrentBasePriority != uxNewPriority ) + { + /* The priority change may have readied a task of higher + * priority than the calling task. */ + if( uxNewPriority > uxCurrentBasePriority ) + { + if( pxTCB != pxCurrentTCB[xPortGetCoreID()] ) + { + /* The priority of a task other than the currently + * running task is being raised. Is the priority being + * raised above that of the running task? */ + if ( tskCAN_RUN_HERE(pxTCB->xCoreID) && uxNewPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) + { + xYieldRequired = pdTRUE; + } + else if ( pxTCB->xCoreID != xPortGetCoreID() ) + { + taskYIELD_OTHER_CORE( pxTCB->xCoreID, uxNewPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* The priority of the running task is being raised, + * but the running task must already be the highest + * priority task able to run so no yield is required. */ + } + } + else if( pxTCB == pxCurrentTCB[xPortGetCoreID()] ) + { + /* Setting the priority of the running task down means + * there may now be another task of higher priority that + * is ready to execute. */ + xYieldRequired = pdTRUE; + } + else if( pxTCB != pxCurrentTCB[xPortGetCoreID()] ) + { + /* The priority of a task other than the currently + * running task is being raised. Is the priority being + * raised above that of the running task? */ + if( uxNewPriority >= pxCurrentTCB[xPortGetCoreID()]->uxPriority ) + { + xYieldRequired = pdTRUE; + } + else if ( pxTCB->xCoreID != xPortGetCoreID() ) //Need to check if not currently running on other core + { + taskYIELD_OTHER_CORE( pxTCB->xCoreID, uxNewPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* Setting the priority of any other task down does not + * require a yield as the running task must be above the + * new priority of the task being modified. */ + } - /* Remember the ready list the task might be referenced from - before its uxPriority member is changed so the - taskRESET_READY_PRIORITY() macro can function correctly. */ - uxPriorityUsedOnEntry = pxTCB->uxPriority; + /* Remember the ready list the task might be referenced from + * before its uxPriority member is changed so the + * taskRESET_READY_PRIORITY() macro can function correctly. */ + uxPriorityUsedOnEntry = pxTCB->uxPriority; - #if ( configUSE_MUTEXES == 1 ) - { - /* Only change the priority being used if the task is not - currently using an inherited priority. */ - if( pxTCB->uxBasePriority == pxTCB->uxPriority ) - { - pxTCB->uxPriority = uxNewPriority; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + #if ( configUSE_MUTEXES == 1 ) + { + /* Only change the priority being used if the task is not + * currently using an inherited priority. */ + if( pxTCB->uxBasePriority == pxTCB->uxPriority ) + { + pxTCB->uxPriority = uxNewPriority; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - /* The base priority gets set whatever. */ - pxTCB->uxBasePriority = uxNewPriority; - } - #else - { - pxTCB->uxPriority = uxNewPriority; - } - #endif + /* The base priority gets set whatever. */ + pxTCB->uxBasePriority = uxNewPriority; + } + #else /* if ( configUSE_MUTEXES == 1 ) */ + { + pxTCB->uxPriority = uxNewPriority; + } + #endif /* if ( configUSE_MUTEXES == 1 ) */ - /* Only reset the event list item value if the value is not - being used for anything else. */ - if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL ) - { - listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxNewPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* Only reset the event list item value if the value is not + * being used for anything else. */ + if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL ) + { + listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxNewPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - /* If the task is in the blocked or suspended list we need do - nothing more than change its priority variable. However, if - the task is in a ready list it needs to be removed and placed - in the list appropriate to its new priority. */ - if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE ) - { - /* The task is currently in its ready list - remove before - adding it to it's new ready list. As we are in a critical - section we can do this even if the scheduler is suspended. */ - if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) - { - /* It is known that the task is in its ready list so - there is no need to check again and the port level - reset macro can be called directly. */ - portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - prvAddTaskToReadyList( pxTCB ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* If the task is in the blocked or suspended list we need do + * nothing more than change its priority variable. However, if + * the task is in a ready list it needs to be removed and placed + * in the list appropriate to its new priority. */ + if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE ) + { + /* The task is currently in its ready list - remove before + * adding it to its new ready list. As we are in a critical + * section we can do this even if the scheduler is suspended. */ + if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) + { + /* It is known that the task is in its ready list so + * there is no need to check again and the port level + * reset macro can be called directly. */ + portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - if( xYieldRequired != pdFALSE ) - { - taskYIELD_IF_USING_PREEMPTION(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + prvAddTaskToReadyList( pxTCB ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - /* Remove compiler warning about unused variables when the port - optimised task selection is not being used. */ - ( void ) uxPriorityUsedOnEntry; - } - } - taskEXIT_CRITICAL( &xTaskQueueMutex ); - } + if( xYieldRequired != pdFALSE ) + { + taskYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Remove compiler warning about unused variables when the port + * optimised task selection is not being used. */ + ( void ) uxPriorityUsedOnEntry; + } + } + taskEXIT_CRITICAL(); + } #endif /* INCLUDE_vTaskPrioritySet */ /*-----------------------------------------------------------*/ #if ( INCLUDE_vTaskSuspend == 1 ) - void vTaskSuspend( TaskHandle_t xTaskToSuspend ) - { - TCB_t *pxTCB; - TCB_t *curTCB; + void vTaskSuspend( TaskHandle_t xTaskToSuspend ) + { + TCB_t * pxTCB; + TCB_t * curTCB; - taskENTER_CRITICAL( &xTaskQueueMutex ); - { - /* If null is passed in here then it is the running task that is - being suspended. */ - pxTCB = prvGetTCBFromHandle( xTaskToSuspend ); + taskENTER_CRITICAL(); + { + /* If null is passed in here then it is the running task that is + * being suspended. */ + pxTCB = prvGetTCBFromHandle( xTaskToSuspend ); - traceTASK_SUSPEND( pxTCB ); + traceTASK_SUSPEND( pxTCB ); - /* Remove task from the ready/delayed list and place in the - suspended list. */ - if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) - { - taskRESET_READY_PRIORITY( pxTCB->uxPriority ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* Remove task from the ready/delayed list and place in the + * suspended list. */ + if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) + { + taskRESET_READY_PRIORITY( pxTCB->uxPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - /* Is the task waiting on an event also? */ - if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) - { - ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* Is the task waiting on an event also? */ + if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) + { + ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) ); - curTCB = pxCurrentTCB[ xPortGetCoreID() ]; + vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) ); + curTCB = pxCurrentTCB[ xPortGetCoreID() ]; - #if( configUSE_TASK_NOTIFICATIONS == 1 ) - { - if( pxTCB->ucNotifyState == taskWAITING_NOTIFICATION ) - { - /* The task was blocked to wait for a notification, but is - now suspended, so no notification was received. */ - pxTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION; - } - } - #endif - } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + #if ( configUSE_TASK_NOTIFICATIONS == 1 ) + { + BaseType_t x; - if( xSchedulerRunning != pdFALSE ) - { - /* Reset the next expected unblock time in case it referred to the - task that is now in the Suspended state. */ - taskENTER_CRITICAL( &xTaskQueueMutex ); - { - prvResetNextTaskUnblockTime(); - } - taskEXIT_CRITICAL( &xTaskQueueMutex ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + for( x = 0; x < configTASK_NOTIFICATION_ARRAY_ENTRIES; x++ ) + { + if( pxTCB->ucNotifyState[ x ] == taskWAITING_NOTIFICATION ) + { + /* The task was blocked to wait for a notification, but is + * now suspended, so no notification was received. */ + pxTCB->ucNotifyState[ x ] = taskNOT_WAITING_NOTIFICATION; + } + } + } + #endif /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */ + } + taskEXIT_CRITICAL(); - if( pxTCB == curTCB ) - { - if( xSchedulerRunning != pdFALSE ) - { - /* The current task has just been suspended. */ - taskENTER_CRITICAL(&xTaskQueueMutex); - BaseType_t suspended = uxSchedulerSuspended[xPortGetCoreID()]; - taskEXIT_CRITICAL(&xTaskQueueMutex); + if( xSchedulerRunning != pdFALSE ) + { + /* Reset the next expected unblock time in case it referred to the + * task that is now in the Suspended state. */ + taskENTER_CRITICAL(); + { + prvResetNextTaskUnblockTime(); + } + taskEXIT_CRITICAL(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - configASSERT( suspended == 0 ); - (void)suspended; - portYIELD_WITHIN_API(); - } - else - { - /* The scheduler is not running, but the task that was pointed - to by pxCurrentTCB has just been suspended and pxCurrentTCB - must be adjusted to point to a different task. */ - if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks ) /*lint !e931 Right has no side effect, just volatile. */ - { - /* No other tasks are ready, so set pxCurrentTCB back to - NULL so when the next task is created pxCurrentTCB will - be set to point to it no matter what its relative priority - is. */ - taskENTER_CRITICAL(&xTaskQueueMutex); - pxCurrentTCB[ xPortGetCoreID() ] = NULL; - taskEXIT_CRITICAL(&xTaskQueueMutex); - } - else - { - vTaskSwitchContext(); - } - } - } - else - { - if( xSchedulerRunning != pdFALSE ) - { - /* A task other than the currently running task was suspended, - reset the next expected unblock time in case it referred to the - task that is now in the Suspended state. */ - taskENTER_CRITICAL(&xTaskQueueMutex); - { - prvResetNextTaskUnblockTime(); - } - taskEXIT_CRITICAL(&xTaskQueueMutex); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - } + if( pxTCB == curTCB ) + { + if( xSchedulerRunning != pdFALSE ) + { + /* The current task has just been suspended. */ + taskENTER_CRITICAL(); + BaseType_t suspended = uxSchedulerSuspended[xPortGetCoreID()]; + taskEXIT_CRITICAL(); + + configASSERT( suspended == 0 ); + (void)suspended; + portYIELD_WITHIN_API(); + } + else + { + /* The scheduler is not running, but the task that was pointed + * to by pxCurrentTCB has just been suspended and pxCurrentTCB + * must be adjusted to point to a different task. */ + if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks ) /*lint !e931 Right has no side effect, just volatile. */ + { + /* No other tasks are ready, so set pxCurrentTCB back to + * NULL so when the next task is created pxCurrentTCB will + * be set to point to it no matter what its relative priority + * is. */ + taskENTER_CRITICAL(); + pxCurrentTCB[ xPortGetCoreID() ] = NULL; + taskEXIT_CRITICAL(); + } + else + { + vTaskSwitchContext(); + } + } + } + else + { + if( xSchedulerRunning != pdFALSE ) + { + /* A task other than the currently running task was suspended, + * reset the next expected unblock time in case it referred to the + * task that is now in the Suspended state. */ + taskENTER_CRITICAL(); + { + prvResetNextTaskUnblockTime(); + } + taskEXIT_CRITICAL(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } #endif /* INCLUDE_vTaskSuspend */ /*-----------------------------------------------------------*/ #if ( INCLUDE_vTaskSuspend == 1 ) - static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) - { - BaseType_t xReturn = pdFALSE; - const TCB_t * const pxTCB = xTask; + static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) + { + BaseType_t xReturn = pdFALSE; + const TCB_t * const pxTCB = xTask; - /* Accesses xPendingReadyList so must be called from a critical - section. */ + /* Accesses xPendingReadyList so must be called from a critical + * section. */ - /* It does not make sense to check if the calling task is suspended. */ - configASSERT( xTask ); + /* It does not make sense to check if the calling task is suspended. */ + configASSERT( xTask ); - /* Is the task being resumed actually in the suspended list? */ - if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xStateListItem ) ) != pdFALSE ) - { - /* Has the task already been resumed from within an ISR? */ - if( listIS_CONTAINED_WITHIN( &xPendingReadyList[xPortGetCoreID()], &( pxTCB->xEventListItem )) || - listIS_CONTAINED_WITHIN( &xPendingReadyList[!xPortGetCoreID()], &( pxTCB->xEventListItem )) == pdFALSE ) - { - /* Is it in the suspended list because it is in the Suspended - state, or because is is blocked with no timeout? */ - if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE ) /*lint !e961. The cast is only redundant when NULL is used. */ - { - xReturn = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* Is the task being resumed actually in the suspended list? */ + if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xStateListItem ) ) != pdFALSE ) + { + /* Has the task already been resumed from within an ISR? */ + if( listIS_CONTAINED_WITHIN( &xPendingReadyList[xPortGetCoreID()], &( pxTCB->xEventListItem )) || + listIS_CONTAINED_WITHIN( &xPendingReadyList[!xPortGetCoreID()], &( pxTCB->xEventListItem )) == pdFALSE ) + { + /* Is it in the suspended list because it is in the Suspended + * state, or because is is blocked with no timeout? */ + if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE ) /*lint !e961. The cast is only redundant when NULL is used. */ + { + xReturn = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - return xReturn; - } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */ + return xReturn; + } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */ #endif /* INCLUDE_vTaskSuspend */ /*-----------------------------------------------------------*/ #if ( INCLUDE_vTaskSuspend == 1 ) - void vTaskResume( TaskHandle_t xTaskToResume ) - { - TCB_t * const pxTCB = xTaskToResume; + void vTaskResume( TaskHandle_t xTaskToResume ) + { + TCB_t * const pxTCB = xTaskToResume; - /* It does not make sense to resume the calling task. */ - configASSERT( xTaskToResume ); - taskENTER_CRITICAL( &xTaskQueueMutex ); + /* It does not make sense to resume the calling task. */ + configASSERT( xTaskToResume ); + taskENTER_CRITICAL(); - /* The parameter cannot be NULL as it is impossible to resume the - currently executing task. */ - if( ( pxTCB != pxCurrentTCB[xPortGetCoreID()] ) && ( pxTCB != NULL ) ) - { - if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE ) - { - traceTASK_RESUME( pxTCB ); + /* The parameter cannot be NULL as it is impossible to resume the + * currently executing task. */ + if( ( pxTCB != pxCurrentTCB[xPortGetCoreID()] ) && ( pxTCB != NULL ) ) + { + { + if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE ) + { + traceTASK_RESUME( pxTCB ); - /* The ready list can be accessed even if the scheduler is - suspended because this is inside a critical section. */ - ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); - prvAddTaskToReadyList( pxTCB ); + /* The ready list can be accessed even if the scheduler is + * suspended because this is inside a critical section. */ + ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); + prvAddTaskToReadyList( pxTCB ); - /* We may have just resumed a higher priority task. */ - if( tskCAN_RUN_HERE(pxTCB->xCoreID) && pxTCB->uxPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) - { - /* This yield may not cause the task just resumed to run, - but will leave the lists in the correct state for the - next yield. */ - taskYIELD_IF_USING_PREEMPTION(); - } - else if( pxTCB->xCoreID != xPortGetCoreID() ) - { - taskYIELD_OTHER_CORE( pxTCB->xCoreID, pxTCB->uxPriority ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - taskEXIT_CRITICAL( &xTaskQueueMutex ); - } + /* We may have just resumed a higher priority task. */ + if( tskCAN_RUN_HERE(pxTCB->xCoreID) && pxTCB->uxPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) + { + /* This yield may not cause the task just resumed to run, + * but will leave the lists in the correct state for the + * next yield. */ + taskYIELD_IF_USING_PREEMPTION(); + } + else if( pxTCB->xCoreID != xPortGetCoreID() ) + { + taskYIELD_OTHER_CORE( pxTCB->xCoreID, pxTCB->uxPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + taskEXIT_CRITICAL(); + } #endif /* INCLUDE_vTaskSuspend */ @@ -2091,255 +2183,257 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode #if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) - BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) - { - BaseType_t xYieldRequired = pdFALSE; - TCB_t * const pxTCB = xTaskToResume; + BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) + { + BaseType_t xYieldRequired = pdFALSE; + TCB_t * const pxTCB = xTaskToResume; - configASSERT( xTaskToResume ); + configASSERT( xTaskToResume ); - /* RTOS ports that support interrupt nesting have the concept of a - maximum system call (or maximum API call) interrupt priority. - Interrupts that are above the maximum system call priority are keep - permanently enabled, even when the RTOS kernel is in a critical section, - but cannot make any calls to FreeRTOS API functions. If configASSERT() - is defined in FreeRTOSConfig.h then - portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion - failure if a FreeRTOS API function is called from an interrupt that has - been assigned a priority above the configured maximum system call - priority. Only FreeRTOS functions that end in FromISR can be called - from interrupts that have been assigned a priority at or (logically) - below the maximum system call interrupt priority. FreeRTOS maintains a - separate interrupt safe API to ensure interrupt entry is as fast and as - simple as possible. More information (albeit Cortex-M specific) is - provided on the following link: - https://www.freertos.org/RTOS-Cortex-M3-M4.html */ - //portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + /* RTOS ports that support interrupt nesting have the concept of a + * maximum system call (or maximum API call) interrupt priority. + * Interrupts that are above the maximum system call priority are keep + * permanently enabled, even when the RTOS kernel is in a critical section, + * but cannot make any calls to FreeRTOS API functions. If configASSERT() + * is defined in FreeRTOSConfig.h then + * portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + * failure if a FreeRTOS API function is called from an interrupt that has + * been assigned a priority above the configured maximum system call + * priority. Only FreeRTOS functions that end in FromISR can be called + * from interrupts that have been assigned a priority at or (logically) + * below the maximum system call interrupt priority. FreeRTOS maintains a + * separate interrupt safe API to ensure interrupt entry is as fast and as + * simple as possible. More information (albeit Cortex-M specific) is + * provided on the following link: + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + //portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); - taskENTER_CRITICAL_ISR(&xTaskQueueMutex); - { - if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE ) - { - traceTASK_RESUME_FROM_ISR( pxTCB ); + taskENTER_CRITICAL_ISR(); + { + if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE ) + { + traceTASK_RESUME_FROM_ISR( pxTCB ); - /* Check the ready lists can be accessed. */ - if( uxSchedulerSuspended[xPortGetCoreID()] == ( UBaseType_t ) pdFALSE ) - { + /* Check the ready lists can be accessed. */ + if( uxSchedulerSuspended[xPortGetCoreID()] == ( UBaseType_t ) pdFALSE ) + { - ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); - prvAddTaskToReadyList( pxTCB ); + ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); + prvAddTaskToReadyList( pxTCB ); - if( tskCAN_RUN_HERE( pxTCB->xCoreID ) && pxTCB->uxPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) - { - xYieldRequired = pdTRUE; - } - else if ( pxTCB->xCoreID != xPortGetCoreID() ) - { - taskYIELD_OTHER_CORE( pxTCB->xCoreID, pxTCB->uxPriority); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + if( tskCAN_RUN_HERE( pxTCB->xCoreID ) && pxTCB->uxPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) + { + xYieldRequired = pdTRUE; + } + else if ( pxTCB->xCoreID != xPortGetCoreID() ) + { + taskYIELD_OTHER_CORE( pxTCB->xCoreID, pxTCB->uxPriority); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - } - else - { - /* The delayed or ready lists cannot be accessed so the task - is held in the pending ready list until the scheduler is - unsuspended. */ - vListInsertEnd( &( xPendingReadyList[xPortGetCoreID()] ), &( pxTCB->xEventListItem ) ); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - taskEXIT_CRITICAL_ISR(&xTaskQueueMutex); + } + else + { + /* The delayed or ready lists cannot be accessed so the task + * is held in the pending ready list until the scheduler is + * unsuspended. */ + vListInsertEnd( &( xPendingReadyList[xPortGetCoreID()] ), &( pxTCB->xEventListItem ) ); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL_ISR(); - return xYieldRequired; - } + return xYieldRequired; + } #endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */ /*-----------------------------------------------------------*/ void vTaskStartScheduler( void ) { -BaseType_t xReturn; + BaseType_t xReturn; -#if( configSUPPORT_STATIC_ALLOCATION == 1 && configSUPPORT_STATIC_ALLOCATION == 0 ) -StaticTask_t *pxIdleTaskTCBBuffer[portNUM_PROCESSORS] = {NULL}; -StackType_t *pxIdleTaskStackBuffer[portNUM_PROCESSORS] = {NULL}; -uint32_t ulIdleTaskStackSize; -#endif + #if ( configSUPPORT_STATIC_ALLOCATION == 1 && configSUPPORT_STATIC_ALLOCATION == 0 ) + StaticTask_t *pxIdleTaskTCBBuffer[portNUM_PROCESSORS] = {NULL}; + StackType_t *pxIdleTaskStackBuffer[portNUM_PROCESSORS] = {NULL}; + uint32_t ulIdleTaskStackSize; + #endif - for(BaseType_t i = 0; i < portNUM_PROCESSORS; i++) - { - /* Add the idle task at the lowest priority. */ + for(BaseType_t i = 0; i < portNUM_PROCESSORS; i++) + { + /* Add the idle task at the lowest priority. */ #if( 0 ) /* configSUPPORT_STATIC_ALLOCATION == 1 ) Temporarily unsupported IDF-2243 */ - { - /* The Idle task is created using user provided RAM - obtain the - address of the RAM then create the idle task. */ - vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer[i], &pxIdleTaskStackBuffer[i], &ulIdleTaskStackSize ); - xIdleTaskHandle[i] = xTaskCreateStaticPinnedToCore( prvIdleTask, - configIDLE_TASK_NAME, - ulIdleTaskStackSize, - ( void * ) NULL, /*lint !e961. The cast is not redundant for all compilers. */ - portPRIVILEGE_BIT, /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */ - pxIdleTaskStackBuffer[i], - pxIdleTaskTCBBuffer[i], - i ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */ + { + /* The Idle task is created using user provided RAM - obtain the + address of the RAM then create the idle task. */ + vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer[i], &pxIdleTaskStackBuffer[i], &ulIdleTaskStackSize ); + xIdleTaskHandle[i] = xTaskCreateStaticPinnedToCore( prvIdleTask, + configIDLE_TASK_NAME, + ulIdleTaskStackSize, + ( void * ) NULL, /*lint !e961. The cast is not redundant for all compilers. */ + portPRIVILEGE_BIT, /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */ + pxIdleTaskStackBuffer[i], + pxIdleTaskTCBBuffer[i], + i ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */ - if( xIdleTaskHandle[i] != NULL ) - { - xReturn = pdPASS; - } - else - { - xReturn = pdFAIL; - } - } - #else - { - /* The Idle task is being created using dynamically allocated RAM. */ - xReturn = xTaskCreatePinnedToCore( prvIdleTask, - configIDLE_TASK_NAME, - configIDLE_TASK_STACK_SIZE, - ( void * ) NULL, - portPRIVILEGE_BIT, /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */ - &xIdleTaskHandle[i], - i ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */ + if( xIdleTaskHandle[i] != NULL ) + { + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + } + } + #else /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ + { + /* The Idle task is being created using dynamically allocated RAM. */ + xReturn = xTaskCreatePinnedToCore( prvIdleTask, + configIDLE_TASK_NAME, + configIDLE_TASK_STACK_SIZE, + ( void * ) NULL, + portPRIVILEGE_BIT, /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */ + &xIdleTaskHandle[i], + i ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */ - if( xIdleTaskHandle[i] != NULL ) - { - xReturn = pdPASS; - } - else - { - xReturn = pdFAIL; - } - } - #endif /* configSUPPORT_STATIC_ALLOCATION */ - } + if( xIdleTaskHandle[i] != NULL ) + { + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + } + } + #endif /* configSUPPORT_STATIC_ALLOCATION */ + } - #if ( configUSE_TIMERS == 1 ) - { - if( xReturn == pdPASS ) - { - xReturn = xTimerCreateTimerTask(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - #endif /* configUSE_TIMERS */ + #if ( configUSE_TIMERS == 1 ) + { + if( xReturn == pdPASS ) + { + xReturn = xTimerCreateTimerTask(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_TIMERS */ - if( xReturn == pdPASS ) - { - /* freertos_tasks_c_additions_init() should only be called if the user - definable macro FREERTOS_TASKS_C_ADDITIONS_INIT() is defined, as that is - the only macro called by the function. */ - #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT - { - freertos_tasks_c_additions_init(); - } - #endif + if( xReturn == pdPASS ) + { + /* freertos_tasks_c_additions_init() should only be called if the user + * definable macro FREERTOS_TASKS_C_ADDITIONS_INIT() is defined, as that is + * the only macro called by the function. */ + #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT + { + freertos_tasks_c_additions_init(); + } + #endif - /* Interrupts are turned off here, to ensure a tick does not occur - before or during the call to xPortStartScheduler(). The stacks of - the created tasks contain a status word with interrupts switched on - so interrupts will automatically get re-enabled when the first task - starts to run. */ - portDISABLE_INTERRUPTS(); + /* Interrupts are turned off here, to ensure a tick does not occur + * before or during the call to xPortStartScheduler(). The stacks of + * the created tasks contain a status word with interrupts switched on + * so interrupts will automatically get re-enabled when the first task + * starts to run. */ + portDISABLE_INTERRUPTS(); - #if ( configUSE_NEWLIB_REENTRANT == 1 ) - { - // /* Switch Newlib's _impure_ptr variable to point to the _reent - // structure specific to the task that will run first. */ - // _impure_ptr = &( pxCurrentTCB[xPortGetCoreID()]->xNewLib_reent ); - } - #endif /* configUSE_NEWLIB_REENTRANT */ + #if ( configUSE_NEWLIB_REENTRANT == 1 ) + { + /* Switch Newlib's _impure_ptr variable to point to the _reent + * structure specific to the task that will run first. + * See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html + * for additional information. */ + // _impure_ptr = &( pxCurrentTCB[xPortGetCoreID()]->xNewLib_reent ); + } + #endif /* configUSE_NEWLIB_REENTRANT */ - xNextTaskUnblockTime = portMAX_DELAY; - xSchedulerRunning = pdTRUE; - xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT; + xNextTaskUnblockTime = portMAX_DELAY; + xSchedulerRunning = pdTRUE; + xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT; - /* If configGENERATE_RUN_TIME_STATS is defined then the following - macro must be defined to configure the timer/counter used to generate - the run time counter time base. NOTE: If configGENERATE_RUN_TIME_STATS - is set to 0 and the following line fails to build then ensure you do not - have portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() defined in your - FreeRTOSConfig.h file. */ - portCONFIGURE_TIMER_FOR_RUN_TIME_STATS(); + /* If configGENERATE_RUN_TIME_STATS is defined then the following + * macro must be defined to configure the timer/counter used to generate + * the run time counter time base. NOTE: If configGENERATE_RUN_TIME_STATS + * is set to 0 and the following line fails to build then ensure you do not + * have portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() defined in your + * FreeRTOSConfig.h file. */ + portCONFIGURE_TIMER_FOR_RUN_TIME_STATS(); - traceTASK_SWITCHED_IN(); + traceTASK_SWITCHED_IN(); - /* Setting up the timer tick is hardware specific and thus in the - portable interface. */ - if( xPortStartScheduler() != pdFALSE ) - { - /* Should not reach here as if the scheduler is running the - function will not return. */ - } - else - { - /* Should only reach here if a task calls xTaskEndScheduler(). */ - } - } - else - { - /* This line will only be reached if the kernel could not be started, - because there was not enough FreeRTOS heap to create the idle task - or the timer task. */ - configASSERT( xReturn != errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ); - } + /* Setting up the timer tick is hardware specific and thus in the + * portable interface. */ + if( xPortStartScheduler() != pdFALSE ) + { + /* Should not reach here as if the scheduler is running the + * function will not return. */ + } + else + { + /* Should only reach here if a task calls xTaskEndScheduler(). */ + } + } + else + { + /* This line will only be reached if the kernel could not be started, + * because there was not enough FreeRTOS heap to create the idle task + * or the timer task. */ + configASSERT( xReturn != errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ); + } - /* Prevent compiler warnings if INCLUDE_xTaskGetIdleTaskHandle is set to 0, - meaning xIdleTaskHandle is not used anywhere else. */ - ( void ) xIdleTaskHandle[0]; + /* Prevent compiler warnings if INCLUDE_xTaskGetIdleTaskHandle is set to 0, + * meaning xIdleTaskHandle is not used anywhere else. */ + ( void ) xIdleTaskHandle[0]; } /*-----------------------------------------------------------*/ void vTaskEndScheduler( void ) { - /* Stop the scheduler interrupts and call the portable scheduler end - routine so the original ISRs can be restored if necessary. The port - layer must ensure interrupts enable bit is left in the correct state. */ - portDISABLE_INTERRUPTS(); - xSchedulerRunning = pdFALSE; - vPortEndScheduler(); + /* Stop the scheduler interrupts and call the portable scheduler end + * routine so the original ISRs can be restored if necessary. The port + * layer must ensure interrupts enable bit is left in the correct state. */ + portDISABLE_INTERRUPTS(); + xSchedulerRunning = pdFALSE; + vPortEndScheduler(); } /*----------------------------------------------------------*/ #if ( configUSE_NEWLIB_REENTRANT == 1 ) //Return global reent struct if FreeRTOS isn't running, struct _reent* __getreent(void) { - //No lock needed because if this changes, we won't be running anymore. - TCB_t *currTask=xTaskGetCurrentTaskHandle(); - if (currTask==NULL) { - //No task running. Return global struct. - return _GLOBAL_REENT; - } else { - //We have a task; return its reentrant struct. - return &currTask->xNewLib_reent; - } + //No lock needed because if this changes, we won't be running anymore. + TCB_t *currTask=xTaskGetCurrentTaskHandle(); + if (currTask==NULL) { + //No task running. Return global struct. + return _GLOBAL_REENT; + } else { + //We have a task; return its reentrant struct. + return &currTask->xNewLib_reent; + } } #endif void vTaskSuspendAll( void ) { - /* A critical section is not required as the variable is of type - BaseType_t. Please read Richard Barry's reply in the following link to a - post in the FreeRTOS support forum before reporting this as a bug! - - http://goo.gl/wu4acr */ - unsigned state; + /* A critical section is not required as the variable is of type + * BaseType_t. Please read Richard Barry's reply in the following link to a + * post in the FreeRTOS support forum before reporting this as a bug! - + * https://goo.gl/wu4acr */ + unsigned state; - state = portENTER_CRITICAL_NESTED(); - ++uxSchedulerSuspended[ xPortGetCoreID() ]; - portEXIT_CRITICAL_NESTED(state); + state = portENTER_CRITICAL_NESTED(); + ++uxSchedulerSuspended[ xPortGetCoreID() ]; + portEXIT_CRITICAL_NESTED(state); } /*----------------------------------------------------------*/ @@ -2347,1405 +2441,1444 @@ void vTaskSuspendAll( void ) #if ( portNUM_PROCESSORS > 1 ) - static BaseType_t xHaveReadyTasks( void ) - { - for (int i = tskIDLE_PRIORITY + 1; i < configMAX_PRIORITIES; ++i) - { - if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ i ] ) ) > 0 ) - { - return pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - return pdFALSE; - } + static BaseType_t xHaveReadyTasks( void ) + { + for (int i = tskIDLE_PRIORITY + 1; i < configMAX_PRIORITIES; ++i) + { + if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ i ] ) ) > 0 ) + { + return pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + return pdFALSE; + } #endif // portNUM_PROCESSORS > 1 - static TickType_t prvGetExpectedIdleTime( void ) - { - TickType_t xReturn; + static TickType_t prvGetExpectedIdleTime( void ) + { + TickType_t xReturn; - taskENTER_CRITICAL(&xTaskQueueMutex); - if( pxCurrentTCB[ xPortGetCoreID() ]->uxPriority > tskIDLE_PRIORITY ) - { - xReturn = 0; - } + taskENTER_CRITICAL(); + if( pxCurrentTCB[ xPortGetCoreID() ]->uxPriority > tskIDLE_PRIORITY ) + { + xReturn = 0; + } #if portNUM_PROCESSORS > 1 - /* This function is called from Idle task; in single core case this - * means that no higher priority tasks are ready to run, and we can - * enter sleep. In SMP case, there might be ready tasks waiting for - * the other CPU, so need to check all ready lists. - */ - else if( xHaveReadyTasks() ) - { - xReturn = 0; - } + /* This function is called from Idle task; in single core case this + * means that no higher priority tasks are ready to run, and we can + * enter sleep. In SMP case, there might be ready tasks waiting for + * the other CPU, so need to check all ready lists. + */ + else if( xHaveReadyTasks() ) + { + xReturn = 0; + } #endif // portNUM_PROCESSORS > 1 - else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > portNUM_PROCESSORS ) - { - /* There are other idle priority tasks in the ready state. If - time slicing is used then the very next tick interrupt must be - processed. */ - xReturn = 0; - } - else - { - xReturn = xNextTaskUnblockTime - xTickCount; - } - taskEXIT_CRITICAL(&xTaskQueueMutex); + else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > portNUM_PROCESSORS ) + { + /* There are other idle priority tasks in the ready state. If + * time slicing is used then the very next tick interrupt must be + * processed. */ + xReturn = 0; + } + else + { + xReturn = xNextTaskUnblockTime - xTickCount; + } + taskEXIT_CRITICAL(); - return xReturn; - } + return xReturn; + } #endif /* configUSE_TICKLESS_IDLE */ /*----------------------------------------------------------*/ BaseType_t xTaskResumeAll( void ) { -TCB_t *pxTCB = NULL; -BaseType_t xAlreadyYielded = pdFALSE; -TickType_t xTicksToNextUnblockTime; + TCB_t *pxTCB = NULL; + BaseType_t xAlreadyYielded = pdFALSE; + TickType_t xTicksToNextUnblockTime; - /* If uxSchedulerSuspended[xPortGetCoreID()] is zero then this function does not match a - previous call to taskENTER_CRITICAL( &xTaskQueueMutex ). */ - configASSERT( uxSchedulerSuspended[xPortGetCoreID()] ); + /* If uxSchedulerSuspended[xPortGetCoreID()] is zero then this function does not match a + * previous call to taskENTER_CRITICAL(). */ + configASSERT( uxSchedulerSuspended[xPortGetCoreID()] ); - /* It is possible that an ISR caused a task to be removed from an event - list while the scheduler was suspended. If this was the case then the - removed task will have been added to the xPendingReadyList. Once the - scheduler has been resumed it is safe to move all the pending ready - tasks from this list into their appropriate ready list. */ - taskENTER_CRITICAL( &xTaskQueueMutex ); - { - --uxSchedulerSuspended[xPortGetCoreID()]; + /* It is possible that an ISR caused a task to be removed from an event + * list while the scheduler was suspended. If this was the case then the + * removed task will have been added to the xPendingReadyList. Once the + * scheduler has been resumed it is safe to move all the pending ready + * tasks from this list into their appropriate ready list. */ + taskENTER_CRITICAL(); + { + --uxSchedulerSuspended[xPortGetCoreID()]; - if( uxSchedulerSuspended[xPortGetCoreID()] == ( UBaseType_t ) pdFALSE ) - { - if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U ) - { - /* Move any readied tasks from the pending list into the - appropriate ready list. */ - while( listLIST_IS_EMPTY( &xPendingReadyList[xPortGetCoreID()] ) == pdFALSE ) - { - pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList[xPortGetCoreID()] ) ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ - ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); - ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); - prvAddTaskToReadyList( pxTCB ); + if( uxSchedulerSuspended[xPortGetCoreID()] == ( UBaseType_t ) pdFALSE ) + { + if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U ) + { + /* Move any readied tasks from the pending list into the + * appropriate ready list. */ + while( listLIST_IS_EMPTY( &xPendingReadyList[xPortGetCoreID()] ) == pdFALSE ) + { + pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList[xPortGetCoreID()] ) ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ + ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); + ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); + prvAddTaskToReadyList( pxTCB ); - /* If the moved task has a priority higher than the current - task then a yield must be performed. */ - if( tskCAN_RUN_HERE(pxTCB->xCoreID) && pxTCB->uxPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) - { - xYieldPending[xPortGetCoreID()] = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } + /* If the moved task has a priority higher than the current + * task then a yield must be performed. */ + if( tskCAN_RUN_HERE(pxTCB->xCoreID) && pxTCB->uxPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) + { + xYieldPending[xPortGetCoreID()] = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } - if( pxTCB != NULL ) - { - /* A task was unblocked while the scheduler was suspended, - which may have prevented the next unblock time from being - re-calculated, in which case re-calculate it now. Mainly - important for low power tickless implementations, where - this can prevent an unnecessary exit from low power - state. */ - prvResetNextTaskUnblockTime(); - } + if( pxTCB != NULL ) + { + /* A task was unblocked while the scheduler was suspended, + * which may have prevented the next unblock time from being + * re-calculated, in which case re-calculate it now. Mainly + * important for low power tickless implementations, where + * this can prevent an unnecessary exit from low power + * state. */ + prvResetNextTaskUnblockTime(); + } - /* If any ticks occurred while the scheduler was suspended then - they should be processed now. This ensures the tick count does - not slip, and that any delayed tasks are resumed at the correct - time. */ - while( xPendedTicks > ( TickType_t ) 0 ) - { - /* Calculate how far into the future the next task will - leave the Blocked state because its timeout expired. If - there are no tasks due to leave the blocked state between - the time now and the time at which the tick count overflows - then xNextTaskUnblockTime will the tick overflow time. - This means xNextTaskUnblockTime can never be less than - xTickCount, and the following can therefore not - underflow. */ - configASSERT( xNextTaskUnblockTime >= xTickCount ); - xTicksToNextUnblockTime = xNextTaskUnblockTime - xTickCount; + /* If any ticks occurred while the scheduler was suspended then + * they should be processed now. This ensures the tick count does + * not slip, and that any delayed tasks are resumed at the correct + * time. */ + while( xPendedTicks > ( TickType_t ) 0 ) + { + /* Calculate how far into the future the next task will + * leave the Blocked state because its timeout expired. If + * there are no tasks due to leave the blocked state between + * the time now and the time at which the tick count overflows + * then xNextTaskUnblockTime will the tick overflow time. + * This means xNextTaskUnblockTime can never be less than + * xTickCount, and the following can therefore not + * underflow. */ + configASSERT( xNextTaskUnblockTime >= xTickCount ); + xTicksToNextUnblockTime = xNextTaskUnblockTime - xTickCount; - /* Don't want to move the tick count more than the number - of ticks that are pending, so cap if necessary. */ - if( xTicksToNextUnblockTime > xPendedTicks ) - { - xTicksToNextUnblockTime = xPendedTicks; - } + /* Don't want to move the tick count more than the number + of ticks that are pending, so cap if necessary. */ + if( xTicksToNextUnblockTime > xPendedTicks ) + { + xTicksToNextUnblockTime = xPendedTicks; + } - if( xTicksToNextUnblockTime == 0 ) - { - /* xTicksToNextUnblockTime could be zero if the tick - count is about to overflow and xTicksToNetUnblockTime - holds the time at which the tick count will overflow - (rather than the time at which the next task will - unblock). Set to 1 otherwise xPendedTicks won't be - decremented below. */ - xTicksToNextUnblockTime = ( TickType_t ) 1; - } - else if( xTicksToNextUnblockTime > ( TickType_t ) 1) - { - /* Move the tick count one short of the next unblock - time, then call xTaskIncrementTick() to move the tick - count up to the next unblock time to unblock the task, - if any. This will also swap the blocked task and - overflow blocked task lists if necessary. */ - xTickCount += ( xTicksToNextUnblockTime - ( TickType_t ) 1 ); - } - xYieldPending[xPortGetCoreID()] |= xTaskIncrementTick(); + if( xTicksToNextUnblockTime == 0 ) + { + /* xTicksToNextUnblockTime could be zero if the tick + * count is about to overflow and xTicksToNetUnblockTime + * holds the time at which the tick count will overflow + * (rather than the time at which the next task will + * unblock). Set to 1 otherwise xPendedTicks won't be + * decremented below. */ + xTicksToNextUnblockTime = ( TickType_t ) 1; + } + else if( xTicksToNextUnblockTime > ( TickType_t ) 1) + { + /* Move the tick count one short of the next unblock + * time, then call xTaskIncrementTick() to move the tick + * count up to the next unblock time to unblock the task, + * if any. This will also swap the blocked task and + * overflow blocked task lists if necessary. */ + xTickCount += ( xTicksToNextUnblockTime - ( TickType_t ) 1 ); + } + xYieldPending[xPortGetCoreID()] |= xTaskIncrementTick(); - /* Adjust for the number of ticks just added to - xTickCount and go around the loop again if - xTicksToCatchUp is still greater than 0. */ - xPendedTicks -= xTicksToNextUnblockTime; - } + /* Adjust for the number of ticks just added to + xTickCount and go around the loop again if + xTicksToCatchUp is still greater than 0. */ + xPendedTicks -= xTicksToNextUnblockTime; + } - if( xYieldPending[xPortGetCoreID()] != pdFALSE ) - { - #if( configUSE_PREEMPTION != 0 ) - { - xAlreadyYielded = pdTRUE; - } - #endif - taskYIELD_IF_USING_PREEMPTION(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + if( xYieldPending[xPortGetCoreID()] != pdFALSE ) + { + #if ( configUSE_PREEMPTION != 0 ) + { + xAlreadyYielded = pdTRUE; + } + #endif + taskYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(); - return xAlreadyYielded; + return xAlreadyYielded; } /*-----------------------------------------------------------*/ TickType_t xTaskGetTickCount( void ) { -TickType_t xTicks; + TickType_t xTicks; - xTicks = xTickCount; + xTicks = xTickCount; - return xTicks; + return xTicks; } /*-----------------------------------------------------------*/ TickType_t xTaskGetTickCountFromISR( void ) { -TickType_t xReturn; -UBaseType_t uxSavedInterruptStatus; + TickType_t xReturn; + UBaseType_t uxSavedInterruptStatus; - /* RTOS ports that support interrupt nesting have the concept of a maximum - system call (or maximum API call) interrupt priority. Interrupts that are - above the maximum system call priority are kept permanently enabled, even - when the RTOS kernel is in a critical section, but cannot make any calls to - FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h - then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion - failure if a FreeRTOS API function is called from an interrupt that has been - assigned a priority above the configured maximum system call priority. - Only FreeRTOS functions that end in FromISR can be called from interrupts - that have been assigned a priority at or (logically) below the maximum - system call interrupt priority. FreeRTOS maintains a separate interrupt - safe API to ensure interrupt entry is as fast and as simple as possible. - More information (albeit Cortex-M specific) is provided on the following - link: https://www.freertos.org/RTOS-Cortex-M3-M4.html */ - portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + /* RTOS ports that support interrupt nesting have the concept of a maximum + * system call (or maximum API call) interrupt priority. Interrupts that are + * above the maximum system call priority are kept permanently enabled, even + * when the RTOS kernel is in a critical section, but cannot make any calls to + * FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h + * then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + * failure if a FreeRTOS API function is called from an interrupt that has been + * assigned a priority above the configured maximum system call priority. + * Only FreeRTOS functions that end in FromISR can be called from interrupts + * that have been assigned a priority at or (logically) below the maximum + * system call interrupt priority. FreeRTOS maintains a separate interrupt + * safe API to ensure interrupt entry is as fast and as simple as possible. + * More information (albeit Cortex-M specific) is provided on the following + * link: https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); - uxSavedInterruptStatus = portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR(); - { - xReturn = xTickCount; - } - portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + uxSavedInterruptStatus = portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR(); + { + xReturn = xTickCount; + } + portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); - return xReturn; + return xReturn; } /*-----------------------------------------------------------*/ UBaseType_t uxTaskGetNumberOfTasks( void ) { - /* A critical section is not required because the variables are of type - BaseType_t. */ - return uxCurrentNumberOfTasks; + /* A critical section is not required because the variables are of type + * BaseType_t. */ + return uxCurrentNumberOfTasks; } /*-----------------------------------------------------------*/ -char *pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ { -TCB_t *pxTCB; + TCB_t * pxTCB; - /* If null is passed in here then the name of the calling task is being - queried. */ - pxTCB = prvGetTCBFromHandle( xTaskToQuery ); - configASSERT( pxTCB ); - return &( pxTCB->pcTaskName[ 0 ] ); + /* If null is passed in here then the name of the calling task is being + * queried. */ + pxTCB = prvGetTCBFromHandle( xTaskToQuery ); + configASSERT( pxTCB ); + return &( pxTCB->pcTaskName[ 0 ] ); } /*-----------------------------------------------------------*/ #if ( INCLUDE_xTaskGetHandle == 1 ) - static TCB_t *prvSearchForNameWithinSingleList( List_t *pxList, const char pcNameToQuery[] ) - { - TCB_t *pxNextTCB, *pxFirstTCB, *pxReturn = NULL; - UBaseType_t x; - char cNextChar; - BaseType_t xBreakLoop; + static TCB_t * prvSearchForNameWithinSingleList( List_t * pxList, + const char pcNameToQuery[] ) + { + TCB_t * pxNextTCB, * pxFirstTCB, * pxReturn = NULL; + UBaseType_t x; + char cNextChar; + BaseType_t xBreakLoop; - /* This function is called with the scheduler suspended. */ + /* This function is called with the scheduler suspended. */ - if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 ) - { - listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ + if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 ) + { + listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ - do - { - listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ + do + { + listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ - /* Check each character in the name looking for a match or - mismatch. */ - xBreakLoop = pdFALSE; - for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ ) - { - cNextChar = pxNextTCB->pcTaskName[ x ]; + /* Check each character in the name looking for a match or + * mismatch. */ + xBreakLoop = pdFALSE; - if( cNextChar != pcNameToQuery[ x ] ) - { - /* Characters didn't match. */ - xBreakLoop = pdTRUE; - } - else if( cNextChar == ( char ) 0x00 ) - { - /* Both strings terminated, a match must have been - found. */ - pxReturn = pxNextTCB; - xBreakLoop = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ ) + { + cNextChar = pxNextTCB->pcTaskName[ x ]; - if( xBreakLoop != pdFALSE ) - { - break; - } - } + if( cNextChar != pcNameToQuery[ x ] ) + { + /* Characters didn't match. */ + xBreakLoop = pdTRUE; + } + else if( cNextChar == ( char ) 0x00 ) + { + /* Both strings terminated, a match must have been + * found. */ + pxReturn = pxNextTCB; + xBreakLoop = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - if( pxReturn != NULL ) - { - /* The handle has been found. */ - break; - } + if( xBreakLoop != pdFALSE ) + { + break; + } + } - } while( pxNextTCB != pxFirstTCB ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + if( pxReturn != NULL ) + { + /* The handle has been found. */ + break; + } + } while( pxNextTCB != pxFirstTCB ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - return pxReturn; - } + return pxReturn; + } #endif /* INCLUDE_xTaskGetHandle */ /*-----------------------------------------------------------*/ #if ( INCLUDE_xTaskGetHandle == 1 ) - TaskHandle_t xTaskGetHandle( const char *pcNameToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ - { - UBaseType_t uxQueue = configMAX_PRIORITIES; - TCB_t* pxTCB; + TaskHandle_t xTaskGetHandle( const char * pcNameToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + { + UBaseType_t uxQueue = configMAX_PRIORITIES; + TCB_t * pxTCB; - /* Task names will be truncated to configMAX_TASK_NAME_LEN - 1 bytes. */ - configASSERT( strlen( pcNameToQuery ) < configMAX_TASK_NAME_LEN ); + /* Task names will be truncated to configMAX_TASK_NAME_LEN - 1 bytes. */ + configASSERT( strlen( pcNameToQuery ) < configMAX_TASK_NAME_LEN ); - taskENTER_CRITICAL( &xTaskQueueMutex ); - { - /* Search the ready lists. */ - do - { - uxQueue--; - pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) &( pxReadyTasksLists[ uxQueue ] ), pcNameToQuery ); +#ifdef ESP_PLATFORM // IDF-3755 + taskENTER_CRITICAL(); +#else + vTaskSuspendAll(); +#endif // ESP_PLATFORM + { + /* Search the ready lists. */ + do + { + uxQueue--; + pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) &( pxReadyTasksLists[ uxQueue ] ), pcNameToQuery ); - if( pxTCB != NULL ) - { - /* Found the handle. */ - break; - } + if( pxTCB != NULL ) + { + /* Found the handle. */ + break; + } + } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ - } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + /* Search the delayed lists. */ + if( pxTCB == NULL ) + { + pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxDelayedTaskList, pcNameToQuery ); + } - /* Search the delayed lists. */ - if( pxTCB == NULL ) - { - pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxDelayedTaskList, pcNameToQuery ); - } + if( pxTCB == NULL ) + { + pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxOverflowDelayedTaskList, pcNameToQuery ); + } - if( pxTCB == NULL ) - { - pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxOverflowDelayedTaskList, pcNameToQuery ); - } + #if ( INCLUDE_vTaskSuspend == 1 ) + { + if( pxTCB == NULL ) + { + /* Search the suspended list. */ + pxTCB = prvSearchForNameWithinSingleList( &xSuspendedTaskList, pcNameToQuery ); + } + } + #endif - #if ( INCLUDE_vTaskSuspend == 1 ) - { - if( pxTCB == NULL ) - { - /* Search the suspended list. */ - pxTCB = prvSearchForNameWithinSingleList( &xSuspendedTaskList, pcNameToQuery ); - } - } - #endif + #if ( INCLUDE_vTaskDelete == 1 ) + { + if( pxTCB == NULL ) + { + /* Search the deleted list. */ + pxTCB = prvSearchForNameWithinSingleList( &xTasksWaitingTermination, pcNameToQuery ); + } + } + #endif + } +#ifdef ESP_PLATFORM // IDF-3755 + taskEXIT_CRITICAL(); +#else + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM - #if( INCLUDE_vTaskDelete == 1 ) - { - if( pxTCB == NULL ) - { - /* Search the deleted list. */ - pxTCB = prvSearchForNameWithinSingleList( &xTasksWaitingTermination, pcNameToQuery ); - } - } - #endif - } - taskEXIT_CRITICAL( &xTaskQueueMutex ); - - return pxTCB; - } + return pxTCB; + } #endif /* INCLUDE_xTaskGetHandle */ /*-----------------------------------------------------------*/ #if ( configUSE_TRACE_FACILITY == 1 ) - UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime ) - { - UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES; + UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, + const UBaseType_t uxArraySize, + uint32_t * const pulTotalRunTime ) + { + UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES; - taskENTER_CRITICAL( &xTaskQueueMutex ); - { - /* Is there a space in the array for each task in the system? */ - if( uxArraySize >= uxCurrentNumberOfTasks ) - { - /* Fill in an TaskStatus_t structure with information on each - task in the Ready state. */ - do - { - uxQueue--; - uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady ); +#ifdef ESP_PLATFORM // IDF-3755 + taskENTER_CRITICAL(); +#else + vTaskSuspendAll(); +#endif // ESP_PLATFORM + { + /* Is there a space in the array for each task in the system? */ + if( uxArraySize >= uxCurrentNumberOfTasks ) + { + /* Fill in an TaskStatus_t structure with information on each + * task in the Ready state. */ + do + { + uxQueue--; + uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady ); + } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ - } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + /* Fill in an TaskStatus_t structure with information on each + * task in the Blocked state. */ + uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked ); + uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked ); - /* Fill in an TaskStatus_t structure with information on each - task in the Blocked state. */ - uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked ); - uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked ); + #if ( INCLUDE_vTaskDelete == 1 ) + { + /* Fill in an TaskStatus_t structure with information on + * each task that has been deleted but not yet cleaned up. */ + uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted ); + } + #endif - #if( INCLUDE_vTaskDelete == 1 ) - { - /* Fill in an TaskStatus_t structure with information on - each task that has been deleted but not yet cleaned up. */ - uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted ); - } - #endif + #if ( INCLUDE_vTaskSuspend == 1 ) + { + /* Fill in an TaskStatus_t structure with information on + * each task in the Suspended state. */ + uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended ); + } + #endif - #if ( INCLUDE_vTaskSuspend == 1 ) - { - /* Fill in an TaskStatus_t structure with information on - each task in the Suspended state. */ - uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended ); - } - #endif + #if ( configGENERATE_RUN_TIME_STATS == 1 ) + { + if( pulTotalRunTime != NULL ) + { + #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE + portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) ); + #else + *pulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE(); + #endif + } + } + #else /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */ + { + if( pulTotalRunTime != NULL ) + { + *pulTotalRunTime = 0; + } + } + #endif /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */ + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } +#ifdef ESP_PLATFORM // IDF-3755 + taskEXIT_CRITICAL(); +#else + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM - #if ( configGENERATE_RUN_TIME_STATS == 1) - { - if( pulTotalRunTime != NULL ) - { - #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE - portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) ); - #else - *pulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE(); - #endif - } - } - #else - { - if( pulTotalRunTime != NULL ) - { - *pulTotalRunTime = 0; - } - } - #endif - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - taskEXIT_CRITICAL( &xTaskQueueMutex ); - - return uxTask; - } + return uxTask; + } #endif /* configUSE_TRACE_FACILITY */ /*----------------------------------------------------------*/ #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) - TaskHandle_t xTaskGetIdleTaskHandle( void ) - { - /* If xTaskGetIdleTaskHandle() is called before the scheduler has been - started, then xIdleTaskHandle will be NULL. */ - configASSERT( ( xIdleTaskHandle[xPortGetCoreID()] != NULL ) ); - return xIdleTaskHandle[xPortGetCoreID()]; - } + TaskHandle_t xTaskGetIdleTaskHandle( void ) + { + /* If xTaskGetIdleTaskHandle() is called before the scheduler has been + * started, then xIdleTaskHandle will be NULL. */ + configASSERT( ( xIdleTaskHandle[xPortGetCoreID()] != NULL ) ); + return xIdleTaskHandle[xPortGetCoreID()]; + } - TaskHandle_t xTaskGetIdleTaskHandleForCPU( UBaseType_t cpuid ) - { - configASSERT( cpuid < portNUM_PROCESSORS ); - configASSERT( ( xIdleTaskHandle[cpuid] != NULL ) ); - return xIdleTaskHandle[cpuid]; - } + TaskHandle_t xTaskGetIdleTaskHandleForCPU( UBaseType_t cpuid ) + { + configASSERT( cpuid < portNUM_PROCESSORS ); + configASSERT( ( xIdleTaskHandle[cpuid] != NULL ) ); + return xIdleTaskHandle[cpuid]; + } #endif /* INCLUDE_xTaskGetIdleTaskHandle */ /*----------------------------------------------------------*/ /* This conditional compilation should use inequality to 0, not equality to 1. -This is to ensure vTaskStepTick() is available when user defined low power mode -implementations require configUSE_TICKLESS_IDLE to be set to a value other than -1. */ + * This is to ensure vTaskStepTick() is available when user defined low power mode + * implementations require configUSE_TICKLESS_IDLE to be set to a value other than + * 1. */ #if ( configUSE_TICKLESS_IDLE != 0 ) - void vTaskStepTick( const TickType_t xTicksToJump ) - { - /* Correct the tick count value after a period during which the tick - was suppressed. Note this does *not* call the tick hook function for - each stepped tick. */ - taskENTER_CRITICAL(&xTaskQueueMutex); - configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime ); - xTickCount += xTicksToJump; - traceINCREASE_TICK_COUNT( xTicksToJump ); - taskEXIT_CRITICAL(&xTaskQueueMutex); - } + void vTaskStepTick( const TickType_t xTicksToJump ) + { + /* Correct the tick count value after a period during which the tick + * was suppressed. Note this does *not* call the tick hook function for + * each stepped tick. */ + taskENTER_CRITICAL(); + configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime ); + xTickCount += xTicksToJump; + traceINCREASE_TICK_COUNT( xTicksToJump ); + taskEXIT_CRITICAL(); + } #endif /* configUSE_TICKLESS_IDLE */ /*----------------------------------------------------------*/ BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) { -BaseType_t xYieldRequired = pdFALSE; +#ifdef ESP_PLATFORM + BaseType_t xYieldRequired = pdFALSE; +#else + BaseType_t xYieldOccurred; +#endif // ESP_PLATFORM - /* Must not be called with the scheduler suspended as the implementation - relies on xPendedTicks being wound down to 0 in xTaskResumeAll(). */ - configASSERT( uxSchedulerSuspended[xPortGetCoreID()] == 0 ); + /* Must not be called with the scheduler suspended as the implementation + * relies on xPendedTicks being wound down to 0 in xTaskResumeAll(). */ + configASSERT( uxSchedulerSuspended[xPortGetCoreID()] == 0 ); - /* Use xPendedTicks to mimic xTicksToCatchUp number of ticks occuring when - the scheduler is suspended so the ticks are executed in xTaskResumeAll(). */ - taskENTER_CRITICAL( &xTaskQueueMutex ); - xPendedTicks += xTicksToCatchUp; - taskEXIT_CRITICAL( &xTaskQueueMutex ); + /* Use xPendedTicks to mimic xTicksToCatchUp number of ticks occuring when + * the scheduler is suspended so the ticks are executed in xTaskResumeAll(). */ +#ifdef ESP_PLATFORM // IDF-3755 + taskENTER_CRITICAL(); +#else + vTaskSuspendAll(); +#endif // ESP_PLATFORM + xPendedTicks += xTicksToCatchUp; +#ifdef ESP_PLATFORM // IDF-3755 + taskEXIT_CRITICAL(); + return xYieldRequired; +#else + xYieldOccurred = xTaskResumeAll(); - return xYieldRequired; + return xYieldOccurred; +#endif // ESP_PLATFORM } /*----------------------------------------------------------*/ #if ( INCLUDE_xTaskAbortDelay == 1 ) - BaseType_t xTaskAbortDelay( TaskHandle_t xTask ) - { - TCB_t *pxTCB = xTask; - BaseType_t xReturn; + BaseType_t xTaskAbortDelay( TaskHandle_t xTask ) + { + TCB_t * pxTCB = xTask; + BaseType_t xReturn; - configASSERT( pxTCB ); + configASSERT( pxTCB ); - taskENTER_CRITICAL( &xTaskQueueMutex ); - { - /* A task can only be prematurely removed from the Blocked state if - it is actually in the Blocked state. */ - if( eTaskGetState( xTask ) == eBlocked ) - { - xReturn = pdPASS; +#ifdef ESP_PLATFORM // IDF-3755 + taskENTER_CRITICAL(); +#else + vTaskSuspendAll(); +#endif // ESP_PLATFORM + { + /* A task can only be prematurely removed from the Blocked state if + * it is actually in the Blocked state. */ + if( eTaskGetState( xTask ) == eBlocked ) + { + xReturn = pdPASS; - /* Remove the reference to the task from the blocked list. An - interrupt won't touch the xStateListItem because the - scheduler is suspended. */ - ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); + /* Remove the reference to the task from the blocked list. An + * interrupt won't touch the xStateListItem because the + * scheduler is suspended. */ + ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); - /* Is the task waiting on an event also? If so remove it from - the event list too. Interrupts can touch the event list item, - even though the scheduler is suspended, so a critical section - is used. */ - taskENTER_CRITICAL( &xTaskQueueMutex ); - { - if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) - { - ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); - pxTCB->ucDelayAborted = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + /* Is the task waiting on an event also? If so remove it from + * the event list too. Interrupts can touch the event list item, + * even though the scheduler is suspended, so a critical section + * is used. */ + taskENTER_CRITICAL(); + { + if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) + { + ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); - /* Place the unblocked task into the appropriate ready list. */ - prvAddTaskToReadyList( pxTCB ); + /* This lets the task know it was forcibly removed from the + * blocked state so it should not re-evaluate its block time and + * then block again. */ + pxTCB->ucDelayAborted = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(); - /* A task being unblocked cannot cause an immediate context - switch if preemption is turned off. */ - #if ( configUSE_PREEMPTION == 1 ) - { - /* Preemption is on, but a context switch should only be - performed if the unblocked task has a priority that is - equal to or higher than the currently executing task. */ - if( tskCAN_RUN_HERE(pxTCB->xCoreID) && pxTCB->uxPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) - { - /* Pend the yield to be performed when the scheduler - is unsuspended. */ - xYieldPending[xPortGetCoreID()] = pdTRUE; - } - else if ( pxTCB->xCoreID != xPortGetCoreID() ) - { - taskYIELD_OTHER_CORE( pxTCB->xCoreID, pxTCB->uxPriority); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - #endif /* configUSE_PREEMPTION */ - } - else - { - xReturn = pdFAIL; - } - } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + /* Place the unblocked task into the appropriate ready list. */ + prvAddTaskToReadyList( pxTCB ); - return xReturn; - } + /* A task being unblocked cannot cause an immediate context + * switch if preemption is turned off. */ + #if ( configUSE_PREEMPTION == 1 ) + { + /* Preemption is on, but a context switch should only be + * performed if the unblocked task has a priority that is + * equal to or higher than the currently executing task. */ + if( tskCAN_RUN_HERE(pxTCB->xCoreID) && pxTCB->uxPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) + { + /* Pend the yield to be performed when the scheduler + * is unsuspended. */ + xYieldPending[xPortGetCoreID()] = pdTRUE; + } + else if ( pxTCB->xCoreID != xPortGetCoreID() ) + { + taskYIELD_OTHER_CORE( pxTCB->xCoreID, pxTCB->uxPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_PREEMPTION */ + } + else + { + xReturn = pdFAIL; + } + } +#ifdef ESP_PLATFORM // IDF-3755 + taskEXIT_CRITICAL(); +#else + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM + + return xReturn; + } #endif /* INCLUDE_xTaskAbortDelay */ /*----------------------------------------------------------*/ BaseType_t xTaskIncrementTick( void ) { -TCB_t * pxTCB; -TickType_t xItemValue; -BaseType_t xSwitchRequired = pdFALSE; + TCB_t * pxTCB; + TickType_t xItemValue; + BaseType_t xSwitchRequired = pdFALSE; - /* Only allow core 0 increase the tick count in the case of xPortSysTickHandler processing. */ - /* And allow core 0 and core 1 to unwind uxPendedTicks during xTaskResumeAll. */ + /* Only allow core 0 increase the tick count in the case of xPortSysTickHandler processing. */ + /* And allow core 0 and core 1 to unwind uxPendedTicks during xTaskResumeAll. */ - if (xPortInIsrContext()) - { - #if ( configUSE_TICK_HOOK == 1 ) - vApplicationTickHook(); - #endif /* configUSE_TICK_HOOK */ - #if ( CONFIG_FREERTOS_LEGACY_HOOKS == 1 ) - esp_vApplicationTickHook(); - #endif /* CONFIG_FREERTOS_LEGACY_HOOKS */ + if (xPortInIsrContext()) + { + #if ( configUSE_TICK_HOOK == 1 ) + vApplicationTickHook(); + #endif /* configUSE_TICK_HOOK */ + #if ( CONFIG_FREERTOS_LEGACY_HOOKS == 1 ) + esp_vApplicationTickHook(); + #endif /* CONFIG_FREERTOS_LEGACY_HOOKS */ - if (xPortGetCoreID() != 0 ) - { - return pdTRUE; - } - } + if (xPortGetCoreID() != 0 ) + { + return pdTRUE; + } + } - /* Called by the portable layer each time a tick interrupt occurs. - Increments the tick then checks to see if the new tick value will cause any - tasks to be unblocked. */ - traceTASK_INCREMENT_TICK( xTickCount ); - if( uxSchedulerSuspended[xPortGetCoreID()] == ( UBaseType_t ) pdFALSE ) - { - taskENTER_CRITICAL_ISR( &xTaskQueueMutex ); - /* Minor optimisation. The tick count cannot change in this - block. */ - const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1; + /* Called by the portable layer each time a tick interrupt occurs. + * Increments the tick then checks to see if the new tick value will cause any + * tasks to be unblocked. */ + traceTASK_INCREMENT_TICK( xTickCount ); - /* Increment the RTOS tick, switching the delayed and overflowed - delayed lists if it wraps to 0. */ - xTickCount = xConstTickCount; + if( uxSchedulerSuspended[xPortGetCoreID()] == ( UBaseType_t ) pdFALSE ) + { + taskENTER_CRITICAL_ISR(); + /* Minor optimisation. The tick count cannot change in this + * block. */ + const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1; - if( xConstTickCount == ( TickType_t ) 0U ) /*lint !e774 'if' does not always evaluate to false as it is looking for an overflow. */ - { - taskSWITCH_DELAYED_LISTS(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* Increment the RTOS tick, switching the delayed and overflowed + * delayed lists if it wraps to 0. */ + xTickCount = xConstTickCount; - /* See if this tick has made a timeout expire. Tasks are stored in - the queue in the order of their wake time - meaning once one task - has been found whose block time has not expired there is no need to - look any further down the list. */ - if( xConstTickCount >= xNextTaskUnblockTime ) - { - for( ;; ) - { - if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) - { - /* The delayed list is empty. Set xNextTaskUnblockTime - to the maximum possible value so it is extremely - unlikely that the - if( xTickCount >= xNextTaskUnblockTime ) test will pass - next time through. */ - xNextTaskUnblockTime = portMAX_DELAY; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ - break; - } - else - { - /* The delayed list is not empty, get the value of the - item at the head of the delayed list. This is the time - at which the task at the head of the delayed list must - be removed from the Blocked state. */ - pxTCB = listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ - xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xStateListItem ) ); + if( xConstTickCount == ( TickType_t ) 0U ) /*lint !e774 'if' does not always evaluate to false as it is looking for an overflow. */ + { + taskSWITCH_DELAYED_LISTS(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - if( xConstTickCount < xItemValue ) - { - /* It is not time to unblock this item yet, but the - item value is the time at which the task at the head - of the blocked list must be removed from the Blocked - state - so record the item value in - xNextTaskUnblockTime. */ - xNextTaskUnblockTime = xItemValue; - break; /*lint !e9011 Code structure here is deedmed easier to understand with multiple breaks. */ - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* See if this tick has made a timeout expire. Tasks are stored in + * the queue in the order of their wake time - meaning once one task + * has been found whose block time has not expired there is no need to + * look any further down the list. */ + if( xConstTickCount >= xNextTaskUnblockTime ) + { + for( ; ; ) + { + if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) + { + /* The delayed list is empty. Set xNextTaskUnblockTime + * to the maximum possible value so it is extremely + * unlikely that the + * if( xTickCount >= xNextTaskUnblockTime ) test will pass + * next time through. */ + xNextTaskUnblockTime = portMAX_DELAY; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + break; + } + else + { + /* The delayed list is not empty, get the value of the + * item at the head of the delayed list. This is the time + * at which the task at the head of the delayed list must + * be removed from the Blocked state. */ + pxTCB = listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ + xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xStateListItem ) ); - /* It is time to remove the item from the Blocked state. */ - ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); + if( xConstTickCount < xItemValue ) + { + /* It is not time to unblock this item yet, but the + * item value is the time at which the task at the head + * of the blocked list must be removed from the Blocked + * state - so record the item value in + * xNextTaskUnblockTime. */ + xNextTaskUnblockTime = xItemValue; + break; /*lint !e9011 Code structure here is deemed easier to understand with multiple breaks. */ + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - /* Is the task waiting on an event also? If so remove - it from the event list. */ - if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) - { - ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* It is time to remove the item from the Blocked state. */ + ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); - /* Place the unblocked task into the appropriate ready - list. */ - prvAddTaskToReadyList( pxTCB ); + /* Is the task waiting on an event also? If so remove + * it from the event list. */ + if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) + { + ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - /* A task being unblocked cannot cause an immediate - context switch if preemption is turned off. */ - #if ( configUSE_PREEMPTION == 1 ) - { - /* Preemption is on, but a context switch should - only be performed if the unblocked task has a - priority that is equal to or higher than the - currently executing task. */ - if( pxTCB->uxPriority >= pxCurrentTCB[xPortGetCoreID()]->uxPriority ) - { - xSwitchRequired = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - #endif /* configUSE_PREEMPTION */ - } - } - } + /* Place the unblocked task into the appropriate ready + * list. */ + prvAddTaskToReadyList( pxTCB ); - /* Tasks of equal priority to the currently running task will share - processing time (time slice) if preemption is on, and the application - writer has not explicitly turned time slicing off. */ - #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) - { - if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB[xPortGetCoreID()]->uxPriority ] ) ) > ( UBaseType_t ) 1 ) - { - xSwitchRequired = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */ - taskEXIT_CRITICAL_ISR(&xTaskQueueMutex); - } - else - { - ++xPendedTicks; - } + /* A task being unblocked cannot cause an immediate + * context switch if preemption is turned off. */ + #if ( configUSE_PREEMPTION == 1 ) + { + /* Preemption is on, but a context switch should + * only be performed if the unblocked task has a + * priority that is equal to or higher than the + * currently executing task. */ + if( pxTCB->uxPriority >= pxCurrentTCB[xPortGetCoreID()]->uxPriority ) + { + xSwitchRequired = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_PREEMPTION */ + } + } + } - #if ( configUSE_PREEMPTION == 1 ) - { - if( xYieldPending[xPortGetCoreID()] != pdFALSE ) - { - xSwitchRequired = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - #endif /* configUSE_PREEMPTION */ + /* Tasks of equal priority to the currently running task will share + * processing time (time slice) if preemption is on, and the application + * writer has not explicitly turned time slicing off. */ + #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) + { + if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB[xPortGetCoreID()]->uxPriority ] ) ) > ( UBaseType_t ) 1 ) + { + xSwitchRequired = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */ + taskEXIT_CRITICAL_ISR(); + } + else + { + ++xPendedTicks; + } - return xSwitchRequired; + #if ( configUSE_PREEMPTION == 1 ) + { + if( xYieldPending[xPortGetCoreID()] != pdFALSE ) + { + xSwitchRequired = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_PREEMPTION */ + + return xSwitchRequired; } /*-----------------------------------------------------------*/ #if ( configUSE_APPLICATION_TASK_TAG == 1 ) - void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction ) - { - TCB_t *xTCB; + void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction ) + { + TCB_t * xTCB; - /* If xTask is NULL then it is the task hook of the calling task that is - getting set. */ - if( xTask == NULL ) - { - xTCB = ( TCB_t * ) pxCurrentTCB[xPortGetCoreID()]; - } - else - { - xTCB = xTask; - } + /* If xTask is NULL then it is the task hook of the calling task that is + * getting set. */ + if( xTask == NULL ) + { + xTCB = ( TCB_t * ) pxCurrentTCB[xPortGetCoreID()]; + } + else + { + xTCB = xTask; + } - /* Save the hook function in the TCB. A critical section is required as - the value can be accessed from an interrupt. */ - taskENTER_CRITICAL( &xTaskQueueMutex ); - { - xTCB->pxTaskTag = pxHookFunction; - } - taskEXIT_CRITICAL( &xTaskQueueMutex ); - } + /* Save the hook function in the TCB. A critical section is required as + * the value can be accessed from an interrupt. */ + taskENTER_CRITICAL(); + { + xTCB->pxTaskTag = pxHookFunction; + } + taskEXIT_CRITICAL(); + } #endif /* configUSE_APPLICATION_TASK_TAG */ /*-----------------------------------------------------------*/ #if ( configUSE_APPLICATION_TASK_TAG == 1 ) - TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask ) - { - TCB_t *pxTCB; - TaskHookFunction_t xReturn; + TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask ) + { + TCB_t * pxTCB; + TaskHookFunction_t xReturn; - /* If xTask is NULL then set the calling task's hook. */ - pxTCB = prvGetTCBFromHandle( xTask ); + /* If xTask is NULL then set the calling task's hook. */ + pxTCB = prvGetTCBFromHandle( xTask ); - /* Save the hook function in the TCB. A critical section is required as - the value can be accessed from an interrupt. */ - taskENTER_CRITICAL( &xTaskQueueMutex ); - { - xReturn = pxTCB->pxTaskTag; - } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + /* Save the hook function in the TCB. A critical section is required as + * the value can be accessed from an interrupt. */ + taskENTER_CRITICAL(); + { + xReturn = pxTCB->pxTaskTag; + } + taskEXIT_CRITICAL(); - return xReturn; - } + return xReturn; + } #endif /* configUSE_APPLICATION_TASK_TAG */ /*-----------------------------------------------------------*/ #if ( configUSE_APPLICATION_TASK_TAG == 1 ) - TaskHookFunction_t xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask ) - { - TCB_t *pxTCB; - TaskHookFunction_t xReturn; - UBaseType_t uxSavedInterruptStatus; + TaskHookFunction_t xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask ) + { + TCB_t * pxTCB; + TaskHookFunction_t xReturn; + UBaseType_t uxSavedInterruptStatus; - /* If xTask is NULL then set the calling task's hook. */ - pxTCB = prvGetTCBFromHandle( xTask ); + /* If xTask is NULL then set the calling task's hook. */ + pxTCB = prvGetTCBFromHandle( xTask ); - /* Save the hook function in the TCB. A critical section is required as - the value can be accessed from an interrupt. */ - portENTER_CRITICAL_ISR(&xTaskQueueMutex); - { - xReturn = pxTCB->pxTaskTag; - } - portEXIT_CRITICAL_ISR(&xTaskQueueMutex); + /* Save the hook function in the TCB. A critical section is required as + * the value can be accessed from an interrupt. */ + portENTER_CRITICAL_ISR(&xTaskQueueMutex); + { + xReturn = pxTCB->pxTaskTag; + } + portEXIT_CRITICAL_ISR(&xTaskQueueMutex); - return xReturn; - } + return xReturn; + } #endif /* configUSE_APPLICATION_TASK_TAG */ /*-----------------------------------------------------------*/ #if ( configUSE_APPLICATION_TASK_TAG == 1 ) - BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter ) - { - TCB_t *xTCB; - BaseType_t xReturn; + BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, + void * pvParameter ) + { + TCB_t * xTCB; + BaseType_t xReturn; - /* If xTask is NULL then we are calling our own task hook. */ - if( xTask == NULL ) - { - xTCB = xTaskGetCurrentTaskHandle(); - } - else - { - xTCB = xTask; - } + /* If xTask is NULL then we are calling our own task hook. */ + if( xTask == NULL ) + { + xTCB = xTaskGetCurrentTaskHandle(); + } + else + { + xTCB = xTask; + } - if( xTCB->pxTaskTag != NULL ) - { - xReturn = xTCB->pxTaskTag( pvParameter ); - } - else - { - xReturn = pdFAIL; - } + if( xTCB->pxTaskTag != NULL ) + { + xReturn = xTCB->pxTaskTag( pvParameter ); + } + else + { + xReturn = pdFAIL; + } - return xReturn; - } + return xReturn; + } #endif /* configUSE_APPLICATION_TASK_TAG */ /*-----------------------------------------------------------*/ void vTaskSwitchContext( void ) { - //Theoretically, this is only called from either the tick interrupt or the crosscore interrupt, so disabling - //interrupts shouldn't be necessary anymore. Still, for safety we'll leave it in for now. - int irqstate=portENTER_CRITICAL_NESTED(); + //Theoretically, this is only called from either the tick interrupt or the crosscore interrupt, so disabling + //interrupts shouldn't be necessary anymore. Still, for safety we'll leave it in for now. + int irqstate=portENTER_CRITICAL_NESTED(); - if( uxSchedulerSuspended[ xPortGetCoreID() ] != ( UBaseType_t ) pdFALSE ) - { - /* The scheduler is currently suspended - do not allow a context - switch. */ - xYieldPending[ xPortGetCoreID() ] = pdTRUE; - } - else - { - xYieldPending[ xPortGetCoreID() ] = pdFALSE; + if( uxSchedulerSuspended[ xPortGetCoreID() ] != ( UBaseType_t ) pdFALSE ) + { + /* The scheduler is currently suspended - do not allow a context + * switch. */ + xYieldPending[ xPortGetCoreID() ] = pdTRUE; + } + else + { + xYieldPending[ xPortGetCoreID() ] = pdFALSE; xSwitchingContext[ xPortGetCoreID() ] = pdTRUE; - traceTASK_SWITCHED_OUT(); + traceTASK_SWITCHED_OUT(); - #if ( configGENERATE_RUN_TIME_STATS == 1 ) - { - #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE - portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime ); - #else - ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE(); - #endif + #if ( configGENERATE_RUN_TIME_STATS == 1 ) + { + #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE + portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime ); + #else + ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE(); + #endif - /* Add the amount of time the task has been running to the - accumulated time so far. The time the task started running was - stored in ulTaskSwitchedInTime. Note that there is no overflow - protection here so count values are only valid until the timer - overflows. The guard against negative values is to protect - against suspect run time stat counter implementations - which - are provided by the application, not the kernel. */ - taskENTER_CRITICAL_ISR(&xTaskQueueMutex); - if( ulTotalRunTime > ulTaskSwitchedInTime[ xPortGetCoreID() ] ) - { - pxCurrentTCB[ xPortGetCoreID() ]->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime[ xPortGetCoreID() ] ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - taskEXIT_CRITICAL_ISR(&xTaskQueueMutex); - ulTaskSwitchedInTime[ xPortGetCoreID() ] = ulTotalRunTime; - } - #endif /* configGENERATE_RUN_TIME_STATS */ + /* Add the amount of time the task has been running to the + * accumulated time so far. The time the task started running was + * stored in ulTaskSwitchedInTime. Note that there is no overflow + * protection here so count values are only valid until the timer + * overflows. The guard against negative values is to protect + * against suspect run time stat counter implementations - which + * are provided by the application, not the kernel. */ + taskENTER_CRITICAL_ISR(); + if( ulTotalRunTime > ulTaskSwitchedInTime[ xPortGetCoreID() ] ) + { + pxCurrentTCB[ xPortGetCoreID() ]->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime[ xPortGetCoreID() ] ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + taskEXIT_CRITICAL_ISR(); + ulTaskSwitchedInTime[ xPortGetCoreID() ] = ulTotalRunTime; + } + #endif /* configGENERATE_RUN_TIME_STATS */ - /* Check for stack overflow, if configured. */ - taskFIRST_CHECK_FOR_STACK_OVERFLOW(); - taskSECOND_CHECK_FOR_STACK_OVERFLOW(); + /* Check for stack overflow, if configured. */ + taskFIRST_CHECK_FOR_STACK_OVERFLOW(); + taskSECOND_CHECK_FOR_STACK_OVERFLOW(); - /* Select a new task to run */ + /* Select a new task to run */ - /* - We cannot do taskENTER_CRITICAL_ISR(&xTaskQueueMutex); here because it saves the interrupt context to the task tcb, and we're - swapping that out here. Instead, we're going to do the work here ourselves. Because interrupts are already disabled, we only - need to acquire the mutex. - */ - vPortCPUAcquireMutex( &xTaskQueueMutex ); + /* + We cannot do taskENTER_CRITICAL_ISR(); here because it saves the interrupt context to the task tcb, and we're + swapping that out here. Instead, we're going to do the work here ourselves. Because interrupts are already disabled, we only + need to acquire the mutex. + */ + vPortCPUAcquireMutex( &xTaskQueueMutex ); - #if !configUSE_PORT_OPTIMISED_TASK_SELECTION - unsigned portBASE_TYPE foundNonExecutingWaiter = pdFALSE, ableToSchedule = pdFALSE, resetListHead; - unsigned portBASE_TYPE holdTop=pdFALSE; - tskTCB * pxTCB; + #if !configUSE_PORT_OPTIMISED_TASK_SELECTION + unsigned portBASE_TYPE foundNonExecutingWaiter = pdFALSE, ableToSchedule = pdFALSE, resetListHead; + unsigned portBASE_TYPE holdTop=pdFALSE; + tskTCB * pxTCB; - portBASE_TYPE uxDynamicTopReady = uxTopReadyPriority; - /* - * ToDo: This scheduler doesn't correctly implement the round-robin scheduling as done in the single-core - * FreeRTOS stack when multiple tasks have the same priority and are all ready; it just keeps grabbing the - * first one. ToDo: fix this. - * (Is this still true? if any, there's the issue with one core skipping over the processes for the other - * core, potentially not giving the skipped-over processes any time.) - */ + portBASE_TYPE uxDynamicTopReady = uxTopReadyPriority; + /* + * ToDo: This scheduler doesn't correctly implement the round-robin scheduling as done in the single-core + * FreeRTOS stack when multiple tasks have the same priority and are all ready; it just keeps grabbing the + * first one. ToDo: fix this. + * (Is this still true? if any, there's the issue with one core skipping over the processes for the other + * core, potentially not giving the skipped-over processes any time.) + */ - while ( ableToSchedule == pdFALSE && uxDynamicTopReady >= 0 ) - { - resetListHead = pdFALSE; - // Nothing to do for empty lists - if (!listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxDynamicTopReady ] ) )) { + while ( ableToSchedule == pdFALSE && uxDynamicTopReady >= 0 ) + { + resetListHead = pdFALSE; + // Nothing to do for empty lists + if (!listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxDynamicTopReady ] ) )) { - ableToSchedule = pdFALSE; - tskTCB * pxRefTCB; + ableToSchedule = pdFALSE; + tskTCB * pxRefTCB; - /* Remember the current list item so that we - can detect if all items have been inspected. - Once this happens, we move on to a lower - priority list (assuming nothing is suitable - for scheduling). Note: This can return NULL if - the list index is at the listItem */ - pxRefTCB = pxReadyTasksLists[ uxDynamicTopReady ].pxIndex->pvOwner; + /* Remember the current list item so that we + can detect if all items have been inspected. + Once this happens, we move on to a lower + priority list (assuming nothing is suitable + for scheduling). Note: This can return NULL if + the list index is at the listItem */ + pxRefTCB = pxReadyTasksLists[ uxDynamicTopReady ].pxIndex->pvOwner; - if ((void*)pxReadyTasksLists[ uxDynamicTopReady ].pxIndex==(void*)&pxReadyTasksLists[ uxDynamicTopReady ].xListEnd) { - //pxIndex points to the list end marker. Skip that and just get the next item. - listGET_OWNER_OF_NEXT_ENTRY( pxRefTCB, &( pxReadyTasksLists[ uxDynamicTopReady ] ) ); - } + if ((void*)pxReadyTasksLists[ uxDynamicTopReady ].pxIndex==(void*)&pxReadyTasksLists[ uxDynamicTopReady ].xListEnd) { + //pxIndex points to the list end marker. Skip that and just get the next item. + listGET_OWNER_OF_NEXT_ENTRY( pxRefTCB, &( pxReadyTasksLists[ uxDynamicTopReady ] ) ); + } - do { - listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &( pxReadyTasksLists[ uxDynamicTopReady ] ) ); - /* Find out if the next task in the list is - already being executed by another core */ - foundNonExecutingWaiter = pdTRUE; - portBASE_TYPE i = 0; - for ( i=0; ixCoreID == tskNO_AFFINITY) { - pxCurrentTCB[xPortGetCoreID()] = pxTCB; - ableToSchedule = pdTRUE; - } else if (pxTCB->xCoreID == xPortGetCoreID()) { - pxCurrentTCB[xPortGetCoreID()] = pxTCB; - ableToSchedule = pdTRUE; - } else { - ableToSchedule = pdFALSE; - holdTop=pdTRUE; //keep this as the top prio, for the other CPU - } - } else { - ableToSchedule = pdFALSE; - } + if (foundNonExecutingWaiter == pdTRUE) { + /* If the task is not being executed + by another core and its affinity is + compatible with the current one, + prepare it to be swapped in */ + if (pxTCB->xCoreID == tskNO_AFFINITY) { + pxCurrentTCB[xPortGetCoreID()] = pxTCB; + ableToSchedule = pdTRUE; + } else if (pxTCB->xCoreID == xPortGetCoreID()) { + pxCurrentTCB[xPortGetCoreID()] = pxTCB; + ableToSchedule = pdTRUE; + } else { + ableToSchedule = pdFALSE; + holdTop=pdTRUE; //keep this as the top prio, for the other CPU + } + } else { + ableToSchedule = pdFALSE; + } - if (ableToSchedule == pdFALSE) { - resetListHead = pdTRUE; - } else if ((ableToSchedule == pdTRUE) && (resetListHead == pdTRUE)) { - tskTCB * pxResetTCB; - do { - listGET_OWNER_OF_NEXT_ENTRY( pxResetTCB, &( pxReadyTasksLists[ uxDynamicTopReady ] ) ); - } while(pxResetTCB != pxRefTCB); - } - } while ((ableToSchedule == pdFALSE) && (pxTCB != pxRefTCB)); - } else { - if (!holdTop) --uxTopReadyPriority; - } - --uxDynamicTopReady; - } + if (ableToSchedule == pdFALSE) { + resetListHead = pdTRUE; + } else if ((ableToSchedule == pdTRUE) && (resetListHead == pdTRUE)) { + tskTCB * pxResetTCB; + do { + listGET_OWNER_OF_NEXT_ENTRY( pxResetTCB, &( pxReadyTasksLists[ uxDynamicTopReady ] ) ); + } while(pxResetTCB != pxRefTCB); + } + } while ((ableToSchedule == pdFALSE) && (pxTCB != pxRefTCB)); + } else { + if (!holdTop) --uxTopReadyPriority; + } + --uxDynamicTopReady; + } - #else - //For Unicore targets we can keep the current FreeRTOS O(1) - //Scheduler. I hope to optimize better the scheduler for - //Multicore settings -- This will involve to create a per - //affinity ready task list which will impact hugely on - //tasks module - taskSELECT_HIGHEST_PRIORITY_TASK(); - #endif + #else + //For Unicore targets we can keep the current FreeRTOS O(1) + //Scheduler. I hope to optimize better the scheduler for + //Multicore settings -- This will involve to create a per + //affinity ready task list which will impact hugely on + //tasks module + taskSELECT_HIGHEST_PRIORITY_TASK(); + #endif - traceTASK_SWITCHED_IN(); + traceTASK_SWITCHED_IN(); xSwitchingContext[ xPortGetCoreID() ] = pdFALSE; - //Exit critical region manually as well: release the mux now, interrupts will be re-enabled when we - //exit the function. - vPortCPUReleaseMutex( &xTaskQueueMutex ); +#ifdef ESP_PLATFORM + //Exit critical region manually as well: release the mux now, interrupts will be re-enabled when we + //exit the function. + vPortCPUReleaseMutex( &xTaskQueueMutex ); +#endif // ESP_PLATFORM - #if CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK - vPortSetStackWatchpoint(pxCurrentTCB[xPortGetCoreID()]->pxStack); - #endif + #if CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK + vPortSetStackWatchpoint(pxCurrentTCB[xPortGetCoreID()]->pxStack); + #endif - } - portEXIT_CRITICAL_NESTED(irqstate); + } + portEXIT_CRITICAL_NESTED(irqstate); } /*-----------------------------------------------------------*/ -void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait ) +void vTaskPlaceOnEventList( List_t * const pxEventList, + const TickType_t xTicksToWait ) { - configASSERT( pxEventList ); - taskENTER_CRITICAL(&xTaskQueueMutex); + configASSERT( pxEventList ); + taskENTER_CRITICAL(); - /* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE - SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */ + /* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE + * SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */ - /* Place the event list item of the TCB in the appropriate event list. - This is placed in the list in priority order so the highest priority task - is the first to be woken by the event. The queue that contains the event - list is locked, preventing simultaneous access from interrupts. */ - vListInsert( pxEventList, &( pxCurrentTCB[xPortGetCoreID()]->xEventListItem ) ); + /* Place the event list item of the TCB in the appropriate event list. + * This is placed in the list in priority order so the highest priority task + * is the first to be woken by the event. The queue that contains the event + * list is locked, preventing simultaneous access from interrupts. */ + vListInsert( pxEventList, &( pxCurrentTCB[xPortGetCoreID()]->xEventListItem ) ); - prvAddCurrentTaskToDelayedList( xPortGetCoreID(), xTicksToWait); - taskEXIT_CRITICAL(&xTaskQueueMutex); + prvAddCurrentTaskToDelayedList( xPortGetCoreID(), xTicksToWait); + taskEXIT_CRITICAL(); } /*-----------------------------------------------------------*/ -void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xItemValue, const TickType_t xTicksToWait ) +void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, + const TickType_t xItemValue, + const TickType_t xTicksToWait ) { - configASSERT( pxEventList ); - taskENTER_CRITICAL(&xTaskQueueMutex); + configASSERT( pxEventList ); + taskENTER_CRITICAL(); - /* Store the item value in the event list item. It is safe to access the - event list item here as interrupts won't access the event list item of a - task that is not in the Blocked state. */ - listSET_LIST_ITEM_VALUE( &( pxCurrentTCB[xPortGetCoreID()]->xEventListItem ), xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE ); + /* Store the item value in the event list item. It is safe to access the + * event list item here as interrupts won't access the event list item of a + * task that is not in the Blocked state. */ + listSET_LIST_ITEM_VALUE( &( pxCurrentTCB[xPortGetCoreID()]->xEventListItem ), xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE ); - /* Place the event list item of the TCB at the end of the appropriate event - list. It is safe to access the event list here because it is part of an - event group implementation - and interrupts don't access event groups - directly (instead they access them indirectly by pending function calls to - the task level). */ - vListInsertEnd( pxEventList, &( pxCurrentTCB[xPortGetCoreID()]->xEventListItem ) ); + /* Place the event list item of the TCB at the end of the appropriate event + * list. It is safe to access the event list here because it is part of an + * event group implementation - and interrupts don't access event groups + * directly (instead they access them indirectly by pending function calls to + * the task level). */ + vListInsertEnd( pxEventList, &( pxCurrentTCB[xPortGetCoreID()]->xEventListItem ) ); - prvAddCurrentTaskToDelayedList( xPortGetCoreID(), xTicksToWait ); - taskEXIT_CRITICAL(&xTaskQueueMutex); + prvAddCurrentTaskToDelayedList( xPortGetCoreID(), xTicksToWait ); + taskEXIT_CRITICAL(); } /*-----------------------------------------------------------*/ -#if( configUSE_TIMERS == 1 ) +#if ( configUSE_TIMERS == 1 ) - void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely ) - { - taskENTER_CRITICAL(&xTaskQueueMutex); - configASSERT( pxEventList ); + void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely ) + { + taskENTER_CRITICAL(); + configASSERT( pxEventList ); - /* This function should not be called by application code hence the - 'Restricted' in its name. It is not part of the public API. It is - designed for use by kernel code, and has special calling requirements - - it should be called with the scheduler suspended. */ + /* This function should not be called by application code hence the + * 'Restricted' in its name. It is not part of the public API. It is + * designed for use by kernel code, and has special calling requirements - + * it should be called with the scheduler suspended. */ - /* Place the event list item of the TCB in the appropriate event list. - In this case it is assume that this is the only task that is going to - be waiting on this event list, so the faster vListInsertEnd() function - can be used in place of vListInsert. */ - vListInsertEnd( pxEventList, &( pxCurrentTCB[xPortGetCoreID()]->xEventListItem ) ); + /* Place the event list item of the TCB in the appropriate event list. + * In this case it is assume that this is the only task that is going to + * be waiting on this event list, so the faster vListInsertEnd() function + * can be used in place of vListInsert. */ + vListInsertEnd( pxEventList, &( pxCurrentTCB[xPortGetCoreID()]->xEventListItem ) ); - /* If the task should block indefinitely then set the block time to a - value that will be recognised as an indefinite delay inside the - prvAddCurrentTaskToDelayedList() function. */ - if( xWaitIndefinitely != pdFALSE ) - { - xTicksToWait = portMAX_DELAY; - } + /* If the task should block indefinitely then set the block time to a + * value that will be recognised as an indefinite delay inside the + * prvAddCurrentTaskToDelayedList() function. */ + if( xWaitIndefinitely != pdFALSE ) + { + xTicksToWait = portMAX_DELAY; + } - traceTASK_DELAY_UNTIL( ); - prvAddCurrentTaskToDelayedList( xPortGetCoreID(), xTicksToWait ); - taskEXIT_CRITICAL(&xTaskQueueMutex); - } + traceTASK_DELAY_UNTIL( ); + prvAddCurrentTaskToDelayedList( xPortGetCoreID(), xTicksToWait ); + taskEXIT_CRITICAL(); + } #endif /* configUSE_TIMERS */ /*-----------------------------------------------------------*/ BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList ) { -TCB_t *pxUnblockedTCB; -BaseType_t xReturn; -BaseType_t xTaskCanBeReady; -UBaseType_t i, uxTargetCPU; + TCB_t * pxUnblockedTCB; + BaseType_t xReturn; + BaseType_t xTaskCanBeReady; + UBaseType_t i, uxTargetCPU; - taskENTER_CRITICAL_ISR(&xTaskQueueMutex); - /* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION. It can also be - called from a critical section within an ISR. */ + taskENTER_CRITICAL_ISR(); + /* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION. It can also be + * called from a critical section within an ISR. */ - /* The event list is sorted in priority order, so the first in the list can - be removed as it is known to be the highest priority. Remove the TCB from - the delayed list, and add it to the ready list. + /* The event list is sorted in priority order, so the first in the list can + * be removed as it is known to be the highest priority. Remove the TCB from + * the delayed list, and add it to the ready list. + * + * If an event is for a queue that is locked then this function will never + * get called - the lock count on the queue will get modified instead. This + * means exclusive access to the event list is guaranteed here. + * + * This function assumes that a check has already been made to ensure that + * pxEventList is not empty. */ + if ( ( listLIST_IS_EMPTY( pxEventList ) ) == pdFALSE ) + { + pxUnblockedTCB = listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ + configASSERT( pxUnblockedTCB ); + ( void ) uxListRemove( &( pxUnblockedTCB->xEventListItem ) ); + } + else + { + taskEXIT_CRITICAL_ISR(); + return pdFALSE; + } - If an event is for a queue that is locked then this function will never - get called - the lock count on the queue will get modified instead. This - means exclusive access to the event list is guaranteed here. + xTaskCanBeReady = pdFALSE; + if ( pxUnblockedTCB->xCoreID == tskNO_AFFINITY ) + { + uxTargetCPU = xPortGetCoreID(); + for (i = 0; i < portNUM_PROCESSORS; i++) + { + if ( uxSchedulerSuspended[ i ] == ( UBaseType_t ) pdFALSE ) + { + xTaskCanBeReady = pdTRUE; + break; + } + } + } + else + { + uxTargetCPU = pxUnblockedTCB->xCoreID; + xTaskCanBeReady = uxSchedulerSuspended[ uxTargetCPU ] == ( UBaseType_t ) pdFALSE; + } - This function assumes that a check has already been made to ensure that - pxEventList is not empty. */ - if ( ( listLIST_IS_EMPTY( pxEventList ) ) == pdFALSE ) - { - pxUnblockedTCB = listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ - configASSERT( pxUnblockedTCB ); - ( void ) uxListRemove( &( pxUnblockedTCB->xEventListItem ) ); - } - else - { - taskEXIT_CRITICAL_ISR(&xTaskQueueMutex); - return pdFALSE; - } + if( xTaskCanBeReady ) + { + ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) ); + prvAddTaskToReadyList( pxUnblockedTCB ); + } + else + { + /* The delayed and ready lists cannot be accessed, so hold this task + * pending until the scheduler is resumed on this CPU. */ + vListInsertEnd( &( xPendingReadyList[ uxTargetCPU ] ), &( pxUnblockedTCB->xEventListItem ) ); + } - xTaskCanBeReady = pdFALSE; - if ( pxUnblockedTCB->xCoreID == tskNO_AFFINITY ) - { - uxTargetCPU = xPortGetCoreID(); - for (i = 0; i < portNUM_PROCESSORS; i++) - { - if ( uxSchedulerSuspended[ i ] == ( UBaseType_t ) pdFALSE ) - { - xTaskCanBeReady = pdTRUE; - break; - } - } - } - else - { - uxTargetCPU = pxUnblockedTCB->xCoreID; - xTaskCanBeReady = uxSchedulerSuspended[ uxTargetCPU ] == ( UBaseType_t ) pdFALSE; - } + if ( tskCAN_RUN_HERE(pxUnblockedTCB->xCoreID) && pxUnblockedTCB->uxPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) + { + /* Return true if the task removed from the event list has a higher + * priority than the calling task. This allows the calling task to know if + * it should force a context switch now. */ + xReturn = pdTRUE; - if( xTaskCanBeReady ) - { - ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) ); - prvAddTaskToReadyList( pxUnblockedTCB ); - } - else - { - /* The delayed and ready lists cannot be accessed, so hold this task - pending until the scheduler is resumed on this CPU. */ - vListInsertEnd( &( xPendingReadyList[ uxTargetCPU ] ), &( pxUnblockedTCB->xEventListItem ) ); - } + /* Mark that a yield is pending in case the user is not using the + * "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */ + xYieldPending[ xPortGetCoreID() ] = pdTRUE; + } + else if ( pxUnblockedTCB->xCoreID != xPortGetCoreID() ) + { + taskYIELD_OTHER_CORE( pxUnblockedTCB->xCoreID, pxUnblockedTCB->uxPriority ); + xReturn = pdFALSE; + } + else + { + xReturn = pdFALSE; + } - if ( tskCAN_RUN_HERE(pxUnblockedTCB->xCoreID) && pxUnblockedTCB->uxPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) - { - /* Return true if the task removed from the event list has a higher - priority than the calling task. This allows the calling task to know if - it should force a context switch now. */ - xReturn = pdTRUE; + #if( configUSE_TICKLESS_IDLE != 0 ) + { + /* If a task is blocked on a kernel object then xNextTaskUnblockTime + might be set to the blocked task's time out time. If the task is + unblocked for a reason other than a timeout xNextTaskUnblockTime is + normally left unchanged, because it is automatically reset to a new + value when the tick count equals xNextTaskUnblockTime. However if + tickless idling is used it might be more important to enter sleep mode + at the earliest possible time - so reset xNextTaskUnblockTime here to + ensure it is updated at the earliest possible time. */ + prvResetNextTaskUnblockTime(); + } + #endif - /* Mark that a yield is pending in case the user is not using the - "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */ - xYieldPending[ xPortGetCoreID() ] = pdTRUE; - } - else if ( pxUnblockedTCB->xCoreID != xPortGetCoreID() ) - { - taskYIELD_OTHER_CORE( pxUnblockedTCB->xCoreID, pxUnblockedTCB->uxPriority ); - xReturn = pdFALSE; - } - else - { - xReturn = pdFALSE; - } - - #if( configUSE_TICKLESS_IDLE != 0 ) - { - /* If a task is blocked on a kernel object then xNextTaskUnblockTime - might be set to the blocked task's time out time. If the task is - unblocked for a reason other than a timeout xNextTaskUnblockTime is - normally left unchanged, because it is automatically reset to a new - value when the tick count equals xNextTaskUnblockTime. However if - tickless idling is used it might be more important to enter sleep mode - at the earliest possible time - so reset xNextTaskUnblockTime here to - ensure it is updated at the earliest possible time. */ - prvResetNextTaskUnblockTime(); - } - #endif - - taskEXIT_CRITICAL_ISR(&xTaskQueueMutex); - return xReturn; + taskEXIT_CRITICAL_ISR(); + return xReturn; } /*-----------------------------------------------------------*/ -BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue ) +void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, + const TickType_t xItemValue ) { -TCB_t *pxUnblockedTCB; -BaseType_t xReturn; + TCB_t * pxUnblockedTCB; - taskENTER_CRITICAL(&xTaskQueueMutex); + taskENTER_CRITICAL(); - /* Store the new item value in the event list. */ - listSET_LIST_ITEM_VALUE( pxEventListItem, xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE ); + /* Store the new item value in the event list. */ + listSET_LIST_ITEM_VALUE( pxEventListItem, xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE ); - /* Remove the event list form the event flag. Interrupts do not access - event flags. */ - pxUnblockedTCB = ( TCB_t * ) listGET_LIST_ITEM_OWNER( pxEventListItem ); - configASSERT( pxUnblockedTCB ); - ( void ) uxListRemove( pxEventListItem ); + /* Remove the event list form the event flag. Interrupts do not access + * event flags. */ + pxUnblockedTCB = ( TCB_t * ) listGET_LIST_ITEM_OWNER( pxEventListItem ); + configASSERT( pxUnblockedTCB ); + ( void ) uxListRemove( pxEventListItem ); - /* Remove the task from the delayed list and add it to the ready list. The - scheduler is suspended so interrupts will not be accessing the ready - lists. */ - ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) ); - prvAddTaskToReadyList( pxUnblockedTCB ); + /* Remove the task from the delayed list and add it to the ready list. The + * scheduler is suspended so interrupts will not be accessing the ready + * lists. */ + ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) ); + prvAddTaskToReadyList( pxUnblockedTCB ); - if ( tskCAN_RUN_HERE(pxUnblockedTCB->xCoreID) && pxUnblockedTCB->uxPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) - { - /* Return true if the task removed from the event list has - a higher priority than the calling task. This allows - the calling task to know if it should force a context - switch now. */ - xReturn = pdTRUE; + if ( tskCAN_RUN_HERE(pxUnblockedTCB->xCoreID) && pxUnblockedTCB->uxPriority >= pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) + { + /* Mark that a yield is pending in case the user is not using the + * "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */ + xYieldPending[ xPortGetCoreID() ] = pdTRUE; + } + else if ( pxUnblockedTCB->xCoreID != xPortGetCoreID() ) + { + taskYIELD_OTHER_CORE( pxUnblockedTCB->xCoreID, pxUnblockedTCB->uxPriority ); + } - /* Mark that a yield is pending in case the user is not using the - "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */ - xYieldPending[ xPortGetCoreID() ] = pdTRUE; - } - else if ( pxUnblockedTCB->xCoreID != xPortGetCoreID() ) - { - taskYIELD_OTHER_CORE( pxUnblockedTCB->xCoreID, pxUnblockedTCB->uxPriority ); - xReturn = pdFALSE; - } - else - { - xReturn = pdFALSE; - } - - taskEXIT_CRITICAL(&xTaskQueueMutex); - return xReturn; + taskEXIT_CRITICAL(); } /*-----------------------------------------------------------*/ void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) { - configASSERT( pxTimeOut ); - taskENTER_CRITICAL( &xTaskQueueMutex ); - { - pxTimeOut->xOverflowCount = xNumOfOverflows; - pxTimeOut->xTimeOnEntering = xTickCount; - } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + configASSERT( pxTimeOut ); + taskENTER_CRITICAL(); + { + pxTimeOut->xOverflowCount = xNumOfOverflows; + pxTimeOut->xTimeOnEntering = xTickCount; + } + taskEXIT_CRITICAL(); } /*-----------------------------------------------------------*/ void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut ) { - /* For internal use only as it does not use a critical section. */ - pxTimeOut->xOverflowCount = xNumOfOverflows; - pxTimeOut->xTimeOnEntering = xTickCount; + /* For internal use only as it does not use a critical section. */ + pxTimeOut->xOverflowCount = xNumOfOverflows; + pxTimeOut->xTimeOnEntering = xTickCount; } /*-----------------------------------------------------------*/ -BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait ) +BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, + TickType_t * const pxTicksToWait ) { -BaseType_t xReturn; + BaseType_t xReturn; - configASSERT( pxTimeOut ); - configASSERT( pxTicksToWait ); + configASSERT( pxTimeOut ); + configASSERT( pxTicksToWait ); - taskENTER_CRITICAL( &xTaskQueueMutex ); - { - /* Minor optimisation. The tick count cannot change in this block. */ - const TickType_t xConstTickCount = xTickCount; - const TickType_t xElapsedTime = xConstTickCount - pxTimeOut->xTimeOnEntering; + taskENTER_CRITICAL(); + { + /* Minor optimisation. The tick count cannot change in this block. */ + const TickType_t xConstTickCount = xTickCount; + const TickType_t xElapsedTime = xConstTickCount - pxTimeOut->xTimeOnEntering; - #if( INCLUDE_xTaskAbortDelay == 1 ) - if( pxCurrentTCB[xPortGetCoreID()]->ucDelayAborted != ( uint8_t ) pdFALSE ) - { - /* The delay was aborted, which is not the same as a time out, - but has the same result. */ - pxCurrentTCB[xPortGetCoreID()]->ucDelayAborted = pdFALSE; - xReturn = pdTRUE; - } - else - #endif + #if ( INCLUDE_xTaskAbortDelay == 1 ) + if( pxCurrentTCB[xPortGetCoreID()]->ucDelayAborted != ( uint8_t ) pdFALSE ) + { + /* The delay was aborted, which is not the same as a time out, + * but has the same result. */ + pxCurrentTCB[xPortGetCoreID()]->ucDelayAborted = pdFALSE; + xReturn = pdTRUE; + } + else + #endif - #if ( INCLUDE_vTaskSuspend == 1 ) - if( *pxTicksToWait == portMAX_DELAY ) - { - /* If INCLUDE_vTaskSuspend is set to 1 and the block time - specified is the maximum block time then the task should block - indefinitely, and therefore never time out. */ - xReturn = pdFALSE; - } - else - #endif + #if ( INCLUDE_vTaskSuspend == 1 ) + if( *pxTicksToWait == portMAX_DELAY ) + { + /* If INCLUDE_vTaskSuspend is set to 1 and the block time + * specified is the maximum block time then the task should block + * indefinitely, and therefore never time out. */ + xReturn = pdFALSE; + } + else + #endif - if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */ - { - /* The tick count is greater than the time at which - vTaskSetTimeout() was called, but has also overflowed since - vTaskSetTimeOut() was called. It must have wrapped all the way - around and gone past again. This passed since vTaskSetTimeout() - was called. */ - xReturn = pdTRUE; - } - else if( xElapsedTime < *pxTicksToWait ) /*lint !e961 Explicit casting is only redundant with some compilers, whereas others require it to prevent integer conversion errors. */ - { - /* Not a genuine timeout. Adjust parameters for time remaining. */ - *pxTicksToWait -= xElapsedTime; - vTaskInternalSetTimeOutState( pxTimeOut ); - xReturn = pdFALSE; - } - else - { - *pxTicksToWait = 0; - xReturn = pdTRUE; - } - } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */ + { + /* The tick count is greater than the time at which + * vTaskSetTimeout() was called, but has also overflowed since + * vTaskSetTimeOut() was called. It must have wrapped all the way + * around and gone past again. This passed since vTaskSetTimeout() + * was called. */ + xReturn = pdTRUE; + } + else if( xElapsedTime < *pxTicksToWait ) /*lint !e961 Explicit casting is only redundant with some compilers, whereas others require it to prevent integer conversion errors. */ + { + /* Not a genuine timeout. Adjust parameters for time remaining. */ + *pxTicksToWait -= xElapsedTime; + vTaskInternalSetTimeOutState( pxTimeOut ); + xReturn = pdFALSE; + } + else + { + *pxTicksToWait = 0; + xReturn = pdTRUE; + } + } + taskEXIT_CRITICAL(); - return xReturn; + return xReturn; } /*-----------------------------------------------------------*/ void vTaskMissedYield( void ) { - xYieldPending[xPortGetCoreID()] = pdTRUE; + xYieldPending[xPortGetCoreID()] = pdTRUE; } /*-----------------------------------------------------------*/ #if ( configUSE_TRACE_FACILITY == 1 ) - UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask ) - { - UBaseType_t uxReturn; - TCB_t const *pxTCB; + UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask ) + { + UBaseType_t uxReturn; + TCB_t const * pxTCB; - if( xTask != NULL ) - { - pxTCB = xTask; - uxReturn = pxTCB->uxTaskNumber; - } - else - { - uxReturn = 0U; - } + if( xTask != NULL ) + { + pxTCB = xTask; + uxReturn = pxTCB->uxTaskNumber; + } + else + { + uxReturn = 0U; + } - return uxReturn; - } + return uxReturn; + } #endif /* configUSE_TRACE_FACILITY */ /*-----------------------------------------------------------*/ #if ( configUSE_TRACE_FACILITY == 1 ) - void vTaskSetTaskNumber( TaskHandle_t xTask, const UBaseType_t uxHandle ) - { - TCB_t * pxTCB; + void vTaskSetTaskNumber( TaskHandle_t xTask, + const UBaseType_t uxHandle ) + { + TCB_t * pxTCB; - if( xTask != NULL ) - { - pxTCB = xTask; - pxTCB->uxTaskNumber = uxHandle; - } - } + if( xTask != NULL ) + { + pxTCB = xTask; + pxTCB->uxTaskNumber = uxHandle; + } + } #endif /* configUSE_TRACE_FACILITY */ @@ -3762,205 +3895,216 @@ void vTaskMissedYield( void ) */ static portTASK_FUNCTION( prvIdleTask, pvParameters ) { - /* Stop warnings. */ - ( void ) pvParameters; + /* Stop warnings. */ + ( void ) pvParameters; - /** THIS IS THE RTOS IDLE TASK - WHICH IS CREATED AUTOMATICALLY WHEN THE - SCHEDULER IS STARTED. **/ + /** THIS IS THE RTOS IDLE TASK - WHICH IS CREATED AUTOMATICALLY WHEN THE + * SCHEDULER IS STARTED. **/ - /* In case a task that has a secure context deletes itself, in which case - the idle task is responsible for deleting the task's secure context, if - any. */ - portALLOCATE_SECURE_CONTEXT( configMINIMAL_SECURE_STACK_SIZE ); + /* In case a task that has a secure context deletes itself, in which case + * the idle task is responsible for deleting the task's secure context, if + * any. */ + portALLOCATE_SECURE_CONTEXT( configMINIMAL_SECURE_STACK_SIZE ); - for( ;; ) - { - /* See if any tasks have deleted themselves - if so then the idle task - is responsible for freeing the deleted task's TCB and stack. */ - prvCheckTasksWaitingTermination(); + for( ; ; ) + { + /* See if any tasks have deleted themselves - if so then the idle task + * is responsible for freeing the deleted task's TCB and stack. */ + prvCheckTasksWaitingTermination(); - #if ( configUSE_PREEMPTION == 0 ) - { - /* If we are not using preemption we keep forcing a task switch to - see if any other task has become available. If we are using - preemption we don't need to do this as any task becoming available - will automatically get the processor anyway. */ - taskYIELD(); - } - #endif /* configUSE_PREEMPTION */ + #if ( configUSE_PREEMPTION == 0 ) + { + /* If we are not using preemption we keep forcing a task switch to + * see if any other task has become available. If we are using + * preemption we don't need to do this as any task becoming available + * will automatically get the processor anyway. */ + taskYIELD(); + } + #endif /* configUSE_PREEMPTION */ - #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) - { - /* When using preemption tasks of equal priority will be - timesliced. If a task that is sharing the idle priority is ready - to run then the idle task should yield before the end of the - timeslice. + #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) + { + /* When using preemption tasks of equal priority will be + * timesliced. If a task that is sharing the idle priority is ready + * to run then the idle task should yield before the end of the + * timeslice. + * + * A critical region is not required here as we are just reading from + * the list, and an occasional incorrect value will not matter. If + * the ready list at the idle priority contains more than one task + * then a task other than the idle task is ready to execute. */ + if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) 1 ) + { + taskYIELD(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */ - A critical region is not required here as we are just reading from - the list, and an occasional incorrect value will not matter. If - the ready list at the idle priority contains more than one task - then a task other than the idle task is ready to execute. */ - if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) 1 ) - { - taskYIELD(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */ + #if ( configUSE_IDLE_HOOK == 1 ) + { + extern void vApplicationIdleHook( void ); - #if ( configUSE_IDLE_HOOK == 1 ) - { - extern void vApplicationIdleHook( void ); + /* Call the user defined function from within the idle task. This + * allows the application designer to add background functionality + * without the overhead of a separate task. + * NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES, + * CALL A FUNCTION THAT MIGHT BLOCK. */ + vApplicationIdleHook(); + } + #endif /* configUSE_IDLE_HOOK */ + #if ( CONFIG_FREERTOS_LEGACY_HOOKS == 1 ) + { + /* Call the esp-idf hook system */ + esp_vApplicationIdleHook(); + } + #endif /* CONFIG_FREERTOS_LEGACY_HOOKS */ - /* Call the user defined function from within the idle task. This - allows the application designer to add background functionality - without the overhead of a separate task. - NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES, - CALL A FUNCTION THAT MIGHT BLOCK. */ - vApplicationIdleHook(); - } - #endif /* configUSE_IDLE_HOOK */ - #if ( CONFIG_FREERTOS_LEGACY_HOOKS == 1 ) - { - /* Call the esp-idf hook system */ - esp_vApplicationIdleHook(); - } - #endif /* CONFIG_FREERTOS_LEGACY_HOOKS */ + /* This conditional compilation should use inequality to 0, not equality + * to 1. This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when + * user defined low power mode implementations require + * configUSE_TICKLESS_IDLE to be set to a value other than 1. */ + #if ( configUSE_TICKLESS_IDLE != 0 ) + { + TickType_t xExpectedIdleTime; - /* This conditional compilation should use inequality to 0, not equality - to 1. This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when - user defined low power mode implementations require - configUSE_TICKLESS_IDLE to be set to a value other than 1. */ - #if ( configUSE_TICKLESS_IDLE != 0 ) - { - TickType_t xExpectedIdleTime; + /* It is not desirable to suspend then resume the scheduler on + * each iteration of the idle task. Therefore, a preliminary + * test of the expected idle time is performed without the + * scheduler suspended. The result here is not necessarily + * valid. */ + xExpectedIdleTime = prvGetExpectedIdleTime(); - /* It is not desirable to suspend then resume the scheduler on - each iteration of the idle task. Therefore, a preliminary - test of the expected idle time is performed without the - scheduler suspended. The result here is not necessarily - valid. */ - xExpectedIdleTime = prvGetExpectedIdleTime(); + if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP ) + { +#ifdef ESP_PLATFORM // IDF-3755 + taskENTER_CRITICAL(); +#else + vTaskSuspendAll(); +#endif // ESP_PLATFORM + { + /* Now the scheduler is suspended, the expected idle + * time can be sampled again, and this time its value can + * be used. */ + configASSERT( xNextTaskUnblockTime >= xTickCount ); + xExpectedIdleTime = prvGetExpectedIdleTime(); - if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP ) - { - taskENTER_CRITICAL( &xTaskQueueMutex ); - { - /* Now the scheduler is suspended, the expected idle - time can be sampled again, and this time its value can - be used. */ - configASSERT( xNextTaskUnblockTime >= xTickCount ); - xExpectedIdleTime = prvGetExpectedIdleTime(); + /* Define the following macro to set xExpectedIdleTime to 0 + * if the application does not want + * portSUPPRESS_TICKS_AND_SLEEP() to be called. */ + configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING( xExpectedIdleTime ); - /* Define the following macro to set xExpectedIdleTime to 0 - if the application does not want - portSUPPRESS_TICKS_AND_SLEEP() to be called. */ - configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING( xExpectedIdleTime ); - - if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP ) - { - traceLOW_POWER_IDLE_BEGIN(); - portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ); - traceLOW_POWER_IDLE_END(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - taskEXIT_CRITICAL( &xTaskQueueMutex ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - #endif /* configUSE_TICKLESS_IDLE */ - } + if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP ) + { + traceLOW_POWER_IDLE_BEGIN(); + portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ); + traceLOW_POWER_IDLE_END(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } +#ifdef ESP_PLATFORM // IDF-3755 + taskEXIT_CRITICAL(); +#else + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_TICKLESS_IDLE */ + } } /*-----------------------------------------------------------*/ -#if( configUSE_TICKLESS_IDLE != 0 ) +#if ( configUSE_TICKLESS_IDLE != 0 ) - eSleepModeStatus eTaskConfirmSleepModeStatus( void ) - { - /* The idle task exists in addition to the application tasks. */ - const UBaseType_t uxNonApplicationTasks = 1; - eSleepModeStatus eReturn = eStandardSleep; + eSleepModeStatus eTaskConfirmSleepModeStatus( void ) + { + /* The idle task exists in addition to the application tasks. */ + const UBaseType_t uxNonApplicationTasks = 1; + eSleepModeStatus eReturn = eStandardSleep; - taskEXIT_CRITICAL(&xTaskQueueMutex); - if( listCURRENT_LIST_LENGTH( &xPendingReadyList[xPortGetCoreID()] ) != 0 ) - { - /* A task was made ready while the scheduler was suspended. */ - eReturn = eAbortSleep; - } - else if( xYieldPending[xPortGetCoreID()] != pdFALSE ) - { - /* A yield was pended while the scheduler was suspended. */ - eReturn = eAbortSleep; - } - else - { - /* If all the tasks are in the suspended list (which might mean they - have an infinite block time rather than actually being suspended) - then it is safe to turn all clocks off and just wait for external - interrupts. */ - if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) ) - { - eReturn = eNoTasksWaitingTimeout; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - taskEXIT_CRITICAL(&xTaskQueueMutex); + taskENTER_CRITICAL(); + if( listCURRENT_LIST_LENGTH( &xPendingReadyList[xPortGetCoreID()] ) != 0 ) + { + /* A task was made ready while the scheduler was suspended. */ + eReturn = eAbortSleep; + } + else if( xYieldPending[xPortGetCoreID()] != pdFALSE ) + { + /* A yield was pended while the scheduler was suspended. */ + eReturn = eAbortSleep; + } + else + { + /* If all the tasks are in the suspended list (which might mean they + * have an infinite block time rather than actually being suspended) + * then it is safe to turn all clocks off and just wait for external + * interrupts. */ + if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) ) + { + eReturn = eNoTasksWaitingTimeout; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(); - return eReturn; - } + return eReturn; + } #endif /* configUSE_TICKLESS_IDLE */ /*-----------------------------------------------------------*/ + #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 ) #if ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS ) - void vTaskSetThreadLocalStoragePointerAndDelCallback( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue , TlsDeleteCallbackFunction_t xDelCallback) - { - TCB_t *pxTCB; + void vTaskSetThreadLocalStoragePointerAndDelCallback( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue , TlsDeleteCallbackFunction_t xDelCallback) + { + TCB_t *pxTCB; - if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) - { - taskENTER_CRITICAL(&xTaskQueueMutex); - pxTCB = prvGetTCBFromHandle( xTaskToSet ); - pxTCB->pvThreadLocalStoragePointers[ xIndex ] = pvValue; - pxTCB->pvThreadLocalStoragePointersDelCallback[ xIndex ] = xDelCallback; - taskEXIT_CRITICAL(&xTaskQueueMutex); - } - } + if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) + { + taskENTER_CRITICAL(); + pxTCB = prvGetTCBFromHandle( xTaskToSet ); + pxTCB->pvThreadLocalStoragePointers[ xIndex ] = pvValue; + pxTCB->pvThreadLocalStoragePointersDelCallback[ xIndex ] = xDelCallback; + taskEXIT_CRITICAL(); + } + } - void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue ) - { - vTaskSetThreadLocalStoragePointerAndDelCallback( xTaskToSet, xIndex, pvValue, (TlsDeleteCallbackFunction_t)NULL ); - } + void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue ) + { + vTaskSetThreadLocalStoragePointerAndDelCallback( xTaskToSet, xIndex, pvValue, (TlsDeleteCallbackFunction_t)NULL ); + } #else - void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue ) - { - TCB_t *pxTCB; + void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, + BaseType_t xIndex, + void * pvValue ) + { + TCB_t * pxTCB; - if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) - { - taskENTER_CRITICAL(&xTaskQueueMutex); - pxTCB = prvGetTCBFromHandle( xTaskToSet ); - pxTCB->pvThreadLocalStoragePointers[ xIndex ] = pvValue; - taskEXIT_CRITICAL(&xTaskQueueMutex); - } - } + if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) + { + taskENTER_CRITICAL(); + pxTCB = prvGetTCBFromHandle( xTaskToSet ); + pxTCB->pvThreadLocalStoragePointers[ xIndex ] = pvValue; + taskEXIT_CRITICAL(); + } + } #endif /* configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS */ #endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */ @@ -3968,463 +4112,478 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 ) - void *pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, BaseType_t xIndex ) - { - void *pvReturn = NULL; - TCB_t *pxTCB; + void * pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, + BaseType_t xIndex ) + { + void * pvReturn = NULL; + TCB_t * pxTCB; - if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) - { - pxTCB = prvGetTCBFromHandle( xTaskToQuery ); - pvReturn = pxTCB->pvThreadLocalStoragePointers[ xIndex ]; - } - else - { - pvReturn = NULL; - } + if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) + { + pxTCB = prvGetTCBFromHandle( xTaskToQuery ); + pvReturn = pxTCB->pvThreadLocalStoragePointers[ xIndex ]; + } + else + { + pvReturn = NULL; + } - return pvReturn; - } + return pvReturn; + } #endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */ /*-----------------------------------------------------------*/ #if ( portUSING_MPU_WRAPPERS == 1 ) - void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify, const MemoryRegion_t * const xRegions ) - { - TCB_t *pxTCB; + void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify, + const MemoryRegion_t * const xRegions ) + { + TCB_t * pxTCB; - /* If null is passed in here then we are modifying the MPU settings of - the calling task. */ - pxTCB = prvGetTCBFromHandle( xTaskToModify ); + /* If null is passed in here then we are modifying the MPU settings of + * the calling task. */ + pxTCB = prvGetTCBFromHandle( xTaskToModify ); - vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 ); - } + vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 ); + } #endif /* portUSING_MPU_WRAPPERS */ /*-----------------------------------------------------------*/ static void prvInitialiseTaskLists( void ) { -UBaseType_t uxPriority; + UBaseType_t uxPriority; - for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ ) - { - vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) ); - } + for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ ) + { + vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) ); + } - vListInitialise( &xDelayedTaskList1 ); - vListInitialise( &xDelayedTaskList2 ); + vListInitialise( &xDelayedTaskList1 ); + vListInitialise( &xDelayedTaskList2 ); - #if ( portNUM_PROCESSORS > 1 ) - for(BaseType_t i = 0; i < portNUM_PROCESSORS; i++) { - vListInitialise( &xPendingReadyList[ i ] ); - } - #else - vListInitialise( &xPendingReadyList[xPortGetCoreID()] ); - #endif + #if ( portNUM_PROCESSORS > 1 ) + for(BaseType_t i = 0; i < portNUM_PROCESSORS; i++) { + vListInitialise( &xPendingReadyList[ i ] ); + } + #else + vListInitialise( &xPendingReadyList[xPortGetCoreID()] ); + #endif - #if ( INCLUDE_vTaskDelete == 1 ) - { - vListInitialise( &xTasksWaitingTermination ); - } - #endif /* INCLUDE_vTaskDelete */ + #if ( INCLUDE_vTaskDelete == 1 ) + { + vListInitialise( &xTasksWaitingTermination ); + } + #endif /* INCLUDE_vTaskDelete */ - #if ( INCLUDE_vTaskSuspend == 1 ) - { - vListInitialise( &xSuspendedTaskList ); - } - #endif /* INCLUDE_vTaskSuspend */ + #if ( INCLUDE_vTaskSuspend == 1 ) + { + vListInitialise( &xSuspendedTaskList ); + } + #endif /* INCLUDE_vTaskSuspend */ - /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList - using list2. */ - pxDelayedTaskList = &xDelayedTaskList1; - pxOverflowDelayedTaskList = &xDelayedTaskList2; + /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList + * using list2. */ + pxDelayedTaskList = &xDelayedTaskList1; + pxOverflowDelayedTaskList = &xDelayedTaskList2; } /*-----------------------------------------------------------*/ static void prvCheckTasksWaitingTermination( void ) { + /** THIS FUNCTION IS CALLED FROM THE RTOS IDLE TASK **/ - /** THIS FUNCTION IS CALLED FROM THE RTOS IDLE TASK **/ + #if ( INCLUDE_vTaskDelete == 1 ) + { + BaseType_t xListIsEmpty; + BaseType_t core = xPortGetCoreID(); - #if ( INCLUDE_vTaskDelete == 1 ) - { - BaseType_t xListIsEmpty; - BaseType_t core = xPortGetCoreID(); + /* uxDeletedTasksWaitingCleanUp is used to prevent taskENTER_CRITICAL() + * being called too often in the idle task. */ + while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U ) + { + TCB_t *pxTCB = NULL; - /* uxDeletedTasksWaitingCleanUp is used to prevent taskENTER_CRITICAL( &xTaskQueueMutex ) - being called too often in the idle task. */ - while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U ) - { - TCB_t *pxTCB = NULL; + taskENTER_CRITICAL(); + { + xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination ); + if( xListIsEmpty == pdFALSE ) + { + /* We only want to kill tasks that ran on this core because e.g. _xt_coproc_release needs to + be called on the core the process is pinned on, if any */ + ListItem_t *target = listGET_HEAD_ENTRY(&xTasksWaitingTermination); + for( ; target != listGET_END_MARKER(&xTasksWaitingTermination); target = listGET_NEXT(target) ){ //Walk the list + TCB_t *tgt_tcb = ( TCB_t * )listGET_LIST_ITEM_OWNER(target); + int affinity = tgt_tcb->xCoreID; + //Self deleting tasks are added to Termination List before they switch context. Ensure they aren't still currently running + if( pxCurrentTCB[core] == tgt_tcb || (portNUM_PROCESSORS > 1 && pxCurrentTCB[!core] == tgt_tcb) ){ + continue; //Can't free memory of task that is still running + } + if(affinity == core || affinity == tskNO_AFFINITY){ //Find first item not pinned to other core + pxTCB = tgt_tcb; + break; + } + } + if(pxTCB != NULL){ + ( void ) uxListRemove( target ); //Remove list item from list + --uxCurrentNumberOfTasks; + --uxDeletedTasksWaitingCleanUp; + } + } + } + taskEXIT_CRITICAL(); //Need to call deletion callbacks outside critical section - taskENTER_CRITICAL(&xTaskQueueMutex); - { - xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination ); - if( xListIsEmpty == pdFALSE ) - { - /* We only want to kill tasks that ran on this core because e.g. _xt_coproc_release needs to - be called on the core the process is pinned on, if any */ - ListItem_t *target = listGET_HEAD_ENTRY(&xTasksWaitingTermination); - for( ; target != listGET_END_MARKER(&xTasksWaitingTermination); target = listGET_NEXT(target) ){ //Walk the list - TCB_t *tgt_tcb = ( TCB_t * )listGET_LIST_ITEM_OWNER(target); - int affinity = tgt_tcb->xCoreID; - //Self deleting tasks are added to Termination List before they switch context. Ensure they aren't still currently running - if( pxCurrentTCB[core] == tgt_tcb || (portNUM_PROCESSORS > 1 && pxCurrentTCB[!core] == tgt_tcb) ){ - continue; //Can't free memory of task that is still running - } - if(affinity == core || affinity == tskNO_AFFINITY){ //Find first item not pinned to other core - pxTCB = tgt_tcb; - break; - } - } - if(pxTCB != NULL){ - ( void ) uxListRemove( target ); //Remove list item from list - --uxCurrentNumberOfTasks; - --uxDeletedTasksWaitingCleanUp; - } - } - } - taskEXIT_CRITICAL(&xTaskQueueMutex); //Need to call deletion callbacks outside critical section - - if (pxTCB != NULL) { //Call deletion callbacks and free TCB memory - #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) && ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS ) - prvDeleteTLS( pxTCB ); - #endif - prvDeleteTCB( pxTCB ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - break; //No TCB found that could be freed by this core, break out of loop - } - } - - } - #endif /* INCLUDE_vTaskDelete */ + if (pxTCB != NULL) { //Call deletion callbacks and free TCB memory + #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) && ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS ) + prvDeleteTLS( pxTCB ); + #endif + prvDeleteTCB( pxTCB ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + break; //No TCB found that could be freed by this core, break out of loop + } + } + } + #endif /* INCLUDE_vTaskDelete */ } /*-----------------------------------------------------------*/ -#if( configUSE_TRACE_FACILITY == 1 ) +#if ( configUSE_TRACE_FACILITY == 1 ) - void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState ) - { - TCB_t *pxTCB; + void vTaskGetInfo( TaskHandle_t xTask, + TaskStatus_t * pxTaskStatus, + BaseType_t xGetFreeStackSpace, + eTaskState eState ) + { + TCB_t * pxTCB; - /* xTask is NULL then get the state of the calling task. */ - pxTCB = prvGetTCBFromHandle( xTask ); + /* xTask is NULL then get the state of the calling task. */ + pxTCB = prvGetTCBFromHandle( xTask ); - pxTaskStatus->xHandle = ( TaskHandle_t ) pxTCB; - pxTaskStatus->pcTaskName = ( const char * ) &( pxTCB->pcTaskName [ 0 ] ); - pxTaskStatus->uxCurrentPriority = pxTCB->uxPriority; - pxTaskStatus->pxStackBase = pxTCB->pxStack; - pxTaskStatus->xTaskNumber = pxTCB->uxTCBNumber; + pxTaskStatus->xHandle = ( TaskHandle_t ) pxTCB; + pxTaskStatus->pcTaskName = ( const char * ) &( pxTCB->pcTaskName[ 0 ] ); + pxTaskStatus->uxCurrentPriority = pxTCB->uxPriority; + pxTaskStatus->pxStackBase = pxTCB->pxStack; + pxTaskStatus->xTaskNumber = pxTCB->uxTCBNumber; - #if ( configTASKLIST_INCLUDE_COREID == 1 ) - pxTaskStatus->xCoreID = pxTCB->xCoreID; - #endif /* configTASKLIST_INCLUDE_COREID */ + #if ( configTASKLIST_INCLUDE_COREID == 1 ) + pxTaskStatus->xCoreID = pxTCB->xCoreID; + #endif /* configTASKLIST_INCLUDE_COREID */ - #if ( configUSE_MUTEXES == 1 ) - { - pxTaskStatus->uxBasePriority = pxTCB->uxBasePriority; - } - #else - { - pxTaskStatus->uxBasePriority = 0; - } - #endif + #if ( configUSE_MUTEXES == 1 ) + { + pxTaskStatus->uxBasePriority = pxTCB->uxBasePriority; + } + #else + { + pxTaskStatus->uxBasePriority = 0; + } + #endif - #if ( configGENERATE_RUN_TIME_STATS == 1 ) - { - pxTaskStatus->ulRunTimeCounter = pxTCB->ulRunTimeCounter; - } - #else - { - pxTaskStatus->ulRunTimeCounter = 0; - } - #endif + #if ( configGENERATE_RUN_TIME_STATS == 1 ) + { + pxTaskStatus->ulRunTimeCounter = pxTCB->ulRunTimeCounter; + } + #else + { + pxTaskStatus->ulRunTimeCounter = 0; + } + #endif - /* Obtaining the task state is a little fiddly, so is only done if the - value of eState passed into this function is eInvalid - otherwise the - state is just set to whatever is passed in. */ - if( eState != eInvalid ) - { - if( pxTCB == pxCurrentTCB[xPortGetCoreID()] ) - { - pxTaskStatus->eCurrentState = eRunning; - } - else - { - pxTaskStatus->eCurrentState = eState; + /* Obtaining the task state is a little fiddly, so is only done if the + * value of eState passed into this function is eInvalid - otherwise the + * state is just set to whatever is passed in. */ + if( eState != eInvalid ) + { + if( pxTCB == pxCurrentTCB[xPortGetCoreID()] ) + { + pxTaskStatus->eCurrentState = eRunning; + } + else + { + pxTaskStatus->eCurrentState = eState; - #if ( INCLUDE_vTaskSuspend == 1 ) - { - /* If the task is in the suspended list then there is a - chance it is actually just blocked indefinitely - so really - it should be reported as being in the Blocked state. */ - if( eState == eSuspended ) - { - taskENTER_CRITICAL( &xTaskQueueMutex ); - { - if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) - { - pxTaskStatus->eCurrentState = eBlocked; - } - } - taskEXIT_CRITICAL( &xTaskQueueMutex ); - } - } - #endif /* INCLUDE_vTaskSuspend */ - } - } - else - { - pxTaskStatus->eCurrentState = eTaskGetState( pxTCB ); - } + #if ( INCLUDE_vTaskSuspend == 1 ) + { + /* If the task is in the suspended list then there is a + * chance it is actually just blocked indefinitely - so really + * it should be reported as being in the Blocked state. */ + if( eState == eSuspended ) + { +#ifdef ESP_PLATFORM // IDF-3755 + taskENTER_CRITICAL(); +#else + vTaskSuspendAll(); +#endif // ESP_PLATFORM + { + if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) + { + pxTaskStatus->eCurrentState = eBlocked; + } + } +#ifdef ESP_PLATFORM // IDF-3755 + taskEXIT_CRITICAL(); +#else + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM + } + } + #endif /* INCLUDE_vTaskSuspend */ + } + } + else + { + pxTaskStatus->eCurrentState = eTaskGetState( pxTCB ); + } - /* Obtaining the stack space takes some time, so the xGetFreeStackSpace - parameter is provided to allow it to be skipped. */ - if( xGetFreeStackSpace != pdFALSE ) - { - #if ( portSTACK_GROWTH > 0 ) - { - pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxEndOfStack ); - } - #else - { - pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxStack ); - } - #endif - } - else - { - pxTaskStatus->usStackHighWaterMark = 0; - } - } + /* Obtaining the stack space takes some time, so the xGetFreeStackSpace + * parameter is provided to allow it to be skipped. */ + if( xGetFreeStackSpace != pdFALSE ) + { + #if ( portSTACK_GROWTH > 0 ) + { + pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxEndOfStack ); + } + #else + { + pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxStack ); + } + #endif + } + else + { + pxTaskStatus->usStackHighWaterMark = 0; + } + } #endif /* configUSE_TRACE_FACILITY */ /*-----------------------------------------------------------*/ BaseType_t xTaskGetAffinity( TaskHandle_t xTask ) { - TCB_t *pxTCB; + TCB_t *pxTCB; - pxTCB = prvGetTCBFromHandle( xTask ); + pxTCB = prvGetTCBFromHandle( xTask ); - return pxTCB->xCoreID; + return pxTCB->xCoreID; } /*-----------------------------------------------------------*/ #if ( configUSE_TRACE_FACILITY == 1 ) - static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState ) - { - configLIST_VOLATILE TCB_t *pxNextTCB, *pxFirstTCB; - UBaseType_t uxTask = 0; + static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t * pxTaskStatusArray, + List_t * pxList, + eTaskState eState ) + { + configLIST_VOLATILE TCB_t * pxNextTCB, * pxFirstTCB; + UBaseType_t uxTask = 0; - if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 ) - { - listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ + if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 ) + { + listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ - /* Populate an TaskStatus_t structure within the - pxTaskStatusArray array for each task that is referenced from - pxList. See the definition of TaskStatus_t in task.h for the - meaning of each TaskStatus_t structure member. */ - do - { - listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ - vTaskGetInfo( ( TaskHandle_t ) pxNextTCB, &( pxTaskStatusArray[ uxTask ] ), pdTRUE, eState ); - uxTask++; - } while( pxNextTCB != pxFirstTCB ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* Populate an TaskStatus_t structure within the + * pxTaskStatusArray array for each task that is referenced from + * pxList. See the definition of TaskStatus_t in task.h for the + * meaning of each TaskStatus_t structure member. */ + do + { + listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ + vTaskGetInfo( ( TaskHandle_t ) pxNextTCB, &( pxTaskStatusArray[ uxTask ] ), pdTRUE, eState ); + uxTask++; + } while( pxNextTCB != pxFirstTCB ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - return uxTask; - } + return uxTask; + } #endif /* configUSE_TRACE_FACILITY */ /*-----------------------------------------------------------*/ #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) ) - static configSTACK_DEPTH_TYPE prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) - { - uint32_t ulCount = 0U; + static configSTACK_DEPTH_TYPE prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) + { + uint32_t ulCount = 0U; - while( *pucStackByte == ( uint8_t ) tskSTACK_FILL_BYTE ) - { - pucStackByte -= portSTACK_GROWTH; - ulCount++; - } + while( *pucStackByte == ( uint8_t ) tskSTACK_FILL_BYTE ) + { + pucStackByte -= portSTACK_GROWTH; + ulCount++; + } - ulCount /= ( uint32_t ) sizeof( StackType_t ); /*lint !e961 Casting is not redundant on smaller architectures. */ + ulCount /= ( uint32_t ) sizeof( StackType_t ); /*lint !e961 Casting is not redundant on smaller architectures. */ - return ( configSTACK_DEPTH_TYPE ) ulCount; - } + return ( configSTACK_DEPTH_TYPE ) ulCount; + } #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) ) */ /*-----------------------------------------------------------*/ #if ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) - /* uxTaskGetStackHighWaterMark() and uxTaskGetStackHighWaterMark2() are the - same except for their return type. Using configSTACK_DEPTH_TYPE allows the - user to determine the return type. It gets around the problem of the value - overflowing on 8-bit types without breaking backward compatibility for - applications that expect an 8-bit return type. */ - configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) - { - TCB_t *pxTCB; - uint8_t *pucEndOfStack; - configSTACK_DEPTH_TYPE uxReturn; +/* uxTaskGetStackHighWaterMark() and uxTaskGetStackHighWaterMark2() are the + * same except for their return type. Using configSTACK_DEPTH_TYPE allows the + * user to determine the return type. It gets around the problem of the value + * overflowing on 8-bit types without breaking backward compatibility for + * applications that expect an 8-bit return type. */ + configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) + { + TCB_t * pxTCB; + uint8_t * pucEndOfStack; + configSTACK_DEPTH_TYPE uxReturn; - /* uxTaskGetStackHighWaterMark() and uxTaskGetStackHighWaterMark2() are - the same except for their return type. Using configSTACK_DEPTH_TYPE - allows the user to determine the return type. It gets around the - problem of the value overflowing on 8-bit types without breaking - backward compatibility for applications that expect an 8-bit return - type. */ + /* uxTaskGetStackHighWaterMark() and uxTaskGetStackHighWaterMark2() are + * the same except for their return type. Using configSTACK_DEPTH_TYPE + * allows the user to determine the return type. It gets around the + * problem of the value overflowing on 8-bit types without breaking + * backward compatibility for applications that expect an 8-bit return + * type. */ - pxTCB = prvGetTCBFromHandle( xTask ); + pxTCB = prvGetTCBFromHandle( xTask ); - #if portSTACK_GROWTH < 0 - { - pucEndOfStack = ( uint8_t * ) pxTCB->pxStack; - } - #else - { - pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack; - } - #endif + #if portSTACK_GROWTH < 0 + { + pucEndOfStack = ( uint8_t * ) pxTCB->pxStack; + } + #else + { + pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack; + } + #endif - uxReturn = prvTaskCheckFreeStackSpace( pucEndOfStack ); + uxReturn = prvTaskCheckFreeStackSpace( pucEndOfStack ); - return uxReturn; - } + return uxReturn; + } #endif /* INCLUDE_uxTaskGetStackHighWaterMark2 */ /*-----------------------------------------------------------*/ #if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) - UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) - { - TCB_t *pxTCB; - uint8_t *pucEndOfStack; - UBaseType_t uxReturn; + UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) + { + TCB_t * pxTCB; + uint8_t * pucEndOfStack; + UBaseType_t uxReturn; - pxTCB = prvGetTCBFromHandle( xTask ); + pxTCB = prvGetTCBFromHandle( xTask ); - #if portSTACK_GROWTH < 0 - { - pucEndOfStack = ( uint8_t * ) pxTCB->pxStack; - } - #else - { - pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack; - } - #endif + #if portSTACK_GROWTH < 0 + { + pucEndOfStack = ( uint8_t * ) pxTCB->pxStack; + } + #else + { + pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack; + } + #endif - uxReturn = ( UBaseType_t ) prvTaskCheckFreeStackSpace( pucEndOfStack ); + uxReturn = ( UBaseType_t ) prvTaskCheckFreeStackSpace( pucEndOfStack ); - return uxReturn; - } + return uxReturn; + } #endif /* INCLUDE_uxTaskGetStackHighWaterMark */ /*-----------------------------------------------------------*/ #if (INCLUDE_pxTaskGetStackStart == 1) - uint8_t* pxTaskGetStackStart( TaskHandle_t xTask) - { - TCB_t *pxTCB; - uint8_t* uxReturn; + uint8_t* pxTaskGetStackStart( TaskHandle_t xTask) + { + TCB_t *pxTCB; + uint8_t* uxReturn; - pxTCB = prvGetTCBFromHandle( xTask ); - uxReturn = (uint8_t*)pxTCB->pxStack; + pxTCB = prvGetTCBFromHandle( xTask ); + uxReturn = (uint8_t*)pxTCB->pxStack; - return uxReturn; - } + return uxReturn; + } #endif /* INCLUDE_pxTaskGetStackStart */ #if ( INCLUDE_vTaskDelete == 1 ) - static void prvDeleteTCB( TCB_t *pxTCB ) - { - /* This call is required specifically for the TriCore port. It must be - above the vPortFree() calls. The call is also used by ports/demos that - want to allocate and clean RAM statically. */ - portCLEAN_UP_TCB( pxTCB ); + static void prvDeleteTCB( TCB_t * pxTCB ) + { + /* This call is required specifically for the TriCore port. It must be + * above the vPortFree() calls. The call is also used by ports/demos that + * want to allocate and clean RAM statically. */ + portCLEAN_UP_TCB( pxTCB ); - /* Free up the memory allocated by the scheduler for the task. It is up - to the task to free any memory allocated at the application level. */ - #if ( configUSE_NEWLIB_REENTRANT == 1 ) - { - _reclaim_reent( &( pxTCB->xNewLib_reent ) ); - } - #endif /* configUSE_NEWLIB_REENTRANT */ + /* Free up the memory allocated by the scheduler for the task. It is up + * to the task to free any memory allocated at the application level. + * See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html + * for additional information. */ + #if ( configUSE_NEWLIB_REENTRANT == 1 ) + { + _reclaim_reent( &( pxTCB->xNewLib_reent ) ); + } + #endif /* configUSE_NEWLIB_REENTRANT */ - #if ( portUSING_MPU_WRAPPERS == 1 ) - vPortReleaseTaskMPUSettings( &( pxTCB->xMPUSettings) ); - #endif + #if ( portUSING_MPU_WRAPPERS == 1 ) + vPortReleaseTaskMPUSettings( &( pxTCB->xMPUSettings) ); + #endif - #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( portUSING_MPU_WRAPPERS == 0 ) ) - { - /* The task can only have been allocated dynamically - free both - the stack and TCB. */ - vPortFree( pxTCB->pxStack ); - vPortFree( pxTCB ); - } - #elif( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */ - { - /* The task could have been allocated statically or dynamically, so - check what was statically allocated before trying to free the - memory. */ - if( pxTCB->ucStaticallyAllocated == tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB ) - { - /* Both the stack and TCB were allocated dynamically, so both - must be freed. */ - vPortFree( pxTCB->pxStack ); - vPortFree( pxTCB ); - } - else if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_ONLY ) - { - /* Only the stack was statically allocated, so the TCB is the - only memory that must be freed. */ - vPortFree( pxTCB ); - } - else - { - /* Neither the stack nor the TCB were allocated dynamically, so - nothing needs to be freed. */ - configASSERT( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB ); - mtCOVERAGE_TEST_MARKER(); - } - } - #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ - } + #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( portUSING_MPU_WRAPPERS == 0 ) ) + { + /* The task can only have been allocated dynamically - free both + * the stack and TCB. */ + vPortFree( pxTCB->pxStack ); + vPortFree( pxTCB ); + } + #elif ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */ + { + /* The task could have been allocated statically or dynamically, so + * check what was statically allocated before trying to free the + * memory. */ + if( pxTCB->ucStaticallyAllocated == tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB ) + { + /* Both the stack and TCB were allocated dynamically, so both + * must be freed. */ + vPortFree( pxTCB->pxStack ); + vPortFree( pxTCB ); + } + else if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_ONLY ) + { + /* Only the stack was statically allocated, so the TCB is the + * only memory that must be freed. */ + vPortFree( pxTCB ); + } + else + { + /* Neither the stack nor the TCB were allocated dynamically, so + * nothing needs to be freed. */ + configASSERT( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB ); + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ + } #endif /* INCLUDE_vTaskDelete */ /*-----------------------------------------------------------*/ #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) && ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS ) - static void prvDeleteTLS( TCB_t *pxTCB ) - { - configASSERT( pxTCB ); - for( int x = 0; x < configNUM_THREAD_LOCAL_STORAGE_POINTERS; x++ ) - { - if (pxTCB->pvThreadLocalStoragePointersDelCallback[ x ] != NULL) //If del cb is set - { - pxTCB->pvThreadLocalStoragePointersDelCallback[ x ](x, pxTCB->pvThreadLocalStoragePointers[ x ]); //Call del cb - } - } - } + static void prvDeleteTLS( TCB_t *pxTCB ) + { + configASSERT( pxTCB ); + for( int x = 0; x < configNUM_THREAD_LOCAL_STORAGE_POINTERS; x++ ) + { + if (pxTCB->pvThreadLocalStoragePointersDelCallback[ x ] != NULL) //If del cb is set + { + pxTCB->pvThreadLocalStoragePointersDelCallback[ x ](x, pxTCB->pvThreadLocalStoragePointers[ x ]); //Call del cb + } + } + } #endif /* ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) && ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS ) */ /*-----------------------------------------------------------*/ @@ -4432,1583 +4591,1477 @@ BaseType_t xTaskGetAffinity( TaskHandle_t xTask ) static void prvResetNextTaskUnblockTime( void ) { -TCB_t *pxTCB; + TCB_t * pxTCB; - if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) - { - /* The new current delayed list is empty. Set xNextTaskUnblockTime to - the maximum possible value so it is extremely unlikely that the - if( xTickCount >= xNextTaskUnblockTime ) test will pass until - there is an item in the delayed list. */ - xNextTaskUnblockTime = portMAX_DELAY; - } - else - { - /* The new current delayed list is not empty, get the value of - the item at the head of the delayed list. This is the time at - which the task at the head of the delayed list should be removed - from the Blocked state. */ - ( pxTCB ) = listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ - xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( ( pxTCB )->xStateListItem ) ); - } + if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) + { + /* The new current delayed list is empty. Set xNextTaskUnblockTime to + * the maximum possible value so it is extremely unlikely that the + * if( xTickCount >= xNextTaskUnblockTime ) test will pass until + * there is an item in the delayed list. */ + xNextTaskUnblockTime = portMAX_DELAY; + } + else + { + /* The new current delayed list is not empty, get the value of + * the item at the head of the delayed list. This is the time at + * which the task at the head of the delayed list should be removed + * from the Blocked state. */ + ( pxTCB ) = listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ + xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( ( pxTCB )->xStateListItem ) ); + } } /*-----------------------------------------------------------*/ #if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) || (portNUM_PROCESSORS > 1) ) - TaskHandle_t xTaskGetCurrentTaskHandle( void ) - { - TaskHandle_t xReturn; - unsigned state; + TaskHandle_t xTaskGetCurrentTaskHandle( void ) + { + TaskHandle_t xReturn; + unsigned state; - state = portENTER_CRITICAL_NESTED(); - xReturn = pxCurrentTCB[ xPortGetCoreID() ]; - portEXIT_CRITICAL_NESTED(state); + state = portENTER_CRITICAL_NESTED(); + xReturn = pxCurrentTCB[ xPortGetCoreID() ]; + portEXIT_CRITICAL_NESTED(state); - return xReturn; - } + return xReturn; + } - TaskHandle_t xTaskGetCurrentTaskHandleForCPU( BaseType_t cpuid ) - { - TaskHandle_t xReturn=NULL; + TaskHandle_t xTaskGetCurrentTaskHandleForCPU( BaseType_t cpuid ) + { + TaskHandle_t xReturn=NULL; - //Xtensa-specific: the pxCurrentPCB pointer is atomic so we shouldn't need a lock. - if (cpuid < portNUM_PROCESSORS) { - xReturn = pxCurrentTCB[ cpuid ]; - } + //Xtensa-specific: the pxCurrentPCB pointer is atomic so we shouldn't need a lock. + if (cpuid < portNUM_PROCESSORS) { + xReturn = pxCurrentTCB[ cpuid ]; + } - return xReturn; - } + return xReturn; + } #endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */ /*-----------------------------------------------------------*/ #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) - BaseType_t xTaskGetSchedulerState( void ) - { - BaseType_t xReturn; + BaseType_t xTaskGetSchedulerState( void ) + { + BaseType_t xReturn; - if( xSchedulerRunning == pdFALSE ) - { - xReturn = taskSCHEDULER_NOT_STARTED; - } - else - { - if( uxSchedulerSuspended[xPortGetCoreID()] == ( UBaseType_t ) pdFALSE ) - { - xReturn = taskSCHEDULER_RUNNING; - } - else - { - xReturn = taskSCHEDULER_SUSPENDED; - } - } + if( xSchedulerRunning == pdFALSE ) + { + xReturn = taskSCHEDULER_NOT_STARTED; + } + else + { + if( uxSchedulerSuspended[xPortGetCoreID()] == ( UBaseType_t ) pdFALSE ) + { + xReturn = taskSCHEDULER_RUNNING; + } + else + { + xReturn = taskSCHEDULER_SUSPENDED; + } + } - return xReturn; - } + return xReturn; + } #endif /* ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) */ /*-----------------------------------------------------------*/ #if ( configUSE_MUTEXES == 1 ) - BaseType_t xTaskPriorityInherit( TaskHandle_t const pxMutexHolder ) - { - TCB_t * const pxMutexHolderTCB = pxMutexHolder; - BaseType_t xReturn = pdFALSE; + BaseType_t xTaskPriorityInherit( TaskHandle_t const pxMutexHolder ) + { + TCB_t * const pxMutexHolderTCB = pxMutexHolder; + BaseType_t xReturn = pdFALSE; - taskENTER_CRITICAL(&xTaskQueueMutex); - /* If the mutex was given back by an interrupt while the queue was - locked then the mutex holder might now be NULL. _RB_ Is this still - needed as interrupts can no longer use mutexes? */ - if( pxMutexHolder != NULL ) - { - /* If the holder of the mutex has a priority below the priority of - the task attempting to obtain the mutex then it will temporarily - inherit the priority of the task attempting to obtain the mutex. */ - if( pxMutexHolderTCB->uxPriority < pxCurrentTCB[xPortGetCoreID()]->uxPriority ) - { - /* Adjust the mutex holder state to account for its new - priority. Only reset the event list item value if the value is - not being used for anything else. */ - if( ( listGET_LIST_ITEM_VALUE( &( pxMutexHolderTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL ) - { - listSET_LIST_ITEM_VALUE( &( pxMutexHolderTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB[xPortGetCoreID()]->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + taskENTER_CRITICAL(); + /* If the mutex was given back by an interrupt while the queue was + * locked then the mutex holder might now be NULL. _RB_ Is this still + * needed as interrupts can no longer use mutexes? */ + if( pxMutexHolder != NULL ) + { + /* If the holder of the mutex has a priority below the priority of + * the task attempting to obtain the mutex then it will temporarily + * inherit the priority of the task attempting to obtain the mutex. */ + if( pxMutexHolderTCB->uxPriority < pxCurrentTCB[xPortGetCoreID()]->uxPriority ) + { + /* Adjust the mutex holder state to account for its new + * priority. Only reset the event list item value if the value is + * not being used for anything else. */ + if( ( listGET_LIST_ITEM_VALUE( &( pxMutexHolderTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL ) + { + listSET_LIST_ITEM_VALUE( &( pxMutexHolderTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB[xPortGetCoreID()]->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - /* If the task being modified is in the ready state it will need - to be moved into a new list. */ - if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxMutexHolderTCB->uxPriority ] ), &( pxMutexHolderTCB->xStateListItem ) ) != pdFALSE ) - { - if( uxListRemove( &( pxMutexHolderTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) - { - /* It is known that the task is in its ready list so - there is no need to check again and the port level - reset macro can be called directly. */ - portRESET_READY_PRIORITY( pxMutexHolderTCB->uxPriority, uxTopReadyPriority ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* If the task being modified is in the ready state it will need + * to be moved into a new list. */ + if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxMutexHolderTCB->uxPriority ] ), &( pxMutexHolderTCB->xStateListItem ) ) != pdFALSE ) + { + if( uxListRemove( &( pxMutexHolderTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) + { + /* It is known that the task is in its ready list so + * there is no need to check again and the port level + * reset macro can be called directly. */ + portRESET_READY_PRIORITY( pxMutexHolderTCB->uxPriority, uxTopReadyPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - /* Inherit the priority before being moved into the new list. */ - pxMutexHolderTCB->uxPriority = pxCurrentTCB[xPortGetCoreID()]->uxPriority; - prvAddTaskToReadyList( pxMutexHolderTCB ); - } - else - { - /* Just inherit the priority. */ - pxMutexHolderTCB->uxPriority = pxCurrentTCB[xPortGetCoreID()]->uxPriority; - } + /* Inherit the priority before being moved into the new list. */ + pxMutexHolderTCB->uxPriority = pxCurrentTCB[xPortGetCoreID()]->uxPriority; + prvAddTaskToReadyList( pxMutexHolderTCB ); + } + else + { + /* Just inherit the priority. */ + pxMutexHolderTCB->uxPriority = pxCurrentTCB[xPortGetCoreID()]->uxPriority; + } - traceTASK_PRIORITY_INHERIT( pxMutexHolderTCB, pxCurrentTCB[xPortGetCoreID()]->uxPriority ); + traceTASK_PRIORITY_INHERIT( pxMutexHolderTCB, pxCurrentTCB[xPortGetCoreID()]->uxPriority ); - /* Inheritance occurred. */ - xReturn = pdTRUE; - } - else - { - if( pxMutexHolderTCB->uxBasePriority < pxCurrentTCB[xPortGetCoreID()]->uxPriority ) - { - /* The base priority of the mutex holder is lower than the - priority of the task attempting to take the mutex, but the - current priority of the mutex holder is not lower than the - priority of the task attempting to take the mutex. - Therefore the mutex holder must have already inherited a - priority, but inheritance would have occurred if that had - not been the case. */ - xReturn = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - taskEXIT_CRITICAL(&xTaskQueueMutex); + /* Inheritance occurred. */ + xReturn = pdTRUE; + } + else + { + if( pxMutexHolderTCB->uxBasePriority < pxCurrentTCB[xPortGetCoreID()]->uxPriority ) + { + /* The base priority of the mutex holder is lower than the + * priority of the task attempting to take the mutex, but the + * current priority of the mutex holder is not lower than the + * priority of the task attempting to take the mutex. + * Therefore the mutex holder must have already inherited a + * priority, but inheritance would have occurred if that had + * not been the case. */ + xReturn = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + taskEXIT_CRITICAL(); - return xReturn; - } + return xReturn; + } #endif /* configUSE_MUTEXES */ /*-----------------------------------------------------------*/ #if ( configUSE_MUTEXES == 1 ) - BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder ) - { - TCB_t * const pxTCB = pxMutexHolder; - BaseType_t xReturn = pdFALSE; + BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder ) + { + TCB_t * const pxTCB = pxMutexHolder; + BaseType_t xReturn = pdFALSE; - taskENTER_CRITICAL(&xTaskQueueMutex); - if( pxMutexHolder != NULL ) - { - /* A task can only have an inherited priority if it holds the mutex. - If the mutex is held by a task then it cannot be given from an - interrupt, and if a mutex is given by the holding task then it must - be the running state task. */ - configASSERT( pxTCB == pxCurrentTCB[xPortGetCoreID()] ); - configASSERT( pxTCB->uxMutexesHeld ); - ( pxTCB->uxMutexesHeld )--; + taskENTER_CRITICAL(); + if( pxMutexHolder != NULL ) + { + /* A task can only have an inherited priority if it holds the mutex. + * If the mutex is held by a task then it cannot be given from an + * interrupt, and if a mutex is given by the holding task then it must + * be the running state task. */ + configASSERT( pxTCB == pxCurrentTCB[xPortGetCoreID()] ); + configASSERT( pxTCB->uxMutexesHeld ); + ( pxTCB->uxMutexesHeld )--; - /* Has the holder of the mutex inherited the priority of another - task? */ - if( pxTCB->uxPriority != pxTCB->uxBasePriority ) - { - /* Only disinherit if no other mutexes are held. */ - if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 ) - { - /* A task can only have an inherited priority if it holds - the mutex. If the mutex is held by a task then it cannot be - given from an interrupt, and if a mutex is given by the - holding task then it must be the running state task. Remove - the holding task from the ready/delayed list. */ - if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) - { - taskRESET_READY_PRIORITY( pxTCB->uxPriority ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* Has the holder of the mutex inherited the priority of another + * task? */ + if( pxTCB->uxPriority != pxTCB->uxBasePriority ) + { + /* Only disinherit if no other mutexes are held. */ + if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 ) + { + /* A task can only have an inherited priority if it holds + * the mutex. If the mutex is held by a task then it cannot be + * given from an interrupt, and if a mutex is given by the + * holding task then it must be the running state task. Remove + * the holding task from the ready list. */ + if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) + { + taskRESET_READY_PRIORITY( pxTCB->uxPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - /* Disinherit the priority before adding the task into the - new ready list. */ - traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority ); - pxTCB->uxPriority = pxTCB->uxBasePriority; + /* Disinherit the priority before adding the task into the + * new ready list. */ + traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority ); + pxTCB->uxPriority = pxTCB->uxBasePriority; - /* Reset the event list item value. It cannot be in use for - any other purpose if this task is running, and it must be - running to give back the mutex. */ - listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ - prvAddTaskToReadyList( pxTCB ); + /* Reset the event list item value. It cannot be in use for + * any other purpose if this task is running, and it must be + * running to give back the mutex. */ + listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + prvAddTaskToReadyList( pxTCB ); - /* Return true to indicate that a context switch is required. - This is only actually required in the corner case whereby - multiple mutexes were held and the mutexes were given back - in an order different to that in which they were taken. - If a context switch did not occur when the first mutex was - returned, even if a task was waiting on it, then a context - switch should occur when the last mutex is returned whether - a task is waiting on it or not. */ - xReturn = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - taskEXIT_CRITICAL(&xTaskQueueMutex); + /* Return true to indicate that a context switch is required. + * This is only actually required in the corner case whereby + * multiple mutexes were held and the mutexes were given back + * in an order different to that in which they were taken. + * If a context switch did not occur when the first mutex was + * returned, even if a task was waiting on it, then a context + * switch should occur when the last mutex is returned whether + * a task is waiting on it or not. */ + xReturn = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + taskEXIT_CRITICAL(); - return xReturn; - } + return xReturn; + } #endif /* configUSE_MUTEXES */ /*-----------------------------------------------------------*/ #if ( configUSE_MUTEXES == 1 ) - void vTaskPriorityDisinheritAfterTimeout( TaskHandle_t const pxMutexHolder, UBaseType_t uxHighestPriorityWaitingTask ) - { - TCB_t * const pxTCB = pxMutexHolder; - UBaseType_t uxPriorityUsedOnEntry, uxPriorityToUse; - const UBaseType_t uxOnlyOneMutexHeld = ( UBaseType_t ) 1; + void vTaskPriorityDisinheritAfterTimeout( TaskHandle_t const pxMutexHolder, + UBaseType_t uxHighestPriorityWaitingTask ) + { + TCB_t * const pxTCB = pxMutexHolder; + UBaseType_t uxPriorityUsedOnEntry, uxPriorityToUse; + const UBaseType_t uxOnlyOneMutexHeld = ( UBaseType_t ) 1; - taskENTER_CRITICAL(&xTaskQueueMutex); - if( pxMutexHolder != NULL ) - { - /* If pxMutexHolder is not NULL then the holder must hold at least - one mutex. */ - configASSERT( pxTCB->uxMutexesHeld ); + taskENTER_CRITICAL(); + if( pxMutexHolder != NULL ) + { + /* If pxMutexHolder is not NULL then the holder must hold at least + * one mutex. */ + configASSERT( pxTCB->uxMutexesHeld ); - /* Determine the priority to which the priority of the task that - holds the mutex should be set. This will be the greater of the - holding task's base priority and the priority of the highest - priority task that is waiting to obtain the mutex. */ - if( pxTCB->uxBasePriority < uxHighestPriorityWaitingTask ) - { - uxPriorityToUse = uxHighestPriorityWaitingTask; - } - else - { - uxPriorityToUse = pxTCB->uxBasePriority; - } + /* Determine the priority to which the priority of the task that + * holds the mutex should be set. This will be the greater of the + * holding task's base priority and the priority of the highest + * priority task that is waiting to obtain the mutex. */ + if( pxTCB->uxBasePriority < uxHighestPriorityWaitingTask ) + { + uxPriorityToUse = uxHighestPriorityWaitingTask; + } + else + { + uxPriorityToUse = pxTCB->uxBasePriority; + } - /* Does the priority need to change? */ - if( pxTCB->uxPriority != uxPriorityToUse ) - { - /* Only disinherit if no other mutexes are held. This is a - simplification in the priority inheritance implementation. If - the task that holds the mutex is also holding other mutexes then - the other mutexes may have caused the priority inheritance. */ - if( pxTCB->uxMutexesHeld == uxOnlyOneMutexHeld ) - { - /* If a task has timed out because it already holds the - mutex it was trying to obtain then it cannot of inherited - its own priority. */ - configASSERT( pxTCB != pxCurrentTCB[xPortGetCoreID()] ); + /* Does the priority need to change? */ + if( pxTCB->uxPriority != uxPriorityToUse ) + { + /* Only disinherit if no other mutexes are held. This is a + * simplification in the priority inheritance implementation. If + * the task that holds the mutex is also holding other mutexes then + * the other mutexes may have caused the priority inheritance. */ + if( pxTCB->uxMutexesHeld == uxOnlyOneMutexHeld ) + { + /* If a task has timed out because it already holds the + * mutex it was trying to obtain then it cannot of inherited + * its own priority. */ + configASSERT( pxTCB != pxCurrentTCB[xPortGetCoreID()] ); - /* Disinherit the priority, remembering the previous - priority to facilitate determining the subject task's - state. */ - traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority ); - uxPriorityUsedOnEntry = pxTCB->uxPriority; - pxTCB->uxPriority = uxPriorityToUse; + /* Disinherit the priority, remembering the previous + * priority to facilitate determining the subject task's + * state. */ + traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority ); + uxPriorityUsedOnEntry = pxTCB->uxPriority; + pxTCB->uxPriority = uxPriorityToUse; - /* Only reset the event list item value if the value is not - being used for anything else. */ - if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL ) - { - listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriorityToUse ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* Only reset the event list item value if the value is not + * being used for anything else. */ + if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL ) + { + listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriorityToUse ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - /* If the running task is not the task that holds the mutex - then the task that holds the mutex could be in either the - Ready, Blocked or Suspended states. Only remove the task - from its current state list if it is in the Ready state as - the task's priority is going to change and there is one - Ready list per priority. */ - if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE ) - { - if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) - { - /* It is known that the task is in its ready list so - there is no need to check again and the port level - reset macro can be called directly. */ - portRESET_READY_PRIORITY( pxTCB->uxPriority, uxTopReadyPriority ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* If the running task is not the task that holds the mutex + * then the task that holds the mutex could be in either the + * Ready, Blocked or Suspended states. Only remove the task + * from its current state list if it is in the Ready state as + * the task's priority is going to change and there is one + * Ready list per priority. */ + if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE ) + { + if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) + { + /* It is known that the task is in its ready list so + * there is no need to check again and the port level + * reset macro can be called directly. */ + portRESET_READY_PRIORITY( pxTCB->uxPriority, uxTopReadyPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - prvAddTaskToReadyList( pxTCB ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - taskEXIT_CRITICAL(&xTaskQueueMutex); - } + prvAddTaskToReadyList( pxTCB ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + taskEXIT_CRITICAL(); + } #endif /* configUSE_MUTEXES */ /*-----------------------------------------------------------*/ #if ( portCRITICAL_NESTING_IN_TCB == 1 ) - void vTaskEnterCritical( void ) - { - portDISABLE_INTERRUPTS(); + void vTaskEnterCritical( void ) + { + portDISABLE_INTERRUPTS(); - if( xSchedulerRunning != pdFALSE ) - { - ( pxCurrentTCB[xPortGetCoreID()]->uxCriticalNesting )++; + if( xSchedulerRunning != pdFALSE ) + { + ( pxCurrentTCB[xPortGetCoreID()]->uxCriticalNesting )++; - /* This is not the interrupt safe version of the enter critical - function so assert() if it is being called from an interrupt - context. Only API functions that end in "FromISR" can be used in an - interrupt. Only assert if the critical nesting count is 1 to - protect against recursive calls if the assert function also uses a - critical section. */ - if( pxCurrentTCB[xPortGetCoreID()]->uxCriticalNesting == 1 ) - { - portASSERT_IF_IN_ISR(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } + /* This is not the interrupt safe version of the enter critical + * function so assert() if it is being called from an interrupt + * context. Only API functions that end in "FromISR" can be used in an + * interrupt. Only assert if the critical nesting count is 1 to + * protect against recursive calls if the assert function also uses a + * critical section. */ + if( pxCurrentTCB[xPortGetCoreID()]->uxCriticalNesting == 1 ) + { + portASSERT_IF_IN_ISR(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } #endif /* portCRITICAL_NESTING_IN_TCB */ /*-----------------------------------------------------------*/ #if ( portCRITICAL_NESTING_IN_TCB == 1 ) - void vTaskExitCritical( void ) - { - if( xSchedulerRunning != pdFALSE ) - { - if( pxCurrentTCB[xPortGetCoreID()]->uxCriticalNesting > 0U ) - { - ( pxCurrentTCB[xPortGetCoreID()]->uxCriticalNesting )--; + void vTaskExitCritical( void ) + { + if( xSchedulerRunning != pdFALSE ) + { + if( pxCurrentTCB[xPortGetCoreID()]->uxCriticalNesting > 0U ) + { + ( pxCurrentTCB[xPortGetCoreID()]->uxCriticalNesting )--; - if( pxCurrentTCB[xPortGetCoreID()]->uxCriticalNesting == 0U ) - { - portENABLE_INTERRUPTS(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } + if( pxCurrentTCB[xPortGetCoreID()]->uxCriticalNesting == 0U ) + { + portENABLE_INTERRUPTS(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } #endif /* portCRITICAL_NESTING_IN_TCB */ /*-----------------------------------------------------------*/ #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) - static char *prvWriteNameToBuffer( char *pcBuffer, const char *pcTaskName ) - { - size_t x; + static char * prvWriteNameToBuffer( char * pcBuffer, + const char * pcTaskName ) + { + size_t x; - /* Start by copying the entire string. */ - strcpy( pcBuffer, pcTaskName ); + /* Start by copying the entire string. */ + strcpy( pcBuffer, pcTaskName ); - /* Pad the end of the string with spaces to ensure columns line up when - printed out. */ - for( x = strlen( pcBuffer ); x < ( size_t ) ( configMAX_TASK_NAME_LEN - 1 ); x++ ) - { - pcBuffer[ x ] = ' '; - } + /* Pad the end of the string with spaces to ensure columns line up when + * printed out. */ + for( x = strlen( pcBuffer ); x < ( size_t ) ( configMAX_TASK_NAME_LEN - 1 ); x++ ) + { + pcBuffer[ x ] = ' '; + } - /* Terminate. */ - pcBuffer[ x ] = ( char ) 0x00; + /* Terminate. */ + pcBuffer[ x ] = ( char ) 0x00; - /* Return the new end of string. */ - return &( pcBuffer[ x ] ); - } + /* Return the new end of string. */ + return &( pcBuffer[ x ] ); + } #endif /* ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) */ /*-----------------------------------------------------------*/ #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) - void vTaskList( char * pcWriteBuffer ) - { - TaskStatus_t *pxTaskStatusArray; - UBaseType_t uxArraySize, x; - char cStatus; + void vTaskList( char * pcWriteBuffer ) + { + TaskStatus_t * pxTaskStatusArray; + UBaseType_t uxArraySize, x; + char cStatus; - /* - * PLEASE NOTE: - * - * This function is provided for convenience only, and is used by many - * of the demo applications. Do not consider it to be part of the - * scheduler. - * - * vTaskList() calls uxTaskGetSystemState(), then formats part of the - * uxTaskGetSystemState() output into a human readable table that - * displays task names, states and stack usage. - * - * vTaskList() has a dependency on the sprintf() C library function that - * might bloat the code size, use a lot of stack, and provide different - * results on different platforms. An alternative, tiny, third party, - * and limited functionality implementation of sprintf() is provided in - * many of the FreeRTOS/Demo sub-directories in a file called - * printf-stdarg.c (note printf-stdarg.c does not provide a full - * snprintf() implementation!). - * - * It is recommended that production systems call uxTaskGetSystemState() - * directly to get access to raw stats data, rather than indirectly - * through a call to vTaskList(). - */ + /* + * PLEASE NOTE: + * + * This function is provided for convenience only, and is used by many + * of the demo applications. Do not consider it to be part of the + * scheduler. + * + * vTaskList() calls uxTaskGetSystemState(), then formats part of the + * uxTaskGetSystemState() output into a human readable table that + * displays task names, states and stack usage. + * + * vTaskList() has a dependency on the sprintf() C library function that + * might bloat the code size, use a lot of stack, and provide different + * results on different platforms. An alternative, tiny, third party, + * and limited functionality implementation of sprintf() is provided in + * many of the FreeRTOS/Demo sub-directories in a file called + * printf-stdarg.c (note printf-stdarg.c does not provide a full + * snprintf() implementation!). + * + * It is recommended that production systems call uxTaskGetSystemState() + * directly to get access to raw stats data, rather than indirectly + * through a call to vTaskList(). + */ - /* Make sure the write buffer does not contain a string. */ - *pcWriteBuffer = ( char ) 0x00; + /* Make sure the write buffer does not contain a string. */ + *pcWriteBuffer = ( char ) 0x00; - /* Take a snapshot of the number of tasks in case it changes while this - function is executing. */ - uxArraySize = uxCurrentNumberOfTasks; + /* Take a snapshot of the number of tasks in case it changes while this + * function is executing. */ + uxArraySize = uxCurrentNumberOfTasks; - /* Allocate an array index for each task. NOTE! if - configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will - equate to NULL. */ - pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation allocates a struct that has the alignment requirements of a pointer. */ + /* Allocate an array index for each task. NOTE! if + * configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will + * equate to NULL. */ + pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation allocates a struct that has the alignment requirements of a pointer. */ - if( pxTaskStatusArray != NULL ) - { - /* Generate the (binary) data. */ - uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, NULL ); + if( pxTaskStatusArray != NULL ) + { + /* Generate the (binary) data. */ + uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, NULL ); - /* Create a human readable table from the binary data. */ - for( x = 0; x < uxArraySize; x++ ) - { - switch( pxTaskStatusArray[ x ].eCurrentState ) - { - case eRunning: cStatus = tskRUNNING_CHAR; - break; + /* Create a human readable table from the binary data. */ + for( x = 0; x < uxArraySize; x++ ) + { + switch( pxTaskStatusArray[ x ].eCurrentState ) + { + case eRunning: + cStatus = tskRUNNING_CHAR; + break; - case eReady: cStatus = tskREADY_CHAR; - break; + case eReady: + cStatus = tskREADY_CHAR; + break; - case eBlocked: cStatus = tskBLOCKED_CHAR; - break; + case eBlocked: + cStatus = tskBLOCKED_CHAR; + break; - case eSuspended: cStatus = tskSUSPENDED_CHAR; - break; + case eSuspended: + cStatus = tskSUSPENDED_CHAR; + break; - case eDeleted: cStatus = tskDELETED_CHAR; - break; + case eDeleted: + cStatus = tskDELETED_CHAR; + break; - case eInvalid: /* Fall through. */ - default: /* Should not get here, but it is included - to prevent static checking errors. */ - cStatus = ( char ) 0x00; - break; - } + case eInvalid: /* Fall through. */ + default: /* Should not get here, but it is included + * to prevent static checking errors. */ + cStatus = ( char ) 0x00; + break; + } - /* Write the task name to the string, padding with spaces so it - can be printed in tabular form more easily. */ - pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName ); + /* Write the task name to the string, padding with spaces so it + * can be printed in tabular form more easily. */ + pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName ); - /* Write the rest of the string. */ + /* Write the rest of the string. */ #if configTASKLIST_INCLUDE_COREID - sprintf( pcWriteBuffer, "\t%c\t%u\t%u\t%u\t%hd\r\n", cStatus, ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber, ( int ) pxTaskStatusArray[ x ].xCoreID ); + sprintf( pcWriteBuffer, "\t%c\t%u\t%u\t%u\t%hd\r\n", cStatus, ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber, ( int ) pxTaskStatusArray[ x ].xCoreID ); #else - sprintf( pcWriteBuffer, "\t%c\t%u\t%u\t%u\r\n", cStatus, ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber ); /*lint !e586 sprintf() allowed as this is compiled with many compilers and this is a utility function only - not part of the core kernel implementation. */ + sprintf( pcWriteBuffer, "\t%c\t%u\t%u\t%u\r\n", cStatus, ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber ); /*lint !e586 sprintf() allowed as this is compiled with many compilers and this is a utility function only - not part of the core kernel implementation. */ #endif - pcWriteBuffer += strlen( pcWriteBuffer ); /*lint !e9016 Pointer arithmetic ok on char pointers especially as in this case where it best denotes the intent of the code. */ - } + pcWriteBuffer += strlen( pcWriteBuffer ); /*lint !e9016 Pointer arithmetic ok on char pointers especially as in this case where it best denotes the intent of the code. */ + } - /* Free the array again. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION - is 0 then vPortFree() will be #defined to nothing. */ - vPortFree( pxTaskStatusArray ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } + /* Free the array again. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION + * is 0 then vPortFree() will be #defined to nothing. */ + vPortFree( pxTaskStatusArray ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */ /*----------------------------------------------------------*/ #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) - void vTaskGetRunTimeStats( char *pcWriteBuffer ) - { - TaskStatus_t *pxTaskStatusArray; - UBaseType_t uxArraySize, x; - uint32_t ulTotalTime, ulStatsAsPercentage; + void vTaskGetRunTimeStats( char * pcWriteBuffer ) + { + TaskStatus_t * pxTaskStatusArray; + UBaseType_t uxArraySize, x; + uint32_t ulTotalTime, ulStatsAsPercentage; - #if( configUSE_TRACE_FACILITY != 1 ) - { - #error configUSE_TRACE_FACILITY must also be set to 1 in FreeRTOSConfig.h to use vTaskGetRunTimeStats(). - } - #endif + #if ( configUSE_TRACE_FACILITY != 1 ) + { + #error configUSE_TRACE_FACILITY must also be set to 1 in FreeRTOSConfig.h to use vTaskGetRunTimeStats(). + } + #endif - /* - * PLEASE NOTE: - * - * This function is provided for convenience only, and is used by many - * of the demo applications. Do not consider it to be part of the - * scheduler. - * - * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part - * of the uxTaskGetSystemState() output into a human readable table that - * displays the amount of time each task has spent in the Running state - * in both absolute and percentage terms. - * - * vTaskGetRunTimeStats() has a dependency on the sprintf() C library - * function that might bloat the code size, use a lot of stack, and - * provide different results on different platforms. An alternative, - * tiny, third party, and limited functionality implementation of - * sprintf() is provided in many of the FreeRTOS/Demo sub-directories in - * a file called printf-stdarg.c (note printf-stdarg.c does not provide - * a full snprintf() implementation!). - * - * It is recommended that production systems call uxTaskGetSystemState() - * directly to get access to raw stats data, rather than indirectly - * through a call to vTaskGetRunTimeStats(). - */ + /* + * PLEASE NOTE: + * + * This function is provided for convenience only, and is used by many + * of the demo applications. Do not consider it to be part of the + * scheduler. + * + * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part + * of the uxTaskGetSystemState() output into a human readable table that + * displays the amount of time each task has spent in the Running state + * in both absolute and percentage terms. + * + * vTaskGetRunTimeStats() has a dependency on the sprintf() C library + * function that might bloat the code size, use a lot of stack, and + * provide different results on different platforms. An alternative, + * tiny, third party, and limited functionality implementation of + * sprintf() is provided in many of the FreeRTOS/Demo sub-directories in + * a file called printf-stdarg.c (note printf-stdarg.c does not provide + * a full snprintf() implementation!). + * + * It is recommended that production systems call uxTaskGetSystemState() + * directly to get access to raw stats data, rather than indirectly + * through a call to vTaskGetRunTimeStats(). + */ - /* Make sure the write buffer does not contain a string. */ - *pcWriteBuffer = ( char ) 0x00; + /* Make sure the write buffer does not contain a string. */ + *pcWriteBuffer = ( char ) 0x00; - /* Take a snapshot of the number of tasks in case it changes while this - function is executing. */ - uxArraySize = uxCurrentNumberOfTasks; + /* Take a snapshot of the number of tasks in case it changes while this + * function is executing. */ + uxArraySize = uxCurrentNumberOfTasks; - /* Allocate an array index for each task. NOTE! If - configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will - equate to NULL. */ - pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation allocates a struct that has the alignment requirements of a pointer. */ + /* Allocate an array index for each task. NOTE! If + * configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will + * equate to NULL. */ + pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation allocates a struct that has the alignment requirements of a pointer. */ - if( pxTaskStatusArray != NULL ) - { - /* Generate the (binary) data. */ - uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalTime ); + if( pxTaskStatusArray != NULL ) + { + /* Generate the (binary) data. */ + uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalTime ); - /* For percentage calculations. */ - ulTotalTime /= 100UL; + /* For percentage calculations. */ + ulTotalTime /= 100UL; - /* Avoid divide by zero errors. */ - if( ulTotalTime > 0UL ) - { - /* Create a human readable table from the binary data. */ - for( x = 0; x < uxArraySize; x++ ) - { - /* What percentage of the total run time has the task used? - This will always be rounded down to the nearest integer. - ulTotalRunTimeDiv100 has already been divided by 100. */ - ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime; + /* Avoid divide by zero errors. */ + if( ulTotalTime > 0UL ) + { + /* Create a human readable table from the binary data. */ + for( x = 0; x < uxArraySize; x++ ) + { + /* What percentage of the total run time has the task used? + * This will always be rounded down to the nearest integer. + * ulTotalRunTimeDiv100 has already been divided by 100. */ + ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime; - /* Write the task name to the string, padding with - spaces so it can be printed in tabular form more - easily. */ - pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName ); + /* Write the task name to the string, padding with + * spaces so it can be printed in tabular form more + * easily. */ + pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName ); - if( ulStatsAsPercentage > 0UL ) - { - #ifdef portLU_PRINTF_SPECIFIER_REQUIRED - { - sprintf( pcWriteBuffer, "\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage ); - } - #else - { - /* sizeof( int ) == sizeof( long ) so a smaller - printf() library can be used. */ - sprintf( pcWriteBuffer, "\t%u\t\t%u%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage ); /*lint !e586 sprintf() allowed as this is compiled with many compilers and this is a utility function only - not part of the core kernel implementation. */ - } - #endif - } - else - { - /* If the percentage is zero here then the task has - consumed less than 1% of the total run time. */ - #ifdef portLU_PRINTF_SPECIFIER_REQUIRED - { - sprintf( pcWriteBuffer, "\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter ); - } - #else - { - /* sizeof( int ) == sizeof( long ) so a smaller - printf() library can be used. */ - sprintf( pcWriteBuffer, "\t%u\t\t<1%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter ); /*lint !e586 sprintf() allowed as this is compiled with many compilers and this is a utility function only - not part of the core kernel implementation. */ - } - #endif - } + if( ulStatsAsPercentage > 0UL ) + { + #ifdef portLU_PRINTF_SPECIFIER_REQUIRED + { + sprintf( pcWriteBuffer, "\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage ); + } + #else + { + /* sizeof( int ) == sizeof( long ) so a smaller + * printf() library can be used. */ + sprintf( pcWriteBuffer, "\t%u\t\t%u%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage ); /*lint !e586 sprintf() allowed as this is compiled with many compilers and this is a utility function only - not part of the core kernel implementation. */ + } + #endif + } + else + { + /* If the percentage is zero here then the task has + * consumed less than 1% of the total run time. */ + #ifdef portLU_PRINTF_SPECIFIER_REQUIRED + { + sprintf( pcWriteBuffer, "\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter ); + } + #else + { + /* sizeof( int ) == sizeof( long ) so a smaller + * printf() library can be used. */ + sprintf( pcWriteBuffer, "\t%u\t\t<1%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter ); /*lint !e586 sprintf() allowed as this is compiled with many compilers and this is a utility function only - not part of the core kernel implementation. */ + } + #endif + } - pcWriteBuffer += strlen( pcWriteBuffer ); /*lint !e9016 Pointer arithmetic ok on char pointers especially as in this case where it best denotes the intent of the code. */ - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + pcWriteBuffer += strlen( pcWriteBuffer ); /*lint !e9016 Pointer arithmetic ok on char pointers especially as in this case where it best denotes the intent of the code. */ + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - /* Free the array again. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION - is 0 then vPortFree() will be #defined to nothing. */ - vPortFree( pxTaskStatusArray ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } + /* Free the array again. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION + * is 0 then vPortFree() will be #defined to nothing. */ + vPortFree( pxTaskStatusArray ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } #endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) */ /*-----------------------------------------------------------*/ TickType_t uxTaskResetEventItemValue( void ) { -TickType_t uxReturn; + TickType_t uxReturn; - taskENTER_CRITICAL(&xTaskQueueMutex); - uxReturn = listGET_LIST_ITEM_VALUE( &( pxCurrentTCB[ xPortGetCoreID() ]->xEventListItem ) ); + taskENTER_CRITICAL(); + uxReturn = listGET_LIST_ITEM_VALUE( &( pxCurrentTCB[ xPortGetCoreID() ]->xEventListItem ) ); - /* Reset the event list item to its normal value - so it can be used with - queues and semaphores. */ - listSET_LIST_ITEM_VALUE( &( pxCurrentTCB[ xPortGetCoreID() ]->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ - taskEXIT_CRITICAL(&xTaskQueueMutex); + /* Reset the event list item to its normal value - so it can be used with + * queues and semaphores. */ + listSET_LIST_ITEM_VALUE( &( pxCurrentTCB[ xPortGetCoreID() ]->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + taskEXIT_CRITICAL(); - return uxReturn; + return uxReturn; } /*-----------------------------------------------------------*/ #if ( configUSE_MUTEXES == 1 ) - void *pvTaskIncrementMutexHeldCount( void ) - { - TCB_t *curTCB; + void *pvTaskIncrementMutexHeldCount( void ) + { + TCB_t * curTCB; - /* If xSemaphoreCreateMutex() is called before any tasks have been created - then pxCurrentTCB will be NULL. */ - taskENTER_CRITICAL(&xTaskQueueMutex); - if( pxCurrentTCB[ xPortGetCoreID() ] != NULL ) - { - ( pxCurrentTCB[ xPortGetCoreID() ]->uxMutexesHeld )++; - } - curTCB = pxCurrentTCB[ xPortGetCoreID() ]; - taskEXIT_CRITICAL(&xTaskQueueMutex); + /* If xSemaphoreCreateMutex() is called before any tasks have been created + * then pxCurrentTCB will be NULL. */ + taskENTER_CRITICAL(); + if( pxCurrentTCB[ xPortGetCoreID() ] != NULL ) + { + ( pxCurrentTCB[ xPortGetCoreID() ]->uxMutexesHeld )++; + } + curTCB = pxCurrentTCB[ xPortGetCoreID() ]; + taskEXIT_CRITICAL(); - return curTCB; - } + return curTCB; + } #endif /* configUSE_MUTEXES */ /*-----------------------------------------------------------*/ -#if( configUSE_TASK_NOTIFICATIONS == 1 ) +#if ( configUSE_TASK_NOTIFICATIONS == 1 ) - uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait ) - { - uint32_t ulReturn; +#ifdef ESP_PLATFORM // IDF-3851 + // included here for backward binary compatibility + #undef ulTaskNotifyTake + uint32_t ulTaskNotifyTake(BaseType_t xClearCountOnExit, + TickType_t xTicksToWait ) + { + return ulTaskGenericNotifyTake(tskDEFAULT_INDEX_TO_NOTIFY, xClearCountOnExit, xTicksToWait); + } +#endif // ESP-PLATFORM - taskENTER_CRITICAL( &xTaskQueueMutex ); - { - /* Only block if the notification count is not already non-zero. */ - if( pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue == 0UL ) - { - /* Mark this task as waiting for a notification. */ - pxCurrentTCB[xPortGetCoreID()]->ucNotifyState = taskWAITING_NOTIFICATION; + uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWait, + BaseType_t xClearCountOnExit, + TickType_t xTicksToWait ) + { + uint32_t ulReturn; - if( xTicksToWait > ( TickType_t ) 0 ) - { - prvAddCurrentTaskToDelayedList( xPortGetCoreID(), xTicksToWait ); - traceTASK_NOTIFY_TAKE_BLOCK(); + configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES ); - /* All ports are written to allow a yield in a critical - section (some will yield immediately, others wait until the - critical section exits) - but it is not something that - application code should ever do. */ - portYIELD_WITHIN_API(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + taskENTER_CRITICAL(); + { + /* Only block if the notification count is not already non-zero. */ + if( pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue[ uxIndexToWait ] == 0UL ) + { + /* Mark this task as waiting for a notification. */ + pxCurrentTCB[xPortGetCoreID()]->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION; - taskENTER_CRITICAL( &xTaskQueueMutex ); - { - traceTASK_NOTIFY_TAKE(); - ulReturn = pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue; + if( xTicksToWait > ( TickType_t ) 0 ) + { + prvAddCurrentTaskToDelayedList( xPortGetCoreID(), xTicksToWait ); + traceTASK_NOTIFY_TAKE_BLOCK( uxIndexToWait ); - if( ulReturn != 0UL ) - { - if( xClearCountOnExit != pdFALSE ) - { - pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue = 0UL; - } - else - { - pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue = ulReturn - ( uint32_t ) 1; - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* All ports are written to allow a yield in a critical + * section (some will yield immediately, others wait until the + * critical section exits) - but it is not something that + * application code should ever do. */ + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(); - pxCurrentTCB[xPortGetCoreID()]->ucNotifyState = taskNOT_WAITING_NOTIFICATION; - } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + taskENTER_CRITICAL(); + { + traceTASK_NOTIFY_TAKE( uxIndexToWait ); + ulReturn = pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue[ uxIndexToWait ]; - return ulReturn; - } + if( ulReturn != 0UL ) + { + if( xClearCountOnExit != pdFALSE ) + { + pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue[ uxIndexToWait ] = 0UL; + } + else + { + pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue[ uxIndexToWait ] = ulReturn - ( uint32_t ) 1; + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + pxCurrentTCB[xPortGetCoreID()]->ucNotifyState[ uxIndexToWait ] = taskNOT_WAITING_NOTIFICATION; + } + taskEXIT_CRITICAL(); + + return ulReturn; + } #endif /* configUSE_TASK_NOTIFICATIONS */ /*-----------------------------------------------------------*/ -#if( configUSE_TASK_NOTIFICATIONS == 1 ) +#if ( configUSE_TASK_NOTIFICATIONS == 1 ) - BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ) - { - BaseType_t xReturn; +#ifdef ESP_PLATFORM // IDF-3851 + // included for backward compatibility + #undef xTaskNotifyWait + BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, + uint32_t ulBitsToClearOnExit, + uint32_t * pulNotificationValue, + TickType_t xTicksToWait ) + { + return xTaskGenericNotifyWait(tskDEFAULT_INDEX_TO_NOTIFY, ulBitsToClearOnEntry, ulBitsToClearOnExit, pulNotificationValue, xTicksToWait); + } +#endif // ESP-PLATFORM - taskENTER_CRITICAL( &xTaskQueueMutex ); - { - /* Only block if a notification is not already pending. */ - if( pxCurrentTCB[xPortGetCoreID()]->ucNotifyState != taskNOTIFICATION_RECEIVED ) - { - /* Clear bits in the task's notification value as bits may get - set by the notifying task or interrupt. This can be used to - clear the value to zero. */ - pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue &= ~ulBitsToClearOnEntry; + BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWait, + uint32_t ulBitsToClearOnEntry, + uint32_t ulBitsToClearOnExit, + uint32_t * pulNotificationValue, + TickType_t xTicksToWait ) + { + BaseType_t xReturn; - /* Mark this task as waiting for a notification. */ - pxCurrentTCB[xPortGetCoreID()]->ucNotifyState = taskWAITING_NOTIFICATION; + configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES ); - if( xTicksToWait > ( TickType_t ) 0 ) - { - prvAddCurrentTaskToDelayedList( xPortGetCoreID(), xTicksToWait); - traceTASK_NOTIFY_WAIT_BLOCK(); + taskENTER_CRITICAL(); + { + /* Only block if a notification is not already pending. */ + if( pxCurrentTCB[xPortGetCoreID()]->ucNotifyState[ uxIndexToWait ] != taskNOTIFICATION_RECEIVED ) + { + /* Clear bits in the task's notification value as bits may get + * set by the notifying task or interrupt. This can be used to + * clear the value to zero. */ + pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue[ uxIndexToWait ] &= ~ulBitsToClearOnEntry; - /* All ports are written to allow a yield in a critical - section (some will yield immediately, others wait until the - critical section exits) - but it is not something that - application code should ever do. */ - portYIELD_WITHIN_API(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + /* Mark this task as waiting for a notification. */ + pxCurrentTCB[xPortGetCoreID()]->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION; - taskENTER_CRITICAL( &xTaskQueueMutex ); - { - traceTASK_NOTIFY_WAIT(); + if( xTicksToWait > ( TickType_t ) 0 ) + { + prvAddCurrentTaskToDelayedList( xPortGetCoreID(), xTicksToWait); + traceTASK_NOTIFY_WAIT_BLOCK( uxIndexToWait ); - if( pulNotificationValue != NULL ) - { - /* Output the current notification value, which may or may not - have changed. */ - *pulNotificationValue = pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue; - } + /* All ports are written to allow a yield in a critical + * section (some will yield immediately, others wait until the + * critical section exits) - but it is not something that + * application code should ever do. */ + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(); - /* If ucNotifyValue is set then either the task never entered the - blocked state (because a notification was already pending) or the - task unblocked because of a notification. Otherwise the task - unblocked because of a timeout. */ - if( pxCurrentTCB[xPortGetCoreID()]->ucNotifyState != taskNOTIFICATION_RECEIVED ) - { - /* A notification was not received. */ - xReturn = pdFALSE; - } - else - { - /* A notification was already pending or a notification was - received while the task was waiting. */ - pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue &= ~ulBitsToClearOnExit; - xReturn = pdTRUE; - } + taskENTER_CRITICAL(); + { + traceTASK_NOTIFY_WAIT( uxIndexToWait ); - pxCurrentTCB[xPortGetCoreID()]->ucNotifyState = taskNOT_WAITING_NOTIFICATION; - } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + if( pulNotificationValue != NULL ) + { + /* Output the current notification value, which may or may not + * have changed. */ + *pulNotificationValue = pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue[ uxIndexToWait ]; + } - return xReturn; - } + /* If ucNotifyValue is set then either the task never entered the + * blocked state (because a notification was already pending) or the + * task unblocked because of a notification. Otherwise the task + * unblocked because of a timeout. */ + if( pxCurrentTCB[xPortGetCoreID()]->ucNotifyState[ uxIndexToWait ] != taskNOTIFICATION_RECEIVED ) + { + /* A notification was not received. */ + xReturn = pdFALSE; + } + else + { + /* A notification was already pending or a notification was + * received while the task was waiting. */ + pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue[ uxIndexToWait ] &= ~ulBitsToClearOnExit; + xReturn = pdTRUE; + } + + pxCurrentTCB[xPortGetCoreID()]->ucNotifyState[ uxIndexToWait ] = taskNOT_WAITING_NOTIFICATION; + } + taskEXIT_CRITICAL(); + + return xReturn; + } #endif /* configUSE_TASK_NOTIFICATIONS */ /*-----------------------------------------------------------*/ -#if( configUSE_TASK_NOTIFICATIONS == 1 ) +#if ( configUSE_TASK_NOTIFICATIONS == 1 ) - BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue ) - { - TCB_t * pxTCB; - BaseType_t xReturn = pdPASS; - uint8_t ucOriginalNotifyState; + BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, + UBaseType_t uxIndexToNotify, + uint32_t ulValue, + eNotifyAction eAction, + uint32_t * pulPreviousNotificationValue ) + { + TCB_t * pxTCB; + BaseType_t xReturn = pdPASS; + uint8_t ucOriginalNotifyState; - configASSERT( xTaskToNotify ); - pxTCB = xTaskToNotify; + configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES ); + configASSERT( xTaskToNotify ); + pxTCB = xTaskToNotify; - taskENTER_CRITICAL( &xTaskQueueMutex ); - { - if( pulPreviousNotificationValue != NULL ) - { - *pulPreviousNotificationValue = pxTCB->ulNotifiedValue; - } + taskENTER_CRITICAL(); + { + if( pulPreviousNotificationValue != NULL ) + { + *pulPreviousNotificationValue = pxTCB->ulNotifiedValue[ uxIndexToNotify ]; + } - ucOriginalNotifyState = pxTCB->ucNotifyState; + ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ]; - pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED; + pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED; - switch( eAction ) - { - case eSetBits : - pxTCB->ulNotifiedValue |= ulValue; - break; + switch( eAction ) + { + case eSetBits: + pxTCB->ulNotifiedValue[ uxIndexToNotify ] |= ulValue; + break; - case eIncrement : - ( pxTCB->ulNotifiedValue )++; - break; + case eIncrement: + ( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++; + break; - case eSetValueWithOverwrite : - pxTCB->ulNotifiedValue = ulValue; - break; + case eSetValueWithOverwrite: + pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue; + break; - case eSetValueWithoutOverwrite : - if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED ) - { - pxTCB->ulNotifiedValue = ulValue; - } - else - { - /* The value could not be written to the task. */ - xReturn = pdFAIL; - } - break; + case eSetValueWithoutOverwrite: - case eNoAction: - /* The task is being notified without its notify value being - updated. */ - break; + if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED ) + { + pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue; + } + else + { + /* The value could not be written to the task. */ + xReturn = pdFAIL; + } - default: - /* Should not get here if all enums are handled. - Artificially force an assert by testing a value the - compiler can't assume is const. */ - configASSERT( pxTCB->ulNotifiedValue == ~0UL ); + break; - break; - } + case eNoAction: - traceTASK_NOTIFY(); + /* The task is being notified without its notify value being + * updated. */ + break; - /* If the task is in the blocked state specifically to wait for a - notification then unblock it now. */ - if( ucOriginalNotifyState == taskWAITING_NOTIFICATION ) - { - ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); - prvAddTaskToReadyList( pxTCB ); + default: - /* The task should not have been on an event list. */ - configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ); + /* Should not get here if all enums are handled. + * Artificially force an assert by testing a value the + * compiler can't assume is const. */ + configASSERT( pxTCB->ulNotifiedValue[ uxIndexToNotify ] == ~0UL ); - #if( configUSE_TICKLESS_IDLE != 0 ) - { - /* If a task is blocked waiting for a notification then - xNextTaskUnblockTime might be set to the blocked task's time - out time. If the task is unblocked for a reason other than - a timeout xNextTaskUnblockTime is normally left unchanged, - because it will automatically get reset to a new value when - the tick count equals xNextTaskUnblockTime. However if - tickless idling is used it might be more important to enter - sleep mode at the earliest possible time - so reset - xNextTaskUnblockTime here to ensure it is updated at the - earliest possible time. */ - prvResetNextTaskUnblockTime(); - } - #endif + break; + } - if( tskCAN_RUN_HERE(pxTCB->xCoreID) && pxTCB->uxPriority > pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) - { - /* The notified task has a priority above the currently - executing task so a yield is required. */ - portYIELD_WITHIN_API(); - } - else if ( pxTCB->xCoreID != xPortGetCoreID() ) - { - taskYIELD_OTHER_CORE(pxTCB->xCoreID, pxTCB->uxPriority); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - taskEXIT_CRITICAL( &xTaskQueueMutex ); + traceTASK_NOTIFY( uxIndexToNotify ); - return xReturn; - } + /* If the task is in the blocked state specifically to wait for a + * notification then unblock it now. */ + if( ucOriginalNotifyState == taskWAITING_NOTIFICATION ) + { + ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); + prvAddTaskToReadyList( pxTCB ); + + /* The task should not have been on an event list. */ + configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ); + + #if ( configUSE_TICKLESS_IDLE != 0 ) + { + /* If a task is blocked waiting for a notification then + * xNextTaskUnblockTime might be set to the blocked task's time + * out time. If the task is unblocked for a reason other than + * a timeout xNextTaskUnblockTime is normally left unchanged, + * because it will automatically get reset to a new value when + * the tick count equals xNextTaskUnblockTime. However if + * tickless idling is used it might be more important to enter + * sleep mode at the earliest possible time - so reset + * xNextTaskUnblockTime here to ensure it is updated at the + * earliest possible time. */ + prvResetNextTaskUnblockTime(); + } + #endif + + if( tskCAN_RUN_HERE(pxTCB->xCoreID) && pxTCB->uxPriority > pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) + { + /* The notified task has a priority above the currently + * executing task so a yield is required. */ + portYIELD_WITHIN_API(); + } + else if ( pxTCB->xCoreID != xPortGetCoreID() ) + { + taskYIELD_OTHER_CORE(pxTCB->xCoreID, pxTCB->uxPriority); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(); + + return xReturn; + } #endif /* configUSE_TASK_NOTIFICATIONS */ /*-----------------------------------------------------------*/ -#if( configUSE_TASK_NOTIFICATIONS == 1 ) +#if ( configUSE_TASK_NOTIFICATIONS == 1 ) - BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken ) - { - TCB_t * pxTCB; - uint8_t ucOriginalNotifyState; - BaseType_t xReturn = pdPASS; + BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, + UBaseType_t uxIndexToNotify, + uint32_t ulValue, + eNotifyAction eAction, + uint32_t * pulPreviousNotificationValue, + BaseType_t * pxHigherPriorityTaskWoken ) + { + TCB_t * pxTCB; + uint8_t ucOriginalNotifyState; + BaseType_t xReturn = pdPASS; - configASSERT( xTaskToNotify ); + configASSERT( xTaskToNotify ); + configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES ); - /* RTOS ports that support interrupt nesting have the concept of a - maximum system call (or maximum API call) interrupt priority. - Interrupts that are above the maximum system call priority are keep - permanently enabled, even when the RTOS kernel is in a critical section, - but cannot make any calls to FreeRTOS API functions. If configASSERT() - is defined in FreeRTOSConfig.h then - portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion - failure if a FreeRTOS API function is called from an interrupt that has - been assigned a priority above the configured maximum system call - priority. Only FreeRTOS functions that end in FromISR can be called - from interrupts that have been assigned a priority at or (logically) - below the maximum system call interrupt priority. FreeRTOS maintains a - separate interrupt safe API to ensure interrupt entry is as fast and as - simple as possible. More information (albeit Cortex-M specific) is - provided on the following link: - http://www.freertos.org/RTOS-Cortex-M3-M4.html */ - portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + /* RTOS ports that support interrupt nesting have the concept of a + * maximum system call (or maximum API call) interrupt priority. + * Interrupts that are above the maximum system call priority are keep + * permanently enabled, even when the RTOS kernel is in a critical section, + * but cannot make any calls to FreeRTOS API functions. If configASSERT() + * is defined in FreeRTOSConfig.h then + * portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + * failure if a FreeRTOS API function is called from an interrupt that has + * been assigned a priority above the configured maximum system call + * priority. Only FreeRTOS functions that end in FromISR can be called + * from interrupts that have been assigned a priority at or (logically) + * below the maximum system call interrupt priority. FreeRTOS maintains a + * separate interrupt safe API to ensure interrupt entry is as fast and as + * simple as possible. More information (albeit Cortex-M specific) is + * provided on the following link: + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); - pxTCB = xTaskToNotify; + pxTCB = xTaskToNotify; - taskENTER_CRITICAL_ISR(&xTaskQueueMutex); - { - if( pulPreviousNotificationValue != NULL ) - { - *pulPreviousNotificationValue = pxTCB->ulNotifiedValue; - } + taskENTER_CRITICAL_ISR(); + { + if( pulPreviousNotificationValue != NULL ) + { + *pulPreviousNotificationValue = pxTCB->ulNotifiedValue[ uxIndexToNotify ]; + } - ucOriginalNotifyState = pxTCB->ucNotifyState; - pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED; + ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ]; + pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED; - switch( eAction ) - { - case eSetBits : - pxTCB->ulNotifiedValue |= ulValue; - break; + switch( eAction ) + { + case eSetBits: + pxTCB->ulNotifiedValue[ uxIndexToNotify ] |= ulValue; + break; - case eIncrement : - ( pxTCB->ulNotifiedValue )++; - break; + case eIncrement: + ( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++; + break; - case eSetValueWithOverwrite : - pxTCB->ulNotifiedValue = ulValue; - break; + case eSetValueWithOverwrite: + pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue; + break; - case eSetValueWithoutOverwrite : - if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED ) - { - pxTCB->ulNotifiedValue = ulValue; - } - else - { - /* The value could not be written to the task. */ - xReturn = pdFAIL; - } - break; + case eSetValueWithoutOverwrite: - case eNoAction : - /* The task is being notified without its notify value being - updated. */ - break; + if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED ) + { + pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue; + } + else + { + /* The value could not be written to the task. */ + xReturn = pdFAIL; + } - default: - /* Should not get here if all enums are handled. - Artificially force an assert by testing a value the - compiler can't assume is const. */ - configASSERT( pxTCB->ulNotifiedValue == ~0UL ); - break; - } + break; - traceTASK_NOTIFY_FROM_ISR(); + case eNoAction: - /* If the task is in the blocked state specifically to wait for a - notification then unblock it now. */ - if( ucOriginalNotifyState == taskWAITING_NOTIFICATION ) - { - /* The task should not have been on an event list. */ - configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ); + /* The task is being notified without its notify value being + * updated. */ + break; - if( uxSchedulerSuspended[xPortGetCoreID()] == ( UBaseType_t ) pdFALSE ) - { - ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); - prvAddTaskToReadyList( pxTCB ); - } - else - { - /* The delayed and ready lists cannot be accessed, so hold - this task pending until the scheduler is resumed. */ - vListInsertEnd( &( xPendingReadyList[xPortGetCoreID()] ), &( pxTCB->xEventListItem ) ); - } + default: - if( tskCAN_RUN_HERE(pxTCB->xCoreID) && pxTCB->uxPriority > pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) - { - /* The notified task has a priority above the currently - executing task so a yield is required. */ - if( pxHigherPriorityTaskWoken != NULL ) - { - *pxHigherPriorityTaskWoken = pdTRUE; - } - } - else if ( pxTCB->xCoreID != xPortGetCoreID() ) - { - taskYIELD_OTHER_CORE( pxTCB->xCoreID, pxTCB->uxPriority ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* Should not get here if all enums are handled. + * Artificially force an assert by testing a value the + * compiler can't assume is const. */ + configASSERT( pxTCB->ulNotifiedValue[ uxIndexToNotify ] == ~0UL ); + break; + } - } - } - taskEXIT_CRITICAL_ISR(&xTaskQueueMutex); + traceTASK_NOTIFY_FROM_ISR( uxIndexToNotify ); - return xReturn; - } + /* If the task is in the blocked state specifically to wait for a + * notification then unblock it now. */ + if( ucOriginalNotifyState == taskWAITING_NOTIFICATION ) + { + /* The task should not have been on an event list. */ + configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ); + + if( uxSchedulerSuspended[xPortGetCoreID()] == ( UBaseType_t ) pdFALSE ) + { + ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); + prvAddTaskToReadyList( pxTCB ); + } + else + { + /* The delayed and ready lists cannot be accessed, so hold + * this task pending until the scheduler is resumed. */ + vListInsertEnd( &( xPendingReadyList[xPortGetCoreID()] ), &( pxTCB->xEventListItem ) ); + } + + if( tskCAN_RUN_HERE(pxTCB->xCoreID) && pxTCB->uxPriority > pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) + { + /* The notified task has a priority above the currently + * executing task so a yield is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + } + else if ( pxTCB->xCoreID != xPortGetCoreID() ) + { + taskYIELD_OTHER_CORE( pxTCB->xCoreID, pxTCB->uxPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + taskEXIT_CRITICAL_ISR(); + + return xReturn; + } #endif /* configUSE_TASK_NOTIFICATIONS */ /*-----------------------------------------------------------*/ -#if( configUSE_TASK_NOTIFICATIONS == 1 ) +#if ( configUSE_TASK_NOTIFICATIONS == 1 ) - void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken ) - { - TCB_t * pxTCB; - uint8_t ucOriginalNotifyState; + void vTaskGenericNotifyGiveFromISR( TaskHandle_t xTaskToNotify, + UBaseType_t uxIndexToNotify, + BaseType_t * pxHigherPriorityTaskWoken ) + { + TCB_t * pxTCB; + uint8_t ucOriginalNotifyState; - configASSERT( xTaskToNotify ); + configASSERT( xTaskToNotify ); + configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES ); - /* RTOS ports that support interrupt nesting have the concept of a - maximum system call (or maximum API call) interrupt priority. - Interrupts that are above the maximum system call priority are keep - permanently enabled, even when the RTOS kernel is in a critical section, - but cannot make any calls to FreeRTOS API functions. If configASSERT() - is defined in FreeRTOSConfig.h then - portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion - failure if a FreeRTOS API function is called from an interrupt that has - been assigned a priority above the configured maximum system call - priority. Only FreeRTOS functions that end in FromISR can be called - from interrupts that have been assigned a priority at or (logically) - below the maximum system call interrupt priority. FreeRTOS maintains a - separate interrupt safe API to ensure interrupt entry is as fast and as - simple as possible. More information (albeit Cortex-M specific) is - provided on the following link: - http://www.freertos.org/RTOS-Cortex-M3-M4.html */ - portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + /* RTOS ports that support interrupt nesting have the concept of a + * maximum system call (or maximum API call) interrupt priority. + * Interrupts that are above the maximum system call priority are keep + * permanently enabled, even when the RTOS kernel is in a critical section, + * but cannot make any calls to FreeRTOS API functions. If configASSERT() + * is defined in FreeRTOSConfig.h then + * portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + * failure if a FreeRTOS API function is called from an interrupt that has + * been assigned a priority above the configured maximum system call + * priority. Only FreeRTOS functions that end in FromISR can be called + * from interrupts that have been assigned a priority at or (logically) + * below the maximum system call interrupt priority. FreeRTOS maintains a + * separate interrupt safe API to ensure interrupt entry is as fast and as + * simple as possible. More information (albeit Cortex-M specific) is + * provided on the following link: + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); - pxTCB = xTaskToNotify; + pxTCB = xTaskToNotify; - taskENTER_CRITICAL_ISR(&xTaskQueueMutex); - { - ucOriginalNotifyState = pxTCB->ucNotifyState; - pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED; + taskENTER_CRITICAL_ISR(); + { + ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ]; + pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED; - /* 'Giving' is equivalent to incrementing a count in a counting - semaphore. */ - ( pxTCB->ulNotifiedValue )++; + /* 'Giving' is equivalent to incrementing a count in a counting + * semaphore. */ + ( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++; - traceTASK_NOTIFY_GIVE_FROM_ISR(); + traceTASK_NOTIFY_GIVE_FROM_ISR( uxIndexToNotify ); - /* If the task is in the blocked state specifically to wait for a - notification then unblock it now. */ - if( ucOriginalNotifyState == taskWAITING_NOTIFICATION ) - { - /* The task should not have been on an event list. */ - configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ); + /* If the task is in the blocked state specifically to wait for a + * notification then unblock it now. */ + if( ucOriginalNotifyState == taskWAITING_NOTIFICATION ) + { + /* The task should not have been on an event list. */ + configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ); - if( uxSchedulerSuspended[ xPortGetCoreID() ] == ( UBaseType_t ) pdFALSE ) - { - ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); - prvAddTaskToReadyList( pxTCB ); - } - else - { - /* The delayed and ready lists cannot be accessed, so hold - this task pending until the scheduler is resumed. */ - vListInsertEnd( &( xPendingReadyList[xPortGetCoreID()] ), &( pxTCB->xEventListItem ) ); - } + if( uxSchedulerSuspended[ xPortGetCoreID() ] == ( UBaseType_t ) pdFALSE ) + { + ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); + prvAddTaskToReadyList( pxTCB ); + } + else + { + /* The delayed and ready lists cannot be accessed, so hold + * this task pending until the scheduler is resumed. */ + vListInsertEnd( &( xPendingReadyList[xPortGetCoreID()] ), &( pxTCB->xEventListItem ) ); + } - - if( tskCAN_RUN_HERE(pxTCB->xCoreID) && pxTCB->uxPriority > pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) - { - /* The notified task has a priority above the currently - executing task so a yield is required. */ - if( pxHigherPriorityTaskWoken != NULL ) - { - *pxHigherPriorityTaskWoken = pdTRUE; - } - } - else if ( pxTCB->xCoreID != xPortGetCoreID() ) - { - taskYIELD_OTHER_CORE( pxTCB->xCoreID, pxTCB->uxPriority ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - } - } - taskEXIT_CRITICAL_ISR(&xTaskQueueMutex); - } - -#endif /* configUSE_TASK_NOTIFICATIONS */ - -/*-----------------------------------------------------------*/ - -#if( configUSE_TASK_NOTIFICATIONS == 1 ) - - BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask ) - { - TCB_t *pxTCB; - BaseType_t xReturn; - - /* If null is passed in here then it is the calling task that is having - its notification state cleared. */ - pxTCB = prvGetTCBFromHandle( xTask ); - - taskENTER_CRITICAL( &xTaskQueueMutex ); - { - if( pxTCB->ucNotifyState == taskNOTIFICATION_RECEIVED ) - { - pxTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION; - xReturn = pdPASS; - } - else - { - xReturn = pdFAIL; - } - } - taskEXIT_CRITICAL( &xTaskQueueMutex ); - - return xReturn; - } + if( tskCAN_RUN_HERE(pxTCB->xCoreID) && pxTCB->uxPriority > pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) + { + /* The notified task has a priority above the currently + * executing task so a yield is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + } + else if ( pxTCB->xCoreID != xPortGetCoreID() ) + { + taskYIELD_OTHER_CORE( pxTCB->xCoreID, pxTCB->uxPriority ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + taskEXIT_CRITICAL_ISR(); + } #endif /* configUSE_TASK_NOTIFICATIONS */ /*-----------------------------------------------------------*/ -#if( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) +#if ( configUSE_TASK_NOTIFICATIONS == 1 ) - uint32_t ulTaskGetIdleRunTimeCounter( void ) - { - taskENTER_CRITICAL(&xTaskQueueMutex); - tskTCB *pxTCB = (tskTCB *)xIdleTaskHandle[xPortGetCoreID()]; - taskEXIT_CRITICAL(&xTaskQueueMutex); + BaseType_t xTaskGenericNotifyStateClear( TaskHandle_t xTask, + UBaseType_t uxIndexToClear ) + { + TCB_t * pxTCB; + BaseType_t xReturn; - return pxTCB->ulRunTimeCounter; - } + configASSERT( uxIndexToClear < configTASK_NOTIFICATION_ARRAY_ENTRIES ); + + /* If null is passed in here then it is the calling task that is having + * its notification state cleared. */ + pxTCB = prvGetTCBFromHandle( xTask ); + + taskENTER_CRITICAL(); + { + if( pxTCB->ucNotifyState[ uxIndexToClear ] == taskNOTIFICATION_RECEIVED ) + { + pxTCB->ucNotifyState[ uxIndexToClear ] = taskNOT_WAITING_NOTIFICATION; + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + } + } + taskEXIT_CRITICAL(); + + return xReturn; + } + +#endif /* configUSE_TASK_NOTIFICATIONS */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_TASK_NOTIFICATIONS == 1 ) + + uint32_t ulTaskGenericNotifyValueClear( TaskHandle_t xTask, + UBaseType_t uxIndexToClear, + uint32_t ulBitsToClear ) + { + TCB_t * pxTCB; + uint32_t ulReturn; + + /* If null is passed in here then it is the calling task that is having + * its notification state cleared. */ + pxTCB = prvGetTCBFromHandle( xTask ); + + taskENTER_CRITICAL(); + { + /* Return the notification as it was before the bits were cleared, + * then clear the bit mask. */ + ulReturn = pxTCB->ulNotifiedValue[ uxIndexToClear ]; + pxTCB->ulNotifiedValue[ uxIndexToClear ] &= ~ulBitsToClear; + } + taskEXIT_CRITICAL(); + + return ulReturn; + } + +#endif /* configUSE_TASK_NOTIFICATIONS */ +/*-----------------------------------------------------------*/ + +#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) + + uint32_t ulTaskGetIdleRunTimeCounter( void ) + { + taskENTER_CRITICAL(); + tskTCB *pxTCB = (tskTCB *)xIdleTaskHandle[xPortGetCoreID()]; + taskEXIT_CRITICAL(); + + return pxTCB->ulRunTimeCounter; + } #endif /*-----------------------------------------------------------*/ static void prvAddCurrentTaskToDelayedList( const portBASE_TYPE xCoreID, const TickType_t xTicksToWait ) { -TickType_t xTimeToWake; -const TickType_t xConstTickCount = xTickCount; + TickType_t xTimeToWake; + const TickType_t xConstTickCount = xTickCount; - if (portNUM_PROCESSORS > 1 && listIS_CONTAINED_WITHIN(&xTasksWaitingTermination, &( pxCurrentTCB[xCoreID]->xStateListItem))) { - /* vTaskDelete() has been called to delete this task. This would have happened from the other core while this task was spinning on xTaskQueueMutex, - so don't move the running task to the delayed list - as soon as this core re-enables interrupts this task will - be suspended permanently */ - return; - } + if (portNUM_PROCESSORS > 1 && listIS_CONTAINED_WITHIN(&xTasksWaitingTermination, &( pxCurrentTCB[xCoreID]->xStateListItem))) { + /* vTaskDelete() has been called to delete this task. This would have happened from the other core while this task was spinning on xTaskQueueMutex, + so don't move the running task to the delayed list - as soon as this core re-enables interrupts this task will + be suspended permanently */ + return; + } - #if( INCLUDE_xTaskAbortDelay == 1 ) - { - /* About to enter a delayed list, so ensure the ucDelayAborted flag is - reset to pdFALSE so it can be detected as having been set to pdTRUE - when the task leaves the Blocked state. */ - pxCurrentTCB[xCoreID]->ucDelayAborted = pdFALSE; - } - #endif + #if ( INCLUDE_xTaskAbortDelay == 1 ) + { + /* About to enter a delayed list, so ensure the ucDelayAborted flag is + * reset to pdFALSE so it can be detected as having been set to pdTRUE + * when the task leaves the Blocked state. */ + pxCurrentTCB[xCoreID]->ucDelayAborted = pdFALSE; + } + #endif - /* Remove the task from the ready list before adding it to the blocked list - as the same list item is used for both lists. */ - if( uxListRemove( &( pxCurrentTCB[xCoreID]->xStateListItem ) ) == ( UBaseType_t ) 0 ) - { - /* The current task must be in a ready list, so there is no need to - check, and the port reset macro can be called directly. */ - portRESET_READY_PRIORITY( pxCurrentTCB[xCoreID]->uxPriority, uxTopReadyPriority ); /*lint !e931 pxCurrentTCB[xPortGetCoreID()] cannot change as it is the calling task. pxCurrentTCB->uxPriority and uxTopReadyPriority cannot change as called with scheduler suspended or in a critical section. */ - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* Remove the task from the ready list before adding it to the blocked list + * as the same list item is used for both lists. */ + if( uxListRemove( &( pxCurrentTCB[xCoreID]->xStateListItem ) ) == ( UBaseType_t ) 0 ) + { + /* The current task must be in a ready list, so there is no need to + * check, and the port reset macro can be called directly. */ + portRESET_READY_PRIORITY( pxCurrentTCB[xCoreID]->uxPriority, uxTopReadyPriority ); /*lint !e931 pxCurrentTCB[xPortGetCoreID()] cannot change as it is the calling task. pxCurrentTCB->uxPriority and uxTopReadyPriority cannot change as called with scheduler suspended or in a critical section. */ + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - #if ( INCLUDE_vTaskSuspend == 1 ) - { - if( ( xTicksToWait == portMAX_DELAY ) ) - { - /* Add the task to the suspended task list instead of a delayed task - list to ensure it is not woken by a timing event. It will block - indefinitely. */ - vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB[xCoreID]->xStateListItem ) ); - } - else - { - /* Calculate the time at which the task should be woken if the event - does not occur. This may overflow but this doesn't matter, the - kernel will manage it correctly. */ - xTimeToWake = xConstTickCount + xTicksToWait; + #if ( INCLUDE_vTaskSuspend == 1 ) + { + if( ( xTicksToWait == portMAX_DELAY ) ) + { + /* Add the task to the suspended task list instead of a delayed task + * list to ensure it is not woken by a timing event. It will block + * indefinitely. */ + vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB[xCoreID]->xStateListItem ) ); + } + else + { + /* Calculate the time at which the task should be woken if the event + * does not occur. This may overflow but this doesn't matter, the + * kernel will manage it correctly. */ + xTimeToWake = xConstTickCount + xTicksToWait; - /* The list item will be inserted in wake time order. */ - listSET_LIST_ITEM_VALUE( &( pxCurrentTCB[xCoreID]->xStateListItem ), xTimeToWake ); + /* The list item will be inserted in wake time order. */ + listSET_LIST_ITEM_VALUE( &( pxCurrentTCB[xCoreID]->xStateListItem ), xTimeToWake ); - if( xTimeToWake < xConstTickCount ) - { - /* Wake time has overflowed. Place this item in the overflow - list. */ - vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB[xCoreID]->xStateListItem ) ); - } - else - { - /* The wake time has not overflowed, so the current block list - is used. */ - vListInsert( pxDelayedTaskList, &( pxCurrentTCB[xCoreID]->xStateListItem ) ); + if( xTimeToWake < xConstTickCount ) + { + /* Wake time has overflowed. Place this item in the overflow + * list. */ + vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB[xCoreID]->xStateListItem ) ); + } + else + { + /* The wake time has not overflowed, so the current block list + * is used. */ + vListInsert( pxDelayedTaskList, &( pxCurrentTCB[xCoreID]->xStateListItem ) ); - /* If the task entering the blocked state was placed at the - head of the list of blocked tasks then xNextTaskUnblockTime - needs to be updated too. */ - if( xTimeToWake < xNextTaskUnblockTime ) - { - xNextTaskUnblockTime = xTimeToWake; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - } - } - #else /* INCLUDE_vTaskSuspend */ - { - /* Calculate the time at which the task should be woken if the event - does not occur. This may overflow but this doesn't matter, the kernel - will manage it correctly. */ - xTimeToWake = xConstTickCount + xTicksToWait; + /* If the task entering the blocked state was placed at the + * head of the list of blocked tasks then xNextTaskUnblockTime + * needs to be updated too. */ + if( xTimeToWake < xNextTaskUnblockTime ) + { + xNextTaskUnblockTime = xTimeToWake; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + } + #else /* INCLUDE_vTaskSuspend */ + { + /* Calculate the time at which the task should be woken if the event + * does not occur. This may overflow but this doesn't matter, the kernel + * will manage it correctly. */ + xTimeToWake = xConstTickCount + xTicksToWait; - /* The list item will be inserted in wake time order. */ - listSET_LIST_ITEM_VALUE( &( pxCurrentTCB[xCoreID]->xStateListItem ), xTimeToWake ); + /* The list item will be inserted in wake time order. */ + listSET_LIST_ITEM_VALUE( &( pxCurrentTCB[xCoreID]->xStateListItem ), xTimeToWake ); - if( xTimeToWake < xConstTickCount ) - { - /* Wake time has overflowed. Place this item in the overflow list. */ - vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB[xCoreID]->xStateListItem ) ); - } - else - { - /* The wake time has not overflowed, so the current block list is used. */ - vListInsert( pxDelayedTaskList, &( pxCurrentTCB[xCoreID]->xStateListItem ) ); + if( xTimeToWake < xConstTickCount ) + { + /* Wake time has overflowed. Place this item in the overflow list. */ + vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB[xCoreID]->xStateListItem ) ); + } + else + { + /* The wake time has not overflowed, so the current block list is used. */ + vListInsert( pxDelayedTaskList, &( pxCurrentTCB[xCoreID]->xStateListItem ) ); - /* If the task entering the blocked state was placed at the head of the - list of blocked tasks then xNextTaskUnblockTime needs to be updated - too. */ - if( xTimeToWake < xNextTaskUnblockTime ) - { - xNextTaskUnblockTime = xTimeToWake; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - } - #endif /* INCLUDE_vTaskSuspend */ + /* If the task entering the blocked state was placed at the head of the + * list of blocked tasks then xNextTaskUnblockTime needs to be updated + * too. */ + if( xTimeToWake < xNextTaskUnblockTime ) + { + xNextTaskUnblockTime = xTimeToWake; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + #endif /* INCLUDE_vTaskSuspend */ } -#if ( configENABLE_TASK_SNAPSHOT == 1 ) - static void prvTaskGetSnapshot( TaskSnapshot_t *pxTaskSnapshotArray, UBaseType_t *uxTask, TCB_t *pxTCB ) - { - if (pxTCB == NULL) { - return; - } - pxTaskSnapshotArray[ *uxTask ].pxTCB = pxTCB; - pxTaskSnapshotArray[ *uxTask ].pxTopOfStack = (StackType_t *)pxTCB->pxTopOfStack; - #if( portSTACK_GROWTH < 0 ) - { - pxTaskSnapshotArray[ *uxTask ].pxEndOfStack = pxTCB->pxEndOfStack; - } - #else - { - pxTaskSnapshotArray[ *uxTask ].pxEndOfStack = pxTCB->pxStack; - } - #endif - (*uxTask)++; - } - - static void prvTaskGetSnapshotsFromList( TaskSnapshot_t *pxTaskSnapshotArray, UBaseType_t *uxTask, const UBaseType_t uxArraySize, List_t *pxList ) - { - TCB_t *pxNextTCB, *pxFirstTCB; - - if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 ) - { - listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); - do - { - if( *uxTask >= uxArraySize ) - break; - - listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); - prvTaskGetSnapshot( pxTaskSnapshotArray, uxTask, pxNextTCB ); - } while( pxNextTCB != pxFirstTCB ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - - UBaseType_t uxTaskGetSnapshotAll( TaskSnapshot_t * const pxTaskSnapshotArray, const UBaseType_t uxArraySize, UBaseType_t * const pxTcbSz ) - { - UBaseType_t uxTask = 0, i = 0; - - - *pxTcbSz = sizeof(TCB_t); - /* Fill in an TaskStatus_t structure with information on each - task in the Ready state. */ - i = configMAX_PRIORITIES; - do - { - i--; - prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, &( pxReadyTasksLists[ i ] ) ); - } while( i > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ - - /* Fill in an TaskStatus_t structure with information on each - task in the Blocked state. */ - prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, ( List_t * ) pxDelayedTaskList ); - prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, ( List_t * ) pxOverflowDelayedTaskList ); - for (i = 0; i < portNUM_PROCESSORS; i++) { - if( uxTask >= uxArraySize ) - break; - prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, &( xPendingReadyList[i]) ); - } - - #if( INCLUDE_vTaskDelete == 1 ) - { - prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, &xTasksWaitingTermination ); - } - #endif - - #if ( INCLUDE_vTaskSuspend == 1 ) - { - prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, &xSuspendedTaskList ); - } - #endif - return uxTask; - } - - static TCB_t *prvFirstTaskGet( List_t *pxList ) - { - ListItem_t *pxListItem = listGET_HEAD_ENTRY( pxList ); - if( pxListItem != listGET_END_MARKER( pxList ) ) { - return listGET_LIST_ITEM_OWNER( pxListItem ); - } - return NULL; - } - - static TCB_t *prvNextTaskGet( TCB_t *pxTCB ) - { - List_t *pxList = listLIST_ITEM_CONTAINER( &( pxTCB->xStateListItem ) ); - ListItem_t *pxListItem = listGET_NEXT( &( pxTCB->xStateListItem ) ); - if( pxListItem != listGET_END_MARKER( pxList ) ) { - return listGET_LIST_ITEM_OWNER( pxListItem ); - } - return NULL; - } - - inline void vTaskGetSnapshot( TaskHandle_t pxTask, TaskSnapshot_t *pxTaskSnapshot ) - { - configASSERT( portVALID_TCB_MEM(pxTask) ); - configASSERT( pxTaskSnapshot != NULL ); - pxTaskSnapshot->pxTCB = (TCB_t *)pxTask; - pxTaskSnapshot->pxTopOfStack = (StackType_t *)((TCB_t *)pxTask)->pxTopOfStack; - pxTaskSnapshot->pxEndOfStack = ((TCB_t *)pxTask)->pxEndOfStack; - } - - TaskHandle_t pxTaskGetNext( TaskHandle_t pxTask ) - { - TCB_t *pxTCB = pxTask; - List_t *pxTaskList = NULL; - UBaseType_t i = configMAX_PRIORITIES; - UBaseType_t bCurTaskListFound = pdFALSE; - List_t *task_lists[] = { - pxDelayedTaskList, - pxOverflowDelayedTaskList, - #if( INCLUDE_vTaskDelete == 1 ) - &xTasksWaitingTermination, - #endif - #if( INCLUDE_vTaskSuspend == 1 ) - &xSuspendedTaskList - #endif - }; - - if( pxTask != NULL && !portVALID_TCB_MEM(pxTask) ) { - return NULL; - } - - if( pxTCB != NULL ) { - pxTCB = prvNextTaskGet( pxTCB ); - if( pxTCB != NULL ) { - // take care not to return garbage - return portVALID_TCB_MEM(pxTCB) ? pxTCB : NULL; - } - pxTaskList = listLIST_ITEM_CONTAINER( &( ((TCB_t *)pxTask)->xStateListItem ) ); - } - /* ready tasks lists */ - do - { - i--; - List_t *pxList = &( pxReadyTasksLists[ i ] ); - if( bCurTaskListFound == pdFALSE && pxTaskList != NULL ) { - /* need to find list the current task item from */ - if( pxTaskList == pxList ) { - bCurTaskListFound = pdTRUE; - } - continue; /* go to the next 'ready list' */ - } - pxTCB = prvFirstTaskGet( pxList ); - if( pxTCB != NULL ) { - // take care not to return garbage - return portVALID_TCB_MEM(pxTCB) ? pxTCB : NULL; - } - } - while( i > tskIDLE_PRIORITY ); - /* pending ready tasks lists */ - for (i = 0; i < portNUM_PROCESSORS; i++) { - List_t *pxList = &( xPendingReadyList[ i ] ); - if( bCurTaskListFound == pdFALSE && pxTaskList != NULL ) { - /* need to find list the current task item from */ - if( pxTaskList == pxList ) { - bCurTaskListFound = pdTRUE; - } - continue; /* go to the next 'ready list' */ - } - pxTCB = prvFirstTaskGet( pxList ); - if( pxTCB != NULL ) { - // take care not to return garbage - return portVALID_TCB_MEM(pxTCB) ? pxTCB : NULL; - } - } - /* other tasks lists */ - for (i = 0; i < sizeof(task_lists)/sizeof(task_lists[0]); i++) { - List_t *pxList = task_lists[ i ]; - if( bCurTaskListFound == pdFALSE && pxTaskList != NULL ) { - /* need to find list the current task item from */ - if( pxTaskList == pxList ) { - bCurTaskListFound = pdTRUE; - } - continue; /* go to the next 'ready list' */ - } - pxTCB = prvFirstTaskGet( pxList ); - if( pxTCB != NULL ) { - // take care not to return garbage - return portVALID_TCB_MEM(pxTCB) ? pxTCB : NULL; - } - } - - return NULL; - } - -#endif - /* Code below here allows additional code to be inserted into this source file, -especially where access to file scope functions and data is needed (for example -when performing module tests). */ + * especially where access to file scope functions and data is needed (for example + * when performing module tests). */ #ifdef FREERTOS_MODULE_TEST - #include "tasks_test_access_functions.h" + #include "tasks_test_access_functions.h" #endif -#if( configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H == 1 ) - #include "freertos_tasks_c_additions.h" +#if ( configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H == 1 ) - #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT - static void freertos_tasks_c_additions_init( void ) - { - FREERTOS_TASKS_C_ADDITIONS_INIT(); - } - #endif + #include "freertos_tasks_c_additions.h" -#endif + #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT + static void freertos_tasks_c_additions_init( void ) + { + FREERTOS_TASKS_C_ADDITIONS_INIT(); + } + #endif + +#endif /* if ( configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H == 1 ) */ /* If timers.c is not referenced anywhere, don't create the timer task to save RAM */ BaseType_t __attribute__((weak)) xTimerCreateTimerTask( void ) { - return pdPASS; + return pdPASS; } diff --git a/components/freertos/test/CMakeLists.txt b/components/freertos/test/CMakeLists.txt index 12d6eed56c..75c356f830 100644 --- a/components/freertos/test/CMakeLists.txt +++ b/components/freertos/test/CMakeLists.txt @@ -1,3 +1,5 @@ idf_component_register(SRC_DIRS . PRIV_INCLUDE_DIRS . PRIV_REQUIRES cmock test_utils esp_ipc driver) +# Enable task snapshots by setting configENABLE_TASK_SNAPSHOT macro +idf_build_set_property(COMPILE_OPTIONS "-DconfigENABLE_TASK_SNAPSHOT=1" APPEND) diff --git a/components/freertos/test/test_freertos_mutex.c b/components/freertos/test/test_freertos_mutex.c index e4b68bb6a0..bd082c068a 100644 --- a/components/freertos/test/test_freertos_mutex.c +++ b/components/freertos/test/test_freertos_mutex.c @@ -14,7 +14,7 @@ static void mutex_release_task(void* arg) TEST_FAIL_MESSAGE("should not be reached"); } -TEST_CASE("mutex released not by owner causes an assert", "[freertos][reset=abort,SW_CPU_RESET]") +TEST_CASE("mutex released not by owner causes an assert", "[freertos][reset=assert,SW_CPU_RESET]") { SemaphoreHandle_t mutex = xSemaphoreCreateMutex(); xSemaphoreTake(mutex, portMAX_DELAY); diff --git a/components/freertos/test/test_tasks_snapshot.c b/components/freertos/test/test_tasks_snapshot.c index d7648584c8..a24685f3d7 100644 --- a/components/freertos/test/test_tasks_snapshot.c +++ b/components/freertos/test/test_tasks_snapshot.c @@ -5,7 +5,7 @@ #include #include "soc/cpu.h" #include "freertos/FreeRTOS.h" -#include "freertos/task.h" +#include "freertos/task_snapshot.h" #include "unity.h" #include "sdkconfig.h" diff --git a/components/freertos/timers.c b/components/freertos/timers.c index 3de2f11f16..e5e313b64f 100644 --- a/components/freertos/timers.c +++ b/components/freertos/timers.c @@ -1,6 +1,6 @@ /* - * FreeRTOS Kernel V10.2.1 - * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * FreeRTOS Kernel V10.4.3 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * 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 @@ -19,18 +19,17 @@ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS * - * 1 tab == 4 spaces! */ /* Standard includes. */ #include /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining -all the API functions to use the MPU wrappers. That should only be done when -task.h is included from an application file. */ + * all the API functions to use the MPU wrappers. That should only be done when + * task.h is included from an application file. */ #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE #include "FreeRTOS.h" @@ -39,167 +38,175 @@ task.h is included from an application file. */ #include "timers.h" #if ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 0 ) - #error configUSE_TIMERS must be set to 1 to make the xTimerPendFunctionCall() function available. + #error configUSE_TIMERS must be set to 1 to make the xTimerPendFunctionCall() function available. +#endif + +#ifdef ESP_PLATFORM +#define taskCRITICAL_MUX &xTimerMux +#undef taskENTER_CRITICAL +#undef taskEXIT_CRITICAL +#undef taskENTER_CRITICAL_ISR +#undef taskEXIT_CRITICAL_ISR +#define taskENTER_CRITICAL( ) portENTER_CRITICAL( taskCRITICAL_MUX ) +#define taskEXIT_CRITICAL( ) portEXIT_CRITICAL( taskCRITICAL_MUX ) +#define taskENTER_CRITICAL_ISR( ) portENTER_CRITICAL_ISR( taskCRITICAL_MUX ) +#define taskEXIT_CRITICAL_ISR( ) portEXIT_CRITICAL_ISR( taskCRITICAL_MUX ) #endif /* Lint e9021, e961 and e750 are suppressed as a MISRA exception justified -because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined -for the header files above, but not in this file, in order to generate the -correct privileged Vs unprivileged linkage and placement. */ + * because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined + * for the header files above, but not in this file, in order to generate the + * correct privileged Vs unprivileged linkage and placement. */ #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e9021 !e961 !e750. */ /* This entire source file will be skipped if the application is not configured -to include software timer functionality. This #if is closed at the very bottom -of this file. If you want to include software timer functionality then ensure -configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */ + * to include software timer functionality. This #if is closed at the very bottom + * of this file. If you want to include software timer functionality then ensure + * configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */ #if ( configUSE_TIMERS == 1 ) /* Misc definitions. */ -#define tmrNO_DELAY ( TickType_t ) 0U + #define tmrNO_DELAY ( TickType_t ) 0U /* The name assigned to the timer service task. This can be overridden by -defining trmTIMER_SERVICE_TASK_NAME in FreeRTOSConfig.h. */ -#ifndef configTIMER_SERVICE_TASK_NAME - #define configTIMER_SERVICE_TASK_NAME "Tmr Svc" -#endif + * defining trmTIMER_SERVICE_TASK_NAME in FreeRTOSConfig.h. */ + #ifndef configTIMER_SERVICE_TASK_NAME + #define configTIMER_SERVICE_TASK_NAME "Tmr Svc" + #endif /* Bit definitions used in the ucStatus member of a timer structure. */ -#define tmrSTATUS_IS_ACTIVE ( ( uint8_t ) 0x01 ) -#define tmrSTATUS_IS_STATICALLY_ALLOCATED ( ( uint8_t ) 0x02 ) -#define tmrSTATUS_IS_AUTORELOAD ( ( uint8_t ) 0x04 ) + #define tmrSTATUS_IS_ACTIVE ( ( uint8_t ) 0x01 ) + #define tmrSTATUS_IS_STATICALLY_ALLOCATED ( ( uint8_t ) 0x02 ) + #define tmrSTATUS_IS_AUTORELOAD ( ( uint8_t ) 0x04 ) /* The definition of the timers themselves. */ -typedef struct tmrTimerControl /* The old naming convention is used to prevent breaking kernel aware debuggers. */ -{ - const char *pcTimerName; /*<< Text name. This is not used by the kernel, it is included simply to make debugging easier. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ - ListItem_t xTimerListItem; /*<< Standard linked list item as used by all kernel features for event management. */ - TickType_t xTimerPeriodInTicks;/*<< How quickly and often the timer expires. */ - void *pvTimerID; /*<< An ID to identify the timer. This allows the timer to be identified when the same callback is used for multiple timers. */ - TimerCallbackFunction_t pxCallbackFunction; /*<< The function that will be called when the timer expires. */ - #if( configUSE_TRACE_FACILITY == 1 ) - UBaseType_t uxTimerNumber; /*<< An ID assigned by trace tools such as FreeRTOS+Trace */ - #endif - uint8_t ucStatus; /*<< Holds bits to say if the timer was statically allocated or not, and if it is active or not. */ -} xTIMER; + typedef struct tmrTimerControl /* The old naming convention is used to prevent breaking kernel aware debuggers. */ + { + const char * pcTimerName; /*<< Text name. This is not used by the kernel, it is included simply to make debugging easier. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + ListItem_t xTimerListItem; /*<< Standard linked list item as used by all kernel features for event management. */ + TickType_t xTimerPeriodInTicks; /*<< How quickly and often the timer expires. */ + void * pvTimerID; /*<< An ID to identify the timer. This allows the timer to be identified when the same callback is used for multiple timers. */ + TimerCallbackFunction_t pxCallbackFunction; /*<< The function that will be called when the timer expires. */ + #if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxTimerNumber; /*<< An ID assigned by trace tools such as FreeRTOS+Trace */ + #endif + uint8_t ucStatus; /*<< Holds bits to say if the timer was statically allocated or not, and if it is active or not. */ + } xTIMER; /* The old xTIMER name is maintained above then typedefed to the new Timer_t -name below to enable the use of older kernel aware debuggers. */ -typedef xTIMER Timer_t; + * name below to enable the use of older kernel aware debuggers. */ + typedef xTIMER Timer_t; /* The definition of messages that can be sent and received on the timer queue. -Two types of message can be queued - messages that manipulate a software timer, -and messages that request the execution of a non-timer related callback. The -two message types are defined in two separate structures, xTimerParametersType -and xCallbackParametersType respectively. */ -typedef struct tmrTimerParameters -{ - TickType_t xMessageValue; /*<< An optional value used by a subset of commands, for example, when changing the period of a timer. */ - Timer_t * pxTimer; /*<< The timer to which the command will be applied. */ -} TimerParameter_t; + * Two types of message can be queued - messages that manipulate a software timer, + * and messages that request the execution of a non-timer related callback. The + * two message types are defined in two separate structures, xTimerParametersType + * and xCallbackParametersType respectively. */ + typedef struct tmrTimerParameters + { + TickType_t xMessageValue; /*<< An optional value used by a subset of commands, for example, when changing the period of a timer. */ + Timer_t * pxTimer; /*<< The timer to which the command will be applied. */ + } TimerParameter_t; -typedef struct tmrCallbackParameters -{ - PendedFunction_t pxCallbackFunction; /* << The callback function to execute. */ - void *pvParameter1; /* << The value that will be used as the callback functions first parameter. */ - uint32_t ulParameter2; /* << The value that will be used as the callback functions second parameter. */ -} CallbackParameters_t; + typedef struct tmrCallbackParameters + { + PendedFunction_t pxCallbackFunction; /* << The callback function to execute. */ + void * pvParameter1; /* << The value that will be used as the callback functions first parameter. */ + uint32_t ulParameter2; /* << The value that will be used as the callback functions second parameter. */ + } CallbackParameters_t; /* The structure that contains the two message types, along with an identifier -that is used to determine which message type is valid. */ -typedef struct tmrTimerQueueMessage -{ - BaseType_t xMessageID; /*<< The command being sent to the timer service task. */ - union - { - TimerParameter_t xTimerParameters; + * that is used to determine which message type is valid. */ + typedef struct tmrTimerQueueMessage + { + BaseType_t xMessageID; /*<< The command being sent to the timer service task. */ + union + { + TimerParameter_t xTimerParameters; - /* Don't include xCallbackParameters if it is not going to be used as - it makes the structure (and therefore the timer queue) larger. */ - #if ( INCLUDE_xTimerPendFunctionCall == 1 ) - CallbackParameters_t xCallbackParameters; - #endif /* INCLUDE_xTimerPendFunctionCall */ - } u; -} DaemonTaskMessage_t; + /* Don't include xCallbackParameters if it is not going to be used as + * it makes the structure (and therefore the timer queue) larger. */ + #if ( INCLUDE_xTimerPendFunctionCall == 1 ) + CallbackParameters_t xCallbackParameters; + #endif /* INCLUDE_xTimerPendFunctionCall */ + } u; + } DaemonTaskMessage_t; /*lint -save -e956 A manual analysis and inspection has been used to determine -which static variables must be declared volatile. */ + * which static variables must be declared volatile. */ /* The list in which active timers are stored. Timers are referenced in expire -time order, with the nearest expiry time at the front of the list. Only the -timer service task is allowed to access these lists. -xActiveTimerList1 and xActiveTimerList2 could be at function scope but that -breaks some kernel aware debuggers, and debuggers that reply on removing the -static qualifier. */ -PRIVILEGED_DATA static List_t xActiveTimerList1; -PRIVILEGED_DATA static List_t xActiveTimerList2; -PRIVILEGED_DATA static List_t *pxCurrentTimerList; -PRIVILEGED_DATA static List_t *pxOverflowTimerList; + * time order, with the nearest expiry time at the front of the list. Only the + * timer service task is allowed to access these lists. + * xActiveTimerList1 and xActiveTimerList2 could be at function scope but that + * breaks some kernel aware debuggers, and debuggers that reply on removing the + * static qualifier. */ + PRIVILEGED_DATA static List_t xActiveTimerList1; + PRIVILEGED_DATA static List_t xActiveTimerList2; + PRIVILEGED_DATA static List_t * pxCurrentTimerList; + PRIVILEGED_DATA static List_t * pxOverflowTimerList; /* A queue that is used to send commands to the timer service task. */ -PRIVILEGED_DATA static QueueHandle_t xTimerQueue = NULL; -PRIVILEGED_DATA static TaskHandle_t xTimerTaskHandle = NULL; + PRIVILEGED_DATA static QueueHandle_t xTimerQueue = NULL; + PRIVILEGED_DATA static TaskHandle_t xTimerTaskHandle = NULL; +#ifdef ESP_PLATFORM /* Mux. We use a single mux for all the timers for now. ToDo: maybe increase granularity here? */ PRIVILEGED_DATA portMUX_TYPE xTimerMux = portMUX_INITIALIZER_UNLOCKED; +#endif // ESP_PLATFORM /*lint -restore */ /*-----------------------------------------------------------*/ -#if( configSUPPORT_STATIC_ALLOCATION == 1 ) - - /* If static allocation is supported then the application must provide the - following callback function - which enables the application to optionally - provide the memory that will be used by the timer task as the task's stack - and TCB. */ - extern void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize ); - -#endif - /* * Initialise the infrastructure used by the timer service task if it has not * been initialised already. */ -static void prvCheckForValidListAndQueue( void ) PRIVILEGED_FUNCTION; + static void prvCheckForValidListAndQueue( void ) PRIVILEGED_FUNCTION; /* * The timer service task (daemon). Timer functionality is controlled by this * task. Other tasks communicate with the timer service task using the * xTimerQueue queue. */ -static portTASK_FUNCTION_PROTO( prvTimerTask, pvParameters ) PRIVILEGED_FUNCTION; + static portTASK_FUNCTION_PROTO( prvTimerTask, pvParameters ) PRIVILEGED_FUNCTION; /* * Called by the timer service task to interpret and process a command it * received on the timer queue. */ -static void prvProcessReceivedCommands( void ) PRIVILEGED_FUNCTION; + static void prvProcessReceivedCommands( void ) PRIVILEGED_FUNCTION; /* * Insert the timer into either xActiveTimerList1, or xActiveTimerList2, * depending on if the expire time causes a timer counter overflow. */ -static BaseType_t prvInsertTimerInActiveList( Timer_t * const pxTimer, const TickType_t xNextExpiryTime, const TickType_t xTimeNow, const TickType_t xCommandTime ) PRIVILEGED_FUNCTION; + static BaseType_t prvInsertTimerInActiveList( Timer_t * const pxTimer, + const TickType_t xNextExpiryTime, + const TickType_t xTimeNow, + const TickType_t xCommandTime ) PRIVILEGED_FUNCTION; /* * An active timer has reached its expire time. Reload the timer if it is an - * auto reload timer, then call its callback. + * auto-reload timer, then call its callback. */ -static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow ) PRIVILEGED_FUNCTION; + static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, + const TickType_t xTimeNow ) PRIVILEGED_FUNCTION; /* * The tick count has overflowed. Switch the timer lists after ensuring the * current timer list does not still reference some timers. */ -static void prvSwitchTimerLists( void ) PRIVILEGED_FUNCTION; + static void prvSwitchTimerLists( void ) PRIVILEGED_FUNCTION; /* * Obtain the current tick count, setting *pxTimerListsWereSwitched to pdTRUE * if a tick count overflow occurred since prvSampleTimeNow() was last called. */ -static TickType_t prvSampleTimeNow( BaseType_t * const pxTimerListsWereSwitched ) PRIVILEGED_FUNCTION; + static TickType_t prvSampleTimeNow( BaseType_t * const pxTimerListsWereSwitched ) PRIVILEGED_FUNCTION; /* * If the timer list contains any active timers then return the expire time of @@ -207,896 +214,971 @@ static TickType_t prvSampleTimeNow( BaseType_t * const pxTimerListsWereSwitched * timer list does not contain any timers then return 0 and set *pxListWasEmpty * to pdTRUE. */ -static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty ) PRIVILEGED_FUNCTION; + static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty ) PRIVILEGED_FUNCTION; /* * If a timer has expired, process it. Otherwise, block the timer service task * until either a timer does expire or a command is received. */ -static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, BaseType_t xListWasEmpty ) PRIVILEGED_FUNCTION; + static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, + BaseType_t xListWasEmpty ) PRIVILEGED_FUNCTION; /* * Called after a Timer_t structure has been allocated either statically or * dynamically to fill in the structure's members. */ -static void prvInitialiseNewTimer( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ - const TickType_t xTimerPeriodInTicks, - const UBaseType_t uxAutoReload, - void * const pvTimerID, - TimerCallbackFunction_t pxCallbackFunction, - Timer_t *pxNewTimer ) PRIVILEGED_FUNCTION; + static void prvInitialiseNewTimer( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + const TickType_t xTimerPeriodInTicks, + const UBaseType_t uxAutoReload, + void * const pvTimerID, + TimerCallbackFunction_t pxCallbackFunction, + Timer_t * pxNewTimer ) PRIVILEGED_FUNCTION; /*-----------------------------------------------------------*/ -BaseType_t xTimerCreateTimerTask( void ) -{ -BaseType_t xReturn = pdFAIL; + BaseType_t xTimerCreateTimerTask( void ) + { + BaseType_t xReturn = pdFAIL; - /* This function is called when the scheduler is started if - configUSE_TIMERS is set to 1. Check that the infrastructure used by the - timer service task has been created/initialised. If timers have already - been created then the initialisation will already have been performed. */ - prvCheckForValidListAndQueue(); + /* This function is called when the scheduler is started if + * configUSE_TIMERS is set to 1. Check that the infrastructure used by the + * timer service task has been created/initialised. If timers have already + * been created then the initialisation will already have been performed. */ + prvCheckForValidListAndQueue(); - if( xTimerQueue != NULL ) - { - #if( configSUPPORT_STATIC_ALLOCATION == 1 && configSUPPORT_STATIC_ALLOCATION == 0 ) - { - StaticTask_t *pxTimerTaskTCBBuffer = NULL; - StackType_t *pxTimerTaskStackBuffer = NULL; - uint32_t ulTimerTaskStackSize; + if( xTimerQueue != NULL ) + { + #if ( configSUPPORT_STATIC_ALLOCATION == 1 && configSUPPORT_STATIC_ALLOCATION == 0 ) + { + StaticTask_t * pxTimerTaskTCBBuffer = NULL; + StackType_t * pxTimerTaskStackBuffer = NULL; + uint32_t ulTimerTaskStackSize; - vApplicationGetTimerTaskMemory( &pxTimerTaskTCBBuffer, &pxTimerTaskStackBuffer, &ulTimerTaskStackSize ); - xTimerTaskHandle = xTaskCreateStaticPinnedToCore( prvTimerTask, - configTIMER_SERVICE_TASK_NAME, - ulTimerTaskStackSize, - NULL, - ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, - pxTimerTaskStackBuffer, - pxTimerTaskTCBBuffer, - 0 ); + vApplicationGetTimerTaskMemory( &pxTimerTaskTCBBuffer, &pxTimerTaskStackBuffer, &ulTimerTaskStackSize ); + xTimerTaskHandle = xTaskCreateStaticPinnedToCore( prvTimerTask, + configTIMER_SERVICE_TASK_NAME, + ulTimerTaskStackSize, + NULL, + ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, + pxTimerTaskStackBuffer, + pxTimerTaskTCBBuffer, + 0 ); - if( xTimerTaskHandle != NULL ) - { - xReturn = pdPASS; - } - } - #else - { - xReturn = xTaskCreatePinnedToCore( prvTimerTask, - configTIMER_SERVICE_TASK_NAME, - configTIMER_TASK_STACK_DEPTH, - NULL, - ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, - &xTimerTaskHandle, 0 ); - } - #endif /* configSUPPORT_STATIC_ALLOCATION */ - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + if( xTimerTaskHandle != NULL ) + { + xReturn = pdPASS; + } + } + #else /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ + { + xReturn = xTaskCreatePinnedToCore( prvTimerTask, + configTIMER_SERVICE_TASK_NAME, + configTIMER_TASK_STACK_DEPTH, + NULL, + ( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, + &xTimerTaskHandle, 0 ); + } + #endif /* configSUPPORT_STATIC_ALLOCATION */ + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - configASSERT( xReturn ); - return xReturn; -} + configASSERT( xReturn ); + return xReturn; + } /*-----------------------------------------------------------*/ -#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) - TimerHandle_t xTimerCreate( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ - const TickType_t xTimerPeriodInTicks, - const UBaseType_t uxAutoReload, - void * const pvTimerID, - TimerCallbackFunction_t pxCallbackFunction ) - { - Timer_t *pxNewTimer; + TimerHandle_t xTimerCreate( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + const TickType_t xTimerPeriodInTicks, + const UBaseType_t uxAutoReload, + void * const pvTimerID, + TimerCallbackFunction_t pxCallbackFunction ) + { + Timer_t * pxNewTimer; - pxNewTimer = ( Timer_t * ) pvPortMalloc( sizeof( Timer_t ) ); /*lint !e9087 !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack, and the first member of Timer_t is always a pointer to the timer's mame. */ + pxNewTimer = ( Timer_t * ) pvPortMalloc( sizeof( Timer_t ) ); /*lint !e9087 !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack, and the first member of Timer_t is always a pointer to the timer's mame. */ - if( pxNewTimer != NULL ) - { - /* Status is thus far zero as the timer is not created statically - and has not been started. The autoreload bit may get set in - prvInitialiseNewTimer. */ - pxNewTimer->ucStatus = 0x00; - prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer ); - } + if( pxNewTimer != NULL ) + { + /* Status is thus far zero as the timer is not created statically + * and has not been started. The auto-reload bit may get set in + * prvInitialiseNewTimer. */ + pxNewTimer->ucStatus = 0x00; + prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer ); + } - return pxNewTimer; - } + return pxNewTimer; + } -#endif /* configSUPPORT_DYNAMIC_ALLOCATION */ + #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ /*-----------------------------------------------------------*/ -#if( configSUPPORT_STATIC_ALLOCATION == 1 ) + #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) - TimerHandle_t xTimerCreateStatic( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ - const TickType_t xTimerPeriodInTicks, - const UBaseType_t uxAutoReload, - void * const pvTimerID, - TimerCallbackFunction_t pxCallbackFunction, - StaticTimer_t *pxTimerBuffer ) - { - Timer_t *pxNewTimer; + TimerHandle_t xTimerCreateStatic( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + const TickType_t xTimerPeriodInTicks, + const UBaseType_t uxAutoReload, + void * const pvTimerID, + TimerCallbackFunction_t pxCallbackFunction, + StaticTimer_t * pxTimerBuffer ) + { + Timer_t * pxNewTimer; - #if( configASSERT_DEFINED == 1 ) - { - /* Sanity check that the size of the structure used to declare a - variable of type StaticTimer_t equals the size of the real timer - structure. */ - volatile size_t xSize = sizeof( StaticTimer_t ); - configASSERT( xSize == sizeof( Timer_t ) ); - ( void ) xSize; /* Keeps lint quiet when configASSERT() is not defined. */ - } - #endif /* configASSERT_DEFINED */ + #if ( configASSERT_DEFINED == 1 ) + { + /* Sanity check that the size of the structure used to declare a + * variable of type StaticTimer_t equals the size of the real timer + * structure. */ + volatile size_t xSize = sizeof( StaticTimer_t ); + configASSERT( xSize == sizeof( Timer_t ) ); + ( void ) xSize; /* Keeps lint quiet when configASSERT() is not defined. */ + } + #endif /* configASSERT_DEFINED */ - /* A pointer to a StaticTimer_t structure MUST be provided, use it. */ - configASSERT( pxTimerBuffer ); - pxNewTimer = ( Timer_t * ) pxTimerBuffer; /*lint !e740 !e9087 StaticTimer_t is a pointer to a Timer_t, so guaranteed to be aligned and sized correctly (checked by an assert()), so this is safe. */ + /* A pointer to a StaticTimer_t structure MUST be provided, use it. */ + configASSERT( pxTimerBuffer ); + pxNewTimer = ( Timer_t * ) pxTimerBuffer; /*lint !e740 !e9087 StaticTimer_t is a pointer to a Timer_t, so guaranteed to be aligned and sized correctly (checked by an assert()), so this is safe. */ - if( pxNewTimer != NULL ) - { - /* Timers can be created statically or dynamically so note this - timer was created statically in case it is later deleted. The - autoreload bit may get set in prvInitialiseNewTimer(). */ - pxNewTimer->ucStatus = tmrSTATUS_IS_STATICALLY_ALLOCATED; + if( pxNewTimer != NULL ) + { + /* Timers can be created statically or dynamically so note this + * timer was created statically in case it is later deleted. The + * auto-reload bit may get set in prvInitialiseNewTimer(). */ + pxNewTimer->ucStatus = tmrSTATUS_IS_STATICALLY_ALLOCATED; - prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer ); - } + prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer ); + } - return pxNewTimer; - } + return pxNewTimer; + } -#endif /* configSUPPORT_STATIC_ALLOCATION */ + #endif /* configSUPPORT_STATIC_ALLOCATION */ /*-----------------------------------------------------------*/ -static void prvInitialiseNewTimer( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ - const TickType_t xTimerPeriodInTicks, - const UBaseType_t uxAutoReload, - void * const pvTimerID, - TimerCallbackFunction_t pxCallbackFunction, - Timer_t *pxNewTimer ) -{ - /* 0 is not a valid value for xTimerPeriodInTicks. */ - configASSERT( ( xTimerPeriodInTicks > 0 ) ); + static void prvInitialiseNewTimer( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + const TickType_t xTimerPeriodInTicks, + const UBaseType_t uxAutoReload, + void * const pvTimerID, + TimerCallbackFunction_t pxCallbackFunction, + Timer_t * pxNewTimer ) + { + /* 0 is not a valid value for xTimerPeriodInTicks. */ + configASSERT( ( xTimerPeriodInTicks > 0 ) ); - if( pxNewTimer != NULL ) - { - /* Ensure the infrastructure used by the timer service task has been - created/initialised. */ - prvCheckForValidListAndQueue(); + if( pxNewTimer != NULL ) + { + /* Ensure the infrastructure used by the timer service task has been + * created/initialised. */ + prvCheckForValidListAndQueue(); - /* Initialise the timer structure members using the function - parameters. */ - pxNewTimer->pcTimerName = pcTimerName; - pxNewTimer->xTimerPeriodInTicks = xTimerPeriodInTicks; - pxNewTimer->pvTimerID = pvTimerID; - pxNewTimer->pxCallbackFunction = pxCallbackFunction; - vListInitialiseItem( &( pxNewTimer->xTimerListItem ) ); - if( uxAutoReload != pdFALSE ) - { - pxNewTimer->ucStatus |= tmrSTATUS_IS_AUTORELOAD; - } - traceTIMER_CREATE( pxNewTimer ); - } -} + /* Initialise the timer structure members using the function + * parameters. */ + pxNewTimer->pcTimerName = pcTimerName; + pxNewTimer->xTimerPeriodInTicks = xTimerPeriodInTicks; + pxNewTimer->pvTimerID = pvTimerID; + pxNewTimer->pxCallbackFunction = pxCallbackFunction; + vListInitialiseItem( &( pxNewTimer->xTimerListItem ) ); + + if( uxAutoReload != pdFALSE ) + { + pxNewTimer->ucStatus |= tmrSTATUS_IS_AUTORELOAD; + } + + traceTIMER_CREATE( pxNewTimer ); + } + } /*-----------------------------------------------------------*/ -BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait ) -{ -BaseType_t xReturn = pdFAIL; -DaemonTaskMessage_t xMessage; + BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, + const BaseType_t xCommandID, + const TickType_t xOptionalValue, + BaseType_t * const pxHigherPriorityTaskWoken, + const TickType_t xTicksToWait ) + { + BaseType_t xReturn = pdFAIL; + DaemonTaskMessage_t xMessage; - configASSERT( xTimer ); + configASSERT( xTimer ); - /* Send a message to the timer service task to perform a particular action - on a particular timer definition. */ - if( xTimerQueue != NULL ) - { - /* Send a command to the timer service task to start the xTimer timer. */ - xMessage.xMessageID = xCommandID; - xMessage.u.xTimerParameters.xMessageValue = xOptionalValue; - xMessage.u.xTimerParameters.pxTimer = xTimer; + /* Send a message to the timer service task to perform a particular action + * on a particular timer definition. */ + if( xTimerQueue != NULL ) + { + /* Send a command to the timer service task to start the xTimer timer. */ + xMessage.xMessageID = xCommandID; + xMessage.u.xTimerParameters.xMessageValue = xOptionalValue; + xMessage.u.xTimerParameters.pxTimer = xTimer; - if( xCommandID < tmrFIRST_FROM_ISR_COMMAND ) - { - if( xTaskGetSchedulerState() == taskSCHEDULER_RUNNING ) - { - xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait ); - } - else - { - xReturn = xQueueSendToBack( xTimerQueue, &xMessage, tmrNO_DELAY ); - } - } - else - { - xReturn = xQueueSendToBackFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken ); - } + if( xCommandID < tmrFIRST_FROM_ISR_COMMAND ) + { + if( xTaskGetSchedulerState() == taskSCHEDULER_RUNNING ) + { + xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait ); + } + else + { + xReturn = xQueueSendToBack( xTimerQueue, &xMessage, tmrNO_DELAY ); + } + } + else + { + xReturn = xQueueSendToBackFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken ); + } - traceTIMER_COMMAND_SEND( xTimer, xCommandID, xOptionalValue, xReturn ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + traceTIMER_COMMAND_SEND( xTimer, xCommandID, xOptionalValue, xReturn ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - return xReturn; -} + return xReturn; + } /*-----------------------------------------------------------*/ -TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) -{ - /* If xTimerGetTimerDaemonTaskHandle() is called before the scheduler has been - started, then xTimerTaskHandle will be NULL. */ - configASSERT( ( xTimerTaskHandle != NULL ) ); - return xTimerTaskHandle; -} + TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) + { + /* If xTimerGetTimerDaemonTaskHandle() is called before the scheduler has been + * started, then xTimerTaskHandle will be NULL. */ + configASSERT( ( xTimerTaskHandle != NULL ) ); + return xTimerTaskHandle; + } /*-----------------------------------------------------------*/ -TickType_t xTimerGetPeriod( TimerHandle_t xTimer ) -{ -Timer_t *pxTimer = xTimer; + TickType_t xTimerGetPeriod( TimerHandle_t xTimer ) + { + Timer_t * pxTimer = xTimer; - configASSERT( xTimer ); - return pxTimer->xTimerPeriodInTicks; -} + configASSERT( xTimer ); + return pxTimer->xTimerPeriodInTicks; + } /*-----------------------------------------------------------*/ -void vTimerSetReloadMode( TimerHandle_t xTimer, const UBaseType_t uxAutoReload ) -{ -Timer_t * pxTimer = xTimer; + void vTimerSetReloadMode( TimerHandle_t xTimer, + const UBaseType_t uxAutoReload ) + { + Timer_t * pxTimer = xTimer; - configASSERT( xTimer ); - taskENTER_CRITICAL( &xTimerMux); - { - if( uxAutoReload != pdFALSE ) - { - pxTimer->ucStatus |= tmrSTATUS_IS_AUTORELOAD; - } - else - { - pxTimer->ucStatus &= ~tmrSTATUS_IS_AUTORELOAD; - } - } - taskEXIT_CRITICAL( &xTimerMux); -} + configASSERT( xTimer ); + taskENTER_CRITICAL(); + { + if( uxAutoReload != pdFALSE ) + { + pxTimer->ucStatus |= tmrSTATUS_IS_AUTORELOAD; + } + else + { + pxTimer->ucStatus &= ~tmrSTATUS_IS_AUTORELOAD; + } + } + taskEXIT_CRITICAL(); + } /*-----------------------------------------------------------*/ -TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer ) -{ -Timer_t * pxTimer = xTimer; -TickType_t xReturn; + UBaseType_t uxTimerGetReloadMode( TimerHandle_t xTimer ) + { + Timer_t * pxTimer = xTimer; + UBaseType_t uxReturn; - configASSERT( xTimer ); - xReturn = listGET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ) ); - return xReturn; -} + configASSERT( xTimer ); + taskENTER_CRITICAL( ); + { + if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) == 0 ) + { + /* Not an auto-reload timer. */ + uxReturn = ( UBaseType_t ) pdFALSE; + } + else + { + /* Is an auto-reload timer. */ + uxReturn = ( UBaseType_t ) pdTRUE; + } + } + taskEXIT_CRITICAL(); + + return uxReturn; + } /*-----------------------------------------------------------*/ -const char * pcTimerGetName( TimerHandle_t xTimer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ -{ -Timer_t *pxTimer = xTimer; + TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer ) + { + Timer_t * pxTimer = xTimer; + TickType_t xReturn; - configASSERT( xTimer ); - return pxTimer->pcTimerName; -} + configASSERT( xTimer ); + xReturn = listGET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ) ); + return xReturn; + } /*-----------------------------------------------------------*/ -static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow ) -{ -BaseType_t xResult; -Timer_t * const pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList ); /*lint !e9087 !e9079 void * is used as this macro is used with tasks and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ + const char * pcTimerGetName( TimerHandle_t xTimer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + { + Timer_t * pxTimer = xTimer; - /* Remove the timer from the list of active timers. A check has already - been performed to ensure the list is not empty. */ - ( void ) uxListRemove( &( pxTimer->xTimerListItem ) ); - traceTIMER_EXPIRED( pxTimer ); - - /* If the timer is an auto reload timer then calculate the next - expiry time and re-insert the timer in the list of active timers. */ - if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) != 0 ) - { - /* The timer is inserted into a list using a time relative to anything - other than the current time. It will therefore be inserted into the - correct list relative to the time this task thinks it is now. */ - if( prvInsertTimerInActiveList( pxTimer, ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xNextExpireTime ) != pdFALSE ) - { - /* The timer expired before it was added to the active timer - list. Reload it now. */ - xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xNextExpireTime, NULL, tmrNO_DELAY ); - configASSERT( xResult ); - ( void ) xResult; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - pxTimer->ucStatus &= ~tmrSTATUS_IS_ACTIVE; - mtCOVERAGE_TEST_MARKER(); - } - - /* Call the timer callback. */ - pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer ); -} + configASSERT( xTimer ); + return pxTimer->pcTimerName; + } /*-----------------------------------------------------------*/ -static portTASK_FUNCTION( prvTimerTask, pvParameters ) -{ -TickType_t xNextExpireTime; -BaseType_t xListWasEmpty; + static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, + const TickType_t xTimeNow ) + { + BaseType_t xResult; + Timer_t * const pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList ); /*lint !e9087 !e9079 void * is used as this macro is used with tasks and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ - /* Just to avoid compiler warnings. */ - ( void ) pvParameters; + /* Remove the timer from the list of active timers. A check has already + * been performed to ensure the list is not empty. */ - #if( configUSE_DAEMON_TASK_STARTUP_HOOK == 1 ) - { - extern void vApplicationDaemonTaskStartupHook( void ); + ( void ) uxListRemove( &( pxTimer->xTimerListItem ) ); + traceTIMER_EXPIRED( pxTimer ); - /* Allow the application writer to execute some code in the context of - this task at the point the task starts executing. This is useful if the - application includes initialisation code that would benefit from - executing after the scheduler has been started. */ - vApplicationDaemonTaskStartupHook(); - } - #endif /* configUSE_DAEMON_TASK_STARTUP_HOOK */ + /* If the timer is an auto-reload timer then calculate the next + * expiry time and re-insert the timer in the list of active timers. */ + if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) != 0 ) + { + /* The timer is inserted into a list using a time relative to anything + * other than the current time. It will therefore be inserted into the + * correct list relative to the time this task thinks it is now. */ + if( prvInsertTimerInActiveList( pxTimer, ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xNextExpireTime ) != pdFALSE ) + { + /* The timer expired before it was added to the active timer + * list. Reload it now. */ + xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xNextExpireTime, NULL, tmrNO_DELAY ); + configASSERT( xResult ); + ( void ) xResult; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + pxTimer->ucStatus &= ~tmrSTATUS_IS_ACTIVE; + mtCOVERAGE_TEST_MARKER(); + } - for( ;; ) - { - /* Query the timers list to see if it contains any timers, and if so, - obtain the time at which the next timer will expire. */ - xNextExpireTime = prvGetNextExpireTime( &xListWasEmpty ); - - /* If a timer has expired, process it. Otherwise, block this task - until either a timer does expire, or a command is received. */ - prvProcessTimerOrBlockTask( xNextExpireTime, xListWasEmpty ); - - /* Empty the command queue. */ - prvProcessReceivedCommands(); - } -} + /* Call the timer callback. */ + pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer ); + } /*-----------------------------------------------------------*/ -static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, BaseType_t xListWasEmpty ) -{ -TickType_t xTimeNow; -BaseType_t xTimerListsWereSwitched; + static portTASK_FUNCTION( prvTimerTask, pvParameters ) + { + TickType_t xNextExpireTime; + BaseType_t xListWasEmpty; - taskENTER_CRITICAL( &xTimerMux); - { - /* Obtain the time now to make an assessment as to whether the timer - has expired or not. If obtaining the time causes the lists to switch - then don't process this timer as any timers that remained in the list - when the lists were switched will have been processed within the - prvSampleTimeNow() function. */ - xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched ); - if( xTimerListsWereSwitched == pdFALSE ) - { - /* The tick count has not overflowed, has the timer expired? */ - if( ( xListWasEmpty == pdFALSE ) && ( xNextExpireTime <= xTimeNow ) ) - { - taskEXIT_CRITICAL( &xTimerMux); - prvProcessExpiredTimer( xNextExpireTime, xTimeNow ); - } - else - { - /* The tick count has not overflowed, and the next expire - time has not been reached yet. This task should therefore - block to wait for the next expire time or a command to be - received - whichever comes first. The following line cannot - be reached unless xNextExpireTime > xTimeNow, except in the - case when the current timer list is empty. */ - if( xListWasEmpty != pdFALSE ) - { - /* The current timer list is empty - is the overflow list - also empty? */ - xListWasEmpty = listLIST_IS_EMPTY( pxOverflowTimerList ); - } + /* Just to avoid compiler warnings. */ + ( void ) pvParameters; - vQueueWaitForMessageRestricted( xTimerQueue, ( xNextExpireTime - xTimeNow ), xListWasEmpty ); + #if ( configUSE_DAEMON_TASK_STARTUP_HOOK == 1 ) + { + extern void vApplicationDaemonTaskStartupHook( void ); - taskEXIT_CRITICAL( &xTimerMux); + /* Allow the application writer to execute some code in the context of + * this task at the point the task starts executing. This is useful if the + * application includes initialisation code that would benefit from + * executing after the scheduler has been started. */ + vApplicationDaemonTaskStartupHook(); + } + #endif /* configUSE_DAEMON_TASK_STARTUP_HOOK */ - /* Yield to wait for either a command to arrive, or the - block time to expire. If a command arrived between the - critical section being exited and this yield then the yield - will not cause the task to block. */ - portYIELD_WITHIN_API(); + for( ; ; ) + { + /* Query the timers list to see if it contains any timers, and if so, + * obtain the time at which the next timer will expire. */ + xNextExpireTime = prvGetNextExpireTime( &xListWasEmpty ); - } - } - else - { - taskEXIT_CRITICAL( &xTimerMux); - } - } -} + /* If a timer has expired, process it. Otherwise, block this task + * until either a timer does expire, or a command is received. */ + prvProcessTimerOrBlockTask( xNextExpireTime, xListWasEmpty ); + + /* Empty the command queue. */ + prvProcessReceivedCommands(); + } + } /*-----------------------------------------------------------*/ -static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty ) -{ -TickType_t xNextExpireTime; + static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, + BaseType_t xListWasEmpty ) + { + TickType_t xTimeNow; + BaseType_t xTimerListsWereSwitched; - /* Timers are listed in expiry time order, with the head of the list - referencing the task that will expire first. Obtain the time at which - the timer with the nearest expiry time will expire. If there are no - active timers then just set the next expire time to 0. That will cause - this task to unblock when the tick count overflows, at which point the - timer lists will be switched and the next expiry time can be - re-assessed. */ - *pxListWasEmpty = listLIST_IS_EMPTY( pxCurrentTimerList ); - if( *pxListWasEmpty == pdFALSE ) - { - xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList ); - } - else - { - /* Ensure the task unblocks when the tick count rolls over. */ - xNextExpireTime = ( TickType_t ) 0U; - } +#ifdef ESP_PLATFORM + taskENTER_CRITICAL(); +#else + vTaskSuspendAll(); +#endif // ESP_PLATFORM + { + /* Obtain the time now to make an assessment as to whether the timer + * has expired or not. If obtaining the time causes the lists to switch + * then don't process this timer as any timers that remained in the list + * when the lists were switched will have been processed within the + * prvSampleTimeNow() function. */ + xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched ); - return xNextExpireTime; -} + if( xTimerListsWereSwitched == pdFALSE ) + { + /* The tick count has not overflowed, has the timer expired? */ + if( ( xListWasEmpty == pdFALSE ) && ( xNextExpireTime <= xTimeNow ) ) + { +#ifdef ESP_PLATFORM + taskEXIT_CRITICAL(); +#else + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM + prvProcessExpiredTimer( xNextExpireTime, xTimeNow ); + } + else + { + /* The tick count has not overflowed, and the next expire + * time has not been reached yet. This task should therefore + * block to wait for the next expire time or a command to be + * received - whichever comes first. The following line cannot + * be reached unless xNextExpireTime > xTimeNow, except in the + * case when the current timer list is empty. */ + if( xListWasEmpty != pdFALSE ) + { + /* The current timer list is empty - is the overflow list + * also empty? */ + xListWasEmpty = listLIST_IS_EMPTY( pxOverflowTimerList ); + } + + vQueueWaitForMessageRestricted( xTimerQueue, ( xNextExpireTime - xTimeNow ), xListWasEmpty ); + +#ifdef ESP_PLATFORM // IDF-3755 + taskEXIT_CRITICAL(); +#else + if( xTaskResumeAll() == pdFALSE ) +#endif // ESP_PLATFORM + { + /* Yield to wait for either a command to arrive, or the + * block time to expire. If a command arrived between the + * critical section being exited and this yield then the yield + * will not cause the task to block. */ + portYIELD_WITHIN_API(); + } +#ifndef ESP_PLATFORM // IDF-3755 + else + { + mtCOVERAGE_TEST_MARKER(); + } +#endif // ESP_PLATFORM + } + } + else + { +#ifdef ESP_PLATFORM // IDF-3755 + taskEXIT_CRITICAL(); +#else + ( void ) xTaskResumeAll(); +#endif // ESP_PLATFORM + } + } + } /*-----------------------------------------------------------*/ -static TickType_t prvSampleTimeNow( BaseType_t * const pxTimerListsWereSwitched ) -{ -TickType_t xTimeNow; -PRIVILEGED_DATA static TickType_t xLastTime = ( TickType_t ) 0U; /*lint !e956 Variable is only accessible to one task. */ + static TickType_t prvGetNextExpireTime( BaseType_t * const pxListWasEmpty ) + { + TickType_t xNextExpireTime; - xTimeNow = xTaskGetTickCount(); + /* Timers are listed in expiry time order, with the head of the list + * referencing the task that will expire first. Obtain the time at which + * the timer with the nearest expiry time will expire. If there are no + * active timers then just set the next expire time to 0. That will cause + * this task to unblock when the tick count overflows, at which point the + * timer lists will be switched and the next expiry time can be + * re-assessed. */ + *pxListWasEmpty = listLIST_IS_EMPTY( pxCurrentTimerList ); - if( xTimeNow < xLastTime ) - { - prvSwitchTimerLists(); - *pxTimerListsWereSwitched = pdTRUE; - } - else - { - *pxTimerListsWereSwitched = pdFALSE; - } + if( *pxListWasEmpty == pdFALSE ) + { + xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList ); + } + else + { + /* Ensure the task unblocks when the tick count rolls over. */ + xNextExpireTime = ( TickType_t ) 0U; + } - xLastTime = xTimeNow; - - return xTimeNow; -} + return xNextExpireTime; + } /*-----------------------------------------------------------*/ -static BaseType_t prvInsertTimerInActiveList( Timer_t * const pxTimer, const TickType_t xNextExpiryTime, const TickType_t xTimeNow, const TickType_t xCommandTime ) -{ -BaseType_t xProcessTimerNow = pdFALSE; + static TickType_t prvSampleTimeNow( BaseType_t * const pxTimerListsWereSwitched ) + { + TickType_t xTimeNow; + PRIVILEGED_DATA static TickType_t xLastTime = ( TickType_t ) 0U; /*lint !e956 Variable is only accessible to one task. */ - listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xNextExpiryTime ); - listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer ); + xTimeNow = xTaskGetTickCount(); - if( xNextExpiryTime <= xTimeNow ) - { - /* Has the expiry time elapsed between the command to start/reset a - timer was issued, and the time the command was processed? */ - if( ( ( TickType_t ) ( xTimeNow - xCommandTime ) ) >= pxTimer->xTimerPeriodInTicks ) /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ - { - /* The time between a command being issued and the command being - processed actually exceeds the timers period. */ - xProcessTimerNow = pdTRUE; - } - else - { - vListInsert( pxOverflowTimerList, &( pxTimer->xTimerListItem ) ); - } - } - else - { - if( ( xTimeNow < xCommandTime ) && ( xNextExpiryTime >= xCommandTime ) ) - { - /* If, since the command was issued, the tick count has overflowed - but the expiry time has not, then the timer must have already passed - its expiry time and should be processed immediately. */ - xProcessTimerNow = pdTRUE; - } - else - { - vListInsert( pxCurrentTimerList, &( pxTimer->xTimerListItem ) ); - } - } + if( xTimeNow < xLastTime ) + { + prvSwitchTimerLists(); + *pxTimerListsWereSwitched = pdTRUE; + } + else + { + *pxTimerListsWereSwitched = pdFALSE; + } - return xProcessTimerNow; -} + xLastTime = xTimeNow; + + return xTimeNow; + } /*-----------------------------------------------------------*/ -static void prvProcessReceivedCommands( void ) -{ -DaemonTaskMessage_t xMessage; -Timer_t *pxTimer; -BaseType_t xTimerListsWereSwitched, xResult; -TickType_t xTimeNow; + static BaseType_t prvInsertTimerInActiveList( Timer_t * const pxTimer, + const TickType_t xNextExpiryTime, + const TickType_t xTimeNow, + const TickType_t xCommandTime ) + { + BaseType_t xProcessTimerNow = pdFALSE; - while( xQueueReceive( xTimerQueue, &xMessage, tmrNO_DELAY ) != pdFAIL ) /*lint !e603 xMessage does not have to be initialised as it is passed out, not in, and it is not used unless xQueueReceive() returns pdTRUE. */ - { - #if ( INCLUDE_xTimerPendFunctionCall == 1 ) - { - /* Negative commands are pended function calls rather than timer - commands. */ - if( xMessage.xMessageID < ( BaseType_t ) 0 ) - { - const CallbackParameters_t * const pxCallback = &( xMessage.u.xCallbackParameters ); + listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xNextExpiryTime ); + listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer ); - /* The timer uses the xCallbackParameters member to request a - callback be executed. Check the callback is not NULL. */ - configASSERT( pxCallback ); + if( xNextExpiryTime <= xTimeNow ) + { + /* Has the expiry time elapsed between the command to start/reset a + * timer was issued, and the time the command was processed? */ + if( ( ( TickType_t ) ( xTimeNow - xCommandTime ) ) >= pxTimer->xTimerPeriodInTicks ) /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + { + /* The time between a command being issued and the command being + * processed actually exceeds the timers period. */ + xProcessTimerNow = pdTRUE; + } + else + { + vListInsert( pxOverflowTimerList, &( pxTimer->xTimerListItem ) ); + } + } + else + { + if( ( xTimeNow < xCommandTime ) && ( xNextExpiryTime >= xCommandTime ) ) + { + /* If, since the command was issued, the tick count has overflowed + * but the expiry time has not, then the timer must have already passed + * its expiry time and should be processed immediately. */ + xProcessTimerNow = pdTRUE; + } + else + { + vListInsert( pxCurrentTimerList, &( pxTimer->xTimerListItem ) ); + } + } - /* Call the function. */ - pxCallback->pxCallbackFunction( pxCallback->pvParameter1, pxCallback->ulParameter2 ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - #endif /* INCLUDE_xTimerPendFunctionCall */ - - /* Commands that are positive are timer commands rather than pended - function calls. */ - if( xMessage.xMessageID >= ( BaseType_t ) 0 ) - { - /* The messages uses the xTimerParameters member to work on a - software timer. */ - pxTimer = xMessage.u.xTimerParameters.pxTimer; - - if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE ) /*lint !e961. The cast is only redundant when NULL is passed into the macro. */ - { - /* The timer is in a list, remove it. */ - ( void ) uxListRemove( &( pxTimer->xTimerListItem ) ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - traceTIMER_COMMAND_RECEIVED( pxTimer, xMessage.xMessageID, xMessage.u.xTimerParameters.xMessageValue ); - - /* In this case the xTimerListsWereSwitched parameter is not used, but - it must be present in the function call. prvSampleTimeNow() must be - called after the message is received from xTimerQueue so there is no - possibility of a higher priority task adding a message to the message - queue with a time that is ahead of the timer daemon task (because it - pre-empted the timer daemon task after the xTimeNow value was set). */ - xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched ); - - switch( xMessage.xMessageID ) - { - case tmrCOMMAND_START : - case tmrCOMMAND_START_FROM_ISR : - case tmrCOMMAND_RESET : - case tmrCOMMAND_RESET_FROM_ISR : - case tmrCOMMAND_START_DONT_TRACE : - /* Start or restart a timer. */ - pxTimer->ucStatus |= tmrSTATUS_IS_ACTIVE; - if( prvInsertTimerInActiveList( pxTimer, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.u.xTimerParameters.xMessageValue ) != pdFALSE ) - { - /* The timer expired before it was added to the active - timer list. Process it now. */ - pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer ); - traceTIMER_EXPIRED( pxTimer ); - - if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) != 0 ) - { - xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, NULL, tmrNO_DELAY ); - configASSERT( xResult ); - ( void ) xResult; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - break; - - case tmrCOMMAND_STOP : - case tmrCOMMAND_STOP_FROM_ISR : - /* The timer has already been removed from the active list. */ - pxTimer->ucStatus &= ~tmrSTATUS_IS_ACTIVE; - break; - - case tmrCOMMAND_CHANGE_PERIOD : - case tmrCOMMAND_CHANGE_PERIOD_FROM_ISR : - pxTimer->ucStatus |= tmrSTATUS_IS_ACTIVE; - pxTimer->xTimerPeriodInTicks = xMessage.u.xTimerParameters.xMessageValue; - configASSERT( ( pxTimer->xTimerPeriodInTicks > 0 ) ); - - /* The new period does not really have a reference, and can - be longer or shorter than the old one. The command time is - therefore set to the current time, and as the period cannot - be zero the next expiry time can only be in the future, - meaning (unlike for the xTimerStart() case above) there is - no fail case that needs to be handled here. */ - ( void ) prvInsertTimerInActiveList( pxTimer, ( xTimeNow + pxTimer->xTimerPeriodInTicks ), xTimeNow, xTimeNow ); - break; - - case tmrCOMMAND_DELETE : - #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) - { - /* The timer has already been removed from the active list, - just free up the memory if the memory was dynamically - allocated. */ - if( ( pxTimer->ucStatus & tmrSTATUS_IS_STATICALLY_ALLOCATED ) == ( uint8_t ) 0 ) - { - vPortFree( pxTimer ); - } - else - { - pxTimer->ucStatus &= ~tmrSTATUS_IS_ACTIVE; - } - } - #else - { - /* If dynamic allocation is not enabled, the memory - could not have been dynamically allocated. So there is - no need to free the memory - just mark the timer as - "not active". */ - pxTimer->ucStatus &= ~tmrSTATUS_IS_ACTIVE; - } - #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ - break; - - default : - /* Don't expect to get here. */ - break; - } - } - } -} + return xProcessTimerNow; + } /*-----------------------------------------------------------*/ -static void prvSwitchTimerLists( void ) -{ -TickType_t xNextExpireTime, xReloadTime; -List_t *pxTemp; -Timer_t *pxTimer; -BaseType_t xResult; + static void prvProcessReceivedCommands( void ) + { + DaemonTaskMessage_t xMessage; + Timer_t * pxTimer; + BaseType_t xTimerListsWereSwitched, xResult; + TickType_t xTimeNow; - /* The tick count has overflowed. The timer lists must be switched. - If there are any timers still referenced from the current timer list - then they must have expired and should be processed before the lists - are switched. */ - while( listLIST_IS_EMPTY( pxCurrentTimerList ) == pdFALSE ) - { - xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList ); + while( xQueueReceive( xTimerQueue, &xMessage, tmrNO_DELAY ) != pdFAIL ) /*lint !e603 xMessage does not have to be initialised as it is passed out, not in, and it is not used unless xQueueReceive() returns pdTRUE. */ + { + #if ( INCLUDE_xTimerPendFunctionCall == 1 ) + { + /* Negative commands are pended function calls rather than timer + * commands. */ + if( xMessage.xMessageID < ( BaseType_t ) 0 ) + { + const CallbackParameters_t * const pxCallback = &( xMessage.u.xCallbackParameters ); - /* Remove the timer from the list. */ - pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList ); /*lint !e9087 !e9079 void * is used as this macro is used with tasks and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ - ( void ) uxListRemove( &( pxTimer->xTimerListItem ) ); - traceTIMER_EXPIRED( pxTimer ); + /* The timer uses the xCallbackParameters member to request a + * callback be executed. Check the callback is not NULL. */ + configASSERT( pxCallback ); - /* Execute its callback, then send a command to restart the timer if - it is an auto-reload timer. It cannot be restarted here as the lists - have not yet been switched. */ - pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer ); + /* Call the function. */ + pxCallback->pxCallbackFunction( pxCallback->pvParameter1, pxCallback->ulParameter2 ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* INCLUDE_xTimerPendFunctionCall */ - if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) != 0 ) - { - /* Calculate the reload value, and if the reload value results in - the timer going into the same timer list then it has already expired - and the timer should be re-inserted into the current list so it is - processed again within this loop. Otherwise a command should be sent - to restart the timer to ensure it is only inserted into a list after - the lists have been swapped. */ - xReloadTime = ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ); - if( xReloadTime > xNextExpireTime ) - { - listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xReloadTime ); - listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer ); - vListInsert( pxCurrentTimerList, &( pxTimer->xTimerListItem ) ); - } - else - { - xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xNextExpireTime, NULL, tmrNO_DELAY ); - configASSERT( xResult ); - ( void ) xResult; - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } + /* Commands that are positive are timer commands rather than pended + * function calls. */ + if( xMessage.xMessageID >= ( BaseType_t ) 0 ) + { + /* The messages uses the xTimerParameters member to work on a + * software timer. */ + pxTimer = xMessage.u.xTimerParameters.pxTimer; - pxTemp = pxCurrentTimerList; - pxCurrentTimerList = pxOverflowTimerList; - pxOverflowTimerList = pxTemp; -} + if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE ) /*lint !e961. The cast is only redundant when NULL is passed into the macro. */ + { + /* The timer is in a list, remove it. */ + ( void ) uxListRemove( &( pxTimer->xTimerListItem ) ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + traceTIMER_COMMAND_RECEIVED( pxTimer, xMessage.xMessageID, xMessage.u.xTimerParameters.xMessageValue ); + + /* In this case the xTimerListsWereSwitched parameter is not used, but + * it must be present in the function call. prvSampleTimeNow() must be + * called after the message is received from xTimerQueue so there is no + * possibility of a higher priority task adding a message to the message + * queue with a time that is ahead of the timer daemon task (because it + * pre-empted the timer daemon task after the xTimeNow value was set). */ + xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched ); + + switch( xMessage.xMessageID ) + { + case tmrCOMMAND_START: + case tmrCOMMAND_START_FROM_ISR: + case tmrCOMMAND_RESET: + case tmrCOMMAND_RESET_FROM_ISR: + case tmrCOMMAND_START_DONT_TRACE: + /* Start or restart a timer. */ + pxTimer->ucStatus |= tmrSTATUS_IS_ACTIVE; + + if( prvInsertTimerInActiveList( pxTimer, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.u.xTimerParameters.xMessageValue ) != pdFALSE ) + { + /* The timer expired before it was added to the active + * timer list. Process it now. */ + pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer ); + traceTIMER_EXPIRED( pxTimer ); + + if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) != 0 ) + { + xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, NULL, tmrNO_DELAY ); + configASSERT( xResult ); + ( void ) xResult; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + break; + + case tmrCOMMAND_STOP: + case tmrCOMMAND_STOP_FROM_ISR: + /* The timer has already been removed from the active list. */ + pxTimer->ucStatus &= ~tmrSTATUS_IS_ACTIVE; + break; + + case tmrCOMMAND_CHANGE_PERIOD: + case tmrCOMMAND_CHANGE_PERIOD_FROM_ISR: + pxTimer->ucStatus |= tmrSTATUS_IS_ACTIVE; + pxTimer->xTimerPeriodInTicks = xMessage.u.xTimerParameters.xMessageValue; + configASSERT( ( pxTimer->xTimerPeriodInTicks > 0 ) ); + + /* The new period does not really have a reference, and can + * be longer or shorter than the old one. The command time is + * therefore set to the current time, and as the period cannot + * be zero the next expiry time can only be in the future, + * meaning (unlike for the xTimerStart() case above) there is + * no fail case that needs to be handled here. */ + ( void ) prvInsertTimerInActiveList( pxTimer, ( xTimeNow + pxTimer->xTimerPeriodInTicks ), xTimeNow, xTimeNow ); + break; + + case tmrCOMMAND_DELETE: + #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + { + /* The timer has already been removed from the active list, + * just free up the memory if the memory was dynamically + * allocated. */ + if( ( pxTimer->ucStatus & tmrSTATUS_IS_STATICALLY_ALLOCATED ) == ( uint8_t ) 0 ) + { + vPortFree( pxTimer ); + } + else + { + pxTimer->ucStatus &= ~tmrSTATUS_IS_ACTIVE; + } + } + #else /* if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) */ + { + /* If dynamic allocation is not enabled, the memory + * could not have been dynamically allocated. So there is + * no need to free the memory - just mark the timer as + * "not active". */ + pxTimer->ucStatus &= ~tmrSTATUS_IS_ACTIVE; + } + #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ + break; + + default: + /* Don't expect to get here. */ + break; + } + } + } + } /*-----------------------------------------------------------*/ -static void prvCheckForValidListAndQueue( void ) -{ - /* Check that the list from which active timers are referenced, and the - queue used to communicate with the timer service, have been - initialised. */ + static void prvSwitchTimerLists( void ) + { + TickType_t xNextExpireTime, xReloadTime; + List_t * pxTemp; + Timer_t * pxTimer; + BaseType_t xResult; - if( xTimerQueue == NULL ) vPortCPUInitializeMutex( &xTimerMux ); + /* The tick count has overflowed. The timer lists must be switched. + * If there are any timers still referenced from the current timer list + * then they must have expired and should be processed before the lists + * are switched. */ + while( listLIST_IS_EMPTY( pxCurrentTimerList ) == pdFALSE ) + { + xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList ); - taskENTER_CRITICAL( &xTimerMux); - { - if( xTimerQueue == NULL ) - { - vListInitialise( &xActiveTimerList1 ); - vListInitialise( &xActiveTimerList2 ); - pxCurrentTimerList = &xActiveTimerList1; - pxOverflowTimerList = &xActiveTimerList2; + /* Remove the timer from the list. */ + pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList ); /*lint !e9087 !e9079 void * is used as this macro is used with tasks and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ + ( void ) uxListRemove( &( pxTimer->xTimerListItem ) ); + traceTIMER_EXPIRED( pxTimer ); - #if( configSUPPORT_STATIC_ALLOCATION == 1 ) - { - /* The timer queue is allocated statically in case - configSUPPORT_DYNAMIC_ALLOCATION is 0. */ - static StaticQueue_t xStaticTimerQueue; /*lint !e956 Ok to declare in this manner to prevent additional conditional compilation guards in other locations. */ - static uint8_t ucStaticTimerQueueStorage[ ( size_t ) configTIMER_QUEUE_LENGTH * sizeof( DaemonTaskMessage_t ) ]; /*lint !e956 Ok to declare in this manner to prevent additional conditional compilation guards in other locations. */ + /* Execute its callback, then send a command to restart the timer if + * it is an auto-reload timer. It cannot be restarted here as the lists + * have not yet been switched. */ + pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer ); - xTimerQueue = xQueueCreateStatic( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, ( UBaseType_t ) sizeof( DaemonTaskMessage_t ), &( ucStaticTimerQueueStorage[ 0 ] ), &xStaticTimerQueue ); - } - #else - { - xTimerQueue = xQueueCreate( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, sizeof( DaemonTaskMessage_t ) ); - } - #endif + if( ( pxTimer->ucStatus & tmrSTATUS_IS_AUTORELOAD ) != 0 ) + { + /* Calculate the reload value, and if the reload value results in + * the timer going into the same timer list then it has already expired + * and the timer should be re-inserted into the current list so it is + * processed again within this loop. Otherwise a command should be sent + * to restart the timer to ensure it is only inserted into a list after + * the lists have been swapped. */ + xReloadTime = ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ); - #if ( configQUEUE_REGISTRY_SIZE > 0 ) - { - if( xTimerQueue != NULL ) - { - vQueueAddToRegistry( xTimerQueue, "TmrQ" ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - #endif /* configQUEUE_REGISTRY_SIZE */ - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - taskEXIT_CRITICAL( &xTimerMux); -} + if( xReloadTime > xNextExpireTime ) + { + listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xReloadTime ); + listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer ); + vListInsert( pxCurrentTimerList, &( pxTimer->xTimerListItem ) ); + } + else + { + xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xNextExpireTime, NULL, tmrNO_DELAY ); + configASSERT( xResult ); + ( void ) xResult; + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + pxTemp = pxCurrentTimerList; + pxCurrentTimerList = pxOverflowTimerList; + pxOverflowTimerList = pxTemp; + } /*-----------------------------------------------------------*/ -BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ) -{ -BaseType_t xReturn; -Timer_t *pxTimer = xTimer; + static void prvCheckForValidListAndQueue( void ) + { + /* Check that the list from which active timers are referenced, and the + * queue used to communicate with the timer service, have been + * initialised. */ +#ifdef ESP_PLATFORM + if( xTimerQueue == NULL ) vPortCPUInitializeMutex( &xTimerMux ); +#endif // ESP_PLATFORM - configASSERT( xTimer ); + taskENTER_CRITICAL(); + { + if( xTimerQueue == NULL ) + { + vListInitialise( &xActiveTimerList1 ); + vListInitialise( &xActiveTimerList2 ); + pxCurrentTimerList = &xActiveTimerList1; + pxOverflowTimerList = &xActiveTimerList2; - /* Is the timer in the list of active timers? */ - taskENTER_CRITICAL( &xTimerMux); - { - if( ( pxTimer->ucStatus & tmrSTATUS_IS_ACTIVE ) == 0 ) - { - xReturn = pdFALSE; - } - else - { - xReturn = pdTRUE; - } - } - taskEXIT_CRITICAL( &xTimerMux); + #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + { + /* The timer queue is allocated statically in case + * configSUPPORT_DYNAMIC_ALLOCATION is 0. */ + PRIVILEGED_DATA static StaticQueue_t xStaticTimerQueue; /*lint !e956 Ok to declare in this manner to prevent additional conditional compilation guards in other locations. */ + PRIVILEGED_DATA static uint8_t ucStaticTimerQueueStorage[ ( size_t ) configTIMER_QUEUE_LENGTH * sizeof( DaemonTaskMessage_t ) ]; /*lint !e956 Ok to declare in this manner to prevent additional conditional compilation guards in other locations. */ - return xReturn; -} /*lint !e818 Can't be pointer to const due to the typedef. */ + xTimerQueue = xQueueCreateStatic( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, ( UBaseType_t ) sizeof( DaemonTaskMessage_t ), &( ucStaticTimerQueueStorage[ 0 ] ), &xStaticTimerQueue ); + } + #else + { + xTimerQueue = xQueueCreate( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, sizeof( DaemonTaskMessage_t ) ); + } + #endif /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ + + #if ( configQUEUE_REGISTRY_SIZE > 0 ) + { + if( xTimerQueue != NULL ) + { + vQueueAddToRegistry( xTimerQueue, "TmrQ" ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configQUEUE_REGISTRY_SIZE */ + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(); + } /*-----------------------------------------------------------*/ -void *pvTimerGetTimerID( const TimerHandle_t xTimer ) -{ -Timer_t * const pxTimer = xTimer; -void *pvReturn; + BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ) + { + BaseType_t xReturn; + Timer_t * pxTimer = xTimer; - configASSERT( xTimer ); + configASSERT( xTimer ); - taskENTER_CRITICAL( &xTimerMux); - { - pvReturn = pxTimer->pvTimerID; - } - taskEXIT_CRITICAL( &xTimerMux); + /* Is the timer in the list of active timers? */ + taskENTER_CRITICAL(); + { + if( ( pxTimer->ucStatus & tmrSTATUS_IS_ACTIVE ) == 0 ) + { + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } + } + taskEXIT_CRITICAL(); - return pvReturn; -} + return xReturn; + } /*lint !e818 Can't be pointer to const due to the typedef. */ /*-----------------------------------------------------------*/ -void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID ) -{ -Timer_t * const pxTimer = xTimer; + void * pvTimerGetTimerID( const TimerHandle_t xTimer ) + { + Timer_t * const pxTimer = xTimer; + void * pvReturn; - configASSERT( xTimer ); + configASSERT( xTimer ); - taskENTER_CRITICAL( &xTimerMux); - { - pxTimer->pvTimerID = pvNewID; - } - taskEXIT_CRITICAL( &xTimerMux); -} + taskENTER_CRITICAL(); + { + pvReturn = pxTimer->pvTimerID; + } + taskEXIT_CRITICAL(); + + return pvReturn; + } /*-----------------------------------------------------------*/ -#if( INCLUDE_xTimerPendFunctionCall == 1 ) + void vTimerSetTimerID( TimerHandle_t xTimer, + void * pvNewID ) + { + Timer_t * const pxTimer = xTimer; - BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, BaseType_t *pxHigherPriorityTaskWoken ) - { - DaemonTaskMessage_t xMessage; - BaseType_t xReturn; + configASSERT( xTimer ); - /* Complete the message with the function parameters and post it to the - daemon task. */ - xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR; - xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend; - xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1; - xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2; - - xReturn = xQueueSendFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken ); - - tracePEND_FUNC_CALL_FROM_ISR( xFunctionToPend, pvParameter1, ulParameter2, xReturn ); - - return xReturn; - } - -#endif /* INCLUDE_xTimerPendFunctionCall */ + taskENTER_CRITICAL(); + { + pxTimer->pvTimerID = pvNewID; + } + taskEXIT_CRITICAL(); + } /*-----------------------------------------------------------*/ -#if( INCLUDE_xTimerPendFunctionCall == 1 ) + #if ( INCLUDE_xTimerPendFunctionCall == 1 ) - BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait ) - { - DaemonTaskMessage_t xMessage; - BaseType_t xReturn; + BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, + void * pvParameter1, + uint32_t ulParameter2, + BaseType_t * pxHigherPriorityTaskWoken ) + { + DaemonTaskMessage_t xMessage; + BaseType_t xReturn; - /* This function can only be called after a timer has been created or - after the scheduler has been started because, until then, the timer - queue does not exist. */ - configASSERT( xTimerQueue ); + /* Complete the message with the function parameters and post it to the + * daemon task. */ + xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR; + xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend; + xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1; + xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2; - /* Complete the message with the function parameters and post it to the - daemon task. */ - xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK; - xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend; - xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1; - xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2; + xReturn = xQueueSendFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken ); - xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait ); + tracePEND_FUNC_CALL_FROM_ISR( xFunctionToPend, pvParameter1, ulParameter2, xReturn ); - tracePEND_FUNC_CALL( xFunctionToPend, pvParameter1, ulParameter2, xReturn ); + return xReturn; + } - return xReturn; - } - -#endif /* INCLUDE_xTimerPendFunctionCall */ + #endif /* INCLUDE_xTimerPendFunctionCall */ /*-----------------------------------------------------------*/ -#if ( configUSE_TRACE_FACILITY == 1 ) + #if ( INCLUDE_xTimerPendFunctionCall == 1 ) - UBaseType_t uxTimerGetTimerNumber( TimerHandle_t xTimer ) - { - return ( ( Timer_t * ) xTimer )->uxTimerNumber; - } + BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, + void * pvParameter1, + uint32_t ulParameter2, + TickType_t xTicksToWait ) + { + DaemonTaskMessage_t xMessage; + BaseType_t xReturn; -#endif /* configUSE_TRACE_FACILITY */ + /* This function can only be called after a timer has been created or + * after the scheduler has been started because, until then, the timer + * queue does not exist. */ + configASSERT( xTimerQueue ); + + /* Complete the message with the function parameters and post it to the + * daemon task. */ + xMessage.xMessageID = tmrCOMMAND_EXECUTE_CALLBACK; + xMessage.u.xCallbackParameters.pxCallbackFunction = xFunctionToPend; + xMessage.u.xCallbackParameters.pvParameter1 = pvParameter1; + xMessage.u.xCallbackParameters.ulParameter2 = ulParameter2; + + xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait ); + + tracePEND_FUNC_CALL( xFunctionToPend, pvParameter1, ulParameter2, xReturn ); + + return xReturn; + } + + #endif /* INCLUDE_xTimerPendFunctionCall */ /*-----------------------------------------------------------*/ -#if ( configUSE_TRACE_FACILITY == 1 ) + #if ( configUSE_TRACE_FACILITY == 1 ) - void vTimerSetTimerNumber( TimerHandle_t xTimer, UBaseType_t uxTimerNumber ) - { - ( ( Timer_t * ) xTimer )->uxTimerNumber = uxTimerNumber; - } + UBaseType_t uxTimerGetTimerNumber( TimerHandle_t xTimer ) + { + return ( ( Timer_t * ) xTimer )->uxTimerNumber; + } -#endif /* configUSE_TRACE_FACILITY */ + #endif /* configUSE_TRACE_FACILITY */ +/*-----------------------------------------------------------*/ + + #if ( configUSE_TRACE_FACILITY == 1 ) + + void vTimerSetTimerNumber( TimerHandle_t xTimer, + UBaseType_t uxTimerNumber ) + { + ( ( Timer_t * ) xTimer )->uxTimerNumber = uxTimerNumber; + } + + #endif /* configUSE_TRACE_FACILITY */ /*-----------------------------------------------------------*/ /* This entire source file will be skipped if the application is not configured -to include software timer functionality. If you want to include software timer -functionality then ensure configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */ + * to include software timer functionality. If you want to include software timer + * functionality then ensure configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */ #endif /* configUSE_TIMERS == 1 */ diff --git a/components/hal/CMakeLists.txt b/components/hal/CMakeLists.txt index b298d44ae8..d688177759 100644 --- a/components/hal/CMakeLists.txt +++ b/components/hal/CMakeLists.txt @@ -1,52 +1,52 @@ idf_build_get_property(target IDF_TARGET) -set(srcs "wdt_hal_iram.c" - "mpu_hal.c" - "cpu_hal.c") +set(srcs "wdt_hal_iram.c" + "mpu_hal.c" + "cpu_hal.c") set(includes "${target}/include" "include" "platform_port/include") if(NOT BOOTLOADER_BUILD) list(APPEND srcs - "rmt_hal.c" - "rtc_io_hal.c" - "spi_hal.c" - "spi_hal_iram.c" - "spi_slave_hal.c" - "spi_slave_hal_iram.c" - "i2s_hal.c" - "sigmadelta_hal.c" - "timer_hal.c" - "ledc_hal.c" - "ledc_hal_iram.c" - "i2c_hal.c" - "i2c_hal_iram.c" - "gpio_hal.c" - "uart_hal.c" - "uart_hal_iram.c" - "spi_flash_hal.c" - "spi_flash_hal_iram.c" - "spi_flash_encrypt_hal_iram.c" - "soc_hal.c" - "interrupt_controller_hal.c" - "sha_hal.c" - "aes_hal.c" - "twai_hal.c" - "twai_hal_iram.c" - "adc_hal.c") + "rmt_hal.c" + "rtc_io_hal.c" + "spi_hal.c" + "spi_hal_iram.c" + "spi_slave_hal.c" + "spi_slave_hal_iram.c" + "i2s_hal.c" + "sigmadelta_hal.c" + "timer_hal.c" + "ledc_hal.c" + "ledc_hal_iram.c" + "i2c_hal.c" + "i2c_hal_iram.c" + "gpio_hal.c" + "uart_hal.c" + "uart_hal_iram.c" + "spi_flash_hal.c" + "spi_flash_hal_iram.c" + "spi_flash_encrypt_hal_iram.c" + "soc_hal.c" + "interrupt_controller_hal.c" + "sha_hal.c" + "aes_hal.c" + "twai_hal.c" + "twai_hal_iram.c" + "adc_hal.c") if(${target} STREQUAL "esp32") list(APPEND srcs - "dac_hal.c" - "mcpwm_hal.c" - "pcnt_hal.c" - "sdio_slave_hal.c" - "touch_sensor_hal.c" - "esp32/adc_hal.c" - "esp32/brownout_hal.c" - "esp32/interrupt_descriptor_table.c" - "esp32/touch_sensor_hal.c" - "esp32/gpio_hal_workaround.c") + "dac_hal.c" + "mcpwm_hal.c" + "pcnt_hal.c" + "sdio_slave_hal.c" + "touch_sensor_hal.c" + "esp32/adc_hal.c" + "esp32/brownout_hal.c" + "esp32/interrupt_descriptor_table.c" + "esp32/touch_sensor_hal.c" + "esp32/gpio_hal_workaround.c") if(NOT BOOTLOADER_BUILD AND CONFIG_ETH_USE_ESP32_EMAC) list(APPEND srcs "emac_hal.c") endif() @@ -61,6 +61,8 @@ if(NOT BOOTLOADER_BUILD) "systimer_hal.c" "touch_sensor_hal.c" "usb_hal.c" + "usb_phy_hal.c" + "xt_wdt_hal.c" "esp32s2/adc_hal.c" "esp32s2/brownout_hal.c" "esp32s2/cp_dma_hal.c" @@ -72,6 +74,7 @@ if(NOT BOOTLOADER_BUILD) if(${target} STREQUAL "esp32s3") list(APPEND srcs + "ds_hal.c" "gdma_hal.c" "lcd_hal.c" "mcpwm_hal.c" @@ -81,9 +84,13 @@ if(NOT BOOTLOADER_BUILD) "systimer_hal.c" "touch_sensor_hal.c" "usb_hal.c" + "usb_phy_hal.c" + "xt_wdt_hal.c" "esp32s3/brownout_hal.c" + "esp32s3/hmac_hal.c" "esp32s3/interrupt_descriptor_table.c" "esp32s3/touch_sensor_hal.c" + "esp32s3/rtc_cntl_hal.c" "usbh_hal.c") endif() @@ -94,6 +101,7 @@ if(NOT BOOTLOADER_BUILD) "spi_flash_hal_gpspi.c" "spi_slave_hd_hal.c" "systimer_hal.c" + "xt_wdt_hal.c" "esp32c3/adc_hal.c" "esp32c3/brownout_hal.c" "esp32c3/hmac_hal.c" @@ -102,15 +110,15 @@ if(NOT BOOTLOADER_BUILD) if(${target} STREQUAL "esp32h2") list(APPEND srcs - "ds_hal.c" - "gdma_hal.c" - "spi_flash_hal_gpspi.c" - "spi_slave_hd_hal.c" - "systimer_hal.c" - "esp32h2/adc_hal.c" - "esp32h2/brownout_hal.c" - "esp32h2/hmac_hal.c" - "esp32h2/rtc_cntl_hal.c") + "ds_hal.c" + "gdma_hal.c" + "spi_flash_hal_gpspi.c" + "spi_slave_hd_hal.c" + "systimer_hal.c" + "esp32h2/adc_hal.c" + "esp32h2/brownout_hal.c" + "esp32h2/hmac_hal.c" + "esp32h2/rtc_cntl_hal.c") endif() endif() diff --git a/components/hal/adc_hal.c b/components/hal/adc_hal.c index b5e3c701dd..bf38b76edb 100644 --- a/components/hal/adc_hal.c +++ b/components/hal/adc_hal.c @@ -55,7 +55,7 @@ void adc_hal_arbiter_config(adc_arbiter_t *config) /*--------------------------------------------------------------- ADC calibration setting ---------------------------------------------------------------*/ -#if SOC_ADC_HW_CALIBRATION_V1 +#if SOC_ADC_CALIBRATION_V1_SUPPORTED void adc_hal_calibration_init(adc_ll_num_t adc_n) { adc_ll_calibration_init(adc_n); @@ -71,10 +71,14 @@ void adc_hal_set_calibration_param(adc_ll_num_t adc_n, uint32_t param) } } -#if CONFIG_IDF_TARGET_ESP32S2 +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 static void cal_setup(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool internal_gnd) { +#if CONFIG_IDF_TARGET_ESP32S2 adc_hal_set_controller(adc_n, ADC_CTRL_RTC); //Set controller +#else + adc_hal_set_controller(adc_n, ADC_LL_CTRL_ARB); //Set controller +#endif /* Enable/disable internal connect GND (for calibration). */ if (internal_gnd) { @@ -189,9 +193,10 @@ uint32_t adc_hal_self_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc : (code_sum - chk_code) / (ADC_HAL_CAL_TIMES - 2) + 1; adc_ll_calibration_finish(adc_n); + return ret; } -#endif //SOC_ADC_HW_CALIBRATION_V1 +#endif //SOC_ADC_CALIBRATION_V1_SUPPORTED #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 //This feature is currently supported on ESP32C3, will be supported on other chips soon diff --git a/components/hal/component.mk b/components/hal/component.mk index 66d5054f62..c5c1e84abc 100644 --- a/components/hal/component.mk +++ b/components/hal/component.mk @@ -2,7 +2,7 @@ COMPONENT_SRCDIRS := . esp32 COMPONENT_ADD_INCLUDEDIRS := esp32/include include platform_port/include COMPONENT_ADD_LDFRAGMENTS += linker.lf -COMPONENT_OBJEXCLUDE += ./spi_slave_hd_hal.o ./spi_flash_hal_gpspi.o ./spi_slave_hd_hal.o ./ds_hal.o ./gdma_hal.o ./lcd_hal.o ./systimer_hal.o ./usb_hal.o ./usbh_hal.o +COMPONENT_OBJEXCLUDE += ./spi_slave_hd_hal.o ./spi_flash_hal_gpspi.o ./spi_slave_hd_hal.o ./ds_hal.o ./gdma_hal.o ./lcd_hal.o ./systimer_hal.o ./usb_hal.o ./usbh_hal.o ./usb_phy_hal.o ./xt_wdt_hal.o ifndef CONFIG_ETH_USE_ESP32_EMAC COMPONENT_OBJEXCLUDE += ./emac_hal.o diff --git a/components/hal/emac_hal.c b/components/hal/emac_hal.c index bd202edb34..ef6318ff7e 100644 --- a/components/hal/emac_hal.c +++ b/components/hal/emac_hal.c @@ -141,16 +141,16 @@ void emac_hal_init(emac_hal_context_t *hal, void *descriptors, void emac_hal_set_csr_clock_range(emac_hal_context_t *hal, int freq) { - /* Tell MAC system clock Frequency, which will determine the frequency range of MDC(1MHz~2.5MHz) */ - if (freq >= 20 && freq < 35) { + /* Tell MAC system clock Frequency in MHz, which will determine the frequency range of MDC(1MHz~2.5MHz) */ + if (freq >= 20000000 && freq < 35000000) { emac_ll_set_csr_clock_division(hal->mac_regs, 2); // CSR clock/16 - } else if (freq >= 35 && freq < 60) { + } else if (freq >= 35000000 && freq < 60000000) { emac_ll_set_csr_clock_division(hal->mac_regs, 3); // CSR clock/26 - } else if (freq >= 60 && freq < 100) { + } else if (freq >= 60000000 && freq < 100000000) { emac_ll_set_csr_clock_division(hal->mac_regs, 0); // CSR clock/42 - } else if (freq >= 100 && freq < 150) { + } else if (freq >= 100000000 && freq < 150000000) { emac_ll_set_csr_clock_division(hal->mac_regs, 1); // CSR clock/62 - } else if (freq > 150 && freq < 250) { + } else if (freq >= 150000000 && freq < 250000000) { emac_ll_set_csr_clock_division(hal->mac_regs, 4); // CSR clock/102 } else { emac_ll_set_csr_clock_division(hal->mac_regs, 5); // CSR clock/124 @@ -281,8 +281,8 @@ void emac_hal_init_dma_default(emac_hal_context_t *hal) emac_ll_recv_store_forward_enable(hal->dma_regs, true); /* Enable Flushing of Received Frames because of the unavailability of receive descriptors or buffers */ emac_ll_flush_recv_frame_enable(hal->dma_regs, true); - /* Enable Transmit Store Forward */ - emac_ll_trans_store_forward_enable(hal->dma_regs, true); + /* Disable Transmit Store Forward */ + emac_ll_trans_store_forward_enable(hal->dma_regs, false); /* Flush Transmit FIFO */ emac_ll_flush_trans_fifo_enable(hal->dma_regs, true); /* Transmit Threshold Control */ diff --git a/components/hal/esp32/include/hal/adc_ll.h b/components/hal/esp32/include/hal/adc_ll.h index 587d7e7a34..1b5969ac43 100644 --- a/components/hal/esp32/include/hal/adc_ll.h +++ b/components/hal/esp32/include/hal/adc_ll.h @@ -3,7 +3,11 @@ #include "soc/adc_periph.h" #include "hal/adc_types.h" #include "soc/rtc_io_struct.h" +#include "soc/sens_struct.h" +#include "soc/syscon_struct.h" +#include "soc/rtc_cntl_struct.h" #include +#include "hal/misc.h" #ifdef __cplusplus extern "C" { @@ -52,11 +56,11 @@ typedef enum { static inline void adc_ll_digi_set_fsm_time(uint32_t rst_wait, uint32_t start_wait, uint32_t standby_wait) { // Internal FSM reset wait time - SYSCON.saradc_fsm.rstb_wait = rst_wait; + HAL_FORCE_MODIFY_U32_REG_FIELD(SYSCON.saradc_fsm, rstb_wait, rst_wait); // Internal FSM start wait time - SYSCON.saradc_fsm.start_wait = start_wait; + HAL_FORCE_MODIFY_U32_REG_FIELD(SYSCON.saradc_fsm, start_wait, start_wait); // Internal FSM standby wait time - SYSCON.saradc_fsm.standby_wait = standby_wait; + HAL_FORCE_MODIFY_U32_REG_FIELD(SYSCON.saradc_fsm, standby_wait, standby_wait); } /** @@ -67,7 +71,7 @@ static inline void adc_ll_digi_set_fsm_time(uint32_t rst_wait, uint32_t start_wa */ static inline void adc_ll_set_sample_cycle(uint32_t sample_cycle) { - SYSCON.saradc_fsm.sample_cycle = sample_cycle; + HAL_FORCE_MODIFY_U32_REG_FIELD(SYSCON.saradc_fsm, sample_cycle, sample_cycle); } /** @@ -78,7 +82,7 @@ static inline void adc_ll_set_sample_cycle(uint32_t sample_cycle) static inline void adc_ll_digi_set_clk_div(uint32_t div) { /* ADC clock divided from APB clk, e.g. 80 / 2 = 40Mhz, */ - SYSCON.saradc_ctrl.sar_clk_div = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(SYSCON.saradc_ctrl, sar_clk_div, div); } /** @@ -99,7 +103,7 @@ static inline void adc_ll_digi_set_output_format(adc_digi_output_format_t format */ static inline void adc_ll_digi_set_convert_limit_num(uint32_t meas_num) { - SYSCON.saradc_ctrl2.max_meas_num = meas_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(SYSCON.saradc_ctrl2, max_meas_num, meas_num); } /** @@ -320,7 +324,7 @@ static inline void adc_ll_rtc_disable_channel(adc_ll_num_t adc_n) static inline void adc_ll_rtc_start_convert(adc_ll_num_t adc_n, int channel) { if (adc_n == ADC_NUM_1) { - while (SENS.sar_slave_addr1.meas_status != 0); + while (HAL_FORCE_READ_U32_REG_FIELD(SENS.sar_slave_addr1, meas_status) != 0) {} SENS.sar_meas_start1.meas1_start_sar = 0; SENS.sar_meas_start1.meas1_start_sar = 1; } else { // adc_n == ADC_NUM_2 @@ -359,9 +363,9 @@ static inline int adc_ll_rtc_get_convert_value(adc_ll_num_t adc_n) { int ret_val = 0; if (adc_n == ADC_NUM_1) { - ret_val = SENS.sar_meas_start1.meas1_data_sar; + ret_val = HAL_FORCE_READ_U32_REG_FIELD(SENS.sar_meas_start1, meas1_data_sar); } else { // adc_n == ADC_NUM_2 - ret_val = SENS.sar_meas_start2.meas2_data_sar; + ret_val = HAL_FORCE_READ_U32_REG_FIELD(SENS.sar_meas_start2, meas2_data_sar); } return ret_val; } @@ -444,9 +448,9 @@ static inline adc_ll_power_t adc_ll_get_power_manage(void) static inline void adc_ll_set_sar_clk_div(adc_ll_num_t adc_n, uint32_t div) { if (adc_n == ADC_NUM_1) { - SENS.sar_read_ctrl.sar1_clk_div = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_read_ctrl, sar1_clk_div, div); } else { // adc_n == ADC_NUM_2 - SENS.sar_read_ctrl2.sar2_clk_div = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_read_ctrl2, sar2_clk_div, div); } } @@ -563,9 +567,9 @@ static inline void adc_ll_amp_disable(void) SENS.sar_meas_ctrl.amp_rst_fb_fsm = 0; SENS.sar_meas_ctrl.amp_short_ref_fsm = 0; SENS.sar_meas_ctrl.amp_short_ref_gnd_fsm = 0; - SENS.sar_meas_wait1.sar_amp_wait1 = 1; - SENS.sar_meas_wait1.sar_amp_wait2 = 1; - SENS.sar_meas_wait2.sar_amp_wait3 = 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_meas_wait1, sar_amp_wait1, 1); + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_meas_wait1, sar_amp_wait2, 1); + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_meas_wait2, sar_amp_wait3, 1); } /*--------------------------------------------------------------- diff --git a/components/hal/esp32/include/hal/aes_ll.h b/components/hal/esp32/include/hal/aes_ll.h index 8283397dde..b0142cbe68 100644 --- a/components/hal/esp32/include/hal/aes_ll.h +++ b/components/hal/esp32/include/hal/aes_ll.h @@ -1,4 +1,4 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// Copyright 2020-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. @@ -17,6 +17,7 @@ #include "soc/hwcrypto_reg.h" #include "soc/dport_access.h" #include "hal/aes_types.h" +#include #ifdef __cplusplus extern "C" { @@ -46,10 +47,13 @@ static inline uint8_t aes_ll_write_key(const uint8_t *key, size_t key_word_len) { /* This variable is used for fault injection checks, so marked volatile to avoid optimisation */ volatile uint8_t key_bytes_in_hardware = 0; - uint32_t *key_words = (uint32_t *)key; + + /* Memcpy to avoid potential unaligned access */ + uint32_t key_word; for (int i = 0; i < key_word_len; i++) { - DPORT_REG_WRITE(AES_KEY_BASE + i * 4, *(key_words + i)); + memcpy(&key_word, key + 4 * i, 4); + DPORT_REG_WRITE(AES_KEY_BASE + i * 4, key_word); key_bytes_in_hardware += 4; } return key_bytes_in_hardware; diff --git a/components/hal/esp32/include/hal/dac_ll.h b/components/hal/esp32/include/hal/dac_ll.h index 5ea4da8978..ec1c20c4fb 100644 --- a/components/hal/esp32/include/hal/dac_ll.h +++ b/components/hal/esp32/include/hal/dac_ll.h @@ -21,7 +21,10 @@ #pragma once #include +#include "hal/misc.h" #include "soc/dac_periph.h" +#include "soc/rtc_io_struct.h" +#include "soc/sens_struct.h" #include "hal/dac_types.h" #ifdef __cplusplus @@ -62,10 +65,10 @@ static inline void dac_ll_update_output_value(dac_channel_t channel, uint8_t val { if (channel == DAC_CHANNEL_1) { SENS.sar_dac_ctrl2.dac_cw_en1 = 0; - RTCIO.pad_dac[channel].dac = value; + HAL_FORCE_MODIFY_U32_REG_FIELD(RTCIO.pad_dac[channel], dac, value); } else if (channel == DAC_CHANNEL_2) { SENS.sar_dac_ctrl2.dac_cw_en2 = 0; - RTCIO.pad_dac[channel].dac = value; + HAL_FORCE_MODIFY_U32_REG_FIELD(RTCIO.pad_dac[channel], dac, value); } } @@ -124,7 +127,7 @@ static inline void dac_ll_cw_set_channel(dac_channel_t channel, bool enable) static inline void dac_ll_cw_set_freq(uint32_t freq) { uint32_t sw_freq = freq * 0xFFFF / RTC_FAST_CLK_FREQ_APPROX; - SENS.sar_dac_ctrl1.sw_fstep = (sw_freq > 0xFFFF) ? 0xFFFF : sw_freq; + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_dac_ctrl1, sw_fstep, (sw_freq > 0xFFFF) ? 0xFFFF : sw_freq); } /** @@ -171,12 +174,12 @@ static inline void dac_ll_cw_set_dc_offset(dac_channel_t channel, int8_t offset) if (SENS.sar_dac_ctrl2.dac_inv1 == DAC_CW_PHASE_180) { offset = 0 - offset; } - SENS.sar_dac_ctrl2.dac_dc1 = offset ? offset : (-128 - offset); + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_dac_ctrl2, dac_dc1, offset ? offset : (-128 - offset)); } else if (channel == DAC_CHANNEL_2) { if (SENS.sar_dac_ctrl2.dac_inv2 == DAC_CW_PHASE_180) { offset = 0 - offset; } - SENS.sar_dac_ctrl2.dac_dc2 = offset ? offset : (-128 - offset); + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_dac_ctrl2, dac_dc2, offset ? offset : (-128 - offset)); } } diff --git a/components/hal/esp32/include/hal/emac_ll.h b/components/hal/esp32/include/hal/emac_ll.h index 36477e36f5..625687b6a0 100644 --- a/components/hal/esp32/include/hal/emac_ll.h +++ b/components/hal/esp32/include/hal/emac_ll.h @@ -23,6 +23,7 @@ #pragma once #include +#include "hal/misc.h" #include "hal/eth_types.h" #include "soc/emac_dma_struct.h" #include "soc/emac_mac_struct.h" @@ -136,7 +137,7 @@ extern "C" { #define EMAC_LL_INTR_OVERFLOW_ENABLE 0x00000010U #define EMAC_LL_INTR_UNDERFLOW_ENABLE 0x00000020U #define EMAC_LL_INTR_RECEIVE_ENABLE 0x00000040U -#define EMAC_LL_INTR_REVEIVE_BUFF_UNAVAILABLE_ENABLE 0x00000080U +#define EMAC_LL_INTR_RECEIVE_BUFF_UNAVAILABLE_ENABLE 0x00000080U #define EMAC_LL_INTR_RECEIVE_STOP_ENABLE 0x00000100U #define EMAC_LL_INTR_RECEIVE_TIMEOUT_ENABLE 0x00000200U #define EMAC_LL_INTR_TRANSMIT_FIRST_BYTE_ENABLE 0x00000400U @@ -310,7 +311,7 @@ static inline void emac_ll_promiscuous_mode_enable(emac_mac_dev_t *mac_regs, boo /* gmacfc */ static inline void emac_ll_set_pause_time(emac_mac_dev_t *mac_regs, uint32_t time) { - mac_regs->gmacfc.pause_time = time; + HAL_FORCE_MODIFY_U32_REG_FIELD(mac_regs->gmacfc, pause_time, time); } static inline void emac_ll_zero_quanta_pause_enable(emac_mac_dev_t *mac_regs, bool enable) @@ -346,18 +347,18 @@ static inline void emac_ll_clear(emac_mac_dev_t *mac_regs) /* emacmiidata */ static inline void emac_ll_set_phy_data(emac_mac_dev_t *mac_regs, uint32_t data) { - mac_regs->emacmiidata.mii_data = data; + HAL_FORCE_MODIFY_U32_REG_FIELD(mac_regs->emacmiidata, mii_data, data); } static inline uint32_t emac_ll_get_phy_data(emac_mac_dev_t *mac_regs) { - return mac_regs->emacmiidata.mii_data; + return HAL_FORCE_READ_U32_REG_FIELD(mac_regs->emacmiidata, mii_data); } /* emacaddr0 */ static inline void emac_ll_set_addr(emac_mac_dev_t *mac_regs, const uint8_t *addr) { - mac_regs->emacaddr0high.address0_hi = (addr[5] << 8) | addr[4]; + HAL_FORCE_MODIFY_U32_REG_FIELD(mac_regs->emacaddr0high, address0_hi, (addr[5] << 8) | addr[4]); mac_regs->emacaddr0low = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | (addr[0]); } /*************** End of mac regs operation *********************/ @@ -405,7 +406,7 @@ static inline void emac_ll_flush_recv_frame_enable(emac_dma_dev_t *dma_regs, boo static inline void emac_ll_trans_store_forward_enable(emac_dma_dev_t *dma_regs, bool enable) { - dma_regs->dmaoperation_mode.tx_str_fwd = !enable; + dma_regs->dmaoperation_mode.tx_str_fwd = enable; } static inline void emac_ll_flush_trans_fifo_enable(emac_dma_dev_t *dma_regs, bool enable) diff --git a/components/hal/esp32/include/hal/gpio_ll.h b/components/hal/esp32/include/hal/gpio_ll.h index 8c1acb3a1c..f5ac5909d5 100644 --- a/components/hal/esp32/include/hal/gpio_ll.h +++ b/components/hal/esp32/include/hal/gpio_ll.h @@ -25,9 +25,11 @@ #include #include "soc/soc.h" #include "soc/gpio_periph.h" +#include "soc/gpio_struct.h" #include "soc/rtc_cntl_reg.h" #include "soc/rtc_io_reg.h" #include "hal/gpio_types.h" +#include "hal/misc.h" #ifdef __cplusplus extern "C" { @@ -245,7 +247,7 @@ static inline void gpio_ll_get_intr_status(gpio_dev_t *hw, uint32_t core_id, uin */ static inline void gpio_ll_get_intr_status_high(gpio_dev_t *hw, uint32_t core_id, uint32_t *status) { - *status = (core_id == 0) ? hw->pcpu_int1.intr : hw->acpu_int1.intr; + *status = (core_id == 0) ? HAL_FORCE_READ_U32_REG_FIELD(hw->pcpu_int1, intr) : HAL_FORCE_READ_U32_REG_FIELD(hw->pcpu_int1, intr); } /** @@ -267,7 +269,7 @@ static inline void gpio_ll_clear_intr_status(gpio_dev_t *hw, uint32_t mask) */ static inline void gpio_ll_clear_intr_status_high(gpio_dev_t *hw, uint32_t mask) { - hw->status1_w1tc.intr_st = mask; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->status1_w1tc, intr_st, mask); } /** @@ -330,7 +332,7 @@ static inline void gpio_ll_output_disable(gpio_dev_t *hw, gpio_num_t gpio_num) if (gpio_num < 32) { hw->enable_w1tc = (0x1 << gpio_num); } else { - hw->enable1_w1tc.data = (0x1 << (gpio_num - 32)); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->enable1_w1tc, data, (0x1 << (gpio_num - 32))); } // Ensure no other output signal is routed via GPIO matrix to this pin @@ -349,7 +351,7 @@ static inline void gpio_ll_output_enable(gpio_dev_t *hw, gpio_num_t gpio_num) if (gpio_num < 32) { hw->enable_w1ts = (0x1 << gpio_num); } else { - hw->enable1_w1ts.data = (0x1 << (gpio_num - 32)); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->enable1_w1ts, data, (0x1 << (gpio_num - 32))); } } @@ -432,13 +434,13 @@ static inline void gpio_ll_set_level(gpio_dev_t *hw, gpio_num_t gpio_num, uint32 if (gpio_num < 32) { hw->out_w1ts = (1 << gpio_num); } else { - hw->out1_w1ts.data = (1 << (gpio_num - 32)); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->out1_w1ts, data, (1 << (gpio_num - 32))); } } else { if (gpio_num < 32) { hw->out_w1tc = (1 << gpio_num); } else { - hw->out1_w1tc.data = (1 << (gpio_num - 32)); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->out1_w1tc, data, (1 << (gpio_num - 32))); } } } @@ -460,7 +462,7 @@ static inline int gpio_ll_get_level(gpio_dev_t *hw, gpio_num_t gpio_num) if (gpio_num < 32) { return (hw->in >> gpio_num) & 0x1; } else { - return (hw->in1.data >> (gpio_num - 32)) & 0x1; + return (HAL_FORCE_READ_U32_REG_FIELD(hw->in1, data) >> (gpio_num - 32)) & 0x1; } } diff --git a/components/hal/esp32/include/hal/i2c_ll.h b/components/hal/esp32/include/hal/i2c_ll.h index 550c1b76d2..650dbbaa04 100644 --- a/components/hal/esp32/include/hal/i2c_ll.h +++ b/components/hal/esp32/include/hal/i2c_ll.h @@ -15,7 +15,10 @@ // The LL layer for I2C register operations #pragma once + +#include "hal/misc.h" #include "soc/i2c_periph.h" +#include "soc/i2c_struct.h" #include "hal/i2c_types.h" #ifdef __cplusplus @@ -558,7 +561,7 @@ static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len) static inline void i2c_ll_read_rxfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len) { for(int i = 0; i < len; i++) { - ptr[i] = hw->fifo_data.data; + ptr[i] = HAL_FORCE_READ_U32_REG_FIELD(hw->fifo_data, data); } } diff --git a/components/hal/esp32/include/hal/i2s_ll.h b/components/hal/esp32/include/hal/i2s_ll.h index 96d4a3f8ec..fd20c406cb 100644 --- a/components/hal/esp32/include/hal/i2s_ll.h +++ b/components/hal/esp32/include/hal/i2s_ll.h @@ -1,4 +1,4 @@ -// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// 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. @@ -23,10 +23,9 @@ #pragma once #include -#include "soc/rtc_periph.h" -#include "soc/rtc.h" -#include "soc/efuse_periph.h" +#include "hal/misc.h" #include "soc/i2s_periph.h" +#include "soc/i2s_struct.h" #include "hal/i2s_types.h" #ifdef __cplusplus @@ -36,87 +35,378 @@ extern "C" { // Get I2S hardware instance with giving i2s num #define I2S_LL_GET_HW(num) (((num) == 0) ? (&I2S0) : (((num) == 1) ? (&I2S1) : NULL)) -#define I2S_INTR_IN_SUC_EOF BIT(9) -#define I2S_INTR_OUT_EOF BIT(12) -#define I2S_INTR_IN_DSCR_ERR BIT(13) -#define I2S_INTR_OUT_DSCR_ERR BIT(14) -#define I2S_INTR_MAX (0xFFFFFFFF) +#define I2S_LL_AD_BCK_FACTOR (2) +#define I2S_LL_PDM_BCK_FACTOR (64) +#define I2S_LL_BASE_CLK (2 * APB_CLK_FREQ) + +#define I2S_LL_MCLK_DIVIDER_BIT_WIDTH (6) +#define I2S_LL_MCLK_DIVIDER_MAX ((1 << I2S_LL_MCLK_DIVIDER_BIT_WIDTH) - 1) + +#define I2S_LL_EVENT_TX_EOF (1 << 12) +#define I2S_LL_BCK_MAX_PRESCALE (64) + +/* I2S clock configuration structure */ +typedef struct { + uint16_t mclk_div; // I2S module clock devider, Fmclk = Fsclk /(mclk_div+b/a) + uint16_t a; + uint16_t b; // The decimal part of module clock devider, the decimal is: b/a +} i2s_ll_mclk_div_t; /** - * @brief Reset rx fifo + * @brief Enable DMA descriptor owner check * * @param hw Peripheral I2S hardware instance address. + * @param en whether to enable owner check */ -static inline void i2s_ll_reset_rx_fifo(i2s_dev_t *hw) +static inline void i2s_ll_dma_enable_owner_check(i2s_dev_t *hw, bool en) { - hw->conf.rx_fifo_reset = 1; - hw->conf.rx_fifo_reset = 0; + hw->lc_conf.check_owner = en; } /** - * @brief Reset tx fifo + * @brief Enable DMA descriptor write back + * + * @param hw Peripheral I2S hardware instance address. + * @param en whether to enable write back + */ +static inline void i2s_ll_dma_enable_auto_write_back(i2s_dev_t *hw, bool en) +{ + hw->lc_conf.out_auto_wrback = en; +} + +/** + * @brief I2S DMA generate EOF event on data in FIFO poped out + * + * @param hw Peripheral I2S hardware instance address. + * @param en True to enable, False to disable + */ +static inline void i2s_ll_dma_enable_eof_on_fifo_empty(i2s_dev_t *hw, bool en) +{ + hw->lc_conf.out_eof_mode = en; +} + +/** + * @brief I2S module general init, enable I2S clock. * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_tx_fifo(i2s_dev_t *hw) +static inline void i2s_ll_enable_clock(i2s_dev_t *hw) +{ + if (hw->clkm_conf.clk_en == 0) { + hw->clkm_conf.clk_en = 1; + hw->conf2.val = 0; + } +} + +/** + * @brief I2S module disable clock. + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_disable_clock(i2s_dev_t *hw) +{ + if (hw->clkm_conf.clk_en == 1) { + hw->clkm_conf.clk_en = 0; + } +} + +/** + * @brief I2S tx msb right enable + * + * @param hw Peripheral I2S hardware instance address. + * @param enable Set true to enable tx msb right + */ +static inline void i2s_ll_tx_enable_msb_right(i2s_dev_t *hw, bool enable) +{ + hw->conf.tx_msb_right = enable; +} + +/** + * @brief I2S rx msb right enable + * + * @param hw Peripheral I2S hardware instance address. + * @param enable Set true to enable rx msb right + */ +static inline void i2s_ll_rx_enable_msb_right(i2s_dev_t *hw, bool enable) +{ + hw->conf.rx_msb_right = enable; +} + +/** + * @brief I2S tx right channel first + * + * @param hw Peripheral I2S hardware instance address. + * @param enable Set true to enable send right channel first + */ +static inline void i2s_ll_tx_enable_right_first(i2s_dev_t *hw, bool enable) +{ + hw->conf.tx_right_first = enable; +} + +/** + * @brief I2S rx right channel first + * + * @param hw Peripheral I2S hardware instance address. + * @param enable Set true to enable receive right channel first + */ +static inline void i2s_ll_rx_enable_right_first(i2s_dev_t *hw, bool enable) +{ + hw->conf.rx_right_first = enable; +} + +/** + * @brief I2S tx fifo module force enable + * + * @param hw Peripheral I2S hardware instance address. + * @param enable Set true to enable tx fifo module + */ +static inline void i2s_ll_tx_force_enable_fifo_mod(i2s_dev_t *hw, bool enable) +{ + hw->fifo_conf.tx_fifo_mod_force_en = enable; +} + +/** + * @brief I2S rx fifo module force enable + * + * @param hw Peripheral I2S hardware instance address. + * @param enable Set true to enable rx fifo module + */ +static inline void i2s_ll_rx_force_enable_fifo_mod(i2s_dev_t *hw, bool enable) +{ + hw->fifo_conf.rx_fifo_mod_force_en = enable; +} +/** + * @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->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->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->conf.tx_reset = 1; + hw->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->conf.rx_reset = 1; + hw->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->conf.tx_fifo_reset = 1; hw->conf.tx_fifo_reset = 0; } /** - * @brief Enable rx interrupt + * @brief Reset I2S RX FIFO * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_enable_rx_intr(i2s_dev_t *hw) +static inline void i2s_ll_rx_reset_fifo(i2s_dev_t *hw) { - hw->int_ena.in_suc_eof = 1; - hw->int_ena.in_dscr_err = 1; + hw->conf.rx_fifo_reset = 1; + hw->conf.rx_fifo_reset = 0; } /** - * @brief Disable rx interrupt + * @brief Set TX source clock * * @param hw Peripheral I2S hardware instance address. + * @param src I2S source clock */ -static inline void i2s_ll_disable_rx_intr(i2s_dev_t *hw) +static inline void i2s_ll_tx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) { - hw->int_ena.in_suc_eof = 0; - hw->int_ena.in_dscr_err = 0; + //0: disable APLL clock, I2S module will using PLL_D2_CLK(160M) as source clock + //1: Enable APLL clock, I2S module will using APLL as source clock + hw->clkm_conf.clka_en = (src == I2S_CLK_APLL) ? 1 : 0; } /** - * @brief Disable tx interrupt + * @brief Set RX source clock * * @param hw Peripheral I2S hardware instance address. + * @param src I2S source clock */ -static inline void i2s_ll_disable_tx_intr(i2s_dev_t *hw) +static inline void i2s_ll_rx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) { - hw->int_ena.out_eof = 0; - hw->int_ena.out_dscr_err = 0; + //0: disable APLL clock, I2S module will using PLL_D2_CLK(160M) as source clock + //1: Enable APLL clock, I2S module will using APLL as source clock + hw->clkm_conf.clka_en = (src == I2S_CLK_APLL) ? 1 : 0; } /** - * @brief Enable tx interrupt + * @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->sample_rate_conf.tx_bck_div_num = val; +} + +/** + * @brief Configure I2S TX clock devider + * + * @param hw Peripheral I2S hardware instance address. + * @param set Pointer to I2S clock devider configuration paramater + */ +static inline void i2s_ll_tx_set_clk(i2s_dev_t *hw, i2s_ll_mclk_div_t *set) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clkm_conf, clkm_div_num, set->mclk_div); + hw->clkm_conf.clkm_div_b = set->b; + hw->clkm_conf.clkm_div_a = set->a; +} + +/** + * @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->sample_rate_conf.rx_bck_div_num = val; +} + +/** + * @brief Configure I2S RX clock devider + * + * @param hw Peripheral I2S hardware instance address. + * @param set Pointer to I2S clock devider configuration paramater + */ +static inline void i2s_ll_rx_set_clk(i2s_dev_t *hw, i2s_ll_mclk_div_t *set) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clkm_conf, clkm_div_num, set->mclk_div); + hw->clkm_conf.clkm_div_b = set->b; + hw->clkm_conf.clkm_div_a = set->a; +} + +/** + * @brief Enable interrupt by mask + * + * @param hw Peripheral I2S hardware instance address. + * @param mask Interrupt event mask + * @param en true to enable, false to disable + */ +static inline void i2s_ll_enable_intr(i2s_dev_t *hw, uint32_t mask, bool en) +{ + if (en) { + hw->int_ena.val |= mask; + } else { + hw->int_ena.val &= ~mask; + } +} + +/** + * @brief Enable TX interrupt * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_enable_tx_intr(i2s_dev_t *hw) +static inline void i2s_ll_tx_enable_intr(i2s_dev_t *hw) { hw->int_ena.out_eof = 1; hw->int_ena.out_dscr_err = 1; } /** - * @brief Reset dma in + * @brief Disable TX interrupt * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_dma_in(i2s_dev_t *hw) +static inline void i2s_ll_tx_disable_intr(i2s_dev_t *hw) { - hw->lc_conf.in_rst = 1; - hw->lc_conf.in_rst = 0; + hw->int_ena.out_eof = 0; + hw->int_ena.out_dscr_err = 0; +} + +/** + * @brief Enable RX interrupt + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_rx_enable_intr(i2s_dev_t *hw) +{ + hw->int_ena.in_suc_eof = 1; + hw->int_ena.in_dscr_err = 1; +} + +/** + * @brief Disable RX interrupt + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_rx_disable_intr(i2s_dev_t *hw) +{ + hw->int_ena.in_suc_eof = 0; + hw->int_ena.in_dscr_err = 0; +} + +/** + * @brief Get interrupt status register address + * + * @param hw Peripheral I2S hardware instance address. + * @return interrupt status register address + */ +static inline volatile void *i2s_ll_get_intr_status_reg(i2s_dev_t *hw) +{ + return &hw->int_st; +} + +/** + * @brief Get I2S interrupt status + * + * @param hw Peripheral I2S hardware instance address. + * @return + * - module interrupt status + */ +static inline uint32_t i2s_ll_get_intr_status(i2s_dev_t *hw) +{ + return hw->int_st.val; +} + +/** + * @brief Clear I2S interrupt status + * + * @param hw Peripheral I2S hardware instance address. + * @param clr_mask Interrupt mask to clear interrupt status + */ +static inline void i2s_ll_clear_intr_status(i2s_dev_t *hw, uint32_t clr_mask) +{ + hw->int_clr.val = clr_mask; } /** @@ -124,32 +414,21 @@ static inline void i2s_ll_reset_dma_in(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_dma_out(i2s_dev_t *hw) +static inline void i2s_ll_tx_reset_dma(i2s_dev_t *hw) { hw->lc_conf.out_rst = 1; hw->lc_conf.out_rst = 0; } /** - * @brief Reset tx + * @brief Reset dma in * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_tx(i2s_dev_t *hw) +static inline void i2s_ll_rx_reset_dma(i2s_dev_t *hw) { - hw->conf.tx_reset = 1; - hw->conf.tx_reset = 0; -} - -/** - * @brief Reset rx - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_reset_rx(i2s_dev_t *hw) -{ - hw->conf.rx_reset = 1; - hw->conf.rx_reset = 0; + hw->lc_conf.in_rst = 1; + hw->lc_conf.in_rst = 0; } /** @@ -162,200 +441,6 @@ static inline void i2s_ll_start_out_link(i2s_dev_t *hw) hw->out_link.start = 1; } -/** - * @brief Start tx - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_start_tx(i2s_dev_t *hw) -{ - hw->conf.tx_start = 1; -} - -/** - * @brief Start in link - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_start_in_link(i2s_dev_t *hw) -{ - hw->in_link.start = 1; -} - -/** - * @brief Start rx - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_start_rx(i2s_dev_t *hw) -{ - hw->conf.rx_start = 1; -} - -/** - * @brief Stop out link - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_stop_out_link(i2s_dev_t *hw) -{ - hw->out_link.stop = 1; -} - -/** - * @brief Stop tx - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_stop_tx(i2s_dev_t *hw) -{ - hw->conf.tx_start = 0; -} - -/** - * @brief Stop in link - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_stop_in_link(i2s_dev_t *hw) -{ - hw->in_link.stop = 1; -} - -/** - * @brief Stop rx - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_stop_rx(i2s_dev_t *hw) -{ - hw->conf.rx_start = 0; -} - -/** - * @brief Enable dma - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_enable_dma(i2s_dev_t *hw) -{ - //Enable and configure DMA - typeof(hw->lc_conf) lc_conf; - lc_conf.val = 0; - lc_conf.out_eof_mode = 1; - hw->lc_conf.val = lc_conf.val; -} - -/** - * @brief Get I2S interrupt status - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get interrupt status - */ -static inline void i2s_ll_get_intr_status(i2s_dev_t *hw, uint32_t *val) -{ - *val = hw->int_st.val; -} - -/** - * @brief Clear I2S interrupt status - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to clear interrupt status - */ -static inline void i2s_ll_clear_intr_status(i2s_dev_t *hw, uint32_t val) -{ - hw->int_clr.val = val; -} - -/** - * @brief Get I2S out eof des address - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get out eof des address - */ -static inline void i2s_ll_get_out_eof_des_addr(i2s_dev_t *hw, uint32_t *val) -{ - *val = hw->out_eof_des_addr; -} - -/** - * @brief Get I2S in eof des address - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get in eof des address - */ -static inline void i2s_ll_get_in_eof_des_addr(i2s_dev_t *hw, uint32_t *val) -{ - *val = hw->in_eof_des_addr; -} - -/** - * @brief Get I2S tx fifo mode - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get tx fifo mode - */ -static inline void i2s_ll_get_tx_fifo_mod(i2s_dev_t *hw, uint32_t *val) -{ - *val = hw->fifo_conf.tx_fifo_mod; -} - -/** - * @brief Set I2S tx fifo mode - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx fifo mode - */ -static inline void i2s_ll_set_tx_fifo_mod(i2s_dev_t *hw, uint32_t val) -{ - hw->fifo_conf.tx_fifo_mod = val; -} - -/** - * @brief Get I2S rx fifo mode - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get rx fifo mode - */ -static inline void i2s_ll_get_rx_fifo_mod(i2s_dev_t *hw, uint32_t *val) -{ - *val = hw->fifo_conf.rx_fifo_mod; -} - -/** - * @brief Set I2S rx fifo mode - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx fifo mode - */ -static inline void i2s_ll_set_rx_fifo_mod(i2s_dev_t *hw, uint32_t val) -{ - hw->fifo_conf.rx_fifo_mod = val; -} - -/** - * @brief Set I2S tx chan mode - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx chan mode - */ -static inline void i2s_ll_set_tx_chan_mod(i2s_dev_t *hw, uint32_t val) -{ - hw->conf_chan.tx_chan_mod = val; -} - -/** - * @brief Set I2S rx chan mode - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx chan mode - */ -static inline void i2s_ll_set_rx_chan_mod(i2s_dev_t *hw, uint32_t val) -{ - hw->conf_chan.rx_chan_mod = val; -} - /** * @brief Set I2S out link address * @@ -368,92 +453,121 @@ static inline void i2s_ll_set_out_link_addr(i2s_dev_t *hw, uint32_t val) } /** - * @brief Set I2S in link address + * @brief Start TX module * * @param hw Peripheral I2S hardware instance address. - * @param val value to set in link address */ -static inline void i2s_ll_set_in_link_addr(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_tx_start(i2s_dev_t *hw) { - hw->in_link.addr = val; + hw->conf.tx_start = 1; } /** - * @brief Set I2S rx eof num + * @brief Start RX module * * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx eof num */ -static inline void i2s_ll_set_rx_eof_num(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_rx_start(i2s_dev_t *hw) +{ + hw->conf.rx_start = 1; +} + +/** + * @brief Configure TX DMA descriptor address and start TX DMA + * + * @param hw Peripheral I2S hardware instance address. + * @param link_addr DMA descriptor link address. + */ +static inline void i2s_ll_tx_start_link(i2s_dev_t *hw, uint32_t link_addr) +{ + i2s_ll_set_out_link_addr(hw, link_addr); + i2s_ll_start_out_link(hw); +} + +/** + * @brief Configure RX DMA descriptor address and start RX DMA + * + * @param hw Peripheral I2S hardware instance address. + * @param link_addr DMA descriptor link address. + */ +static inline void i2s_ll_rx_start_link(i2s_dev_t *hw, uint32_t link_addr) +{ + hw->in_link.addr = link_addr; + hw->in_link.start = 1; +} + +/** + * @brief Stop TX module + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_tx_stop(i2s_dev_t *hw) +{ + hw->conf.tx_start = 0; +} + +/** + * @brief Stop RX module + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_rx_stop(i2s_dev_t *hw) +{ + hw->conf.rx_start = 0; +} + +/** + * @brief Stop out link + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_tx_stop_link(i2s_dev_t *hw) +{ + hw->out_link.stop = 1; +} + +/** + * @brief Stop in link + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_rx_stop_link(i2s_dev_t *hw) +{ + hw->in_link.stop = 1; +} + +/** + * @brief Get I2S out eof descriptor address + * + * @param hw Peripheral I2S hardware instance address. + * @param eof_addr Pointer to accept out eof des address + */ +static inline void i2s_ll_tx_get_eof_des_addr(i2s_dev_t *hw, uint32_t *eof_addr) +{ + *eof_addr = hw->out_eof_des_addr; +} + +/** + * @brief Get I2S in eof descriptor address + * + * @param hw Peripheral I2S hardware instance address. + * @param eof_addr Pointer to accept in eof des address + */ +static inline void i2s_ll_rx_get_eof_des_addr(i2s_dev_t *hw, uint32_t *eof_addr) +{ + *eof_addr = hw->in_eof_des_addr; +} + +/** + * @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) { // On ESP32, the eof_num count in words. - hw->rx_eof_num = val / 4; -} - -/** - * @brief Set I2S clkm div num - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set clkm div num - */ -static inline void i2s_ll_set_clkm_div_num(i2s_dev_t *hw, uint32_t val) -{ - hw->clkm_conf.clkm_div_num = val; -} - -/** - * @brief Set I2S clkm div b - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set clkm div b - */ -static inline void i2s_ll_set_clkm_div_b(i2s_dev_t *hw, uint32_t val) -{ - hw->clkm_conf.clkm_div_b = val; -} - -/** - * @brief Set I2S clkm div a - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set clkm div a - */ -static inline void i2s_ll_set_clkm_div_a(i2s_dev_t *hw, uint32_t val) -{ - hw->clkm_conf.clkm_div_a = val; -} - -/** - * @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_set_tx_bck_div_num(i2s_dev_t *hw, uint32_t val) -{ - hw->sample_rate_conf.tx_bck_div_num = val; -} - -/** - * @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_set_rx_bck_div_num(i2s_dev_t *hw, uint32_t val) -{ - hw->sample_rate_conf.rx_bck_div_num = val; -} - -/** - * @brief Set I2S clk sel - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set clk sel - */ -static inline void i2s_ll_set_clk_sel(i2s_dev_t *hw, uint32_t val) -{ - hw->clkm_conf.clka_en = (val == 1) ? 1 : 0; + hw->rx_eof_num = eof_num / 4; } /** @@ -462,389 +576,365 @@ static inline void i2s_ll_set_clk_sel(i2s_dev_t *hw, uint32_t val) * @param hw Peripheral I2S hardware instance address. * @param val value to set tx bits mod */ -static inline void i2s_ll_set_tx_bits_mod(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_tx_set_bits_mod(i2s_dev_t *hw, uint32_t val) { hw->sample_rate_conf.tx_bits_mod = val; } /** - * @brief Set I2S rx bits mod + * @brief Congfigure TX chan bit and audio data bit, on ESP32, sample_bit should equals to data_bit * * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx bits mod + * @param chan_bit The chan bit width + * @param data_bit The audio data bit width */ -static inline void i2s_ll_set_rx_bits_mod(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_tx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_bit, int data_bit) { - hw->sample_rate_conf.rx_bits_mod = val; + hw->fifo_conf.tx_fifo_mod = (chan_bit <= I2S_BITS_PER_SAMPLE_16BIT ? 0 : 2); + hw->sample_rate_conf.tx_bits_mod = data_bit; } /** - * @brief Set I2S dscr en + * @brief Congfigure RX chan bit and audio data bit, on ESP32, sample_bit should equals to data_bit * * @param hw Peripheral I2S hardware instance address. - * @param val value to set dscr en + * @param chan_bit The chan bit width + * @param data_bit The audio data bit width */ -static inline void i2s_ll_set_dscr_en(i2s_dev_t *hw, bool val) +static inline void i2s_ll_rx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_bit, int data_bit) { - hw->fifo_conf.dscr_en = val; + hw->fifo_conf.rx_fifo_mod = (chan_bit <= I2S_BITS_PER_SAMPLE_16BIT ? 0 : 2); + hw->sample_rate_conf.rx_bits_mod = data_bit; } /** - * @brief Set I2S lcd en + * @brief Set whether to continue I2S signal on bus when TX FIFO is empty * * @param hw Peripheral I2S hardware instance address. - * @param val value to set lcd en + * @param en whether to stop when tx fifo is empty */ -static inline void i2s_ll_set_lcd_en(i2s_dev_t *hw, bool val) +static inline void i2s_ll_tx_stop_on_fifo_empty(i2s_dev_t *hw, bool en) { - hw->conf2.lcd_en = val; + hw->conf1.tx_stop_en = en; } /** - * @brief Set I2S camera en + * @brief Set whether to bypass the internal PCM module * * @param hw Peripheral I2S hardware instance address. - * @param val value to set camera en + * @param bypass whether to bypass the PCM module */ -static inline void i2s_ll_set_camera_en(i2s_dev_t *hw, bool val) +static inline void i2s_ll_tx_bypass_pcm(i2s_dev_t *hw, bool bypass) { - hw->conf2.camera_en = val; + hw->conf1.tx_pcm_bypass = bypass; } /** - * @brief Set I2S tx fifo mod force en + * @brief Enable I2S DMA * * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx fifo mod force en + * @param ena Set true to enable DMA */ -static inline void i2s_ll_set_tx_fifo_mod_force_en(i2s_dev_t *hw, bool val) +static inline void i2s_ll_enable_dma(i2s_dev_t *hw, bool ena) { - hw->fifo_conf.tx_fifo_mod_force_en = val; + hw->fifo_conf.dscr_en = ena; } /** - * @brief Set I2S rx fifo mod force en + * @brief Configure TX WS signal width * * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx fifo mod force en + * @param width WS width in BCK cycle */ -static inline void i2s_ll_set_rx_fifo_mod_force_en(i2s_dev_t *hw, bool val) +static inline void i2s_ll_tx_set_ws_width(i2s_dev_t *hw, int width) { - hw->fifo_conf.rx_fifo_mod_force_en = val; + hw->conf.tx_short_sync = width == 1 ? 1 : 0; } /** - * @brief Set I2S tx right first + * @brief Configure RX WS signal width * * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx right first + * @param width WS width in BCK cycle */ -static inline void i2s_ll_set_tx_right_first(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_rx_set_ws_width(i2s_dev_t *hw, int width) { - hw->conf.tx_right_first = val; + hw->conf.rx_short_sync = width == 1 ? 1 : 0; } /** - * @brief Set I2S rx right first + * @brief Enable TX MSB shift, the data will be launch at the first BCK clock * * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx right first + * @param msb_shift_enable Set true to enable MSB shift */ -static inline void i2s_ll_set_rx_right_first(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_tx_enable_msb_shift(i2s_dev_t *hw, bool msb_shift_enable) { - hw->conf.rx_right_first = val; + hw->conf.tx_msb_shift = msb_shift_enable; } /** - * @brief Set I2S tx slave mod + * @brief Enable RX MSB shift, the data will be launch at the first BCK clock * * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx slave mod + * @param msb_shift_enable Set true to enable MSB shift */ -static inline void i2s_ll_set_tx_slave_mod(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_rx_enable_msb_shift(i2s_dev_t *hw, bool msb_shift_enable) { - hw->conf.tx_slave_mod = val; + hw->conf.rx_msb_shift = msb_shift_enable; } /** - * @brief Set I2S rx slave mod + * @brief Set I2S tx chan mode * * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx slave mod + * @param val value to set tx chan mode */ -static inline void i2s_ll_set_rx_slave_mod(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_tx_set_chan_mod(i2s_dev_t *hw, uint32_t val) { - hw->conf.rx_slave_mod = val; + hw->conf_chan.tx_chan_mod = val; } /** - * @brief Get I2S tx msb right + * @brief Enable TX mono mode * * @param hw Peripheral I2S hardware instance address. - * @param val value to get tx msb right + * @param mono_ena Set true to enable mono mde. */ -static inline void i2s_ll_get_tx_msb_right(i2s_dev_t *hw, uint32_t *val) +static inline void i2s_ll_tx_enable_mono_mode(i2s_dev_t *hw, bool mono_ena) { - *val = hw->conf.tx_msb_right; + int data_bit = hw->sample_rate_conf.tx_bits_mod; + hw->fifo_conf.tx_fifo_mod = data_bit <= I2S_BITS_PER_SAMPLE_16BIT ? mono_ena : 2 + mono_ena; + hw->conf_chan.tx_chan_mod = mono_ena; } /** - * @brief Get I2S rx msb right + * @brief Enable RX mono mode * * @param hw Peripheral I2S hardware instance address. - * @param val value to get rx msb right + * @param mono_ena Set true to enable mono mde. */ -static inline void i2s_ll_get_rx_msb_right(i2s_dev_t *hw, uint32_t *val) +static inline void i2s_ll_rx_enable_mono_mode(i2s_dev_t *hw, bool mono_ena) { - *val = hw->conf.rx_msb_right; + int data_bit = hw->sample_rate_conf.rx_bits_mod; + hw->fifo_conf.rx_fifo_mod = data_bit <= I2S_BITS_PER_SAMPLE_16BIT ? mono_ena : 2 + mono_ena; + hw->conf_chan.rx_chan_mod = mono_ena; } /** - * @brief Set I2S tx msb right + * @brief Enable I2S loopback mode * * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx msb right + * @param loopback_en Set true to share BCK and WS signal for tx module and rx module. */ -static inline void i2s_ll_set_tx_msb_right(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_share_bck_ws(i2s_dev_t *hw, bool loopback_en) { - hw->conf.tx_msb_right = val; + hw->conf.sig_loopback = loopback_en; +} + + + +/******************************I2S PDM Configurations*************************************/ +/** + * @brief Configure RX PDM downsample + * + * @param hw Peripheral I2S hardware instance address. + * @param dsr PDM downsample configuration paramater + */ +static inline void i2s_ll_rx_set_pdm_dsr(i2s_dev_t *hw, i2s_pdm_dsr_t dsr) +{ + hw->pdm_conf.rx_sinc_dsr_16_en = dsr; } /** - * @brief Set I2S rx msb right + * @brief Get RX PDM downsample configuration * * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx msb right + * @param dsr Pointer to accept PDM downsample configuration */ -static inline void i2s_ll_set_rx_msb_right(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_rx_get_pdm_dsr(i2s_dev_t *hw, i2s_pdm_dsr_t *dsr) { - hw->conf.rx_msb_right = val; + *dsr = hw->pdm_conf.rx_sinc_dsr_16_en; } /** - * @brief Set I2S tx mono + * @brief Enable I2S TX PDM mode * * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx mono + * @param pdm_ena Set true to enable TX PDM mode */ -static inline void i2s_ll_set_tx_mono(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_tx_enable_pdm(i2s_dev_t *hw, bool pdm_ena) { - hw->conf.tx_mono = val; + hw->pdm_conf.tx_pdm_en = pdm_ena; + hw->pdm_conf.pcm2pdm_conv_en = pdm_ena; } /** - * @brief Set I2S rx mono + * @brief Enable I2S RX PDM mode * * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx mono + * @param pdm_ena Set true to enable RX PDM mode */ -static inline void i2s_ll_set_rx_mono(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_rx_enable_pdm(i2s_dev_t *hw, bool pdm_ena) { - hw->conf.rx_mono = val; + hw->pdm_conf.rx_pdm_en = pdm_ena; + hw->pdm_conf.pdm2pcm_conv_en = pdm_ena; } /** - * @brief Set I2S sig loopback + * @brief Set I2S TX PDM prescale * * @param hw Peripheral I2S hardware instance address. - * @param val value to set sig loopback + * @param prescale I2S TX PDM prescale */ -static inline void i2s_ll_set_sig_loopback(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_tx_set_pdm_prescale(i2s_dev_t *hw, bool prescale) { - hw->conf.sig_loopback = val; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->pdm_conf, tx_prescale, prescale); } /** - * @brief Set I2S TX to philip standard + * @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_set_tx_format_philip(i2s_dev_t *hw) +static inline void i2s_ll_tx_set_pdm_hp_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale) { - hw->conf.tx_short_sync = 0; - hw->conf.tx_msb_shift = 1; + hw->pdm_conf.tx_hp_in_shift = sig_scale; } /** - * @brief Set I2S RX to philip standard + * @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_set_rx_format_philip(i2s_dev_t *hw) +static inline void i2s_ll_tx_set_pdm_lp_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale) { - hw->conf.rx_short_sync = 0; - hw->conf.rx_msb_shift = 1; + hw->pdm_conf.tx_lp_in_shift = sig_scale; } /** - * @brief Set I2S TX to MSB Alignment Standard + * @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_set_tx_format_msb_align(i2s_dev_t *hw) +static inline void i2s_ll_tx_set_pdm_sinc_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale) { - hw->conf.tx_short_sync = 0; - hw->conf.tx_msb_shift = 0; + hw->pdm_conf.tx_sinc_in_shift = sig_scale; } /** - * @brief Set I2S RX to MSB Alignment Standard + * @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_set_rx_format_msb_align(i2s_dev_t *hw) +static inline void i2s_ll_tx_set_pdm_sd_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale) { - hw->conf.rx_short_sync = 0; - hw->conf.rx_msb_shift = 0; + hw->pdm_conf.tx_sigmadelta_in_shift = sig_scale; } /** - * @brief Set I2S TX to PCM short standard + * @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_set_tx_pcm_short(i2s_dev_t *hw) +static inline void i2s_ll_tx_set_pdm_fpfs(i2s_dev_t *hw, uint32_t fp, uint32_t fs) { - hw->conf.tx_short_sync = 1; - hw->conf.tx_msb_shift = 0; + hw->pdm_freq_conf.tx_pdm_fp = fp; + hw->pdm_freq_conf.tx_pdm_fs = fs; + hw->pdm_conf.tx_sinc_osr2 = fp / fs; } /** - * @brief Set I2S RX to PCM short standard + * @brief Get I2S TX PDM fp configuration paramater * * @param hw Peripheral I2S hardware instance address. + * @return + * - fp configuration paramater */ -static inline void i2s_ll_set_rx_pcm_short(i2s_dev_t *hw) +static inline uint32_t i2s_ll_tx_get_pdm_fp(i2s_dev_t *hw) { - hw->conf.rx_short_sync = 1; - hw->conf.rx_msb_shift = 0; + return hw->pdm_freq_conf.tx_pdm_fp; } /** - * @brief Set I2S TX to PCM long standard + * @brief Get I2S TX PDM fs configuration paramater * * @param hw Peripheral I2S hardware instance address. + * @return + * - fs configuration paramater */ -static inline void i2s_ll_set_tx_pcm_long(i2s_dev_t *hw) +static inline uint32_t i2s_ll_tx_get_pdm_fs(i2s_dev_t *hw) { - hw->conf.tx_short_sync = 0; - hw->conf.tx_msb_shift = 0; + return hw->pdm_freq_conf.tx_pdm_fs; +} + + + + +/****************************I2S ADC/DAC Configurations***********************************/ +/** + * @brief Enable I2S LCD mode + * @note Have to enable LCD mode to use build in ADC/DAC + * + * @param hw Peripheral I2S hardware instance address. + * @param enable Set true to enable LCD mode. + */ +static inline void i2s_ll_enable_lcd(i2s_dev_t *hw, bool enable) +{ + hw->conf2.lcd_en = enable; } /** - * @brief Set I2S RX to PCM long standard + * @brief Enable I2S camera mode * * @param hw Peripheral I2S hardware instance address. + * @param enable Set true to enable camera mode. */ -static inline void i2s_ll_set_rx_pcm_long(i2s_dev_t *hw) +static inline void i2s_ll_enable_camera(i2s_dev_t *hw, bool enable) { - hw->conf.rx_short_sync = 0; - hw->conf.rx_msb_shift = 0; + hw->conf2.camera_en = enable; } /** * @brief Enable I2S build in ADC mode * * @param hw Peripheral I2S hardware instance address. + * @param enable Set true to enable build in ADC */ -static inline void i2s_ll_build_in_adc_ena(i2s_dev_t *hw) +static inline void i2s_ll_enable_builtin_adc(i2s_dev_t *hw, bool enable) { - hw->conf2.lcd_en = 1; + hw->conf2.lcd_en = enable; hw->conf2.camera_en = 0; + hw->conf.rx_right_first = 0; hw->conf.rx_msb_shift = 0; + hw->conf.rx_mono = 0; hw->conf.rx_short_sync = 0; + hw->fifo_conf.rx_fifo_mod = enable; + hw->conf_chan.rx_chan_mod = enable; } /** * @brief Enable I2S build in DAC mode * * @param hw Peripheral I2S hardware instance address. + * * @param enable Set true to enable build in DAC */ -static inline void i2s_ll_build_in_dac_ena(i2s_dev_t *hw) +static inline void i2s_ll_enable_builtin_dac(i2s_dev_t *hw, bool enable) { - hw->conf2.lcd_en = 1; + hw->conf2.lcd_en = enable; hw->conf2.camera_en = 0; - hw->conf.tx_right_first = 1; + hw->conf.tx_right_first = enable; hw->conf.tx_msb_shift = 0; hw->conf.tx_short_sync = 0; } - -/** - * @brief Enable I2S RX PDM mode - * - * @param hw Peripheral I2S hardware instance address. - * @param pdm_en Set true to enable rx PDM mode - */ -static inline void i2s_ll_set_rx_pdm_en(i2s_dev_t *hw, bool pdm_en) -{ - hw->pdm_conf.rx_pdm_en = pdm_en; -} - -/** - * @brief Enable I2S tx pdm mode - * - * @param hw Peripheral I2S hardware instance address. - * @param pdm_en Set true to enable tx PDM mode - */ -static inline void i2s_ll_set_tx_pdm_en(i2s_dev_t *hw, bool pdm_en) -{ - hw->pdm_conf.tx_pdm_en = pdm_en; -} - -/** - * @brief Configure I2S tx PDM filter module group0 - * - * @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_pdm_cfg(i2s_dev_t *hw, uint32_t fp, uint32_t fs) -{ - hw->pdm_freq_conf.tx_pdm_fp = fp; - hw->pdm_freq_conf.tx_pdm_fs = fs; - hw->pdm_conf.tx_sinc_osr2 = fp/fs; - hw->pdm_conf.pcm2pdm_conv_en = 1; - hw->pdm_conf.tx_pdm_en = 1; -} - -/** - * @brief Configure I2S rx PDM - * - * @param hw Peripheral I2S hardware instance address. - * @param dsr Down-sampling rate value of rx PDM - */ -static inline void i2s_ll_rx_pdm_cfg(i2s_dev_t *hw, uint32_t dsr) -{ - hw->pdm_conf.rx_sinc_dsr_16_en = dsr; - hw->pdm_conf.pdm2pcm_conv_en = 1; - hw->pdm_conf.rx_pdm_en = 1; -} - -/** - * @brief Get I2S tx PDM configuration - * - * @param hw Peripheral I2S hardware instance address. - * @param fp Pointer to store tx PDM fp configuration - * @param fs Pointer to store tx PDM fs configuration - */ -static inline void i2s_ll_get_tx_pdm(i2s_dev_t *hw, uint32_t *fp, uint32_t *fs) -{ - *fp = hw->pdm_freq_conf.tx_pdm_fp; - *fs = hw->pdm_freq_conf.tx_pdm_fs; -} - -/** - * @brief Get I2S rx PDM configuration - * - * @param hw Peripheral I2S hardware instance address. - * @param dsr Pointer to stoe the rx PDM down-sample rate configuration - */ -static inline void i2s_ll_get_rx_pdm(i2s_dev_t *hw, uint32_t *dsr) -{ - *dsr = hw->pdm_conf.rx_sinc_dsr_16_en; -} - #ifdef __cplusplus } #endif diff --git a/components/hal/esp32/include/hal/ledc_ll.h b/components/hal/esp32/include/hal/ledc_ll.h index f7331872b6..1682c7c410 100644 --- a/components/hal/esp32/include/hal/ledc_ll.h +++ b/components/hal/esp32/include/hal/ledc_ll.h @@ -19,6 +19,7 @@ #include "hal/ledc_types.h" #include "soc/ledc_periph.h" +#include "soc/ledc_struct.h" #define LEDC_LL_GET_HW() &LEDC diff --git a/components/hal/esp32/include/hal/mcpwm_ll.h b/components/hal/esp32/include/hal/mcpwm_ll.h index f2e3b34183..3e2b4b762c 100644 --- a/components/hal/esp32/include/hal/mcpwm_ll.h +++ b/components/hal/esp32/include/hal/mcpwm_ll.h @@ -23,6 +23,7 @@ #pragma once #include +#include "hal/misc.h" #include "soc/soc_caps.h" #include "soc/mcpwm_struct.h" #include "hal/mcpwm_types.h" @@ -41,15 +42,15 @@ extern "C" { /********************* Group registers *******************/ -// Set/Get group clock: PWM_clk = CLK_160M / (clk_cfg.prescale + 1) +// Set/Get group clock: PWM_clk = CLK_160M / (prescale + 1) static inline void mcpwm_ll_group_set_clock_prescale(mcpwm_dev_t *mcpwm, int pre_scale) { - mcpwm->clk_cfg.prescale = pre_scale - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->clk_cfg, clk_prescale, pre_scale - 1); } static inline uint32_t mcpwm_ll_group_get_clock_prescale(mcpwm_dev_t *mcpwm) { - return mcpwm->clk_cfg.prescale + 1; + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->clk_cfg, clk_prescale) + 1; } static inline void mcpwm_ll_group_enable_shadow_mode(mcpwm_dev_t *mcpwm) @@ -126,6 +127,7 @@ static inline uint32_t mcpwm_ll_intr_get_trip_ost_status(mcpwm_dev_t *mcpwm) return (mcpwm->int_st.val >> 24) & 0x07; } +__attribute__((always_inline)) static inline uint32_t mcpwm_ll_intr_get_capture_status(mcpwm_dev_t *mcpwm) { return (mcpwm->int_st.val >> 27) & 0x07; @@ -173,6 +175,7 @@ static inline void mcpwm_ll_intr_clear_trip_ost_status(mcpwm_dev_t *mcpwm, uint3 mcpwm->int_clr.val = (ost_mask & 0x07) << 24; } +__attribute__((always_inline)) static inline void mcpwm_ll_intr_clear_capture_status(mcpwm_dev_t *mcpwm, uint32_t capture_mask) { mcpwm->int_clr.val = (capture_mask & 0x07) << 27; @@ -265,20 +268,20 @@ static inline void mcpwm_ll_intr_enable_capture(mcpwm_dev_t *mcpwm, uint32_t cap static inline void mcpwm_ll_timer_set_clock_prescale(mcpwm_dev_t *mcpwm, int timer_id, uint32_t prescale) { - mcpwm->timer[timer_id].period.prescale = prescale - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_prescale, prescale - 1); } static inline uint32_t mcpwm_ll_timer_get_clock_prescale(mcpwm_dev_t *mcpwm, int timer_id) { - return mcpwm->timer[timer_id].period.prescale + 1; + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_prescale) + 1; } static inline void mcpwm_ll_timer_set_peak(mcpwm_dev_t *mcpwm, int timer_id, uint32_t peak, bool symmetric) { if (!symmetric) { // in asymmetric mode, period = [0,peak-1] - mcpwm->timer[timer_id].period.period = peak - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period, peak - 1); } else { // in symmetric mode, period = [0,peak-1] + [peak,1] - mcpwm->timer[timer_id].period.period = peak; + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period, peak); } } @@ -286,32 +289,32 @@ static inline uint32_t mcpwm_ll_timer_get_peak(mcpwm_dev_t *mcpwm, int timer_id, { // asymmetric mode if (!symmetric) { - return mcpwm->timer[timer_id].period.period + 1; + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period) + 1; } // symmetric mode - return mcpwm->timer[timer_id].period.period; + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period); } static inline void mcpwm_ll_timer_update_period_at_once(mcpwm_dev_t *mcpwm, int timer_id) { - mcpwm->timer[timer_id].period.upmethod = 0; + mcpwm->timer[timer_id].timer_cfg0.timer_period_upmethod = 0; } static inline void mcpwm_ll_timer_enable_update_period_on_tez(mcpwm_dev_t *mcpwm, int timer_id, bool enable) { if (enable) { - mcpwm->timer[timer_id].period.upmethod |= 0x01; + mcpwm->timer[timer_id].timer_cfg0.timer_period_upmethod |= 0x01; } else { - mcpwm->timer[timer_id].period.upmethod &= ~0x01; + mcpwm->timer[timer_id].timer_cfg0.timer_period_upmethod &= ~0x01; } } static inline void mcpwm_ll_timer_enable_update_period_on_sync(mcpwm_dev_t *mcpwm, int timer_id, bool enable) { if (enable) { - mcpwm->timer[timer_id].period.upmethod |= 0x02; + mcpwm->timer[timer_id].timer_cfg0.timer_period_upmethod |= 0x02; } else { - mcpwm->timer[timer_id].period.upmethod &= ~0x02; + mcpwm->timer[timer_id].timer_cfg0.timer_period_upmethod &= ~0x02; } } @@ -319,23 +322,23 @@ static inline void mcpwm_ll_timer_set_count_mode(mcpwm_dev_t *mcpwm, int timer_i { switch (mode) { case MCPWM_TIMER_COUNT_MODE_PAUSE: - mcpwm->timer[timer_id].mode.mode = 0; + mcpwm->timer[timer_id].timer_cfg1.timer_mod = 0; break; case MCPWM_TIMER_COUNT_MODE_UP: - mcpwm->timer[timer_id].mode.mode = 1; + mcpwm->timer[timer_id].timer_cfg1.timer_mod = 1; break; case MCPWM_TIMER_COUNT_MODE_DOWN: - mcpwm->timer[timer_id].mode.mode = 2; + mcpwm->timer[timer_id].timer_cfg1.timer_mod = 2; break; case MCPWM_TIMER_COUNT_MODE_UP_DOWN: - mcpwm->timer[timer_id].mode.mode = 3; + mcpwm->timer[timer_id].timer_cfg1.timer_mod = 3; break; } } static inline mcpwm_timer_count_mode_t mcpwm_ll_timer_get_count_mode(mcpwm_dev_t *mcpwm, int timer_id) { - switch (mcpwm->timer[timer_id].mode.mode) { + switch (mcpwm->timer[timer_id].timer_cfg1.timer_mod) { case 0: return MCPWM_TIMER_COUNT_MODE_PAUSE; case 1: @@ -344,6 +347,9 @@ static inline mcpwm_timer_count_mode_t mcpwm_ll_timer_get_count_mode(mcpwm_dev_t return MCPWM_TIMER_COUNT_MODE_DOWN; case 3: return MCPWM_TIMER_COUNT_MODE_UP_DOWN; + default: + HAL_ASSERT(false && "unknown count mode"); + return mcpwm->timer[timer_id].timer_cfg1.timer_mod; } } @@ -351,74 +357,74 @@ static inline void mcpwm_ll_timer_set_execute_command(mcpwm_dev_t *mcpwm, int ti { switch (cmd) { case MCPWM_TIMER_STOP_AT_ZERO: - mcpwm->timer[timer_id].mode.start = 0; + mcpwm->timer[timer_id].timer_cfg1.timer_start = 0; break; case MCPWM_TIMER_STOP_AT_PEAK: - mcpwm->timer[timer_id].mode.start = 1; + mcpwm->timer[timer_id].timer_cfg1.timer_start = 1; break; case MCPWM_TIMER_START_NO_STOP: - mcpwm->timer[timer_id].mode.start = 2; + mcpwm->timer[timer_id].timer_cfg1.timer_start = 2; break; case MCPWM_TIMER_START_STOP_AT_ZERO: - mcpwm->timer[timer_id].mode.start = 3; + mcpwm->timer[timer_id].timer_cfg1.timer_start = 3; break; case MCPWM_TIMER_START_STOP_AT_PEAK: - mcpwm->timer[timer_id].mode.start = 4; + mcpwm->timer[timer_id].timer_cfg1.timer_start = 4; break; } } static inline uint32_t mcpwm_ll_timer_get_count_value(mcpwm_dev_t *mcpwm, int timer_id) { - return mcpwm->timer[timer_id].status.value; + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_status, timer_value); } static inline mcpwm_timer_direction_t mcpwm_ll_timer_get_count_direction(mcpwm_dev_t *mcpwm, int timer_id) { - return mcpwm->timer[timer_id].status.direction ? MCPWM_TIMER_DIRECTION_DOWN : MCPWM_TIMER_DIRECTION_UP; + return mcpwm->timer[timer_id].timer_status.timer_direction ? MCPWM_TIMER_DIRECTION_DOWN : MCPWM_TIMER_DIRECTION_UP; } static inline void mcpwm_ll_timer_enable_sync_input(mcpwm_dev_t *mcpwm, int timer_id, bool enable) { - mcpwm->timer[timer_id].sync.in_en = enable; + mcpwm->timer[timer_id].timer_sync.timer_synci_en = enable; } static inline void mcpwm_ll_timer_sync_out_penetrate(mcpwm_dev_t *mcpwm, int timer_id) { // sync_out is selected to sync_in - mcpwm->timer[timer_id].sync.out_sel = 0; + mcpwm->timer[timer_id].timer_sync.timer_synco_sel = 0; } static inline void mcpwm_ll_timer_sync_out_on_timer_event(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_event_t event) { if (event == MCPWM_TIMER_EVENT_ZERO) { - mcpwm->timer[timer_id].sync.out_sel = 1; + mcpwm->timer[timer_id].timer_sync.timer_synco_sel = 1; } else if (event == MCPWM_TIMER_EVENT_PEAK) { - mcpwm->timer[timer_id].sync.out_sel = 2; + mcpwm->timer[timer_id].timer_sync.timer_synco_sel = 2; } else { - HAL_ASSERT(false); + HAL_ASSERT(false && "unknown sync out event"); } } static inline void mcpwm_ll_timer_disable_sync_out(mcpwm_dev_t *mcpwm, int timer_id) { // sync_out will always be zero - mcpwm->timer[timer_id].sync.out_sel = 3; + mcpwm->timer[timer_id].timer_sync.timer_synco_sel = 3; } static inline void mcpwm_ll_timer_trigger_soft_sync(mcpwm_dev_t *mcpwm, int timer_id) { - mcpwm->timer[timer_id].sync.sync_sw = ~mcpwm->timer[timer_id].sync.sync_sw; + mcpwm->timer[timer_id].timer_sync.timer_sync_sw = ~mcpwm->timer[timer_id].timer_sync.timer_sync_sw; } static inline void mcpwm_ll_timer_set_sync_phase_value(mcpwm_dev_t *mcpwm, int timer_id, uint32_t phase_value) { - mcpwm->timer[timer_id].sync.timer_phase = phase_value; + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_sync, timer_phase, phase_value); } static inline void mcpwm_ll_timer_set_sync_phase_direction(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_direction_t direction) { - mcpwm->timer[timer_id].sync.phase_direct = direction; + mcpwm->timer[timer_id].timer_sync.timer_phase_direction = direction; } static inline void mcpwm_ll_timer_set_gpio_synchro(mcpwm_dev_t *mcpwm, int timer, int gpio_sync_id) @@ -458,117 +464,117 @@ static inline void mcpwm_ll_operator_flush_shadow(mcpwm_dev_t *mcpwm, int operat static inline void mcpwm_ll_operator_select_timer(mcpwm_dev_t *mcpwm, int operator_id, int timer_id) { if (operator_id == 0) { - mcpwm->timer_sel.operator0_sel = timer_id; + mcpwm->operator_timersel.operator0_timersel = timer_id; } else if (operator_id == 1) { - mcpwm->timer_sel.operator1_sel = timer_id; + mcpwm->operator_timersel.operator1_timersel = timer_id; } else { - mcpwm->timer_sel.operator2_sel = timer_id; + mcpwm->operator_timersel.operator2_timersel = timer_id; } } static inline void mcpwm_ll_operator_update_compare_at_once(mcpwm_dev_t *mcpwm, int operator_id, int compare_id) { - mcpwm->channel[operator_id].cmpr_cfg.val &= ~(0x0F << (4 * compare_id)); + mcpwm->operators[operator_id].gen_stmp_cfg.val &= ~(0x0F << (4 * compare_id)); } static inline void mcpwm_ll_operator_enable_update_compare_on_tez(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].cmpr_cfg.val |= (1 << 0) << (4 * compare_id); + mcpwm->operators[operator_id].gen_stmp_cfg.val |= (1 << 0) << (4 * compare_id); } else { - mcpwm->channel[operator_id].cmpr_cfg.val &= ~((1 << 0) << (4 * compare_id)); + mcpwm->operators[operator_id].gen_stmp_cfg.val &= ~((1 << 0) << (4 * compare_id)); } } static inline void mcpwm_ll_operator_enable_update_compare_on_tep(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].cmpr_cfg.val |= (1 << 1) << (4 * compare_id); + mcpwm->operators[operator_id].gen_stmp_cfg.val |= (1 << 1) << (4 * compare_id); } else { - mcpwm->channel[operator_id].cmpr_cfg.val &= ~((1 << 1) << (4 * compare_id)); + mcpwm->operators[operator_id].gen_stmp_cfg.val &= ~((1 << 1) << (4 * compare_id)); } } static inline void mcpwm_ll_operator_enable_update_compare_on_sync(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].cmpr_cfg.val |= (1 << 2) << (4 * compare_id); + mcpwm->operators[operator_id].gen_stmp_cfg.val |= (1 << 2) << (4 * compare_id); } else { - mcpwm->channel[operator_id].cmpr_cfg.val &= ~((1 << 2) << (4 * compare_id)); + mcpwm->operators[operator_id].gen_stmp_cfg.val &= ~((1 << 2) << (4 * compare_id)); } } static inline void mcpwm_ll_operator_set_compare_value(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, uint32_t compare_value) { - mcpwm->channel[operator_id].cmpr_value[compare_id].cmpr_val = compare_value; + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->operators[operator_id].timestamp[compare_id], gen, compare_value); } static inline uint32_t mcpwm_ll_operator_get_compare_value(mcpwm_dev_t *mcpwm, int operator_id, int compare_id) { - return mcpwm->channel[operator_id].cmpr_value[compare_id].cmpr_val; + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->operators[operator_id].timestamp[compare_id], gen); } static inline void mcpwm_ll_operator_update_action_at_once(mcpwm_dev_t *mcpwm, int operator_id) { - mcpwm->channel[operator_id].gen_cfg0.upmethod = 0; + mcpwm->operators[operator_id].gen_cfg0.gen_cfg_upmethod = 0; } static inline void mcpwm_ll_operator_enable_update_action_on_tez(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].gen_cfg0.upmethod |= 1 << 0; + mcpwm->operators[operator_id].gen_cfg0.gen_cfg_upmethod |= 1 << 0; } else { - mcpwm->channel[operator_id].gen_cfg0.upmethod &= ~(1 << 0); + mcpwm->operators[operator_id].gen_cfg0.gen_cfg_upmethod &= ~(1 << 0); } } static inline void mcpwm_ll_operator_enable_update_action_on_tep(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].gen_cfg0.upmethod |= 1 << 1; + mcpwm->operators[operator_id].gen_cfg0.gen_cfg_upmethod |= 1 << 1; } else { - mcpwm->channel[operator_id].gen_cfg0.upmethod &= ~(1 << 1); + mcpwm->operators[operator_id].gen_cfg0.gen_cfg_upmethod &= ~(1 << 1); } } static inline void mcpwm_ll_operator_enable_update_action_on_sync(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].gen_cfg0.upmethod |= 1 << 2; + mcpwm->operators[operator_id].gen_cfg0.gen_cfg_upmethod |= 1 << 2; } else { - mcpwm->channel[operator_id].gen_cfg0.upmethod &= ~(1 << 2); + mcpwm->operators[operator_id].gen_cfg0.gen_cfg_upmethod &= ~(1 << 2); } } static inline void mcpwm_ll_operator_set_trigger_gpio_fault(mcpwm_dev_t *mcpwm, int operator_id, int trig_id, int fault_id) { - mcpwm->channel[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id)); - mcpwm->channel[operator_id].gen_cfg0.val |= (fault_id << (4 + 3 * trig_id)); + mcpwm->operators[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id)); + mcpwm->operators[operator_id].gen_cfg0.val |= (fault_id << (4 + 3 * trig_id)); } static inline void mcpwm_ll_operator_set_trigger_timer_sync(mcpwm_dev_t *mcpwm, int operator_id, int trig_id) { // the timer here is not selectable, must be the one connected with the operator - mcpwm->channel[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id)); - mcpwm->channel[operator_id].gen_cfg0.val |= (3 << (4 + 3 * trig_id)); + mcpwm->operators[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id)); + mcpwm->operators[operator_id].gen_cfg0.val |= (3 << (4 + 3 * trig_id)); } /********************* Generator registers *******************/ static inline void mcpwm_ll_generator_reset_actions(mcpwm_dev_t *mcpwm, int operator_id, int generator_id) { - mcpwm->channel[operator_id].generator[generator_id].val = 0; + mcpwm->operators[operator_id].generator[generator_id].val = 0; } static inline void mcpwm_ll_generator_set_action_on_timer_event(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, mcpwm_timer_direction_t direction, mcpwm_timer_event_t event, mcpwm_generator_action_t action) { if (direction == MCPWM_TIMER_DIRECTION_UP) { // utez, utep - mcpwm->channel[operator_id].generator[generator_id].val &= ~(0x03 << (event * 2)); - mcpwm->channel[operator_id].generator[generator_id].val |= action << (event * 2); + mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (event * 2)); + mcpwm->operators[operator_id].generator[generator_id].val |= action << (event * 2); } else if (direction == MCPWM_TIMER_DIRECTION_DOWN) { // dtez, dtep - mcpwm->channel[operator_id].generator[generator_id].val &= ~(0x03 << (event * 2 + 12)); - mcpwm->channel[operator_id].generator[generator_id].val |= action << (event * 2 + 12); + mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (event * 2 + 12)); + mcpwm->operators[operator_id].generator[generator_id].val |= action << (event * 2 + 12); } } @@ -576,11 +582,11 @@ static inline void mcpwm_ll_generator_set_action_on_compare_event(mcpwm_dev_t *m mcpwm_timer_direction_t direction, int cmp_id, int action) { if (direction == MCPWM_TIMER_DIRECTION_UP) { // utea, uteb - mcpwm->channel[operator_id].generator[generator_id].val &= ~(0x03 << (cmp_id * 2 + 4)); - mcpwm->channel[operator_id].generator[generator_id].val |= action << (cmp_id * 2 + 4); + mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (cmp_id * 2 + 4)); + mcpwm->operators[operator_id].generator[generator_id].val |= action << (cmp_id * 2 + 4); } else if (direction == MCPWM_TIMER_DIRECTION_DOWN) { // dtea, dteb - mcpwm->channel[operator_id].generator[generator_id].val &= ~(0x03 << (cmp_id * 2 + 16)); - mcpwm->channel[operator_id].generator[generator_id].val |= action << (cmp_id * 2 + 16); + mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (cmp_id * 2 + 16)); + mcpwm->operators[operator_id].generator[generator_id].val |= action << (cmp_id * 2 + 16); } } @@ -588,58 +594,58 @@ static inline void mcpwm_ll_generator_set_action_on_trigger_event(mcpwm_dev_t *m mcpwm_timer_direction_t direction, int trig_id, int action) { if (direction == MCPWM_TIMER_DIRECTION_UP) { // ut0, ut1 - mcpwm->channel[operator_id].generator[generator_id].val &= ~(0x03 << (trig_id * 2 + 8)); - mcpwm->channel[operator_id].generator[generator_id].val |= action << (trig_id * 2 + 8); + mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (trig_id * 2 + 8)); + mcpwm->operators[operator_id].generator[generator_id].val |= action << (trig_id * 2 + 8); } else if (direction == MCPWM_TIMER_DIRECTION_DOWN) { // dt0, dt1 - mcpwm->channel[operator_id].generator[generator_id].val &= ~(0x03 << (trig_id * 2 + 20)); - mcpwm->channel[operator_id].generator[generator_id].val |= action << (trig_id * 2 + 20); + mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (trig_id * 2 + 20)); + mcpwm->operators[operator_id].generator[generator_id].val |= action << (trig_id * 2 + 20); } } static inline void mcpwm_ll_gen_trigger_noncontinue_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id) { if (generator_id == 0) { - mcpwm->channel[operator_id].gen_force.a_nciforce = ~mcpwm->channel[operator_id].gen_force.a_nciforce; + mcpwm->operators[operator_id].gen_force.gen_a_nciforce = ~mcpwm->operators[operator_id].gen_force.gen_a_nciforce; } else { - mcpwm->channel[operator_id].gen_force.b_nciforce = ~mcpwm->channel[operator_id].gen_force.b_nciforce; + mcpwm->operators[operator_id].gen_force.gen_b_nciforce = ~mcpwm->operators[operator_id].gen_force.gen_b_nciforce; } } static inline void mcpwm_ll_gen_disable_continue_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id) { - mcpwm->channel[operator_id].gen_force.cntu_force_upmethod = 0; // update force method immediately + mcpwm->operators[operator_id].gen_force.gen_cntuforce_upmethod = 0; // update force method immediately if (generator_id == 0) { - mcpwm->channel[operator_id].gen_force.a_cntuforce_mode = 0; + mcpwm->operators[operator_id].gen_force.gen_a_cntuforce_mode = 0; } else { - mcpwm->channel[operator_id].gen_force.b_cntuforce_mode = 0; + mcpwm->operators[operator_id].gen_force.gen_b_cntuforce_mode = 0; } } static inline void mcpwm_ll_gen_disable_noncontinue_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id) { if (generator_id == 0) { - mcpwm->channel[operator_id].gen_force.a_nciforce_mode = 0; + mcpwm->operators[operator_id].gen_force.gen_a_nciforce_mode = 0; } else { - mcpwm->channel[operator_id].gen_force.b_nciforce_mode = 0; + mcpwm->operators[operator_id].gen_force.gen_b_nciforce_mode = 0; } } static inline void mcpwm_ll_gen_set_continue_force_level(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, int level) { - mcpwm->channel[operator_id].gen_force.cntu_force_upmethod = 0; // update force method immediately + mcpwm->operators[operator_id].gen_force.gen_cntuforce_upmethod = 0; // update force method immediately if (generator_id == 0) { - mcpwm->channel[operator_id].gen_force.a_cntuforce_mode = level + 1; + mcpwm->operators[operator_id].gen_force.gen_a_cntuforce_mode = level + 1; } else { - mcpwm->channel[operator_id].gen_force.b_cntuforce_mode = level + 1; + mcpwm->operators[operator_id].gen_force.gen_b_cntuforce_mode = level + 1; } } static inline void mcpwm_ll_gen_set_noncontinue_force_level(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, int level) { if (generator_id == 0) { - mcpwm->channel[operator_id].gen_force.a_nciforce_mode = level + 1; + mcpwm->operators[operator_id].gen_force.gen_a_nciforce_mode = level + 1; } else { - mcpwm->channel[operator_id].gen_force.b_nciforce_mode = level + 1; + mcpwm->operators[operator_id].gen_force.gen_b_nciforce_mode = level + 1; } } @@ -648,116 +654,116 @@ static inline void mcpwm_ll_gen_set_noncontinue_force_level(mcpwm_dev_t *mcpwm, static inline void mcpwm_ll_deadtime_resolution_to_timer(mcpwm_dev_t *mcpwm, int operator_id, bool same) { // whether to make the resolution of dead time delay module the same to the timer connected with operator - mcpwm->channel[operator_id].db_cfg.clk_sel = same; + mcpwm->operators[operator_id].dt_cfg.dt_clk_sel = same; } static inline void mcpwm_ll_deadtime_red_select_generator(mcpwm_dev_t *mcpwm, int operator_id, int generator) { - mcpwm->channel[operator_id].db_cfg.red_insel = generator; + mcpwm->operators[operator_id].dt_cfg.dt_red_insel = generator; } static inline void mcpwm_ll_deadtime_fed_select_generator(mcpwm_dev_t *mcpwm, int operator_id, int generator) { - mcpwm->channel[operator_id].db_cfg.fed_insel = generator; + mcpwm->operators[operator_id].dt_cfg.dt_fed_insel = generator; } static inline void mcpwm_ll_deadtime_bypass_path(mcpwm_dev_t *mcpwm, int operator_id, int path, bool bypass) { if (bypass) { - mcpwm->channel[operator_id].db_cfg.val |= 1 << (path + 15); + mcpwm->operators[operator_id].dt_cfg.val |= 1 << (path + 15); } else { - mcpwm->channel[operator_id].db_cfg.val &= ~(1 << (path + 15)); + mcpwm->operators[operator_id].dt_cfg.val &= ~(1 << (path + 15)); } } static inline void mcpwm_ll_deadtime_invert_outpath(mcpwm_dev_t *mcpwm, int operator_id, int path, bool invert) { if (invert) { - mcpwm->channel[operator_id].db_cfg.val |= 1 << (path + 13); + mcpwm->operators[operator_id].dt_cfg.val |= 1 << (path + 13); } else { - mcpwm->channel[operator_id].db_cfg.val &= ~(1 << (path + 13)); + mcpwm->operators[operator_id].dt_cfg.val &= ~(1 << (path + 13)); } } static inline void mcpwm_ll_deadtime_swap_out_path(mcpwm_dev_t *mcpwm, int operator_id, int path, bool swap) { if (swap) { - mcpwm->channel[operator_id].db_cfg.val |= 1 << (path + 9); + mcpwm->operators[operator_id].dt_cfg.val |= 1 << (path + 9); } else { - mcpwm->channel[operator_id].db_cfg.val &= ~(1 << (path + 9)); + mcpwm->operators[operator_id].dt_cfg.val &= ~(1 << (path + 9)); } } static inline void mcpwm_ll_deadtime_enable_deb(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { - mcpwm->channel[operator_id].db_cfg.deb_mode = enable; + mcpwm->operators[operator_id].dt_cfg.dt_deb_mode = enable; } static inline uint32_t mcpwm_ll_deadtime_get_switch_topology(mcpwm_dev_t *mcpwm, int operator_id) { - return (mcpwm->channel[operator_id].db_cfg.deb_mode << 8) | (mcpwm->channel[operator_id].db_cfg.b_outswap << 7) | - (mcpwm->channel[operator_id].db_cfg.a_outswap << 6) | (mcpwm->channel[operator_id].db_cfg.fed_insel << 5) | - (mcpwm->channel[operator_id].db_cfg.red_insel << 4) | (mcpwm->channel[operator_id].db_cfg.fed_outinvert << 3) | - (mcpwm->channel[operator_id].db_cfg.red_outinvert << 2) | (mcpwm->channel[operator_id].db_cfg.a_outbypass << 1) | - (mcpwm->channel[operator_id].db_cfg.b_outbypass << 0); + return (mcpwm->operators[operator_id].dt_cfg.dt_deb_mode << 8) | (mcpwm->operators[operator_id].dt_cfg.dt_b_outswap << 7) | + (mcpwm->operators[operator_id].dt_cfg.dt_a_outswap << 6) | (mcpwm->operators[operator_id].dt_cfg.dt_fed_insel << 5) | + (mcpwm->operators[operator_id].dt_cfg.dt_red_insel << 4) | (mcpwm->operators[operator_id].dt_cfg.dt_fed_outinvert << 3) | + (mcpwm->operators[operator_id].dt_cfg.dt_red_outinvert << 2) | (mcpwm->operators[operator_id].dt_cfg.dt_a_outbypass << 1) | + (mcpwm->operators[operator_id].dt_cfg.dt_b_outbypass << 0); } static inline void mcpwm_ll_deadtime_set_falling_delay(mcpwm_dev_t *mcpwm, int operator_id, uint32_t fed) { - mcpwm->channel[operator_id].db_fed_cfg.fed = fed - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->operators[operator_id].dt_fed_cfg, dt_fed, fed - 1); } static inline uint32_t mcpwm_ll_deadtime_get_falling_delay(mcpwm_dev_t *mcpwm, int operator_id) { - return mcpwm->channel[operator_id].db_fed_cfg.fed + 1; + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->operators[operator_id].dt_fed_cfg, dt_fed) + 1; } static inline void mcpwm_ll_deadtime_set_rising_delay(mcpwm_dev_t *mcpwm, int operator_id, uint32_t red) { - mcpwm->channel[operator_id].db_red_cfg.red = red - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->operators[operator_id].dt_red_cfg, dt_red, red - 1); } static inline uint32_t mcpwm_ll_deadtime_get_rising_delay(mcpwm_dev_t *mcpwm, int operator_id) { - return mcpwm->channel[operator_id].db_red_cfg.red + 1; + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->operators[operator_id].dt_red_cfg, dt_red) + 1; } static inline void mcpwm_ll_deadtime_update_delay_at_once(mcpwm_dev_t *mcpwm, int operator_id) { - mcpwm->channel[operator_id].db_cfg.fed_upmethod = 0; - mcpwm->channel[operator_id].db_cfg.red_upmethod = 0; + mcpwm->operators[operator_id].dt_cfg.dt_fed_upmethod = 0; + mcpwm->operators[operator_id].dt_cfg.dt_red_upmethod = 0; } static inline void mcpwm_ll_deadtime_enable_update_delay_on_tez(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].db_cfg.fed_upmethod |= 1 << 0; - mcpwm->channel[operator_id].db_cfg.red_upmethod |= 1 << 0; + mcpwm->operators[operator_id].dt_cfg.dt_fed_upmethod |= 1 << 0; + mcpwm->operators[operator_id].dt_cfg.dt_red_upmethod |= 1 << 0; } else { - mcpwm->channel[operator_id].db_cfg.fed_upmethod &= ~(1 << 0); - mcpwm->channel[operator_id].db_cfg.red_upmethod &= ~(1 << 0); + mcpwm->operators[operator_id].dt_cfg.dt_fed_upmethod &= ~(1 << 0); + mcpwm->operators[operator_id].dt_cfg.dt_red_upmethod &= ~(1 << 0); } } static inline void mcpwm_ll_deadtime_enable_update_delay_on_tep(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].db_cfg.fed_upmethod |= 1 << 1; - mcpwm->channel[operator_id].db_cfg.red_upmethod |= 1 << 1; + mcpwm->operators[operator_id].dt_cfg.dt_fed_upmethod |= 1 << 1; + mcpwm->operators[operator_id].dt_cfg.dt_red_upmethod |= 1 << 1; } else { - mcpwm->channel[operator_id].db_cfg.fed_upmethod &= ~(1 << 1); - mcpwm->channel[operator_id].db_cfg.red_upmethod &= ~(1 << 1); + mcpwm->operators[operator_id].dt_cfg.dt_fed_upmethod &= ~(1 << 1); + mcpwm->operators[operator_id].dt_cfg.dt_red_upmethod &= ~(1 << 1); } } static inline void mcpwm_ll_deadtime_enable_update_delay_on_sync(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].db_cfg.fed_upmethod |= 1 << 2; - mcpwm->channel[operator_id].db_cfg.red_upmethod |= 1 << 2; + mcpwm->operators[operator_id].dt_cfg.dt_fed_upmethod |= 1 << 2; + mcpwm->operators[operator_id].dt_cfg.dt_red_upmethod |= 1 << 2; } else { - mcpwm->channel[operator_id].db_cfg.fed_upmethod &= ~(1 << 2); - mcpwm->channel[operator_id].db_cfg.red_upmethod &= ~(1 << 2); + mcpwm->operators[operator_id].dt_cfg.dt_fed_upmethod &= ~(1 << 2); + mcpwm->operators[operator_id].dt_cfg.dt_red_upmethod &= ~(1 << 2); } } @@ -765,47 +771,47 @@ static inline void mcpwm_ll_deadtime_enable_update_delay_on_sync(mcpwm_dev_t *mc static inline void mcpwm_ll_carrier_enable(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { - mcpwm->channel[operator_id].carrier_cfg.en = enable; + mcpwm->operators[operator_id].carrier_cfg.carrier_en = enable; } static inline void mcpwm_ll_carrier_set_prescale(mcpwm_dev_t *mcpwm, int operator_id, uint8_t prescale) { - mcpwm->channel[operator_id].carrier_cfg.prescale = prescale - 1; + mcpwm->operators[operator_id].carrier_cfg.carrier_prescale = prescale - 1; } static inline uint8_t mcpwm_ll_carrier_get_prescale(mcpwm_dev_t *mcpwm, int operator_id) { - return mcpwm->channel[operator_id].carrier_cfg.prescale + 1; + return mcpwm->operators[operator_id].carrier_cfg.carrier_prescale + 1; } static inline void mcpwm_ll_carrier_set_duty(mcpwm_dev_t *mcpwm, int operator_id, uint8_t carrier_duty) { - mcpwm->channel[operator_id].carrier_cfg.duty = carrier_duty; + mcpwm->operators[operator_id].carrier_cfg.carrier_duty = carrier_duty; } static inline uint8_t mcpwm_ll_carrier_get_duty(mcpwm_dev_t *mcpwm, int operator_id) { - return mcpwm->channel[operator_id].carrier_cfg.duty; + return mcpwm->operators[operator_id].carrier_cfg.carrier_duty; } static inline void mcpwm_ll_carrier_out_invert(mcpwm_dev_t *mcpwm, int operator_id, bool invert) { - mcpwm->channel[operator_id].carrier_cfg.out_invert = invert; + mcpwm->operators[operator_id].carrier_cfg.carrier_out_invert = invert; } static inline void mcpwm_ll_carrier_in_invert(mcpwm_dev_t *mcpwm, int operator_id, bool invert) { - mcpwm->channel[operator_id].carrier_cfg.in_invert = invert; + mcpwm->operators[operator_id].carrier_cfg.carrier_in_invert = invert; } static inline void mcpwm_ll_carrier_set_oneshot_width(mcpwm_dev_t *mcpwm, int operator_id, uint8_t pulse_width) { - mcpwm->channel[operator_id].carrier_cfg.oshtwth = pulse_width - 1; + mcpwm->operators[operator_id].carrier_cfg.carrier_oshtwth = pulse_width - 1; } static inline uint8_t mcpwm_ll_carrier_get_oneshot_width(mcpwm_dev_t *mcpwm, int operator_id) { - return mcpwm->channel[operator_id].carrier_cfg.oshtwth + 1; + return mcpwm->operators[operator_id].carrier_cfg.carrier_oshtwth + 1; } /********************* Fault detector registers *******************/ @@ -831,157 +837,159 @@ static inline void mcpwm_ll_fault_set_active_level(mcpwm_dev_t *mcpwm, int fault static inline void mcpwm_ll_fault_clear_ost(mcpwm_dev_t *mcpwm, int operator_id) { // a posedge can clear the ost fault status - mcpwm->channel[operator_id].tz_cfg1.clr_ost = 0; - mcpwm->channel[operator_id].tz_cfg1.clr_ost = 1; + mcpwm->operators[operator_id].fh_cfg1.fh_clr_ost = 0; + mcpwm->operators[operator_id].fh_cfg1.fh_clr_ost = 1; } static inline void mcpwm_ll_fault_enable_oneshot_mode(mcpwm_dev_t *mcpwm, int operator_id, int fault_sig, bool enable) { - mcpwm->channel[operator_id].tz_cfg0.val &= ~(1 << (7 - fault_sig)); - mcpwm->channel[operator_id].tz_cfg0.val |= (enable << (7 - fault_sig)); + mcpwm->operators[operator_id].fh_cfg0.val &= ~(1 << (7 - fault_sig)); + mcpwm->operators[operator_id].fh_cfg0.val |= (enable << (7 - fault_sig)); } static inline void mcpwm_ll_fault_enable_cbc_mode(mcpwm_dev_t *mcpwm, int operator_id, int fault_sig, bool enable) { - mcpwm->channel[operator_id].tz_cfg0.val &= ~(1 << (3 - fault_sig)); - mcpwm->channel[operator_id].tz_cfg0.val |= (enable << (3 - fault_sig)); + mcpwm->operators[operator_id].fh_cfg0.val &= ~(1 << (3 - fault_sig)); + mcpwm->operators[operator_id].fh_cfg0.val |= (enable << (3 - fault_sig)); } static inline void mcpwm_ll_fault_enable_cbc_refresh_on_tez(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].tz_cfg1.val |= 1 << 1; + mcpwm->operators[operator_id].fh_cfg1.val |= 1 << 1; } else { - mcpwm->channel[operator_id].tz_cfg1.val &= ~(1 << 1); + mcpwm->operators[operator_id].fh_cfg1.val &= ~(1 << 1); } } static inline void mcpwm_ll_fault_enable_cbc_refresh_on_tep(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].tz_cfg1.val |= 1 << 2; + mcpwm->operators[operator_id].fh_cfg1.val |= 1 << 2; } else { - mcpwm->channel[operator_id].tz_cfg1.val &= ~(1 << 2); + mcpwm->operators[operator_id].fh_cfg1.val &= ~(1 << 2); } } static inline void mcpwm_ll_fault_enable_sw_cbc(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { - mcpwm->channel[operator_id].tz_cfg0.sw_cbc = enable; + mcpwm->operators[operator_id].fh_cfg0.fh_sw_cbc = enable; } static inline void mcpwm_ll_fault_enable_sw_oneshot(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { - mcpwm->channel[operator_id].tz_cfg0.sw_ost = enable; + mcpwm->operators[operator_id].fh_cfg0.fh_sw_ost = enable; } static inline void mcpwm_ll_fault_trigger_sw_cbc(mcpwm_dev_t *mcpwm, int operator_id) { - mcpwm->channel[operator_id].tz_cfg1.force_cbc = ~mcpwm->channel[operator_id].tz_cfg1.force_cbc; + mcpwm->operators[operator_id].fh_cfg1.fh_force_cbc = ~mcpwm->operators[operator_id].fh_cfg1.fh_force_cbc; } static inline void mcpwm_ll_fault_trigger_sw_ost(mcpwm_dev_t *mcpwm, int operator_id) { - mcpwm->channel[operator_id].tz_cfg1.force_ost = ~mcpwm->channel[operator_id].tz_cfg1.force_ost; + mcpwm->operators[operator_id].fh_cfg1.fh_force_ost = ~mcpwm->operators[operator_id].fh_cfg1.fh_force_ost; } static inline void mcpwm_ll_generator_set_action_on_trip_event(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, mcpwm_timer_direction_t direction, mcpwm_trip_type_t trip, int action) { if (direction == MCPWM_TIMER_DIRECTION_UP) { - mcpwm->channel[operator_id].tz_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * trip + 2)); - mcpwm->channel[operator_id].tz_cfg0.val |= action << (8 + 8 * generator_id + 4 * trip + 2); + mcpwm->operators[operator_id].fh_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * trip + 2)); + mcpwm->operators[operator_id].fh_cfg0.val |= action << (8 + 8 * generator_id + 4 * trip + 2); } else if (direction == MCPWM_TIMER_DIRECTION_DOWN) { - mcpwm->channel[operator_id].tz_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * trip)); - mcpwm->channel[operator_id].tz_cfg0.val |= action << (8 + 8 * generator_id + 4 * trip); + mcpwm->operators[operator_id].fh_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * trip)); + mcpwm->operators[operator_id].fh_cfg0.val |= action << (8 + 8 * generator_id + 4 * trip); } } static inline bool mcpwm_ll_fault_is_ost_on(mcpwm_dev_t *mcpwm, int op) { - return mcpwm->channel[op].tz_status.ost_on; + return mcpwm->operators[op].fh_status.fh_ost_on; } static inline bool mcpwm_ll_fault_is_cbc_on(mcpwm_dev_t *mcpwm, int op) { - return mcpwm->channel[op].tz_status.cbc_on; + return mcpwm->operators[op].fh_status.fh_cbc_on; } /********************* Capture registers *******************/ static inline void mcpwm_ll_capture_enable_timer(mcpwm_dev_t *mcpwm, bool enable) { - mcpwm->cap_timer_cfg.timer_en = enable; + mcpwm->cap_timer_cfg.cap_timer_en = enable; } static inline void mcpwm_ll_capture_enable_channel(mcpwm_dev_t *mcpwm, int channel, bool enable) { - mcpwm->cap_cfg_ch[channel].en = enable; + mcpwm->cap_chn_cfg[channel].capn_en = enable; } static inline void mcpwm_ll_capture_set_sync_phase_value(mcpwm_dev_t *mcpwm, uint32_t phase_value) { - mcpwm->cap_timer_phase = phase_value; + mcpwm->cap_timer_phase.cap_timer_phase = phase_value; } static inline uint32_t mcpwm_ll_capture_get_sync_phase_value(mcpwm_dev_t *mcpwm) { - return mcpwm->cap_timer_phase; + return mcpwm->cap_timer_phase.cap_timer_phase; } static inline void mcpwm_ll_capture_enable_timer_sync(mcpwm_dev_t *mcpwm, bool enable) { - mcpwm->cap_timer_cfg.synci_en = enable; + mcpwm->cap_timer_cfg.cap_synci_en = enable; } static inline void mcpwm_ll_capture_set_internal_timer_synchro(mcpwm_dev_t *mcpwm, int sync_out_timer) { - mcpwm->cap_timer_cfg.synci_sel = sync_out_timer + 1; + mcpwm->cap_timer_cfg.cap_synci_sel = sync_out_timer + 1; } static inline void mcpwm_ll_capture_set_external_synchro(mcpwm_dev_t *mcpwm, int extern_synchro) { - mcpwm->cap_timer_cfg.synci_sel = extern_synchro + 4; + mcpwm->cap_timer_cfg.cap_synci_sel = extern_synchro + 4; } static inline void mcpwm_ll_capture_trigger_sw_sync(mcpwm_dev_t *mcpwm) { - mcpwm->cap_timer_cfg.sync_sw = 1; // auto clear + mcpwm->cap_timer_cfg.cap_sync_sw = 1; // auto clear } static inline void mcpwm_ll_capture_enable_posedge(mcpwm_dev_t *mcpwm, int channel, bool enable) { if (enable) { - mcpwm->cap_cfg_ch[channel].val |= 1 << 2; + mcpwm->cap_chn_cfg[channel].val |= 1 << 2; } else { - mcpwm->cap_cfg_ch[channel].val &= ~(1 << 2); + mcpwm->cap_chn_cfg[channel].val &= ~(1 << 2); } } static inline void mcpwm_ll_capture_enable_negedge(mcpwm_dev_t *mcpwm, int channel, bool enable) { if (enable) { - mcpwm->cap_cfg_ch[channel].val |= 1 << 1; + mcpwm->cap_chn_cfg[channel].val |= 1 << 1; } else { - mcpwm->cap_cfg_ch[channel].val &= ~(1 << 1); + mcpwm->cap_chn_cfg[channel].val &= ~(1 << 1); } } static inline void mcpwm_ll_invert_input(mcpwm_dev_t *mcpwm, int channel, bool invert) { - mcpwm->cap_cfg_ch[channel].in_invert = invert; + mcpwm->cap_chn_cfg[channel].capn_in_invert = invert; } static inline void mcpwm_ll_trigger_soft_capture(mcpwm_dev_t *mcpwm, int channel) { - mcpwm->cap_cfg_ch[channel].sw = 1; // auto clear + mcpwm->cap_chn_cfg[channel].capn_sw = 1; // auto clear } +__attribute__((always_inline)) static inline uint32_t mcpwm_ll_capture_get_value(mcpwm_dev_t *mcpwm, int channel) { - return mcpwm->cap_val_ch[channel]; + return mcpwm->cap_chn[channel].capn_value; } +__attribute__((always_inline)) static inline bool mcpwm_ll_capture_is_negedge(mcpwm_dev_t *mcpwm, int channel) { return mcpwm->cap_status.val & (1 << channel) ? true : false; @@ -989,12 +997,12 @@ static inline bool mcpwm_ll_capture_is_negedge(mcpwm_dev_t *mcpwm, int channel) static inline void mcpwm_ll_capture_set_prescale(mcpwm_dev_t *mcpwm, int channel, uint32_t prescale) { - mcpwm->cap_cfg_ch[channel].prescale = prescale - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->cap_chn_cfg[channel], capn_prescale, prescale - 1); } static inline uint32_t mcpwm_ll_capture_get_prescale(mcpwm_dev_t *mcpwm, int channel) { - return mcpwm->cap_cfg_ch[channel].prescale + 1; + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->cap_chn_cfg[channel], capn_prescale) + 1; } #ifdef __cplusplus diff --git a/components/hal/esp32/include/hal/mwdt_ll.h b/components/hal/esp32/include/hal/mwdt_ll.h index 9a981c6855..267f15ef2c 100644 --- a/components/hal/esp32/include/hal/mwdt_ll.h +++ b/components/hal/esp32/include/hal/mwdt_ll.h @@ -23,7 +23,9 @@ extern "C" { #include #include +#include "hal/misc.h" #include "soc/timer_periph.h" +#include "soc/timer_group_struct.h" #include "hal/wdt_types.h" #include "esp_attr.h" @@ -201,7 +203,7 @@ FORCE_INLINE_ATTR void mwdt_ll_set_flashboot_en(timg_dev_t* hw, bool enable) */ FORCE_INLINE_ATTR void mwdt_ll_set_prescaler(timg_dev_t *hw, uint32_t prescaler) { - hw->wdt_config1.clk_prescale = prescaler; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->wdt_config1, clk_prescale, prescaler); } /** diff --git a/components/hal/esp32/include/hal/pcnt_ll.h b/components/hal/esp32/include/hal/pcnt_ll.h index b5b20ff49d..40d4aff973 100644 --- a/components/hal/esp32/include/hal/pcnt_ll.h +++ b/components/hal/esp32/include/hal/pcnt_ll.h @@ -1,4 +1,4 @@ -// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// Copyright 2015-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. @@ -22,75 +22,67 @@ #pragma once -#include "soc/pcnt_periph.h" +#include +#include +#include "soc/pcnt_struct.h" #include "hal/pcnt_types.h" #ifdef __cplusplus extern "C" { #endif -// Get PCNT hardware instance with giving pcnt num #define PCNT_LL_GET_HW(num) (((num) == 0) ? (&PCNT) : NULL) +#define PCNT_LL_MAX_GLITCH_WIDTH 1023 + +typedef enum { + PCNT_LL_EVENT_THRES1, + PCNT_LL_EVENT_THRES0, + PCNT_LL_EVENT_LOW_LIMIT, + PCNT_LL_EVENT_HIGH_LIMIT, + PCNT_LL_EVENT_ZERO_CROSS, + PCNT_LL_EVENT_MAX +} pcnt_ll_event_id_t; + +#define PCNT_LL_EVENT_MASK ((1 << PCNT_LL_EVENT_MAX) - 1) /** - * @brief Set PCNT channel edge mode + * @brief Set PCNT channel edge action * * @param hw Peripheral PCNT hardware instance address. * @param unit PCNT unit number * @param channel PCNT channel number - * @param pos_mode Counter mode when detecting positive edge - * @param neg_mode Counter mode when detecting negative edge + * @param pos_act Counter action when detecting positive edge + * @param neg_act Counter action when detecting negative edge */ -static inline void pcnt_ll_set_edge_mode(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_channel_t channel, pcnt_count_mode_t pos_mode, pcnt_count_mode_t neg_mode) +static inline void pcnt_ll_set_edge_action(pcnt_dev_t *hw, uint32_t unit, uint32_t channel, pcnt_channel_edge_action_t pos_act, pcnt_channel_edge_action_t neg_act) { - typeof(hw->conf_unit[unit].conf0) conf0_reg = hw->conf_unit[unit].conf0; if (channel == 0) { - conf0_reg.ch0_pos_mode = pos_mode; - conf0_reg.ch0_neg_mode = neg_mode; + hw->conf_unit[unit].conf0.ch0_pos_mode = pos_act; + hw->conf_unit[unit].conf0.ch0_neg_mode = neg_act; } else { - conf0_reg.ch1_pos_mode = pos_mode; - conf0_reg.ch1_neg_mode = neg_mode; + hw->conf_unit[unit].conf0.ch1_pos_mode = pos_act; + hw->conf_unit[unit].conf0.ch1_neg_mode = neg_act; } - hw->conf_unit[unit].conf0 = conf0_reg; } /** - * @brief Set PCNT channel level mode + * @brief Set PCNT channel level action * * @param hw Peripheral PCNT hardware instance address. * @param unit PCNT unit number * @param channel PCNT channel number - * @param hctrl_mode Counter mode when control signal is high level - * @param lctrl_mode Counter mode when control signal is low level + * @param high_act Counter action when control signal is high level + * @param low_act Counter action when control signal is low level */ -static inline void pcnt_ll_set_level_mode(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_channel_t channel, pcnt_ctrl_mode_t hctrl_mode, pcnt_ctrl_mode_t lctrl_mode) +static inline void pcnt_ll_set_level_action(pcnt_dev_t *hw, uint32_t unit, uint32_t channel, pcnt_channel_level_action_t high_act, pcnt_channel_level_action_t low_act) { - typeof(hw->conf_unit[unit].conf0) conf0_reg = hw->conf_unit[unit].conf0; if (channel == 0) { - conf0_reg.ch0_hctrl_mode = hctrl_mode; - conf0_reg.ch0_lctrl_mode = lctrl_mode; + hw->conf_unit[unit].conf0.ch0_hctrl_mode = high_act; + hw->conf_unit[unit].conf0.ch0_lctrl_mode = low_act; } else { - conf0_reg.ch1_hctrl_mode = hctrl_mode; - conf0_reg.ch1_lctrl_mode = lctrl_mode; + hw->conf_unit[unit].conf0.ch1_hctrl_mode = high_act; + hw->conf_unit[unit].conf0.ch1_lctrl_mode = low_act; } - hw->conf_unit[unit].conf0 = conf0_reg; -} - -/** - * @brief Set PCNT counter mode - * - * @param hw Peripheral PCNT hardware instance address. - * @param unit PCNT unit number - * @param channel PCNT channel number - * @param pos_mode Counter mode when detecting positive edge - * @param neg_mode Counter mode when detecting negative edge - * @param hctrl_mode Counter mode when control signal is high level - * @param lctrl_mode Counter mode when control signal is low level - */ -static inline void pcnt_ll_set_mode(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_channel_t channel, pcnt_count_mode_t pos_mode, pcnt_count_mode_t neg_mode, pcnt_ctrl_mode_t hctrl_mode, pcnt_ctrl_mode_t lctrl_mode) -{ - pcnt_ll_set_edge_mode(hw, unit, channel, pos_mode, neg_mode); - pcnt_ll_set_level_mode(hw, unit, channel, hctrl_mode, lctrl_mode); } /** @@ -98,11 +90,13 @@ static inline void pcnt_ll_set_mode(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_chann * * @param hw Peripheral PCNT hardware instance address. * @param unit Pulse Counter unit number - * @param count Pointer to accept counter value + * @return PCNT count value (a signed integer) */ -static inline void pcnt_ll_get_counter_value(pcnt_dev_t *hw, pcnt_unit_t unit, int16_t *count) +static inline int pcnt_ll_get_count(pcnt_dev_t *hw, uint32_t unit) { - *count = (int16_t) hw->cnt_unit[unit].cnt_val; + typeof(hw->cnt_unit[unit]) cnt_reg = hw->cnt_unit[unit]; + int16_t value = cnt_reg.cnt_val; + return value; } /** @@ -111,69 +105,60 @@ static inline void pcnt_ll_get_counter_value(pcnt_dev_t *hw, pcnt_unit_t unit, i * @param hw Peripheral PCNT hardware instance address. * @param unit PCNT unit number */ -static inline void pcnt_ll_counter_pause(pcnt_dev_t *hw, pcnt_unit_t unit) +static inline void pcnt_ll_stop_count(pcnt_dev_t *hw, uint32_t unit) { - hw->ctrl.val |= BIT(PCNT_CNT_PAUSE_U0_S + (unit * 2)); + hw->ctrl.val |= 1 << (2 * unit + 1); } /** * @brief Resume counting for PCNT counter * * @param hw Peripheral PCNT hardware instance address. - * @param unit PCNT unit number, select from pcnt_unit_t + * @param unit PCNT unit number, select from uint32_t */ -static inline void pcnt_ll_counter_resume(pcnt_dev_t *hw, pcnt_unit_t unit) +static inline void pcnt_ll_start_count(pcnt_dev_t *hw, uint32_t unit) { - hw->ctrl.val &= (~(BIT(PCNT_CNT_PAUSE_U0_S + (unit * 2)))); + hw->ctrl.val &= ~(1 << (2 * unit + 1)); } /** - * @brief Clear and reset PCNT counter value to zero + * @brief Clear PCNT counter value to zero * * @param hw Peripheral PCNT hardware instance address. - * @param unit PCNT unit number, select from pcnt_unit_t + * @param unit PCNT unit number, select from uint32_t */ -static inline void pcnt_ll_counter_clear(pcnt_dev_t *hw, pcnt_unit_t unit) +static inline void pcnt_ll_clear_count(pcnt_dev_t *hw, uint32_t unit) { - uint32_t reset_bit = BIT(PCNT_PLUS_CNT_RST_U0_S + (unit * 2)); - hw->ctrl.val |= reset_bit; - hw->ctrl.val &= ~reset_bit; + hw->ctrl.val |= 1 << (2 * unit); + hw->ctrl.val &= ~(1 << (2 * unit)); } /** * @brief Enable PCNT interrupt for PCNT unit - * @note - * Each Pulse counter unit has five watch point events that share the same interrupt. - * Configure events with pcnt_event_enable() and pcnt_event_disable() + * @note Each PCNT unit has five watch point events that share the same interrupt bit. * * @param hw Peripheral PCNT hardware instance address. - * @param unit PCNT unit number + * @param unit_mask PCNT units mask + * @param enable True to enable interrupt, False to disable interrupt */ -static inline void pcnt_ll_intr_enable(pcnt_dev_t *hw, pcnt_unit_t unit) +static inline void pcnt_ll_enable_intr(pcnt_dev_t *hw, uint32_t unit_mask, bool enable) { - hw->int_ena.val |= BIT(PCNT_CNT_THR_EVENT_U0_INT_ENA_S + unit); -} - -/** - * @brief Disable PCNT interrupt for PCNT unit - * - * @param hw Peripheral PCNT hardware instance address. - * @param unit PCNT unit number - */ -static inline void pcnt_ll_intr_disable(pcnt_dev_t *hw, pcnt_unit_t unit) -{ - hw->int_ena.val &= (~(BIT(PCNT_CNT_THR_EVENT_U0_INT_ENA_S + unit))); + if (enable) { + hw->int_ena.val |= unit_mask; + } else { + hw->int_ena.val &= ~unit_mask; + } } /** * @brief Get PCNT interrupt status * * @param hw Peripheral PCNT hardware instance address. - * @param status Pointer to accept value + * @return Interrupt status word */ -static inline void pcnt_ll_get_intr_status(pcnt_dev_t *hw, uint32_t *status) +__attribute__((always_inline)) static inline uint32_t pcnt_ll_get_intr_status(pcnt_dev_t *hw) { - *status = hw->int_st.val; + return hw->int_st.val; } /** @@ -182,163 +167,241 @@ static inline void pcnt_ll_get_intr_status(pcnt_dev_t *hw, uint32_t *status) * @param hw Peripheral PCNT hardware instance address. * @param status value to clear interrupt status */ -static inline void pcnt_ll_clear_intr_status(pcnt_dev_t *hw, uint32_t status) +__attribute__((always_inline)) static inline void pcnt_ll_clear_intr_status(pcnt_dev_t *hw, uint32_t status) { hw->int_clr.val = status; } /** - * @brief Enable PCNT event of PCNT unit + * @brief Enable PCNT high limit event * * @param hw Peripheral PCNT hardware instance address. * @param unit PCNT unit number - * @param evt_type Watch point event type. - * All enabled events share the same interrupt (one interrupt per pulse counter unit). + * @param enable true to enable, false to disable */ -static inline void pcnt_ll_event_enable(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_evt_type_t evt_type) +static inline void pcnt_ll_enable_high_limit_event(pcnt_dev_t *hw, uint32_t unit, bool enable) { - if (evt_type == PCNT_EVT_L_LIM) { - hw->conf_unit[unit].conf0.thr_l_lim_en = 1; - } else if (evt_type == PCNT_EVT_H_LIM) { - hw->conf_unit[unit].conf0.thr_h_lim_en = 1; - } else if (evt_type == PCNT_EVT_THRES_0) { - hw->conf_unit[unit].conf0.thr_thres0_en = 1; - } else if (evt_type == PCNT_EVT_THRES_1) { - hw->conf_unit[unit].conf0.thr_thres1_en = 1; - } else if (evt_type == PCNT_EVT_ZERO) { - hw->conf_unit[unit].conf0.thr_zero_en = 1; - } + hw->conf_unit[unit].conf0.thr_h_lim_en = enable; } /** - * @brief Disable PCNT event of PCNT unit + * @brief Enable PCNT low limit event * * @param hw Peripheral PCNT hardware instance address. * @param unit PCNT unit number - * @param evt_type Watch point event type. - * All enabled events share the same interrupt (one interrupt per pulse counter unit). + * @param enable true to enable, false to disable */ -static inline void pcnt_ll_event_disable(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_evt_type_t evt_type) +static inline void pcnt_ll_enable_low_limit_event(pcnt_dev_t *hw, uint32_t unit, bool enable) { - if (evt_type == PCNT_EVT_L_LIM) { - hw->conf_unit[unit].conf0.thr_l_lim_en = 0; - } else if (evt_type == PCNT_EVT_H_LIM) { - hw->conf_unit[unit].conf0.thr_h_lim_en = 0; - } else if (evt_type == PCNT_EVT_THRES_0) { - hw->conf_unit[unit].conf0.thr_thres0_en = 0; - } else if (evt_type == PCNT_EVT_THRES_1) { - hw->conf_unit[unit].conf0.thr_thres1_en = 0; - } else if (evt_type == PCNT_EVT_ZERO) { - hw->conf_unit[unit].conf0.thr_zero_en = 0; - } + hw->conf_unit[unit].conf0.thr_l_lim_en = enable; } /** - * @brief Set PCNT event value of PCNT unit + * @brief Enable PCNT zero cross event * * @param hw Peripheral PCNT hardware instance address. * @param unit PCNT unit number - * @param evt_type Watch point event type. - * All enabled events share the same interrupt (one interrupt per pulse counter unit). - * - * @param value Counter value for PCNT event + * @param enable true to enable, false to disable */ -static inline void pcnt_ll_set_event_value(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t value) +static inline void pcnt_ll_enable_zero_cross_event(pcnt_dev_t *hw, uint32_t unit, bool enable) { - if (evt_type == PCNT_EVT_L_LIM) { - hw->conf_unit[unit].conf2.cnt_l_lim = value; - } else if (evt_type == PCNT_EVT_H_LIM) { - hw->conf_unit[unit].conf2.cnt_h_lim = value; - } else if (evt_type == PCNT_EVT_THRES_0) { - hw->conf_unit[unit].conf1.cnt_thres0 = value; - } else if (evt_type == PCNT_EVT_THRES_1) { - hw->conf_unit[unit].conf1.cnt_thres1 = value; - } + hw->conf_unit[unit].conf0.thr_zero_en = enable; } /** - * @brief Get PCNT event value of PCNT unit + * @brief Enable PCNT threshold event * * @param hw Peripheral PCNT hardware instance address. * @param unit PCNT unit number - * @param evt_type Watch point event type. - * All enabled events share the same interrupt (one interrupt per pulse counter unit). - * @param value Pointer to accept counter value for PCNT event + * @param thres Threshold ID + * @param enable true to enable, false to disable */ -static inline void pcnt_ll_get_event_value(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t *value) +static inline void pcnt_ll_enable_thres_event(pcnt_dev_t *hw, uint32_t unit, uint32_t thres, bool enable) { - if (evt_type == PCNT_EVT_L_LIM) { - *value = (int16_t) hw->conf_unit[unit].conf2.cnt_l_lim; - } else if (evt_type == PCNT_EVT_H_LIM) { - *value = (int16_t) hw->conf_unit[unit].conf2.cnt_h_lim; - } else if (evt_type == PCNT_EVT_THRES_0) { - *value = (int16_t) hw->conf_unit[unit].conf1.cnt_thres0; - } else if (evt_type == PCNT_EVT_THRES_1) { - *value = (int16_t) hw->conf_unit[unit].conf1.cnt_thres1; + if (thres == 0) { + hw->conf_unit[unit].conf0.thr_thres0_en = enable; } else { - *value = 0; + hw->conf_unit[unit].conf0.thr_thres1_en = enable; } } +/** + * @brief Disable all PCNT threshold events + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit unit number + */ +static inline void pcnt_ll_disable_all_events(pcnt_dev_t *hw, uint32_t unit) +{ + hw->conf_unit[unit].conf0.val &= ~(PCNT_LL_EVENT_MASK << 11); +} + +/** + * @brief Set PCNT high limit value + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @param value PCNT high limit value + */ +static inline void pcnt_ll_set_high_limit_value(pcnt_dev_t *hw, uint32_t unit, int value) +{ + typeof(hw->conf_unit[unit].conf2) conf2_reg = hw->conf_unit[unit].conf2; + conf2_reg.cnt_h_lim = value; + hw->conf_unit[unit].conf2 = conf2_reg; +} + +/** + * @brief Set PCNT low limit value + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @param value PCNT low limit value + */ +static inline void pcnt_ll_set_low_limit_value(pcnt_dev_t *hw, uint32_t unit, int value) +{ + typeof(hw->conf_unit[unit].conf2) conf2_reg = hw->conf_unit[unit].conf2; + conf2_reg.cnt_l_lim = value; + hw->conf_unit[unit].conf2 = conf2_reg; +} + +/** + * @brief Set PCNT threshold value + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @param thres Threshold ID + * @param value PCNT threshold value + */ +static inline void pcnt_ll_set_thres_value(pcnt_dev_t *hw, uint32_t unit, uint32_t thres, int value) +{ + typeof(hw->conf_unit[unit].conf1) conf1_reg = hw->conf_unit[unit].conf1; + if (thres == 0) { + conf1_reg.cnt_thres0 = value; + } else { + conf1_reg.cnt_thres1 = value; + } + hw->conf_unit[unit].conf1 = conf1_reg; +} + +/** + * @brief Get PCNT high limit value + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @return PCNT high limit value + */ +static inline int pcnt_ll_get_high_limit_value(pcnt_dev_t *hw, uint32_t unit) +{ + typeof(hw->conf_unit[unit].conf2) conf2_reg = hw->conf_unit[unit].conf2; + int16_t value = conf2_reg.cnt_h_lim; + return value; +} + +/** + * @brief Get PCNT low limit value + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @return PCNT high limit value + */ +static inline int pcnt_ll_get_low_limit_value(pcnt_dev_t *hw, uint32_t unit) +{ + typeof(hw->conf_unit[unit].conf2) conf2_reg = hw->conf_unit[unit].conf2; + int16_t value = conf2_reg.cnt_l_lim; + return value; +} + +/** + * @brief Get PCNT threshold value + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @param thres Threshold ID + * @return PCNT threshold value + */ +static inline int pcnt_ll_get_thres_value(pcnt_dev_t *hw, uint32_t unit, uint32_t thres) +{ + int16_t value; + typeof(hw->conf_unit[unit].conf1) conf1_reg = hw->conf_unit[unit].conf1; + if (thres == 0) { + value = conf1_reg.cnt_thres0; + } else { + value = conf1_reg.cnt_thres1; + } + return value; +} + +/** + * @brief Get PCNT unit runtime status + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @return PCNT unit runtime status + */ +static inline uint32_t pcnt_ll_get_unit_status(pcnt_dev_t *hw, uint32_t unit) +{ + return hw->status_unit[unit].val; +} + +/** + * @brief Get PCNT count sign + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @return Count sign + */ +static inline pcnt_unit_count_sign_t pcnt_ll_get_count_sign(pcnt_dev_t *hw, uint32_t unit) +{ + return hw->status_unit[unit].val & 0x03; +} + /** * @brief Get PCNT event status * * @param hw Peripheral PCNT hardware instance address. * @param unit PCNT unit number - * @return event status word + * @return Event status word */ -static inline uint32_t pcnt_ll_get_event_status(pcnt_dev_t *hw, pcnt_unit_t unit) +static inline uint32_t pcnt_ll_get_event_status(pcnt_dev_t *hw, uint32_t unit) { - return hw->status_unit[unit].val; + return hw->status_unit[unit].val >> 2; } /** - * @brief Set PCNT filter value + * @brief Set PCNT glitch filter threshold * * @param hw Peripheral PCNT hardware instance address. * @param unit PCNT unit number * @param filter_val PCNT signal filter value, counter in APB_CLK cycles. * Any pulses lasting shorter than this will be ignored when the filter is enabled. - * @note - * filter_val is a 10-bit value, so the maximum filter_val should be limited to 1023. */ -static inline void pcnt_ll_set_filter_value(pcnt_dev_t *hw, pcnt_unit_t unit, uint16_t filter_val) +static inline void pcnt_ll_set_glitch_filter_thres(pcnt_dev_t *hw, uint32_t unit, uint32_t filter_val) { hw->conf_unit[unit].conf0.filter_thres = filter_val; } /** - * @brief Get PCNT filter value + * @brief Get PCNT glitch filter threshold * * @param hw Peripheral PCNT hardware instance address. * @param unit PCNT unit number - * @param filter_val Pointer to accept PCNT filter value. + * @return glitch filter threshold */ -static inline void pcnt_ll_get_filter_value(pcnt_dev_t *hw, pcnt_unit_t unit, uint16_t *filter_val) +static inline uint32_t pcnt_ll_get_glitch_filter_thres(pcnt_dev_t *hw, uint32_t unit) { - *filter_val = hw->conf_unit[unit].conf0.filter_thres; + return hw->conf_unit[unit].conf0.filter_thres; } /** - * @brief Enable PCNT input filter + * @brief Enable PCNT glitch filter * * @param hw Peripheral PCNT hardware instance address. * @param unit PCNT unit number + * @param enable True to enable the filter, False to disable the filter */ -static inline void pcnt_ll_filter_enable(pcnt_dev_t *hw, pcnt_unit_t unit) +static inline void pcnt_ll_enable_glitch_filter(pcnt_dev_t *hw, uint32_t unit, bool enable) { - hw->conf_unit[unit].conf0.filter_en = 1; -} - -/** - * @brief Disable PCNT input filter - * - * @param hw Peripheral PCNT hardware instance address. - * @param unit PCNT unit number - */ -static inline void pcnt_ll_filter_disable(pcnt_dev_t *hw, pcnt_unit_t unit) -{ - hw->conf_unit[unit].conf0.filter_en = 0; + hw->conf_unit[unit].conf0.filter_en = enable; } #ifdef __cplusplus diff --git a/components/hal/esp32/include/hal/rmt_ll.h b/components/hal/esp32/include/hal/rmt_ll.h index edd4f27912..dfd8199d5b 100644 --- a/components/hal/esp32/include/hal/rmt_ll.h +++ b/components/hal/esp32/include/hal/rmt_ll.h @@ -15,6 +15,7 @@ #include #include +#include "hal/misc.h" #include "soc/rmt_struct.h" #ifdef __cplusplus @@ -119,23 +120,23 @@ static inline uint32_t rmt_ll_rx_get_mem_blocks(rmt_dev_t *dev, uint32_t channel static inline void rmt_ll_tx_set_channel_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div) { - dev->conf_ch[channel].conf0.div_cnt = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->conf_ch[channel].conf0, div_cnt, div); } static inline void rmt_ll_rx_set_channel_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div) { - dev->conf_ch[channel].conf0.div_cnt = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->conf_ch[channel].conf0, div_cnt, div); } static inline uint32_t rmt_ll_tx_get_channel_clock_div(rmt_dev_t *dev, uint32_t channel) { - uint32_t div = dev->conf_ch[channel].conf0.div_cnt; + uint32_t div = HAL_FORCE_READ_U32_REG_FIELD(dev->conf_ch[channel].conf0, div_cnt); return div == 0 ? 256 : div; } static inline uint32_t rmt_ll_rx_get_channel_clock_div(rmt_dev_t *dev, uint32_t channel) { - uint32_t div = dev->conf_ch[channel].conf0.div_cnt; + uint32_t div = HAL_FORCE_READ_U32_REG_FIELD(dev->conf_ch[channel].conf0, div_cnt); return div == 0 ? 256 : div; } @@ -146,12 +147,12 @@ static inline void rmt_ll_tx_enable_pingpong(rmt_dev_t *dev, uint32_t channel, b static inline void rmt_ll_rx_set_idle_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres) { - dev->conf_ch[channel].conf0.idle_thres = thres; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->conf_ch[channel].conf0, idle_thres, thres); } static inline uint32_t rmt_ll_rx_get_idle_thres(rmt_dev_t *dev, uint32_t channel) { - return dev->conf_ch[channel].conf0.idle_thres; + return HAL_FORCE_READ_U32_REG_FIELD(dev->conf_ch[channel].conf0, idle_thres); } static inline void rmt_ll_rx_set_mem_owner(rmt_dev_t *dev, uint32_t channel, uint8_t owner) @@ -186,7 +187,7 @@ static inline void rmt_ll_rx_enable_filter(rmt_dev_t *dev, uint32_t channel, boo static inline void rmt_ll_rx_set_filter_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres) { - dev->conf_ch[channel].conf1.rx_filter_thres = thres; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->conf_ch[channel].conf1, rx_filter_thres, thres); } static inline void rmt_ll_tx_enable_idle(rmt_dev_t *dev, uint32_t channel, bool enable) @@ -324,14 +325,14 @@ static inline uint32_t rmt_ll_get_tx_thres_interrupt_status(rmt_dev_t *dev) static inline void rmt_ll_tx_set_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t high_ticks, uint32_t low_ticks) { - dev->carrier_duty_ch[channel].high = high_ticks; - dev->carrier_duty_ch[channel].low = low_ticks; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->carrier_duty_ch[channel], high, high_ticks); + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->carrier_duty_ch[channel], low, low_ticks); } static inline void rmt_ll_tx_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks) { - *high_ticks = dev->carrier_duty_ch[channel].high; - *low_ticks = dev->carrier_duty_ch[channel].low; + *high_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->carrier_duty_ch[channel], high); + *low_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->carrier_duty_ch[channel], low); } static inline void rmt_ll_tx_enable_carrier_modulation(rmt_dev_t *dev, uint32_t channel, bool enable) diff --git a/components/hal/esp32/include/hal/rtc_io_ll.h b/components/hal/esp32/include/hal/rtc_io_ll.h index 3e5a1af8ff..f96452532e 100644 --- a/components/hal/esp32/include/hal/rtc_io_ll.h +++ b/components/hal/esp32/include/hal/rtc_io_ll.h @@ -22,6 +22,7 @@ #include #include "soc/rtc_io_periph.h" +#include "soc/rtc_io_struct.h" #include "hal/rtc_io_types.h" #include "hal/gpio_types.h" diff --git a/components/hal/esp32/include/hal/rwdt_ll.h b/components/hal/esp32/include/hal/rwdt_ll.h index c1d2d60607..e409eeaa8b 100644 --- a/components/hal/esp32/include/hal/rwdt_ll.h +++ b/components/hal/esp32/include/hal/rwdt_ll.h @@ -25,6 +25,7 @@ extern "C" { #include #include "hal/wdt_types.h" #include "soc/rtc_cntl_periph.h" +#include "soc/rtc_cntl_struct.h" #include "esp_attr.h" //Type check wdt_stage_action_t diff --git a/components/hal/esp32/include/hal/sigmadelta_ll.h b/components/hal/esp32/include/hal/sigmadelta_ll.h index 929546fe0c..9e151871d2 100644 --- a/components/hal/esp32/include/hal/sigmadelta_ll.h +++ b/components/hal/esp32/include/hal/sigmadelta_ll.h @@ -22,7 +22,9 @@ #pragma once #include +#include "hal/misc.h" #include "soc/sigmadelta_periph.h" +#include "soc/gpio_sd_struct.h" #include "hal/sigmadelta_types.h" #ifdef __cplusplus @@ -53,7 +55,7 @@ static inline void sigmadelta_ll_set_en(gpio_sd_dev_t *hw, bool en) */ static inline void sigmadelta_ll_set_duty(gpio_sd_dev_t *hw, sigmadelta_channel_t channel, int8_t duty) { - hw->channel[channel].duty = duty; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], duty, (uint32_t)duty); } /** @@ -65,7 +67,7 @@ static inline void sigmadelta_ll_set_duty(gpio_sd_dev_t *hw, sigmadelta_channel_ */ static inline void sigmadelta_ll_set_prescale(gpio_sd_dev_t *hw, sigmadelta_channel_t channel, uint8_t prescale) { - hw->channel[channel].prescale = prescale; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], prescale, prescale); } #ifdef __cplusplus diff --git a/components/hal/esp32/include/hal/spi_flash_ll.h b/components/hal/esp32/include/hal/spi_flash_ll.h index 7c0862eddc..3f18774a29 100644 --- a/components/hal/esp32/include/hal/spi_flash_ll.h +++ b/components/hal/esp32/include/hal/spi_flash_ll.h @@ -24,11 +24,13 @@ #include #include "soc/spi_periph.h" +#include "soc/spi_struct.h" #include "hal/spi_types.h" #include "hal/spi_flash_types.h" #include // For MIN/MAX #include #include +#include "hal/misc.h" #ifdef __cplusplus extern "C" { @@ -393,7 +395,7 @@ static inline void spi_flash_ll_set_address(spi_dev_t *dev, uint32_t addr) static inline void spi_flash_ll_set_dummy(spi_dev_t *dev, uint32_t dummy_n) { dev->user.usr_dummy = dummy_n ? 1 : 0; - dev->user1.usr_dummy_cyclelen = dummy_n - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user1, usr_dummy_cyclelen, dummy_n - 1); } static inline void spi_flash_ll_set_hold(spi_dev_t *dev, uint32_t hold_n) diff --git a/components/hal/esp32/include/hal/spi_ll.h b/components/hal/esp32/include/hal/spi_ll.h index 426d720843..89b4dedae3 100644 --- a/components/hal/esp32/include/hal/spi_ll.h +++ b/components/hal/esp32/include/hal/spi_ll.h @@ -27,7 +27,10 @@ #include "esp_types.h" #include "esp32/rom/lldesc.h" #include "soc/spi_periph.h" +#include "soc/spi_struct.h" #include "hal/misc.h" +#include "hal/spi_types.h" +#include "hal/assert.h" #ifdef __cplusplus extern "C" { @@ -37,6 +40,9 @@ extern "C" { #define SPI_LL_DMA_FIFO_RST_MASK (SPI_AHBM_RST | SPI_AHBM_FIFO_RST) /// Interrupt not used. Don't use in app. #define SPI_LL_UNUSED_INT_MASK (SPI_INT_EN | SPI_SLV_WR_STA_DONE | SPI_SLV_RD_STA_DONE | SPI_SLV_WR_BUF_DONE | SPI_SLV_RD_BUF_DONE) +/// These 2 masks together will set SPI transaction to one line mode +#define SPI_LL_ONE_LINE_CTRL_MASK (SPI_FREAD_DUAL | SPI_FREAD_QUAD | SPI_FREAD_DIO | SPI_FREAD_QIO) +#define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_DUAL | SPI_FWRITE_QUAD | SPI_FWRITE_DIO | SPI_FWRITE_QIO) /// Swap the bit order to its correct place to send #define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len)) /// This is the expected clock frequency @@ -53,16 +59,6 @@ typedef uint32_t spi_ll_clock_val_t; //On ESP32-S2 and earlier chips, DMA registers are part of SPI registers. So set the registers of SPI peripheral to control DMA. typedef spi_dev_t spi_dma_dev_t; -/** IO modes supported by the master. */ -typedef enum { - SPI_LL_IO_MODE_NORMAL = 0, ///< 1-bit mode for all phases - SPI_LL_IO_MODE_DIO, ///< 2-bit mode for address and data phases, 1-bit mode for command phase - SPI_LL_IO_MODE_DUAL, ///< 2-bit mode for data phases only, 1-bit mode for command and address phases - SPI_LL_IO_MODE_QIO, ///< 4-bit mode for address and data phases, 1-bit mode for command phase - SPI_LL_IO_MODE_QUAD, ///< 4-bit mode for data phases only, 1-bit mode for command and address phases -} spi_ll_io_mode_t; - - /*------------------------------------------------------------------------------ * Control *----------------------------------------------------------------------------*/ @@ -449,37 +445,50 @@ static inline void spi_ll_set_sio_mode(spi_dev_t *hw, int sio_mode) } /** - * Configure the io mode for the master to work at. + * Configure the SPI transaction line mode for the master to use. * - * @param hw Beginning address of the peripheral registers. - * @param io_mode IO mode to work at, see ``spi_ll_io_mode_t``. + * @param hw Beginning address of the peripheral registers. + * @param line_mode SPI transaction line mode to use, see ``spi_line_mode_t``. */ -static inline void spi_ll_master_set_io_mode(spi_dev_t *hw, spi_ll_io_mode_t io_mode) +static inline void spi_ll_master_set_line_mode(spi_dev_t *hw, spi_line_mode_t line_mode) { - hw->ctrl.val &= ~(SPI_FREAD_DUAL | SPI_FREAD_QUAD | SPI_FREAD_DIO | SPI_FREAD_QIO); - hw->user.val &= ~(SPI_FWRITE_DUAL | SPI_FWRITE_QUAD | SPI_FWRITE_DIO | SPI_FWRITE_QIO); - switch (io_mode) { - case SPI_LL_IO_MODE_DIO: - hw->ctrl.fread_dio = 1; - hw->user.fwrite_dio = 1; + hw->ctrl.val &= ~SPI_LL_ONE_LINE_CTRL_MASK; + hw->user.val &= ~SPI_LL_ONE_LINE_USER_MASK; + if (line_mode.cmd_lines > 1) { + HAL_ASSERT(false); + } + switch (line_mode.data_lines) { + case 2: + if (line_mode.addr_lines == 1) { + // 1-line-cmd + 1-line-addr + 2-line-data + hw->ctrl.fread_dual = 1; + hw->user.fwrite_dual = 1; + } else if (line_mode.addr_lines == 2) { + // 1-line-cmd + 2-line-addr + 2-line-data + hw->ctrl.fread_dio = 1; + hw->user.fwrite_dio = 1; + } else { + HAL_ASSERT(false); + } + hw->ctrl.fastrd_mode = 1; break; - case SPI_LL_IO_MODE_DUAL: - hw->ctrl.fread_dual = 1; - hw->user.fwrite_dual = 1; - break; - case SPI_LL_IO_MODE_QIO: - hw->ctrl.fread_qio = 1; - hw->user.fwrite_qio = 1; - break; - case SPI_LL_IO_MODE_QUAD: - hw->ctrl.fread_quad = 1; - hw->user.fwrite_quad = 1; + case 4: + if (line_mode.addr_lines == 1) { + // 1-line-cmd + 1-line-addr + 4-line-data + hw->ctrl.fread_quad = 1; + hw->user.fwrite_quad = 1; + } else if (line_mode.addr_lines == 4) { + // 1-line-cmd + 4-line-addr + 4-line-data + hw->ctrl.fread_qio = 1; + hw->user.fwrite_qio = 1; + } else { + HAL_ASSERT(false); + } + hw->ctrl.fastrd_mode = 1; break; default: + // 1-line-cmd + 1-line-addr + 1-line-data break; - }; - if (io_mode != SPI_LL_IO_MODE_NORMAL) { - hw->ctrl.fastrd_mode = 1; } } @@ -502,7 +511,8 @@ static inline void spi_ll_master_select_cs(spi_dev_t *hw, int cs_id) * @param hw Beginning address of the peripheral registers. * @param keep_active if 0 don't keep CS activated, else keep CS activated */ -static inline void spi_ll_master_keep_cs(spi_dev_t *hw, int keep_active) { +static inline void spi_ll_master_keep_cs(spi_dev_t *hw, int keep_active) +{ hw->pin.cs_keep_active = (keep_active != 0) ? 1 : 0; } @@ -691,7 +701,7 @@ static inline void spi_ll_set_miso_delay(spi_dev_t *hw, int delay_mode, int dela static inline void spi_ll_set_dummy(spi_dev_t *hw, int dummy_n) { hw->user.usr_dummy = dummy_n ? 1 : 0; - hw->user1.usr_dummy_cyclelen = dummy_n - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user1, usr_dummy_cyclelen, dummy_n - 1); } /** @@ -849,13 +859,13 @@ static inline void spi_ll_set_command(spi_dev_t *hw, uint16_t cmd, int cmdlen, b { if (lsbfirst) { // The output command start from bit0 to bit 15, kept as is. - hw->user2.usr_command_value = cmd; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user2, usr_command_value, cmd); } else { /* Output command will be sent from bit 7 to 0 of command_value, and * then bit 15 to 8 of the same register field. Shift and swap to send * more straightly. */ - hw->user2.usr_command_value = HAL_SPI_SWAP_DATA_TX(cmd, cmdlen); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user2, usr_command_value, HAL_SPI_SWAP_DATA_TX(cmd, cmdlen)); } } diff --git a/components/hal/esp32/include/hal/timer_ll.h b/components/hal/esp32/include/hal/timer_ll.h index f9efc82d22..35ce7d1025 100644 --- a/components/hal/esp32/include/hal/timer_ll.h +++ b/components/hal/esp32/include/hal/timer_ll.h @@ -22,9 +22,11 @@ extern "C" { #endif #include +#include "hal/misc.h" #include "hal/assert.h" #include "hal/timer_types.h" #include "soc/timer_periph.h" +#include "soc/timer_group_struct.h" _Static_assert(TIMER_INTR_T0 == TIMG_T0_INT_CLR, "Add mapping to LL interrupt handling, since it's no longer naturally compatible with the timer_intr_t"); _Static_assert(TIMER_INTR_T1 == TIMG_T1_INT_CLR, "Add mapping to LL interrupt handling, since it's no longer naturally compatible with the timer_intr_t"); @@ -50,7 +52,7 @@ static inline void timer_ll_set_divider(timg_dev_t *hw, timer_idx_t timer_num, u } int timer_en = hw->hw_timer[timer_num].config.enable; hw->hw_timer[timer_num].config.enable = 0; - hw->hw_timer[timer_num].config.divider = divider; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->hw_timer[timer_num].config, divider, divider); hw->hw_timer[timer_num].config.enable = timer_en; } @@ -65,7 +67,7 @@ static inline void timer_ll_set_divider(timg_dev_t *hw, timer_idx_t timer_num, u */ static inline void timer_ll_get_divider(timg_dev_t *hw, timer_idx_t timer_num, uint32_t *divider) { - uint32_t d = hw->hw_timer[timer_num].config.divider; + uint32_t d = HAL_FORCE_READ_U32_REG_FIELD(hw->hw_timer[timer_num].config, divider); if (d == 0) { d = 65536; } else if (d == 1) { diff --git a/components/hal/esp32/include/hal/touch_sensor_ll.h b/components/hal/esp32/include/hal/touch_sensor_ll.h index 5642d28cc2..07f17d4b65 100644 --- a/components/hal/esp32/include/hal/touch_sensor_ll.h +++ b/components/hal/esp32/include/hal/touch_sensor_ll.h @@ -24,7 +24,11 @@ #include #include +#include "hal/misc.h" #include "soc/touch_sensor_periph.h" +#include "soc/sens_struct.h" +#include "soc/rtc_io_struct.h" +#include "soc/rtc_cntl_struct.h" #include "hal/touch_sensor_types.h" @@ -60,9 +64,9 @@ static inline touch_pad_t touch_ll_num_wrap(touch_pad_t touch_num) static inline void touch_ll_set_meas_time(uint16_t meas_time) { //touch sensor measure time= meas_cycle / 8Mhz - SENS.sar_touch_ctrl1.touch_meas_delay = meas_time; + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_touch_ctrl1, touch_meas_delay, meas_time); //the waiting cycles (in 8MHz) between TOUCH_START and TOUCH_XPD - SENS.sar_touch_ctrl1.touch_xpd_wait = SOC_TOUCH_PAD_MEASURE_WAIT_MAX; + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_touch_ctrl1, touch_xpd_wait, SOC_TOUCH_PAD_MEASURE_WAIT_MAX); } /** @@ -72,7 +76,7 @@ static inline void touch_ll_set_meas_time(uint16_t meas_time) */ static inline void touch_ll_get_meas_time(uint16_t *meas_time) { - *meas_time = SENS.sar_touch_ctrl1.touch_meas_delay; + *meas_time = HAL_FORCE_READ_U32_REG_FIELD(SENS.sar_touch_ctrl1, touch_meas_delay); } /** @@ -86,7 +90,7 @@ static inline void touch_ll_get_meas_time(uint16_t *meas_time) static inline void touch_ll_set_sleep_time(uint16_t sleep_time) { //touch sensor sleep cycle Time = sleep_cycle / RTC_SLOW_CLK( can be 150k or 32k depending on the options) - SENS.sar_touch_ctrl2.touch_sleep_cycles = sleep_time; + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_touch_ctrl2, touch_sleep_cycles, sleep_time); } /** @@ -96,7 +100,7 @@ static inline void touch_ll_set_sleep_time(uint16_t sleep_time) */ static inline void touch_ll_get_sleep_time(uint16_t *sleep_time) { - *sleep_time = SENS.sar_touch_ctrl2.touch_sleep_cycles; + *sleep_time = HAL_FORCE_READ_U32_REG_FIELD(SENS.sar_touch_ctrl2, touch_sleep_cycles); } /** @@ -291,9 +295,9 @@ static inline void touch_ll_set_threshold(touch_pad_t touch_num, uint16_t thresh { touch_pad_t tp_wrap = touch_ll_num_wrap(touch_num); if (tp_wrap & 0x1) { - SENS.touch_thresh[tp_wrap / 2].l_thresh = threshold; + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.touch_thresh[tp_wrap / 2], l_thresh, threshold); } else { - SENS.touch_thresh[tp_wrap / 2].h_thresh = threshold; + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.touch_thresh[tp_wrap / 2], h_thresh, threshold); } } @@ -308,8 +312,8 @@ static inline void touch_ll_get_threshold(touch_pad_t touch_num, uint16_t *thres touch_pad_t tp_wrap = touch_ll_num_wrap(touch_num); if (threshold) { *threshold = (tp_wrap & 0x1 ) ? - SENS.touch_thresh[tp_wrap / 2].l_thresh : - SENS.touch_thresh[tp_wrap / 2].h_thresh; + HAL_FORCE_READ_U32_REG_FIELD(SENS.touch_thresh[tp_wrap / 2], l_thresh) : + HAL_FORCE_READ_U32_REG_FIELD(SENS.touch_thresh[tp_wrap / 2], h_thresh); } } @@ -489,7 +493,8 @@ static inline void touch_ll_intr_clear(void) static inline uint32_t touch_ll_read_raw_data(touch_pad_t touch_num) { touch_pad_t tp_wrap = touch_ll_num_wrap(touch_num); - return ((tp_wrap & 0x1) ? SENS.touch_meas[tp_wrap / 2].l_val : SENS.touch_meas[tp_wrap / 2].h_val); + return ((tp_wrap & 0x1) ? HAL_FORCE_READ_U32_REG_FIELD(SENS.touch_meas[tp_wrap / 2], l_val) : + HAL_FORCE_READ_U32_REG_FIELD(SENS.touch_meas[tp_wrap / 2], h_val)); } /** diff --git a/components/hal/esp32/include/hal/twai_ll.h b/components/hal/esp32/include/hal/twai_ll.h index 0a37c61631..72949aa9cf 100644 --- a/components/hal/esp32/include/hal/twai_ll.h +++ b/components/hal/esp32/include/hal/twai_ll.h @@ -32,6 +32,7 @@ extern "C" { #include "hal/misc.h" #include "hal/twai_types.h" #include "soc/twai_periph.h" +#include "soc/twai_struct.h" /* ------------------------- Defines and Typedefs --------------------------- */ @@ -491,7 +492,7 @@ static inline void twai_ll_parse_err_code_cap(twai_dev_t *hw, */ static inline void twai_ll_set_err_warn_lim(twai_dev_t *hw, uint32_t ewl) { - hw->error_warning_limit_reg.ewl = ewl; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->error_warning_limit_reg, ewl, ewl); } /** @@ -531,7 +532,7 @@ static inline uint32_t twai_ll_get_rec(twai_dev_t *hw) */ static inline void twai_ll_set_rec(twai_dev_t *hw, uint32_t rec) { - hw->rx_error_counter_reg.rxerr = rec; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_error_counter_reg, rxerr, rec); } /* ------------------------ TX Error Count Register ------------------------- */ @@ -559,7 +560,7 @@ static inline uint32_t twai_ll_get_tec(twai_dev_t *hw) */ static inline void twai_ll_set_tec(twai_dev_t *hw, uint32_t tec) { - hw->tx_error_counter_reg.txerr = tec; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_error_counter_reg, txerr, tec); } /* ---------------------- Acceptance Filter Registers ----------------------- */ @@ -578,8 +579,8 @@ static inline void twai_ll_set_acc_filter(twai_dev_t* hw, uint32_t code, uint32_ uint32_t code_swapped = HAL_SWAP32(code); uint32_t mask_swapped = HAL_SWAP32(mask); for (int i = 0; i < 4; i++) { - hw->acceptance_filter.acr[i].byte = ((code_swapped >> (i * 8)) & 0xFF); - hw->acceptance_filter.amr[i].byte = ((mask_swapped >> (i * 8)) & 0xFF); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->acceptance_filter.acr[i], byte, ((code_swapped >> (i * 8)) & 0xFF)); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->acceptance_filter.amr[i], byte, ((mask_swapped >> (i * 8)) & 0xFF)); } hw->mode_reg.afm = single_filter; } @@ -614,7 +615,7 @@ static inline void twai_ll_get_rx_buffer(twai_dev_t *hw, twai_ll_frame_buffer_t { //Copy RX buffer registers into frame for (int i = 0; i < 13; i++) { - rx_frame->bytes[i] = hw->tx_rx_buffer[i].byte; + rx_frame->bytes[i] = HAL_FORCE_READ_U32_REG_FIELD(hw->tx_rx_buffer[i], byte); } } @@ -794,8 +795,8 @@ static inline void twai_ll_save_reg(twai_dev_t *hw, twai_ll_reg_save_t *reg_save reg_save->bus_timing_1_reg = (uint8_t) hw->bus_timing_1_reg.val; reg_save->error_warning_limit_reg = (uint8_t) hw->error_warning_limit_reg.val; for (int i = 0; i < 4; i++) { - reg_save->acr_reg[i] = hw->acceptance_filter.acr[i].byte; - reg_save->amr_reg[i] = hw->acceptance_filter.amr[i].byte; + reg_save->acr_reg[i] = HAL_FORCE_READ_U32_REG_FIELD(hw->acceptance_filter.acr[i], byte); + reg_save->amr_reg[i] = HAL_FORCE_READ_U32_REG_FIELD(hw->acceptance_filter.amr[i], byte); } reg_save->rx_error_counter_reg = (uint8_t) hw->rx_error_counter_reg.val; reg_save->tx_error_counter_reg = (uint8_t) hw->tx_error_counter_reg.val; @@ -821,8 +822,8 @@ static inline void twai_ll_restore_reg(twai_dev_t *hw, twai_ll_reg_save_t *reg_s hw->bus_timing_1_reg.val = reg_save->bus_timing_1_reg; hw->error_warning_limit_reg.val = reg_save->error_warning_limit_reg; for (int i = 0; i < 4; i++) { - hw->acceptance_filter.acr[i].byte = reg_save->acr_reg[i]; - hw->acceptance_filter.amr[i].byte = reg_save->amr_reg[i]; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->acceptance_filter.acr[i], byte, reg_save->acr_reg[i]); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->acceptance_filter.amr[i], byte, reg_save->amr_reg[i]); } hw->rx_error_counter_reg.val = reg_save->rx_error_counter_reg; hw->tx_error_counter_reg.val = reg_save->tx_error_counter_reg; diff --git a/components/hal/esp32/include/hal/uart_ll.h b/components/hal/esp32/include/hal/uart_ll.h index ed52f969bd..de8fc640ff 100644 --- a/components/hal/esp32/include/hal/uart_ll.h +++ b/components/hal/esp32/include/hal/uart_ll.h @@ -17,8 +17,11 @@ #pragma once + +#include "hal/misc.h" #include "esp_attr.h" #include "soc/uart_periph.h" +#include "soc/uart_struct.h" #include "hal/uart_types.h" #ifdef __cplusplus @@ -249,7 +252,7 @@ FORCE_INLINE_ATTR void uart_ll_rxfifo_rst(uart_dev_t *hw) //Get the UART APB fifo addr uint32_t fifo_addr = (hw == &UART0) ? UART_FIFO_REG(0) : (hw == &UART1) ? UART_FIFO_REG(1) : UART_FIFO_REG(2); do { - fifo_cnt = hw->status.rxfifo_cnt; + fifo_cnt = HAL_FORCE_READ_U32_REG_FIELD(hw->status, rxfifo_cnt); rxmem_sta.val = hw->mem_rx_status.val; if(fifo_cnt != 0 || (rxmem_sta.rd_addr != rxmem_sta.wr_addr)) { READ_PERI_REG(fifo_addr); @@ -287,7 +290,7 @@ FORCE_INLINE_ATTR void uart_ll_txfifo_rst(uart_dev_t *hw) */ FORCE_INLINE_ATTR uint32_t uart_ll_get_rxfifo_len(uart_dev_t *hw) { - uint32_t fifo_cnt = hw->status.rxfifo_cnt; + uint32_t fifo_cnt = HAL_FORCE_READ_U32_REG_FIELD(hw->status, rxfifo_cnt); typeof(hw->mem_rx_status) rx_status = hw->mem_rx_status; uint32_t len = 0; @@ -313,7 +316,7 @@ FORCE_INLINE_ATTR uint32_t uart_ll_get_rxfifo_len(uart_dev_t *hw) */ FORCE_INLINE_ATTR uint32_t uart_ll_get_txfifo_len(uart_dev_t *hw) { - return UART_LL_FIFO_DEF_LEN - hw->status.txfifo_cnt; + return UART_LL_FIFO_DEF_LEN - HAL_FORCE_READ_U32_REG_FIELD(hw->status, txfifo_cnt); } /** @@ -453,7 +456,7 @@ FORCE_INLINE_ATTR void uart_ll_set_tx_idle_num(uart_dev_t *hw, uint32_t idle_num FORCE_INLINE_ATTR void uart_ll_tx_break(uart_dev_t *hw, uint32_t break_num) { if(break_num > 0) { - hw->idle_conf.tx_brk_num = break_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->idle_conf, tx_brk_num, break_num); hw->conf0.txd_brk = 1; } else { hw->conf0.txd_brk = 0; @@ -518,10 +521,10 @@ FORCE_INLINE_ATTR void uart_ll_set_sw_flow_ctrl(uart_dev_t *hw, uart_sw_flowctrl if(sw_flow_ctrl_en) { hw->flow_conf.xonoff_del = 1; hw->flow_conf.sw_flow_con_en = 1; - hw->swfc_conf.xon_threshold = flow_ctrl->xon_thrd; - hw->swfc_conf.xoff_threshold = flow_ctrl->xoff_thrd; - hw->swfc_conf.xon_char = flow_ctrl->xon_char; - hw->swfc_conf.xoff_char = flow_ctrl->xoff_char; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->swfc_conf, xon_threshold, flow_ctrl->xon_thrd); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->swfc_conf, xoff_threshold, flow_ctrl->xoff_thrd); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->swfc_conf, xon_char, flow_ctrl->xon_char); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->swfc_conf, xoff_char, flow_ctrl->xoff_char); } else { hw->flow_conf.sw_flow_con_en = 0; hw->flow_conf.xonoff_del = 0; @@ -543,8 +546,8 @@ FORCE_INLINE_ATTR void uart_ll_set_sw_flow_ctrl(uart_dev_t *hw, uart_sw_flowctrl */ FORCE_INLINE_ATTR void uart_ll_set_at_cmd_char(uart_dev_t *hw, uart_at_cmd_t *cmd_char) { - hw->at_cmd_char.data = cmd_char->cmd_char; - hw->at_cmd_char.char_num = cmd_char->char_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_char, data, cmd_char->cmd_char); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_char, char_num, cmd_char->char_num); hw->at_cmd_postcnt.post_idle_num = cmd_char->post_idle; hw->at_cmd_precnt.pre_idle_num = cmd_char->pre_idle; hw->at_cmd_gaptout.rx_gap_tout = cmd_char->gap_tout; @@ -729,8 +732,8 @@ FORCE_INLINE_ATTR void uart_ll_set_mode(uart_dev_t *hw, uart_mode_t mode) */ FORCE_INLINE_ATTR void uart_ll_get_at_cmd_char(uart_dev_t *hw, uint8_t *cmd_char, uint8_t *char_num) { - *cmd_char = hw->at_cmd_char.data; - *char_num = hw->at_cmd_char.char_num; + *cmd_char = HAL_FORCE_READ_U32_REG_FIELD(hw->at_cmd_char, data); + *char_num = HAL_FORCE_READ_U32_REG_FIELD(hw->at_cmd_char, char_num); } /** diff --git a/components/hal/esp32c3/include/hal/adc_ll.h b/components/hal/esp32c3/include/hal/adc_ll.h index a2fd21f2b5..49ff4a23f4 100644 --- a/components/hal/esp32c3/include/hal/adc_ll.h +++ b/components/hal/esp32c3/include/hal/adc_ll.h @@ -15,6 +15,7 @@ #include #include +#include "hal/misc.h" #include "regi2c_ctrl.h" #include "esp_attr.h" @@ -94,11 +95,11 @@ typedef enum { static inline void adc_ll_digi_set_fsm_time(uint32_t rst_wait, uint32_t start_wait, uint32_t standby_wait) { // Internal FSM reset wait time - APB_SARADC.fsm_wait.rstb_wait = rst_wait; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.fsm_wait, rstb_wait, rst_wait); // Internal FSM start wait time - APB_SARADC.fsm_wait.xpd_wait = start_wait; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.fsm_wait, xpd_wait, start_wait); // Internal FSM standby wait time - APB_SARADC.fsm_wait.standby_wait = standby_wait; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.fsm_wait, standby_wait, standby_wait); } /** @@ -124,7 +125,7 @@ static inline void adc_ll_set_sample_cycle(uint32_t sample_cycle) static inline void adc_ll_digi_set_clk_div(uint32_t div) { /* ADC clock devided from digital controller clock clk */ - APB_SARADC.ctrl.sar_clk_div = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.ctrl, sar_clk_div, div); } /** @@ -135,7 +136,7 @@ static inline void adc_ll_digi_set_clk_div(uint32_t div) */ static inline void adc_ll_digi_set_convert_limit_num(uint32_t meas_num) { - APB_SARADC.ctrl2.max_meas_num = meas_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.ctrl2, max_meas_num, meas_num); } /** @@ -267,7 +268,7 @@ static inline void adc_ll_digi_trigger_disable(void) */ static inline void adc_ll_digi_controller_clk_div(uint32_t div_num, uint32_t div_b, uint32_t div_a) { - APB_SARADC.apb_adc_clkm_conf.clkm_div_num = div_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.apb_adc_clkm_conf, clkm_div_num, div_num); APB_SARADC.apb_adc_clkm_conf.clkm_div_b = div_b; APB_SARADC.apb_adc_clkm_conf.clkm_div_a = div_a; } @@ -404,7 +405,7 @@ static inline void adc_ll_digi_monitor_disable(adc_digi_monitor_idx_t idx) */ static inline void adc_ll_digi_dma_set_eof_num(uint32_t num) { - APB_SARADC.dma_conf.apb_adc_eof_num = num; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.dma_conf, apb_adc_eof_num, num); } /** diff --git a/components/hal/esp32c3/include/hal/aes_ll.h b/components/hal/esp32c3/include/hal/aes_ll.h index 0eb7fabc64..e18c44e58e 100644 --- a/components/hal/esp32c3/include/hal/aes_ll.h +++ b/components/hal/esp32c3/include/hal/aes_ll.h @@ -1,4 +1,4 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// Copyright 2020-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. @@ -15,6 +15,7 @@ #pragma once #include +#include #include "soc/hwcrypto_reg.h" #include "hal/aes_types.h" @@ -39,16 +40,17 @@ typedef enum { * @param key Key to be written to the AES hardware * @param key_word_len Number of words in the key * - * @return volatile number of bytes written to hardware, used for fault injection check + * @return Number of bytes written to hardware, used for fault injection check */ static inline uint8_t aes_ll_write_key(const uint8_t *key, size_t key_word_len) { /* This variable is used for fault injection checks, so marked volatile to avoid optimisation */ volatile uint8_t key_in_hardware = 0; - uint32_t *key_words = (uint32_t *)key; - + /* Memcpy to avoid potential unaligned access */ + uint32_t key_word; for (int i = 0; i < key_word_len; i++) { - REG_WRITE(AES_KEY_BASE + i * 4, *(key_words + i)); + memcpy(&key_word, key + 4 * i, 4); + REG_WRITE(AES_KEY_BASE + i * 4, key_word); key_in_hardware += 4; } return key_in_hardware; @@ -76,22 +78,12 @@ static inline void aes_ll_set_mode(int mode, uint8_t key_bytes) */ static inline void aes_ll_write_block(const void *input) { - const uint32_t *input_words = (const uint32_t *)input; - uint32_t i0, i1, i2, i3; + uint32_t input_word; - /* Storing i0,i1,i2,i3 in registers, not in an array - helps a lot with optimisations at -Os level */ - i0 = input_words[0]; - REG_WRITE(AES_TEXT_IN_BASE, i0); - - i1 = input_words[1]; - REG_WRITE(AES_TEXT_IN_BASE + 4, i1); - - i2 = input_words[2]; - REG_WRITE(AES_TEXT_IN_BASE + 8, i2); - - i3 = input_words[3]; - REG_WRITE(AES_TEXT_IN_BASE + 12, i3); + for (int i = 0; i < AES_BLOCK_WORDS; i++) { + memcpy(&input_word, (uint8_t*)input + 4 * i, 4); + REG_WRITE(AES_TEXT_IN_BASE + i * 4, input_word); + } } /** @@ -101,11 +93,13 @@ static inline void aes_ll_write_block(const void *input) */ static inline void aes_ll_read_block(void *output) { - uint32_t *output_words = (uint32_t *)output; + uint32_t output_word; const size_t REG_WIDTH = sizeof(uint32_t); for (size_t i = 0; i < AES_BLOCK_WORDS; i++) { - output_words[i] = REG_READ(AES_TEXT_OUT_BASE + (i * REG_WIDTH)); + output_word = REG_READ(AES_TEXT_OUT_BASE + (i * REG_WIDTH)); + /* Memcpy to avoid potential unaligned access */ + memcpy( (uint8_t*)output + i * 4, &output_word, sizeof(output_word)); } } @@ -179,11 +173,13 @@ static inline void aes_ll_set_num_blocks(size_t num_blocks) */ static inline void aes_ll_set_iv(const uint8_t *iv) { - uint32_t *iv_words = (uint32_t *)iv; uint32_t *reg_addr_buf = (uint32_t *)(AES_IV_BASE); + uint32_t iv_word; for (int i = 0; i < IV_WORDS; i++ ) { - REG_WRITE(®_addr_buf[i], iv_words[i]); + /* Memcpy to avoid potential unaligned access */ + memcpy(&iv_word, iv + 4 * i, sizeof(iv_word)); + REG_WRITE(®_addr_buf[i], iv_word); } } @@ -192,11 +188,13 @@ static inline void aes_ll_set_iv(const uint8_t *iv) */ static inline void aes_ll_read_iv(uint8_t *iv) { - uint32_t *iv_words = (uint32_t *)iv; + uint32_t iv_word; const size_t REG_WIDTH = sizeof(uint32_t); for (size_t i = 0; i < IV_WORDS; i++) { - iv_words[i] = REG_READ(AES_IV_BASE + (i * REG_WIDTH)); + iv_word = REG_READ(AES_IV_BASE + (i * REG_WIDTH)); + /* Memcpy to avoid potential unaligned access */ + memcpy(iv + i * 4, &iv_word, sizeof(iv_word)); } } diff --git a/components/hal/esp32c3/include/hal/cpu_ll.h b/components/hal/esp32c3/include/hal/cpu_ll.h index 5c9e56dfc9..fe0f11d434 100644 --- a/components/hal/esp32c3/include/hal/cpu_ll.h +++ b/components/hal/esp32c3/include/hal/cpu_ll.h @@ -28,6 +28,11 @@ #define CSR_PCMR_MACHINE 0x7e1 #define CSR_PCCR_MACHINE 0x7e2 +/*fast gpio*/ +#define CSR_GPIO_OEN_USER 0x803 +#define CSR_GPIO_IN_USER 0x804 +#define CSR_GPIO_OUT_USER 0x805 + #ifdef __cplusplus extern "C" { #endif @@ -137,7 +142,7 @@ static inline void cpu_ll_clear_watchpoint(int id) FORCE_INLINE_ATTR bool cpu_ll_is_debugger_attached(void) { - return REG_GET_BIT(ASSIST_DEBUG_C0RE_0_DEBUG_MODE_REG, ASSIST_DEBUG_CORE_0_DEBUG_MODULE_ACTIVE); + return REG_GET_BIT(ASSIST_DEBUG_CORE_0_DEBUG_MODE_REG, ASSIST_DEBUG_CORE_0_DEBUG_MODULE_ACTIVE); } static inline void cpu_ll_break(void) @@ -163,6 +168,34 @@ static inline void cpu_ll_waiti(void) asm volatile ("wfi\n"); } +static inline void cpu_ll_enable_dedic_gpio_output(uint32_t mask) +{ + RV_WRITE_CSR(CSR_GPIO_OEN_USER, mask); +} + +static inline void cpu_ll_write_dedic_gpio_all(uint32_t value) +{ + RV_WRITE_CSR(CSR_GPIO_OUT_USER, value); +} + +static inline uint32_t cpu_ll_read_dedic_gpio_in(void) +{ + uint32_t value = RV_READ_CSR(CSR_GPIO_IN_USER); + return value; +} + +static inline uint32_t cpu_ll_read_dedic_gpio_out(void) +{ + uint32_t value = RV_READ_CSR(CSR_GPIO_OUT_USER); + return value; +} + +static inline void cpu_ll_write_dedic_gpio_mask(uint32_t mask, uint32_t value) +{ + RV_SET_CSR(CSR_GPIO_OUT_USER, mask & value); + RV_CLEAR_CSR(CSR_GPIO_OUT_USER, mask & ~(value)); +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32c3/include/hal/gpio_ll.h b/components/hal/esp32c3/include/hal/gpio_ll.h index 6ba4d601b9..6214bc06e3 100644 --- a/components/hal/esp32c3/include/hal/gpio_ll.h +++ b/components/hal/esp32c3/include/hal/gpio_ll.h @@ -24,6 +24,7 @@ #include "soc/soc.h" #include "soc/gpio_periph.h" +#include "soc/gpio_struct.h" #include "soc/rtc_cntl_reg.h" #include "hal/gpio_types.h" #include "stdlib.h" @@ -334,6 +335,7 @@ static inline void gpio_ll_get_drive_capability(gpio_dev_t *hw, gpio_num_t gpio_ */ static inline void gpio_ll_deep_sleep_hold_en(gpio_dev_t *hw) { + CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD); SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_AUTOHOLD_EN_M); } diff --git a/components/hal/esp32c3/include/hal/gpspi_flash_ll.h b/components/hal/esp32c3/include/hal/gpspi_flash_ll.h index 9f7f8e54a1..212e03a06d 100644 --- a/components/hal/esp32c3/include/hal/gpspi_flash_ll.h +++ b/components/hal/esp32c3/include/hal/gpspi_flash_ll.h @@ -24,11 +24,13 @@ #include #include "soc/spi_periph.h" +#include "soc/spi_struct.h" #include "hal/spi_types.h" #include "hal/spi_flash_types.h" #include // For MIN/MAX #include #include +#include "hal/misc.h" #ifdef __cplusplus extern "C" { @@ -363,7 +365,7 @@ static inline void gpspi_flash_ll_set_address(spi_dev_t *dev, uint32_t addr) static inline void gpspi_flash_ll_set_dummy(spi_dev_t *dev, uint32_t dummy_n) { dev->user.usr_dummy = dummy_n ? 1 : 0; - dev->user1.usr_dummy_cyclelen = dummy_n - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user1, usr_dummy_cyclelen, dummy_n - 1); } /** diff --git a/components/hal/esp32c3/include/hal/i2c_ll.h b/components/hal/esp32c3/include/hal/i2c_ll.h index 85c946c23b..31743005b6 100644 --- a/components/hal/esp32c3/include/hal/i2c_ll.h +++ b/components/hal/esp32c3/include/hal/i2c_ll.h @@ -15,8 +15,11 @@ // The LL layer for I2C register operations #pragma once + +#include "hal/misc.h" #include "soc/i2c_periph.h" #include "soc/soc_caps.h" +#include "soc/i2c_struct.h" #include "hal/i2c_types.h" #include "soc/rtc_cntl_reg.h" #include "esp_rom_sys.h" @@ -154,7 +157,7 @@ static inline void i2c_ll_update(i2c_dev_t *hw) */ static inline void i2c_ll_set_bus_timing(i2c_dev_t *hw, i2c_clk_cal_t *bus_cfg) { - hw->clk_conf.sclk_div_num = bus_cfg->clkm_div - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clk_conf, sclk_div_num, bus_cfg->clkm_div - 1); //scl period hw->scl_low_period.period = bus_cfg->scl_low - 1; hw->scl_high_period.period = bus_cfg->scl_high; @@ -576,7 +579,7 @@ static inline void i2c_ll_get_scl_timing(i2c_dev_t *hw, int *high_period, int *l static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len) { for (int i = 0; i< len; i++) { - hw->fifo_data.data = ptr[i]; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->fifo_data, data, ptr[i]); } } @@ -592,7 +595,7 @@ static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len) static inline void i2c_ll_read_rxfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len) { for(int i = 0; i < len; i++) { - ptr[i] = hw->fifo_data.data; + ptr[i] = HAL_FORCE_READ_U32_REG_FIELD(hw->fifo_data, data); } } @@ -801,9 +804,12 @@ static inline void i2c_ll_master_fsm_rst(i2c_dev_t *hw) static inline void i2c_ll_master_clr_bus(i2c_dev_t *hw) { hw->scl_sp_conf.scl_rst_slv_num = 9; - hw->scl_sp_conf.scl_rst_slv_en = 0; - hw->ctr.conf_upgate = 1; hw->scl_sp_conf.scl_rst_slv_en = 1; + hw->ctr.conf_upgate = 1; + // hardward will clear scl_rst_slv_en after sending SCL pulses, + // and we should set conf_upgate bit to synchronize register value. + while (hw->scl_sp_conf.scl_rst_slv_en); + hw->ctr.conf_upgate = 1; } /** diff --git a/components/hal/esp32c3/include/hal/i2s_ll.h b/components/hal/esp32c3/include/hal/i2s_ll.h index 4a6042cf12..670db91616 100644 --- a/components/hal/esp32c3/include/hal/i2s_ll.h +++ b/components/hal/esp32c3/include/hal/i2s_ll.h @@ -1,4 +1,4 @@ -// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD +// Copyright 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. @@ -12,507 +12,186 @@ // See the License for the specific language governing permissions and // limitations under the License. +// The LL layer for I2S register operations /******************************************************************************* * NOTICE * The hal is not public api, don't use in application code. - * See readme.md in soc/include/hal/readme.md + * See readme.md in hal/include/hal/readme.md ******************************************************************************/ -// The LL layer for ESP32-S3 I2S register operations - #pragma once - #include -#include +#include "hal/misc.h" #include "soc/i2s_periph.h" +#include "soc/i2s_struct.h" #include "hal/i2s_types.h" #ifdef __cplusplus extern "C" { #endif -// Get I2S hardware instance with giving i2s num -#define I2S_LL_GET_HW(num) (((num) == 0) ? (&I2S0) : NULL) +#define I2S_LL_GET_HW(num) (&I2S0) -#define I2S_INTR_IN_SUC_EOF BIT(9) -#define I2S_INTR_OUT_EOF BIT(12) -#define I2S_INTR_IN_DSCR_ERR BIT(13) -#define I2S_INTR_OUT_DSCR_ERR BIT(14) -#define I2S_INTR_MAX (0xFFFFFFFF) +#define I2S_LL_TDM_CH_MASK (0xffff) +#define I2S_LL_PDM_BCK_FACTOR (64) +#define I2S_LL_BASE_CLK (2*APB_CLK_FREQ) + +#define I2S_LL_MCLK_DIVIDER_BIT_WIDTH (9) +#define I2S_LL_MCLK_DIVIDER_MAX ((1 << I2S_LL_MCLK_DIVIDER_BIT_WIDTH) - 1) + +/* I2S clock configuration structure */ +typedef struct { + uint16_t mclk_div; // I2S module clock devider, Fmclk = Fsclk /(mclk_div+b/a) + uint16_t a; + uint16_t b; // The decimal part of module clock devider, the decimal is: b/a +} i2s_ll_mclk_div_t; /** - * @brief Reset rx fifo + * @brief I2S module general init, enable I2S clock. * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_rx_fifo(i2s_dev_t *hw) +static inline void i2s_ll_enable_clock(i2s_dev_t *hw) { - abort(); // TODO ESP32-C3 IDF-2098 - - + hw->tx_clkm_conf.clk_en = 1; } /** - * @brief Reset tx fifo + * @brief I2S module disable I2S clock. * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_tx_fifo(i2s_dev_t *hw) +static inline void i2s_ll_disable_clock(i2s_dev_t *hw) { - abort(); // TODO ESP32-C3 IDF-2098 - - + hw->tx_clkm_conf.clk_en = 0; } /** - * @brief Enable rx interrupt + * @brief Enable I2S tx module clock * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_enable_rx_intr(i2s_dev_t *hw) +static inline void i2s_ll_tx_enable_clock(i2s_dev_t *hw) { - abort(); // TODO ESP32-C3 IDF-2098 - - + hw->tx_clkm_conf.tx_clk_active = 1; } /** - * @brief Disable rx interrupt + * @brief Enable I2S rx module clock * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_disable_rx_intr(i2s_dev_t *hw) +static inline void i2s_ll_rx_enable_clock(i2s_dev_t *hw) { - abort(); // TODO ESP32-C3 IDF-2098 - - + hw->rx_clkm_conf.rx_clk_active = 1; } /** - * @brief Disable tx interrupt + * @brief I2S mclk use tx module clock * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_disable_tx_intr(i2s_dev_t *hw) +static inline void i2s_ll_mclk_use_tx_clk(i2s_dev_t *hw) { - abort(); // TODO ESP32-C3 IDF-2098 - - + hw->rx_clkm_conf.mclk_sel = 0; } /** - * @brief Enable tx interrupt + * @brief I2S mclk use rx module clock * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_enable_tx_intr(i2s_dev_t *hw) +static inline void i2s_ll_mclk_use_rx_clk(i2s_dev_t *hw) { - abort(); // TODO ESP32-C3 IDF-2098 - - + hw->rx_clkm_conf.mclk_sel = 1; } /** - * @brief Reset dma in + * @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_reset_dma_in(i2s_dev_t *hw) +static inline void i2s_ll_tx_set_slave_mod(i2s_dev_t *hw, bool slave_en) { - abort(); // TODO ESP32-C3 IDF-2098 - - + hw->tx_conf.tx_slave_mod = slave_en; } /** - * @brief Reset dma out + * @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_reset_dma_out(i2s_dev_t *hw) +static inline void i2s_ll_rx_set_slave_mod(i2s_dev_t *hw, bool slave_en) { - abort(); // TODO ESP32-C3 IDF-2098 - - + hw->rx_conf.rx_slave_mod = slave_en; } /** - * @brief Reset tx + * @brief Reset I2S TX module * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_tx(i2s_dev_t *hw) +static inline void i2s_ll_tx_reset(i2s_dev_t *hw) { - abort(); // TODO ESP32-C3 IDF-2098 - - + hw->tx_conf.tx_reset = 1; + hw->tx_conf.tx_reset = 0; } /** - * @brief Reset rx + * @brief Reset I2S RX module * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_rx(i2s_dev_t *hw) +static inline void i2s_ll_rx_reset(i2s_dev_t *hw) { - abort(); // TODO ESP32-C3 IDF-2098 - - + hw->rx_conf.rx_reset = 1; + hw->rx_conf.rx_reset = 0; } /** - * @brief Start out link + * @brief Reset I2S TX FIFO * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_start_out_link(i2s_dev_t *hw) +static inline void i2s_ll_tx_reset_fifo(i2s_dev_t *hw) { - abort(); // TODO ESP32-C3 IDF-2098 - + hw->tx_conf.tx_fifo_reset = 1; + hw->tx_conf.tx_fifo_reset = 0; } /** - * @brief Start tx + * @brief Reset I2S RX FIFO * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_start_tx(i2s_dev_t *hw) +static inline void i2s_ll_rx_reset_fifo(i2s_dev_t *hw) { - abort(); // TODO ESP32-C3 IDF-2098 - + hw->rx_conf.rx_fifo_reset = 1; + hw->rx_conf.rx_fifo_reset = 0; } /** - * @brief Start in link + * @brief Set TX source clock * * @param hw Peripheral I2S hardware instance address. + * @param src I2S source clock. */ -static inline void i2s_ll_start_in_link(i2s_dev_t *hw) +static inline void i2s_ll_tx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) { - abort(); // TODO ESP32-C3 IDF-2098 - + hw->tx_clkm_conf.tx_clk_sel = 2; } /** - * @brief Start rx + * @brief Set RX source clock * * @param hw Peripheral I2S hardware instance address. + * @param src I2S source clock, ESP32-C3 only support `I2S_CLK_D2CLK` */ -static inline void i2s_ll_start_rx(i2s_dev_t *hw) +static inline void i2s_ll_rx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) { - abort(); // TODO ESP32-C3 IDF-2098 - -} - -/** - * @brief Stop out link - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_stop_out_link(i2s_dev_t *hw) -{ - abort(); // TODO ESP32-C3 IDF-2098 - -} - -/** - * @brief Stop tx - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_stop_tx(i2s_dev_t *hw) -{ - abort(); // TODO ESP32-C3 IDF-2098 - -} - -/** - * @brief Stop in link - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_stop_in_link(i2s_dev_t *hw) -{ - abort(); // TODO ESP32-C3 IDF-2098 - -} - -/** - * @brief Stop rx - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_stop_rx(i2s_dev_t *hw) -{ - abort(); // TODO ESP32-C3 IDF-2098 - -} - -/** - * @brief Enable dma - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_enable_dma(i2s_dev_t *hw) -{ - abort(); // TODO ESP32-C3 IDF-2098 - // //Enable and configure DMA - // typeof(hw->lc_conf) lc_conf; - // lc_conf.val = 0; - // lc_conf.out_eof_mode = 1; - -} - -/** - * @brief Get I2S interrupt status - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get interrupt status - */ -static inline void i2s_ll_get_intr_status(i2s_dev_t *hw, uint32_t *val) -{ - abort(); // TODO ESP32-C3 IDF-2098 - // *val = hw->int_st.val; -} - -/** - * @brief Clear I2S interrupt status - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to clear interrupt status - */ -static inline void i2s_ll_clear_intr_status(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-C3 IDF-2098 - -} - -/** - * @brief Get I2S out eof des address - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get out eof des address - */ -static inline void i2s_ll_get_out_eof_des_addr(i2s_dev_t *hw, uint32_t *val) -{ - abort(); // TODO ESP32-C3 IDF-2098 - // *val = hw->out_eof_des_addr; -} - -/** - * @brief Get I2S in eof des address - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get in eof des address - */ -static inline void i2s_ll_get_in_eof_des_addr(i2s_dev_t *hw, uint32_t *val) -{ - abort(); // TODO ESP32-C3 IDF-2098 - // *val = hw->in_eof_des_addr; -} - -/** - * @brief Get I2S tx fifo mode - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get tx fifo mode - */ -static inline void i2s_ll_get_tx_fifo_mod(i2s_dev_t *hw, uint32_t *val) -{ - abort(); // TODO ESP32-C3 IDF-2098 - // *val = hw->fifo_conf.tx_fifo_mod; -} - -/** - * @brief Set I2S tx fifo mode - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx fifo mode - */ -static inline void i2s_ll_set_tx_fifo_mod(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-C3 IDF-2098 - -} - -/** - * @brief Get I2S rx fifo mode - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get rx fifo mode - */ -static inline void i2s_ll_get_rx_fifo_mod(i2s_dev_t *hw, uint32_t *val) -{ - abort(); // TODO ESP32-C3 IDF-2098 - // *val = hw->fifo_conf.rx_fifo_mod; -} - -/** - * @brief Set I2S rx fifo mode - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx fifo mode - */ -static inline void i2s_ll_set_rx_fifo_mod(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-C3 IDF-2098 - -} - -/** - * @brief Set I2S tx chan mode - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx chan mode - */ -static inline void i2s_ll_set_tx_chan_mod(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-C3 IDF-2098 - -} - -/** - * @brief Set I2S rx chan mode - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx chan mode - */ -static inline void i2s_ll_set_rx_chan_mod(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-C3 IDF-2098 - -} - -/** - * @brief Set I2S out link address - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set out link address - */ -static inline void i2s_ll_set_out_link_addr(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-C3 IDF-2098 - -} - -/** - * @brief Set I2S in link address - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set in link address - */ -static inline void i2s_ll_set_in_link_addr(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-C3 IDF-2098 - -} - -/** - * @brief Set I2S rx eof num - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx eof num - */ -static inline void i2s_ll_set_rx_eof_num(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-C3 IDF-2098 - -} - -/** - * @brief Get I2S tx pdm fp - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get tx pdm fp - */ -static inline void i2s_ll_get_tx_pdm_fp(i2s_dev_t *hw, uint32_t *val) -{ - abort(); // TODO ESP32-C3 IDF-2098 - // *val = hw->pdm_freq_conf.tx_pdm_fp; -} - -/** - * @brief Get I2S tx pdm fs - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get tx pdm fs - */ -static inline void i2s_ll_get_tx_pdm_fs(i2s_dev_t *hw, uint32_t *val) -{ - abort(); // TODO ESP32-C3 IDF-2098 - // *val = hw->pdm_freq_conf.tx_pdm_fs; -} - -/** - * @brief Set I2S tx pdm fp - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx pdm fp - */ -static inline void i2s_ll_set_tx_pdm_fp(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-C3 IDF-2098 - -} - -/** - * @brief Set I2S tx pdm fs - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx pdm fs - */ -static inline void i2s_ll_set_tx_pdm_fs(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-C3 IDF-2098 - -} - -/** - * @brief Get I2S rx sinc dsr 16 en - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get rx sinc dsr 16 en - */ -static inline void i2s_ll_get_rx_sinc_dsr_16_en(i2s_dev_t *hw, bool *val) -{ - abort(); // TODO ESP32-C3 IDF-2098 - // *val = hw->pdm_conf.rx_sinc_dsr_16_en; -} - -/** - * @brief Set I2S clkm div num - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set clkm div num - */ -static inline void i2s_ll_set_clkm_div_num(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-C3 IDF-2098 - -} - -/** - * @brief Set I2S clkm div b - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set clkm div b - */ -static inline void i2s_ll_set_clkm_div_b(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-C3 IDF-2098 - -} - -/** - * @brief Set I2S clkm div a - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set clkm div a - */ -static inline void i2s_ll_set_clkm_div_a(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-C3 IDF-2098 - + hw->rx_clkm_conf.rx_clk_sel = 2; } /** @@ -521,10 +200,37 @@ static inline void i2s_ll_set_clkm_div_a(i2s_dev_t *hw, uint32_t val) * @param hw Peripheral I2S hardware instance address. * @param val value to set tx bck div num */ -static inline void i2s_ll_set_tx_bck_div_num(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_tx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) { - abort(); // TODO ESP32-C3 IDF-2098 + hw->tx_conf1.tx_bck_div_num = val - 1; +} +/** + * @brief Configure I2S TX clock devider + * + * @param hw Peripheral I2S hardware instance address. + * @param set Pointer to I2S clock devider configuration paramater + */ +static inline void i2s_ll_tx_set_clk(i2s_dev_t *hw, i2s_ll_mclk_div_t *set) +{ + if (set->a == 0 || set->b == 0) { + hw->tx_clkm_div_conf.tx_clkm_div_x = 0; + hw->tx_clkm_div_conf.tx_clkm_div_y = 0; + hw->tx_clkm_div_conf.tx_clkm_div_z = 0; + } else { + if (set->b > set->a / 2) { + hw->tx_clkm_div_conf.tx_clkm_div_x = set->a / (set->a - set->b) - 1; + hw->tx_clkm_div_conf.tx_clkm_div_y = set->a % (set->a - set->b); + hw->tx_clkm_div_conf.tx_clkm_div_z = set->a - set->b; + hw->tx_clkm_div_conf.tx_clkm_div_yn1 = 1; + } else { + hw->tx_clkm_div_conf.tx_clkm_div_x = set->a / set->b - 1; + hw->tx_clkm_div_conf.tx_clkm_div_y = set->a % set->b + 1; + hw->tx_clkm_div_conf.tx_clkm_div_z = set->b; + hw->tx_clkm_div_conf.tx_clkm_div_yn1 = 0; + } + } + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_clkm_conf, tx_clkm_div_num, set->mclk_div); } /** @@ -533,378 +239,595 @@ static inline void i2s_ll_set_tx_bck_div_num(i2s_dev_t *hw, uint32_t val) * @param hw Peripheral I2S hardware instance address. * @param val value to set rx bck div num */ -static inline void i2s_ll_set_rx_bck_div_num(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_rx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) { - abort(); // TODO ESP32-C3 IDF-2098 - + hw->rx_conf1.rx_bck_div_num = val - 1; } /** - * @brief Set I2S clk sel + * @brief Configure I2S RX clock devider * * @param hw Peripheral I2S hardware instance address. - * @param val value to set clk sel + * @param set Pointer to I2S clock devider configuration paramater */ -static inline void i2s_ll_set_clk_sel(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_rx_set_clk(i2s_dev_t *hw, i2s_ll_mclk_div_t *set) { - abort(); // TODO ESP32-C3 IDF-2098 - + if (set->a == 0 || set->b == 0) { + hw->rx_clkm_div_conf.rx_clkm_div_x = 0; + hw->rx_clkm_div_conf.rx_clkm_div_y = 0; + hw->rx_clkm_div_conf.rx_clkm_div_z = 0; + } else { + if (set->b > set->a / 2) { + hw->rx_clkm_div_conf.rx_clkm_div_x = set->a / (set->a - set->b) - 1; + hw->rx_clkm_div_conf.rx_clkm_div_y = set->a % (set->a - set->b); + hw->rx_clkm_div_conf.rx_clkm_div_z = set->a - set->b; + hw->rx_clkm_div_conf.rx_clkm_div_yn1 = 1; + } else { + hw->rx_clkm_div_conf.rx_clkm_div_x = set->a / set->b - 1; + hw->rx_clkm_div_conf.rx_clkm_div_y = set->a % set->b + 1; + hw->rx_clkm_div_conf.rx_clkm_div_z = set->b; + hw->rx_clkm_div_conf.rx_clkm_div_yn1 = 0; + } + } + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_clkm_conf, rx_clkm_div_num, set->mclk_div); } /** - * @brief Set I2S tx bits mod + * @brief Start I2S TX * * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx bits mod */ -static inline void i2s_ll_set_tx_bits_mod(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_tx_start(i2s_dev_t *hw) { - abort(); // TODO ESP32-C3 IDF-2098 - + hw->tx_conf.tx_update = 0; + hw->tx_conf.tx_update = 1; + hw->tx_conf.tx_start = 1; } /** - * @brief Set I2S rx bits mod + * @brief Start I2S RX * * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx bits mod */ -static inline void i2s_ll_set_rx_bits_mod(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_rx_start(i2s_dev_t *hw) { - abort(); // TODO ESP32-C3 IDF-2098 - + hw->rx_conf.rx_update = 0; + hw->rx_conf.rx_update = 1; + hw->rx_conf.rx_start = 1; } /** - * @brief Set I2S rx sinc dsr 16 en + * @brief Stop I2S TX * * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx sinc dsr 16 en */ -static inline void i2s_ll_set_rx_sinc_dsr_16_en(i2s_dev_t *hw, bool val) +static inline void i2s_ll_tx_stop(i2s_dev_t *hw) { - abort(); // TODO ESP32-C3 IDF-2098 - + hw->tx_conf.tx_start = 0; } /** - * @brief Set I2S dscr en + * @brief Stop I2S RX * * @param hw Peripheral I2S hardware instance address. - * @param val value to set dscr en */ -static inline void i2s_ll_set_dscr_en(i2s_dev_t *hw, bool val) +static inline void i2s_ll_rx_stop(i2s_dev_t *hw) { - abort(); // TODO ESP32-C3 IDF-2098 - + hw->rx_conf.rx_start = 0; } /** - * @brief Set I2S lcd en + * @brief Configure TX WS signal width * * @param hw Peripheral I2S hardware instance address. - * @param val value to set lcd en + * @param width WS width in BCK cycle */ -static inline void i2s_ll_set_lcd_en(i2s_dev_t *hw, bool val) +static inline void i2s_ll_tx_set_ws_width(i2s_dev_t *hw, int width) { - abort(); // TODO ESP32-C3 IDF-2098 - + hw->tx_conf1.tx_tdm_ws_width = width - 1; } /** - * @brief Set I2S camera en + * @brief Configure RX WS signal width * * @param hw Peripheral I2S hardware instance address. - * @param val value to set camera en + * @param width WS width in BCK cycle */ -static inline void i2s_ll_set_camera_en(i2s_dev_t *hw, bool val) +static inline void i2s_ll_rx_set_ws_width(i2s_dev_t *hw, int width) { - abort(); // TODO ESP32-C3 IDF-2098 - + hw->rx_conf1.rx_tdm_ws_width = width - 1; } /** - * @brief Set I2S pcm2pdm conv en + * @brief Configure the received length to trigger in_suc_eof interrupt * * @param hw Peripheral I2S hardware instance address. - * @param val value to set pcm2pdm conv en + * @param eof_num the byte length to trigger in_suc_eof interrupt */ -static inline void i2s_ll_set_pcm2pdm_conv_en(i2s_dev_t *hw, bool val) +static inline void i2s_ll_rx_set_eof_num(i2s_dev_t *hw, int eof_num) { - abort(); // TODO ESP32-C3 IDF-2098 - + hw->rx_eof_num.rx_eof_num = eof_num; } /** - * @brief Set I2S TX to MSB Alignment Standard + * @brief Congfigure 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_set_tx_format_msb_align(i2s_dev_t *hw) -{ -} - - -static inline void i2s_ll_set_rx_format_msb_align(i2s_dev_t *hw) +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 Set I2S TX to PCM long standard + * @brief Congfigure 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_set_tx_pcm_long(i2s_dev_t *hw) +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 Set I2S RX to PCM long standard + * @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_set_rx_pcm_long(i2s_dev_t *hw) +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 Set I2S RX to PCM short standard + * @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_set_rx_pcm_short(i2s_dev_t *hw) +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 Set I2S RX to philip standard + * @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_set_rx_format_philip(i2s_dev_t *hw) +static inline void i2s_ll_tx_enable_msb_shift(i2s_dev_t *hw, bool msb_shift_enable) { + hw->tx_conf1.tx_msb_shift = msb_shift_enable; } /** - * @brief Set I2S TX to PCM short standard + * @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_set_tx_pcm_short(i2s_dev_t *hw) +static inline void i2s_ll_rx_enable_msb_shift(i2s_dev_t *hw, bool msb_shift_enable) { + hw->rx_conf1.rx_msb_shift = msb_shift_enable; } /** - * @brief Set I2S TX to philip standard + * @brief Configure TX total chan number * * @param hw Peripheral I2S hardware instance address. + * @param total_num Total chan number */ -static inline void i2s_ll_set_tx_format_philip(i2s_dev_t *hw) +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 Set I2S pdm2pcm conv en + * @brief Configure RX total chan number * * @param hw Peripheral I2S hardware instance address. - * @param val value to set pdm2pcm conv en + * @param total_num Total chan number */ -static inline void i2s_ll_set_pdm2pcm_conv_en(i2s_dev_t *hw, bool val) +static inline void i2s_ll_rx_set_chan_num(i2s_dev_t *hw, int total_num) { - abort(); // TODO ESP32-C3 IDF-2098 - + hw->rx_tdm_ctrl.rx_tdm_tot_chan_num = total_num - 1; } /** - * @brief Set I2S rx pdm en + * @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 val value to set rx pdm en + * @param chan_mask mask of tx active chan */ -static inline void i2s_ll_set_rx_pdm_en(i2s_dev_t *hw, bool val) +static inline void i2s_ll_tx_set_active_chan_mask(i2s_dev_t *hw, uint32_t chan_mask) { - abort(); // TODO ESP32-C3 IDF-2098 - + typeof(hw->tx_tdm_ctrl) tdm_ctrl_reg = hw->tx_tdm_ctrl; + tdm_ctrl_reg.val &= ~I2S_LL_TDM_CH_MASK; + tdm_ctrl_reg.val |= chan_mask & I2S_LL_TDM_CH_MASK; + hw->tx_tdm_ctrl.val = tdm_ctrl_reg.val; } /** - * @brief Set I2S tx pdm en + * @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 val value to set tx pdm en + * @param chan_mask mask of rx active chan */ -static inline void i2s_ll_set_tx_pdm_en(i2s_dev_t *hw, bool val) +static inline void i2s_ll_rx_set_active_chan_mask(i2s_dev_t *hw, uint32_t chan_mask) { - abort(); // TODO ESP32-C3 IDF-2098 - + typeof(hw->rx_tdm_ctrl) tdm_ctrl_reg = hw->rx_tdm_ctrl; + tdm_ctrl_reg.val &= ~I2S_LL_TDM_CH_MASK; + tdm_ctrl_reg.val |= chan_mask & I2S_LL_TDM_CH_MASK; + hw->rx_tdm_ctrl.val = tdm_ctrl_reg.val; } /** - * @brief Set I2S tx fifo mod force en + * @brief Set TX WS signal pol level * * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx fifo mod force en + * @param ws_pol_level pin level of WS(output) when receiving left channel data */ -static inline void i2s_ll_set_tx_fifo_mod_force_en(i2s_dev_t *hw, bool val) +static inline void i2s_tx_set_ws_idle_pol(i2s_dev_t *hw, int ws_pol_level) { - abort(); // TODO ESP32-C3 IDF-2098 - + hw->tx_conf.tx_ws_idle_pol = ws_pol_level; } /** - * @brief Set I2S rx fifo mod force en + * @brief Set RX WS signal pol level * * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx fifo mod force en + * @param ws_pol_level pin level of WS(input) when receiving left channel data */ -static inline void i2s_ll_set_rx_fifo_mod_force_en(i2s_dev_t *hw, bool val) +static inline void i2s_rx_set_ws_idle_pol(i2s_dev_t *hw, int ws_pol_level) { - abort(); // TODO ESP32-C3 IDF-2098 - + hw->rx_conf.rx_ws_idle_pol = ws_pol_level; } /** - * @brief Set I2S tx right first + * @brief Enable TX PDM mode. * * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx right first + * @param pdm_enable Set true to TX enable PDM mode */ -static inline void i2s_ll_set_tx_right_first(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_tx_enable_pdm(i2s_dev_t *hw, bool pdm_enable) { - abort(); // TODO ESP32-C3 IDF-2098 - + hw->tx_conf.tx_pdm_en = pdm_enable; + hw->tx_conf.tx_tdm_en = !pdm_enable; + hw->tx_pcm2pdm_conf.pcm2pdm_conv_en = pdm_enable; } /** - * @brief Set I2S rx right first + * @brief Set I2S TX PDM prescale * * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx right first + * @param prescale I2S TX PDM prescale */ -static inline void i2s_ll_set_rx_right_first(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_tx_set_pdm_prescale(i2s_dev_t *hw, bool prescale) { - abort(); // TODO ESP32-C3 IDF-2098 - + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_pcm2pdm_conf, tx_pdm_prescale, prescale); } /** - * @brief Set I2S tx slave mod + * @brief Set I2S TX PDM high pass filter scaling * * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx slave mod + * @param sig_scale I2S TX PDM signal scaling before transmit to the filter */ -static inline void i2s_ll_set_tx_slave_mod(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_tx_set_pdm_hp_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale) { - abort(); // TODO ESP32-C3 IDF-2098 - + hw->tx_pcm2pdm_conf.tx_pdm_hp_in_shift = sig_scale; } /** - * @brief Set I2S rx slave mod + * @brief Set I2S TX PDM low pass filter scaling * * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx slave mod + * @param sig_scale I2S TX PDM signal scaling before transmit to the filter */ -static inline void i2s_ll_set_rx_slave_mod(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_tx_set_pdm_lp_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale) { - abort(); // TODO ESP32-C3 IDF-2098 - + hw->tx_pcm2pdm_conf.tx_pdm_lp_in_shift = sig_scale; } /** - * @brief Get I2S tx msb right + * @brief Set I2S TX PDM sinc filter scaling * * @param hw Peripheral I2S hardware instance address. - * @param val value to get tx msb right + * @param sig_scale I2S TX PDM signal scaling before transmit to the filter */ -static inline void i2s_ll_get_tx_msb_right(i2s_dev_t *hw, uint32_t *val) +static inline void i2s_ll_tx_set_pdm_sinc_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale) { - abort(); // TODO ESP32-C3 IDF-2098 - // *val = hw->conf.tx_msb_right; + hw->tx_pcm2pdm_conf.tx_pdm_sinc_in_shift = sig_scale; } /** - * @brief Get I2S rx msb right + * @brief Set I2S TX PDM sigma-delta filter scaling * * @param hw Peripheral I2S hardware instance address. - * @param val value to get rx msb right + * @param sig_scale I2S TX PDM signal scaling before transmit to the filter */ -static inline void i2s_ll_get_rx_msb_right(i2s_dev_t *hw, uint32_t *val) +static inline void i2s_ll_tx_set_pdm_sd_scale(i2s_dev_t *hw, i2s_pdm_sig_scale_t sig_scale) { - abort(); // TODO ESP32-C3 IDF-2098 - // *val = hw->conf.rx_msb_right; + hw->tx_pcm2pdm_conf.tx_pdm_sigmadelta_in_shift = sig_scale; } /** - * @brief Set I2S tx msb right + * @brief Set I2S TX PDM high pass filter param0 * * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx msb right + * @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_set_tx_msb_right(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_tx_set_pdm_hp_filter_param0(i2s_dev_t *hw, uint32_t param) { - abort(); // TODO ESP32-C3 IDF-2098 - + hw->tx_pcm2pdm_conf1.tx_iir_hp_mult12_0 = param; } /** - * @brief Set I2S rx msb right + * @brief Set I2S TX PDM high pass filter param5 * * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx msb right + * @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_set_rx_msb_right(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_tx_set_pdm_hp_filter_param5(i2s_dev_t *hw, uint32_t param) { - abort(); // TODO ESP32-C3 IDF-2098 - + hw->tx_pcm2pdm_conf1.tx_iir_hp_mult12_5 = param; } /** - * @brief Set I2S tx mono + * @brief Enable I2S TX PDM high pass filter * * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx mono + * @param enable Set true to enable I2S TX PDM high pass filter, set false to bypass it */ -static inline void i2s_ll_set_tx_mono(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_tx_enable_pdm_hp_filter(i2s_dev_t *hw, bool enable) { - abort(); // TODO ESP32-C3 IDF-2098 - + hw->tx_pcm2pdm_conf.tx_pdm_hp_bypass = !enable; } /** - * @brief Set I2S rx mono + * @brief Enable I2S TX PDM sigma-delta codec * * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx mono + * @param dither I2S TX PDM sigmadelta dither value */ -static inline void i2s_ll_set_rx_mono(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_tx_enable_pdm_sd_codec(i2s_dev_t *hw, bool enable) { - abort(); // TODO ESP32-C3 IDF-2098 - + hw->tx_pcm2pdm_conf.tx_pdm_dac_2out_en = enable; + hw->tx_pcm2pdm_conf.tx_pdm_dac_mode_en = enable; } /** - * @brief Set I2S tx sinc osr2 + * @brief Set I2S TX PDM sigma-delta codec dither * * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx sinc osr2 + * @param dither I2S TX PDM sigmadelta dither value */ -static inline void i2s_ll_set_tx_sinc_osr2(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_tx_set_pdm_sd_dither(i2s_dev_t *hw, uint32_t dither) { - abort(); // TODO ESP32-C3 IDF-2098 - + hw->tx_pcm2pdm_conf.tx_pdm_sigmadelta_dither = dither; } /** - * @brief Set I2S sig loopback + * @brief Set I2S TX PDM sigma-delta codec dither * * @param hw Peripheral I2S hardware instance address. - * @param val value to set sig loopback + * @param dither2 I2S TX PDM sigmadelta dither2 value */ -static inline void i2s_ll_set_sig_loopback(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_tx_set_pdm_sd_dither2(i2s_dev_t *hw, uint32_t dither2) { - abort(); // TODO ESP32-C3 IDF-2098 + hw->tx_pcm2pdm_conf.tx_pdm_sigmadelta_dither2 = dither2; +} +/** + * @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; + hw->tx_pcm2pdm_conf.tx_pdm_sinc_osr2 = fp / fs; +} + +/** + * @brief Get I2S TX PDM fp configuration paramater + * + * @param hw Peripheral I2S hardware instance address. + * @return + * - fp configuration paramater + */ +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 paramater + * + * @param hw Peripheral I2S hardware instance address. + * @return + * - fs configuration paramater + */ +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-C3 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) +{ + 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 paramater + */ +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 paramater + */ +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 = 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; } #ifdef __cplusplus diff --git a/components/hal/esp32c3/include/hal/ledc_ll.h b/components/hal/esp32c3/include/hal/ledc_ll.h index eafae904ba..fb495b0319 100644 --- a/components/hal/esp32c3/include/hal/ledc_ll.h +++ b/components/hal/esp32c3/include/hal/ledc_ll.h @@ -19,6 +19,7 @@ #include "hal/ledc_types.h" #include "soc/ledc_periph.h" +#include "soc/ledc_struct.h" #ifdef __cplusplus extern "C" { diff --git a/components/hal/esp32c3/include/hal/mwdt_ll.h b/components/hal/esp32c3/include/hal/mwdt_ll.h index c1fd5be9d6..944108439e 100644 --- a/components/hal/esp32c3/include/hal/mwdt_ll.h +++ b/components/hal/esp32c3/include/hal/mwdt_ll.h @@ -24,6 +24,7 @@ extern "C" { #include #include #include "soc/timer_periph.h" +#include "soc/timer_group_struct.h" #include "hal/wdt_types.h" #include "esp_attr.h" @@ -42,6 +43,13 @@ _Static_assert(WDT_RESET_SIG_LENGTH_800ns == TIMG_WDT_RESET_LENGTH_800_NS, "Add _Static_assert(WDT_RESET_SIG_LENGTH_1_6us == TIMG_WDT_RESET_LENGTH_1600_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t"); _Static_assert(WDT_RESET_SIG_LENGTH_3_2us == TIMG_WDT_RESET_LENGTH_3200_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t"); +#define FORCE_MODIFY_WHOLE_REG(i, j, k) \ +{ \ + typeof(i) temp_reg = (i); \ + temp_reg.j = (k); \ + (i) = temp_reg; \ +} + /** * @brief Enable the MWDT * @@ -49,7 +57,7 @@ _Static_assert(WDT_RESET_SIG_LENGTH_3_2us == TIMG_WDT_RESET_LENGTH_3200_NS, "Add */ FORCE_INLINE_ATTR void mwdt_ll_enable(timg_dev_t *hw) { - hw->wdt_config0.en = 1; + hw->wdtconfig0.wdt_en = 1; } /** @@ -62,7 +70,7 @@ FORCE_INLINE_ATTR void mwdt_ll_enable(timg_dev_t *hw) */ FORCE_INLINE_ATTR void mwdt_ll_disable(timg_dev_t *hw) { - hw->wdt_config0.en = 0; + hw->wdtconfig0.wdt_en = 0; } /** @@ -73,7 +81,7 @@ FORCE_INLINE_ATTR void mwdt_ll_disable(timg_dev_t *hw) */ FORCE_INLINE_ATTR bool mwdt_ll_check_if_enabled(timg_dev_t *hw) { - return (hw->wdt_config0.en) ? true : false; + return (hw->wdtconfig0.wdt_en) ? true : false; } /** @@ -88,26 +96,26 @@ FORCE_INLINE_ATTR void mwdt_ll_config_stage(timg_dev_t *hw, wdt_stage_t stage, u { switch (stage) { case WDT_STAGE0: - hw->wdt_config0.stg0 = behavior; - hw->wdt_config2 = timeout; + hw->wdtconfig0.wdt_stg0 = behavior; + hw->wdtconfig2.wdt_stg0_hold = timeout; break; case WDT_STAGE1: - hw->wdt_config0.stg1 = behavior; - hw->wdt_config3 = timeout; + hw->wdtconfig0.wdt_stg1 = behavior; + hw->wdtconfig3.wdt_stg1_hold = timeout; break; case WDT_STAGE2: - hw->wdt_config0.stg2 = behavior; - hw->wdt_config4 = timeout; + hw->wdtconfig0.wdt_stg2 = behavior; + hw->wdtconfig4.wdt_stg2_hold = timeout; break; case WDT_STAGE3: - hw->wdt_config0.stg3 = behavior; - hw->wdt_config5 = timeout; + hw->wdtconfig0.wdt_stg3 = behavior; + hw->wdtconfig5.wdt_stg3_hold = timeout; break; default: break; } //Config registers are updated asynchronously - hw->wdt_config0.conf_update_en = 1; + hw->wdtconfig0.wdt_conf_update_en = 1; } /** @@ -120,22 +128,22 @@ FORCE_INLINE_ATTR void mwdt_ll_disable_stage(timg_dev_t *hw, uint32_t stage) { switch (stage) { case WDT_STAGE0: - hw->wdt_config0.stg0 = WDT_STAGE_ACTION_OFF; + hw->wdtconfig0.wdt_stg0 = WDT_STAGE_ACTION_OFF; break; case WDT_STAGE1: - hw->wdt_config0.stg1 = WDT_STAGE_ACTION_OFF; + hw->wdtconfig0.wdt_stg1 = WDT_STAGE_ACTION_OFF; break; case WDT_STAGE2: - hw->wdt_config0.stg2 = WDT_STAGE_ACTION_OFF; + hw->wdtconfig0.wdt_stg2 = WDT_STAGE_ACTION_OFF; break; case WDT_STAGE3: - hw->wdt_config0.stg3 = WDT_STAGE_ACTION_OFF; + hw->wdtconfig0.wdt_stg3 = WDT_STAGE_ACTION_OFF; break; default: break; } //Config registers are updated asynchronously - hw->wdt_config0.conf_update_en = 1; + hw->wdtconfig0.wdt_conf_update_en = 1; } /** @@ -146,9 +154,9 @@ FORCE_INLINE_ATTR void mwdt_ll_disable_stage(timg_dev_t *hw, uint32_t stage) */ FORCE_INLINE_ATTR void mwdt_ll_set_cpu_reset_length(timg_dev_t *hw, wdt_reset_sig_length_t length) { - hw->wdt_config0.cpu_reset_length = length; + hw->wdtconfig0.wdt_cpu_reset_length = length; //Config registers are updated asynchronously - hw->wdt_config0.conf_update_en = 1; + hw->wdtconfig0.wdt_conf_update_en = 1; } /** @@ -159,9 +167,9 @@ FORCE_INLINE_ATTR void mwdt_ll_set_cpu_reset_length(timg_dev_t *hw, wdt_reset_si */ FORCE_INLINE_ATTR void mwdt_ll_set_sys_reset_length(timg_dev_t *hw, wdt_reset_sig_length_t length) { - hw->wdt_config0.sys_reset_length = length; + hw->wdtconfig0.wdt_sys_reset_length = length; //Config registers are updated asynchronously - hw->wdt_config0.conf_update_en = 1; + hw->wdtconfig0.wdt_conf_update_en = 1; } /** @@ -176,9 +184,9 @@ FORCE_INLINE_ATTR void mwdt_ll_set_sys_reset_length(timg_dev_t *hw, wdt_reset_si */ FORCE_INLINE_ATTR void mwdt_ll_set_flashboot_en(timg_dev_t *hw, bool enable) { - hw->wdt_config0.flashboot_mod_en = (enable) ? 1 : 0; + hw->wdtconfig0.wdt_flashboot_mod_en = (enable) ? 1 : 0; //Config registers are updated asynchronously - hw->wdt_config0.conf_update_en = 1; + hw->wdtconfig0.wdt_conf_update_en = 1; } /** @@ -189,9 +197,11 @@ FORCE_INLINE_ATTR void mwdt_ll_set_flashboot_en(timg_dev_t *hw, bool enable) */ FORCE_INLINE_ATTR void mwdt_ll_set_prescaler(timg_dev_t *hw, uint32_t prescaler) { - hw->wdt_config1.clk_prescale = prescaler; + // In case the compiler optimise a 32bit instruction (e.g. s32i) into 8/16bit instruction (e.g. s8i, which is not allowed to access a register) + // We take care of the "read-modify-write" procedure by ourselves. + FORCE_MODIFY_WHOLE_REG(hw->wdtconfig1, wdt_clk_prescale, prescaler); //Config registers are updated asynchronously - hw->wdt_config0.conf_update_en = 1; + hw->wdtconfig0.wdt_conf_update_en = 1; } /** @@ -203,7 +213,7 @@ FORCE_INLINE_ATTR void mwdt_ll_set_prescaler(timg_dev_t *hw, uint32_t prescaler) */ FORCE_INLINE_ATTR void mwdt_ll_feed(timg_dev_t *hw) { - hw->wdt_feed = 1; + hw->wdtfeed.wdt_feed = 1; } /** @@ -215,7 +225,7 @@ FORCE_INLINE_ATTR void mwdt_ll_feed(timg_dev_t *hw) */ FORCE_INLINE_ATTR void mwdt_ll_write_protect_enable(timg_dev_t *hw) { - hw->wdt_wprotect = 0; + hw->wdtwprotect.wdt_wkey = 0; } /** @@ -225,7 +235,7 @@ FORCE_INLINE_ATTR void mwdt_ll_write_protect_enable(timg_dev_t *hw) */ FORCE_INLINE_ATTR void mwdt_ll_write_protect_disable(timg_dev_t *hw) { - hw->wdt_wprotect = TIMG_WDT_WKEY_VALUE; + hw->wdtwprotect.wdt_wkey = TIMG_WDT_WKEY_VALUE; } /** @@ -235,7 +245,7 @@ FORCE_INLINE_ATTR void mwdt_ll_write_protect_disable(timg_dev_t *hw) */ FORCE_INLINE_ATTR void mwdt_ll_clear_intr_status(timg_dev_t *hw) { - hw->int_clr.wdt = 1; + hw->int_clr_timers.wdt_int_clr = 1; } /** @@ -246,7 +256,7 @@ FORCE_INLINE_ATTR void mwdt_ll_clear_intr_status(timg_dev_t *hw) */ FORCE_INLINE_ATTR void mwdt_ll_set_intr_enable(timg_dev_t *hw, bool enable) { - hw->int_ena.wdt = (enable) ? 1 : 0; + hw->int_ena_timers.wdt_int_ena = (enable) ? 1 : 0; } #ifdef __cplusplus diff --git a/components/hal/esp32c3/include/hal/rmt_ll.h b/components/hal/esp32c3/include/hal/rmt_ll.h index f5427d150a..662e63f784 100644 --- a/components/hal/esp32c3/include/hal/rmt_ll.h +++ b/components/hal/esp32c3/include/hal/rmt_ll.h @@ -1,27 +1,24 @@ -// 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + #pragma once #include #include #include +#include "hal/misc.h" #include "soc/rmt_struct.h" #ifdef __cplusplus extern "C" { #endif + +#define RMT_LL_MAX_LOOP_COUNT (1023)/*!< Max loop count that hardware is supported */ + #define RMT_LL_HW_BASE (&RMT) #define RMT_LL_MEM_BASE (&RMTMEM) @@ -58,7 +55,7 @@ static inline void rmt_ll_set_group_clock_src(rmt_dev_t *dev, uint32_t channel, // Formula: rmt_sclk = module_clock_src / (1 + div_num + div_a / div_b) dev->sys_conf.sclk_active = 0; dev->sys_conf.sclk_sel = src; - dev->sys_conf.sclk_div_num = div_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->sys_conf, sclk_div_num, div_num); dev->sys_conf.sclk_div_a = div_a; dev->sys_conf.sclk_div_b = div_b; dev->sys_conf.sclk_active = 1; @@ -140,22 +137,22 @@ static inline uint32_t rmt_ll_rx_get_mem_blocks(rmt_dev_t *dev, uint32_t channel static inline void rmt_ll_tx_set_channel_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div) { - dev->tx_conf[channel].div_cnt = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->tx_conf[channel], div_cnt, div); } static inline void rmt_ll_rx_set_channel_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div) { - dev->rx_conf[channel].conf0.div_cnt = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->rx_conf[channel].conf0, div_cnt, div); } static inline uint32_t rmt_ll_tx_get_channel_clock_div(rmt_dev_t *dev, uint32_t channel) { - return dev->tx_conf[channel].div_cnt; + return HAL_FORCE_READ_U32_REG_FIELD(dev->tx_conf[channel], div_cnt); } static inline uint32_t rmt_ll_rx_get_channel_clock_div(rmt_dev_t *dev, uint32_t channel) { - return dev->rx_conf[channel].conf0.div_cnt; + return HAL_FORCE_READ_U32_REG_FIELD(dev->rx_conf[channel].conf0, div_cnt); } static inline void rmt_ll_tx_enable_pingpong(rmt_dev_t *dev, uint32_t channel, bool enable) @@ -231,7 +228,7 @@ static inline void rmt_ll_rx_enable_filter(rmt_dev_t *dev, uint32_t channel, boo static inline void rmt_ll_rx_set_filter_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres) { - dev->rx_conf[channel].conf1.rx_filter_thres = thres; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->rx_conf[channel].conf1, rx_filter_thres, thres); } static inline void rmt_ll_tx_enable_idle(rmt_dev_t *dev, uint32_t channel, bool enable) @@ -441,14 +438,14 @@ static inline void rmt_ll_rx_set_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t static inline void rmt_ll_tx_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks) { - *high_ticks = dev->tx_carrier[channel].high; - *low_ticks = dev->tx_carrier[channel].low; + *high_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->tx_carrier[channel], high); + *low_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->tx_carrier[channel], low); } static inline void rmt_ll_rx_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks) { - *high_ticks = dev->rx_carrier[channel].high_thres; - *low_ticks = dev->rx_carrier[channel].low_thres; + *high_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->rx_carrier[channel], high_thres); + *low_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->rx_carrier[channel], low_thres); } static inline void rmt_ll_tx_enable_carrier_modulation(rmt_dev_t *dev, uint32_t channel, bool enable) diff --git a/components/hal/esp32c3/include/hal/rtc_cntl_ll.h b/components/hal/esp32c3/include/hal/rtc_cntl_ll.h index 72385568a4..9f298bbf09 100644 --- a/components/hal/esp32c3/include/hal/rtc_cntl_ll.h +++ b/components/hal/esp32c3/include/hal/rtc_cntl_ll.h @@ -17,7 +17,7 @@ #include "soc/soc.h" #include "soc/rtc.h" #include "soc/rtc_cntl_reg.h" -#include "soc/apb_ctrl_reg.h" +#include "soc/syscon_reg.h" #ifdef __cplusplus extern "C" { @@ -47,12 +47,18 @@ static inline void rtc_cntl_ll_gpio_clear_wakeup_pins(void) REG_SET_BIT(RTC_CNTL_GPIO_WAKEUP_REG, RTC_CNTL_GPIO_WAKEUP_STATUS_CLR); } -static inline void rtc_cntl_ll_enable_cpu_retention(uint32_t addr) +static inline void rtc_cntl_ll_set_cpu_retention_link_addr(uint32_t addr) +{ + REG_SET_FIELD(SYSCON_RETENTION_CTRL_REG, SYSCON_RETENTION_LINK_ADDR, (uint32_t)addr); +} + +static inline void rtc_cntl_ll_enable_cpu_retention_clock(void) { - /* write memory address to register */ - REG_SET_FIELD(APB_CTRL_RETENTION_CTRL_REG, APB_CTRL_RETENTION_LINK_ADDR, (uint32_t)addr); - /* Enable clock */ REG_SET_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN); +} + +static inline void rtc_cntl_ll_enable_cpu_retention(void) +{ /* Enable retention when cpu sleep enable */ REG_SET_BIT(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_EN); } diff --git a/components/hal/esp32c3/include/hal/rwdt_ll.h b/components/hal/esp32c3/include/hal/rwdt_ll.h index 87ae4f7294..0986ce3dec 100644 --- a/components/hal/esp32c3/include/hal/rwdt_ll.h +++ b/components/hal/esp32c3/include/hal/rwdt_ll.h @@ -23,8 +23,10 @@ extern "C" { #include #include +#include "hal/misc.h" #include "hal/wdt_types.h" #include "soc/rtc_cntl_periph.h" +#include "soc/rtc_cntl_struct.h" #include "soc/efuse_reg.h" #include "esp_attr.h" @@ -239,7 +241,7 @@ FORCE_INLINE_ATTR void rwdt_ll_set_chip_reset_en(rtc_cntl_dev_t *hw, bool enable */ FORCE_INLINE_ATTR void rwdt_ll_set_chip_reset_width(rtc_cntl_dev_t *hw, uint32_t width) { - hw->wdt_config0.chip_reset_width = width; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->wdt_config0, chip_reset_width, width); } /** diff --git a/components/hal/esp32c3/include/hal/sigmadelta_ll.h b/components/hal/esp32c3/include/hal/sigmadelta_ll.h index 87f75dab9e..f6c37054a3 100644 --- a/components/hal/esp32c3/include/hal/sigmadelta_ll.h +++ b/components/hal/esp32c3/include/hal/sigmadelta_ll.h @@ -22,7 +22,9 @@ #pragma once #include +#include "hal/misc.h" #include "soc/sigmadelta_periph.h" +#include "soc/gpio_sd_struct.h" #include "hal/sigmadelta_types.h" #ifdef __cplusplus @@ -53,7 +55,7 @@ static inline void sigmadelta_ll_set_en(gpio_sd_dev_t *hw, bool en) */ static inline void sigmadelta_ll_set_duty(gpio_sd_dev_t *hw, sigmadelta_channel_t channel, int8_t duty) { - hw->channel[channel].duty = duty; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], duty, (uint32_t)duty); } /** @@ -65,7 +67,7 @@ static inline void sigmadelta_ll_set_duty(gpio_sd_dev_t *hw, sigmadelta_channel_ */ static inline void sigmadelta_ll_set_prescale(gpio_sd_dev_t *hw, sigmadelta_channel_t channel, uint8_t prescale) { - hw->channel[channel].prescale = prescale; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], prescale, prescale); } #ifdef __cplusplus diff --git a/components/hal/esp32c3/include/hal/spi_ll.h b/components/hal/esp32c3/include/hal/spi_ll.h index 8d2c1079f5..38e1676d04 100644 --- a/components/hal/esp32c3/include/hal/spi_ll.h +++ b/components/hal/esp32c3/include/hal/spi_ll.h @@ -27,9 +27,11 @@ #include "esp_attr.h" #include "esp_types.h" #include "soc/spi_periph.h" +#include "soc/spi_struct.h" #include "soc/lldesc.h" #include "hal/assert.h" #include "hal/misc.h" +#include "hal/spi_types.h" #ifdef __cplusplus extern "C" { @@ -37,6 +39,9 @@ extern "C" { /// Interrupt not used. Don't use in app. #define SPI_LL_UNUSED_INT_MASK (SPI_TRANS_DONE_INT_ENA | SPI_SLV_WR_DMA_DONE_INT_ENA | SPI_SLV_RD_DMA_DONE_INT_ENA | SPI_SLV_WR_BUF_DONE_INT_ENA | SPI_SLV_RD_BUF_DONE_INT_ENA) +/// These 2 masks together will set SPI transaction to one line mode +#define SPI_LL_ONE_LINE_CTRL_MASK (SPI_FREAD_QUAD | SPI_FREAD_DUAL | SPI_FCMD_QUAD | SPI_FCMD_DUAL | SPI_FADDR_QUAD | SPI_FADDR_DUAL) +#define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_QUAD | SPI_FWRITE_DUAL) /// Swap the bit order to its correct place to send #define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len)) /// This is the expected clock frequency @@ -51,15 +56,6 @@ extern "C" { typedef uint32_t spi_ll_clock_val_t; typedef spi_dev_t spi_dma_dev_t; -/** IO modes supported by the master. */ -typedef enum { - SPI_LL_IO_MODE_NORMAL = 0, ///< 1-bit mode for all phases - SPI_LL_IO_MODE_DIO, ///< 2-bit mode for address and data phases, 1-bit mode for command phase - SPI_LL_IO_MODE_DUAL, ///< 2-bit mode for data phases only, 1-bit mode for command and address phases - SPI_LL_IO_MODE_QIO, ///< 4-bit mode for address and data phases, 1-bit mode for command phase - SPI_LL_IO_MODE_QUAD, ///< 4-bit mode for data phases only, 1-bit mode for command and address phases -} spi_ll_io_mode_t; - // Type definition of all supported interrupts typedef enum { SPI_LL_INTR_TRANS_DONE = BIT(0), ///< A transaction has done @@ -354,7 +350,7 @@ static inline void spi_ll_write_buffer(spi_dev_t *hw, const uint8_t *buffer_to_s */ static inline void spi_ll_write_buffer_byte(spi_dev_t *hw, int byte_id, uint8_t *data, int len) { - HAL_ASSERT(byte_id+len <= 64); + HAL_ASSERT(byte_id + len <= 64); HAL_ASSERT(len > 0); HAL_ASSERT(byte_id >= 0); @@ -362,10 +358,14 @@ static inline void spi_ll_write_buffer_byte(spi_dev_t *hw, int byte_id, uint8_t uint32_t word; int offset = byte_id % 4; int copy_len = 4 - offset; - if (copy_len > len) copy_len = len; + if (copy_len > len) { + copy_len = len; + } //read-modify-write - if (copy_len != 4) word = hw->data_buf[byte_id / 4]; //read + if (copy_len != 4) { + word = hw->data_buf[byte_id / 4]; //read + } memcpy(((uint8_t *)&word) + offset, data, copy_len); //modify hw->data_buf[byte_id / 4] = word; //write @@ -409,7 +409,9 @@ static inline void spi_ll_read_buffer_byte(spi_dev_t *hw, int byte_id, uint8_t * uint32_t word = hw->data_buf[byte_id / 4]; int offset = byte_id % 4; int copy_len = 4 - offset; - if (copy_len > len) copy_len = len; + if (copy_len > len) { + copy_len = len; + } memcpy(out_data, ((uint8_t *)&word) + offset, copy_len); byte_id += copy_len; @@ -540,41 +542,23 @@ static inline void spi_ll_set_sio_mode(spi_dev_t *hw, int sio_mode) } /** - * Configure the io mode for the master to work at. + * Configure the SPI transaction line mode for the master to use. * - * @param hw Beginning address of the peripheral registers. - * @param io_mode IO mode to work at, see ``spi_ll_io_mode_t``. + * @param hw Beginning address of the peripheral registers. + * @param line_mode SPI transaction line mode to use, see ``spi_line_mode_t``. */ -static inline void spi_ll_master_set_io_mode(spi_dev_t *hw, spi_ll_io_mode_t io_mode) +static inline void spi_ll_master_set_line_mode(spi_dev_t *hw, spi_line_mode_t line_mode) { - if (io_mode == SPI_LL_IO_MODE_DIO || io_mode == SPI_LL_IO_MODE_DUAL) { - hw->ctrl.fcmd_dual = (io_mode == SPI_LL_IO_MODE_DIO) ? 1 : 0; - hw->ctrl.faddr_dual = (io_mode == SPI_LL_IO_MODE_DIO) ? 1 : 0; - hw->ctrl.fread_dual = 1; - hw->user.fwrite_dual = 1; - hw->ctrl.fcmd_quad = 0; - hw->ctrl.faddr_quad = 0; - hw->ctrl.fread_quad = 0; - hw->user.fwrite_quad = 0; - } else if (io_mode == SPI_LL_IO_MODE_QIO || io_mode == SPI_LL_IO_MODE_QUAD) { - hw->ctrl.fcmd_quad = (io_mode == SPI_LL_IO_MODE_QIO) ? 1 : 0; - hw->ctrl.faddr_quad = (io_mode == SPI_LL_IO_MODE_QIO) ? 1 : 0; - hw->ctrl.fread_quad = 1; - hw->user.fwrite_quad = 1; - hw->ctrl.fcmd_dual = 0; - hw->ctrl.faddr_dual = 0; - hw->ctrl.fread_dual = 0; - hw->user.fwrite_dual = 0; - } else { - hw->ctrl.fcmd_dual = 0; - hw->ctrl.faddr_dual = 0; - hw->ctrl.fread_dual = 0; - hw->user.fwrite_dual = 0; - hw->ctrl.fcmd_quad = 0; - hw->ctrl.faddr_quad = 0; - hw->ctrl.fread_quad = 0; - hw->user.fwrite_quad = 0; - } + hw->ctrl.val &= ~SPI_LL_ONE_LINE_CTRL_MASK; + hw->user.val &= ~SPI_LL_ONE_LINE_USER_MASK; + hw->ctrl.fcmd_dual = (line_mode.cmd_lines == 2); + hw->ctrl.fcmd_quad = (line_mode.cmd_lines == 4); + hw->ctrl.faddr_dual = (line_mode.addr_lines == 2); + hw->ctrl.faddr_quad = (line_mode.addr_lines == 4); + hw->ctrl.fread_dual = (line_mode.data_lines == 2); + hw->user.fwrite_dual = (line_mode.data_lines == 2); + hw->ctrl.fread_quad = (line_mode.data_lines == 4); + hw->user.fwrite_quad = (line_mode.data_lines == 4); } /** @@ -610,7 +594,8 @@ static inline void spi_ll_master_select_cs(spi_dev_t *hw, int cs_id) * @param hw Beginning address of the peripheral registers. * @param keep_active if 0 don't keep CS activated, else keep CS activated */ -static inline void spi_ll_master_keep_cs(spi_dev_t *hw, int keep_active) { +static inline void spi_ll_master_keep_cs(spi_dev_t *hw, int keep_active) +{ hw->misc.cs_keep_active = (keep_active != 0) ? 1 : 0; } @@ -917,13 +902,13 @@ static inline void spi_ll_set_command(spi_dev_t *hw, uint16_t cmd, int cmdlen, b { if (lsbfirst) { // The output command start from bit0 to bit 15, kept as is. - hw->user2.usr_command_value = cmd; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user2, usr_command_value, cmd); } else { /* Output command will be sent from bit 7 to 0 of command_value, and * then bit 15 to 8 of the same register field. Shift and swap to send * more straightly. */ - hw->user2.usr_command_value = HAL_SPI_SWAP_DATA_TX(cmd, cmdlen); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user2, usr_command_value, HAL_SPI_SWAP_DATA_TX(cmd, cmdlen)); } } @@ -939,7 +924,7 @@ static inline void spi_ll_set_command(spi_dev_t *hw, uint16_t cmd, int cmdlen, b static inline void spi_ll_set_dummy(spi_dev_t *hw, int dummy_n) { hw->user.usr_dummy = dummy_n ? 1 : 0; - hw->user1.usr_dummy_cyclelen = dummy_n - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user1, usr_dummy_cyclelen, dummy_n - 1); } /** @@ -994,35 +979,35 @@ static inline uint32_t spi_ll_slave_get_rcv_bitlen(spi_dev_t *hw) item(SPI_LL_INTR_CMDA, dma_int_ena.cmda, dma_int_raw.cmda, dma_int_clr.cmda=1) -static inline void spi_ll_enable_intr(spi_dev_t* hw, spi_ll_intr_t intr_mask) +static inline void spi_ll_enable_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask) { #define ENA_INTR(intr_bit, en_reg, ...) if (intr_mask & (intr_bit)) hw->en_reg = 1; FOR_EACH_ITEM(ENA_INTR, INTR_LIST); #undef ENA_INTR } -static inline void spi_ll_disable_intr(spi_dev_t* hw, spi_ll_intr_t intr_mask) +static inline void spi_ll_disable_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask) { #define DIS_INTR(intr_bit, en_reg, ...) if (intr_mask & (intr_bit)) hw->en_reg = 0; FOR_EACH_ITEM(DIS_INTR, INTR_LIST); #undef DIS_INTR } -static inline void spi_ll_set_intr(spi_dev_t* hw, spi_ll_intr_t intr_mask) +static inline void spi_ll_set_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask) { #define SET_INTR(intr_bit, _, st_reg, ...) if (intr_mask & (intr_bit)) hw->st_reg = 1; FOR_EACH_ITEM(SET_INTR, INTR_LIST); #undef SET_INTR } -static inline void spi_ll_clear_intr(spi_dev_t* hw, spi_ll_intr_t intr_mask) +static inline void spi_ll_clear_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask) { #define CLR_INTR(intr_bit, _, __, clr_reg) if (intr_mask & (intr_bit)) hw->clr_reg; FOR_EACH_ITEM(CLR_INTR, INTR_LIST); #undef CLR_INTR } -static inline bool spi_ll_get_intr(spi_dev_t* hw, spi_ll_intr_t intr_mask) +static inline bool spi_ll_get_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask) { #define GET_INTR(intr_bit, _, st_reg, ...) if (intr_mask & (intr_bit) && hw->st_reg) return true; FOR_EACH_ITEM(GET_INTR, INTR_LIST); @@ -1076,7 +1061,7 @@ static inline void spi_ll_enable_int(spi_dev_t *hw) /*------------------------------------------------------------------------------ * Slave HD *----------------------------------------------------------------------------*/ -static inline void spi_ll_slave_hd_set_len_cond(spi_dev_t* hw, spi_ll_trans_len_cond_t cond_mask) +static inline void spi_ll_slave_hd_set_len_cond(spi_dev_t *hw, spi_ll_trans_len_cond_t cond_mask) { hw->slave.rdbuf_bitlen_en = (cond_mask & SPI_LL_TRANS_LEN_COND_RDBUF) ? 1 : 0; hw->slave.wrbuf_bitlen_en = (cond_mask & SPI_LL_TRANS_LEN_COND_WRBUF) ? 1 : 0; @@ -1084,12 +1069,12 @@ static inline void spi_ll_slave_hd_set_len_cond(spi_dev_t* hw, spi_ll_trans_len_ hw->slave.wrdma_bitlen_en = (cond_mask & SPI_LL_TRANS_LEN_COND_WRDMA) ? 1 : 0; } -static inline int spi_ll_slave_get_rx_byte_len(spi_dev_t* hw) +static inline int spi_ll_slave_get_rx_byte_len(spi_dev_t *hw) { return hw->slave1.data_bitlen / 8; } -static inline uint32_t spi_ll_slave_hd_get_last_addr(spi_dev_t* hw) +static inline uint32_t spi_ll_slave_hd_get_last_addr(spi_dev_t *hw) { return hw->slave1.last_addr; } diff --git a/components/hal/esp32c3/include/hal/spimem_flash_ll.h b/components/hal/esp32c3/include/hal/spimem_flash_ll.h index 7641c3d723..92c8748dd4 100644 --- a/components/hal/esp32c3/include/hal/spimem_flash_ll.h +++ b/components/hal/esp32c3/include/hal/spimem_flash_ll.h @@ -28,6 +28,7 @@ #include #include "soc/spi_periph.h" +#include "soc/spi_mem_struct.h" #include "hal/spi_types.h" #include "hal/spi_flash_types.h" @@ -157,7 +158,7 @@ static inline void spimem_flash_ll_auto_resume_init(spi_mem_dev_t *dev, bool aut */ static inline void spimem_flash_ll_suspend_cmd_setup(spi_mem_dev_t *dev, uint32_t sus_cmd) { - dev->flash_sus_cmd.flash_pes_command = sus_cmd; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_cmd, flash_pes_command, sus_cmd); } /** @@ -169,7 +170,7 @@ static inline void spimem_flash_ll_suspend_cmd_setup(spi_mem_dev_t *dev, uint32_ */ static inline void spimem_flash_ll_resume_cmd_setup(spi_mem_dev_t *dev, uint32_t res_cmd) { - dev->flash_sus_cmd.flash_per_command = res_cmd; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_cmd, flash_per_command, res_cmd); } /** @@ -181,7 +182,7 @@ static inline void spimem_flash_ll_resume_cmd_setup(spi_mem_dev_t *dev, uint32_t */ static inline void spimem_flash_ll_rd_sus_cmd_setup(spi_mem_dev_t *dev, uint32_t pesr_cmd) { - dev->flash_sus_cmd.wait_pesr_command = pesr_cmd; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_cmd, wait_pesr_command, pesr_cmd); } /** @@ -218,7 +219,7 @@ static inline void spimem_flash_ll_res_check_sus_setup(spi_mem_dev_t *dev, bool static inline void spimem_flash_ll_set_read_sus_status(spi_mem_dev_t *dev, uint32_t sus_conf) { dev->flash_sus_ctrl.frd_sus_2b = 0; - dev->flash_sus_ctrl.pesr_end_msk = sus_conf; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_ctrl, pesr_end_msk, sus_conf); } /** @@ -229,7 +230,7 @@ static inline void spimem_flash_ll_set_read_sus_status(spi_mem_dev_t *dev, uint3 */ static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool auto_waiti) { - dev->flash_waiti_ctrl.waiti_cmd = 0x05; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_waiti_ctrl, waiti_cmd, 0x05); dev->flash_sus_ctrl.flash_per_wait_en = auto_waiti; dev->flash_sus_ctrl.flash_pes_wait_en = auto_waiti; } diff --git a/components/hal/esp32c3/include/hal/systimer_ll.h b/components/hal/esp32c3/include/hal/systimer_ll.h index 769f68703f..3628978f68 100644 --- a/components/hal/esp32c3/include/hal/systimer_ll.h +++ b/components/hal/esp32c3/include/hal/systimer_ll.h @@ -124,6 +124,11 @@ __attribute__((always_inline)) static inline void systimer_ll_set_alarm_period(s dev->target_conf[alarm_id].target_period = period; } +__attribute__((always_inline)) static inline uint32_t systimer_ll_get_alarm_period(systimer_dev_t *dev, uint32_t alarm_id) +{ + return dev->target_conf[alarm_id].target_period; +} + __attribute__((always_inline)) static inline void systimer_ll_apply_alarm_value(systimer_dev_t *dev, uint32_t alarm_id) { dev->comp_load[alarm_id].val = 0x01; diff --git a/components/hal/esp32c3/include/hal/timer_ll.h b/components/hal/esp32c3/include/hal/timer_ll.h index 8547fab25f..5e51b102f1 100644 --- a/components/hal/esp32c3/include/hal/timer_ll.h +++ b/components/hal/esp32c3/include/hal/timer_ll.h @@ -22,7 +22,9 @@ extern "C" { #endif #include +#include "hal/misc.h" #include "soc/timer_periph.h" +#include "soc/timer_group_struct.h" #include "hal/timer_types.h" #include "hal/assert.h" @@ -52,11 +54,11 @@ static inline void timer_ll_set_divider(timg_dev_t *hw, timer_idx_t timer_num, u if (divider >= 65536) { divider = 0; } - int timer_en = hw->hw_timer[timer_num].config.enable; - hw->hw_timer[timer_num].config.enable = 0; - hw->hw_timer[timer_num].config.divcnt_rst = 1; - hw->hw_timer[timer_num].config.divider = divider; - hw->hw_timer[timer_num].config.enable = timer_en; + int timer_en = hw->hw_timer[timer_num].config.tx_en; + hw->hw_timer[timer_num].config.tx_en = 0; + hw->hw_timer[timer_num].config.tx_divcnt_rst = 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->hw_timer[timer_num].config, tx_divider, divider); + hw->hw_timer[timer_num].config.tx_en = timer_en; } /** @@ -70,7 +72,7 @@ static inline void timer_ll_set_divider(timg_dev_t *hw, timer_idx_t timer_num, u */ static inline void timer_ll_get_divider(timg_dev_t *hw, timer_idx_t timer_num, uint32_t *divider) { - uint32_t d = hw->hw_timer[timer_num].config.divider; + uint32_t d = HAL_FORCE_READ_U32_REG_FIELD(hw->hw_timer[timer_num].config, tx_divider); if (d == 0) { d = 65536; } else if (d == 1) { @@ -90,9 +92,9 @@ static inline void timer_ll_get_divider(timg_dev_t *hw, timer_idx_t timer_num, u */ static inline void timer_ll_set_counter_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t load_val) { - hw->hw_timer[timer_num].load_high.load_hi = (uint32_t) (load_val >> 32); - hw->hw_timer[timer_num].load_low = (uint32_t) load_val; - hw->hw_timer[timer_num].reload = 1; + hw->hw_timer[timer_num].loadhi.tx_load_hi = (uint32_t) (load_val >> 32); + hw->hw_timer[timer_num].loadlo.tx_load_lo = (uint32_t) load_val; + hw->hw_timer[timer_num].load.tx_load = 1; } /** @@ -106,9 +108,9 @@ static inline void timer_ll_set_counter_value(timg_dev_t *hw, timer_idx_t timer_ */ FORCE_INLINE_ATTR void timer_ll_get_counter_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t *timer_val) { - hw->hw_timer[timer_num].update.update = 1; - while (hw->hw_timer[timer_num].update.update) {} - *timer_val = ((uint64_t) hw->hw_timer[timer_num].cnt_high.hi << 32) | (hw->hw_timer[timer_num].cnt_low); + hw->hw_timer[timer_num].update.tx_update = 1; + while (hw->hw_timer[timer_num].update.tx_update) {} + *timer_val = ((uint64_t) hw->hw_timer[timer_num].hi.tx_hi << 32) | (hw->hw_timer[timer_num].lo.tx_lo); } /** @@ -122,7 +124,7 @@ FORCE_INLINE_ATTR void timer_ll_get_counter_value(timg_dev_t *hw, timer_idx_t ti */ static inline void timer_ll_set_counter_increase(timg_dev_t *hw, timer_idx_t timer_num, bool increase_en) { - hw->hw_timer[timer_num].config.increase = increase_en; + hw->hw_timer[timer_num].config.tx_increase = increase_en; } /** @@ -137,7 +139,7 @@ static inline void timer_ll_set_counter_increase(timg_dev_t *hw, timer_idx_t tim */ static inline bool timer_ll_get_counter_increase(timg_dev_t *hw, timer_idx_t timer_num) { - return hw->hw_timer[timer_num].config.increase; + return hw->hw_timer[timer_num].config.tx_increase; } /** @@ -151,7 +153,7 @@ static inline bool timer_ll_get_counter_increase(timg_dev_t *hw, timer_idx_t tim */ FORCE_INLINE_ATTR void timer_ll_set_counter_enable(timg_dev_t *hw, timer_idx_t timer_num, bool counter_en) { - hw->hw_timer[timer_num].config.enable = counter_en; + hw->hw_timer[timer_num].config.tx_en = counter_en; } /** @@ -166,7 +168,7 @@ FORCE_INLINE_ATTR void timer_ll_set_counter_enable(timg_dev_t *hw, timer_idx_t t */ static inline bool timer_ll_get_counter_enable(timg_dev_t *hw, timer_idx_t timer_num) { - return hw->hw_timer[timer_num].config.enable; + return hw->hw_timer[timer_num].config.tx_en; } /** @@ -180,7 +182,7 @@ static inline bool timer_ll_get_counter_enable(timg_dev_t *hw, timer_idx_t timer */ static inline void timer_ll_set_auto_reload(timg_dev_t *hw, timer_idx_t timer_num, bool auto_reload_en) { - hw->hw_timer[timer_num].config.autoreload = auto_reload_en; + hw->hw_timer[timer_num].config.tx_autoreload = auto_reload_en; } /** @@ -195,7 +197,7 @@ static inline void timer_ll_set_auto_reload(timg_dev_t *hw, timer_idx_t timer_nu */ FORCE_INLINE_ATTR bool timer_ll_get_auto_reload(timg_dev_t *hw, timer_idx_t timer_num) { - return hw->hw_timer[timer_num].config.autoreload; + return hw->hw_timer[timer_num].config.tx_autoreload; } /** @@ -209,8 +211,8 @@ FORCE_INLINE_ATTR bool timer_ll_get_auto_reload(timg_dev_t *hw, timer_idx_t time */ FORCE_INLINE_ATTR void timer_ll_set_alarm_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t alarm_value) { - hw->hw_timer[timer_num].alarm_high.alarm_hi = (uint32_t) (alarm_value >> 32); - hw->hw_timer[timer_num].alarm_low = (uint32_t) alarm_value; + hw->hw_timer[timer_num].alarmhi.tx_alarm_hi = (uint32_t) (alarm_value >> 32); + hw->hw_timer[timer_num].alarmlo.tx_alarm_lo = (uint32_t) alarm_value; } /** @@ -224,7 +226,7 @@ FORCE_INLINE_ATTR void timer_ll_set_alarm_value(timg_dev_t *hw, timer_idx_t time */ static inline void timer_ll_get_alarm_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t *alarm_value) { - *alarm_value = ((uint64_t) hw->hw_timer[timer_num].alarm_high.alarm_hi << 32) | (hw->hw_timer[timer_num].alarm_low); + *alarm_value = ((uint64_t) hw->hw_timer[timer_num].alarmhi.tx_alarm_hi << 32) | (hw->hw_timer[timer_num].alarmlo.tx_alarm_lo); } /** @@ -238,7 +240,7 @@ static inline void timer_ll_get_alarm_value(timg_dev_t *hw, timer_idx_t timer_nu */ FORCE_INLINE_ATTR void timer_ll_set_alarm_enable(timg_dev_t *hw, timer_idx_t timer_num, bool alarm_en) { - hw->hw_timer[timer_num].config.alarm_en = alarm_en; + hw->hw_timer[timer_num].config.tx_alarm_en = alarm_en; } /** @@ -253,7 +255,7 @@ FORCE_INLINE_ATTR void timer_ll_set_alarm_enable(timg_dev_t *hw, timer_idx_t tim */ static inline bool timer_ll_get_alarm_enable(timg_dev_t *hw, timer_idx_t timer_num) { - return hw->hw_timer[timer_num].config.alarm_en; + return hw->hw_timer[timer_num].config.tx_alarm_en; } /** @@ -266,7 +268,7 @@ static inline bool timer_ll_get_alarm_enable(timg_dev_t *hw, timer_idx_t timer_n */ FORCE_INLINE_ATTR void timer_ll_intr_enable(timg_dev_t *hw, timer_idx_t timer_num) { - hw->int_ena.val |= BIT(timer_num); + hw->int_ena_timers.val |= BIT(timer_num); } /** @@ -279,7 +281,7 @@ FORCE_INLINE_ATTR void timer_ll_intr_enable(timg_dev_t *hw, timer_idx_t timer_nu */ FORCE_INLINE_ATTR void timer_ll_intr_disable(timg_dev_t *hw, timer_idx_t timer_num) { - hw->int_ena.val &= (~BIT(timer_num)); + hw->int_ena_timers.val &= (~BIT(timer_num)); } /** @@ -292,7 +294,7 @@ FORCE_INLINE_ATTR void timer_ll_intr_disable(timg_dev_t *hw, timer_idx_t timer_n */ FORCE_INLINE_ATTR void timer_ll_clear_intr_status(timg_dev_t *hw, timer_idx_t timer_num) { - hw->int_clr.val |= BIT(timer_num); + hw->int_clr_timers.val |= BIT(timer_num); } /** @@ -305,7 +307,7 @@ FORCE_INLINE_ATTR void timer_ll_clear_intr_status(timg_dev_t *hw, timer_idx_t ti */ FORCE_INLINE_ATTR void timer_ll_get_intr_status(timg_dev_t *hw, uint32_t *intr_status) { - *intr_status = hw->int_st.val & 0x01; + *intr_status = hw->int_st_timers.val & 0x01; } /** @@ -319,7 +321,7 @@ FORCE_INLINE_ATTR void timer_ll_get_intr_status(timg_dev_t *hw, uint32_t *intr_s FORCE_INLINE_ATTR void timer_ll_get_intr_raw_status(timer_group_t group_num, uint32_t *intr_raw_status) { timg_dev_t *hw = TIMER_LL_GET_HW(group_num); - *intr_raw_status = hw->int_raw.val & 0x01; + *intr_raw_status = hw->int_raw_timers.val & 0x01; } /** @@ -391,7 +393,7 @@ static inline bool timer_ll_get_edge_int_enable(timg_dev_t *hw, timer_idx_t time */ static inline uint32_t timer_ll_get_intr_status_reg(timg_dev_t *hw) { - return (uint32_t) & (hw->int_st.val); + return (uint32_t) & (hw->int_st_timers.val); } static inline uint32_t timer_ll_get_intr_mask_bit(timg_dev_t *hw, timer_idx_t timer_num) @@ -409,7 +411,7 @@ static inline uint32_t timer_ll_get_intr_mask_bit(timg_dev_t *hw, timer_idx_t ti */ static inline void timer_ll_set_use_xtal(timg_dev_t *hw, timer_idx_t timer_num, bool use_xtal_en) { - hw->hw_timer[timer_num].config.use_xtal = use_xtal_en; + hw->hw_timer[timer_num].config.tx_use_xtal = use_xtal_en; } /** @@ -423,7 +425,7 @@ static inline void timer_ll_set_use_xtal(timg_dev_t *hw, timer_idx_t timer_num, */ static inline bool timer_ll_get_use_xtal(timg_dev_t *hw, timer_idx_t timer_num) { - return hw->hw_timer[timer_num].config.use_xtal; + return hw->hw_timer[timer_num].config.tx_use_xtal; } #ifdef __cplusplus diff --git a/components/hal/esp32c3/include/hal/twai_ll.h b/components/hal/esp32c3/include/hal/twai_ll.h index 92e0401118..371d4dd361 100644 --- a/components/hal/esp32c3/include/hal/twai_ll.h +++ b/components/hal/esp32c3/include/hal/twai_ll.h @@ -31,6 +31,7 @@ extern "C" { #include "hal/misc.h" #include "hal/twai_types.h" #include "soc/twai_periph.h" +#include "soc/twai_struct.h" /* ------------------------- Defines and Typedefs --------------------------- */ @@ -399,7 +400,7 @@ static inline void twai_ll_clear_err_code_cap(twai_dev_t *hw) */ static inline void twai_ll_set_err_warn_lim(twai_dev_t *hw, uint32_t ewl) { - hw->error_warning_limit_reg.ewl = ewl; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->error_warning_limit_reg, ewl, ewl); } /** @@ -439,7 +440,7 @@ static inline uint32_t twai_ll_get_rec(twai_dev_t *hw) */ static inline void twai_ll_set_rec(twai_dev_t *hw, uint32_t rec) { - hw->rx_error_counter_reg.rxerr = rec; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_error_counter_reg, rxerr, rec); } /* ------------------------ TX Error Count Register ------------------------- */ @@ -467,7 +468,7 @@ static inline uint32_t twai_ll_get_tec(twai_dev_t *hw) */ static inline void twai_ll_set_tec(twai_dev_t *hw, uint32_t tec) { - hw->tx_error_counter_reg.txerr = tec; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_error_counter_reg, txerr, tec); } /* ---------------------- Acceptance Filter Registers ----------------------- */ @@ -486,8 +487,8 @@ static inline void twai_ll_set_acc_filter(twai_dev_t* hw, uint32_t code, uint32_ uint32_t code_swapped = HAL_SWAP32(code); uint32_t mask_swapped = HAL_SWAP32(mask); for (int i = 0; i < 4; i++) { - hw->acceptance_filter.acr[i].byte = ((code_swapped >> (i * 8)) & 0xFF); - hw->acceptance_filter.amr[i].byte = ((mask_swapped >> (i * 8)) & 0xFF); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->acceptance_filter.acr[i], byte, ((code_swapped >> (i * 8)) & 0xFF)); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->acceptance_filter.amr[i], byte, ((mask_swapped >> (i * 8)) & 0xFF)); } hw->mode_reg.afm = single_filter; } @@ -522,7 +523,7 @@ static inline void twai_ll_get_rx_buffer(twai_dev_t *hw, twai_ll_frame_buffer_t { //Copy RX buffer registers into frame for (int i = 0; i < 13; i++) { - rx_frame->bytes[i] = hw->tx_rx_buffer[i].byte; + rx_frame->bytes[i] = HAL_FORCE_READ_U32_REG_FIELD(hw->tx_rx_buffer[i], byte); } } @@ -652,14 +653,14 @@ static inline void twai_ll_set_clkout(twai_dev_t *hw, uint32_t divider) { if (divider >= 2 && divider <= 490) { hw->clock_divider_reg.co = 0; - hw->clock_divider_reg.cd = (divider / 2) - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clock_divider_reg, cd, (divider / 2) - 1); } else if (divider == 1) { //Setting the divider reg to max value (255) means a divider of 1 hw->clock_divider_reg.co = 0; - hw->clock_divider_reg.cd = 255; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clock_divider_reg, cd, 255); } else { hw->clock_divider_reg.co = 1; - hw->clock_divider_reg.cd = 0; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clock_divider_reg, cd, 0); } } diff --git a/components/hal/esp32c3/include/hal/uart_ll.h b/components/hal/esp32c3/include/hal/uart_ll.h index 344a6ecc42..f94296327a 100644 --- a/components/hal/esp32c3/include/hal/uart_ll.h +++ b/components/hal/esp32c3/include/hal/uart_ll.h @@ -17,8 +17,11 @@ #pragma once + +#include "hal/misc.h" #include "hal/uart_types.h" #include "soc/uart_periph.h" +#include "soc/uart_struct.h" #ifdef __cplusplus extern "C" { @@ -163,7 +166,7 @@ static inline void uart_ll_set_baudrate(uart_dev_t *hw, uint32_t baud) // an integer part and a fractional part. hw->clk_div.div_int = clk_div >> 4; hw->clk_div.div_frag = clk_div & 0xf; - hw->clk_conf.sclk_div_num = sclk_div - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clk_conf, sclk_div_num, sclk_div - 1); #undef DIV_UP } @@ -178,7 +181,7 @@ static inline uint32_t uart_ll_get_baudrate(uart_dev_t *hw) { uint32_t sclk_freq = uart_ll_get_sclk_freq(hw); typeof(hw->clk_div) div_reg = hw->clk_div; - return ((sclk_freq << 4)) / (((div_reg.div_int << 4) | div_reg.div_frag) * (hw->clk_conf.sclk_div_num + 1)); + return ((sclk_freq << 4)) / (((div_reg.div_int << 4) | div_reg.div_frag) * (HAL_FORCE_READ_U32_REG_FIELD(hw->clk_conf, sclk_div_num) + 1)); } /** @@ -451,7 +454,7 @@ static inline void uart_ll_set_tx_idle_num(uart_dev_t *hw, uint32_t idle_num) static inline void uart_ll_tx_break(uart_dev_t *hw, uint32_t break_num) { if (break_num > 0) { - hw->txbrk_conf.tx_brk_num = break_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->txbrk_conf, tx_brk_num, break_num); hw->conf0.txd_brk = 1; } else { hw->conf0.txd_brk = 0; @@ -518,8 +521,8 @@ static inline void uart_ll_set_sw_flow_ctrl(uart_dev_t *hw, uart_sw_flowctrl_t * hw->flow_conf.sw_flow_con_en = 1; hw->swfc_conf1.xon_threshold = flow_ctrl->xon_thrd; hw->swfc_conf0.xoff_threshold = flow_ctrl->xoff_thrd; - hw->swfc_conf1.xon_char = flow_ctrl->xon_char; - hw->swfc_conf0.xoff_char = flow_ctrl->xoff_char; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->swfc_conf1, xon_char, flow_ctrl->xon_char); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->swfc_conf0, xoff_char, flow_ctrl->xoff_char); } else { hw->flow_conf.sw_flow_con_en = 0; hw->flow_conf.xonoff_del = 0; @@ -541,11 +544,11 @@ static inline void uart_ll_set_sw_flow_ctrl(uart_dev_t *hw, uart_sw_flowctrl_t * */ static inline void uart_ll_set_at_cmd_char(uart_dev_t *hw, uart_at_cmd_t *cmd_char) { - hw->at_cmd_char.data = cmd_char->cmd_char; - hw->at_cmd_char.char_num = cmd_char->char_num; - hw->at_cmd_postcnt.post_idle_num = cmd_char->post_idle; - hw->at_cmd_precnt.pre_idle_num = cmd_char->pre_idle; - hw->at_cmd_gaptout.rx_gap_tout = cmd_char->gap_tout; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_char, data, cmd_char->cmd_char); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_char, char_num, cmd_char->char_num); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_postcnt, post_idle_num, cmd_char->post_idle); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_precnt, pre_idle_num, cmd_char->pre_idle); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_gaptout, rx_gap_tout, cmd_char->gap_tout); } /** @@ -734,8 +737,8 @@ static inline void uart_ll_set_mode(uart_dev_t *hw, uart_mode_t mode) */ static inline void uart_ll_get_at_cmd_char(uart_dev_t *hw, uint8_t *cmd_char, uint8_t *char_num) { - *cmd_char = hw->at_cmd_char.data; - *char_num = hw->at_cmd_char.char_num; + *cmd_char = HAL_FORCE_READ_U32_REG_FIELD(hw->at_cmd_char, data); + *char_num = HAL_FORCE_READ_U32_REG_FIELD(hw->at_cmd_char, char_num); } /** diff --git a/components/hal/esp32c3/include/hal/uhci_ll.h b/components/hal/esp32c3/include/hal/uhci_ll.h index 235d28ab3a..a766797ea0 100644 --- a/components/hal/esp32c3/include/hal/uhci_ll.h +++ b/components/hal/esp32c3/include/hal/uhci_ll.h @@ -18,9 +18,13 @@ #pragma once #include -#include "uhci_types.h" +#include "hal/uhci_types.h" #include "soc/uhci_struct.h" +#ifdef __cplusplus +extern "C" { +#endif + #define UHCI_LL_GET_HW(num) (((num) == 0) ? (&UHCI0) : (NULL)) typedef enum { @@ -128,3 +132,7 @@ static inline void uhci_ll_set_eof_mode(uhci_dev_t *hw, uint32_t eof_mode) hw->conf0.len_eof_en = 1; } } + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32c3/include/hal/xt_wdt_ll.h b/components/hal/esp32c3/include/hal/xt_wdt_ll.h new file mode 100644 index 0000000000..65b36253e5 --- /dev/null +++ b/components/hal/esp32c3/include/hal/xt_wdt_ll.h @@ -0,0 +1,101 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// The LL layer for xtal32k WDT register operations. +// Note that most of the register operations in this layer are non-atomic operations. + +#pragma once + +#include +#include "soc/rtc_cntl_periph.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define XT_WDT_LL_XTAL32_DEAD_INTR_MASK RTC_CNTL_XTAL32K_DEAD_INT_ST_M + +/** + * @brief Enable the XT_WDT + * + * @param hw Start address of the peripheral registers. + */ +inline void xt_wdt_ll_enable(rtc_cntl_dev_t *hw, bool enable) +{ + hw->ext_xtl_conf.xtal32k_wdt_en = enable; +} + +/** + * @brief Check if the XT_WDT is enabled + * + * @param hw Start address of the peripheral registers. + * @return True if XT WDT is enabled + */ +inline bool xt_wdt_ll_check_if_enabled(rtc_cntl_dev_t *hw) +{ + return (hw->ext_xtl_conf.xtal32k_wdt_en) ? true : false; +} + +/** + * @brief Set the watchdog timeout value + * + * @param hw Start address of the peripheral registers. + * @param timeout timeout value in RTC_CLK cycles + */ +inline void xt_wdt_ll_set_timeout(rtc_cntl_dev_t *hw, uint8_t timeout) +{ + hw->xtal32k_conf.xtal32k_wdt_timeout = timeout; +} + + +/** + * @brief Reset the XT_WDT + * + * @param hw Start address of the peripheral registers. + */ +inline void xt_wdt_ll_reset(rtc_cntl_dev_t *hw) +{ + hw->ext_xtl_conf.xtal32k_wdt_reset = 1; + hw->ext_xtl_conf.xtal32k_wdt_reset = 0; +} + + +/** + * @brief Set the backup clock value + * + * @param hw Start address of the peripheral registers. + * @param backup_clk_val Backup clock value, see TRM for definition + */ +inline void xt_wdt_ll_set_backup_clk_factor(rtc_cntl_dev_t *hw, uint32_t backup_clk_val) +{ + hw->xtal32k_clk_factor = backup_clk_val; +} + +/** + * @brief Enable the auto-backup clock feature + * + * @param hw Start address of the peripheral registers. + * @param enable True - enable, False - disable + */ +inline void xt_wdt_ll_auto_backup_enable(rtc_cntl_dev_t *hw, bool enable) +{ + hw->ext_xtl_conf.xtal32k_auto_backup = enable; +} + +/** + * @brief Enable the timeout interrupt + * + * @param hw Start address of the peripheral registers. + * @param enable True - enable, False - disable + */ +inline void xt_wdt_ll_intr_enable(rtc_cntl_dev_t *hw, bool enable) +{ + hw->int_ena.rtc_xtal32k_dead = enable; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32c3/rtc_cntl_hal.c b/components/hal/esp32c3/rtc_cntl_hal.c index 2fb14a5b2f..90b2e9d083 100644 --- a/components/hal/esp32c3/rtc_cntl_hal.c +++ b/components/hal/esp32c3/rtc_cntl_hal.c @@ -16,8 +16,10 @@ #include "soc/soc_caps.h" #include "soc/lldesc.h" +#include "hal/dma_types.h" #include "hal/rtc_hal.h" #include "hal/assert.h" +#include "esp_attr.h" #define RTC_CNTL_HAL_LINK_BUF_SIZE_MIN (SOC_RTC_CNTL_CPU_PD_DMA_BLOCK_SIZE) /* The minimum size of dma link buffer */ @@ -34,7 +36,7 @@ void * rtc_cntl_hal_dma_link_init(void *elem, void *buff, int size, void *next) lldesc_t *plink = (lldesc_t *)elem; plink->eof = next ? 0 : 1; - plink->owner = 1; + plink->owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA; plink->size = size >> 4; /* in unit of 16 bytes */ plink->length = size >> 4; plink->buf = buff; @@ -44,18 +46,39 @@ void * rtc_cntl_hal_dma_link_init(void *elem, void *buff, int size, void *next) return (void *)plink; } +#if SOC_PM_SUPPORT_CPU_PD + void rtc_cntl_hal_enable_cpu_retention(void *addr) { + rtc_cntl_sleep_retent_t *retent = (rtc_cntl_sleep_retent_t *)addr; + if (addr) { - lldesc_t *plink = (lldesc_t *)addr; + if (retent->cpu_pd_mem) { + lldesc_t *plink = (lldesc_t *)retent->cpu_pd_mem; - /* dma link buffer configure */ - rtc_cntl_link_buf_conf_t *pbuf = (rtc_cntl_link_buf_conf_t *)plink->buf; - pbuf->cfg[0] = 0; - pbuf->cfg[1] = 0; - pbuf->cfg[2] = 0; - pbuf->cfg[3] = (uint32_t)-1; + /* dma link buffer configure */ + rtc_cntl_link_buf_conf_t *pbuf = (rtc_cntl_link_buf_conf_t *)plink->buf; + pbuf->cfg[0] = 0; + pbuf->cfg[1] = 0; + pbuf->cfg[2] = 0; + pbuf->cfg[3] = (uint32_t)-1; - rtc_cntl_ll_enable_cpu_retention((uint32_t)addr); + rtc_cntl_ll_set_cpu_retention_link_addr((uint32_t)plink); + rtc_cntl_ll_enable_cpu_retention_clock(); + rtc_cntl_ll_enable_cpu_retention(); + } } } + +void IRAM_ATTR rtc_cntl_hal_disable_cpu_retention(void *addr) +{ + rtc_cntl_sleep_retent_t *retent = (rtc_cntl_sleep_retent_t *)addr; + + if (addr) { + if (retent->cpu_pd_mem) { + rtc_cntl_ll_disable_cpu_retention(); + } + } +} + +#endif // SOC_PM_SUPPORT_CPU_PD diff --git a/components/hal/esp32h2/brownout_hal.c b/components/hal/esp32h2/brownout_hal.c index 5dac36f067..f60410b490 100644 --- a/components/hal/esp32h2/brownout_hal.c +++ b/components/hal/esp32h2/brownout_hal.c @@ -17,12 +17,13 @@ #include "soc/rtc_cntl_struct.h" #include "soc/rtc_cntl_reg.h" #include "regi2c_ctrl.h" +#include "i2c_pmu.h" #include "regi2c_brownout.h" void brownout_hal_config(const brownout_hal_config_t *cfg) { - REGI2C_WRITE_MASK(I2C_BOD, I2C_BOD_THRESHOLD, cfg->threshold); + REGI2C_WRITE_MASK(I2C_PMU, I2C_PMU_OC_DREF_LVDET, cfg->threshold); typeof(RTCCNTL.brown_out) brown_out_reg = { .close_flash_ena = cfg->flash_power_down, .pd_rf_ena = cfg->rf_power_down, diff --git a/components/hal/esp32h2/include/hal/adc_ll.h b/components/hal/esp32h2/include/hal/adc_ll.h index 6e6ce7c2fc..7806465258 100644 --- a/components/hal/esp32h2/include/hal/adc_ll.h +++ b/components/hal/esp32h2/include/hal/adc_ll.h @@ -24,6 +24,7 @@ #include "soc/apb_saradc_reg.h" #include "soc/rtc_cntl_struct.h" #include "soc/rtc_cntl_reg.h" +#include "hal/misc.h" #ifdef __cplusplus extern "C" { @@ -94,11 +95,11 @@ typedef enum { static inline void adc_ll_digi_set_fsm_time(uint32_t rst_wait, uint32_t start_wait, uint32_t standby_wait) { // Internal FSM reset wait time - APB_SARADC.fsm_wait.rstb_wait = rst_wait; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.fsm_wait, rstb_wait, rst_wait); // Internal FSM start wait time - APB_SARADC.fsm_wait.xpd_wait = start_wait; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.fsm_wait, xpd_wait, start_wait); // Internal FSM standby wait time - APB_SARADC.fsm_wait.standby_wait = standby_wait; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.fsm_wait, standby_wait, standby_wait); } /** @@ -124,7 +125,7 @@ static inline void adc_ll_set_sample_cycle(uint32_t sample_cycle) static inline void adc_ll_digi_set_clk_div(uint32_t div) { /* ADC clock devided from digital controller clock clk */ - APB_SARADC.ctrl.sar_clk_div = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.ctrl, sar_clk_div, div); } /** @@ -135,7 +136,7 @@ static inline void adc_ll_digi_set_clk_div(uint32_t div) */ static inline void adc_ll_digi_set_convert_limit_num(uint32_t meas_num) { - APB_SARADC.ctrl2.max_meas_num = meas_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.ctrl2, max_meas_num, meas_num); } /** @@ -267,7 +268,7 @@ static inline void adc_ll_digi_trigger_disable(void) */ static inline void adc_ll_digi_controller_clk_div(uint32_t div_num, uint32_t div_b, uint32_t div_a) { - APB_SARADC.apb_adc_clkm_conf.clkm_div_num = div_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.apb_adc_clkm_conf, clkm_div_num, div_num); APB_SARADC.apb_adc_clkm_conf.clkm_div_b = div_b; APB_SARADC.apb_adc_clkm_conf.clkm_div_a = div_a; } @@ -404,7 +405,7 @@ static inline void adc_ll_digi_monitor_disable(adc_digi_monitor_idx_t idx) */ static inline void adc_ll_digi_dma_set_eof_num(uint32_t num) { - APB_SARADC.dma_conf.apb_adc_eof_num = num; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.dma_conf, apb_adc_eof_num, num); } /** diff --git a/components/hal/esp32h2/include/hal/aes_ll.h b/components/hal/esp32h2/include/hal/aes_ll.h index 0eb7fabc64..e18c44e58e 100644 --- a/components/hal/esp32h2/include/hal/aes_ll.h +++ b/components/hal/esp32h2/include/hal/aes_ll.h @@ -1,4 +1,4 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// Copyright 2020-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. @@ -15,6 +15,7 @@ #pragma once #include +#include #include "soc/hwcrypto_reg.h" #include "hal/aes_types.h" @@ -39,16 +40,17 @@ typedef enum { * @param key Key to be written to the AES hardware * @param key_word_len Number of words in the key * - * @return volatile number of bytes written to hardware, used for fault injection check + * @return Number of bytes written to hardware, used for fault injection check */ static inline uint8_t aes_ll_write_key(const uint8_t *key, size_t key_word_len) { /* This variable is used for fault injection checks, so marked volatile to avoid optimisation */ volatile uint8_t key_in_hardware = 0; - uint32_t *key_words = (uint32_t *)key; - + /* Memcpy to avoid potential unaligned access */ + uint32_t key_word; for (int i = 0; i < key_word_len; i++) { - REG_WRITE(AES_KEY_BASE + i * 4, *(key_words + i)); + memcpy(&key_word, key + 4 * i, 4); + REG_WRITE(AES_KEY_BASE + i * 4, key_word); key_in_hardware += 4; } return key_in_hardware; @@ -76,22 +78,12 @@ static inline void aes_ll_set_mode(int mode, uint8_t key_bytes) */ static inline void aes_ll_write_block(const void *input) { - const uint32_t *input_words = (const uint32_t *)input; - uint32_t i0, i1, i2, i3; + uint32_t input_word; - /* Storing i0,i1,i2,i3 in registers, not in an array - helps a lot with optimisations at -Os level */ - i0 = input_words[0]; - REG_WRITE(AES_TEXT_IN_BASE, i0); - - i1 = input_words[1]; - REG_WRITE(AES_TEXT_IN_BASE + 4, i1); - - i2 = input_words[2]; - REG_WRITE(AES_TEXT_IN_BASE + 8, i2); - - i3 = input_words[3]; - REG_WRITE(AES_TEXT_IN_BASE + 12, i3); + for (int i = 0; i < AES_BLOCK_WORDS; i++) { + memcpy(&input_word, (uint8_t*)input + 4 * i, 4); + REG_WRITE(AES_TEXT_IN_BASE + i * 4, input_word); + } } /** @@ -101,11 +93,13 @@ static inline void aes_ll_write_block(const void *input) */ static inline void aes_ll_read_block(void *output) { - uint32_t *output_words = (uint32_t *)output; + uint32_t output_word; const size_t REG_WIDTH = sizeof(uint32_t); for (size_t i = 0; i < AES_BLOCK_WORDS; i++) { - output_words[i] = REG_READ(AES_TEXT_OUT_BASE + (i * REG_WIDTH)); + output_word = REG_READ(AES_TEXT_OUT_BASE + (i * REG_WIDTH)); + /* Memcpy to avoid potential unaligned access */ + memcpy( (uint8_t*)output + i * 4, &output_word, sizeof(output_word)); } } @@ -179,11 +173,13 @@ static inline void aes_ll_set_num_blocks(size_t num_blocks) */ static inline void aes_ll_set_iv(const uint8_t *iv) { - uint32_t *iv_words = (uint32_t *)iv; uint32_t *reg_addr_buf = (uint32_t *)(AES_IV_BASE); + uint32_t iv_word; for (int i = 0; i < IV_WORDS; i++ ) { - REG_WRITE(®_addr_buf[i], iv_words[i]); + /* Memcpy to avoid potential unaligned access */ + memcpy(&iv_word, iv + 4 * i, sizeof(iv_word)); + REG_WRITE(®_addr_buf[i], iv_word); } } @@ -192,11 +188,13 @@ static inline void aes_ll_set_iv(const uint8_t *iv) */ static inline void aes_ll_read_iv(uint8_t *iv) { - uint32_t *iv_words = (uint32_t *)iv; + uint32_t iv_word; const size_t REG_WIDTH = sizeof(uint32_t); for (size_t i = 0; i < IV_WORDS; i++) { - iv_words[i] = REG_READ(AES_IV_BASE + (i * REG_WIDTH)); + iv_word = REG_READ(AES_IV_BASE + (i * REG_WIDTH)); + /* Memcpy to avoid potential unaligned access */ + memcpy(iv + i * 4, &iv_word, sizeof(iv_word)); } } diff --git a/components/hal/esp32h2/include/hal/cpu_ll.h b/components/hal/esp32h2/include/hal/cpu_ll.h index 0b05675d32..dec049a30c 100644 --- a/components/hal/esp32h2/include/hal/cpu_ll.h +++ b/components/hal/esp32h2/include/hal/cpu_ll.h @@ -26,6 +26,11 @@ #define CSR_PCMR_MACHINE 0x7e1 #define CSR_PCCR_MACHINE 0x7e2 +/*fast gpio*/ +#define CSR_GPIO_OEN_USER 0x803 +#define CSR_GPIO_IN_USER 0x804 +#define CSR_GPIO_OUT_USER 0x805 + #ifdef __cplusplus extern "C" { #endif @@ -135,7 +140,7 @@ static inline void cpu_ll_clear_watchpoint(int id) FORCE_INLINE_ATTR bool cpu_ll_is_debugger_attached(void) { - return REG_GET_BIT(ASSIST_DEBUG_C0RE_0_DEBUG_MODE_REG, ASSIST_DEBUG_CORE_0_DEBUG_MODULE_ACTIVE); + return REG_GET_BIT(ASSIST_DEBUG_CORE_0_DEBUG_MODE_REG, ASSIST_DEBUG_CORE_0_DEBUG_MODULE_ACTIVE); } static inline void cpu_ll_break(void) @@ -156,6 +161,34 @@ static inline void cpu_ll_waiti(void) asm volatile ("wfi\n"); } +static inline void cpu_ll_enable_dedic_gpio_output(uint32_t mask) +{ + RV_WRITE_CSR(CSR_GPIO_OEN_USER, mask); +} + +static inline void cpu_ll_write_dedic_gpio_all(uint32_t value) +{ + RV_WRITE_CSR(CSR_GPIO_OUT_USER, value); +} + +static inline uint32_t cpu_ll_read_dedic_gpio_in(void) +{ + uint32_t value = RV_READ_CSR(CSR_GPIO_IN_USER); + return value; +} + +static inline uint32_t cpu_ll_read_dedic_gpio_out(void) +{ + uint32_t value = RV_READ_CSR(CSR_GPIO_OUT_USER); + return value; +} + +static inline void cpu_ll_write_dedic_gpio_mask(uint32_t mask, uint32_t value) +{ + RV_SET_CSR(CSR_GPIO_OUT_USER, mask & value); + RV_CLEAR_CSR(CSR_GPIO_OUT_USER, mask & ~(value)); +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32h2/include/hal/gpio_ll.h b/components/hal/esp32h2/include/hal/gpio_ll.h index e35a71db39..c6d751847c 100644 --- a/components/hal/esp32h2/include/hal/gpio_ll.h +++ b/components/hal/esp32h2/include/hal/gpio_ll.h @@ -25,6 +25,7 @@ #include "soc/soc.h" #include "soc/gpio_periph.h" #include "soc/rtc_cntl_reg.h" +#include "soc/gpio_struct.h" #include "hal/gpio_types.h" #include "stdlib.h" diff --git a/components/hal/esp32h2/include/hal/gpspi_flash_ll.h b/components/hal/esp32h2/include/hal/gpspi_flash_ll.h index d26e00c720..d6b227e6f6 100644 --- a/components/hal/esp32h2/include/hal/gpspi_flash_ll.h +++ b/components/hal/esp32h2/include/hal/gpspi_flash_ll.h @@ -24,11 +24,13 @@ #include #include "soc/spi_periph.h" +#include "soc/spi_struct.h" #include "hal/spi_types.h" #include "hal/spi_flash_types.h" #include // For MIN/MAX #include #include +#include "hal/misc.h" #ifdef __cplusplus extern "C" { @@ -363,7 +365,7 @@ static inline void gpspi_flash_ll_set_address(spi_dev_t *dev, uint32_t addr) static inline void gpspi_flash_ll_set_dummy(spi_dev_t *dev, uint32_t dummy_n) { dev->user.usr_dummy = dummy_n ? 1 : 0; - dev->user1.usr_dummy_cyclelen = dummy_n - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user1, usr_dummy_cyclelen, dummy_n - 1); } /** diff --git a/components/hal/esp32h2/include/hal/i2c_ll.h b/components/hal/esp32h2/include/hal/i2c_ll.h index 88d4493b0e..2e34e4a55c 100644 --- a/components/hal/esp32h2/include/hal/i2c_ll.h +++ b/components/hal/esp32h2/include/hal/i2c_ll.h @@ -15,8 +15,11 @@ // The LL layer for I2C register operations #pragma once + +#include "hal/misc.h" #include "soc/i2c_periph.h" #include "soc/soc_caps.h" +#include "soc/i2c_struct.h" #include "hal/i2c_types.h" #include "soc/rtc_cntl_reg.h" #include "esp_rom_sys.h" @@ -154,7 +157,7 @@ static inline void i2c_ll_update(i2c_dev_t *hw) */ static inline void i2c_ll_set_bus_timing(i2c_dev_t *hw, i2c_clk_cal_t *bus_cfg) { - hw->clk_conf.sclk_div_num = bus_cfg->clkm_div - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clk_conf, sclk_div_num, bus_cfg->clkm_div - 1); //scl period hw->scl_low_period.period = bus_cfg->scl_low - 1; hw->scl_high_period.period = bus_cfg->scl_high; @@ -576,7 +579,7 @@ static inline void i2c_ll_get_scl_timing(i2c_dev_t *hw, int *high_period, int *l static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len) { for (int i = 0; i< len; i++) { - hw->fifo_data.data = ptr[i]; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->fifo_data, data, ptr[i]); } } @@ -592,7 +595,7 @@ static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len) static inline void i2c_ll_read_rxfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len) { for(int i = 0; i < len; i++) { - ptr[i] = hw->fifo_data.data; + ptr[i] = HAL_FORCE_READ_U32_REG_FIELD(hw->fifo_data, data); } } diff --git a/components/hal/esp32h2/include/hal/i2s_ll.h b/components/hal/esp32h2/include/hal/i2s_ll.h index c54d7de83a..e241ac2185 100644 --- a/components/hal/esp32h2/include/hal/i2s_ll.h +++ b/components/hal/esp32h2/include/hal/i2s_ll.h @@ -18,501 +18,181 @@ * See readme.md in soc/include/hal/readme.md ******************************************************************************/ -// The LL layer for ESP32-S3 I2S register operations +// The LL layer for ESP32-H2 I2S register operations #pragma once - #include -#include +#include "hal/misc.h" #include "soc/i2s_periph.h" +#include "soc/i2s_struct.h" #include "hal/i2s_types.h" #ifdef __cplusplus extern "C" { #endif -// Get I2S hardware instance with giving i2s num -#define I2S_LL_GET_HW(num) (((num) == 0) ? (&I2S0) : NULL) +#define I2S_LL_GET_HW(num) (&I2S0) -#define I2S_INTR_IN_SUC_EOF BIT(9) -#define I2S_INTR_OUT_EOF BIT(12) -#define I2S_INTR_IN_DSCR_ERR BIT(13) -#define I2S_INTR_OUT_DSCR_ERR BIT(14) -#define I2S_INTR_MAX (0xFFFFFFFF) +#define I2S_LL_TDM_CH_MASK (0xffff) +#define I2S_LL_PDM_BCK_FACTOR (64) +#define I2S_LL_BASE_CLK (2*APB_CLK_FREQ) + +#define I2S_LL_MCLK_DIVIDER_BIT_WIDTH (9) +#define I2S_LL_MCLK_DIVIDER_MAX ((1 << I2S_LL_MCLK_DIVIDER_BIT_WIDTH) - 1) + +/* I2S clock configuration structure */ +typedef struct { + uint16_t mclk_div; // I2S module clock devider, Fmclk = Fsclk /(mclk_div+b/a) + uint16_t a; + uint16_t b; // The decimal part of module clock devider, the decimal is: b/a +} i2s_ll_mclk_div_t; /** - * @brief Reset rx fifo + * @brief I2S module general init, enable I2S clock. * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_rx_fifo(i2s_dev_t *hw) +static inline void i2s_ll_enable_clock(i2s_dev_t *hw) { - abort(); // TODO ESP32-H2 IDF-2098 - - + hw->tx_clkm_conf.clk_en = 1; } /** - * @brief Reset tx fifo + * @brief I2S module disable I2S clock. * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_tx_fifo(i2s_dev_t *hw) +static inline void i2s_ll_disable_clock(i2s_dev_t *hw) { - abort(); // TODO ESP32-H2 IDF-2098 - - + hw->tx_clkm_conf.clk_en = 0; } /** - * @brief Enable rx interrupt + * @brief Enable I2S tx module clock * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_enable_rx_intr(i2s_dev_t *hw) +static inline void i2s_ll_tx_enable_clock(i2s_dev_t *hw) { - abort(); // TODO ESP32-H2 IDF-2098 - - + hw->tx_clkm_conf.tx_clk_active = 1; } /** - * @brief Disable rx interrupt + * @brief Enable I2S rx module clock * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_disable_rx_intr(i2s_dev_t *hw) +static inline void i2s_ll_rx_enable_clock(i2s_dev_t *hw) { - abort(); // TODO ESP32-H2 IDF-2098 - - + hw->rx_clkm_conf.rx_clk_active = 1; } /** - * @brief Disable tx interrupt + * @brief I2S mclk use tx module clock * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_disable_tx_intr(i2s_dev_t *hw) +static inline void i2s_ll_mclk_use_tx_clk(i2s_dev_t *hw) { - abort(); // TODO ESP32-H2 IDF-2098 - - + hw->rx_clkm_conf.mclk_sel = 0; } /** - * @brief Enable tx interrupt + * @brief I2S mclk use rx module clock * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_enable_tx_intr(i2s_dev_t *hw) +static inline void i2s_ll_mclk_use_rx_clk(i2s_dev_t *hw) { - abort(); // TODO ESP32-H2 IDF-2098 - - + hw->rx_clkm_conf.mclk_sel = 1; } /** - * @brief Reset dma in + * @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_reset_dma_in(i2s_dev_t *hw) +static inline void i2s_ll_tx_set_slave_mod(i2s_dev_t *hw, bool slave_en) { - abort(); // TODO ESP32-H2 IDF-2098 - - + hw->tx_conf.tx_slave_mod = slave_en; } /** - * @brief Reset dma out + * @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_reset_dma_out(i2s_dev_t *hw) +static inline void i2s_ll_rx_set_slave_mod(i2s_dev_t *hw, bool slave_en) { - abort(); // TODO ESP32-H2 IDF-2098 - - + hw->rx_conf.rx_slave_mod = slave_en; } /** - * @brief Reset tx + * @brief Reset I2S TX module * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_tx(i2s_dev_t *hw) +static inline void i2s_ll_tx_reset(i2s_dev_t *hw) { - abort(); // TODO ESP32-H2 IDF-2098 - - + hw->tx_conf.tx_reset = 1; + hw->tx_conf.tx_reset = 0; } /** - * @brief Reset rx + * @brief Reset I2S RX module * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_rx(i2s_dev_t *hw) +static inline void i2s_ll_rx_reset(i2s_dev_t *hw) { - abort(); // TODO ESP32-H2 IDF-2098 - - + hw->rx_conf.rx_reset = 1; + hw->rx_conf.rx_reset = 0; } /** - * @brief Start out link + * @brief Reset I2S TX FIFO * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_start_out_link(i2s_dev_t *hw) +static inline void i2s_ll_tx_reset_fifo(i2s_dev_t *hw) { - abort(); // TODO ESP32-H2 IDF-2098 - + hw->tx_conf.tx_fifo_reset = 1; + hw->tx_conf.tx_fifo_reset = 0; } /** - * @brief Start tx + * @brief Reset I2S RX FIFO * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_start_tx(i2s_dev_t *hw) +static inline void i2s_ll_rx_reset_fifo(i2s_dev_t *hw) { - abort(); // TODO ESP32-H2 IDF-2098 - + hw->rx_conf.rx_fifo_reset = 1; + hw->rx_conf.rx_fifo_reset = 0; } /** - * @brief Start in link + * @brief Set TX source clock * * @param hw Peripheral I2S hardware instance address. + * @param src I2S source clock. */ -static inline void i2s_ll_start_in_link(i2s_dev_t *hw) +static inline void i2s_ll_tx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) { - abort(); // TODO ESP32-H2 IDF-2098 - + hw->tx_clkm_conf.tx_clk_sel = 2; } /** - * @brief Start rx + * @brief Set RX source clock * * @param hw Peripheral I2S hardware instance address. + * @param src I2S source clock, ESP32-H2 only support `I2S_CLK_D2CLK` */ -static inline void i2s_ll_start_rx(i2s_dev_t *hw) +static inline void i2s_ll_rx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) { - abort(); // TODO ESP32-H2 IDF-2098 - -} - -/** - * @brief Stop out link - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_stop_out_link(i2s_dev_t *hw) -{ - abort(); // TODO ESP32-H2 IDF-2098 - -} - -/** - * @brief Stop tx - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_stop_tx(i2s_dev_t *hw) -{ - abort(); // TODO ESP32-H2 IDF-2098 - -} - -/** - * @brief Stop in link - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_stop_in_link(i2s_dev_t *hw) -{ - abort(); // TODO ESP32-H2 IDF-2098 - -} - -/** - * @brief Stop rx - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_stop_rx(i2s_dev_t *hw) -{ - abort(); // TODO ESP32-H2 IDF-2098 - -} - -/** - * @brief Enable dma - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_enable_dma(i2s_dev_t *hw) -{ - abort(); // TODO ESP32-H2 IDF-2098 - // //Enable and configure DMA - // typeof(hw->lc_conf) lc_conf; - // lc_conf.val = 0; - // lc_conf.out_eof_mode = 1; - -} - -/** - * @brief Get I2S interrupt status - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get interrupt status - */ -static inline void i2s_ll_get_intr_status(i2s_dev_t *hw, uint32_t *val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - // *val = hw->int_st.val; -} - -/** - * @brief Clear I2S interrupt status - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to clear interrupt status - */ -static inline void i2s_ll_clear_intr_status(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - -} - -/** - * @brief Get I2S out eof des address - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get out eof des address - */ -static inline void i2s_ll_get_out_eof_des_addr(i2s_dev_t *hw, uint32_t *val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - // *val = hw->out_eof_des_addr; -} - -/** - * @brief Get I2S in eof des address - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get in eof des address - */ -static inline void i2s_ll_get_in_eof_des_addr(i2s_dev_t *hw, uint32_t *val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - // *val = hw->in_eof_des_addr; -} - -/** - * @brief Get I2S tx fifo mode - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get tx fifo mode - */ -static inline void i2s_ll_get_tx_fifo_mod(i2s_dev_t *hw, uint32_t *val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - // *val = hw->fifo_conf.tx_fifo_mod; -} - -/** - * @brief Set I2S tx fifo mode - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx fifo mode - */ -static inline void i2s_ll_set_tx_fifo_mod(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - -} - -/** - * @brief Get I2S rx fifo mode - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get rx fifo mode - */ -static inline void i2s_ll_get_rx_fifo_mod(i2s_dev_t *hw, uint32_t *val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - // *val = hw->fifo_conf.rx_fifo_mod; -} - -/** - * @brief Set I2S rx fifo mode - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx fifo mode - */ -static inline void i2s_ll_set_rx_fifo_mod(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - -} - -/** - * @brief Set I2S tx chan mode - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx chan mode - */ -static inline void i2s_ll_set_tx_chan_mod(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - -} - -/** - * @brief Set I2S rx chan mode - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx chan mode - */ -static inline void i2s_ll_set_rx_chan_mod(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - -} - -/** - * @brief Set I2S out link address - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set out link address - */ -static inline void i2s_ll_set_out_link_addr(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - -} - -/** - * @brief Set I2S in link address - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set in link address - */ -static inline void i2s_ll_set_in_link_addr(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - -} - -/** - * @brief Set I2S rx eof num - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx eof num - */ -static inline void i2s_ll_set_rx_eof_num(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - -} - -/** - * @brief Get I2S tx pdm fp - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get tx pdm fp - */ -static inline void i2s_ll_get_tx_pdm_fp(i2s_dev_t *hw, uint32_t *val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - // *val = hw->pdm_freq_conf.tx_pdm_fp; -} - -/** - * @brief Get I2S tx pdm fs - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get tx pdm fs - */ -static inline void i2s_ll_get_tx_pdm_fs(i2s_dev_t *hw, uint32_t *val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - // *val = hw->pdm_freq_conf.tx_pdm_fs; -} - -/** - * @brief Set I2S tx pdm fp - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx pdm fp - */ -static inline void i2s_ll_set_tx_pdm_fp(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - -} - -/** - * @brief Set I2S tx pdm fs - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx pdm fs - */ -static inline void i2s_ll_set_tx_pdm_fs(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - -} - -/** - * @brief Get I2S rx sinc dsr 16 en - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get rx sinc dsr 16 en - */ -static inline void i2s_ll_get_rx_sinc_dsr_16_en(i2s_dev_t *hw, bool *val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - // *val = hw->pdm_conf.rx_sinc_dsr_16_en; -} - -/** - * @brief Set I2S clkm div num - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set clkm div num - */ -static inline void i2s_ll_set_clkm_div_num(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - -} - -/** - * @brief Set I2S clkm div b - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set clkm div b - */ -static inline void i2s_ll_set_clkm_div_b(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - -} - -/** - * @brief Set I2S clkm div a - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set clkm div a - */ -static inline void i2s_ll_set_clkm_div_a(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - + hw->rx_clkm_conf.rx_clk_sel = 2; } /** @@ -521,10 +201,37 @@ static inline void i2s_ll_set_clkm_div_a(i2s_dev_t *hw, uint32_t val) * @param hw Peripheral I2S hardware instance address. * @param val value to set tx bck div num */ -static inline void i2s_ll_set_tx_bck_div_num(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_tx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) { - abort(); // TODO ESP32-H2 IDF-2098 + hw->tx_conf1.tx_bck_div_num = val - 1; +} +/** + * @brief Configure I2S TX clock devider + * + * @param hw Peripheral I2S hardware instance address. + * @param set Pointer to I2S clock devider configuration paramater + */ +static inline void i2s_ll_tx_set_clk(i2s_dev_t *hw, i2s_ll_mclk_div_t *set) +{ + if (set->a == 0 || set->b == 0) { + hw->tx_clkm_div_conf.tx_clkm_div_x = 0; + hw->tx_clkm_div_conf.tx_clkm_div_y = 0; + hw->tx_clkm_div_conf.tx_clkm_div_z = 0; + } else { + if (set->b > set->a / 2) { + hw->tx_clkm_div_conf.tx_clkm_div_x = set->a / (set->a - set->b) - 1; + hw->tx_clkm_div_conf.tx_clkm_div_y = set->a % (set->a - set->b); + hw->tx_clkm_div_conf.tx_clkm_div_z = set->a - set->b; + hw->tx_clkm_div_conf.tx_clkm_div_yn1 = 1; + } else { + hw->tx_clkm_div_conf.tx_clkm_div_x = set->a / set->b - 1; + hw->tx_clkm_div_conf.tx_clkm_div_y = set->a % set->b + 1; + hw->tx_clkm_div_conf.tx_clkm_div_z = set->b; + hw->tx_clkm_div_conf.tx_clkm_div_yn1 = 0; + } + } + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_clkm_conf, tx_clkm_div_num, set->mclk_div); } /** @@ -533,174 +240,566 @@ static inline void i2s_ll_set_tx_bck_div_num(i2s_dev_t *hw, uint32_t val) * @param hw Peripheral I2S hardware instance address. * @param val value to set rx bck div num */ -static inline void i2s_ll_set_rx_bck_div_num(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_rx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) { - abort(); // TODO ESP32-H2 IDF-2098 - + hw->rx_conf1.rx_bck_div_num = val - 1; } /** - * @brief Set I2S clk sel + * @brief Configure I2S RX clock devider * * @param hw Peripheral I2S hardware instance address. - * @param val value to set clk sel + * @param set Pointer to I2S clock devider configuration paramater */ -static inline void i2s_ll_set_clk_sel(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_rx_set_clk(i2s_dev_t *hw, i2s_ll_mclk_div_t *set) { - abort(); // TODO ESP32-H2 IDF-2098 - + if (set->a == 0 || set->b == 0) { + hw->rx_clkm_div_conf.rx_clkm_div_x = 0; + hw->rx_clkm_div_conf.rx_clkm_div_y = 0; + hw->rx_clkm_div_conf.rx_clkm_div_z = 0; + } else { + if (set->b > set->a / 2) { + hw->rx_clkm_div_conf.rx_clkm_div_x = set->a / (set->a - set->b) - 1; + hw->rx_clkm_div_conf.rx_clkm_div_y = set->a % (set->a - set->b); + hw->rx_clkm_div_conf.rx_clkm_div_z = set->a - set->b; + hw->rx_clkm_div_conf.rx_clkm_div_yn1 = 1; + } else { + hw->rx_clkm_div_conf.rx_clkm_div_x = set->a / set->b - 1; + hw->rx_clkm_div_conf.rx_clkm_div_y = set->a % set->b + 1; + hw->rx_clkm_div_conf.rx_clkm_div_z = set->b; + hw->rx_clkm_div_conf.rx_clkm_div_yn1 = 0; + } + } + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_clkm_conf, rx_clkm_div_num, set->mclk_div); } /** - * @brief Set I2S tx bits mod + * @brief Start I2S TX * * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx bits mod */ -static inline void i2s_ll_set_tx_bits_mod(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_tx_start(i2s_dev_t *hw) { - abort(); // TODO ESP32-H2 IDF-2098 - + hw->tx_conf.tx_update = 0; + hw->tx_conf.tx_update = 1; + hw->tx_conf.tx_start = 1; } /** - * @brief Set I2S rx bits mod + * @brief Start I2S RX * * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx bits mod */ -static inline void i2s_ll_set_rx_bits_mod(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_rx_start(i2s_dev_t *hw) { - abort(); // TODO ESP32-H2 IDF-2098 - + hw->rx_conf.rx_update = 0; + hw->rx_conf.rx_update = 1; + hw->rx_conf.rx_start = 1; } /** - * @brief Set I2S rx sinc dsr 16 en + * @brief Stop I2S TX * * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx sinc dsr 16 en */ -static inline void i2s_ll_set_rx_sinc_dsr_16_en(i2s_dev_t *hw, bool val) +static inline void i2s_ll_tx_stop(i2s_dev_t *hw) { - abort(); // TODO ESP32-H2 IDF-2098 - + hw->tx_conf.tx_start = 0; } /** - * @brief Set I2S dscr en + * @brief Stop I2S RX * * @param hw Peripheral I2S hardware instance address. - * @param val value to set dscr en */ -static inline void i2s_ll_set_dscr_en(i2s_dev_t *hw, bool val) +static inline void i2s_ll_rx_stop(i2s_dev_t *hw) { - abort(); // TODO ESP32-H2 IDF-2098 - + hw->rx_conf.rx_start = 0; } /** - * @brief Set I2S lcd en + * @brief Configure TX WS signal width * * @param hw Peripheral I2S hardware instance address. - * @param val value to set lcd en + * @param width WS width in BCK cycle */ -static inline void i2s_ll_set_lcd_en(i2s_dev_t *hw, bool val) +static inline void i2s_ll_tx_set_ws_width(i2s_dev_t *hw, int width) { - abort(); // TODO ESP32-H2 IDF-2098 - + hw->tx_conf1.tx_tdm_ws_width = width - 1; } /** - * @brief Set I2S camera en + * @brief Configure RX WS signal width * * @param hw Peripheral I2S hardware instance address. - * @param val value to set camera en + * @param width WS width in BCK cycle */ -static inline void i2s_ll_set_camera_en(i2s_dev_t *hw, bool val) +static inline void i2s_ll_rx_set_ws_width(i2s_dev_t *hw, int width) { - abort(); // TODO ESP32-H2 IDF-2098 - + hw->rx_conf1.rx_tdm_ws_width = width - 1; } /** - * @brief Set I2S pcm2pdm conv en + * @brief Configure the received length to trigger in_suc_eof interrupt * * @param hw Peripheral I2S hardware instance address. - * @param val value to set pcm2pdm conv en + * @param eof_num the byte length to trigger in_suc_eof interrupt */ -static inline void i2s_ll_set_pcm2pdm_conv_en(i2s_dev_t *hw, bool val) +static inline void i2s_ll_rx_set_eof_num(i2s_dev_t *hw, int eof_num) { - abort(); // TODO ESP32-H2 IDF-2098 - + hw->rx_eof_num.rx_eof_num = eof_num; } /** - * @brief Set I2S TX to MSB Alignment Standard + * @brief Congfigure 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_set_tx_format_msb_align(i2s_dev_t *hw) -{ -} - - -static inline void i2s_ll_set_rx_format_msb_align(i2s_dev_t *hw) +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 Set I2S TX to PCM long standard + * @brief Congfigure 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_set_tx_pcm_long(i2s_dev_t *hw) +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 Set I2S RX to PCM long standard + * @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_set_rx_pcm_long(i2s_dev_t *hw) +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 Set I2S RX to PCM short standard + * @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_set_rx_pcm_short(i2s_dev_t *hw) +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 Set I2S RX to philip standard + * @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_set_rx_format_philip(i2s_dev_t *hw) +static inline void i2s_ll_tx_enable_msb_shift(i2s_dev_t *hw, bool msb_shift_enable) { + hw->tx_conf1.tx_msb_shift = msb_shift_enable; } /** - * @brief Set I2S TX to PCM short standard + * @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_set_tx_pcm_short(i2s_dev_t *hw) +static inline void i2s_ll_rx_enable_msb_shift(i2s_dev_t *hw, bool msb_shift_enable) { + hw->rx_conf1.rx_msb_shift = msb_shift_enable; } /** - * @brief Set I2S TX to philip standard + * @brief Configure TX total chan number * * @param hw Peripheral I2S hardware instance address. + * @param total_num Total chan number */ -static inline void i2s_ll_set_tx_format_philip(i2s_dev_t *hw) +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) +{ + typeof(hw->tx_tdm_ctrl) tdm_ctrl_reg = hw->tx_tdm_ctrl; + tdm_ctrl_reg.val &= ~I2S_LL_TDM_CH_MASK; + tdm_ctrl_reg.val |= chan_mask & I2S_LL_TDM_CH_MASK; + hw->tx_tdm_ctrl.val = tdm_ctrl_reg.val; +} + +/** + * @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) +{ + typeof(hw->rx_tdm_ctrl) tdm_ctrl_reg = hw->rx_tdm_ctrl; + tdm_ctrl_reg.val &= ~I2S_LL_TDM_CH_MASK; + tdm_ctrl_reg.val |= chan_mask & I2S_LL_TDM_CH_MASK; + hw->rx_tdm_ctrl.val = tdm_ctrl_reg.val; +} + +/** + * @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_tx_set_ws_idle_pol(i2s_dev_t *hw, int 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_rx_set_ws_idle_pol(i2s_dev_t *hw, int ws_pol_level) +{ + hw->rx_conf.rx_ws_idle_pol = ws_pol_level; +} + +/** + * @brief Enable TX PDM mode. + * + * @param hw Peripheral I2S hardware instance address. + * @param pdm_enable Set true to TX enable PDM mode + */ +static inline void i2s_ll_tx_enable_pdm(i2s_dev_t *hw, bool pdm_enable) +{ + hw->tx_conf.tx_pdm_en = pdm_enable; + hw->tx_conf.tx_tdm_en = !pdm_enable; + hw->tx_pcm2pdm_conf.pcm2pdm_conv_en = pdm_enable; +} + +/** + * @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 Enable I2S TX PDM sigma-delta codec + * + * @param hw Peripheral I2S hardware instance address. + * @param dither I2S TX PDM sigmadelta dither value + */ +static inline void i2s_ll_tx_enable_pdm_sd_codec(i2s_dev_t *hw, bool enable) +{ + hw->tx_pcm2pdm_conf.tx_pdm_dac_2out_en = enable; + hw->tx_pcm2pdm_conf.tx_pdm_dac_mode_en = 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 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; + hw->tx_pcm2pdm_conf.tx_pdm_sinc_osr2 = fp / fs; +} + +/** + * @brief Get I2S TX PDM fp configuration paramater + * + * @param hw Peripheral I2S hardware instance address. + * @return + * - fp configuration paramater + */ +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 paramater + * + * @param hw Peripheral I2S hardware instance address. + * @return + * - fs configuration paramater + */ +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. + * + * @param hw Peripheral I2S hardware instance address. + * @param pdm_enable Set true to RX enable PDM mode + */ +static inline void i2s_ll_rx_enable_pdm(i2s_dev_t *hw, bool pdm_enable) +{ + hw->rx_conf.rx_pdm_en = pdm_enable; + hw->rx_conf.rx_tdm_en = !pdm_enable; +} + +/** + * @brief Configura TX a/u-law decompress or compress + * + * @param hw Peripheral I2S hardware instance address. + * @param pcm_cfg PCM configuration paramater + */ +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 paramater + */ +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 = data; +} + +/** + * @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; } /** @@ -716,195 +815,31 @@ static inline void i2s_ll_set_pdm2pcm_conv_en(i2s_dev_t *hw, bool val) } /** - * @brief Set I2S rx pdm en + * @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 val value to set rx pdm en + * @param mono_ena Set true to enable mono mde. */ -static inline void i2s_ll_set_rx_pdm_en(i2s_dev_t *hw, bool val) +static inline void i2s_ll_tx_enable_mono_mode(i2s_dev_t *hw, bool mono_ena) { - abort(); // TODO ESP32-H2 IDF-2098 - + hw->tx_conf.tx_mono = mono_ena; + hw->tx_conf.tx_chan_equal = mono_ena; } /** - * @brief Set I2S tx pdm en + * @brief Enable RX mono mode * * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx pdm en + * @param mono_ena Set true to enable mono mde. */ -static inline void i2s_ll_set_tx_pdm_en(i2s_dev_t *hw, bool val) +static inline void i2s_ll_rx_enable_mono_mode(i2s_dev_t *hw, bool mono_ena) { - abort(); // TODO ESP32-H2 IDF-2098 - -} - -/** - * @brief Set I2S tx fifo mod force en - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx fifo mod force en - */ -static inline void i2s_ll_set_tx_fifo_mod_force_en(i2s_dev_t *hw, bool val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - -} - -/** - * @brief Set I2S rx fifo mod force en - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx fifo mod force en - */ -static inline void i2s_ll_set_rx_fifo_mod_force_en(i2s_dev_t *hw, bool val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - -} - -/** - * @brief Set I2S tx right first - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx right first - */ -static inline void i2s_ll_set_tx_right_first(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - -} - -/** - * @brief Set I2S rx right first - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx right first - */ -static inline void i2s_ll_set_rx_right_first(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - -} - -/** - * @brief Set I2S tx slave mod - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx slave mod - */ -static inline void i2s_ll_set_tx_slave_mod(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - -} - -/** - * @brief Set I2S rx slave mod - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx slave mod - */ -static inline void i2s_ll_set_rx_slave_mod(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - -} - -/** - * @brief Get I2S tx msb right - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get tx msb right - */ -static inline void i2s_ll_get_tx_msb_right(i2s_dev_t *hw, uint32_t *val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - // *val = hw->conf.tx_msb_right; -} - -/** - * @brief Get I2S rx msb right - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get rx msb right - */ -static inline void i2s_ll_get_rx_msb_right(i2s_dev_t *hw, uint32_t *val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - // *val = hw->conf.rx_msb_right; -} - -/** - * @brief Set I2S tx msb right - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx msb right - */ -static inline void i2s_ll_set_tx_msb_right(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - -} - -/** - * @brief Set I2S rx msb right - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx msb right - */ -static inline void i2s_ll_set_rx_msb_right(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - -} - -/** - * @brief Set I2S tx mono - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx mono - */ -static inline void i2s_ll_set_tx_mono(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - -} - -/** - * @brief Set I2S rx mono - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx mono - */ -static inline void i2s_ll_set_rx_mono(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - -} - -/** - * @brief Set I2S tx sinc osr2 - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx sinc osr2 - */ -static inline void i2s_ll_set_tx_sinc_osr2(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - -} - -/** - * @brief Set I2S sig loopback - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set sig loopback - */ -static inline void i2s_ll_set_sig_loopback(i2s_dev_t *hw, uint32_t val) -{ - abort(); // TODO ESP32-H2 IDF-2098 - + hw->rx_conf.rx_mono = mono_ena; + hw->rx_conf.rx_mono_fst_vld = mono_ena; } #ifdef __cplusplus diff --git a/components/hal/esp32h2/include/hal/ledc_ll.h b/components/hal/esp32h2/include/hal/ledc_ll.h index eafae904ba..fb495b0319 100644 --- a/components/hal/esp32h2/include/hal/ledc_ll.h +++ b/components/hal/esp32h2/include/hal/ledc_ll.h @@ -19,6 +19,7 @@ #include "hal/ledc_types.h" #include "soc/ledc_periph.h" +#include "soc/ledc_struct.h" #ifdef __cplusplus extern "C" { diff --git a/components/hal/esp32h2/include/hal/mwdt_ll.h b/components/hal/esp32h2/include/hal/mwdt_ll.h index c1fd5be9d6..944108439e 100644 --- a/components/hal/esp32h2/include/hal/mwdt_ll.h +++ b/components/hal/esp32h2/include/hal/mwdt_ll.h @@ -24,6 +24,7 @@ extern "C" { #include #include #include "soc/timer_periph.h" +#include "soc/timer_group_struct.h" #include "hal/wdt_types.h" #include "esp_attr.h" @@ -42,6 +43,13 @@ _Static_assert(WDT_RESET_SIG_LENGTH_800ns == TIMG_WDT_RESET_LENGTH_800_NS, "Add _Static_assert(WDT_RESET_SIG_LENGTH_1_6us == TIMG_WDT_RESET_LENGTH_1600_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t"); _Static_assert(WDT_RESET_SIG_LENGTH_3_2us == TIMG_WDT_RESET_LENGTH_3200_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t"); +#define FORCE_MODIFY_WHOLE_REG(i, j, k) \ +{ \ + typeof(i) temp_reg = (i); \ + temp_reg.j = (k); \ + (i) = temp_reg; \ +} + /** * @brief Enable the MWDT * @@ -49,7 +57,7 @@ _Static_assert(WDT_RESET_SIG_LENGTH_3_2us == TIMG_WDT_RESET_LENGTH_3200_NS, "Add */ FORCE_INLINE_ATTR void mwdt_ll_enable(timg_dev_t *hw) { - hw->wdt_config0.en = 1; + hw->wdtconfig0.wdt_en = 1; } /** @@ -62,7 +70,7 @@ FORCE_INLINE_ATTR void mwdt_ll_enable(timg_dev_t *hw) */ FORCE_INLINE_ATTR void mwdt_ll_disable(timg_dev_t *hw) { - hw->wdt_config0.en = 0; + hw->wdtconfig0.wdt_en = 0; } /** @@ -73,7 +81,7 @@ FORCE_INLINE_ATTR void mwdt_ll_disable(timg_dev_t *hw) */ FORCE_INLINE_ATTR bool mwdt_ll_check_if_enabled(timg_dev_t *hw) { - return (hw->wdt_config0.en) ? true : false; + return (hw->wdtconfig0.wdt_en) ? true : false; } /** @@ -88,26 +96,26 @@ FORCE_INLINE_ATTR void mwdt_ll_config_stage(timg_dev_t *hw, wdt_stage_t stage, u { switch (stage) { case WDT_STAGE0: - hw->wdt_config0.stg0 = behavior; - hw->wdt_config2 = timeout; + hw->wdtconfig0.wdt_stg0 = behavior; + hw->wdtconfig2.wdt_stg0_hold = timeout; break; case WDT_STAGE1: - hw->wdt_config0.stg1 = behavior; - hw->wdt_config3 = timeout; + hw->wdtconfig0.wdt_stg1 = behavior; + hw->wdtconfig3.wdt_stg1_hold = timeout; break; case WDT_STAGE2: - hw->wdt_config0.stg2 = behavior; - hw->wdt_config4 = timeout; + hw->wdtconfig0.wdt_stg2 = behavior; + hw->wdtconfig4.wdt_stg2_hold = timeout; break; case WDT_STAGE3: - hw->wdt_config0.stg3 = behavior; - hw->wdt_config5 = timeout; + hw->wdtconfig0.wdt_stg3 = behavior; + hw->wdtconfig5.wdt_stg3_hold = timeout; break; default: break; } //Config registers are updated asynchronously - hw->wdt_config0.conf_update_en = 1; + hw->wdtconfig0.wdt_conf_update_en = 1; } /** @@ -120,22 +128,22 @@ FORCE_INLINE_ATTR void mwdt_ll_disable_stage(timg_dev_t *hw, uint32_t stage) { switch (stage) { case WDT_STAGE0: - hw->wdt_config0.stg0 = WDT_STAGE_ACTION_OFF; + hw->wdtconfig0.wdt_stg0 = WDT_STAGE_ACTION_OFF; break; case WDT_STAGE1: - hw->wdt_config0.stg1 = WDT_STAGE_ACTION_OFF; + hw->wdtconfig0.wdt_stg1 = WDT_STAGE_ACTION_OFF; break; case WDT_STAGE2: - hw->wdt_config0.stg2 = WDT_STAGE_ACTION_OFF; + hw->wdtconfig0.wdt_stg2 = WDT_STAGE_ACTION_OFF; break; case WDT_STAGE3: - hw->wdt_config0.stg3 = WDT_STAGE_ACTION_OFF; + hw->wdtconfig0.wdt_stg3 = WDT_STAGE_ACTION_OFF; break; default: break; } //Config registers are updated asynchronously - hw->wdt_config0.conf_update_en = 1; + hw->wdtconfig0.wdt_conf_update_en = 1; } /** @@ -146,9 +154,9 @@ FORCE_INLINE_ATTR void mwdt_ll_disable_stage(timg_dev_t *hw, uint32_t stage) */ FORCE_INLINE_ATTR void mwdt_ll_set_cpu_reset_length(timg_dev_t *hw, wdt_reset_sig_length_t length) { - hw->wdt_config0.cpu_reset_length = length; + hw->wdtconfig0.wdt_cpu_reset_length = length; //Config registers are updated asynchronously - hw->wdt_config0.conf_update_en = 1; + hw->wdtconfig0.wdt_conf_update_en = 1; } /** @@ -159,9 +167,9 @@ FORCE_INLINE_ATTR void mwdt_ll_set_cpu_reset_length(timg_dev_t *hw, wdt_reset_si */ FORCE_INLINE_ATTR void mwdt_ll_set_sys_reset_length(timg_dev_t *hw, wdt_reset_sig_length_t length) { - hw->wdt_config0.sys_reset_length = length; + hw->wdtconfig0.wdt_sys_reset_length = length; //Config registers are updated asynchronously - hw->wdt_config0.conf_update_en = 1; + hw->wdtconfig0.wdt_conf_update_en = 1; } /** @@ -176,9 +184,9 @@ FORCE_INLINE_ATTR void mwdt_ll_set_sys_reset_length(timg_dev_t *hw, wdt_reset_si */ FORCE_INLINE_ATTR void mwdt_ll_set_flashboot_en(timg_dev_t *hw, bool enable) { - hw->wdt_config0.flashboot_mod_en = (enable) ? 1 : 0; + hw->wdtconfig0.wdt_flashboot_mod_en = (enable) ? 1 : 0; //Config registers are updated asynchronously - hw->wdt_config0.conf_update_en = 1; + hw->wdtconfig0.wdt_conf_update_en = 1; } /** @@ -189,9 +197,11 @@ FORCE_INLINE_ATTR void mwdt_ll_set_flashboot_en(timg_dev_t *hw, bool enable) */ FORCE_INLINE_ATTR void mwdt_ll_set_prescaler(timg_dev_t *hw, uint32_t prescaler) { - hw->wdt_config1.clk_prescale = prescaler; + // In case the compiler optimise a 32bit instruction (e.g. s32i) into 8/16bit instruction (e.g. s8i, which is not allowed to access a register) + // We take care of the "read-modify-write" procedure by ourselves. + FORCE_MODIFY_WHOLE_REG(hw->wdtconfig1, wdt_clk_prescale, prescaler); //Config registers are updated asynchronously - hw->wdt_config0.conf_update_en = 1; + hw->wdtconfig0.wdt_conf_update_en = 1; } /** @@ -203,7 +213,7 @@ FORCE_INLINE_ATTR void mwdt_ll_set_prescaler(timg_dev_t *hw, uint32_t prescaler) */ FORCE_INLINE_ATTR void mwdt_ll_feed(timg_dev_t *hw) { - hw->wdt_feed = 1; + hw->wdtfeed.wdt_feed = 1; } /** @@ -215,7 +225,7 @@ FORCE_INLINE_ATTR void mwdt_ll_feed(timg_dev_t *hw) */ FORCE_INLINE_ATTR void mwdt_ll_write_protect_enable(timg_dev_t *hw) { - hw->wdt_wprotect = 0; + hw->wdtwprotect.wdt_wkey = 0; } /** @@ -225,7 +235,7 @@ FORCE_INLINE_ATTR void mwdt_ll_write_protect_enable(timg_dev_t *hw) */ FORCE_INLINE_ATTR void mwdt_ll_write_protect_disable(timg_dev_t *hw) { - hw->wdt_wprotect = TIMG_WDT_WKEY_VALUE; + hw->wdtwprotect.wdt_wkey = TIMG_WDT_WKEY_VALUE; } /** @@ -235,7 +245,7 @@ FORCE_INLINE_ATTR void mwdt_ll_write_protect_disable(timg_dev_t *hw) */ FORCE_INLINE_ATTR void mwdt_ll_clear_intr_status(timg_dev_t *hw) { - hw->int_clr.wdt = 1; + hw->int_clr_timers.wdt_int_clr = 1; } /** @@ -246,7 +256,7 @@ FORCE_INLINE_ATTR void mwdt_ll_clear_intr_status(timg_dev_t *hw) */ FORCE_INLINE_ATTR void mwdt_ll_set_intr_enable(timg_dev_t *hw, bool enable) { - hw->int_ena.wdt = (enable) ? 1 : 0; + hw->int_ena_timers.wdt_int_ena = (enable) ? 1 : 0; } #ifdef __cplusplus diff --git a/components/hal/esp32h2/include/hal/rmt_ll.h b/components/hal/esp32h2/include/hal/rmt_ll.h index f5427d150a..0403741429 100644 --- a/components/hal/esp32h2/include/hal/rmt_ll.h +++ b/components/hal/esp32h2/include/hal/rmt_ll.h @@ -1,27 +1,23 @@ -// 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + #pragma once #include #include #include #include "soc/rmt_struct.h" +#include "hal/misc.h" #ifdef __cplusplus extern "C" { #endif +#define RMT_LL_MAX_LOOP_COUNT (1023)/*!< Max loop count that hardware is supported */ + #define RMT_LL_HW_BASE (&RMT) #define RMT_LL_MEM_BASE (&RMTMEM) @@ -58,7 +54,7 @@ static inline void rmt_ll_set_group_clock_src(rmt_dev_t *dev, uint32_t channel, // Formula: rmt_sclk = module_clock_src / (1 + div_num + div_a / div_b) dev->sys_conf.sclk_active = 0; dev->sys_conf.sclk_sel = src; - dev->sys_conf.sclk_div_num = div_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->sys_conf, sclk_div_num, div_num); dev->sys_conf.sclk_div_a = div_a; dev->sys_conf.sclk_div_b = div_b; dev->sys_conf.sclk_active = 1; @@ -140,22 +136,22 @@ static inline uint32_t rmt_ll_rx_get_mem_blocks(rmt_dev_t *dev, uint32_t channel static inline void rmt_ll_tx_set_channel_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div) { - dev->tx_conf[channel].div_cnt = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->tx_conf[channel], div_cnt, div); } static inline void rmt_ll_rx_set_channel_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div) { - dev->rx_conf[channel].conf0.div_cnt = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->rx_conf[channel].conf0, div_cnt, div); } static inline uint32_t rmt_ll_tx_get_channel_clock_div(rmt_dev_t *dev, uint32_t channel) { - return dev->tx_conf[channel].div_cnt; + return HAL_FORCE_READ_U32_REG_FIELD(dev->tx_conf[channel], div_cnt); } static inline uint32_t rmt_ll_rx_get_channel_clock_div(rmt_dev_t *dev, uint32_t channel) { - return dev->rx_conf[channel].conf0.div_cnt; + return HAL_FORCE_READ_U32_REG_FIELD(dev->rx_conf[channel].conf0, div_cnt); } static inline void rmt_ll_tx_enable_pingpong(rmt_dev_t *dev, uint32_t channel, bool enable) @@ -231,7 +227,7 @@ static inline void rmt_ll_rx_enable_filter(rmt_dev_t *dev, uint32_t channel, boo static inline void rmt_ll_rx_set_filter_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres) { - dev->rx_conf[channel].conf1.rx_filter_thres = thres; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->rx_conf[channel].conf1, rx_filter_thres, thres); } static inline void rmt_ll_tx_enable_idle(rmt_dev_t *dev, uint32_t channel, bool enable) @@ -441,14 +437,14 @@ static inline void rmt_ll_rx_set_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t static inline void rmt_ll_tx_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks) { - *high_ticks = dev->tx_carrier[channel].high; - *low_ticks = dev->tx_carrier[channel].low; + *high_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->tx_carrier[channel], high); + *low_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->tx_carrier[channel], low); } static inline void rmt_ll_rx_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks) { - *high_ticks = dev->rx_carrier[channel].high_thres; - *low_ticks = dev->rx_carrier[channel].low_thres; + *high_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->rx_carrier[channel], high_thres); + *low_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->rx_carrier[channel], low_thres); } static inline void rmt_ll_tx_enable_carrier_modulation(rmt_dev_t *dev, uint32_t channel, bool enable) diff --git a/components/hal/esp32h2/include/hal/rtc_cntl_ll.h b/components/hal/esp32h2/include/hal/rtc_cntl_ll.h index 48fa2a4e6e..bff6c79390 100644 --- a/components/hal/esp32h2/include/hal/rtc_cntl_ll.h +++ b/components/hal/esp32h2/include/hal/rtc_cntl_ll.h @@ -17,7 +17,7 @@ #include "soc/soc.h" #include "soc/rtc.h" #include "soc/rtc_cntl_reg.h" -#include "soc/apb_ctrl_reg.h" +#include "soc/syscon_reg.h" #ifdef __cplusplus extern "C" { diff --git a/components/hal/esp32h2/include/hal/rwdt_ll.h b/components/hal/esp32h2/include/hal/rwdt_ll.h index 87ae4f7294..0986ce3dec 100644 --- a/components/hal/esp32h2/include/hal/rwdt_ll.h +++ b/components/hal/esp32h2/include/hal/rwdt_ll.h @@ -23,8 +23,10 @@ extern "C" { #include #include +#include "hal/misc.h" #include "hal/wdt_types.h" #include "soc/rtc_cntl_periph.h" +#include "soc/rtc_cntl_struct.h" #include "soc/efuse_reg.h" #include "esp_attr.h" @@ -239,7 +241,7 @@ FORCE_INLINE_ATTR void rwdt_ll_set_chip_reset_en(rtc_cntl_dev_t *hw, bool enable */ FORCE_INLINE_ATTR void rwdt_ll_set_chip_reset_width(rtc_cntl_dev_t *hw, uint32_t width) { - hw->wdt_config0.chip_reset_width = width; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->wdt_config0, chip_reset_width, width); } /** diff --git a/components/hal/esp32h2/include/hal/sigmadelta_ll.h b/components/hal/esp32h2/include/hal/sigmadelta_ll.h index 87f75dab9e..f6c37054a3 100644 --- a/components/hal/esp32h2/include/hal/sigmadelta_ll.h +++ b/components/hal/esp32h2/include/hal/sigmadelta_ll.h @@ -22,7 +22,9 @@ #pragma once #include +#include "hal/misc.h" #include "soc/sigmadelta_periph.h" +#include "soc/gpio_sd_struct.h" #include "hal/sigmadelta_types.h" #ifdef __cplusplus @@ -53,7 +55,7 @@ static inline void sigmadelta_ll_set_en(gpio_sd_dev_t *hw, bool en) */ static inline void sigmadelta_ll_set_duty(gpio_sd_dev_t *hw, sigmadelta_channel_t channel, int8_t duty) { - hw->channel[channel].duty = duty; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], duty, (uint32_t)duty); } /** @@ -65,7 +67,7 @@ static inline void sigmadelta_ll_set_duty(gpio_sd_dev_t *hw, sigmadelta_channel_ */ static inline void sigmadelta_ll_set_prescale(gpio_sd_dev_t *hw, sigmadelta_channel_t channel, uint8_t prescale) { - hw->channel[channel].prescale = prescale; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], prescale, prescale); } #ifdef __cplusplus diff --git a/components/hal/esp32h2/include/hal/spi_ll.h b/components/hal/esp32h2/include/hal/spi_ll.h index 1f68acac7b..764f3fd872 100644 --- a/components/hal/esp32h2/include/hal/spi_ll.h +++ b/components/hal/esp32h2/include/hal/spi_ll.h @@ -27,9 +27,11 @@ #include "esp_attr.h" #include "esp_types.h" #include "soc/spi_periph.h" +#include "soc/spi_struct.h" #include "soc/lldesc.h" #include "hal/assert.h" #include "hal/misc.h" +#include "hal/spi_types.h" #ifdef __cplusplus extern "C" { @@ -37,6 +39,9 @@ extern "C" { /// Interrupt not used. Don't use in app. #define SPI_LL_UNUSED_INT_MASK (SPI_TRANS_DONE_INT_ENA | SPI_SLV_WR_DMA_DONE_INT_ENA | SPI_SLV_RD_DMA_DONE_INT_ENA | SPI_SLV_WR_BUF_DONE_INT_ENA | SPI_SLV_RD_BUF_DONE_INT_ENA) +/// These 2 masks together will set SPI transaction to one line mode +#define SPI_LL_ONE_LINE_CTRL_MASK (SPI_FREAD_QUAD | SPI_FREAD_DUAL | SPI_FCMD_QUAD | SPI_FCMD_DUAL | SPI_FADDR_QUAD | SPI_FADDR_DUAL) +#define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_QUAD | SPI_FWRITE_DUAL) /// Swap the bit order to its correct place to send #define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len)) /// This is the expected clock frequency @@ -51,15 +56,6 @@ extern "C" { typedef uint32_t spi_ll_clock_val_t; typedef spi_dev_t spi_dma_dev_t; -/** IO modes supported by the master. */ -typedef enum { - SPI_LL_IO_MODE_NORMAL = 0, ///< 1-bit mode for all phases - SPI_LL_IO_MODE_DIO, ///< 2-bit mode for address and data phases, 1-bit mode for command phase - SPI_LL_IO_MODE_DUAL, ///< 2-bit mode for data phases only, 1-bit mode for command and address phases - SPI_LL_IO_MODE_QIO, ///< 4-bit mode for address and data phases, 1-bit mode for command phase - SPI_LL_IO_MODE_QUAD, ///< 4-bit mode for data phases only, 1-bit mode for command and address phases -} spi_ll_io_mode_t; - // Type definition of all supported interrupts typedef enum { SPI_LL_INTR_TRANS_DONE = BIT(0), ///< A transaction has done @@ -352,7 +348,7 @@ static inline void spi_ll_write_buffer(spi_dev_t *hw, const uint8_t *buffer_to_s */ static inline void spi_ll_write_buffer_byte(spi_dev_t *hw, int byte_id, uint8_t *data, int len) { - HAL_ASSERT(byte_id+len <= 64); + HAL_ASSERT(byte_id + len <= 64); HAL_ASSERT(len > 0); HAL_ASSERT(byte_id >= 0); @@ -360,10 +356,14 @@ static inline void spi_ll_write_buffer_byte(spi_dev_t *hw, int byte_id, uint8_t uint32_t word; int offset = byte_id % 4; int copy_len = 4 - offset; - if (copy_len > len) copy_len = len; + if (copy_len > len) { + copy_len = len; + } //read-modify-write - if (copy_len != 4) word = hw->data_buf[byte_id / 4]; //read + if (copy_len != 4) { + word = hw->data_buf[byte_id / 4]; //read + } memcpy(((uint8_t *)&word) + offset, data, copy_len); //modify hw->data_buf[byte_id / 4] = word; //write @@ -407,7 +407,9 @@ static inline void spi_ll_read_buffer_byte(spi_dev_t *hw, int byte_id, uint8_t * uint32_t word = hw->data_buf[byte_id / 4]; int offset = byte_id % 4; int copy_len = 4 - offset; - if (copy_len > len) copy_len = len; + if (copy_len > len) { + copy_len = len; + } memcpy(out_data, ((uint8_t *)&word) + offset, copy_len); byte_id += copy_len; @@ -538,41 +540,23 @@ static inline void spi_ll_set_sio_mode(spi_dev_t *hw, int sio_mode) } /** - * Configure the io mode for the master to work at. + * Configure the SPI transaction line mode for the master to use. * - * @param hw Beginning address of the peripheral registers. - * @param io_mode IO mode to work at, see ``spi_ll_io_mode_t``. + * @param hw Beginning address of the peripheral registers. + * @param line_mode SPI transaction line mode to use, see ``spi_line_mode_t``. */ -static inline void spi_ll_master_set_io_mode(spi_dev_t *hw, spi_ll_io_mode_t io_mode) +static inline void spi_ll_master_set_line_mode(spi_dev_t *hw, spi_line_mode_t line_mode) { - if (io_mode == SPI_LL_IO_MODE_DIO || io_mode == SPI_LL_IO_MODE_DUAL) { - hw->ctrl.fcmd_dual = (io_mode == SPI_LL_IO_MODE_DIO) ? 1 : 0; - hw->ctrl.faddr_dual = (io_mode == SPI_LL_IO_MODE_DIO) ? 1 : 0; - hw->ctrl.fread_dual = 1; - hw->user.fwrite_dual = 1; - hw->ctrl.fcmd_quad = 0; - hw->ctrl.faddr_quad = 0; - hw->ctrl.fread_quad = 0; - hw->user.fwrite_quad = 0; - } else if (io_mode == SPI_LL_IO_MODE_QIO || io_mode == SPI_LL_IO_MODE_QUAD) { - hw->ctrl.fcmd_quad = (io_mode == SPI_LL_IO_MODE_QIO) ? 1 : 0; - hw->ctrl.faddr_quad = (io_mode == SPI_LL_IO_MODE_QIO) ? 1 : 0; - hw->ctrl.fread_quad = 1; - hw->user.fwrite_quad = 1; - hw->ctrl.fcmd_dual = 0; - hw->ctrl.faddr_dual = 0; - hw->ctrl.fread_dual = 0; - hw->user.fwrite_dual = 0; - } else { - hw->ctrl.fcmd_dual = 0; - hw->ctrl.faddr_dual = 0; - hw->ctrl.fread_dual = 0; - hw->user.fwrite_dual = 0; - hw->ctrl.fcmd_quad = 0; - hw->ctrl.faddr_quad = 0; - hw->ctrl.fread_quad = 0; - hw->user.fwrite_quad = 0; - } + hw->ctrl.val &= ~SPI_LL_ONE_LINE_CTRL_MASK; + hw->user.val &= ~SPI_LL_ONE_LINE_USER_MASK; + hw->ctrl.fcmd_dual = (line_mode.cmd_lines == 2); + hw->ctrl.fcmd_quad = (line_mode.cmd_lines == 4); + hw->ctrl.faddr_dual = (line_mode.addr_lines == 2); + hw->ctrl.faddr_quad = (line_mode.addr_lines == 4); + hw->ctrl.fread_dual = (line_mode.data_lines == 2); + hw->user.fwrite_dual = (line_mode.data_lines == 2); + hw->ctrl.fread_quad = (line_mode.data_lines == 4); + hw->user.fwrite_quad = (line_mode.data_lines == 4); } /** @@ -609,7 +593,8 @@ static inline void spi_ll_master_select_cs(spi_dev_t *hw, int cs_id) * @param hw Beginning address of the peripheral registers. * @param keep_active if 0 don't keep CS activated, else keep CS activated */ -static inline void spi_ll_master_keep_cs(spi_dev_t *hw, int keep_active) { +static inline void spi_ll_master_keep_cs(spi_dev_t *hw, int keep_active) +{ hw->misc.cs_keep_active = (keep_active != 0) ? 1 : 0; } @@ -916,13 +901,13 @@ static inline void spi_ll_set_command(spi_dev_t *hw, uint16_t cmd, int cmdlen, b { if (lsbfirst) { // The output command start from bit0 to bit 15, kept as is. - hw->user2.usr_command_value = cmd; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user2, usr_command_value, cmd); } else { /* Output command will be sent from bit 7 to 0 of command_value, and * then bit 15 to 8 of the same register field. Shift and swap to send * more straightly. */ - hw->user2.usr_command_value = HAL_SPI_SWAP_DATA_TX(cmd, cmdlen); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user2, usr_command_value, HAL_SPI_SWAP_DATA_TX(cmd, cmdlen)); } } @@ -938,7 +923,7 @@ static inline void spi_ll_set_command(spi_dev_t *hw, uint16_t cmd, int cmdlen, b static inline void spi_ll_set_dummy(spi_dev_t *hw, int dummy_n) { hw->user.usr_dummy = dummy_n ? 1 : 0; - hw->user1.usr_dummy_cyclelen = dummy_n - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user1, usr_dummy_cyclelen, dummy_n - 1); } /** @@ -993,35 +978,35 @@ static inline uint32_t spi_ll_slave_get_rcv_bitlen(spi_dev_t *hw) item(SPI_LL_INTR_CMDA, dma_int_ena.cmda, dma_int_raw.cmda, dma_int_clr.cmda=1) -static inline void spi_ll_enable_intr(spi_dev_t* hw, spi_ll_intr_t intr_mask) +static inline void spi_ll_enable_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask) { #define ENA_INTR(intr_bit, en_reg, ...) if (intr_mask & (intr_bit)) hw->en_reg = 1; FOR_EACH_ITEM(ENA_INTR, INTR_LIST); #undef ENA_INTR } -static inline void spi_ll_disable_intr(spi_dev_t* hw, spi_ll_intr_t intr_mask) +static inline void spi_ll_disable_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask) { #define DIS_INTR(intr_bit, en_reg, ...) if (intr_mask & (intr_bit)) hw->en_reg = 0; FOR_EACH_ITEM(DIS_INTR, INTR_LIST); #undef DIS_INTR } -static inline void spi_ll_set_intr(spi_dev_t* hw, spi_ll_intr_t intr_mask) +static inline void spi_ll_set_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask) { #define SET_INTR(intr_bit, _, st_reg, ...) if (intr_mask & (intr_bit)) hw->st_reg = 1; FOR_EACH_ITEM(SET_INTR, INTR_LIST); #undef SET_INTR } -static inline void spi_ll_clear_intr(spi_dev_t* hw, spi_ll_intr_t intr_mask) +static inline void spi_ll_clear_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask) { #define CLR_INTR(intr_bit, _, __, clr_reg) if (intr_mask & (intr_bit)) hw->clr_reg; FOR_EACH_ITEM(CLR_INTR, INTR_LIST); #undef CLR_INTR } -static inline bool spi_ll_get_intr(spi_dev_t* hw, spi_ll_intr_t intr_mask) +static inline bool spi_ll_get_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask) { #define GET_INTR(intr_bit, _, st_reg, ...) if (intr_mask & (intr_bit) && hw->st_reg) return true; FOR_EACH_ITEM(GET_INTR, INTR_LIST); @@ -1075,7 +1060,7 @@ static inline void spi_ll_enable_int(spi_dev_t *hw) /*------------------------------------------------------------------------------ * Slave HD *----------------------------------------------------------------------------*/ -static inline void spi_ll_slave_hd_set_len_cond(spi_dev_t* hw, spi_ll_trans_len_cond_t cond_mask) +static inline void spi_ll_slave_hd_set_len_cond(spi_dev_t *hw, spi_ll_trans_len_cond_t cond_mask) { hw->slave.rdbuf_bitlen_en = (cond_mask & SPI_LL_TRANS_LEN_COND_RDBUF) ? 1 : 0; hw->slave.wrbuf_bitlen_en = (cond_mask & SPI_LL_TRANS_LEN_COND_WRBUF) ? 1 : 0; @@ -1083,12 +1068,12 @@ static inline void spi_ll_slave_hd_set_len_cond(spi_dev_t* hw, spi_ll_trans_len_ hw->slave.wrdma_bitlen_en = (cond_mask & SPI_LL_TRANS_LEN_COND_WRDMA) ? 1 : 0; } -static inline int spi_ll_slave_get_rx_byte_len(spi_dev_t* hw) +static inline int spi_ll_slave_get_rx_byte_len(spi_dev_t *hw) { return hw->slave1.data_bitlen / 8; } -static inline uint32_t spi_ll_slave_hd_get_last_addr(spi_dev_t* hw) +static inline uint32_t spi_ll_slave_hd_get_last_addr(spi_dev_t *hw) { return hw->slave1.last_addr; } diff --git a/components/hal/esp32h2/include/hal/spimem_flash_ll.h b/components/hal/esp32h2/include/hal/spimem_flash_ll.h index 14613abe02..0c464a20b2 100644 --- a/components/hal/esp32h2/include/hal/spimem_flash_ll.h +++ b/components/hal/esp32h2/include/hal/spimem_flash_ll.h @@ -28,6 +28,7 @@ #include #include "soc/spi_periph.h" +#include "soc/spi_mem_struct.h" #include "hal/spi_types.h" #include "hal/spi_flash_types.h" @@ -157,7 +158,7 @@ static inline void spimem_flash_ll_auto_resume_init(spi_mem_dev_t *dev, bool aut */ static inline void spimem_flash_ll_suspend_cmd_setup(spi_mem_dev_t *dev, uint32_t sus_cmd) { - dev->flash_sus_cmd.flash_pes_command = sus_cmd; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_cmd, flash_pes_command, sus_cmd); } /** @@ -169,7 +170,7 @@ static inline void spimem_flash_ll_suspend_cmd_setup(spi_mem_dev_t *dev, uint32_ */ static inline void spimem_flash_ll_resume_cmd_setup(spi_mem_dev_t *dev, uint32_t res_cmd) { - dev->flash_sus_cmd.flash_per_command = res_cmd; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_cmd, flash_per_command, res_cmd); } /** @@ -181,7 +182,7 @@ static inline void spimem_flash_ll_resume_cmd_setup(spi_mem_dev_t *dev, uint32_t */ static inline void spimem_flash_ll_rd_sus_cmd_setup(spi_mem_dev_t *dev, uint32_t pesr_cmd) { - dev->flash_sus_cmd.wait_pesr_command = pesr_cmd; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_cmd, wait_pesr_command, pesr_cmd); } /** @@ -218,7 +219,7 @@ static inline void spimem_flash_ll_res_check_sus_setup(spi_mem_dev_t *dev, bool static inline void spimem_flash_ll_set_read_sus_status(spi_mem_dev_t *dev, uint32_t sus_conf) { dev->flash_sus_ctrl.frd_sus_2b = 0; - dev->flash_sus_ctrl.pesr_end_msk = sus_conf; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_ctrl, pesr_end_msk, sus_conf); } /** @@ -229,7 +230,7 @@ static inline void spimem_flash_ll_set_read_sus_status(spi_mem_dev_t *dev, uint3 */ static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool auto_waiti) { - dev->flash_waiti_ctrl.waiti_cmd = 0x05; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_waiti_ctrl, waiti_cmd, 0x05); dev->flash_sus_ctrl.flash_per_wait_en = auto_waiti; dev->flash_sus_ctrl.flash_pes_wait_en = auto_waiti; } diff --git a/components/hal/esp32h2/include/hal/systimer_ll.h b/components/hal/esp32h2/include/hal/systimer_ll.h index 769f68703f..3628978f68 100644 --- a/components/hal/esp32h2/include/hal/systimer_ll.h +++ b/components/hal/esp32h2/include/hal/systimer_ll.h @@ -124,6 +124,11 @@ __attribute__((always_inline)) static inline void systimer_ll_set_alarm_period(s dev->target_conf[alarm_id].target_period = period; } +__attribute__((always_inline)) static inline uint32_t systimer_ll_get_alarm_period(systimer_dev_t *dev, uint32_t alarm_id) +{ + return dev->target_conf[alarm_id].target_period; +} + __attribute__((always_inline)) static inline void systimer_ll_apply_alarm_value(systimer_dev_t *dev, uint32_t alarm_id) { dev->comp_load[alarm_id].val = 0x01; diff --git a/components/hal/esp32h2/include/hal/timer_ll.h b/components/hal/esp32h2/include/hal/timer_ll.h index caa1eda89f..4032a1b1dd 100644 --- a/components/hal/esp32h2/include/hal/timer_ll.h +++ b/components/hal/esp32h2/include/hal/timer_ll.h @@ -22,7 +22,9 @@ extern "C" { #endif #include +#include "hal/misc.h" #include "soc/timer_periph.h" +#include "soc/timer_group_struct.h" #include "hal/timer_types.h" #include "hal/assert.h" @@ -52,11 +54,11 @@ static inline void timer_ll_set_divider(timg_dev_t *hw, timer_idx_t timer_num, u if (divider >= 65536) { divider = 0; } - int timer_en = hw->hw_timer[timer_num].config.enable; - hw->hw_timer[timer_num].config.enable = 0; - hw->hw_timer[timer_num].config.divcnt_rst = 1; - hw->hw_timer[timer_num].config.divider = divider; - hw->hw_timer[timer_num].config.enable = timer_en; + int timer_en = hw->hw_timer[timer_num].config.tx_en; + hw->hw_timer[timer_num].config.tx_en = 0; + hw->hw_timer[timer_num].config.tx_divcnt_rst = 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->hw_timer[timer_num].config, tx_divider, divider); + hw->hw_timer[timer_num].config.tx_en = timer_en; } /** @@ -70,7 +72,7 @@ static inline void timer_ll_set_divider(timg_dev_t *hw, timer_idx_t timer_num, u */ static inline void timer_ll_get_divider(timg_dev_t *hw, timer_idx_t timer_num, uint32_t *divider) { - uint32_t d = hw->hw_timer[timer_num].config.divider; + uint32_t d = HAL_FORCE_READ_U32_REG_FIELD(hw->hw_timer[timer_num].config, tx_divider); if (d == 0) { d = 65536; } else if (d == 1) { @@ -90,9 +92,9 @@ static inline void timer_ll_get_divider(timg_dev_t *hw, timer_idx_t timer_num, u */ static inline void timer_ll_set_counter_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t load_val) { - hw->hw_timer[timer_num].load_high.load_hi = (uint32_t) (load_val >> 32); - hw->hw_timer[timer_num].load_low = (uint32_t) load_val; - hw->hw_timer[timer_num].reload = 1; + hw->hw_timer[timer_num].loadhi.tx_load_hi = (uint32_t) (load_val >> 32); + hw->hw_timer[timer_num].loadlo.tx_load_lo = (uint32_t) load_val; + hw->hw_timer[timer_num].load.tx_load = 1; } /** @@ -106,9 +108,9 @@ static inline void timer_ll_set_counter_value(timg_dev_t *hw, timer_idx_t timer_ */ FORCE_INLINE_ATTR void timer_ll_get_counter_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t *timer_val) { - hw->hw_timer[timer_num].update.update = 1; - while (hw->hw_timer[timer_num].update.update) {} - *timer_val = ((uint64_t) hw->hw_timer[timer_num].cnt_high.hi << 32) | (hw->hw_timer[timer_num].cnt_low); + hw->hw_timer[timer_num].update.tx_update = 1; + while (hw->hw_timer[timer_num].update.tx_update) {} + *timer_val = ((uint64_t) hw->hw_timer[timer_num].hi.tx_hi << 32) | (hw->hw_timer[timer_num].lo.tx_lo); } /** @@ -122,7 +124,7 @@ FORCE_INLINE_ATTR void timer_ll_get_counter_value(timg_dev_t *hw, timer_idx_t ti */ static inline void timer_ll_set_counter_increase(timg_dev_t *hw, timer_idx_t timer_num, bool increase_en) { - hw->hw_timer[timer_num].config.increase = increase_en; + hw->hw_timer[timer_num].config.tx_increase = increase_en; } /** @@ -137,7 +139,7 @@ static inline void timer_ll_set_counter_increase(timg_dev_t *hw, timer_idx_t tim */ static inline bool timer_ll_get_counter_increase(timg_dev_t *hw, timer_idx_t timer_num) { - return hw->hw_timer[timer_num].config.increase; + return hw->hw_timer[timer_num].config.tx_increase; } /** @@ -151,7 +153,7 @@ static inline bool timer_ll_get_counter_increase(timg_dev_t *hw, timer_idx_t tim */ FORCE_INLINE_ATTR void timer_ll_set_counter_enable(timg_dev_t *hw, timer_idx_t timer_num, bool counter_en) { - hw->hw_timer[timer_num].config.enable = counter_en; + hw->hw_timer[timer_num].config.tx_en = counter_en; } /** @@ -166,7 +168,7 @@ FORCE_INLINE_ATTR void timer_ll_set_counter_enable(timg_dev_t *hw, timer_idx_t t */ static inline bool timer_ll_get_counter_enable(timg_dev_t *hw, timer_idx_t timer_num) { - return hw->hw_timer[timer_num].config.enable; + return hw->hw_timer[timer_num].config.tx_en; } /** @@ -180,7 +182,7 @@ static inline bool timer_ll_get_counter_enable(timg_dev_t *hw, timer_idx_t timer */ static inline void timer_ll_set_auto_reload(timg_dev_t *hw, timer_idx_t timer_num, bool auto_reload_en) { - hw->hw_timer[timer_num].config.autoreload = auto_reload_en; + hw->hw_timer[timer_num].config.tx_autoreload = auto_reload_en; } /** @@ -195,7 +197,7 @@ static inline void timer_ll_set_auto_reload(timg_dev_t *hw, timer_idx_t timer_nu */ FORCE_INLINE_ATTR bool timer_ll_get_auto_reload(timg_dev_t *hw, timer_idx_t timer_num) { - return hw->hw_timer[timer_num].config.autoreload; + return hw->hw_timer[timer_num].config.tx_autoreload; } /** @@ -209,8 +211,8 @@ FORCE_INLINE_ATTR bool timer_ll_get_auto_reload(timg_dev_t *hw, timer_idx_t time */ FORCE_INLINE_ATTR void timer_ll_set_alarm_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t alarm_value) { - hw->hw_timer[timer_num].alarm_high.alarm_hi = (uint32_t) (alarm_value >> 32); - hw->hw_timer[timer_num].alarm_low = (uint32_t) alarm_value; + hw->hw_timer[timer_num].alarmhi.tx_alarm_hi = (uint32_t) (alarm_value >> 32); + hw->hw_timer[timer_num].alarmlo.tx_alarm_lo = (uint32_t) alarm_value; } /** @@ -224,7 +226,7 @@ FORCE_INLINE_ATTR void timer_ll_set_alarm_value(timg_dev_t *hw, timer_idx_t time */ static inline void timer_ll_get_alarm_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t *alarm_value) { - *alarm_value = ((uint64_t) hw->hw_timer[timer_num].alarm_high.alarm_hi << 32) | (hw->hw_timer[timer_num].alarm_low); + *alarm_value = ((uint64_t) hw->hw_timer[timer_num].alarmhi.tx_alarm_hi << 32) | (hw->hw_timer[timer_num].alarmlo.tx_alarm_lo); } /** @@ -238,7 +240,7 @@ static inline void timer_ll_get_alarm_value(timg_dev_t *hw, timer_idx_t timer_nu */ FORCE_INLINE_ATTR void timer_ll_set_alarm_enable(timg_dev_t *hw, timer_idx_t timer_num, bool alarm_en) { - hw->hw_timer[timer_num].config.alarm_en = alarm_en; + hw->hw_timer[timer_num].config.tx_alarm_en = alarm_en; } /** @@ -253,7 +255,7 @@ FORCE_INLINE_ATTR void timer_ll_set_alarm_enable(timg_dev_t *hw, timer_idx_t tim */ static inline bool timer_ll_get_alarm_enable(timg_dev_t *hw, timer_idx_t timer_num) { - return hw->hw_timer[timer_num].config.alarm_en; + return hw->hw_timer[timer_num].config.tx_alarm_en; } /** @@ -266,7 +268,7 @@ static inline bool timer_ll_get_alarm_enable(timg_dev_t *hw, timer_idx_t timer_n */ FORCE_INLINE_ATTR void timer_ll_intr_enable(timg_dev_t *hw, timer_idx_t timer_num) { - hw->int_ena.val |= BIT(timer_num); + hw->int_ena_timers.val |= BIT(timer_num); } /** @@ -279,7 +281,7 @@ FORCE_INLINE_ATTR void timer_ll_intr_enable(timg_dev_t *hw, timer_idx_t timer_nu */ FORCE_INLINE_ATTR void timer_ll_intr_disable(timg_dev_t *hw, timer_idx_t timer_num) { - hw->int_ena.val &= (~BIT(timer_num)); + hw->int_ena_timers.val &= (~BIT(timer_num)); } /** @@ -292,7 +294,7 @@ FORCE_INLINE_ATTR void timer_ll_intr_disable(timg_dev_t *hw, timer_idx_t timer_n */ FORCE_INLINE_ATTR void timer_ll_clear_intr_status(timg_dev_t *hw, timer_idx_t timer_num) { - hw->int_clr.val |= BIT(timer_num); + hw->int_clr_timers.val |= BIT(timer_num); } /** @@ -305,7 +307,7 @@ FORCE_INLINE_ATTR void timer_ll_clear_intr_status(timg_dev_t *hw, timer_idx_t ti */ FORCE_INLINE_ATTR void timer_ll_get_intr_status(timg_dev_t *hw, uint32_t *intr_status) { - *intr_status = hw->int_st.val & 0x01; + *intr_status = hw->int_st_timers.val & 0x01; } /** @@ -319,7 +321,7 @@ FORCE_INLINE_ATTR void timer_ll_get_intr_status(timg_dev_t *hw, uint32_t *intr_s FORCE_INLINE_ATTR void timer_ll_get_intr_raw_status(timer_group_t group_num, uint32_t *intr_raw_status) { timg_dev_t *hw = TIMER_LL_GET_HW(group_num); - *intr_raw_status = hw->int_raw.val & 0x01; + *intr_raw_status = hw->int_raw_timers.val & 0x01; } /** @@ -391,7 +393,7 @@ static inline bool timer_ll_get_edge_int_enable(timg_dev_t *hw, timer_idx_t time */ static inline uint32_t timer_ll_get_intr_status_reg(timg_dev_t *hw) { - return (uint32_t) & (hw->int_st.val); + return (uint32_t) & (hw->int_st_timers.val); } static inline uint32_t timer_ll_get_intr_mask_bit(timg_dev_t *hw, timer_idx_t timer_num) @@ -409,7 +411,7 @@ static inline uint32_t timer_ll_get_intr_mask_bit(timg_dev_t *hw, timer_idx_t ti */ static inline void timer_ll_set_use_xtal(timg_dev_t *hw, timer_idx_t timer_num, bool use_xtal_en) { - hw->hw_timer[timer_num].config.use_xtal = use_xtal_en; + hw->hw_timer[timer_num].config.tx_use_xtal = use_xtal_en; } /** @@ -423,7 +425,7 @@ static inline void timer_ll_set_use_xtal(timg_dev_t *hw, timer_idx_t timer_num, */ static inline bool timer_ll_get_use_xtal(timg_dev_t *hw, timer_idx_t timer_num) { - return hw->hw_timer[timer_num].config.use_xtal; + return hw->hw_timer[timer_num].config.tx_use_xtal; } #ifdef __cplusplus diff --git a/components/hal/esp32h2/include/hal/twai_ll.h b/components/hal/esp32h2/include/hal/twai_ll.h index ed6fbc5795..92c46d010b 100644 --- a/components/hal/esp32h2/include/hal/twai_ll.h +++ b/components/hal/esp32h2/include/hal/twai_ll.h @@ -28,8 +28,10 @@ extern "C" { #include #include +#include "hal/misc.h" #include "hal/twai_types.h" #include "soc/twai_periph.h" +#include "soc/twai_struct.h" /* ------------------------- Defines and Typedefs --------------------------- */ @@ -398,7 +400,7 @@ static inline void twai_ll_clear_err_code_cap(twai_dev_t *hw) */ static inline void twai_ll_set_err_warn_lim(twai_dev_t *hw, uint32_t ewl) { - hw->error_warning_limit_reg.ewl = ewl; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->error_warning_limit_reg, ewl, ewl); } /** @@ -438,7 +440,7 @@ static inline uint32_t twai_ll_get_rec(twai_dev_t *hw) */ static inline void twai_ll_set_rec(twai_dev_t *hw, uint32_t rec) { - hw->rx_error_counter_reg.rxerr = rec; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_error_counter_reg, rxerr, rec); } /* ------------------------ TX Error Count Register ------------------------- */ @@ -466,7 +468,7 @@ static inline uint32_t twai_ll_get_tec(twai_dev_t *hw) */ static inline void twai_ll_set_tec(twai_dev_t *hw, uint32_t tec) { - hw->tx_error_counter_reg.txerr = tec; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_error_counter_reg, txerr, tec); } /* ---------------------- Acceptance Filter Registers ----------------------- */ @@ -485,8 +487,8 @@ static inline void twai_ll_set_acc_filter(twai_dev_t* hw, uint32_t code, uint32_ uint32_t code_swapped = __builtin_bswap32(code); uint32_t mask_swapped = __builtin_bswap32(mask); for (int i = 0; i < 4; i++) { - hw->acceptance_filter.acr[i].byte = ((code_swapped >> (i * 8)) & 0xFF); - hw->acceptance_filter.amr[i].byte = ((mask_swapped >> (i * 8)) & 0xFF); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->acceptance_filter.acr[i], byte, ((code_swapped >> (i * 8)) & 0xFF)); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->acceptance_filter.amr[i], byte, ((mask_swapped >> (i * 8)) & 0xFF)); } hw->mode_reg.afm = single_filter; } @@ -521,7 +523,7 @@ static inline void twai_ll_get_rx_buffer(twai_dev_t *hw, twai_ll_frame_buffer_t { //Copy RX buffer registers into frame for (int i = 0; i < 13; i++) { - rx_frame->bytes[i] = hw->tx_rx_buffer[i].byte; + rx_frame->bytes[i] = HAL_FORCE_READ_U32_REG_FIELD(hw->tx_rx_buffer[i], byte); } } @@ -651,14 +653,14 @@ static inline void twai_ll_set_clkout(twai_dev_t *hw, uint32_t divider) { if (divider >= 2 && divider <= 490) { hw->clock_divider_reg.co = 0; - hw->clock_divider_reg.cd = (divider / 2) - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clock_divider_reg, cd, (divider / 2) - 1); } else if (divider == 1) { //Setting the divider reg to max value (255) means a divider of 1 hw->clock_divider_reg.co = 0; - hw->clock_divider_reg.cd = 255; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clock_divider_reg, cd, 255); } else { hw->clock_divider_reg.co = 1; - hw->clock_divider_reg.cd = 0; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clock_divider_reg, cd, 0); } } diff --git a/components/hal/esp32h2/include/hal/uart_ll.h b/components/hal/esp32h2/include/hal/uart_ll.h index 6d8fd0f3e9..ca51779548 100644 --- a/components/hal/esp32h2/include/hal/uart_ll.h +++ b/components/hal/esp32h2/include/hal/uart_ll.h @@ -17,8 +17,11 @@ #pragma once + +#include "hal/misc.h" #include "hal/uart_types.h" #include "soc/uart_periph.h" +#include "soc/uart_struct.h" #ifdef __cplusplus extern "C" { @@ -163,7 +166,7 @@ static inline void uart_ll_set_baudrate(uart_dev_t *hw, uint32_t baud) // an integer part and a fractional part. hw->clk_div.div_int = clk_div >> 4; hw->clk_div.div_frag = clk_div & 0xf; - hw->clk_conf.sclk_div_num = sclk_div - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clk_conf, sclk_div_num, sclk_div - 1); #undef DIV_UP } @@ -178,7 +181,7 @@ static inline uint32_t uart_ll_get_baudrate(uart_dev_t *hw) { uint32_t sclk_freq = uart_ll_get_sclk_freq(hw); typeof(hw->clk_div) div_reg = hw->clk_div; - return ((sclk_freq << 4)) / (((div_reg.div_int << 4) | div_reg.div_frag) * (hw->clk_conf.sclk_div_num + 1)); + return ((sclk_freq << 4)) / (((div_reg.div_int << 4) | div_reg.div_frag) * (HAL_FORCE_READ_U32_REG_FIELD(hw->clk_conf, sclk_div_num) + 1)); } /** @@ -451,7 +454,7 @@ static inline void uart_ll_set_tx_idle_num(uart_dev_t *hw, uint32_t idle_num) static inline void uart_ll_tx_break(uart_dev_t *hw, uint32_t break_num) { if (break_num > 0) { - hw->txbrk_conf.tx_brk_num = break_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->txbrk_conf, tx_brk_num, break_num); hw->conf0.txd_brk = 1; } else { hw->conf0.txd_brk = 0; @@ -518,8 +521,8 @@ static inline void uart_ll_set_sw_flow_ctrl(uart_dev_t *hw, uart_sw_flowctrl_t * hw->flow_conf.sw_flow_con_en = 1; hw->swfc_conf1.xon_threshold = flow_ctrl->xon_thrd; hw->swfc_conf0.xoff_threshold = flow_ctrl->xoff_thrd; - hw->swfc_conf1.xon_char = flow_ctrl->xon_char; - hw->swfc_conf0.xoff_char = flow_ctrl->xoff_char; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->swfc_conf1, xon_char, flow_ctrl->xon_char); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->swfc_conf0, xoff_char, flow_ctrl->xoff_char); } else { hw->flow_conf.sw_flow_con_en = 0; hw->flow_conf.xonoff_del = 0; @@ -541,11 +544,11 @@ static inline void uart_ll_set_sw_flow_ctrl(uart_dev_t *hw, uart_sw_flowctrl_t * */ static inline void uart_ll_set_at_cmd_char(uart_dev_t *hw, uart_at_cmd_t *cmd_char) { - hw->at_cmd_char.data = cmd_char->cmd_char; - hw->at_cmd_char.char_num = cmd_char->char_num; - hw->at_cmd_postcnt.post_idle_num = cmd_char->post_idle; - hw->at_cmd_precnt.pre_idle_num = cmd_char->pre_idle; - hw->at_cmd_gaptout.rx_gap_tout = cmd_char->gap_tout; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_char, data, cmd_char->cmd_char); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_char, char_num, cmd_char->char_num); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_postcnt, post_idle_num, cmd_char->post_idle); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_precnt, pre_idle_num, cmd_char->pre_idle); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_gaptout, rx_gap_tout, cmd_char->gap_tout); } /** @@ -734,8 +737,8 @@ static inline void uart_ll_set_mode(uart_dev_t *hw, uart_mode_t mode) */ static inline void uart_ll_get_at_cmd_char(uart_dev_t *hw, uint8_t *cmd_char, uint8_t *char_num) { - *cmd_char = hw->at_cmd_char.data; - *char_num = hw->at_cmd_char.char_num; + *cmd_char = HAL_FORCE_READ_U32_REG_FIELD(hw->at_cmd_char, data); + *char_num = HAL_FORCE_READ_U32_REG_FIELD(hw->at_cmd_char, char_num); } /** diff --git a/components/hal/esp32h2/include/hal/uhci_ll.h b/components/hal/esp32h2/include/hal/uhci_ll.h index 235d28ab3a..a766797ea0 100644 --- a/components/hal/esp32h2/include/hal/uhci_ll.h +++ b/components/hal/esp32h2/include/hal/uhci_ll.h @@ -18,9 +18,13 @@ #pragma once #include -#include "uhci_types.h" +#include "hal/uhci_types.h" #include "soc/uhci_struct.h" +#ifdef __cplusplus +extern "C" { +#endif + #define UHCI_LL_GET_HW(num) (((num) == 0) ? (&UHCI0) : (NULL)) typedef enum { @@ -128,3 +132,7 @@ static inline void uhci_ll_set_eof_mode(uhci_dev_t *hw, uint32_t eof_mode) hw->conf0.len_eof_en = 1; } } + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32h2/include/hal/usb_serial_jtag_ll.h b/components/hal/esp32h2/include/hal/usb_serial_jtag_ll.h index e75cf67b43..0241436ec4 100644 --- a/components/hal/esp32h2/include/hal/usb_serial_jtag_ll.h +++ b/components/hal/esp32h2/include/hal/usb_serial_jtag_ll.h @@ -15,6 +15,8 @@ // The LL layer of the USB-serial-jtag controller #pragma once + +#include "hal/misc.h" #include "soc/usb_serial_jtag_reg.h" #include "soc/usb_serial_jtag_struct.h" @@ -108,7 +110,7 @@ static inline int usb_serial_jtag_ll_read_rxfifo(uint8_t *buf, uint32_t rd_len) int i; for (i = 0; i < (int)rd_len; i++) { if (!USB_SERIAL_JTAG.ep1_conf.serial_out_ep_data_avail) break; - buf[i] = USB_SERIAL_JTAG.ep1.rdwr_byte; + buf[i] = HAL_FORCE_READ_U32_REG_FIELD(USB_SERIAL_JTAG.ep1, rdwr_byte); } return i; } @@ -127,7 +129,7 @@ static inline int usb_serial_jtag_ll_write_txfifo(const uint8_t *buf, uint32_t w int i; for (i = 0; i < (int)wr_len; i++) { if (!USB_SERIAL_JTAG.ep1_conf.serial_in_ep_data_free) break; - USB_SERIAL_JTAG.ep1.rdwr_byte = buf[i]; + HAL_FORCE_MODIFY_U32_REG_FIELD(USB_SERIAL_JTAG.ep1, rdwr_byte, buf[i]); } return i; } diff --git a/components/hal/esp32s2/adc_hal.c b/components/hal/esp32s2/adc_hal.c index b11de2776f..d1196c61e3 100644 --- a/components/hal/esp32s2/adc_hal.c +++ b/components/hal/esp32s2/adc_hal.c @@ -18,7 +18,6 @@ #include "hal/adc_hal.h" #include "hal/adc_types.h" #include "hal/adc_hal_conf.h" -#include "esp_log.h" /*--------------------------------------------------------------- Digital controller setting diff --git a/components/hal/esp32s2/include/hal/adc_ll.h b/components/hal/esp32s2/include/hal/adc_ll.h index ffad47a5c3..a44f50915f 100644 --- a/components/hal/esp32s2/include/hal/adc_ll.h +++ b/components/hal/esp32s2/include/hal/adc_ll.h @@ -1,9 +1,11 @@ #pragma once #include +#include "hal/misc.h" #include "soc/adc_periph.h" #include "hal/adc_types.h" #include "soc/apb_saradc_struct.h" +#include "soc/sens_struct.h" #include "soc/apb_saradc_reg.h" #include "soc/rtc_cntl_struct.h" #include "soc/rtc_cntl_reg.h" @@ -83,11 +85,11 @@ typedef enum { static inline void adc_ll_digi_set_fsm_time(uint32_t rst_wait, uint32_t start_wait, uint32_t standby_wait) { // Internal FSM reset wait time - APB_SARADC.fsm_wait.rstb_wait = rst_wait; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.fsm_wait, rstb_wait, rst_wait); // Internal FSM start wait time - APB_SARADC.fsm_wait.xpd_wait = start_wait; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.fsm_wait, xpd_wait, start_wait); // Internal FSM standby wait time - APB_SARADC.fsm_wait.standby_wait = standby_wait; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.fsm_wait, standby_wait, standby_wait); } /** @@ -115,7 +117,7 @@ static inline void adc_ll_set_sample_cycle(uint32_t sample_cycle) static inline void adc_ll_digi_set_clk_div(uint32_t div) { /* ADC clock devided from digital controller clock clk */ - APB_SARADC.ctrl.sar_clk_div = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.ctrl, sar_clk_div, div); } /** @@ -136,7 +138,7 @@ static inline void adc_ll_digi_set_output_format(adc_digi_output_format_t format */ static inline void adc_ll_digi_set_convert_limit_num(uint32_t meas_num) { - APB_SARADC.ctrl2.max_meas_num = meas_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.ctrl2, max_meas_num, meas_num); } /** @@ -307,7 +309,7 @@ static inline void adc_ll_digi_trigger_disable(void) */ static inline void adc_ll_digi_controller_clk_div(uint32_t div_num, uint32_t div_b, uint32_t div_a) { - APB_SARADC.apb_adc_clkm_conf.clkm_div_num = div_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.apb_adc_clkm_conf, clkm_div_num, div_num); APB_SARADC.apb_adc_clkm_conf.clkm_div_b = div_b; APB_SARADC.apb_adc_clkm_conf.clkm_div_a = div_a; } @@ -427,9 +429,9 @@ static inline void adc_ll_digi_filter_enable(adc_ll_num_t adc_n, bool enable) static inline uint32_t adc_ll_digi_filter_read_data(adc_ll_num_t adc_n) { if (adc_n == ADC_NUM_1) { - return APB_SARADC.filter_status.adc1_filter_data; + return HAL_FORCE_READ_U32_REG_FIELD(APB_SARADC.filter_status, adc1_filter_data); } else { // adc_n == ADC_NUM_2 - return APB_SARADC.filter_status.adc2_filter_data; + return HAL_FORCE_READ_U32_REG_FIELD(APB_SARADC.filter_status, adc2_filter_data); } } @@ -595,7 +597,7 @@ static inline uint32_t adc_ll_digi_get_intr_status(adc_ll_num_t adc_n) */ static inline void adc_ll_digi_dma_set_eof_num(uint32_t num) { - APB_SARADC.dma_conf.apb_adc_eof_num = num; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.dma_conf, apb_adc_eof_num, num); } /** @@ -710,7 +712,7 @@ static inline void adc_ll_rtc_disable_channel(adc_ll_num_t adc_n) static inline void adc_ll_rtc_start_convert(adc_ll_num_t adc_n, int channel) { if (adc_n == ADC_NUM_1) { - while (SENS.sar_slave_addr1.meas_status != 0); + while (HAL_FORCE_READ_U32_REG_FIELD(SENS.sar_slave_addr1, meas_status) != 0) {} SENS.sar_meas1_ctrl2.meas1_start_sar = 0; SENS.sar_meas1_ctrl2.meas1_start_sar = 1; } else { // adc_n == ADC_NUM_2 @@ -749,9 +751,9 @@ static inline int adc_ll_rtc_get_convert_value(adc_ll_num_t adc_n) { int ret_val = 0; if (adc_n == ADC_NUM_1) { - ret_val = SENS.sar_meas1_ctrl2.meas1_data_sar; + ret_val = HAL_FORCE_READ_U32_REG_FIELD(SENS.sar_meas1_ctrl2, meas1_data_sar); } else { // adc_n == ADC_NUM_2 - ret_val = SENS.sar_meas2_ctrl2.meas2_data_sar; + ret_val = HAL_FORCE_READ_U32_REG_FIELD(SENS.sar_meas2_ctrl2, meas2_data_sar); } return ret_val; } @@ -906,9 +908,9 @@ static inline adc_ll_power_t adc_ll_get_power_manage(void) static inline void adc_ll_set_sar_clk_div(adc_ll_num_t adc_n, uint32_t div) { if (adc_n == ADC_NUM_1) { - SENS.sar_reader1_ctrl.sar1_clk_div = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_reader1_ctrl, sar1_clk_div, div); } else { // adc_n == ADC_NUM_2 - SENS.sar_reader2_ctrl.sar2_clk_div = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_reader2_ctrl, sar2_clk_div, div); } } diff --git a/components/hal/esp32s2/include/hal/aes_ll.h b/components/hal/esp32s2/include/hal/aes_ll.h index 9056216517..653253d06d 100644 --- a/components/hal/esp32s2/include/hal/aes_ll.h +++ b/components/hal/esp32s2/include/hal/aes_ll.h @@ -1,4 +1,4 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// Copyright 2020-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. @@ -15,6 +15,7 @@ #pragma once #include +#include #include "soc/hwcrypto_reg.h" #include "hal/aes_types.h" @@ -46,10 +47,11 @@ static inline uint8_t aes_ll_write_key(const uint8_t *key, size_t key_word_len) { /* This variable is used for fault injection checks, so marked volatile to avoid optimisation */ volatile uint8_t key_in_hardware = 0; - uint32_t *key_words = (uint32_t *)key; - + /* Memcpy to avoid potential unaligned access */ + uint32_t key_word; for (int i = 0; i < key_word_len; i++) { - REG_WRITE(AES_KEY_BASE + i * 4, *(key_words + i)); + memcpy(&key_word, key + 4 * i, 4); + REG_WRITE(AES_KEY_BASE + i * 4, key_word); key_in_hardware += 4; } return key_in_hardware; @@ -77,22 +79,12 @@ static inline void aes_ll_set_mode(int mode, uint8_t key_bytes) */ static inline void aes_ll_write_block(const void *input) { - const uint32_t *input_words = (const uint32_t *)input; - uint32_t i0, i1, i2, i3; + uint32_t input_word; - /* Storing i0,i1,i2,i3 in registers not an array - helps a lot with optimisations at -Os level */ - i0 = input_words[0]; - REG_WRITE(AES_TEXT_IN_BASE, i0); - - i1 = input_words[1]; - REG_WRITE(AES_TEXT_IN_BASE + 4, i1); - - i2 = input_words[2]; - REG_WRITE(AES_TEXT_IN_BASE + 8, i2); - - i3 = input_words[3]; - REG_WRITE(AES_TEXT_IN_BASE + 12, i3); + for (int i = 0; i < AES_BLOCK_WORDS; i++) { + memcpy(&input_word, (uint8_t*)input + 4 * i, 4); + REG_WRITE(AES_TEXT_IN_BASE + i * 4, input_word); + } } /** @@ -102,11 +94,13 @@ static inline void aes_ll_write_block(const void *input) */ static inline void aes_ll_read_block(void *output) { - uint32_t *output_words = (uint32_t *)output; + uint32_t output_word; const size_t REG_WIDTH = sizeof(uint32_t); for (size_t i = 0; i < AES_BLOCK_WORDS; i++) { - output_words[i] = REG_READ(AES_TEXT_OUT_BASE + (i * REG_WIDTH)); + output_word = REG_READ(AES_TEXT_OUT_BASE + (i * REG_WIDTH)); + /* Memcpy to avoid potential unaligned access */ + memcpy( (uint8_t*)output + i * 4, &output_word, sizeof(output_word)); } } @@ -190,11 +184,13 @@ static inline void aes_ll_set_num_blocks(size_t num_blocks) */ static inline void aes_ll_set_iv(const uint8_t *iv) { - uint32_t *iv_words = (uint32_t *)iv; uint32_t *reg_addr_buf = (uint32_t *)(AES_IV_BASE); + uint32_t iv_word; for (int i = 0; i < IV_WORDS; i++ ) { - REG_WRITE(®_addr_buf[i], iv_words[i]); + /* Memcpy to avoid potential unaligned access */ + memcpy(&iv_word, iv + 4 * i, sizeof(iv_word)); + REG_WRITE(®_addr_buf[i], iv_word); } } @@ -203,11 +199,13 @@ static inline void aes_ll_set_iv(const uint8_t *iv) */ static inline void aes_ll_read_iv(uint8_t *iv) { - uint32_t *iv_words = (uint32_t *)iv; + uint32_t iv_word; const size_t REG_WIDTH = sizeof(uint32_t); for (size_t i = 0; i < IV_WORDS; i++) { - iv_words[i] = REG_READ(AES_IV_BASE + (i * REG_WIDTH)); + iv_word = REG_READ(AES_IV_BASE + (i * REG_WIDTH)); + /* Memcpy to avoid potential unaligned access */ + memcpy(iv + i * 4, &iv_word, sizeof(iv_word)); } } @@ -247,13 +245,14 @@ static inline void aes_ll_interrupt_clear(void) */ static inline void aes_ll_gcm_read_hash(uint8_t *gcm_hash) { - uint32_t *hash_words = (uint32_t *)gcm_hash; const size_t REG_WIDTH = sizeof(uint32_t); + uint32_t hash_word; for (size_t i = 0; i < AES_BLOCK_WORDS; i++) { - hash_words[i] = REG_READ(AES_H_BASE + (i * REG_WIDTH)); + hash_word = REG_READ(AES_H_BASE + (i * REG_WIDTH)); + /* Memcpy to avoid potential unaligned access */ + memcpy(gcm_hash + i * 4, &hash_word, sizeof(hash_word)); } - } /** @@ -277,11 +276,13 @@ static inline void aes_ll_gcm_set_aad_num_blocks(size_t aad_num_blocks) */ static inline void aes_ll_gcm_set_j0(const uint8_t *j0) { - uint32_t *j0_words = (uint32_t *)j0; uint32_t *reg_addr_buf = (uint32_t *)(AES_J_BASE); + uint32_t j0_word; for (int i = 0; i < AES_BLOCK_WORDS; i++ ) { - REG_WRITE(®_addr_buf[i], j0_words[i]); + /* Memcpy to avoid potential unaligned access */ + memcpy(&j0_word, j0 + 4 * i, sizeof(j0_word)); + REG_WRITE(®_addr_buf[i], j0_word); } } @@ -304,11 +305,13 @@ static inline void aes_ll_gcm_set_num_valid_bit(size_t num_valid_bits) */ static inline void aes_ll_gcm_read_tag(uint8_t *tag) { - uint32_t *tag_words = (uint32_t *)tag; + uint32_t tag_word; const size_t REG_WIDTH = sizeof(uint32_t); for (size_t i = 0; i < TAG_WORDS; i++) { - tag_words[i] = REG_READ(AES_T_BASE + (i * REG_WIDTH)); + tag_word = REG_READ(AES_T_BASE + (i * REG_WIDTH)); + /* Memcpy to avoid potential unaligned access */ + memcpy(tag + i * 4, &tag_word, sizeof(tag_word)); } } diff --git a/components/hal/esp32s2/include/hal/clk_gate_ll.h b/components/hal/esp32s2/include/hal/clk_gate_ll.h index ab0e04dee6..7a2bbe6cf2 100644 --- a/components/hal/esp32s2/include/hal/clk_gate_ll.h +++ b/components/hal/esp32s2/include/hal/clk_gate_ll.h @@ -43,8 +43,6 @@ static inline uint32_t periph_ll_get_clk_en_mask(periph_module_t periph) return DPORT_I2C_EXT1_CLK_EN; case PERIPH_I2S0_MODULE: return DPORT_I2S0_CLK_EN; - case PERIPH_I2S1_MODULE: - return DPORT_I2S1_CLK_EN; case PERIPH_TIMG0_MODULE: return DPORT_TIMERGROUP_CLK_EN; case PERIPH_TIMG1_MODULE: @@ -115,8 +113,6 @@ static inline uint32_t periph_ll_get_rst_en_mask(periph_module_t periph, bool en return DPORT_I2C_EXT1_RST; case PERIPH_I2S0_MODULE: return DPORT_I2S0_RST; - case PERIPH_I2S1_MODULE: - return DPORT_I2S1_RST; case PERIPH_TIMG0_MODULE: return DPORT_TIMERGROUP_RST; case PERIPH_TIMG1_MODULE: diff --git a/components/hal/esp32s2/include/hal/dac_ll.h b/components/hal/esp32s2/include/hal/dac_ll.h index 11f3284f11..28c8ae2066 100644 --- a/components/hal/esp32s2/include/hal/dac_ll.h +++ b/components/hal/esp32s2/include/hal/dac_ll.h @@ -21,9 +21,12 @@ #pragma once #include +#include "hal/misc.h" #include "soc/dac_periph.h" #include "hal/dac_types.h" #include "soc/apb_saradc_struct.h" +#include "soc/sens_struct.h" +#include "soc/rtc_io_struct.h" #include "soc/apb_saradc_reg.h" #ifdef __cplusplus @@ -74,10 +77,10 @@ static inline void dac_ll_update_output_value(dac_channel_t channel, uint8_t val { if (channel == DAC_CHANNEL_1) { SENS.sar_dac_ctrl2.dac_cw_en1 = 0; - RTCIO.pad_dac[channel].dac = value; + HAL_FORCE_MODIFY_U32_REG_FIELD(RTCIO.pad_dac[channel], dac, value); } else if (channel == DAC_CHANNEL_2) { SENS.sar_dac_ctrl2.dac_cw_en2 = 0; - RTCIO.pad_dac[channel].dac = value; + HAL_FORCE_MODIFY_U32_REG_FIELD(RTCIO.pad_dac[channel], dac, value); } } @@ -145,7 +148,7 @@ static inline void dac_ll_cw_set_channel(dac_channel_t channel, bool enable) static inline void dac_ll_cw_set_freq(uint32_t freq) { uint32_t sw_freq = freq * 0xFFFF / RTC_FAST_CLK_FREQ_APPROX; - SENS.sar_dac_ctrl1.sw_fstep = (sw_freq > 0xFFFF) ? 0xFFFF : sw_freq; + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_dac_ctrl1, sw_fstep, (sw_freq > 0xFFFF) ? 0xFFFF : sw_freq); } /** @@ -192,12 +195,12 @@ static inline void dac_ll_cw_set_dc_offset(dac_channel_t channel, int8_t offset) if (SENS.sar_dac_ctrl2.dac_inv1 == DAC_CW_PHASE_180) { offset = 0 - offset; } - SENS.sar_dac_ctrl2.dac_dc1 = offset ? offset : (-128 - offset); + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_dac_ctrl2, dac_dc1, offset ? offset : (-128 - offset)); } else if (channel == DAC_CHANNEL_2) { if (SENS.sar_dac_ctrl2.dac_inv2 == DAC_CW_PHASE_180) { offset = 0 - offset; } - SENS.sar_dac_ctrl2.dac_dc2 = offset ? offset : (-128 - offset); + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_dac_ctrl2, dac_dc2, offset ? offset : (-128 - offset)); } } diff --git a/components/hal/esp32s2/include/hal/dedic_gpio_ll.h b/components/hal/esp32s2/include/hal/dedic_gpio_ll.h index 3cbf29b7bb..8fcdd0e7a6 100644 --- a/components/hal/esp32s2/include/hal/dedic_gpio_ll.h +++ b/components/hal/esp32s2/include/hal/dedic_gpio_ll.h @@ -19,6 +19,7 @@ extern "C" { #include #include +#include "hal/misc.h" #include "soc/dedic_gpio_struct.h" static inline void dedic_gpio_ll_enable_instruction_access_out(dedic_dev_t *dev, uint32_t channel_mask, bool enable) @@ -61,12 +62,12 @@ static inline void dedic_gpio_ll_toggle_channel(dedic_dev_t *dev, uint32_t chann static inline uint32_t dedic_gpio_ll_read_out_all(dedic_dev_t *dev) { - return dev->gpio_out_scan.gpio_out_status; + return HAL_FORCE_READ_U32_REG_FIELD(dev->gpio_out_scan, gpio_out_status); } static inline uint32_t dedic_gpio_ll_read_in_all(dedic_dev_t *dev) { - return dev->gpio_in_scan.gpio_in_status; + return HAL_FORCE_READ_U32_REG_FIELD(dev->gpio_in_scan, gpio_in_status); } static inline void dedic_gpio_ll_set_input_delay(dedic_dev_t *dev, uint32_t channel, uint32_t delay_cpu_clks) diff --git a/components/hal/esp32s2/include/hal/gpio_ll.h b/components/hal/esp32s2/include/hal/gpio_ll.h index d6330db630..34cdc464bc 100644 --- a/components/hal/esp32s2/include/hal/gpio_ll.h +++ b/components/hal/esp32s2/include/hal/gpio_ll.h @@ -26,6 +26,7 @@ #include "soc/gpio_periph.h" #include "soc/rtc_cntl_reg.h" #include "soc/rtc_io_reg.h" +#include "soc/gpio_struct.h" #include "hal/gpio_types.h" #ifdef __cplusplus diff --git a/components/hal/esp32s2/include/hal/gpspi_flash_ll.h b/components/hal/esp32s2/include/hal/gpspi_flash_ll.h index 6f7d441c06..79fc727bdd 100644 --- a/components/hal/esp32s2/include/hal/gpspi_flash_ll.h +++ b/components/hal/esp32s2/include/hal/gpspi_flash_ll.h @@ -24,11 +24,13 @@ #include #include "soc/spi_periph.h" +#include "soc/spi_struct.h" #include "hal/spi_types.h" #include "hal/spi_flash_types.h" #include // For MIN/MAX #include #include +#include "hal/misc.h" #ifdef __cplusplus extern "C" { @@ -357,7 +359,7 @@ static inline void gpspi_flash_ll_set_address(spi_dev_t *dev, uint32_t addr) static inline void gpspi_flash_ll_set_dummy(spi_dev_t *dev, uint32_t dummy_n) { dev->user.usr_dummy = dummy_n ? 1 : 0; - dev->user1.usr_dummy_cyclelen = dummy_n - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user1, usr_dummy_cyclelen, dummy_n - 1); } /** diff --git a/components/hal/esp32s2/include/hal/i2c_ll.h b/components/hal/esp32s2/include/hal/i2c_ll.h index 81fb326b55..1d2b8a0c13 100644 --- a/components/hal/esp32s2/include/hal/i2c_ll.h +++ b/components/hal/esp32s2/include/hal/i2c_ll.h @@ -16,6 +16,7 @@ #pragma once #include "soc/i2c_periph.h" +#include "soc/i2c_struct.h" #include "hal/i2c_types.h" #ifdef __cplusplus diff --git a/components/hal/esp32s2/include/hal/i2s_ll.h b/components/hal/esp32s2/include/hal/i2s_ll.h index 3e0a7eeb20..6f453221ee 100644 --- a/components/hal/esp32s2/include/hal/i2s_ll.h +++ b/components/hal/esp32s2/include/hal/i2s_ll.h @@ -1,4 +1,4 @@ -// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// 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. @@ -23,7 +23,9 @@ #pragma once #include +#include "hal/misc.h" #include "soc/i2s_periph.h" +#include "soc/i2s_struct.h" #include "hal/i2s_types.h" #ifdef __cplusplus @@ -31,89 +33,376 @@ extern "C" { #endif // Get I2S hardware instance with giving i2s num -#define I2S_LL_GET_HW(num) (((num) == 0) ? (&I2S0) : NULL) +#define I2S_LL_GET_HW(num) (((num) == 0) ? (&I2S0) : NULL) -#define I2S_INTR_IN_SUC_EOF BIT(9) -#define I2S_INTR_OUT_EOF BIT(12) -#define I2S_INTR_IN_DSCR_ERR BIT(13) -#define I2S_INTR_OUT_DSCR_ERR BIT(14) -#define I2S_INTR_MAX (0xFFFFFFFF) +#define I2S_LL_BASE_CLK (2 * APB_CLK_FREQ) + +#define I2S_LL_MCLK_DIVIDER_BIT_WIDTH (6) +#define I2S_LL_MCLK_DIVIDER_MAX ((1 << I2S_LL_MCLK_DIVIDER_BIT_WIDTH) - 1) + +/* I2S clock configuration structure */ +typedef struct { + uint16_t mclk_div; // I2S module clock devider, Fmclk = Fsclk /(mclk_div+b/a) + uint16_t a; + uint16_t b; // The decimal part of module clock devider, the decimal is: b/a +} i2s_ll_mclk_div_t; + +#define I2S_LL_EVENT_TX_EOF (1 << 12) +#define I2S_LL_BCK_MAX_PRESCALE (64) /** - * @brief Reset rx fifo + * @brief Enable DMA descriptor owner check * * @param hw Peripheral I2S hardware instance address. + * @param en whether to enable owner check */ -static inline void i2s_ll_reset_rx_fifo(i2s_dev_t *hw) +static inline void i2s_ll_dma_enable_owner_check(i2s_dev_t *hw, bool en) { - hw->conf.rx_fifo_reset = 1; - hw->conf.rx_fifo_reset = 0; + hw->lc_conf.check_owner = en; } /** - * @brief Reset tx fifo + * @brief Enable DMA descriptor write back + * + * @param hw Peripheral I2S hardware instance address. + * @param en whether to enable write back + */ +static inline void i2s_ll_dma_enable_auto_write_back(i2s_dev_t *hw, bool en) +{ + hw->lc_conf.out_auto_wrback = en; +} + +/** + * @brief I2S DMA generate EOF event on data in FIFO poped out + * + * @param hw Peripheral I2S hardware instance address. + * @param en True to enable, False to disable + */ +static inline void i2s_ll_dma_enable_eof_on_fifo_empty(i2s_dev_t *hw, bool en) +{ + hw->lc_conf.out_eof_mode = en; +} + +/** + * @brief I2S module general init, enable I2S clock. * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_tx_fifo(i2s_dev_t *hw) +static inline void i2s_ll_enable_clock(i2s_dev_t *hw) +{ + if (hw->clkm_conf.clk_en == 0) { + hw->clkm_conf.clk_sel = 2; + hw->clkm_conf.clk_en = 1; + hw->conf2.val = 0; + } +} + +/** + * @brief I2S module disable clock. + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_disable_clock(i2s_dev_t *hw) +{ + if (hw->clkm_conf.clk_en == 1) { + hw->clkm_conf.clk_en = 0; + } +} + +/** + * @brief I2S tx msb right enable + * + * @param hw Peripheral I2S hardware instance address. + * @param enable Set true to enable tx msb right + */ +static inline void i2s_ll_tx_enable_msb_right(i2s_dev_t *hw, bool enable) +{ + hw->conf.tx_msb_right = enable; +} + +/** + * @brief I2S rx msb right enable + * + * @param hw Peripheral I2S hardware instance address. + * @param enable Set true to enable rx msb right + */ +static inline void i2s_ll_rx_enable_msb_right(i2s_dev_t *hw, bool enable) +{ + hw->conf.rx_msb_right = enable; +} + +/** + * @brief I2S tx right channel first + * + * @param hw Peripheral I2S hardware instance address. + * @param enable Set true to enable send right channel first + */ +static inline void i2s_ll_tx_enable_right_first(i2s_dev_t *hw, bool enable) +{ + hw->conf.tx_right_first = enable; +} + +/** + * @brief I2S rx right channel first + * + * @param hw Peripheral I2S hardware instance address. + * @param enable Set true to enable receive right channel first + */ +static inline void i2s_ll_rx_enable_right_first(i2s_dev_t *hw, bool enable) +{ + hw->conf.rx_right_first = enable; +} + +/** + * @brief I2S tx fifo module force enable + * + * @param hw Peripheral I2S hardware instance address. + * @param enable Set true to enable tx fifo module + */ +static inline void i2s_ll_tx_force_enable_fifo_mod(i2s_dev_t *hw, bool enable) +{ + hw->fifo_conf.tx_fifo_mod_force_en = enable; +} + +/** + * @brief I2S rx fifo module force enable + * + * @param hw Peripheral I2S hardware instance address. + * @param enable Set true to enable rx fifo module + */ +static inline void i2s_ll_rx_force_enable_fifo_mod(i2s_dev_t *hw, bool enable) +{ + hw->fifo_conf.rx_fifo_mod_force_en = enable; +} + +/** + * @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->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->conf.rx_slave_mod = slave_en; +} + +/** + * @brief Reset TX module + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_tx_reset(i2s_dev_t *hw) +{ + hw->conf.tx_reset = 1; + hw->conf.tx_reset = 0; +} + +/** + * @brief Reset RX module + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_rx_reset(i2s_dev_t *hw) +{ + hw->conf.rx_reset = 1; + hw->conf.rx_reset = 0; +} + +/** + * @brief Reset TX FIFO + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_tx_reset_fifo(i2s_dev_t *hw) { hw->conf.tx_fifo_reset = 1; hw->conf.tx_fifo_reset = 0; } /** - * @brief Enable rx interrupt + * @brief Reset RX FIFO * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_enable_rx_intr(i2s_dev_t *hw) +static inline void i2s_ll_rx_reset_fifo(i2s_dev_t *hw) { - hw->int_ena.in_suc_eof = 1; - hw->int_ena.in_dscr_err = 1; + hw->conf.rx_fifo_reset = 1; + hw->conf.rx_fifo_reset = 0; } /** - * @brief Disable rx interrupt + * @brief Set TX source clock * * @param hw Peripheral I2S hardware instance address. + * @param src I2S source clock */ -static inline void i2s_ll_disable_rx_intr(i2s_dev_t *hw) +static inline void i2s_ll_tx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) { - hw->int_ena.in_suc_eof = 0; - hw->int_ena.in_dscr_err = 0; + hw->clkm_conf.clk_sel = (src == I2S_CLK_APLL) ? 1 : 2; } /** - * @brief Disable tx interrupt + * @brief Set RX source clock * * @param hw Peripheral I2S hardware instance address. + * @param src I2S source clock */ -static inline void i2s_ll_disable_tx_intr(i2s_dev_t *hw) +static inline void i2s_ll_rx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) { - hw->int_ena.out_eof = 0; - hw->int_ena.out_dscr_err = 0; + hw->clkm_conf.clk_sel = (src == I2S_CLK_APLL) ? 1 : 2; } /** - * @brief Enable tx interrupt + * @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->sample_rate_conf.tx_bck_div_num = val; +} + +/** + * @brief Configure I2S TX clock devider + * + * @param hw Peripheral I2S hardware instance address. + * @param set Pointer to I2S clock devider configuration paramater + */ +static inline void i2s_ll_tx_set_clk(i2s_dev_t *hw, i2s_ll_mclk_div_t *set) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clkm_conf, clkm_div_num, set->mclk_div); + hw->clkm_conf.clkm_div_b = set->b; + hw->clkm_conf.clkm_div_a = set->a; +} + +/** + * @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->sample_rate_conf.rx_bck_div_num = val; +} + +/** + * @brief Configure I2S RX clock devider + * + * @param hw Peripheral I2S hardware instance address. + * @param set Pointer to I2S clock devider configuration paramater + */ +static inline void i2s_ll_rx_set_clk(i2s_dev_t *hw, i2s_ll_mclk_div_t *set) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clkm_conf, clkm_div_num, set->mclk_div); + hw->clkm_conf.clkm_div_b = set->b; + hw->clkm_conf.clkm_div_a = set->a; +} + +/** + * @brief Enable interrupt by mask + * + * @param hw Peripheral I2S hardware instance address. + * @param mask Interrupt event mask + * @param en true to enable, false to disable + */ +static inline void i2s_ll_enable_intr(i2s_dev_t *hw, uint32_t mask, bool en) +{ + if (en) { + hw->int_ena.val |= mask; + } else { + hw->int_ena.val &= ~mask; + } +} + +/** + * @brief Enable TX interrupt * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_enable_tx_intr(i2s_dev_t *hw) +static inline void i2s_ll_tx_enable_intr(i2s_dev_t *hw) { hw->int_ena.out_eof = 1; hw->int_ena.out_dscr_err = 1; } /** - * @brief Reset dma in + * @brief Disable TX interrupt * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_dma_in(i2s_dev_t *hw) +static inline void i2s_ll_tx_disable_intr(i2s_dev_t *hw) { - hw->lc_conf.in_rst = 1; - hw->lc_conf.in_rst = 0; + hw->int_ena.out_eof = 0; + hw->int_ena.out_dscr_err = 0; +} + +/** + * @brief Enable RX interrupt + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_rx_enable_intr(i2s_dev_t *hw) +{ + hw->int_ena.in_suc_eof = 1; + hw->int_ena.in_dscr_err = 1; +} + +/** + * @brief Disable RX interrupt + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_rx_disable_intr(i2s_dev_t *hw) +{ + hw->int_ena.in_suc_eof = 0; + hw->int_ena.in_dscr_err = 0; +} + +/** + * @brief Get interrupt status register address + * + * @param hw Peripheral I2S hardware instance address. + * @return interrupt status register address + */ +static inline volatile void *i2s_ll_get_intr_status_reg(i2s_dev_t *hw) +{ + return &hw->int_st; +} + +/** + * @brief Get I2S interrupt status + * + * @param hw Peripheral I2S hardware instance address. + * @return + * - module interrupt status + */ +static inline uint32_t i2s_ll_get_intr_status(i2s_dev_t *hw) +{ + return hw->int_st.val; +} + +/** + * @brief Clear I2S interrupt status + * + * @param hw Peripheral I2S hardware instance address. + * @param clr_mask Interrupt mask to be cleared. + */ +static inline void i2s_ll_clear_intr_status(i2s_dev_t *hw, uint32_t clr_mask) +{ + hw->int_clr.val = clr_mask; } /** @@ -121,32 +410,47 @@ static inline void i2s_ll_reset_dma_in(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_dma_out(i2s_dev_t *hw) +static inline void i2s_ll_tx_reset_dma(i2s_dev_t *hw) { hw->lc_conf.out_rst = 1; hw->lc_conf.out_rst = 0; } /** - * @brief Reset tx + * @brief Reset dma in * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_tx(i2s_dev_t *hw) +static inline void i2s_ll_rx_reset_dma(i2s_dev_t *hw) { - hw->conf.tx_reset = 1; - hw->conf.tx_reset = 0; + hw->lc_conf.in_rst = 1; + hw->lc_conf.in_rst = 0; } /** - * @brief Reset rx + * @brief Enable TX PDM mode. + * @note ESP32-S2 doesn't support pdm + * This function is used to be compatible with those support pdm * - * @param hw Peripheral I2S hardware instance address. + * @param hw Peripheral I2S hardware instance address (ignored) + * @param pdm_enable Set true to TX enable PDM mode (ignored) */ -static inline void i2s_ll_reset_rx(i2s_dev_t *hw) +static inline void i2s_ll_tx_enable_pdm(i2s_dev_t *hw, bool pdm_enable) { - hw->conf.rx_reset = 1; - hw->conf.rx_reset = 0; + // Remain empty +} + +/** + * @brief Enable RX PDM mode. + * @note ESP32-S2 doesn't support pdm + * This function is used to be compatible with those support pdm + * + * @param hw Peripheral I2S hardware instance address (ignored) + * @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) +{ + // Remain empty } /** @@ -159,222 +463,6 @@ static inline void i2s_ll_start_out_link(i2s_dev_t *hw) hw->out_link.start = 1; } -/** - * @brief Start tx - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_start_tx(i2s_dev_t *hw) -{ - hw->conf.tx_start = 1; -} - -/** - * @brief Start in link - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_start_in_link(i2s_dev_t *hw) -{ - hw->in_link.start = 1; -} - -/** - * @brief Start rx - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_start_rx(i2s_dev_t *hw) -{ - hw->conf.rx_start = 1; -} - -/** - * @brief Stop out link - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_stop_out_link(i2s_dev_t *hw) -{ - hw->out_link.stop = 1; -} - -/** - * @brief Stop tx - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_stop_tx(i2s_dev_t *hw) -{ - hw->conf.tx_start = 0; -} - -/** - * @brief Stop in link - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_stop_in_link(i2s_dev_t *hw) -{ - hw->in_link.stop = 1; -} - -/** - * @brief Stop rx - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_stop_rx(i2s_dev_t *hw) -{ - hw->conf.rx_start = 0; -} - -/** - * @brief Enable dma - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_enable_dma(i2s_dev_t *hw) -{ - //Enable and configure DMA - typeof(hw->lc_conf) lc_conf; - lc_conf.val = 0; - lc_conf.out_eof_mode = 1; - hw->lc_conf.val = lc_conf.val; -} - -/** - * @brief Get I2S interrupt status - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get interrupt status - */ -static inline void i2s_ll_get_intr_status(i2s_dev_t *hw, uint32_t *val) -{ - *val = hw->int_st.val; -} - -/** - * @brief Clear I2S interrupt status - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to clear interrupt status - */ -static inline void i2s_ll_clear_intr_status(i2s_dev_t *hw, uint32_t val) -{ - hw->int_clr.val = val; -} - -/** - * @brief Get I2S out eof des address - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get out eof des address - */ -static inline void i2s_ll_get_out_eof_des_addr(i2s_dev_t *hw, uint32_t *val) -{ - *val = hw->out_eof_des_addr; -} - -/** - * @brief Get I2S in eof des address - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get in eof des address - */ -static inline void i2s_ll_get_in_eof_des_addr(i2s_dev_t *hw, uint32_t *val) -{ - *val = hw->in_eof_des_addr; -} - -/** - * @brief Get I2S tx fifo mode - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get tx fifo mode - */ -static inline void i2s_ll_get_tx_fifo_mod(i2s_dev_t *hw, uint32_t *val) -{ - *val = hw->fifo_conf.tx_fifo_mod; -} - -/** - * @brief Set I2S tx fifo mode - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx fifo mode - */ -static inline void i2s_ll_set_tx_fifo_mod(i2s_dev_t *hw, uint32_t val) -{ - hw->fifo_conf.tx_fifo_mod = val; -} - -/** - * @brief Get I2S rx fifo mode - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get rx fifo mode - */ -static inline void i2s_ll_get_rx_fifo_mod(i2s_dev_t *hw, uint32_t *val) -{ - *val = hw->fifo_conf.rx_fifo_mod; -} - -/** - * @brief Set I2S rx fifo mode - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx fifo mode - */ -static inline void i2s_ll_set_rx_fifo_mod(i2s_dev_t *hw, uint32_t val) -{ - hw->fifo_conf.rx_fifo_mod = val; -} - -/** - * @brief Set I2S tx chan mode - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx chan mode - */ -static inline void i2s_ll_set_tx_chan_mod(i2s_dev_t *hw, uint32_t val) -{ - hw->conf_chan.tx_chan_mod = val; -} - -/** - * @brief Set I2S rx chan mode - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx chan mode - */ -static inline void i2s_ll_set_rx_chan_mod(i2s_dev_t *hw, uint32_t val) -{ - hw->conf_chan.rx_chan_mod = val; -} - -/** - * @brief Set I2S tx dma equal - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx dma equal - */ -static inline void i2s_ll_set_tx_dma_equal(i2s_dev_t *hw, uint32_t val) -{ - hw->conf.tx_dma_equal = val; -} - -/** - * @brief Set I2S rx dma equal - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx dma equal - */ -static inline void i2s_ll_set_rx_dma_equal(i2s_dev_t *hw, uint32_t val) -{ - hw->conf.rx_dma_equal = val; -} - /** * @brief Set I2S out link address * @@ -387,289 +475,157 @@ static inline void i2s_ll_set_out_link_addr(i2s_dev_t *hw, uint32_t val) } /** - * @brief Set I2S in link address + * @brief Start TX module * * @param hw Peripheral I2S hardware instance address. - * @param val value to set in link address */ -static inline void i2s_ll_set_in_link_addr(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_tx_start(i2s_dev_t *hw) { - hw->in_link.addr = val; + hw->conf.tx_start = 1; } /** - * @brief Set I2S rx eof num + * @brief Start RX module * * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx eof num */ -static inline void i2s_ll_set_rx_eof_num(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_rx_start(i2s_dev_t *hw) { - hw->rx_eof_num = val; + hw->conf.rx_start = 1; } /** - * @brief Set I2S clkm div num + * @brief Configure TX DMA descriptor address and start TX DMA * * @param hw Peripheral I2S hardware instance address. - * @param val value to set clkm div num + * @param link_addr DMA descriptor link address. */ -static inline void i2s_ll_set_clkm_div_num(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_tx_start_link(i2s_dev_t *hw, uint32_t link_addr) { - hw->clkm_conf.clkm_div_num = val; + i2s_ll_set_out_link_addr(hw, link_addr); + i2s_ll_start_out_link(hw); } /** - * @brief Set I2S clkm div b + * @brief Configure RX DMA descriptor address and start TX DMA * * @param hw Peripheral I2S hardware instance address. - * @param val value to set clkm div b + * @param link_addr DMA descriptor link address. */ -static inline void i2s_ll_set_clkm_div_b(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_rx_start_link(i2s_dev_t *hw, uint32_t link_addr) { - hw->clkm_conf.clkm_div_b = val; + hw->in_link.addr = link_addr; + hw->in_link.start = 1; } /** - * @brief Set I2S clkm div a + * @brief Stop TX module * * @param hw Peripheral I2S hardware instance address. - * @param val value to set clkm div a */ -static inline void i2s_ll_set_clkm_div_a(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_tx_stop(i2s_dev_t *hw) { - hw->clkm_conf.clkm_div_a = val; + hw->conf.tx_start = 0; } /** - * @brief Set I2S tx bck div num + * @brief Stop RX module * * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx bck div num */ -static inline void i2s_ll_set_tx_bck_div_num(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_rx_stop(i2s_dev_t *hw) { - hw->sample_rate_conf.tx_bck_div_num = val; + hw->conf.rx_start = 0; } /** - * @brief Set I2S rx bck div num + * @brief Stop out link * * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx bck div num */ -static inline void i2s_ll_set_rx_bck_div_num(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_tx_stop_link(i2s_dev_t *hw) { - hw->sample_rate_conf.rx_bck_div_num = val; + hw->out_link.stop = 1; } /** - * @brief Set I2S clk sel + * @brief Stop in link * * @param hw Peripheral I2S hardware instance address. - * @param val value to set clk sel */ -static inline void i2s_ll_set_clk_sel(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_rx_stop_link(i2s_dev_t *hw) { - hw->clkm_conf.clk_sel = (val == 1) ? 1 : 2; + hw->in_link.stop = 1; } /** - * @brief Set I2S tx bits mod + * @brief Get I2S out eof descriptor address * * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx bits mod + * @param eof_addr Pointer to accept out eof des address */ -static inline void i2s_ll_set_tx_bits_mod(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_tx_get_eof_des_addr(i2s_dev_t *hw, uint32_t *eof_addr) { - hw->sample_rate_conf.tx_bits_mod = val; + *eof_addr = hw->out_eof_des_addr; } /** - * @brief Set I2S rx bits mod + * @brief Get I2S in eof descriptor address * * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx bits mod + * @param eof_addr Pointer to accept in eof des address */ -static inline void i2s_ll_set_rx_bits_mod(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_rx_get_eof_des_addr(i2s_dev_t *hw, uint32_t *eof_addr) { - hw->sample_rate_conf.rx_bits_mod = val; + *eof_addr = hw->in_eof_des_addr; } /** - * @brief Set I2S dscr en + * @brief Configure the received length to trigger in_suc_eof interrupt * * @param hw Peripheral I2S hardware instance address. - * @param val value to set dscr en + * @param eof_num the byte length to trigger in_suc_eof interrupt */ -static inline void i2s_ll_set_dscr_en(i2s_dev_t *hw, bool val) +static inline void i2s_ll_rx_set_eof_num(i2s_dev_t *hw, uint32_t eof_num) { - hw->fifo_conf.dscr_en = val; + hw->rx_eof_num = eof_num; } /** - * @brief Set I2S lcd en + * @brief Congfigure 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 val value to set lcd en + * @param chan_bit The chan bit width + * @param data_bit The audio data bit width */ -static inline void i2s_ll_set_lcd_en(i2s_dev_t *hw, bool val) +static inline void i2s_ll_tx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_bit, int data_bit) { - hw->conf2.lcd_en = val; + hw->fifo_conf.tx_fifo_mod = (chan_bit <= I2S_BITS_PER_SAMPLE_16BIT ? 0 : 2); + hw->sample_rate_conf.tx_bits_mod = data_bit; } /** - * @brief Set I2S camera en + * @brief Congfigure 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 val value to set camera en + * @param chan_bit The chan bit width + * @param data_bit The audio data bit width */ -static inline void i2s_ll_set_camera_en(i2s_dev_t *hw, bool val) +static inline void i2s_ll_rx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_bit, int data_bit) { - hw->conf2.camera_en = val; + hw->fifo_conf.rx_fifo_mod = (chan_bit <= I2S_BITS_PER_SAMPLE_16BIT ? 0 : 2); + hw->sample_rate_conf.rx_bits_mod = data_bit; } /** - * @brief Set I2S tx fifo mod force en + * @brief Enable I2S DMA * * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx fifo mod force en + * @param ena Set true to enable DMA */ -static inline void i2s_ll_set_tx_fifo_mod_force_en(i2s_dev_t *hw, bool val) +static inline void i2s_ll_enable_dma(i2s_dev_t *hw, bool ena) { - hw->fifo_conf.tx_fifo_mod_force_en = val; -} - -/** - * @brief Set I2S rx fifo mod force en - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx fifo mod force en - */ -static inline void i2s_ll_set_rx_fifo_mod_force_en(i2s_dev_t *hw, bool val) -{ - hw->fifo_conf.rx_fifo_mod_force_en = val; -} - -/** - * @brief Set I2S tx right first - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx right first - */ -static inline void i2s_ll_set_tx_right_first(i2s_dev_t *hw, uint32_t val) -{ - hw->conf.tx_right_first = val; -} - -/** - * @brief Set I2S rx right first - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx right first - */ -static inline void i2s_ll_set_rx_right_first(i2s_dev_t *hw, uint32_t val) -{ - hw->conf.rx_right_first = val; -} - -/** - * @brief Set I2S tx slave mod - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx slave mod - */ -static inline void i2s_ll_set_tx_slave_mod(i2s_dev_t *hw, uint32_t val) -{ - hw->conf.tx_slave_mod = val; -} - -/** - * @brief Set I2S rx slave mod - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx slave mod - */ -static inline void i2s_ll_set_rx_slave_mod(i2s_dev_t *hw, uint32_t val) -{ - hw->conf.rx_slave_mod = val; -} - -/** - * @brief Get I2S tx msb right - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get tx msb right - */ -static inline void i2s_ll_get_tx_msb_right(i2s_dev_t *hw, uint32_t *val) -{ - *val = hw->conf.tx_msb_right; -} - -/** - * @brief Get I2S rx msb right - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get rx msb right - */ -static inline void i2s_ll_get_rx_msb_right(i2s_dev_t *hw, uint32_t *val) -{ - *val = hw->conf.rx_msb_right; -} - -/** - * @brief Set I2S tx msb right - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx msb right - */ -static inline void i2s_ll_set_tx_msb_right(i2s_dev_t *hw, uint32_t val) -{ - hw->conf.tx_msb_right = val; -} - -/** - * @brief Set I2S rx msb right - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx msb right - */ -static inline void i2s_ll_set_rx_msb_right(i2s_dev_t *hw, uint32_t val) -{ - hw->conf.rx_msb_right = val; -} - -/** - * @brief Set I2S tx mono - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx mono - */ -static inline void i2s_ll_set_tx_mono(i2s_dev_t *hw, uint32_t val) -{ - hw->conf.tx_mono = val; -} - -/** - * @brief Set I2S rx mono - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx mono - */ -static inline void i2s_ll_set_rx_mono(i2s_dev_t *hw, uint32_t val) -{ - hw->conf.rx_mono = val; -} - -/** - * @brief Set I2S sig loopback - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set sig loopback - */ -static inline void i2s_ll_set_sig_loopback(i2s_dev_t *hw, uint32_t val) -{ - hw->conf.sig_loopback = val; + hw->fifo_conf.dscr_en = ena; } /** @@ -677,7 +633,7 @@ static inline void i2s_ll_set_sig_loopback(i2s_dev_t *hw, uint32_t val) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_set_tx_format_philip(i2s_dev_t *hw) +static inline void i2s_ll_tx_set_format_philip(i2s_dev_t *hw) { hw->conf.tx_short_sync = 0; hw->conf.tx_msb_shift = 1; @@ -688,7 +644,7 @@ static inline void i2s_ll_set_tx_format_philip(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_set_rx_format_philip(i2s_dev_t *hw) +static inline void i2s_ll_rx_set_format_philip(i2s_dev_t *hw) { hw->conf.rx_short_sync = 0; hw->conf.rx_msb_shift = 1; @@ -699,7 +655,7 @@ static inline void i2s_ll_set_rx_format_philip(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_set_tx_format_msb_align(i2s_dev_t *hw) +static inline void i2s_ll_tx_set_format_msb_align(i2s_dev_t *hw) { hw->conf.tx_short_sync = 0; hw->conf.tx_msb_shift = 0; @@ -710,7 +666,7 @@ static inline void i2s_ll_set_tx_format_msb_align(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_set_rx_format_msb_align(i2s_dev_t *hw) +static inline void i2s_ll_rx_set_format_msb_align(i2s_dev_t *hw) { hw->conf.rx_short_sync = 0; hw->conf.rx_msb_shift = 0; @@ -721,7 +677,7 @@ static inline void i2s_ll_set_rx_format_msb_align(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_set_tx_pcm_short(i2s_dev_t *hw) +static inline void i2s_ll_tx_set_pcm_short(i2s_dev_t *hw) { hw->conf.tx_short_sync = 1; hw->conf.tx_msb_shift = 0; @@ -732,7 +688,7 @@ static inline void i2s_ll_set_tx_pcm_short(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_set_rx_pcm_short(i2s_dev_t *hw) +static inline void i2s_ll_rx_set_pcm_short(i2s_dev_t *hw) { hw->conf.rx_short_sync = 1; hw->conf.rx_msb_shift = 0; @@ -743,7 +699,7 @@ static inline void i2s_ll_set_rx_pcm_short(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_set_tx_pcm_long(i2s_dev_t *hw) +static inline void i2s_ll_tx_set_pcm_long(i2s_dev_t *hw) { hw->conf.tx_short_sync = 0; hw->conf.tx_msb_shift = 0; @@ -754,12 +710,161 @@ static inline void i2s_ll_set_tx_pcm_long(i2s_dev_t *hw) * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_set_rx_pcm_long(i2s_dev_t *hw) +static inline void i2s_ll_rx_set_pcm_long(i2s_dev_t *hw) { hw->conf.rx_short_sync = 0; hw->conf.rx_msb_shift = 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->conf.tx_short_sync = width == 1 ? 1 : 0; +} + +/** + * @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->conf.rx_short_sync = width == 1 ? 1 : 0; +} + +/** + * @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->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->conf.rx_msb_shift = msb_shift_enable; +} + +/** + * @brief Set I2S tx chan mode + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx chan mode + */ +static inline void i2s_ll_tx_set_chan_mod(i2s_dev_t *hw, uint32_t val) +{ + hw->conf_chan.tx_chan_mod = val; +} + +/** + * @brief Set I2S tx bits mod + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx bits mod + */ +static inline void i2s_ll_tx_set_bits_mod(i2s_dev_t *hw, uint32_t val) +{ + hw->sample_rate_conf.tx_bits_mod = val; +} + +/** + * @brief Set I2S tx dma equal + * + * @param hw Peripheral I2S hardware instance address. + * @param val value to set tx dma equal + */ +static inline void i2s_ll_tx_enable_dma_equal(i2s_dev_t *hw, bool en) +{ + hw->conf.tx_dma_equal = en; +} + +/** + * @brief Enable TX mono mode + * + * @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) +{ + int data_bit = hw->sample_rate_conf.tx_bits_mod; + hw->fifo_conf.tx_fifo_mod = data_bit <= I2S_BITS_PER_SAMPLE_16BIT ? mono_ena : 2 + mono_ena; + hw->conf.tx_dma_equal = mono_ena; + hw->conf_chan.tx_chan_mod = 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) +{ + int data_bit = hw->sample_rate_conf.rx_bits_mod; + hw->fifo_conf.rx_fifo_mod = data_bit <= I2S_BITS_PER_SAMPLE_16BIT ? mono_ena : 2 + mono_ena; + hw->conf.rx_dma_equal = mono_ena; + hw->conf_chan.rx_chan_mod = mono_ena; +} + +/** + * @brief Enable I2S loopback mode + * + * @param hw Peripheral I2S hardware instance address. + * @param loopback_en 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 loopback_en) +{ + hw->conf.sig_loopback = loopback_en; +} + +/** + * @brief Enable I2S LCD mode + * + * @param hw Peripheral I2S hardware instance address. + * @param enable Set true to enable LCD mode. + */ +static inline void i2s_ll_enable_lcd(i2s_dev_t *hw, bool enable) +{ + hw->conf2.lcd_en = enable; +} + +/** + * @brief Set whether to continue I2S signal on bus when TX FIFO is empty + * + * @param hw Peripheral I2S hardware instance address. + * @param en whether to stop when tx fifo is empty + */ +static inline void i2s_ll_tx_stop_on_fifo_empty(i2s_dev_t *hw, bool en) +{ + hw->conf1.tx_stop_en = en; +} + +/** + * @brief Set whether to bypass the internal PCM module + * + * @param hw Peripheral I2S hardware instance address. + * @param bypass whether to bypass the PCM module + */ +static inline void i2s_ll_tx_bypass_pcm(i2s_dev_t *hw, bool bypass) +{ + hw->conf1.tx_pcm_bypass = bypass; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32s2/include/hal/ledc_ll.h b/components/hal/esp32s2/include/hal/ledc_ll.h index 19d61f127f..677a2e36d3 100644 --- a/components/hal/esp32s2/include/hal/ledc_ll.h +++ b/components/hal/esp32s2/include/hal/ledc_ll.h @@ -19,6 +19,7 @@ #include "hal/ledc_types.h" #include "soc/ledc_periph.h" +#include "soc/ledc_struct.h" #ifdef __cplusplus extern "C" { diff --git a/components/hal/esp32s2/include/hal/memprot_ll.h b/components/hal/esp32s2/include/hal/memprot_ll.h index eeaa73dcc8..fa77e2f3ab 100644 --- a/components/hal/esp32s2/include/hal/memprot_ll.h +++ b/components/hal/esp32s2/include/hal/memprot_ll.h @@ -14,7 +14,9 @@ #pragma once -#include "hal/assert.h" +#include +#include "soc/memprot_defs.h" +#include "hal/memprot_types.h" #ifdef __cplusplus extern "C" { @@ -25,23 +27,18 @@ extern "C" { * === IRAM0 common * ======================================================================================== */ -//IRAM0 interrupt status bitmasks -#define IRAM0_INTR_ST_OP_TYPE_BIT BIT(1) //instruction: 0, data: 1 -#define IRAM0_INTR_ST_OP_RW_BIT BIT(0) //read: 0, write: 1 -#define CONF_REG_ADDRESS_SHIFT 2 - -static inline void esp_memprot_iram0_clear_intr(void) +static inline void memprot_ll_iram0_clear_intr(void) { DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_CLR); DPORT_CLEAR_PERI_REG_MASK(DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_CLR); } -static inline uint32_t esp_memprot_iram0_get_intr_source_num(void) +static inline uint32_t memprot_ll_iram0_get_intr_source_num(void) { return ETS_PMS_PRO_IRAM0_ILG_INTR_SOURCE; } -static inline void esp_memprot_iram0_intr_ena(bool enable) +static inline void memprot_ll_iram0_intr_ena(bool enable) { if (enable) { DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_EN); @@ -50,55 +47,55 @@ static inline void esp_memprot_iram0_intr_ena(bool enable) } } -static inline uint32_t esp_memprot_iram0_get_conf_reg(void) +static inline uint32_t memprot_ll_iram0_get_conf_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_IRAM0_4_REG); } -static inline uint32_t esp_memprot_iram0_get_fault_reg(void) +static inline uint32_t memprot_ll_iram0_get_fault_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_IRAM0_5_REG); } -static inline void esp_memprot_iram0_get_fault_op_type(uint32_t *op_type, uint32_t *op_subtype) +static inline void memprot_ll_iram0_get_fault_op_type(uint32_t *op_type, uint32_t *op_subtype) { - uint32_t status_bits = esp_memprot_iram0_get_fault_reg(); + uint32_t status_bits = memprot_ll_iram0_get_fault_reg(); *op_type = (uint32_t)status_bits & IRAM0_INTR_ST_OP_RW_BIT; *op_subtype = (uint32_t)status_bits & IRAM0_INTR_ST_OP_TYPE_BIT; } -static inline bool esp_memprot_iram0_is_assoc_intr(void) +static inline bool memprot_ll_iram0_is_assoc_intr(void) { return DPORT_GET_PERI_REG_MASK(DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_INTR) > 0; } -static inline uint32_t esp_memprot_iram0_get_intr_ena_bit(void) +static inline uint32_t memprot_ll_iram0_get_intr_ena_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_EN); } -static inline uint32_t esp_memprot_iram0_get_intr_on_bit(void) +static inline uint32_t memprot_ll_iram0_get_intr_on_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_INTR); } -static inline uint32_t esp_memprot_iram0_get_intr_clr_bit(void) +static inline uint32_t memprot_ll_iram0_get_intr_clr_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_CLR); } //resets automatically on CPU restart -static inline void esp_memprot_iram0_set_lock(void) +static inline void memprot_ll_iram0_set_lock(void) { DPORT_WRITE_PERI_REG( DPORT_PMS_PRO_IRAM0_0_REG, DPORT_PMS_PRO_IRAM0_LOCK); } -static inline uint32_t esp_memprot_iram0_get_lock_reg(void) +static inline uint32_t memprot_ll_iram0_get_lock_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_IRAM0_0_REG); } -static inline uint32_t esp_memprot_iram0_get_lock_bit(void) +static inline uint32_t memprot_ll_iram0_get_lock_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_0_REG, DPORT_PMS_PRO_IRAM0_LOCK); } @@ -108,52 +105,26 @@ static inline uint32_t esp_memprot_iram0_get_lock_bit(void) * === IRAM0 SRAM * ======================================================================================== */ -#define IRAM0_SRAM_BASE_ADDRESS 0x40000000 -#define IRAM0_SRAM_ADDRESS_LOW 0x40020000 -#define IRAM0_SRAM_ADDRESS_HIGH 0x4006FFFF - -#define IRAM0_SRAM_TOTAL_UNI_BLOCKS 4 -#define IRAM0_SRAM_UNI_BLOCK_0 0 -#define IRAM0_SRAM_UNI_BLOCK_1 1 -#define IRAM0_SRAM_UNI_BLOCK_2 2 -#define IRAM0_SRAM_UNI_BLOCK_3 3 - -//unified management (SRAM blocks 0-3) -#define IRAM0_SRAM_UNI_BLOCK_0_LOW 0x40020000 -#define IRAM0_SRAM_UNI_BLOCK_1_LOW 0x40022000 -#define IRAM0_SRAM_UNI_BLOCK_2_LOW 0x40024000 -#define IRAM0_SRAM_UNI_BLOCK_3_LOW 0x40026000 - -//split management (SRAM blocks 4-21) -#define IRAM0_SRAM_SPL_BLOCK_LOW 0x40028000 //block 4 low -#define IRAM0_SRAM_SPL_BLOCK_HIGH 0x4006FFFF //block 21 high - -#define IRAM0_INTR_ST_FAULTADDR_M 0x003FFFFC //bits 21:6 in the reg, as well as in real address -#define IRAM0_SRAM_INTR_ST_FAULTADDR_HI 0x40000000 //high nonsignificant bits 31:22 of the faulting address - constant - -#define IRAM0_SRAM_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_IRAM0_SRAM_4_SPLTADDR) << DPORT_PMS_PRO_IRAM0_SRAM_4_SPLTADDR_S) - -static inline uint32_t *esp_memprot_iram0_sram_get_fault_address(void) +static inline intptr_t memprot_ll_iram0_sram_get_fault_address(void) { - uint32_t status_bits = esp_memprot_iram0_get_fault_reg(); - return (uint32_t *)((status_bits & IRAM0_INTR_ST_FAULTADDR_M) | IRAM0_SRAM_INTR_ST_FAULTADDR_HI); + uint32_t status_bits = memprot_ll_iram0_get_fault_reg(); + return (intptr_t)((status_bits & IRAM0_INTR_ST_FAULTADDR_M) | IRAM0_SRAM_INTR_ST_FAULTADDR_HI); } -static inline bool esp_memprot_iram0_sram_is_intr_mine(void) +static inline bool memprot_ll_iram0_sram_is_intr_mine(void) { - if (esp_memprot_iram0_is_assoc_intr()) { - uint32_t *faulting_address = esp_memprot_iram0_sram_get_fault_address(); - return (uint32_t)faulting_address >= IRAM0_SRAM_ADDRESS_LOW && (uint32_t)faulting_address <= IRAM0_SRAM_ADDRESS_HIGH; + if (memprot_ll_iram0_is_assoc_intr()) { + uint32_t faulting_address = (uint32_t)memprot_ll_iram0_sram_get_fault_address(); + return faulting_address >= IRAM0_SRAM_ADDRESS_LOW && faulting_address <= IRAM0_SRAM_ADDRESS_HIGH; } return false; } //block 0-3 -static inline void esp_memprot_iram0_sram_set_uni_block_perm(uint32_t block, bool write_perm, bool read_perm, bool exec_perm) +static inline bool memprot_ll_iram0_sram_set_uni_block_perm(uint32_t block, bool write_perm, bool read_perm, bool exec_perm) { - HAL_ASSERT(block < IRAM0_SRAM_TOTAL_UNI_BLOCKS); - uint32_t write_bit, read_bit, exec_bit; + switch (block) { case IRAM0_SRAM_UNI_BLOCK_0: write_bit = DPORT_PMS_PRO_IRAM0_SRAM_0_W; @@ -176,7 +147,7 @@ static inline void esp_memprot_iram0_sram_set_uni_block_perm(uint32_t block, boo exec_bit = DPORT_PMS_PRO_IRAM0_SRAM_3_F; break; default: - abort(); + return false; } if (write_perm) { @@ -196,66 +167,78 @@ static inline void esp_memprot_iram0_sram_set_uni_block_perm(uint32_t block, boo } else { DPORT_CLEAR_PERI_REG_MASK(DPORT_PMS_PRO_IRAM0_1_REG, exec_bit); } + + return true; } -static inline uint32_t esp_memprot_iram0_sram_get_uni_block_read_bit(uint32_t block) +static inline bool memprot_ll_iram0_sram_get_uni_block_read_bit(uint32_t block, uint32_t *read_bit) { - HAL_ASSERT(block < IRAM0_SRAM_TOTAL_UNI_BLOCKS); - switch (block) { case IRAM0_SRAM_UNI_BLOCK_0: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_0_R); + *read_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_0_R); + break; case IRAM0_SRAM_UNI_BLOCK_1: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_1_R); + *read_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_1_R); + break; case IRAM0_SRAM_UNI_BLOCK_2: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_2_R); + *read_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_2_R); + break; case IRAM0_SRAM_UNI_BLOCK_3: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_3_R); + *read_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_3_R); + break; default: - abort(); + return false; } + + return true; } -static inline uint32_t esp_memprot_iram0_sram_get_uni_block_write_bit(uint32_t block) +static inline bool memprot_ll_iram0_sram_get_uni_block_write_bit(uint32_t block, uint32_t *write_bit) { - HAL_ASSERT(block < IRAM0_SRAM_TOTAL_UNI_BLOCKS); - switch (block) { case IRAM0_SRAM_UNI_BLOCK_0: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_0_W); + *write_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_0_W); + break; case IRAM0_SRAM_UNI_BLOCK_1: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_1_W); + *write_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_1_W); + break; case IRAM0_SRAM_UNI_BLOCK_2: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_2_W); + *write_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_2_W); + break; case IRAM0_SRAM_UNI_BLOCK_3: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_3_W); + *write_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_3_W); + break; default: - abort(); + return false; } + + return true; } -static inline uint32_t esp_memprot_iram0_sram_get_uni_block_exec_bit(uint32_t block) +static inline bool memprot_ll_iram0_sram_get_uni_block_exec_bit(uint32_t block, uint32_t *exec_bit) { - HAL_ASSERT(block < IRAM0_SRAM_TOTAL_UNI_BLOCKS); - switch (block) { case IRAM0_SRAM_UNI_BLOCK_0: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_0_F); + *exec_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_0_F); + break; case IRAM0_SRAM_UNI_BLOCK_1: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_1_F); + *exec_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_1_F); + break; case IRAM0_SRAM_UNI_BLOCK_2: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_2_F); + *exec_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_2_F); + break; case IRAM0_SRAM_UNI_BLOCK_3: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_3_F); + *exec_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_3_F); + break; default: - abort(); + return false; } + + return true; } -static inline void esp_memprot_iram0_sram_get_uni_block_sgnf_bits(uint32_t block, uint32_t *write_bit, uint32_t *read_bit, uint32_t *exec_bit) +static inline bool memprot_ll_iram0_sram_get_uni_block_sgnf_bits(uint32_t block, uint32_t *write_bit, uint32_t *read_bit, uint32_t *exec_bit) { - HAL_ASSERT(block < IRAM0_SRAM_TOTAL_UNI_BLOCKS); - switch (block) { case IRAM0_SRAM_UNI_BLOCK_0: *write_bit = DPORT_PMS_PRO_IRAM0_SRAM_0_W; @@ -278,25 +261,33 @@ static inline void esp_memprot_iram0_sram_get_uni_block_sgnf_bits(uint32_t block *exec_bit = DPORT_PMS_PRO_IRAM0_SRAM_3_F; break; default: - abort(); + return false; } + + return true; } -static inline uint32_t esp_memprot_iram0_sram_get_perm_uni_reg(void) +static inline uint32_t memprot_ll_iram0_sram_get_perm_uni_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_IRAM0_1_REG); } -static inline uint32_t esp_memprot_iram0_sram_get_perm_split_reg(void) +static inline uint32_t memprot_ll_iram0_sram_get_perm_split_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_IRAM0_2_REG); } -static inline void esp_memprot_iram0_sram_set_prot(uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx) +static inline memprot_ll_err_t memprot_ll_iram0_sram_set_prot(uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx) { uint32_t addr = (uint32_t)split_addr; - HAL_ASSERT(addr <= IRAM0_SRAM_SPL_BLOCK_HIGH); - HAL_ASSERT(addr % 0x4 == 0); + + //sanity check: split address required above unified mgmt region & 32bit aligned + if (addr > IRAM0_SRAM_SPL_BLOCK_HIGH) { + return MEMP_LL_ERR_SPLIT_ADDR_INVALID; + } + if (addr % 0x4 != 0) { + return MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED; + } //find possible split.address in low region blocks int uni_blocks_low = -1; @@ -318,7 +309,9 @@ static inline void esp_memprot_iram0_sram_set_prot(uint32_t *split_addr, bool lw uint32_t uni_block_perm = 0; for (int x = 0; x < IRAM0_SRAM_TOTAL_UNI_BLOCKS; x++) { - esp_memprot_iram0_sram_get_uni_block_sgnf_bits(x, &write_bit, &read_bit, &exec_bit); + if (!memprot_ll_iram0_sram_get_uni_block_sgnf_bits(x, &write_bit, &read_bit, &exec_bit)) { + return MEMP_LL_ERR_UNI_BLOCK_INVALID; + } if (x <= uni_blocks_low) { if (lw) { uni_block_perm |= write_bit; @@ -346,7 +339,7 @@ static inline void esp_memprot_iram0_sram_set_prot(uint32_t *split_addr, bool lw uint32_t reg_split_addr = 0; if (addr >= IRAM0_SRAM_SPL_BLOCK_LOW) { - reg_split_addr = IRAM0_SRAM_ADDR_TO_CONF_REG( addr ); //cfg reg - [16:0] + reg_split_addr = IRAM0_SRAM_ADDR_TO_CONF_REG(addr); //cfg reg - [16:0] } //prepare high & low permission mask (bits: [22:20] high range, [19:17] low range) @@ -373,9 +366,11 @@ static inline void esp_memprot_iram0_sram_set_prot(uint32_t *split_addr, bool lw //write IRAM SRAM uni & splt cfg. registers DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_IRAM0_1_REG, uni_block_perm); DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_IRAM0_2_REG, (uint32_t)(reg_split_addr | permission_mask)); + + return MEMP_LL_OK; } -static inline void esp_memprot_iram0_sram_get_split_sgnf_bits(bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) +static inline void memprot_ll_iram0_sram_get_split_sgnf_bits(bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) { *lw = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_L_W); *lr = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_L_R); @@ -385,19 +380,19 @@ static inline void esp_memprot_iram0_sram_get_split_sgnf_bits(bool *lw, bool *lr *hx = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_H_F); } -static inline void esp_memprot_iram0_sram_set_read_perm(bool lr, bool hr) +static inline void memprot_ll_iram0_sram_set_read_perm(bool lr, bool hr) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_L_R, lr ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_H_R, hr ? 1 : 0); } -static inline void esp_memprot_iram0_sram_set_write_perm(bool lw, bool hw) +static inline void memprot_ll_iram0_sram_set_write_perm(bool lw, bool hw) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_L_W, lw ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_H_W, hw ? 1 : 0); } -static inline void esp_memprot_iram0_sram_set_exec_perm(bool lx, bool hx) +static inline void memprot_ll_iram0_sram_set_exec_perm(bool lx, bool hx) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_L_F, lx ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_H_F, hx ? 1 : 0); @@ -409,37 +404,37 @@ static inline void esp_memprot_iram0_sram_set_exec_perm(bool lx, bool hx) * === IRAM0 RTC FAST * ======================================================================================== */ -#define IRAM0_RTCFAST_ADDRESS_LOW 0x40070000 -#define IRAM0_RTCFAST_ADDRESS_HIGH 0x40071FFF -#define IRAM0_RTCFAST_INTR_ST_FAULTADDR_HI 0x40070000 //RTCFAST faulting address high bits (31:22, constant) - -#define IRAM0_RTCFAST_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_IRAM0_RTCFAST_SPLTADDR) << DPORT_PMS_PRO_IRAM0_RTCFAST_SPLTADDR_S) - - -static inline uint32_t *esp_memprot_iram0_rtcfast_get_fault_address(void) +static inline intptr_t memprot_ll_iram0_rtcfast_get_fault_address(void) { - uint32_t status_bits = esp_memprot_iram0_get_fault_reg(); - return (uint32_t *)((status_bits & IRAM0_INTR_ST_FAULTADDR_M) | IRAM0_RTCFAST_INTR_ST_FAULTADDR_HI); + uint32_t status_bits = memprot_ll_iram0_get_fault_reg(); + return (intptr_t)((status_bits & IRAM0_INTR_ST_FAULTADDR_M) | IRAM0_RTCFAST_INTR_ST_FAULTADDR_HI); } -static inline bool esp_memprot_iram0_rtcfast_is_intr_mine(void) +static inline bool memprot_ll_iram0_rtcfast_is_intr_mine(void) { - if (esp_memprot_iram0_is_assoc_intr()) { - uint32_t *faulting_address = esp_memprot_iram0_rtcfast_get_fault_address(); - return (uint32_t)faulting_address >= IRAM0_RTCFAST_ADDRESS_LOW && (uint32_t)faulting_address <= IRAM0_RTCFAST_ADDRESS_HIGH; + if (memprot_ll_iram0_is_assoc_intr()) { + uint32_t faulting_address = (uint32_t)memprot_ll_iram0_rtcfast_get_fault_address(); + return faulting_address >= IRAM0_RTCFAST_ADDRESS_LOW && faulting_address <= IRAM0_RTCFAST_ADDRESS_HIGH; } return false; } -static inline uint32_t esp_memprot_iram0_rtcfast_get_perm_split_reg(void) +static inline uint32_t memprot_ll_iram0_rtcfast_get_perm_split_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_IRAM0_3_REG); } -static inline void esp_memprot_iram0_rtcfast_set_prot(uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx) +static inline memprot_ll_err_t memprot_ll_iram0_rtcfast_set_prot(uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx) { uint32_t addr = (uint32_t)split_addr; - HAL_ASSERT(addr % 0x4 == 0); + + //32bit aligned + if (addr < IRAM0_RTCFAST_ADDRESS_LOW || addr > IRAM0_RTCFAST_ADDRESS_HIGH) { + return MEMP_LL_ERR_SPLIT_ADDR_INVALID; + } + if (addr % 0x4 != 0) { + return MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED; + } //conf reg [10:0] uint32_t reg_split_addr = IRAM0_RTCFAST_ADDR_TO_CONF_REG(addr); @@ -467,9 +462,11 @@ static inline void esp_memprot_iram0_rtcfast_set_prot(uint32_t *split_addr, bool //write IRAM0 RTCFAST cfg register DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_IRAM0_3_REG, reg_split_addr | permission_mask); + + return MEMP_LL_OK; } -static inline void esp_memprot_iram0_rtcfast_get_split_sgnf_bits(bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) +static inline void memprot_ll_iram0_rtcfast_get_split_sgnf_bits(bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) { *lw = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_3_REG, DPORT_PMS_PRO_IRAM0_RTCFAST_L_W); *lr = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_3_REG, DPORT_PMS_PRO_IRAM0_RTCFAST_L_R); @@ -479,19 +476,19 @@ static inline void esp_memprot_iram0_rtcfast_get_split_sgnf_bits(bool *lw, bool *hx = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_3_REG, DPORT_PMS_PRO_IRAM0_RTCFAST_H_F); } -static inline void esp_memprot_iram0_rtcfast_set_read_perm(bool lr, bool hr) +static inline void memprot_ll_iram0_rtcfast_set_read_perm(bool lr, bool hr) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_3_REG, DPORT_PMS_PRO_IRAM0_RTCFAST_L_R, lr ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_3_REG, DPORT_PMS_PRO_IRAM0_RTCFAST_H_R, hr ? 1 : 0); } -static inline void esp_memprot_iram0_rtcfast_set_write_perm(bool lw, bool hw) +static inline void memprot_ll_iram0_rtcfast_set_write_perm(bool lw, bool hw) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_3_REG, DPORT_PMS_PRO_IRAM0_RTCFAST_L_W, lw ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_3_REG, DPORT_PMS_PRO_IRAM0_RTCFAST_H_W, hw ? 1 : 0); } -static inline void esp_memprot_iram0_rtcfast_set_exec_perm(bool lx, bool hx) +static inline void memprot_ll_iram0_rtcfast_set_exec_perm(bool lx, bool hx) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_3_REG, DPORT_PMS_PRO_IRAM0_RTCFAST_L_F, lx ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_3_REG, DPORT_PMS_PRO_IRAM0_RTCFAST_H_F, hx ? 1 : 0); @@ -503,19 +500,12 @@ static inline void esp_memprot_iram0_rtcfast_set_exec_perm(bool lx, bool hx) * === DRAM0 common * ======================================================================================== */ -//DRAM0 interrupt status bitmasks -#define DRAM0_INTR_ST_FAULTADDR_M 0x03FFFFC0 //(bits 25:6 in the reg) -#define DRAM0_INTR_ST_FAULTADDR_S 0x4 //(bits 21:2 of real address) -#define DRAM0_INTR_ST_OP_RW_BIT BIT(4) //read: 0, write: 1 -#define DRAM0_INTR_ST_OP_ATOMIC_BIT BIT(5) //non-atomic: 0, atomic: 1 - - -static inline uint32_t esp_memprot_dram0_get_intr_source_num(void) +static inline uint32_t memprot_ll_dram0_get_intr_source_num(void) { return ETS_PMS_PRO_DRAM0_ILG_INTR_SOURCE; } -static inline void esp_memprot_dram0_intr_ena(bool enable) +static inline void memprot_ll_dram0_intr_ena(bool enable) { if (enable) { DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_EN); @@ -524,112 +514,87 @@ static inline void esp_memprot_dram0_intr_ena(bool enable) } } -static inline bool esp_memprot_dram0_is_assoc_intr(void) +static inline bool memprot_ll_dram0_is_assoc_intr(void) { return DPORT_GET_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_INTR) > 0; } -static inline void esp_memprot_dram0_clear_intr(void) +static inline void memprot_ll_dram0_clear_intr(void) { DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_CLR); DPORT_CLEAR_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_CLR); } -static inline uint32_t esp_memprot_dram0_get_intr_ena_bit(void) +static inline uint32_t memprot_ll_dram0_get_intr_ena_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_EN); } -static inline uint32_t esp_memprot_dram0_get_intr_on_bit(void) +static inline uint32_t memprot_ll_dram0_get_intr_on_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_INTR); } -static inline uint32_t esp_memprot_dram0_get_intr_clr_bit(void) +static inline uint32_t memprot_ll_dram0_get_intr_clr_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_CLR); } //lock resets automatically on CPU restart -static inline void esp_memprot_dram0_set_lock(void) +static inline void memprot_ll_dram0_set_lock(void) { DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_DRAM0_0_REG, DPORT_PMS_PRO_DRAM0_LOCK); } -static inline uint32_t esp_memprot_dram0_get_lock_reg(void) +static inline uint32_t memprot_ll_dram0_get_lock_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DRAM0_0_REG); } -static inline uint32_t esp_memprot_dram0_get_lock_bit(void) +static inline uint32_t memprot_ll_dram0_get_lock_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_0_REG, DPORT_PMS_PRO_DRAM0_LOCK); } -static inline uint32_t esp_memprot_dram0_get_conf_reg(void) +static inline uint32_t memprot_ll_dram0_get_conf_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DRAM0_3_REG); } -static inline uint32_t esp_memprot_dram0_get_fault_reg(void) +static inline uint32_t memprot_ll_dram0_get_fault_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DRAM0_4_REG); } -static inline void esp_memprot_dram0_get_fault_op_type(uint32_t *op_type, uint32_t *op_subtype) +static inline void memprot_ll_dram0_get_fault_op_type(uint32_t *op_type, uint32_t *op_subtype) { - uint32_t status_bits = esp_memprot_dram0_get_fault_reg(); + uint32_t status_bits = memprot_ll_dram0_get_fault_reg(); *op_type = status_bits & DRAM0_INTR_ST_OP_RW_BIT; *op_subtype = status_bits & DRAM0_INTR_ST_OP_ATOMIC_BIT; } - /** * ======================================================================================== * === DRAM0 SRAM * ======================================================================================== */ -#define DRAM0_SRAM_ADDRESS_LOW 0x3FFB0000 -#define DRAM0_SRAM_ADDRESS_HIGH 0x3FFFFFFF - -#define DRAM0_SRAM_TOTAL_UNI_BLOCKS 4 -#define DRAM0_SRAM_UNI_BLOCK_0 0 -#define DRAM0_SRAM_UNI_BLOCK_1 1 -#define DRAM0_SRAM_UNI_BLOCK_2 2 -#define DRAM0_SRAM_UNI_BLOCK_3 3 - -//unified management (SRAM blocks 0-3) -#define DRAM0_SRAM_UNI_BLOCK_0_LOW 0x3FFB0000 -#define DRAM0_SRAM_UNI_BLOCK_1_LOW 0x3FFB2000 -#define DRAM0_SRAM_UNI_BLOCK_2_LOW 0x3FFB4000 -#define DRAM0_SRAM_UNI_BLOCK_3_LOW 0x3FFB6000 - -//split management (SRAM blocks 4-21) -#define DRAM0_SRAM_SPL_BLOCK_HIGH 0x3FFFFFFF //block 21 high -#define DRAM0_SRAM_INTR_ST_FAULTADDR_HI 0x3FF00000 //SRAM high bits 31:22 of the faulting address - constant - -#define DRAM0_SRAM_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_DRAM0_SRAM_4_SPLTADDR) << DPORT_PMS_PRO_DRAM0_SRAM_4_SPLTADDR_S) - - -static inline uint32_t *esp_memprot_dram0_sram_get_fault_address(void) +static inline intptr_t memprot_ll_dram0_sram_get_fault_address(void) { - uint32_t status_bits = esp_memprot_dram0_get_fault_reg(); - return (uint32_t *)(((status_bits & DRAM0_INTR_ST_FAULTADDR_M) >> DRAM0_INTR_ST_FAULTADDR_S) | DRAM0_SRAM_INTR_ST_FAULTADDR_HI); + uint32_t status_bits = memprot_ll_dram0_get_fault_reg(); + return (intptr_t)(((status_bits & DRAM0_INTR_ST_FAULTADDR_M) >> DRAM0_INTR_ST_FAULTADDR_S) | DRAM0_SRAM_INTR_ST_FAULTADDR_HI); } -static inline bool esp_memprot_dram0_sram_is_intr_mine(void) +static inline bool memprot_ll_dram0_sram_is_intr_mine(void) { - if (esp_memprot_dram0_is_assoc_intr()) { - uint32_t *faulting_address = esp_memprot_dram0_sram_get_fault_address(); - return (uint32_t)faulting_address >= DRAM0_SRAM_ADDRESS_LOW && (uint32_t)faulting_address <= DRAM0_SRAM_ADDRESS_HIGH; + if (memprot_ll_dram0_is_assoc_intr()) { + uint32_t faulting_address = (uint32_t)memprot_ll_dram0_sram_get_fault_address(); + return faulting_address >= DRAM0_SRAM_ADDRESS_LOW && faulting_address <= DRAM0_SRAM_ADDRESS_HIGH; } return false; } -static inline void esp_memprot_dram0_sram_get_uni_block_sgnf_bits(uint32_t block, uint32_t *write_bit, uint32_t *read_bit) +static inline bool memprot_ll_dram0_sram_get_uni_block_sgnf_bits(uint32_t block, uint32_t *write_bit, uint32_t *read_bit) { - HAL_ASSERT(block < DRAM0_SRAM_TOTAL_UNI_BLOCKS); - switch (block) { case DRAM0_SRAM_UNI_BLOCK_0: *write_bit = DPORT_PMS_PRO_DRAM0_SRAM_0_W; @@ -648,79 +613,97 @@ static inline void esp_memprot_dram0_sram_get_uni_block_sgnf_bits(uint32_t block *read_bit = DPORT_PMS_PRO_DRAM0_SRAM_3_R; break; default: - abort(); + return false; } + + return true; } -static inline void esp_memprot_dram0_sram_set_uni_block_perm(uint32_t block, bool write_perm, bool read_perm) +static inline memprot_ll_err_t memprot_ll_dram0_sram_set_uni_block_perm(uint32_t block, bool write_perm, bool read_perm) { - HAL_ASSERT(block < DRAM0_SRAM_TOTAL_UNI_BLOCKS); - - uint32_t write_bit, read_bit; - esp_memprot_dram0_sram_get_uni_block_sgnf_bits(block, &write_bit, &read_bit); + //get block-specific WR flags offset within the conf.register + uint32_t write_bit_offset, read_bit_offset; + if (!memprot_ll_dram0_sram_get_uni_block_sgnf_bits(block, &write_bit_offset, &read_bit_offset)) { + return MEMP_LL_ERR_UNI_BLOCK_INVALID; + } + //set/reset required flags if (write_perm) { - DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_1_REG, write_bit); + DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_1_REG, write_bit_offset); } else { - DPORT_CLEAR_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_1_REG, write_bit); + DPORT_CLEAR_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_1_REG, write_bit_offset); } if (read_perm) { - DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_1_REG, read_bit); + DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_1_REG, read_bit_offset); } else { - DPORT_CLEAR_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_1_REG, read_bit); + DPORT_CLEAR_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_1_REG, read_bit_offset); } + + return MEMP_LL_OK; } -static inline uint32_t esp_memprot_dram0_sram_get_uni_block_read_bit(uint32_t block) +static inline bool memprot_ll_dram0_sram_get_uni_block_read_bit(uint32_t block, uint32_t *read_bit) { - HAL_ASSERT(block < DRAM0_SRAM_TOTAL_UNI_BLOCKS); - switch (block) { case DRAM0_SRAM_UNI_BLOCK_0: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_0_R); + *read_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_0_R); + break; case DRAM0_SRAM_UNI_BLOCK_1: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_1_R); + *read_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_1_R); + break; case DRAM0_SRAM_UNI_BLOCK_2: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_2_R); + *read_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_2_R); + break; case DRAM0_SRAM_UNI_BLOCK_3: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_3_R); + *read_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_3_R); + break; default: - abort(); + return false; } + + return true; } -static inline uint32_t esp_memprot_dram0_sram_get_uni_block_write_bit(uint32_t block) +static inline bool memprot_ll_dram0_sram_get_uni_block_write_bit(uint32_t block, uint32_t *write_bit) { - HAL_ASSERT(block < DRAM0_SRAM_TOTAL_UNI_BLOCKS); - switch (block) { case DRAM0_SRAM_UNI_BLOCK_0: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_0_W); + *write_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_0_W); + break; case DRAM0_SRAM_UNI_BLOCK_1: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_1_W); + *write_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_1_W); + break; case DRAM0_SRAM_UNI_BLOCK_2: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_2_W); + *write_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_2_W); + break; case DRAM0_SRAM_UNI_BLOCK_3: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_3_W); + *write_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_3_W); + break; default: - abort(); + return false; } + + return true; } //DRAM0 has both unified blocks and split address configured in 1 register -static inline uint32_t esp_memprot_dram0_sram_get_perm_reg(void) +static inline uint32_t memprot_ll_dram0_sram_get_perm_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DRAM0_1_REG); } -static inline void esp_memprot_dram0_sram_set_prot(uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr) +static inline memprot_ll_err_t memprot_ll_dram0_sram_set_prot(uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr) { uint32_t addr = (uint32_t)split_addr; - //low boundary check provided by LD script. see comment in esp_memprot_iram0_sram_set_prot() - HAL_ASSERT(addr <= DRAM0_SRAM_SPL_BLOCK_HIGH); - HAL_ASSERT(addr % 0x4 == 0 ); + //low boundary check provided by LD script. see comment in memprot_ll_iram0_sram_set_prot() + if (addr > DRAM0_SRAM_SPL_BLOCK_HIGH) { + return MEMP_LL_ERR_SPLIT_ADDR_INVALID; + } + if (addr % 0x4 != 0) { + return MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED; + } //set low region int uni_blocks_low = -1; @@ -740,7 +723,9 @@ static inline void esp_memprot_dram0_sram_set_prot(uint32_t *split_addr, bool lw //set unified mgmt region uint32_t write_bit, read_bit, uni_block_perm = 0; for (int x = 0; x < DRAM0_SRAM_TOTAL_UNI_BLOCKS; x++) { - esp_memprot_dram0_sram_get_uni_block_sgnf_bits(x, &write_bit, &read_bit); + if (!memprot_ll_dram0_sram_get_uni_block_sgnf_bits(x, &write_bit, &read_bit)) { + return MEMP_LL_ERR_UNI_BLOCK_INVALID; + } if (x <= uni_blocks_low) { if (lw) { uni_block_perm |= write_bit; @@ -778,9 +763,11 @@ static inline void esp_memprot_dram0_sram_set_prot(uint32_t *split_addr, bool lw //write DRAM0 SRAM cfg register DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_DRAM0_1_REG, reg_split_addr | permission_mask | uni_block_perm); + + return MEMP_LL_OK; } -static inline void esp_memprot_dram0_sram_get_split_sgnf_bits(bool *lw, bool *lr, bool *hw, bool *hr) +static inline void memprot_ll_dram0_sram_get_split_sgnf_bits(bool *lw, bool *lr, bool *hw, bool *hr) { *lw = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_4_L_W); *lr = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_4_L_R); @@ -788,13 +775,13 @@ static inline void esp_memprot_dram0_sram_get_split_sgnf_bits(bool *lw, bool *lr *hr = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_4_H_R); } -static inline void esp_memprot_dram0_sram_set_read_perm(bool lr, bool hr) +static inline void memprot_ll_dram0_sram_set_read_perm(bool lr, bool hr) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_4_L_R, lr ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_4_H_R, hr ? 1 : 0); } -static inline void esp_memprot_dram0_sram_set_write_perm(bool lw, bool hw) +static inline void memprot_ll_dram0_sram_set_write_perm(bool lw, bool hw) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_4_L_W, lw ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_4_H_W, hw ? 1 : 0); @@ -806,34 +793,35 @@ static inline void esp_memprot_dram0_sram_set_write_perm(bool lw, bool hw) * === DRAM0 RTC FAST * ======================================================================================== */ -#define DRAM0_RTCFAST_ADDRESS_LOW 0x3FF9E000 -#define DRAM0_RTCFAST_ADDRESS_HIGH 0x3FF9FFFF -#define DRAM0_RTCFAST_INTR_ST_FAULTADDR_HI 0x3FF00000 //RTCFAST high bits 31:22 of the faulting address - constant -#define DRAM0_RTCFAST_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_DRAM0_RTCFAST_SPLTADDR) << DPORT_PMS_PRO_DRAM0_RTCFAST_SPLTADDR_S) - - -static inline uint32_t *esp_memprot_dram0_rtcfast_get_fault_address(void) +static inline intptr_t memprot_ll_dram0_rtcfast_get_fault_address(void) { - uint32_t status_bits = esp_memprot_dram0_get_fault_reg(); - return (uint32_t *)(((status_bits & DRAM0_INTR_ST_FAULTADDR_M) >> DRAM0_INTR_ST_FAULTADDR_S) | DRAM0_RTCFAST_INTR_ST_FAULTADDR_HI); + uint32_t status_bits = memprot_ll_dram0_get_fault_reg(); + return (intptr_t)(((status_bits & DRAM0_INTR_ST_FAULTADDR_M) >> DRAM0_INTR_ST_FAULTADDR_S) | DRAM0_RTCFAST_INTR_ST_FAULTADDR_HI); } -static inline bool esp_memprot_dram0_rtcfast_is_intr_mine(void) +static inline bool memprot_ll_dram0_rtcfast_is_intr_mine(void) { - if (esp_memprot_dram0_is_assoc_intr()) { - uint32_t *faulting_address = esp_memprot_dram0_rtcfast_get_fault_address(); - return (uint32_t)faulting_address >= DRAM0_RTCFAST_ADDRESS_LOW && (uint32_t)faulting_address <= DRAM0_RTCFAST_ADDRESS_HIGH; + if (memprot_ll_dram0_is_assoc_intr()) { + uint32_t faulting_address = (uint32_t)memprot_ll_dram0_rtcfast_get_fault_address(); + return faulting_address >= DRAM0_RTCFAST_ADDRESS_LOW && faulting_address <= DRAM0_RTCFAST_ADDRESS_HIGH; } return false; } -static inline void esp_memprot_dram0_rtcfast_set_prot(uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr) +static inline memprot_ll_err_t memprot_ll_dram0_rtcfast_set_prot(uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr) { uint32_t addr = (uint32_t)split_addr; - HAL_ASSERT(addr % 0x4 == 0); + + //addr: 32bit aligned, inside corresponding range + if (addr < DRAM0_RTCFAST_ADDRESS_LOW || addr > DRAM0_RTCFAST_ADDRESS_HIGH) { + return MEMP_LL_ERR_SPLIT_ADDR_INVALID; + } + if (addr % 0x4 != 0) { + return MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED; + } //conf reg [10:0] - uint32_t reg_split_addr = DRAM0_RTCFAST_ADDR_TO_CONF_REG( addr ); + uint32_t reg_split_addr = DRAM0_RTCFAST_ADDR_TO_CONF_REG(addr); //prepare high & low permission mask uint32_t permission_mask = 0; @@ -852,9 +840,11 @@ static inline void esp_memprot_dram0_rtcfast_set_prot(uint32_t *split_addr, bool //write DRAM0 RTC FAST cfg register DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_DRAM0_2_REG, reg_split_addr | permission_mask); + + return MEMP_LL_OK; } -static inline void esp_memprot_dram0_rtcfast_get_split_sgnf_bits(bool *lw, bool *lr, bool *hw, bool *hr) +static inline void memprot_ll_dram0_rtcfast_get_split_sgnf_bits(bool *lw, bool *lr, bool *hw, bool *hr) { *lw = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_2_REG, DPORT_PMS_PRO_DRAM0_RTCFAST_L_W); *lr = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_2_REG, DPORT_PMS_PRO_DRAM0_RTCFAST_L_R); @@ -862,18 +852,18 @@ static inline void esp_memprot_dram0_rtcfast_get_split_sgnf_bits(bool *lw, bool *hr = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_2_REG, DPORT_PMS_PRO_DRAM0_RTCFAST_H_R); } -static inline uint32_t esp_memprot_dram0_rtcfast_get_perm_split_reg(void) +static inline uint32_t memprot_ll_dram0_rtcfast_get_perm_split_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DRAM0_2_REG); } -static inline void esp_memprot_dram0_rtcfast_set_read_perm(bool lr, bool hr) +static inline void memprot_ll_dram0_rtcfast_set_read_perm(bool lr, bool hr) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DRAM0_2_REG, DPORT_PMS_PRO_DRAM0_RTCFAST_L_R, lr ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DRAM0_2_REG, DPORT_PMS_PRO_DRAM0_RTCFAST_H_R, hr ? 1 : 0); } -static inline void esp_memprot_dram0_rtcfast_set_write_perm(bool lw, bool hw) +static inline void memprot_ll_dram0_rtcfast_set_write_perm(bool lw, bool hw) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DRAM0_2_REG, DPORT_PMS_PRO_DRAM0_RTCFAST_L_W, lw ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DRAM0_2_REG, DPORT_PMS_PRO_DRAM0_RTCFAST_H_W, hw ? 1 : 0); diff --git a/components/hal/esp32s2/include/hal/memprot_peri_ll.h b/components/hal/esp32s2/include/hal/memprot_peri_ll.h index d699df6cf4..4611f7a35d 100644 --- a/components/hal/esp32s2/include/hal/memprot_peri_ll.h +++ b/components/hal/esp32s2/include/hal/memprot_peri_ll.h @@ -14,38 +14,31 @@ #pragma once -#include "hal/assert.h" +#include +#include "soc/memprot_defs.h" +#include "hal/memprot_types.h" #ifdef __cplusplus extern "C" { #endif -#define RTCSLOW_MEMORY_SIZE 0x00002000 - /** * ======================================================================================== * === PeriBus1 common * ======================================================================================== */ -//PeriBus1 interrupt status bitmasks -#define PERI1_INTR_ST_OP_TYPE_BIT BIT(4) //0: non-atomic, 1: atomic -#define PERI1_INTR_ST_OP_HIGH_BITS BIT(5) //0: high bits = unchanged, 1: high bits = 0x03F40000 -#define PERI1_INTR_ST_FAULTADDR_M 0x03FFFFC0 //(bits 25:6 in the reg) -#define PERI1_INTR_ST_FAULTADDR_S 0x4 //(bits 21:2 of real address) - - -static inline void esp_memprot_peri1_clear_intr(void) +static inline void memprot_ll_peri1_clear_intr(void) { DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_DPORT_6_REG, DPORT_PMS_PRO_DPORT_ILG_CLR); DPORT_CLEAR_PERI_REG_MASK(DPORT_PMS_PRO_DPORT_6_REG, DPORT_PMS_PRO_DPORT_ILG_CLR); } -static inline uint32_t esp_memprot_peri1_get_intr_source_num(void) +static inline uint32_t memprot_ll_peri1_get_intr_source_num(void) { return ETS_PMS_PRO_DPORT_ILG_INTR_SOURCE; } -static inline void esp_memprot_peri1_intr_ena(bool enable) +static inline void memprot_ll_peri1_intr_ena(bool enable) { if (enable) { DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_DPORT_6_REG, DPORT_PMS_PRO_DPORT_ILG_EN); @@ -54,95 +47,94 @@ static inline void esp_memprot_peri1_intr_ena(bool enable) } } -static inline uint32_t esp_memprot_peri1_get_ctrl_reg(void) +static inline uint32_t memprot_ll_peri1_get_ctrl_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DPORT_6_REG); } -static inline uint32_t esp_memprot_peri1_get_fault_reg(void) +static inline uint32_t memprot_ll_peri1_get_fault_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DPORT_7_REG); } -static inline void esp_memprot_peri1_get_fault_op_type(uint32_t *op_type, uint32_t *op_subtype) +static inline void memprot_ll_peri1_get_fault_op_type(uint32_t *op_type, uint32_t *op_subtype) { - uint32_t status_bits = esp_memprot_peri1_get_fault_reg(); + uint32_t status_bits = memprot_ll_peri1_get_fault_reg(); //*op_type = (uint32_t)status_bits & PERI1_INTR_ST_OP_RW_BIT; *op_type = 0; //! DPORT_PMS_PRO_DPORT_7_REG is missing op_type bit *op_subtype = (uint32_t)status_bits & PERI1_INTR_ST_OP_TYPE_BIT; } -static inline bool esp_memprot_peri1_is_assoc_intr(void) +static inline bool memprot_ll_peri1_is_assoc_intr(void) { return DPORT_GET_PERI_REG_MASK(DPORT_PMS_PRO_DPORT_7_REG, DPORT_PMS_PRO_DPORT_ILG_INTR) > 0; } -static inline uint32_t esp_memprot_peri1_get_intr_ena_bit(void) +static inline uint32_t memprot_ll_peri1_get_intr_ena_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DPORT_6_REG, DPORT_PMS_PRO_DPORT_ILG_EN); } -static inline uint32_t esp_memprot_peri1_get_intr_on_bit(void) +static inline uint32_t memprot_ll_peri1_get_intr_on_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DPORT_6_REG, DPORT_PMS_PRO_DPORT_ILG_INTR); } -static inline uint32_t esp_memprot_peri1_get_intr_clr_bit(void) +static inline uint32_t memprot_ll_peri1_get_intr_clr_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DPORT_6_REG, DPORT_PMS_PRO_DPORT_ILG_CLR); } -static inline uint32_t esp_memprot_peri1_get_lock_reg(void) +static inline uint32_t memprot_ll_peri1_get_lock_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DPORT_0_REG); } //resets automatically on CPU restart -static inline void esp_memprot_peri1_set_lock(void) +static inline void memprot_ll_peri1_set_lock(void) { DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_DPORT_0_REG, DPORT_PMS_PRO_DPORT_LOCK); } -static inline uint32_t esp_memprot_peri1_get_lock_bit(void) +static inline uint32_t memprot_ll_peri1_get_lock_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DPORT_0_REG, DPORT_PMS_PRO_DPORT_LOCK); } - /** * ======================================================================================== * === PeriBus1 RTC SLOW * ======================================================================================== */ -#define PERI1_RTCSLOW_ADDRESS_BASE 0x3F421000 -#define PERI1_RTCSLOW_ADDRESS_LOW PERI1_RTCSLOW_ADDRESS_BASE -#define PERI1_RTCSLOW_ADDRESS_HIGH PERI1_RTCSLOW_ADDRESS_LOW + RTCSLOW_MEMORY_SIZE -#define PERI1_RTCSLOW_INTR_ST_FAULTADDR_HI_0 0x3F400000 - -#define PERI1_RTCSLOW_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_DPORT_RTCSLOW_SPLTADDR) << DPORT_PMS_PRO_DPORT_RTCSLOW_SPLTADDR_S) - -static inline uint32_t *esp_memprot_peri1_rtcslow_get_fault_address(void) +static inline intptr_t memprot_ll_peri1_rtcslow_get_fault_address(void) { - uint32_t status_bits = esp_memprot_peri1_get_fault_reg(); + uint32_t status_bits = memprot_ll_peri1_get_fault_reg(); uint32_t fault_address = (status_bits & PERI1_INTR_ST_FAULTADDR_M) >> PERI1_INTR_ST_FAULTADDR_S; uint32_t high_bits = (status_bits & PERI1_INTR_ST_OP_HIGH_BITS) ? PERI1_RTCSLOW_INTR_ST_FAULTADDR_HI_0 : 0; - return (uint32_t *)(fault_address | high_bits); + return (intptr_t)(fault_address | high_bits); } -static inline bool esp_memprot_peri1_rtcslow_is_intr_mine(void) +static inline bool memprot_ll_peri1_rtcslow_is_intr_mine(void) { - if (esp_memprot_dram0_is_assoc_intr()) { - uint32_t *faulting_address = esp_memprot_peri1_rtcslow_get_fault_address(); - return (uint32_t)faulting_address >= PERI1_RTCSLOW_ADDRESS_LOW && (uint32_t)faulting_address <= PERI1_RTCSLOW_ADDRESS_HIGH; + if (memprot_ll_dram0_is_assoc_intr()) { + uint32_t faulting_address = (uint32_t)memprot_ll_peri1_rtcslow_get_fault_address(); + return faulting_address >= PERI1_RTCSLOW_ADDRESS_LOW && faulting_address <= PERI1_RTCSLOW_ADDRESS_HIGH; } return false; } -static inline void esp_memprot_peri1_rtcslow_set_prot(uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr) +static inline memprot_ll_err_t memprot_ll_peri1_rtcslow_set_prot(uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr) { uint32_t addr = (uint32_t)split_addr; - HAL_ASSERT(addr % 0x4 == 0); + + //check corresponding range fit & aligment to 32bit boundaries + if (addr < PERI1_RTCSLOW_ADDRESS_LOW || addr > PERI1_RTCSLOW_ADDRESS_HIGH) { + return MEMP_LL_ERR_SPLIT_ADDR_INVALID; + } + if (addr % 0x4 != 0) { + return MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED; + } uint32_t reg_split_addr = PERI1_RTCSLOW_ADDR_TO_CONF_REG(addr); @@ -163,9 +155,11 @@ static inline void esp_memprot_peri1_rtcslow_set_prot(uint32_t *split_addr, bool //write PERIBUS1 RTC SLOW cfg register DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_DPORT_1_REG, reg_split_addr | permission_mask); + + return MEMP_LL_OK; } -static inline void esp_memprot_peri1_rtcslow_get_split_sgnf_bits(bool *lw, bool *lr, bool *hw, bool *hr) +static inline void memprot_ll_peri1_rtcslow_get_split_sgnf_bits(bool *lw, bool *lr, bool *hw, bool *hr) { *lw = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DPORT_1_REG, DPORT_PMS_PRO_DPORT_RTCSLOW_L_W); *lr = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DPORT_1_REG, DPORT_PMS_PRO_DPORT_RTCSLOW_L_R); @@ -173,46 +167,40 @@ static inline void esp_memprot_peri1_rtcslow_get_split_sgnf_bits(bool *lw, bool *hr = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DPORT_1_REG, DPORT_PMS_PRO_DPORT_RTCSLOW_H_R); } -static inline void esp_memprot_peri1_rtcslow_set_read_perm(bool lr, bool hr) +static inline void memprot_ll_peri1_rtcslow_set_read_perm(bool lr, bool hr) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DPORT_1_REG, DPORT_PMS_PRO_DPORT_RTCSLOW_L_R, lr ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DPORT_1_REG, DPORT_PMS_PRO_DPORT_RTCSLOW_H_R, hr ? 1 : 0); } -static inline void esp_memprot_peri1_rtcslow_set_write_perm(bool lw, bool hw) +static inline void memprot_ll_peri1_rtcslow_set_write_perm(bool lw, bool hw) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DPORT_1_REG, DPORT_PMS_PRO_DPORT_RTCSLOW_L_W, lw ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DPORT_1_REG, DPORT_PMS_PRO_DPORT_RTCSLOW_H_W, hw ? 1 : 0); } -static inline uint32_t esp_memprot_peri1_rtcslow_get_conf_reg(void) +static inline uint32_t memprot_ll_peri1_rtcslow_get_conf_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DPORT_1_REG); } - /** * ======================================================================================== * === PeriBus2 common * ======================================================================================== */ -//PeriBus2 interrupt status bitmasks -#define PERI2_INTR_ST_OP_TYPE_BIT BIT(1) //instruction: 0, data: 1 -#define PERI2_INTR_ST_OP_RW_BIT BIT(0) //read: 0, write: 1 -#define PERI2_INTR_ST_FAULTADDR_M 0xFFFFFFFC //(bits 31:2 in the reg) - -static inline void esp_memprot_peri2_clear_intr(void) +static inline void memprot_ll_peri2_clear_intr(void) { DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_AHB_3_REG, DPORT_PMS_PRO_AHB_ILG_CLR); DPORT_CLEAR_PERI_REG_MASK(DPORT_PMS_PRO_AHB_3_REG, DPORT_PMS_PRO_AHB_ILG_CLR); } -static inline uint32_t esp_memprot_peri2_get_intr_source_num(void) +static inline uint32_t memprot_ll_peri2_get_intr_source_num(void) { return ETS_PMS_PRO_AHB_ILG_INTR_SOURCE; } -static inline void esp_memprot_peri2_intr_ena(bool enable) +static inline void memprot_ll_peri2_intr_ena(bool enable) { if (enable) { DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_AHB_3_REG, DPORT_PMS_PRO_AHB_ILG_EN); @@ -221,90 +209,90 @@ static inline void esp_memprot_peri2_intr_ena(bool enable) } } -static inline uint32_t esp_memprot_peri2_get_ctrl_reg(void) +static inline uint32_t memprot_ll_peri2_get_ctrl_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_AHB_3_REG); } -static inline uint32_t esp_memprot_peri2_get_fault_reg(void) +static inline uint32_t memprot_ll_peri2_get_fault_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_AHB_4_REG); } -static inline void esp_memprot_peri2_get_fault_op_type(uint32_t *op_type, uint32_t *op_subtype) +static inline void memprot_ll_peri2_get_fault_op_type(uint32_t *op_type, uint32_t *op_subtype) { - uint32_t status_bits = esp_memprot_peri2_get_fault_reg(); + uint32_t status_bits = memprot_ll_peri2_get_fault_reg(); *op_type = (uint32_t)status_bits & PERI2_INTR_ST_OP_RW_BIT; *op_subtype = (uint32_t)status_bits & PERI2_INTR_ST_OP_TYPE_BIT; } -static inline bool esp_memprot_peri2_is_assoc_intr(void) +static inline bool memprot_ll_peri2_is_assoc_intr(void) { return DPORT_GET_PERI_REG_MASK(DPORT_PMS_PRO_AHB_3_REG, DPORT_PMS_PRO_AHB_ILG_INTR) > 0; } -static inline uint32_t esp_memprot_peri2_get_intr_ena_bit(void) +static inline uint32_t memprot_ll_peri2_get_intr_ena_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_3_REG, DPORT_PMS_PRO_AHB_ILG_EN); } -static inline uint32_t esp_memprot_peri2_get_intr_on_bit(void) +static inline uint32_t memprot_ll_peri2_get_intr_on_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_3_REG, DPORT_PMS_PRO_AHB_ILG_INTR); } -static inline uint32_t esp_memprot_peri2_get_intr_clr_bit(void) +static inline uint32_t memprot_ll_peri2_get_intr_clr_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_3_REG, DPORT_PMS_PRO_AHB_ILG_CLR); } -static inline uint32_t esp_memprot_peri2_get_lock_reg(void) +static inline uint32_t memprot_ll_peri2_get_lock_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_AHB_0_REG); } //resets automatically on CPU restart -static inline void esp_memprot_peri2_set_lock(void) +static inline void memprot_ll_peri2_set_lock(void) { DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_AHB_0_REG, DPORT_PMS_PRO_AHB_LOCK); } -static inline uint32_t esp_memprot_peri2_get_lock_bit(void) +static inline uint32_t memprot_ll_peri2_get_lock_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_0_REG, DPORT_PMS_PRO_AHB_LOCK); } -static inline uint32_t *esp_memprot_peri2_rtcslow_get_fault_address(void) +static inline intptr_t memprot_ll_peri2_rtcslow_get_fault_address(void) { - uint32_t status_bits = esp_memprot_peri2_get_fault_reg(); - return (uint32_t *)(status_bits & PERI2_INTR_ST_FAULTADDR_M); + uint32_t status_bits = memprot_ll_peri2_get_fault_reg(); + return (intptr_t)(status_bits & PERI2_INTR_ST_FAULTADDR_M); } - /** * ======================================================================================== * === PeriBus2 RTC SLOW 0 (AHB0) * ======================================================================================== */ -#define PERI2_RTCSLOW_0_ADDRESS_BASE 0x50000000 -#define PERI2_RTCSLOW_0_ADDRESS_LOW PERI2_RTCSLOW_0_ADDRESS_BASE -#define PERI2_RTCSLOW_0_ADDRESS_HIGH PERI2_RTCSLOW_0_ADDRESS_LOW + RTCSLOW_MEMORY_SIZE - -#define PERI2_RTCSLOW_0_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_AHB_RTCSLOW_0_SPLTADDR) << DPORT_PMS_PRO_AHB_RTCSLOW_0_SPLTADDR_S) - -static inline bool esp_memprot_peri2_rtcslow_0_is_intr_mine(void) +static inline bool memprot_ll_peri2_rtcslow_0_is_intr_mine(void) { - if (esp_memprot_peri2_is_assoc_intr()) { - uint32_t *faulting_address = esp_memprot_peri2_rtcslow_get_fault_address(); - return (uint32_t)faulting_address >= PERI2_RTCSLOW_0_ADDRESS_LOW && (uint32_t)faulting_address <= PERI2_RTCSLOW_0_ADDRESS_HIGH; + if (memprot_ll_peri2_is_assoc_intr()) { + uint32_t faulting_address = (uint32_t)memprot_ll_peri2_rtcslow_get_fault_address(); + return faulting_address >= PERI2_RTCSLOW_0_ADDRESS_LOW && faulting_address <= PERI2_RTCSLOW_0_ADDRESS_HIGH; } return false; } -static inline void esp_memprot_peri2_rtcslow_0_set_prot(uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx) +static inline memprot_ll_err_t memprot_ll_peri2_rtcslow_0_set_prot(uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx) { uint32_t addr = (uint32_t)split_addr; - HAL_ASSERT(addr % 0x4 == 0); + + //check corresponding range fit & aligment to 32bit boundaries + if (addr < PERI2_RTCSLOW_0_ADDRESS_LOW || addr > PERI2_RTCSLOW_0_ADDRESS_HIGH) { + return MEMP_LL_ERR_SPLIT_ADDR_INVALID; + } + if (addr % 0x4 != 0) { + return MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED; + } uint32_t reg_split_addr = PERI2_RTCSLOW_0_ADDR_TO_CONF_REG(addr); @@ -331,9 +319,11 @@ static inline void esp_memprot_peri2_rtcslow_0_set_prot(uint32_t *split_addr, bo //write PERIBUS1 RTC SLOW cfg register DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_AHB_1_REG, reg_split_addr | permission_mask); + + return MEMP_LL_OK; } -static inline void esp_memprot_peri2_rtcslow_0_get_split_sgnf_bits(bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) +static inline void memprot_ll_peri2_rtcslow_0_get_split_sgnf_bits(bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) { *lw = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_1_REG, DPORT_PMS_PRO_AHB_RTCSLOW_0_L_W); *lr = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_1_REG, DPORT_PMS_PRO_AHB_RTCSLOW_0_L_R); @@ -343,25 +333,25 @@ static inline void esp_memprot_peri2_rtcslow_0_get_split_sgnf_bits(bool *lw, boo *hx = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_1_REG, DPORT_PMS_PRO_AHB_RTCSLOW_0_H_F); } -static inline void esp_memprot_peri2_rtcslow_0_set_read_perm(bool lr, bool hr) +static inline void memprot_ll_peri2_rtcslow_0_set_read_perm(bool lr, bool hr) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_1_REG, DPORT_PMS_PRO_AHB_RTCSLOW_0_L_R, lr ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_1_REG, DPORT_PMS_PRO_AHB_RTCSLOW_0_H_R, hr ? 1 : 0); } -static inline void esp_memprot_peri2_rtcslow_0_set_write_perm(bool lw, bool hw) +static inline void memprot_ll_peri2_rtcslow_0_set_write_perm(bool lw, bool hw) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_1_REG, DPORT_PMS_PRO_AHB_RTCSLOW_0_L_W, lw ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_1_REG, DPORT_PMS_PRO_AHB_RTCSLOW_0_H_W, hw ? 1 : 0); } -static inline void esp_memprot_peri2_rtcslow_0_set_exec_perm(bool lx, bool hx) +static inline void memprot_ll_peri2_rtcslow_0_set_exec_perm(bool lx, bool hx) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_1_REG, DPORT_PMS_PRO_AHB_RTCSLOW_0_L_F, lx ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_1_REG, DPORT_PMS_PRO_AHB_RTCSLOW_0_H_F, hx ? 1 : 0); } -static inline uint32_t esp_memprot_peri2_rtcslow_0_get_conf_reg(void) +static inline uint32_t memprot_ll_peri2_rtcslow_0_get_conf_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DPORT_1_REG); } @@ -371,25 +361,26 @@ static inline uint32_t esp_memprot_peri2_rtcslow_0_get_conf_reg(void) * === PeriBus2 RTC SLOW 1 (AHB1) * ======================================================================================== */ -#define PERI2_RTCSLOW_1_ADDRESS_BASE 0x60021000 -#define PERI2_RTCSLOW_1_ADDRESS_LOW PERI2_RTCSLOW_1_ADDRESS_BASE -#define PERI2_RTCSLOW_1_ADDRESS_HIGH PERI2_RTCSLOW_1_ADDRESS_LOW + RTCSLOW_MEMORY_SIZE - -#define PERI2_RTCSLOW_1_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_AHB_RTCSLOW_1_SPLTADDR) << DPORT_PMS_PRO_AHB_RTCSLOW_1_SPLTADDR_S) - -static inline bool esp_memprot_peri2_rtcslow_1_is_intr_mine(void) +static inline bool memprot_ll_peri2_rtcslow_1_is_intr_mine(void) { - if (esp_memprot_peri2_is_assoc_intr()) { - uint32_t *faulting_address = esp_memprot_peri2_rtcslow_get_fault_address(); - return (uint32_t)faulting_address >= PERI2_RTCSLOW_1_ADDRESS_LOW && (uint32_t)faulting_address <= PERI2_RTCSLOW_1_ADDRESS_HIGH; + if (memprot_ll_peri2_is_assoc_intr()) { + uint32_t faulting_address = (uint32_t)memprot_ll_peri2_rtcslow_get_fault_address(); + return faulting_address >= PERI2_RTCSLOW_1_ADDRESS_LOW && faulting_address <= PERI2_RTCSLOW_1_ADDRESS_HIGH; } return false; } -static inline void esp_memprot_peri2_rtcslow_1_set_prot(uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx) +static inline memprot_ll_err_t memprot_ll_peri2_rtcslow_1_set_prot(uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx) { uint32_t addr = (uint32_t)split_addr; - HAL_ASSERT(addr % 0x4 == 0); + + //check corresponding range fit & aligment to 32bit boundaries + if (addr < PERI2_RTCSLOW_1_ADDRESS_LOW || addr > PERI2_RTCSLOW_1_ADDRESS_HIGH) { + return MEMP_LL_ERR_SPLIT_ADDR_INVALID; + } + if (addr % 0x4 != 0) { + return MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED; + } uint32_t reg_split_addr = PERI2_RTCSLOW_1_ADDR_TO_CONF_REG(addr); @@ -416,9 +407,11 @@ static inline void esp_memprot_peri2_rtcslow_1_set_prot(uint32_t *split_addr, bo //write PERIBUS1 RTC SLOW cfg register DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_AHB_2_REG, reg_split_addr | permission_mask); + + return MEMP_LL_OK; } -static inline void esp_memprot_peri2_rtcslow_1_get_split_sgnf_bits(bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) +static inline void memprot_ll_peri2_rtcslow_1_get_split_sgnf_bits(bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) { *lw = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_2_REG, DPORT_PMS_PRO_AHB_RTCSLOW_1_L_W); *lr = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_2_REG, DPORT_PMS_PRO_AHB_RTCSLOW_1_L_R); @@ -428,25 +421,25 @@ static inline void esp_memprot_peri2_rtcslow_1_get_split_sgnf_bits(bool *lw, boo *hx = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_2_REG, DPORT_PMS_PRO_AHB_RTCSLOW_1_H_F); } -static inline void esp_memprot_peri2_rtcslow_1_set_read_perm(bool lr, bool hr) +static inline void memprot_ll_peri2_rtcslow_1_set_read_perm(bool lr, bool hr) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_2_REG, DPORT_PMS_PRO_AHB_RTCSLOW_1_L_R, lr ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_2_REG, DPORT_PMS_PRO_AHB_RTCSLOW_1_H_R, hr ? 1 : 0); } -static inline void esp_memprot_peri2_rtcslow_1_set_write_perm(bool lw, bool hw) +static inline void memprot_ll_peri2_rtcslow_1_set_write_perm(bool lw, bool hw) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_2_REG, DPORT_PMS_PRO_AHB_RTCSLOW_1_L_W, lw ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_2_REG, DPORT_PMS_PRO_AHB_RTCSLOW_1_H_W, hw ? 1 : 0); } -static inline void esp_memprot_peri2_rtcslow_1_set_exec_perm(bool lx, bool hx) +static inline void memprot_ll_peri2_rtcslow_1_set_exec_perm(bool lx, bool hx) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_2_REG, DPORT_PMS_PRO_AHB_RTCSLOW_1_L_F, lx ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_2_REG, DPORT_PMS_PRO_AHB_RTCSLOW_1_H_F, hx ? 1 : 0); } -static inline uint32_t esp_memprot_peri2_rtcslow_1_get_conf_reg(void) +static inline uint32_t memprot_ll_peri2_rtcslow_1_get_conf_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DPORT_2_REG); } diff --git a/components/hal/esp32s2/include/hal/mwdt_ll.h b/components/hal/esp32s2/include/hal/mwdt_ll.h index f909678b39..6d50f740b6 100644 --- a/components/hal/esp32s2/include/hal/mwdt_ll.h +++ b/components/hal/esp32s2/include/hal/mwdt_ll.h @@ -24,6 +24,7 @@ extern "C" { #include #include #include "soc/timer_periph.h" +#include "soc/timer_group_struct.h" #include "hal/wdt_types.h" #include "esp_attr.h" @@ -42,6 +43,13 @@ _Static_assert(WDT_RESET_SIG_LENGTH_800ns == TIMG_WDT_RESET_LENGTH_800_NS, "Add _Static_assert(WDT_RESET_SIG_LENGTH_1_6us == TIMG_WDT_RESET_LENGTH_1600_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t"); _Static_assert(WDT_RESET_SIG_LENGTH_3_2us == TIMG_WDT_RESET_LENGTH_3200_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t"); +#define FORCE_MODIFY_WHOLE_REG(i, j, k) \ +{ \ + typeof(i) temp_reg = (i); \ + temp_reg.j = (k); \ + (i) = temp_reg; \ +} + /** * @brief Enable the MWDT * @@ -49,7 +57,7 @@ _Static_assert(WDT_RESET_SIG_LENGTH_3_2us == TIMG_WDT_RESET_LENGTH_3200_NS, "Add */ FORCE_INLINE_ATTR void mwdt_ll_enable(timg_dev_t *hw) { - hw->wdt_config0.en = 1; + hw->wdtconfig0.wdt_en = 1; } /** @@ -62,7 +70,7 @@ FORCE_INLINE_ATTR void mwdt_ll_enable(timg_dev_t *hw) */ FORCE_INLINE_ATTR void mwdt_ll_disable(timg_dev_t *hw) { - hw->wdt_config0.en = 0; + hw->wdtconfig0.wdt_en = 0; } /** @@ -73,7 +81,7 @@ FORCE_INLINE_ATTR void mwdt_ll_disable(timg_dev_t *hw) */ FORCE_INLINE_ATTR bool mwdt_ll_check_if_enabled(timg_dev_t *hw) { - return (hw->wdt_config0.en) ? true : false; + return (hw->wdtconfig0.wdt_en) ? true : false; } /** @@ -88,20 +96,20 @@ FORCE_INLINE_ATTR void mwdt_ll_config_stage(timg_dev_t *hw, wdt_stage_t stage, u { switch (stage) { case WDT_STAGE0: - hw->wdt_config0.stg0 = behavior; - hw->wdt_config2 = timeout; + hw->wdtconfig0.wdt_stg0 = behavior; + hw->wdtconfig2.wdt_stg0_hold = timeout; break; case WDT_STAGE1: - hw->wdt_config0.stg1 = behavior; - hw->wdt_config3 = timeout; + hw->wdtconfig0.wdt_stg1 = behavior; + hw->wdtconfig3.wdt_stg1_hold = timeout; break; case WDT_STAGE2: - hw->wdt_config0.stg2 = behavior; - hw->wdt_config4 = timeout; + hw->wdtconfig0.wdt_stg2 = behavior; + hw->wdtconfig4.wdt_stg2_hold = timeout; break; case WDT_STAGE3: - hw->wdt_config0.stg3 = behavior; - hw->wdt_config5 = timeout; + hw->wdtconfig0.wdt_stg3 = behavior; + hw->wdtconfig5.wdt_stg3_hold = timeout; break; default: break; @@ -118,16 +126,16 @@ FORCE_INLINE_ATTR void mwdt_ll_disable_stage(timg_dev_t *hw, uint32_t stage) { switch (stage) { case WDT_STAGE0: - hw->wdt_config0.stg0 = WDT_STAGE_ACTION_OFF; + hw->wdtconfig0.wdt_stg0 = WDT_STAGE_ACTION_OFF; break; case WDT_STAGE1: - hw->wdt_config0.stg1 = WDT_STAGE_ACTION_OFF; + hw->wdtconfig0.wdt_stg1 = WDT_STAGE_ACTION_OFF; break; case WDT_STAGE2: - hw->wdt_config0.stg2 = WDT_STAGE_ACTION_OFF; + hw->wdtconfig0.wdt_stg2 = WDT_STAGE_ACTION_OFF; break; case WDT_STAGE3: - hw->wdt_config0.stg3 = WDT_STAGE_ACTION_OFF; + hw->wdtconfig0.wdt_stg3 = WDT_STAGE_ACTION_OFF; break; default: break; @@ -142,7 +150,7 @@ FORCE_INLINE_ATTR void mwdt_ll_disable_stage(timg_dev_t *hw, uint32_t stage) */ FORCE_INLINE_ATTR void mwdt_ll_set_edge_intr(timg_dev_t *hw, bool enable) { - hw->wdt_config0.edge_int_en = (enable) ? 1 : 0; + hw->wdtconfig0.wdt_edge_int_en = (enable) ? 1 : 0; } /** @@ -153,7 +161,7 @@ FORCE_INLINE_ATTR void mwdt_ll_set_edge_intr(timg_dev_t *hw, bool enable) */ FORCE_INLINE_ATTR void mwdt_ll_set_level_intr(timg_dev_t *hw, bool enable) { - hw->wdt_config0.level_int_en = (enable) ? 1 : 0; + hw->wdtconfig0.wdt_level_int_en = (enable) ? 1 : 0; } /** @@ -164,7 +172,7 @@ FORCE_INLINE_ATTR void mwdt_ll_set_level_intr(timg_dev_t *hw, bool enable) */ FORCE_INLINE_ATTR void mwdt_ll_set_cpu_reset_length(timg_dev_t *hw, wdt_reset_sig_length_t length) { - hw->wdt_config0.cpu_reset_length = length; + hw->wdtconfig0.wdt_cpu_reset_length = length; } /** @@ -175,7 +183,7 @@ FORCE_INLINE_ATTR void mwdt_ll_set_cpu_reset_length(timg_dev_t *hw, wdt_reset_si */ FORCE_INLINE_ATTR void mwdt_ll_set_sys_reset_length(timg_dev_t *hw, wdt_reset_sig_length_t length) { - hw->wdt_config0.sys_reset_length = length; + hw->wdtconfig0.wdt_sys_reset_length = length; } /** @@ -190,7 +198,7 @@ FORCE_INLINE_ATTR void mwdt_ll_set_sys_reset_length(timg_dev_t *hw, wdt_reset_si */ FORCE_INLINE_ATTR void mwdt_ll_set_flashboot_en(timg_dev_t* hw, bool enable) { - hw->wdt_config0.flashboot_mod_en = (enable) ? 1 : 0; + hw->wdtconfig0.wdt_flashboot_mod_en = (enable) ? 1 : 0; } /** @@ -201,7 +209,9 @@ FORCE_INLINE_ATTR void mwdt_ll_set_flashboot_en(timg_dev_t* hw, bool enable) */ FORCE_INLINE_ATTR void mwdt_ll_set_prescaler(timg_dev_t *hw, uint32_t prescaler) { - hw->wdt_config1.clk_prescale = prescaler; + // In case the compiler optimise a 32bit instruction (e.g. s32i) into 8/16bit instruction (e.g. s8i, which is not allowed to access a register) + // We take care of the "read-modify-write" procedure by ourselves. + FORCE_MODIFY_WHOLE_REG(hw->wdtconfig1, wdt_clk_prescaler, prescaler); } /** @@ -213,7 +223,7 @@ FORCE_INLINE_ATTR void mwdt_ll_set_prescaler(timg_dev_t *hw, uint32_t prescaler) */ FORCE_INLINE_ATTR void mwdt_ll_feed(timg_dev_t *hw) { - hw->wdt_feed = 1; + hw->wdtfeed.wdt_feed = 1; } /** @@ -225,7 +235,7 @@ FORCE_INLINE_ATTR void mwdt_ll_feed(timg_dev_t *hw) */ FORCE_INLINE_ATTR void mwdt_ll_write_protect_enable(timg_dev_t *hw) { - hw->wdt_wprotect = 0; + hw->wdtwprotect.wdt_wkey = 0; } /** @@ -235,7 +245,7 @@ FORCE_INLINE_ATTR void mwdt_ll_write_protect_enable(timg_dev_t *hw) */ FORCE_INLINE_ATTR void mwdt_ll_write_protect_disable(timg_dev_t *hw) { - hw->wdt_wprotect = TIMG_WDT_WKEY_VALUE; + hw->wdtwprotect.wdt_wkey = TIMG_WDT_WKEY_VALUE; } /** @@ -245,7 +255,7 @@ FORCE_INLINE_ATTR void mwdt_ll_write_protect_disable(timg_dev_t *hw) */ FORCE_INLINE_ATTR void mwdt_ll_clear_intr_status(timg_dev_t* hw) { - hw->int_clr.wdt = 1; + hw->int_clr_timers.wdt_int_clr = 1; } /** @@ -256,7 +266,7 @@ FORCE_INLINE_ATTR void mwdt_ll_clear_intr_status(timg_dev_t* hw) */ FORCE_INLINE_ATTR void mwdt_ll_set_intr_enable(timg_dev_t* hw, bool enable) { - hw->int_ena.wdt = (enable) ? 1 : 0; + hw->int_ena_timers.wdt_int_ena = (enable) ? 1 : 0; } #ifdef __cplusplus diff --git a/components/hal/esp32s2/include/hal/pcnt_ll.h b/components/hal/esp32s2/include/hal/pcnt_ll.h index 11dad5cf35..b9286fa92f 100644 --- a/components/hal/esp32s2/include/hal/pcnt_ll.h +++ b/components/hal/esp32s2/include/hal/pcnt_ll.h @@ -1,4 +1,4 @@ -// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// Copyright 2015-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. @@ -22,75 +22,67 @@ #pragma once -#include "soc/pcnt_periph.h" +#include +#include +#include "soc/pcnt_struct.h" #include "hal/pcnt_types.h" #ifdef __cplusplus extern "C" { #endif -// Get PCNT hardware instance with giving pcnt num #define PCNT_LL_GET_HW(num) (((num) == 0) ? (&PCNT) : NULL) +#define PCNT_LL_MAX_GLITCH_WIDTH 1023 + +typedef enum { + PCNT_LL_EVENT_THRES1, + PCNT_LL_EVENT_THRES0, + PCNT_LL_EVENT_LOW_LIMIT, + PCNT_LL_EVENT_HIGH_LIMIT, + PCNT_LL_EVENT_ZERO_CROSS, + PCNT_LL_EVENT_MAX +} pcnt_ll_event_id_t; + +#define PCNT_LL_EVENT_MASK ((1 << PCNT_LL_EVENT_MAX) - 1) /** - * @brief Set PCNT channel edge mode + * @brief Set PCNT channel edge action * * @param hw Peripheral PCNT hardware instance address. * @param unit PCNT unit number * @param channel PCNT channel number - * @param pos_mode Counter mode when detecting positive edge - * @param neg_mode Counter mode when detecting negative edge + * @param pos_act Counter action when detecting positive edge + * @param neg_act Counter action when detecting negative edge */ -static inline void pcnt_ll_set_edge_mode(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_channel_t channel, pcnt_count_mode_t pos_mode, pcnt_count_mode_t neg_mode) +static inline void pcnt_ll_set_edge_action(pcnt_dev_t *hw, uint32_t unit, uint32_t channel, pcnt_channel_edge_action_t pos_act, pcnt_channel_edge_action_t neg_act) { - typeof(hw->conf_unit[unit].conf0) conf0_reg = hw->conf_unit[unit].conf0; if (channel == 0) { - conf0_reg.ch0_pos_mode = pos_mode; - conf0_reg.ch0_neg_mode = neg_mode; + hw->conf_unit[unit].conf0.ch0_pos_mode_un = pos_act; + hw->conf_unit[unit].conf0.ch0_neg_mode_un = neg_act; } else { - conf0_reg.ch1_pos_mode = pos_mode; - conf0_reg.ch1_neg_mode = neg_mode; + hw->conf_unit[unit].conf0.ch1_pos_mode_un = pos_act; + hw->conf_unit[unit].conf0.ch1_neg_mode_un = neg_act; } - hw->conf_unit[unit].conf0 = conf0_reg; } /** - * @brief Set PCNT channel level mode + * @brief Set PCNT channel level action * * @param hw Peripheral PCNT hardware instance address. * @param unit PCNT unit number * @param channel PCNT channel number - * @param hctrl_mode Counter mode when control signal is high level - * @param lctrl_mode Counter mode when control signal is low level + * @param high_act Counter action when control signal is high level + * @param low_act Counter action when control signal is low level */ -static inline void pcnt_ll_set_level_mode(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_channel_t channel, pcnt_ctrl_mode_t hctrl_mode, pcnt_ctrl_mode_t lctrl_mode) +static inline void pcnt_ll_set_level_action(pcnt_dev_t *hw, uint32_t unit, uint32_t channel, pcnt_channel_level_action_t high_act, pcnt_channel_level_action_t low_act) { - typeof(hw->conf_unit[unit].conf0) conf0_reg = hw->conf_unit[unit].conf0; if (channel == 0) { - conf0_reg.ch0_hctrl_mode = hctrl_mode; - conf0_reg.ch0_lctrl_mode = lctrl_mode; + hw->conf_unit[unit].conf0.ch0_hctrl_mode_un = high_act; + hw->conf_unit[unit].conf0.ch0_lctrl_mode_un = low_act; } else { - conf0_reg.ch1_hctrl_mode = hctrl_mode; - conf0_reg.ch1_lctrl_mode = lctrl_mode; + hw->conf_unit[unit].conf0.ch1_hctrl_mode_un = high_act; + hw->conf_unit[unit].conf0.ch1_lctrl_mode_un = low_act; } - hw->conf_unit[unit].conf0 = conf0_reg; -} - -/** - * @brief Set PCNT counter mode - * - * @param hw Peripheral PCNT hardware instance address. - * @param unit PCNT unit number - * @param channel PCNT channel number - * @param pos_mode Counter mode when detecting positive edge - * @param neg_mode Counter mode when detecting negative edge - * @param hctrl_mode Counter mode when control signal is high level - * @param lctrl_mode Counter mode when control signal is low level - */ -static inline void pcnt_ll_set_mode(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_channel_t channel, pcnt_count_mode_t pos_mode, pcnt_count_mode_t neg_mode, pcnt_ctrl_mode_t hctrl_mode, pcnt_ctrl_mode_t lctrl_mode) -{ - pcnt_ll_set_edge_mode(hw, unit, channel, pos_mode, neg_mode); - pcnt_ll_set_level_mode(hw, unit, channel, hctrl_mode, lctrl_mode); } /** @@ -98,11 +90,13 @@ static inline void pcnt_ll_set_mode(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_chann * * @param hw Peripheral PCNT hardware instance address. * @param unit Pulse Counter unit number - * @param count Pointer to accept counter value + * @return PCNT count value (a signed integer) */ -static inline void pcnt_ll_get_counter_value(pcnt_dev_t *hw, pcnt_unit_t unit, int16_t *count) +static inline int pcnt_ll_get_count(pcnt_dev_t *hw, uint32_t unit) { - *count = (int16_t) hw->cnt_unit[unit].cnt_val; + pcnt_un_cnt_reg_t cnt_reg = hw->cnt_unit[unit]; + int16_t value = cnt_reg.pulse_cnt_un; + return value; } /** @@ -111,69 +105,60 @@ static inline void pcnt_ll_get_counter_value(pcnt_dev_t *hw, pcnt_unit_t unit, i * @param hw Peripheral PCNT hardware instance address. * @param unit PCNT unit number */ -static inline void pcnt_ll_counter_pause(pcnt_dev_t *hw, pcnt_unit_t unit) +static inline void pcnt_ll_stop_count(pcnt_dev_t *hw, uint32_t unit) { - hw->ctrl.val |= BIT(PCNT_CNT_PAUSE_U0_S + (unit * 2)); + hw->ctrl.val |= 1 << (2 * unit + 1); } /** * @brief Resume counting for PCNT counter * * @param hw Peripheral PCNT hardware instance address. - * @param unit PCNT unit number, select from pcnt_unit_t + * @param unit PCNT unit number, select from uint32_t */ -static inline void pcnt_ll_counter_resume(pcnt_dev_t *hw, pcnt_unit_t unit) +static inline void pcnt_ll_start_count(pcnt_dev_t *hw, uint32_t unit) { - hw->ctrl.val &= (~(BIT(PCNT_CNT_PAUSE_U0_S + (unit * 2)))); + hw->ctrl.val &= ~(1 << (2 * unit + 1)); } /** - * @brief Clear and reset PCNT counter value to zero + * @brief Clear PCNT counter value to zero * * @param hw Peripheral PCNT hardware instance address. - * @param unit PCNT unit number, select from pcnt_unit_t + * @param unit PCNT unit number, select from uint32_t */ -static inline void pcnt_ll_counter_clear(pcnt_dev_t *hw, pcnt_unit_t unit) +static inline void pcnt_ll_clear_count(pcnt_dev_t *hw, uint32_t unit) { - uint32_t reset_bit = BIT(PCNT_PULSE_CNT_RST_U0_S + (unit * 2)); - hw->ctrl.val |= reset_bit; - hw->ctrl.val &= ~reset_bit; + hw->ctrl.val |= 1 << (2 * unit); + hw->ctrl.val &= ~(1 << (2 * unit)); } /** * @brief Enable PCNT interrupt for PCNT unit - * @note - * Each Pulse counter unit has five watch point events that share the same interrupt. - * Configure events with pcnt_event_enable() and pcnt_event_disable() + * @note Each PCNT unit has five watch point events that share the same interrupt bit. * * @param hw Peripheral PCNT hardware instance address. - * @param unit PCNT unit number + * @param unit_mask PCNT units mask + * @param enable True to enable interrupt, False to disable interrupt */ -static inline void pcnt_ll_intr_enable(pcnt_dev_t *hw, pcnt_unit_t unit) +static inline void pcnt_ll_enable_intr(pcnt_dev_t *hw, uint32_t unit_mask, bool enable) { - hw->int_ena.val |= BIT(PCNT_CNT_THR_EVENT_U0_INT_ENA_S + unit); -} - -/** - * @brief Disable PCNT interrupt for PCNT unit - * - * @param hw Peripheral PCNT hardware instance address. - * @param unit PCNT unit number - */ -static inline void pcnt_ll_intr_disable(pcnt_dev_t *hw, pcnt_unit_t unit) -{ - hw->int_ena.val &= (~(BIT(PCNT_CNT_THR_EVENT_U0_INT_ENA_S + unit))); + if (enable) { + hw->int_ena.val |= unit_mask; + } else { + hw->int_ena.val &= ~unit_mask; + } } /** * @brief Get PCNT interrupt status * * @param hw Peripheral PCNT hardware instance address. - * @param status Pointer to accept value + * @return Interrupt status word */ -static inline void pcnt_ll_get_intr_status(pcnt_dev_t *hw, uint32_t *status) +__attribute__((always_inline)) static inline uint32_t pcnt_ll_get_intr_status(pcnt_dev_t *hw) { - *status = hw->int_st.val; + return hw->int_st.val; } /** @@ -182,163 +167,241 @@ static inline void pcnt_ll_get_intr_status(pcnt_dev_t *hw, uint32_t *status) * @param hw Peripheral PCNT hardware instance address. * @param status value to clear interrupt status */ -static inline void pcnt_ll_clear_intr_status(pcnt_dev_t *hw, uint32_t status) +__attribute__((always_inline)) static inline void pcnt_ll_clear_intr_status(pcnt_dev_t *hw, uint32_t status) { hw->int_clr.val = status; } /** - * @brief Enable PCNT event of PCNT unit + * @brief Enable PCNT high limit event * * @param hw Peripheral PCNT hardware instance address. * @param unit PCNT unit number - * @param evt_type Watch point event type. - * All enabled events share the same interrupt (one interrupt per pulse counter unit). + * @param enable true to enable, false to disable */ -static inline void pcnt_ll_event_enable(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_evt_type_t evt_type) +static inline void pcnt_ll_enable_high_limit_event(pcnt_dev_t *hw, uint32_t unit, bool enable) { - if (evt_type == PCNT_EVT_L_LIM) { - hw->conf_unit[unit].conf0.thr_l_lim_en = 1; - } else if (evt_type == PCNT_EVT_H_LIM) { - hw->conf_unit[unit].conf0.thr_h_lim_en = 1; - } else if (evt_type == PCNT_EVT_THRES_0) { - hw->conf_unit[unit].conf0.thr_thres0_en = 1; - } else if (evt_type == PCNT_EVT_THRES_1) { - hw->conf_unit[unit].conf0.thr_thres1_en = 1; - } else if (evt_type == PCNT_EVT_ZERO) { - hw->conf_unit[unit].conf0.thr_zero_en = 1; - } + hw->conf_unit[unit].conf0.thr_h_lim_en_un = enable; } /** - * @brief Disable PCNT event of PCNT unit + * @brief Enable PCNT low limit event * * @param hw Peripheral PCNT hardware instance address. * @param unit PCNT unit number - * @param evt_type Watch point event type. - * All enabled events share the same interrupt (one interrupt per pulse counter unit). + * @param enable true to enable, false to disable */ -static inline void pcnt_ll_event_disable(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_evt_type_t evt_type) +static inline void pcnt_ll_enable_low_limit_event(pcnt_dev_t *hw, uint32_t unit, bool enable) { - if (evt_type == PCNT_EVT_L_LIM) { - hw->conf_unit[unit].conf0.thr_l_lim_en = 0; - } else if (evt_type == PCNT_EVT_H_LIM) { - hw->conf_unit[unit].conf0.thr_h_lim_en = 0; - } else if (evt_type == PCNT_EVT_THRES_0) { - hw->conf_unit[unit].conf0.thr_thres0_en = 0; - } else if (evt_type == PCNT_EVT_THRES_1) { - hw->conf_unit[unit].conf0.thr_thres1_en = 0; - } else if (evt_type == PCNT_EVT_ZERO) { - hw->conf_unit[unit].conf0.thr_zero_en = 0; - } + hw->conf_unit[unit].conf0.thr_l_lim_en_un = enable; } /** - * @brief Set PCNT event value of PCNT unit + * @brief Enable PCNT zero cross event * * @param hw Peripheral PCNT hardware instance address. * @param unit PCNT unit number - * @param evt_type Watch point event type. - * All enabled events share the same interrupt (one interrupt per pulse counter unit). - * - * @param value Counter value for PCNT event + * @param enable true to enable, false to disable */ -static inline void pcnt_ll_set_event_value(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t value) +static inline void pcnt_ll_enable_zero_cross_event(pcnt_dev_t *hw, uint32_t unit, bool enable) { - if (evt_type == PCNT_EVT_L_LIM) { - hw->conf_unit[unit].conf2.cnt_l_lim = value; - } else if (evt_type == PCNT_EVT_H_LIM) { - hw->conf_unit[unit].conf2.cnt_h_lim = value; - } else if (evt_type == PCNT_EVT_THRES_0) { - hw->conf_unit[unit].conf1.cnt_thres0 = value; - } else if (evt_type == PCNT_EVT_THRES_1) { - hw->conf_unit[unit].conf1.cnt_thres1 = value; - } + hw->conf_unit[unit].conf0.thr_zero_en_un = enable; } /** - * @brief Get PCNT event value of PCNT unit + * @brief Enable PCNT threshold event * * @param hw Peripheral PCNT hardware instance address. * @param unit PCNT unit number - * @param evt_type Watch point event type. - * All enabled events share the same interrupt (one interrupt per pulse counter unit). - * @param value Pointer to accept counter value for PCNT event + * @param thres Threshold ID + * @param enable true to enable, false to disable */ -static inline void pcnt_ll_get_event_value(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t *value) +static inline void pcnt_ll_enable_thres_event(pcnt_dev_t *hw, uint32_t unit, uint32_t thres, bool enable) { - if (evt_type == PCNT_EVT_L_LIM) { - *value = (int16_t) hw->conf_unit[unit].conf2.cnt_l_lim; - } else if (evt_type == PCNT_EVT_H_LIM) { - *value = (int16_t) hw->conf_unit[unit].conf2.cnt_h_lim; - } else if (evt_type == PCNT_EVT_THRES_0) { - *value = (int16_t) hw->conf_unit[unit].conf1.cnt_thres0; - } else if (evt_type == PCNT_EVT_THRES_1) { - *value = (int16_t) hw->conf_unit[unit].conf1.cnt_thres1; + if (thres == 0) { + hw->conf_unit[unit].conf0.thr_thres0_en_un = enable; } else { - *value = 0; + hw->conf_unit[unit].conf0.thr_thres1_en_un = enable; } } +/** + * @brief Disable all PCNT threshold events + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit unit number + */ +static inline void pcnt_ll_disable_all_events(pcnt_dev_t *hw, uint32_t unit) +{ + hw->conf_unit[unit].conf0.val &= ~(PCNT_LL_EVENT_MASK << 11); +} + +/** + * @brief Set PCNT high limit value + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @param value PCNT high limit value + */ +static inline void pcnt_ll_set_high_limit_value(pcnt_dev_t *hw, uint32_t unit, int value) +{ + pcnt_un_conf2_reg_t conf2_reg = hw->conf_unit[unit].conf2; + conf2_reg.cnt_h_lim_un = value; + hw->conf_unit[unit].conf2 = conf2_reg; +} + +/** + * @brief Set PCNT low limit value + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @param value PCNT low limit value + */ +static inline void pcnt_ll_set_low_limit_value(pcnt_dev_t *hw, uint32_t unit, int value) +{ + pcnt_un_conf2_reg_t conf2_reg = hw->conf_unit[unit].conf2; + conf2_reg.cnt_l_lim_un = value; + hw->conf_unit[unit].conf2 = conf2_reg; +} + +/** + * @brief Set PCNT threshold value + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @param thres Threshold ID + * @param value PCNT threshold value + */ +static inline void pcnt_ll_set_thres_value(pcnt_dev_t *hw, uint32_t unit, uint32_t thres, int value) +{ + pcnt_un_conf1_reg_t conf1_reg = hw->conf_unit[unit].conf1; + if (thres == 0) { + conf1_reg.cnt_thres0_un = value; + } else { + conf1_reg.cnt_thres1_un = value; + } + hw->conf_unit[unit].conf1 = conf1_reg; +} + +/** + * @brief Get PCNT high limit value + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @return PCNT high limit value + */ +static inline int pcnt_ll_get_high_limit_value(pcnt_dev_t *hw, uint32_t unit) +{ + pcnt_un_conf2_reg_t conf2_reg = hw->conf_unit[unit].conf2; + int16_t value = conf2_reg.cnt_h_lim_un; + return value; +} + +/** + * @brief Get PCNT low limit value + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @return PCNT high limit value + */ +static inline int pcnt_ll_get_low_limit_value(pcnt_dev_t *hw, uint32_t unit) +{ + pcnt_un_conf2_reg_t conf2_reg = hw->conf_unit[unit].conf2; + int16_t value = conf2_reg.cnt_l_lim_un; + return value; +} + +/** + * @brief Get PCNT threshold value + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @param thres Threshold ID + * @return PCNT threshold value + */ +static inline int pcnt_ll_get_thres_value(pcnt_dev_t *hw, uint32_t unit, uint32_t thres) +{ + int16_t value; + pcnt_un_conf1_reg_t conf1_reg = hw->conf_unit[unit].conf1; + if (thres == 0) { + value = conf1_reg.cnt_thres0_un; + } else { + value = conf1_reg.cnt_thres1_un; + } + return value; +} + +/** + * @brief Get PCNT unit runtime status + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @return PCNT unit runtime status + */ +static inline uint32_t pcnt_ll_get_unit_status(pcnt_dev_t *hw, uint32_t unit) +{ + return hw->status_unit[unit].val; +} + +/** + * @brief Get PCNT count sign + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @return Count sign + */ +static inline pcnt_unit_count_sign_t pcnt_ll_get_count_sign(pcnt_dev_t *hw, uint32_t unit) +{ + return hw->status_unit[unit].val & 0x03; +} + /** * @brief Get PCNT event status * * @param hw Peripheral PCNT hardware instance address. * @param unit PCNT unit number - * @return event status word + * @return Event status word */ -static inline uint32_t pcnt_ll_get_event_status(pcnt_dev_t *hw, pcnt_unit_t unit) +static inline uint32_t pcnt_ll_get_event_status(pcnt_dev_t *hw, uint32_t unit) { - return hw->status_unit[unit].val; + return hw->status_unit[unit].val >> 2; } /** - * @brief Set PCNT filter value + * @brief Set PCNT glitch filter threshold * * @param hw Peripheral PCNT hardware instance address. * @param unit PCNT unit number * @param filter_val PCNT signal filter value, counter in APB_CLK cycles. * Any pulses lasting shorter than this will be ignored when the filter is enabled. - * @note - * filter_val is a 10-bit value, so the maximum filter_val should be limited to 1023. */ -static inline void pcnt_ll_set_filter_value(pcnt_dev_t *hw, pcnt_unit_t unit, uint16_t filter_val) +static inline void pcnt_ll_set_glitch_filter_thres(pcnt_dev_t *hw, uint32_t unit, uint32_t filter_val) { - hw->conf_unit[unit].conf0.filter_thres = filter_val; + hw->conf_unit[unit].conf0.filter_thres_un = filter_val; } /** - * @brief Get PCNT filter value + * @brief Get PCNT glitch filter threshold * * @param hw Peripheral PCNT hardware instance address. * @param unit PCNT unit number - * @param filter_val Pointer to accept PCNT filter value. + * @return glitch filter threshold */ -static inline void pcnt_ll_get_filter_value(pcnt_dev_t *hw, pcnt_unit_t unit, uint16_t *filter_val) +static inline uint32_t pcnt_ll_get_glitch_filter_thres(pcnt_dev_t *hw, uint32_t unit) { - *filter_val = hw->conf_unit[unit].conf0.filter_thres; + return hw->conf_unit[unit].conf0.filter_thres_un; } /** - * @brief Enable PCNT input filter + * @brief Enable PCNT glitch filter * * @param hw Peripheral PCNT hardware instance address. * @param unit PCNT unit number + * @param enable True to enable the filter, False to disable the filter */ -static inline void pcnt_ll_filter_enable(pcnt_dev_t *hw, pcnt_unit_t unit) +static inline void pcnt_ll_enable_glitch_filter(pcnt_dev_t *hw, uint32_t unit, bool enable) { - hw->conf_unit[unit].conf0.filter_en = 1; -} - -/** - * @brief Disable PCNT input filter - * - * @param hw Peripheral PCNT hardware instance address. - * @param unit PCNT unit number - */ -static inline void pcnt_ll_filter_disable(pcnt_dev_t *hw, pcnt_unit_t unit) -{ - hw->conf_unit[unit].conf0.filter_en = 0; + hw->conf_unit[unit].conf0.filter_en_un = enable; } #ifdef __cplusplus diff --git a/components/hal/esp32s2/include/hal/rmt_ll.h b/components/hal/esp32s2/include/hal/rmt_ll.h index 0354afc766..ba73eaa2b7 100644 --- a/components/hal/esp32s2/include/hal/rmt_ll.h +++ b/components/hal/esp32s2/include/hal/rmt_ll.h @@ -1,26 +1,22 @@ -// 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + #pragma once #include #include +#include "hal/misc.h" #include "soc/rmt_struct.h" #ifdef __cplusplus extern "C" { #endif +#define RMT_LL_MAX_LOOP_COUNT (1023)/*!< Max loop count that hardware is supported */ + #define RMT_LL_HW_BASE (&RMT) #define RMT_LL_MEM_BASE (&RMTMEM) @@ -126,23 +122,23 @@ static inline uint32_t rmt_ll_rx_get_mem_blocks(rmt_dev_t *dev, uint32_t channel static inline void rmt_ll_tx_set_channel_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div) { - dev->conf_ch[channel].conf0.div_cnt = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->conf_ch[channel].conf0, div_cnt, div); } static inline void rmt_ll_rx_set_channel_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div) { - dev->conf_ch[channel].conf0.div_cnt = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->conf_ch[channel].conf0, div_cnt, div); } static inline uint32_t rmt_ll_tx_get_channel_clock_div(rmt_dev_t *dev, uint32_t channel) { - uint32_t div = dev->conf_ch[channel].conf0.div_cnt; + uint32_t div = HAL_FORCE_READ_U32_REG_FIELD(dev->conf_ch[channel].conf0, div_cnt); return div == 0 ? 256 : div; } static inline uint32_t rmt_ll_rx_get_channel_clock_div(rmt_dev_t *dev, uint32_t channel) { - uint32_t div = dev->conf_ch[channel].conf0.div_cnt; + uint32_t div = HAL_FORCE_READ_U32_REG_FIELD(dev->conf_ch[channel].conf0, div_cnt); return div == 0 ? 256 : div; } @@ -153,12 +149,12 @@ static inline void rmt_ll_tx_enable_pingpong(rmt_dev_t *dev, uint32_t channel, b static inline void rmt_ll_rx_set_idle_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres) { - dev->conf_ch[channel].conf0.idle_thres = thres; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->conf_ch[channel].conf0, idle_thres, thres); } static inline uint32_t rmt_ll_rx_get_idle_thres(rmt_dev_t *dev, uint32_t channel) { - return dev->conf_ch[channel].conf0.idle_thres; + return HAL_FORCE_READ_U32_REG_FIELD(dev->conf_ch[channel].conf0, idle_thres); } static inline void rmt_ll_rx_set_mem_owner(rmt_dev_t *dev, uint32_t channel, uint8_t owner) @@ -219,7 +215,7 @@ static inline void rmt_ll_rx_enable_filter(rmt_dev_t *dev, uint32_t channel, boo static inline void rmt_ll_rx_set_filter_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres) { - dev->conf_ch[channel].conf1.rx_filter_thres = thres; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->conf_ch[channel].conf1, rx_filter_thres, thres); } static inline void rmt_ll_tx_enable_idle(rmt_dev_t *dev, uint32_t channel, bool enable) @@ -415,14 +411,14 @@ static inline void rmt_ll_rx_set_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t static inline void rmt_ll_tx_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks) { - *high_ticks = dev->carrier_duty_ch[channel].high; - *low_ticks = dev->carrier_duty_ch[channel].low; + *high_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->carrier_duty_ch[channel], high); + *low_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->carrier_duty_ch[channel], low); } static inline void rmt_ll_rx_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks) { - *high_ticks = dev->ch_rx_carrier_rm[channel].carrier_high_thres_ch; - *low_ticks = dev->ch_rx_carrier_rm[channel].carrier_low_thres_ch; + *high_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->ch_rx_carrier_rm[channel], carrier_high_thres_ch); + *low_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->ch_rx_carrier_rm[channel], carrier_low_thres_ch); } static inline void rmt_ll_tx_enable_carrier_modulation(rmt_dev_t *dev, uint32_t channel, bool enable) diff --git a/components/hal/esp32s2/include/hal/rtc_io_ll.h b/components/hal/esp32s2/include/hal/rtc_io_ll.h index c519f70030..cdd19466b6 100644 --- a/components/hal/esp32s2/include/hal/rtc_io_ll.h +++ b/components/hal/esp32s2/include/hal/rtc_io_ll.h @@ -22,6 +22,8 @@ #include #include "soc/rtc_io_periph.h" +#include "soc/rtc_io_struct.h" +#include "soc/sens_struct.h" #include "hal/rtc_io_types.h" #include "hal/gpio_types.h" diff --git a/components/hal/esp32s2/include/hal/rwdt_ll.h b/components/hal/esp32s2/include/hal/rwdt_ll.h index 681c2fdf4f..f3cc3c0cc4 100644 --- a/components/hal/esp32s2/include/hal/rwdt_ll.h +++ b/components/hal/esp32s2/include/hal/rwdt_ll.h @@ -23,8 +23,10 @@ extern "C" { #include #include +#include "hal/misc.h" #include "hal/wdt_types.h" #include "soc/rtc_cntl_periph.h" +#include "soc/rtc_cntl_struct.h" #include "soc/efuse_reg.h" #include "esp_attr.h" @@ -239,7 +241,7 @@ FORCE_INLINE_ATTR void rwdt_ll_set_chip_reset_en(rtc_cntl_dev_t* hw, bool enable */ FORCE_INLINE_ATTR void rwdt_ll_set_chip_reset_width(rtc_cntl_dev_t *hw, uint32_t width) { - hw->wdt_config0.chip_reset_width = width; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->wdt_config0, chip_reset_width, width); } /** diff --git a/components/hal/esp32s2/include/hal/sigmadelta_ll.h b/components/hal/esp32s2/include/hal/sigmadelta_ll.h index e06464a5ff..20406e19fd 100644 --- a/components/hal/esp32s2/include/hal/sigmadelta_ll.h +++ b/components/hal/esp32s2/include/hal/sigmadelta_ll.h @@ -22,7 +22,9 @@ #pragma once #include +#include "hal/misc.h" #include "soc/sigmadelta_periph.h" +#include "soc/gpio_sd_struct.h" #include "hal/sigmadelta_types.h" #ifdef __cplusplus @@ -53,7 +55,7 @@ static inline void sigmadelta_ll_set_en(gpio_sd_dev_t *hw, bool en) */ static inline void sigmadelta_ll_set_duty(gpio_sd_dev_t *hw, sigmadelta_channel_t channel, int8_t duty) { - hw->channel[channel].duty = duty; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], duty, (uint32_t)duty); } /** @@ -65,7 +67,7 @@ static inline void sigmadelta_ll_set_duty(gpio_sd_dev_t *hw, sigmadelta_channel_ */ static inline void sigmadelta_ll_set_prescale(gpio_sd_dev_t *hw, sigmadelta_channel_t channel, uint8_t prescale) { - hw->channel[channel].prescale = prescale; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], prescale, prescale); } #ifdef __cplusplus diff --git a/components/hal/esp32s2/include/hal/spi_ll.h b/components/hal/esp32s2/include/hal/spi_ll.h index 855036d05d..b81b36c53b 100644 --- a/components/hal/esp32s2/include/hal/spi_ll.h +++ b/components/hal/esp32s2/include/hal/spi_ll.h @@ -27,9 +27,11 @@ #include "esp_types.h" #include "esp_attr.h" #include "soc/spi_periph.h" +#include "soc/spi_struct.h" #include "soc/lldesc.h" #include "hal/assert.h" #include "hal/misc.h" +#include "hal/spi_types.h" #ifdef __cplusplus extern "C" { @@ -39,6 +41,10 @@ extern "C" { #define SPI_LL_DMA_FIFO_RST_MASK (SPI_AHBM_RST | SPI_AHBM_FIFO_RST) /// Interrupt not used. Don't use in app. #define SPI_LL_UNUSED_INT_MASK (SPI_INT_TRANS_DONE_EN | SPI_INT_WR_DMA_DONE_EN | SPI_INT_RD_DMA_DONE_EN | SPI_INT_WR_BUF_DONE_EN | SPI_INT_RD_BUF_DONE_EN) +/// These 2 masks together will set SPI transaction to one line mode +#define SPI_LL_ONE_LINE_CTRL_MASK (SPI_FREAD_OCT | SPI_FREAD_QUAD | SPI_FREAD_DUAL | SPI_FCMD_OCT | \ + SPI_FCMD_QUAD | SPI_FCMD_DUAL | SPI_FADDR_OCT | SPI_FADDR_QUAD | SPI_FADDR_DUAL) +#define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_OCT | SPI_FWRITE_QUAD | SPI_FWRITE_DUAL) /// Swap the bit order to its correct place to send #define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len)) /// This is the expected clock frequency @@ -55,15 +61,6 @@ typedef uint32_t spi_ll_clock_val_t; //On ESP32-S2 and earlier chips, DMA registers are part of SPI registers. So set the registers of SPI peripheral to control DMA. typedef spi_dev_t spi_dma_dev_t; -/** IO modes supported by the master. */ -typedef enum { - SPI_LL_IO_MODE_NORMAL = 0, ///< 1-bit mode for all phases - SPI_LL_IO_MODE_DIO, ///< 2-bit mode for address and data phases, 1-bit mode for command phase - SPI_LL_IO_MODE_DUAL, ///< 2-bit mode for data phases only, 1-bit mode for command and address phases - SPI_LL_IO_MODE_QIO, ///< 4-bit mode for address and data phases, 1-bit mode for command phase - SPI_LL_IO_MODE_QUAD, ///< 4-bit mode for data phases only, 1-bit mode for command and address phases -} spi_ll_io_mode_t; - /// Type definition of all supported interrupts typedef enum { SPI_LL_INTR_TRANS_DONE = BIT(0), ///< A transaction has done @@ -348,14 +345,16 @@ static inline void spi_ll_read_buffer(spi_dev_t *hw, uint8_t *buffer_to_rcv, siz static inline void spi_ll_read_buffer_byte(spi_dev_t *hw, int byte_addr, uint8_t *out_data, int len) { - while (len>0) { - uint32_t word = hw->data_buf[byte_addr/4]; + while (len > 0) { + uint32_t word = hw->data_buf[byte_addr / 4]; int offset = byte_addr % 4; int copy_len = 4 - offset; - if (copy_len > len) copy_len = len; + if (copy_len > len) { + copy_len = len; + } - memcpy(out_data, ((uint8_t*)&word)+offset, copy_len); + memcpy(out_data, ((uint8_t *)&word) + offset, copy_len); byte_addr += copy_len; out_data += copy_len; len -= copy_len; @@ -373,10 +372,14 @@ static inline void spi_ll_write_buffer_byte(spi_dev_t *hw, int byte_addr, uint8_ int offset = byte_addr % 4; int copy_len = 4 - offset; - if (copy_len > len) copy_len = len; + if (copy_len > len) { + copy_len = len; + } //read-modify-write - if (copy_len != 4) word = hw->data_buf[byte_addr / 4]; + if (copy_len != 4) { + word = hw->data_buf[byte_addr / 4]; + } memcpy(((uint8_t *)&word) + offset, data, copy_len); hw->data_buf[byte_addr / 4] = word; @@ -508,41 +511,27 @@ static inline void spi_ll_set_sio_mode(spi_dev_t *hw, int sio_mode) } /** - * Configure the io mode for the master to work at. + * Configure the SPI transaction line mode for the master to use. * - * @param hw Beginning address of the peripheral registers. - * @param io_mode IO mode to work at, see ``spi_ll_io_mode_t``. + * @param hw Beginning address of the peripheral registers. + * @param line_mode SPI transaction line mode to use, see ``spi_line_mode_t``. */ -static inline void spi_ll_master_set_io_mode(spi_dev_t *hw, spi_ll_io_mode_t io_mode) +static inline void spi_ll_master_set_line_mode(spi_dev_t *hw, spi_line_mode_t line_mode) { - if (io_mode == SPI_LL_IO_MODE_DIO || io_mode == SPI_LL_IO_MODE_DUAL) { - hw->ctrl.fcmd_dual= (io_mode == SPI_LL_IO_MODE_DIO) ? 1 : 0; - hw->ctrl.faddr_dual= (io_mode == SPI_LL_IO_MODE_DIO) ? 1 : 0; - hw->ctrl.fread_dual=1; - hw->user.fwrite_dual=1; - hw->ctrl.fcmd_quad = 0; - hw->ctrl.faddr_quad = 0; - hw->ctrl.fread_quad = 0; - hw->user.fwrite_quad = 0; - } else if (io_mode == SPI_LL_IO_MODE_QIO || io_mode == SPI_LL_IO_MODE_QUAD) { - hw->ctrl.fcmd_quad = (io_mode == SPI_LL_IO_MODE_QIO) ? 1 : 0; - hw->ctrl.faddr_quad = (io_mode == SPI_LL_IO_MODE_QIO) ? 1 : 0; - hw->ctrl.fread_quad=1; - hw->user.fwrite_quad=1; - hw->ctrl.fcmd_dual = 0; - hw->ctrl.faddr_dual = 0; - hw->ctrl.fread_dual = 0; - hw->user.fwrite_dual = 0; - } else { - hw->ctrl.fcmd_dual = 0; - hw->ctrl.faddr_dual = 0; - hw->ctrl.fread_dual = 0; - hw->user.fwrite_dual = 0; - hw->ctrl.fcmd_quad = 0; - hw->ctrl.faddr_quad = 0; - hw->ctrl.fread_quad = 0; - hw->user.fwrite_quad = 0; - } + hw->ctrl.val &= ~SPI_LL_ONE_LINE_CTRL_MASK; + hw->user.val &= ~SPI_LL_ONE_LINE_USER_MASK; + hw->ctrl.fcmd_dual = (line_mode.cmd_lines == 2); + hw->ctrl.fcmd_quad = (line_mode.cmd_lines == 4); + hw->ctrl.fcmd_oct = (line_mode.cmd_lines == 8); + hw->ctrl.faddr_dual = (line_mode.addr_lines == 2); + hw->ctrl.faddr_quad = (line_mode.addr_lines == 4); + hw->ctrl.faddr_oct = (line_mode.addr_lines == 8); + hw->ctrl.fread_dual = (line_mode.data_lines == 2); + hw->user.fwrite_dual = (line_mode.data_lines == 2); + hw->ctrl.fread_quad = (line_mode.data_lines == 4); + hw->user.fwrite_quad = (line_mode.data_lines == 4); + hw->ctrl.fread_oct = (line_mode.data_lines == 8); + hw->user.fwrite_oct = (line_mode.data_lines == 8); } static inline void spi_ll_slave_set_seg_mode(spi_dev_t *hw, bool seg_trans) @@ -572,7 +561,8 @@ static inline void spi_ll_master_select_cs(spi_dev_t *hw, int cs_id) * @param hw Beginning address of the peripheral registers. * @param keep_active if 0 don't keep CS activated, else keep CS activated */ -static inline void spi_ll_master_keep_cs(spi_dev_t *hw, int keep_active) { +static inline void spi_ll_master_keep_cs(spi_dev_t *hw, int keep_active) +{ hw->misc.cs_keep_active = (keep_active != 0) ? 1 : 0; } @@ -745,7 +735,7 @@ static inline void spi_ll_set_miso_delay(spi_dev_t *hw, int delay_mode, int dela static inline void spi_ll_set_dummy(spi_dev_t *hw, int dummy_n) { hw->user.usr_dummy = dummy_n ? 1 : 0; - hw->user1.usr_dummy_cyclelen = dummy_n - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user1, usr_dummy_cyclelen, dummy_n - 1); } /** @@ -906,13 +896,13 @@ static inline void spi_ll_set_command(spi_dev_t *hw, uint16_t cmd, int cmdlen, b { if (lsbfirst) { // The output command start from bit0 to bit 15, kept as is. - hw->user2.usr_command_value = cmd; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user2, usr_command_value, cmd); } else { /* Output command will be sent from bit 7 to 0 of command_value, and * then bit 15 to 8 of the same register field. Shift and swap to send * more straightly. */ - hw->user2.usr_command_value = HAL_SPI_SWAP_DATA_TX(cmd, cmdlen); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user2, usr_command_value, HAL_SPI_SWAP_DATA_TX(cmd, cmdlen)); } } @@ -985,35 +975,35 @@ static inline uint32_t spi_ll_slave_get_rcv_bitlen(spi_dev_t *hw) item(SPI_LL_INTR_CMDA, dma_int_ena.cmda, dma_int_raw.cmda, dma_int_clr.cmda=1) -static inline void spi_ll_enable_intr(spi_dev_t* hw, spi_ll_intr_t intr_mask) +static inline void spi_ll_enable_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask) { #define ENA_INTR(intr_bit, en_reg, ...) if (intr_mask & (intr_bit)) hw->en_reg = 1; FOR_EACH_ITEM(ENA_INTR, INTR_LIST); #undef ENA_INTR } -static inline void spi_ll_disable_intr(spi_dev_t* hw, spi_ll_intr_t intr_mask) +static inline void spi_ll_disable_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask) { #define DIS_INTR(intr_bit, en_reg, ...) if (intr_mask & (intr_bit)) hw->en_reg = 0; FOR_EACH_ITEM(DIS_INTR, INTR_LIST); #undef DIS_INTR } -static inline void spi_ll_set_intr(spi_dev_t* hw, spi_ll_intr_t intr_mask) +static inline void spi_ll_set_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask) { #define SET_INTR(intr_bit, _, st_reg, ...) if (intr_mask & (intr_bit)) hw->st_reg = 1; FOR_EACH_ITEM(SET_INTR, INTR_LIST); #undef SET_INTR } -static inline void spi_ll_clear_intr(spi_dev_t* hw, spi_ll_intr_t intr_mask) +static inline void spi_ll_clear_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask) { #define CLR_INTR(intr_bit, _, __, clr_reg) if (intr_mask & (intr_bit)) hw->clr_reg; FOR_EACH_ITEM(CLR_INTR, INTR_LIST); #undef CLR_INTR } -static inline bool spi_ll_get_intr(spi_dev_t* hw, spi_ll_intr_t intr_mask) +static inline bool spi_ll_get_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask) { #define GET_INTR(intr_bit, _, st_reg, ...) if (intr_mask & (intr_bit) && hw->st_reg) return true; FOR_EACH_ITEM(GET_INTR, INTR_LIST); @@ -1067,7 +1057,7 @@ static inline void spi_ll_enable_int(spi_dev_t *hw) /*------------------------------------------------------------------------------ * Slave HD *----------------------------------------------------------------------------*/ -static inline void spi_ll_slave_hd_set_len_cond(spi_dev_t* hw, spi_ll_trans_len_cond_t cond_mask) +static inline void spi_ll_slave_hd_set_len_cond(spi_dev_t *hw, spi_ll_trans_len_cond_t cond_mask) { hw->slv_rd_byte.rdbuf_bytelen_en = (cond_mask & SPI_LL_TRANS_LEN_COND_RDBUF) ? 1 : 0; hw->slv_rd_byte.wrbuf_bytelen_en = (cond_mask & SPI_LL_TRANS_LEN_COND_WRBUF) ? 1 : 0; @@ -1075,14 +1065,14 @@ static inline void spi_ll_slave_hd_set_len_cond(spi_dev_t* hw, spi_ll_trans_len_ hw->slv_rd_byte.wrdma_bytelen_en = (cond_mask & SPI_LL_TRANS_LEN_COND_WRDMA) ? 1 : 0; } -static inline int spi_ll_slave_get_rx_byte_len(spi_dev_t* hw) +static inline int spi_ll_slave_get_rx_byte_len(spi_dev_t *hw) { return hw->slv_rd_byte.data_bytelen; } -static inline uint32_t spi_ll_slave_hd_get_last_addr(spi_dev_t* hw) +static inline uint32_t spi_ll_slave_hd_get_last_addr(spi_dev_t *hw) { - return hw->slave1.last_addr; + return HAL_FORCE_READ_U32_REG_FIELD(hw->slave1, last_addr); } /*------------------------------------------------------------------------------ diff --git a/components/hal/esp32s2/include/hal/spimem_flash_ll.h b/components/hal/esp32s2/include/hal/spimem_flash_ll.h index b04020eb51..2bbd6e90ff 100644 --- a/components/hal/esp32s2/include/hal/spimem_flash_ll.h +++ b/components/hal/esp32s2/include/hal/spimem_flash_ll.h @@ -28,6 +28,7 @@ #include #include "soc/spi_periph.h" +#include "soc/spi_mem_struct.h" #include "hal/spi_types.h" #include "hal/spi_flash_types.h" @@ -167,7 +168,7 @@ static inline void spimem_flash_ll_set_read_sus_status(spi_mem_dev_t *dev, uint3 */ static inline void spimem_flash_ll_suspend_cmd_setup(spi_mem_dev_t *dev, uint32_t sus_cmd) { - dev->flash_sus_ctrl.flash_pes_command = sus_cmd; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_ctrl, flash_pes_command, sus_cmd); } /** @@ -179,7 +180,7 @@ static inline void spimem_flash_ll_suspend_cmd_setup(spi_mem_dev_t *dev, uint32_ */ static inline void spimem_flash_ll_resume_cmd_setup(spi_mem_dev_t *dev, uint32_t res_cmd) { - dev->flash_sus_ctrl.flash_per_command = res_cmd; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_ctrl, flash_per_command, res_cmd); } /** @@ -226,7 +227,7 @@ static inline void spimem_flash_ll_res_check_sus_setup(spi_mem_dev_t *dev, bool */ static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool auto_waiti) { - dev->flash_waiti_ctrl.waiti_cmd = 0x05; // Set the command to send, to fetch flash status reg value. + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_waiti_ctrl, waiti_cmd, 0x05); // Set the command to send, to fetch flash status reg value. dev->flash_waiti_ctrl.waiti_en = auto_waiti; // enable auto wait-idle function. } @@ -516,7 +517,7 @@ static inline void spimem_flash_ll_set_usr_address(spi_mem_dev_t *dev, uint32_t static inline void spimem_flash_ll_set_dummy(spi_mem_dev_t *dev, uint32_t dummy_n) { dev->user.usr_dummy = dummy_n ? 1 : 0; - dev->user1.usr_dummy_cyclelen = dummy_n - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user1, usr_dummy_cyclelen, dummy_n - 1); } /** diff --git a/components/hal/esp32s2/include/hal/systimer_ll.h b/components/hal/esp32s2/include/hal/systimer_ll.h index f1c0ef0adf..6066674243 100644 --- a/components/hal/esp32s2/include/hal/systimer_ll.h +++ b/components/hal/esp32s2/include/hal/systimer_ll.h @@ -135,6 +135,11 @@ __attribute__((always_inline)) static inline void systimer_ll_set_alarm_period(s dev->target_conf[alarm_id].target_period = period; } +__attribute__((always_inline)) static inline uint32_t systimer_ll_get_alarm_period(systimer_dev_t *dev, uint32_t alarm_id) +{ + return dev->target_conf[alarm_id].target_period; +} + __attribute__((always_inline)) static inline void systimer_ll_apply_alarm_value(systimer_dev_t *dev, uint32_t alarm_id) { (void)dev; diff --git a/components/hal/esp32s2/include/hal/timer_ll.h b/components/hal/esp32s2/include/hal/timer_ll.h index 522b58f425..59921e2364 100644 --- a/components/hal/esp32s2/include/hal/timer_ll.h +++ b/components/hal/esp32s2/include/hal/timer_ll.h @@ -22,7 +22,9 @@ extern "C" { #endif #include +#include "hal/misc.h" #include "soc/timer_periph.h" +#include "soc/timer_group_struct.h" #include "hal/timer_types.h" #include "hal/assert.h" @@ -48,10 +50,10 @@ static inline void timer_ll_set_divider(timg_dev_t *hw, timer_idx_t timer_num, u if (divider >= 65536) { divider = 0; } - int timer_en = hw->hw_timer[timer_num].config.enable; - hw->hw_timer[timer_num].config.enable = 0; - hw->hw_timer[timer_num].config.divider = divider; - hw->hw_timer[timer_num].config.enable = timer_en; + int timer_en = hw->hw_timer[timer_num].config.tx_en; + hw->hw_timer[timer_num].config.tx_en = 0; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->hw_timer[timer_num].config, tx_divider, divider); + hw->hw_timer[timer_num].config.tx_en = timer_en; } /** @@ -65,7 +67,7 @@ static inline void timer_ll_set_divider(timg_dev_t *hw, timer_idx_t timer_num, u */ static inline void timer_ll_get_divider(timg_dev_t *hw, timer_idx_t timer_num, uint32_t *divider) { - uint32_t d = hw->hw_timer[timer_num].config.divider; + uint32_t d = HAL_FORCE_READ_U32_REG_FIELD(hw->hw_timer[timer_num].config, tx_divider); if (d == 0) { d = 65536; } else if (d == 1) { @@ -85,9 +87,9 @@ static inline void timer_ll_get_divider(timg_dev_t *hw, timer_idx_t timer_num, u */ static inline void timer_ll_set_counter_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t load_val) { - hw->hw_timer[timer_num].load_high = (uint32_t) (load_val >> 32); - hw->hw_timer[timer_num].load_low = (uint32_t) load_val; - hw->hw_timer[timer_num].reload = 1; + hw->hw_timer[timer_num].loadhi.tx_load_hi = (uint32_t) (load_val >> 32); + hw->hw_timer[timer_num].loadlo.tx_load_lo = (uint32_t) load_val; + hw->hw_timer[timer_num].load.tx_load = 1; } /** @@ -101,9 +103,9 @@ static inline void timer_ll_set_counter_value(timg_dev_t *hw, timer_idx_t timer_ */ FORCE_INLINE_ATTR void timer_ll_get_counter_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t *timer_val) { - hw->hw_timer[timer_num].update.update = 1; - while (hw->hw_timer[timer_num].update.update) {} - *timer_val = ((uint64_t) hw->hw_timer[timer_num].cnt_high << 32) | (hw->hw_timer[timer_num].cnt_low); + hw->hw_timer[timer_num].update.tx_update = 1; + while (hw->hw_timer[timer_num].update.tx_update) {} + *timer_val = ((uint64_t) hw->hw_timer[timer_num].hi.tx_hi << 32) | (hw->hw_timer[timer_num].lo.tx_lo); } /** @@ -117,7 +119,7 @@ FORCE_INLINE_ATTR void timer_ll_get_counter_value(timg_dev_t *hw, timer_idx_t ti */ static inline void timer_ll_set_counter_increase(timg_dev_t *hw, timer_idx_t timer_num, bool increase_en) { - hw->hw_timer[timer_num].config.increase = increase_en; + hw->hw_timer[timer_num].config.tx_increase = increase_en; } /** @@ -132,7 +134,7 @@ static inline void timer_ll_set_counter_increase(timg_dev_t *hw, timer_idx_t tim */ static inline bool timer_ll_get_counter_increase(timg_dev_t *hw, timer_idx_t timer_num) { - return hw->hw_timer[timer_num].config.increase; + return hw->hw_timer[timer_num].config.tx_increase; } /** @@ -146,7 +148,7 @@ static inline bool timer_ll_get_counter_increase(timg_dev_t *hw, timer_idx_t tim */ FORCE_INLINE_ATTR void timer_ll_set_counter_enable(timg_dev_t *hw, timer_idx_t timer_num, bool counter_en) { - hw->hw_timer[timer_num].config.enable = counter_en; + hw->hw_timer[timer_num].config.tx_en = counter_en; } /** @@ -161,7 +163,7 @@ FORCE_INLINE_ATTR void timer_ll_set_counter_enable(timg_dev_t *hw, timer_idx_t t */ static inline bool timer_ll_get_counter_enable(timg_dev_t *hw, timer_idx_t timer_num) { - return hw->hw_timer[timer_num].config.enable; + return hw->hw_timer[timer_num].config.tx_en; } /** @@ -175,7 +177,7 @@ static inline bool timer_ll_get_counter_enable(timg_dev_t *hw, timer_idx_t timer */ static inline void timer_ll_set_auto_reload(timg_dev_t *hw, timer_idx_t timer_num, bool auto_reload_en) { - hw->hw_timer[timer_num].config.autoreload = auto_reload_en; + hw->hw_timer[timer_num].config.tx_autoreload = auto_reload_en; } /** @@ -190,7 +192,7 @@ static inline void timer_ll_set_auto_reload(timg_dev_t *hw, timer_idx_t timer_nu */ FORCE_INLINE_ATTR bool timer_ll_get_auto_reload(timg_dev_t *hw, timer_idx_t timer_num) { - return hw->hw_timer[timer_num].config.autoreload; + return hw->hw_timer[timer_num].config.tx_autoreload; } /** @@ -204,8 +206,8 @@ FORCE_INLINE_ATTR bool timer_ll_get_auto_reload(timg_dev_t *hw, timer_idx_t time */ FORCE_INLINE_ATTR void timer_ll_set_alarm_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t alarm_value) { - hw->hw_timer[timer_num].alarm_high = (uint32_t) (alarm_value >> 32); - hw->hw_timer[timer_num].alarm_low = (uint32_t) alarm_value; + hw->hw_timer[timer_num].alarmhi.tx_alarm_hi = (uint32_t) (alarm_value >> 32); + hw->hw_timer[timer_num].alarmlo.tx_alarm_lo = (uint32_t) alarm_value; } /** @@ -219,7 +221,7 @@ FORCE_INLINE_ATTR void timer_ll_set_alarm_value(timg_dev_t *hw, timer_idx_t time */ static inline void timer_ll_get_alarm_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t *alarm_value) { - *alarm_value = ((uint64_t) hw->hw_timer[timer_num].alarm_high << 32) | (hw->hw_timer[timer_num].alarm_low); + *alarm_value = ((uint64_t) hw->hw_timer[timer_num].alarmhi.tx_alarm_hi << 32) | (hw->hw_timer[timer_num].alarmlo.tx_alarm_lo); } /** @@ -233,7 +235,7 @@ static inline void timer_ll_get_alarm_value(timg_dev_t *hw, timer_idx_t timer_nu */ FORCE_INLINE_ATTR void timer_ll_set_alarm_enable(timg_dev_t *hw, timer_idx_t timer_num, bool alarm_en) { - hw->hw_timer[timer_num].config.alarm_en = alarm_en; + hw->hw_timer[timer_num].config.tx_alarm_en = alarm_en; } /** @@ -248,7 +250,7 @@ FORCE_INLINE_ATTR void timer_ll_set_alarm_enable(timg_dev_t *hw, timer_idx_t tim */ static inline bool timer_ll_get_alarm_enable(timg_dev_t *hw, timer_idx_t timer_num) { - return hw->hw_timer[timer_num].config.alarm_en; + return hw->hw_timer[timer_num].config.tx_alarm_en; } /** @@ -261,8 +263,8 @@ static inline bool timer_ll_get_alarm_enable(timg_dev_t *hw, timer_idx_t timer_n */ FORCE_INLINE_ATTR void timer_ll_intr_enable(timg_dev_t *hw, timer_idx_t timer_num) { - hw->int_ena.val |= BIT(timer_num); - hw->hw_timer[timer_num].config.level_int_en = 1; + hw->int_ena_timers.val |= BIT(timer_num); + hw->hw_timer[timer_num].config.tx_level_int_en = 1; } /** @@ -275,8 +277,8 @@ FORCE_INLINE_ATTR void timer_ll_intr_enable(timg_dev_t *hw, timer_idx_t timer_nu */ FORCE_INLINE_ATTR void timer_ll_intr_disable(timg_dev_t *hw, timer_idx_t timer_num) { - hw->int_ena.val &= (~BIT(timer_num)); - hw->hw_timer[timer_num].config.level_int_en = 0; + hw->int_ena_timers.val &= (~BIT(timer_num)); + hw->hw_timer[timer_num].config.tx_level_int_en = 0; } /** @@ -289,7 +291,7 @@ FORCE_INLINE_ATTR void timer_ll_intr_disable(timg_dev_t *hw, timer_idx_t timer_n */ FORCE_INLINE_ATTR void timer_ll_clear_intr_status(timg_dev_t *hw, timer_idx_t timer_num) { - hw->int_clr.val |= BIT(timer_num); + hw->int_clr_timers.val |= BIT(timer_num); } /** @@ -302,7 +304,7 @@ FORCE_INLINE_ATTR void timer_ll_clear_intr_status(timg_dev_t *hw, timer_idx_t ti */ FORCE_INLINE_ATTR void timer_ll_get_intr_status(timg_dev_t *hw, uint32_t *intr_status) { - *intr_status = hw->int_st.val & 0x03; + *intr_status = hw->int_st_timers.val & 0x03; } /** @@ -316,7 +318,7 @@ FORCE_INLINE_ATTR void timer_ll_get_intr_status(timg_dev_t *hw, uint32_t *intr_s FORCE_INLINE_ATTR void timer_ll_get_intr_raw_status(timer_group_t group_num, uint32_t *intr_raw_status) { timg_dev_t *hw = TIMER_LL_GET_HW(group_num); - *intr_raw_status = hw->int_raw.val & 0x03; + *intr_raw_status = hw->int_raw_timers.val & 0x03; } /** @@ -330,7 +332,7 @@ FORCE_INLINE_ATTR void timer_ll_get_intr_raw_status(timer_group_t group_num, uin */ static inline void timer_ll_set_level_int_enable(timg_dev_t *hw, timer_idx_t timer_num, bool level_int_en) { - hw->hw_timer[timer_num].config.level_int_en = level_int_en; + hw->hw_timer[timer_num].config.tx_level_int_en = level_int_en; } /** @@ -345,7 +347,7 @@ static inline void timer_ll_set_level_int_enable(timg_dev_t *hw, timer_idx_t tim */ static inline bool timer_ll_get_level_int_enable(timg_dev_t *hw, timer_idx_t timer_num) { - return hw->hw_timer[timer_num].config.level_int_en; + return hw->hw_timer[timer_num].config.tx_level_int_en; } /** @@ -359,7 +361,7 @@ static inline bool timer_ll_get_level_int_enable(timg_dev_t *hw, timer_idx_t tim */ static inline void timer_ll_set_edge_int_enable(timg_dev_t *hw, timer_idx_t timer_num, bool edge_int_en) { - hw->hw_timer[timer_num].config.edge_int_en = edge_int_en; + hw->hw_timer[timer_num].config.tx_edge_int_en = edge_int_en; } /** @@ -374,7 +376,7 @@ static inline void timer_ll_set_edge_int_enable(timg_dev_t *hw, timer_idx_t time */ static inline bool timer_ll_get_edge_int_enable(timg_dev_t *hw, timer_idx_t timer_num) { - return hw->hw_timer[timer_num].config.edge_int_en; + return hw->hw_timer[timer_num].config.tx_edge_int_en; } /** @@ -386,7 +388,7 @@ static inline bool timer_ll_get_edge_int_enable(timg_dev_t *hw, timer_idx_t time */ static inline uint32_t timer_ll_get_intr_status_reg(timg_dev_t *hw) { - return (uint32_t) & (hw->int_st.val); + return (uint32_t) & (hw->int_st_timers.val); } static inline uint32_t timer_ll_get_intr_mask_bit(timg_dev_t *hw, timer_idx_t timer_num) @@ -404,7 +406,7 @@ static inline uint32_t timer_ll_get_intr_mask_bit(timg_dev_t *hw, timer_idx_t ti */ static inline void timer_ll_set_use_xtal(timg_dev_t *hw, timer_idx_t timer_num, bool use_xtal_en) { - hw->hw_timer[timer_num].config.use_xtal = use_xtal_en; + hw->hw_timer[timer_num].config.tx_use_xtal = use_xtal_en; } /** @@ -418,7 +420,7 @@ static inline void timer_ll_set_use_xtal(timg_dev_t *hw, timer_idx_t timer_num, */ static inline bool timer_ll_get_use_xtal(timg_dev_t *hw, timer_idx_t timer_num) { - return hw->hw_timer[timer_num].config.use_xtal; + return hw->hw_timer[timer_num].config.tx_use_xtal; } #ifdef __cplusplus diff --git a/components/hal/esp32s2/include/hal/touch_sensor_ll.h b/components/hal/esp32s2/include/hal/touch_sensor_ll.h index 2fa8227153..30c3cc1014 100644 --- a/components/hal/esp32s2/include/hal/touch_sensor_ll.h +++ b/components/hal/esp32s2/include/hal/touch_sensor_ll.h @@ -24,8 +24,12 @@ #include #include +#include "hal/misc.h" #include "soc/touch_sensor_periph.h" #include "soc/soc_caps.h" +#include "soc/sens_struct.h" +#include "soc/rtc_cntl_struct.h" +#include "soc/rtc_io_struct.h" #include "hal/touch_sensor_types.h" #ifdef __cplusplus @@ -47,9 +51,9 @@ extern "C" { static inline void touch_ll_set_meas_times(uint16_t meas_time) { //The times of charge and discharge in each measure process of touch channels. - RTCCNTL.touch_ctrl1.touch_meas_num = meas_time; + HAL_FORCE_MODIFY_U32_REG_FIELD(RTCCNTL.touch_ctrl1, touch_meas_num, meas_time); //the waiting cycles (in 8MHz) between TOUCH_START and TOUCH_XPD - RTCCNTL.touch_ctrl2.touch_xpd_wait = SOC_TOUCH_PAD_MEASURE_WAIT_MAX; //wait volt stable + HAL_FORCE_MODIFY_U32_REG_FIELD(RTCCNTL.touch_ctrl2, touch_xpd_wait, SOC_TOUCH_PAD_MEASURE_WAIT_MAX); //wait volt stable } /** @@ -59,7 +63,7 @@ static inline void touch_ll_set_meas_times(uint16_t meas_time) */ static inline void touch_ll_get_measure_times(uint16_t *meas_time) { - *meas_time = RTCCNTL.touch_ctrl1.touch_meas_num; + *meas_time = HAL_FORCE_READ_U32_REG_FIELD(RTCCNTL.touch_ctrl1, touch_meas_num); } /** @@ -73,7 +77,7 @@ static inline void touch_ll_get_measure_times(uint16_t *meas_time) static inline void touch_ll_set_sleep_time(uint16_t sleep_time) { // touch sensor sleep cycle Time = sleep_cycle / RTC_SLOW_CLK(90k) - RTCCNTL.touch_ctrl1.touch_sleep_cycles = sleep_time; + HAL_FORCE_MODIFY_U32_REG_FIELD(RTCCNTL.touch_ctrl1, touch_sleep_cycles, sleep_time); } /** @@ -83,7 +87,7 @@ static inline void touch_ll_set_sleep_time(uint16_t sleep_time) */ static inline void touch_ll_get_sleep_time(uint16_t *sleep_time) { - *sleep_time = RTCCNTL.touch_ctrl1.touch_sleep_cycles; + *sleep_time = HAL_FORCE_READ_U32_REG_FIELD(RTCCNTL.touch_ctrl1, touch_sleep_cycles); } /** @@ -990,7 +994,7 @@ static inline void touch_ll_proximity_get_channel_num(touch_pad_t prox_pad[]) */ static inline void touch_ll_proximity_set_meas_times(uint32_t times) { - RTCCNTL.touch_approach.touch_approach_meas_time = times; + HAL_FORCE_MODIFY_U32_REG_FIELD(RTCCNTL.touch_approach, touch_approach_meas_time, times); } /** @@ -1000,7 +1004,7 @@ static inline void touch_ll_proximity_set_meas_times(uint32_t times) */ static inline void touch_ll_proximity_get_meas_times(uint32_t *times) { - *times = RTCCNTL.touch_approach.touch_approach_meas_time; + *times = HAL_FORCE_READ_U32_REG_FIELD(RTCCNTL.touch_approach, touch_approach_meas_time); } /** @@ -1011,11 +1015,11 @@ static inline void touch_ll_proximity_get_meas_times(uint32_t *times) static inline void touch_ll_proximity_read_meas_cnt(touch_pad_t touch_num, uint32_t *cnt) { if (SENS.sar_touch_conf.touch_approach_pad0 == touch_num) { - *cnt = SENS.sar_touch_appr_status.touch_approach_pad0_cnt; + *cnt = HAL_FORCE_READ_U32_REG_FIELD(SENS.sar_touch_appr_status, touch_approach_pad0_cnt); } else if (SENS.sar_touch_conf.touch_approach_pad1 == touch_num) { - *cnt = SENS.sar_touch_appr_status.touch_approach_pad1_cnt; + *cnt = HAL_FORCE_READ_U32_REG_FIELD(SENS.sar_touch_appr_status, touch_approach_pad1_cnt); } else if (SENS.sar_touch_conf.touch_approach_pad2 == touch_num) { - *cnt = SENS.sar_touch_appr_status.touch_approach_pad2_cnt; + *cnt = HAL_FORCE_READ_U32_REG_FIELD(SENS.sar_touch_appr_status, touch_approach_pad2_cnt); } } @@ -1163,7 +1167,7 @@ static inline void touch_ll_sleep_read_debounce(uint32_t *debounce) */ static inline void touch_ll_sleep_read_proximity_cnt(uint32_t *approach_cnt) { - *approach_cnt = SENS.sar_touch_appr_status.touch_slp_approach_cnt; + *approach_cnt = HAL_FORCE_READ_U32_REG_FIELD(SENS.sar_touch_appr_status, touch_slp_approach_cnt); } /** diff --git a/components/hal/esp32s2/include/hal/twai_ll.h b/components/hal/esp32s2/include/hal/twai_ll.h index 106f3adc6f..7a04c18aef 100644 --- a/components/hal/esp32s2/include/hal/twai_ll.h +++ b/components/hal/esp32s2/include/hal/twai_ll.h @@ -31,6 +31,7 @@ extern "C" { #include "hal/misc.h" #include "hal/twai_types.h" #include "soc/twai_periph.h" +#include "soc/twai_struct.h" /* ------------------------- Defines and Typedefs --------------------------- */ @@ -399,7 +400,7 @@ static inline void twai_ll_clear_err_code_cap(twai_dev_t *hw) */ static inline void twai_ll_set_err_warn_lim(twai_dev_t *hw, uint32_t ewl) { - hw->error_warning_limit_reg.ewl = ewl; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->error_warning_limit_reg, ewl, ewl); } /** @@ -439,7 +440,7 @@ static inline uint32_t twai_ll_get_rec(twai_dev_t *hw) */ static inline void twai_ll_set_rec(twai_dev_t *hw, uint32_t rec) { - hw->rx_error_counter_reg.rxerr = rec; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_error_counter_reg, rxerr, rec); } /* ------------------------ TX Error Count Register ------------------------- */ @@ -467,7 +468,7 @@ static inline uint32_t twai_ll_get_tec(twai_dev_t *hw) */ static inline void twai_ll_set_tec(twai_dev_t *hw, uint32_t tec) { - hw->tx_error_counter_reg.txerr = tec; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_error_counter_reg, txerr, tec); } /* ---------------------- Acceptance Filter Registers ----------------------- */ @@ -486,8 +487,8 @@ static inline void twai_ll_set_acc_filter(twai_dev_t* hw, uint32_t code, uint32_ uint32_t code_swapped = HAL_SWAP32(code); uint32_t mask_swapped = HAL_SWAP32(mask); for (int i = 0; i < 4; i++) { - hw->acceptance_filter.acr[i].byte = ((code_swapped >> (i * 8)) & 0xFF); - hw->acceptance_filter.amr[i].byte = ((mask_swapped >> (i * 8)) & 0xFF); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->acceptance_filter.acr[i], byte, ((code_swapped >> (i * 8)) & 0xFF)); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->acceptance_filter.amr[i], byte, ((mask_swapped >> (i * 8)) & 0xFF)); } hw->mode_reg.afm = single_filter; } @@ -522,7 +523,7 @@ static inline void twai_ll_get_rx_buffer(twai_dev_t *hw, twai_ll_frame_buffer_t { //Copy RX buffer registers into frame for (int i = 0; i < 13; i++) { - rx_frame->bytes[i] = hw->tx_rx_buffer[i].byte; + rx_frame->bytes[i] = HAL_FORCE_READ_U32_REG_FIELD(hw->tx_rx_buffer[i], byte); } } @@ -652,14 +653,14 @@ static inline void twai_ll_set_clkout(twai_dev_t *hw, uint32_t divider) { if (divider >= 2 && divider <= 490) { hw->clock_divider_reg.co = 0; - hw->clock_divider_reg.cd = (divider / 2) - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clock_divider_reg, cd, (divider / 2) - 1); } else if (divider == 1) { //Setting the divider reg to max value (255) means a divider of 1 hw->clock_divider_reg.co = 0; - hw->clock_divider_reg.cd = 255; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clock_divider_reg, cd, 255); } else { hw->clock_divider_reg.co = 1; - hw->clock_divider_reg.cd = 0; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clock_divider_reg, cd, 0); } } diff --git a/components/hal/esp32s2/include/hal/uart_ll.h b/components/hal/esp32s2/include/hal/uart_ll.h index 15b96f8bed..9309d3b8f2 100644 --- a/components/hal/esp32s2/include/hal/uart_ll.h +++ b/components/hal/esp32s2/include/hal/uart_ll.h @@ -17,8 +17,11 @@ #pragma once + +#include "hal/misc.h" #include "hal/uart_types.h" #include "soc/uart_periph.h" +#include "soc/uart_struct.h" #include "esp_attr.h" #ifdef __cplusplus @@ -403,7 +406,7 @@ FORCE_INLINE_ATTR void uart_ll_set_tx_idle_num(uart_dev_t *hw, uint32_t idle_num FORCE_INLINE_ATTR void uart_ll_tx_break(uart_dev_t *hw, uint32_t break_num) { if(break_num > 0) { - hw->idle_conf.tx_brk_num = break_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->idle_conf, tx_brk_num, break_num); hw->conf0.txd_brk = 1; } else { hw->conf0.txd_brk = 0; @@ -470,8 +473,8 @@ FORCE_INLINE_ATTR void uart_ll_set_sw_flow_ctrl(uart_dev_t *hw, uart_sw_flowctrl hw->flow_conf.sw_flow_con_en = 1; hw->swfc_conf1.xon_threshold = flow_ctrl->xon_thrd; hw->swfc_conf0.xoff_threshold = flow_ctrl->xoff_thrd; - hw->swfc_conf1.xon_char = flow_ctrl->xon_char; - hw->swfc_conf0.xoff_char = flow_ctrl->xoff_char; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->swfc_conf1, xon_char, flow_ctrl->xon_char); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->swfc_conf0, xoff_char, flow_ctrl->xoff_char); } else { hw->flow_conf.sw_flow_con_en = 0; hw->flow_conf.xonoff_del = 0; @@ -493,11 +496,11 @@ FORCE_INLINE_ATTR void uart_ll_set_sw_flow_ctrl(uart_dev_t *hw, uart_sw_flowctrl */ FORCE_INLINE_ATTR void uart_ll_set_at_cmd_char(uart_dev_t *hw, uart_at_cmd_t *cmd_char) { - hw->at_cmd_char.data = cmd_char->cmd_char; - hw->at_cmd_char.char_num = cmd_char->char_num; - hw->at_cmd_postcnt.post_idle_num = cmd_char->post_idle; - hw->at_cmd_precnt.pre_idle_num = cmd_char->pre_idle; - hw->at_cmd_gaptout.rx_gap_tout = cmd_char->gap_tout; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_char, data, cmd_char->cmd_char); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_char, char_num, cmd_char->char_num); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_postcnt, post_idle_num, cmd_char->post_idle); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_precnt, pre_idle_num, cmd_char->pre_idle); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_gaptout, rx_gap_tout, cmd_char->gap_tout); } /** @@ -679,8 +682,8 @@ FORCE_INLINE_ATTR void uart_ll_set_mode(uart_dev_t *hw, uart_mode_t mode) */ FORCE_INLINE_ATTR void uart_ll_get_at_cmd_char(uart_dev_t *hw, uint8_t *cmd_char, uint8_t *char_num) { - *cmd_char = hw->at_cmd_char.data; - *char_num = hw->at_cmd_char.char_num; + *cmd_char = HAL_FORCE_READ_U32_REG_FIELD(hw->at_cmd_char, data); + *char_num = HAL_FORCE_READ_U32_REG_FIELD(hw->at_cmd_char, char_num); } /** diff --git a/components/hal/esp32s2/include/hal/usb_phy_ll.h b/components/hal/esp32s2/include/hal/usb_phy_ll.h new file mode 100644 index 0000000000..ed175cf9ce --- /dev/null +++ b/components/hal/esp32s2/include/hal/usb_phy_ll.h @@ -0,0 +1,83 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "soc/soc.h" +#include "soc/system_reg.h" +#include "soc/usb_wrap_struct.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Configures the internal PHY for USB_OTG + * + * @param hw Start address of the USB Wrap registers + */ +static inline void usb_phy_ll_int_otg_enable(usb_wrap_dev_t *hw) +{ + //Enable internal PHY + hw->otg_conf.pad_enable = 1; + hw->otg_conf.phy_sel = 0; +} + +/** + * @brief Configures the external PHY for USB_OTG + * + * @param hw Start address of the USB Wrap registers + */ +static inline void usb_phy_ll_ext_otg_enable(usb_wrap_dev_t *hw) +{ + //Enable external PHY + hw->otg_conf.phy_sel = 1; +} + +/** + * @brief Configures port loads for the internal PHY + * + * @param hw Start address of the USB Wrap registers + * @param dp_pu D+ pullup load + * @param dp_pd D+ pulldown load + * @param dm_pu D- pullup load + * @param dm_pd D- pulldown load + */ +static inline void usb_phy_ll_int_load_conf(usb_wrap_dev_t *hw, bool dp_pu, bool dp_pd, bool dm_pu, bool dm_pd) +{ + usb_wrap_otg_conf_reg_t conf = hw->otg_conf; + conf.pad_pull_override = 1; + conf.dp_pullup = dp_pu; + conf.dp_pulldown = dp_pd; + conf.dm_pullup = dm_pu; + conf.dm_pulldown = dm_pd; + hw->otg_conf = conf; +} + +/** + * @brief Enable the internal PHY's test mode + * + * @param hw Start address of the USB Wrap registers + * @param en Whether to enable the internal PHY's test mode + */ +static inline void usb_phy_ll_int_enable_test_mode(usb_wrap_dev_t *hw, bool en) +{ + if (en) { + // Clear USB_WRAP_TEST_CONF_REG + hw->test_conf.val = 0; + // Set USB test pad oen + hw->test_conf.test_usb_wrap_oe = 1; + // Enable USB test mode + hw->test_conf.test_enable = 1; + } else { + hw->test_conf.test_enable = 0; + } +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32s2/include/hal/xt_wdt_ll.h b/components/hal/esp32s2/include/hal/xt_wdt_ll.h new file mode 100644 index 0000000000..65b36253e5 --- /dev/null +++ b/components/hal/esp32s2/include/hal/xt_wdt_ll.h @@ -0,0 +1,101 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// The LL layer for xtal32k WDT register operations. +// Note that most of the register operations in this layer are non-atomic operations. + +#pragma once + +#include +#include "soc/rtc_cntl_periph.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define XT_WDT_LL_XTAL32_DEAD_INTR_MASK RTC_CNTL_XTAL32K_DEAD_INT_ST_M + +/** + * @brief Enable the XT_WDT + * + * @param hw Start address of the peripheral registers. + */ +inline void xt_wdt_ll_enable(rtc_cntl_dev_t *hw, bool enable) +{ + hw->ext_xtl_conf.xtal32k_wdt_en = enable; +} + +/** + * @brief Check if the XT_WDT is enabled + * + * @param hw Start address of the peripheral registers. + * @return True if XT WDT is enabled + */ +inline bool xt_wdt_ll_check_if_enabled(rtc_cntl_dev_t *hw) +{ + return (hw->ext_xtl_conf.xtal32k_wdt_en) ? true : false; +} + +/** + * @brief Set the watchdog timeout value + * + * @param hw Start address of the peripheral registers. + * @param timeout timeout value in RTC_CLK cycles + */ +inline void xt_wdt_ll_set_timeout(rtc_cntl_dev_t *hw, uint8_t timeout) +{ + hw->xtal32k_conf.xtal32k_wdt_timeout = timeout; +} + + +/** + * @brief Reset the XT_WDT + * + * @param hw Start address of the peripheral registers. + */ +inline void xt_wdt_ll_reset(rtc_cntl_dev_t *hw) +{ + hw->ext_xtl_conf.xtal32k_wdt_reset = 1; + hw->ext_xtl_conf.xtal32k_wdt_reset = 0; +} + + +/** + * @brief Set the backup clock value + * + * @param hw Start address of the peripheral registers. + * @param backup_clk_val Backup clock value, see TRM for definition + */ +inline void xt_wdt_ll_set_backup_clk_factor(rtc_cntl_dev_t *hw, uint32_t backup_clk_val) +{ + hw->xtal32k_clk_factor = backup_clk_val; +} + +/** + * @brief Enable the auto-backup clock feature + * + * @param hw Start address of the peripheral registers. + * @param enable True - enable, False - disable + */ +inline void xt_wdt_ll_auto_backup_enable(rtc_cntl_dev_t *hw, bool enable) +{ + hw->ext_xtl_conf.xtal32k_auto_backup = enable; +} + +/** + * @brief Enable the timeout interrupt + * + * @param hw Start address of the peripheral registers. + * @param enable True - enable, False - disable + */ +inline void xt_wdt_ll_intr_enable(rtc_cntl_dev_t *hw, bool enable) +{ + hw->int_ena.rtc_xtal32k_dead = enable; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32s3/hmac_hal.c b/components/hal/esp32s3/hmac_hal.c new file mode 100644 index 0000000000..ef2b2c5e12 --- /dev/null +++ b/components/hal/esp32s3/hmac_hal.c @@ -0,0 +1,74 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "hal/hmac_hal.h" +#include "hal/hmac_ll.h" + +void hmac_hal_start(void) +{ + hmac_ll_wait_idle(); + hmac_ll_start(); +} + +uint32_t hmac_hal_configure(hmac_hal_output_t config, uint32_t key_id) +{ + hmac_ll_wait_idle(); + hmac_ll_config_output(config); + hmac_ll_config_hw_key_id(key_id); + hmac_ll_config_finish(); + hmac_ll_wait_idle(); + + uint32_t conf_error = hmac_ll_query_config_error(); + if (conf_error) { + hmac_ll_calc_finish(); + return 1; + } else if (config != HMAC_OUTPUT_USER) { + // In "downstream" mode, this will be the last hmac operation. Make sure HMAC is ready for + // the other peripheral. + hmac_ll_wait_idle(); + } + + return 0; +} + +void hmac_hal_write_one_block_512(const void *block) +{ + hmac_ll_wait_idle(); + hmac_ll_write_block_512(block); + hmac_ll_wait_idle(); + hmac_ll_msg_one_block(); +} + +void hmac_hal_write_block_512(const void *block) +{ + hmac_ll_wait_idle(); + hmac_ll_write_block_512(block); +} + +void hmac_hal_next_block_padding(void) +{ + hmac_ll_wait_idle(); + hmac_ll_msg_padding(); +} + +void hmac_hal_next_block_normal(void) +{ + hmac_ll_wait_idle(); + hmac_ll_msg_continue(); +} + +void hmac_hal_read_result_256(void *result) +{ + hmac_ll_wait_idle(); + hmac_ll_read_result_256(result); + hmac_ll_calc_finish(); +} + +void hmac_hal_clean(void) +{ + hmac_ll_wait_idle(); + hmac_ll_clean(); +} diff --git a/components/hal/esp32s3/include/hal/adc_ll.h b/components/hal/esp32s3/include/hal/adc_ll.h index 58302045e5..778e9d8d78 100644 --- a/components/hal/esp32s3/include/hal/adc_ll.h +++ b/components/hal/esp32s3/include/hal/adc_ll.h @@ -15,12 +15,16 @@ #include #include +#include "regi2c_ctrl.h" + #include "soc/adc_periph.h" #include "hal/adc_types.h" #include "soc/apb_saradc_struct.h" +#include "soc/sens_struct.h" #include "soc/apb_saradc_reg.h" #include "soc/rtc_cntl_struct.h" #include "soc/rtc_cntl_reg.h" +#include "hal/misc.h" #ifdef __cplusplus extern "C" { @@ -109,11 +113,11 @@ typedef struct { static inline void adc_ll_digi_set_fsm_time(uint32_t rst_wait, uint32_t start_wait, uint32_t standby_wait) { // Internal FSM reset wait time - APB_SARADC.fsm_wait.rstb_wait = rst_wait; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.fsm_wait, rstb_wait, rst_wait); // Internal FSM start wait time - APB_SARADC.fsm_wait.xpd_wait = start_wait; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.fsm_wait, xpd_wait, start_wait); // Internal FSM standby wait time - APB_SARADC.fsm_wait.standby_wait = standby_wait; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.fsm_wait, standby_wait, standby_wait); } /** @@ -125,8 +129,12 @@ static inline void adc_ll_digi_set_fsm_time(uint32_t rst_wait, uint32_t start_wa */ static inline void adc_ll_set_sample_cycle(uint32_t sample_cycle) { - //To be added including RTC_CNTR reg and functions - abort(); + /* Should be called before writing I2C registers. */ + SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_PU_M); + CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, I2C_SAR_M); + SET_PERI_REG_MASK(ANA_CONFIG2_REG, ANA_SAR_CFG2_M); + + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_SAMPLE_CYCLE_ADDR, sample_cycle); } /** @@ -138,7 +146,7 @@ static inline void adc_ll_set_sample_cycle(uint32_t sample_cycle) static inline void adc_ll_digi_set_clk_div(uint32_t div) { /* ADC clock divided from digital controller clock clk */ - APB_SARADC.ctrl.sar_clk_div = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.ctrl, sar_clk_div, div); } /** @@ -149,7 +157,7 @@ static inline void adc_ll_digi_set_clk_div(uint32_t div) */ static inline void adc_ll_digi_set_convert_limit_num(uint32_t meas_num) { - APB_SARADC.ctrl2.max_meas_num = meas_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.ctrl2, max_meas_num, meas_num); } /** @@ -307,7 +315,7 @@ static inline void adc_ll_digi_trigger_disable(void) */ static inline void adc_ll_digi_controller_clk_div(uint32_t div_num, uint32_t div_b, uint32_t div_a) { - APB_SARADC.apb_adc_clkm_conf.clkm_div_num = div_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.apb_adc_clkm_conf, clkm_div_num, div_num); APB_SARADC.apb_adc_clkm_conf.clkm_div_b = div_b; APB_SARADC.apb_adc_clkm_conf.clkm_div_a = div_a; } @@ -450,7 +458,7 @@ static inline void adc_ll_digi_monitor_enable(adc_ll_num_t adc_n, bool enable) */ static inline void adc_ll_digi_dma_set_eof_num(uint32_t num) { - APB_SARADC.dma_conf.apb_adc_eof_num = num; + HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.dma_conf, apb_adc_eof_num, num); } /** @@ -701,19 +709,47 @@ static inline void adc_ll_disable_sleep_controller(void) SENS.sar_meas2_mux.sar2_rtc_force = 0; } +/** + * @brief Set common calibration configuration. Should be shared with other parts (PWDET). + */ +static inline void adc_ll_calibration_init(adc_ll_num_t adc_n) +{ + if (adc_n == ADC_NUM_1) { + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_DREF_ADDR, 4); + } else { + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_DREF_ADDR, 4); + } +} + /** * Configure the registers for ADC calibration. You need to call the ``adc_ll_calibration_finish`` interface to resume after calibration. * - * @note Different ADC units and different attenuation options use different calibration data (initial data). - * * @param adc_n ADC index number. - * @param channel adc channel number. + * @param channel Not used * @param internal_gnd true: Disconnect from the IO port and use the internal GND as the calibration voltage. * false: Use IO external voltage as calibration voltage. */ static inline void adc_ll_calibration_prepare(adc_ll_num_t adc_n, adc_channel_t channel, bool internal_gnd) { - abort(); + /* Should be called before writing I2C registers. */ + SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_PU_M); + CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, I2C_SAR_M); + SET_PERI_REG_MASK(ANA_CONFIG2_REG, ANA_SAR_CFG2_M); + + /* Enable/disable internal connect GND (for calibration). */ + if (adc_n == ADC_NUM_1) { + if (internal_gnd) { + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_ENCAL_GND_ADDR, 1); + } else { + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_ENCAL_GND_ADDR, 0); + } + } else { //adc_n == ADC_NUM_2 + if (internal_gnd) { + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_ENCAL_GND_ADDR, 1); + } else { + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_ENCAL_GND_ADDR, 0); + } + } } /** @@ -723,7 +759,11 @@ static inline void adc_ll_calibration_prepare(adc_ll_num_t adc_n, adc_channel_t */ static inline void adc_ll_calibration_finish(adc_ll_num_t adc_n) { - abort(); + if (adc_n == ADC_NUM_1) { + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_ENCAL_GND_ADDR, 0); + } else { //adc_n == ADC_NUM_2 + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_ENCAL_GND_ADDR, 0); + } } /** @@ -735,7 +775,15 @@ static inline void adc_ll_calibration_finish(adc_ll_num_t adc_n) */ static inline void adc_ll_set_calibration_param(adc_ll_num_t adc_n, uint32_t param) { - abort(); + uint8_t msb = param >> 8; + uint8_t lsb = param & 0xFF; + if (adc_n == ADC_NUM_1) { + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_HIGH_ADDR, msb); + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_LOW_ADDR, lsb); + } else { + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_INITIAL_CODE_HIGH_ADDR, msb); + REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_INITIAL_CODE_LOW_ADDR, lsb); + } } /** @@ -765,9 +813,9 @@ static inline void adc_ll_vref_output(adc_ll_num_t adc, adc_channel_t channel, b static inline void adc_ll_set_sar_clk_div(adc_ll_num_t adc_n, uint32_t div) { if (adc_n == ADC_NUM_1) { - SENS.sar_reader1_ctrl.sar1_clk_div = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_reader1_ctrl, sar1_clk_div, div); } else { // adc_n == ADC_NUM_2 - SENS.sar_reader2_ctrl.sar2_clk_div = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_reader2_ctrl, sar2_clk_div, div); } } @@ -828,7 +876,7 @@ static inline void adc_ll_rtc_disable_channel(adc_ll_num_t adc_n) static inline void adc_ll_rtc_start_convert(adc_ll_num_t adc_n, int channel) { if (adc_n == ADC_NUM_1) { - while (SENS.sar_slave_addr1.meas_status != 0); + while (HAL_FORCE_READ_U32_REG_FIELD(SENS.sar_slave_addr1, meas_status) != 0) {} SENS.sar_meas1_ctrl2.meas1_start_sar = 0; SENS.sar_meas1_ctrl2.meas1_start_sar = 1; } else { // adc_n == ADC_NUM_2 @@ -867,9 +915,9 @@ static inline int adc_ll_rtc_get_convert_value(adc_ll_num_t adc_n) { int ret_val = 0; if (adc_n == ADC_NUM_1) { - ret_val = SENS.sar_meas1_ctrl2.meas1_data_sar; + ret_val = HAL_FORCE_READ_U32_REG_FIELD(SENS.sar_meas1_ctrl2, meas1_data_sar); } else { // adc_n == ADC_NUM_2 - ret_val = SENS.sar_meas2_ctrl2.meas2_data_sar; + ret_val = HAL_FORCE_READ_U32_REG_FIELD(SENS.sar_meas2_ctrl2, meas2_data_sar); } return ret_val; } @@ -1013,6 +1061,22 @@ static inline void adc_ll_set_atten(adc_ll_num_t adc_n, adc_channel_t channel, a } } +/** + * Get the attenuation of a particular channel on ADCn. + * + * @param adc_n ADC unit. + * @param channel ADCn channel number. + * @return atten The attenuation option. + */ +static inline adc_atten_t adc_ll_get_atten(adc_ll_num_t adc_n, adc_channel_t channel) +{ + if (adc_n == ADC_NUM_1) { + return (adc_atten_t)((SENS.sar_atten1 >> (channel * 2)) & 0x3); + } else { + return (adc_atten_t)((SENS.sar_atten2 >> (channel * 2)) & 0x3); + } +} + static inline uint32_t adc_ll_adc1_read(void) { //On ESP32S3, valid data width is 12-bit diff --git a/components/hal/esp32s3/include/hal/aes_ll.h b/components/hal/esp32s3/include/hal/aes_ll.h index dbc831f038..e18c44e58e 100644 --- a/components/hal/esp32s3/include/hal/aes_ll.h +++ b/components/hal/esp32s3/include/hal/aes_ll.h @@ -1,4 +1,4 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// Copyright 2020-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. @@ -15,6 +15,7 @@ #pragma once #include +#include #include "soc/hwcrypto_reg.h" #include "hal/aes_types.h" @@ -39,16 +40,17 @@ typedef enum { * @param key Key to be written to the AES hardware * @param key_word_len Number of words in the key * - * @return volatile number of bytes written to hardware, used for fault injection check + * @return Number of bytes written to hardware, used for fault injection check */ static inline uint8_t aes_ll_write_key(const uint8_t *key, size_t key_word_len) { /* This variable is used for fault injection checks, so marked volatile to avoid optimisation */ volatile uint8_t key_in_hardware = 0; - uint32_t *key_words = (uint32_t *)key; - + /* Memcpy to avoid potential unaligned access */ + uint32_t key_word; for (int i = 0; i < key_word_len; i++) { - REG_WRITE(AES_KEY_BASE + i * 4, *(key_words + i)); + memcpy(&key_word, key + 4 * i, 4); + REG_WRITE(AES_KEY_BASE + i * 4, key_word); key_in_hardware += 4; } return key_in_hardware; @@ -76,22 +78,12 @@ static inline void aes_ll_set_mode(int mode, uint8_t key_bytes) */ static inline void aes_ll_write_block(const void *input) { - const uint32_t *input_words = (const uint32_t *)input; - uint32_t i0, i1, i2, i3; + uint32_t input_word; - /* Storing i0,i1,i2,i3 in registers not an array - helps a lot with optimisations at -Os level */ - i0 = input_words[0]; - REG_WRITE(AES_TEXT_IN_BASE, i0); - - i1 = input_words[1]; - REG_WRITE(AES_TEXT_IN_BASE + 4, i1); - - i2 = input_words[2]; - REG_WRITE(AES_TEXT_IN_BASE + 8, i2); - - i3 = input_words[3]; - REG_WRITE(AES_TEXT_IN_BASE + 12, i3); + for (int i = 0; i < AES_BLOCK_WORDS; i++) { + memcpy(&input_word, (uint8_t*)input + 4 * i, 4); + REG_WRITE(AES_TEXT_IN_BASE + i * 4, input_word); + } } /** @@ -101,11 +93,13 @@ static inline void aes_ll_write_block(const void *input) */ static inline void aes_ll_read_block(void *output) { - uint32_t *output_words = (uint32_t *)output; + uint32_t output_word; const size_t REG_WIDTH = sizeof(uint32_t); for (size_t i = 0; i < AES_BLOCK_WORDS; i++) { - output_words[i] = REG_READ(AES_TEXT_OUT_BASE + (i * REG_WIDTH)); + output_word = REG_READ(AES_TEXT_OUT_BASE + (i * REG_WIDTH)); + /* Memcpy to avoid potential unaligned access */ + memcpy( (uint8_t*)output + i * 4, &output_word, sizeof(output_word)); } } @@ -179,11 +173,13 @@ static inline void aes_ll_set_num_blocks(size_t num_blocks) */ static inline void aes_ll_set_iv(const uint8_t *iv) { - uint32_t *iv_words = (uint32_t *)iv; uint32_t *reg_addr_buf = (uint32_t *)(AES_IV_BASE); + uint32_t iv_word; for (int i = 0; i < IV_WORDS; i++ ) { - REG_WRITE(®_addr_buf[i], iv_words[i]); + /* Memcpy to avoid potential unaligned access */ + memcpy(&iv_word, iv + 4 * i, sizeof(iv_word)); + REG_WRITE(®_addr_buf[i], iv_word); } } @@ -192,11 +188,13 @@ static inline void aes_ll_set_iv(const uint8_t *iv) */ static inline void aes_ll_read_iv(uint8_t *iv) { - uint32_t *iv_words = (uint32_t *)iv; + uint32_t iv_word; const size_t REG_WIDTH = sizeof(uint32_t); for (size_t i = 0; i < IV_WORDS; i++) { - iv_words[i] = REG_READ(AES_IV_BASE + (i * REG_WIDTH)); + iv_word = REG_READ(AES_IV_BASE + (i * REG_WIDTH)); + /* Memcpy to avoid potential unaligned access */ + memcpy(iv + i * 4, &iv_word, sizeof(iv_word)); } } diff --git a/components/hal/esp32s3/include/hal/clk_gate_ll.h b/components/hal/esp32s3/include/hal/clk_gate_ll.h index 2068963ee5..01f684732f 100644 --- a/components/hal/esp32s3/include/hal/clk_gate_ll.h +++ b/components/hal/esp32s3/include/hal/clk_gate_ll.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -99,6 +91,10 @@ static inline uint32_t periph_ll_get_clk_en_mask(periph_module_t periph) return SYSTEM_CRYPTO_SHA_CLK_EN; case PERIPH_RSA_MODULE: return SYSTEM_CRYPTO_RSA_CLK_EN; + case PERIPH_HMAC_MODULE: + return SYSTEM_CRYPTO_HMAC_CLK_EN; + case PERIPH_DS_MODULE: + return SYSTEM_CRYPTO_DS_CLK_EN; default: return 0; } @@ -106,9 +102,6 @@ static inline uint32_t periph_ll_get_clk_en_mask(periph_module_t periph) static inline uint32_t periph_ll_get_rst_en_mask(periph_module_t periph, bool enable) { - - (void)enable; // unused - switch (periph) { case PERIPH_RMT_MODULE: return SYSTEM_RMT_RST; @@ -162,6 +155,10 @@ static inline uint32_t periph_ll_get_rst_en_mask(periph_module_t periph, bool en return SYSTEM_RST_EN_DEDICATED_GPIO; case PERIPH_GDMA_MODULE: return SYSTEM_DMA_RST; + case PERIPH_HMAC_MODULE: + return SYSTEM_CRYPTO_HMAC_RST; + case PERIPH_DS_MODULE: + return SYSTEM_CRYPTO_DS_RST; case PERIPH_AES_MODULE: if (enable == true) { // Clear reset on digital signature, otherwise AES unit is held in reset also. @@ -207,6 +204,8 @@ static uint32_t periph_ll_get_clk_en_reg(periph_module_t periph) case PERIPH_SDMMC_MODULE: case PERIPH_LCD_CAM_MODULE: case PERIPH_GDMA_MODULE: + case PERIPH_HMAC_MODULE: + case PERIPH_DS_MODULE: case PERIPH_AES_MODULE: case PERIPH_SHA_MODULE: case PERIPH_RSA_MODULE: @@ -230,8 +229,10 @@ static uint32_t periph_ll_get_rst_en_reg(periph_module_t periph) return SYSTEM_CORE_RST_EN_REG; case PERIPH_UART2_MODULE: case PERIPH_SDMMC_MODULE: - case PERIPH_GDMA_MODULE: case PERIPH_LCD_CAM_MODULE: + case PERIPH_GDMA_MODULE: + case PERIPH_HMAC_MODULE: + case PERIPH_DS_MODULE: case PERIPH_AES_MODULE: case PERIPH_SHA_MODULE: case PERIPH_RSA_MODULE: diff --git a/components/hal/esp32s3/include/hal/ds_ll.h b/components/hal/esp32s3/include/hal/ds_ll.h new file mode 100644 index 0000000000..f5ae99074c --- /dev/null +++ b/components/hal/esp32s3/include/hal/ds_ll.h @@ -0,0 +1,162 @@ +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include + +#include "soc/hwcrypto_reg.h" +#include "soc/soc_caps.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static inline void ds_ll_start(void) +{ + REG_WRITE(DS_SET_START_REG, 1); +} + +/** + * @brief Wait until DS peripheral has finished any outstanding operation. + */ +static inline bool ds_ll_busy(void) +{ + return (REG_READ(DS_QUERY_BUSY_REG) > 0) ? true : false; +} + +/** + * @brief Busy wait until the hardware is ready. + */ +static inline void ds_ll_wait_busy(void) +{ + while (ds_ll_busy()); +} + +/** + * @brief In case of a key error, check what caused it. + */ +static inline ds_key_check_t ds_ll_key_error_source(void) +{ + uint32_t key_error = REG_READ(DS_QUERY_KEY_WRONG_REG); + if (key_error == 0) { + return DS_NO_KEY_INPUT; + } else { + return DS_OTHER_WRONG; + } +} + +/** + * @brief Write the initialization vector to the corresponding register field. + */ +static inline void ds_ll_configure_iv(const uint32_t *iv) +{ + for (size_t i = 0; i < (SOC_DS_KEY_PARAM_MD_IV_LENGTH / sizeof(uint32_t)); i++) { + REG_WRITE(DS_IV_BASE + (i * 4), iv[i]); + } +} + +/** + * @brief Write the message which should be signed. + * + * @param msg Pointer to the message. + * @param size Length of msg in bytes. It is the RSA signature length in bytes. + */ +static inline void ds_ll_write_message(const uint8_t *msg, size_t size) +{ + memcpy((uint8_t *) DS_X_BASE, msg, size); +} + +/** + * @brief Write the encrypted private key parameters. + */ +static inline void ds_ll_write_private_key_params(const uint8_t *encrypted_key_params) +{ + /* Note: as the internal peripheral still has RSA 4096 structure, + but C is encrypted based on the actual max RSA length (ETS_DS_MAX_BITS), need to fragment it + when copying to hardware... + + (note if ETS_DS_MAX_BITS == 4096, this should be the same as copying data->c to hardware in one fragment) + */ + typedef struct { + uint32_t addr; + size_t len; + } frag_t; + const frag_t frags[] = { + {DS_C_Y_BASE, SOC_DS_SIGNATURE_MAX_BIT_LEN / 8}, + {DS_C_M_BASE, SOC_DS_SIGNATURE_MAX_BIT_LEN / 8}, + {DS_C_RB_BASE, SOC_DS_SIGNATURE_MAX_BIT_LEN / 8}, + {DS_C_BOX_BASE, DS_IV_BASE - DS_C_BOX_BASE}, + }; + const size_t NUM_FRAGS = sizeof(frags) / sizeof(frag_t); + const uint8_t *from = encrypted_key_params; + + for (int i = 0; i < NUM_FRAGS; i++) { + memcpy((uint8_t *)frags[i].addr, from, frags[i].len); + from += frags[i].len; + } +} + +/** + * @brief Begin signing procedure. + */ +static inline void ds_ll_start_sign(void) +{ + REG_WRITE(DS_SET_ME_REG, 1); +} + +/** + * @brief check the calculated signature. + * + * @return + * - DS_SIGNATURE_OK if no issue is detected with the signature. + * - DS_SIGNATURE_PADDING_FAIL if the padding of the private key parameters is wrong. + * - DS_SIGNATURE_MD_FAIL if the message digest check failed. This means that the message digest calculated using + * the private key parameters fails, i.e., the integrity of the private key parameters is not protected. + * - DS_SIGNATURE_PADDING_AND_MD_FAIL if both padding and message digest check fail. + */ +static inline ds_signature_check_t ds_ll_check_signature(void) +{ + uint32_t result = REG_READ(DS_QUERY_CHECK_REG); + switch (result) { + case 0: + return DS_SIGNATURE_OK; + case 1: + return DS_SIGNATURE_MD_FAIL; + case 2: + return DS_SIGNATURE_PADDING_FAIL; + default: + return DS_SIGNATURE_PADDING_AND_MD_FAIL; + } +} + +/** + * @brief Read the signature from the hardware. + * + * @param result The signature result. + * @param size Length of signature result in bytes. It is the RSA signature length in bytes. + */ +static inline void ds_ll_read_result(uint8_t *result, size_t size) +{ + memcpy(result, (uint8_t *) DS_Z_BASE, size); +} + +/** + * @brief Exit the signature operation. + * + * @note This does not deactivate the module. Corresponding clock/reset bits have to be triggered for deactivation. + */ +static inline void ds_ll_finish(void) +{ + REG_WRITE(DS_SET_FINISH_REG, 1); + ds_ll_wait_busy(); +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32s3/include/hal/gpio_ll.h b/components/hal/esp32s3/include/hal/gpio_ll.h index 0b054bf25d..2248c41afc 100644 --- a/components/hal/esp32s3/include/hal/gpio_ll.h +++ b/components/hal/esp32s3/include/hal/gpio_ll.h @@ -28,6 +28,7 @@ #include "soc/rtc_io_reg.h" #include "soc/usb_serial_jtag_reg.h" #include "hal/gpio_types.h" +#include "soc/gpio_struct.h" #ifdef __cplusplus extern "C" { diff --git a/components/hal/esp32s3/include/hal/gpspi_flash_ll.h b/components/hal/esp32s3/include/hal/gpspi_flash_ll.h index 6669db4be2..47f11e637a 100644 --- a/components/hal/esp32s3/include/hal/gpspi_flash_ll.h +++ b/components/hal/esp32s3/include/hal/gpspi_flash_ll.h @@ -24,11 +24,13 @@ #include #include "soc/spi_periph.h" +#include "soc/spi_struct.h" #include "hal/spi_types.h" #include "hal/spi_flash_types.h" #include // For MIN/MAX #include #include +#include "hal/misc.h" #ifdef __cplusplus extern "C" { @@ -369,7 +371,7 @@ static inline void gpspi_flash_ll_set_address(spi_dev_t *dev, uint32_t addr) static inline void gpspi_flash_ll_set_dummy(spi_dev_t *dev, uint32_t dummy_n) { dev->user.usr_dummy = dummy_n ? 1 : 0; - dev->user1.usr_dummy_cyclelen = dummy_n - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user1, usr_dummy_cyclelen, dummy_n - 1) } /** diff --git a/components/hal/esp32s3/include/hal/hmac_hal.h b/components/hal/esp32s3/include/hal/hmac_hal.h new file mode 100644 index 0000000000..af6fb65af4 --- /dev/null +++ b/components/hal/esp32s3/include/hal/hmac_hal.h @@ -0,0 +1,101 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 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. + * See readme.md in soc/include/hal/readme.md + ******************************************************************************/ + +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * The HMAC peripheral can be configured to deliver its output to the user directly, or to deliver + * the output directly to another peripheral instead, e.g. the Digital Signature peripheral. + */ +typedef enum { + HMAC_OUTPUT_USER = 0, /**< Let user provide a message and read the HMAC result */ + HMAC_OUTPUT_DS = 1, /**< HMAC is provided to the DS peripheral to decrypt DS private key parameters */ + HMAC_OUTPUT_JTAG_ENABLE = 2, /**< HMAC is used to enable JTAG after soft-disabling it */ + HMAC_OUTPUT_ALL = 3 /**< HMAC is used for both as DS input for or enabling JTAG */ +} hmac_hal_output_t; + +/** + * @brief Make the peripheral ready for use. + * + * This triggers any further steps necessary after enabling the device + */ +void hmac_hal_start(void); + +/** + * @brief Configure which hardware key slot should be used and configure the target of the HMAC output. + * + * @note Writing out-of-range values is undefined behavior. The user has to ensure that the parameters are in range. + * + * @param config The target of the HMAC. Possible targets are described in \c hmac_hal_output_t. + * See the ESP32S3 TRM for more details. + * @param key_id The ID of the hardware key slot to be used. + * + * @return 0 if the configuration was successful, non-zero if not. + * An unsuccessful configuration means that the purpose value in the eFuse of the corresponding key slot + * doesn't match to supplied value of \c config. + */ +uint32_t hmac_hal_configure(hmac_hal_output_t config, uint32_t key_id); + +/** + * @brief Write a padded single-block message of 512 bits to the HMAC peripheral. + * + * The message must not be longer than one block (512 bits) and the padding has to be applied by software before + * writing. The padding has to be able to fit into the block after the message. + * For more information on HMAC padding, see the ESP32S3 TRM. + */ +void hmac_hal_write_one_block_512(const void *block); + +/** + * @brief Write a message block of 512 bits to the HMAC peripheral. + * + * This function must be used incombination with \c hmac_hal_next_block_normal() or \c hmac_hal_next_block_padding(). + * The first message block is written without any prerequisite. + * All message blocks which are not the last one, need a call to \c hmac_hal_next_block_normal() before, indicating + * to the hardware that a "normal", i.e. non-padded block will follow. This is even the case for a block which begins + * padding already but where the padding doesn't fit in (remaining message size > (block size - padding size)). + * Before writing the last block which contains the padding, a call to \c hmac_hal_next_block_padding() is necessary + * to indicate to the hardware that a block with padding will be written. + * + * For more information on HMAC padding, see the ESP32S3 TRM. + */ +void hmac_hal_write_block_512(const void *block); + +/** + * @brief Indicate to the hardware that a normal block will be written. + */ +void hmac_hal_next_block_normal(void); + +/** + * @brief Indicate to the hardware that a block with padding will be written. + */ +void hmac_hal_next_block_padding(void); + +/** + * @brief Read the 256 bit HMAC result from the hardware. + */ +void hmac_hal_read_result_256(void *result); + +/** + * @brief Clear (invalidate) the HMAC result provided to other hardware. + */ +void hmac_hal_clean(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32s3/include/hal/hmac_ll.h b/components/hal/esp32s3/include/hal/hmac_ll.h new file mode 100644 index 0000000000..a4cfb68830 --- /dev/null +++ b/components/hal/esp32s3/include/hal/hmac_ll.h @@ -0,0 +1,187 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 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. + * See readme.md in soc/include/hal/readme.md + ******************************************************************************/ + +#pragma once + +#include "soc/hwcrypto_reg.h" + +#define SHA256_BLOCK_SZ 64 +#define SHA256_DIGEST_SZ 32 + +#define HMAC_LL_EFUSE_KEY_PURPOSE_DOWN_JTAG 6 +#define HMAC_LL_EFUSE_KEY_PURPOSE_DOWN_DIGITAL_SIGNATURE 7 +#define HMAC_LL_EFUSE_KEY_PURPOSE_UP 8 +#define HMAC_LL_EFUSE_KEY_PURPOSE_DOWN_ALL 5 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Makes the peripheral ready for use, after enabling it. + */ +static inline void hmac_ll_start(void) +{ + REG_WRITE(HMAC_SET_START_REG, 1); +} + +/** + * @brief Determine where the HMAC output should go. + * + * The HMAC peripheral can be configured to deliver its output to the user directly, or to deliver + * the output directly to another peripheral instead, e.g. the Digital Signature peripheral. + */ +static inline void hmac_ll_config_output(hmac_hal_output_t config) +{ + switch(config) { + case HMAC_OUTPUT_USER: + REG_WRITE(HMAC_SET_PARA_PURPOSE_REG, HMAC_LL_EFUSE_KEY_PURPOSE_UP); + break; + case HMAC_OUTPUT_DS: + REG_WRITE(HMAC_SET_PARA_PURPOSE_REG, HMAC_LL_EFUSE_KEY_PURPOSE_DOWN_DIGITAL_SIGNATURE); + break; + case HMAC_OUTPUT_JTAG_ENABLE: + REG_WRITE(HMAC_SET_PARA_PURPOSE_REG, HMAC_LL_EFUSE_KEY_PURPOSE_DOWN_JTAG); + break; + case HMAC_OUTPUT_ALL: + REG_WRITE(HMAC_SET_PARA_PURPOSE_REG, HMAC_LL_EFUSE_KEY_PURPOSE_DOWN_ALL); + break; + default: + ; // do nothing, error will be indicated by hmac_hal_config_error() + } +} + +/** + * @brief Selects which hardware key should be used. + */ +static inline void hmac_ll_config_hw_key_id(uint32_t key_id) +{ + REG_WRITE(HMAC_SET_PARA_KEY_REG, key_id); +} + +/** + * @brief Apply and check configuration. + * + * Afterwards, the configuration can be checked for errors with hmac_hal_config_error(). + */ +static inline void hmac_ll_config_finish(void) +{ + REG_WRITE(HMAC_SET_PARA_FINISH_REG, 1); +} + +/** + * + * @brief Query HMAC error state after configuration actions. + * + * @return + * - 1 or greater on error + * - 0 on success + */ +static inline uint32_t hmac_ll_query_config_error(void) +{ + return REG_READ(HMAC_QUERY_ERROR_REG); +} + +/** + * Wait until the HAL is ready for the next interaction. + */ +static inline void hmac_ll_wait_idle(void) +{ + uint32_t query; + do { + query = REG_READ(HMAC_QUERY_BUSY_REG); + } while(query != 0); +} + +/** + * @brief Write a message block of 512 bits to the HMAC peripheral. + */ +static inline void hmac_ll_write_block_512(const uint32_t *block) +{ + const size_t REG_WIDTH = sizeof(uint32_t); + for (size_t i = 0; i < SHA256_BLOCK_SZ / REG_WIDTH; i++) { + REG_WRITE(HMAC_WDATA_BASE + (i * REG_WIDTH), block[i]); + } + + REG_WRITE(HMAC_SET_MESSAGE_ONE_REG, 1); +} + +/** + * @brief Read the 256 bit HMAC. + */ +static inline void hmac_ll_read_result_256(uint32_t *result) +{ + const size_t REG_WIDTH = sizeof(uint32_t); + for (size_t i = 0; i < SHA256_DIGEST_SZ / REG_WIDTH; i++) { + result[i] = REG_READ(HMAC_RDATA_BASE + (i * REG_WIDTH)); + } +} + +/** + * @brief Clean the HMAC result provided to other hardware. + */ +static inline void hmac_ll_clean(void) +{ + REG_WRITE(HMAC_SET_INVALIDATE_DS_REG, 1); + REG_WRITE(HMAC_SET_INVALIDATE_JTAG_REG, 1); +} + +/** + * @brief Signals that the following block will be the padded last block. + */ +static inline void hmac_ll_msg_padding(void) +{ + REG_WRITE(HMAC_SET_MESSAGE_PAD_REG, 1); +} + +/** + * @brief Signals that all blocks have been written and a padding block will automatically be applied by hardware. + * + * Only applies if the message length is a multiple of 512 bits. + * See ESP32S3 TRM HMAC chapter for more details. + */ +static inline void hmac_ll_msg_end(void) +{ + REG_WRITE(HMAC_SET_MESSAGE_END_REG, 1); +} + +/** + * @brief The message including padding fits into one block, so no further action needs to be taken. + * + * This is called after the one-block-message has been written. + */ +static inline void hmac_ll_msg_one_block(void) +{ + REG_WRITE(HMAC_ONE_BLOCK_REG, 1); +} + +/** + * @brief Indicate that more blocks will be written after the last block. + */ +static inline void hmac_ll_msg_continue(void) +{ + REG_WRITE(HMAC_SET_MESSAGE_ING_REG, 1); +} + +/** + * @brief Clear the HMAC result. + * + * Use this after reading the HMAC result or if aborting after any of the other steps above. + */ +static inline void hmac_ll_calc_finish(void) +{ + REG_WRITE(HMAC_SET_RESULT_FINISH_REG, 2); +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32s3/include/hal/i2c_ll.h b/components/hal/esp32s3/include/hal/i2c_ll.h index 566ada8b3f..eae2a660fb 100644 --- a/components/hal/esp32s3/include/hal/i2c_ll.h +++ b/components/hal/esp32s3/include/hal/i2c_ll.h @@ -15,8 +15,11 @@ // The LL layer for I2C register operations #pragma once + +#include "hal/misc.h" #include "soc/i2c_periph.h" #include "soc/soc_caps.h" +#include "soc/i2c_struct.h" #include "hal/i2c_types.h" #ifdef __cplusplus @@ -148,7 +151,7 @@ static inline void i2c_ll_update(i2c_dev_t *hw) */ static inline void i2c_ll_set_bus_timing(i2c_dev_t *hw, i2c_clk_cal_t *bus_cfg) { - hw->clk_conf.sclk_div_num = bus_cfg->clkm_div - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clk_conf, sclk_div_num, bus_cfg->clkm_div - 1); //scl period hw->scl_low_period.scl_low_period = bus_cfg->scl_low - 1; hw->scl_high_period.scl_high_period = bus_cfg->scl_high; @@ -574,7 +577,7 @@ static inline void i2c_ll_get_scl_timing(i2c_dev_t *hw, int *high_period, int *l static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len) { for (int i = 0; i< len; i++) { - hw->data.fifo_rdata = ptr[i]; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->data, fifo_rdata, ptr[i]); } } @@ -590,7 +593,7 @@ static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len) static inline void i2c_ll_read_rxfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len) { for(int i = 0; i < len; i++) { - ptr[i] = hw->data.fifo_rdata; + ptr[i] = HAL_FORCE_READ_U32_REG_FIELD(hw->data, fifo_rdata); } } diff --git a/components/hal/esp32s3/include/hal/i2s_ll.h b/components/hal/esp32s3/include/hal/i2s_ll.h index 645e84793e..5e27b9352e 100644 --- a/components/hal/esp32s3/include/hal/i2s_ll.h +++ b/components/hal/esp32s3/include/hal/i2s_ll.h @@ -1,4 +1,4 @@ -// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD +// Copyright 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. @@ -12,418 +12,189 @@ // See the License for the specific language governing permissions and // limitations under the License. +// 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 ******************************************************************************/ -// The LL layer for ESP32-S3 I2S register operations - #pragma once - #include +#include "hal/misc.h" #include "soc/i2s_periph.h" +#include "soc/i2s_struct.h" #include "hal/i2s_types.h" #ifdef __cplusplus extern "C" { #endif -// Get I2S hardware instance with giving i2s num -#define I2S_LL_GET_HW(num) (((num) == 0) ? (&I2S0) : NULL) -#define I2S_INTR_IN_SUC_EOF BIT(9) -#define I2S_INTR_OUT_EOF BIT(12) -#define I2S_INTR_IN_DSCR_ERR BIT(13) -#define I2S_INTR_OUT_DSCR_ERR BIT(14) -#define I2S_INTR_MAX (0xFFFFFFFF) +#define I2S_LL_GET_HW(num) (((num) == 0) ? (&I2S0) : &I2S1) + +#define I2S_LL_TDM_CH_MASK (0xffff) +#define I2S_LL_PDM_BCK_FACTOR (64) +#define I2S_LL_BASE_CLK (2*APB_CLK_FREQ) + +#define I2S_LL_MCLK_DIVIDER_BIT_WIDTH (9) +#define I2S_LL_MCLK_DIVIDER_MAX ((1 << I2S_LL_MCLK_DIVIDER_BIT_WIDTH) - 1) + +/* I2S clock configuration structure */ +typedef struct { + uint16_t mclk_div; // I2S module clock devider, Fmclk = Fsclk /(mclk_div+b/a) + uint16_t a; + uint16_t b; // The decimal part of module clock devider, the decimal is: b/a +} i2s_ll_mclk_div_t; /** - * @brief Reset rx fifo + * @brief I2S module general init, enable I2S clock. * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_rx_fifo(i2s_dev_t *hw) +static inline void i2s_ll_enable_clock(i2s_dev_t *hw) { - hw->rx_conf.rx_fifo_reset = 1; - hw->rx_conf.rx_fifo_reset = 0; + hw->tx_clkm_conf.clk_en = 1; } /** - * @brief Reset tx fifo + * @brief I2S module disable I2S clock. * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_reset_tx_fifo(i2s_dev_t *hw) +static inline void i2s_ll_disable_clock(i2s_dev_t *hw) +{ + hw->tx_clkm_conf.clk_en = 0; +} + +/** + * @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) +{ + hw->tx_clkm_conf.tx_clk_active = 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) +{ + hw->rx_clkm_conf.rx_clk_active = 1; +} + +/** + * @brief I2S mclk use tx module clock + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_mclk_use_tx_clk(i2s_dev_t *hw) +{ + hw->rx_clkm_conf.mclk_sel = 0; +} + +/** + * @brief I2S mclk use rx module clock + * + * @param hw Peripheral I2S hardware instance address. + */ +static inline void i2s_ll_mclk_use_rx_clk(i2s_dev_t *hw) +{ + hw->rx_clkm_conf.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 Enable rx interrupt + * @brief Reset I2S RX FIFO * * @param hw Peripheral I2S hardware instance address. */ -static inline void i2s_ll_enable_rx_intr(i2s_dev_t *hw) +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 Disable rx interrupt + * @brief Set TX source clock * * @param hw Peripheral I2S hardware instance address. + * @param src I2S source clock, ESP32-S3 only support `I2S_CLK_D2CLK` + * TX and RX share the same clock setting */ -static inline void i2s_ll_disable_rx_intr(i2s_dev_t *hw) +static inline void i2s_ll_tx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) { + hw->tx_clkm_conf.tx_clk_sel = 2; } /** - * @brief Disable tx interrupt + * @brief Set RX source clock * * @param hw Peripheral I2S hardware instance address. + * @param src I2S source clock, ESP32-S3 only support `I2S_CLK_D2CLK` + * TX and RX share the same clock setting */ -static inline void i2s_ll_disable_tx_intr(i2s_dev_t *hw) -{ -} - -/** - * @brief Enable tx interrupt - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_enable_tx_intr(i2s_dev_t *hw) -{ -} - -/** - * @brief Reset dma in - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_reset_dma_in(i2s_dev_t *hw) -{ -} - -/** - * @brief Reset dma out - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_reset_dma_out(i2s_dev_t *hw) -{ -} - -/** - * @brief Reset tx - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_reset_tx(i2s_dev_t *hw) -{ -} - -/** - * @brief Reset rx - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_reset_rx(i2s_dev_t *hw) -{ -} - -/** - * @brief Start out link - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_start_out_link(i2s_dev_t *hw) -{ -} - -/** - * @brief Start tx - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_start_tx(i2s_dev_t *hw) -{ -} - -/** - * @brief Start in link - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_start_in_link(i2s_dev_t *hw) -{ -} - -/** - * @brief Start rx - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_start_rx(i2s_dev_t *hw) -{ -} - -/** - * @brief Stop out link - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_stop_out_link(i2s_dev_t *hw) -{ -} - -/** - * @brief Stop tx - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_stop_tx(i2s_dev_t *hw) -{ -} - -/** - * @brief Stop in link - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_stop_in_link(i2s_dev_t *hw) -{ -} - -/** - * @brief Stop rx - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_stop_rx(i2s_dev_t *hw) -{ -} - -/** - * @brief Enable dma - * - * @param hw Peripheral I2S hardware instance address. - */ -static inline void i2s_ll_enable_dma(i2s_dev_t *hw) -{ -} - -/** - * @brief Get I2S interrupt status - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get interrupt status - */ -static inline void i2s_ll_get_intr_status(i2s_dev_t *hw, uint32_t *val) -{ - *val = hw->int_st.val; -} - -/** - * @brief Clear I2S interrupt status - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to clear interrupt status - */ -static inline void i2s_ll_clear_intr_status(i2s_dev_t *hw, uint32_t val) -{ - hw->int_clr.val = val; -} - -/** - * @brief Get I2S out eof des address - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get out eof des address - */ -static inline void i2s_ll_get_out_eof_des_addr(i2s_dev_t *hw, uint32_t *val) -{ -} - -/** - * @brief Get I2S in eof des address - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get in eof des address - */ -static inline void i2s_ll_get_in_eof_des_addr(i2s_dev_t *hw, uint32_t *val) -{ -} - -/** - * @brief Get I2S tx fifo mode - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get tx fifo mode - */ -static inline void i2s_ll_get_tx_fifo_mod(i2s_dev_t *hw, uint32_t *val) -{ -} - -/** - * @brief Set I2S tx fifo mode - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx fifo mode - */ -static inline void i2s_ll_set_tx_fifo_mod(i2s_dev_t *hw, uint32_t val) -{ -} - -/** - * @brief Get I2S rx fifo mode - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get rx fifo mode - */ -static inline void i2s_ll_get_rx_fifo_mod(i2s_dev_t *hw, uint32_t *val) -{ -} - -/** - * @brief Set I2S rx fifo mode - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx fifo mode - */ -static inline void i2s_ll_set_rx_fifo_mod(i2s_dev_t *hw, uint32_t val) -{ -} - -/** - * @brief Set I2S tx chan mode - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx chan mode - */ -static inline void i2s_ll_set_tx_chan_mod(i2s_dev_t *hw, uint32_t val) -{ -} - -/** - * @brief Set I2S rx chan mode - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx chan mode - */ -static inline void i2s_ll_set_rx_chan_mod(i2s_dev_t *hw, uint32_t val) -{ -} - -/** - * @brief Set I2S out link address - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set out link address - */ -static inline void i2s_ll_set_out_link_addr(i2s_dev_t *hw, uint32_t val) -{ -} - -/** - * @brief Set I2S in link address - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set in link address - */ -static inline void i2s_ll_set_in_link_addr(i2s_dev_t *hw, uint32_t val) -{ -} - -/** - * @brief Set I2S rx eof num - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx eof num - */ -static inline void i2s_ll_set_rx_eof_num(i2s_dev_t *hw, uint32_t val) -{ -} - -/** - * @brief Get I2S tx pdm fp - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get tx pdm fp - */ -static inline void i2s_ll_get_tx_pdm_fp(i2s_dev_t *hw, uint32_t *val) -{ -} - -/** - * @brief Get I2S tx pdm fs - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get tx pdm fs - */ -static inline void i2s_ll_get_tx_pdm_fs(i2s_dev_t *hw, uint32_t *val) -{ -} - -/** - * @brief Set I2S tx pdm fp - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx pdm fp - */ -static inline void i2s_ll_set_tx_pdm_fp(i2s_dev_t *hw, uint32_t val) -{ -} - -/** - * @brief Set I2S tx pdm fs - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx pdm fs - */ -static inline void i2s_ll_set_tx_pdm_fs(i2s_dev_t *hw, uint32_t val) -{ -} - -/** - * @brief Get I2S rx sinc dsr 16 en - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to get rx sinc dsr 16 en - */ -static inline void i2s_ll_get_rx_sinc_dsr_16_en(i2s_dev_t *hw, bool *val) -{ -} - -/** - * @brief Set I2S clkm div num - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set clkm div num - */ -static inline void i2s_ll_set_clkm_div_num(i2s_dev_t *hw, uint32_t val) -{ -} - -/** - * @brief Set I2S clkm div b - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set clkm div b - */ -static inline void i2s_ll_set_clkm_div_b(i2s_dev_t *hw, uint32_t val) -{ -} - -/** - * @brief Set I2S clkm div a - * - * @param hw Peripheral I2S hardware instance address. - * @param val value to set clkm div a - */ -static inline void i2s_ll_set_clkm_div_a(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_rx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) { + hw->rx_clkm_conf.rx_clk_sel = 2; } /** @@ -432,8 +203,37 @@ static inline void i2s_ll_set_clkm_div_a(i2s_dev_t *hw, uint32_t val) * @param hw Peripheral I2S hardware instance address. * @param val value to set tx bck div num */ -static inline void i2s_ll_set_tx_bck_div_num(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_tx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) { + hw->tx_conf1.tx_bck_div_num = val - 1; +} + +/** + * @brief Configure I2S TX clock devider + * + * @param hw Peripheral I2S hardware instance address. + * @param set Pointer to I2S clock devider configuration paramater + */ +static inline void i2s_ll_tx_set_clk(i2s_dev_t *hw, i2s_ll_mclk_div_t *set) +{ + if (set->a == 0 || set->b == 0) { + hw->tx_clkm_div_conf.tx_clkm_div_x = 0; + hw->tx_clkm_div_conf.tx_clkm_div_y = 0; + hw->tx_clkm_div_conf.tx_clkm_div_z = 0; + } else { + if (set->b > set->a / 2) { + hw->tx_clkm_div_conf.tx_clkm_div_x = set->a / (set->a - set->b) - 1; + hw->tx_clkm_div_conf.tx_clkm_div_y = set->a % (set->a - set->b); + hw->tx_clkm_div_conf.tx_clkm_div_z = set->a - set->b; + hw->tx_clkm_div_conf.tx_clkm_div_yn1 = 1; + } else { + hw->tx_clkm_div_conf.tx_clkm_div_x = set->a / set->b - 1; + hw->tx_clkm_div_conf.tx_clkm_div_y = set->a % set->b + 1; + hw->tx_clkm_div_conf.tx_clkm_div_z = set->b; + hw->tx_clkm_div_conf.tx_clkm_div_yn1 = 0; + } + } + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_clkm_conf, tx_clkm_div_num, set->mclk_div); } /** @@ -442,407 +242,617 @@ static inline void i2s_ll_set_tx_bck_div_num(i2s_dev_t *hw, uint32_t val) * @param hw Peripheral I2S hardware instance address. * @param val value to set rx bck div num */ -static inline void i2s_ll_set_rx_bck_div_num(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_rx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) { + hw->rx_conf1.rx_bck_div_num = val - 1; } /** - * @brief Set I2S clk sel + * @brief Configure I2S RX clock devider * * @param hw Peripheral I2S hardware instance address. - * @param val value to set clk sel + * @param set Pointer to I2S clock devider configuration paramater */ -static inline void i2s_ll_set_clk_sel(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_rx_set_clk(i2s_dev_t *hw, i2s_ll_mclk_div_t *set) { + if (set->a == 0 || set->b == 0) { + hw->rx_clkm_div_conf.rx_clkm_div_x = 0; + hw->rx_clkm_div_conf.rx_clkm_div_y = 0; + hw->rx_clkm_div_conf.rx_clkm_div_z = 0; + } else { + if (set->b > set->a / 2) { + hw->rx_clkm_div_conf.rx_clkm_div_x = set->a / (set->a - set->b) - 1; + hw->rx_clkm_div_conf.rx_clkm_div_y = set->a % (set->a - set->b); + hw->rx_clkm_div_conf.rx_clkm_div_z = set->a - set->b; + hw->rx_clkm_div_conf.rx_clkm_div_yn1 = 1; + } else { + hw->rx_clkm_div_conf.rx_clkm_div_x = set->a / set->b - 1; + hw->rx_clkm_div_conf.rx_clkm_div_y = set->a % set->b + 1; + hw->rx_clkm_div_conf.rx_clkm_div_z = set->b; + hw->rx_clkm_div_conf.rx_clkm_div_yn1 = 0; + } + } + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_clkm_conf, rx_clkm_div_num, set->mclk_div); } /** - * @brief Set I2S tx bits mod + * @brief Start I2S TX * * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx bits mod */ -static inline void i2s_ll_set_tx_bits_mod(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_tx_start(i2s_dev_t *hw) { + hw->tx_conf.tx_update = 0; + hw->tx_conf.tx_update = 1; + hw->tx_conf.tx_start = 1; } /** - * @brief Set I2S rx bits mod + * @brief Start I2S RX * * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx bits mod */ -static inline void i2s_ll_set_rx_bits_mod(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_rx_start(i2s_dev_t *hw) { + hw->rx_conf.rx_update = 0; + hw->rx_conf.rx_update = 1; + hw->rx_conf.rx_start = 1; } /** - * @brief Set I2S rx sinc dsr 16 en + * @brief Stop I2S TX * * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx sinc dsr 16 en */ -static inline void i2s_ll_set_rx_sinc_dsr_16_en(i2s_dev_t *hw, bool val) +static inline void i2s_ll_tx_stop(i2s_dev_t *hw) { + hw->tx_conf.tx_start = 0; } /** - * @brief Set I2S dscr en + * @brief Stop I2S RX * * @param hw Peripheral I2S hardware instance address. - * @param val value to set dscr en */ -static inline void i2s_ll_set_dscr_en(i2s_dev_t *hw, bool val) +static inline void i2s_ll_rx_stop(i2s_dev_t *hw) { + hw->rx_conf.rx_start = 0; } /** - * @brief Set I2S lcd en + * @brief Configure TX WS signal width * * @param hw Peripheral I2S hardware instance address. - * @param val value to set lcd en + * @param width WS width in BCK cycle */ -static inline void i2s_ll_set_lcd_en(i2s_dev_t *hw, bool val) +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 Set I2S camera en + * @brief Configure RX WS signal width * * @param hw Peripheral I2S hardware instance address. - * @param val value to set camera en + * @param width WS width in BCK cycle */ -static inline void i2s_ll_set_camera_en(i2s_dev_t *hw, bool val) +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 Set I2S pcm2pdm conv en + * @brief Configure the received length to trigger in_suc_eof interrupt * * @param hw Peripheral I2S hardware instance address. - * @param val value to set pcm2pdm conv en + * @param eof_num the byte length to trigger in_suc_eof interrupt */ -static inline void i2s_ll_set_pcm2pdm_conv_en(i2s_dev_t *hw, bool val) +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 Set I2S pdm2pcm conv en + * @brief Congfigure TX chan bit and audio data bit * * @param hw Peripheral I2S hardware instance address. - * @param val value to set pdm2pcm conv en + * @param chan_bit The chan bit width + * @param data_bit The audio data bit width */ -static inline void i2s_ll_set_pdm2pcm_conv_en(i2s_dev_t *hw, bool val) +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 Set I2S rx pdm en + * @brief Congfigure RX chan bit and audio data bit * * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx pdm en + * @param chan_bit The chan bit width + * @param data_bit The audio data bit width */ -static inline void i2s_ll_set_rx_pdm_en(i2s_dev_t *hw, bool val) +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 Set I2S tx pdm en + * @brief Configure RX half_sample_bit * * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx pdm en + * @param half_sample_bits half sample bit width */ -static inline void i2s_ll_set_tx_pdm_en(i2s_dev_t *hw, bool val) +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 Set I2S tx msb shift + * @brief Configure RX half_sample_bit * * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx msb shift + * @param half_sample_bits half sample bit width */ -static inline void i2s_ll_set_tx_msb_shift(i2s_dev_t *hw, uint32_t val) +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 Set I2S rx msb shift + * @brief Enable TX MSB shift, the data will be launch at the first BCK clock * * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx msb shift + * @param msb_shift_enable Set true to enable MSB shift */ -static inline void i2s_ll_set_rx_msb_shift(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_tx_enable_msb_shift(i2s_dev_t *hw, bool msb_shift_enable) { + hw->tx_conf1.tx_msb_shift = msb_shift_enable; } /** - * @brief Set I2S tx short sync + * @brief Enable RX MSB shift, the data will be launch at the first BCK clock * * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx short sync + * @param msb_shift_enable Set true to enable MSB shift */ -static inline void i2s_ll_set_tx_short_sync(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_rx_enable_msb_shift(i2s_dev_t *hw, bool msb_shift_enable) { + hw->rx_conf1.rx_msb_shift = msb_shift_enable; } /** - * @brief Set I2S rx short sync + * @brief Configure TX total chan number * * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx short sync + * @param total_num Total chan number */ -static inline void i2s_ll_set_rx_short_sync(i2s_dev_t *hw, uint32_t val) +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 Set I2S tx fifo mod force en + * @brief Configure RX total chan number * * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx fifo mod force en + * @param total_num Total chan number */ -static inline void i2s_ll_set_tx_fifo_mod_force_en(i2s_dev_t *hw, bool val) +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 I2S rx fifo mod force en + * @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 val value to set rx fifo mod force en + * @param chan_mask mask of tx active chan */ -static inline void i2s_ll_set_rx_fifo_mod_force_en(i2s_dev_t *hw, bool val) +static inline void i2s_ll_tx_set_active_chan_mask(i2s_dev_t *hw, uint32_t chan_mask) { + typeof(hw->tx_tdm_ctrl) tdm_ctrl_reg = hw->tx_tdm_ctrl; + tdm_ctrl_reg.val &= ~I2S_LL_TDM_CH_MASK; + tdm_ctrl_reg.val |= chan_mask & I2S_LL_TDM_CH_MASK; + hw->tx_tdm_ctrl.val = tdm_ctrl_reg.val; } /** - * @brief Set I2S tx right first + * @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 val value to set tx right first + * @param chan_mask mask of rx active chan */ -static inline void i2s_ll_set_tx_right_first(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_rx_set_active_chan_mask(i2s_dev_t *hw, uint32_t chan_mask) { + typeof(hw->rx_tdm_ctrl) tdm_ctrl_reg = hw->rx_tdm_ctrl; + tdm_ctrl_reg.val &= ~I2S_LL_TDM_CH_MASK; + tdm_ctrl_reg.val |= chan_mask & I2S_LL_TDM_CH_MASK; + hw->rx_tdm_ctrl.val = tdm_ctrl_reg.val; } /** - * @brief Set I2S rx right first + * @brief Set TX WS signal pol level * * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx right first + * @param ws_pol_level pin level of WS(output) when receiving left channel data */ -static inline void i2s_ll_set_rx_right_first(i2s_dev_t *hw, uint32_t val) +static inline void i2s_tx_set_ws_idle_pol(i2s_dev_t *hw, int ws_pol_level) { + hw->tx_conf.tx_ws_idle_pol = ws_pol_level; } /** - * @brief Set I2S tx slave mod + * @brief Set RX WS signal pol level * * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx slave mod + * @param ws_pol_level pin level of WS(input) when receiving left channel data */ -static inline void i2s_ll_set_tx_slave_mod(i2s_dev_t *hw, uint32_t val) +static inline void i2s_rx_set_ws_idle_pol(i2s_dev_t *hw, int ws_pol_level) { + hw->rx_conf.rx_ws_idle_pol = ws_pol_level; } /** - * @brief Set I2S rx slave mod + * @brief Enable TX PDM mode. * * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx slave mod + * @param pdm_enable Set true to TX enable PDM mode */ -static inline void i2s_ll_set_rx_slave_mod(i2s_dev_t *hw, uint32_t val) +static inline void i2s_ll_tx_enable_pdm(i2s_dev_t *hw, bool pdm_enable) { + hw->tx_conf.tx_pdm_en = pdm_enable; + hw->tx_conf.tx_tdm_en = !pdm_enable; + hw->tx_pcm2pdm_conf.pcm2pdm_conv_en = pdm_enable; } /** - * @brief Get I2S tx msb right + * @brief Enable RX PDM mode. * * @param hw Peripheral I2S hardware instance address. - * @param val value to get tx msb right + * @param pdm_enable Set true to RX enable PDM mode */ -static inline void i2s_ll_get_tx_msb_right(i2s_dev_t *hw, uint32_t *val) +static inline void i2s_ll_rx_enable_pdm(i2s_dev_t *hw, bool pdm_enable) { + hw->rx_conf.rx_pdm_en = pdm_enable; + hw->rx_conf.rx_tdm_en = !pdm_enable; + hw->rx_conf.rx_pdm2pcm_en = pdm_enable; } /** - * @brief Get I2S rx msb right + * @brief Configure I2S TX PDM sample rate + * Fpdm = 64*Fpcm*fp/fs * * @param hw Peripheral I2S hardware instance address. - * @param val value to get rx msb right + * @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_get_rx_msb_right(i2s_dev_t *hw, uint32_t *val) +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; + hw->tx_pcm2pdm_conf.tx_sinc_osr2 = fp / fs; } /** - * @brief Set I2S tx msb right + * @brief Get I2S TX PDM fp configuration paramater * * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx msb right + * @return + * - fp configuration paramater */ -static inline void i2s_ll_set_tx_msb_right(i2s_dev_t *hw, uint32_t val) +static inline uint32_t i2s_ll_tx_get_pdm_fp(i2s_dev_t *hw) { + return hw->tx_pcm2pdm_conf1.tx_pdm_fp; } /** - * @brief Set I2S rx msb right + * @brief Get I2S TX PDM fs configuration paramater * * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx msb right + * @return + * - fs configuration paramater */ -static inline void i2s_ll_set_rx_msb_right(i2s_dev_t *hw, uint32_t val) +static inline uint32_t i2s_ll_tx_get_pdm_fs(i2s_dev_t *hw) { + return hw->tx_pcm2pdm_conf1.tx_pdm_fs; } /** - * @brief Set I2S tx mono + * @brief Set I2S TX PDM prescale * * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx mono + * @param prescale I2S TX PDM prescale */ -static inline void i2s_ll_set_tx_mono(i2s_dev_t *hw, uint32_t val) +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_prescale, prescale); } /** - * @brief Set I2S rx mono + * @brief Set I2S TX PDM high pass filter scaling * * @param hw Peripheral I2S hardware instance address. - * @param val value to set rx mono + * @param sig_scale I2S TX PDM signal scaling before transmit to the filter */ -static inline void i2s_ll_set_rx_mono(i2s_dev_t *hw, uint32_t val) +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_hp_in_shift = sig_scale; } /** - * @brief Set I2S tx sinc osr2 + * @brief Set I2S TX PDM low pass filter scaling * * @param hw Peripheral I2S hardware instance address. - * @param val value to set tx sinc osr2 + * @param sig_scale I2S TX PDM signal scaling before transmit to the filter */ -static inline void i2s_ll_set_tx_sinc_osr2(i2s_dev_t *hw, uint32_t val) +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_lp_in_shift = sig_scale; } /** - * @brief Set I2S sig loopback + * @brief Set I2S TX PDM sinc filter scaling * * @param hw Peripheral I2S hardware instance address. - * @param val value to set sig loopback + * @param sig_scale I2S TX PDM signal scaling before transmit to the filter */ -static inline void i2s_ll_set_sig_loopback(i2s_dev_t *hw, uint32_t val) +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_sinc_in_shift = sig_scale; } /** - * @brief Set I2S TX to philip standard + * @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_set_tx_format_philip(i2s_dev_t *hw) +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_sigmadelta_in_shift = sig_scale; } /** - * @brief Set I2S RX to philip standard + * @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_set_rx_format_philip(i2s_dev_t *hw) +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 to MSB Alignment Standard + * @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_set_tx_format_msb_align(i2s_dev_t *hw) +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 Set I2S RX to MSB Alignment Standard + * @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_set_rx_format_msb_align(i2s_dev_t *hw) +static inline void i2s_ll_tx_enable_pdm_hp_filter(i2s_dev_t *hw, bool enable) { + hw->tx_pcm2pdm_conf.tx_hp_bypass = !enable; } /** - * @brief Set I2S TX to PCM short standard + * @brief Enable I2S TX PDM sigma-delta codec * * @param hw Peripheral I2S hardware instance address. + * @param dither I2S TX PDM sigmadelta dither value */ -static inline void i2s_ll_set_tx_pcm_short(i2s_dev_t *hw) +static inline void i2s_ll_tx_enable_pdm_sd_codec(i2s_dev_t *hw, bool enable) { + hw->tx_pcm2pdm_conf.tx_dac_2out_en = enable; + hw->tx_pcm2pdm_conf.tx_dac_mode_en = enable; } /** - * @brief Set I2S RX to PCM short standard + * @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_set_rx_pcm_short(i2s_dev_t *hw) +static inline void i2s_ll_tx_set_pdm_sd_dither(i2s_dev_t *hw, uint32_t dither) { + hw->tx_pcm2pdm_conf.tx_sigmadelta_dither = dither; } /** - * @brief Set I2S TX to PCM long standard + * @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_set_tx_pcm_long(i2s_dev_t *hw) +static inline void i2s_ll_tx_set_pdm_sd_dither2(i2s_dev_t *hw, uint32_t dither2) { + hw->tx_pcm2pdm_conf.tx_sigmadelta_dither2 = dither2; } /** - * @brief Set I2S RX to PCM long standard + * @brief Configure RX PDM downsample * * @param hw Peripheral I2S hardware instance address. + * @param dsr PDM downsample configuration paramater */ -static inline void i2s_ll_set_rx_pcm_long(i2s_dev_t *hw) +static inline void i2s_ll_rx_set_pdm_dsr(i2s_dev_t *hw, i2s_pdm_dsr_t dsr) { + hw->rx_conf.rx_pdm_sinc_dsr_16_en = dsr; } /** - * @brief Configure I2S TX pdm + * @brief Get RX PDM downsample configuration * - * @param sample_rate The sample rate to be set. * @param hw Peripheral I2S hardware instance address. + * @param dsr Pointer to accept PDM downsample configuration */ -static inline void i2s_ll_tx_pdm_cfg(i2s_dev_t *hw, uint32_t sample_rate) +static inline void i2s_ll_rx_get_pdm_dsr(i2s_dev_t *hw, i2s_pdm_dsr_t *dsr) { + *dsr = hw->rx_conf.rx_pdm_sinc_dsr_16_en; } /** - * @brief Configure I2S TX pdm + * @brief Configura TX a/u-law decompress or compress * * @param hw Peripheral I2S hardware instance address. + * @param pcm_cfg PCM configuration paramater */ -static inline void i2s_ll_rx_pdm_cfg(i2s_dev_t *hw) +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 Enable I2S build in ADC mode + * @brief Configure RX a/u-law decompress or compress * * @param hw Peripheral I2S hardware instance address. + * @param pcm_cfg PCM configuration paramater */ -static inline void i2s_ll_build_in_adc_ena(i2s_dev_t *hw) +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 I2S build in DAC mode + * @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_build_in_dac_ena(i2s_dev_t *hw) +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 = 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; } #ifdef __cplusplus diff --git a/components/hal/esp32s3/include/hal/lcd_ll.h b/components/hal/esp32s3/include/hal/lcd_ll.h index 271b4f3b6b..f7c41897d3 100644 --- a/components/hal/esp32s3/include/hal/lcd_ll.h +++ b/components/hal/esp32s3/include/hal/lcd_ll.h @@ -15,9 +15,11 @@ #include #include +#include "hal/misc.h" #include "soc/lcd_cam_reg.h" #include "soc/lcd_cam_struct.h" #include "hal/assert.h" +#include "hal/lcd_types.h" #ifdef __cplusplus extern "C" { @@ -29,11 +31,6 @@ extern "C" { #define LCD_LL_EVENT_VSYNC_END (1 << 0) #define LCD_LL_EVENT_TRANS_DONE (1 << 1) -// Clock source ID represented in register -#define LCD_LL_CLOCK_SRC_XTAL (1) -#define LCD_LL_CLOCK_SRC_APLL (2) -#define LCD_LL_CLOCK_SRC_PLL160M (3) - // Maximum coefficient of clock prescaler #define LCD_LL_CLOCK_PRESCALE_MAX (64) @@ -42,14 +39,28 @@ static inline void lcd_ll_enable_clock(lcd_cam_dev_t *dev, bool en) dev->lcd_clock.clk_en = en; } -static inline void lcd_ll_set_group_clock_src(lcd_cam_dev_t *dev, int src, int div_num, int div_a, int div_b) +static inline void lcd_ll_set_group_clock_src(lcd_cam_dev_t *dev, lcd_clock_source_t src, int div_num, int div_a, int div_b) { // lcd_clk = module_clock_src / (div_num + div_b / div_a) HAL_ASSERT(div_num >= 2); dev->lcd_clock.lcd_clk_sel = src; - dev->lcd_clock.lcd_clkm_div_num = div_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->lcd_clock, lcd_clkm_div_num, div_num); dev->lcd_clock.lcd_clkm_div_a = div_a; dev->lcd_clock.lcd_clkm_div_b = div_b; + switch (src) { + case LCD_CLK_SRC_PLL160M: + dev->lcd_clock.lcd_clk_sel = 3; + break; + case LCD_CLK_SRC_APLL: + dev->lcd_clock.lcd_clk_sel = 2; + break; + case LCD_CLK_SRC_XTAL: + dev->lcd_clock.lcd_clk_sel = 1; + break; + default: + HAL_ASSERT(false && "unsupported clock source"); + break; + } } static inline void lcd_ll_set_clock_idle_level(lcd_cam_dev_t *dev, bool level) @@ -131,15 +142,14 @@ static inline void lcd_ll_reverse_data_bit_order(lcd_cam_dev_t *dev, bool en) dev->lcd_user.lcd_bit_order = en; } -static inline void lcd_ll_reverse_data_byte_order(lcd_cam_dev_t *dev, uint32_t data_width, bool en) +static inline void lcd_ll_reverse_data_byte_order(lcd_cam_dev_t *dev, bool en) { - if (data_width == 8) { - dev->lcd_user.lcd_8bits_order = en; // valid in 8bit mode - dev->lcd_user.lcd_byte_order = 0; - } else if (data_width == 16) { - dev->lcd_user.lcd_byte_order = en; // valid in 16bit mode - dev->lcd_user.lcd_8bits_order = 0; - } + dev->lcd_user.lcd_byte_order = en; +} + +static inline void lcd_ll_reverse_data_8bits_order(lcd_cam_dev_t *dev, bool en) +{ + dev->lcd_user.lcd_8bits_order = en; } static inline void lcd_ll_fifo_reset(lcd_cam_dev_t *dev) @@ -189,7 +199,7 @@ static inline void lcd_ll_enable_output_hsync_in_porch_region(lcd_cam_dev_t *dev static inline void lcd_ll_set_hsync_position(lcd_cam_dev_t *dev, uint32_t offset_in_line) { - dev->lcd_ctrl2.lcd_hsync_position = offset_in_line; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->lcd_ctrl2, lcd_hsync_position, offset_in_line); } static inline void lcd_ll_set_horizontal_timing(lcd_cam_dev_t *dev, uint32_t hsw, uint32_t hbp, uint32_t active_width, uint32_t hfp) @@ -203,7 +213,7 @@ static inline void lcd_ll_set_horizontal_timing(lcd_cam_dev_t *dev, uint32_t hsw static inline void lcd_ll_set_vertical_timing(lcd_cam_dev_t *dev, uint32_t vsw, uint32_t vbp, uint32_t active_height, uint32_t vfp) { dev->lcd_ctrl2.lcd_vsync_width = vsw - 1; - dev->lcd_ctrl1.lcd_vb_front = vbp + vsw - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->lcd_ctrl1, lcd_vb_front, vbp + vsw - 1); dev->lcd_ctrl.lcd_va_height = active_height - 1; dev->lcd_ctrl.lcd_vt_height = vsw + vbp + active_height + vfp - 1; } diff --git a/components/hal/esp32s3/include/hal/ledc_ll.h b/components/hal/esp32s3/include/hal/ledc_ll.h index eafae904ba..fb495b0319 100644 --- a/components/hal/esp32s3/include/hal/ledc_ll.h +++ b/components/hal/esp32s3/include/hal/ledc_ll.h @@ -19,6 +19,7 @@ #include "hal/ledc_types.h" #include "soc/ledc_periph.h" +#include "soc/ledc_struct.h" #ifdef __cplusplus extern "C" { diff --git a/components/hal/esp32s3/include/hal/mcpwm_ll.h b/components/hal/esp32s3/include/hal/mcpwm_ll.h index 93f44e2470..ef6a63824f 100644 --- a/components/hal/esp32s3/include/hal/mcpwm_ll.h +++ b/components/hal/esp32s3/include/hal/mcpwm_ll.h @@ -23,6 +23,7 @@ #pragma once #include +#include "hal/misc.h" #include "soc/soc_caps.h" #include "soc/mcpwm_struct.h" #include "hal/mcpwm_types.h" @@ -41,20 +42,20 @@ extern "C" { /********************* Group registers *******************/ -// Set/Get group clock: PWM_clk = CLK_160M / (clk_cfg.prescale + 1) +// Set/Get group clock: PWM_clk = CLK_160M / (prescale + 1) static inline void mcpwm_ll_group_set_clock_prescale(mcpwm_dev_t *mcpwm, int pre_scale) { // In case the compiler optimise a 32bit instruction (e.g. s32i) into 8bit instruction (e.g. s8i, which is not allowed to access a register) // We take care of the "read-modify-write" procedure by ourselves. - typeof(mcpwm->clk_cfg) clkcfg = mcpwm->clk_cfg; - clkcfg.prescale = pre_scale - 1; + mcpwm_clk_cfg_reg_t clkcfg = mcpwm->clk_cfg; + clkcfg.clk_prescale = pre_scale - 1; mcpwm->clk_cfg = clkcfg; } static inline uint32_t mcpwm_ll_group_get_clock_prescale(mcpwm_dev_t *mcpwm) { - typeof(mcpwm->clk_cfg) clkcfg = mcpwm->clk_cfg; - return clkcfg.prescale + 1; + mcpwm_clk_cfg_reg_t clkcfg = mcpwm->clk_cfg; + return clkcfg.clk_prescale + 1; } static inline void mcpwm_ll_group_enable_shadow_mode(mcpwm_dev_t *mcpwm) @@ -131,6 +132,7 @@ static inline uint32_t mcpwm_ll_intr_get_trip_ost_status(mcpwm_dev_t *mcpwm) return (mcpwm->int_st.val >> 24) & 0x07; } +__attribute__((always_inline)) static inline uint32_t mcpwm_ll_intr_get_capture_status(mcpwm_dev_t *mcpwm) { return (mcpwm->int_st.val >> 27) & 0x07; @@ -178,6 +180,7 @@ static inline void mcpwm_ll_intr_clear_trip_ost_status(mcpwm_dev_t *mcpwm, uint3 mcpwm->int_clr.val = (ost_mask & 0x07) << 24; } +__attribute__((always_inline)) static inline void mcpwm_ll_intr_clear_capture_status(mcpwm_dev_t *mcpwm, uint32_t capture_mask) { mcpwm->int_clr.val = (capture_mask & 0x07) << 27; @@ -272,23 +275,23 @@ static inline void mcpwm_ll_timer_set_clock_prescale(mcpwm_dev_t *mcpwm, int tim { // In case the compiler optimise a 32bit instruction (e.g. s32i) into 8bit instruction (e.g. s8i, which is not allowed to access a register) // We take care of the "read-modify-write" procedure by ourselves. - typeof(mcpwm->timer[timer_id].period) period = mcpwm->timer[timer_id].period; - period.prescale = prescale - 1; - mcpwm->timer[timer_id].period = period; + mcpwm_timer_cfg0_reg_t cfg0 = mcpwm->timer[timer_id].timer_cfg0; + cfg0.timer_prescale = prescale - 1; + mcpwm->timer[timer_id].timer_cfg0 = cfg0; } static inline uint32_t mcpwm_ll_timer_get_clock_prescale(mcpwm_dev_t *mcpwm, int timer_id) { - typeof(mcpwm->timer[timer_id].period) period = mcpwm->timer[timer_id].period; - return period.prescale + 1; + mcpwm_timer_cfg0_reg_t cfg0 = mcpwm->timer[timer_id].timer_cfg0; + return cfg0.timer_prescale + 1; } static inline void mcpwm_ll_timer_set_peak(mcpwm_dev_t *mcpwm, int timer_id, uint32_t peak, bool symmetric) { if (!symmetric) { // in asymmetric mode, period = [0,peak-1] - mcpwm->timer[timer_id].period.period = peak - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period, peak - 1); } else { // in symmetric mode, period = [0,peak-1] + [peak,1] - mcpwm->timer[timer_id].period.period = peak; + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period, peak); } } @@ -296,32 +299,32 @@ static inline uint32_t mcpwm_ll_timer_get_peak(mcpwm_dev_t *mcpwm, int timer_id, { // asymmetric mode if (!symmetric) { - return mcpwm->timer[timer_id].period.period + 1; + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period) + 1; } // symmetric mode - return mcpwm->timer[timer_id].period.period; + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period); } static inline void mcpwm_ll_timer_update_period_at_once(mcpwm_dev_t *mcpwm, int timer_id) { - mcpwm->timer[timer_id].period.upmethod = 0; + mcpwm->timer[timer_id].timer_cfg0.timer_period_upmethod = 0; } static inline void mcpwm_ll_timer_enable_update_period_on_tez(mcpwm_dev_t *mcpwm, int timer_id, bool enable) { if (enable) { - mcpwm->timer[timer_id].period.upmethod |= 0x01; + mcpwm->timer[timer_id].timer_cfg0.timer_period_upmethod |= 0x01; } else { - mcpwm->timer[timer_id].period.upmethod &= ~0x01; + mcpwm->timer[timer_id].timer_cfg0.timer_period_upmethod &= ~0x01; } } static inline void mcpwm_ll_timer_enable_update_period_on_sync(mcpwm_dev_t *mcpwm, int timer_id, bool enable) { if (enable) { - mcpwm->timer[timer_id].period.upmethod |= 0x02; + mcpwm->timer[timer_id].timer_cfg0.timer_period_upmethod |= 0x02; } else { - mcpwm->timer[timer_id].period.upmethod &= ~0x02; + mcpwm->timer[timer_id].timer_cfg0.timer_period_upmethod &= ~0x02; } } @@ -329,23 +332,23 @@ static inline void mcpwm_ll_timer_set_count_mode(mcpwm_dev_t *mcpwm, int timer_i { switch (mode) { case MCPWM_TIMER_COUNT_MODE_PAUSE: - mcpwm->timer[timer_id].mode.mode = 0; + mcpwm->timer[timer_id].timer_cfg1.timer_mod = 0; break; case MCPWM_TIMER_COUNT_MODE_UP: - mcpwm->timer[timer_id].mode.mode = 1; + mcpwm->timer[timer_id].timer_cfg1.timer_mod = 1; break; case MCPWM_TIMER_COUNT_MODE_DOWN: - mcpwm->timer[timer_id].mode.mode = 2; + mcpwm->timer[timer_id].timer_cfg1.timer_mod = 2; break; case MCPWM_TIMER_COUNT_MODE_UP_DOWN: - mcpwm->timer[timer_id].mode.mode = 3; + mcpwm->timer[timer_id].timer_cfg1.timer_mod = 3; break; } } static inline mcpwm_timer_count_mode_t mcpwm_ll_timer_get_count_mode(mcpwm_dev_t *mcpwm, int timer_id) { - switch (mcpwm->timer[timer_id].mode.mode) { + switch (mcpwm->timer[timer_id].timer_cfg1.timer_mod) { case 0: return MCPWM_TIMER_COUNT_MODE_PAUSE; case 1: @@ -354,6 +357,9 @@ static inline mcpwm_timer_count_mode_t mcpwm_ll_timer_get_count_mode(mcpwm_dev_t return MCPWM_TIMER_COUNT_MODE_DOWN; case 3: return MCPWM_TIMER_COUNT_MODE_UP_DOWN; + default: + HAL_ASSERT(false && "unknown count mode"); + return mcpwm->timer[timer_id].timer_cfg1.timer_mod; } } @@ -361,19 +367,19 @@ static inline void mcpwm_ll_timer_set_execute_command(mcpwm_dev_t *mcpwm, int ti { switch (cmd) { case MCPWM_TIMER_STOP_AT_ZERO: - mcpwm->timer[timer_id].mode.start = 0; + mcpwm->timer[timer_id].timer_cfg1.timer_start = 0; break; case MCPWM_TIMER_STOP_AT_PEAK: - mcpwm->timer[timer_id].mode.start = 1; + mcpwm->timer[timer_id].timer_cfg1.timer_start = 1; break; case MCPWM_TIMER_START_NO_STOP: - mcpwm->timer[timer_id].mode.start = 2; + mcpwm->timer[timer_id].timer_cfg1.timer_start = 2; break; case MCPWM_TIMER_START_STOP_AT_ZERO: - mcpwm->timer[timer_id].mode.start = 3; + mcpwm->timer[timer_id].timer_cfg1.timer_start = 3; break; case MCPWM_TIMER_START_STOP_AT_PEAK: - mcpwm->timer[timer_id].mode.start = 4; + mcpwm->timer[timer_id].timer_cfg1.timer_start = 4; break; } } @@ -382,62 +388,65 @@ static inline uint32_t mcpwm_ll_timer_get_count_value(mcpwm_dev_t *mcpwm, int ti { // status.value saves the "next count value", so need an extra round up here to get the current count value according to count mode // timer is paused - if (mcpwm->timer[timer_id].mode.mode == 0) { - return mcpwm->timer[timer_id].status.value; + if (mcpwm->timer[timer_id].timer_cfg1.timer_mod == 0) { + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_status, timer_value); } - if (mcpwm->timer[timer_id].status.direction) { // down direction - return (mcpwm->timer[timer_id].status.value + 1) % (mcpwm->timer[timer_id].period.period + 1); + if (mcpwm->timer[timer_id].timer_status.timer_direction) { // down direction + return (HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_status, timer_value) + 1) % + (HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period) + 1); } // up direction - return (mcpwm->timer[timer_id].status.value + mcpwm->timer[timer_id].period.period) % (mcpwm->timer[timer_id].period.period + 1); + return (HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_status, timer_value) + + HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period)) % + (HAL_FORCE_READ_U32_REG_FIELD(mcpwm->timer[timer_id].timer_cfg0, timer_period) + 1); } static inline mcpwm_timer_direction_t mcpwm_ll_timer_get_count_direction(mcpwm_dev_t *mcpwm, int timer_id) { - return mcpwm->timer[timer_id].status.direction ? MCPWM_TIMER_DIRECTION_DOWN : MCPWM_TIMER_DIRECTION_UP; + return mcpwm->timer[timer_id].timer_status.timer_direction ? MCPWM_TIMER_DIRECTION_DOWN : MCPWM_TIMER_DIRECTION_UP; } static inline void mcpwm_ll_timer_enable_sync_input(mcpwm_dev_t *mcpwm, int timer_id, bool enable) { - mcpwm->timer[timer_id].sync.in_en = enable; + mcpwm->timer[timer_id].timer_sync.timer_synci_en = enable; } static inline void mcpwm_ll_timer_sync_out_penetrate(mcpwm_dev_t *mcpwm, int timer_id) { // sync_out is selected to sync_in - mcpwm->timer[timer_id].sync.out_sel = 0; + mcpwm->timer[timer_id].timer_sync.timer_synco_sel = 0; } static inline void mcpwm_ll_timer_sync_out_on_timer_event(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_event_t event) { if (event == MCPWM_TIMER_EVENT_ZERO) { - mcpwm->timer[timer_id].sync.out_sel = 1; + mcpwm->timer[timer_id].timer_sync.timer_synco_sel = 1; } else if (event == MCPWM_TIMER_EVENT_PEAK) { - mcpwm->timer[timer_id].sync.out_sel = 2; + mcpwm->timer[timer_id].timer_sync.timer_synco_sel = 2; } else { - HAL_ASSERT(false); + HAL_ASSERT(false && "unknown sync out event"); } } static inline void mcpwm_ll_timer_disable_sync_out(mcpwm_dev_t *mcpwm, int timer_id) { // sync_out will always be zero - mcpwm->timer[timer_id].sync.out_sel = 3; + mcpwm->timer[timer_id].timer_sync.timer_synco_sel = 3; } static inline void mcpwm_ll_timer_trigger_soft_sync(mcpwm_dev_t *mcpwm, int timer_id) { - mcpwm->timer[timer_id].sync.sync_sw = ~mcpwm->timer[timer_id].sync.sync_sw; + mcpwm->timer[timer_id].timer_sync.timer_sync_sw = ~mcpwm->timer[timer_id].timer_sync.timer_sync_sw; } static inline void mcpwm_ll_timer_set_sync_phase_value(mcpwm_dev_t *mcpwm, int timer_id, uint32_t phase_value) { - mcpwm->timer[timer_id].sync.timer_phase = phase_value; + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->timer[timer_id].timer_sync, timer_phase, phase_value); } static inline void mcpwm_ll_timer_set_sync_phase_direction(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_direction_t direction) { - mcpwm->timer[timer_id].sync.phase_direct = direction; + mcpwm->timer[timer_id].timer_sync.timer_phase_direction = direction; } static inline void mcpwm_ll_timer_set_gpio_synchro(mcpwm_dev_t *mcpwm, int timer, int gpio_sync_id) @@ -477,117 +486,117 @@ static inline void mcpwm_ll_operator_flush_shadow(mcpwm_dev_t *mcpwm, int operat static inline void mcpwm_ll_operator_select_timer(mcpwm_dev_t *mcpwm, int operator_id, int timer_id) { if (operator_id == 0) { - mcpwm->timer_sel.operator0_sel = timer_id; + mcpwm->operator_timersel.operator0_timersel = timer_id; } else if (operator_id == 1) { - mcpwm->timer_sel.operator1_sel = timer_id; + mcpwm->operator_timersel.operator1_timersel = timer_id; } else { - mcpwm->timer_sel.operator2_sel = timer_id; + mcpwm->operator_timersel.operator2_timersel = timer_id; } } static inline void mcpwm_ll_operator_update_compare_at_once(mcpwm_dev_t *mcpwm, int operator_id, int compare_id) { - mcpwm->channel[operator_id].cmpr_cfg.val &= ~(0x0F << (4 * compare_id)); + mcpwm->operators[operator_id].gen_stmp_cfg.val &= ~(0x0F << (4 * compare_id)); } static inline void mcpwm_ll_operator_enable_update_compare_on_tez(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].cmpr_cfg.val |= (1 << 0) << (4 * compare_id); + mcpwm->operators[operator_id].gen_stmp_cfg.val |= (1 << 0) << (4 * compare_id); } else { - mcpwm->channel[operator_id].cmpr_cfg.val &= ~((1 << 0) << (4 * compare_id)); + mcpwm->operators[operator_id].gen_stmp_cfg.val &= ~((1 << 0) << (4 * compare_id)); } } static inline void mcpwm_ll_operator_enable_update_compare_on_tep(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].cmpr_cfg.val |= (1 << 1) << (4 * compare_id); + mcpwm->operators[operator_id].gen_stmp_cfg.val |= (1 << 1) << (4 * compare_id); } else { - mcpwm->channel[operator_id].cmpr_cfg.val &= ~((1 << 1) << (4 * compare_id)); + mcpwm->operators[operator_id].gen_stmp_cfg.val &= ~((1 << 1) << (4 * compare_id)); } } static inline void mcpwm_ll_operator_enable_update_compare_on_sync(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].cmpr_cfg.val |= (1 << 2) << (4 * compare_id); + mcpwm->operators[operator_id].gen_stmp_cfg.val |= (1 << 2) << (4 * compare_id); } else { - mcpwm->channel[operator_id].cmpr_cfg.val &= ~((1 << 2) << (4 * compare_id)); + mcpwm->operators[operator_id].gen_stmp_cfg.val &= ~((1 << 2) << (4 * compare_id)); } } static inline void mcpwm_ll_operator_set_compare_value(mcpwm_dev_t *mcpwm, int operator_id, int compare_id, uint32_t compare_value) { - mcpwm->channel[operator_id].cmpr_value[compare_id].cmpr_val = compare_value; + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->operators[operator_id].timestamp[compare_id], gen, compare_value); } static inline uint32_t mcpwm_ll_operator_get_compare_value(mcpwm_dev_t *mcpwm, int operator_id, int compare_id) { - return mcpwm->channel[operator_id].cmpr_value[compare_id].cmpr_val; + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->operators[operator_id].timestamp[compare_id], gen); } static inline void mcpwm_ll_operator_update_action_at_once(mcpwm_dev_t *mcpwm, int operator_id) { - mcpwm->channel[operator_id].gen_cfg0.upmethod = 0; + mcpwm->operators[operator_id].gen_cfg0.gen_cfg_upmethod = 0; } static inline void mcpwm_ll_operator_enable_update_action_on_tez(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].gen_cfg0.upmethod |= 1 << 0; + mcpwm->operators[operator_id].gen_cfg0.gen_cfg_upmethod |= 1 << 0; } else { - mcpwm->channel[operator_id].gen_cfg0.upmethod &= ~(1 << 0); + mcpwm->operators[operator_id].gen_cfg0.gen_cfg_upmethod &= ~(1 << 0); } } static inline void mcpwm_ll_operator_enable_update_action_on_tep(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].gen_cfg0.upmethod |= 1 << 1; + mcpwm->operators[operator_id].gen_cfg0.gen_cfg_upmethod |= 1 << 1; } else { - mcpwm->channel[operator_id].gen_cfg0.upmethod &= ~(1 << 1); + mcpwm->operators[operator_id].gen_cfg0.gen_cfg_upmethod &= ~(1 << 1); } } static inline void mcpwm_ll_operator_enable_update_action_on_sync(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].gen_cfg0.upmethod |= 1 << 2; + mcpwm->operators[operator_id].gen_cfg0.gen_cfg_upmethod |= 1 << 2; } else { - mcpwm->channel[operator_id].gen_cfg0.upmethod &= ~(1 << 2); + mcpwm->operators[operator_id].gen_cfg0.gen_cfg_upmethod &= ~(1 << 2); } } static inline void mcpwm_ll_operator_set_trigger_gpio_fault(mcpwm_dev_t *mcpwm, int operator_id, int trig_id, int fault_id) { - mcpwm->channel[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id)); - mcpwm->channel[operator_id].gen_cfg0.val |= (fault_id << (4 + 3 * trig_id)); + mcpwm->operators[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id)); + mcpwm->operators[operator_id].gen_cfg0.val |= (fault_id << (4 + 3 * trig_id)); } static inline void mcpwm_ll_operator_set_trigger_timer_sync(mcpwm_dev_t *mcpwm, int operator_id, int trig_id) { // the timer here is not selectable, must be the one connected with the operator - mcpwm->channel[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id)); - mcpwm->channel[operator_id].gen_cfg0.val |= (3 << (4 + 3 * trig_id)); + mcpwm->operators[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id)); + mcpwm->operators[operator_id].gen_cfg0.val |= (3 << (4 + 3 * trig_id)); } /********************* Generator registers *******************/ static inline void mcpwm_ll_generator_reset_actions(mcpwm_dev_t *mcpwm, int operator_id, int generator_id) { - mcpwm->channel[operator_id].generator[generator_id].val = 0; + mcpwm->operators[operator_id].generator[generator_id].val = 0; } static inline void mcpwm_ll_generator_set_action_on_timer_event(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, mcpwm_timer_direction_t direction, mcpwm_timer_event_t event, mcpwm_generator_action_t action) { if (direction == MCPWM_TIMER_DIRECTION_UP) { // utez, utep - mcpwm->channel[operator_id].generator[generator_id].val &= ~(0x03 << (event * 2)); - mcpwm->channel[operator_id].generator[generator_id].val |= action << (event * 2); + mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (event * 2)); + mcpwm->operators[operator_id].generator[generator_id].val |= action << (event * 2); } else if (direction == MCPWM_TIMER_DIRECTION_DOWN) { // dtez, dtep - mcpwm->channel[operator_id].generator[generator_id].val &= ~(0x03 << (event * 2 + 12)); - mcpwm->channel[operator_id].generator[generator_id].val |= action << (event * 2 + 12); + mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (event * 2 + 12)); + mcpwm->operators[operator_id].generator[generator_id].val |= action << (event * 2 + 12); } } @@ -595,11 +604,11 @@ static inline void mcpwm_ll_generator_set_action_on_compare_event(mcpwm_dev_t *m mcpwm_timer_direction_t direction, int cmp_id, int action) { if (direction == MCPWM_TIMER_DIRECTION_UP) { // utea, uteb - mcpwm->channel[operator_id].generator[generator_id].val &= ~(0x03 << (cmp_id * 2 + 4)); - mcpwm->channel[operator_id].generator[generator_id].val |= action << (cmp_id * 2 + 4); + mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (cmp_id * 2 + 4)); + mcpwm->operators[operator_id].generator[generator_id].val |= action << (cmp_id * 2 + 4); } else if (direction == MCPWM_TIMER_DIRECTION_DOWN) { // dtea, dteb - mcpwm->channel[operator_id].generator[generator_id].val &= ~(0x03 << (cmp_id * 2 + 16)); - mcpwm->channel[operator_id].generator[generator_id].val |= action << (cmp_id * 2 + 16); + mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (cmp_id * 2 + 16)); + mcpwm->operators[operator_id].generator[generator_id].val |= action << (cmp_id * 2 + 16); } } @@ -607,58 +616,58 @@ static inline void mcpwm_ll_generator_set_action_on_trigger_event(mcpwm_dev_t *m mcpwm_timer_direction_t direction, int trig_id, int action) { if (direction == MCPWM_TIMER_DIRECTION_UP) { // ut0, ut1 - mcpwm->channel[operator_id].generator[generator_id].val &= ~(0x03 << (trig_id * 2 + 8)); - mcpwm->channel[operator_id].generator[generator_id].val |= action << (trig_id * 2 + 8); + mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (trig_id * 2 + 8)); + mcpwm->operators[operator_id].generator[generator_id].val |= action << (trig_id * 2 + 8); } else if (direction == MCPWM_TIMER_DIRECTION_DOWN) { // dt0, dt1 - mcpwm->channel[operator_id].generator[generator_id].val &= ~(0x03 << (trig_id * 2 + 20)); - mcpwm->channel[operator_id].generator[generator_id].val |= action << (trig_id * 2 + 20); + mcpwm->operators[operator_id].generator[generator_id].val &= ~(0x03 << (trig_id * 2 + 20)); + mcpwm->operators[operator_id].generator[generator_id].val |= action << (trig_id * 2 + 20); } } static inline void mcpwm_ll_gen_trigger_noncontinue_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id) { if (generator_id == 0) { - mcpwm->channel[operator_id].gen_force.a_nciforce = ~mcpwm->channel[operator_id].gen_force.a_nciforce; + mcpwm->operators[operator_id].gen_force.gen_a_nciforce = ~mcpwm->operators[operator_id].gen_force.gen_a_nciforce; } else { - mcpwm->channel[operator_id].gen_force.b_nciforce = ~mcpwm->channel[operator_id].gen_force.b_nciforce; + mcpwm->operators[operator_id].gen_force.gen_b_nciforce = ~mcpwm->operators[operator_id].gen_force.gen_b_nciforce; } } static inline void mcpwm_ll_gen_disable_continue_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id) { - mcpwm->channel[operator_id].gen_force.cntu_force_upmethod = 0; // update force method immediately + mcpwm->operators[operator_id].gen_force.gen_cntuforce_upmethod = 0; // update force method immediately if (generator_id == 0) { - mcpwm->channel[operator_id].gen_force.a_cntuforce_mode = 0; + mcpwm->operators[operator_id].gen_force.gen_a_cntuforce_mode = 0; } else { - mcpwm->channel[operator_id].gen_force.b_cntuforce_mode = 0; + mcpwm->operators[operator_id].gen_force.gen_b_cntuforce_mode = 0; } } static inline void mcpwm_ll_gen_disable_noncontinue_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id) { if (generator_id == 0) { - mcpwm->channel[operator_id].gen_force.a_nciforce_mode = 0; + mcpwm->operators[operator_id].gen_force.gen_a_nciforce_mode = 0; } else { - mcpwm->channel[operator_id].gen_force.b_nciforce_mode = 0; + mcpwm->operators[operator_id].gen_force.gen_b_nciforce_mode = 0; } } static inline void mcpwm_ll_gen_set_continue_force_level(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, int level) { - mcpwm->channel[operator_id].gen_force.cntu_force_upmethod = 0; // update force method immediately + mcpwm->operators[operator_id].gen_force.gen_cntuforce_upmethod = 0; // update force method immediately if (generator_id == 0) { - mcpwm->channel[operator_id].gen_force.a_cntuforce_mode = level + 1; + mcpwm->operators[operator_id].gen_force.gen_a_cntuforce_mode = level + 1; } else { - mcpwm->channel[operator_id].gen_force.b_cntuforce_mode = level + 1; + mcpwm->operators[operator_id].gen_force.gen_b_cntuforce_mode = level + 1; } } static inline void mcpwm_ll_gen_set_noncontinue_force_level(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, int level) { if (generator_id == 0) { - mcpwm->channel[operator_id].gen_force.a_nciforce_mode = level + 1; + mcpwm->operators[operator_id].gen_force.gen_a_nciforce_mode = level + 1; } else { - mcpwm->channel[operator_id].gen_force.b_nciforce_mode = level + 1; + mcpwm->operators[operator_id].gen_force.gen_b_nciforce_mode = level + 1; } } @@ -667,116 +676,116 @@ static inline void mcpwm_ll_gen_set_noncontinue_force_level(mcpwm_dev_t *mcpwm, static inline void mcpwm_ll_deadtime_resolution_to_timer(mcpwm_dev_t *mcpwm, int operator_id, bool same) { // whether to make the resolution of dead time delay module the same to the timer connected with operator - mcpwm->channel[operator_id].db_cfg.clk_sel = same; + mcpwm->operators[operator_id].dt_cfg.dt_clk_sel = same; } static inline void mcpwm_ll_deadtime_red_select_generator(mcpwm_dev_t *mcpwm, int operator_id, int generator) { - mcpwm->channel[operator_id].db_cfg.red_insel = generator; + mcpwm->operators[operator_id].dt_cfg.dt_red_insel = generator; } static inline void mcpwm_ll_deadtime_fed_select_generator(mcpwm_dev_t *mcpwm, int operator_id, int generator) { - mcpwm->channel[operator_id].db_cfg.fed_insel = generator; + mcpwm->operators[operator_id].dt_cfg.dt_fed_insel = generator; } static inline void mcpwm_ll_deadtime_bypass_path(mcpwm_dev_t *mcpwm, int operator_id, int path, bool bypass) { if (bypass) { - mcpwm->channel[operator_id].db_cfg.val |= 1 << (path + 15); + mcpwm->operators[operator_id].dt_cfg.val |= 1 << (path + 15); } else { - mcpwm->channel[operator_id].db_cfg.val &= ~(1 << (path + 15)); + mcpwm->operators[operator_id].dt_cfg.val &= ~(1 << (path + 15)); } } static inline void mcpwm_ll_deadtime_invert_outpath(mcpwm_dev_t *mcpwm, int operator_id, int path, bool invert) { if (invert) { - mcpwm->channel[operator_id].db_cfg.val |= 1 << (path + 13); + mcpwm->operators[operator_id].dt_cfg.val |= 1 << (path + 13); } else { - mcpwm->channel[operator_id].db_cfg.val &= ~(1 << (path + 13)); + mcpwm->operators[operator_id].dt_cfg.val &= ~(1 << (path + 13)); } } static inline void mcpwm_ll_deadtime_swap_out_path(mcpwm_dev_t *mcpwm, int operator_id, int path, bool swap) { if (swap) { - mcpwm->channel[operator_id].db_cfg.val |= 1 << (path + 9); + mcpwm->operators[operator_id].dt_cfg.val |= 1 << (path + 9); } else { - mcpwm->channel[operator_id].db_cfg.val &= ~(1 << (path + 9)); + mcpwm->operators[operator_id].dt_cfg.val &= ~(1 << (path + 9)); } } static inline void mcpwm_ll_deadtime_enable_deb(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { - mcpwm->channel[operator_id].db_cfg.deb_mode = enable; + mcpwm->operators[operator_id].dt_cfg.dt_deb_mode = enable; } static inline uint32_t mcpwm_ll_deadtime_get_switch_topology(mcpwm_dev_t *mcpwm, int operator_id) { - return (mcpwm->channel[operator_id].db_cfg.deb_mode << 8) | (mcpwm->channel[operator_id].db_cfg.b_outswap << 7) | - (mcpwm->channel[operator_id].db_cfg.a_outswap << 6) | (mcpwm->channel[operator_id].db_cfg.fed_insel << 5) | - (mcpwm->channel[operator_id].db_cfg.red_insel << 4) | (mcpwm->channel[operator_id].db_cfg.fed_outinvert << 3) | - (mcpwm->channel[operator_id].db_cfg.red_outinvert << 2) | (mcpwm->channel[operator_id].db_cfg.a_outbypass << 1) | - (mcpwm->channel[operator_id].db_cfg.b_outbypass << 0); + return (mcpwm->operators[operator_id].dt_cfg.dt_deb_mode << 8) | (mcpwm->operators[operator_id].dt_cfg.dt_b_outswap << 7) | + (mcpwm->operators[operator_id].dt_cfg.dt_a_outswap << 6) | (mcpwm->operators[operator_id].dt_cfg.dt_fed_insel << 5) | + (mcpwm->operators[operator_id].dt_cfg.dt_red_insel << 4) | (mcpwm->operators[operator_id].dt_cfg.dt_fed_outinvert << 3) | + (mcpwm->operators[operator_id].dt_cfg.dt_red_outinvert << 2) | (mcpwm->operators[operator_id].dt_cfg.dt_a_outbypass << 1) | + (mcpwm->operators[operator_id].dt_cfg.dt_b_outbypass << 0); } static inline void mcpwm_ll_deadtime_set_falling_delay(mcpwm_dev_t *mcpwm, int operator_id, uint32_t fed) { - mcpwm->channel[operator_id].db_fed_cfg.fed = fed - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->operators[operator_id].dt_fed_cfg, dt_fed, fed - 1); } static inline uint32_t mcpwm_ll_deadtime_get_falling_delay(mcpwm_dev_t *mcpwm, int operator_id) { - return mcpwm->channel[operator_id].db_fed_cfg.fed + 1; + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->operators[operator_id].dt_fed_cfg, dt_fed) + 1; } static inline void mcpwm_ll_deadtime_set_rising_delay(mcpwm_dev_t *mcpwm, int operator_id, uint32_t red) { - mcpwm->channel[operator_id].db_red_cfg.red = red - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->operators[operator_id].dt_red_cfg, dt_red, red - 1); } static inline uint32_t mcpwm_ll_deadtime_get_rising_delay(mcpwm_dev_t *mcpwm, int operator_id) { - return mcpwm->channel[operator_id].db_red_cfg.red + 1; + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->operators[operator_id].dt_red_cfg, dt_red) + 1; } static inline void mcpwm_ll_deadtime_update_delay_at_once(mcpwm_dev_t *mcpwm, int operator_id) { - mcpwm->channel[operator_id].db_cfg.fed_upmethod = 0; - mcpwm->channel[operator_id].db_cfg.red_upmethod = 0; + mcpwm->operators[operator_id].dt_cfg.dt_fed_upmethod = 0; + mcpwm->operators[operator_id].dt_cfg.dt_red_upmethod = 0; } static inline void mcpwm_ll_deadtime_enable_update_delay_on_tez(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].db_cfg.fed_upmethod |= 1 << 0; - mcpwm->channel[operator_id].db_cfg.red_upmethod |= 1 << 0; + mcpwm->operators[operator_id].dt_cfg.dt_fed_upmethod |= 1 << 0; + mcpwm->operators[operator_id].dt_cfg.dt_red_upmethod |= 1 << 0; } else { - mcpwm->channel[operator_id].db_cfg.fed_upmethod &= ~(1 << 0); - mcpwm->channel[operator_id].db_cfg.red_upmethod &= ~(1 << 0); + mcpwm->operators[operator_id].dt_cfg.dt_fed_upmethod &= ~(1 << 0); + mcpwm->operators[operator_id].dt_cfg.dt_red_upmethod &= ~(1 << 0); } } static inline void mcpwm_ll_deadtime_enable_update_delay_on_tep(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].db_cfg.fed_upmethod |= 1 << 1; - mcpwm->channel[operator_id].db_cfg.red_upmethod |= 1 << 1; + mcpwm->operators[operator_id].dt_cfg.dt_fed_upmethod |= 1 << 1; + mcpwm->operators[operator_id].dt_cfg.dt_red_upmethod |= 1 << 1; } else { - mcpwm->channel[operator_id].db_cfg.fed_upmethod &= ~(1 << 1); - mcpwm->channel[operator_id].db_cfg.red_upmethod &= ~(1 << 1); + mcpwm->operators[operator_id].dt_cfg.dt_fed_upmethod &= ~(1 << 1); + mcpwm->operators[operator_id].dt_cfg.dt_red_upmethod &= ~(1 << 1); } } static inline void mcpwm_ll_deadtime_enable_update_delay_on_sync(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].db_cfg.fed_upmethod |= 1 << 2; - mcpwm->channel[operator_id].db_cfg.red_upmethod |= 1 << 2; + mcpwm->operators[operator_id].dt_cfg.dt_fed_upmethod |= 1 << 2; + mcpwm->operators[operator_id].dt_cfg.dt_red_upmethod |= 1 << 2; } else { - mcpwm->channel[operator_id].db_cfg.fed_upmethod &= ~(1 << 2); - mcpwm->channel[operator_id].db_cfg.red_upmethod &= ~(1 << 2); + mcpwm->operators[operator_id].dt_cfg.dt_fed_upmethod &= ~(1 << 2); + mcpwm->operators[operator_id].dt_cfg.dt_red_upmethod &= ~(1 << 2); } } @@ -784,47 +793,47 @@ static inline void mcpwm_ll_deadtime_enable_update_delay_on_sync(mcpwm_dev_t *mc static inline void mcpwm_ll_carrier_enable(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { - mcpwm->channel[operator_id].carrier_cfg.en = enable; + mcpwm->operators[operator_id].carrier_cfg.carrier_en = enable; } static inline void mcpwm_ll_carrier_set_prescale(mcpwm_dev_t *mcpwm, int operator_id, uint8_t prescale) { - mcpwm->channel[operator_id].carrier_cfg.prescale = prescale - 1; + mcpwm->operators[operator_id].carrier_cfg.carrier_prescale = prescale - 1; } static inline uint8_t mcpwm_ll_carrier_get_prescale(mcpwm_dev_t *mcpwm, int operator_id) { - return mcpwm->channel[operator_id].carrier_cfg.prescale + 1; + return mcpwm->operators[operator_id].carrier_cfg.carrier_prescale + 1; } static inline void mcpwm_ll_carrier_set_duty(mcpwm_dev_t *mcpwm, int operator_id, uint8_t carrier_duty) { - mcpwm->channel[operator_id].carrier_cfg.duty = carrier_duty; + mcpwm->operators[operator_id].carrier_cfg.carrier_duty = carrier_duty; } static inline uint8_t mcpwm_ll_carrier_get_duty(mcpwm_dev_t *mcpwm, int operator_id) { - return mcpwm->channel[operator_id].carrier_cfg.duty; + return mcpwm->operators[operator_id].carrier_cfg.carrier_duty; } static inline void mcpwm_ll_carrier_out_invert(mcpwm_dev_t *mcpwm, int operator_id, bool invert) { - mcpwm->channel[operator_id].carrier_cfg.out_invert = invert; + mcpwm->operators[operator_id].carrier_cfg.carrier_out_invert = invert; } static inline void mcpwm_ll_carrier_in_invert(mcpwm_dev_t *mcpwm, int operator_id, bool invert) { - mcpwm->channel[operator_id].carrier_cfg.in_invert = invert; + mcpwm->operators[operator_id].carrier_cfg.carrier_in_invert = invert; } static inline void mcpwm_ll_carrier_set_oneshot_width(mcpwm_dev_t *mcpwm, int operator_id, uint8_t pulse_width) { - mcpwm->channel[operator_id].carrier_cfg.oshtwth = pulse_width - 1; + mcpwm->operators[operator_id].carrier_cfg.carrier_oshtwth = pulse_width - 1; } static inline uint8_t mcpwm_ll_carrier_get_oneshot_width(mcpwm_dev_t *mcpwm, int operator_id) { - return mcpwm->channel[operator_id].carrier_cfg.oshtwth + 1; + return mcpwm->operators[operator_id].carrier_cfg.carrier_oshtwth + 1; } /********************* Fault detector registers *******************/ @@ -850,157 +859,159 @@ static inline void mcpwm_ll_fault_set_active_level(mcpwm_dev_t *mcpwm, int fault static inline void mcpwm_ll_fault_clear_ost(mcpwm_dev_t *mcpwm, int operator_id) { // a posedge can clear the ost fault status - mcpwm->channel[operator_id].tz_cfg1.clr_ost = 0; - mcpwm->channel[operator_id].tz_cfg1.clr_ost = 1; + mcpwm->operators[operator_id].fh_cfg1.fh_clr_ost = 0; + mcpwm->operators[operator_id].fh_cfg1.fh_clr_ost = 1; } static inline void mcpwm_ll_fault_enable_oneshot_mode(mcpwm_dev_t *mcpwm, int operator_id, int fault_sig, bool enable) { - mcpwm->channel[operator_id].tz_cfg0.val &= ~(1 << (7 - fault_sig)); - mcpwm->channel[operator_id].tz_cfg0.val |= (enable << (7 - fault_sig)); + mcpwm->operators[operator_id].fh_cfg0.val &= ~(1 << (7 - fault_sig)); + mcpwm->operators[operator_id].fh_cfg0.val |= (enable << (7 - fault_sig)); } static inline void mcpwm_ll_fault_enable_cbc_mode(mcpwm_dev_t *mcpwm, int operator_id, int fault_sig, bool enable) { - mcpwm->channel[operator_id].tz_cfg0.val &= ~(1 << (3 - fault_sig)); - mcpwm->channel[operator_id].tz_cfg0.val |= (enable << (3 - fault_sig)); + mcpwm->operators[operator_id].fh_cfg0.val &= ~(1 << (3 - fault_sig)); + mcpwm->operators[operator_id].fh_cfg0.val |= (enable << (3 - fault_sig)); } static inline void mcpwm_ll_fault_enable_cbc_refresh_on_tez(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].tz_cfg1.val |= 1 << 1; + mcpwm->operators[operator_id].fh_cfg1.val |= 1 << 1; } else { - mcpwm->channel[operator_id].tz_cfg1.val &= ~(1 << 1); + mcpwm->operators[operator_id].fh_cfg1.val &= ~(1 << 1); } } static inline void mcpwm_ll_fault_enable_cbc_refresh_on_tep(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { if (enable) { - mcpwm->channel[operator_id].tz_cfg1.val |= 1 << 2; + mcpwm->operators[operator_id].fh_cfg1.val |= 1 << 2; } else { - mcpwm->channel[operator_id].tz_cfg1.val &= ~(1 << 2); + mcpwm->operators[operator_id].fh_cfg1.val &= ~(1 << 2); } } static inline void mcpwm_ll_fault_enable_sw_cbc(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { - mcpwm->channel[operator_id].tz_cfg0.sw_cbc = enable; + mcpwm->operators[operator_id].fh_cfg0.fh_sw_cbc = enable; } static inline void mcpwm_ll_fault_enable_sw_oneshot(mcpwm_dev_t *mcpwm, int operator_id, bool enable) { - mcpwm->channel[operator_id].tz_cfg0.sw_ost = enable; + mcpwm->operators[operator_id].fh_cfg0.fh_sw_ost = enable; } static inline void mcpwm_ll_fault_trigger_sw_cbc(mcpwm_dev_t *mcpwm, int operator_id) { - mcpwm->channel[operator_id].tz_cfg1.force_cbc = ~mcpwm->channel[operator_id].tz_cfg1.force_cbc; + mcpwm->operators[operator_id].fh_cfg1.fh_force_cbc = ~mcpwm->operators[operator_id].fh_cfg1.fh_force_cbc; } static inline void mcpwm_ll_fault_trigger_sw_ost(mcpwm_dev_t *mcpwm, int operator_id) { - mcpwm->channel[operator_id].tz_cfg1.force_ost = ~mcpwm->channel[operator_id].tz_cfg1.force_ost; + mcpwm->operators[operator_id].fh_cfg1.fh_force_ost = ~mcpwm->operators[operator_id].fh_cfg1.fh_force_ost; } static inline void mcpwm_ll_generator_set_action_on_trip_event(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, mcpwm_timer_direction_t direction, mcpwm_trip_type_t trip, int action) { if (direction == MCPWM_TIMER_DIRECTION_UP) { - mcpwm->channel[operator_id].tz_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * trip + 2)); - mcpwm->channel[operator_id].tz_cfg0.val |= action << (8 + 8 * generator_id + 4 * trip + 2); + mcpwm->operators[operator_id].fh_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * trip + 2)); + mcpwm->operators[operator_id].fh_cfg0.val |= action << (8 + 8 * generator_id + 4 * trip + 2); } else if (direction == MCPWM_TIMER_DIRECTION_DOWN) { - mcpwm->channel[operator_id].tz_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * trip)); - mcpwm->channel[operator_id].tz_cfg0.val |= action << (8 + 8 * generator_id + 4 * trip); + mcpwm->operators[operator_id].fh_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * trip)); + mcpwm->operators[operator_id].fh_cfg0.val |= action << (8 + 8 * generator_id + 4 * trip); } } static inline bool mcpwm_ll_fault_is_ost_on(mcpwm_dev_t *mcpwm, int op) { - return mcpwm->channel[op].tz_status.ost_on; + return mcpwm->operators[op].fh_status.fh_ost_on; } static inline bool mcpwm_ll_fault_is_cbc_on(mcpwm_dev_t *mcpwm, int op) { - return mcpwm->channel[op].tz_status.cbc_on; + return mcpwm->operators[op].fh_status.fh_cbc_on; } /********************* Capture registers *******************/ static inline void mcpwm_ll_capture_enable_timer(mcpwm_dev_t *mcpwm, bool enable) { - mcpwm->cap_timer_cfg.timer_en = enable; + mcpwm->cap_timer_cfg.cap_timer_en = enable; } static inline void mcpwm_ll_capture_enable_channel(mcpwm_dev_t *mcpwm, int channel, bool enable) { - mcpwm->cap_cfg_ch[channel].en = enable; + mcpwm->cap_chn_cfg[channel].capn_en = enable; } static inline void mcpwm_ll_capture_set_sync_phase_value(mcpwm_dev_t *mcpwm, uint32_t phase_value) { - mcpwm->cap_timer_phase = phase_value; + mcpwm->cap_timer_phase.cap_timer_phase = phase_value; } static inline uint32_t mcpwm_ll_capture_get_sync_phase_value(mcpwm_dev_t *mcpwm) { - return mcpwm->cap_timer_phase; + return mcpwm->cap_timer_phase.cap_timer_phase; } static inline void mcpwm_ll_capture_enable_timer_sync(mcpwm_dev_t *mcpwm, bool enable) { - mcpwm->cap_timer_cfg.synci_en = enable; + mcpwm->cap_timer_cfg.cap_synci_en = enable; } static inline void mcpwm_ll_capture_set_internal_timer_synchro(mcpwm_dev_t *mcpwm, int sync_out_timer) { - mcpwm->cap_timer_cfg.synci_sel = sync_out_timer + 1; + mcpwm->cap_timer_cfg.cap_synci_sel = sync_out_timer + 1; } static inline void mcpwm_ll_capture_set_external_synchro(mcpwm_dev_t *mcpwm, int extern_synchro) { - mcpwm->cap_timer_cfg.synci_sel = extern_synchro + 4; + mcpwm->cap_timer_cfg.cap_synci_sel = extern_synchro + 4; } static inline void mcpwm_ll_capture_trigger_sw_sync(mcpwm_dev_t *mcpwm) { - mcpwm->cap_timer_cfg.sync_sw = 1; // auto clear + mcpwm->cap_timer_cfg.cap_sync_sw = 1; // auto clear } static inline void mcpwm_ll_capture_enable_posedge(mcpwm_dev_t *mcpwm, int channel, bool enable) { if (enable) { - mcpwm->cap_cfg_ch[channel].val |= 1 << 2; + mcpwm->cap_chn_cfg[channel].val |= 1 << 2; } else { - mcpwm->cap_cfg_ch[channel].val &= ~(1 << 2); + mcpwm->cap_chn_cfg[channel].val &= ~(1 << 2); } } static inline void mcpwm_ll_capture_enable_negedge(mcpwm_dev_t *mcpwm, int channel, bool enable) { if (enable) { - mcpwm->cap_cfg_ch[channel].val |= 1 << 1; + mcpwm->cap_chn_cfg[channel].val |= 1 << 1; } else { - mcpwm->cap_cfg_ch[channel].val &= ~(1 << 1); + mcpwm->cap_chn_cfg[channel].val &= ~(1 << 1); } } static inline void mcpwm_ll_invert_input(mcpwm_dev_t *mcpwm, int channel, bool invert) { - mcpwm->cap_cfg_ch[channel].in_invert = invert; + mcpwm->cap_chn_cfg[channel].capn_in_invert = invert; } static inline void mcpwm_ll_trigger_soft_capture(mcpwm_dev_t *mcpwm, int channel) { - mcpwm->cap_cfg_ch[channel].sw = 1; // auto clear + mcpwm->cap_chn_cfg[channel].capn_sw = 1; // auto clear } +__attribute__((always_inline)) static inline uint32_t mcpwm_ll_capture_get_value(mcpwm_dev_t *mcpwm, int channel) { - return mcpwm->cap_val_ch[channel]; + return mcpwm->cap_chn[channel].capn_value; } +__attribute__((always_inline)) static inline bool mcpwm_ll_capture_is_negedge(mcpwm_dev_t *mcpwm, int channel) { return mcpwm->cap_status.val & (1 << channel) ? true : false; @@ -1008,12 +1019,12 @@ static inline bool mcpwm_ll_capture_is_negedge(mcpwm_dev_t *mcpwm, int channel) static inline void mcpwm_ll_capture_set_prescale(mcpwm_dev_t *mcpwm, int channel, uint32_t prescale) { - mcpwm->cap_cfg_ch[channel].prescale = prescale - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(mcpwm->cap_chn_cfg[channel], capn_prescale, prescale - 1); } static inline uint32_t mcpwm_ll_capture_get_prescale(mcpwm_dev_t *mcpwm, int channel) { - return mcpwm->cap_cfg_ch[channel].prescale + 1; + return HAL_FORCE_READ_U32_REG_FIELD(mcpwm->cap_chn_cfg[channel], capn_prescale) + 1; } #ifdef __cplusplus diff --git a/components/hal/esp32s3/include/hal/mwdt_ll.h b/components/hal/esp32s3/include/hal/mwdt_ll.h index 0d34e2cc87..c15d7b8cd5 100644 --- a/components/hal/esp32s3/include/hal/mwdt_ll.h +++ b/components/hal/esp32s3/include/hal/mwdt_ll.h @@ -23,7 +23,9 @@ extern "C" { #include #include +#include "hal/misc.h" #include "soc/timer_periph.h" +#include "soc/timer_group_struct.h" #include "hal/wdt_types.h" #include "esp_attr.h" @@ -219,7 +221,7 @@ FORCE_INLINE_ATTR void mwdt_ll_set_flashboot_en(timg_dev_t *hw, bool enable) */ FORCE_INLINE_ATTR void mwdt_ll_set_prescaler(timg_dev_t *hw, uint32_t prescaler) { - hw->wdtconfig1.wdt_clk_prescale = prescaler; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->wdtconfig1, wdt_clk_prescale, prescaler); } /** diff --git a/components/hal/esp32s3/include/hal/pcnt_ll.h b/components/hal/esp32s3/include/hal/pcnt_ll.h index ffa4956e45..a8b32df50c 100644 --- a/components/hal/esp32s3/include/hal/pcnt_ll.h +++ b/components/hal/esp32s3/include/hal/pcnt_ll.h @@ -1,4 +1,4 @@ -// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD +// Copyright 2015-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. @@ -22,75 +22,67 @@ #pragma once -#include "soc/pcnt_periph.h" +#include +#include +#include "soc/pcnt_struct.h" #include "hal/pcnt_types.h" #ifdef __cplusplus extern "C" { #endif -// Get PCNT hardware instance with giving pcnt num #define PCNT_LL_GET_HW(num) (((num) == 0) ? (&PCNT) : NULL) +#define PCNT_LL_MAX_GLITCH_WIDTH 1023 + +typedef enum { + PCNT_LL_EVENT_THRES1, + PCNT_LL_EVENT_THRES0, + PCNT_LL_EVENT_LOW_LIMIT, + PCNT_LL_EVENT_HIGH_LIMIT, + PCNT_LL_EVENT_ZERO_CROSS, + PCNT_LL_EVENT_MAX +} pcnt_ll_event_id_t; + +#define PCNT_LL_EVENT_MASK ((1 << PCNT_LL_EVENT_MAX) - 1) /** - * @brief Set PCNT channel edge mode + * @brief Set PCNT channel edge action * * @param hw Peripheral PCNT hardware instance address. * @param unit PCNT unit number * @param channel PCNT channel number - * @param pos_mode Counter mode when detecting positive edge - * @param neg_mode Counter mode when detecting negative edge + * @param pos_act Counter action when detecting positive edge + * @param neg_act Counter action when detecting negative edge */ -static inline void pcnt_ll_set_edge_mode(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_channel_t channel, pcnt_count_mode_t pos_mode, pcnt_count_mode_t neg_mode) +static inline void pcnt_ll_set_edge_action(pcnt_dev_t *hw, uint32_t unit, uint32_t channel, pcnt_channel_edge_action_t pos_act, pcnt_channel_edge_action_t neg_act) { - typeof(hw->conf_unit[unit].conf0) conf0_reg = hw->conf_unit[unit].conf0; if (channel == 0) { - conf0_reg.ch0_pos_mode = pos_mode; - conf0_reg.ch0_neg_mode = neg_mode; + hw->conf_unit[unit].conf0.ch0_pos_mode_un = pos_act; + hw->conf_unit[unit].conf0.ch0_neg_mode_un = neg_act; } else { - conf0_reg.ch1_pos_mode = pos_mode; - conf0_reg.ch1_neg_mode = neg_mode; + hw->conf_unit[unit].conf0.ch1_pos_mode_un = pos_act; + hw->conf_unit[unit].conf0.ch1_neg_mode_un = neg_act; } - hw->conf_unit[unit].conf0 = conf0_reg; } /** - * @brief Set PCNT channel level mode + * @brief Set PCNT channel level action * * @param hw Peripheral PCNT hardware instance address. * @param unit PCNT unit number * @param channel PCNT channel number - * @param hctrl_mode Counter mode when control signal is high level - * @param lctrl_mode Counter mode when control signal is low level + * @param high_act Counter action when control signal is high level + * @param low_act Counter action when control signal is low level */ -static inline void pcnt_ll_set_level_mode(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_channel_t channel, pcnt_ctrl_mode_t hctrl_mode, pcnt_ctrl_mode_t lctrl_mode) +static inline void pcnt_ll_set_level_action(pcnt_dev_t *hw, uint32_t unit, uint32_t channel, pcnt_channel_level_action_t high_act, pcnt_channel_level_action_t low_act) { - typeof(hw->conf_unit[unit].conf0) conf0_reg = hw->conf_unit[unit].conf0; if (channel == 0) { - conf0_reg.ch0_hctrl_mode = hctrl_mode; - conf0_reg.ch0_lctrl_mode = lctrl_mode; + hw->conf_unit[unit].conf0.ch0_hctrl_mode_un = high_act; + hw->conf_unit[unit].conf0.ch0_lctrl_mode_un = low_act; } else { - conf0_reg.ch1_hctrl_mode = hctrl_mode; - conf0_reg.ch1_lctrl_mode = lctrl_mode; + hw->conf_unit[unit].conf0.ch1_hctrl_mode_un = high_act; + hw->conf_unit[unit].conf0.ch1_lctrl_mode_un = low_act; } - hw->conf_unit[unit].conf0 = conf0_reg; -} - -/** - * @brief Set PCNT counter mode - * - * @param hw Peripheral PCNT hardware instance address. - * @param unit PCNT unit number - * @param channel PCNT channel number - * @param pos_mode Counter mode when detecting positive edge - * @param neg_mode Counter mode when detecting negative edge - * @param hctrl_mode Counter mode when control signal is high level - * @param lctrl_mode Counter mode when control signal is low level - */ -static inline void pcnt_ll_set_mode(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_channel_t channel, pcnt_count_mode_t pos_mode, pcnt_count_mode_t neg_mode, pcnt_ctrl_mode_t hctrl_mode, pcnt_ctrl_mode_t lctrl_mode) -{ - pcnt_ll_set_edge_mode(hw, unit, channel, pos_mode, neg_mode); - pcnt_ll_set_level_mode(hw, unit, channel, hctrl_mode, lctrl_mode); } /** @@ -98,11 +90,13 @@ static inline void pcnt_ll_set_mode(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_chann * * @param hw Peripheral PCNT hardware instance address. * @param unit Pulse Counter unit number - * @param count Pointer to accept counter value + * @return PCNT count value (a signed integer) */ -static inline void pcnt_ll_get_counter_value(pcnt_dev_t *hw, pcnt_unit_t unit, int16_t *count) +static inline int pcnt_ll_get_count(pcnt_dev_t *hw, uint32_t unit) { - *count = (int16_t) hw->cnt_unit[unit].cnt_val; + pcnt_un_cnt_reg_t cnt_reg = hw->cnt_unit[unit]; + int16_t value = cnt_reg.pulse_cnt_un; + return value; } /** @@ -111,69 +105,60 @@ static inline void pcnt_ll_get_counter_value(pcnt_dev_t *hw, pcnt_unit_t unit, i * @param hw Peripheral PCNT hardware instance address. * @param unit PCNT unit number */ -static inline void pcnt_ll_counter_pause(pcnt_dev_t *hw, pcnt_unit_t unit) +static inline void pcnt_ll_stop_count(pcnt_dev_t *hw, uint32_t unit) { - hw->ctrl.val |= BIT(PCNT_CNT_PAUSE_U0_S + (unit * 2)); + hw->ctrl.val |= 1 << (2 * unit + 1); } /** * @brief Resume counting for PCNT counter * * @param hw Peripheral PCNT hardware instance address. - * @param unit PCNT unit number, select from pcnt_unit_t + * @param unit PCNT unit number, select from uint32_t */ -static inline void pcnt_ll_counter_resume(pcnt_dev_t *hw, pcnt_unit_t unit) +static inline void pcnt_ll_start_count(pcnt_dev_t *hw, uint32_t unit) { - hw->ctrl.val &= (~(BIT(PCNT_CNT_PAUSE_U0_S + (unit * 2)))); + hw->ctrl.val &= ~(1 << (2 * unit + 1)); } /** - * @brief Clear and reset PCNT counter value to zero + * @brief Clear PCNT counter value to zero * * @param hw Peripheral PCNT hardware instance address. - * @param unit PCNT unit number, select from pcnt_unit_t + * @param unit PCNT unit number, select from uint32_t */ -static inline void pcnt_ll_counter_clear(pcnt_dev_t *hw, pcnt_unit_t unit) +static inline void pcnt_ll_clear_count(pcnt_dev_t *hw, uint32_t unit) { - uint32_t reset_bit = BIT(PCNT_PULSE_CNT_RST_U0_S + (unit * 2)); - hw->ctrl.val |= reset_bit; - hw->ctrl.val &= ~reset_bit; + hw->ctrl.val |= 1 << (2 * unit); + hw->ctrl.val &= ~(1 << (2 * unit)); } /** * @brief Enable PCNT interrupt for PCNT unit - * @note - * Each Pulse counter unit has five watch point events that share the same interrupt. - * Configure events with pcnt_event_enable() and pcnt_event_disable() + * @note Each PCNT unit has five watch point events that share the same interrupt bit. * * @param hw Peripheral PCNT hardware instance address. - * @param unit PCNT unit number + * @param unit_mask PCNT units mask + * @param enable True to enable interrupt, False to disable interrupt */ -static inline void pcnt_ll_intr_enable(pcnt_dev_t *hw, pcnt_unit_t unit) +static inline void pcnt_ll_enable_intr(pcnt_dev_t *hw, uint32_t unit_mask, bool enable) { - hw->int_ena.val |= BIT(PCNT_CNT_THR_EVENT_U0_INT_ENA_S + unit); -} - -/** - * @brief Disable PCNT interrupt for PCNT unit - * - * @param hw Peripheral PCNT hardware instance address. - * @param unit PCNT unit number - */ -static inline void pcnt_ll_intr_disable(pcnt_dev_t *hw, pcnt_unit_t unit) -{ - hw->int_ena.val &= (~(BIT(PCNT_CNT_THR_EVENT_U0_INT_ENA_S + unit))); + if (enable) { + hw->int_ena.val |= unit_mask; + } else { + hw->int_ena.val &= ~unit_mask; + } } /** * @brief Get PCNT interrupt status * * @param hw Peripheral PCNT hardware instance address. - * @param status Pointer to accept value + * @return Interrupt status word */ -static inline void pcnt_ll_get_intr_status(pcnt_dev_t *hw, uint32_t *status) +__attribute__((always_inline)) static inline uint32_t pcnt_ll_get_intr_status(pcnt_dev_t *hw) { - *status = hw->int_st.val; + return hw->int_st.val; } /** @@ -182,163 +167,241 @@ static inline void pcnt_ll_get_intr_status(pcnt_dev_t *hw, uint32_t *status) * @param hw Peripheral PCNT hardware instance address. * @param status value to clear interrupt status */ -static inline void pcnt_ll_clear_intr_status(pcnt_dev_t *hw, uint32_t status) +__attribute__((always_inline)) static inline void pcnt_ll_clear_intr_status(pcnt_dev_t *hw, uint32_t status) { hw->int_clr.val = status; } /** - * @brief Enable PCNT event of PCNT unit + * @brief Enable PCNT high limit event * * @param hw Peripheral PCNT hardware instance address. * @param unit PCNT unit number - * @param evt_type Watch point event type. - * All enabled events share the same interrupt (one interrupt per pulse counter unit). + * @param enable true to enable, false to disable */ -static inline void pcnt_ll_event_enable(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_evt_type_t evt_type) +static inline void pcnt_ll_enable_high_limit_event(pcnt_dev_t *hw, uint32_t unit, bool enable) { - if (evt_type == PCNT_EVT_L_LIM) { - hw->conf_unit[unit].conf0.thr_l_lim_en = 1; - } else if (evt_type == PCNT_EVT_H_LIM) { - hw->conf_unit[unit].conf0.thr_h_lim_en = 1; - } else if (evt_type == PCNT_EVT_THRES_0) { - hw->conf_unit[unit].conf0.thr_thres0_en = 1; - } else if (evt_type == PCNT_EVT_THRES_1) { - hw->conf_unit[unit].conf0.thr_thres1_en = 1; - } else if (evt_type == PCNT_EVT_ZERO) { - hw->conf_unit[unit].conf0.thr_zero_en = 1; - } + hw->conf_unit[unit].conf0.thr_h_lim_en_un = enable; } /** - * @brief Disable PCNT event of PCNT unit + * @brief Enable PCNT low limit event * * @param hw Peripheral PCNT hardware instance address. * @param unit PCNT unit number - * @param evt_type Watch point event type. - * All enabled events share the same interrupt (one interrupt per pulse counter unit). + * @param enable true to enable, false to disable */ -static inline void pcnt_ll_event_disable(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_evt_type_t evt_type) +static inline void pcnt_ll_enable_low_limit_event(pcnt_dev_t *hw, uint32_t unit, bool enable) { - if (evt_type == PCNT_EVT_L_LIM) { - hw->conf_unit[unit].conf0.thr_l_lim_en = 0; - } else if (evt_type == PCNT_EVT_H_LIM) { - hw->conf_unit[unit].conf0.thr_h_lim_en = 0; - } else if (evt_type == PCNT_EVT_THRES_0) { - hw->conf_unit[unit].conf0.thr_thres0_en = 0; - } else if (evt_type == PCNT_EVT_THRES_1) { - hw->conf_unit[unit].conf0.thr_thres1_en = 0; - } else if (evt_type == PCNT_EVT_ZERO) { - hw->conf_unit[unit].conf0.thr_zero_en = 0; - } + hw->conf_unit[unit].conf0.thr_l_lim_en_un = enable; } /** - * @brief Set PCNT event value of PCNT unit + * @brief Enable PCNT zero cross event * * @param hw Peripheral PCNT hardware instance address. * @param unit PCNT unit number - * @param evt_type Watch point event type. - * All enabled events share the same interrupt (one interrupt per pulse counter unit). - * - * @param value Counter value for PCNT event + * @param enable true to enable, false to disable */ -static inline void pcnt_ll_set_event_value(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t value) +static inline void pcnt_ll_enable_zero_cross_event(pcnt_dev_t *hw, uint32_t unit, bool enable) { - if (evt_type == PCNT_EVT_L_LIM) { - hw->conf_unit[unit].conf2.cnt_l_lim = value; - } else if (evt_type == PCNT_EVT_H_LIM) { - hw->conf_unit[unit].conf2.cnt_h_lim = value; - } else if (evt_type == PCNT_EVT_THRES_0) { - hw->conf_unit[unit].conf1.cnt_thres0 = value; - } else if (evt_type == PCNT_EVT_THRES_1) { - hw->conf_unit[unit].conf1.cnt_thres1 = value; - } + hw->conf_unit[unit].conf0.thr_zero_en_un = enable; } /** - * @brief Get PCNT event value of PCNT unit + * @brief Enable PCNT threshold event * * @param hw Peripheral PCNT hardware instance address. * @param unit PCNT unit number - * @param evt_type Watch point event type. - * All enabled events share the same interrupt (one interrupt per pulse counter unit). - * @param value Pointer to accept counter value for PCNT event + * @param thres Threshold ID + * @param enable true to enable, false to disable */ -static inline void pcnt_ll_get_event_value(pcnt_dev_t *hw, pcnt_unit_t unit, pcnt_evt_type_t evt_type, int16_t *value) +static inline void pcnt_ll_enable_thres_event(pcnt_dev_t *hw, uint32_t unit, uint32_t thres, bool enable) { - if (evt_type == PCNT_EVT_L_LIM) { - *value = (int16_t) hw->conf_unit[unit].conf2.cnt_l_lim; - } else if (evt_type == PCNT_EVT_H_LIM) { - *value = (int16_t) hw->conf_unit[unit].conf2.cnt_h_lim; - } else if (evt_type == PCNT_EVT_THRES_0) { - *value = (int16_t) hw->conf_unit[unit].conf1.cnt_thres0; - } else if (evt_type == PCNT_EVT_THRES_1) { - *value = (int16_t) hw->conf_unit[unit].conf1.cnt_thres1; + if (thres == 0) { + hw->conf_unit[unit].conf0.thr_thres0_en_un = enable; } else { - *value = 0; + hw->conf_unit[unit].conf0.thr_thres1_en_un = enable; } } +/** + * @brief Disable all PCNT threshold events + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit unit number + */ +static inline void pcnt_ll_disable_all_events(pcnt_dev_t *hw, uint32_t unit) +{ + hw->conf_unit[unit].conf0.val &= ~(PCNT_LL_EVENT_MASK << 11); +} + +/** + * @brief Set PCNT high limit value + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @param value PCNT high limit value + */ +static inline void pcnt_ll_set_high_limit_value(pcnt_dev_t *hw, uint32_t unit, int value) +{ + pcnt_un_conf2_reg_t conf2_reg = hw->conf_unit[unit].conf2; + conf2_reg.cnt_h_lim_un = value; + hw->conf_unit[unit].conf2 = conf2_reg; +} + +/** + * @brief Set PCNT low limit value + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @param value PCNT low limit value + */ +static inline void pcnt_ll_set_low_limit_value(pcnt_dev_t *hw, uint32_t unit, int value) +{ + pcnt_un_conf2_reg_t conf2_reg = hw->conf_unit[unit].conf2; + conf2_reg.cnt_l_lim_un = value; + hw->conf_unit[unit].conf2 = conf2_reg; +} + +/** + * @brief Set PCNT threshold value + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @param thres Threshold ID + * @param value PCNT threshold value + */ +static inline void pcnt_ll_set_thres_value(pcnt_dev_t *hw, uint32_t unit, uint32_t thres, int value) +{ + pcnt_un_conf1_reg_t conf1_reg = hw->conf_unit[unit].conf1; + if (thres == 0) { + conf1_reg.cnt_thres0_un = value; + } else { + conf1_reg.cnt_thres1_un = value; + } + hw->conf_unit[unit].conf1 = conf1_reg; +} + +/** + * @brief Get PCNT high limit value + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @return PCNT high limit value + */ +static inline int pcnt_ll_get_high_limit_value(pcnt_dev_t *hw, uint32_t unit) +{ + pcnt_un_conf2_reg_t conf2_reg = hw->conf_unit[unit].conf2; + int16_t value = conf2_reg.cnt_h_lim_un; + return value; +} + +/** + * @brief Get PCNT low limit value + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @return PCNT high limit value + */ +static inline int pcnt_ll_get_low_limit_value(pcnt_dev_t *hw, uint32_t unit) +{ + pcnt_un_conf2_reg_t conf2_reg = hw->conf_unit[unit].conf2; + int16_t value = conf2_reg.cnt_l_lim_un; + return value; +} + +/** + * @brief Get PCNT threshold value + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @param thres Threshold ID + * @return PCNT threshold value + */ +static inline int pcnt_ll_get_thres_value(pcnt_dev_t *hw, uint32_t unit, uint32_t thres) +{ + int16_t value; + pcnt_un_conf1_reg_t conf1_reg = hw->conf_unit[unit].conf1; + if (thres == 0) { + value = conf1_reg.cnt_thres0_un; + } else { + value = conf1_reg.cnt_thres1_un; + } + return value; +} + +/** + * @brief Get PCNT unit runtime status + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @return PCNT unit runtime status + */ +static inline uint32_t pcnt_ll_get_unit_status(pcnt_dev_t *hw, uint32_t unit) +{ + return hw->status_unit[unit].val; +} + +/** + * @brief Get PCNT count sign + * + * @param hw Peripheral PCNT hardware instance address. + * @param unit PCNT unit number + * @return Count sign + */ +static inline pcnt_unit_count_sign_t pcnt_ll_get_count_sign(pcnt_dev_t *hw, uint32_t unit) +{ + return hw->status_unit[unit].val & 0x03; +} + /** * @brief Get PCNT event status * * @param hw Peripheral PCNT hardware instance address. * @param unit PCNT unit number - * @return event status word + * @return Event status word */ -static inline uint32_t pcnt_ll_get_event_status(pcnt_dev_t *hw, pcnt_unit_t unit) +static inline uint32_t pcnt_ll_get_event_status(pcnt_dev_t *hw, uint32_t unit) { - return hw->status_unit[unit].val; + return hw->status_unit[unit].val >> 2; } /** - * @brief Set PCNT filter value + * @brief Set PCNT glitch filter threshold * * @param hw Peripheral PCNT hardware instance address. * @param unit PCNT unit number * @param filter_val PCNT signal filter value, counter in APB_CLK cycles. * Any pulses lasting shorter than this will be ignored when the filter is enabled. - * @note - * filter_val is a 10-bit value, so the maximum filter_val should be limited to 1023. */ -static inline void pcnt_ll_set_filter_value(pcnt_dev_t *hw, pcnt_unit_t unit, uint16_t filter_val) +static inline void pcnt_ll_set_glitch_filter_thres(pcnt_dev_t *hw, uint32_t unit, uint32_t filter_val) { - hw->conf_unit[unit].conf0.filter_thres = filter_val; + hw->conf_unit[unit].conf0.filter_thres_un = filter_val; } /** - * @brief Get PCNT filter value + * @brief Get PCNT glitch filter threshold * * @param hw Peripheral PCNT hardware instance address. * @param unit PCNT unit number - * @param filter_val Pointer to accept PCNT filter value. + * @return glitch filter threshold */ -static inline void pcnt_ll_get_filter_value(pcnt_dev_t *hw, pcnt_unit_t unit, uint16_t *filter_val) +static inline uint32_t pcnt_ll_get_glitch_filter_thres(pcnt_dev_t *hw, uint32_t unit) { - *filter_val = hw->conf_unit[unit].conf0.filter_thres; + return hw->conf_unit[unit].conf0.filter_thres_un; } /** - * @brief Enable PCNT input filter + * @brief Enable PCNT glitch filter * * @param hw Peripheral PCNT hardware instance address. * @param unit PCNT unit number + * @param enable True to enable the filter, False to disable the filter */ -static inline void pcnt_ll_filter_enable(pcnt_dev_t *hw, pcnt_unit_t unit) +static inline void pcnt_ll_enable_glitch_filter(pcnt_dev_t *hw, uint32_t unit, bool enable) { - hw->conf_unit[unit].conf0.filter_en = 1; -} - -/** - * @brief Disable PCNT input filter - * - * @param hw Peripheral PCNT hardware instance address. - * @param unit PCNT unit number - */ -static inline void pcnt_ll_filter_disable(pcnt_dev_t *hw, pcnt_unit_t unit) -{ - hw->conf_unit[unit].conf0.filter_en = 0; + hw->conf_unit[unit].conf0.filter_en_un = enable; } #ifdef __cplusplus diff --git a/components/hal/esp32s3/include/hal/rmt_ll.h b/components/hal/esp32s3/include/hal/rmt_ll.h index 0dc87853fa..2e6ddd563a 100644 --- a/components/hal/esp32s3/include/hal/rmt_ll.h +++ b/components/hal/esp32s3/include/hal/rmt_ll.h @@ -1,26 +1,21 @@ -// Copyright 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: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + #pragma once #include #include +#include "hal/misc.h" #include "soc/rmt_struct.h" #ifdef __cplusplus extern "C" { #endif +#define RMT_LL_MAX_LOOP_COUNT (1023)/*!< Max loop count that hardware is supported */ #define RMT_LL_HW_BASE (&RMT) #define RMT_LL_MEM_BASE (&RMTMEM) @@ -57,7 +52,7 @@ static inline void rmt_ll_set_group_clock_src(rmt_dev_t *dev, uint32_t channel, // Formula: rmt_sclk = module_clock_src / (1 + div_num + div_a / div_b) dev->sys_conf.sclk_active = 0; dev->sys_conf.sclk_sel = src; - dev->sys_conf.sclk_div_num = div_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->sys_conf, sclk_div_num, div_num); dev->sys_conf.sclk_div_a = div_a; dev->sys_conf.sclk_div_b = div_b; dev->sys_conf.sclk_active = 1; @@ -139,22 +134,22 @@ static inline uint32_t rmt_ll_rx_get_mem_blocks(rmt_dev_t *dev, uint32_t channel static inline void rmt_ll_tx_set_channel_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div) { - dev->chnconf0[channel].div_cnt_n = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->chnconf0[channel], div_cnt_n, div); } static inline void rmt_ll_rx_set_channel_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div) { - dev->chmconf[channel].conf0.div_cnt_m = div; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->chmconf[channel].conf0, div_cnt_m, div); } static inline uint32_t rmt_ll_tx_get_channel_clock_div(rmt_dev_t *dev, uint32_t channel) { - return dev->chnconf0[channel].div_cnt_n; + return HAL_FORCE_READ_U32_REG_FIELD(dev->chnconf0[channel], div_cnt_n); } static inline uint32_t rmt_ll_rx_get_channel_clock_div(rmt_dev_t *dev, uint32_t channel) { - return dev->chmconf[channel].conf0.div_cnt_m; + return HAL_FORCE_READ_U32_REG_FIELD(dev->chmconf[channel].conf0, div_cnt_m); } static inline void rmt_ll_tx_enable_pingpong(rmt_dev_t *dev, uint32_t channel, bool enable) @@ -192,6 +187,11 @@ static inline bool rmt_ll_is_tx_loop_enabled(rmt_dev_t *dev, uint32_t channel) return dev->chnconf0[channel].tx_conti_mode_n; } +static inline void rmt_ll_tx_enable_loop_autostop(rmt_dev_t *dev, uint32_t channel, bool enable) +{ + dev->chn_tx_lim[channel].loop_stop_en_chn = enable; +} + static inline void rmt_ll_tx_set_loop_count(rmt_dev_t *dev, uint32_t channel, uint32_t count) { dev->chn_tx_lim[channel].tx_loop_num_chn = count; @@ -230,7 +230,7 @@ static inline void rmt_ll_rx_enable_filter(rmt_dev_t *dev, uint32_t channel, boo static inline void rmt_ll_rx_set_filter_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres) { - dev->chmconf[channel].conf1.rx_filter_thres_m = thres; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->chmconf[channel].conf1, rx_filter_thres_m, thres); } static inline void rmt_ll_tx_enable_idle(rmt_dev_t *dev, uint32_t channel, bool enable) @@ -440,14 +440,14 @@ static inline void rmt_ll_rx_set_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t static inline void rmt_ll_tx_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks ) { - *high_ticks = dev->chncarrier_duty[channel].carrier_high_chn; - *low_ticks = dev->chncarrier_duty[channel].carrier_low_chn; + *high_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->chncarrier_duty[channel], carrier_high_chn); + *low_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->chncarrier_duty[channel], carrier_low_chn); } static inline void rmt_ll_rx_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks) { - *high_ticks = dev->chm_rx_carrier_rm[channel].carrier_high_thres_chm; - *low_ticks = dev->chm_rx_carrier_rm[channel].carrier_low_thres_chm; + *high_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->chm_rx_carrier_rm[channel], carrier_high_thres_chm); + *low_ticks = HAL_FORCE_READ_U32_REG_FIELD(dev->chm_rx_carrier_rm[channel], carrier_low_thres_chm); } static inline void rmt_ll_tx_enable_carrier_modulation(rmt_dev_t *dev, uint32_t channel, bool enable) diff --git a/components/hal/esp32s3/include/hal/rtc_cntl_ll.h b/components/hal/esp32s3/include/hal/rtc_cntl_ll.h index e1ad1d52cd..075b961aa2 100644 --- a/components/hal/esp32s3/include/hal/rtc_cntl_ll.h +++ b/components/hal/esp32s3/include/hal/rtc_cntl_ll.h @@ -17,11 +17,15 @@ #include "soc/soc.h" #include "soc/rtc.h" #include "soc/rtc_cntl_reg.h" +#include "soc/apb_ctrl_reg.h" #ifdef __cplusplus extern "C" { #endif +#define RTC_CNTL_LL_RETENTION_TARGET_CPU (BIT(0)) +#define RTC_CNTL_LL_RETENTION_TARGET_TAGMEM (BIT(1)) + static inline void rtc_cntl_ll_set_wakeup_timer(uint64_t t) { WRITE_PERI_REG(RTC_CNTL_SLP_TIMER0_REG, t & UINT32_MAX); @@ -53,6 +57,82 @@ static inline void rtc_cntl_ll_ulp_wakeup_enable(void) SET_PERI_REG_BITS(RTC_CNTL_STATE0_REG, RTC_CNTL_WAKEUP_ENA_V, 0x800, RTC_CNTL_WAKEUP_ENA_S); } +static inline void rtc_cntl_ll_set_tagmem_retention_link_addr(uint32_t link_addr) +{ + REG_SET_FIELD(APB_CTRL_RETENTION_CTRL1_REG, APB_CTRL_RETENTION_TAG_LINK_ADDR, link_addr); +} + +static inline void rtc_cntl_ll_enable_tagmem_retention(void) +{ + /* Enable i/d-cache tagmem retenttion. cpu: 1, tagmem: 2, cpu + tagmem: 3 */ + uint32_t target = REG_GET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_TARGET); + REG_SET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_TARGET, (target | RTC_CNTL_LL_RETENTION_TARGET_TAGMEM)); +} + +static inline void rtc_cntl_ll_enable_icache_tagmem_retention(uint32_t start_point, uint32_t vld_size, uint32_t size) +{ + REG_SET_FIELD(APB_CTRL_RETENTION_CTRL2_REG, APB_CTRL_RET_ICACHE_START_POINT, start_point); + REG_SET_FIELD(APB_CTRL_RETENTION_CTRL2_REG, APB_CTRL_RET_ICACHE_VLD_SIZE, vld_size); + REG_SET_FIELD(APB_CTRL_RETENTION_CTRL2_REG, APB_CTRL_RET_ICACHE_SIZE, size); + REG_SET_BIT(APB_CTRL_RETENTION_CTRL2_REG, APB_CTRL_RET_ICACHE_ENABLE); +} + +static inline void rtc_cntl_ll_enable_dcache_tagmem_retention(uint32_t start_point, uint32_t vld_size, uint32_t size) +{ + REG_SET_FIELD(APB_CTRL_RETENTION_CTRL3_REG, APB_CTRL_RET_DCACHE_START_POINT, start_point); + REG_SET_FIELD(APB_CTRL_RETENTION_CTRL3_REG, APB_CTRL_RET_DCACHE_VLD_SIZE, vld_size); + REG_SET_FIELD(APB_CTRL_RETENTION_CTRL3_REG, APB_CTRL_RET_DCACHE_SIZE, size); + REG_SET_BIT(APB_CTRL_RETENTION_CTRL3_REG, APB_CTRL_RET_DCACHE_ENABLE); +} + +static inline void rtc_cntl_ll_disable_tagmem_retention(void) +{ + /* Enable i/d-cache tagmem retenttion. cpu: 1, tagmem: 2, cpu + tagmem: 3 */ + uint32_t target = REG_GET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_TARGET); + REG_SET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_TARGET, (target & ~RTC_CNTL_LL_RETENTION_TARGET_TAGMEM)); +} + +static inline void rtc_cntl_ll_disable_icache_tagmem_retention(void) +{ + REG_CLR_BIT(APB_CTRL_RETENTION_CTRL2_REG, APB_CTRL_RET_ICACHE_ENABLE); +} + +static inline void rtc_cntl_ll_disable_dcache_tagmem_retention(void) +{ + REG_CLR_BIT(APB_CTRL_RETENTION_CTRL3_REG, APB_CTRL_RET_DCACHE_ENABLE); +} + +static inline void rtc_cntl_ll_set_cpu_retention_link_addr(uint32_t link_addr) +{ + REG_SET_FIELD(APB_CTRL_RETENTION_CTRL_REG, APB_CTRL_RETENTION_CPU_LINK_ADDR, link_addr); +} + +static inline void rtc_cntl_ll_enable_cpu_retention_clock(void) +{ + REG_SET_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN); /* Enable internal 20 MHz clock */ +} + +static inline void rtc_cntl_ll_enable_cpu_retention(void) +{ + uint32_t target = REG_GET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_TARGET); + + REG_SET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_TARGET, (target | RTC_CNTL_LL_RETENTION_TARGET_CPU)); + /* Enable retention when cpu sleep enable */ + REG_SET_BIT(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_EN); +} + +static inline void rtc_cntl_ll_config_cpu_retention_timing(int wait, int clkoff_wait, int done_wait) +{ + REG_SET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_WAIT, wait); + REG_SET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_CLKOFF_WAIT, clkoff_wait); + REG_SET_FIELD(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_DONE_WAIT, done_wait); +} + +static inline void rtc_cntl_ll_disable_cpu_retention(void) +{ + REG_CLR_BIT(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_EN); +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32s3/include/hal/rtc_io_ll.h b/components/hal/esp32s3/include/hal/rtc_io_ll.h index 22990e6504..bde6bf3c66 100644 --- a/components/hal/esp32s3/include/hal/rtc_io_ll.h +++ b/components/hal/esp32s3/include/hal/rtc_io_ll.h @@ -22,6 +22,7 @@ #include #include "soc/rtc_io_periph.h" +#include "soc/rtc_io_struct.h" #include "hal/rtc_io_types.h" #include "hal/gpio_types.h" diff --git a/components/hal/esp32s3/include/hal/rwdt_ll.h b/components/hal/esp32s3/include/hal/rwdt_ll.h index 57af63721b..da716126ff 100644 --- a/components/hal/esp32s3/include/hal/rwdt_ll.h +++ b/components/hal/esp32s3/include/hal/rwdt_ll.h @@ -25,6 +25,7 @@ extern "C" { #include #include "hal/wdt_types.h" #include "soc/rtc_cntl_periph.h" +#include "soc/rtc_cntl_struct.h" #include "soc/efuse_reg.h" #include "esp_attr.h" @@ -259,7 +260,7 @@ FORCE_INLINE_ATTR void rwdt_ll_set_chip_reset_en(rtc_cntl_dev_t *hw, bool enable */ FORCE_INLINE_ATTR void rwdt_ll_set_chip_reset_width(rtc_cntl_dev_t *hw, uint32_t width) { - hw->wdt_config0.chip_reset_width = width; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->wdt_config0, chip_reset_width, width); } /** diff --git a/components/hal/esp32s3/include/hal/sigmadelta_ll.h b/components/hal/esp32s3/include/hal/sigmadelta_ll.h index 99d75853c5..ecae8cf352 100644 --- a/components/hal/esp32s3/include/hal/sigmadelta_ll.h +++ b/components/hal/esp32s3/include/hal/sigmadelta_ll.h @@ -23,7 +23,9 @@ #include #include "soc/sigmadelta_periph.h" +#include "soc/gpio_sd_struct.h" #include "hal/sigmadelta_types.h" +#include "hal/misc.h" #ifdef __cplusplus extern "C" { @@ -53,7 +55,7 @@ static inline void sigmadelta_ll_set_en(gpio_sd_dev_t *hw, bool en) */ static inline void sigmadelta_ll_set_duty(gpio_sd_dev_t *hw, sigmadelta_channel_t channel, int8_t duty) { - hw->channel[channel].duty = duty; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], duty, (uint8_t)duty); } /** @@ -65,7 +67,7 @@ static inline void sigmadelta_ll_set_duty(gpio_sd_dev_t *hw, sigmadelta_channel_ */ static inline void sigmadelta_ll_set_prescale(gpio_sd_dev_t *hw, sigmadelta_channel_t channel, uint8_t prescale) { - hw->channel[channel].prescale = prescale; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->channel[channel], prescale, prescale); } #ifdef __cplusplus diff --git a/components/hal/esp32s3/include/hal/spi_ll.h b/components/hal/esp32s3/include/hal/spi_ll.h index 1748105bff..bc4a68b6bf 100644 --- a/components/hal/esp32s3/include/hal/spi_ll.h +++ b/components/hal/esp32s3/include/hal/spi_ll.h @@ -27,9 +27,11 @@ #include "esp_attr.h" #include "esp_types.h" #include "soc/spi_periph.h" +#include "soc/spi_struct.h" #include "soc/lldesc.h" #include "hal/assert.h" #include "hal/misc.h" +#include "hal/spi_types.h" #ifdef __cplusplus extern "C" { @@ -37,6 +39,11 @@ extern "C" { /// Interrupt not used. Don't use in app. #define SPI_LL_UNUSED_INT_MASK (SPI_TRANS_DONE_INT_ENA | SPI_SLV_WR_DMA_DONE_INT_ENA | SPI_SLV_RD_DMA_DONE_INT_ENA | SPI_SLV_WR_BUF_DONE_INT_ENA | SPI_SLV_RD_BUF_DONE_INT_ENA) +/// These 2 masks together will set SPI transaction to one line mode +#define SPI_LL_ONE_LINE_CTRL_MASK (SPI_FREAD_OCT | SPI_FREAD_QUAD | SPI_FREAD_DUAL | SPI_FCMD_OCT | \ + SPI_FCMD_QUAD | SPI_FCMD_DUAL | SPI_FADDR_OCT | SPI_FADDR_QUAD | SPI_FADDR_DUAL) +#define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_OCT | SPI_FWRITE_QUAD | SPI_FWRITE_DUAL) + /// Swap the bit order to its correct place to send #define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len)) /// This is the expected clock frequency @@ -51,15 +58,6 @@ extern "C" { typedef uint32_t spi_ll_clock_val_t; typedef spi_dev_t spi_dma_dev_t; -/** IO modes supported by the master. */ -typedef enum { - SPI_LL_IO_MODE_NORMAL = 0, ///< 1-bit mode for all phases - SPI_LL_IO_MODE_DIO, ///< 2-bit mode for address and data phases, 1-bit mode for command phase - SPI_LL_IO_MODE_DUAL, ///< 2-bit mode for data phases only, 1-bit mode for command and address phases - SPI_LL_IO_MODE_QIO, ///< 4-bit mode for address and data phases, 1-bit mode for command phase - SPI_LL_IO_MODE_QUAD, ///< 4-bit mode for data phases only, 1-bit mode for command and address phases -} spi_ll_io_mode_t; - // Type definition of all supported interrupts typedef enum { SPI_LL_INTR_TRANS_DONE = BIT(0), ///< A transaction has done @@ -354,7 +352,7 @@ static inline void spi_ll_write_buffer(spi_dev_t *hw, const uint8_t *buffer_to_s */ static inline void spi_ll_write_buffer_byte(spi_dev_t *hw, int byte_id, uint8_t *data, int len) { - HAL_ASSERT(byte_id+len <= 64); + HAL_ASSERT(byte_id + len <= 64); HAL_ASSERT(len > 0); HAL_ASSERT(byte_id >= 0); @@ -362,10 +360,14 @@ static inline void spi_ll_write_buffer_byte(spi_dev_t *hw, int byte_id, uint8_t uint32_t word; int offset = byte_id % 4; int copy_len = 4 - offset; - if (copy_len > len) copy_len = len; + if (copy_len > len) { + copy_len = len; + } //read-modify-write - if (copy_len != 4) word = hw->data_buf[byte_id / 4]; //read + if (copy_len != 4) { + word = hw->data_buf[byte_id / 4]; //read + } memcpy(((uint8_t *)&word) + offset, data, copy_len); //modify hw->data_buf[byte_id / 4] = word; //write @@ -409,7 +411,9 @@ static inline void spi_ll_read_buffer_byte(spi_dev_t *hw, int byte_id, uint8_t * uint32_t word = hw->data_buf[byte_id / 4]; int offset = byte_id % 4; int copy_len = 4 - offset; - if (copy_len > len) copy_len = len; + if (copy_len > len) { + copy_len = len; + } memcpy(out_data, ((uint8_t *)&word) + offset, copy_len); byte_id += copy_len; @@ -540,41 +544,27 @@ static inline void spi_ll_set_sio_mode(spi_dev_t *hw, int sio_mode) } /** - * Configure the io mode for the master to work at. + * Configure the SPI transaction line mode for the master to use. * - * @param hw Beginning address of the peripheral registers. - * @param io_mode IO mode to work at, see ``spi_ll_io_mode_t``. + * @param hw Beginning address of the peripheral registers. + * @param line_mode SPI transaction line mode to use, see ``spi_line_mode_t``. */ -static inline void spi_ll_master_set_io_mode(spi_dev_t *hw, spi_ll_io_mode_t io_mode) +static inline void spi_ll_master_set_line_mode(spi_dev_t *hw, spi_line_mode_t line_mode) { - if (io_mode == SPI_LL_IO_MODE_DIO || io_mode == SPI_LL_IO_MODE_DUAL) { - hw->ctrl.fcmd_dual = (io_mode == SPI_LL_IO_MODE_DIO) ? 1 : 0; - hw->ctrl.faddr_dual = (io_mode == SPI_LL_IO_MODE_DIO) ? 1 : 0; - hw->ctrl.fread_dual = 1; - hw->user.fwrite_dual = 1; - hw->ctrl.fcmd_quad = 0; - hw->ctrl.faddr_quad = 0; - hw->ctrl.fread_quad = 0; - hw->user.fwrite_quad = 0; - } else if (io_mode == SPI_LL_IO_MODE_QIO || io_mode == SPI_LL_IO_MODE_QUAD) { - hw->ctrl.fcmd_quad = (io_mode == SPI_LL_IO_MODE_QIO) ? 1 : 0; - hw->ctrl.faddr_quad = (io_mode == SPI_LL_IO_MODE_QIO) ? 1 : 0; - hw->ctrl.fread_quad = 1; - hw->user.fwrite_quad = 1; - hw->ctrl.fcmd_dual = 0; - hw->ctrl.faddr_dual = 0; - hw->ctrl.fread_dual = 0; - hw->user.fwrite_dual = 0; - } else { - hw->ctrl.fcmd_dual = 0; - hw->ctrl.faddr_dual = 0; - hw->ctrl.fread_dual = 0; - hw->user.fwrite_dual = 0; - hw->ctrl.fcmd_quad = 0; - hw->ctrl.faddr_quad = 0; - hw->ctrl.fread_quad = 0; - hw->user.fwrite_quad = 0; - } + hw->ctrl.val &= ~SPI_LL_ONE_LINE_CTRL_MASK; + hw->user.val &= ~SPI_LL_ONE_LINE_USER_MASK; + hw->ctrl.fcmd_dual = (line_mode.cmd_lines == 2); + hw->ctrl.fcmd_quad = (line_mode.cmd_lines == 4); + hw->ctrl.fcmd_oct = (line_mode.cmd_lines == 8); + hw->ctrl.faddr_dual = (line_mode.addr_lines == 2); + hw->ctrl.faddr_quad = (line_mode.addr_lines == 4); + hw->ctrl.faddr_oct = (line_mode.addr_lines == 8); + hw->ctrl.fread_dual = (line_mode.data_lines == 2); + hw->user.fwrite_dual = (line_mode.data_lines == 2); + hw->ctrl.fread_quad = (line_mode.data_lines == 4); + hw->user.fwrite_quad = (line_mode.data_lines == 4); + hw->ctrl.fread_oct = (line_mode.data_lines == 8); + hw->user.fwrite_oct = (line_mode.data_lines == 8); } /** @@ -618,7 +608,8 @@ static inline void spi_ll_master_select_cs(spi_dev_t *hw, int cs_id) * @param hw Beginning address of the peripheral registers. * @param keep_active if 0 don't keep CS activated, else keep CS activated */ -static inline void spi_ll_master_keep_cs(spi_dev_t *hw, int keep_active) { +static inline void spi_ll_master_keep_cs(spi_dev_t *hw, int keep_active) +{ hw->misc.cs_keep_active = (keep_active != 0) ? 1 : 0; } @@ -925,13 +916,13 @@ static inline void spi_ll_set_command(spi_dev_t *hw, uint16_t cmd, int cmdlen, b { if (lsbfirst) { // The output command start from bit0 to bit 15, kept as is. - hw->user2.usr_command_value = cmd; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user2, usr_command_value, cmd); } else { /* Output command will be sent from bit 7 to 0 of command_value, and * then bit 15 to 8 of the same register field. Shift and swap to send * more straightly. */ - hw->user2.usr_command_value = HAL_SPI_SWAP_DATA_TX(cmd, cmdlen); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user2, usr_command_value, HAL_SPI_SWAP_DATA_TX(cmd, cmdlen)); } } @@ -948,7 +939,7 @@ static inline void spi_ll_set_command(spi_dev_t *hw, uint16_t cmd, int cmdlen, b static inline void spi_ll_set_dummy(spi_dev_t *hw, int dummy_n) { hw->user.usr_dummy = dummy_n ? 1 : 0; - hw->user1.usr_dummy_cyclelen = dummy_n - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user1, usr_dummy_cyclelen, dummy_n - 1); } /** @@ -1003,35 +994,35 @@ static inline uint32_t spi_ll_slave_get_rcv_bitlen(spi_dev_t *hw) item(SPI_LL_INTR_CMDA, dma_int_ena.cmda, dma_int_raw.cmda, dma_int_clr.cmda, dma_int_set.cmda_int_set) -static inline void spi_ll_enable_intr(spi_dev_t* hw, spi_ll_intr_t intr_mask) +static inline void spi_ll_enable_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask) { #define ENA_INTR(intr_bit, en_reg, ...) if (intr_mask & (intr_bit)) hw->en_reg = 1; FOR_EACH_ITEM(ENA_INTR, INTR_LIST); #undef ENA_INTR } -static inline void spi_ll_disable_intr(spi_dev_t* hw, spi_ll_intr_t intr_mask) +static inline void spi_ll_disable_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask) { #define DIS_INTR(intr_bit, en_reg, ...) if (intr_mask & (intr_bit)) hw->en_reg = 0; FOR_EACH_ITEM(DIS_INTR, INTR_LIST); #undef DIS_INTR } -static inline void spi_ll_set_intr(spi_dev_t* hw, spi_ll_intr_t intr_mask) +static inline void spi_ll_set_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask) { #define SET_INTR(intr_bit, _, __, ___, set_reg) if (intr_mask & (intr_bit)) hw->set_reg = 1; FOR_EACH_ITEM(SET_INTR, INTR_LIST); #undef SET_INTR } -static inline void spi_ll_clear_intr(spi_dev_t* hw, spi_ll_intr_t intr_mask) +static inline void spi_ll_clear_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask) { #define CLR_INTR(intr_bit, _, __, clr_reg, ...) if (intr_mask & (intr_bit)) hw->clr_reg = 1; FOR_EACH_ITEM(CLR_INTR, INTR_LIST); #undef CLR_INTR } -static inline bool spi_ll_get_intr(spi_dev_t* hw, spi_ll_intr_t intr_mask) +static inline bool spi_ll_get_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask) { #define GET_INTR(intr_bit, _, raw_reg, ...) if (intr_mask & (intr_bit) && hw->raw_reg) return true; FOR_EACH_ITEM(GET_INTR, INTR_LIST); @@ -1085,7 +1076,7 @@ static inline void spi_ll_enable_int(spi_dev_t *hw) /*------------------------------------------------------------------------------ * Slave HD *----------------------------------------------------------------------------*/ -static inline void spi_ll_slave_hd_set_len_cond(spi_dev_t* hw, spi_ll_trans_len_cond_t cond_mask) +static inline void spi_ll_slave_hd_set_len_cond(spi_dev_t *hw, spi_ll_trans_len_cond_t cond_mask) { hw->slave.rdbuf_bitlen_en = (cond_mask & SPI_LL_TRANS_LEN_COND_RDBUF) ? 1 : 0; hw->slave.wrbuf_bitlen_en = (cond_mask & SPI_LL_TRANS_LEN_COND_WRBUF) ? 1 : 0; @@ -1093,12 +1084,12 @@ static inline void spi_ll_slave_hd_set_len_cond(spi_dev_t* hw, spi_ll_trans_len_ hw->slave.wrdma_bitlen_en = (cond_mask & SPI_LL_TRANS_LEN_COND_WRDMA) ? 1 : 0; } -static inline int spi_ll_slave_get_rx_byte_len(spi_dev_t* hw) +static inline int spi_ll_slave_get_rx_byte_len(spi_dev_t *hw) { return hw->slave1.data_bitlen / 8; } -static inline uint32_t spi_ll_slave_hd_get_last_addr(spi_dev_t* hw) +static inline uint32_t spi_ll_slave_hd_get_last_addr(spi_dev_t *hw) { return hw->slave1.last_addr; } diff --git a/components/hal/esp32s3/include/hal/spimem_flash_ll.h b/components/hal/esp32s3/include/hal/spimem_flash_ll.h index 098c14c4c2..ea394d2f47 100644 --- a/components/hal/esp32s3/include/hal/spimem_flash_ll.h +++ b/components/hal/esp32s3/include/hal/spimem_flash_ll.h @@ -28,6 +28,7 @@ #include #include "soc/spi_periph.h" +#include "soc/spi_mem_struct.h" #include "hal/spi_types.h" #include "hal/spi_flash_types.h" @@ -157,7 +158,7 @@ static inline void spimem_flash_ll_auto_resume_init(spi_mem_dev_t *dev, bool aut */ static inline void spimem_flash_ll_suspend_cmd_setup(spi_mem_dev_t *dev, uint32_t sus_cmd) { - dev->flash_sus_ctrl.flash_pes_command = sus_cmd; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_ctrl, flash_pes_command, sus_cmd); } /** @@ -169,7 +170,7 @@ static inline void spimem_flash_ll_suspend_cmd_setup(spi_mem_dev_t *dev, uint32_ */ static inline void spimem_flash_ll_resume_cmd_setup(spi_mem_dev_t *dev, uint32_t res_cmd) { - dev->flash_sus_ctrl.flash_per_command = res_cmd; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_ctrl, flash_per_command, res_cmd); } /** @@ -226,7 +227,7 @@ static inline void spimem_flash_ll_set_read_sus_status(spi_mem_dev_t *dev, uint3 */ static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool auto_waiti) { - dev->flash_waiti_ctrl.waiti_cmd = 0x05; // Set the command to send, to fetch flash status reg value. + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_waiti_ctrl, waiti_cmd, 0x05); // Set the command to send, to fetch flash status reg value. dev->flash_waiti_ctrl.waiti_en = auto_waiti; // enable auto wait-idle function. } @@ -381,7 +382,8 @@ static inline void spimem_flash_ll_set_cs_pin(spi_mem_dev_t *dev, int pin) static inline void spimem_flash_ll_set_read_mode(spi_mem_dev_t *dev, esp_flash_io_mode_t read_mode) { typeof (dev->ctrl) ctrl = dev->ctrl; - ctrl.val &= ~(SPI_MEM_FREAD_QIO_M | SPI_MEM_FREAD_QUAD_M | SPI_MEM_FREAD_DIO_M | SPI_MEM_FREAD_DUAL_M); + ctrl.val &= ~(SPI_MEM_FREAD_QIO_M | SPI_MEM_FREAD_QUAD_M | SPI_MEM_FREAD_DIO_M | SPI_MEM_FREAD_DUAL_M | SPI_MEM_FCMD_OCT | SPI_MEM_FADDR_OCT | SPI_MEM_FDIN_OCT | SPI_MEM_FDOUT_OCT); + dev->ddr.fmem_ddr_en = 0; ctrl.val |= SPI_MEM_FASTRD_MODE_M; switch (read_mode) { case SPI_FLASH_FASTRD: @@ -402,6 +404,19 @@ static inline void spimem_flash_ll_set_read_mode(spi_mem_dev_t *dev, esp_flash_i case SPI_FLASH_SLOWRD: ctrl.fastrd_mode = 0; break; + case SPI_FLASH_OPI_STR: + ctrl.faddr_oct = 1; + ctrl.fcmd_oct = 1; + ctrl.fdin_oct = 1; + ctrl.fdout_oct = 1; + break; + case SPI_FLASH_OPI_DTR: + ctrl.faddr_oct = 1; + ctrl.fcmd_oct = 1; + ctrl.fdin_oct = 1; + ctrl.fdout_oct = 1; + dev->ddr.fmem_ddr_en = 1; + break; default: abort(); } @@ -545,6 +560,11 @@ static inline void spimem_flash_ll_set_cs_setup(spi_mem_dev_t *dev, uint32_t cs_ dev->ctrl2.cs_setup_time = cs_setup_time - 1; } +static inline void spimem_flash_ll_set_extra_dummy(spi_mem_dev_t *dev, uint32_t extra_dummy) +{ + dev->timing_cali.extra_dummy_cyclelen = extra_dummy; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32s3/include/hal/systimer_ll.h b/components/hal/esp32s3/include/hal/systimer_ll.h index 0c8dde75e2..7f171e92e3 100644 --- a/components/hal/esp32s3/include/hal/systimer_ll.h +++ b/components/hal/esp32s3/include/hal/systimer_ll.h @@ -125,6 +125,11 @@ __attribute__((always_inline)) static inline void systimer_ll_set_alarm_period(s dev->target_conf[alarm_id].target_period = period; } +__attribute__((always_inline)) static inline uint32_t systimer_ll_get_alarm_period(systimer_dev_t *dev, uint32_t alarm_id) +{ + return dev->target_conf[alarm_id].target_period; +} + __attribute__((always_inline)) static inline void systimer_ll_apply_alarm_value(systimer_dev_t *dev, uint32_t alarm_id) { dev->comp_load[alarm_id].val = 0x01; diff --git a/components/hal/esp32s3/include/hal/timer_ll.h b/components/hal/esp32s3/include/hal/timer_ll.h index de95e437ea..36288f7887 100644 --- a/components/hal/esp32s3/include/hal/timer_ll.h +++ b/components/hal/esp32s3/include/hal/timer_ll.h @@ -22,7 +22,9 @@ extern "C" { #endif #include +#include "hal/misc.h" #include "soc/timer_periph.h" +#include "soc/timer_group_struct.h" #include "hal/timer_types.h" #include "hal/assert.h" @@ -55,7 +57,7 @@ static inline void timer_ll_set_divider(timg_dev_t *hw, timer_idx_t timer_num, u } int timer_en = hw->hw_timer[timer_num].config.tn_en; hw->hw_timer[timer_num].config.tn_en = 0; - hw->hw_timer[timer_num].config.tn_divider = divider; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->hw_timer[timer_num].config, tn_divider, divider); hw->hw_timer[timer_num].config.tn_en = timer_en; } @@ -70,7 +72,7 @@ static inline void timer_ll_set_divider(timg_dev_t *hw, timer_idx_t timer_num, u */ static inline void timer_ll_get_divider(timg_dev_t *hw, timer_idx_t timer_num, uint32_t *divider) { - uint32_t d = hw->hw_timer[timer_num].config.tn_divider; + uint32_t d = HAL_FORCE_READ_U32_REG_FIELD(hw->hw_timer[timer_num].config, tn_divider); if (d == 0) { d = 65536; } else if (d == 1) { diff --git a/components/hal/esp32s3/include/hal/touch_sensor_ll.h b/components/hal/esp32s3/include/hal/touch_sensor_ll.h index 48d62faf47..1d62690be0 100644 --- a/components/hal/esp32s3/include/hal/touch_sensor_ll.h +++ b/components/hal/esp32s3/include/hal/touch_sensor_ll.h @@ -24,7 +24,11 @@ #include #include +#include "hal/misc.h" #include "soc/touch_sensor_periph.h" +#include "soc/rtc_cntl_struct.h" +#include "soc/rtc_io_struct.h" +#include "soc/sens_struct.h" #include "soc/soc_caps.h" #include "hal/touch_sensor_types.h" @@ -47,9 +51,9 @@ extern "C" { static inline void touch_ll_set_meas_times(uint16_t meas_time) { //The times of charge and discharge in each measure process of touch channels. - RTCCNTL.touch_ctrl1.touch_meas_num = meas_time; + HAL_FORCE_MODIFY_U32_REG_FIELD(RTCCNTL.touch_ctrl1, touch_meas_num, meas_time); //the waiting cycles (in 8MHz) between TOUCH_START and TOUCH_XPD - RTCCNTL.touch_ctrl2.touch_xpd_wait = SOC_TOUCH_PAD_MEASURE_WAIT_MAX; //wait volt stable + HAL_FORCE_MODIFY_U32_REG_FIELD(RTCCNTL.touch_ctrl2, touch_xpd_wait, SOC_TOUCH_PAD_MEASURE_WAIT_MAX); //wait volt stable } /** @@ -59,7 +63,7 @@ static inline void touch_ll_set_meas_times(uint16_t meas_time) */ static inline void touch_ll_get_measure_times(uint16_t *meas_time) { - *meas_time = RTCCNTL.touch_ctrl1.touch_meas_num; + *meas_time = HAL_FORCE_READ_U32_REG_FIELD(RTCCNTL.touch_ctrl1, touch_meas_num); } /** @@ -73,7 +77,7 @@ static inline void touch_ll_get_measure_times(uint16_t *meas_time) static inline void touch_ll_set_sleep_time(uint16_t sleep_time) { // touch sensor sleep cycle Time = sleep_cycle / RTC_SLOW_CLK(150k) - RTCCNTL.touch_ctrl1.touch_sleep_cycles = sleep_time; + HAL_FORCE_MODIFY_U32_REG_FIELD(RTCCNTL.touch_ctrl1, touch_sleep_cycles, sleep_time); } /** @@ -83,7 +87,7 @@ static inline void touch_ll_set_sleep_time(uint16_t sleep_time) */ static inline void touch_ll_get_sleep_time(uint16_t *sleep_time) { - *sleep_time = RTCCNTL.touch_ctrl1.touch_sleep_cycles; + *sleep_time = HAL_FORCE_READ_U32_REG_FIELD(RTCCNTL.touch_ctrl1, touch_sleep_cycles); } /** @@ -990,7 +994,7 @@ static inline void touch_ll_proximity_get_channel_num(touch_pad_t prox_pad[]) */ static inline void touch_ll_proximity_set_meas_times(uint32_t times) { - RTCCNTL.touch_approach.touch_approach_meas_time = times; + HAL_FORCE_MODIFY_U32_REG_FIELD(RTCCNTL.touch_approach, touch_approach_meas_time, times); } /** @@ -1000,7 +1004,7 @@ static inline void touch_ll_proximity_set_meas_times(uint32_t times) */ static inline void touch_ll_proximity_get_meas_times(uint32_t *times) { - *times = RTCCNTL.touch_approach.touch_approach_meas_time; + *times = HAL_FORCE_READ_U32_REG_FIELD(RTCCNTL.touch_approach, touch_approach_meas_time); } /** diff --git a/components/hal/esp32s3/include/hal/twai_ll.h b/components/hal/esp32s3/include/hal/twai_ll.h index 62941845a4..e9eef59104 100644 --- a/components/hal/esp32s3/include/hal/twai_ll.h +++ b/components/hal/esp32s3/include/hal/twai_ll.h @@ -31,6 +31,7 @@ extern "C" { #include "hal/misc.h" #include "hal/twai_types.h" #include "soc/twai_periph.h" +#include "soc/twai_struct.h" /* ------------------------- Defines and Typedefs --------------------------- */ @@ -399,7 +400,7 @@ static inline void twai_ll_clear_err_code_cap(twai_dev_t *hw) */ static inline void twai_ll_set_err_warn_lim(twai_dev_t *hw, uint32_t ewl) { - hw->error_warning_limit_reg.ewl = ewl; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->error_warning_limit_reg, ewl, ewl); } /** @@ -439,7 +440,7 @@ static inline uint32_t twai_ll_get_rec(twai_dev_t *hw) */ static inline void twai_ll_set_rec(twai_dev_t *hw, uint32_t rec) { - hw->rx_error_counter_reg.rxerr = rec; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_error_counter_reg, rxerr, rec); } /* ------------------------ TX Error Count Register ------------------------- */ @@ -467,7 +468,7 @@ static inline uint32_t twai_ll_get_tec(twai_dev_t *hw) */ static inline void twai_ll_set_tec(twai_dev_t *hw, uint32_t tec) { - hw->tx_error_counter_reg.txerr = tec; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_error_counter_reg, txerr, tec); } /* ---------------------- Acceptance Filter Registers ----------------------- */ @@ -486,8 +487,8 @@ static inline void twai_ll_set_acc_filter(twai_dev_t* hw, uint32_t code, uint32_ uint32_t code_swapped = HAL_SWAP32(code); uint32_t mask_swapped = HAL_SWAP32(mask); for (int i = 0; i < 4; i++) { - hw->acceptance_filter.acr[i].byte = ((code_swapped >> (i * 8)) & 0xFF); - hw->acceptance_filter.amr[i].byte = ((mask_swapped >> (i * 8)) & 0xFF); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->acceptance_filter.acr[i], byte, ((code_swapped >> (i * 8)) & 0xFF)); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->acceptance_filter.amr[i], byte, ((mask_swapped >> (i * 8)) & 0xFF)); } hw->mode_reg.afm = single_filter; } @@ -522,7 +523,7 @@ static inline void twai_ll_get_rx_buffer(twai_dev_t *hw, twai_ll_frame_buffer_t { //Copy RX buffer registers into frame for (int i = 0; i < 13; i++) { - rx_frame->bytes[i] = hw->tx_rx_buffer[i].byte; + rx_frame->bytes[i] = HAL_FORCE_READ_U32_REG_FIELD(hw->tx_rx_buffer[i], byte); } } @@ -652,14 +653,14 @@ static inline void twai_ll_set_clkout(twai_dev_t *hw, uint32_t divider) { if (divider >= 2 && divider <= 490) { hw->clock_divider_reg.co = 0; - hw->clock_divider_reg.cd = (divider / 2) - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clock_divider_reg, cd, (divider / 2) - 1); } else if (divider == 1) { //Setting the divider reg to max value (255) means a divider of 1 hw->clock_divider_reg.co = 0; - hw->clock_divider_reg.cd = 255; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clock_divider_reg, cd, 255); } else { hw->clock_divider_reg.co = 1; - hw->clock_divider_reg.cd = 0; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clock_divider_reg, cd, 0); } } diff --git a/components/hal/esp32s3/include/hal/uart_ll.h b/components/hal/esp32s3/include/hal/uart_ll.h index 5570d58bf3..f437c502e0 100644 --- a/components/hal/esp32s3/include/hal/uart_ll.h +++ b/components/hal/esp32s3/include/hal/uart_ll.h @@ -17,8 +17,11 @@ #pragma once + +#include "hal/misc.h" #include "hal/uart_types.h" #include "soc/uart_periph.h" +#include "soc/uart_struct.h" #include "esp_attr.h" #ifdef __cplusplus @@ -149,7 +152,7 @@ FORCE_INLINE_ATTR void uart_ll_set_baudrate(uart_dev_t *hw, uint32_t baud) // an integer part and a fractional part. hw->clkdiv.clkdiv = clk_div >> 4; hw->clkdiv.clkdiv_frag = clk_div & 0xf; - hw->clk_conf.sclk_div_num = sclk_div - 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clk_conf, sclk_div_num, sclk_div - 1); #undef DIV_UP } @@ -164,7 +167,8 @@ FORCE_INLINE_ATTR uint32_t uart_ll_get_baudrate(uart_dev_t *hw) { uint32_t sclk_freq = uart_ll_get_sclk_freq(hw); uart_clkdiv_reg_t div_reg = hw->clkdiv; - return ((sclk_freq << 4)) / (((div_reg.clkdiv << 4) | div_reg.clkdiv_frag) * (hw->clk_conf.sclk_div_num + 1)); + return ((sclk_freq << 4)) / + (((div_reg.clkdiv << 4) | div_reg.clkdiv_frag) * (HAL_FORCE_READ_U32_REG_FIELD(hw->clk_conf, sclk_div_num) + 1)); } /** @@ -437,7 +441,7 @@ FORCE_INLINE_ATTR void uart_ll_set_tx_idle_num(uart_dev_t *hw, uint32_t idle_num FORCE_INLINE_ATTR void uart_ll_tx_break(uart_dev_t *hw, uint32_t break_num) { if (break_num > 0) { - hw->txbrk_conf.tx_brk_num = break_num; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->txbrk_conf, tx_brk_num, break_num); hw->conf0.txd_brk = 1; } else { hw->conf0.txd_brk = 0; @@ -503,8 +507,8 @@ FORCE_INLINE_ATTR void uart_ll_set_sw_flow_ctrl(uart_dev_t *hw, uart_sw_flowctrl hw->flow_conf.sw_flow_con_en = 1; hw->swfc_conf1.xon_threshold = flow_ctrl->xon_thrd; hw->swfc_conf0.xoff_threshold = flow_ctrl->xoff_thrd; - hw->swfc_conf1.xon_char = flow_ctrl->xon_char; - hw->swfc_conf0.xoff_char = flow_ctrl->xoff_char; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->swfc_conf1, xon_char, flow_ctrl->xon_char); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->swfc_conf0, xoff_char, flow_ctrl->xoff_char); } else { hw->flow_conf.sw_flow_con_en = 0; hw->flow_conf.xonoff_del = 0; @@ -526,11 +530,11 @@ FORCE_INLINE_ATTR void uart_ll_set_sw_flow_ctrl(uart_dev_t *hw, uart_sw_flowctrl */ FORCE_INLINE_ATTR void uart_ll_set_at_cmd_char(uart_dev_t *hw, uart_at_cmd_t *cmd_char) { - hw->at_cmd_char.at_cmd_char = cmd_char->cmd_char; - hw->at_cmd_char.char_num = cmd_char->char_num; - hw->at_cmd_postcnt.post_idle_num = cmd_char->post_idle; - hw->at_cmd_precnt.pre_idle_num = cmd_char->pre_idle; - hw->at_cmd_gaptout.rx_gap_tout = cmd_char->gap_tout; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_char, at_cmd_char, cmd_char->cmd_char); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_char, char_num, cmd_char->char_num); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_postcnt, post_idle_num, cmd_char->post_idle); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_precnt, pre_idle_num, cmd_char->pre_idle); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_gaptout, rx_gap_tout, cmd_char->gap_tout); } /** @@ -713,8 +717,8 @@ FORCE_INLINE_ATTR void uart_ll_set_mode(uart_dev_t *hw, uart_mode_t mode) */ FORCE_INLINE_ATTR void uart_ll_get_at_cmd_char(uart_dev_t *hw, uint8_t *cmd_char, uint8_t *char_num) { - *cmd_char = hw->at_cmd_char.at_cmd_char; - *char_num = hw->at_cmd_char.char_num; + *cmd_char = HAL_FORCE_READ_U32_REG_FIELD(hw->at_cmd_char, at_cmd_char); + *char_num = HAL_FORCE_READ_U32_REG_FIELD(hw->at_cmd_char, char_num); } /** diff --git a/components/hal/esp32s3/include/hal/uhci_ll.h b/components/hal/esp32s3/include/hal/uhci_ll.h new file mode 100644 index 0000000000..0ea4440853 --- /dev/null +++ b/components/hal/esp32s3/include/hal/uhci_ll.h @@ -0,0 +1,139 @@ +// 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. + +// The LL layer for UHCI register operations. +// Note that most of the register operations in this layer are non-atomic operations. + + +#pragma once +#include +#include "hal/uhci_types.h" +#include "soc/uhci_struct.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define UHCI_LL_GET_HW(num) (((num) == 0) ? (&UHCI0) : (NULL)) + +typedef enum { + UHCI_RX_BREAK_CHR_EOF = 0x1, + UHCI_RX_IDLE_EOF = 0x2, + UHCI_RX_LEN_EOF = 0x4, + UHCI_RX_EOF_MAX = 0x7, +} uhci_rxeof_cfg_t; + +static inline void uhci_ll_init(uhci_dev_t *hw) +{ + typeof(hw->conf0) conf0_reg; + hw->conf0.clk_en = 1; + conf0_reg.val = 0; + conf0_reg.clk_en = 1; + hw->conf0.val = conf0_reg.val; + hw->conf1.val = 0; +} + +static inline void uhci_ll_attach_uart_port(uhci_dev_t *hw, int uart_num) +{ + hw->conf0.uart0_ce = (uart_num == 0)? 1: 0; + hw->conf0.uart1_ce = (uart_num == 1)? 1: 0; + hw->conf0.uart2_ce = (uart_num == 2)? 1: 0; +} + +static inline void uhci_ll_set_seper_chr(uhci_dev_t *hw, uhci_seper_chr_t *seper_char) +{ + if (seper_char->sub_chr_en) { + typeof(hw->esc_conf0) esc_conf0_reg = hw->esc_conf0; + esc_conf0_reg.seper_char = seper_char->seper_chr; + esc_conf0_reg.seper_esc_char0 = seper_char->sub_chr1; + esc_conf0_reg.seper_esc_char1 = seper_char->sub_chr2; + hw->esc_conf0.val = esc_conf0_reg.val; + hw->escape_conf.tx_c0_esc_en = 1; + hw->escape_conf.rx_c0_esc_en = 1; + } else { + hw->escape_conf.tx_c0_esc_en = 0; + hw->escape_conf.rx_c0_esc_en = 0; + } +} + +static inline void uhci_ll_get_seper_chr(uhci_dev_t *hw, uhci_seper_chr_t *seper_chr) +{ + (void)hw; + (void)seper_chr; +} + +static inline void uhci_ll_set_swflow_ctrl_sub_chr(uhci_dev_t *hw, uhci_swflow_ctrl_sub_chr_t *sub_ctr) +{ + typeof(hw->escape_conf) escape_conf_reg = hw->escape_conf; + if (sub_ctr->flow_en == 1) { + typeof(hw->esc_conf2) esc_conf2_reg = hw->esc_conf2; + typeof(hw->esc_conf3) esc_conf3_reg = hw->esc_conf3; + esc_conf2_reg.seq1 = sub_ctr->xon_chr; + esc_conf2_reg.seq1_char0 = sub_ctr->xon_sub1; + esc_conf2_reg.seq1_char1 = sub_ctr->xon_sub2; + esc_conf3_reg.seq2 = sub_ctr->xoff_chr; + esc_conf3_reg.seq2_char0 = sub_ctr->xoff_sub1; + esc_conf3_reg.seq2_char1 = sub_ctr->xoff_sub2; + escape_conf_reg.tx_11_esc_en = 1; + escape_conf_reg.tx_13_esc_en = 1; + escape_conf_reg.rx_11_esc_en = 1; + escape_conf_reg.rx_13_esc_en = 1; + hw->esc_conf2.val = esc_conf2_reg.val; + hw->esc_conf3.val = esc_conf3_reg.val; + } else { + escape_conf_reg.tx_11_esc_en = 0; + escape_conf_reg.tx_13_esc_en = 0; + escape_conf_reg.rx_11_esc_en = 0; + escape_conf_reg.rx_13_esc_en = 0; + } + hw->escape_conf.val = escape_conf_reg.val; +} + +static inline void uhci_ll_enable_intr(uhci_dev_t *hw, uint32_t intr_mask) +{ + hw->int_ena.val |= intr_mask; +} + +static inline void uhci_ll_disable_intr(uhci_dev_t *hw, uint32_t intr_mask) +{ + hw->int_ena.val &= (~intr_mask); +} + +static inline void uhci_ll_clear_intr(uhci_dev_t *hw, uint32_t intr_mask) +{ + hw->int_clr.val = intr_mask; +} + +static inline uint32_t uhci_ll_get_intr(uhci_dev_t *hw) +{ + return hw->int_st.val; +} + + +static inline void uhci_ll_set_eof_mode(uhci_dev_t *hw, uint32_t eof_mode) +{ + if (eof_mode & UHCI_RX_BREAK_CHR_EOF) { + hw->conf0.uart_rx_brk_eof_en = 1; + } + if (eof_mode & UHCI_RX_IDLE_EOF) { + hw->conf0.uart_idle_eof_en = 1; + } + if (eof_mode & UHCI_RX_LEN_EOF) { + hw->conf0.len_eof_en = 1; + } +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32s3/include/hal/usb_phy_ll.h b/components/hal/esp32s3/include/hal/usb_phy_ll.h new file mode 100644 index 0000000000..fc665552d8 --- /dev/null +++ b/components/hal/esp32s3/include/hal/usb_phy_ll.h @@ -0,0 +1,127 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "soc/soc.h" +#include "soc/system_reg.h" +#include "soc/usb_wrap_struct.h" +#include "soc/rtc_cntl_struct.h" +#include "soc/usb_serial_jtag_struct.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Configures the internal PHY for USB_OTG + * + * @param hw Start address of the USB Wrap registers + */ +static inline void usb_phy_ll_int_otg_enable(usb_wrap_dev_t *hw) +{ + hw->otg_conf.pad_enable = 1; + // USB_OTG use internal PHY + hw->otg_conf.phy_sel = 0; + // phy_sel is controlled by the following register value + RTCCNTL.usb_conf.sw_hw_usb_phy_sel = 1; + // phy_sel=sw_usb_phy_sel=1, USB_OTG is connected with internal PHY + RTCCNTL.usb_conf.sw_usb_phy_sel = 1; +} + +/** + * @brief Configures the external PHY for USB_OTG + * + * @param hw Start address of the USB Wrap registers + */ +static inline void usb_phy_ll_ext_otg_enable(usb_wrap_dev_t *hw) +{ + // USB_OTG use external PHY + hw->otg_conf.phy_sel = 1; + // phy_sel is controlled by the following register value + RTCCNTL.usb_conf.sw_hw_usb_phy_sel = 1; + // phy_sel=sw_usb_phy_sel=0, USB_OTG is connected with external PHY through GPIO Matrix + RTCCNTL.usb_conf.sw_usb_phy_sel = 0; +} + +/** + * @brief Configures the internal PHY for USB_Serial_JTAG + * + * @param hw Start address of the USB Serial_JTAG registers + */ +static inline void usb_phy_ll_int_jtag_enable(usb_serial_jtag_dev_t *hw) +{ + // USB_Serial_JTAG use internal PHY + hw->conf0.phy_sel = 0; + // Disable software control USB D+ D- pullup pulldown (Device FS: dp_pullup = 1) + hw->conf0.pad_pull_override = 0; + // Enable USB pad function + hw->conf0.usb_pad_enable = 1; + // phy_sel is controlled by the following register value + RTCCNTL.usb_conf.sw_hw_usb_phy_sel = 1; + // phy_sel=sw_usb_phy_sel=0, USB_Serial_JTAG is connected with internal PHY + RTCCNTL.usb_conf.sw_usb_phy_sel = 0; +} + +/** + * @brief Configures the external PHY for USB_Serial_JTAG + * + * @param hw Start address of the USB Serial_JTAG registers + */ +static inline void usb_phy_ll_ext_jtag_enable(usb_serial_jtag_dev_t *hw) +{ + // USB_Serial_JTAG use external PHY + hw->conf0.phy_sel = 1; + // phy_sel is controlled by the following register value + RTCCNTL.usb_conf.sw_hw_usb_phy_sel = 1; + // phy_sel=sw_usb_phy_sel=1, USB_Serial_JTAG is connected with external PHY + RTCCNTL.usb_conf.sw_usb_phy_sel = 1; +} + +/** + * @brief Configures port loads for the internal PHY + * + * @param hw Start address of the USB Wrap registers + * @param dp_pu D+ pullup load + * @param dp_pd D+ pulldown load + * @param dm_pu D- pullup load + * @param dm_pd D- pulldown load + */ +static inline void usb_phy_ll_int_load_conf(usb_wrap_dev_t *hw, bool dp_pu, bool dp_pd, bool dm_pu, bool dm_pd) +{ + usb_wrap_otg_conf_reg_t conf = hw->otg_conf; + conf.pad_pull_override = 1; + conf.dp_pullup = dp_pu; + conf.dp_pulldown = dp_pd; + conf.dm_pullup = dm_pu; + conf.dm_pulldown = dm_pd; + hw->otg_conf = conf; +} + +/** + * @brief Enable the internal PHY's test mode + * + * @param hw Start address of the USB Wrap registers + * @param en Whether to enable the internal PHY's test mode + */ +static inline void usb_phy_ll_int_enable_test_mode(usb_wrap_dev_t *hw, bool en) +{ + if (en) { + // Clear USB_WRAP_TEST_CONF_REG + hw->test_conf.val = 0; + // Set USB test pad oen + hw->test_conf.test_usb_wrap_oe = 1; + // Enable USB test mode + hw->test_conf.test_enable = 1; + } else { + hw->test_conf.test_enable = 0; + } +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32s3/include/hal/xt_wdt_ll.h b/components/hal/esp32s3/include/hal/xt_wdt_ll.h new file mode 100644 index 0000000000..65b36253e5 --- /dev/null +++ b/components/hal/esp32s3/include/hal/xt_wdt_ll.h @@ -0,0 +1,101 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// The LL layer for xtal32k WDT register operations. +// Note that most of the register operations in this layer are non-atomic operations. + +#pragma once + +#include +#include "soc/rtc_cntl_periph.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define XT_WDT_LL_XTAL32_DEAD_INTR_MASK RTC_CNTL_XTAL32K_DEAD_INT_ST_M + +/** + * @brief Enable the XT_WDT + * + * @param hw Start address of the peripheral registers. + */ +inline void xt_wdt_ll_enable(rtc_cntl_dev_t *hw, bool enable) +{ + hw->ext_xtl_conf.xtal32k_wdt_en = enable; +} + +/** + * @brief Check if the XT_WDT is enabled + * + * @param hw Start address of the peripheral registers. + * @return True if XT WDT is enabled + */ +inline bool xt_wdt_ll_check_if_enabled(rtc_cntl_dev_t *hw) +{ + return (hw->ext_xtl_conf.xtal32k_wdt_en) ? true : false; +} + +/** + * @brief Set the watchdog timeout value + * + * @param hw Start address of the peripheral registers. + * @param timeout timeout value in RTC_CLK cycles + */ +inline void xt_wdt_ll_set_timeout(rtc_cntl_dev_t *hw, uint8_t timeout) +{ + hw->xtal32k_conf.xtal32k_wdt_timeout = timeout; +} + + +/** + * @brief Reset the XT_WDT + * + * @param hw Start address of the peripheral registers. + */ +inline void xt_wdt_ll_reset(rtc_cntl_dev_t *hw) +{ + hw->ext_xtl_conf.xtal32k_wdt_reset = 1; + hw->ext_xtl_conf.xtal32k_wdt_reset = 0; +} + + +/** + * @brief Set the backup clock value + * + * @param hw Start address of the peripheral registers. + * @param backup_clk_val Backup clock value, see TRM for definition + */ +inline void xt_wdt_ll_set_backup_clk_factor(rtc_cntl_dev_t *hw, uint32_t backup_clk_val) +{ + hw->xtal32k_clk_factor = backup_clk_val; +} + +/** + * @brief Enable the auto-backup clock feature + * + * @param hw Start address of the peripheral registers. + * @param enable True - enable, False - disable + */ +inline void xt_wdt_ll_auto_backup_enable(rtc_cntl_dev_t *hw, bool enable) +{ + hw->ext_xtl_conf.xtal32k_auto_backup = enable; +} + +/** + * @brief Enable the timeout interrupt + * + * @param hw Start address of the peripheral registers. + * @param enable True - enable, False - disable + */ +inline void xt_wdt_ll_intr_enable(rtc_cntl_dev_t *hw, bool enable) +{ + hw->int_ena.rtc_xtal32k_dead = enable; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32s3/rtc_cntl_hal.c b/components/hal/esp32s3/rtc_cntl_hal.c new file mode 100644 index 0000000000..27d3c605be --- /dev/null +++ b/components/hal/esp32s3/rtc_cntl_hal.c @@ -0,0 +1,147 @@ +/* + * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// The HAL layer for RTC CNTL (common part) + +#include "hal/rtc_hal.h" +#include "soc/soc_caps.h" +#include "esp32s3/rom/lldesc.h" +#include "esp32s3/rom/cache.h" +#include "hal/dma_types.h" +#include "hal/assert.h" +#include "esp_attr.h" + +#define RTC_CNTL_HAL_LINK_BUF_SIZE_MIN (SOC_RTC_CNTL_CPU_PD_DMA_BLOCK_SIZE) /* The minimum size of dma link buffer */ + +typedef struct rtc_cntl_link_buf_conf { + uint32_t cfg[4]; /* 4 word for dma link buffer configuration */ +} rtc_cntl_link_buf_conf_t; + +void * rtc_cntl_hal_dma_link_init(void *elem, void *buff, int size, void *next) +{ + HAL_ASSERT(elem != NULL); + HAL_ASSERT(buff != NULL); + HAL_ASSERT(size >= RTC_CNTL_HAL_LINK_BUF_SIZE_MIN); + + lldesc_t *plink = (lldesc_t *)elem; + + plink->eof = next ? 0 : 1; + plink->owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA; + plink->size = size >> 4; /* in unit of 16 bytes */ + plink->length = size >> 4; + plink->buf = buff; + plink->offset = 0; + plink->sosf = 0; + STAILQ_NEXT(plink, qe) = next; + return (void *)plink; +} + +#if SOC_PM_SUPPORT_CPU_PD + +#define DEFAULT_RETENTION_WAIT_CYCLES (0x7f) +#define DEFAULT_RETENTION_CLKOFF_WAIT_CYCLES (0xf) +#define DEFAULT_RETENTION_DONE_WAIT_CYCLES (0x7) + +void rtc_cntl_hal_enable_cpu_retention(void *addr) +{ + rtc_cntl_sleep_retent_t *retent = (rtc_cntl_sleep_retent_t *)addr; + + if (addr) { + if (retent->cpu_pd_mem) { + lldesc_t *plink = (lldesc_t *)retent->cpu_pd_mem; + + /* dma link buffer configure */ + rtc_cntl_link_buf_conf_t *pbuf = (rtc_cntl_link_buf_conf_t *)plink->buf; + pbuf->cfg[0] = 0; + pbuf->cfg[1] = 0; + pbuf->cfg[2] = 0; + pbuf->cfg[3] = 0xfffe0000; + + rtc_cntl_ll_set_cpu_retention_link_addr((uint32_t)plink); + rtc_cntl_ll_config_cpu_retention_timing( + DEFAULT_RETENTION_WAIT_CYCLES, + DEFAULT_RETENTION_CLKOFF_WAIT_CYCLES, + DEFAULT_RETENTION_DONE_WAIT_CYCLES + ); + rtc_cntl_ll_enable_cpu_retention_clock(); + rtc_cntl_ll_enable_cpu_retention(); + } + } +} + +void IRAM_ATTR rtc_cntl_hal_disable_cpu_retention(void *addr) +{ + rtc_cntl_sleep_retent_t *retent = (rtc_cntl_sleep_retent_t *)addr; + + if (addr) { + if (retent->cpu_pd_mem) { + /* I/d-cache tagmem retention has not been included or not + * been enabled, after the system wakes up, all the contents + * of i/d-cache need to be invalidated. */ +#if SOC_PM_SUPPORT_TAGMEM_PD + if (!retent->tagmem.icache.enable) { + Cache_Invalidate_ICache_All(); + } + if (!retent->tagmem.dcache.enable) { + Cache_Invalidate_DCache_All(); + } +#else + Cache_Invalidate_ICache_All(); + Cache_Invalidate_DCache_All(); +#endif // SOC_PM_SUPPORT_TAGMEM_PD + rtc_cntl_ll_disable_cpu_retention(); + } + } +} + +#endif // SOC_PM_SUPPORT_CPU_PD + +#if SOC_PM_SUPPORT_TAGMEM_PD + +void rtc_cntl_hal_enable_tagmem_retention(void *addr) +{ + rtc_cntl_sleep_retent_t *retent = (rtc_cntl_sleep_retent_t *)addr; + + if (addr) { + if (retent->tagmem.link_addr) { + rtc_cntl_ll_set_tagmem_retention_link_addr((uint32_t)(retent->tagmem.link_addr)); + rtc_cntl_ll_enable_tagmem_retention(); + if (retent->tagmem.icache.enable) { + rtc_cntl_ll_enable_icache_tagmem_retention( + retent->tagmem.icache.start_point, + retent->tagmem.icache.vld_size, + retent->tagmem.icache.size + ); + } + if (retent->tagmem.dcache.enable) { + rtc_cntl_ll_enable_dcache_tagmem_retention( + retent->tagmem.dcache.start_point, + retent->tagmem.dcache.vld_size, + retent->tagmem.dcache.size + ); + } + } + } +} + +void IRAM_ATTR rtc_cntl_hal_disable_tagmem_retention(void *addr) +{ + rtc_cntl_sleep_retent_t *retent = (rtc_cntl_sleep_retent_t *)addr; + + if (addr) { + if (retent->tagmem.link_addr) { + rtc_cntl_ll_disable_tagmem_retention(); + if (retent->tagmem.icache.enable) { + rtc_cntl_ll_disable_icache_tagmem_retention(); + } + if (retent->tagmem.dcache.enable) { + rtc_cntl_ll_disable_dcache_tagmem_retention(); + } + } + } +} + +#endif // SOC_PM_SUPPORT_TAGMEM_PD diff --git a/components/hal/i2c_hal_iram.c b/components/hal/i2c_hal_iram.c index 80c490009b..f40d4a3a0b 100644 --- a/components/hal/i2c_hal_iram.c +++ b/components/hal/i2c_hal_iram.c @@ -16,25 +16,30 @@ void i2c_hal_master_handle_tx_event(i2c_hal_context_t *hal, i2c_intr_event_t *event) { - i2c_ll_master_get_event(hal->dev, event); - if ((*event < I2C_INTR_EVENT_END_DET) || - (*event == I2C_INTR_EVENT_TRANS_DONE)) { - i2c_ll_master_disable_tx_it(hal->dev); - i2c_ll_master_clr_tx_it(hal->dev); - } else if (*event == I2C_INTR_EVENT_END_DET) { - i2c_ll_master_clr_tx_it(hal->dev); + if (i2c_ll_get_intsts_mask(hal->dev) != 0) { + // If intr status is 0, no need to handle it. + i2c_ll_master_get_event(hal->dev, event); + if ((*event < I2C_INTR_EVENT_END_DET) || + (*event == I2C_INTR_EVENT_TRANS_DONE)) { + i2c_ll_master_disable_tx_it(hal->dev); + i2c_ll_master_clr_tx_it(hal->dev); + } else if (*event == I2C_INTR_EVENT_END_DET) { + i2c_ll_master_clr_tx_it(hal->dev); + } } } void i2c_hal_master_handle_rx_event(i2c_hal_context_t *hal, i2c_intr_event_t *event) { - i2c_ll_master_get_event(hal->dev, event); - if ((*event < I2C_INTR_EVENT_END_DET) || - (*event == I2C_INTR_EVENT_TRANS_DONE)) { - i2c_ll_master_disable_rx_it(hal->dev); - i2c_ll_master_clr_rx_it(hal->dev); - } else if (*event == I2C_INTR_EVENT_END_DET) { - i2c_ll_master_clr_rx_it(hal->dev); + if (i2c_ll_get_intsts_mask(hal->dev) != 0) { + i2c_ll_master_get_event(hal->dev, event); + if ((*event < I2C_INTR_EVENT_END_DET) || + (*event == I2C_INTR_EVENT_TRANS_DONE)) { + i2c_ll_master_disable_rx_it(hal->dev); + i2c_ll_master_clr_rx_it(hal->dev); + } else if (*event == I2C_INTR_EVENT_END_DET) { + i2c_ll_master_clr_rx_it(hal->dev); + } } } diff --git a/components/hal/i2s_hal.c b/components/hal/i2s_hal.c index f994add41b..edb2660590 100644 --- a/components/hal/i2s_hal.c +++ b/components/hal/i2s_hal.c @@ -1,4 +1,4 @@ -// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// 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. @@ -12,263 +12,309 @@ // See the License for the specific language governing permissions and // limitations under the License. + // The HAL layer for I2S (common part) #include "soc/soc.h" #include "soc/soc_caps.h" #include "hal/i2s_hal.h" -#define I2S_TX_PDM_FP_DEF 960 // Set to the recommended value(960) in TRM -#define I2S_RX_PDM_DSR_DEF 0 - -void i2s_hal_set_tx_mode(i2s_hal_context_t *hal, i2s_channel_t ch, i2s_bits_per_sample_t bits) +/** + * @brief Calculate the closest sample rate clock configuration. + * clock relationship: + * Fmclk = bck_div*fbck = fsclk/(mclk_div+b/a) + * + * @param clk_cfg I2S clock configuration(input) + * @param cal Point to `i2s_ll_mclk_div_t` structure(output). + */ +static void i2s_hal_mclk_div_decimal_cal(i2s_hal_clock_cfg_t *clk_cfg, i2s_ll_mclk_div_t *cal) { - if (bits <= I2S_BITS_PER_SAMPLE_16BIT) { - i2s_ll_set_tx_fifo_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1); - } else { - i2s_ll_set_tx_fifo_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 2 : 3); - } - i2s_ll_set_tx_chan_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1); -#if SOC_I2S_SUPPORTS_DMA_EQUAL - i2s_ll_set_tx_dma_equal(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1); -#endif -} - -void i2s_hal_set_rx_mode(i2s_hal_context_t *hal, i2s_channel_t ch, i2s_bits_per_sample_t bits) -{ - if (bits <= I2S_BITS_PER_SAMPLE_16BIT) { - i2s_ll_set_rx_fifo_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1); - } else { - i2s_ll_set_rx_fifo_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 2 : 3); - } - i2s_ll_set_rx_chan_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1); -#if SOC_I2S_SUPPORTS_DMA_EQUAL - i2s_ll_set_rx_dma_equal(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1); -#endif -} - -void i2s_hal_set_in_link(i2s_hal_context_t *hal, uint32_t bytes_num, uint32_t addr) -{ - i2s_ll_set_in_link_addr(hal->dev, addr); - i2s_ll_set_rx_eof_num(hal->dev, bytes_num); -} - -#if SOC_I2S_SUPPORTS_PDM -void i2s_hal_tx_pdm_cfg(i2s_hal_context_t *hal, uint32_t fp, uint32_t fs) -{ - i2s_ll_tx_pdm_cfg(hal->dev, fp, fs); -} - -void i2s_hal_get_tx_pdm(i2s_hal_context_t *hal, uint32_t *fp, uint32_t *fs) -{ - i2s_ll_get_tx_pdm(hal->dev, fp, fs); -} - -void i2s_hal_rx_pdm_cfg(i2s_hal_context_t *hal, uint32_t dsr) -{ - i2s_ll_rx_pdm_cfg(hal->dev, dsr); -} - -void i2s_hal_get_rx_pdm(i2s_hal_context_t *hal, uint32_t *dsr) -{ - i2s_ll_get_rx_pdm(hal->dev, dsr); -} -#endif - -void i2s_hal_set_clk_div(i2s_hal_context_t *hal, int div_num, int div_a, int div_b, int tx_bck_div, int rx_bck_div) -{ - i2s_ll_set_clkm_div_num(hal->dev, div_num); - i2s_ll_set_clkm_div_a(hal->dev, div_a); - i2s_ll_set_clkm_div_b(hal->dev, div_b); - i2s_ll_set_tx_bck_div_num(hal->dev, tx_bck_div); - i2s_ll_set_rx_bck_div_num(hal->dev, rx_bck_div); -} - -void i2s_hal_set_tx_bits_mod(i2s_hal_context_t *hal, i2s_bits_per_sample_t bits) -{ - i2s_ll_set_tx_bits_mod(hal->dev, bits); -} - -void i2s_hal_set_rx_bits_mod(i2s_hal_context_t *hal, i2s_bits_per_sample_t bits) -{ - i2s_ll_set_rx_bits_mod(hal->dev, bits); -} - -void i2s_hal_reset(i2s_hal_context_t *hal) -{ - // Reset I2S TX/RX module first, and then, reset DMA and FIFO. - i2s_ll_reset_tx(hal->dev); - i2s_ll_reset_rx(hal->dev); - i2s_ll_reset_dma_in(hal->dev); - i2s_ll_reset_dma_out(hal->dev); - i2s_ll_reset_rx_fifo(hal->dev); - i2s_ll_reset_tx_fifo(hal->dev); -} - -void i2s_hal_start_tx(i2s_hal_context_t *hal) -{ - i2s_ll_start_out_link(hal->dev); - i2s_ll_start_tx(hal->dev); -} - -void i2s_hal_start_rx(i2s_hal_context_t *hal) -{ - i2s_ll_start_in_link(hal->dev); - i2s_ll_start_rx(hal->dev); -} - -void i2s_hal_stop_tx(i2s_hal_context_t *hal) -{ - i2s_ll_stop_out_link(hal->dev); - i2s_ll_stop_tx(hal->dev); -} - -void i2s_hal_stop_rx(i2s_hal_context_t *hal) -{ - i2s_ll_stop_in_link(hal->dev); - i2s_ll_stop_rx(hal->dev); -} - -void i2s_hal_format_config(i2s_hal_context_t *hal, const i2s_config_t *i2s_config) -{ - switch (i2s_config->communication_format) { - case I2S_COMM_FORMAT_STAND_MSB: - if (i2s_config->mode & I2S_MODE_TX) { - i2s_ll_set_tx_format_msb_align(hal->dev); - } - if (i2s_config->mode & I2S_MODE_RX) { - i2s_ll_set_rx_format_msb_align(hal->dev); - } - break; - case I2S_COMM_FORMAT_STAND_PCM_SHORT: - if (i2s_config->mode & I2S_MODE_TX) { - i2s_ll_set_tx_pcm_long(hal->dev); - } - if (i2s_config->mode & I2S_MODE_RX) { - i2s_ll_set_rx_pcm_long(hal->dev); - } - break; - case I2S_COMM_FORMAT_STAND_PCM_LONG: - if (i2s_config->mode & I2S_MODE_TX) { - i2s_ll_set_tx_pcm_short(hal->dev); - } - if (i2s_config->mode & I2S_MODE_RX) { - i2s_ll_set_rx_pcm_short(hal->dev); - } - break; - default: //I2S_COMM_FORMAT_STAND_I2S - if (i2s_config->mode & I2S_MODE_TX) { - i2s_ll_set_tx_format_philip(hal->dev); - } - if (i2s_config->mode & I2S_MODE_RX) { - i2s_ll_set_rx_format_philip(hal->dev); - } - break; - } -} - -void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_config_t *i2s_config) -{ - //reset i2s - i2s_ll_reset_tx(hal->dev); - i2s_ll_reset_rx(hal->dev); - - //reset dma - i2s_ll_reset_dma_in(hal->dev); - i2s_ll_reset_dma_out(hal->dev); - - i2s_ll_enable_dma(hal->dev); - - i2s_ll_set_lcd_en(hal->dev, 0); - i2s_ll_set_camera_en(hal->dev, 0); - - i2s_ll_set_dscr_en(hal->dev, 0); - - i2s_ll_set_tx_chan_mod(hal->dev, i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? i2s_config->channel_format : (i2s_config->channel_format >> 1)); // 0-two channel;1-right;2-left;3-righ;4-left - i2s_ll_set_tx_fifo_mod(hal->dev, i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? 0 : 1); // 0-right&left channel;1-one channel - i2s_ll_set_tx_mono(hal->dev, 0); - - i2s_ll_set_rx_chan_mod(hal->dev, i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? i2s_config->channel_format : (i2s_config->channel_format >> 1)); // 0-two channel;1-right;2-left;3-righ;4-left - i2s_ll_set_rx_fifo_mod(hal->dev, i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? 0 : 1); // 0-right&left channel;1-one channel - i2s_ll_set_rx_mono(hal->dev, 0); - - i2s_ll_set_dscr_en(hal->dev, 1); //connect dma to fifo - - i2s_ll_stop_tx(hal->dev); - i2s_ll_stop_rx(hal->dev); - - if (i2s_config->mode & I2S_MODE_TX) { - i2s_ll_set_tx_msb_right(hal->dev, 0); - i2s_ll_set_tx_right_first(hal->dev, 0); - - i2s_ll_set_tx_slave_mod(hal->dev, 0); // Master - i2s_ll_set_tx_fifo_mod_force_en(hal->dev, 1); - - if (i2s_config->mode & I2S_MODE_SLAVE) { - i2s_ll_set_tx_slave_mod(hal->dev, 1); //TX Slave - } - } - - if (i2s_config->mode & I2S_MODE_RX) { - i2s_ll_set_rx_msb_right(hal->dev, 0); - i2s_ll_set_rx_right_first(hal->dev, 0); - i2s_ll_set_rx_slave_mod(hal->dev, 0); // Master - i2s_ll_set_rx_fifo_mod_force_en(hal->dev, 1); - - if (i2s_config->mode & I2S_MODE_SLAVE) { - i2s_ll_set_rx_slave_mod(hal->dev, 1); //RX Slave - } - } - -#if SOC_I2S_SUPPORTS_PDM - if (!(i2s_config->mode & I2S_MODE_PDM)) { - i2s_ll_set_rx_pdm_en(hal->dev, 0); - i2s_ll_set_tx_pdm_en(hal->dev, 0); - } else { - if (i2s_config->mode & I2S_MODE_TX) { - i2s_ll_tx_pdm_cfg(hal->dev, I2S_TX_PDM_FP_DEF, i2s_config->sample_rate/100); - } - if(i2s_config->mode & I2S_MODE_RX) { - i2s_ll_rx_pdm_cfg(hal->dev, I2S_RX_PDM_DSR_DEF); - } - // PDM mode have nothing to do with communication format configuration. + int ma = 0; + int mb = 0; + cal->mclk_div = clk_cfg->mclk_div; + cal->a = 1; + cal->b = 0; + /* If sclk = 0 means APLL clock applied, mclk_div should set to 1 */ + if (!clk_cfg->sclk) { + cal->mclk_div = 1; return; } -#endif - -#if SOC_I2S_SUPPORTS_ADC_DAC - if (i2s_config->mode & (I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN)) { - if (i2s_config->mode & I2S_MODE_DAC_BUILT_IN) { - i2s_ll_build_in_dac_ena(hal->dev); + uint32_t freq_diff = clk_cfg->sclk - clk_cfg->mclk * cal->mclk_div; + uint32_t min = ~0; + for (int a = 2; a <= I2S_LL_MCLK_DIVIDER_MAX; a++) { + for (int b = 1; b < a; b++) { + ma = freq_diff * a; + mb = clk_cfg->mclk * b; + if (ma == mb) { + cal->a = a; + cal->b = b; + return; + } + if (abs((mb - ma)) < min) { + cal->a = a; + cal->b = b; + min = abs(mb - ma); + } } - if (i2s_config->mode & I2S_MODE_ADC_BUILT_IN) { - i2s_ll_build_in_adc_ena(hal->dev); - i2s_ll_set_rx_chan_mod(hal->dev, 1); - i2s_ll_set_rx_fifo_mod(hal->dev, 1); - i2s_ll_set_rx_mono(hal->dev, 0); - } - // Buildin ADC and DAC have nothing to do with communication format configuration. - return; } -#endif - - i2s_hal_format_config(hal, i2s_config); } -void i2s_hal_enable_master_mode(i2s_hal_context_t *hal) +void i2s_hal_set_clock_src(i2s_hal_context_t *hal, i2s_clock_src_t sel) { - i2s_ll_set_tx_slave_mod(hal->dev, 0); //MASTER Slave - i2s_ll_set_rx_slave_mod(hal->dev, 1); //RX Slave + i2s_ll_tx_clk_set_src(hal->dev, sel); + i2s_ll_rx_clk_set_src(hal->dev, sel); } -void i2s_hal_enable_slave_mode(i2s_hal_context_t *hal) +void i2s_hal_tx_clock_config(i2s_hal_context_t *hal, i2s_hal_clock_cfg_t *clk_cfg) { - i2s_ll_set_tx_slave_mod(hal->dev, 1); //TX Slave - i2s_ll_set_rx_slave_mod(hal->dev, 1); //RX Slave + i2s_ll_mclk_div_t mclk_set; + i2s_hal_mclk_div_decimal_cal(clk_cfg, &mclk_set); + i2s_ll_tx_set_clk(hal->dev, &mclk_set); + i2s_ll_tx_set_bck_div_num(hal->dev, clk_cfg->bclk_div); +} + +void i2s_hal_rx_clock_config(i2s_hal_context_t *hal, i2s_hal_clock_cfg_t *clk_cfg) +{ + i2s_ll_mclk_div_t mclk_set; + i2s_hal_mclk_div_decimal_cal(clk_cfg, &mclk_set); + i2s_ll_rx_set_clk(hal->dev, &mclk_set); + i2s_ll_rx_set_bck_div_num(hal->dev, clk_cfg->bclk_div); +} + +void i2s_hal_enable_master_fd_mode(i2s_hal_context_t *hal) +{ + i2s_ll_tx_set_slave_mod(hal->dev, false); //TX master + i2s_ll_rx_set_slave_mod(hal->dev, true); //RX Slave +} + +void i2s_hal_enable_slave_fd_mode(i2s_hal_context_t *hal) +{ + i2s_ll_tx_set_slave_mod(hal->dev, true); //TX Slave + i2s_ll_rx_set_slave_mod(hal->dev, true); //RX Slave } void i2s_hal_init(i2s_hal_context_t *hal, int i2s_num) { - //Get hardware instance. + /* Get hardware instance */ hal->dev = I2S_LL_GET_HW(i2s_num); } + +#if SOC_I2S_SUPPORTS_PDM_TX +void i2s_hal_tx_set_pdm_mode_default(i2s_hal_context_t *hal, uint32_t sample_rate) +{ + /* enable pdm tx mode */ + i2s_ll_tx_enable_pdm(hal->dev, true); + /* set pdm tx default presacle */ + i2s_ll_tx_set_pdm_prescale(hal->dev, 0); + /* set pdm tx default sacle of high pass filter */ + i2s_ll_tx_set_pdm_hp_scale(hal->dev, I2S_PDM_SIG_SCALING_MUL_1); + /* set pdm tx default sacle of low pass filter */ + i2s_ll_tx_set_pdm_lp_scale(hal->dev, I2S_PDM_SIG_SCALING_MUL_1); + /* set pdm tx default sacle of sinc filter */ + i2s_ll_tx_set_pdm_sinc_scale(hal->dev, I2S_PDM_SIG_SCALING_MUL_1); + /* set pdm tx default sacle of sigma-delta filter */ + i2s_ll_tx_set_pdm_sd_scale(hal->dev, I2S_PDM_SIG_SCALING_MUL_1); + /* set pdm tx sample rate */ + i2s_ll_tx_set_pdm_fpfs(hal->dev, 960, sample_rate / 100); + +#if SOC_I2S_SUPPORTS_PDM_CODEC + /* enable pdm high pass filter */ + i2s_ll_tx_enable_pdm_hp_filter(hal->dev, true); + /* set pdm tx high pass filter parameters */ + i2s_ll_tx_set_pdm_hp_filter_param0(hal->dev, 6); + i2s_ll_tx_set_pdm_hp_filter_param5(hal->dev, 7); + /* enable pdm sigma-delta codec */ + i2s_ll_tx_enable_pdm_sd_codec(hal->dev, true); + /* set pdm tx sigma-delta codec dither */ + i2s_ll_tx_set_pdm_sd_dither(hal->dev, 0); + i2s_ll_tx_set_pdm_sd_dither2(hal->dev, 0); + +#endif // SOC_I2S_SUPPORTS_PDM_CODEC +} +#endif // SOC_I2S_SUPPORTS_PDM_TX + +#if SOC_I2S_SUPPORTS_PDM_RX +void i2s_hal_rx_set_pdm_mode_default(i2s_hal_context_t *hal) +{ + /* enable pdm rx mode */ + i2s_ll_rx_enable_pdm(hal->dev, true); + /* set pdm rx downsample number */ + i2s_ll_rx_set_pdm_dsr(hal->dev, I2S_PDM_DSR_8S); +} +#endif // SOC_I2S_SUPPORTS_PDM_RX + + +void i2s_hal_tx_set_common_mode(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg) +{ + /* Disable PDM tx mode and enable TDM mode (if support) */ + i2s_ll_tx_enable_pdm(hal->dev, false); + +#if SOC_I2S_SUPPORTS_TDM + i2s_ll_tx_enable_clock(hal->dev); + i2s_ll_tx_clk_set_src(hal->dev, I2S_CLK_D2CLK); // Set I2S_CLK_D2CLK as default + i2s_ll_mclk_use_tx_clk(hal->dev); + + i2s_ll_tx_set_active_chan_mask(hal->dev, hal_cfg->chan_mask); + i2s_ll_tx_enable_left_align(hal->dev, hal_cfg->left_align); + i2s_ll_tx_enable_big_endian(hal->dev, hal_cfg->big_edin); + i2s_ll_tx_set_bit_order(hal->dev, hal_cfg->bit_order_msb); + i2s_ll_tx_set_skip_mask(hal->dev, hal_cfg->skip_msk); +#else + i2s_ll_tx_enable_msb_right(hal->dev, false); + i2s_ll_tx_enable_right_first(hal->dev, false); + i2s_ll_tx_force_enable_fifo_mod(hal->dev, true); +#endif +} + +void i2s_hal_rx_set_common_mode(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg) +{ + /* Disable PDM rx mode and enable TDM rx mode (if support)*/ + i2s_ll_rx_enable_pdm(hal->dev, false); + +#if SOC_I2S_SUPPORTS_TDM + i2s_ll_rx_enable_clock(hal->dev); + i2s_ll_rx_clk_set_src(hal->dev, I2S_CLK_D2CLK); // Set I2S_CLK_D2CLK as default + i2s_ll_mclk_use_rx_clk(hal->dev); + + i2s_ll_rx_set_active_chan_mask(hal->dev, hal_cfg->chan_mask); + i2s_ll_rx_enable_left_align(hal->dev, hal_cfg->left_align); + i2s_ll_rx_enable_big_endian(hal->dev, hal_cfg->big_edin); + i2s_ll_rx_set_bit_order(hal->dev, hal_cfg->bit_order_msb); +#else + i2s_ll_rx_enable_msb_right(hal->dev, false); + i2s_ll_rx_enable_right_first(hal->dev, false); + i2s_ll_rx_force_enable_fifo_mod(hal->dev, true); +#endif +} + +static uint32_t i2s_hal_get_ws_bit(i2s_comm_format_t fmt, uint32_t chan_num, uint32_t chan_bits) +{ + switch (fmt) { + case I2S_COMM_FORMAT_STAND_MSB: + return chan_num * chan_bits / 2; + case I2S_COMM_FORMAT_STAND_PCM_SHORT: + return 1; + case I2S_COMM_FORMAT_STAND_PCM_LONG: + return chan_bits; + default: //I2S_COMM_FORMAT_STAND_I2S + return chan_num * chan_bits / 2; + } +} + +void i2s_hal_tx_set_channel_style(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg) +{ + uint32_t chan_num = 2; + uint32_t chan_bits = hal_cfg->chan_bits; + uint32_t data_bits = hal_cfg->sample_bits; + bool is_mono = (hal_cfg->chan_fmt == I2S_CHANNEL_FMT_ONLY_RIGHT) || + (hal_cfg->chan_fmt == I2S_CHANNEL_FMT_ONLY_LEFT); + + /* Set channel number and valid data bits */ +#if SOC_I2S_SUPPORTS_TDM + chan_num = hal_cfg->total_chan; + i2s_ll_tx_set_chan_num(hal->dev, chan_num); +#endif + i2s_ll_tx_set_sample_bit(hal->dev, chan_bits, data_bits); + i2s_ll_tx_enable_mono_mode(hal->dev, is_mono); + + /* Set communication format */ + bool shift_en = hal_cfg->comm_fmt == I2S_COMM_FORMAT_STAND_I2S ? true : false; + uint32_t ws_width = i2s_hal_get_ws_bit(hal_cfg->comm_fmt, chan_num, chan_bits); + i2s_ll_tx_enable_msb_shift(hal->dev, shift_en); + i2s_ll_tx_set_ws_width(hal->dev, ws_width); +#if SOC_I2S_SUPPORTS_TDM + i2s_ll_tx_set_half_sample_bit(hal->dev, chan_num * chan_bits / 2); +#endif +} + +void i2s_hal_rx_set_channel_style(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg) +{ + uint32_t chan_num = 2; + uint32_t chan_bits = hal_cfg->chan_bits; + uint32_t data_bits = hal_cfg->sample_bits; + bool is_mono = (hal_cfg->chan_fmt == I2S_CHANNEL_FMT_ONLY_RIGHT) || + (hal_cfg->chan_fmt == I2S_CHANNEL_FMT_ONLY_LEFT); + +#if SOC_I2S_SUPPORTS_TDM + chan_num = hal_cfg->total_chan; + i2s_ll_rx_set_chan_num(hal->dev, chan_num); +#endif + i2s_ll_rx_set_sample_bit(hal->dev, chan_bits, data_bits); + i2s_ll_rx_enable_mono_mode(hal->dev, is_mono); + + /* Set communication format */ + bool shift_en = hal_cfg->comm_fmt == I2S_COMM_FORMAT_STAND_I2S ? true : false; + uint32_t ws_width = i2s_hal_get_ws_bit(hal_cfg->comm_fmt, chan_num, chan_bits); + i2s_ll_rx_enable_msb_shift(hal->dev, shift_en); + i2s_ll_rx_set_ws_width(hal->dev, ws_width); +#if SOC_I2S_SUPPORTS_TDM + i2s_ll_rx_set_half_sample_bit(hal->dev, chan_num * chan_bits / 2); +#endif +} + +void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg) +{ +#if SOC_I2S_SUPPORTS_ADC + if (hal_cfg->mode & I2S_MODE_ADC_BUILT_IN) { + /* In ADC built-in mode, we need to call i2s_set_adc_mode to initialize the specific ADC channel. + * In the current stage, we only support ADC1 and single channel mode. + * In default data mode, the ADC data is in 12-bit resolution mode. + */ + i2s_ll_enable_builtin_adc(hal->dev, true); + return; + } + i2s_ll_enable_builtin_adc(hal->dev, false); +#endif +#if SOC_I2S_SUPPORTS_DAC + if (hal_cfg->mode & I2S_MODE_DAC_BUILT_IN) { + i2s_ll_enable_builtin_dac(hal->dev, true); + return; + } + i2s_ll_enable_builtin_dac(hal->dev, false); +#endif + /* Set configurations for TX mode */ + if (hal_cfg->mode & I2S_MODE_TX) { + i2s_ll_tx_stop(hal->dev); + i2s_ll_tx_reset(hal->dev); + i2s_ll_tx_set_slave_mod(hal->dev, (hal_cfg->mode & I2S_MODE_SLAVE) != 0); //TX Slave +#if SOC_I2S_SUPPORTS_PDM_TX + if (hal_cfg->mode & I2S_MODE_PDM) { + /* Set tx pdm mode */ + i2s_hal_tx_set_pdm_mode_default(hal, hal_cfg->sample_rate); + } else +#endif + { + /* Set tx common mode */ + i2s_hal_tx_set_common_mode(hal, hal_cfg); + i2s_hal_tx_set_channel_style(hal, hal_cfg); + } + } + + /* Set configurations for RX mode */ + if (hal_cfg->mode & I2S_MODE_RX) { + i2s_ll_rx_stop(hal->dev); + i2s_ll_rx_reset(hal->dev); + i2s_ll_rx_set_slave_mod(hal->dev, (hal_cfg->mode & I2S_MODE_SLAVE) != 0); //RX Slave +#if SOC_I2S_SUPPORTS_PDM_RX + if (hal_cfg->mode & I2S_MODE_PDM) { + /* Set rx pdm mode */ + i2s_hal_rx_set_pdm_mode_default(hal); + } else +#endif + { + /* Set rx common mode */ + i2s_hal_rx_set_common_mode(hal, hal_cfg); + i2s_hal_rx_set_channel_style(hal, hal_cfg); + } + } + + /* Set configurations for full-duplex mode */ + if ((hal_cfg->mode & I2S_MODE_RX) && (hal_cfg->mode & I2S_MODE_TX)) { + i2s_ll_share_bck_ws(hal->dev, true); + if (hal_cfg->mode & I2S_MODE_MASTER) { + i2s_hal_enable_master_fd_mode(hal); + } else { + i2s_hal_enable_slave_fd_mode(hal); + } + } +} diff --git a/components/hal/include/hal/adc_hal.h b/components/hal/include/hal/adc_hal.h index 5effc61b4b..807d620c63 100644 --- a/components/hal/include/hal/adc_hal.h +++ b/components/hal/include/hal/adc_hal.h @@ -276,7 +276,7 @@ esp_err_t adc_hal_convert(adc_ll_num_t adc_n, int channel, int *out_raw); /*--------------------------------------------------------------- ADC calibration setting ---------------------------------------------------------------*/ -#if SOC_ADC_HW_CALIBRATION_V1 +#if SOC_ADC_CALIBRATION_V1_SUPPORTED // ESP32-S2, C3 and H2 support HW offset calibration. /** @@ -312,7 +312,7 @@ void adc_hal_set_calibration_param(adc_ll_num_t adc_n, uint32_t param); */ uint32_t adc_hal_self_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool internal_gnd); -#endif //SOC_ADC_HW_CALIBRATION_V1 +#endif //SOC_ADC_CALIBRATION_V1_SUPPORTED #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 /*--------------------------------------------------------------- diff --git a/components/hal/include/hal/ds_hal.h b/components/hal/include/hal/ds_hal.h index 253fab9f96..40d5c35893 100644 --- a/components/hal/include/hal/ds_hal.h +++ b/components/hal/include/hal/ds_hal.h @@ -21,7 +21,7 @@ #pragma once #if CONFIG_IDF_TARGET_ESP32 - #error "ESP32 doesn't have a DS peripheral" +#error "ESP32 doesn't have a DS peripheral" #endif #include diff --git a/components/hal/include/hal/i2s_hal.h b/components/hal/include/hal/i2s_hal.h index 6964bfdf94..a08813db80 100644 --- a/components/hal/include/hal/i2s_hal.h +++ b/components/hal/include/hal/i2s_hal.h @@ -1,4 +1,4 @@ -// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// 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. @@ -25,13 +25,47 @@ #include "soc/i2s_periph.h" #include "soc/soc_caps.h" -#include "hal/i2s_ll.h" #include "hal/i2s_types.h" +#include "hal/i2s_ll.h" #ifdef __cplusplus extern "C" { #endif +/** + * @brief I2S clock configuration + */ +typedef struct { + uint32_t sclk; /*!< I2S module clock */ + uint32_t mclk; /*!< I2S master clock */ + uint32_t bclk; /*!< I2S bit clock */ + uint16_t mclk_div; /*!< I2S master clock division */ + uint16_t bclk_div; /*!< I2S bit clock division*/ +} i2s_hal_clock_cfg_t; + + +/** + * @brief I2S HAL configurations + */ +typedef struct { + i2s_mode_t mode; /*!< I2S work mode, using ored mask of `i2s_mode_t`*/ + uint32_t sample_rate; /*!< I2S sample rate*/ + i2s_comm_format_t comm_fmt; /*!< I2S communication format */ + i2s_channel_fmt_t chan_fmt; /*!< I2S channel format, there are total 16 channels in TDM mode.*/ + uint32_t sample_bits; /*!< I2S sample bits in one channel */ + uint32_t chan_bits; /*!< I2S total bits in one channel. Should not be smaller than 'sample_bits', default '0' means equal to 'sample_bits' */ + uint32_t active_chan; /*!< I2S active channel number */ + uint32_t total_chan; /*!< Total number of I2S channels */ + +#if SOC_I2S_SUPPORTS_TDM + uint32_t chan_mask; /*!< Active channel bit mask, set value in `i2s_channel_t` to enable specific channel, the bit map of active channel can not exceed (0x1<dev, status) - -/** - * @brief Clear I2S interrupt status - * - * @param hal Context of the HAL layer - * @param mask interrupt status mask - */ -#define i2s_hal_clear_intr_status(hal, mask) i2s_ll_clear_intr_status((hal)->dev, mask) - -/** - * @brief Get I2S out eof des address - * - * @param hal Context of the HAL layer - * @param addr out eof des address - */ -#define i2s_hal_get_out_eof_des_addr(hal, addr) i2s_ll_get_out_eof_des_addr((hal)->dev, addr) - -/** - * @brief Get I2S in eof des address - * - * @param hal Context of the HAL layer - * @param addr in eof des address - */ -#define i2s_hal_get_in_eof_des_addr(hal, addr) i2s_ll_get_in_eof_des_addr((hal)->dev, addr) - -/** - * @brief Enable I2S rx interrupt + * @brief Enable I2S module clock * * @param hal Context of the HAL layer */ -#define i2s_hal_enable_rx_intr(hal) i2s_ll_enable_rx_intr((hal)->dev) +#define i2s_hal_enable_module_clock(hal) i2s_ll_enable_clock((hal)->dev); /** - * @brief Disable I2S rx interrupt + * @brief Disable I2S module clock * * @param hal Context of the HAL layer */ -#define i2s_hal_disable_rx_intr(hal) i2s_ll_disable_rx_intr((hal)->dev) +#define i2s_hal_disable_module_clock(hal) i2s_ll_disable_clock((hal)->dev); /** - * @brief Disable I2S tx interrupt + * @brief Reset I2S TX channel * * @param hal Context of the HAL layer */ -#define i2s_hal_disable_tx_intr(hal) i2s_ll_disable_tx_intr((hal)->dev) +#define i2s_hal_reset_tx(hal) i2s_ll_tx_reset((hal)->dev) /** - * @brief Enable I2S tx interrupt + * @brief Reset I2S TX fifo * * @param hal Context of the HAL layer */ -#define i2s_hal_enable_tx_intr(hal) i2s_ll_enable_tx_intr((hal)->dev) +#define i2s_hal_reset_tx_fifo(hal) i2s_ll_tx_reset_fifo((hal)->dev) /** - * @brief Set I2S tx mode - * - * @param hal Context of the HAL layer - * @param ch i2s channel - * @param bits bits per sample - */ -void i2s_hal_set_tx_mode(i2s_hal_context_t *hal, i2s_channel_t ch, i2s_bits_per_sample_t bits); - -/** - * @brief Set I2S rx mode - * - * @param hal Context of the HAL layer - * @param ch i2s channel - * @param bits bits per sample - */ -void i2s_hal_set_rx_mode(i2s_hal_context_t *hal, i2s_channel_t ch, i2s_bits_per_sample_t bits); - -/** - * @brief Set I2S out link address - * - * @param hal Context of the HAL layer - * @param addr out link address - */ -#define i2s_hal_set_out_link_addr(hal, addr) i2s_ll_set_out_link_addr((hal)->dev, addr) - -/** - * @brief Set I2S out link address - * - * @param hal Context of the HAL layer - * @param addr out link address - */ -#define i2s_hal_set_out_link_addr(hal, addr) i2s_ll_set_out_link_addr((hal)->dev, addr) - -/** - * @brief Set I2S out link address - * - * @param hal Context of the HAL layer - * @param addr out link address - */ -#define i2s_hal_set_out_link_addr(hal, addr) i2s_ll_set_out_link_addr((hal)->dev, addr) - -/** - * @brief Set I2S in link - * - * @param hal Context of the HAL layer - * @param rx_eof_num in link eof num - * @param addr in link address - */ -void i2s_hal_set_in_link(i2s_hal_context_t *hal, uint32_t rx_eof_num, uint32_t addr); - -/** - * @brief Set I2S clk div - * - * @param hal Context of the HAL layer - * @param div_num i2s clkm div num - * @param div_a i2s clkm div a - * @param div_b i2s clkm div b - * @param tx_bck_div tx bck div num - * @param rx_bck_div rx bck div num - */ -void i2s_hal_set_clk_div(i2s_hal_context_t *hal, int div_num, int div_a, int div_b, int tx_bck_div, int rx_bck_div); - -/** - * @brief Set I2S clock sel - * - * @param hal Context of the HAL layer - * @param sel clock sel - */ -#define i2s_hal_set_clock_sel(hal, sel) i2s_ll_set_clk_sel((hal)->dev, sel) - -/** - * @brief Set I2S tx bits mod - * - * @param hal Context of the HAL layer - * @param bits bit width per sample. - */ -void i2s_hal_set_tx_bits_mod(i2s_hal_context_t *hal, i2s_bits_per_sample_t bits); - -/** - * @brief Set I2S rx bits mod - * - * @param hal Context of the HAL layer - * @param bits bit width per sample. - */ -void i2s_hal_set_rx_bits_mod(i2s_hal_context_t *hal, i2s_bits_per_sample_t bits); - -/** - * @brief Reset I2S TX & RX module, including DMA and FIFO + * @brief Reset I2S RX channel * * @param hal Context of the HAL layer */ -void i2s_hal_reset(i2s_hal_context_t *hal); +#define i2s_hal_reset_rx(hal) i2s_ll_rx_reset((hal)->dev) /** - * @brief Start I2S tx + * @brief Reset I2S RX fifo * * @param hal Context of the HAL layer */ -void i2s_hal_start_tx(i2s_hal_context_t *hal); +#define i2s_hal_reset_rx_fifo(hal) i2s_ll_rx_reset_fifo((hal)->dev) /** - * @brief Start I2S rx - * - * @param hal Context of the HAL layer - */ -void i2s_hal_start_rx(i2s_hal_context_t *hal); - -/** - * @brief Stop I2S tx - * - * @param hal Context of the HAL layer - */ -void i2s_hal_stop_tx(i2s_hal_context_t *hal); - -/** - * @brief Stop I2S rx - * - * @param hal Context of the HAL layer - */ -void i2s_hal_stop_rx(i2s_hal_context_t *hal); - -/** - * @brief Config I2S param - * - * @param hal Context of the HAL layer - * @param i2s_config I2S configurations - see i2s_config_t struct - */ -void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_config_t *i2s_config); - -/** - * @brief Enable I2S sig loopback - * - * @param hal Context of the HAL layer - */ -#define i2s_hal_enable_sig_loopback(hal) i2s_ll_set_sig_loopback((hal)->dev, 1) - -/** - * @brief Enable I2S master mode - * - * @param hal Context of the HAL layer - */ -void i2s_hal_enable_master_mode(i2s_hal_context_t *hal); - -/** - * @brief Enable I2S slave mode - * - * @param hal Context of the HAL layer - */ -void i2s_hal_enable_slave_mode(i2s_hal_context_t *hal); - -/** - * @brief Init the I2S hal and set the I2S to the default configuration. This function should be called first before other hal layer function is called + * @brief Get I2S hardware instance and enable I2S module clock + * @note This function should be called first before other hal layer function is called * * @param hal Context of the HAL layer * @param i2s_num The uart port number, the max port number is (I2S_NUM_MAX -1) */ void i2s_hal_init(i2s_hal_context_t *hal, int i2s_num); -#if SOC_I2S_SUPPORTS_PDM /** - * @brief Set I2S tx pdm + * @brief Configure I2S source clock * * @param hal Context of the HAL layer - * @param fp tx pdm fp - * @param fs tx pdm fs + * @param sel The source clock index */ -void i2s_hal_tx_pdm_cfg(i2s_hal_context_t *hal, uint32_t fp, uint32_t fs); +void i2s_hal_set_clock_src(i2s_hal_context_t *hal, i2s_clock_src_t sel); /** - * @brief Get I2S tx pdm + * @brief Set Tx channel style * * @param hal Context of the HAL layer - * @param dsr rx pdm dsr + * @param hal_cfg I2S hal configuration structer, refer to `i2s_hal_config_t` */ -void i2s_hal_rx_pdm_cfg(i2s_hal_context_t *hal, uint32_t dsr); +void i2s_hal_tx_set_channel_style(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg); /** - * @brief Get I2S tx pdm configuration + * @brief Set Rx channel style * * @param hal Context of the HAL layer - * @param fp Pointer to receive tx PDM fp configuration - * @param fs Pointer to receive tx PDM fs configuration + * @param hal_cfg I2S hal configuration structer, refer to `i2s_hal_config_t` */ -void i2s_hal_get_tx_pdm(i2s_hal_context_t *hal, uint32_t *fp, uint32_t *fs); +void i2s_hal_rx_set_channel_style(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg); /** - * @brief Get I2S rx pdm configuration + * @brief Initialize I2S hardware * * @param hal Context of the HAL layer - * @param dsr rx pdm dsr + * @param hal_cfg I2S hal configuration structer, refer to `i2s_hal_config_t` */ -void i2s_hal_get_rx_pdm(i2s_hal_context_t *hal, uint32_t *dsr); +void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg); + +/** + * @brief Enable I2S master full-duplex mode + * + * @param hal Context of the HAL layer + */ +void i2s_hal_enable_master_fd_mode(i2s_hal_context_t *hal); + +/** + * @brief Enable I2S slave full-duplex mode + * + * @param hal Context of the HAL layer + */ +void i2s_hal_enable_slave_fd_mode(i2s_hal_context_t *hal); + +/** + * @brief Start I2S tx + * + * @param hal Context of the HAL layer + */ +#define i2s_hal_start_tx(hal) i2s_ll_tx_start((hal)->dev) + +/** + * @brief Start I2S rx + * + * @param hal Context of the HAL layer + */ +#define i2s_hal_start_rx(hal) i2s_ll_rx_start((hal)->dev) + +/** + * @brief Stop I2S tx + * + * @param hal Context of the HAL layer + */ +#define i2s_hal_stop_tx(hal) i2s_ll_tx_stop((hal)->dev) + +/** + * @brief Stop I2S rx + * + * @param hal Context of the HAL layer + */ +#define i2s_hal_stop_rx(hal) i2s_ll_rx_stop((hal)->dev) + +/** + * @brief Set the received data length to trigger `in_suc_eof` interrupt. + * + * @param hal Context of the HAL layer + * @param eof_byte The byte length that trigger in_suc_eof interrupt. + */ +#define i2s_hal_set_rx_eof_num(hal, eof_byte) i2s_ll_rx_set_eof_num((hal)->dev, eof_byte) + +/** + * @brief Set I2S TX sample bit + * + * @param hal Context of the HAL layer + * @param chan_bit I2S TX chan bit + * @param data_bit The sample data bit length. + */ +#define i2s_hal_set_tx_sample_bit(hal, chan_bit, data_bit) i2s_ll_tx_set_sample_bit((hal)->dev, chan_bit, data_bit) + +/** + * @brief Set I2S RX sample bit + * + * @param hal Context of the HAL layer + * @param chan_bit I2S RX chan bit + * @param data_bit The sample data bit length. + */ +#define i2s_hal_set_rx_sample_bit(hal, chan_bit, data_bit) i2s_ll_rx_set_sample_bit((hal)->dev, chan_bit, data_bit) + +/** + * @brief Configure I2S TX module clock devider + * + * @param hal Context of the HAL layer + * @param clk_cfg I2S clock configuration + */ +void i2s_hal_tx_clock_config(i2s_hal_context_t *hal, i2s_hal_clock_cfg_t *clk_cfg); + +/** + * @brief Configure I2S RX module clock devider + * + * @param hal Context of the HAL layer + * @param clk_cfg I2S clock configuration + */ +void i2s_hal_rx_clock_config(i2s_hal_context_t *hal, i2s_hal_clock_cfg_t *clk_cfg); + +/** + * @brief Set I2S tx clock source + * + * @param hal Context of the HAL layer + * @param clk_src i2s tx clock source (see 'i2s_clock_src_t') + */ +#define i2s_hal_tx_set_clock_source(hal, clk_src) i2s_ll_tx_clk_set_src((hal)->dev, clk_src) + +/** + * @brief Set I2S rx clock source + * + * @param hal Context of the HAL layer + * @param clk_src i2s rx clock source (see 'i2s_clock_src_t') + */ +#define i2s_hal_rx_set_clock_source(hal, clk_src) i2s_ll_rx_clk_set_src((hal)->dev, clk_src) + +/** + * @brief Enable I2S tx slave mode + * + * @param hal Context of the HAL layer + * @param enable set 'true' to enable tx slave mode + */ +#define i2s_hal_tx_enable_slave_mode(hal, enable) i2s_ll_tx_set_slave_mod((hal)->dev, enable) + +/** + * @brief Enable I2S rx slave mode + * + * @param hal Context of the HAL layer + * @param enable set 'true' to enable rx slave mode + */ +#define i2s_hal_rx_enable_slave_mode(hal, enable) i2s_ll_rx_set_slave_mod((hal)->dev, enable) + +/** + * @brief Enable loopback mode + * + * @param hal Context of the HAL layer + */ +#define i2s_hal_enable_sig_loopback(hal) i2s_ll_share_bck_ws((hal)->dev, true) + +/** + * @brief Set I2S configuration for common TX mode + * @note Common mode is for non-PDM mode like philip/MSB/PCM + * + * @param hal Context of the HAL layer + * @param hal_cfg hal configuration structure + */ +void i2s_hal_tx_set_common_mode(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg); + +/** + * @brief Set I2S configuration for common RX mode + * @note Common mode is for non-PDM mode like philip/MSB/PCM + * + * @param hal Context of the HAL layer + * @param hal_cfg hal configuration structure + */ +void i2s_hal_rx_set_common_mode(i2s_hal_context_t *hal, const i2s_hal_config_t *hal_cfg); + +#if SOC_I2S_SUPPORTS_PCM +/** + * @brief Configure I2S TX PCM encoder or decoder. + * + * @param hal Context of the HAL layer + * @param cfg PCM configure paramater, refer to `i2s_pcm_compress_t` + */ +#define i2s_hal_tx_pcm_cfg(hal, cfg) i2s_ll_tx_set_pcm_type((hal)->dev, cfg) + +/** + * @brief Configure I2S RX PCM encoder or decoder. + * + * @param hal Context of the HAL layer + * @param cfg PCM configure paramater, refer to `i2s_pcm_compress_t` + */ +#define i2s_hal_rx_pcm_cfg(hal, cfg) i2s_ll_rx_set_pcm_type((hal)->dev, cfg) +#endif + +#if SOC_I2S_SUPPORTS_PDM_TX +/** + * @brief Configure I2S TX PDM sample rate + * Fpdm = 64*Fpcm*fp/fs + * + * @param hal Context of the HAL layer + * @param fp TX PDM fp paramater configuration + * @param fs TX PDM fs paramater configuration + */ +#define i2s_hal_set_tx_pdm_fpfs(hal, fp, fs) i2s_ll_tx_set_pdm_fpfs((hal)->dev, fp, fs) + +/** + * @brief Get I2S TX PDM fp + * + * @param hal Context of the HAL layer + * @return + * - fp configuration paramater + */ +#define i2s_hal_get_tx_pdm_fp(hal) i2s_ll_tx_get_pdm_fp((hal)->dev) + +/** + * @brief Get I2S TX PDM fs + * + * @param hal Context of the HAL layer + * @return + * - fs configuration paramater + */ +#define i2s_hal_get_tx_pdm_fs(hal) i2s_ll_tx_get_pdm_fs((hal)->dev) + +/** + * @brief Set I2S default configuration for PDM TX mode + * + * @param hal Context of the HAL layer + * @param sample_rate PDM sample rate + */ +void i2s_hal_tx_set_pdm_mode_default(i2s_hal_context_t *hal, uint32_t sample_rate); +#endif + +#if SOC_I2S_SUPPORTS_PDM_RX + +/** + * @brief Configure RX PDM downsample + * + * @param hal Context of the HAL layer + * @param dsr PDM downsample configuration paramater + */ +#define i2s_hal_set_rx_pdm_dsr(hal, dsr) i2s_ll_rx_set_pdm_dsr((hal)->dev, dsr) + +/** + * @brief Get RX PDM downsample configuration + * + * @param hal Context of the HAL layer + * @param dsr Pointer to accept PDM downsample configuration + */ +#define i2s_hal_get_rx_pdm_dsr(hal, dsr) i2s_ll_rx_get_pdm_dsr((hal)->dev, dsr) + +/** + * @brief Set I2S default configuration for PDM R mode + * + * @param hal Context of the HAL layer + */ +void i2s_hal_rx_set_pdm_mode_default(i2s_hal_context_t *hal); +#endif + +#if !SOC_GDMA_SUPPORTED +/** + * @brief Enable I2S TX DMA + * + * @param hal Context of the HAL layer + */ +#define i2s_hal_enable_tx_dma(hal) i2s_ll_enable_dma((hal)->dev,true) + +/** + * @brief Enable I2S RX DMA + * + * @param hal Context of the HAL layer + */ +#define i2s_hal_enable_rx_dma(hal) i2s_ll_enable_dma((hal)->dev,true) + +/** + * @brief Disable I2S TX DMA + * + * @param hal Context of the HAL layer + */ +#define i2s_hal_disable_tx_dma(hal) i2s_ll_enable_dma((hal)->dev,false) + +/** + * @brief Disable I2S RX DMA + * + * @param hal Context of the HAL layer + */ +#define i2s_hal_disable_rx_dma(hal) i2s_ll_enable_dma((hal)->dev,false) + +/** + * @brief Get I2S interrupt status + * + * @param hal Context of the HAL layer + * @return + * - module interrupt status + */ +#define i2s_hal_get_intr_status(hal) i2s_ll_get_intr_status((hal)->dev) + +/** + * @brief Get I2S interrupt status + * + * @param hal Context of the HAL layer + * @param mask Interrupt mask to be cleared. + */ +#define i2s_hal_clear_intr_status(hal, mask) i2s_ll_clear_intr_status((hal)->dev, mask) + +/** + * @brief Enable I2S RX interrupt + * + * @param hal Context of the HAL layer + */ +#define i2s_hal_enable_rx_intr(hal) i2s_ll_rx_enable_intr((hal)->dev) + +/** + * @brief Disable I2S RX interrupt + * + * @param hal Context of the HAL layer + */ +#define i2s_hal_disable_rx_intr(hal) i2s_ll_rx_disable_intr((hal)->dev) + +/** + * @brief Disable I2S TX interrupt + * + * @param hal Context of the HAL layer + */ +#define i2s_hal_disable_tx_intr(hal) i2s_ll_tx_disable_intr((hal)->dev) + +/** + * @brief Enable I2S TX interrupt + * + * @param hal Context of the HAL layer + */ +#define i2s_hal_enable_tx_intr(hal) i2s_ll_tx_enable_intr((hal)->dev) + +/** + * @brief Configure TX DMA descriptor address and start TX DMA + * + * @param hal Context of the HAL layer + * @param link_addr DMA descriptor link address. + */ +#define i2s_hal_start_tx_link(hal, link_addr) i2s_ll_tx_start_link((hal)->dev, link_addr) + +/** + * @brief Configure RX DMA descriptor address and start RX DMA + * + * @param hal Context of the HAL layer + * @param link_addr DMA descriptor link address. + */ +#define i2s_hal_start_rx_link(hal, link_addr) i2s_ll_rx_start_link((hal)->dev, link_addr) + +/** + * @brief Stop TX DMA link + * + * @param hal Context of the HAL layer + */ +#define i2s_hal_stop_tx_link(hal) i2s_ll_tx_stop_link((hal)->dev) + +/** + * @brief Stop RX DMA link + * + * @param hal Context of the HAL layer + */ +#define i2s_hal_stop_rx_link(hal) i2s_ll_rx_stop_link((hal)->dev) + +/** + * @brief Reset RX DMA + * + * @param hal Context of the HAL layer + */ +#define i2s_hal_reset_rxdma(hal) i2s_ll_rx_reset_dma((hal)->dev) + +/** + * @brief Reset TX DMA + * + * @param hal Context of the HAL layer + */ +#define i2s_hal_reset_txdma(hal) i2s_ll_tx_reset_dma((hal)->dev) + +/** + * @brief Get I2S out eof descriptor address + * + * @param hal Context of the HAL layer + * @param addr Pointer to accept out eof des address + */ +#define i2s_hal_get_out_eof_des_addr(hal, addr) i2s_ll_tx_get_eof_des_addr((hal)->dev, addr) + +/** + * @brief Get I2S in suc eof descriptor address + * + * @param hal Context of the HAL layer + * @param addr Pointer to accept in suc eof des address + */ +#define i2s_hal_get_in_eof_des_addr(hal, addr) i2s_ll_rx_get_eof_des_addr((hal)->dev, addr) +#endif + +#if SOC_I2S_SUPPORTS_ADC +/** + * @brief Enable Builtin DAC + * + * @param hal Context of the HAL layer + */ +#define i2s_hal_enable_builtin_dac(hal) i2s_ll_enable_builtin_dac((hal)->dev, true); + +/** + * @brief Enable Builtin ADC + * + * @param hal Context of the HAL layer + */ +#define i2s_hal_enable_builtin_adc(hal) i2s_ll_enable_builtin_adc((hal)->dev, true); + +/** + * @brief Disable Builtin ADC + * + * @param hal Context of the HAL layer + */ +#define i2s_hal_disable_builtin_adc(hal) i2s_ll_enable_builtin_adc((hal)->dev, false); +#endif + +#if SOC_I2S_SUPPORTS_DAC +/** + * @brief Disable Builtin DAC + * + * @param hal Context of the HAL layer + */ +#define i2s_hal_disable_builtin_dac(hal) i2s_ll_enable_builtin_dac((hal)->dev, false); #endif #ifdef __cplusplus diff --git a/components/hal/include/hal/i2s_types.h b/components/hal/include/hal/i2s_types.h index ba150cc7b3..48d745eb2f 100644 --- a/components/hal/include/hal/i2s_types.h +++ b/components/hal/include/hal/i2s_types.h @@ -1,4 +1,4 @@ -// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD +// 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. @@ -16,6 +16,7 @@ #include #include +#include #include #include "soc/soc_caps.h" @@ -23,35 +24,60 @@ extern "C" { #endif -/** - * @brief I2S port number, the max port number is (I2S_NUM_MAX -1). - */ -typedef enum { - I2S_NUM_0 = 0, /*!< I2S port 0 */ -#if SOC_I2S_NUM > 1 - I2S_NUM_1 = 1, /*!< I2S port 1 */ -#endif - I2S_NUM_MAX, /*!< I2S port max */ -} i2s_port_t; - /** * @brief I2S bit width per sample. * */ typedef enum { - I2S_BITS_PER_SAMPLE_8BIT = 8, /*!< I2S bits per sample: 8-bits*/ - I2S_BITS_PER_SAMPLE_16BIT = 16, /*!< I2S bits per sample: 16-bits*/ - I2S_BITS_PER_SAMPLE_24BIT = 24, /*!< I2S bits per sample: 24-bits*/ - I2S_BITS_PER_SAMPLE_32BIT = 32, /*!< I2S bits per sample: 32-bits*/ + I2S_BITS_PER_SAMPLE_8BIT = 8, /*!< data bit-width: 8 */ + I2S_BITS_PER_SAMPLE_16BIT = 16, /*!< data bit-width: 16 */ + I2S_BITS_PER_SAMPLE_24BIT = 24, /*!< data bit-width: 24 */ + I2S_BITS_PER_SAMPLE_32BIT = 32, /*!< data bit-width: 32 */ } i2s_bits_per_sample_t; +/** + * @brief I2S bit width per chan. + * + */ +typedef enum { + I2S_BITS_PER_CHAN_DEFAULT = (0), /*!< channel bit-width equals to data bit-width */ + I2S_BITS_PER_CHAN_8BIT = (8), /*!< channel bit-width: 8 */ + I2S_BITS_PER_CHAN_16BIT = (16), /*!< channel bit-width: 16 */ + I2S_BITS_PER_CHAN_24BIT = (24), /*!< channel bit-width: 24 */ + I2S_BITS_PER_CHAN_32BIT = (32), /*!< channel bit-width: 32 */ +} i2s_bits_per_chan_t; + /** * @brief I2S channel. * */ typedef enum { - I2S_CHANNEL_MONO = 1, /*!< I2S 1 channel (mono)*/ - I2S_CHANNEL_STEREO = 2 /*!< I2S 2 channel (stereo)*/ + I2S_CHANNEL_MONO = (0x01 << 31) | 0x03, /*!< I2S channel (mono), two channel enabled. In this mode, you only need to send one channel data but the fifo will copy same data for another channel automatically, then both channels will transmit same data. The highest bit is for differentiating I2S_CHANNEL_STEREO since they both use two channels */ + I2S_CHANNEL_STEREO = 0x03, /*!< I2S channel (stereo), two channel enabled. In this mode, two channels will transmit different data. */ +#if SOC_I2S_SUPPORTS_TDM + // Bit map of active chan. + // There are 16 channels in TDM mode. + // For TX module, only the active channel send the audio data, the inactive channel send a constant(configurable) or will be skiped if 'skip_msk' is set. + // For RX module, only receive the audio data in active channels, the data in inactive channels will be ignored. + // the bit map of active channel can not exceed (0x1< 0, then the clock output for i2s is fixed and equal to the fixed_mclk value.*/ -} i2s_config_t; - -/** - * @brief I2S event types - * + * @brief The multiple of mclk to sample rate */ typedef enum { - I2S_EVENT_DMA_ERROR, - I2S_EVENT_TX_DONE, /*!< I2S DMA finish sent 1 buffer*/ - I2S_EVENT_RX_DONE, /*!< I2S DMA finish received 1 buffer*/ - I2S_EVENT_MAX, /*!< I2S event max index*/ -} i2s_event_type_t; + I2S_MCLK_MULTIPLE_DEFAULT = 0, /*!< Default value. mclk = sample_rate * 256 */ + I2S_MCLK_MULTIPLE_128 = 128, /*!< mclk = sample_rate * 128 */ + I2S_MCLK_MULTIPLE_256 = 256, /*!< mclk = sample_rate * 256 */ + I2S_MCLK_MULTIPLE_384 = 384, /*!< mclk = sample_rate * 384 */ +} i2s_mclk_multiple_t; -#if SOC_I2S_SUPPORTS_ADC_DAC +#if SOC_I2S_SUPPORTS_DAC /** * @brief I2S DAC mode for i2s_set_dac_mode. * - * @note PDM and built-in DAC functions are only supported on I2S0 for current ESP32 chip. + * @note Built-in DAC functions are only supported on I2S0 for current ESP32 chip. */ typedef enum { I2S_DAC_CHANNEL_DISABLE = 0, /*!< Disable I2S built-in DAC signals*/ @@ -157,29 +167,23 @@ typedef enum { I2S_DAC_CHANNEL_BOTH_EN = 0x3, /*!< Enable both of the I2S built-in DAC channels.*/ I2S_DAC_CHANNEL_MAX = 0x4, /*!< I2S built-in DAC mode max index*/ } i2s_dac_mode_t; -#endif //SOC_I2S_SUPPORTS_ADC_DAC +#endif //SOC_I2S_SUPPORTS_DAC +#if SOC_I2S_SUPPORTS_PCM /** - * @brief Event structure used in I2S event queue + * @brief A/U-law decompress or compress configuration. * */ -typedef struct { - i2s_event_type_t type; /*!< I2S event type */ - size_t size; /*!< I2S data size for I2S_DATA event*/ -} i2s_event_t; +typedef enum { + I2S_PCM_DISABLE = 0, /*!< Disable A/U law decopress or compress*/ + I2S_PCM_A_DECOMPRESS, /*!< A-law decompress*/ + I2S_PCM_A_COMPRESS, /*!< A-law compress*/ + I2S_PCM_U_DECOMPRESS, /*!< U-law decompress*/ + I2S_PCM_U_COMPRESS, /*!< U-law compress*/ +} i2s_pcm_compress_t; +#endif -/** - * @brief I2S pin number for i2s_set_pin - * - */ -typedef struct { - int bck_io_num; /*!< BCK in out pin*/ - int ws_io_num; /*!< WS in out pin*/ - int data_out_num; /*!< DATA out pin*/ - int data_in_num; /*!< DATA in pin*/ -} i2s_pin_config_t; - -#if SOC_I2S_SUPPORTS_PDM +#if SOC_I2S_SUPPORTS_PDM_RX /** * @brief I2S PDM RX downsample mode */ @@ -188,17 +192,16 @@ typedef enum { I2S_PDM_DSR_16S, /*!< downsampling number is 16 for PDM RX mode*/ I2S_PDM_DSR_MAX, } i2s_pdm_dsr_t; - -/** - * @brief PDM PCM convter enable/disable. - * - */ -typedef enum { - PDM_PCM_CONV_ENABLE, /*!< Enable PDM PCM convert*/ - PDM_PCM_CONV_DISABLE, /*!< Disable PDM PCM convert*/ -} pdm_pcm_conv_t; #endif +#if SOC_I2S_SUPPORTS_PDM_TX +typedef enum { + I2S_PDM_SIG_SCALING_DIV_2 = 0, /*!< I2S TX PDM sigmadelta signal scaling: /2 */ + I2S_PDM_SIG_SCALING_MUL_1 = 1, /*!< I2S TX PDM sigmadelta signal scaling: x1 */ + I2S_PDM_SIG_SCALING_MUL_2 = 2, /*!< I2S TX PDM sigmadelta signal scaling: x2 */ + I2S_PDM_SIG_SCALING_MUL_4 = 3, /*!< I2S TX PDM sigmadelta signal scaling: x4 */ +} i2s_pdm_sig_scale_t; +#endif #ifdef __cplusplus } diff --git a/components/hal/include/hal/lcd_hal.h b/components/hal/include/hal/lcd_hal.h index a6bcba166c..76e28dda0e 100644 --- a/components/hal/include/hal/lcd_hal.h +++ b/components/hal/include/hal/lcd_hal.h @@ -24,10 +24,10 @@ extern "C" { #endif -#include "soc/lcd_cam_struct.h" +typedef struct lcd_cam_dev_t *lcd_soc_handle_t; typedef struct { - lcd_cam_dev_t *dev; + lcd_soc_handle_t dev; } lcd_hal_context_t; void lcd_hal_init(lcd_hal_context_t *hal, int id); diff --git a/components/hal/include/hal/lcd_types.h b/components/hal/include/hal/lcd_types.h new file mode 100644 index 0000000000..69dab14801 --- /dev/null +++ b/components/hal/include/hal/lcd_types.h @@ -0,0 +1,42 @@ +// Copyright 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. + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief LCD clock source + * @note User should select the clock source based on the real requirement: + * ╔═════════════════════╦══════════════════════════╦════════════════════════════╗ + * ║ LCD clock source ║ Features ║ Power Management ║ + * ╠═════════════════════╬══════════════════════════╬════════════════════════════╣ + * ║ LCD_CLK_SRC_PLL160M ║ High resolution, fixed ║ ESP_PM_APB_FREQ_MAX lock ║ + * ╠═════════════════════╬══════════════════════════╬════════════════════════════╣ + * ║ LCD_CLK_SRC_APLL ║ Configurable resolution ║ ESP_PM_NO_LIGHT_SLEEP lock ║ + * ╠═════════════════════╬══════════════════════════╬════════════════════════════╣ + * ║ LCD_CLK_SRC_XTAL ║ Medium resolution, fixed ║ No PM lock ║ + * ╚═════════════════════╩══════════════════════════╩════════════════════════════╝ + */ +typedef enum { + LCD_CLK_SRC_PLL160M, /*!< Select PLL160M as the source clock */ + LCD_CLK_SRC_APLL, /*!< Select APLL as the source clock */ + LCD_CLK_SRC_XTAL, /*!< Select XTAL as the source clock */ +} lcd_clock_source_t; + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32h2/include/soc/i2s_caps.h b/components/hal/include/hal/memprot_types.h similarity index 58% rename from components/soc/esp32h2/include/soc/i2s_caps.h rename to components/hal/include/hal/memprot_types.h index 69dfb68373..42231f43ea 100644 --- a/components/soc/esp32h2/include/soc/i2s_caps.h +++ b/components/hal/include/hal/memprot_types.h @@ -1,4 +1,4 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// Copyright 2015-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. @@ -14,9 +14,22 @@ #pragma once -#define SOC_I2S_APLL_MIN_FREQ (250000000) -#define SOC_I2S_APLL_MAX_FREQ (500000000) -#define SOC_I2S_APLL_MIN_RATE (10675) //in Hz, I2S Clock rate limited by hardware -#define SOC_I2S_MAX_BUFFER_SIZE (4 * 1024 * 1024) //the maximum RAM can be allocated +#ifdef __cplusplus +extern "C" { +#endif -#define SOC_I2S_NUM (1) +/** + * @brief Memprot LL error codes + * + */ +typedef enum { + MEMP_LL_OK = 0, + MEMP_LL_FAIL = 1, + MEMP_LL_ERR_SPLIT_ADDR_INVALID = 2, + MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED = 3, + MEMP_LL_ERR_UNI_BLOCK_INVALID = 4 +} memprot_ll_err_t; + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/include/hal/pcnt_hal.h b/components/hal/include/hal/pcnt_hal.h index 8d2253e46e..3d10c8d8c6 100644 --- a/components/hal/include/hal/pcnt_hal.h +++ b/components/hal/include/hal/pcnt_hal.h @@ -23,10 +23,7 @@ #pragma once -#include -#include "soc/pcnt_periph.h" -#include "hal/pcnt_types.h" -#include "hal/pcnt_ll.h" +#include "soc/pcnt_struct.h" #ifdef __cplusplus extern "C" { @@ -35,188 +32,18 @@ extern "C" { /** * Context that should be maintained by both the driver and the HAL */ - typedef struct { - pcnt_dev_t *dev; + pcnt_dev_t *dev; /*!< PCNT peripheral register base address */ } pcnt_hal_context_t; /** - * @brief Set PCNT counter mode + * @brief Init the PCNT hal and set the PCNT to the default configuration. + * @note This function should be called first before other hal layer function is called. * * @param hal Context of the HAL layer - * @param unit PCNT unit number - * @param channel PCNT channel number - * @param pos_mode Counter mode when detecting positive edge - * @param neg_mode Counter mode when detecting negative edge - * @param hctrl_mode Counter mode when control signal is high level - * @param lctrl_mode Counter mode when control signal is low level + * @param group_id PCNT group ID */ -#define pcnt_hal_set_mode(hal, unit, channel, pos_mode, neg_mode, hctrl_mode, lctrl_mode) pcnt_ll_set_mode((hal)->dev, unit, channel, pos_mode, neg_mode, hctrl_mode, lctrl_mode) - -/** - * @brief Get pulse counter value - * - * @param hal Context of the HAL layer - * @param unit Pulse Counter unit number - * @param count Pointer to accept counter value - */ -#define pcnt_hal_get_counter_value(hal, unit, count) pcnt_ll_get_counter_value((hal)->dev, unit, count) - -/** - * @brief Pause PCNT counter of PCNT unit - * - * @param hal Context of the HAL layer - * @param unit PCNT unit number - */ -#define pcnt_hal_counter_pause(hal, unit) pcnt_ll_counter_pause((hal)->dev, unit) - -/** - * @brief Resume counting for PCNT counter - * - * @param hal Context of the HAL layer - * @param unit PCNT unit number, select from unit_t - */ -#define pcnt_hal_counter_resume(hal, unit) pcnt_ll_counter_resume((hal)->dev, unit) - -/** - * @brief Clear and reset PCNT counter value to zero - * - * @param hal Context of the HAL layer - * @param unit PCNT unit number, select from unit_t - */ -#define pcnt_hal_counter_clear(hal, unit) pcnt_ll_counter_clear((hal)->dev, unit) - -/** - * @brief Enable PCNT interrupt for PCNT unit - * @note - * Each Pulse counter unit has five watch point events that share the same interrupt. - * Configure events with pcnt_event_enable() and pcnt_event_disable() - * - * @param hal Context of the HAL layer - * @param unit PCNT unit number - */ -#define pcnt_hal_intr_enable(hal, unit) pcnt_ll_intr_enable((hal)->dev, unit) - -/** - * @brief Disable PCNT interrupt for PCNT unit - * - * @param hal Context of the HAL layer - * @param unit PCNT unit number - */ -#define pcnt_hal_intr_disable(hal, unit) pcnt_ll_intr_disable((hal)->dev, unit) - -/** - * @brief Get PCNT interrupt status - * - * @param hal Context of the HAL layer - * @param mask The interrupt status mask to be cleared. Pointer to accept value interrupt status mask. - */ -#define pcnt_hal_get_intr_status(hal, mask) pcnt_ll_get_intr_status((hal)->dev, mask) - -/** - * @brief Clear PCNT interrupt status - * - * @param hal Context of the HAL layer - * @param mask The interrupt status mask to be cleared. - */ -#define pcnt_hal_clear_intr_status(hal, mask) pcnt_ll_clear_intr_status((hal)->dev, mask) - -/** - * @brief Enable PCNT event of PCNT unit - * - * @param hal Context of the HAL layer - * @param unit PCNT unit number - * @param evt_type Watch point event type. - * All enabled events share the same interrupt (one interrupt per pulse counter unit). - */ -#define pcnt_hal_event_enable(hal, unit, evt_type) pcnt_ll_event_enable((hal)->dev, unit, evt_type) - -/** - * @brief Disable PCNT event of PCNT unit - * - * @param hal Context of the HAL layer - * @param unit PCNT unit number - * @param evt_type Watch point event type. - * All enabled events share the same interrupt (one interrupt per pulse counter unit). - */ -#define pcnt_hal_event_disable(hal, unit, evt_type) pcnt_ll_event_disable((hal)->dev, unit, evt_type) - -/** - * @brief Set PCNT event value of PCNT unit - * - * @param hal Context of the HAL layer - * @param unit PCNT unit number - * @param evt_type Watch point event type. - * All enabled events share the same interrupt (one interrupt per pulse counter unit). - * - * @param value Counter value for PCNT event - */ -#define pcnt_hal_set_event_value(hal, unit, evt_type, value) pcnt_ll_set_event_value((hal)->dev, unit, evt_type, value) - -/** - * @brief Get PCNT event value of PCNT unit - * - * @param hal Context of the HAL layer - * @param unit PCNT unit number - * @param evt_type Watch point event type. - * All enabled events share the same interrupt (one interrupt per pulse counter unit). - * @param value Pointer to accept counter value for PCNT event - */ -#define pcnt_hal_get_event_value(hal, unit, evt_type, value) pcnt_ll_get_event_value((hal)->dev, unit, evt_type, value) - -/** - * @brief Get PCNT event status - * - * @param hal Context of the HAL layer - * @param unit PCNT unit number - * @return event status word - */ -#define pcnt_hal_get_event_status(hal, unit) pcnt_ll_get_event_status((hal)->dev, unit) - -/** - * @brief Set PCNT filter value - * - * @param hal Context of the HAL layer - * @param unit PCNT unit number - * @param filter_val PCNT signal filter value, counter in APB_CLK cycles. - * Any pulses lasting shorter than this will be ignored when the filter is enabled. - * @note - * filter_val is a 10-bit value, so the maximum filter_val should be limited to 1023. - */ -#define pcnt_hal_set_filter_value(hal, unit, filter_val) pcnt_ll_set_filter_value((hal)->dev, unit, filter_val) - -/** - * @brief Get PCNT filter value - * - * @param hal Context of the HAL layer - * @param unit PCNT unit number - * @param filter_val Pointer to accept PCNT filter value. - */ -#define pcnt_hal_get_filter_value(hal, unit, filter_val) pcnt_ll_get_filter_value((hal)->dev, unit, filter_val) - -/** - * @brief Enable PCNT input filter - * - * @param hal Context of the HAL layer - * @param unit PCNT unit number - */ -#define pcnt_hal_filter_enable(hal, unit) pcnt_ll_filter_enable((hal)->dev, unit) - -/** - * @brief Disable PCNT input filter - * - * @param hal Context of the HAL layer - * @param unit PCNT unit number - */ -#define pcnt_hal_filter_disable(hal, unit) pcnt_ll_filter_disable((hal)->dev, unit) - -/** - * @brief Init the PCNT hal and set the PCNT to the default configuration. This function should be called first before other hal layer function is called - * - * @param hal Context of the HAL layer - * @param pcnt_num The uart port number, the max port number is (PCNT_NUM_MAX -1) - */ -void pcnt_hal_init(pcnt_hal_context_t *hal, int pcnt_num); +void pcnt_hal_init(pcnt_hal_context_t *hal, int group_id); #ifdef __cplusplus } diff --git a/components/hal/include/hal/pcnt_types.h b/components/hal/include/hal/pcnt_types.h index 6f09177b53..0696e756cc 100644 --- a/components/hal/include/hal/pcnt_types.h +++ b/components/hal/include/hal/pcnt_types.h @@ -1,4 +1,4 @@ -// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// Copyright 2015-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. @@ -18,93 +18,36 @@ extern "C" { #endif -#include "soc/soc_caps.h" - -#define PCNT_PIN_NOT_USED (-1) /*!< When selected for a pin, this pin will not be used */ - /** - * @brief PCNT port number, the max port number is (PCNT_PORT_MAX - 1). + * @brief PCNT channel action on control level + * */ typedef enum { - PCNT_PORT_0 = 0, /*!< PCNT port 0 */ - PCNT_PORT_MAX, /*!< PCNT port max */ -} pcnt_port_t; + PCNT_CHANNEL_LEVEL_ACTION_KEEP, /*!< Keep current count mode */ + PCNT_CHANNEL_LEVEL_ACTION_INVERSE, /*!< Invert current count mode (increase -> decrease, decrease -> increase) */ + PCNT_CHANNEL_LEVEL_ACTION_HOLD, /*!< Hold current count value */ +} pcnt_channel_level_action_t; /** - * @brief Selection of all available PCNT units + * @brief PCNT channel action on signal edge + * */ typedef enum { - PCNT_UNIT_0 = 0, /*!< PCNT unit 0 */ - PCNT_UNIT_1 = 1, /*!< PCNT unit 1 */ - PCNT_UNIT_2 = 2, /*!< PCNT unit 2 */ - PCNT_UNIT_3 = 3, /*!< PCNT unit 3 */ -#if SOC_PCNT_UNIT_NUM > 4 - PCNT_UNIT_4 = 4, /*!< PCNT unit 4 */ - PCNT_UNIT_5 = 5, /*!< PCNT unit 5 */ - PCNT_UNIT_6 = 6, /*!< PCNT unit 6 */ - PCNT_UNIT_7 = 7, /*!< PCNT unit 7 */ -#endif - PCNT_UNIT_MAX, -} pcnt_unit_t; + PCNT_CHANNEL_EDGE_ACTION_HOLD, /*!< Hold current count value */ + PCNT_CHANNEL_EDGE_ACTION_INCREASE, /*!< Increase count value */ + PCNT_CHANNEL_EDGE_ACTION_DECREASE, /*!< Decrease count value */ +} pcnt_channel_edge_action_t; /** - * @brief Selection of available modes that determine the counter's action depending on the state of the control signal's input GPIO - * @note Configuration covers two actions, one for high, and one for low level on the control input + * @brief PCNT unit counter value's sign + * */ typedef enum { - PCNT_MODE_KEEP = 0, /*!< Control mode: won't change counter mode*/ - PCNT_MODE_REVERSE = 1, /*!< Control mode: invert counter mode(increase -> decrease, decrease -> increase) */ - PCNT_MODE_DISABLE = 2, /*!< Control mode: Inhibit counter(counter value will not change in this condition) */ - PCNT_MODE_MAX -} pcnt_ctrl_mode_t; - -/** - * @brief Selection of available modes that determine the counter's action on the edge of the pulse signal's input GPIO - * @note Configuration covers two actions, one for positive, and one for negative edge on the pulse input - */ -typedef enum { - PCNT_COUNT_DIS = 0, /*!< Counter mode: Inhibit counter(counter value will not change in this condition) */ - PCNT_COUNT_INC = 1, /*!< Counter mode: Increase counter value */ - PCNT_COUNT_DEC = 2, /*!< Counter mode: Decrease counter value */ - PCNT_COUNT_MAX -} pcnt_count_mode_t; - -/** - * @brief Selection of channels available for a single PCNT unit - */ -typedef enum { - PCNT_CHANNEL_0 = 0x00, /*!< PCNT channel 0 */ - PCNT_CHANNEL_1 = 0x01, /*!< PCNT channel 1 */ - PCNT_CHANNEL_MAX, -} pcnt_channel_t; - -/** - * @brief Selection of counter's events the may trigger an interrupt - */ -typedef enum { - PCNT_EVT_THRES_1 = BIT(2), /*!< PCNT watch point event: threshold1 value event */ - PCNT_EVT_THRES_0 = BIT(3), /*!< PCNT watch point event: threshold0 value event */ - PCNT_EVT_L_LIM = BIT(4), /*!< PCNT watch point event: Minimum counter value */ - PCNT_EVT_H_LIM = BIT(5), /*!< PCNT watch point event: Maximum counter value */ - PCNT_EVT_ZERO = BIT(6), /*!< PCNT watch point event: counter value zero event */ - PCNT_EVT_MAX -} pcnt_evt_type_t; - -/** - * @brief Pulse Counter configuration for a single channel - */ -typedef struct { - int pulse_gpio_num; /*!< Pulse input GPIO number, if you want to use GPIO16, enter pulse_gpio_num = 16, a negative value will be ignored */ - int ctrl_gpio_num; /*!< Control signal input GPIO number, a negative value will be ignored */ - pcnt_ctrl_mode_t lctrl_mode; /*!< PCNT low control mode */ - pcnt_ctrl_mode_t hctrl_mode; /*!< PCNT high control mode */ - pcnt_count_mode_t pos_mode; /*!< PCNT positive edge count mode */ - pcnt_count_mode_t neg_mode; /*!< PCNT negative edge count mode */ - int16_t counter_h_lim; /*!< Maximum counter value */ - int16_t counter_l_lim; /*!< Minimum counter value */ - pcnt_unit_t unit; /*!< PCNT unit number */ - pcnt_channel_t channel; /*!< the PCNT channel */ -} pcnt_config_t; + PCNT_UNIT_COUNT_SIGN_ZERO_POS, /*!< positive value to zero */ + PCNT_UNIT_COUNT_SIGN_ZERO_NEG, /*!< negative value to zero */ + PCNT_UNIT_COUNT_SIGN_NEG, /*!< counter value negative */ + PCNT_UNIT_COUNT_SIGN_POS, /*!< counter value positive */ +} pcnt_unit_count_sign_t; #ifdef __cplusplus } diff --git a/components/hal/include/hal/rtc_hal.h b/components/hal/include/hal/rtc_hal.h index 8d74f4c4cd..90f965ed58 100644 --- a/components/hal/include/hal/rtc_hal.h +++ b/components/hal/include/hal/rtc_hal.h @@ -14,12 +14,36 @@ #pragma once +#include "soc/soc_caps.h" #include "hal/gpio_types.h" #include "hal/rtc_cntl_ll.h" #if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 #include "hal/rtc_io_ll.h" #endif +typedef struct rtc_cntl_sleep_retent { +#if SOC_PM_SUPPORT_CPU_PD + void *cpu_pd_mem; /* Internal ram address for cpu retention */ +#endif // SOC_PM_SUPPORT_CPU_PD +#if SOC_PM_SUPPORT_TAGMEM_PD + struct { + void *link_addr; /* Internal ram address for tagmem retention */ + struct { + uint32_t start_point: 8, /* the row of start for i-cache tag memory */ + vld_size: 8, /* valid size of i-cache tag memory, unit: 4 i-cache tagmem blocks */ + size: 8, /* i-cache tag memory size, unit: 4 i-cache tagmem blocks */ + enable: 1; /* enable or disable i-cache tagmem retention */ + } icache; + struct { + uint32_t start_point: 9, /* the row of start for d-cache tag memory */ + vld_size: 9, /* valid size of d-cache tag memory, unit: 4 d-cache tagmem blocks */ + size: 9, /* d-cache tag memory size, unit: 4 d-cache tagmem blocks */ + enable: 1; /* enable or disable d-cache tagmem retention */ + } dcache; + } tagmem; +#endif // SOC_PM_SUPPORT_TAGMEM_PD +} rtc_cntl_sleep_retent_t; + #define RTC_HAL_DMA_LINK_NODE_SIZE (16) #if SOC_PM_SUPPORT_EXT_WAKEUP @@ -46,9 +70,21 @@ void * rtc_cntl_hal_dma_link_init(void *elem, void *buff, int size, void *next); +#if SOC_PM_SUPPORT_CPU_PD + void rtc_cntl_hal_enable_cpu_retention(void *addr); -#define rtc_cntl_hal_disable_cpu_retention() rtc_cntl_ll_disable_cpu_retention() +void rtc_cntl_hal_disable_cpu_retention(void *addr); + +#endif + +#if SOC_PM_SUPPORT_TAGMEM_PD + +void rtc_cntl_hal_enable_tagmem_retention(void *addr); + +void rtc_cntl_hal_disable_tagmem_retention(void *addr); + +#endif /* * Enable wakeup from ULP coprocessor. diff --git a/components/hal/include/hal/spi_flash_hal.h b/components/hal/include/hal/spi_flash_hal.h index dbbb5ff53b..ae37016fa2 100644 --- a/components/hal/include/hal/spi_flash_hal.h +++ b/components/hal/include/hal/spi_flash_hal.h @@ -51,20 +51,41 @@ typedef struct { uint32_t flags; ///< Flags for configurations with one set of driver code. (e.g. QPI mode, auto-suspend mode, 64-bit address mode, etc.) #define SPI_FLASH_HOST_CONTEXT_FLAG_AUTO_SUSPEND BIT(0) ///< When the auto-suspend is setup in configuration. #define SPI_FLASH_HOST_CONTEXT_FLAG_AUTO_RESUME BIT(1) ///< Setup auto-resume feature. +#define SPI_FLASH_HOST_CONTEXT_FLAG_OCTAL_MODE BIT(2) ///< Flash works under octal spi mode. spi_flash_sus_cmd_conf sus_cfg; ///< To store suspend command/mask information. + uint32_t slicer_flags; /// Slicer flags for configuring how to slice data correctly while reading or writing. +#define SPI_FLASH_HOST_CONTEXT_SLICER_FLAG_DTR BIT(0) ///< Slice data according to DTR mode, the address and length must be even (A0=0). } spi_flash_hal_context_t; -_Static_assert(sizeof(spi_flash_hal_context_t) == 36, "size of spi_flash_hal_context_t incorrect. Please check data compatibility with the ROM"); +_Static_assert(sizeof(spi_flash_hal_context_t) == 40, "size of spi_flash_hal_context_t incorrect. Please check data compatibility with the ROM"); + +/// This struct provide MSPI Flash necessary timing related config, should be consistent with that in union in `spi_flash_hal_config_t`. +typedef struct { + uint32_t extra_dummy; + uint32_t cs_hold; + uint8_t cs_setup; + spi_flash_ll_clock_reg_t clock_config; +} spi_flash_hal_timing_config_t; /// Configuration structure for the SPI driver. typedef struct { - spi_host_device_t host_id; ///< SPI peripheral ID. - int cs_num; ///< Which cs pin is used, 0-(SOC_SPI_PERIPH_CS_NUM-1). + union { + struct { + uint32_t extra_dummy; ///< extra dummy for timing compensation. + uint32_t cs_hold; ///< CS hold time config used by the host + uint8_t cs_setup; ///< (cycles-1) of prepare phase by spi clock + spi_flash_ll_clock_reg_t clock_config; ///< (optional) Clock configuration for Octal flash. + }; + spi_flash_hal_timing_config_t timing_reg; ///< Reconfigure timing tuning regs. + }; bool iomux; ///< Whether the IOMUX is used, used for timing compensation. int input_delay_ns; ///< Input delay on the MISO pin after the launch clock, used for timing compensation. esp_flash_speed_t speed;///< SPI flash clock speed to work at. - uint32_t cs_hold; ///< CS hold time config used by the host - uint8_t cs_setup; ///< (cycles-1) of prepare phase by spi clock + spi_host_device_t host_id; ///< SPI peripheral ID. + int cs_num; ///< Which cs pin is used, 0-(SOC_SPI_PERIPH_CS_NUM-1). bool auto_sus_en; ///< Auto suspend feature enable bit 1: enable, 0: disable. + bool octal_mode_en; ///< Octal spi flash mode enable bit 1: enable, 0: disable. + bool using_timing_tuning; ///< System exist SPI0/1 timing tuning, using value from system directely if set to 1. + esp_flash_io_mode_t default_io_mode; ///< Default flash io mode. } spi_flash_hal_config_t; /** diff --git a/components/hal/include/hal/spi_flash_types.h b/components/hal/include/hal/spi_flash_types.h index 0cc605595f..c9d5035e60 100644 --- a/components/hal/include/hal/spi_flash_types.h +++ b/components/hal/include/hal/spi_flash_types.h @@ -37,6 +37,7 @@ typedef struct { #define SPI_FLASH_TRANS_FLAG_BYTE_SWAP BIT(2) ///< Used for DTR mode, to swap the bytes of a pair of rising/falling edge uint16_t command; ///< Command to send uint8_t dummy_bitlen; ///< Basic dummy bits to use + uint32_t io_mode; ///< Flash working mode when `SPI_FLASH_IGNORE_BASEIO` is specified. } spi_flash_trans_t; /** @@ -54,6 +55,7 @@ typedef enum { ESP_FLASH_26MHZ, ///< The flash runs under 26MHz ESP_FLASH_40MHZ, ///< The flash runs under 40MHz ESP_FLASH_80MHZ, ///< The flash runs under 80MHz + ESP_FLASH_120MHZ, ///< The flash runs under 120MHz, 120MHZ can only be used by main flash after timing tuning in system. Do not use this directely in any API. ESP_FLASH_SPEED_MAX, ///< The maximum frequency supported by the host is ``ESP_FLASH_SPEED_MAX-1``. } esp_flash_speed_t; @@ -71,7 +73,9 @@ typedef enum { SPI_FLASH_DIO, ///< Both address & data transferred using dual I/O SPI_FLASH_QOUT, ///< Data read using quad I/O SPI_FLASH_QIO, ///< Both address & data transferred using quad I/O - +#define SPI_FLASH_OPI_FLAG 16 ///< A flag for flash work in opi mode, the io mode below are opi, above are SPI/QSPI mode. DO NOT use this value in any API. + SPI_FLASH_OPI_STR = SPI_FLASH_OPI_FLAG,///< Only support on OPI flash, flash read and write under STR mode + SPI_FLASH_OPI_DTR,///< Only support on OPI flash, flash read and write under DTR mode SPI_FLASH_READ_MODE_MAX, ///< The fastest io mode supported by the host is ``ESP_FLASH_READ_MODE_MAX-1``. } esp_flash_io_mode_t; diff --git a/components/hal/include/hal/spi_hal.h b/components/hal/include/hal/spi_hal.h index b37c7c9250..5be7db32ea 100644 --- a/components/hal/include/hal/spi_hal.h +++ b/components/hal/include/hal/spi_hal.h @@ -38,6 +38,7 @@ #include #include "soc/lldesc.h" #include "soc/soc_caps.h" +#include "hal/spi_types.h" /** * Input parameters to the ``spi_hal_cal_clock_conf`` to calculate the timing configuration @@ -100,7 +101,7 @@ typedef struct { uint64_t addr; ///< Address value to be sent uint8_t *send_buffer; ///< Data to be sent uint8_t *rcv_buffer; ///< Buffer to hold the receive data. - spi_ll_io_mode_t io_mode; ///< IO mode of the master + spi_line_mode_t line_mode; ///< SPI line mode of this transaction int cs_keep_active; ///< Keep CS active after transaction } spi_hal_trans_config_t; diff --git a/components/hal/include/hal/spi_types.h b/components/hal/include/hal/spi_types.h index 400b922a5c..169069c5c6 100644 --- a/components/hal/include/hal/spi_types.h +++ b/components/hal/include/hal/spi_types.h @@ -14,8 +14,9 @@ #pragma once +#include #include "esp_attr.h" -#include +#include "esp_bit_defs.h" #include "soc/soc_caps.h" #include "sdkconfig.h" @@ -45,6 +46,15 @@ typedef enum { } spi_event_t; FLAG_ATTR(spi_event_t) +/** + * @brief Line mode of SPI transaction phases: CMD, ADDR, DOUT/DIN. + */ +typedef struct { + uint8_t cmd_lines; ///< The line width of command phase, e.g. 2-line-cmd-phase. + uint8_t addr_lines; ///< The line width of address phase, e.g. 1-line-addr-phase. + uint8_t data_lines; ///< The line width of data phase, e.g. 4-line-data-phase. +} spi_line_mode_t; + /** @cond */ //Doxy command to hide preprocessor definitions from docs */ diff --git a/components/hal/include/hal/timer_hal.h b/components/hal/include/hal/timer_hal.h index f8c91739d9..cb3d5e0671 100644 --- a/components/hal/include/hal/timer_hal.h +++ b/components/hal/include/hal/timer_hal.h @@ -59,6 +59,15 @@ void timer_hal_init(timer_hal_context_t *hal, timer_group_t group_num, timer_idx */ void timer_hal_get_status_reg_mask_bit(timer_hal_context_t *hal, uint32_t *status_reg, uint32_t *mask_bit); +/** + * @brief Reset timer peripheral + * + * @param hal Context of the HAL layer + * + * @return None + */ +void timer_hal_reset_periph(timer_hal_context_t *hal); + /** * @brief Set timer clock prescale value * diff --git a/components/hal/esp32c3/include/hal/uhci_types.h b/components/hal/include/hal/uhci_types.h similarity index 100% rename from components/hal/esp32c3/include/hal/uhci_types.h rename to components/hal/include/hal/uhci_types.h index 7b7f41d0f9..7122e2a41a 100644 --- a/components/hal/esp32c3/include/hal/uhci_types.h +++ b/components/hal/include/hal/uhci_types.h @@ -19,13 +19,13 @@ #pragma once +#include +#include + #ifdef __cplusplus extern "C" { #endif -#include -#include - /** * @brief UHCI escape sequence */ diff --git a/components/hal/include/hal/usb_phy_hal.h b/components/hal/include/hal/usb_phy_hal.h new file mode 100644 index 0000000000..fe77eb8744 --- /dev/null +++ b/components/hal/include/hal/usb_phy_hal.h @@ -0,0 +1,81 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "usb_types_private.h" +#include "usb_phy_types.h" +#include "soc/soc_caps.h" +#include "soc/usb_wrap_struct.h" +#if SOC_USB_SERIAL_JTAG_SUPPORTED +#include "soc/usb_serial_jtag_struct.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Context that should be maintained by both the driver and the HAL + */ +typedef struct { + usb_wrap_dev_t *wrap_dev; /**< Pointer to base address of USB Wrapper registers */ +#if SOC_USB_SERIAL_JTAG_SUPPORTED + usb_serial_jtag_dev_t *jtag_dev; /**< Pointer to base address of USB Serial JTAG registers */ +#endif +} usb_phy_hal_context_t; + +/** + * @brief Init the USB PHY hal. This function should be called first before other hal layer function is called + * + * @param hal Context of the HAL layer + */ +void usb_phy_hal_init(usb_phy_hal_context_t *hal); + +/** + * @brief Configure internal/external PHY for USB_OTG + * + * @param hal Context of the HAL layer + * @param phy_target USB PHY target + */ +void usb_phy_hal_otg_conf(usb_phy_hal_context_t *hal, usb_phy_target_t phy_target); + +#if SOC_USB_SERIAL_JTAG_SUPPORTED +/** + * @brief Configure internal/external PHY for USB_Serial_JTAG + * + * @param hal Context of the HAL layer + * @param phy_target USB PHY target + */ +void usb_phy_hal_jtag_conf(usb_phy_hal_context_t *hal, usb_phy_target_t phy_target); +#endif + +/** + * @brief Configure pullup/pulldown loads for the D+/D- as a host + * + * @param hal Context of the HAL layer + */ +void usb_phy_hal_int_load_conf_host(usb_phy_hal_context_t *hal); + +/** + * @brief Configure pullup/pulldown loads for the D+/D- as a device + * + * @param hal Context of the HAL layer + * @param speed USB speed + */ +void usb_phy_hal_int_load_conf_dev(usb_phy_hal_context_t *hal, usb_priv_speed_t speed); + +/** + * @brief Enable/Disable test mode for internal PHY to mimick host-device disconnection + * + * @param hal Context of the HAL layer + * @param disconn Whether to disconnect + */ +void usb_phy_hal_int_mimick_disconn(usb_phy_hal_context_t *hal, bool disconn); + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/include/hal/usb_phy_types.h b/components/hal/include/hal/usb_phy_types.h new file mode 100644 index 0000000000..1f5ac431ef --- /dev/null +++ b/components/hal/include/hal/usb_phy_types.h @@ -0,0 +1,63 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* +Note: This header file contains USB2.0 related types and macros that can be used by code specific to the DWC_OTG +controller (i.e., the HW specific layers of the USB host stack). Thus, this header is only meant to be used below (and +including) the HAL layer. For types and macros that are HW implementation agnostic (i.e., HCD layer and above), add them +to the "usb/usb_types_ch9.h" header instead. +*/ + +#pragma once + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @brief USB PHY target + */ +typedef enum { + USB_PHY_TARGET_INT, /**< USB target is internal PHY */ + USB_PHY_TARGET_EXT, /**< USB target is external PHY */ + USB_PHY_TARGET_MAX, +} usb_phy_target_t; + +/** + * @brief USB PHY source + */ +typedef enum { + USB_PHY_CTRL_OTG, /**< PHY controller is USB OTG */ +#if SOC_USB_SERIAL_JTAG_SUPPORTED + USB_PHY_CTRL_SERIAL_JTAG, /**< PHY controller is USB Serial JTAG */ +#endif + USB_PHY_CTRL_MAX, +} usb_phy_controller_t; + +/** + * @brief USB OTG mode + */ +typedef enum { + USB_PHY_MODE_DEFAULT, /**< USB OTG default mode */ + USB_OTG_MODE_HOST, /**< USB OTG host mode */ + USB_OTG_MODE_DEVICE, /**< USB OTG device mode */ + USB_OTG_MODE_MAX, +} usb_otg_mode_t; + +/** + * @brief USB speed + */ +typedef enum { + USB_PHY_SPEED_UNDEFINED, + USB_PHY_SPEED_LOW, /**< USB Low Speed (1.5 Mbit/s) */ + USB_PHY_SPEED_FULL, /**< USB Full Speed (12 Mbit/s) */ + USB_PHY_SPEED_MAX, +} usb_phy_speed_t; + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/include/hal/usb_types_private.h b/components/hal/include/hal/usb_types_private.h index 868fdee589..5cce6b66af 100644 --- a/components/hal/include/hal/usb_types_private.h +++ b/components/hal/include/hal/usb_types_private.h @@ -16,7 +16,7 @@ Note: This header file contains USB2.0 related types and macros that can be used by code specific to the DWC_OTG controller (i.e., the HW specific layers of the USB host stack). Thus, this header is only meant to be used below (and including) the HAL layer. For types and macros that are HW implementation agnostic (i.e., HCD layer and above), add them -to the "usb.h" header instead. +to the "usb/usb_types_ch9.h" header instead. */ #pragma once diff --git a/components/hal/include/hal/usbh_hal.h b/components/hal/include/hal/usbh_hal.h index 1ff721c373..b315f6c0b1 100644 --- a/components/hal/include/hal/usbh_hal.h +++ b/components/hal/include/hal/usbh_hal.h @@ -151,7 +151,7 @@ typedef struct { //Channel control, status, and information union { struct { - uint32_t active: 1; /**< The channel is enabled */ + uint32_t active: 1; /**< Debugging bit to indicate whether channel is enabled */ uint32_t halt_requested: 1; /**< A halt has been requested */ uint32_t error_pending: 1; /**< The channel is waiting for the error to be handled */ uint32_t reserved: 1; @@ -811,6 +811,8 @@ usbh_hal_chan_t *usbh_hal_get_chan_pending_intr(usbh_hal_context_t *hal); * - Returns the corresponding event for that channel * * @param chan_obj Channel object + * @note If the host port has an error (e.g., a sudden disconnect or an port error), any active channels will not + * receive an interrupt. Each active channel must be manually halted. * @return usbh_hal_chan_event_t Channel event */ usbh_hal_chan_event_t usbh_hal_chan_decode_intr(usbh_hal_chan_t *chan_obj); diff --git a/components/hal/include/hal/xt_wdt_hal.h b/components/hal/include/hal/xt_wdt_hal.h new file mode 100644 index 0000000000..bd08f2a989 --- /dev/null +++ b/components/hal/include/hal/xt_wdt_hal.h @@ -0,0 +1,61 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include + +#include "hal/xt_wdt_ll.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + rtc_cntl_dev_t *dev; /* Pointer to the RTC register struct */ +} xt_wdt_hal_context_t; /* HAL context struct */ + +typedef struct { + uint32_t timeout; /* Watchdog timer timeout in RTC_CLK cycles*/ +} xt_wdt_hal_config_t; /* HAL config parameter struct */ + +/* ---------------------------- Init and Config ----------------------------- */ + +/** + * @brief Initialize the WDTs associated HAL context + * + * Prepares the register for enabling the WDT and sets the timeout value + * + * @param hal Pointer to the HAL layer context + * @param config Pointer to config struct + */ +void xt_wdt_hal_init(xt_wdt_hal_context_t *hal, const xt_wdt_hal_config_t *config); + + +/** + * @brief Enable or disable the WDT + * + * @param hal Pointer to the HAL layer context + * @param enable true for enable WDT, false for disable + */ +void xt_wdt_hal_enable(xt_wdt_hal_context_t *hal, bool enable); + +/** + * @brief Enable the automatic RTC backup clock with the given frequency + * + * Calculates and sets the necessary hardware parameters to meet the desired + * backup clock frequency + * + * @param hal Pointer to the HAL layer context + * @param rtc_clk_frequency_khz desired frequency for the backup clock + * @return uint32_t the calculated clock factor value + */ +uint32_t xt_wdt_hal_enable_backup_clk(xt_wdt_hal_context_t *hal, uint32_t rtc_clk_frequency_khz); + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/pcnt_hal.c b/components/hal/pcnt_hal.c index f703f70af8..93db4765dd 100644 --- a/components/hal/pcnt_hal.c +++ b/components/hal/pcnt_hal.c @@ -15,6 +15,7 @@ // The HAL layer for PCNT (common part) #include "hal/pcnt_hal.h" +#include "hal/pcnt_ll.h" void pcnt_hal_init(pcnt_hal_context_t *hal, int pcnt_num) { diff --git a/components/hal/platform_port/include/hal/log.h b/components/hal/platform_port/include/hal/log.h index 28bde429d4..6d5cbda381 100644 --- a/components/hal/platform_port/include/hal/log.h +++ b/components/hal/platform_port/include/hal/log.h @@ -21,3 +21,9 @@ #define HAL_LOGI(...) ESP_LOGI(__VA_ARGS__) #define HAL_LOGD(...) ESP_LOGD(__VA_ARGS__) #define HAL_LOGV(...) ESP_LOGV(__VA_ARGS__) + +#define HAL_EARLY_LOGE(...) ESP_EARLY_LOGE(__VA_ARGS__) +#define HAL_EARLY_LOGW(...) ESP_EARLY_LOGW(__VA_ARGS__) +#define HAL_EARLY_LOGI(...) ESP_EARLY_LOGI(__VA_ARGS__) +#define HAL_EARLY_LOGD(...) ESP_EARLY_LOGD(__VA_ARGS__) +#define HAL_EARLY_LOGV(...) ESP_EARLY_LOGV(__VA_ARGS__) diff --git a/components/hal/platform_port/include/hal/misc.h b/components/hal/platform_port/include/hal/misc.h index 472ec8be2a..4afb49653f 100644 --- a/components/hal/platform_port/include/hal/misc.h +++ b/components/hal/platform_port/include/hal/misc.h @@ -16,3 +16,44 @@ #define HAL_SWAP16(d) __builtin_bswap16((d)) #define HAL_SWAP32(d) __builtin_bswap32((d)) #define HAL_SWAP64(d) __builtin_bswap64((d)) + +/** @cond */ //Doxy command to hide preprocessor definitions from docs */ + +/** + * @brief Macro to force a 32-bit read, modify, then write on a peripheral register + * + * Due to a GCC bug, the compiler may still try to optimize read/writes to peripheral register fields by using 8/16 bit + * access, even if they are marked volatile (i.e., -fstrict-volatile-bitfields has no effect). + * + * For ESP chips, the peripheral bus only allows 32-bit read/writes. The following macro works around the compiler issue + * by forcing a 32-bit read/modify/write. + * + * @note This macro should only be called on register fields of xxx_struct.h type headers, as it depends on the presence + * of a 'val' field of the register union. + * @note Current implementation reads into a uint32_t instead of copy base_reg direclty to temp_reg. The reason being + * that C++ does not create a copy constructor for volatile structs. + */ +#define HAL_FORCE_MODIFY_U32_REG_FIELD(base_reg, reg_field, field_val) \ +{ \ + uint32_t temp_val = base_reg.val; \ + typeof(base_reg) temp_reg; \ + temp_reg.val = temp_val; \ + temp_reg.reg_field = (field_val); \ + (base_reg).val = temp_reg.val; \ +} + +/** + * @brief Macro to force a 32-bit read on a peripheral register + * + * @note This macro should only be called on register fields of xxx_struct.h type headers. See description above for + * more details. + * @note Current implementation reads into a uint32_t. See description above for more details. + */ +#define HAL_FORCE_READ_U32_REG_FIELD(base_reg, reg_field) ({ \ + uint32_t temp_val = base_reg.val; \ + typeof(base_reg) temp_reg; \ + temp_reg.val = temp_val; \ + temp_reg.reg_field; \ +}) + +/** @endcond */ diff --git a/components/hal/sdio_slave_hal.c b/components/hal/sdio_slave_hal.c index 457d4b9a1a..aa7568ee39 100644 --- a/components/hal/sdio_slave_hal.c +++ b/components/hal/sdio_slave_hal.c @@ -325,11 +325,11 @@ static void send_new_packet(sdio_slave_context_t *hal) // update pkt_len register to allow host reading. sdio_slave_ll_send_write_len(hal->slc, end_desc->pkt_len); - ESP_EARLY_LOGV(TAG, "send_length_write: %d, last_len: %08X", end_desc->pkt_len, sdio_slave_ll_send_read_len(hal->host)); + HAL_EARLY_LOGV(TAG, "send_length_write: %d, last_len: %08X", end_desc->pkt_len, sdio_slave_ll_send_read_len(hal->host)); send_set_state(hal, STATE_SENDING); - ESP_EARLY_LOGD(TAG, "restart new send: %p->%p, pkt_len: %d", start_desc, end_desc, end_desc->pkt_len); + HAL_EARLY_LOGD(TAG, "restart new send: %p->%p, pkt_len: %d", start_desc, end_desc, end_desc->pkt_len); } static esp_err_t send_check_new_packet(sdio_slave_context_t *hal) @@ -374,7 +374,7 @@ esp_err_t sdio_slave_hal_send_reset_counter(sdio_slave_context_t* hal) "reset counter when transmission started", ESP_ERR_INVALID_STATE); sdio_slave_ll_send_write_len(hal->slc, 0); - ESP_EARLY_LOGV(TAG, "last_len: %08X", sdio_slave_ll_send_read_len(hal->host)); + HAL_EARLY_LOGV(TAG, "last_len: %08X", sdio_slave_ll_send_read_len(hal->host)); hal->tail_pkt_len = 0; sdio_slave_hal_send_desc_t *desc = hal->in_flight_head; @@ -674,20 +674,20 @@ void sdio_slave_hal_load_buf(sdio_slave_context_t *hal, lldesc_t *desc) static inline void show_queue_item(lldesc_t *item) { - ESP_EARLY_LOGI(TAG, "=> %p: size: %d(%d), eof: %d, owner: %d", item, item->size, item->length, item->eof, item->owner); - ESP_EARLY_LOGI(TAG, " buf: %p, stqe_next: %p", item->buf, item->qe.stqe_next); + HAL_EARLY_LOGI(TAG, "=> %p: size: %d(%d), eof: %d, owner: %d", item, item->size, item->length, item->eof, item->owner); + HAL_EARLY_LOGI(TAG, " buf: %p, stqe_next: %p", item->buf, item->qe.stqe_next); } static void __attribute((unused)) dump_queue(sdio_slave_hal_recv_stailq_t *queue) { int cnt = 0; lldesc_t *item = NULL; - ESP_EARLY_LOGI(TAG, ">>>>> first: %p, last: %p <<<<<", queue->stqh_first, queue->stqh_last); + HAL_EARLY_LOGI(TAG, ">>>>> first: %p, last: %p <<<<<", queue->stqh_first, queue->stqh_last); STAILQ_FOREACH(item, queue, qe) { cnt++; show_queue_item(item); } - ESP_EARLY_LOGI(TAG, "total: %d", cnt); + HAL_EARLY_LOGI(TAG, "total: %d", cnt); } /*--------------------------------------------------------------------------- diff --git a/components/hal/spi_flash_hal.c b/components/hal/spi_flash_hal.c index d2dea8ebf8..d417eccf20 100644 --- a/components/hal/spi_flash_hal.c +++ b/components/hal/spi_flash_hal.c @@ -71,6 +71,26 @@ static inline int get_dummy_n(bool gpio_is_used, int input_delay_ns, int eff_clk return apb_period_n / apbclk_n; } +#if SOC_SPI_MEM_SUPPORT_TIME_TUNING +static inline int extra_dummy_under_timing_tuning(const spi_flash_hal_config_t *cfg) +{ + bool main_flash = (cfg->host_id == SPI1_HOST && cfg->cs_num == 0); + int extra_dummy = 0; + if (main_flash) { + /** + * For Octal Flash, the dummy is `usr_dummy` + `extra_dummy`, they are in two different regs, we don't touch `extra_dummy` here, so set extra_dummy 0. + * Instead, for both Quad and Octal Flash, we use `usr_dummy` and set the whole dummy length (usr_dummy + extra_dummy) to this register. + */ + extra_dummy = cfg->extra_dummy; + } else { + // TODO: for other flash chips, dummy get logic implement here. Currently, still calculate extra dummy by itself. + abort(); + } + + return extra_dummy; +} +#endif //SOC_SPI_MEM_SUPPORT_TIME_TUNING + esp_err_t spi_flash_hal_init(spi_flash_hal_context_t *data_out, const spi_flash_hal_config_t *cfg) { if (!esp_ptr_internal(data_out) && cfg->host_id == SPI1_HOST) { @@ -87,16 +107,37 @@ esp_err_t spi_flash_hal_init(spi_flash_hal_context_t *data_out, const spi_flash_ .inst = data_out->inst, // Keeps the function pointer table .spi = spi_flash_ll_get_hw(cfg->host_id), .cs_num = cfg->cs_num, - .extra_dummy = get_dummy_n(!cfg->iomux, cfg->input_delay_ns, APB_CLK_FREQ/clock_cfg->div), - .clock_conf = clock_cfg->clock_reg_val, .cs_hold = cfg->cs_hold, .cs_setup = cfg->cs_setup, + .base_io_mode = cfg->default_io_mode, }; +#if SOC_SPI_MEM_SUPPORT_TIME_TUNING + if (cfg->using_timing_tuning) { + data_out->extra_dummy = extra_dummy_under_timing_tuning(cfg); + data_out->clock_conf = cfg->clock_config; + } else +#endif // SOC_SPI_MEM_SUPPORT_TIME_TUNING + { + data_out->extra_dummy = get_dummy_n(!cfg->iomux, cfg->input_delay_ns, APB_CLK_FREQ/clock_cfg->div); + data_out->clock_conf = clock_cfg->clock_reg_val; + } + + if (cfg->auto_sus_en) { data_out->flags |= SPI_FLASH_HOST_CONTEXT_FLAG_AUTO_SUSPEND; data_out->flags |= SPI_FLASH_HOST_CONTEXT_FLAG_AUTO_RESUME; } +#if SOC_SPI_MEM_SUPPORT_OPI_MODE + if (cfg->octal_mode_en) { + data_out->flags |= SPI_FLASH_HOST_CONTEXT_FLAG_OCTAL_MODE; + } + + if (cfg->default_io_mode == SPI_FLASH_OPI_DTR) { + data_out->slicer_flags |= SPI_FLASH_HOST_CONTEXT_SLICER_FLAG_DTR; + } +#endif + HAL_LOGD(TAG, "extra_dummy: %d", data_out->extra_dummy); return ESP_OK; } diff --git a/components/hal/spi_flash_hal_common.inc b/components/hal/spi_flash_hal_common.inc index c4a47ac094..60fed70431 100644 --- a/components/hal/spi_flash_hal_common.inc +++ b/components/hal/spi_flash_hal_common.inc @@ -65,6 +65,10 @@ esp_err_t spi_flash_hal_device_config(spi_flash_host_inst_t *host) spi_flash_hal_disable_auto_resume_mode(host); } #endif //SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND +#if SOC_SPI_MEM_SUPPORT_TIME_TUNING + // Always keep the extra dummy on SPI1 is 0, add extra dummy to user dummy + spimem_flash_ll_set_extra_dummy((spi_mem_dev_t*)dev, 0); +#endif #else gpspi_flash_ll_set_hold_pol(dev, 1); #endif //GPSPI_BUILD @@ -139,7 +143,7 @@ esp_err_t spi_flash_hal_common_command(spi_flash_host_inst_t *host, spi_flash_tr command = trans->command; dummy_bitlen = trans->dummy_bitlen; if ((trans->flags & SPI_FLASH_TRANS_FLAG_IGNORE_BASEIO) != 0) { - io_mode = ((spi_flash_hal_context_t*)host)->base_io_mode; + io_mode = trans->io_mode; } } diff --git a/components/hal/spi_hal_iram.c b/components/hal/spi_hal_iram.c index 6eae4e2bce..e36a3ebd43 100644 --- a/components/hal/spi_hal_iram.c +++ b/components/hal/spi_hal_iram.c @@ -66,8 +66,8 @@ void spi_hal_setup_trans(spi_hal_context_t *hal, const spi_hal_dev_config_t *dev spi_ll_clear_int_stat(hal->hw); //We should be done with the transmission. HAL_ASSERT(spi_ll_get_running_cmd(hw) == 0); - - spi_ll_master_set_io_mode(hw, trans->io_mode); + //set transaction line mode + spi_ll_master_set_line_mode(hw, trans->line_mode); int extra_dummy = 0; //when no_dummy is not set and in half-duplex mode, sets the dummy bit if RX phase exist diff --git a/components/hal/timer_hal.c b/components/hal/timer_hal.c index 7337b19464..48a918e9c7 100644 --- a/components/hal/timer_hal.c +++ b/components/hal/timer_hal.c @@ -26,3 +26,10 @@ void timer_hal_get_status_reg_mask_bit(timer_hal_context_t *hal, uint32_t *statu *status_reg = timer_ll_get_intr_status_reg(hal->dev); *mask_bit = timer_ll_get_intr_mask_bit(hal->dev, hal->idx); } + +void timer_hal_reset_periph(timer_hal_context_t *hal) +{ + timer_ll_intr_disable(hal->dev, hal->idx); + timer_ll_set_counter_enable(hal->dev, hal->idx, TIMER_PAUSE); + timer_ll_set_counter_value(hal->dev, hal->idx, 0ULL); +} diff --git a/components/hal/usb_phy_hal.c b/components/hal/usb_phy_hal.c new file mode 100644 index 0000000000..16a8f60d81 --- /dev/null +++ b/components/hal/usb_phy_hal.c @@ -0,0 +1,63 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "hal/usb_phy_ll.h" +#include "hal/usb_phy_hal.h" + +void usb_phy_hal_init(usb_phy_hal_context_t *hal) +{ + hal->wrap_dev = &USB_WRAP; +#if SOC_USB_SERIAL_JTAG_SUPPORTED + hal->jtag_dev = &USB_SERIAL_JTAG; +#endif +} + +void usb_phy_hal_otg_conf(usb_phy_hal_context_t *hal, usb_phy_target_t phy_target) +{ + if (phy_target == USB_PHY_TARGET_EXT) { + usb_phy_ll_ext_otg_enable(hal->wrap_dev); + } else if (phy_target == USB_PHY_TARGET_INT) { + usb_phy_ll_int_otg_enable(hal->wrap_dev); + } +} + +#if SOC_USB_SERIAL_JTAG_SUPPORTED +void usb_phy_hal_jtag_conf(usb_phy_hal_context_t *hal, usb_phy_target_t phy_target) +{ + if (phy_target == USB_PHY_TARGET_EXT) { + usb_phy_ll_ext_jtag_enable(hal->jtag_dev); + } else if (phy_target == USB_PHY_TARGET_INT) { + usb_phy_ll_int_jtag_enable(hal->jtag_dev); + } +} +#endif + +void usb_phy_hal_int_load_conf_host(usb_phy_hal_context_t *hal) +{ + // HOST - upstream: dp_pd = 1, dm_pd = 1 + usb_phy_ll_int_load_conf(hal->wrap_dev, false, true, false, true); +} + +void usb_phy_hal_int_load_conf_dev(usb_phy_hal_context_t *hal, usb_priv_speed_t speed) +{ + // DEVICE - downstream + if (speed == USB_PRIV_SPEED_LOW) { + // LS: dm_pu = 1 + usb_phy_ll_int_load_conf(hal->wrap_dev, false, false, true, false); + } else { + // FS: dp_pu = 1 + usb_phy_ll_int_load_conf(hal->wrap_dev, true, false, false, false); + } +} + +void usb_phy_hal_int_mimick_disconn(usb_phy_hal_context_t *hal, bool disconn) +{ + /* + We mimick a disconnect by enabling the internal PHY's test mode, then forcing the output_enable to HIGH. This will: + A HIGH output_enable will cause the received VP and VM to be zero, thus mimicking a disconnection. + */ + usb_phy_ll_int_enable_test_mode(hal->wrap_dev, disconn); +} diff --git a/components/hal/usbh_hal.c b/components/hal/usbh_hal.c index c85438c61b..5091952de8 100644 --- a/components/hal/usbh_hal.c +++ b/components/hal/usbh_hal.c @@ -291,27 +291,19 @@ void usbh_hal_chan_activate(usbh_hal_chan_t *chan_obj, void *xfer_desc_list, int bool usbh_hal_chan_request_halt(usbh_hal_chan_t *chan_obj) { //Cannot request halt on a channel that is pending error handling - HAL_ASSERT(!chan_obj->flags.error_pending); - if (usbh_ll_chan_is_active(chan_obj->regs) || chan_obj->flags.active) { + HAL_ASSERT(chan_obj->flags.active && !chan_obj->flags.error_pending); + if (usbh_ll_chan_is_active(chan_obj->regs)) { usbh_ll_chan_halt(chan_obj->regs); chan_obj->flags.halt_requested = 1; return false; + } else { + chan_obj->flags.active = 0; + return true; } - return true; } // ------------------------------------------------- Event Handling ---------------------------------------------------- -//When a device on the port is no longer valid (e.g., disconnect, port error). All channels are no longer valid -static void chan_all_halt(usbh_hal_context_t *hal) -{ - for (int i = 0; i < USBH_HAL_NUM_CHAN; i++) { - if (hal->channels.hdls[i] != NULL) { - hal->channels.hdls[i]->flags.active = 0; - } - } -} - usbh_hal_port_event_t usbh_hal_decode_intr(usbh_hal_context_t *hal) { uint32_t intrs_core = usb_ll_intr_read_and_clear(hal->dev); //Read and clear core interrupts @@ -321,7 +313,7 @@ usbh_hal_port_event_t usbh_hal_decode_intr(usbh_hal_context_t *hal) intrs_port = usbh_ll_hprt_intr_read_and_clear(hal->dev); } //Note: Do not change order of checks. Regressing events (e.g. enable -> disabled, connected -> connected) - //always take precendance. ENABLED < DISABLED < CONN < DISCONN < OVRCUR + //always take precedence. ENABLED < DISABLED < CONN < DISCONN < OVRCUR usbh_hal_port_event_t event = USBH_HAL_PORT_EVENT_NONE; //Check if this is a core or port event @@ -330,13 +322,11 @@ usbh_hal_port_event_t usbh_hal_decode_intr(usbh_hal_context_t *hal) if (intrs_core & USB_LL_INTR_CORE_DISCONNINT) { event = USBH_HAL_PORT_EVENT_DISCONN; debounce_lock_enable(hal); - chan_all_halt(hal); //All channels are halted on a disconnect //Mask the port connection and disconnection interrupts to prevent repeated triggering } else if (intrs_port & USBH_LL_INTR_HPRT_PRTOVRCURRCHNG) { //Check if this is an overcurrent or an overcurrent cleared if (usbh_ll_hprt_get_port_overcur(hal->dev)) { event = USBH_HAL_PORT_EVENT_OVRCUR; - chan_all_halt(hal); //All channels are halted on an overcurrent } else { event = USBH_HAL_PORT_EVENT_OVRCUR_CLR; } @@ -345,14 +335,13 @@ usbh_hal_port_event_t usbh_hal_decode_intr(usbh_hal_context_t *hal) event = USBH_HAL_PORT_EVENT_ENABLED; } else { //Host port has been disabled event = USBH_HAL_PORT_EVENT_DISABLED; - chan_all_halt(hal); //All channels are halted when the port is disabled } } else if (intrs_port & USBH_LL_INTR_HPRT_PRTCONNDET && !hal->flags.dbnc_lock_enabled) { event = USBH_HAL_PORT_EVENT_CONN; debounce_lock_enable(hal); } } - //Port events always take precendance over channel events + //Port events always take precedence over channel events if (event == USBH_HAL_PORT_EVENT_NONE && (intrs_core & USB_LL_INTR_CORE_HCHINT)) { //One or more channels have pending interrupts. Store the mask of those channels hal->channels.chan_pend_intrs_msk = usbh_ll_get_chan_intrs_msk(hal->dev); diff --git a/components/hal/xt_wdt_hal.c b/components/hal/xt_wdt_hal.c new file mode 100644 index 0000000000..29ebb710a3 --- /dev/null +++ b/components/hal/xt_wdt_hal.c @@ -0,0 +1,78 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +#include "soc/soc_caps.h" + +#include "hal/xt_wdt_hal.h" +#include "hal/xt_wdt_ll.h" +#include "hal/assert.h" + +#define DIV_COMP_N_MAX 8 + +static uint32_t xt_wdt_hal_calculate(uint32_t rtc_clk_frequency_khz) +{ + uint32_t xtal32k_clk_factor = 0; + uint8_t divisor_comps[DIV_COMP_N_MAX]; + + /* From the TRM: + + Define the frequency of RTC_CLK as f_rtc_clk (unit: kHz), and the eight divisor components as + x0, x1, x2, x3, x4, x5, x6, and x7, respectively. S = x0 + x1 + x2 + x3 + x4 + x5 + x6 + x7. + The following conditions should be fulfilled: + S = f_rtc_clk * (4/32) + M + 1 >= xn >= M(0 <= n <= 7) + M = f_rtc_clk/32/2 + xn should be an integer. M and S are rounded up or down. Each divisor component (x0 ~x7) is 4-bit long, and + corresponds to the value of RTC_CNTL_XTAL32K_CLK_FACTOR (32-bit) in order. + */ + + uint8_t M = ((rtc_clk_frequency_khz / 32) / 2); + uint32_t S = ((4 * rtc_clk_frequency_khz) / 32); + + memset(divisor_comps, M, DIV_COMP_N_MAX); + + /* Calculate how far we are away from satisfying S = SUM(x_n) */ + uint8_t off = S - DIV_COMP_N_MAX * M; + + /* Offset should never be this big */ + HAL_ASSERT(off <= DIV_COMP_N_MAX); + + for (int i = 0; i < DIV_COMP_N_MAX; i++) { + if (off) { + divisor_comps[i]++; + off--; + } + /* Sum up all divisors */ + xtal32k_clk_factor |= (divisor_comps[i] << 4 * i); + } + + return xtal32k_clk_factor; +} + +void xt_wdt_hal_init(xt_wdt_hal_context_t *hal, const xt_wdt_hal_config_t *config) +{ + hal->dev = &RTCCNTL; + + xt_wdt_ll_enable(hal->dev, false); + xt_wdt_ll_set_timeout(hal->dev, config->timeout); +} + +uint32_t xt_wdt_hal_enable_backup_clk(xt_wdt_hal_context_t *hal, uint32_t rtc_clk_frequency_khz) +{ + uint32_t xtal32k_clk_factor = xt_wdt_hal_calculate(rtc_clk_frequency_khz); + + xt_wdt_ll_set_backup_clk_factor(hal->dev, xtal32k_clk_factor); + xt_wdt_ll_auto_backup_enable(hal->dev, true); + + return xtal32k_clk_factor; +} + +void xt_wdt_hal_enable(xt_wdt_hal_context_t *hal, bool enable) +{ + xt_wdt_ll_enable(hal->dev, enable); + xt_wdt_ll_intr_enable(hal->dev, enable); +} diff --git a/components/heap/port/esp32s3/memory_layout.c b/components/heap/port/esp32s3/memory_layout.c index 96dad59e80..1bd6ad62fc 100644 --- a/components/heap/port/esp32s3/memory_layout.c +++ b/components/heap/port/esp32s3/memory_layout.c @@ -44,6 +44,8 @@ const soc_memory_type_desc_t soc_memory_types[] = { { "IRAM", { MALLOC_CAP_EXEC | MALLOC_CAP_32BIT | MALLOC_CAP_INTERNAL, 0, 0 }, false, false}, // Type 4: SPI SRAM data { "SPIRAM", { MALLOC_CAP_SPIRAM | MALLOC_CAP_DEFAULT, 0, MALLOC_CAP_8BIT | MALLOC_CAP_32BIT}, false, false}, + // Type 5: DRAM which is not DMA accesible + { "NON_DMA_DRAM", { MALLOC_CAP_8BIT | MALLOC_CAP_DEFAULT, MALLOC_CAP_INTERNAL | MALLOC_CAP_32BIT, 0 }, false, false}, }; const size_t soc_memory_type_count = sizeof(soc_memory_types) / sizeof(soc_memory_type_desc_t); @@ -69,9 +71,12 @@ const soc_memory_region_t soc_memory_regions[] = { { 0x3FCC0000, 0x10000, 2, 0x403B0000}, //Level 6, IDRAM, can be used as trace memroy { 0x3FCD0000, 0x10000, 2, 0x403C0000}, //Level 7, IDRAM, can be used as trace memroy { 0x3FCE0000, 0x10000, 1, 0}, //Level 8, IDRAM, can be used as trace memroy, contains stacks used by startup flow, recycled by heap allocator in app_main task -#if CONFIG_ESP32S3_DATA_CACHE_32KB +#if CONFIG_ESP32S3_DATA_CACHE_16KB || CONFIG_ESP32S3_DATA_CACHE_32KB { 0x3FCF0000, 0x8000, 0, 0}, //Level 9, DRAM #endif +#if CONFIG_ESP32S3_DATA_CACHE_16KB + { 0x3C000000, 0x4000, 5, 0} +#endif #ifdef CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP { 0x50000000, 0x2000, 4, 0}, //Fast RTC memory #endif @@ -93,11 +98,11 @@ SOC_RESERVE_MEMORY_REGION((intptr_t)&_data_start, (intptr_t)&_heap_start, dram_d // ESP32S3 has a big D/IRAM region, the part used by code is reserved // The address of the D/I bus are in the same order, directly shift IRAM address to get reserved DRAM address #define I_D_OFFSET (SOC_DIRAM_IRAM_LOW - SOC_DIRAM_DRAM_LOW) -#if CONFIG_ESP32S3_INSTRUCTION_CACHE_16KB -SOC_RESERVE_MEMORY_REGION((intptr_t)&_iram_start, (intptr_t)&_iram_start + 0x4000, iram_code_1); -SOC_RESERVE_MEMORY_REGION((intptr_t)&_iram_start + 0x4000 - I_D_OFFSET, (intptr_t)&_iram_end - I_D_OFFSET, iram_code_2); -#else +// .text region in diram. DRAM used by text (shared with IBUS). SOC_RESERVE_MEMORY_REGION((intptr_t)&_iram_start - I_D_OFFSET, (intptr_t)&_iram_end - I_D_OFFSET, iram_code); + +#if CONFIG_ESP32S3_INSTRUCTION_CACHE_16KB +SOC_RESERVE_MEMORY_REGION((intptr_t)&_iram_start, (intptr_t)&_iram_end, iram_code_2); #endif #ifdef CONFIG_SPIRAM diff --git a/components/ieee802154/CMakeLists.txt b/components/ieee802154/CMakeLists.txt index 180a2303e5..9db0e672a5 100644 --- a/components/ieee802154/CMakeLists.txt +++ b/components/ieee802154/CMakeLists.txt @@ -1,18 +1,19 @@ +idf_build_get_property(idf_target IDF_TARGET) + idf_component_register( INCLUDE_DIRS include + REQUIRES esp_phy ) if(CONFIG_IEEE802154_ENABLED) + idf_component_get_property(esp_phy_lib esp_phy COMPONENT_LIB) if(CONFIG_IEEE802154_LIB_FROM_INTERNAL_SRC) idf_component_get_property(ieee802154_lib ieee802154_driver COMPONENT_LIB) - target_link_libraries(${COMPONENT_LIB} INTERFACE $) + target_link_libraries(${COMPONENT_LIB} INTERFACE $ libphy.a libbtbb.a + $) else() - add_prebuilt_library(ieee802154_lib "${CMAKE_CURRENT_SOURCE_DIR}/lib/${idf_target}/lib802154.a") - target_link_libraries(${COMPONENT_LIB} INTERFACE ieee802154_lib) + target_link_libraries(${COMPONENT_LIB} INTERFACE "-L ${CMAKE_CURRENT_SOURCE_DIR}/lib/${idf_target}") + target_link_libraries(${COMPONENT_LIB} INTERFACE $ lib802154.a libphy.a libbtbb.a + $) endif() - - # force the phy libraries to be linked behind ieee802154 - idf_component_get_property(esp_phy_lib esp_phy COMPONENT_LIB) - target_link_libraries(${COMPONENT_LIB} INTERFACE $ libphy.a libbtbb.a - $) endif() diff --git a/components/ieee802154/include/esp_ieee802154.h b/components/ieee802154/include/esp_ieee802154.h index a8d4678e92..e31a5ca37e 100644 --- a/components/ieee802154/include/esp_ieee802154.h +++ b/components/ieee802154/include/esp_ieee802154.h @@ -192,6 +192,24 @@ void esp_ieee802154_get_extended_address(uint8_t *ext_addr); */ void esp_ieee802154_set_extended_address(const uint8_t *ext_addr); +/** + * @brief Get the device coordinator. + * + * @return + * - True The coordinator is enabled. + * - False The coordinator is disabled. + * + */ +bool esp_ieee802154_get_coordinator(void); + +/** + * @brief Set the device coordinator role. + * + * @param[in] enable The coordinator role to be set. + * + */ +void esp_ieee802154_set_coordinator(bool enable); + /** * @brief Get the auto frame pending mode. * diff --git a/components/ieee802154/include/esp_ieee802154_types.h b/components/ieee802154/include/esp_ieee802154_types.h index 6979991cc3..823e3cdcf3 100644 --- a/components/ieee802154/include/esp_ieee802154_types.h +++ b/components/ieee802154/include/esp_ieee802154_types.h @@ -41,6 +41,8 @@ typedef enum { ESP_IEEE802154_TX_ERR_NO_ACK, /*!< No Ack frame received until timeout */ ESP_IEEE802154_TX_ERR_INVALID_ACK, /*!< Invalid Ack frame */ ESP_IEEE802154_TX_ERR_COEXIST, /*!< Rejected by coexist system */ + ESP_IEEE802154_TX_ERR_COEXIST_REJ, /*!< Rejected by coexist system before transmitting frame */ + ESP_IEEE802154_TX_ERR_COEXIST_ACK, /*!< Rejected by coexist system when receiving ack */ } esp_ieee802154_tx_error_t; /** @@ -60,6 +62,7 @@ typedef enum { ESP_IEEE802154_AUTO_PENDING_DISABLE, /*!< Frame pending bit always set to 1 in the ack to Data Request */ ESP_IEEE802154_AUTO_PENDING_ENABLE, /*!< Frame pending bit set to 1 if src address matches, in the ack to Data Request */ ESP_IEEE802154_AUTO_PENDING_ENHANCED, /*!< Frame pending bit set to 1 if src address matches, in all ack frames */ + ESP_IEEE802154_AUTO_PENDING_ZIGBEE, /*!< Frame pending bit set to 0 only if src address is short address and matches in table, in the ack to Data Request */ } esp_ieee802154_pending_mode_t; /** diff --git a/components/ieee802154/lib b/components/ieee802154/lib index efbc05d641..9f5363e97a 160000 --- a/components/ieee802154/lib +++ b/components/ieee802154/lib @@ -1 +1 @@ -Subproject commit efbc05d641040253567e825dae53731da595c7b5 +Subproject commit 9f5363e97ae6d53d62f1ef90edf2717fb72e47a8 diff --git a/components/json/cJSON b/components/json/cJSON index d2735278ed..d348621ca9 160000 --- a/components/json/cJSON +++ b/components/json/cJSON @@ -1 +1 @@ -Subproject commit d2735278ed1c2e4556f53a7a782063b31331dbf7 +Subproject commit d348621ca93571343a56862df7de4ff3bc9b5667 diff --git a/components/libsodium/component.mk b/components/libsodium/component.mk index 610c83cd2b..68e91cc5a8 100644 --- a/components/libsodium/component.mk +++ b/components/libsodium/component.mk @@ -16,7 +16,8 @@ COMPONENT_SRCDIRS += \ $(LSRC)/crypto_auth/hmacsha512256 \ $(LSRC)/crypto_box \ $(LSRC)/crypto_box/curve25519xsalsa20poly1305 \ - $(LSRC)/crypto_core/curve25519/ref10 \ + $(LSRC)/crypto_core/ed25519 \ + $(LSRC)/crypto_core/ed25519/ref10 \ $(LSRC)/crypto_core/hchacha20 \ $(LSRC)/crypto_core/hsalsa20/ref2 \ $(LSRC)/crypto_core/hsalsa20 \ @@ -40,6 +41,9 @@ COMPONENT_SRCDIRS += \ $(LSRC)/crypto_scalarmult \ $(LSRC)/crypto_scalarmult/curve25519 \ $(LSRC)/crypto_scalarmult/curve25519/ref10 \ + $(LSRC)/crypto_scalarmult/curve25519/sandy2x \ + $(LSRC)/crypto_scalarmult/ed25519/ref10 \ + $(LSRC)/crypto_scalarmult/ristretto255/ref10 \ $(LSRC)/crypto_secretbox \ $(LSRC)/crypto_secretbox/xsalsa20poly1305 \ $(LSRC)/crypto_shorthash \ diff --git a/components/linux/CMakeLists.txt b/components/linux/CMakeLists.txt new file mode 100644 index 0000000000..b7d2bd46a7 --- /dev/null +++ b/components/linux/CMakeLists.txt @@ -0,0 +1,7 @@ +idf_build_get_property(target IDF_TARGET) +if(NOT "${target}" STREQUAL "linux") + return() +endif() + +idf_component_register(INCLUDE_DIRS include + REQUIRED_IDF_TARGETS linux) diff --git a/components/linux/include/sys/queue.h b/components/linux/include/sys/queue.h new file mode 100644 index 0000000000..9787d9d5f8 --- /dev/null +++ b/components/linux/include/sys/queue.h @@ -0,0 +1 @@ +#include "bsd/sys/queue.h" diff --git a/components/log/CMakeLists.txt b/components/log/CMakeLists.txt index a90f92abe4..b57770a234 100644 --- a/components/log/CMakeLists.txt +++ b/components/log/CMakeLists.txt @@ -1,7 +1,9 @@ idf_build_get_property(target IDF_TARGET) set(srcs "log.c") +set(priv_requires "") if(${target} STREQUAL "linux") - # We leave log buffers out for now on Linux since it's rarely used + # We leave log buffers out for now on Linux since it's rarely used. Explicitely add esp_rom to Linux target + # since we don't have the common components there yet. list(APPEND srcs "log_linux.c") else() list(APPEND srcs "log_buffers.c") diff --git a/components/log/host_test/log_test/CMakeLists.txt b/components/log/host_test/log_test/CMakeLists.txt index 087f96fe7e..7d53a82335 100644 --- a/components/log/host_test/log_test/CMakeLists.txt +++ b/components/log/host_test/log_test/CMakeLists.txt @@ -2,4 +2,5 @@ cmake_minimum_required(VERSION 3.5) include($ENV{IDF_PATH}/tools/cmake/project.cmake) set(COMPONENTS main) +list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/mocks/freertos/") project(test_log_host) diff --git a/components/log/host_test/log_test/README.md b/components/log/host_test/log_test/README.md index f4ca93ac1c..4c37b52c7d 100644 --- a/components/log/host_test/log_test/README.md +++ b/components/log/host_test/log_test/README.md @@ -3,9 +3,7 @@ # Simple log test on Linux target -This unit test tests basic functionality of the log component. The test does not use mocks. Instead, it runs the whole implementation of the component on the Linux host. The test framework is CATCH. - -*Note that the early log (ESP_EARLY_LOG) functionality has not been ported to Linux since it depends on the ROM component.* +This unit test tests basic functionality of the log component. The test does not use mocks. Instead, it runs the whole implementation of the component on the Linux host. The test framework is CATCH. For early log, we only perform a compile time test since there's nothing to test on Linux except for the log macros themselves (all the implementation will be in chip ROM). ## Requirements diff --git a/components/log/host_test/log_test/main/log_test.cpp b/components/log/host_test/log_test/main/log_test.cpp index 196fb91757..76c4dfc5a7 100644 --- a/components/log/host_test/log_test/main/log_test.cpp +++ b/components/log/host_test/log_test/main/log_test.cpp @@ -18,29 +18,19 @@ using namespace std; static const char *TEST_TAG = "test"; -struct PrintFixture { +class BasicLogFixture { +public: static const size_t BUFFER_SIZE = 4096; - PrintFixture(esp_log_level_t log_level = ESP_LOG_VERBOSE) + BasicLogFixture(esp_log_level_t log_level = ESP_LOG_VERBOSE) { - if (instance != nullptr) { - throw exception(); - } - std::memset(print_buffer, 0, BUFFER_SIZE); - - instance = this; - - old_vprintf = esp_log_set_vprintf(print_callback); - - esp_log_level_set(TEST_TAG, log_level); + esp_log_level_set("*", log_level); } - ~PrintFixture() + virtual ~BasicLogFixture() { - esp_log_level_set(TEST_TAG, ESP_LOG_INFO); - esp_log_set_vprintf(old_vprintf); - instance = nullptr; + esp_log_level_set("*", ESP_LOG_INFO); } string get_print_buffer_string() const @@ -51,10 +41,33 @@ struct PrintFixture { void reset_buffer() { std::memset(print_buffer, 0, BUFFER_SIZE); + additional_reset(); } +protected: char print_buffer [BUFFER_SIZE]; + virtual void additional_reset() { } +}; + +struct PrintFixture : BasicLogFixture { + PrintFixture(esp_log_level_t log_level = ESP_LOG_VERBOSE) : BasicLogFixture(log_level) + { + if (instance != nullptr) { + throw exception(); + } + + instance = this; + + old_vprintf = esp_log_set_vprintf(print_callback); + } + + virtual ~PrintFixture() + { + esp_log_set_vprintf(old_vprintf); + instance = nullptr; + } + private: static int print_callback(const char *format, va_list args) { @@ -72,7 +85,47 @@ private: vprintf_like_t old_vprintf; }; +struct PutcFixture : BasicLogFixture { + PutcFixture(esp_log_level_t log_level = ESP_LOG_VERBOSE) : BasicLogFixture(log_level), counter(0) + { + if (instance != nullptr) { + throw exception(); + } + + esp_rom_install_channel_putc(0, putc_callback); + + instance = this; + } + + ~PutcFixture() + { + esp_rom_install_uart_printf(); + instance = nullptr; + } + + void additional_reset() override + { + counter = 0; + } + + size_t counter; + +private: + static void putc_callback(char c) + { + return instance->putc_to_buffer(c); + } + + void putc_to_buffer(char c) + { + print_buffer[counter++] = c; + } + + static PutcFixture *instance; +}; + PrintFixture *PrintFixture::instance = nullptr; +PutcFixture *PutcFixture::instance = nullptr; TEST_CASE("verbose log level") { @@ -139,3 +192,78 @@ TEST_CASE("changing log level") ESP_LOGI(TEST_TAG, "must indeed be printed"); CHECK(regex_search(fix.get_print_buffer_string(), test_print) == true); } + +TEST_CASE("rom printf") +{ + PutcFixture fix; + int printed_chars = esp_rom_printf("info"); + + CHECK(printed_chars == 4); + CHECK(fix.get_print_buffer_string() == "info"); +} + +TEST_CASE("early verbose log level") +{ + PutcFixture fix; + const std::regex test_print("V \\([0-9]*\\) test: verbose", std::regex::ECMAScript); + + ESP_EARLY_LOGV(TEST_TAG, "verbose"); + CHECK(regex_search(fix.get_print_buffer_string(), test_print) == true); +} + +TEST_CASE("early debug log level") +{ + PutcFixture fix; + const std::regex test_print("D \\([0-9]*\\) test: debug", std::regex::ECMAScript); + + ESP_EARLY_LOGD(TEST_TAG, "debug"); + CHECK(regex_search(fix.get_print_buffer_string(), test_print) == true); +} + +TEST_CASE("early info log level") +{ + PutcFixture fix; + const std::regex test_print("I \\([0-9]*\\) test: info", std::regex::ECMAScript); + + ESP_EARLY_LOGI(TEST_TAG, "info"); + CHECK(regex_search(fix.get_print_buffer_string(), test_print) == true); +} + +TEST_CASE("early warn log level") +{ + PutcFixture fix; + const std::regex test_print("W \\([0-9]*\\) test: warn", std::regex::ECMAScript); + + ESP_EARLY_LOGW(TEST_TAG, "warn"); + CHECK(regex_search(fix.get_print_buffer_string(), test_print) == true); +} + +TEST_CASE("early error log level") +{ + PutcFixture fix; + const std::regex test_print("E \\([0-9]*\\) test: error", std::regex::ECMAScript); + + ESP_EARLY_LOGE(TEST_TAG, "error"); + CHECK(regex_search(fix.get_print_buffer_string(), test_print) == true); +} + +TEST_CASE("changing early log level") +{ + PutcFixture fix(ESP_LOG_INFO); + const std::regex test_print("I \\([0-9]*\\) test: must indeed be printed", std::regex::ECMAScript); + + ESP_EARLY_LOGI(TEST_TAG, "must indeed be printed"); + CHECK(regex_search(fix.get_print_buffer_string(), test_print) == true); + + fix.reset_buffer(); + esp_log_level_set("*", ESP_LOG_WARN); + + ESP_EARLY_LOGI(TEST_TAG, "must not be printed"); + CHECK(fix.get_print_buffer_string().size() == 0); + + fix.reset_buffer(); + esp_log_level_set("*", ESP_LOG_INFO); + + ESP_EARLY_LOGI(TEST_TAG, "must indeed be printed"); + CHECK(regex_search(fix.get_print_buffer_string(), test_print) == true); +} diff --git a/components/log/host_test/log_test/sdkconfig.defaults b/components/log/host_test/log_test/sdkconfig.defaults index b1e1b9b77a..a35fc5148f 100644 --- a/components/log/host_test/log_test/sdkconfig.defaults +++ b/components/log/host_test/log_test/sdkconfig.defaults @@ -5,3 +5,4 @@ CONFIG_LOG_DEFAULT_LEVEL_VERBOSE=y CONFIG_LOG_DEFAULT_LEVEL=5 CONFIG_LOG_MAXIMUM_LEVEL=5 CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT=y +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=n diff --git a/components/log/include/esp_log.h b/components/log/include/esp_log.h index cf7bcd601a..0e3148f62d 100644 --- a/components/log/include/esp_log.h +++ b/components/log/include/esp_log.h @@ -10,9 +10,7 @@ #include #include #include "sdkconfig.h" -#if !defined(CONFIG_IDF_TARGET_LINUX) #include "esp_rom_sys.h" -#endif // !CONFIG_IDF_TARGET_LINUX #if CONFIG_IDF_TARGET_ESP32 #include "esp32/rom/ets_sys.h" // will be removed in idf v5.0 #elif CONFIG_IDF_TARGET_ESP32S2 @@ -90,6 +88,9 @@ esp_log_level_t esp_log_level_get(const char* tag); * output to some other destination, such as file or network. Returns the original * log handler, which may be necessary to return output to the previous destination. * + * @note Please note that function callback here must be re-entrant as it can be + * invoked in parallel from multiple thread context. + * * @param func new Function used for output. Must have same signature as vprintf. * * @return func old Function used for output. diff --git a/components/log/log_linux.c b/components/log/log_linux.c index 62c56c9860..b6d42a9f30 100644 --- a/components/log/log_linux.c +++ b/components/log/log_linux.c @@ -41,6 +41,6 @@ uint32_t esp_log_timestamp(void) struct timespec current_time; int result = clock_gettime(CLOCK_MONOTONIC, ¤t_time); assert(result == 0); - uint32_t seconds = current_time.tv_sec * 1000 + current_time.tv_nsec / 1000000; - return seconds; + uint32_t milliseconds = current_time.tv_sec * 1000 + current_time.tv_nsec / 1000000; + return milliseconds; } diff --git a/components/lwip/Kconfig b/components/lwip/Kconfig index 3393df5bc5..dae592cafb 100644 --- a/components/lwip/Kconfig +++ b/components/lwip/Kconfig @@ -15,6 +15,16 @@ menu "LWIP" could be used to convert network interface index to name instead of IDF specific esp-netif APIs (such as esp_netif_get_netif_impl_name()) + config LWIP_TCPIP_CORE_LOCKING + bool "Enable tcpip core locking" + default n + help + If Enable tcpip core locking,Creates a global mutex that is held + during TCPIP thread operations.Can be locked by client code to perform + lwIP operations without changing into TCPIP thread using callbacks. + See LOCK_TCPIP_CORE() and UNLOCK_TCPIP_CORE(). + + If disable tcpip core locking,TCP IP will perform tasks through context switching. config LWIP_DNS_SUPPORT_MDNS_QUERIES bool "Enable mDNS queries in resolving host name" @@ -256,6 +266,15 @@ menu "LWIP" server. Last valid DHCP configuration is stored in nvs and restored after reset/power-up. If IP is still available, there is no need for sending discovery message to DHCP server and save some time. + config LWIP_DHCP_OPTIONS_LEN + int "DHCP total option length" + default 68 + range 68 255 + help + Set total length of outgoing DHCP option msg. Generally bigger value means it can carry more + options and values. If your code meets LWIP_ASSERT due to option value is too long. + Please increase the LWIP_DHCP_OPTIONS_LEN value. + menu "DHCP server" config LWIP_DHCPS @@ -363,7 +382,7 @@ menu "LWIP" config LWIP_IPV6_RDNSS_MAX_DNS_SERVERS int "Use IPv6 Router Advertisement Recursive DNS Server Option" - depends on LWIP_IPV6 + depends on LWIP_IPV6_AUTOCONFIG default 0 help Use IPv6 Router Advertisement Recursive DNS Server Option (as per RFC 6106) to @@ -371,6 +390,15 @@ menu "LWIP" Set this option to a number of desired DNS servers advertised in the RA protocol. This feature is disabled when set to 0. + config LWIP_IPV6_DHCP6 + bool "Enable DHCPv6 stateless address autoconfiguration" + depends on LWIP_IPV6_AUTOCONFIG + default n + help + Enable DHCPv6 for IPv6 stateless address autoconfiguration. + Note that the dhcpv6 client has to be started using dhcp6_enable_stateless(netif); + Note that the stateful address autoconfiguration is not supported. + config LWIP_NETIF_STATUS_CALLBACK bool "Enable status callback for network interfaces" default n @@ -837,7 +865,7 @@ menu "LWIP" menu "SNTP" - config LWIP_DHCP_MAX_NTP_SERVERS + config LWIP_SNTP_MAX_SERVERS int "Maximum number of NTP servers" default 1 range 1 16 @@ -846,6 +874,23 @@ menu "LWIP" First argument of sntp_setserver/sntp_setservername functions is limited to this value. + config LWIP_DHCP_GET_NTP_SRV + bool "Request NTP servers from DHCP" + default n + help + If enabled, LWIP will add 'NTP' to Parameter-Request Option sent via DHCP-request. + DHCP server might reply with an NTP server address in option 42. + SNTP callback for such replies should be set accordingly (see sntp_servermode_dhcp() func.) + + config LWIP_DHCP_MAX_NTP_SERVERS + int "Maximum number of NTP servers aquired via DHCP" + default 1 + range 1 16 + depends on LWIP_DHCP_GET_NTP_SRV + help + Set maximum number of NTP servers aquired via DHCP-offer. + Should be less or equal to "Maximum number of NTP servers", any extra servers would be just ignored. + config LWIP_SNTP_UPDATE_DELAY int "Request interval to update time (ms)" range 15000 4294967295 @@ -1025,4 +1070,9 @@ menu "LWIP" depends on LWIP_DEBUG default n + config LWIP_SNTP_DEBUG + bool "Enable SNTP debug messages" + depends on LWIP_DEBUG + default n + endmenu diff --git a/components/lwip/apps/ping/ping_sock.c b/components/lwip/apps/ping/ping_sock.c index 00595514c5..c082b8cff3 100644 --- a/components/lwip/apps/ping/ping_sock.c +++ b/components/lwip/apps/ping/ping_sock.c @@ -214,7 +214,7 @@ static void esp_ping_thread(void *args) esp_err_t esp_ping_new_session(const esp_ping_config_t *config, const esp_ping_callbacks_t *cbs, esp_ping_handle_t *hdl_out) { - esp_err_t ret = ESP_OK; + esp_err_t ret = ESP_FAIL; esp_ping_t *ep = NULL; PING_CHECK(config, "ping config can't be null", err, ESP_ERR_INVALID_ARG); PING_CHECK(hdl_out, "ping handle can't be null", err, ESP_ERR_INVALID_ARG); @@ -272,10 +272,12 @@ esp_err_t esp_ping_new_session(const esp_ping_config_t *config, const esp_ping_c if(config->interface) { struct ifreq iface; if(netif_index_to_name(config->interface, iface.ifr_name) == NULL) { - goto err; + ESP_LOGE(TAG, "fail to find interface name with netif index %d", config->interface); + goto err; } - if(setsockopt(ep->sock, SOL_SOCKET, SO_BINDTODEVICE, &iface, sizeof(iface) !=0)) { - goto err; + if(setsockopt(ep->sock, SOL_SOCKET, SO_BINDTODEVICE, &iface, sizeof(iface)) != 0) { + ESP_LOGE(TAG, "fail to setsockopt SO_BINDTODEVICE"); + goto err; } } struct timeval timeout; diff --git a/components/lwip/apps/sntp/sntp.c b/components/lwip/apps/sntp/sntp.c index d6ff2993cf..677574d200 100644 --- a/components/lwip/apps/sntp/sntp.c +++ b/components/lwip/apps/sntp/sntp.c @@ -117,3 +117,18 @@ bool sntp_restart(void) } return false; } + +void sntp_set_system_time(uint32_t sec, uint32_t us) +{ + struct timeval tv = { .tv_sec = sec, .tv_usec = us }; + sntp_sync_time(&tv); +} + +void sntp_get_system_time(uint32_t *sec, uint32_t *us) +{ + struct timeval tv = { .tv_sec = 0, .tv_usec = 0 }; + gettimeofday(&tv, NULL); + *(sec) = tv.tv_sec; + *(us) = tv.tv_usec; + sntp_set_sync_status(SNTP_SYNC_STATUS_RESET); +} diff --git a/components/lwip/include/apps/dhcpserver/dhcpserver.h b/components/lwip/include/apps/dhcpserver/dhcpserver.h index 39a58bbfa9..262ebf43d8 100644 --- a/components/lwip/include/apps/dhcpserver/dhcpserver.h +++ b/components/lwip/include/apps/dhcpserver/dhcpserver.h @@ -17,6 +17,10 @@ #include "sdkconfig.h" #include "lwip/ip_addr.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct dhcps_state{ s16_t state; } dhcps_state; @@ -91,4 +95,8 @@ void dhcps_dns_setserver(const ip_addr_t *dnsserver); ip4_addr_t dhcps_dns_getserver(void); void dhcps_set_new_lease_cb(dhcps_cb_t cb); +#ifdef __cplusplus +} #endif + +#endif /* __DHCPS_H__ */ diff --git a/components/lwip/include/apps/dhcpserver/dhcpserver_options.h b/components/lwip/include/apps/dhcpserver/dhcpserver_options.h index 38d46f6bff..31a6799283 100644 --- a/components/lwip/include/apps/dhcpserver/dhcpserver_options.h +++ b/components/lwip/include/apps/dhcpserver/dhcpserver_options.h @@ -13,6 +13,9 @@ // limitations under the License. #pragma once +#ifdef __cplusplus +extern "C" { +#endif /** DHCP Options This macros are not part of the public dhcpserver.h interface. @@ -132,3 +135,7 @@ typedef enum DOMAIN_SEARCH = 119, CLASSLESS_ROUTE = 121, } dhcp_msg_option; + +#ifdef __cplusplus +} +#endif diff --git a/components/lwip/port/esp32/include/lwipopts.h b/components/lwip/port/esp32/include/lwipopts.h index 72e2bc4a97..b9cfe17aca 100644 --- a/components/lwip/port/esp32/include/lwipopts.h +++ b/components/lwip/port/esp32/include/lwipopts.h @@ -33,9 +33,7 @@ #define __LWIPOPTS_H__ #include -#include #include -#include #include #include #include @@ -44,6 +42,7 @@ #include "esp_system.h" #include "sdkconfig.h" #include "netif/dhcp_state.h" +#include "sntp/sntp_get_set_time.h" /* Enable all Espressif-only options */ @@ -267,6 +266,12 @@ #endif +/** + * CONFIG_LWIP_DHCP_OPTIONS_LEN: The total length of outgoing DHCP option msg. If you have many options + * and options value is too long, you can configure the length according to your requirements + */ +#define DHCP_OPTIONS_LEN CONFIG_LWIP_DHCP_OPTIONS_LEN + /* ------------------------------------ ---------- AUTOIP options ---------- @@ -595,7 +600,7 @@ * LWIP_TCPIP_CORE_LOCKING: (EXPERIMENTAL!) * Don't use it if you're not an active lwIP project member */ -#define LWIP_TCPIP_CORE_LOCKING 0 +#define LWIP_TCPIP_CORE_LOCKING CONFIG_LWIP_TCPIP_CORE_LOCKING /* ------------------------------------ @@ -910,6 +915,15 @@ #define TCP_DEBUG LWIP_DBG_OFF #endif +/** + * SNTP_DEBUG: Enable debugging for SNTP. + */ +#ifdef CONFIG_LWIP_SNTP_DEBUG +#define SNTP_DEBUG LWIP_DBG_ON +#else +#define SNTP_DEBUG LWIP_DBG_OFF +#endif + /** * MEMP_DEBUG: Enable debugging in memp.c. */ @@ -970,6 +984,8 @@ #define LWIP_ND6_RDNSS_MAX_DNS_SERVERS CONFIG_LWIP_IPV6_RDNSS_MAX_DNS_SERVERS +#define LWIP_IPV6_DHCP6 CONFIG_LWIP_IPV6_DHCP6 + /* Enable all Espressif-only options */ #define ESP_LWIP 1 @@ -1044,7 +1060,11 @@ #define CHECKSUM_CHECK_ICMP CONFIG_LWIP_CHECKSUM_CHECK_ICMP #define LWIP_NETCONN_FULLDUPLEX 1 +#if LWIP_TCPIP_CORE_LOCKING +#define LWIP_NETCONN_SEM_PER_THREAD 0 +#else #define LWIP_NETCONN_SEM_PER_THREAD 1 +#endif /* LWIP_TCPIP_CORE_LOCKING */ #define LWIP_DHCP_MAX_NTP_SERVERS CONFIG_LWIP_DHCP_MAX_NTP_SERVERS #define LWIP_TIMEVAL_PRIVATE 0 @@ -1054,25 +1074,15 @@ ------------ SNTP options ------------ -------------------------------------- */ -/* - * SNTP update delay - in milliseconds - */ -/* - * Forward declarations of weak definitions from lwip's sntp.c which could - * be redefined by user application. This is needed to provide custom definition - * of the below macros in lwip's sntp.c. - * Full declaration is provided in IDF's port layer in esp_sntp.h - */ -#ifdef __cplusplus -#define LWIP_FORWARD_DECLARE_C_CXX extern "C" -#else -#define LWIP_FORWARD_DECLARE_C_CXX -#endif +// Max number of SNTP servers handled (default equal to LWIP_DHCP_MAX_NTP_SERVERS) +#if defined CONFIG_LWIP_SNTP_MAX_SERVERS +#define SNTP_MAX_SERVERS CONFIG_LWIP_SNTP_MAX_SERVERS +#endif // CONFIG_LWIP_SNTP_MAX_SERVERS -LWIP_FORWARD_DECLARE_C_CXX void sntp_sync_time(struct timeval *tv); - -LWIP_FORWARD_DECLARE_C_CXX uint32_t sntp_get_sync_interval(void); +#ifdef CONFIG_LWIP_DHCP_GET_NTP_SRV +#define LWIP_DHCP_GET_NTP_SRV CONFIG_LWIP_DHCP_GET_NTP_SRV +#endif // CONFIG_LWIP_DHCP_GET_NTP_SRV /** Set this to 1 to support DNS names (or IP address strings) to set sntp servers * One server address/name can be defined as default if SNTP_SERVER_DNS == 1: @@ -1083,22 +1093,9 @@ LWIP_FORWARD_DECLARE_C_CXX uint32_t sntp_get_sync_interval(void); // It disables a check of SNTP_UPDATE_DELAY it is done in sntp_set_sync_interval #define SNTP_SUPPRESS_DELAY_CHECK -#define SNTP_UPDATE_DELAY (sntp_get_sync_interval()) - -#define SNTP_SET_SYSTEM_TIME_US(sec, us) \ - do { \ - struct timeval tv = { .tv_sec = sec, .tv_usec = us }; \ - sntp_sync_time(&tv); \ - } while (0); - -#define SNTP_GET_SYSTEM_TIME(sec, us) \ - do { \ - struct timeval tv = { .tv_sec = 0, .tv_usec = 0 }; \ - gettimeofday(&tv, NULL); \ - (sec) = tv.tv_sec; \ - (us) = tv.tv_usec; \ - sntp_set_sync_status(SNTP_SYNC_STATUS_RESET); \ - } while (0); +#define SNTP_UPDATE_DELAY (sntp_get_sync_interval()) +#define SNTP_SET_SYSTEM_TIME_US(sec, us) (sntp_set_system_time(sec, us)) +#define SNTP_GET_SYSTEM_TIME(sec, us) (sntp_get_system_time(&(sec), &(us))) #define SOC_SEND_LOG //printf diff --git a/components/lwip/port/esp32/include/sntp/sntp_get_set_time.h b/components/lwip/port/esp32/include/sntp/sntp_get_set_time.h new file mode 100644 index 0000000000..1991620804 --- /dev/null +++ b/components/lwip/port/esp32/include/sntp/sntp_get_set_time.h @@ -0,0 +1,55 @@ +// Copyright 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. + +#ifndef __SNTP_GET_SET_TIME_H__ +#define __SNTP_GET_SET_TIME_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + * Declarations of functions used in lwipopts.h to redefine + * default sntp macros, such as: + * - SNTP_UPDATE_DELAY() + * - SNTP_SET_SYSTEM_TIME_US() + * - SNTP_GET_SYSTEM_TIME() + */ + +/* + * @brief Get the sync interval of SNTP operation + * Full definition is provided in IDF's layer in esp_sntp.c + */ +uint32_t sntp_get_sync_interval(void); + +/** + * @brief system time setter used in the sntp module + * @note The lwip sntp uses u32_t types for sec and us arguments + */ +void sntp_set_system_time(uint32_t sec, uint32_t us); + +/** + * @brief system time getter used in the sntp module + * @note The lwip sntp uses u32_t types for sec and us arguments + */ +void sntp_get_system_time(uint32_t* sec, uint32_t* us); + +#ifdef __cplusplus +} +#endif + +#endif //__SNTP_GET_SET_TIME_H__ diff --git a/components/lwip/port/esp32/vfs_lwip.c b/components/lwip/port/esp32/vfs_lwip.c index 9704308e2e..517838e30e 100644 --- a/components/lwip/port/esp32/vfs_lwip.c +++ b/components/lwip/port/esp32/vfs_lwip.c @@ -70,13 +70,25 @@ static int lwip_ioctl_r_wrapper(int fd, int cmd, va_list args) return lwip_ioctl(fd, cmd, va_arg(args, void *)); } +static int lwip_fstat(int fd, struct stat * st) +{ + if (st == NULL || fd < LWIP_SOCKET_OFFSET || fd > (MAX_FDS - 1)) { + errno = EBADF; + return -1; + } + memset(st, 0, sizeof(*st)); + /* set the stat mode to socket type */ + st->st_mode = S_IFSOCK; + return 0; +} + void esp_vfs_lwip_sockets_register(void) { esp_vfs_t vfs = { .flags = ESP_VFS_FLAG_DEFAULT, .write = &lwip_write, .open = NULL, - .fstat = NULL, + .fstat = &lwip_fstat, .close = &lwip_close, .read = &lwip_read, .fcntl = &lwip_fcntl_r_wrapper, diff --git a/components/lwip/test/CMakeLists.txt b/components/lwip/test/CMakeLists.txt new file mode 100644 index 0000000000..568494320b --- /dev/null +++ b/components/lwip/test/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRC_DIRS "." + PRIV_REQUIRES test_utils) diff --git a/components/lwip/test/component.mk b/components/lwip/test/component.mk new file mode 100644 index 0000000000..8c6eb513e4 --- /dev/null +++ b/components/lwip/test/component.mk @@ -0,0 +1,4 @@ +# +#Component Makefile +# +COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive diff --git a/components/lwip/test/test_lwip_apps.c b/components/lwip/test/test_lwip_apps.c new file mode 100644 index 0000000000..bf55b5f38a --- /dev/null +++ b/components/lwip/test/test_lwip_apps.c @@ -0,0 +1,106 @@ +#include "freertos/FreeRTOS.h" +#include "freertos/event_groups.h" +#include "test_utils.h" +#include "unity.h" +#include "lwip/inet.h" +#include "lwip/netdb.h" +#include "lwip/sockets.h" +#include "ping/ping_sock.h" + +#define ETH_PING_END_BIT BIT(1) +#define ETH_PING_DURATION_MS (5000) +#define ETH_PING_END_TIMEOUT_MS (ETH_PING_DURATION_MS * 2) +#define TEST_ICMP_DESTINATION_DOMAIN_NAME "127.0.0.1" + +static void test_on_ping_success(esp_ping_handle_t hdl, void *args) +{ + uint8_t ttl; + uint16_t seqno; + uint32_t elapsed_time, recv_len; + ip_addr_t target_addr; + esp_ping_get_profile(hdl, ESP_PING_PROF_SEQNO, &seqno, sizeof(seqno)); + esp_ping_get_profile(hdl, ESP_PING_PROF_TTL, &ttl, sizeof(ttl)); + esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr)); + esp_ping_get_profile(hdl, ESP_PING_PROF_SIZE, &recv_len, sizeof(recv_len)); + esp_ping_get_profile(hdl, ESP_PING_PROF_TIMEGAP, &elapsed_time, sizeof(elapsed_time)); + printf("%d bytes from %s icmp_seq=%d ttl=%d time=%d ms\n", + recv_len, inet_ntoa(target_addr.u_addr.ip4), seqno, ttl, elapsed_time); +} + +static void test_on_ping_timeout(esp_ping_handle_t hdl, void *args) +{ + uint16_t seqno; + ip_addr_t target_addr; + esp_ping_get_profile(hdl, ESP_PING_PROF_SEQNO, &seqno, sizeof(seqno)); + esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr)); + printf("From %s icmp_seq=%d timeout\n", inet_ntoa(target_addr.u_addr.ip4), seqno); +} + +static void test_on_ping_end(esp_ping_handle_t hdl, void *args) +{ + EventGroupHandle_t eth_event_group = (EventGroupHandle_t)args; + uint32_t transmitted; + uint32_t received; + uint32_t total_time_ms; + + esp_ping_get_profile(hdl, ESP_PING_PROF_REQUEST, &transmitted, sizeof(transmitted)); + esp_ping_get_profile(hdl, ESP_PING_PROF_REPLY, &received, sizeof(received)); + esp_ping_get_profile(hdl, ESP_PING_PROF_DURATION, &total_time_ms, sizeof(total_time_ms)); + printf("%d packets transmitted, %d received, time %dms\n", transmitted, received, total_time_ms); + if (transmitted == received) { + xEventGroupSetBits(eth_event_group, ETH_PING_END_BIT); + } +} + +TEST_CASE("localhost ping test", "[lwip]") +{ + EventBits_t bits; + EventGroupHandle_t eth_event_group = xEventGroupCreate(); + TEST_ASSERT(eth_event_group != NULL); + test_case_uses_tcpip(); + + // Parse IP address: Destination is a localhost address, so we don't need any interface (esp-netif/driver) + ip_addr_t target_addr; + struct addrinfo hint; + struct addrinfo *res = NULL; + memset(&hint, 0, sizeof(hint)); + memset(&target_addr, 0, sizeof(target_addr)); + /* convert URL to IP */ + TEST_ASSERT(getaddrinfo(TEST_ICMP_DESTINATION_DOMAIN_NAME, NULL, &hint, &res) == 0); + struct in_addr addr4 = ((struct sockaddr_in *)(res->ai_addr))->sin_addr; + inet_addr_to_ip4addr(ip_2_ip4(&target_addr), &addr4); + freeaddrinfo(res); + + esp_ping_config_t ping_config = ESP_PING_DEFAULT_CONFIG(); + ping_config.timeout_ms = 2000; + ping_config.target_addr = target_addr; + ping_config.count = 0; // ping in infinite mode + /* set callback functions */ + esp_ping_callbacks_t cbs; + cbs.on_ping_success = test_on_ping_success; + cbs.on_ping_timeout = test_on_ping_timeout; + cbs.on_ping_end = test_on_ping_end; + cbs.cb_args = eth_event_group; + + esp_ping_handle_t ping; + TEST_ESP_OK(esp_ping_new_session(&ping_config, &cbs, &ping)); + /* start ping */ + TEST_ESP_OK(esp_ping_start(ping)); + /* ping for a while */ + vTaskDelay(pdMS_TO_TICKS(ETH_PING_DURATION_MS)); + /* stop ping */ + TEST_ESP_OK(esp_ping_stop(ping)); + /* wait for end of ping */ + bits = xEventGroupWaitBits(eth_event_group, ETH_PING_END_BIT, true, true, pdMS_TO_TICKS(ETH_PING_END_TIMEOUT_MS)); + TEST_ASSERT((bits & ETH_PING_END_BIT) == ETH_PING_END_BIT); + /* restart ping */ + TEST_ESP_OK(esp_ping_start(ping)); + vTaskDelay(pdMS_TO_TICKS(ETH_PING_DURATION_MS)); + TEST_ESP_OK(esp_ping_stop(ping)); + bits = xEventGroupWaitBits(eth_event_group, ETH_PING_END_BIT, true, true, pdMS_TO_TICKS(ETH_PING_END_TIMEOUT_MS)); + TEST_ASSERT((bits & ETH_PING_END_BIT) == ETH_PING_END_BIT); + /* de-initialize ping process */ + TEST_ESP_OK(esp_ping_delete_session(ping)); + + vEventGroupDelete(eth_event_group); +} diff --git a/components/lwip/test_afl_host/Makefile b/components/lwip/test_afl_host/Makefile index 4d5e2e5d23..2eeda96a7d 100644 --- a/components/lwip/test_afl_host/Makefile +++ b/components/lwip/test_afl_host/Makefile @@ -2,7 +2,7 @@ COMPONENTS_DIR=../.. COMPILER_ICLUDE_DIR=$(shell echo `which xtensa-esp32-elf-gcc | xargs dirname | xargs dirname`/xtensa-esp32-elf) CFLAGS=-std=gnu99 -Og -ggdb -ffunction-sections -fdata-sections -nostdlib -Wall -Werror=all -Wno-int-to-pointer-cast -Wno-error=unused-function -Wno-error=unused-variable -Wno-error=deprecated-declarations -Wno-macro-redefined -Wno-constant-conversion -Wno-incompatible-pointer-types-discards-qualifiers -Wno-typedef-redefinition -Wno-incompatible-pointer-types -Wextra \ -Wno-unused-parameter -Wno-sign-compare -Wno-address -Wno-unused-variable -DESP_PLATFORM -D IDF_VER=\"v3.1\" -MMD -MP -DWITH_POSIX -DLWIP_NO_CTYPE_H=1 -INC_DIRS=-I . -I ./build/config -I $(COMPONENTS_DIR)/newlib/platform_include -I $(COMPONENTS_DIR)/newlib/include -I $(COMPONENTS_DIR)/driver/include -I $(COMPONENTS_DIR)/esp32/include -I $(COMPONENTS_DIR)/ethernet/include -I $(COMPONENTS_DIR)/freertos/include -I $(COMPONENTS_DIR)/heap/include -I $(COMPONENTS_DIR)/lwip/lwip/src/include -I $(COMPONENTS_DIR)/lwip/include/apps -I $(COMPONENTS_DIR)/lwip/lwip/src/include/netif -I $(COMPONENTS_DIR)/lwip/lwip/src/include/posix -I $(COMPONENTS_DIR)/lwip/port/esp32/include -I $(COMPONENTS_DIR)/lwip/lwip/src/include/posix -I $(COMPONENTS_DIR)/lwip/include/apps/ping -I $(COMPONENTS_DIR)/lwip/include/apps/sntp -I $(COMPONENTS_DIR)/soc/esp32/include -I $(COMPONENTS_DIR)/soc/include -I $(COMPONENTS_DIR)/tcpip_adapter/include -I $(COMPONENTS_DIR)/esp_rom/include -I $(COMPONENTS_DIR)/esp_common/include -I $(COMPONENTS_DIR)/esp_hw_support/include -I $(COMPONENTS_DIR)/xtensa/include -I $(COMPONENTS_DIR)/xtensa/esp32/include -I $(COMPONENTS_DIR)/esp_wifi/include -I $(COMPONENTS_DIR)/esp_event/include -I $(COMPONENTS_DIR)/freertos/port/xtensa/include -I $(COMPONENTS_DIR)/esp_system/include -I $(COMPONENTS_DIR)/esp_timer/include -I $(COMPONENTS_DIR)/soc/include -I $(COMPONENTS_DIR)/soc/include -I $(COMPONENTS_DIR)/soc/src/esp32/include -I $(COMPONENTS_DIR)/soc/esp32/include -I $(COMPONENTS_DIR)/esp_netif/include -I $(COMPONENTS_DIR)/esp_eth/include -I $(COMPONENTS_DIR)/esp_netif/lwip -I $(COMPONENTS_DIR)/hal/include -I $(COMPONENTS_DIR)/hal/esp32/include -I $(COMPILER_ICLUDE_DIR)/include +INC_DIRS=-I . -I ./build/config -I $(COMPONENTS_DIR)/newlib/platform_include -I $(COMPONENTS_DIR)/newlib/include -I $(COMPONENTS_DIR)/driver/include -I $(COMPONENTS_DIR)/esp32/include -I $(COMPONENTS_DIR)/ethernet/include -I $(COMPONENTS_DIR)/freertos/include/esp_additions -I $(COMPONENTS_DIR)/freertos/include/esp_additions/freertos -I $(COMPONENTS_DIR)/freertos/include -I $(COMPONENTS_DIR)/heap/include -I $(COMPONENTS_DIR)/lwip/lwip/src/include -I $(COMPONENTS_DIR)/lwip/include/apps -I $(COMPONENTS_DIR)/lwip/lwip/src/include/netif -I $(COMPONENTS_DIR)/lwip/lwip/src/include/posix -I $(COMPONENTS_DIR)/lwip/port/esp32/include -I $(COMPONENTS_DIR)/lwip/lwip/src/include/posix -I $(COMPONENTS_DIR)/lwip/include/apps/ping -I $(COMPONENTS_DIR)/lwip/include/apps/sntp -I $(COMPONENTS_DIR)/soc/esp32/include -I $(COMPONENTS_DIR)/soc/include -I $(COMPONENTS_DIR)/tcpip_adapter/include -I $(COMPONENTS_DIR)/esp_rom/include -I $(COMPONENTS_DIR)/esp_common/include -I $(COMPONENTS_DIR)/esp_hw_support/include -I $(COMPONENTS_DIR)/xtensa/include -I $(COMPONENTS_DIR)/xtensa/esp32/include -I $(COMPONENTS_DIR)/esp_wifi/include -I $(COMPONENTS_DIR)/esp_event/include -I $(COMPONENTS_DIR)/freertos/port/xtensa/include -I $(COMPONENTS_DIR)/esp_system/include -I $(COMPONENTS_DIR)/esp_timer/include -I $(COMPONENTS_DIR)/soc/include -I $(COMPONENTS_DIR)/soc/include -I $(COMPONENTS_DIR)/soc/src/esp32/include -I $(COMPONENTS_DIR)/soc/esp32/include -I $(COMPONENTS_DIR)/esp_netif/include -I $(COMPONENTS_DIR)/esp_eth/include -I $(COMPONENTS_DIR)/esp_netif/lwip -I $(COMPONENTS_DIR)/hal/include -I $(COMPONENTS_DIR)/hal/esp32/include -I $(COMPILER_ICLUDE_DIR)/include TEST_NAME=test FUZZ=afl-fuzz GEN_CFG=generate_config diff --git a/components/mbedtls/port/crypto_shared_gdma/esp_crypto_shared_gdma.c b/components/mbedtls/port/crypto_shared_gdma/esp_crypto_shared_gdma.c index ec35725fdf..30ec888dd7 100644 --- a/components/mbedtls/port/crypto_shared_gdma/esp_crypto_shared_gdma.c +++ b/components/mbedtls/port/crypto_shared_gdma/esp_crypto_shared_gdma.c @@ -53,20 +53,6 @@ static inline esp_err_t crypto_shared_gdma_new_channel(gdma_channel_alloc_config return ret; } - -#if SOC_GDMA_SUPPORT_PSRAM -/* Initialize external memory specific DMA configs */ -static void esp_crypto_shared_dma_init_extmem(void) -{ - gdma_transfer_ability_t transfer_ability = { - .sram_trans_align = 4, - .psram_trans_align = 16, - }; - gdma_set_transfer_ability(tx_channel, &transfer_ability); - gdma_set_transfer_ability(rx_channel, &transfer_ability); -} -#endif //SOC_GDMA_SUPPORT_PSRAM - /* Initialize GDMA module and channels */ static esp_err_t crypto_shared_gdma_init(void) { @@ -80,6 +66,12 @@ static esp_err_t crypto_shared_gdma_init(void) .direction = GDMA_CHANNEL_DIRECTION_RX, }; + gdma_transfer_ability_t transfer_ability = { + .sram_trans_align = 1, + .psram_trans_align = 16, + }; + + ret = crypto_shared_gdma_new_channel(&channel_config_tx, &tx_channel); if (ret != ESP_OK) { goto err; @@ -91,9 +83,9 @@ static esp_err_t crypto_shared_gdma_init(void) goto err; } -#if SOC_GDMA_SUPPORT_PSRAM - esp_crypto_shared_dma_init_extmem(); -#endif //SOC_GDMA_SUPPORT_PSRAM + + gdma_set_transfer_ability(tx_channel, &transfer_ability); + gdma_set_transfer_ability(rx_channel, &transfer_ability); gdma_connect(rx_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_AES, 0)); gdma_connect(tx_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_AES, 0)); @@ -136,7 +128,7 @@ esp_err_t esp_crypto_shared_gdma_start(const lldesc_t *input, const lldesc_t *ou } /* tx channel is reset by gdma_connect(), also reset rx to ensure a known state */ - gdma_get_channel_id(tx_channel, &rx_ch_id); + gdma_get_channel_id(rx_channel, &rx_ch_id); gdma_ll_rx_reset_channel(&GDMA, rx_ch_id); gdma_start(tx_channel, (intptr_t)input); diff --git a/components/mbedtls/port/esp_ds/esp_rsa_sign_alt.c b/components/mbedtls/port/esp_ds/esp_rsa_sign_alt.c index a01134fae0..b0914cf01e 100644 --- a/components/mbedtls/port/esp_ds/esp_rsa_sign_alt.c +++ b/components/mbedtls/port/esp_ds/esp_rsa_sign_alt.c @@ -21,6 +21,8 @@ #include "esp32c3/rom/digital_signature.h" #elif CONFIG_IDF_TARGET_ESP32H2 #include "esp32h2/rom/digital_signature.h" +#elif CONFIG_IDF_TARGET_ESP32S3 +#include "esp32s3/rom/digital_signature.h" #else #error "Selected target does not support esp_rsa_sign_alt (for DS)" #endif diff --git a/components/mbedtls/test/test_aes.c b/components/mbedtls/test/test_aes.c index 2c89d3f370..d66cef22fd 100644 --- a/components/mbedtls/test/test_aes.c +++ b/components/mbedtls/test/test_aes.c @@ -773,9 +773,7 @@ TEST_CASE("mbedtls OFB, chained DMA descriptors", "[aes]") -#ifdef CONFIG_SPIRAM_USE_MALLOC - -const uint8_t expected_cipher_psram_end[] = { +const uint8_t expected_cipher_ctr_end[] = { 0x7e, 0xdf, 0x13, 0xf3, 0x56, 0xef, 0x67, 0x01, 0xfc, 0x08, 0x49, 0x62, 0xfa, 0xfe, 0x0c, 0x8b, 0x99, 0x39, 0x09, 0x51, 0x2c, 0x9a, 0xd5, 0x48, @@ -783,7 +781,7 @@ const uint8_t expected_cipher_psram_end[] = { }; -void aes_psram_ctr_test(uint32_t input_buf_caps, uint32_t output_buf_caps) +void aes_ctr_alignment_test(uint32_t input_buf_caps, uint32_t output_buf_caps) { mbedtls_aes_context ctx; uint8_t nonce[16]; @@ -815,7 +813,7 @@ void aes_psram_ctr_test(uint32_t input_buf_caps, uint32_t output_buf_caps) 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_psram_end, chipertext + i + SZ - 32, 32); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_ctr_end, chipertext + i + SZ - 32, 32); // Decrypt offset = 0; @@ -833,6 +831,15 @@ void aes_psram_ctr_test(uint32_t input_buf_caps, uint32_t output_buf_caps) free(decryptedtext); } +TEST_CASE("mbedtls AES internal mem alignment tests", "[aes]") +{ + uint32_t internal_dma_caps = MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL; + aes_ctr_alignment_test(internal_dma_caps, internal_dma_caps); +} + + +#ifdef CONFIG_SPIRAM_USE_MALLOC + void aes_psram_one_buf_ctr_test(void) { mbedtls_aes_context ctx; @@ -862,7 +869,7 @@ void aes_psram_one_buf_ctr_test(void) memset(buf, 0x26, SZ + ALIGNMENT_SIZE_BYTES); memset(nonce, 0x2F, 16); mbedtls_aes_crypt_ctr(&ctx, SZ, &offset, nonce, stream_block, buf + i, buf + i); - TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_psram_end, buf + i + SZ - 32, 32); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_ctr_end, buf + i + SZ - 32, 32); // Decrypt offset = 0; @@ -1444,9 +1451,9 @@ void aes_ext_flash_ctr_test(uint32_t output_buf_caps) /* Tests how crypto DMA handles data in external memory */ TEST_CASE("mbedtls AES PSRAM tests", "[aes]") { - aes_psram_ctr_test(MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); - aes_psram_ctr_test(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); - aes_psram_ctr_test(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); + aes_ctr_alignment_test(MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); + aes_ctr_alignment_test(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + aes_ctr_alignment_test(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); aes_psram_one_buf_ctr_test(); } diff --git a/components/mdns/CMakeLists.txt b/components/mdns/CMakeLists.txt index a8d2cedb3d..cb3ed49960 100644 --- a/components/mdns/CMakeLists.txt +++ b/components/mdns/CMakeLists.txt @@ -1,7 +1,22 @@ -idf_component_register(SRCS "mdns.c" - "mdns_console.c" - "mdns_networking.c" - INCLUDE_DIRS "include" - PRIV_INCLUDE_DIRS "private_include" - REQUIRES lwip console esp_netif - PRIV_REQUIRES esp_timer) +if(CONFIG_MDNS_NETWORKING_SOCKET) + set(MDNS_NETWORKING "mdns_networking_socket.c") +else() + set(MDNS_NETWORKING "mdns_networking_lwip.c") +endif() + +idf_build_get_property(target IDF_TARGET) +if(${target} STREQUAL "linux") + set(dependencies esp_system_protocols_linux) + set(srcs "mdns.c" ${MDNS_NETWORKING}) +else() + set(dependencies lwip console esp_netif) + set(private_dependencies esp_timer) + set(srcs "mdns.c" ${MDNS_NETWORKING} "mdns_console.c") +endif() + +idf_component_register( + SRCS ${srcs} + INCLUDE_DIRS "include" + PRIV_INCLUDE_DIRS "private_include" + REQUIRES ${dependencies} + PRIV_REQUIRES ${private_dependencies}) diff --git a/components/mdns/Kconfig b/components/mdns/Kconfig index 38dec76287..b49ae703c7 100644 --- a/components/mdns/Kconfig +++ b/components/mdns/Kconfig @@ -75,4 +75,13 @@ menu "mDNS" Configures period of mDNS timer, which periodically transmits packets and schedules mDNS searches. + config MDNS_NETWORKING_SOCKET + bool "Use BSD sockets for mdns networking" + default n + help + Enables optional mdns networking implementation using BSD sockets + in UDP multicast mode. + This option creates a new thread to serve receiving packets (TODO). + This option uses additional N sockets, where N is number of interfaces. + endmenu diff --git a/components/mdns/component.mk b/components/mdns/component.mk index 064cc0608e..f22f83094a 100644 --- a/components/mdns/component.mk +++ b/components/mdns/component.mk @@ -1,2 +1,7 @@ +ifdef CONFIG_MDNS_NETWORKING_SOCKET +COMPONENT_OBJEXCLUDE := mdns_networking_lwip.o +else +COMPONENT_OBJEXCLUDE := mdns_networking_socket.o +endif COMPONENT_ADD_INCLUDEDIRS := include COMPONENT_PRIV_INCLUDEDIRS := private_include diff --git a/components/mdns/host_test/CMakeLists.txt b/components/mdns/host_test/CMakeLists.txt new file mode 100644 index 0000000000..132e436eaf --- /dev/null +++ b/components/mdns/host_test/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +set(COMPONENTS main) +project(mdns_host) diff --git a/components/mdns/host_test/README.md b/components/mdns/host_test/README.md new file mode 100644 index 0000000000..ab916520dd --- /dev/null +++ b/components/mdns/host_test/README.md @@ -0,0 +1,25 @@ +# Setup dummy network interfaces +``` +sudo ip link add eth2 type dummy +sudo ip addr add 192.168.1.200/24 dev eth2 +sudo ip link set eth2 up +sudo ifconfig eth2 multicast +``` + +# Dig on a specified interface + +``` +dig +short -b 192.168.1.200 -p 5353 @224.0.0.251 myesp.local +``` + +# Run avahi to browse services + +Avahi needs the netif to have the "multicast" flag set + +```bash +david@david-comp:~/esp/idf (feature/mdns_networking_socket)$ avahi-browse -a -r -p ++;eth2;IPv6;myesp-service2;Web Site;local ++;eth2;IPv4;myesp-service2;Web Site;local +=;eth2;IPv6;myesp-service2;Web Site;local;myesp.local;192.168.1.200;80;"board=esp32" "u=user" "p=password" +=;eth2;IPv4;myesp-service2;Web Site;local;myesp.local;192.168.1.200;80;"board=esp32" "u=user" "p=password" +``` diff --git a/components/mdns/host_test/components/esp_event_mock/CMakeLists.txt b/components/mdns/host_test/components/esp_event_mock/CMakeLists.txt new file mode 100644 index 0000000000..606c16f808 --- /dev/null +++ b/components/mdns/host_test/components/esp_event_mock/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS esp_event_mock.c + INCLUDE_DIRS include + REQUIRES esp_system_protocols_linux) diff --git a/components/mdns/host_test/components/esp_event_mock/esp_event_mock.c b/components/mdns/host_test/components/esp_event_mock/esp_event_mock.c new file mode 100644 index 0000000000..cd6b079b35 --- /dev/null +++ b/components/mdns/host_test/components/esp_event_mock/esp_event_mock.c @@ -0,0 +1,29 @@ +// Copyright 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. + +#include "esp_err.h" +#include "esp_event.h" + +const char * WIFI_EVENT = "WIFI_EVENT"; +const char * IP_EVENT = "IP_EVENT"; + +esp_err_t esp_event_handler_register(const char * event_base, int32_t event_id, void* event_handler, void* event_handler_arg) +{ + return ESP_OK; +} + +esp_err_t esp_event_handler_unregister(const char * event_base, int32_t event_id, void* event_handler) +{ + return ESP_OK; +} diff --git a/components/mdns/host_test/components/esp_event_mock/include/esp_event.h b/components/mdns/host_test/components/esp_event_mock/include/esp_event.h new file mode 100644 index 0000000000..18801e4b9f --- /dev/null +++ b/components/mdns/host_test/components/esp_event_mock/include/esp_event.h @@ -0,0 +1,32 @@ +// Copyright 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. +#pragma once + +#include "stdbool.h" +#include "esp_err.h" +#include "esp_event_base.h" +#include "bsd_strings.h" + +#define ESP_EVENT_DECLARE_BASE(x) +#define ESP_EVENT_ANY_ID (-1) + +typedef void * esp_event_base_t; +typedef void * system_event_t; + +const char* WIFI_EVENT; +const char* IP_EVENT; + +esp_err_t esp_event_handler_register(const char * event_base, int32_t event_id, void* event_handler, void* event_handler_arg); + +esp_err_t esp_event_handler_unregister(const char * event_base, int32_t event_id, void* event_handler); diff --git a/components/mdns/host_test/components/esp_event_mock/include/esp_event_base.h b/components/mdns/host_test/components/esp_event_mock/include/esp_event_base.h new file mode 100644 index 0000000000..740b712702 --- /dev/null +++ b/components/mdns/host_test/components/esp_event_mock/include/esp_event_base.h @@ -0,0 +1,21 @@ +// Copyright 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. +#pragma once + +typedef enum { + WIFI_EVENT_STA_CONNECTED, /**< ESP32 station connected to AP */ + WIFI_EVENT_STA_DISCONNECTED, /**< ESP32 station disconnected from AP */ + WIFI_EVENT_AP_START, /**< ESP32 soft-AP start */ + WIFI_EVENT_AP_STOP, /**< ESP32 soft-AP stop */ +} mdns_used_event_t; diff --git a/components/mdns/host_test/components/esp_netif_linux/CMakeLists.txt b/components/mdns/host_test/components/esp_netif_linux/CMakeLists.txt new file mode 100644 index 0000000000..086034b089 --- /dev/null +++ b/components/mdns/host_test/components/esp_netif_linux/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS esp_netif_linux.c + INCLUDE_DIRS include + REQUIRES esp_system_protocols_linux) diff --git a/components/mdns/host_test/components/esp_netif_linux/Kconfig b/components/mdns/host_test/components/esp_netif_linux/Kconfig new file mode 100644 index 0000000000..c903f7ca5f --- /dev/null +++ b/components/mdns/host_test/components/esp_netif_linux/Kconfig @@ -0,0 +1,9 @@ +menu "LWIP-MOCK-CONFIG" + + config LWIP_IPV6 + bool "Enable IPv6" + default true + help + Enable/disable IPv6 + +endmenu diff --git a/components/mdns/host_test/components/esp_netif_linux/esp_netif_linux.c b/components/mdns/host_test/components/esp_netif_linux/esp_netif_linux.c new file mode 100644 index 0000000000..bbde590737 --- /dev/null +++ b/components/mdns/host_test/components/esp_netif_linux/esp_netif_linux.c @@ -0,0 +1,163 @@ +// Copyright 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. +#include +#include + +#include "esp_netif.h" +#include "esp_err.h" +#include //strlen +#include +#include //inet_addr +#include +#include +#include +#include "esp_netif_types.h" + +#define MAX_NETIFS 4 + +static esp_netif_t* s_netif_list[MAX_NETIFS] = { 0 }; + +struct esp_netif_obj +{ + const char *if_key; + const char *if_desc; +}; + +esp_netif_t *esp_netif_get_handle_from_ifkey(const char *if_key) +{ + for (int i=0; iif_key, if_key) == 0) { + return s_netif_list[i]; + } + } + return NULL; +} + +esp_err_t esp_netif_get_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_info) +{ + if (esp_netif == NULL) { + return ESP_ERR_INVALID_STATE; + } + struct ifaddrs *addrs, *tmp; + getifaddrs(&addrs); + tmp = addrs; + + while (tmp) { + if (tmp->ifa_addr && tmp->ifa_addr->sa_family == AF_INET) { + char addr[20]; + struct sockaddr_in *pAddr = (struct sockaddr_in *) tmp->ifa_addr; + inet_ntop(AF_INET, &pAddr->sin_addr, addr, sizeof(addr) ); + if (strcmp(esp_netif->if_desc, tmp->ifa_name) == 0) { + printf("AF_INET: %s: %s\n", tmp->ifa_name, addr); + memcpy(&ip_info->ip.addr, &pAddr->sin_addr, 4); + break; + } + } + tmp = tmp->ifa_next; + } + return ESP_OK; +} + +esp_err_t esp_netif_dhcpc_get_status(esp_netif_t *esp_netif, esp_netif_dhcp_status_t *status) +{ + return ESP_OK; +} + + +esp_err_t esp_netif_get_ip6_linklocal(esp_netif_t *esp_netif, esp_ip6_addr_t *if_ip6) +{ + if (esp_netif == NULL) { + return ESP_ERR_INVALID_STATE; + } + struct ifaddrs *addrs, *tmp; + getifaddrs(&addrs); + tmp = addrs; + + while (tmp) + { + if (tmp->ifa_addr && tmp->ifa_addr->sa_family == AF_INET6) { + char addr[64]; + struct sockaddr_in6 *pAddr = (struct sockaddr_in6 *)tmp->ifa_addr; + inet_ntop(AF_INET6, &pAddr->sin6_addr, addr, sizeof(addr) ); + if (strcmp(esp_netif->if_desc, tmp->ifa_name) == 0) { + printf("AF_INET6: %s: %s\n", tmp->ifa_name, addr); + memcpy(if_ip6->addr, &pAddr->sin6_addr, 4*4); + break; + } + } + tmp = tmp->ifa_next; + } + + freeifaddrs(addrs); + return ESP_OK; +} + + +int esp_netif_get_netif_impl_index(esp_netif_t *esp_netif) +{ + if (esp_netif == NULL) { + return -1; + } + uint32_t interfaceIndex = if_nametoindex(esp_netif->if_desc); + return interfaceIndex; +} + +esp_err_t esp_netif_get_netif_impl_name(esp_netif_t *esp_netif, char* name) +{ + if (esp_netif == NULL) { + return ESP_ERR_INVALID_STATE; + } + strcpy(name, esp_netif->if_desc); + return ESP_OK; +} + +const char *esp_netif_get_desc(esp_netif_t *esp_netif) +{ + if (esp_netif == NULL) { + return NULL; + } + return esp_netif->if_desc; +} + +esp_netif_t *esp_netif_new(const esp_netif_config_t *config) +{ + if (esp_netif_get_handle_from_ifkey(config->base->if_key)) { + return NULL; + } + esp_netif_t* netif = calloc(1, sizeof(struct esp_netif_obj)); + if (netif) { + netif->if_desc = config->base->if_desc; + netif->if_key = config->base->if_key; + } + + for (int i=0; i + +void _esp_error_check_failed(esp_err_t rc, const char *file, int line, const char *function, const char *expression) +{ + ESP_LOGE("ESP_ERROR_CHECK", "Failed with esp_err_t: 0x%x", rc); + ESP_LOGE("ESP_ERROR_CHECK", "Expression: %s", expression); + ESP_LOGE("ESP_ERROR_CHECK", "Functions: %s %s(%d)", function, file, line); + abort(); +} + +void esp_log_buffer_hexdump_internal(const char *tag, const void *buffer, uint16_t buff_len, esp_log_level_t log_level) +{ + if ( LOG_LOCAL_LEVEL >= log_level ) { + ESP_LOG_LEVEL(log_level, tag, "Buffer:%p length:%d", buffer, buff_len); + for (int i=0; i + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "string.h" + +/* + * Appends src to string dst of size siz (unlike strncat, siz is the + * full size of dst, not space left). At most siz-1 characters + * will be copied. Always NUL terminates (unless siz <= strlen(dst)). + * Returns strlen(src) + MIN(siz, strlen(initial dst)). + * If retval >= siz, truncation occurred. + */ +size_t +strlcat(dst, src, siz) + char *dst; + const char *src; + size_t siz; +{ + char *d = dst; + const char *s = src; + size_t n = siz; + size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (n-- != 0 && *d != '\0') + d++; + dlen = d - dst; + n = siz - dlen; + + if (n == 0) + return(dlen + strlen(s)); + while (*s != '\0') { + if (n != 1) { + *d++ = *s; + n--; + } + s++; + } + *d = '\0'; + + return(dlen + (s - src)); /* count does not include NUL */ +} diff --git a/components/mdns/host_test/components/esp_timer_linux/CMakeLists.txt b/components/mdns/host_test/components/esp_timer_linux/CMakeLists.txt new file mode 100644 index 0000000000..0c598a2e61 --- /dev/null +++ b/components/mdns/host_test/components/esp_timer_linux/CMakeLists.txt @@ -0,0 +1,5 @@ +idf_component_register(SRCS esp_timer_linux.c timer_task.cpp + INCLUDE_DIRS include + REQUIRES esp_system_protocols_linux freertos_linux) + +target_compile_features(${COMPONENT_LIB} PRIVATE cxx_std_17) diff --git a/components/mdns/host_test/components/esp_timer_linux/esp_timer_linux.c b/components/mdns/host_test/components/esp_timer_linux/esp_timer_linux.c new file mode 100644 index 0000000000..bb2326985f --- /dev/null +++ b/components/mdns/host_test/components/esp_timer_linux/esp_timer_linux.c @@ -0,0 +1,47 @@ +// Copyright 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. +#include "esp_err.h" +#include "esp_timer.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +void * create_tt(esp_timer_cb_t cb); + +void destroy_tt(void* tt); + +void set_tout(void* tt, uint32_t ms); + +esp_err_t esp_timer_create(const esp_timer_create_args_t* create_args, + esp_timer_handle_t* out_handle) +{ + *out_handle = (esp_timer_handle_t)create_tt(create_args->callback); + return ESP_OK; +} + +esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period) +{ + set_tout(timer, period/1000); + return ESP_OK; +} + +esp_err_t esp_timer_stop(esp_timer_handle_t timer) +{ + return ESP_OK; +} + +esp_err_t esp_timer_delete(esp_timer_handle_t timer) +{ + destroy_tt(timer); + return ESP_OK; +} diff --git a/components/mdns/host_test/components/esp_timer_linux/include/esp_timer.h b/components/mdns/host_test/components/esp_timer_linux/include/esp_timer.h new file mode 100644 index 0000000000..6691630490 --- /dev/null +++ b/components/mdns/host_test/components/esp_timer_linux/include/esp_timer.h @@ -0,0 +1,41 @@ +// Copyright 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. +#pragma once + +#include +#include + +typedef struct esp_timer* esp_timer_handle_t; + +typedef void (*esp_timer_cb_t)(void* arg); + +typedef enum { + ESP_TIMER_TASK, +} esp_timer_dispatch_t; + +typedef struct { + esp_timer_cb_t callback; //!< Function to call when timer expires + void* arg; //!< Argument to pass to the callback + esp_timer_dispatch_t dispatch_method; //!< Call the callback from task or from ISR + const char* name; //!< Timer name, used in esp_timer_dump function + bool skip_unhandled_events; //!< Skip unhandled events for periodic timers +} esp_timer_create_args_t; + +esp_err_t esp_timer_create(const esp_timer_create_args_t* create_args, + esp_timer_handle_t* out_handle); +esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period); + +esp_err_t esp_timer_stop(esp_timer_handle_t timer); + +esp_err_t esp_timer_delete(esp_timer_handle_t timer); diff --git a/components/mdns/host_test/components/esp_timer_linux/timer_task.cpp b/components/mdns/host_test/components/esp_timer_linux/timer_task.cpp new file mode 100644 index 0000000000..bd971b3f0c --- /dev/null +++ b/components/mdns/host_test/components/esp_timer_linux/timer_task.cpp @@ -0,0 +1,38 @@ +// Copyright 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. + +#include "timer_task.hpp" +#include +#include +#include +#include + +extern "C" void * create_tt(cb_t cb) +{ + auto * tt = new TimerTaskMock(cb); + return tt; +} + +extern "C" void destroy_tt(void* tt) +{ + auto * timer_task = static_cast(tt); + delete(timer_task); +} + + +extern "C" void set_tout(void* tt, uint32_t ms) +{ + auto * timer_task = static_cast(tt); + timer_task->SetTimeout(ms); +} diff --git a/components/mdns/host_test/components/esp_timer_linux/timer_task.hpp b/components/mdns/host_test/components/esp_timer_linux/timer_task.hpp new file mode 100644 index 0000000000..8d32a6bd0b --- /dev/null +++ b/components/mdns/host_test/components/esp_timer_linux/timer_task.hpp @@ -0,0 +1,61 @@ +// Copyright 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. +#pragma once + +#include +#include +#include +#include +#include +#include + +typedef void (*cb_t)(void* arg); + +class TimerTaskMock +{ +public: + TimerTaskMock(cb_t cb): cb(cb), t(run_static, this), active(false), ms(INT32_MAX) {} + ~TimerTaskMock(void) { active = false; t.join(); } + + void SetTimeout(uint32_t m) + { + ms = m; + active = true; + } + +private: + + static void run_static(TimerTaskMock* timer) + { + timer->run(); + } + + void run(void) + { + while (!active.load()) { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + + while (active.load()) { + std::this_thread::sleep_for(std::chrono::milliseconds(ms)); + cb(nullptr); + } + } + + cb_t cb; + std::thread t; + std::atomic active; + uint32_t ms; + +}; diff --git a/components/mdns/host_test/components/freertos_linux/CMakeLists.txt b/components/mdns/host_test/components/freertos_linux/CMakeLists.txt new file mode 100644 index 0000000000..7a84af21a7 --- /dev/null +++ b/components/mdns/host_test/components/freertos_linux/CMakeLists.txt @@ -0,0 +1,9 @@ +idf_component_register(SRCS freertos_linux.c queue_unique_ptr.cpp + INCLUDE_DIRS include + REQUIRES esp_system_protocols_linux) + +set(THREADS_PREFER_PTHREAD_FLAG ON) +find_package(Threads REQUIRED) +target_link_libraries(${COMPONENT_LIB} PRIVATE Threads::Threads) + +target_compile_features(${COMPONENT_LIB} PRIVATE cxx_std_17) diff --git a/components/mdns/host_test/components/freertos_linux/Kconfig b/components/mdns/host_test/components/freertos_linux/Kconfig new file mode 100644 index 0000000000..fa57dab7e2 --- /dev/null +++ b/components/mdns/host_test/components/freertos_linux/Kconfig @@ -0,0 +1,7 @@ +menu "FreeRTOS" + + config FREERTOS_NO_AFFINITY + hex + default 0x7FFFFFFF + +endmenu diff --git a/components/mdns/host_test/components/freertos_linux/freertos_linux.c b/components/mdns/host_test/components/freertos_linux/freertos_linux.c new file mode 100644 index 0000000000..7633645045 --- /dev/null +++ b/components/mdns/host_test/components/freertos_linux/freertos_linux.c @@ -0,0 +1,192 @@ +// Copyright 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. + +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include +#include +#include +#include + +void * create_q(void); + +void destroy_q(void* q); + +bool send_q(void* q, uint8_t *data, size_t len); + +bool recv_q(void* q, uint8_t *data, size_t len, uint32_t ms); + +static uint64_t s_semaphore_data = 0; + +struct queue_handle { + size_t item_size; + void * q; +}; + +QueueHandle_t xQueueCreate( uint32_t uxQueueLength, uint32_t uxItemSize ) +{ + struct queue_handle * h = calloc(1, sizeof(struct queue_handle)); + h->item_size = uxItemSize; + h->q = create_q(); + return (QueueHandle_t)h; +} + +uint32_t xQueueSend(QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait) +{ + struct queue_handle * h = xQueue; + return send_q(h->q, (uint8_t*)pvItemToQueue, h->item_size) ? pdTRUE : pdFAIL; +} + +uint32_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait) +{ + struct queue_handle * h = xQueue; + return recv_q(h->q, (uint8_t*)pvBuffer, h->item_size, xTicksToWait) ? pdTRUE : pdFAIL; +} + +BaseType_t xSemaphoreGive( QueueHandle_t xQueue) +{ + return xQueueSend(xQueue, &s_semaphore_data, portMAX_DELAY); +} + +BaseType_t xSemaphoreTake( QueueHandle_t xQueue, TickType_t pvTask ) +{ + return xQueueReceive(xQueue, &s_semaphore_data, portMAX_DELAY); +} + +void vQueueDelete( QueueHandle_t xQueue ) +{ + struct queue_handle * h = xQueue; + if (h->q) { + destroy_q(h->q); + } + free(xQueue); +} + +QueueHandle_t xSemaphoreCreateBinary(void) +{ + QueueHandle_t sempaphore = xQueueCreate(1, 1); + return sempaphore; +} + +QueueHandle_t xSemaphoreCreateMutex(void) +{ + QueueHandle_t sempaphore = xQueueCreate(1, 1); + if (sempaphore) { + xSemaphoreGive(sempaphore); + } + return sempaphore; +} + +void vTaskDelete(TaskHandle_t *task) +{ + if (task == NULL) { + pthread_exit(0); + } + void *thread_rval = NULL; + pthread_join((pthread_t)task, &thread_rval); +} + +TickType_t xTaskGetTickCount( void ) +{ + struct timespec spec; + clock_gettime(CLOCK_REALTIME, &spec); + return spec.tv_nsec / 1000000 + spec.tv_sec * 1000; +} + +void vTaskDelay( const TickType_t xTicksToDelay ) +{ + usleep(xTicksToDelay*1000); +} + +void * pthread_task(void * params) +{ + struct { + void * const param; + TaskFunction_t task; + bool started; + } *pthread_params = params; + + void * const param = pthread_params->param; + TaskFunction_t task = pthread_params->task; + pthread_params->started = true; + + task(param); + + return NULL; +} + +BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pvTaskCode, + const char * const pcName, + const uint32_t usStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + TaskHandle_t * const pvCreatedTask, + const BaseType_t xCoreID) +{ + xTaskCreate(pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pvCreatedTask); + return pdTRUE; +} + + +void xTaskCreate(TaskFunction_t pvTaskCode, const char * const pcName, const uint32_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pvCreatedTask) +{ + pthread_t new_thread = (pthread_t)NULL; + pthread_attr_t attr; + struct { + void * const param; + TaskFunction_t task; + bool started; + } pthread_params = { .param = pvParameters, .task = pvTaskCode}; + int res = pthread_attr_init(&attr); + assert(res == 0); + res = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + assert(res == 0); + res = pthread_create(&new_thread, &attr, pthread_task, &pthread_params); + assert(res == 0); + + if (pvCreatedTask) { + *pvCreatedTask = (void*)new_thread; + } + + // just wait till the task started so we can unwind params from the stack + while (pthread_params.started == false) { + usleep(1000); + } +} + +uint32_t esp_get_free_heap_size(void) +{ + return 0; +} + +uint32_t esp_random(void) +{ + return rand(); +} + +void xTaskNotifyGive(TaskHandle_t task) +{ + +} + +BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, uint32_t *value, TickType_t wait_time ) +{ + return true; +} + +TaskHandle_t xTaskGetCurrentTaskHandle(void) +{ + return NULL; +} diff --git a/components/mdns/host_test/components/freertos_linux/include/esp_task.h b/components/mdns/host_test/components/freertos_linux/include/esp_task.h new file mode 100644 index 0000000000..797b416b6e --- /dev/null +++ b/components/mdns/host_test/components/freertos_linux/include/esp_task.h @@ -0,0 +1,20 @@ +// Copyright 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. +#pragma once + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#define ESP_TASK_PRIO_MAX 25 +#define ESP_TASKD_EVENT_PRIO 5 diff --git a/components/mdns/host_test/components/freertos_linux/include/freertos/FreeRTOS.h b/components/mdns/host_test/components/freertos_linux/include/freertos/FreeRTOS.h new file mode 100644 index 0000000000..ca13d0463f --- /dev/null +++ b/components/mdns/host_test/components/freertos_linux/include/freertos/FreeRTOS.h @@ -0,0 +1,46 @@ +// Copyright 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. +#pragma once + +#include +#include +#include +#include + +#define portTICK_PERIOD_MS 1 +#define portMAX_DELAY ( TickType_t ) 0xffffffffUL + +typedef void * xSemaphoreHandle; +typedef void * SemaphoreHandle_t; +typedef void * xQueueHandle; +typedef void * QueueHandle_t; +typedef void * TaskHandle_t; +typedef uint32_t TickType_t; +typedef uint32_t portTickType; + +typedef void (*TaskFunction_t)( void * ); +typedef unsigned int UBaseType_t; +typedef int BaseType_t; + +#define pdFALSE ( ( BaseType_t ) 0 ) +#define pdTRUE ( ( BaseType_t ) 1 ) + +#define pdPASS ( pdTRUE ) +#define pdFAIL ( pdFALSE ) + +#define portTICK_RATE_MS portTICK_PERIOD_MS +#define pdMS_TO_TICKS(tick) (tick) + +uint32_t esp_get_free_heap_size(void); +uint32_t esp_random(void); diff --git a/components/mdns/host_test/components/freertos_linux/include/freertos/task.h b/components/mdns/host_test/components/freertos_linux/include/freertos/task.h new file mode 100644 index 0000000000..f6c213ed42 --- /dev/null +++ b/components/mdns/host_test/components/freertos_linux/include/freertos/task.h @@ -0,0 +1,58 @@ +// Copyright 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. +#pragma once + +#include "freertos/FreeRTOS.h" + +#define xTaskHandle TaskHandle_t +#define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) ) + +void vTaskDelay( const TickType_t xTicksToDelay ); + +void xTaskNotifyGive(TaskHandle_t task); + +TaskHandle_t xTaskGetCurrentTaskHandle(void); + +BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, uint32_t *value, TickType_t wait_time ); + +BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pvTaskCode, + const char * const pcName, + const uint32_t usStackDepth, + void * const pvParameters, + UBaseType_t uxPriority, + TaskHandle_t * const pvCreatedTask, + const BaseType_t xCoreID); + +void xTaskCreate(TaskFunction_t pvTaskCode, const char * const pcName, const uint32_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pvCreatedTask); + +TickType_t xTaskGetTickCount( void ); + +void vQueueDelete( QueueHandle_t xQueue ); + +QueueHandle_t xSemaphoreCreateBinary(void); + +QueueHandle_t xSemaphoreCreateMutex(void); + +BaseType_t xSemaphoreGive( QueueHandle_t xQueue); + +BaseType_t xSemaphoreTake( QueueHandle_t xQueue, TickType_t pvTask ); + +void vTaskDelete(TaskHandle_t *task); + +QueueHandle_t xQueueCreate( uint32_t uxQueueLength, + uint32_t uxItemSize ); + +uint32_t xQueueSend(QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait); + +uint32_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait); diff --git a/components/mdns/host_test/components/freertos_linux/queue_unique_ptr.cpp b/components/mdns/host_test/components/freertos_linux/queue_unique_ptr.cpp new file mode 100644 index 0000000000..60c4a8a285 --- /dev/null +++ b/components/mdns/host_test/components/freertos_linux/queue_unique_ptr.cpp @@ -0,0 +1,51 @@ +// Copyright 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. + +#include "queue_unique_ptr.hpp" +#include +#include +#include +#include + +extern "C" void * create_q(void) +{ + auto * q = new QueueMock>(); + return q; +} + +extern "C" void destroy_q(void* q) +{ + auto * queue = static_cast> *>(q); + delete(queue); +} + +extern "C" bool send_q(void* q, uint8_t *data, size_t len) +{ + auto v = std::make_unique>(len); + v->assign(data, data+len); + auto queue = static_cast> *>(q); + queue->send(std::move(v)); + return true; +} + +extern "C" bool recv_q(void* q, uint8_t *data, size_t len, uint32_t ms) +{ + auto queue = static_cast> *>(q); + auto v = queue->receive(ms); + if (v == nullptr) { + return false; + } + memcpy(data, (void *)v->data(), len); + return true; +} diff --git a/components/mdns/host_test/components/freertos_linux/queue_unique_ptr.hpp b/components/mdns/host_test/components/freertos_linux/queue_unique_ptr.hpp new file mode 100644 index 0000000000..fe722b97f0 --- /dev/null +++ b/components/mdns/host_test/components/freertos_linux/queue_unique_ptr.hpp @@ -0,0 +1,55 @@ +// Copyright 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. + +#pragma once + +#include +#include +#include +#include +#include +#include + +template +class QueueMock +{ +public: + QueueMock(void): q(), m(), c() {} + ~QueueMock(void) {} + +void send(std::unique_ptr t) +{ + std::lock_guard lock(m); + q.push(std::move(t)); + c.notify_one(); +} + +std::unique_ptr receive(uint32_t ms) +{ + std::unique_lock lock(m); + while(q.empty()) { + if (c.wait_for(lock, std::chrono::milliseconds(ms)) == std::cv_status::timeout) { + return nullptr; + } + } + std::unique_ptr val = std::move(q.front()); + q.pop(); + return val; +} + +private: + std::queue> q; + mutable std::mutex m; + std::condition_variable c; +}; diff --git a/components/mdns/host_test/main/CMakeLists.txt b/components/mdns/host_test/main/CMakeLists.txt new file mode 100644 index 0000000000..8d5202d647 --- /dev/null +++ b/components/mdns/host_test/main/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register(SRCS "main.c" + INCLUDE_DIRS + "." + REQUIRES mdns) diff --git a/components/mdns/host_test/main/main.c b/components/mdns/host_test/main/main.c new file mode 100644 index 0000000000..f3883b8c35 --- /dev/null +++ b/components/mdns/host_test/main/main.c @@ -0,0 +1,59 @@ +#include +#include "mdns.h" +#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +static const char *TAG = "mdns-test"; + +static void query_mdns_host(const char * host_name) +{ + ESP_LOGI(TAG, "Query A: %s.local", host_name); + + struct esp_ip4_addr addr; + addr.addr = 0; + + esp_err_t err = mdns_query_a(host_name, 2000, &addr); + if(err){ + if(err == ESP_ERR_NOT_FOUND){ + ESP_LOGW(TAG, "%x: Host was not found!", (err)); + return; + } + ESP_LOGE(TAG, "Query Failed: %x", (err)); + return; + } + + ESP_LOGI(TAG, "Query A: %s.local resolved to: " IPSTR, host_name, IP2STR(&addr)); +} + +int main(int argc , char *argv[]) +{ + + setvbuf(stdout, NULL, _IONBF, 0); + const esp_netif_inherent_config_t base_cg = { .if_key = "WIFI_STA_DEF", .if_desc = "eth2" }; + esp_netif_config_t cfg = { .base = &base_cg }; + esp_netif_t *sta = esp_netif_new(&cfg); + + mdns_init(); + + mdns_hostname_set("myesp"); + ESP_LOGI(TAG, "mdns hostname set to: [%s]", "myesp"); + //set default mDNS instance name + mdns_instance_name_set("myesp-inst"); + //structure with TXT records + mdns_txt_item_t serviceTxtData[3] = { + {"board","esp32"}, + {"u","user"}, + {"p","password"} + }; + vTaskDelay(1000); + ESP_ERROR_CHECK(mdns_service_add("myesp-service2", "_http", "_tcp", 80, serviceTxtData, 3)); + vTaskDelay(2000); + + query_mdns_host("david-comp"); + vTaskDelay(2000); + esp_netif_destroy(sta); + mdns_free(); + ESP_LOGI(TAG, "Exit"); + return 0; +} diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index 7089eabe6a..4bb288d417 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -75,10 +75,13 @@ typedef struct mdns_result_s { struct mdns_result_s * next; /*!< next result, or NULL for the last result in the list */ mdns_if_t tcpip_if; /*!< interface index */ + uint32_t ttl; /*!< time to live */ mdns_ip_protocol_t ip_protocol; /*!< ip_protocol type of the interface (v4/v6) */ // PTR char * instance_name; /*!< instance name */ + char * service_type; /*!< service type */ + char * proto; /*!< srevice protocol */ // SRV char * hostname; /*!< hostname */ uint16_t port; /*!< service port */ @@ -90,6 +93,8 @@ typedef struct mdns_result_s { mdns_ip_addr_t * addr; /*!< linked list of IP addresses found */ } mdns_result_t; +typedef void (*mdns_query_notify_t)(mdns_search_once_t *search); + /** * @brief Initialize mDNS on given interface * @@ -519,11 +524,13 @@ bool mdns_query_async_get_results(mdns_search_once_t* search, uint32_t timeout, * @param type type of query (MDNS_TYPE_*) * @param timeout time in milliseconds during which mDNS query is active * @param max_results maximum results to be collected + * @param notifier Notification function to be called when the result is ready, can be NULL * * @return mdns_search_once_s pointer to new search object if query initiated successfully. * NULL otherwise. */ -mdns_search_once_t* mdns_query_async_new(const char * name, const char * service_type, const char * proto, uint16_t type, uint32_t timeout, size_t max_results); +mdns_search_once_t *mdns_query_async_new(const char *name, const char *service_type, const char *proto, uint16_t type, + uint32_t timeout, size_t max_results, mdns_query_notify_t notifier); /** * @brief Query mDNS for host or service diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index ea69afccc7..417b01fe0f 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -41,10 +41,16 @@ static SemaphoreHandle_t _mdns_service_semaphore = NULL; static void _mdns_search_finish_done(void); static mdns_search_once_t * _mdns_search_find_from(mdns_search_once_t * search, mdns_name_t * name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); -static void _mdns_search_result_add_ip(mdns_search_once_t * search, const char * hostname, esp_ip_addr_t * ip, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); -static void _mdns_search_result_add_srv(mdns_search_once_t * search, const char * hostname, uint16_t port, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); -static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_item_t * txt, uint8_t *txt_value_len, size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); -static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, const char * instance, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +static void _mdns_search_result_add_ip(mdns_search_once_t * search, const char * hostname, esp_ip_addr_t * ip, + mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl); +static void _mdns_search_result_add_srv(mdns_search_once_t *search, const char *hostname, uint16_t port, + mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl); +static void _mdns_search_result_add_txt(mdns_search_once_t *search, mdns_txt_item_t *txt, uint8_t *txt_value_len, + size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, + uint32_t ttl); +static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, const char * instance, + const char * service_type, const char * proto, mdns_if_t tcpip_if, + mdns_ip_protocol_t ip_protocol, uint32_t ttl); static bool _mdns_append_host_list_in_services(mdns_out_answer_t ** destination, mdns_srv_item_t * services[], size_t services_len, bool flush, bool bye); static bool _mdns_append_host_list(mdns_out_answer_t ** destination, bool flush, bool bye); static void _mdns_remap_self_service_hostname(const char *old_hostname, const char *new_hostname); @@ -178,7 +184,7 @@ static mdns_srv_item_t * _mdns_get_service_item(const char * service, const char static mdns_host_item_t * mdns_get_host_item(const char * hostname) { - if (strcasecmp(hostname, _mdns_server->hostname) == 0) { + if (hostname == NULL || strcasecmp(hostname, _mdns_server->hostname) == 0) { return &_mdns_self_host; } mdns_host_item_t * host = _mdns_host_list; @@ -3162,7 +3168,8 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) continue;//error } if (search_result) { - _mdns_search_result_add_ptr(search_result, name->host, packet->tcpip_if, packet->ip_protocol); + _mdns_search_result_add_ptr(search_result, name->host, name->service, name->proto, + packet->tcpip_if, packet->ip_protocol, ttl); } else if ((discovery || ours) && !name->sub && _mdns_name_is_ours(name)) { if (discovery) { service = _mdns_get_service_item(name->service, name->proto, NULL); @@ -3189,7 +3196,8 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) result = result->next; } if (!result) { - result = _mdns_search_result_add_ptr(search_result, name->host, packet->tcpip_if, packet->ip_protocol); + result = _mdns_search_result_add_ptr(search_result, name->host, name->service, name->proto, + packet->tcpip_if, packet->ip_protocol, ttl); if (!result) { continue;//error } @@ -3210,7 +3218,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) result->hostname = strdup(name->host); } } else { - _mdns_search_result_add_srv(search_result, name->host, port, packet->tcpip_if, packet->ip_protocol); + _mdns_search_result_add_srv(search_result, name->host, port, packet->tcpip_if, packet->ip_protocol, ttl); } } else if (ours) { if (parsed_packet->questions && !parsed_packet->probe) { @@ -3285,7 +3293,8 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) result = result->next; } if (!result) { - result = _mdns_search_result_add_ptr(search_result, name->host, packet->tcpip_if, packet->ip_protocol); + result = _mdns_search_result_add_ptr(search_result, name->host, name->service, name->proto, + packet->tcpip_if, packet->ip_protocol, ttl); if (!result) { continue;//error } @@ -3301,7 +3310,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) } else { _mdns_result_txt_create(data_ptr, data_len, &txt, &txt_value_len, &txt_count); if (txt_count) { - _mdns_search_result_add_txt(search_result, txt, txt_value_len, txt_count, packet->tcpip_if, packet->ip_protocol); + _mdns_search_result_add_txt(search_result, txt, txt_value_len, txt_count, packet->tcpip_if, packet->ip_protocol, ttl); } } } else if (ours) { @@ -3335,7 +3344,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) if (search_result) { //check for more applicable searches (PTR & A/AAAA at the same time) while (search_result) { - _mdns_search_result_add_ip(search_result, name->host, &ip6, packet->tcpip_if, packet->ip_protocol); + _mdns_search_result_add_ip(search_result, name->host, &ip6, packet->tcpip_if, packet->ip_protocol, ttl); search_result = _mdns_search_find_from(search_result->next, name, type, packet->tcpip_if, packet->ip_protocol); } } else if (ours) { @@ -3385,7 +3394,7 @@ void mdns_parse_packet(mdns_rx_packet_t * packet) if (search_result) { //check for more applicable searches (PTR & A/AAAA at the same time) while (search_result) { - _mdns_search_result_add_ip(search_result, name->host, &ip, packet->tcpip_if, packet->ip_protocol); + _mdns_search_result_add_ip(search_result, name->host, &ip, packet->tcpip_if, packet->ip_protocol, ttl); search_result = _mdns_search_find_from(search_result->next, name, type, packet->tcpip_if, packet->ip_protocol); } } else if (ours) { @@ -3592,7 +3601,8 @@ static void _mdns_search_free(mdns_search_once_t * search) /** * @brief Allocate new search structure */ -static mdns_search_once_t * _mdns_search_init(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, uint8_t max_results) +static mdns_search_once_t *_mdns_search_init(const char *name, const char *service, const char *proto, uint16_t type, + uint32_t timeout, uint8_t max_results, mdns_query_notify_t notifier) { mdns_search_once_t * search = (mdns_search_once_t *)malloc(sizeof(mdns_search_once_t)); if (!search) { @@ -3639,6 +3649,7 @@ static mdns_search_once_t * _mdns_search_init(const char * name, const char * se search->state = SEARCH_INIT; search->sent_at = 0; search->started_at = xTaskGetTickCount() * portTICK_PERIOD_MS; + search->notifier = notifier; search->next = NULL; return search; @@ -3651,6 +3662,9 @@ static void _mdns_search_finish(mdns_search_once_t * search) { search->state = SEARCH_OFF; queueDetach(mdns_search_once_t, _mdns_server->search_once, search); + if (search->notifier) { + search->notifier(search); + } xSemaphoreGive(search->done_semaphore); } @@ -3699,6 +3713,11 @@ static mdns_ip_addr_t * _mdns_result_addr_create_ip(esp_ip_addr_t * ip) return a; } +static inline void _mdns_result_update_ttl(mdns_result_t * r, uint32_t ttl) +{ + r->ttl = r->ttl < ttl ? r->ttl : ttl; +} + /** * @brief Chain new IP to search result */ @@ -3727,7 +3746,8 @@ static void _mdns_result_add_ip(mdns_result_t * r, esp_ip_addr_t * ip) /** * @brief Called from parser to add A/AAAA data to search result */ -static void _mdns_search_result_add_ip(mdns_search_once_t * search, const char * hostname, esp_ip_addr_t * ip, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +static void _mdns_search_result_add_ip(mdns_search_once_t * search, const char * hostname, esp_ip_addr_t * ip, + mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl) { mdns_result_t * r = NULL; mdns_ip_addr_t * a = NULL; @@ -3739,6 +3759,7 @@ static void _mdns_search_result_add_ip(mdns_search_once_t * search, const char * while (r) { if (r->tcpip_if == tcpip_if && r->ip_protocol == ip_protocol) { _mdns_result_add_ip(r, ip); + _mdns_result_update_ttl(r, ttl); return; } r = r->next; @@ -3758,18 +3779,21 @@ static void _mdns_search_result_add_ip(mdns_search_once_t * search, const char * return; } a->next = r->addr; + r->hostname = strdup(hostname); r->addr = a; r->tcpip_if = tcpip_if; r->ip_protocol = ip_protocol; r->next = search->result; + r->ttl = ttl; search->result = r; search->num_results++; } - } else if (search->type == MDNS_TYPE_PTR) { + } else if (search->type == MDNS_TYPE_PTR || search->type == MDNS_TYPE_SRV) { r = search->result; while (r) { if (r->tcpip_if == tcpip_if && r->ip_protocol == ip_protocol && !_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { _mdns_result_add_ip(r, ip); + _mdns_result_update_ttl(r, ttl); break; } r = r->next; @@ -3780,11 +3804,14 @@ static void _mdns_search_result_add_ip(mdns_search_once_t * search, const char * /** * @brief Called from parser to add PTR data to search result */ -static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, const char * instance, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, const char * instance, + const char * service_type, const char * proto, mdns_if_t tcpip_if, + mdns_ip_protocol_t ip_protocol, uint32_t ttl) { mdns_result_t * r = search->result; while (r) { if (r->tcpip_if == tcpip_if && r->ip_protocol == ip_protocol && !_str_null_or_empty(r->instance_name) && !strcasecmp(instance, r->instance_name)) { + _mdns_result_update_ttl(r, ttl); return r; } r = r->next; @@ -3798,6 +3825,8 @@ static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, memset(r, 0 , sizeof(mdns_result_t)); r->instance_name = strdup(instance); + r->service_type = strdup(service_type); + r->proto = strdup(proto); if (!r->instance_name) { free(r); return NULL; @@ -3805,6 +3834,7 @@ static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, r->tcpip_if = tcpip_if; r->ip_protocol = ip_protocol; + r->ttl = ttl; r->next = search->result; search->result = r; search->num_results++; @@ -3816,11 +3846,13 @@ static mdns_result_t * _mdns_search_result_add_ptr(mdns_search_once_t * search, /** * @brief Called from parser to add SRV data to search result */ -static void _mdns_search_result_add_srv(mdns_search_once_t * search, const char * hostname, uint16_t port, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +static void _mdns_search_result_add_srv(mdns_search_once_t *search, const char *hostname, uint16_t port, + mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl) { mdns_result_t * r = search->result; while (r) { if (r->tcpip_if == tcpip_if && r->ip_protocol == ip_protocol && !_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { + _mdns_result_update_ttl(r, ttl); return; } r = r->next; @@ -3838,9 +3870,15 @@ static void _mdns_search_result_add_srv(mdns_search_once_t * search, const char free(r); return; } + if (search->instance) { + r->instance_name = strdup(search->instance); + } + r->service_type = strdup(search->service); + r->proto = strdup(search->proto); r->port = port; r->tcpip_if = tcpip_if; r->ip_protocol = ip_protocol; + r->ttl = ttl; r->next = search->result; search->result = r; search->num_results++; @@ -3850,7 +3888,9 @@ static void _mdns_search_result_add_srv(mdns_search_once_t * search, const char /** * @brief Called from parser to add TXT data to search result */ -static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_item_t * txt, uint8_t *txt_value_len, size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +static void _mdns_search_result_add_txt(mdns_search_once_t *search, mdns_txt_item_t *txt, uint8_t *txt_value_len, + size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, + uint32_t ttl) { mdns_result_t * r = search->result; while (r) { @@ -3861,6 +3901,7 @@ static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_it r->txt = txt; r->txt_value_len = txt_value_len; r->txt_count = txt_count; + _mdns_result_update_ttl(r, ttl); return; } r = r->next; @@ -3878,6 +3919,7 @@ static void _mdns_search_result_add_txt(mdns_search_once_t * search, mdns_txt_it r->txt_count = txt_count; r->tcpip_if = tcpip_if; r->ip_protocol = ip_protocol; + r->ttl = ttl; r->next = search->result; search->result = r; search->num_results++; @@ -3906,12 +3948,12 @@ static mdns_search_once_t * _mdns_search_find_from(mdns_search_once_t * s, mdns_ if (type == MDNS_TYPE_A || type == MDNS_TYPE_AAAA) { if ((s->type == MDNS_TYPE_ANY && s->service != NULL) - || (s->type != MDNS_TYPE_ANY && s->type != type && s->type != MDNS_TYPE_PTR)) + || (s->type != MDNS_TYPE_ANY && s->type != type && s->type != MDNS_TYPE_PTR && s->type != MDNS_TYPE_SRV)) { s = s->next; continue; } - if (s->type != MDNS_TYPE_PTR) { + if (s->type != MDNS_TYPE_PTR && s->type != MDNS_TYPE_SRV) { if (!strcasecmp(name->host, s->instance)) { return s; } @@ -4898,8 +4940,7 @@ esp_err_t mdns_instance_name_set(const char * instance) esp_err_t mdns_service_add_for_host(const char * instance, const char * service, const char * proto, const char * hostname, uint16_t port, mdns_txt_item_t txt[], size_t num_items) { - if (!_mdns_server || _str_null_or_empty(service) || _str_null_or_empty(proto) || _str_null_or_empty(hostname) || - !port) { + if (!_mdns_server || _str_null_or_empty(service) || _str_null_or_empty(proto) || !port) { return ESP_ERR_INVALID_ARG; } @@ -4959,7 +5000,7 @@ esp_err_t mdns_service_add_for_host(const char * instance, const char * service, esp_err_t mdns_service_add(const char * instance, const char * service, const char * proto, uint16_t port, mdns_txt_item_t txt[], size_t num_items) { - if (!_mdns_server || _str_null_or_empty(_mdns_server->hostname)) { + if (!_mdns_server) { return ESP_ERR_INVALID_STATE; } return mdns_service_add_for_host(instance, service, proto, _mdns_server->hostname, port, txt, num_items); @@ -5267,6 +5308,8 @@ void mdns_query_results_free(mdns_result_t * results) free((char *)(r->hostname)); free((char *)(r->instance_name)); + free((char *)(r->service_type)); + free((char *)(r->proto)); for (size_t i=0; itxt_count; i++) { free((char *)(r->txt[i].key)); @@ -5311,7 +5354,8 @@ bool mdns_query_async_get_results(mdns_search_once_t* search, uint32_t timeout, return false; } -mdns_search_once_t* mdns_query_async_new(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, size_t max_results) +mdns_search_once_t *mdns_query_async_new(const char *name, const char *service, const char *proto, uint16_t type, + uint32_t timeout, size_t max_results, mdns_query_notify_t notifier) { mdns_search_once_t *search = NULL; @@ -5319,7 +5363,7 @@ mdns_search_once_t* mdns_query_async_new(const char * name, const char * service return NULL; } - search = _mdns_search_init(name, service, proto, type, timeout, max_results); + search = _mdns_search_init(name, service, proto, type, timeout, max_results, notifier); if (!search) { return NULL; } @@ -5346,7 +5390,7 @@ esp_err_t mdns_query(const char * name, const char * service, const char * proto return ESP_ERR_INVALID_ARG; } - search = _mdns_search_init(name, service, proto, type, timeout, max_results); + search = _mdns_search_init(name, service, proto, type, timeout, max_results, NULL); if (!search) { return ESP_ERR_NO_MEM; } diff --git a/components/mdns/mdns_networking.c b/components/mdns/mdns_networking_lwip.c similarity index 100% rename from components/mdns/mdns_networking.c rename to components/mdns/mdns_networking_lwip.c diff --git a/components/mdns/mdns_networking_socket.c b/components/mdns/mdns_networking_socket.c new file mode 100644 index 0000000000..55533a9f7f --- /dev/null +++ b/components/mdns/mdns_networking_socket.c @@ -0,0 +1,504 @@ +// Copyright 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. + +/** + * @brief MDNS Server Networking module implemented using BSD sockets + */ + +#include +#include "esp_event.h" +#include "mdns_networking.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "esp_log.h" + +#if defined(CONFIG_IDF_TARGET_LINUX) +#include +#include +#endif + +extern mdns_server_t * _mdns_server; + +static const char *TAG = "MDNS_Networking"; +static bool s_run_sock_recv_task = false; +static int create_socket(esp_netif_t *netif); +static int join_mdns_multicast_group(int sock, esp_netif_t *netif, mdns_ip_protocol_t ip_protocol); + +#if defined(CONFIG_IDF_TARGET_LINUX) +// Need to define packet buffer struct on linux +struct pbuf { + struct pbuf * next; + void * payload; + size_t tot_len; + size_t len; +}; +#else +// Compatibility define to access sock-addr struct the same way for lwip and linux +#define s6_addr32 un.u32_addr +#endif // CONFIG_IDF_TARGET_LINUX + +static void delete_socket(int sock) +{ + close(sock); +} + +static struct udp_pcb* sock_to_pcb(int sock) +{ + if (sock < 0) { + return NULL; + } + // Note: sock=0 is a valid descriptor, so save it as +1 ("1" is a valid pointer) + intptr_t sock_plus_one = sock + 1; + return (struct udp_pcb*)sock_plus_one; +} + +static int pcb_to_sock(struct udp_pcb* pcb) +{ + if (pcb == NULL) { + return -1; + } + intptr_t sock_plus_one = (intptr_t)pcb; + return sock_plus_one - 1; +} + +void* _mdns_get_packet_data(mdns_rx_packet_t *packet) +{ + return packet->pb->payload; +} + +size_t _mdns_get_packet_len(mdns_rx_packet_t *packet) +{ + return packet->pb->len; +} + +void _mdns_packet_free(mdns_rx_packet_t *packet) +{ + free(packet->pb->payload); + free(packet->pb); + free(packet); +} + +esp_err_t _mdns_pcb_deinit(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + struct udp_pcb * pcb = _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb; + _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb = NULL; + if (_mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].pcb == NULL && + _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].pcb == NULL) { + // if the interface for both protocol uninitialized, close the interface socket + int sock = pcb_to_sock(pcb); + if (sock >= 0) { + delete_socket(sock); + } + } + + for (int i=0; iinterfaces[i].pcbs[j].pcb) + // If any of the interfaces/protocol initialized + return ESP_OK; + } + } + + // no interface alive, stop the rx task + s_run_sock_recv_task = false; + vTaskDelay(pdMS_TO_TICKS(500)); + return ESP_OK; +} + +#if defined(CONFIG_IDF_TARGET_LINUX) +#ifdef CONFIG_LWIP_IPV6 +static char* inet6_ntoa_r(struct in6_addr addr, char* ptr, size_t size) +{ + inet_ntop(AF_INET6, &(addr.s6_addr32[0]), ptr, size); + return ptr; +} +#endif // CONFIG_LWIP_IPV6 +static char* inet_ntoa_r(struct in_addr addr, char* ptr, size_t size) +{ + char * res = inet_ntoa(addr); + if (res && strlen(res) < size) { + strcpy(ptr, res); + } + return res; +} +#endif // CONFIG_IDF_TARGET_LINUX + +static inline char* get_string_address(struct sockaddr_storage *source_addr) +{ + static char address_str[40]; // 40=(8*4+7+term) is the max size of ascii IPv6 addr "XXXX:XX...XX:XXXX" + char *res = NULL; + // Convert ip address to string + if (source_addr->ss_family == PF_INET) { + res = inet_ntoa_r(((struct sockaddr_in *)source_addr)->sin_addr, address_str, sizeof(address_str)); + } +#ifdef CONFIG_LWIP_IPV6 + else if (source_addr->ss_family == PF_INET6) { + res = inet6_ntoa_r(((struct sockaddr_in6 *)source_addr)->sin6_addr, address_str, sizeof(address_str)); + } +#endif + if (!res) { + address_str[0] = '\0'; // Returns empty string if conversion didn't succeed + } + return address_str; +} + + +static inline size_t espaddr_to_inet(const esp_ip_addr_t *addr, const uint16_t port, const mdns_ip_protocol_t ip_protocol, struct sockaddr_storage *in_addr) +{ + size_t ss_addr_len = 0; + memset(in_addr, 0, sizeof(struct sockaddr_storage)); + if (ip_protocol == MDNS_IP_PROTOCOL_V4 && addr->type == ESP_IPADDR_TYPE_V4) { + in_addr->ss_family = PF_INET; +#if !defined(CONFIG_IDF_TARGET_LINUX) + in_addr->s2_len = sizeof(struct sockaddr_in); +#endif + ss_addr_len = sizeof(struct sockaddr_in); + struct sockaddr_in *in_addr_ip4 = (struct sockaddr_in *) in_addr; + in_addr_ip4->sin_port = port; + in_addr_ip4->sin_addr.s_addr = addr->u_addr.ip4.addr; + } +#if CONFIG_LWIP_IPV6 + else if (ip_protocol == MDNS_IP_PROTOCOL_V6 && addr->type == ESP_IPADDR_TYPE_V6) { + memset(in_addr, 0, sizeof(struct sockaddr_storage)); + in_addr->ss_family = PF_INET6; +#if !defined(CONFIG_IDF_TARGET_LINUX) + in_addr->s2_len = sizeof(struct sockaddr_in6); +#endif + ss_addr_len = sizeof(struct sockaddr_in6); + struct sockaddr_in6 * in_addr_ip6 = (struct sockaddr_in6 *)in_addr; + uint32_t *u32_addr = in_addr_ip6->sin6_addr.s6_addr32; + in_addr_ip6->sin6_port = port; + u32_addr[0] = addr->u_addr.ip6.addr[0]; + u32_addr[1] = addr->u_addr.ip6.addr[1]; + u32_addr[2] = addr->u_addr.ip6.addr[2]; + u32_addr[3] = addr->u_addr.ip6.addr[3]; + } +#endif // CONFIG_LWIP_IPV6 + return ss_addr_len; +} + +size_t _mdns_udp_pcb_write(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const esp_ip_addr_t *ip, uint16_t port, uint8_t * data, size_t len) +{ + int sock = pcb_to_sock(_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb); + if (sock < 0) { + return 0; + } + struct sockaddr_storage in_addr; + size_t ss_size = espaddr_to_inet(ip, htons(port), ip_protocol, &in_addr); + if (!ss_size) { + ESP_LOGE(TAG, "espaddr_to_inet() failed: Mismatch of IP protocols"); + return 0; + } + ESP_LOGD(TAG, "[sock=%d]: Sending to IP %s port %d", sock, get_string_address(&in_addr), port); + ssize_t actual_len = sendto(sock, data, len, 0, (struct sockaddr *)&in_addr, ss_size); + if (actual_len < 0) { + ESP_LOGE(TAG, "[sock=%d]: _mdns_udp_pcb_write sendto() has failed\n error=%d: %s", sock, errno, strerror(errno)); + } + return actual_len; +} + +static inline void inet_to_espaddr(const struct sockaddr_storage *in_addr, esp_ip_addr_t *addr, uint16_t *port) +{ + if (in_addr->ss_family == PF_INET) { + struct sockaddr_in * in_addr_ip4 = (struct sockaddr_in *)in_addr; + memset(addr, 0, sizeof(esp_ip_addr_t)); + *port = in_addr_ip4->sin_port; + addr->u_addr.ip4.addr = in_addr_ip4->sin_addr.s_addr; + addr->type = ESP_IPADDR_TYPE_V4; + } +#if CONFIG_LWIP_IPV6 + else if (in_addr->ss_family == PF_INET6) { + struct sockaddr_in6 * in_addr_ip6 = (struct sockaddr_in6 *)in_addr; + memset(addr, 0, sizeof(esp_ip_addr_t)); + *port = in_addr_ip6->sin6_port; + uint32_t *u32_addr = in_addr_ip6->sin6_addr.s6_addr32; + if (u32_addr[0] == 0 && u32_addr[1] == 0 && u32_addr[2] == esp_netif_htonl(0x0000FFFFUL)) { + // Mapped IPv4 address, convert directly to IPv4 + addr->type = ESP_IPADDR_TYPE_V4; + addr->u_addr.ip4.addr = u32_addr[3]; + } else { + addr->type = ESP_IPADDR_TYPE_V6; + addr->u_addr.ip6.addr[0] = u32_addr[0]; + addr->u_addr.ip6.addr[1] = u32_addr[1]; + addr->u_addr.ip6.addr[2] = u32_addr[2]; + addr->u_addr.ip6.addr[3] = u32_addr[3]; + } + } +#endif // CONFIG_LWIP_IPV6 +} + +void sock_recv_task(void* arg) +{ + while (s_run_sock_recv_task) { + struct timeval tv = { + .tv_sec = 1, + .tv_usec = 0, + }; + fd_set rfds; + FD_ZERO(&rfds); + int max_sock = -1; + for (int i=0; iinterfaces[i].pcbs[j].pcb); + if (sock >= 0) { + FD_SET(sock, &rfds); + max_sock = MAX(max_sock, sock); + } + } + } + if (max_sock < 0) { + vTaskDelay(pdMS_TO_TICKS(1000)); + ESP_LOGI(TAG, "No sock!"); + continue; + } + + int s = select(max_sock + 1, &rfds, NULL, NULL, &tv); + if (s < 0) { + ESP_LOGE(TAG, "Select failed: errno %d", errno); + break; + } else if (s > 0) { + for (int tcpip_if=0; tcpip_ifinterfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].pcb); + if (sock < 0) { + sock = pcb_to_sock(_mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].pcb); + } + if (sock < 0) { + continue; + } + if (FD_ISSET(sock, &rfds)) { + static char recvbuf[MDNS_MAX_PACKET_SIZE]; + uint16_t port = 0; + + struct sockaddr_storage raddr; // Large enough for both IPv4 or IPv6 + socklen_t socklen = sizeof(struct sockaddr_storage); + esp_ip_addr_t addr = {0}; + int len = recvfrom(sock, recvbuf, sizeof(recvbuf), 0, + (struct sockaddr *) &raddr, &socklen); + if (len < 0) { + ESP_LOGE(TAG, "multicast recvfrom failed: errno %d", errno); + break; + } + ESP_LOGD(TAG, "[sock=%d]: Received from IP:%s", sock, get_string_address(&raddr)); + ESP_LOG_BUFFER_HEXDUMP(TAG, recvbuf, len, ESP_LOG_VERBOSE); + inet_to_espaddr(&raddr, &addr, &port); + + // Allocate the packet structure and pass it to the mdns main engine + mdns_rx_packet_t *packet = (mdns_rx_packet_t *) calloc(1, sizeof(mdns_rx_packet_t)); + struct pbuf *packet_pbuf = calloc(1, sizeof(struct pbuf)); + uint8_t *buf = malloc(len); + if (packet == NULL || packet_pbuf == NULL || buf == NULL ) { + free(buf); + free(packet_pbuf); + free(packet); + HOOK_MALLOC_FAILED; + ESP_LOGE(TAG, "Failed to allocate the mdns packet"); + continue; + } + memcpy(buf, recvbuf, len); + packet_pbuf->next = NULL; + packet_pbuf->payload = buf; + packet_pbuf->tot_len = len; + packet_pbuf->len = len; + packet->tcpip_if = tcpip_if; + packet->pb = packet_pbuf; + packet->src_port = ntohs(port); + memcpy(&packet->src, &addr, sizeof(esp_ip_addr_t)); + // TODO(IDF-3651): Add the correct dest addr -- for mdns to decide multicast/unicast + // Currently it's enough to assume the packet is multicast and mdns to check the source port of the packet + memset(&packet->dest, 0, sizeof(esp_ip_addr_t)); + packet->multicast = 1; + packet->dest.type = packet->src.type; + packet->ip_protocol = + packet->src.type == ESP_IPADDR_TYPE_V4 ? MDNS_IP_PROTOCOL_V4 : MDNS_IP_PROTOCOL_V6; + if (!_mdns_server || !_mdns_server->action_queue || _mdns_send_rx_action(packet) != ESP_OK) { + ESP_LOGE(TAG, "_mdns_send_rx_action failed!"); + free(packet->pb->payload); + free(packet->pb); + free(packet); + } + } + } + } + } + vTaskDelete(NULL); +} + +static void mdns_networking_init(void) +{ + if (s_run_sock_recv_task == false) { + s_run_sock_recv_task = true; + xTaskCreate( sock_recv_task, "mdns recv task", 3*1024, NULL, 5, NULL ); + } +} + +static struct udp_pcb* create_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + if (_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb) { + return _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb; + } + mdns_ip_protocol_t other_ip_proto = ip_protocol==MDNS_IP_PROTOCOL_V4?MDNS_IP_PROTOCOL_V6:MDNS_IP_PROTOCOL_V4; + esp_netif_t *netif = _mdns_get_esp_netif(tcpip_if); + if (_mdns_server->interfaces[tcpip_if].pcbs[other_ip_proto].pcb) { + struct udp_pcb* other_pcb = _mdns_server->interfaces[tcpip_if].pcbs[other_ip_proto].pcb; + int err = join_mdns_multicast_group(pcb_to_sock(other_pcb), netif, ip_protocol); + if (err < 0) { + ESP_LOGE(TAG, "Failed to add ipv6 multicast group for protocol %d", ip_protocol); + return NULL; + } + return other_pcb; + } + int sock = create_socket(netif); + if (sock < 0) { + ESP_LOGE(TAG, "Failed to create the socket!"); + return NULL; + } + int err = join_mdns_multicast_group(sock, netif, ip_protocol); + if (err < 0) { + ESP_LOGE(TAG, "Failed to add ipv6 multicast group for protocol %d", ip_protocol); + } + return sock_to_pcb(sock); +} + +esp_err_t _mdns_pcb_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + ESP_LOGI(TAG, "_mdns_pcb_init(tcpip_if=%d, ip_protocol=%d)", tcpip_if, ip_protocol); + _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb = create_pcb(tcpip_if, ip_protocol); + _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].failed_probes = 0; + + mdns_networking_init(); + return ESP_OK; +} + +static int create_socket(esp_netif_t *netif) +{ +#if CONFIG_LWIP_IPV6 + int sock = socket(PF_INET6, SOCK_DGRAM, 0); +#else + int sock = socket(PF_INET, SOCK_DGRAM, 0); +#endif + if (sock < 0) { + ESP_LOGE(TAG, "Failed to create socket. Error %d", errno); + return -1; + } + + int on = 1; + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) ) < 0) { + ESP_LOGE(TAG, "setsockopt SO_REUSEADDR: %s\n", strerror(errno)); + } + // Bind the socket to any address +#if CONFIG_LWIP_IPV6 + struct sockaddr_in6 saddr = { INADDR_ANY }; + saddr.sin6_family = AF_INET6; + saddr.sin6_port = htons(5353); + bzero(&saddr.sin6_addr.s6_addr, sizeof(saddr.sin6_addr.s6_addr)); + int err = bind(sock, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in6)); + if (err < 0) { + ESP_LOGE(TAG, "Failed to bind socket. Error %d", errno); + goto err; + } +#else + struct sockaddr_in saddr = { 0 }; + saddr.sin_family = AF_INET; + saddr.sin_port = htons(5353); + bzero(&saddr.sin_addr.s_addr, sizeof(saddr.sin_addr.s_addr)); + int err = bind(sock, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in)); + if (err < 0) { + ESP_LOGE(TAG, "Failed to bind socket. Error %d", errno); + goto err; + } +#endif // CONFIG_LWIP_IPV6 + struct ifreq ifr; + esp_netif_get_netif_impl_name(netif, ifr.ifr_name); + int ret = setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, (void*)&ifr, sizeof(struct ifreq)); + if (ret < 0) { + ESP_LOGE(TAG, "\"%s\" Unable to bind socket to specified interface: errno %d", esp_netif_get_desc(netif), errno); + goto err; + } + + return sock; + +err: + close(sock); + return -1; +} + +#if CONFIG_LWIP_IPV6 +static int socket_add_ipv6_multicast_group(int sock, esp_netif_t *netif) +{ + int ifindex = esp_netif_get_netif_impl_index(netif); + int err = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(ifindex)); + if (err < 0) { + ESP_LOGE(TAG, "Failed to set IPV6_MULTICAST_IF. Error %d", errno); + return err; + } + + struct ipv6_mreq v6imreq = { 0 }; + esp_ip_addr_t multi_addr = ESP_IP6ADDR_INIT(0x000002ff, 0, 0, 0xfb000000); + memcpy(&v6imreq.ipv6mr_multiaddr, &multi_addr.u_addr.ip6.addr, sizeof(v6imreq.ipv6mr_multiaddr)); + v6imreq.ipv6mr_interface = ifindex; + err = setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &v6imreq, sizeof(struct ipv6_mreq)); + if (err < 0) { + ESP_LOGE(TAG, "Failed to set IPV6_ADD_MEMBERSHIP. Error %d", errno); + return err; + } + return err; +} +#endif // CONFIG_LWIP_IPV6 + +static int socket_add_ipv4_multicast_group(int sock, esp_netif_t *netif) +{ + struct ip_mreq imreq = { 0 }; + int err = 0; + esp_netif_ip_info_t ip_info = { 0 }; + + if (esp_netif_get_ip_info(netif, &ip_info) != ESP_OK) { + ESP_LOGE(TAG, "Failed to esp_netif_get_ip_info()"); + goto err; + } + imreq.imr_interface.s_addr = ip_info.ip.addr; + + esp_ip_addr_t multicast_addr = ESP_IP4ADDR_INIT(224, 0, 0, 251); + imreq.imr_multiaddr.s_addr = multicast_addr.u_addr.ip4.addr; + + err = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imreq, sizeof(struct ip_mreq)); + if (err < 0) { + ESP_LOGE(TAG, "%d %s", sock, strerror(errno)); + ESP_LOGE(TAG, "Failed to set IP_ADD_MEMBERSHIP. Error %d", errno); + goto err; + } + + err: + return err; +} + +static int join_mdns_multicast_group(int sock, esp_netif_t *netif, mdns_ip_protocol_t ip_protocol) +{ + if (ip_protocol == MDNS_IP_PROTOCOL_V4) { + return socket_add_ipv4_multicast_group(sock, netif); + } +#if CONFIG_LWIP_IPV6 + if (ip_protocol == MDNS_IP_PROTOCOL_V6) { + return socket_add_ipv6_multicast_group(sock, netif); + } +#endif // CONFIG_LWIP_IPV6 + return -1; +} diff --git a/components/mdns/private_include/mdns_private.h b/components/mdns/private_include/mdns_private.h index 6931d4f5a7..059d1ad252 100644 --- a/components/mdns/private_include/mdns_private.h +++ b/components/mdns/private_include/mdns_private.h @@ -14,8 +14,10 @@ #ifndef MDNS_PRIVATE_H_ #define MDNS_PRIVATE_H_ +#include "sdkconfig.h" #include "mdns.h" #include "esp_task.h" +#include "esp_timer.h" //#define MDNS_ENABLE_DEBUG @@ -248,7 +250,6 @@ typedef struct mdns_parsed_record_s { typedef struct { mdns_if_t tcpip_if; mdns_ip_protocol_t ip_protocol; - //struct udp_pcb *pcb; esp_ip_addr_t src; uint16_t src_port; uint8_t multicast; @@ -364,6 +365,7 @@ typedef struct mdns_search_once_s { uint32_t started_at; uint32_t sent_at; uint32_t timeout; + mdns_query_notify_t notifier; SemaphoreHandle_t done_semaphore; uint16_t type; uint8_t max_results; diff --git a/components/mdns/test_afl_fuzz_host/mdns_di.h b/components/mdns/test_afl_fuzz_host/mdns_di.h index 4ed0e84cdd..12c0c56f77 100644 --- a/components/mdns/test_afl_fuzz_host/mdns_di.h +++ b/components/mdns/test_afl_fuzz_host/mdns_di.h @@ -8,13 +8,16 @@ void (*mdns_test_static_execute_action)(mdns_action_t *) = NULL; mdns_srv_item_t * (*mdns_test_static_mdns_get_service_item)(const char * service, const char * proto, const char *hostname) = NULL; -mdns_search_once_t * (*mdns_test_static_search_init)(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, uint8_t max_results) = NULL; +mdns_search_once_t *(*mdns_test_static_search_init)(const char *name, const char *service, const char *proto, + uint16_t type, uint32_t timeout, uint8_t max_results, + mdns_query_notify_t notifier) = NULL; esp_err_t (*mdns_test_static_send_search_action)(mdns_action_type_t type, mdns_search_once_t * search) = NULL; void (*mdns_test_static_search_free)(mdns_search_once_t * search) = NULL; static void _mdns_execute_action(mdns_action_t * action); static mdns_srv_item_t * _mdns_get_service_item(const char * service, const char * proto, const char *hostname); -static mdns_search_once_t * _mdns_search_init(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, uint8_t max_results); +static mdns_search_once_t *_mdns_search_init(const char *name, const char *service, const char *proto, uint16_t type, + uint32_t timeout, uint8_t max_results, mdns_query_notify_t notifier); static esp_err_t _mdns_send_search_action(mdns_action_type_t type, mdns_search_once_t * search); static void _mdns_search_free(mdns_search_once_t * search); @@ -44,7 +47,7 @@ esp_err_t mdns_test_send_search_action(mdns_action_type_t type, mdns_search_once mdns_search_once_t * mdns_test_search_init(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, uint8_t max_results) { - return mdns_test_static_search_init(name, service, proto, type, timeout, max_results); + return mdns_test_static_search_init(name, service, proto, type, timeout, max_results, NULL); } mdns_srv_item_t * mdns_test_mdns_get_service_item(const char * service, const char * proto) diff --git a/components/mdns/test_afl_fuzz_host/sdkconfig.h b/components/mdns/test_afl_fuzz_host/sdkconfig.h index 1b5997b648..e09b70b804 100644 --- a/components/mdns/test_afl_fuzz_host/sdkconfig.h +++ b/components/mdns/test_afl_fuzz_host/sdkconfig.h @@ -53,7 +53,7 @@ #define CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF 0 #define CONFIG_BTDM_CTRL_PINNED_TO_CORE 0 #define CONFIG_BTDM_BLE_SLEEP_CLOCK_ACCURACY_INDEX_EFF 1 -#define CONFIG_BT_RESERVE_DRAM 0x0 +#define CONFIG_BTDM_RESERVE_DRAM 0x0 #define CONFIG_COAP_MBEDTLS_PSK 1 #define CONFIG_COAP_LOG_DEFAULT_LEVEL 0 #define CONFIG_ADC_DISABLE_DAC 1 diff --git a/components/mqtt/host_test/mocks/include/freertos/portmacro.h b/components/mqtt/host_test/mocks/include/freertos/portmacro.h index 67ce5f06d5..1ff7b7c953 100644 --- a/components/mqtt/host_test/mocks/include/freertos/portmacro.h +++ b/components/mqtt/host_test/mocks/include/freertos/portmacro.h @@ -1,5 +1,5 @@ /* - * FreeRTOS Kernel V10.2.1 + * FreeRTOS Kernel V10.4.3 * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of diff --git a/components/newlib/CMakeLists.txt b/components/newlib/CMakeLists.txt index 4fa4856879..5e837b6cd8 100644 --- a/components/newlib/CMakeLists.txt +++ b/components/newlib/CMakeLists.txt @@ -6,6 +6,7 @@ endif() set(srcs "abort.c" + "assert.c" "heap.c" "locks.c" "poll.c" @@ -28,7 +29,7 @@ list(APPEND ldfragments "newlib.lf" "system_libs.lf") idf_component_register(SRCS "${srcs}" INCLUDE_DIRS "${include_dirs}" PRIV_INCLUDE_DIRS priv_include - PRIV_REQUIRES soc + PRIV_REQUIRES soc spi_flash LDFRAGMENTS "${ldfragments}") # Toolchain libraries require code defined in this component @@ -37,11 +38,12 @@ target_link_libraries(${COMPONENT_LIB} INTERFACE c m gcc "$ +#include +#include "esp_system.h" +#include "esp_spi_flash.h" +#include "soc/soc_memory_layout.h" + +#define ASSERT_STR "assert failed: " +#define CACHE_DISABLED_STR "" + +#if __XTENSA__ +#define INST_LEN 3 +#elif __riscv +#define INST_LEN 4 +#endif + +static inline void ra_to_str(char *addr) +{ + addr[0] = '0'; + addr[1] = 'x'; + itoa((uint32_t)(__builtin_return_address(0) - INST_LEN), addr + 2, 16); +} + +/* Overriding assert function so that whenever assert is called from critical section, + * it does not lead to a crash of its own. + */ +void __attribute__((noreturn)) __assert_func(const char *file, int line, const char *func, const char *expr) +{ +#if CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT + char buff[sizeof(ASSERT_STR) + 11 + 1] = ASSERT_STR; + + ra_to_str(&buff[sizeof(ASSERT_STR) - 1]); + + esp_system_abort(buff); +#else + char addr[11] = { 0 }; + char buff[200]; + char lbuf[5]; + uint32_t rem_len = sizeof(buff) - 1; + uint32_t off = 0; + + itoa(line, lbuf, 10); + + if (!spi_flash_cache_enabled()) { + if (esp_ptr_in_drom(file)) { + file = CACHE_DISABLED_STR; + } + + if (esp_ptr_in_drom(func)) { + ra_to_str(addr); + func = addr; + } + + if (esp_ptr_in_drom(expr)) { + expr = CACHE_DISABLED_STR; + } + } + + const char *str[] = {ASSERT_STR, func ? func : "\b", " ", file, ":", lbuf, " (", expr, ")"}; + + for (int i = 0; i < sizeof(str) / sizeof(str[0]); i++) { + uint32_t len = strlen(str[i]); + uint32_t cpy_len = MIN(len, rem_len); + memcpy(buff + off, str[i], cpy_len); + rem_len -= cpy_len; + off += cpy_len; + if (rem_len == 0) { + break; + } + } + buff[off] = '\0'; + esp_system_abort(buff); +#endif /* CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT */ +} + +void __attribute__((noreturn)) __assert(const char *file, int line, const char *failedexpr) +{ + __assert_func(file, line, NULL, failedexpr); +} + +/* No-op function, used to force linker to include these changes */ +void newlib_include_assert_impl(void) +{ +} diff --git a/components/newlib/component.mk b/components/newlib/component.mk index 3841d7b8e6..f633905a67 100644 --- a/components/newlib/component.mk +++ b/components/newlib/component.mk @@ -15,10 +15,12 @@ endif COMPONENT_PRIV_INCLUDEDIRS := priv_include COMPONENT_SRCDIRS := . port -# Forces the linker to include heap, syscalls, and pthread from this component, +# Forces the linker to include heap, syscalls, pthread, and assert from this component, # instead of the implementations provided by newlib. COMPONENT_ADD_LDFLAGS += -u newlib_include_heap_impl COMPONENT_ADD_LDFLAGS += -u newlib_include_syscalls_impl +COMPONENT_ADD_LDFLAGS += -u newlib_include_pthread_impl +COMPONENT_ADD_LDFLAGS += -u newlib_include_assert_impl COMPONENT_ADD_LDFRAGMENTS += newlib.lf system_libs.lf diff --git a/components/newlib/newlib.lf b/components/newlib/newlib.lf index 3d9a0ed14d..d92c04fb0f 100644 --- a/components/newlib/newlib.lf +++ b/components/newlib/newlib.lf @@ -3,4 +3,5 @@ archive: libnewlib.a entries: heap (noflash) abort (noflash) + assert (noflash) stdatomic (noflash) diff --git a/components/newlib/platform_include/assert.h b/components/newlib/platform_include/assert.h index 8522286148..39db39a6f0 100644 --- a/components/newlib/platform_include/assert.h +++ b/components/newlib/platform_include/assert.h @@ -19,6 +19,7 @@ #pragma once #include #include +#include #include_next @@ -31,16 +32,21 @@ */ #undef assert +/* __FILENAME__ points to the file name instead of path + filename + * e.g __FILE__ points to "/apps/test.c" where as __FILENAME__ points to "test.c" + */ +#define __FILENAME__ (__builtin_strrchr( "/" __FILE__, '/') + 1) + #if defined(NDEBUG) -# define assert(__e) ((void)(__e)) +#define assert(__e) ((void)(__e)) #elif CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT -#define assert(__e) __builtin_expect(!!(__e), 1) ? (void)0 : abort() +#define assert(__e) (__builtin_expect(!!(__e), 1) ? (void)0 : __assert_func(NULL, 0, NULL, NULL)) #else // !CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT -#define assert(__e) (__builtin_expect(!!(__e), 1) ? (void)0 : __assert_func (__FILE__, __LINE__, \ +#define assert(__e) (__builtin_expect(!!(__e), 1) ? (void)0 : __assert_func (__FILENAME__, __LINE__, \ __ASSERT_FUNC, #__e)) #endif diff --git a/components/newlib/syscalls.c b/components/newlib/syscalls.c index d6c3098592..e72fd14442 100644 --- a/components/newlib/syscalls.c +++ b/components/newlib/syscalls.c @@ -17,15 +17,16 @@ #include #include #include +#include #include #include #include #include "sdkconfig.h" #include "esp_rom_uart.h" -static int syscall_not_implemented(void) +static int syscall_not_implemented(struct _reent *r, ...) { - errno = ENOSYS; + __errno_r(r) = ENOSYS; return -1; } @@ -43,7 +44,7 @@ ssize_t _write_r_console(struct _reent *r, int fd, const void * data, size_t siz } return size; } - errno = EBADF; + __errno_r(r) = EBADF; return -1; } @@ -60,7 +61,19 @@ ssize_t _read_r_console(struct _reent *r, int fd, void * data, size_t size) } return received; } - errno = EBADF; + __errno_r(r) = EBADF; + return -1; +} + +static ssize_t _fstat_r_console(struct _reent *r, int fd, struct stat * st) +{ + if (fd == STDOUT_FILENO || fd == STDERR_FILENO) { + memset(st, 0, sizeof(*st)); + /* This needs to be set so that stdout and stderr are line buffered. */ + st->st_mode = S_IFCHR; + return 0; + } + __errno_r(r) = EBADF; return -1; } @@ -73,14 +86,18 @@ ssize_t _read_r(struct _reent *r, int fd, void * dst, size_t size) __attribute__((weak,alias("_read_r_console"))); ssize_t _write_r(struct _reent *r, int fd, const void * data, size_t size) __attribute__((weak,alias("_write_r_console"))); +int _fstat_r (struct _reent *r, int fd, struct stat *st) + __attribute__((weak,alias("_fstat_r_console"))); /* The aliases below are to "syscall_not_implemented", which * doesn't have the same signature as the original function. * Disable type mismatch warnings for this reason. */ +#if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wattribute-alias" +#endif int _open_r(struct _reent *r, const char * path, int flags, int mode) __attribute__((weak,alias("syscall_not_implemented"))); @@ -90,8 +107,6 @@ off_t _lseek_r(struct _reent *r, int fd, off_t size, int mode) __attribute__((weak,alias("syscall_not_implemented"))); int _fcntl_r(struct _reent *r, int fd, int cmd, int arg) __attribute__((weak,alias("syscall_not_implemented"))); -int _fstat_r(struct _reent *r, int fd, struct stat * st) - __attribute__((weak,alias("syscall_not_implemented"))); int _stat_r(struct _reent *r, const char * path, struct stat * st) __attribute__((weak,alias("syscall_not_implemented"))); int _link_r(struct _reent *r, const char* n1, const char* n2) @@ -105,8 +120,6 @@ int _isatty_r(struct _reent *r, int fd) /* These functions are not expected to be overridden */ -int system(const char* str) - __attribute__((alias("syscall_not_implemented"))); int _system_r(struct _reent *r, const char *str) __attribute__((alias("syscall_not_implemented"))); int raise(int sig) @@ -122,7 +135,16 @@ int _kill_r(struct _reent *r, int pid, int sig) void _exit(int __status) __attribute__((alias("syscall_not_implemented_aborts"))); +#if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic pop +#endif + +/* Similar to syscall_not_implemented, but not taking struct _reent argument */ +int system(const char* str) +{ + errno = ENOSYS; + return -1; +} /* Replaces newlib fcntl, which has been compiled without HAVE_FCNTL */ int fcntl(int fd, int cmd, ...) diff --git a/components/newlib/test/test_time.c b/components/newlib/test/test_time.c index 1f164d5b04..b0f139b87c 100644 --- a/components/newlib/test/test_time.c +++ b/components/newlib/test/test_time.c @@ -46,26 +46,26 @@ #if portNUM_PROCESSORS == 2 +// This runs on APP CPU: +static void time_adc_test_task(void* arg) +{ + for (int i = 0; i < 200000; ++i) { + // wait for 20us, reading one of RTC registers + uint32_t ccount = xthal_get_ccount(); + while (xthal_get_ccount() - ccount < 20 * TARGET_DEFAULT_CPU_FREQ_MHZ) { + volatile uint32_t val = REG_READ(RTC_CNTL_STATE0_REG); + (void) val; + } + } + SemaphoreHandle_t * p_done = (SemaphoreHandle_t *) arg; + xSemaphoreGive(*p_done); + vTaskDelay(1); + vTaskDelete(NULL); +} + // https://github.com/espressif/arduino-esp32/issues/120 TEST_CASE("Reading RTC registers on APP CPU doesn't affect clock", "[newlib]") { - // This runs on APP CPU: - void time_adc_test_task(void* arg) - { - for (int i = 0; i < 200000; ++i) { - // wait for 20us, reading one of RTC registers - uint32_t ccount = xthal_get_ccount(); - while (xthal_get_ccount() - ccount < 20 * TARGET_DEFAULT_CPU_FREQ_MHZ) { - volatile uint32_t val = REG_READ(RTC_CNTL_STATE0_REG); - (void) val; - } - } - SemaphoreHandle_t * p_done = (SemaphoreHandle_t *) arg; - xSemaphoreGive(*p_done); - vTaskDelay(1); - vTaskDelete(NULL); - } - SemaphoreHandle_t done = xSemaphoreCreateBinary(); xTaskCreatePinnedToCore(&time_adc_test_task, "time_adc", 4096, &done, 5, NULL, 1); @@ -251,6 +251,7 @@ static void get_time_task(void *pvParameters) // although exit flag is set in another task, checking (exit_flag == false) is safe while (exit_flag == false) { gettimeofday(&tv_time, NULL); + vTaskDelay(1500 / portTICK_PERIOD_MS); } xSemaphoreGive(*sema); vTaskDelete(NULL); @@ -259,13 +260,9 @@ static void get_time_task(void *pvParameters) static void start_measure(int64_t* sys_time, int64_t* real_time) { struct timeval tv_time; - int64_t t1, t2; - do { - t1 = esp_timer_get_time(); - gettimeofday(&tv_time, NULL); - t2 = esp_timer_get_time(); - } while (t2 - t1 > 40); - *real_time = t2; + // there shouldn't be much time between gettimeofday and esp_timer_get_time + gettimeofday(&tv_time, NULL); + *real_time = esp_timer_get_time(); *sys_time = (int64_t)tv_time.tv_sec * 1000000L + tv_time.tv_usec; } @@ -301,7 +298,7 @@ static void measure_time_task(void *pvParameters) int64_t sys_time_us[2] = { main_sys_time_us[0], 0}; // although exit flag is set in another task, checking (exit_flag == false) is safe while (exit_flag == false) { - esp_rom_delay_us(2 * 1000000); // 2 sec + vTaskDelay(2000 / portTICK_PERIOD_MS); start_measure(&sys_time_us[1], &real_time_us[1]); result_adjtime_correction_us[1] += calc_correction("measure", sys_time_us, real_time_us); @@ -322,7 +319,7 @@ static void measure_time_task(void *pvParameters) vTaskDelete(NULL); } -TEST_CASE("test time adjustment happens linearly", "[newlib][timeout=35]") +TEST_CASE("test time adjustment happens linearly", "[newlib][timeout=15]") { exit_flag = false; @@ -335,8 +332,8 @@ TEST_CASE("test time adjustment happens linearly", "[newlib][timeout=35]") xTaskCreatePinnedToCore(get_time_task, "get_time_task", 4096, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, NULL, 0); xTaskCreatePinnedToCore(measure_time_task, "measure_time_task", 4096, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, NULL, 1); - printf("start waiting for 30 seconds\n"); - vTaskDelay(30000 / portTICK_PERIOD_MS); + printf("start waiting for 10 seconds\n"); + vTaskDelay(10000 / portTICK_PERIOD_MS); // set exit flag to let thread exit exit_flag = true; diff --git a/components/nvs_flash/CMakeLists.txt b/components/nvs_flash/CMakeLists.txt index 7ce2871c1a..063ffc0832 100644 --- a/components/nvs_flash/CMakeLists.txt +++ b/components/nvs_flash/CMakeLists.txt @@ -13,13 +13,9 @@ set(srcs "src/nvs_api.cpp" "src/nvs_partition_manager.cpp" "src/nvs_types.cpp") -set(public_req spi_flash) - -set(include_dirs "include") - idf_component_register(SRCS "${srcs}" - REQUIRES "${public_req}" - INCLUDE_DIRS "${include_dirs}") + REQUIRES "spi_flash" + INCLUDE_DIRS "include") # If we use the linux target, we need to redirect the crc functions to the linux if(${target} STREQUAL "linux") @@ -27,11 +23,6 @@ if(${target} STREQUAL "linux") # mbedtls isn't configured for building with linux or as mock target. It will draw in all kind of dependencies message(FATAL_ERROR "NVS currently doesn't support encryption if built for Linux.") endif() - idf_component_get_property(spi_flash_dir spi_flash COMPONENT_DIR) - target_include_directories(${COMPONENT_LIB} PUBLIC - "${CMAKE_CURRENT_SOURCE_DIR}/mock/int" - "${spi_flash_dir}/sim/stubs/freertos/include") - target_sources(${COMPONENT_LIB} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/mock/int/crc.cpp") target_compile_options(${COMPONENT_LIB} PUBLIC "-DLINUX_TARGET") else() # TODO: this is a workaround until IDF-2085 is fixed diff --git a/components/nvs_flash/host_test/fixtures/test_fixtures.hpp b/components/nvs_flash/host_test/fixtures/test_fixtures.hpp index 06b12ce176..b0915682f1 100644 --- a/components/nvs_flash/host_test/fixtures/test_fixtures.hpp +++ b/components/nvs_flash/host_test/fixtures/test_fixtures.hpp @@ -122,6 +122,9 @@ struct PartitionMockFixture { const char *partition_name = NVS_DEFAULT_PART_NAME) : part_mock(start_sector * SPI_FLASH_SEC_SIZE, sector_size * SPI_FLASH_SEC_SIZE) { std::fill_n(raw_header, sizeof(raw_header)/sizeof(raw_header[0]), UINT8_MAX); + + // This resets the mocks and prevents meeting accidental expectations from previous tests. + Mockesp_partition_Init(); } ~PartitionMockFixture() { } @@ -151,7 +154,7 @@ struct NVSPageFixture : public PartitionMockFixture { nvs::Page page; }; -struct NVSValidPageFixture : public PartitionMockFixture { +struct NVSValidPageFlashFixture : public PartitionMockFixture { const static uint8_t NS_INDEX = 1; // valid header @@ -164,7 +167,7 @@ struct NVSValidPageFixture : public PartitionMockFixture { uint8_t value_entry [32]; - NVSValidPageFixture(uint32_t start_sector = 0, + NVSValidPageFlashFixture(uint32_t start_sector = 0, uint32_t sector_size = 1, const char *partition_name = NVS_DEFAULT_PART_NAME) : PartitionMockFixture(start_sector, sector_size, partition_name), @@ -173,8 +176,7 @@ struct NVSValidPageFixture : public PartitionMockFixture { ns_entry {0x00, 0x01, 0x01, 0xff, 0x68, 0xc5, 0x3f, 0x0b, 't', 'e', 's', 't', '_', 'n', 's', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', 1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, value_entry {0x01, 0x01, 0x01, 0xff, 0x3d, 0xf3, 0x99, 0xe5, 't', 'e', 's', 't', '_', 'v', 'a', 'l', - 'u', 'e', '\0', '\0', '\0', '\0', '\0', '\0', 47, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - page() + 'u', 'e', '\0', '\0', '\0', '\0', '\0', '\0', 47, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} { std::fill_n(raw_entry_table, sizeof(raw_entry_table)/sizeof(raw_entry_table[0]), 0); raw_entry_table[0] = 0xfa; @@ -202,7 +204,15 @@ struct NVSValidPageFixture : public PartitionMockFixture { // read normal entry second time during duplicated entry check esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); esp_partition_read_ReturnArrayThruPtr_dst(value_entry, 32); + } +}; +struct NVSValidPageFixture : public NVSValidPageFlashFixture { + NVSValidPageFixture(uint32_t start_sector = 0, + uint32_t sector_size = 1, + const char *partition_name = NVS_DEFAULT_PART_NAME) + : NVSValidPageFlashFixture(start_sector, sector_size, partition_name), page() + { if (page.load(&part_mock, start_sector) != ESP_OK) throw FixtureException("couldn't setup page"); } @@ -392,9 +402,6 @@ struct NVSFullPageFixture : public PartitionMockFixture { 'u', 'e', '\0', '\0', '\0', '\0', '\0', '\0', 47, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, page() { - std::fill_n(raw_entry_table, sizeof(raw_entry_table)/sizeof(raw_entry_table[0]), 0); - raw_entry_table[0] = 0xfa; - // entry_table with all elements deleted except the namespace entry written and the last entry free std::fill_n(raw_entry_table, sizeof(raw_entry_table)/sizeof(raw_entry_table[0]), 0); raw_entry_table[0] = 0x0a; diff --git a/components/nvs_flash/host_test/nvs_page_test/CMakeLists.txt b/components/nvs_flash/host_test/nvs_page_test/CMakeLists.txt index 4ab7323a9a..797ef37d40 100644 --- a/components/nvs_flash/host_test/nvs_page_test/CMakeLists.txt +++ b/components/nvs_flash/host_test/nvs_page_test/CMakeLists.txt @@ -1,10 +1,15 @@ cmake_minimum_required(VERSION 3.5) include($ENV{IDF_PATH}/tools/cmake/project.cmake) + set(COMPONENTS main) -idf_component_set_property(spi_flash USE_MOCK 1) +list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/mocks/driver/") +list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/mocks/freertos/") +list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/mocks/spi_flash/") + idf_build_set_property(COMPILE_DEFINITIONS "-DNO_DEBUG_STORAGE" APPEND) -project(host_nvs_page_test) +project(test_nvs_page_host) + add_custom_command( OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/build/coverage.info" diff --git a/components/nvs_flash/host_test/nvs_page_test/main/nvs_page_test.cpp b/components/nvs_flash/host_test/nvs_page_test/main/nvs_page_test.cpp index ec63aeac76..e5ca9ed089 100644 --- a/components/nvs_flash/host_test/nvs_page_test/main/nvs_page_test.cpp +++ b/components/nvs_flash/host_test/nvs_page_test/main/nvs_page_test.cpp @@ -30,6 +30,8 @@ void test_Page_load_reading_header_fails() TEST_ASSERT_EQUAL(Page::PageState::INVALID, page.state()); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, page.load(&mock, 0)); + + Mockesp_partition_Verify(); } void test_Page_load_reading_data_fails() @@ -44,6 +46,8 @@ void test_Page_load_reading_data_fails() TEST_ASSERT_EQUAL(Page::PageState::INVALID, page.state()); TEST_ASSERT_EQUAL(ESP_FAIL, page.load(&mock, 0)); + + Mockesp_partition_Verify(); } void test_Page_load__uninitialized_page_has_0xfe() @@ -62,6 +66,8 @@ void test_Page_load__uninitialized_page_has_0xfe() TEST_ASSERT_EQUAL(ESP_OK, page.load(&fix.part_mock, 0)); TEST_ASSERT_EQUAL(Page::PageState::CORRUPT, page.state()); + + Mockesp_partition_Verify(); } void test_Page_load__initialized_corrupt_header() @@ -79,6 +85,60 @@ void test_Page_load__initialized_corrupt_header() TEST_ASSERT_EQUAL(ESP_OK, page.load(&fix.part_mock, 0)); TEST_ASSERT_EQUAL(Page::PageState::CORRUPT, page.state()); + + Mockesp_partition_Verify(); +} + +void test_Page_load__corrupt_entry_table() +{ + PartitionMockFixture fix; + + // valid header + uint8_t raw_header_valid [32] = {0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc2, 0x16, 0xdd, 0xdc}; + + // entry table with one entry + uint8_t raw_entry_table [32]; + + uint8_t ns_entry [32] = {0x00, 0x01, 0x01, 0xff, 0x68, 0xc5, 0x3f, 0x0b, 't', 'e', 's', 't', '_', 'n', 's', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', 1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + uint8_t raw_header[4] = {0xff, 0xff, 0xff, 0xff}; + std::fill_n(raw_entry_table, sizeof(raw_entry_table)/sizeof(raw_entry_table[0]), 0); + raw_entry_table[0] = 0xfa; + + // read page header + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header_valid, 32); + + // read entry table + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_entry_table, 32); + + // read next free entry's header + esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header, 4); + + // read namespace entry + esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK); + esp_partition_read_ReturnArrayThruPtr_dst(ns_entry, 32); + + // we expect a raw word write from the partition in order to change the entry bits to erased (0) + esp_partition_write_raw_ExpectAndReturn(&fix.part_mock.partition, 32, nullptr, 4, ESP_OK); + esp_partition_write_raw_IgnoreArg_src(); + + // corrupt entry table as well as crc of corresponding item + raw_entry_table[0] = 0xf6; + + Page page; + + // Page::load() should return ESP_OK, but state has to be corrupt + TEST_ASSERT_EQUAL(ESP_OK, page.load(&fix.part_mock, 0)); + + TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, page.state()); + TEST_ASSERT_EQUAL(1, page.getUsedEntryCount()); + + Mockesp_partition_Verify(); } void test_Page_load_success() @@ -886,6 +946,7 @@ int main(int argc, char **argv) RUN_TEST(test_Page_load_reading_data_fails); RUN_TEST(test_Page_load__uninitialized_page_has_0xfe); RUN_TEST(test_Page_load__initialized_corrupt_header); + RUN_TEST(test_Page_load__corrupt_entry_table); RUN_TEST(test_Page_load_success); RUN_TEST(test_Page_load_full_page); RUN_TEST(test_Page_load__seq_number_0); diff --git a/components/nvs_flash/host_test/nvs_page_test/sdkconfig.defaults b/components/nvs_flash/host_test/nvs_page_test/sdkconfig.defaults index d7ae4dee46..209c6da062 100644 --- a/components/nvs_flash/host_test/nvs_page_test/sdkconfig.defaults +++ b/components/nvs_flash/host_test/nvs_page_test/sdkconfig.defaults @@ -1,4 +1,4 @@ CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=n CONFIG_COMPILER_HIDE_PATHS_MACROS=n CONFIG_IDF_TARGET="linux" -CONFIG_CXX_EXCEPTIONS=y +CONFIG_COMPILER_CXX_EXCEPTIONS=y diff --git a/components/nvs_flash/mock/int/crc.cpp b/components/nvs_flash/mock/int/crc.cpp deleted file mode 100644 index 5c1b745648..0000000000 --- a/components/nvs_flash/mock/int/crc.cpp +++ /dev/null @@ -1,63 +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 -#include - -static const unsigned int crc32_le_table[256] = { - 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, - 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, - 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, - 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L, - 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, - 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, - 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL, - 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, - 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L, - 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, - 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, - 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L, - 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, - 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, - 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, - 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, - - 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L, - 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, - 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, - 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, - 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, - 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L, - 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, - 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL, - 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, - 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, - 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L, - 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, - 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, - 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, - 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, - 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL -}; - - - -extern "C" uint32_t esp_rom_crc32_le(unsigned int crc, unsigned char const * buf,unsigned int len) -{ - unsigned int i; - crc = ~crc; - for(i=0;i>8); - } - return ~crc; -} diff --git a/components/nvs_flash/nvs_partition_generator/README.rst b/components/nvs_flash/nvs_partition_generator/README.rst index 3a78a109d6..9ea5911200 100644 --- a/components/nvs_flash/nvs_partition_generator/README.rst +++ b/components/nvs_flash/nvs_partition_generator/README.rst @@ -43,7 +43,7 @@ Each line of a .csv file should contain 4 parameters, separated by a comma. The | | | | Any values in these cells are ignored. | +-----+-----------+----------------------------------------------------------------------+-----------------------------------------------------+ -.. note:: The first line of the CSV file should always be the column header and it is not configurable. +.. note:: The first line of the CSV file should be the column header and it is not configurable. Comments (if provided) are allowed only as the first line of the CSV file, the following line then should always be the column header. Comments should always start with the `#` symbol. Below is an example dump of such a CSV file:: @@ -308,5 +308,5 @@ Caveats ------- - Utility does not check for duplicate keys and will write data pertaining to both keys. You need to make sure that the keys are distinct. - Once a new page is created, no data will be written in the space left on the previous page. Fields in the CSV file need to be ordered in such a way as to optimize memory. +- Utility supports using multiline strings with ``file`` type and singleline strings with ``data`` type in the CSV file. - 64-bit datatype is not yet supported. - diff --git a/components/nvs_flash/src/nvs_api.cpp b/components/nvs_flash/src/nvs_api.cpp index 84f104e2aa..57ffebc1cb 100644 --- a/components/nvs_flash/src/nvs_api.cpp +++ b/components/nvs_flash/src/nvs_api.cpp @@ -22,18 +22,12 @@ #include #include "nvs_handle_simple.hpp" #include "esp_err.h" - -#ifdef LINUX_TARGET -#include "crc.h" -#define ESP_LOGD(...) -#else // LINUX_TARGET -#include +#include // Uncomment this line to force output from this module // #define LOG_LOCAL_LEVEL ESP_LOG_DEBUG #include "esp_log.h" static const char* TAG = "nvs"; -#endif // ! LINUX_TARGET class NVSHandleEntry : public intrusive_list_node { public: @@ -311,7 +305,7 @@ extern "C" esp_err_t nvs_open(const char* name, nvs_open_mode_t open_mode, nvs_h extern "C" void nvs_close(nvs_handle_t handle) { Lock lock; - ESP_LOGD(TAG, "%s %d", __func__, handle); + ESP_LOGD(TAG, "%s %d", __func__, static_cast(handle)); auto it = find_if(begin(s_nvs_handles), end(s_nvs_handles), [=](NVSHandleEntry& e) -> bool { return e.mHandle == handle; }); @@ -352,7 +346,7 @@ template static esp_err_t nvs_set(nvs_handle_t c_handle, const char* key, T value) { Lock lock; - ESP_LOGD(TAG, "%s %s %d %d", __func__, key, sizeof(T), (uint32_t) value); + ESP_LOGD(TAG, "%s %s %d %ld", __func__, key, static_cast(sizeof(T)), static_cast(value)); NVSHandleSimple *handle; auto err = nvs_find_ns_handle(c_handle, &handle); if (err != ESP_OK) { @@ -429,7 +423,7 @@ extern "C" esp_err_t nvs_set_str(nvs_handle_t c_handle, const char* key, const c extern "C" esp_err_t nvs_set_blob(nvs_handle_t c_handle, const char* key, const void* value, size_t length) { Lock lock; - ESP_LOGD(TAG, "%s %s %d", __func__, key, length); + ESP_LOGD(TAG, "%s %s %d", __func__, key, static_cast(length)); NVSHandleSimple *handle; auto err = nvs_find_ns_handle(c_handle, &handle); if (err != ESP_OK) { @@ -443,7 +437,7 @@ template static esp_err_t nvs_get(nvs_handle_t c_handle, const char* key, T* out_value) { Lock lock; - ESP_LOGD(TAG, "%s %s %d", __func__, key, sizeof(T)); + ESP_LOGD(TAG, "%s %s %ld", __func__, key, static_cast(sizeof(T))); NVSHandleSimple *handle; auto err = nvs_find_ns_handle(c_handle, &handle); if (err != ESP_OK) { @@ -629,8 +623,8 @@ extern "C" esp_err_t nvs_flash_generate_keys(const esp_partition_t* partition, n return err; } - uint32_t crc_calc = crc32_le(0xffffffff, cfg->eky, NVS_KEY_SIZE); - crc_calc = crc32_le(crc_calc, cfg->tky, NVS_KEY_SIZE); + uint32_t crc_calc = esp_rom_crc32_le(0xffffffff, cfg->eky, NVS_KEY_SIZE); + crc_calc = esp_rom_crc32_le(crc_calc, cfg->tky, NVS_KEY_SIZE); uint8_t crc_wr[16]; memset(crc_wr, 0xff, sizeof(crc_wr)); @@ -702,8 +696,8 @@ extern "C" esp_err_t nvs_flash_read_security_cfg(const esp_partition_t* partitio return err; } - crc_calc = crc32_le(0xffffffff, cfg->eky, NVS_KEY_SIZE); - crc_calc = crc32_le(crc_calc, cfg->tky, NVS_KEY_SIZE); + crc_calc = esp_rom_crc32_le(0xffffffff, cfg->eky, NVS_KEY_SIZE); + crc_calc = esp_rom_crc32_le(crc_calc, cfg->tky, NVS_KEY_SIZE); if(crc_calc != crc_read) { if(!check_if_initialized(cfg->eky, cfg->tky, crc_read)) { diff --git a/components/nvs_flash/src/nvs_item_hash_list.cpp b/components/nvs_flash/src/nvs_item_hash_list.cpp index 7e1c1241a6..21bf8b3153 100644 --- a/components/nvs_flash/src/nvs_item_hash_list.cpp +++ b/components/nvs_flash/src/nvs_item_hash_list.cpp @@ -65,7 +65,7 @@ esp_err_t HashList::insert(const Item& item, size_t index) return ESP_OK; } -void HashList::erase(size_t index, bool itemShouldExist) +bool HashList::erase(size_t index) { for (auto it = mBlockList.begin(); it != mBlockList.end();) { bool haveEntries = false; @@ -81,7 +81,7 @@ void HashList::erase(size_t index, bool itemShouldExist) } if (haveEntries && foundIndex) { /* item was found, and HashListBlock still has some items */ - return; + return true; } } /* no items left in HashListBlock, can remove */ @@ -95,12 +95,12 @@ void HashList::erase(size_t index, bool itemShouldExist) } if (foundIndex) { /* item was found and empty HashListBlock was removed */ - return; + return true; } } - if (itemShouldExist) { - assert(false && "item should have been present in cache"); - } + + // item hasn't been present in cache"); + return false; } size_t HashList::find(size_t start, const Item& item) diff --git a/components/nvs_flash/src/nvs_item_hash_list.hpp b/components/nvs_flash/src/nvs_item_hash_list.hpp index ca21c92c18..e724c4f02f 100644 --- a/components/nvs_flash/src/nvs_item_hash_list.hpp +++ b/components/nvs_flash/src/nvs_item_hash_list.hpp @@ -29,7 +29,7 @@ public: ~HashList(); esp_err_t insert(const Item& item, size_t index); - void erase(const size_t index, bool itemShouldExist=true); + bool erase(const size_t index); size_t find(size_t start, const Item& item); void clear(); diff --git a/components/nvs_flash/src/nvs_page.cpp b/components/nvs_flash/src/nvs_page.cpp index 2f72a2090d..8097c096ce 100644 --- a/components/nvs_flash/src/nvs_page.cpp +++ b/components/nvs_flash/src/nvs_page.cpp @@ -12,11 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. #include "nvs_page.hpp" -#if defined(LINUX_TARGET) -#include "crc.h" -#else #include -#endif #include #include @@ -393,8 +389,9 @@ esp_err_t Page::findItem(uint8_t nsIndex, ItemType datatype, const char* key, ui esp_err_t Page::eraseEntryAndSpan(size_t index) { + uint32_t seq_num; + getSeqNumber(seq_num); auto state = mEntryTable.get(index); - assert(state == EntryState::WRITTEN || state == EntryState::EMPTY); size_t span = 1; if (state == EntryState::WRITTEN) { @@ -404,7 +401,7 @@ esp_err_t Page::eraseEntryAndSpan(size_t index) return rc; } if (item.calculateCrc32() != item.crc32) { - mHashList.erase(index, false); + mHashList.erase(index); rc = alterEntryState(index, EntryState::ERASED); --mUsedEntryCount; ++mErasedEntryCount; @@ -601,6 +598,16 @@ esp_err_t Page::mLoadEntryTable() continue; } + if (mEntryTable.get(i) == EntryState::ILLEGAL) { + lastItemIndex = INVALID_ENTRY; + auto err = eraseEntryAndSpan(i); + if (err != ESP_OK) { + mState = PageState::INVALID; + return err; + } + continue; + } + lastItemIndex = i; auto err = readEntry(i, item); diff --git a/components/nvs_flash/src/nvs_page.hpp b/components/nvs_flash/src/nvs_page.hpp index 5857f1ffe4..f4c00e84ca 100644 --- a/components/nvs_flash/src/nvs_page.hpp +++ b/components/nvs_flash/src/nvs_page.hpp @@ -175,6 +175,7 @@ protected: EMPTY = 0x3, // 0b11, default state after flash erase WRITTEN = EMPTY & ~ESB_WRITTEN, // entry was written ERASED = WRITTEN & ~ESB_ERASED, // entry was written and then erased + ILLEGAL = 0x1, // only possible if flash is inconsistent INVALID = 0x4 // entry is in inconsistent state (write started but ESB_WRITTEN has not been set yet) }; diff --git a/components/nvs_flash/src/nvs_types.cpp b/components/nvs_flash/src/nvs_types.cpp index 0189dd70b9..a9369a4e27 100644 --- a/components/nvs_flash/src/nvs_types.cpp +++ b/components/nvs_flash/src/nvs_types.cpp @@ -13,11 +13,7 @@ // limitations under the License. #include "nvs_types.hpp" -#if defined(LINUX_TARGET) -#include "crc.h" -#else -#include -#endif +#include "esp_rom_crc.h" namespace nvs { diff --git a/components/nvs_flash/test_nvs_host/Makefile b/components/nvs_flash/test_nvs_host/Makefile index 5031de6a8e..9fd1f5cf32 100644 --- a/components/nvs_flash/test_nvs_host/Makefile +++ b/components/nvs_flash/test_nvs_host/Makefile @@ -3,7 +3,6 @@ all: $(TEST_PROGRAM) SOURCE_FILES = \ esp_error_check_stub.cpp \ - ../mock/int/crc.cpp \ $(addprefix ../src/, \ nvs_types.cpp \ nvs_api.cpp \ @@ -31,13 +30,15 @@ SOURCE_FILES = \ test_nvs_initialization.cpp \ main.cpp +SOURCE_FILES_C = ../../esp_rom/linux/esp_rom_crc.c + ifeq ($(shell $(CC) -v 2>&1 | grep -c "clang version"), 1) COMPILER := clang else COMPILER := gcc endif -CPPFLAGS += -I../include -I../src -I../mock/int -I./ -I../../esp_common/include -I../../esp32/include -I ../../mbedtls/mbedtls/include -I ../../spi_flash/include -I ../../hal/include -I ../../xtensa/include -I ../../../tools/catch -fprofile-arcs -ftest-coverage -g2 -ggdb +CPPFLAGS += -I../include -I../src -I../../esp_rom/include -I../../esp_rom/include/linux -I../../log/include -I./ -I../../esp_common/include -I../../esp32/include -I ../../mbedtls/mbedtls/include -I ../../spi_flash/include -I ../../hal/include -I ../../xtensa/include -I ../../../tools/catch -fprofile-arcs -ftest-coverage -g2 -ggdb CFLAGS += -fprofile-arcs -ftest-coverage -DLINUX_TARGET CXXFLAGS += -std=c++11 -Wall -Werror -DLINUX_TARGET LDFLAGS += -lstdc++ -Wall -fprofile-arcs -ftest-coverage @@ -49,14 +50,16 @@ LDFLAGS += -fsanitize=address endif OBJ_FILES = $(SOURCE_FILES:.cpp=.o) +OBJ_FILES_C = $(SOURCE_FILES_C:.c=.o) COVERAGE_FILES = $(OBJ_FILES:.o=.gc*) $(OBJ_FILES): %.o: %.cpp +$(OBJ_FILES_C): %.c: %.c -$(TEST_PROGRAM): clean-coverage $(OBJ_FILES) +$(TEST_PROGRAM): clean-coverage $(OBJ_FILES) $(OBJ_FILES_C) $(MAKE) -C ../../mbedtls/mbedtls/ lib - g++ $(LDFLAGS) -o $(TEST_PROGRAM) $(OBJ_FILES) ../../mbedtls/mbedtls/library/libmbedcrypto.a + g++ $(LDFLAGS) -o $(TEST_PROGRAM) $(OBJ_FILES) $(OBJ_FILES_C) ../../mbedtls/mbedtls/library/libmbedcrypto.a $(OUTPUT_DIR): mkdir -p $(OUTPUT_DIR) @@ -84,7 +87,7 @@ clean-coverage: clean: clean-coverage $(MAKE) -C ../../mbedtls/mbedtls/ clean - rm -f $(OBJ_FILES) $(TEST_PROGRAM) + 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 diff --git a/components/nvs_flash/test_nvs_host/sdkconfig.h b/components/nvs_flash/test_nvs_host/sdkconfig.h index a38e0a10d8..2f9361f1a7 100644 --- a/components/nvs_flash/test_nvs_host/sdkconfig.h +++ b/components/nvs_flash/test_nvs_host/sdkconfig.h @@ -1,3 +1,6 @@ #define CONFIG_NVS_ENCRYPTION 1 //currently use the legacy implementation, since the stubs for new HAL are not done yet #define CONFIG_SPI_FLASH_USE_LEGACY_IMPL 1 +#define CONFIG_LOG_MAXIMUM_LEVEL 3 +#define CONFIG_LOG_TIMESTAMP_SOURCE_RTOS 1 +#define CONFIG_IDF_TARGET_LINUX 1 diff --git a/components/nvs_flash/test_nvs_host/test_nvs.cpp b/components/nvs_flash/test_nvs_host/test_nvs.cpp index bf2712e796..76affc310d 100644 --- a/components/nvs_flash/test_nvs_host/test_nvs.cpp +++ b/components/nvs_flash/test_nvs_host/test_nvs.cpp @@ -313,7 +313,8 @@ TEST_CASE("HashList is cleaned up as soon as items are erased", "[nvs]") INFO("Added " << count << " items, " << hashlist.getBlockCount() << " blocks"); // Remove them in reverse order for (size_t i = count; i > 0; --i) { - hashlist.erase(i - 1, true); + // Make sure that the element existed before it's erased + CHECK(hashlist.erase(i - 1) == true); } CHECK(hashlist.getBlockCount() == 0); // Add again @@ -326,7 +327,7 @@ TEST_CASE("HashList is cleaned up as soon as items are erased", "[nvs]") INFO("Added " << count << " items, " << hashlist.getBlockCount() << " blocks"); // Remove them in the same order for (size_t i = 0; i < count; ++i) { - hashlist.erase(i, true); + CHECK(hashlist.erase(i) == true); } CHECK(hashlist.getBlockCount() == 0); } diff --git a/components/openthread/CMakeLists.txt b/components/openthread/CMakeLists.txt index c32211eadc..993432260d 100644 --- a/components/openthread/CMakeLists.txt +++ b/components/openthread/CMakeLists.txt @@ -1,51 +1,10 @@ if(CONFIG_OPENTHREAD_ENABLED) - set(public_include_dirs - "include" - "openthread/include") - - set(private_include_dirs - "openthread/src" - "openthread/src/core" - "openthread/src/lib/hdlc" - "openthread/src/lib/spinel" - "openthread/src/ncp" - "openthread/examples/platforms/") - - set(src_dirs - "openthread/examples/apps/cli" - "openthread/examples/platforms/utils" - "openthread/src/cli" - "openthread/src/core/api" - "openthread/src/core/backbone_router" - "openthread/src/core/coap" - "openthread/src/core/common" - "openthread/src/core/crypto" - "openthread/src/core/diags" - "openthread/src/core/mac" - "openthread/src/core/meshcop" - "openthread/src/core/net" - "openthread/src/core/radio" - "openthread/src/core/thread" - "openthread/src/core/utils" - "openthread/src/lib/platform" - "openthread/src/lib/hdlc" - "openthread/src/lib/spinel") - - if(CONFIG_OPENTHREAD_BORDER_ROUTER) - list(APPEND src_dirs - "openthread/src/core/border_router") + if(CONFIG_OPENTHREAD_FTD) + include(ftd.cmake) + else() + include(radio.cmake) endif() - set(exclude_srcs - "openthread/examples/apps/cli/main.c" - "openthread/examples/platforms/utils/logging_rtt.c" - "openthread/examples/platforms/utils/soft_source_match_table.c" - "openthread/src/core/common/extension_example.cpp") - - set_source_files_properties("openthread/src/core/net/srp_server.cpp" - PROPERTIES COMPILE_FLAGS - -Wno-maybe-uninitialized) - if(CONFIG_OPENTHREAD_FTD) set(device_type "OPENTHREAD_FTD=1") elseif(CONFIG_OPENTHREAD_MTD) @@ -75,13 +34,19 @@ idf_component_register(SRC_DIRS "${src_dirs}" REQUIRES mbedtls ieee802154) if(CONFIG_OPENTHREAD_ENABLED) + if(CONFIG_OPENTHREAD_RADIO) + set(CONFIG_FILE_TYPE "radio") + else() + set(CONFIG_FILE_TYPE "ftd") + endif() + target_compile_definitions( ${COMPONENT_LIB} PUBLIC - "OPENTHREAD_CONFIG_FILE=\"openthread-core-esp32x-config.h\"" + "OPENTHREAD_CONFIG_FILE=\"openthread-core-esp32x-${CONFIG_FILE_TYPE}-config.h\"" "${device_type}" PRIVATE - "PACKAGE_VERSION=\"${IDF_VERSION_FOR_OPENTHREAD_PACKAGE}-${OPENTHREAD_VERSION}\"") + "PACKAGE_VERSION=\"${IDF_VERSION_FOR_OPENTHREAD_PACKAGE}-${OPENTHREAD_VERSION}\"") if(CONFIG_OPENTHREAD_ESP_LIB_FROM_INTERNAL_SRC) idf_component_get_property(openthread_port_lib openthread_port COMPONENT_LIB) diff --git a/components/openthread/Kconfig b/components/openthread/Kconfig index 7803240730..ab63e14185 100644 --- a/components/openthread/Kconfig +++ b/components/openthread/Kconfig @@ -77,6 +77,14 @@ menu "OpenThread" Select this option to enable Joiner in OpenThread. This allows a device to join the Thread network with a pre-shared key using the Thread commissioning protocol. + config OPENTHREAD_SRP_CLIENT + bool "Enable SRP Client" + depends on OPENTHREAD_ENABLED + default n + help + Select this option to enable SRP Client in OpenThread. This allows a device to register SRP services to SRP + Server. + config OPENTHREAD_BORDER_ROUTER bool "Enable Border Router" depends on OPENTHREAD_ENABLED @@ -91,4 +99,10 @@ menu "OpenThread" help Override the shipped libopenthread_br.a and libopenthread_port.a, for internal builds. + config OPENTHREAD_NUM_MESSAGE_BUFFERS + int "The number of openthread message buffers" + depends on OPENTHREAD_ENABLED + default 65 + range 50 100 + endmenu diff --git a/components/openthread/component.mk b/components/openthread/component.mk index c49b004d42..b404e35c21 100644 --- a/components/openthread/component.mk +++ b/components/openthread/component.mk @@ -57,7 +57,7 @@ OPENTHREAD_VERSION := $(shell git -C $(COMPONENT_PATH)/openthread rev-parse --sh OPENTHREAD_PACKAGE_VERSION := $(IDF_VERSION_FOR_OPENTHREAD_PACKAGE)-$(OPENTHREAD_VERSION) COMMON_FLAGS := \ - -DOPENTHREAD_CONFIG_FILE=\ \ + -DOPENTHREAD_CONFIG_FILE=\ \ -DPACKAGE_VERSION=\"OPENTHREAD_PACKAGE_VERSION\" \ -Wno-maybe-uninitialized diff --git a/components/openthread/ftd.cmake b/components/openthread/ftd.cmake new file mode 100644 index 0000000000..d87bd93159 --- /dev/null +++ b/components/openthread/ftd.cmake @@ -0,0 +1,53 @@ +set(public_include_dirs + "include" + "openthread/include") + +set(private_include_dirs + "openthread/examples/platforms" + "openthread/include/openthread" + "openthread/src" + "openthread/src/core" + "openthread/src/lib/hdlc" + "openthread/src/lib/spinel" + "openthread/src/ncp" + "private_include" + ) + +set(src_dirs + "openthread/examples/apps/cli" + "openthread/examples/platforms/utils" + "openthread/src/core/api" + "openthread/src/core/backbone_router" + "openthread/src/core/coap" + "openthread/src/core/common" + "openthread/src/core/crypto" + "openthread/src/core/diags" + "openthread/src/core/mac" + "openthread/src/core/meshcop" + "openthread/src/core/net" + "openthread/src/core/radio" + "openthread/src/core/thread" + "openthread/src/core/utils" + "openthread/src/cli" + "openthread/src/lib/hdlc" + "openthread/src/lib/spinel" + "openthread/src/lib/platform") + +set(exclude_srcs + "openthread/examples/apps/cli/main.c" + "openthread/examples/platforms/utils/logging_rtt.c" + "openthread/examples/platforms/utils/soft_source_match_table.c" + "openthread/src/core/common/extension_example.cpp") + +if(CONFIG_OPENTHREAD_BORDER_ROUTER) + list(APPEND src_dirs + "openthread/src/core/border_router") +endif() + +set_source_files_properties("openthread/src/core/net/srp_server.cpp" + PROPERTIES COMPILE_FLAGS + -Wno-maybe-uninitialized) + +if(CONFIG_OPENTHREAD_FTD) + set(device_type "OPENTHREAD_FTD=1") +endif() diff --git a/components/openthread/include/esp_openthread_types.h b/components/openthread/include/esp_openthread_types.h index a3fb31ed41..8fed9fbd0d 100644 --- a/components/openthread/include/esp_openthread_types.h +++ b/components/openthread/include/esp_openthread_types.h @@ -49,11 +49,11 @@ ESP_EVENT_DECLARE_BASE(OPENTHREAD_EVENT); * */ typedef struct { - fd_set read_fds; /*!< The read file descriptors.*/ - fd_set write_fds; /*!< The write file descriptors.*/ - fd_set error_fds; /*!< The error file descriptors.*/ - int max_fd; /*!< The max file descriptor.*/ - struct timeval timeout; /*!< The timeout.*/ + fd_set read_fds; /*!< The read file descriptors */ + fd_set write_fds; /*!< The write file descriptors */ + fd_set error_fds; /*!< The error file descriptors */ + int max_fd; /*!< The max file descriptor */ + struct timeval timeout; /*!< The timeout */ } esp_openthread_mainloop_context_t; /** @@ -61,8 +61,8 @@ typedef struct { * */ typedef struct { - uart_port_t port; /*!< UART port number*/ - uart_config_t uart_config; /*!< UART configuration, see uart_config_t docs*/ + uart_port_t port; /*!< UART port number */ + uart_config_t uart_config; /*!< UART configuration, see uart_config_t docs */ int rx_pin; /*!< UART RX pin */ int tx_pin; /*!< UART TX pin */ } esp_openthread_uart_config_t; @@ -72,9 +72,9 @@ typedef struct { * */ typedef enum { - RADIO_MODE_NATIVE = 0x0, /*!< Use the native 15.4 radio*/ - RADIO_MODE_UART_RCP = 0x1, /*!< UART connection to a 15.4 capable radio co-processor (RCP)*/ - RADIO_MODE_SPI_RCP = 0x2, /*!< SPI connection to a 15.4 capable radio co-processor (RCP)*/ + RADIO_MODE_NATIVE = 0x0, /*!< Use the native 15.4 radio */ + RADIO_MODE_UART_RCP = 0x1, /*!< UART connection to a 15.4 capable radio co-processor (RCP) */ + RADIO_MODE_SPI_RCP = 0x2, /*!< SPI connection to a 15.4 capable radio co-processor (RCP) */ } esp_openthread_radio_mode_t; /** @@ -82,8 +82,9 @@ typedef enum { * */ typedef enum { - HOST_CONNECTION_MODE_NONE = 0x0, /*!< Disable host connection*/ - HOST_CONNECTION_MODE_UART = 0x1, /*!< UART connection to the host*/ + HOST_CONNECTION_MODE_NONE = 0x0, /*!< Disable host connection */ + HOST_CONNECTION_MODE_CLI_UART = 0x1, /*!< CLI UART connection to the host */ + HOST_CONNECTION_MODE_RCP_UART = 0x2, /*!< RCP UART connection to the host */ } esp_openthread_host_connection_mode_t; /** @@ -91,8 +92,8 @@ typedef enum { * */ typedef struct { - esp_openthread_radio_mode_t radio_mode; /*!< The radio mode*/ - esp_openthread_uart_config_t radio_uart_config; /*!< The uart configuration to RCP*/ + esp_openthread_radio_mode_t radio_mode; /*!< The radio mode */ + esp_openthread_uart_config_t radio_uart_config; /*!< The uart configuration to RCP */ } esp_openthread_radio_config_t; /** @@ -100,8 +101,8 @@ typedef struct { * */ typedef struct { - esp_openthread_host_connection_mode_t host_connection_mode; /*!< The host connection mode*/ - esp_openthread_uart_config_t host_uart_config; /*!< The uart configuration to host*/ + esp_openthread_host_connection_mode_t host_connection_mode; /*!< The host connection mode */ + esp_openthread_uart_config_t host_uart_config; /*!< The uart configuration to host */ } esp_openthread_host_connection_config_t; /** @@ -109,9 +110,9 @@ typedef struct { * */ typedef struct { - const char *storage_partition_name; /*!< The partition for storing OpenThread dataset*/ - uint8_t netif_queue_size; /*!< The packet queue size for the network interface*/ - uint8_t task_queue_size; /*!< The task queue size*/ + const char *storage_partition_name; /*!< The partition for storing OpenThread dataset */ + uint8_t netif_queue_size; /*!< The packet queue size for the network interface */ + uint8_t task_queue_size; /*!< The task queue size */ } esp_openthread_port_config_t; /** @@ -119,9 +120,9 @@ typedef struct { * */ typedef struct { - esp_openthread_radio_config_t radio_config; /*!< The radio configuration*/ - esp_openthread_host_connection_config_t host_config; /*!< The host connection configuration*/ - esp_openthread_port_config_t port_config; /*!< The port configuration*/ + esp_openthread_radio_config_t radio_config; /*!< The radio configuration */ + esp_openthread_host_connection_config_t host_config; /*!< The host connection configuration */ + esp_openthread_port_config_t port_config; /*!< The port configuration */ } esp_openthread_platform_config_t; #ifdef __cplusplus diff --git a/components/openthread/lib b/components/openthread/lib index 105f3610d2..6cb8a43666 160000 --- a/components/openthread/lib +++ b/components/openthread/lib @@ -1 +1 @@ -Subproject commit 105f3610d2258d7a7dd1c72f5f1adea89077c6cc +Subproject commit 6cb8a436669f3a0f7e967625141c94930e3cb8bc diff --git a/components/openthread/openthread b/components/openthread/openthread index a662c32eb0..71bc37bbc3 160000 --- a/components/openthread/openthread +++ b/components/openthread/openthread @@ -1 +1 @@ -Subproject commit a662c32eb074cc624bf344f810f65f8637a89552 +Subproject commit 71bc37bbc353b0ca1775f5654a2b65fcbe044650 diff --git a/components/openthread/include/openthread-core-esp32x-config.h b/components/openthread/private_include/openthread-core-esp32x-ftd-config.h similarity index 90% rename from components/openthread/include/openthread-core-esp32x-config.h rename to components/openthread/private_include/openthread-core-esp32x-ftd-config.h index 254672aa88..6f0dd0fbbd 100644 --- a/components/openthread/include/openthread-core-esp32x-config.h +++ b/components/openthread/private_include/openthread-core-esp32x-ftd-config.h @@ -95,7 +95,7 @@ * * The number of message buffers in buffer pool */ -#define OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS 50 +#define OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS CONFIG_OPENTHREAD_NUM_MESSAGE_BUFFERS /** * @def OPENTHREAD_CONFIG_COAP_API_ENABLE @@ -126,6 +126,16 @@ #define OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE 1 #endif +/** + * @def OPENTHREAD_CONFIG_TCP_ENABLE + * + * Define to 0 to disable TCP + * + */ +#ifndef OPENTHREAD_CONFIG_TCP_ENABLE +#define OPENTHREAD_CONFIG_TCP_ENABLE 0 +#endif + #if CONFIG_OPENTHREAD_BORDER_ROUTER /** @@ -188,6 +198,16 @@ #define OPENTHREAD_CONFIG_SRP_SERVER_ENABLE 1 #endif +/** + * @def OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE + * + * Define to 1 to enable DNS-SD Server support. + * + */ +#ifndef OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE +#define OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE 1 +#endif + #endif // CONFIG_OPENTHREAD_BORDER_ROUTER /** @@ -330,6 +350,16 @@ */ #define OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE 1 +/** + * @def OPENTHREAD_CONFIG_PING_SENDER_ENABLE + * + * Define to 1 to enable ping sender module. + * + * Ping sender module implements sending ICMPv6 Echo Request messages and processing ICMPv6 Echo Reply messages. + * + */ +#define OPENTHREAD_CONFIG_PING_SENDER_ENABLE 1 + /** * @def OPENTHREAD_CONFIG_DTLS_MAX_CONTENT_LEN * @@ -355,6 +385,16 @@ #define OPENTHREAD_CONFIG_DIAG_ENABLE 1 #endif +#if CONFIG_OPENTHREAD_SRP_CLIENT +#ifndef OPENTHREAD_CONFIG_ECDSA_ENABLE +#define OPENTHREAD_CONFIG_ECDSA_ENABLE 1 +#endif + +#ifndef OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE +#define OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE 1 +#endif +#endif + #if CONFIG_OPENTHREAD_FTD #define OPENTHREAD_FTD 1 #elif CONFIG_OPENTHREAD_MTD diff --git a/components/openthread/private_include/openthread-core-esp32x-radio-config.h b/components/openthread/private_include/openthread-core-esp32x-radio-config.h new file mode 100644 index 0000000000..4e5e667dd1 --- /dev/null +++ b/components/openthread/private_include/openthread-core-esp32x-radio-config.h @@ -0,0 +1,318 @@ +// 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 + +#pragma once + +#include "sdkconfig.h" +/** + * @def OPENTHREAD_CONFIG_PLATFORM_INFO + * + * The platform-specific string to insert into the OpenThread version string. + * + */ +#define OPENTHREAD_CONFIG_PLATFORM_INFO CONFIG_IDF_TARGET + +/** + * @def OPENTHREAD_CONFIG_PLATFORM_ASSERT_MANAGEMENT + * + * The assert is managed by platform defined logic when this flag is set. + * + */ +#define OPENTHREAD_CONFIG_PLATFORM_ASSERT_MANAGEMENT 1 + +/** + * @def OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE + * + * Define to 1 to enable otPlatFlash* APIs to support non-volatile storage. + * + * When defined to 1, the platform MUST implement the otPlatFlash* APIs instead of the otPlatSettings* APIs. + * + */ +#define OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE 1 + +/** + * @def OPENTHREAD_CONFIG_LOG_OUTPUT + * + * The ESP-IDF platform provides an otPlatLog() function. + */ +#define OPENTHREAD_CONFIG_LOG_OUTPUT OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED + +/** + * @def OPENTHREAD_CONFIG_LOG_LEVEL + * + * The log level (used at compile time). If `OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE` is set, this defines the most + * verbose log level possible. See `OPENTHREAD_CONFIG_LOG_LEVEL_INIT` to set the initial log level. + * + */ +#ifndef OPENTHREAD_CONFIG_LOG_LEVEL +#if CONFIG_LOG_DEFAULT_LEVEL_NONE +#define OPENTHREAD_CONFIG_LOG_LEVEL OT_LOG_LEVEL_NONE +#elif CONFIG_LOG_DEFAULT_LEVEL_ERROR +#define OPENTHREAD_CONFIG_LOG_LEVEL OT_LOG_LEVEL_CRIT +#elif CONFIG_LOG_DEFAULT_LEVEL_WARN +#define OPENTHREAD_CONFIG_LOG_LEVEL OT_LOG_LEVEL_WARN +#elif CONFIG_LOG_DEFAULT_LEVEL_INFO +#define OPENTHREAD_CONFIG_LOG_LEVEL OT_LOG_LEVEL_INFO +#elif CONFIG_LOG_DEFAULT_LEVEL_DEBUG +#define OPENTHREAD_CONFIG_LOG_LEVEL OT_LOG_LEVEL_DEBG +#elif CONFIG_LOG_DEFAULT_LEVEL_VERBOSE +#define OPENTHREAD_CONFIG_LOG_LEVEL OT_LOG_LEVEL_DEBG +#endif +#endif + +#define OPENTHREAD_CONFIG_LOG_API 1 +#define OPENTHREAD_CONFIG_LOG_ARP 1 +#define OPENTHREAD_CONFIG_LOG_BBR 1 +#define OPENTHREAD_CONFIG_LOG_CLI 1 +#define OPENTHREAD_CONFIG_LOG_COAP 1 +#define OPENTHREAD_CONFIG_LOG_DUA 1 +#define OPENTHREAD_CONFIG_LOG_ICMP 1 +#define OPENTHREAD_CONFIG_LOG_IP6 1 +#define OPENTHREAD_CONFIG_LOG_MAC 1 +#define OPENTHREAD_CONFIG_LOG_MEM 1 +#define OPENTHREAD_CONFIG_LOG_MESHCOP 1 +#define OPENTHREAD_CONFIG_LOG_MLE 1 +#define OPENTHREAD_CONFIG_LOG_MLR 1 +#define OPENTHREAD_CONFIG_LOG_NETDATA 1 +#define OPENTHREAD_CONFIG_LOG_NETDIAG 1 +#define OPENTHREAD_CONFIG_LOG_PKT_DUMP 1 +#define OPENTHREAD_CONFIG_LOG_PLATFORM 1 + +/** + * @def OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS + * + * The number of message buffers in buffer pool + */ +#define OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS 50 + +/** + * @def OPENTHREAD_CONFIG_COAP_API_ENABLE + * + * Define to 1 to enable the CoAP API. + * + */ +#define OPENTHREAD_CONFIG_COAP_API_ENABLE 0 + +/** + * @def OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE + * + * Define to 1 to enable Border Router support. + * + */ +#ifndef OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE +#define OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE 0 +#endif + +/** + * @def OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE + * + * Define to 1 to enable Thread Test Harness reference device support. + * + */ +#define OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE 0 + +/** + * @def OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE + * + * Define to 1 to enable Child Supervision support. + * + */ +#ifndef OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE +#define OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE 0 +#endif + +/** + * @def OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE + * + * Define to 1 to enable DHCPv6 Client support. + * + */ +#ifndef OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE +#define OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE 0 +#endif + +/** + * @def OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE + * + * Define to 1 to enable DHCPv6 Server support. + * + */ +#ifndef OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE +#define OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE 0 +#endif + +/** + * @def OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE + * + * Define to 1 to enable DNS Client support. + * + */ +#ifndef OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE +#define OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE 0 +#endif + +/** + * @def OPENTHREAD_CONFIG_NCP_SPI_ENABLE + * + * Define to 1 to enable NCP SPI support. + * + */ +#define OPENTHREAD_CONFIG_NCP_SPI_ENABLE 0 + +/** + * @def OPENTHREAD_ENABLE_NCP_SPINEL_ENCRYPTER + * + * Define to 1 to enable NCP Spinel Encrypter. + * + */ +#define OPENTHREAD_ENABLE_NCP_SPINEL_ENCRYPTER 0 + +/** + * @def OPENTHREAD_CONFIG_NCP_HDLC_ENABLE + * + * Define to 1 to enable NCP HDLC support. + * + */ +#define OPENTHREAD_CONFIG_NCP_HDLC_ENABLE 1 + +/** + * @def OPENTHREAD_SPINEL_CONFIG_OPENTHREAD_MESSAGE_ENABLE + * + * Define 1 to enable feeding an OpenThread message to encoder/decoder. + * + */ +#define OPENTHREAD_SPINEL_CONFIG_OPENTHREAD_MESSAGE_ENABLE 0 + +/** + * @def OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE + * + * Define to 1 to support injecting Service entries into the Thread Network Data. + * + */ +#define OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE 0 + +/** + * @def PACKAGE_NAME + * + * Define to the full name of this package. + * + */ +#define PACKAGE_NAME "openthread-esp32" + +/** + * @def PACKAGE_STRING + * + * Define to the full name and version of this package. + * + */ +#define PACKAGE_STRING (PACKAGE_NAME " - " PACKAGE_VERSION) + +/** + * @def OPENTHREAD_CONFIG_ENABLE_BUILTIN_MBEDTLS + * + * Define as 1 to enable bultin-mbedtls. + * + * Note that the OPENTHREAD_CONFIG_ENABLE_BUILTIN_MBEDTLS determines whether to use bultin-mbedtls as well as + * whether to manage mbedTLS internally, such as memory allocation and debug. + * + */ +#define OPENTHREAD_CONFIG_ENABLE_BUILTIN_MBEDTLS 0 + +/** + * @def OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE + * + * Define as 1 to enable support for adding of auto-configured SLAAC addresses by OpenThread. + * + */ +#define OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE 0 + +/** + * @def OPENTHREAD_CONFIG_MAX_STATECHANGE_HANDLERS + * + * The maximum number of state-changed callback handlers (set using `otSetStateChangedCallback()`). + * + */ +#define OPENTHREAD_CONFIG_MAX_STATECHANGE_HANDLERS 3 + +/** + * @def OPENTHREAD_CONFIG_PLATFORM_RADIO_SPINEL_RX_FRAME_BUFFER_SIZE + * + * Specifies the rx frame buffer size used by `SpinelInterface` in RCP host code. This is applicable/used when + * `RadioSpinel` platform is used. + * + */ +#define OPENTHREAD_CONFIG_PLATFORM_RADIO_SPINEL_RX_FRAME_BUFFER_SIZE 1024 + +/** + * @def OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE + * + * Define as 1 to enable microsecond timer. + * + */ +#define OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE 1 + +/** + * @def OPENTHREAD_CONFIG_MAC_SOFTWARE_CSMA_BACKOFF_ENABLE + * + * Define to 1 to enable software CSMA-CA backoff logic. + * + */ +#define OPENTHREAD_CONFIG_MAC_SOFTWARE_CSMA_BACKOFF_ENABLE 1 + +/** + * @def OPENTHREAD_CONFIG_MAC_SOFTWARE_RETRANSMIT_ENABLE + * + * Define to 1 to enable software retransmission logic. + * + */ +#define OPENTHREAD_CONFIG_MAC_SOFTWARE_RETRANSMIT_ENABLE 1 + +/** + * @def OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_SECURITY_ENABLE + * + * Define to 1 to enable software transmission security logic. + * + */ +#define OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_SECURITY_ENABLE 1 + +/** + * @def OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_TIMING_ENABLE + * + * Define to 1 to enable software transmission target time logic. + * + */ +#define OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_TIMING_ENABLE 1 + +/** + * The configurable definitions via Kconfig + */ +#if CONFIG_OPENTHREAD_COMMISSIONER +#error "Commissioner shouldn't be enabled for RCP" +#endif + +#if CONFIG_OPENTHREAD_JOINER +#error "Joiner shouldn't be enabled for RCP" +#endif + +#if CONFIG_OPENTHREAD_DIAG +#define OPENTHREAD_CONFIG_DIAG_ENABLE 1 +#endif + +#if CONFIG_OPENTHREAD_FTD +#error "Only OPENTHREAD_RADIO is used for RCP" +#elif CONFIG_OPENTHREAD_MTD +#error "Only OPENTHREAD_RADIO is used for RCP" +#elif CONFIG_OPENTHREAD_RADIO +#define OPENTHREAD_RADIO 1 +#endif diff --git a/components/openthread/radio.cmake b/components/openthread/radio.cmake new file mode 100644 index 0000000000..93b6f1166f --- /dev/null +++ b/components/openthread/radio.cmake @@ -0,0 +1,78 @@ +set(public_include_dirs + "include" + "openthread/include") + +set(private_include_dirs + "openthread/examples/platforms" + "openthread/include/openthread" + "openthread/src" + "openthread/src/core" + "openthread/src/lib/hdlc" + "openthread/src/lib/spinel" + "openthread/src/ncp" + "private_include" + ) + +set(src_dirs + "openthread/examples/platforms/utils" + "openthread/src/core/api" + "openthread/src/core/common" + "openthread/src/core/crypto" + "openthread/src/core/diags" + "openthread/src/core/mac" + "openthread/src/core/radio" + "openthread/src/core/thread" + "openthread/src/core/utils" + "openthread/src/lib/hdlc" + "openthread/src/lib/spinel" + "openthread/src/ncp" + "openthread/examples/apps/ncp") + +set(exclude_srcs + "openthread/examples/platforms/utils/logging_rtt.c" + "openthread/examples/platforms/utils/soft_source_match_table.c" + "openthread/examples/apps/ncp/main.c" + "openthread/src/core/api/backbone_router_api.cpp" + "openthread/src/core/api/entropy_api.cpp" + "openthread/src/core/api/netdata_api.cpp" + "openthread/src/core/api/link_api.cpp" + "openthread/src/core/api/icmp6_api.cpp" + "openthread/src/core/api/ip6_api.cpp" + "openthread/src/core/api/udp_api.cpp" + "openthread/src/core/common/settings.cpp" + "openthread/src/core/api/dataset_api.cpp" + "openthread/src/core/api/random_crypto_api.cpp" + "openthread/src/core/common/extension_example.cpp" + "openthread/src/core/common/heap_string.cpp" + "openthread/src/core/common/time_ticker.cpp" + "openthread/src/core/common/notifier.cpp" + "openthread/src/core/api/message_api.cpp" + "openthread/src/core/thread/energy_scan_server.cpp" + "openthread/src/core/thread/mesh_forwarder.cpp" + "openthread/src/core/thread/mle.cpp" + "openthread/src/core/thread/neighbor_table.cpp" + "openthread/src/core/thread/tmf.cpp" + "openthread/src/core/thread/network_data_leader_ftd.cpp" + "openthread/src/core/thread/discover_scanner.cpp" + "openthread/src/core/thread/lowpan.cpp" + "openthread/src/core/thread/network_data_leader.cpp" + "openthread/src/core/thread/mesh_forwarder_mtd.cpp" + "openthread/src/core/thread/key_manager.cpp" + "openthread/src/core/thread/network_data_types.cpp" + "openthread/src/core/thread/mesh_forwarder_ftd.cpp" + "openthread/src/core/thread/network_data.cpp" + "openthread/src/core/thread/network_data_service.cpp" + "openthread/src/core/thread/announce_begin_server.cpp" + "openthread/src/core/thread/announce_sender.cpp" + "openthread/src/core/thread/thread_netif.cpp" + "openthread/src/core/thread/topology.cpp" + "openthread/src/core/thread/panid_query_server.cpp" + "openthread/src/core/mac/channel_mask.cpp" + "openthread/src/core/mac/data_poll_handler.cpp" + "openthread/src/core/mac/data_poll_sender.cpp" + "openthread/src/core/mac/mac.cpp" + "openthread/src/core/mac/mac_filter.cpp" + "openthread/src/core/mac/mac_links.cpp" + "openthread/src/core/utils/child_supervision.cpp") + +set(device_type "OPENTHREAD_RADIO=1") diff --git a/components/partition_table/check_sizes.py b/components/partition_table/check_sizes.py index d47b9d2838..c53e8c0725 100755 --- a/components/partition_table/check_sizes.py +++ b/components/partition_table/check_sizes.py @@ -64,7 +64,7 @@ def check_bootloader(partition_table_offset, bootloader_offset, binary_file): # _fail(msg) free_size = max_size - bootloader_size print('Bootloader binary size {:#x} bytes. {:#x} bytes ({}%) free.'.format( - bootloader_size, free_size, round(free_size * 100 / bootloader_size))) + bootloader_size, free_size, round(free_size * 100 / max_size))) def check_partition(ptype, subtype, partition_table_file, bin_file): # type: (str, str, io.IOBase, IO) -> None diff --git a/components/partition_table/gen_esp32part.py b/components/partition_table/gen_esp32part.py index 36efbfb0e3..f1423a310e 100755 --- a/components/partition_table/gen_esp32part.py +++ b/components/partition_table/gen_esp32part.py @@ -73,6 +73,7 @@ SUBTYPES = { 'coredump': 0x03, 'nvs_keys': 0x04, 'efuse': 0x05, + 'undefined': 0x06, 'esphttpd': 0x80, 'fat': 0x81, 'spiffs': 0x82, @@ -91,6 +92,19 @@ def get_subtype_as_int(ptype, subtype): return subtype +ALIGNMENT = { + APP_TYPE: 0x10000, + DATA_TYPE: 0x4, +} + + +STRICT_DATA_ALIGNMENT = 0x1000 + + +def get_alignment_for_type(ptype): + return ALIGNMENT.get(ptype, ALIGNMENT[DATA_TYPE]) + + quiet = False md5sum = True secure = False @@ -143,8 +157,8 @@ class PartitionTable(list): continue try: res.append(PartitionDefinition.from_csv(line, line_no + 1)) - except InputError as e: - raise InputError('Error at line %d: %s' % (line_no + 1, e)) + except InputError as err: + raise InputError('Error at line %d: %s' % (line_no + 1, err)) except Exception: critical('Unexpected error parsing CSV line %d: %s' % (line_no + 1, line)) raise @@ -160,7 +174,7 @@ class PartitionTable(list): raise InputError('CSV Error: Partitions overlap. Partition at line %d sets offset 0x%x. Previous partition ends 0x%x' % (e.line_no, e.offset, last_end)) if e.offset is None: - pad_to = 0x10000 if e.type == APP_TYPE else 4 + pad_to = get_alignment_for_type(e.type) if last_end % pad_to != 0: last_end += pad_to - (last_end % pad_to) e.offset = last_end @@ -210,10 +224,10 @@ class PartitionTable(list): # print sorted duplicate partitions by name if len(duplicates) != 0: - print('A list of partitions that have the same name:') + critical('A list of partitions that have the same name:') for p in sorted(self, key=lambda x:x.name): if len(duplicates.intersection([p.name])) != 0: - print('%s' % (p.to_csv())) + critical('%s' % (p.to_csv())) raise InputError('Partition names must be unique') # check for overlaps @@ -225,6 +239,18 @@ class PartitionTable(list): raise InputError('Partition at 0x%x overlaps 0x%x-0x%x' % (p.offset, last.offset, last.offset + last.size - 1)) last = p + # check that otadata should be unique + otadata_duplicates = [p for p in self if p.type == TYPES['data'] and p.subtype == SUBTYPES[DATA_TYPE]['ota']] + if len(otadata_duplicates) > 1: + for p in otadata_duplicates: + critical('%s' % (p.to_csv())) + raise InputError('Found multiple otadata partitions. Only one partition can be defined with type="data"(1) and subtype="ota"(0).') + + if len(otadata_duplicates) == 1 and otadata_duplicates[0].size != 0x2000: + p = otadata_duplicates[0] + critical('%s' % (p.to_csv())) + raise InputError('otadata partition must have size = 0x2000') + def flash_size(self): """ Return the size that partitions will occupy in flash (ie the offset the last partition ends at) @@ -274,11 +300,6 @@ class PartitionTable(list): class PartitionDefinition(object): MAGIC_BYTES = b'\xAA\x50' - ALIGNMENT = { - APP_TYPE: 0x10000, - DATA_TYPE: 0x04, - } - # dictionary maps flag name (as used in CSV flags list, property name) # to bit set in flags words in binary format FLAGS = { @@ -358,7 +379,9 @@ class PartitionDefinition(object): def parse_subtype(self, strval): if strval == '': - return 0 # default + if self.type == TYPES['app']: + raise InputError('App partition cannot have an empty subtype') + return SUBTYPES[DATA_TYPE]['undefined'] return parse_int(strval, SUBTYPES.get(self.type, {})) def parse_address(self, strval): @@ -373,10 +396,15 @@ class PartitionDefinition(object): raise ValidationError(self, 'Subtype field is not set') if self.offset is None: raise ValidationError(self, 'Offset field is not set') - align = self.ALIGNMENT.get(self.type, 4) + align = get_alignment_for_type(self.type) if self.offset % align: raise ValidationError(self, 'Offset 0x%x is not aligned to 0x%x' % (self.offset, align)) - if self.size % align and secure: + # The alignment requirement for non-app partition is 4 bytes, but it should be 4 kB. + # Print a warning for now, make it an error in IDF 5.0 (IDF-3742). + if self.type != APP_TYPE and self.offset % STRICT_DATA_ALIGNMENT: + critical('WARNING: Partition %s not aligned to 0x%x.' + 'This is deprecated and will be considered an error in the future release.' % (self.name, STRICT_DATA_ALIGNMENT)) + if self.size % align and secure and self.type == APP_TYPE: raise ValidationError(self, 'Size 0x%x is not aligned to 0x%x' % (self.size, align)) if self.size is None: raise ValidationError(self, 'Size field is not set') diff --git a/components/partition_table/test_gen_esp32part_host/gen_esp32part_tests.py b/components/partition_table/test_gen_esp32part_host/gen_esp32part_tests.py index 70911f12e4..11dd2170e2 100755 --- a/components/partition_table/test_gen_esp32part_host/gen_esp32part_tests.py +++ b/components/partition_table/test_gen_esp32part_host/gen_esp32part_tests.py @@ -88,7 +88,7 @@ myota_0, 0, 0x10,, 0x100000 myota_1, 0, 0x11,, 0x100000 myota_15, 0, 0x1f,, 0x100000 mytest, 0, 0x20,, 0x100000 -myota_status, 1, 0,, 0x100000 +myota_status, 1, 0,, 0x2000 """ csv_nomagicnumbers = """ # Name, Type, SubType, Offset, Size @@ -97,7 +97,7 @@ myota_0, app, ota_0,, 0x100000 myota_1, app, ota_1,, 0x100000 myota_15, app, ota_15,, 0x100000 mytest, app, test,, 0x100000 -myota_status, data, ota,, 0x100000 +myota_status, data, ota,, 0x2000 """ # make two equivalent partition tables, one using # magic numbers and one using shortcuts. Ensure they match @@ -219,6 +219,30 @@ first, app, factory,, 1M, encrypted tr = gen_esp32part.PartitionTable.from_binary(tb) self.assertTrue(tr[0].encrypted) + def test_only_empty_subtype_is_not_0(self): + csv_txt = """ +# Name,Type, SubType,Offset,Size +nvs, data, nvs, , 0x4000, +otadata, data, ota, , 0x2000, +phy_init, data, phy, , 0x1000, +factory, app, factory, , 1M +ota_0, 0, ota_0, , 1M, +ota_1, 0, ota_1, , 1M, +storage, data, , , 512k, +storage2, data, undefined, , 12k, +""" + t = gen_esp32part.PartitionTable.from_csv(csv_txt) + t.verify() + self.assertEqual(t[1].name, 'otadata') + self.assertEqual(t[1].type, 1) + self.assertEqual(t[1].subtype, 0) + self.assertEqual(t[6].name, 'storage') + self.assertEqual(t[6].type, 1) + self.assertEqual(t[6].subtype, 0x06) + self.assertEqual(t[7].name, 'storage2') + self.assertEqual(t[7].type, 1) + self.assertEqual(t[7].subtype, 0x06) + class BinaryParserTests(Py23TestCase): def test_parse_one_entry(self): @@ -372,6 +396,46 @@ app,app, factory, 32K, 1M t = gen_esp32part.PartitionTable.from_csv(csv) t.verify() + def test_only_one_otadata(self): + csv_txt = """ +# Name,Type, SubType,Offset,Size +nvs, data, nvs, , 0x4000, +otadata, data, ota, , 0x2000, +otadata2, data, ota, , 0x2000, +factory, app, factory, , 1M +ota_0, 0, ota_0, , 1M, +ota_1, 0, ota_1, , 1M, +""" + with self.assertRaisesRegex(gen_esp32part.InputError, r'Found multiple otadata partitions'): + t = gen_esp32part.PartitionTable.from_csv(csv_txt) + t.verify() + + def test_otadata_must_have_fixed_size(self): + csv_txt = """ +# Name,Type, SubType,Offset,Size +nvs, data, nvs, , 0x4000, +otadata, data, ota, , 0x3000, +factory, app, factory, , 1M +ota_0, 0, ota_0, , 1M, +ota_1, 0, ota_1, , 1M, +""" + with self.assertRaisesRegex(gen_esp32part.InputError, r'otadata partition must have size = 0x2000'): + t = gen_esp32part.PartitionTable.from_csv(csv_txt) + t.verify() + + def test_app_cannot_have_empty_subtype(self): + csv_txt = """ +# Name,Type, SubType,Offset,Size +nvs, data, nvs, , 0x4000, +otadata, data, ota, , 0x2000, +factory, app, , , 1M +ota_0, 0, ota_0, , 1M, +ota_1, 0, ota_1, , 1M, +""" + with self.assertRaisesRegex(gen_esp32part.InputError, r'App partition cannot have an empty subtype'): + t = gen_esp32part.PartitionTable.from_csv(csv_txt) + t.verify() + def test_warnings(self): try: sys.stderr = io.StringIO() # capture stderr @@ -387,6 +451,19 @@ app,app, factory, 32K, 1M self.assertIn('WARNING', sys.stderr.getvalue()) self.assertIn('partition subtype', sys.stderr.getvalue()) + sys.stderr = io.StringIO() + csv_3 = 'nvs, data, nvs, 0x8800, 32k' + gen_esp32part.PartitionTable.from_csv(csv_3).verify() + self.assertIn('WARNING', sys.stderr.getvalue()) + self.assertIn('not aligned to 0x1000', sys.stderr.getvalue()) + + sys.stderr = io.StringIO() + csv_4 = 'factory, app, factory, 0x10000, 0x100100\n' \ + 'nvs, data, nvs, , 32k' + gen_esp32part.PartitionTable.from_csv(csv_4).verify() + self.assertIn('WARNING', sys.stderr.getvalue()) + self.assertIn('not aligned to 0x1000', sys.stderr.getvalue()) + finally: sys.stderr = sys.__stderr__ diff --git a/components/sdmmc/test/test_sd.c b/components/sdmmc/test/test_sd.c index 6ab0bbe431..3a47b9b0a8 100644 --- a/components/sdmmc/test/test_sd.c +++ b/components/sdmmc/test/test_sd.c @@ -1,16 +1,8 @@ -// 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. +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -35,8 +27,8 @@ // Currently no runners for S3 #define WITH_SD_TEST (SOC_SDMMC_HOST_SUPPORTED && !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)) -//Currently no runners for S2, S3 and C3 -#define WITH_SDSPI_TEST (!TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3, ESP32C3)) +// Currently, no runners for S3 +#define WITH_SDSPI_TEST (!TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)) // Can't test eMMC (slot 0) and PSRAM together #define WITH_EMMC_TEST (SOC_SDMMC_HOST_SUPPORTED && !CONFIG_SPIRAM && !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)) @@ -48,8 +40,6 @@ #define SD_TEST_BOARD_VSEL_3V3 1 #define SD_TEST_BOARD_VSEL_1V8 0 -#define TEST_SDSPI_DMACHAN 1 - /* time to wait for reset / power-on */ #define SD_TEST_BOARD_PWR_RST_DELAY_MS 5 #define SD_TEST_BOARD_PWR_ON_DELAY_MS 50 @@ -57,6 +47,24 @@ /* gpio which is not connected to actual CD pin, used to simulate CD behavior */ #define CD_WP_TEST_GPIO 18 +/* default GPIO selection */ +#ifdef CONFIG_IDF_TARGET_ESP32S2 +#define SDSPI_TEST_MOSI_PIN GPIO_NUM_35 +#define SDSPI_TEST_MISO_PIN GPIO_NUM_37 +#define SDSPI_TEST_SCLK_PIN GPIO_NUM_36 +#define SDSPI_TEST_CS_PIN GPIO_NUM_34 +#elif defined(CONFIG_IDF_TARGET_ESP32C3) +#define SDSPI_TEST_MOSI_PIN GPIO_NUM_4 +#define SDSPI_TEST_MISO_PIN GPIO_NUM_6 +#define SDSPI_TEST_SCLK_PIN GPIO_NUM_5 +#define SDSPI_TEST_CS_PIN GPIO_NUM_1 +#else +#define SDSPI_TEST_MOSI_PIN GPIO_NUM_15 +#define SDSPI_TEST_MISO_PIN GPIO_NUM_2 +#define SDSPI_TEST_SCLK_PIN GPIO_NUM_14 +#define SDSPI_TEST_CS_PIN GPIO_NUM_13 +#endif + TEST_CASE("MMC_RSP_BITS", "[sd]") { @@ -174,6 +182,19 @@ TEST_CASE("probe eMMC, slot 0, 8-bit", "[sd][test_env=EMMC]") #endif // WITH_EMMC_TEST #if WITH_SDSPI_TEST + +#if !WITH_SD_TEST && !WITH_EMMC_TEST +static void sd_test_board_power_on(void) +{ + // do nothing +} + +static void sd_test_board_power_off(void) +{ + // do nothing +} +#endif + static void test_sdspi_init_bus(spi_host_device_t host, int mosi_pin, int miso_pin, int clk_pin, int dma_chan) { spi_bus_config_t bus_config = { @@ -213,7 +234,7 @@ static void probe_spi(int freq_khz, int pin_miso, int pin_mosi, int pin_sck, int sdspi_dev_handle_t handle; sdspi_device_config_t dev_config = SDSPI_DEVICE_CONFIG_DEFAULT(); dev_config.gpio_cs = pin_cs; - test_sdspi_init_bus(dev_config.host_id, pin_mosi, pin_miso, pin_sck, TEST_SDSPI_DMACHAN); + test_sdspi_init_bus(dev_config.host_id, pin_mosi, pin_miso, pin_sck, SPI_DMA_CH_AUTO); TEST_ESP_OK(sdspi_host_init()); TEST_ESP_OK(sdspi_host_init_device(&dev_config, &handle)); @@ -233,6 +254,7 @@ static void probe_spi_legacy(int freq_khz, int pin_miso, int pin_mosi, int pin_s slot_config.gpio_mosi = pin_mosi; slot_config.gpio_sck = pin_sck; slot_config.gpio_cs = pin_cs; + slot_config.dma_channel = SPI_DMA_CH_AUTO; TEST_ESP_OK(sdspi_host_init()); TEST_ESP_OK(sdspi_host_init_slot(config.slot, &slot_config)); @@ -240,13 +262,16 @@ static void probe_spi_legacy(int freq_khz, int pin_miso, int pin_mosi, int pin_s probe_core(config.slot); TEST_ESP_OK(sdspi_host_deinit()); + + TEST_ESP_OK(spi_bus_free(config.slot)); + sd_test_board_power_off(); } TEST_CASE("probe SD in SPI mode", "[sd][test_env=UT_T1_SPIMODE]") { - probe_spi(SDMMC_FREQ_DEFAULT, 2, 15, 14, 13); - probe_spi_legacy(SDMMC_FREQ_DEFAULT, 2, 15, 14, 13); + probe_spi(SDMMC_FREQ_DEFAULT, SDSPI_TEST_MISO_PIN, SDSPI_TEST_MOSI_PIN, SDSPI_TEST_SCLK_PIN, SDSPI_TEST_CS_PIN); + probe_spi_legacy(SDMMC_FREQ_DEFAULT, SDSPI_TEST_MISO_PIN, SDSPI_TEST_MOSI_PIN, SDSPI_TEST_SCLK_PIN, SDSPI_TEST_CS_PIN); } // No runner for this @@ -455,14 +480,15 @@ void sdspi_test_rw_blocks(sd_test_func_t test_func) { sd_test_board_power_on(); + sdmmc_host_t config = SDSPI_HOST_DEFAULT(); sdspi_dev_handle_t handle; sdspi_device_config_t dev_config = SDSPI_DEVICE_CONFIG_DEFAULT(); - test_sdspi_init_bus(dev_config.host_id, GPIO_NUM_15, GPIO_NUM_2, GPIO_NUM_14, TEST_SDSPI_DMACHAN); + dev_config.host_id = config.slot; + dev_config.gpio_cs = SDSPI_TEST_CS_PIN; + test_sdspi_init_bus(dev_config.host_id, SDSPI_TEST_MOSI_PIN, SDSPI_TEST_MISO_PIN, SDSPI_TEST_SCLK_PIN, SPI_DMA_CH_AUTO); TEST_ESP_OK(sdspi_host_init()); TEST_ESP_OK(sdspi_host_init_device(&dev_config, &handle)); - sdmmc_host_t config = SDSPI_HOST_DEFAULT(); - config.slot = handle; // This test can only run under 20MHz on ESP32, because the runner connects the card to // non-IOMUX pins of HSPI. @@ -623,14 +649,16 @@ TEST_CASE("CD input works in SPI mode", "[sd][test_env=UT_T1_SPIMODE]") { sd_test_board_power_on(); + sdmmc_host_t config = SDSPI_HOST_DEFAULT(); sdspi_dev_handle_t handle; sdspi_device_config_t dev_config = SDSPI_DEVICE_CONFIG_DEFAULT(); + dev_config.host_id = config.slot; + dev_config.gpio_cs = SDSPI_TEST_CS_PIN; dev_config.gpio_cd = CD_WP_TEST_GPIO; - test_sdspi_init_bus(dev_config.host_id, GPIO_NUM_15, GPIO_NUM_2, GPIO_NUM_14, TEST_SDSPI_DMACHAN); + test_sdspi_init_bus(dev_config.host_id, SDSPI_TEST_MOSI_PIN, SDSPI_TEST_MISO_PIN, SDSPI_TEST_SCLK_PIN, SPI_DMA_CH_AUTO); TEST_ESP_OK(sdspi_host_init()); TEST_ESP_OK(sdspi_host_init_device(&dev_config, &handle)); - sdmmc_host_t config = SDSPI_HOST_DEFAULT(); config.slot = handle; test_cd_input(CD_WP_TEST_GPIO, &config); @@ -644,15 +672,17 @@ TEST_CASE("WP input works in SPI mode", "[sd][test_env=UT_T1_SPIMODE]") { sd_test_board_power_on(); + sdmmc_host_t config = SDSPI_HOST_DEFAULT(); sdspi_dev_handle_t handle; sdspi_device_config_t dev_config = SDSPI_DEVICE_CONFIG_DEFAULT(); + dev_config.host_id = config.slot; + dev_config.gpio_cs = SDSPI_TEST_CS_PIN; dev_config.gpio_wp = CD_WP_TEST_GPIO; - test_sdspi_init_bus(dev_config.host_id, GPIO_NUM_15, GPIO_NUM_2, GPIO_NUM_14, TEST_SDSPI_DMACHAN); + test_sdspi_init_bus(dev_config.host_id, SDSPI_TEST_MOSI_PIN, SDSPI_TEST_MISO_PIN, SDSPI_TEST_SCLK_PIN, SPI_DMA_CH_AUTO); TEST_ESP_OK(sdspi_host_init()); TEST_ESP_OK(sdspi_host_init_device(&dev_config, &handle)); - sdmmc_host_t config = SDSPI_HOST_DEFAULT(); config.slot = handle; test_wp_input(CD_WP_TEST_GPIO, &config); diff --git a/components/soc/esp32/CMakeLists.txt b/components/soc/esp32/CMakeLists.txt index 344c8157c4..1d3cb61c9e 100644 --- a/components/soc/esp32/CMakeLists.txt +++ b/components/soc/esp32/CMakeLists.txt @@ -5,6 +5,7 @@ set(srcs "i2c_periph.c" "i2s_periph.c" "interrupts.c" + "lcd_periph.c" "ledc_periph.c" "mcpwm_periph.c" "pcnt_periph.c" diff --git a/components/soc/esp32/gpio_periph.c b/components/soc/esp32/gpio_periph.c index a413203741..d993cb42ac 100644 --- a/components/soc/esp32/gpio_periph.c +++ b/components/soc/esp32/gpio_periph.c @@ -35,7 +35,7 @@ const uint32_t GPIO_PIN_MUX_REG[SOC_GPIO_PIN_COUNT] = { IO_MUX_GPIO17_REG, IO_MUX_GPIO18_REG, IO_MUX_GPIO19_REG, - 0, + IO_MUX_GPIO20_REG, // This corresponding pin is only available on ESP32-PICO-V3 chip package IO_MUX_GPIO21_REG, IO_MUX_GPIO22_REG, IO_MUX_GPIO23_REG, diff --git a/components/soc/esp32/i2s_periph.c b/components/soc/esp32/i2s_periph.c index 84985aaf6a..b65dc9602d 100644 --- a/components/soc/esp32/i2s_periph.c +++ b/components/soc/esp32/i2s_periph.c @@ -1,9 +1,9 @@ -// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// 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 @@ -20,31 +20,41 @@ */ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { { - .o_bck_in_sig = I2S0O_BCK_IN_IDX, - .o_ws_in_sig = I2S0O_WS_IN_IDX, - .o_bck_out_sig = I2S0O_BCK_OUT_IDX, - .o_ws_out_sig = I2S0O_WS_OUT_IDX, - .o_data_out_sig = I2S0O_DATA_OUT23_IDX, - .i_bck_in_sig = I2S0I_BCK_OUT_IDX, - .i_ws_in_sig = I2S0I_WS_OUT_IDX, - .i_bck_out_sig = I2S0I_BCK_IN_IDX, - .i_ws_out_sig = I2S0I_WS_IN_IDX, - .i_data_in_sig = I2S0I_DATA_IN15_IDX, - .irq = ETS_I2S0_INTR_SOURCE, - .module = PERIPH_I2S0_MODULE, + .mck_out_sig = -1, // Unavailable + + .m_tx_bck_sig = I2S0O_BCK_OUT_IDX, + .m_rx_bck_sig = I2S0I_BCK_OUT_IDX, + .m_tx_ws_sig = I2S0O_WS_OUT_IDX, + .m_rx_ws_sig = I2S0I_WS_OUT_IDX, + + .s_tx_bck_sig = I2S0O_BCK_IN_IDX, + .s_rx_bck_sig = I2S0I_BCK_IN_IDX, + .s_tx_ws_sig = I2S0O_WS_IN_IDX, + .s_rx_ws_sig = I2S0I_WS_IN_IDX, + + .data_out_sig = I2S0O_DATA_OUT23_IDX, + .data_in_sig = I2S0I_DATA_IN15_IDX, + + .irq = ETS_I2S0_INTR_SOURCE, + .module = PERIPH_I2S0_MODULE, }, { - .o_bck_in_sig = I2S1O_BCK_IN_IDX, - .o_ws_in_sig = I2S1O_WS_IN_IDX, - .o_bck_out_sig = I2S1O_BCK_OUT_IDX, - .o_ws_out_sig = I2S1O_WS_OUT_IDX, - .o_data_out_sig = I2S1O_DATA_OUT23_IDX, - .i_bck_in_sig = I2S1I_BCK_OUT_IDX, - .i_ws_in_sig = I2S1I_WS_OUT_IDX, - .i_bck_out_sig = I2S1I_BCK_IN_IDX, - .i_ws_out_sig = I2S1I_WS_IN_IDX, - .i_data_in_sig = I2S1I_DATA_IN15_IDX, - .irq = ETS_I2S1_INTR_SOURCE, - .module = PERIPH_I2S1_MODULE, + .mck_out_sig = -1, // Unavailable + + .m_tx_bck_sig = I2S1O_BCK_OUT_IDX, + .m_rx_bck_sig = I2S1I_BCK_OUT_IDX, + .m_tx_ws_sig = I2S1O_WS_OUT_IDX, + .m_rx_ws_sig = I2S1I_WS_OUT_IDX, + + .s_tx_bck_sig = I2S1O_BCK_IN_IDX, + .s_rx_bck_sig = I2S1I_BCK_IN_IDX, + .s_tx_ws_sig = I2S1O_WS_IN_IDX, + .s_rx_ws_sig = I2S1I_WS_IN_IDX, + + .data_out_sig = I2S1O_DATA_OUT23_IDX, + .data_in_sig = I2S1I_DATA_IN15_IDX, + + .irq = ETS_I2S1_INTR_SOURCE, + .module = PERIPH_I2S1_MODULE, } }; diff --git a/components/soc/esp32/include/soc/dport_reg.h b/components/soc/esp32/include/soc/dport_reg.h index 727d181e1a..367c9e43e0 100644 --- a/components/soc/esp32/include/soc/dport_reg.h +++ b/components/soc/esp32/include/soc/dport_reg.h @@ -1156,6 +1156,8 @@ #define DPORT_CPU_INTR_FROM_CPU_1_V 0x1 #define DPORT_CPU_INTR_FROM_CPU_1_S 0 +#define SYSTEM_CPU_INTR_FROM_CPU_2_REG DPORT_CPU_INTR_FROM_CPU_2_REG +#define SYSTEM_CPU_INTR_FROM_CPU_2 DPORT_CPU_INTR_FROM_CPU_2 #define DPORT_CPU_INTR_FROM_CPU_2_REG (DR_REG_DPORT_BASE + 0x0E4) /* DPORT_CPU_INTR_FROM_CPU_2 : R/W ;bitpos:[0] ;default: 1'b0 ; */ /*description: */ @@ -1164,6 +1166,8 @@ #define DPORT_CPU_INTR_FROM_CPU_2_V 0x1 #define DPORT_CPU_INTR_FROM_CPU_2_S 0 +#define SYSTEM_CPU_INTR_FROM_CPU_3_REG DPORT_CPU_INTR_FROM_CPU_3_REG +#define SYSTEM_CPU_INTR_FROM_CPU_3 DPORT_CPU_INTR_FROM_CPU_3 #define DPORT_CPU_INTR_FROM_CPU_3_REG (DR_REG_DPORT_BASE + 0x0E8) /* DPORT_CPU_INTR_FROM_CPU_3 : R/W ;bitpos:[0] ;default: 1'b0 ; */ /*description: */ diff --git a/components/soc/esp32/include/soc/emac_dma_struct.h b/components/soc/esp32/include/soc/emac_dma_struct.h index 35d1361281..1f9a9832e1 100644 --- a/components/soc/esp32/include/soc/emac_dma_struct.h +++ b/components/soc/esp32/include/soc/emac_dma_struct.h @@ -20,7 +20,7 @@ extern "C" #include -typedef volatile struct { +typedef volatile struct emac_dma_dev_s { union { struct { uint32_t sw_rst : 1; /*When this bit is set the MAC DMA Controller resets the logic and all internal registers of the MAC. It is cleared automatically after the reset operation is complete in all of the ETH_MAC clock domains. Before reprogramming any register of the ETH_MAC you should read a zero (0) value in this bit.*/ diff --git a/components/soc/esp32/include/soc/emac_ext_struct.h b/components/soc/esp32/include/soc/emac_ext_struct.h index 9b65c8d91c..5d2e1fecf5 100644 --- a/components/soc/esp32/include/soc/emac_ext_struct.h +++ b/components/soc/esp32/include/soc/emac_ext_struct.h @@ -19,7 +19,7 @@ extern "C" { #include -typedef volatile struct { +typedef volatile struct emac_ext_dev_s { union { struct { uint32_t div_num : 4; diff --git a/components/soc/esp32/include/soc/emac_mac_struct.h b/components/soc/esp32/include/soc/emac_mac_struct.h index b7f5b80ff5..a798b00f99 100644 --- a/components/soc/esp32/include/soc/emac_mac_struct.h +++ b/components/soc/esp32/include/soc/emac_mac_struct.h @@ -19,7 +19,7 @@ extern "C" { #include -typedef volatile struct { +typedef volatile struct emac_mac_dev_s { union { struct { uint32_t pltf : 2; /*These bits control the number of preamble bytes that are added to the beginning of every Transmit frame. The preamble reduction occurs only when the MAC is operating in the full-duplex mode.2'b00: 7 bytes of preamble. 2'b01: 5 bytes of preamble. 2'b10: 3 bytes of preamble.*/ diff --git a/components/soc/esp32/include/soc/i2c_struct.h b/components/soc/esp32/include/soc/i2c_struct.h index 3b17aeb463..7e4afb0601 100644 --- a/components/soc/esp32/include/soc/i2c_struct.h +++ b/components/soc/esp32/include/soc/i2c_struct.h @@ -104,8 +104,8 @@ typedef volatile struct i2c_dev_s { } fifo_conf; union { struct { - uint8_t data; /*The register represent the byte data read from rx_fifo when use apb fifo access*/ - uint8_t reserved[3]; + uint32_t data: 8; /*The register represent the byte data read from rx_fifo when use apb fifo access*/ + uint32_t reserved: 24; }; uint32_t val; } fifo_data; diff --git a/components/soc/esp32/include/soc/mcpwm_reg.h b/components/soc/esp32/include/soc/mcpwm_reg.h index e919d16a70..6a370aa691 100644 --- a/components/soc/esp32/include/soc/mcpwm_reg.h +++ b/components/soc/esp32/include/soc/mcpwm_reg.h @@ -1,3027 +1,3829 @@ -// 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 +/** + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once -// 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. -#ifndef _SOC_MCPWM_REG_H_ -#define _SOC_MCPWM_REG_H_ -#include "soc.h" +#include +#include "soc/soc.h" +#ifdef __cplusplus +extern "C" { +#endif -#define REG_MCPWM_BASE(i) (DR_REG_PWM0_BASE + i * (0xE000)) +#define DR_REG_MCPWM_BASE(i) (DR_REG_PWM0_BASE + i * (0xE000)) -#define MCPWM_CLK_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x0000) -/* MCPWM_CLK_PRESCALE : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ -/*description: Period of PWM_clk = 6.25ns * (PWM_CLK_PRESCALE + 1)*/ -#define MCPWM_CLK_PRESCALE 0x000000FF -#define MCPWM_CLK_PRESCALE_M ((MCPWM_CLK_PRESCALE_V)<<(MCPWM_CLK_PRESCALE_S)) -#define MCPWM_CLK_PRESCALE_V 0xFF +/** MCPWM_CLK_CFG_REG register + * PWM clock prescaler register. + */ +#define MCPWM_CLK_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x0) +/** MCPWM_CLK_PRESCALE : R/W; bitpos: [7:0]; default: 0; + * Period of PWM_clk = 6.25ns * (PWM_CLK_PRESCALE + 1) + */ +#define MCPWM_CLK_PRESCALE 0x000000FFU +#define MCPWM_CLK_PRESCALE_M (MCPWM_CLK_PRESCALE_V << MCPWM_CLK_PRESCALE_S) +#define MCPWM_CLK_PRESCALE_V 0x000000FFU #define MCPWM_CLK_PRESCALE_S 0 -#define MCPWM_TIMER0_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0x0004) -/* MCPWM_TIMER0_PERIOD_UPMETHOD : R/W ;bitpos:[25:24] ;default: 2'd0 ; */ -/*description: Update method for active reg of PWM timer0 period 0: immediate - 1: TEZ 2: sync 3: TEZ or sync. TEZ here and below means timer equal zero event*/ -#define MCPWM_TIMER0_PERIOD_UPMETHOD 0x00000003 -#define MCPWM_TIMER0_PERIOD_UPMETHOD_M ((MCPWM_TIMER0_PERIOD_UPMETHOD_V)<<(MCPWM_TIMER0_PERIOD_UPMETHOD_S)) -#define MCPWM_TIMER0_PERIOD_UPMETHOD_V 0x3 -#define MCPWM_TIMER0_PERIOD_UPMETHOD_S 24 -/* MCPWM_TIMER0_PERIOD : R/W ;bitpos:[23:8] ;default: 16'h00ff ; */ -/*description: Period shadow reg of PWM timer0*/ -#define MCPWM_TIMER0_PERIOD 0x0000FFFF -#define MCPWM_TIMER0_PERIOD_M ((MCPWM_TIMER0_PERIOD_V)<<(MCPWM_TIMER0_PERIOD_S)) -#define MCPWM_TIMER0_PERIOD_V 0xFFFF -#define MCPWM_TIMER0_PERIOD_S 8 -/* MCPWM_TIMER0_PRESCALE : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ -/*description: Period of PT0_clk = Period of PWM_clk * (PWM_TIMER0_PRESCALE + 1)*/ -#define MCPWM_TIMER0_PRESCALE 0x000000FF -#define MCPWM_TIMER0_PRESCALE_M ((MCPWM_TIMER0_PRESCALE_V)<<(MCPWM_TIMER0_PRESCALE_S)) -#define MCPWM_TIMER0_PRESCALE_V 0xFF +/** MCPWM_TIMER0_CFG0_REG register + * PWM timer0 period and update method configuration register. + */ +#define MCPWM_TIMER0_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0x4) +/** MCPWM_TIMER0_PRESCALE : R/W; bitpos: [7:0]; default: 0; + * Configure the divisor of PT0_clk, takes effect when PWM timer0 stops and starts + * agsin. period of PT0_clk = Period of PWM_clk * (PWM_TIMER0_PRESCALE + 1) + */ +#define MCPWM_TIMER0_PRESCALE 0x000000FFU +#define MCPWM_TIMER0_PRESCALE_M (MCPWM_TIMER0_PRESCALE_V << MCPWM_TIMER0_PRESCALE_S) +#define MCPWM_TIMER0_PRESCALE_V 0x000000FFU #define MCPWM_TIMER0_PRESCALE_S 0 +/** MCPWM_TIMER0_PERIOD : R/W; bitpos: [23:8]; default: 255; + * period shadow register of PWM timer0 + */ +#define MCPWM_TIMER0_PERIOD 0x0000FFFFU +#define MCPWM_TIMER0_PERIOD_M (MCPWM_TIMER0_PERIOD_V << MCPWM_TIMER0_PERIOD_S) +#define MCPWM_TIMER0_PERIOD_V 0x0000FFFFU +#define MCPWM_TIMER0_PERIOD_S 8 +/** MCPWM_TIMER0_PERIOD_UPMETHOD : R/W; bitpos: [25:24]; default: 0; + * Update method for active register of PWM timer0 period, 0: immediate, 1: TEZ, 2: + * sync, 3: TEZ or sync. TEZ here and below means timer equal zero event + */ +#define MCPWM_TIMER0_PERIOD_UPMETHOD 0x00000003U +#define MCPWM_TIMER0_PERIOD_UPMETHOD_M (MCPWM_TIMER0_PERIOD_UPMETHOD_V << MCPWM_TIMER0_PERIOD_UPMETHOD_S) +#define MCPWM_TIMER0_PERIOD_UPMETHOD_V 0x00000003U +#define MCPWM_TIMER0_PERIOD_UPMETHOD_S 24 -#define MCPWM_TIMER0_CFG1_REG(i) (REG_MCPWM_BASE(i) + 0x0008) -/* MCPWM_TIMER0_MOD : R/W ;bitpos:[4:3] ;default: 2'h0 ; */ -/*description: PWM timer0 working mode 0: freeze 1: increase mod 2: decrease - mod 3: up-down mod*/ -#define MCPWM_TIMER0_MOD 0x00000003 -#define MCPWM_TIMER0_MOD_M ((MCPWM_TIMER0_MOD_V)<<(MCPWM_TIMER0_MOD_S)) -#define MCPWM_TIMER0_MOD_V 0x3 -#define MCPWM_TIMER0_MOD_S 3 -/* MCPWM_TIMER0_START : R/W ;bitpos:[2:0] ;default: 3'h0 ; */ -/*description: PWM timer0 start and stop control. 0: stop @ TEZ 1: stop @ TEP - 2: free run 3: start and stop @ next TEZ 4: start and stop @ next TEP. TEP here and below means timer equal period event*/ -#define MCPWM_TIMER0_START 0x00000007 -#define MCPWM_TIMER0_START_M ((MCPWM_TIMER0_START_V)<<(MCPWM_TIMER0_START_S)) -#define MCPWM_TIMER0_START_V 0x7 +/** MCPWM_TIMER0_CFG1_REG register + * PWM timer0 working mode and start/stop control configuration register. + */ +#define MCPWM_TIMER0_CFG1_REG(i) (DR_REG_MCPWM_BASE(i) + 0x8) +/** MCPWM_TIMER0_START : R/W/SC; bitpos: [2:0]; default: 0; + * PWM timer0 start and stop control. 0: if PWM timer0 starts, then stops at TEZ, 1: + * if timer0 starts, then stops at TEP, 2: PWM timer0 starts and runs on, 3: timer0 + * starts and stops at the next TEZ, 4: timer0 starts and stops at the next TEP. TEP + * here and below means the event that happens when the timer equals to period + */ +#define MCPWM_TIMER0_START 0x00000007U +#define MCPWM_TIMER0_START_M (MCPWM_TIMER0_START_V << MCPWM_TIMER0_START_S) +#define MCPWM_TIMER0_START_V 0x00000007U #define MCPWM_TIMER0_START_S 0 +/** MCPWM_TIMER0_MOD : R/W; bitpos: [4:3]; default: 0; + * PWM timer0 working mode, 0: freeze, 1: increase mode, 2: decrease mode, 3: up-down + * mode + */ +#define MCPWM_TIMER0_MOD 0x00000003U +#define MCPWM_TIMER0_MOD_M (MCPWM_TIMER0_MOD_V << MCPWM_TIMER0_MOD_S) +#define MCPWM_TIMER0_MOD_V 0x00000003U +#define MCPWM_TIMER0_MOD_S 3 -#define MCPWM_TIMER0_SYNC_REG(i) (REG_MCPWM_BASE(i) + 0x000c) -/* MCPWM_TIMER0_PHASE : R/W ;bitpos:[20:4] ;default: 17'd0 ; */ -/*description: Phase for timer reload on sync event*/ -#define MCPWM_TIMER0_PHASE 0x0001FFFF -#define MCPWM_TIMER0_PHASE_M ((MCPWM_TIMER0_PHASE_V)<<(MCPWM_TIMER0_PHASE_S)) -#define MCPWM_TIMER0_PHASE_V 0x1FFFF -#define MCPWM_TIMER0_PHASE_S 4 -/* MCPWM_TIMER0_SYNCO_SEL : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: PWM timer0 synco selection 0: synci 1: TEZ 2: TEP else 0*/ -#define MCPWM_TIMER0_SYNCO_SEL 0x00000003 -#define MCPWM_TIMER0_SYNCO_SEL_M ((MCPWM_TIMER0_SYNCO_SEL_V)<<(MCPWM_TIMER0_SYNCO_SEL_S)) -#define MCPWM_TIMER0_SYNCO_SEL_V 0x3 -#define MCPWM_TIMER0_SYNCO_SEL_S 2 -/* MCPWM_TIMER0_SYNC_SW : R/W ;bitpos:[1] ;default: 1'h0 ; */ -/*description: Toggling this bit will trigger a software sync*/ -#define MCPWM_TIMER0_SYNC_SW (BIT(1)) -#define MCPWM_TIMER0_SYNC_SW_M (BIT(1)) -#define MCPWM_TIMER0_SYNC_SW_V 0x1 -#define MCPWM_TIMER0_SYNC_SW_S 1 -/* MCPWM_TIMER0_SYNCI_EN : R/W ;bitpos:[0] ;default: 1'h0 ; */ -/*description: When set timer reload with phase on sync input event is enabled*/ -#define MCPWM_TIMER0_SYNCI_EN (BIT(0)) -#define MCPWM_TIMER0_SYNCI_EN_M (BIT(0)) -#define MCPWM_TIMER0_SYNCI_EN_V 0x1 +/** MCPWM_TIMER0_SYNC_REG register + * PWM timer0 sync function configuration register. + */ +#define MCPWM_TIMER0_SYNC_REG(i) (DR_REG_MCPWM_BASE(i) + 0xc) +/** MCPWM_TIMER0_SYNCI_EN : R/W; bitpos: [0]; default: 0; + * When set, timer reloading with phase on sync input event is enabled. + */ +#define MCPWM_TIMER0_SYNCI_EN (BIT(0)) +#define MCPWM_TIMER0_SYNCI_EN_M (MCPWM_TIMER0_SYNCI_EN_V << MCPWM_TIMER0_SYNCI_EN_S) +#define MCPWM_TIMER0_SYNCI_EN_V 0x00000001U #define MCPWM_TIMER0_SYNCI_EN_S 0 +/** MCPWM_TIMER0_SYNC_SW : R/W; bitpos: [1]; default: 0; + * Toggling this bit will trigger a software sync. + */ +#define MCPWM_TIMER0_SYNC_SW (BIT(1)) +#define MCPWM_TIMER0_SYNC_SW_M (MCPWM_TIMER0_SYNC_SW_V << MCPWM_TIMER0_SYNC_SW_S) +#define MCPWM_TIMER0_SYNC_SW_V 0x00000001U +#define MCPWM_TIMER0_SYNC_SW_S 1 +/** MCPWM_TIMER0_SYNCO_SEL : R/W; bitpos: [3:2]; default: 0; + * PWM timer0 sync_out selection, 0: sync_in, 1: TEZ, 2: TEP, and sync out will always + * generate when toggling the reg_timer0_sync_sw bit + */ +#define MCPWM_TIMER0_SYNCO_SEL 0x00000003U +#define MCPWM_TIMER0_SYNCO_SEL_M (MCPWM_TIMER0_SYNCO_SEL_V << MCPWM_TIMER0_SYNCO_SEL_S) +#define MCPWM_TIMER0_SYNCO_SEL_V 0x00000003U +#define MCPWM_TIMER0_SYNCO_SEL_S 2 +/** MCPWM_TIMER0_PHASE : R/W; bitpos: [19:4]; default: 0; + * phase for timer reload on sync event + */ +#define MCPWM_TIMER0_PHASE 0x0000FFFFU +#define MCPWM_TIMER0_PHASE_M (MCPWM_TIMER0_PHASE_V << MCPWM_TIMER0_PHASE_S) +#define MCPWM_TIMER0_PHASE_V 0x0000FFFFU +#define MCPWM_TIMER0_PHASE_S 4 +/** MCPWM_TIMER0_PHASE_DIRECTION : R/W; bitpos: [20]; default: 0; + * Configure the PWM timer0's direction at the time sync event occurs when timer0 mode + * is up-down mode: 0-increase,1-decrease + */ +#define MCPWM_TIMER0_PHASE_DIRECTION (BIT(20)) +#define MCPWM_TIMER0_PHASE_DIRECTION_M (MCPWM_TIMER0_PHASE_DIRECTION_V << MCPWM_TIMER0_PHASE_DIRECTION_S) +#define MCPWM_TIMER0_PHASE_DIRECTION_V 0x00000001U +#define MCPWM_TIMER0_PHASE_DIRECTION_S 20 -#define MCPWM_TIMER0_STATUS_REG(i) (REG_MCPWM_BASE(i) + 0x0010) -/* MCPWM_TIMER0_DIRECTION : RO ;bitpos:[16] ;default: 1'd0 ; */ -/*description: Current PWM timer0 counter direction 0: increment 1: decrement*/ -#define MCPWM_TIMER0_DIRECTION (BIT(16)) -#define MCPWM_TIMER0_DIRECTION_M (BIT(16)) -#define MCPWM_TIMER0_DIRECTION_V 0x1 -#define MCPWM_TIMER0_DIRECTION_S 16 -/* MCPWM_TIMER0_VALUE : RO ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: Current PWM timer0 counter value*/ -#define MCPWM_TIMER0_VALUE 0x0000FFFF -#define MCPWM_TIMER0_VALUE_M ((MCPWM_TIMER0_VALUE_V)<<(MCPWM_TIMER0_VALUE_S)) -#define MCPWM_TIMER0_VALUE_V 0xFFFF +/** MCPWM_TIMER0_STATUS_REG register + * PWM timer0 status register. + */ +#define MCPWM_TIMER0_STATUS_REG(i) (DR_REG_MCPWM_BASE(i) + 0x10) +/** MCPWM_TIMER0_VALUE : RO; bitpos: [15:0]; default: 0; + * current PWM timer0 counter value + */ +#define MCPWM_TIMER0_VALUE 0x0000FFFFU +#define MCPWM_TIMER0_VALUE_M (MCPWM_TIMER0_VALUE_V << MCPWM_TIMER0_VALUE_S) +#define MCPWM_TIMER0_VALUE_V 0x0000FFFFU #define MCPWM_TIMER0_VALUE_S 0 +/** MCPWM_TIMER0_DIRECTION : RO; bitpos: [16]; default: 0; + * current PWM timer0 counter direction, 0: increment 1: decrement + */ +#define MCPWM_TIMER0_DIRECTION (BIT(16)) +#define MCPWM_TIMER0_DIRECTION_M (MCPWM_TIMER0_DIRECTION_V << MCPWM_TIMER0_DIRECTION_S) +#define MCPWM_TIMER0_DIRECTION_V 0x00000001U +#define MCPWM_TIMER0_DIRECTION_S 16 -#define MCPWM_TIMER1_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0x0014) -/* MCPWM_TIMER1_PERIOD_UPMETHOD : R/W ;bitpos:[25:24] ;default: 2'd0 ; */ -/*description: Update method for active reg of PWM timer1 period 0: immediate - 1: TEZ 2: sync 3: TEZ or sync*/ -#define MCPWM_TIMER1_PERIOD_UPMETHOD 0x00000003 -#define MCPWM_TIMER1_PERIOD_UPMETHOD_M ((MCPWM_TIMER1_PERIOD_UPMETHOD_V)<<(MCPWM_TIMER1_PERIOD_UPMETHOD_S)) -#define MCPWM_TIMER1_PERIOD_UPMETHOD_V 0x3 -#define MCPWM_TIMER1_PERIOD_UPMETHOD_S 24 -/* MCPWM_TIMER1_PERIOD : R/W ;bitpos:[23:8] ;default: 16'h00ff ; */ -/*description: Period shadow reg of PWM timer1*/ -#define MCPWM_TIMER1_PERIOD 0x0000FFFF -#define MCPWM_TIMER1_PERIOD_M ((MCPWM_TIMER1_PERIOD_V)<<(MCPWM_TIMER1_PERIOD_S)) -#define MCPWM_TIMER1_PERIOD_V 0xFFFF -#define MCPWM_TIMER1_PERIOD_S 8 -/* MCPWM_TIMER1_PRESCALE : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ -/*description: Period of PT1_clk = Period of PWM_clk * (PWM_TIMER1_PRESCALE + 1)*/ -#define MCPWM_TIMER1_PRESCALE 0x000000FF -#define MCPWM_TIMER1_PRESCALE_M ((MCPWM_TIMER1_PRESCALE_V)<<(MCPWM_TIMER1_PRESCALE_S)) -#define MCPWM_TIMER1_PRESCALE_V 0xFF +/** MCPWM_TIMER1_CFG0_REG register + * PWM timer1 period and update method configuration register. + */ +#define MCPWM_TIMER1_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0x14) +/** MCPWM_TIMER1_PRESCALE : R/W; bitpos: [7:0]; default: 0; + * Configure the divisor of PT1_clk, takes effect when PWM timer1 stops and starts + * agsin. period of PT1_clk = Period of PWM_clk * (PWM_TIMER1_PRESCALE + 1) + */ +#define MCPWM_TIMER1_PRESCALE 0x000000FFU +#define MCPWM_TIMER1_PRESCALE_M (MCPWM_TIMER1_PRESCALE_V << MCPWM_TIMER1_PRESCALE_S) +#define MCPWM_TIMER1_PRESCALE_V 0x000000FFU #define MCPWM_TIMER1_PRESCALE_S 0 +/** MCPWM_TIMER1_PERIOD : R/W; bitpos: [23:8]; default: 255; + * period shadow register of PWM timer1 + */ +#define MCPWM_TIMER1_PERIOD 0x0000FFFFU +#define MCPWM_TIMER1_PERIOD_M (MCPWM_TIMER1_PERIOD_V << MCPWM_TIMER1_PERIOD_S) +#define MCPWM_TIMER1_PERIOD_V 0x0000FFFFU +#define MCPWM_TIMER1_PERIOD_S 8 +/** MCPWM_TIMER1_PERIOD_UPMETHOD : R/W; bitpos: [25:24]; default: 0; + * Update method for active register of PWM timer1 period, 0: immediate, 1: TEZ, 2: + * sync, 3: TEZ | sync. TEZ here and below means timer equal zero event + */ +#define MCPWM_TIMER1_PERIOD_UPMETHOD 0x00000003U +#define MCPWM_TIMER1_PERIOD_UPMETHOD_M (MCPWM_TIMER1_PERIOD_UPMETHOD_V << MCPWM_TIMER1_PERIOD_UPMETHOD_S) +#define MCPWM_TIMER1_PERIOD_UPMETHOD_V 0x00000003U +#define MCPWM_TIMER1_PERIOD_UPMETHOD_S 24 -#define MCPWM_TIMER1_CFG1_REG(i) (REG_MCPWM_BASE(i) + 0x0018) -/* MCPWM_TIMER1_MOD : R/W ;bitpos:[4:3] ;default: 2'h0 ; */ -/*description: PWM timer1 working mode 0: freeze 1: increase mod 2: decrease - mod 3: up-down mod*/ -#define MCPWM_TIMER1_MOD 0x00000003 -#define MCPWM_TIMER1_MOD_M ((MCPWM_TIMER1_MOD_V)<<(MCPWM_TIMER1_MOD_S)) -#define MCPWM_TIMER1_MOD_V 0x3 -#define MCPWM_TIMER1_MOD_S 3 -/* MCPWM_TIMER1_START : R/W ;bitpos:[2:0] ;default: 3'h0 ; */ -/*description: PWM timer1 start and stop control. 0: stop @ TEZ 1: stop @ TEP - 2: free run 3: start and stop @ next TEZ 4: start and stop @ next TEP.*/ -#define MCPWM_TIMER1_START 0x00000007 -#define MCPWM_TIMER1_START_M ((MCPWM_TIMER1_START_V)<<(MCPWM_TIMER1_START_S)) -#define MCPWM_TIMER1_START_V 0x7 +/** MCPWM_TIMER1_CFG1_REG register + * PWM timer1 working mode and start/stop control configuration register. + */ +#define MCPWM_TIMER1_CFG1_REG(i) (DR_REG_MCPWM_BASE(i) + 0x18) +/** MCPWM_TIMER1_START : R/W/SC; bitpos: [2:0]; default: 0; + * PWM timer1 start and stop control. 0: if PWM timer1 starts, then stops at TEZ, 1: + * if timer1 starts, then stops at TEP, 2: PWM timer1 starts and runs on, 3: timer1 + * starts and stops at the next TEZ, 4: timer1 starts and stops at the next TEP. TEP + * here and below means the event that happens when the timer equals to period + */ +#define MCPWM_TIMER1_START 0x00000007U +#define MCPWM_TIMER1_START_M (MCPWM_TIMER1_START_V << MCPWM_TIMER1_START_S) +#define MCPWM_TIMER1_START_V 0x00000007U #define MCPWM_TIMER1_START_S 0 +/** MCPWM_TIMER1_MOD : R/W; bitpos: [4:3]; default: 0; + * PWM timer1 working mode, 0: freeze, 1: increase mode, 2: decrease mode, 3: up-down + * mode + */ +#define MCPWM_TIMER1_MOD 0x00000003U +#define MCPWM_TIMER1_MOD_M (MCPWM_TIMER1_MOD_V << MCPWM_TIMER1_MOD_S) +#define MCPWM_TIMER1_MOD_V 0x00000003U +#define MCPWM_TIMER1_MOD_S 3 -#define MCPWM_TIMER1_SYNC_REG(i) (REG_MCPWM_BASE(i) + 0x001c) -/* MCPWM_TIMER1_PHASE : R/W ;bitpos:[20:4] ;default: 17'd0 ; */ -/*description: Phase for timer reload on sync event*/ -#define MCPWM_TIMER1_PHASE 0x0001FFFF -#define MCPWM_TIMER1_PHASE_M ((MCPWM_TIMER1_PHASE_V)<<(MCPWM_TIMER1_PHASE_S)) -#define MCPWM_TIMER1_PHASE_V 0x1FFFF -#define MCPWM_TIMER1_PHASE_S 4 -/* MCPWM_TIMER1_SYNCO_SEL : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: PWM timer1 synco selection 0: synci 1: TEZ 2: TEP else 0*/ -#define MCPWM_TIMER1_SYNCO_SEL 0x00000003 -#define MCPWM_TIMER1_SYNCO_SEL_M ((MCPWM_TIMER1_SYNCO_SEL_V)<<(MCPWM_TIMER1_SYNCO_SEL_S)) -#define MCPWM_TIMER1_SYNCO_SEL_V 0x3 -#define MCPWM_TIMER1_SYNCO_SEL_S 2 -/* MCPWM_TIMER1_SYNC_SW : R/W ;bitpos:[1] ;default: 1'h0 ; */ -/*description: Toggling this bit will trigger a software sync*/ -#define MCPWM_TIMER1_SYNC_SW (BIT(1)) -#define MCPWM_TIMER1_SYNC_SW_M (BIT(1)) -#define MCPWM_TIMER1_SYNC_SW_V 0x1 -#define MCPWM_TIMER1_SYNC_SW_S 1 -/* MCPWM_TIMER1_SYNCI_EN : R/W ;bitpos:[0] ;default: 1'h0 ; */ -/*description: When set timer reload with phase on sync input event is enabled*/ -#define MCPWM_TIMER1_SYNCI_EN (BIT(0)) -#define MCPWM_TIMER1_SYNCI_EN_M (BIT(0)) -#define MCPWM_TIMER1_SYNCI_EN_V 0x1 +/** MCPWM_TIMER1_SYNC_REG register + * PWM timer1 sync function configuration register. + */ +#define MCPWM_TIMER1_SYNC_REG(i) (DR_REG_MCPWM_BASE(i) + 0x1c) +/** MCPWM_TIMER1_SYNCI_EN : R/W; bitpos: [0]; default: 0; + * When set, timer reloading with phase on sync input event is enabled. + */ +#define MCPWM_TIMER1_SYNCI_EN (BIT(0)) +#define MCPWM_TIMER1_SYNCI_EN_M (MCPWM_TIMER1_SYNCI_EN_V << MCPWM_TIMER1_SYNCI_EN_S) +#define MCPWM_TIMER1_SYNCI_EN_V 0x00000001U #define MCPWM_TIMER1_SYNCI_EN_S 0 +/** MCPWM_TIMER1_SYNC_SW : R/W; bitpos: [1]; default: 0; + * Toggling this bit will trigger a software sync. + */ +#define MCPWM_TIMER1_SYNC_SW (BIT(1)) +#define MCPWM_TIMER1_SYNC_SW_M (MCPWM_TIMER1_SYNC_SW_V << MCPWM_TIMER1_SYNC_SW_S) +#define MCPWM_TIMER1_SYNC_SW_V 0x00000001U +#define MCPWM_TIMER1_SYNC_SW_S 1 +/** MCPWM_TIMER1_SYNCO_SEL : R/W; bitpos: [3:2]; default: 0; + * PWM timer1 sync_out selection, 0: sync_in, 1: TEZ, 2: TEP, and sync out will always + * generate when toggling the reg_timer1_sync_sw bit + */ +#define MCPWM_TIMER1_SYNCO_SEL 0x00000003U +#define MCPWM_TIMER1_SYNCO_SEL_M (MCPWM_TIMER1_SYNCO_SEL_V << MCPWM_TIMER1_SYNCO_SEL_S) +#define MCPWM_TIMER1_SYNCO_SEL_V 0x00000003U +#define MCPWM_TIMER1_SYNCO_SEL_S 2 +/** MCPWM_TIMER1_PHASE : R/W; bitpos: [19:4]; default: 0; + * phase for timer reload on sync event + */ +#define MCPWM_TIMER1_PHASE 0x0000FFFFU +#define MCPWM_TIMER1_PHASE_M (MCPWM_TIMER1_PHASE_V << MCPWM_TIMER1_PHASE_S) +#define MCPWM_TIMER1_PHASE_V 0x0000FFFFU +#define MCPWM_TIMER1_PHASE_S 4 +/** MCPWM_TIMER1_PHASE_DIRECTION : R/W; bitpos: [20]; default: 0; + * Configure the PWM timer1's direction at the time sync event occurs when timer1 mode + * is up-down mode: 0-increase,1-decrease + */ +#define MCPWM_TIMER1_PHASE_DIRECTION (BIT(20)) +#define MCPWM_TIMER1_PHASE_DIRECTION_M (MCPWM_TIMER1_PHASE_DIRECTION_V << MCPWM_TIMER1_PHASE_DIRECTION_S) +#define MCPWM_TIMER1_PHASE_DIRECTION_V 0x00000001U +#define MCPWM_TIMER1_PHASE_DIRECTION_S 20 -#define MCPWM_TIMER1_STATUS_REG(i) (REG_MCPWM_BASE(i) + 0x0020) -/* MCPWM_TIMER1_DIRECTION : RO ;bitpos:[16] ;default: 1'd0 ; */ -/*description: Current PWM timer1 counter direction 0: increment 1: decrement*/ -#define MCPWM_TIMER1_DIRECTION (BIT(16)) -#define MCPWM_TIMER1_DIRECTION_M (BIT(16)) -#define MCPWM_TIMER1_DIRECTION_V 0x1 -#define MCPWM_TIMER1_DIRECTION_S 16 -/* MCPWM_TIMER1_VALUE : RO ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: Current PWM timer1 counter value*/ -#define MCPWM_TIMER1_VALUE 0x0000FFFF -#define MCPWM_TIMER1_VALUE_M ((MCPWM_TIMER1_VALUE_V)<<(MCPWM_TIMER1_VALUE_S)) -#define MCPWM_TIMER1_VALUE_V 0xFFFF +/** MCPWM_TIMER1_STATUS_REG register + * PWM timer1 status register. + */ +#define MCPWM_TIMER1_STATUS_REG(i) (DR_REG_MCPWM_BASE(i) + 0x20) +/** MCPWM_TIMER1_VALUE : RO; bitpos: [15:0]; default: 0; + * current PWM timer1 counter value + */ +#define MCPWM_TIMER1_VALUE 0x0000FFFFU +#define MCPWM_TIMER1_VALUE_M (MCPWM_TIMER1_VALUE_V << MCPWM_TIMER1_VALUE_S) +#define MCPWM_TIMER1_VALUE_V 0x0000FFFFU #define MCPWM_TIMER1_VALUE_S 0 +/** MCPWM_TIMER1_DIRECTION : RO; bitpos: [16]; default: 0; + * current PWM timer1 counter direction, 0: increment 1: decrement + */ +#define MCPWM_TIMER1_DIRECTION (BIT(16)) +#define MCPWM_TIMER1_DIRECTION_M (MCPWM_TIMER1_DIRECTION_V << MCPWM_TIMER1_DIRECTION_S) +#define MCPWM_TIMER1_DIRECTION_V 0x00000001U +#define MCPWM_TIMER1_DIRECTION_S 16 -#define MCPWM_TIMER2_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0x0024) -/* MCPWM_TIMER2_PERIOD_UPMETHOD : R/W ;bitpos:[25:24] ;default: 2'd0 ; */ -/*description: Update method for active reg of PWM timer2 period 0: immediate - 1: TEZ 2: sync 3: TEZ or sync*/ -#define MCPWM_TIMER2_PERIOD_UPMETHOD 0x00000003 -#define MCPWM_TIMER2_PERIOD_UPMETHOD_M ((MCPWM_TIMER2_PERIOD_UPMETHOD_V)<<(MCPWM_TIMER2_PERIOD_UPMETHOD_S)) -#define MCPWM_TIMER2_PERIOD_UPMETHOD_V 0x3 -#define MCPWM_TIMER2_PERIOD_UPMETHOD_S 24 -/* MCPWM_TIMER2_PERIOD : R/W ;bitpos:[23:8] ;default: 16'h00ff ; */ -/*description: Period shadow reg of PWM timer2*/ -#define MCPWM_TIMER2_PERIOD 0x0000FFFF -#define MCPWM_TIMER2_PERIOD_M ((MCPWM_TIMER2_PERIOD_V)<<(MCPWM_TIMER2_PERIOD_S)) -#define MCPWM_TIMER2_PERIOD_V 0xFFFF -#define MCPWM_TIMER2_PERIOD_S 8 -/* MCPWM_TIMER2_PRESCALE : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ -/*description: Period of PT2_clk = Period of PWM_clk * (PWM_TIMER2_PRESCALE + 1)*/ -#define MCPWM_TIMER2_PRESCALE 0x000000FF -#define MCPWM_TIMER2_PRESCALE_M ((MCPWM_TIMER2_PRESCALE_V)<<(MCPWM_TIMER2_PRESCALE_S)) -#define MCPWM_TIMER2_PRESCALE_V 0xFF +/** MCPWM_TIMER2_CFG0_REG register + * PWM timer2 period and update method configuration register. + */ +#define MCPWM_TIMER2_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0x24) +/** MCPWM_TIMER2_PRESCALE : R/W; bitpos: [7:0]; default: 0; + * Configure the divisor of PT2_clk, takes effect when PWM timer2 stops and starts + * agsin. period of PT2_clk = Period of PWM_clk * (PWM_TIMER2_PRESCALE + 1) + */ +#define MCPWM_TIMER2_PRESCALE 0x000000FFU +#define MCPWM_TIMER2_PRESCALE_M (MCPWM_TIMER2_PRESCALE_V << MCPWM_TIMER2_PRESCALE_S) +#define MCPWM_TIMER2_PRESCALE_V 0x000000FFU #define MCPWM_TIMER2_PRESCALE_S 0 +/** MCPWM_TIMER2_PERIOD : R/W; bitpos: [23:8]; default: 255; + * period shadow register of PWM timer2 + */ +#define MCPWM_TIMER2_PERIOD 0x0000FFFFU +#define MCPWM_TIMER2_PERIOD_M (MCPWM_TIMER2_PERIOD_V << MCPWM_TIMER2_PERIOD_S) +#define MCPWM_TIMER2_PERIOD_V 0x0000FFFFU +#define MCPWM_TIMER2_PERIOD_S 8 +/** MCPWM_TIMER2_PERIOD_UPMETHOD : R/W; bitpos: [25:24]; default: 0; + * Update method for active register of PWM timer2 period, 0: immediate, 1: TEZ, 2: + * sync, 3: TEZ | sync. TEZ here and below means timer equal zero event + */ +#define MCPWM_TIMER2_PERIOD_UPMETHOD 0x00000003U +#define MCPWM_TIMER2_PERIOD_UPMETHOD_M (MCPWM_TIMER2_PERIOD_UPMETHOD_V << MCPWM_TIMER2_PERIOD_UPMETHOD_S) +#define MCPWM_TIMER2_PERIOD_UPMETHOD_V 0x00000003U +#define MCPWM_TIMER2_PERIOD_UPMETHOD_S 24 -#define MCPWM_TIMER2_CFG1_REG(i) (REG_MCPWM_BASE(i) + 0x0028) -/* MCPWM_TIMER2_MOD : R/W ;bitpos:[4:3] ;default: 2'h0 ; */ -/*description: PWM timer2 working mode 0: freeze 1: increase mod 2: decrease - mod 3: up-down mod*/ -#define MCPWM_TIMER2_MOD 0x00000003 -#define MCPWM_TIMER2_MOD_M ((MCPWM_TIMER2_MOD_V)<<(MCPWM_TIMER2_MOD_S)) -#define MCPWM_TIMER2_MOD_V 0x3 -#define MCPWM_TIMER2_MOD_S 3 -/* MCPWM_TIMER2_START : R/W ;bitpos:[2:0] ;default: 3'h0 ; */ -/*description: PWM timer2 start and stop control. 0: stop @ TEZ 1: stop @ TEP - 2: free run 3: start and stop @ next TEZ 4: start and stop @ next TEP.*/ -#define MCPWM_TIMER2_START 0x00000007 -#define MCPWM_TIMER2_START_M ((MCPWM_TIMER2_START_V)<<(MCPWM_TIMER2_START_S)) -#define MCPWM_TIMER2_START_V 0x7 +/** MCPWM_TIMER2_CFG1_REG register + * PWM timer2 working mode and start/stop control configuration register. + */ +#define MCPWM_TIMER2_CFG1_REG(i) (DR_REG_MCPWM_BASE(i) + 0x28) +/** MCPWM_TIMER2_START : R/W/SC; bitpos: [2:0]; default: 0; + * PWM timer2 start and stop control. 0: if PWM timer2 starts, then stops at TEZ, 1: + * if timer2 starts, then stops at TEP, 2: PWM timer2 starts and runs on, 3: timer2 + * starts and stops at the next TEZ, 4: timer2 starts and stops at the next TEP. TEP + * here and below means the event that happens when the timer equals to period + */ +#define MCPWM_TIMER2_START 0x00000007U +#define MCPWM_TIMER2_START_M (MCPWM_TIMER2_START_V << MCPWM_TIMER2_START_S) +#define MCPWM_TIMER2_START_V 0x00000007U #define MCPWM_TIMER2_START_S 0 +/** MCPWM_TIMER2_MOD : R/W; bitpos: [4:3]; default: 0; + * PWM timer2 working mode, 0: freeze, 1: increase mode, 2: decrease mode, 3: up-down + * mode + */ +#define MCPWM_TIMER2_MOD 0x00000003U +#define MCPWM_TIMER2_MOD_M (MCPWM_TIMER2_MOD_V << MCPWM_TIMER2_MOD_S) +#define MCPWM_TIMER2_MOD_V 0x00000003U +#define MCPWM_TIMER2_MOD_S 3 -#define MCPWM_TIMER2_SYNC_REG(i) (REG_MCPWM_BASE(i) + 0x002c) -/* MCPWM_TIMER2_PHASE : R/W ;bitpos:[20:4] ;default: 17'd0 ; */ -/*description: Phase for timer reload on sync event*/ -#define MCPWM_TIMER2_PHASE 0x0001FFFF -#define MCPWM_TIMER2_PHASE_M ((MCPWM_TIMER2_PHASE_V)<<(MCPWM_TIMER2_PHASE_S)) -#define MCPWM_TIMER2_PHASE_V 0x1FFFF -#define MCPWM_TIMER2_PHASE_S 4 -/* MCPWM_TIMER2_SYNCO_SEL : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: PWM timer2 synco selection 0: synci 1: TEZ 2: TEP else 0*/ -#define MCPWM_TIMER2_SYNCO_SEL 0x00000003 -#define MCPWM_TIMER2_SYNCO_SEL_M ((MCPWM_TIMER2_SYNCO_SEL_V)<<(MCPWM_TIMER2_SYNCO_SEL_S)) -#define MCPWM_TIMER2_SYNCO_SEL_V 0x3 -#define MCPWM_TIMER2_SYNCO_SEL_S 2 -/* MCPWM_TIMER2_SYNC_SW : R/W ;bitpos:[1] ;default: 1'h0 ; */ -/*description: Toggling this bit will trigger a software sync*/ -#define MCPWM_TIMER2_SYNC_SW (BIT(1)) -#define MCPWM_TIMER2_SYNC_SW_M (BIT(1)) -#define MCPWM_TIMER2_SYNC_SW_V 0x1 -#define MCPWM_TIMER2_SYNC_SW_S 1 -/* MCPWM_TIMER2_SYNCI_EN : R/W ;bitpos:[0] ;default: 1'h0 ; */ -/*description: When set timer reload with phase on sync input event is enabled*/ -#define MCPWM_TIMER2_SYNCI_EN (BIT(0)) -#define MCPWM_TIMER2_SYNCI_EN_M (BIT(0)) -#define MCPWM_TIMER2_SYNCI_EN_V 0x1 +/** MCPWM_TIMER2_SYNC_REG register + * PWM timer2 sync function configuration register. + */ +#define MCPWM_TIMER2_SYNC_REG(i) (DR_REG_MCPWM_BASE(i) + 0x2c) +/** MCPWM_TIMER2_SYNCI_EN : R/W; bitpos: [0]; default: 0; + * When set, timer reloading with phase on sync input event is enabled. + */ +#define MCPWM_TIMER2_SYNCI_EN (BIT(0)) +#define MCPWM_TIMER2_SYNCI_EN_M (MCPWM_TIMER2_SYNCI_EN_V << MCPWM_TIMER2_SYNCI_EN_S) +#define MCPWM_TIMER2_SYNCI_EN_V 0x00000001U #define MCPWM_TIMER2_SYNCI_EN_S 0 +/** MCPWM_TIMER2_SYNC_SW : R/W; bitpos: [1]; default: 0; + * Toggling this bit will trigger a software sync. + */ +#define MCPWM_TIMER2_SYNC_SW (BIT(1)) +#define MCPWM_TIMER2_SYNC_SW_M (MCPWM_TIMER2_SYNC_SW_V << MCPWM_TIMER2_SYNC_SW_S) +#define MCPWM_TIMER2_SYNC_SW_V 0x00000001U +#define MCPWM_TIMER2_SYNC_SW_S 1 +/** MCPWM_TIMER2_SYNCO_SEL : R/W; bitpos: [3:2]; default: 0; + * PWM timer2 sync_out selection, 0: sync_in, 1: TEZ, 2: TEP, and sync out will always + * generate when toggling the reg_timer0_sync_sw bit + */ +#define MCPWM_TIMER2_SYNCO_SEL 0x00000003U +#define MCPWM_TIMER2_SYNCO_SEL_M (MCPWM_TIMER2_SYNCO_SEL_V << MCPWM_TIMER2_SYNCO_SEL_S) +#define MCPWM_TIMER2_SYNCO_SEL_V 0x00000003U +#define MCPWM_TIMER2_SYNCO_SEL_S 2 +/** MCPWM_TIMER2_PHASE : R/W; bitpos: [19:4]; default: 0; + * phase for timer reload on sync event + */ +#define MCPWM_TIMER2_PHASE 0x0000FFFFU +#define MCPWM_TIMER2_PHASE_M (MCPWM_TIMER2_PHASE_V << MCPWM_TIMER2_PHASE_S) +#define MCPWM_TIMER2_PHASE_V 0x0000FFFFU +#define MCPWM_TIMER2_PHASE_S 4 +/** MCPWM_TIMER2_PHASE_DIRECTION : R/W; bitpos: [20]; default: 0; + * Configure the PWM timer2's direction at the time sync event occurs when timer2 mode + * is up-down mode: 0-increase,1-decrease + */ +#define MCPWM_TIMER2_PHASE_DIRECTION (BIT(20)) +#define MCPWM_TIMER2_PHASE_DIRECTION_M (MCPWM_TIMER2_PHASE_DIRECTION_V << MCPWM_TIMER2_PHASE_DIRECTION_S) +#define MCPWM_TIMER2_PHASE_DIRECTION_V 0x00000001U +#define MCPWM_TIMER2_PHASE_DIRECTION_S 20 -#define MCPWM_TIMER2_STATUS_REG(i) (REG_MCPWM_BASE(i) + 0x0030) -/* MCPWM_TIMER2_DIRECTION : RO ;bitpos:[16] ;default: 1'd0 ; */ -/*description: Current PWM timer2 counter direction 0: increment 1: decrement*/ -#define MCPWM_TIMER2_DIRECTION (BIT(16)) -#define MCPWM_TIMER2_DIRECTION_M (BIT(16)) -#define MCPWM_TIMER2_DIRECTION_V 0x1 -#define MCPWM_TIMER2_DIRECTION_S 16 -/* MCPWM_TIMER2_VALUE : RO ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: Current PWM timer2 counter value*/ -#define MCPWM_TIMER2_VALUE 0x0000FFFF -#define MCPWM_TIMER2_VALUE_M ((MCPWM_TIMER2_VALUE_V)<<(MCPWM_TIMER2_VALUE_S)) -#define MCPWM_TIMER2_VALUE_V 0xFFFF +/** MCPWM_TIMER2_STATUS_REG register + * PWM timer2 status register. + */ +#define MCPWM_TIMER2_STATUS_REG(i) (DR_REG_MCPWM_BASE(i) + 0x30) +/** MCPWM_TIMER2_VALUE : RO; bitpos: [15:0]; default: 0; + * current PWM timer2 counter value + */ +#define MCPWM_TIMER2_VALUE 0x0000FFFFU +#define MCPWM_TIMER2_VALUE_M (MCPWM_TIMER2_VALUE_V << MCPWM_TIMER2_VALUE_S) +#define MCPWM_TIMER2_VALUE_V 0x0000FFFFU #define MCPWM_TIMER2_VALUE_S 0 +/** MCPWM_TIMER2_DIRECTION : RO; bitpos: [16]; default: 0; + * current PWM timer2 counter direction, 0: increment 1: decrement + */ +#define MCPWM_TIMER2_DIRECTION (BIT(16)) +#define MCPWM_TIMER2_DIRECTION_M (MCPWM_TIMER2_DIRECTION_V << MCPWM_TIMER2_DIRECTION_S) +#define MCPWM_TIMER2_DIRECTION_V 0x00000001U +#define MCPWM_TIMER2_DIRECTION_S 16 -#define MCPWM_TIMER_SYNCI_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x0034) -/* MCPWM_EXTERNAL_SYNCI2_INVERT : R/W ;bitpos:[11] ;default: 1'd0 ; */ -/*description: Onvert SYNC2 from GPIO matrix*/ -#define MCPWM_EXTERNAL_SYNCI2_INVERT (BIT(11)) -#define MCPWM_EXTERNAL_SYNCI2_INVERT_M (BIT(11)) -#define MCPWM_EXTERNAL_SYNCI2_INVERT_V 0x1 -#define MCPWM_EXTERNAL_SYNCI2_INVERT_S 11 -/* MCPWM_EXTERNAL_SYNCI1_INVERT : R/W ;bitpos:[10] ;default: 1'd0 ; */ -/*description: Invert SYNC1 from GPIO matrix*/ -#define MCPWM_EXTERNAL_SYNCI1_INVERT (BIT(10)) -#define MCPWM_EXTERNAL_SYNCI1_INVERT_M (BIT(10)) -#define MCPWM_EXTERNAL_SYNCI1_INVERT_V 0x1 -#define MCPWM_EXTERNAL_SYNCI1_INVERT_S 10 -/* MCPWM_EXTERNAL_SYNCI0_INVERT : R/W ;bitpos:[9] ;default: 1'd0 ; */ -/*description: Invert SYNC0 from GPIO matrix*/ -#define MCPWM_EXTERNAL_SYNCI0_INVERT (BIT(9)) -#define MCPWM_EXTERNAL_SYNCI0_INVERT_M (BIT(9)) -#define MCPWM_EXTERNAL_SYNCI0_INVERT_V 0x1 -#define MCPWM_EXTERNAL_SYNCI0_INVERT_S 9 -/* MCPWM_TIMER2_SYNCISEL : R/W ;bitpos:[8:6] ;default: 3'd0 ; */ -/*description: Select sync input for PWM timer2 1: PWM timer0 synco 2: PWM - timer1 synco 3: PWM timer2 synco 4: SYNC0 from GPIO matrix 5: SYNC1 from GPIO matrix 6: SYNC2 from GPIO matrix other values: no sync input selected*/ -#define MCPWM_TIMER2_SYNCISEL 0x00000007 -#define MCPWM_TIMER2_SYNCISEL_M ((MCPWM_TIMER2_SYNCISEL_V)<<(MCPWM_TIMER2_SYNCISEL_S)) -#define MCPWM_TIMER2_SYNCISEL_V 0x7 -#define MCPWM_TIMER2_SYNCISEL_S 6 -/* MCPWM_TIMER1_SYNCISEL : R/W ;bitpos:[5:3] ;default: 3'd0 ; */ -/*description: Select sync input for PWM timer1 1: PWM timer0 synco 2: PWM - timer1 synco 3: PWM timer2 synco 4: SYNC0 from GPIO matrix 5: SYNC1 from GPIO matrix 6: SYNC2 from GPIO matrix other values: no sync input selected*/ -#define MCPWM_TIMER1_SYNCISEL 0x00000007 -#define MCPWM_TIMER1_SYNCISEL_M ((MCPWM_TIMER1_SYNCISEL_V)<<(MCPWM_TIMER1_SYNCISEL_S)) -#define MCPWM_TIMER1_SYNCISEL_V 0x7 -#define MCPWM_TIMER1_SYNCISEL_S 3 -/* MCPWM_TIMER0_SYNCISEL : R/W ;bitpos:[2:0] ;default: 3'd0 ; */ -/*description: Select sync input for PWM timer0 1: PWM timer0 synco 2: PWM - timer1 synco 3: PWM timer2 synco 4: SYNC0 from GPIO matrix 5: SYNC1 from GPIO matrix 6: SYNC2 from GPIO matrix other values: no sync input selected*/ -#define MCPWM_TIMER0_SYNCISEL 0x00000007 -#define MCPWM_TIMER0_SYNCISEL_M ((MCPWM_TIMER0_SYNCISEL_V)<<(MCPWM_TIMER0_SYNCISEL_S)) -#define MCPWM_TIMER0_SYNCISEL_V 0x7 +/** MCPWM_TIMER_SYNCI_CFG_REG register + * Synchronization input selection for three PWM timers. + */ +#define MCPWM_TIMER_SYNCI_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x34) +/** MCPWM_TIMER0_SYNCISEL : R/W; bitpos: [2:0]; default: 0; + * select sync input for PWM timer0, 1: PWM timer0 sync_out, 2: PWM timer1 sync_out, + * 3: PWM timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, 6: + * SYNC2 from GPIO matrix, other values: no sync input selected + */ +#define MCPWM_TIMER0_SYNCISEL 0x00000007U +#define MCPWM_TIMER0_SYNCISEL_M (MCPWM_TIMER0_SYNCISEL_V << MCPWM_TIMER0_SYNCISEL_S) +#define MCPWM_TIMER0_SYNCISEL_V 0x00000007U #define MCPWM_TIMER0_SYNCISEL_S 0 +/** MCPWM_TIMER1_SYNCISEL : R/W; bitpos: [5:3]; default: 0; + * select sync input for PWM timer1, 1: PWM timer0 sync_out, 2: PWM timer1 sync_out, + * 3: PWM timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, 6: + * SYNC2 from GPIO matrix, other values: no sync input selected + */ +#define MCPWM_TIMER1_SYNCISEL 0x00000007U +#define MCPWM_TIMER1_SYNCISEL_M (MCPWM_TIMER1_SYNCISEL_V << MCPWM_TIMER1_SYNCISEL_S) +#define MCPWM_TIMER1_SYNCISEL_V 0x00000007U +#define MCPWM_TIMER1_SYNCISEL_S 3 +/** MCPWM_TIMER2_SYNCISEL : R/W; bitpos: [8:6]; default: 0; + * select sync input for PWM timer2, 1: PWM timer0 sync_out, 2: PWM timer1 sync_out, + * 3: PWM timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, 6: + * SYNC2 from GPIO matrix, other values: no sync input selected + */ +#define MCPWM_TIMER2_SYNCISEL 0x00000007U +#define MCPWM_TIMER2_SYNCISEL_M (MCPWM_TIMER2_SYNCISEL_V << MCPWM_TIMER2_SYNCISEL_S) +#define MCPWM_TIMER2_SYNCISEL_V 0x00000007U +#define MCPWM_TIMER2_SYNCISEL_S 6 +/** MCPWM_EXTERNAL_SYNCI0_INVERT : R/W; bitpos: [9]; default: 0; + * invert SYNC0 from GPIO matrix + */ +#define MCPWM_EXTERNAL_SYNCI0_INVERT (BIT(9)) +#define MCPWM_EXTERNAL_SYNCI0_INVERT_M (MCPWM_EXTERNAL_SYNCI0_INVERT_V << MCPWM_EXTERNAL_SYNCI0_INVERT_S) +#define MCPWM_EXTERNAL_SYNCI0_INVERT_V 0x00000001U +#define MCPWM_EXTERNAL_SYNCI0_INVERT_S 9 +/** MCPWM_EXTERNAL_SYNCI1_INVERT : R/W; bitpos: [10]; default: 0; + * invert SYNC1 from GPIO matrix + */ +#define MCPWM_EXTERNAL_SYNCI1_INVERT (BIT(10)) +#define MCPWM_EXTERNAL_SYNCI1_INVERT_M (MCPWM_EXTERNAL_SYNCI1_INVERT_V << MCPWM_EXTERNAL_SYNCI1_INVERT_S) +#define MCPWM_EXTERNAL_SYNCI1_INVERT_V 0x00000001U +#define MCPWM_EXTERNAL_SYNCI1_INVERT_S 10 +/** MCPWM_EXTERNAL_SYNCI2_INVERT : R/W; bitpos: [11]; default: 0; + * invert SYNC2 from GPIO matrix + */ +#define MCPWM_EXTERNAL_SYNCI2_INVERT (BIT(11)) +#define MCPWM_EXTERNAL_SYNCI2_INVERT_M (MCPWM_EXTERNAL_SYNCI2_INVERT_V << MCPWM_EXTERNAL_SYNCI2_INVERT_S) +#define MCPWM_EXTERNAL_SYNCI2_INVERT_V 0x00000001U +#define MCPWM_EXTERNAL_SYNCI2_INVERT_S 11 -#define MCPWM_OPERATOR_TIMERSEL_REG(i) (REG_MCPWM_BASE(i) + 0x0038) -/* MCPWM_OPERATOR2_TIMERSEL : R/W ;bitpos:[5:4] ;default: 2'd0 ; */ -/*description: Select which PWM timer's is the timing reference for PWM operator2 - 0: timer0 1: timer1 2: timer2*/ -#define MCPWM_OPERATOR2_TIMERSEL 0x00000003 -#define MCPWM_OPERATOR2_TIMERSEL_M ((MCPWM_OPERATOR2_TIMERSEL_V)<<(MCPWM_OPERATOR2_TIMERSEL_S)) -#define MCPWM_OPERATOR2_TIMERSEL_V 0x3 -#define MCPWM_OPERATOR2_TIMERSEL_S 4 -/* MCPWM_OPERATOR1_TIMERSEL : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: Select which PWM timer's is the timing reference for PWM operator1 - 0: timer0 1: timer1 2: timer2*/ -#define MCPWM_OPERATOR1_TIMERSEL 0x00000003 -#define MCPWM_OPERATOR1_TIMERSEL_M ((MCPWM_OPERATOR1_TIMERSEL_V)<<(MCPWM_OPERATOR1_TIMERSEL_S)) -#define MCPWM_OPERATOR1_TIMERSEL_V 0x3 -#define MCPWM_OPERATOR1_TIMERSEL_S 2 -/* MCPWM_OPERATOR0_TIMERSEL : R/W ;bitpos:[1:0] ;default: 2'd0 ; */ -/*description: Select which PWM timer's is the timing reference for PWM operator0 - 0: timer0 1: timer1 2: timer2*/ -#define MCPWM_OPERATOR0_TIMERSEL 0x00000003 -#define MCPWM_OPERATOR0_TIMERSEL_M ((MCPWM_OPERATOR0_TIMERSEL_V)<<(MCPWM_OPERATOR0_TIMERSEL_S)) -#define MCPWM_OPERATOR0_TIMERSEL_V 0x3 +/** MCPWM_OPERATOR_TIMERSEL_REG register + * Select specific timer for PWM operators. + */ +#define MCPWM_OPERATOR_TIMERSEL_REG(i) (DR_REG_MCPWM_BASE(i) + 0x38) +/** MCPWM_OPERATOR0_TIMERSEL : R/W; bitpos: [1:0]; default: 0; + * Select which PWM timer is the timing reference for PWM operator0, 0: timer0, 1: + * timer1, 2: timer2 + */ +#define MCPWM_OPERATOR0_TIMERSEL 0x00000003U +#define MCPWM_OPERATOR0_TIMERSEL_M (MCPWM_OPERATOR0_TIMERSEL_V << MCPWM_OPERATOR0_TIMERSEL_S) +#define MCPWM_OPERATOR0_TIMERSEL_V 0x00000003U #define MCPWM_OPERATOR0_TIMERSEL_S 0 +/** MCPWM_OPERATOR1_TIMERSEL : R/W; bitpos: [3:2]; default: 0; + * Select which PWM timer is the timing reference for PWM operator1, 0: timer0, 1: + * timer1, 2: timer2 + */ +#define MCPWM_OPERATOR1_TIMERSEL 0x00000003U +#define MCPWM_OPERATOR1_TIMERSEL_M (MCPWM_OPERATOR1_TIMERSEL_V << MCPWM_OPERATOR1_TIMERSEL_S) +#define MCPWM_OPERATOR1_TIMERSEL_V 0x00000003U +#define MCPWM_OPERATOR1_TIMERSEL_S 2 +/** MCPWM_OPERATOR2_TIMERSEL : R/W; bitpos: [5:4]; default: 0; + * Select which PWM timer is the timing reference for PWM operator2, 0: timer0, 1: + * timer1, 2: timer2 + */ +#define MCPWM_OPERATOR2_TIMERSEL 0x00000003U +#define MCPWM_OPERATOR2_TIMERSEL_M (MCPWM_OPERATOR2_TIMERSEL_V << MCPWM_OPERATOR2_TIMERSEL_S) +#define MCPWM_OPERATOR2_TIMERSEL_V 0x00000003U +#define MCPWM_OPERATOR2_TIMERSEL_S 4 -#define MCPWM_GEN0_STMP_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x003c) -/* MCPWM_GEN0_B_SHDW_FULL : RO ;bitpos:[9] ;default: 1'd0 ; */ -/*description: Set and reset by hardware. If set PWM generator 0 time stamp - B's shadow reg is filled and waiting to be transferred to B's active reg. If cleared B's active reg has been updated with shadow reg latest value*/ -#define MCPWM_GEN0_B_SHDW_FULL (BIT(9)) -#define MCPWM_GEN0_B_SHDW_FULL_M (BIT(9)) -#define MCPWM_GEN0_B_SHDW_FULL_V 0x1 -#define MCPWM_GEN0_B_SHDW_FULL_S 9 -/* MCPWM_GEN0_A_SHDW_FULL : RO ;bitpos:[8] ;default: 1'd0 ; */ -/*description: Set and reset by hardware. If set PWM generator 0 time stamp - A's shadow reg is filled and waiting to be transferred to A's active reg. If cleared A's active reg has been updated with shadow reg latest value*/ -#define MCPWM_GEN0_A_SHDW_FULL (BIT(8)) -#define MCPWM_GEN0_A_SHDW_FULL_M (BIT(8)) -#define MCPWM_GEN0_A_SHDW_FULL_V 0x1 -#define MCPWM_GEN0_A_SHDW_FULL_S 8 -/* MCPWM_GEN0_B_UPMETHOD : R/W ;bitpos:[7:4] ;default: 4'd0 ; */ -/*description: Update method for PWM generator 0 time stamp B's active reg. - 0: immediate bit0: TEZ bit1: TEP bit2: sync bit3: disable update*/ -#define MCPWM_GEN0_B_UPMETHOD 0x0000000F -#define MCPWM_GEN0_B_UPMETHOD_M ((MCPWM_GEN0_B_UPMETHOD_V)<<(MCPWM_GEN0_B_UPMETHOD_S)) -#define MCPWM_GEN0_B_UPMETHOD_V 0xF -#define MCPWM_GEN0_B_UPMETHOD_S 4 -/* MCPWM_GEN0_A_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: Update method for PWM generator 0 time stamp A's active reg. - 0: immediate bit0: TEZ bit1: TEP bit2: sync bit3: disable update*/ -#define MCPWM_GEN0_A_UPMETHOD 0x0000000F -#define MCPWM_GEN0_A_UPMETHOD_M ((MCPWM_GEN0_A_UPMETHOD_V)<<(MCPWM_GEN0_A_UPMETHOD_S)) -#define MCPWM_GEN0_A_UPMETHOD_V 0xF +/** MCPWM_GEN0_STMP_CFG_REG register + * Transfer status and update method for time stamp registers A and B + */ +#define MCPWM_GEN0_STMP_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x3c) +/** MCPWM_GEN0_A_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for PWM generator 0 time stamp A's active register. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when + * bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + */ +#define MCPWM_GEN0_A_UPMETHOD 0x0000000FU +#define MCPWM_GEN0_A_UPMETHOD_M (MCPWM_GEN0_A_UPMETHOD_V << MCPWM_GEN0_A_UPMETHOD_S) +#define MCPWM_GEN0_A_UPMETHOD_V 0x0000000FU #define MCPWM_GEN0_A_UPMETHOD_S 0 +/** MCPWM_GEN0_B_UPMETHOD : R/W; bitpos: [7:4]; default: 0; + * Update method for PWM generator 0 time stamp B's active register. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when + * bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + */ +#define MCPWM_GEN0_B_UPMETHOD 0x0000000FU +#define MCPWM_GEN0_B_UPMETHOD_M (MCPWM_GEN0_B_UPMETHOD_V << MCPWM_GEN0_B_UPMETHOD_S) +#define MCPWM_GEN0_B_UPMETHOD_V 0x0000000FU +#define MCPWM_GEN0_B_UPMETHOD_S 4 +/** MCPWM_GEN0_A_SHDW_FULL : R/W/WTC/SC; bitpos: [8]; default: 0; + * Set and reset by hardware. If set, PWM generator 0 time stamp A's shadow reg is + * filled and waiting to be transferred to A's active reg. If cleared, A's active reg + * has been updated with shadow register latest value + */ +#define MCPWM_GEN0_A_SHDW_FULL (BIT(8)) +#define MCPWM_GEN0_A_SHDW_FULL_M (MCPWM_GEN0_A_SHDW_FULL_V << MCPWM_GEN0_A_SHDW_FULL_S) +#define MCPWM_GEN0_A_SHDW_FULL_V 0x00000001U +#define MCPWM_GEN0_A_SHDW_FULL_S 8 +/** MCPWM_GEN0_B_SHDW_FULL : R/W/WTC/SC; bitpos: [9]; default: 0; + * Set and reset by hardware. If set, PWM generator 0 time stamp B's shadow reg is + * filled and waiting to be transferred to B's active reg. If cleared, B's active reg + * has been updated with shadow register latest value + */ +#define MCPWM_GEN0_B_SHDW_FULL (BIT(9)) +#define MCPWM_GEN0_B_SHDW_FULL_M (MCPWM_GEN0_B_SHDW_FULL_V << MCPWM_GEN0_B_SHDW_FULL_S) +#define MCPWM_GEN0_B_SHDW_FULL_V 0x00000001U +#define MCPWM_GEN0_B_SHDW_FULL_S 9 -#define MCPWM_GEN0_TSTMP_A_REG(i) (REG_MCPWM_BASE(i) + 0x0040) -/* MCPWM_GEN0_A : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: PWM generator 0 time stamp A's shadow reg*/ -#define MCPWM_GEN0_A 0x0000FFFF -#define MCPWM_GEN0_A_M ((MCPWM_GEN0_A_V)<<(MCPWM_GEN0_A_S)) -#define MCPWM_GEN0_A_V 0xFFFF +/** MCPWM_GEN0_TSTMP_A_REG register + * PWM generator 0 shadow register for timer stamp A. + */ +#define MCPWM_GEN0_TSTMP_A_REG(i) (DR_REG_MCPWM_BASE(i) + 0x40) +/** MCPWM_GEN0_A : R/W; bitpos: [15:0]; default: 0; + * PWM generator 0 time stamp A's shadow register + */ +#define MCPWM_GEN0_A 0x0000FFFFU +#define MCPWM_GEN0_A_M (MCPWM_GEN0_A_V << MCPWM_GEN0_A_S) +#define MCPWM_GEN0_A_V 0x0000FFFFU #define MCPWM_GEN0_A_S 0 -#define MCPWM_GEN0_TSTMP_B_REG(i) (REG_MCPWM_BASE(i) + 0x0044) -/* MCPWM_GEN0_B : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: PWM generator 0 time stamp B's shadow reg*/ -#define MCPWM_GEN0_B 0x0000FFFF -#define MCPWM_GEN0_B_M ((MCPWM_GEN0_B_V)<<(MCPWM_GEN0_B_S)) -#define MCPWM_GEN0_B_V 0xFFFF +/** MCPWM_GEN0_TSTMP_B_REG register + * PWM generator 0 shadow register for timer stamp B. + */ +#define MCPWM_GEN0_TSTMP_B_REG(i) (DR_REG_MCPWM_BASE(i) + 0x44) +/** MCPWM_GEN0_B : R/W; bitpos: [15:0]; default: 0; + * PWM generator 0 time stamp B's shadow register + */ +#define MCPWM_GEN0_B 0x0000FFFFU +#define MCPWM_GEN0_B_M (MCPWM_GEN0_B_V << MCPWM_GEN0_B_S) +#define MCPWM_GEN0_B_V 0x0000FFFFU #define MCPWM_GEN0_B_S 0 -#define MCPWM_GEN0_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0x0048) -/* MCPWM_GEN0_T1_SEL : R/W ;bitpos:[9:7] ;default: 3'd0 ; */ -/*description: Source selection for PWM generator 0 event_t1 take effect immediately - 0: fault_event0 1: fault_event1 2: fault_event2 3: sync_taken 4: none*/ -#define MCPWM_GEN0_T1_SEL 0x00000007 -#define MCPWM_GEN0_T1_SEL_M ((MCPWM_GEN0_T1_SEL_V)<<(MCPWM_GEN0_T1_SEL_S)) -#define MCPWM_GEN0_T1_SEL_V 0x7 -#define MCPWM_GEN0_T1_SEL_S 7 -/* MCPWM_GEN0_T0_SEL : R/W ;bitpos:[6:4] ;default: 3'd0 ; */ -/*description: Source selection for PWM generator 0 event_t0 take effect immediately - 0: fault_event0 1: fault_event1 2: fault_event2 3: sync_taken 4: none*/ -#define MCPWM_GEN0_T0_SEL 0x00000007 -#define MCPWM_GEN0_T0_SEL_M ((MCPWM_GEN0_T0_SEL_V)<<(MCPWM_GEN0_T0_SEL_S)) -#define MCPWM_GEN0_T0_SEL_V 0x7 -#define MCPWM_GEN0_T0_SEL_S 4 -/* MCPWM_GEN0_CFG_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: Update method for PWM generator 0's active reg of configuration. - 0: immediate bit0: TEZ bit1: TEP bit2: sync. bit3: disable update*/ -#define MCPWM_GEN0_CFG_UPMETHOD 0x0000000F -#define MCPWM_GEN0_CFG_UPMETHOD_M ((MCPWM_GEN0_CFG_UPMETHOD_V)<<(MCPWM_GEN0_CFG_UPMETHOD_S)) -#define MCPWM_GEN0_CFG_UPMETHOD_V 0xF +/** MCPWM_GEN0_CFG0_REG register + * PWM generator 0 event T0 and T1 handling + */ +#define MCPWM_GEN0_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0x48) +/** MCPWM_GEN0_CFG_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for PWM generator 0's active register of configuration. When all bits + * are set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to + * 1:TEP,when bit2 is set to 1:sync,when bit3 is set to 1:disable the update + */ +#define MCPWM_GEN0_CFG_UPMETHOD 0x0000000FU +#define MCPWM_GEN0_CFG_UPMETHOD_M (MCPWM_GEN0_CFG_UPMETHOD_V << MCPWM_GEN0_CFG_UPMETHOD_S) +#define MCPWM_GEN0_CFG_UPMETHOD_V 0x0000000FU #define MCPWM_GEN0_CFG_UPMETHOD_S 0 +/** MCPWM_GEN0_T0_SEL : R/W; bitpos: [6:4]; default: 0; + * Source selection for PWM generator 0 event_t0, take effect immediately, 0: + * fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + */ +#define MCPWM_GEN0_T0_SEL 0x00000007U +#define MCPWM_GEN0_T0_SEL_M (MCPWM_GEN0_T0_SEL_V << MCPWM_GEN0_T0_SEL_S) +#define MCPWM_GEN0_T0_SEL_V 0x00000007U +#define MCPWM_GEN0_T0_SEL_S 4 +/** MCPWM_GEN0_T1_SEL : R/W; bitpos: [9:7]; default: 0; + * Source selection for PWM generator 0 event_t1, take effect immediately, 0: + * fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + */ +#define MCPWM_GEN0_T1_SEL 0x00000007U +#define MCPWM_GEN0_T1_SEL_M (MCPWM_GEN0_T1_SEL_V << MCPWM_GEN0_T1_SEL_S) +#define MCPWM_GEN0_T1_SEL_V 0x00000007U +#define MCPWM_GEN0_T1_SEL_S 7 -#define MCPWM_GEN0_FORCE_REG(i) (REG_MCPWM_BASE(i) + 0x004c) -/* MCPWM_GEN0_B_NCIFORCE_MODE : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: Non-continuous immediate software force mode for PWM0B 0: disabled - 1: low 2: high 3: disabled*/ -#define MCPWM_GEN0_B_NCIFORCE_MODE 0x00000003 -#define MCPWM_GEN0_B_NCIFORCE_MODE_M ((MCPWM_GEN0_B_NCIFORCE_MODE_V)<<(MCPWM_GEN0_B_NCIFORCE_MODE_S)) -#define MCPWM_GEN0_B_NCIFORCE_MODE_V 0x3 -#define MCPWM_GEN0_B_NCIFORCE_MODE_S 14 -/* MCPWM_GEN0_B_NCIFORCE : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: Non-continuous immediate software force trigger for PWM0B a - toggle will trigger a force event*/ -#define MCPWM_GEN0_B_NCIFORCE (BIT(13)) -#define MCPWM_GEN0_B_NCIFORCE_M (BIT(13)) -#define MCPWM_GEN0_B_NCIFORCE_V 0x1 -#define MCPWM_GEN0_B_NCIFORCE_S 13 -/* MCPWM_GEN0_A_NCIFORCE_MODE : R/W ;bitpos:[12:11] ;default: 2'd0 ; */ -/*description: Non-continuous immediate software force mode for PWM0A 0: disabled - 1: low 2: high 3: disabled*/ -#define MCPWM_GEN0_A_NCIFORCE_MODE 0x00000003 -#define MCPWM_GEN0_A_NCIFORCE_MODE_M ((MCPWM_GEN0_A_NCIFORCE_MODE_V)<<(MCPWM_GEN0_A_NCIFORCE_MODE_S)) -#define MCPWM_GEN0_A_NCIFORCE_MODE_V 0x3 -#define MCPWM_GEN0_A_NCIFORCE_MODE_S 11 -/* MCPWM_GEN0_A_NCIFORCE : R/W ;bitpos:[10] ;default: 1'd0 ; */ -/*description: Non-continuous immediate software force trigger for PWM0A a - toggle will trigger a force event*/ -#define MCPWM_GEN0_A_NCIFORCE (BIT(10)) -#define MCPWM_GEN0_A_NCIFORCE_M (BIT(10)) -#define MCPWM_GEN0_A_NCIFORCE_V 0x1 -#define MCPWM_GEN0_A_NCIFORCE_S 10 -/* MCPWM_GEN0_B_CNTUFORCE_MODE : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: Continuous software force mode for PWM0B. 0: disabled 1: low - 2: high 3: disabled*/ -#define MCPWM_GEN0_B_CNTUFORCE_MODE 0x00000003 -#define MCPWM_GEN0_B_CNTUFORCE_MODE_M ((MCPWM_GEN0_B_CNTUFORCE_MODE_V)<<(MCPWM_GEN0_B_CNTUFORCE_MODE_S)) -#define MCPWM_GEN0_B_CNTUFORCE_MODE_V 0x3 -#define MCPWM_GEN0_B_CNTUFORCE_MODE_S 8 -/* MCPWM_GEN0_A_CNTUFORCE_MODE : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: Continuous software force mode for PWM0A. 0: disabled 1: low - 2: high 3: disabled*/ -#define MCPWM_GEN0_A_CNTUFORCE_MODE 0x00000003 -#define MCPWM_GEN0_A_CNTUFORCE_MODE_M ((MCPWM_GEN0_A_CNTUFORCE_MODE_V)<<(MCPWM_GEN0_A_CNTUFORCE_MODE_S)) -#define MCPWM_GEN0_A_CNTUFORCE_MODE_V 0x3 -#define MCPWM_GEN0_A_CNTUFORCE_MODE_S 6 -/* MCPWM_GEN0_CNTUFORCE_UPMETHOD : R/W ;bitpos:[5:0] ;default: 6'h20 ; */ -/*description: Update method for continuous software force of PWM generator0. - 0: immediate bit0: TEZ bit1: TEP bit2: TEA bit3: TEB bit4: sync bit5: disable update. (TEA/B here and below means an event generated when timer value equals A/B register)*/ -#define MCPWM_GEN0_CNTUFORCE_UPMETHOD 0x0000003F -#define MCPWM_GEN0_CNTUFORCE_UPMETHOD_M ((MCPWM_GEN0_CNTUFORCE_UPMETHOD_V)<<(MCPWM_GEN0_CNTUFORCE_UPMETHOD_S)) -#define MCPWM_GEN0_CNTUFORCE_UPMETHOD_V 0x3F +/** MCPWM_GEN0_FORCE_REG register + * Permissives to force PWM0A and PWM0B outputs by software + */ +#define MCPWM_GEN0_FORCE_REG(i) (DR_REG_MCPWM_BASE(i) + 0x4c) +/** MCPWM_GEN0_CNTUFORCE_UPMETHOD : R/W; bitpos: [5:0]; default: 32; + * Updating method for continuous software force of PWM generator0. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ,,when bit1 is set to 1: TEP, when + * bit2 is set to 1: TEA, when bit3 is set to 1: TEB, when bit4 is set to 1: sync, + * when bit5 is set to 1: disable update. (TEA/B here and below means an event + * generated when the timer's value equals to that of register A/B.) + */ +#define MCPWM_GEN0_CNTUFORCE_UPMETHOD 0x0000003FU +#define MCPWM_GEN0_CNTUFORCE_UPMETHOD_M (MCPWM_GEN0_CNTUFORCE_UPMETHOD_V << MCPWM_GEN0_CNTUFORCE_UPMETHOD_S) +#define MCPWM_GEN0_CNTUFORCE_UPMETHOD_V 0x0000003FU #define MCPWM_GEN0_CNTUFORCE_UPMETHOD_S 0 +/** MCPWM_GEN0_A_CNTUFORCE_MODE : R/W; bitpos: [7:6]; default: 0; + * Continuous software force mode for PWM0A. 0: disabled, 1: low, 2: high, 3: disabled + */ +#define MCPWM_GEN0_A_CNTUFORCE_MODE 0x00000003U +#define MCPWM_GEN0_A_CNTUFORCE_MODE_M (MCPWM_GEN0_A_CNTUFORCE_MODE_V << MCPWM_GEN0_A_CNTUFORCE_MODE_S) +#define MCPWM_GEN0_A_CNTUFORCE_MODE_V 0x00000003U +#define MCPWM_GEN0_A_CNTUFORCE_MODE_S 6 +/** MCPWM_GEN0_B_CNTUFORCE_MODE : R/W; bitpos: [9:8]; default: 0; + * Continuous software force mode for PWM0B. 0: disabled, 1: low, 2: high, 3: disabled + */ +#define MCPWM_GEN0_B_CNTUFORCE_MODE 0x00000003U +#define MCPWM_GEN0_B_CNTUFORCE_MODE_M (MCPWM_GEN0_B_CNTUFORCE_MODE_V << MCPWM_GEN0_B_CNTUFORCE_MODE_S) +#define MCPWM_GEN0_B_CNTUFORCE_MODE_V 0x00000003U +#define MCPWM_GEN0_B_CNTUFORCE_MODE_S 8 +/** MCPWM_GEN0_A_NCIFORCE : R/W; bitpos: [10]; default: 0; + * Trigger of non-continuous immediate software-force event for PWM0A, a toggle will + * trigger a force event. + */ +#define MCPWM_GEN0_A_NCIFORCE (BIT(10)) +#define MCPWM_GEN0_A_NCIFORCE_M (MCPWM_GEN0_A_NCIFORCE_V << MCPWM_GEN0_A_NCIFORCE_S) +#define MCPWM_GEN0_A_NCIFORCE_V 0x00000001U +#define MCPWM_GEN0_A_NCIFORCE_S 10 +/** MCPWM_GEN0_A_NCIFORCE_MODE : R/W; bitpos: [12:11]; default: 0; + * non-continuous immediate software force mode for PWM0A, 0: disabled, 1: low, 2: + * high, 3: disabled + */ +#define MCPWM_GEN0_A_NCIFORCE_MODE 0x00000003U +#define MCPWM_GEN0_A_NCIFORCE_MODE_M (MCPWM_GEN0_A_NCIFORCE_MODE_V << MCPWM_GEN0_A_NCIFORCE_MODE_S) +#define MCPWM_GEN0_A_NCIFORCE_MODE_V 0x00000003U +#define MCPWM_GEN0_A_NCIFORCE_MODE_S 11 +/** MCPWM_GEN0_B_NCIFORCE : R/W; bitpos: [13]; default: 0; + * Trigger of non-continuous immediate software-force event for PWM0B, a toggle will + * trigger a force event. + */ +#define MCPWM_GEN0_B_NCIFORCE (BIT(13)) +#define MCPWM_GEN0_B_NCIFORCE_M (MCPWM_GEN0_B_NCIFORCE_V << MCPWM_GEN0_B_NCIFORCE_S) +#define MCPWM_GEN0_B_NCIFORCE_V 0x00000001U +#define MCPWM_GEN0_B_NCIFORCE_S 13 +/** MCPWM_GEN0_B_NCIFORCE_MODE : R/W; bitpos: [15:14]; default: 0; + * non-continuous immediate software force mode for PWM0B, 0: disabled, 1: low, 2: + * high, 3: disabled + */ +#define MCPWM_GEN0_B_NCIFORCE_MODE 0x00000003U +#define MCPWM_GEN0_B_NCIFORCE_MODE_M (MCPWM_GEN0_B_NCIFORCE_MODE_V << MCPWM_GEN0_B_NCIFORCE_MODE_S) +#define MCPWM_GEN0_B_NCIFORCE_MODE_V 0x00000003U +#define MCPWM_GEN0_B_NCIFORCE_MODE_S 14 -#define MCPWM_GEN0_A_REG(i) (REG_MCPWM_BASE(i) + 0x0050) -/* MCPWM_GEN0_A_DT1 : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: Action on PWM0A triggered by event_t1 when timer decreasing. - 0: no change 1: low 2: high 3: toggle*/ -#define MCPWM_GEN0_A_DT1 0x00000003 -#define MCPWM_GEN0_A_DT1_M ((MCPWM_GEN0_A_DT1_V)<<(MCPWM_GEN0_A_DT1_S)) -#define MCPWM_GEN0_A_DT1_V 0x3 -#define MCPWM_GEN0_A_DT1_S 22 -/* MCPWM_GEN0_A_DT0 : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: Action on PWM0A triggered by event_t0 when timer decreasing*/ -#define MCPWM_GEN0_A_DT0 0x00000003 -#define MCPWM_GEN0_A_DT0_M ((MCPWM_GEN0_A_DT0_V)<<(MCPWM_GEN0_A_DT0_S)) -#define MCPWM_GEN0_A_DT0_V 0x3 -#define MCPWM_GEN0_A_DT0_S 20 -/* MCPWM_GEN0_A_DTEB : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: Action on PWM0A triggered by event TEB when timer decreasing*/ -#define MCPWM_GEN0_A_DTEB 0x00000003 -#define MCPWM_GEN0_A_DTEB_M ((MCPWM_GEN0_A_DTEB_V)<<(MCPWM_GEN0_A_DTEB_S)) -#define MCPWM_GEN0_A_DTEB_V 0x3 -#define MCPWM_GEN0_A_DTEB_S 18 -/* MCPWM_GEN0_A_DTEA : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: Action on PWM0A triggered by event TEA when timer decreasing*/ -#define MCPWM_GEN0_A_DTEA 0x00000003 -#define MCPWM_GEN0_A_DTEA_M ((MCPWM_GEN0_A_DTEA_V)<<(MCPWM_GEN0_A_DTEA_S)) -#define MCPWM_GEN0_A_DTEA_V 0x3 -#define MCPWM_GEN0_A_DTEA_S 16 -/* MCPWM_GEN0_A_DTEP : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: Action on PWM0A triggered by event TEP when timer decreasing*/ -#define MCPWM_GEN0_A_DTEP 0x00000003 -#define MCPWM_GEN0_A_DTEP_M ((MCPWM_GEN0_A_DTEP_V)<<(MCPWM_GEN0_A_DTEP_S)) -#define MCPWM_GEN0_A_DTEP_V 0x3 -#define MCPWM_GEN0_A_DTEP_S 14 -/* MCPWM_GEN0_A_DTEZ : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: Action on PWM0A triggered by event TEZ when timer decreasing*/ -#define MCPWM_GEN0_A_DTEZ 0x00000003 -#define MCPWM_GEN0_A_DTEZ_M ((MCPWM_GEN0_A_DTEZ_V)<<(MCPWM_GEN0_A_DTEZ_S)) -#define MCPWM_GEN0_A_DTEZ_V 0x3 -#define MCPWM_GEN0_A_DTEZ_S 12 -/* MCPWM_GEN0_A_UT1 : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: Action on PWM0A triggered by event_t1 when timer increasing*/ -#define MCPWM_GEN0_A_UT1 0x00000003 -#define MCPWM_GEN0_A_UT1_M ((MCPWM_GEN0_A_UT1_V)<<(MCPWM_GEN0_A_UT1_S)) -#define MCPWM_GEN0_A_UT1_V 0x3 -#define MCPWM_GEN0_A_UT1_S 10 -/* MCPWM_GEN0_A_UT0 : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: Action on PWM0A triggered by event_t0 when timer increasing*/ -#define MCPWM_GEN0_A_UT0 0x00000003 -#define MCPWM_GEN0_A_UT0_M ((MCPWM_GEN0_A_UT0_V)<<(MCPWM_GEN0_A_UT0_S)) -#define MCPWM_GEN0_A_UT0_V 0x3 -#define MCPWM_GEN0_A_UT0_S 8 -/* MCPWM_GEN0_A_UTEB : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: Action on PWM0A triggered by event TEB when timer increasing*/ -#define MCPWM_GEN0_A_UTEB 0x00000003 -#define MCPWM_GEN0_A_UTEB_M ((MCPWM_GEN0_A_UTEB_V)<<(MCPWM_GEN0_A_UTEB_S)) -#define MCPWM_GEN0_A_UTEB_V 0x3 -#define MCPWM_GEN0_A_UTEB_S 6 -/* MCPWM_GEN0_A_UTEA : R/W ;bitpos:[5:4] ;default: 2'd0 ; */ -/*description: Action on PWM0A triggered by event TEA when timer increasing*/ -#define MCPWM_GEN0_A_UTEA 0x00000003 -#define MCPWM_GEN0_A_UTEA_M ((MCPWM_GEN0_A_UTEA_V)<<(MCPWM_GEN0_A_UTEA_S)) -#define MCPWM_GEN0_A_UTEA_V 0x3 -#define MCPWM_GEN0_A_UTEA_S 4 -/* MCPWM_GEN0_A_UTEP : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: Action on PWM0A triggered by event TEP when timer increasing*/ -#define MCPWM_GEN0_A_UTEP 0x00000003 -#define MCPWM_GEN0_A_UTEP_M ((MCPWM_GEN0_A_UTEP_V)<<(MCPWM_GEN0_A_UTEP_S)) -#define MCPWM_GEN0_A_UTEP_V 0x3 -#define MCPWM_GEN0_A_UTEP_S 2 -/* MCPWM_GEN0_A_UTEZ : R/W ;bitpos:[1:0] ;default: 2'd0 ; */ -/*description: Action on PWM0A triggered by event TEZ when timer increasing*/ -#define MCPWM_GEN0_A_UTEZ 0x00000003 -#define MCPWM_GEN0_A_UTEZ_M ((MCPWM_GEN0_A_UTEZ_V)<<(MCPWM_GEN0_A_UTEZ_S)) -#define MCPWM_GEN0_A_UTEZ_V 0x3 +/** MCPWM_GEN0_A_REG register + * Actions triggered by events on PWM0A + */ +#define MCPWM_GEN0_A_REG(i) (DR_REG_MCPWM_BASE(i) + 0x50) +/** MCPWM_GEN0_A_UTEZ : R/W; bitpos: [1:0]; default: 0; + * Action on PWM0A triggered by event TEZ when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_UTEZ 0x00000003U +#define MCPWM_GEN0_A_UTEZ_M (MCPWM_GEN0_A_UTEZ_V << MCPWM_GEN0_A_UTEZ_S) +#define MCPWM_GEN0_A_UTEZ_V 0x00000003U #define MCPWM_GEN0_A_UTEZ_S 0 +/** MCPWM_GEN0_A_UTEP : R/W; bitpos: [3:2]; default: 0; + * Action on PWM0A triggered by event TEP when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_UTEP 0x00000003U +#define MCPWM_GEN0_A_UTEP_M (MCPWM_GEN0_A_UTEP_V << MCPWM_GEN0_A_UTEP_S) +#define MCPWM_GEN0_A_UTEP_V 0x00000003U +#define MCPWM_GEN0_A_UTEP_S 2 +/** MCPWM_GEN0_A_UTEA : R/W; bitpos: [5:4]; default: 0; + * Action on PWM0A triggered by event TEA when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_UTEA 0x00000003U +#define MCPWM_GEN0_A_UTEA_M (MCPWM_GEN0_A_UTEA_V << MCPWM_GEN0_A_UTEA_S) +#define MCPWM_GEN0_A_UTEA_V 0x00000003U +#define MCPWM_GEN0_A_UTEA_S 4 +/** MCPWM_GEN0_A_UTEB : R/W; bitpos: [7:6]; default: 0; + * Action on PWM0A triggered by event TEB when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_UTEB 0x00000003U +#define MCPWM_GEN0_A_UTEB_M (MCPWM_GEN0_A_UTEB_V << MCPWM_GEN0_A_UTEB_S) +#define MCPWM_GEN0_A_UTEB_V 0x00000003U +#define MCPWM_GEN0_A_UTEB_S 6 +/** MCPWM_GEN0_A_UT0 : R/W; bitpos: [9:8]; default: 0; + * Action on PWM0A triggered by event_t0 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_UT0 0x00000003U +#define MCPWM_GEN0_A_UT0_M (MCPWM_GEN0_A_UT0_V << MCPWM_GEN0_A_UT0_S) +#define MCPWM_GEN0_A_UT0_V 0x00000003U +#define MCPWM_GEN0_A_UT0_S 8 +/** MCPWM_GEN0_A_UT1 : R/W; bitpos: [11:10]; default: 0; + * Action on PWM0A triggered by event_t1 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_UT1 0x00000003U +#define MCPWM_GEN0_A_UT1_M (MCPWM_GEN0_A_UT1_V << MCPWM_GEN0_A_UT1_S) +#define MCPWM_GEN0_A_UT1_V 0x00000003U +#define MCPWM_GEN0_A_UT1_S 10 +/** MCPWM_GEN0_A_DTEZ : R/W; bitpos: [13:12]; default: 0; + * Action on PWM0A triggered by event TEZ when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_DTEZ 0x00000003U +#define MCPWM_GEN0_A_DTEZ_M (MCPWM_GEN0_A_DTEZ_V << MCPWM_GEN0_A_DTEZ_S) +#define MCPWM_GEN0_A_DTEZ_V 0x00000003U +#define MCPWM_GEN0_A_DTEZ_S 12 +/** MCPWM_GEN0_A_DTEP : R/W; bitpos: [15:14]; default: 0; + * Action on PWM0A triggered by event TEP when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_DTEP 0x00000003U +#define MCPWM_GEN0_A_DTEP_M (MCPWM_GEN0_A_DTEP_V << MCPWM_GEN0_A_DTEP_S) +#define MCPWM_GEN0_A_DTEP_V 0x00000003U +#define MCPWM_GEN0_A_DTEP_S 14 +/** MCPWM_GEN0_A_DTEA : R/W; bitpos: [17:16]; default: 0; + * Action on PWM0A triggered by event TEA when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_DTEA 0x00000003U +#define MCPWM_GEN0_A_DTEA_M (MCPWM_GEN0_A_DTEA_V << MCPWM_GEN0_A_DTEA_S) +#define MCPWM_GEN0_A_DTEA_V 0x00000003U +#define MCPWM_GEN0_A_DTEA_S 16 +/** MCPWM_GEN0_A_DTEB : R/W; bitpos: [19:18]; default: 0; + * Action on PWM0A triggered by event TEB when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_DTEB 0x00000003U +#define MCPWM_GEN0_A_DTEB_M (MCPWM_GEN0_A_DTEB_V << MCPWM_GEN0_A_DTEB_S) +#define MCPWM_GEN0_A_DTEB_V 0x00000003U +#define MCPWM_GEN0_A_DTEB_S 18 +/** MCPWM_GEN0_A_DT0 : R/W; bitpos: [21:20]; default: 0; + * Action on PWM0A triggered by event_t0 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_DT0 0x00000003U +#define MCPWM_GEN0_A_DT0_M (MCPWM_GEN0_A_DT0_V << MCPWM_GEN0_A_DT0_S) +#define MCPWM_GEN0_A_DT0_V 0x00000003U +#define MCPWM_GEN0_A_DT0_S 20 +/** MCPWM_GEN0_A_DT1 : R/W; bitpos: [23:22]; default: 0; + * Action on PWM0A triggered by event_t1 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_DT1 0x00000003U +#define MCPWM_GEN0_A_DT1_M (MCPWM_GEN0_A_DT1_V << MCPWM_GEN0_A_DT1_S) +#define MCPWM_GEN0_A_DT1_V 0x00000003U +#define MCPWM_GEN0_A_DT1_S 22 -#define MCPWM_GEN0_B_REG(i) (REG_MCPWM_BASE(i) + 0x0054) -/* MCPWM_GEN0_B_DT1 : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: Action on PWM0B triggered by event_t1 when timer decreasing. - 0: no change 1: low 2: high 3: toggle*/ -#define MCPWM_GEN0_B_DT1 0x00000003 -#define MCPWM_GEN0_B_DT1_M ((MCPWM_GEN0_B_DT1_V)<<(MCPWM_GEN0_B_DT1_S)) -#define MCPWM_GEN0_B_DT1_V 0x3 -#define MCPWM_GEN0_B_DT1_S 22 -/* MCPWM_GEN0_B_DT0 : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: Action on PWM0B triggered by event_t0 when timer decreasing*/ -#define MCPWM_GEN0_B_DT0 0x00000003 -#define MCPWM_GEN0_B_DT0_M ((MCPWM_GEN0_B_DT0_V)<<(MCPWM_GEN0_B_DT0_S)) -#define MCPWM_GEN0_B_DT0_V 0x3 -#define MCPWM_GEN0_B_DT0_S 20 -/* MCPWM_GEN0_B_DTEB : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: Action on PWM0B triggered by event TEB when timer decreasing*/ -#define MCPWM_GEN0_B_DTEB 0x00000003 -#define MCPWM_GEN0_B_DTEB_M ((MCPWM_GEN0_B_DTEB_V)<<(MCPWM_GEN0_B_DTEB_S)) -#define MCPWM_GEN0_B_DTEB_V 0x3 -#define MCPWM_GEN0_B_DTEB_S 18 -/* MCPWM_GEN0_B_DTEA : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: Action on PWM0B triggered by event TEA when timer decreasing*/ -#define MCPWM_GEN0_B_DTEA 0x00000003 -#define MCPWM_GEN0_B_DTEA_M ((MCPWM_GEN0_B_DTEA_V)<<(MCPWM_GEN0_B_DTEA_S)) -#define MCPWM_GEN0_B_DTEA_V 0x3 -#define MCPWM_GEN0_B_DTEA_S 16 -/* MCPWM_GEN0_B_DTEP : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: Action on PWM0B triggered by event TEP when timer decreasing*/ -#define MCPWM_GEN0_B_DTEP 0x00000003 -#define MCPWM_GEN0_B_DTEP_M ((MCPWM_GEN0_B_DTEP_V)<<(MCPWM_GEN0_B_DTEP_S)) -#define MCPWM_GEN0_B_DTEP_V 0x3 -#define MCPWM_GEN0_B_DTEP_S 14 -/* MCPWM_GEN0_B_DTEZ : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: Action on PWM0B triggered by event TEZ when timer decreasing*/ -#define MCPWM_GEN0_B_DTEZ 0x00000003 -#define MCPWM_GEN0_B_DTEZ_M ((MCPWM_GEN0_B_DTEZ_V)<<(MCPWM_GEN0_B_DTEZ_S)) -#define MCPWM_GEN0_B_DTEZ_V 0x3 -#define MCPWM_GEN0_B_DTEZ_S 12 -/* MCPWM_GEN0_B_UT1 : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: Action on PWM0B triggered by event_t1 when timer increasing*/ -#define MCPWM_GEN0_B_UT1 0x00000003 -#define MCPWM_GEN0_B_UT1_M ((MCPWM_GEN0_B_UT1_V)<<(MCPWM_GEN0_B_UT1_S)) -#define MCPWM_GEN0_B_UT1_V 0x3 -#define MCPWM_GEN0_B_UT1_S 10 -/* MCPWM_GEN0_B_UT0 : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: Action on PWM0B triggered by event_t0 when timer increasing*/ -#define MCPWM_GEN0_B_UT0 0x00000003 -#define MCPWM_GEN0_B_UT0_M ((MCPWM_GEN0_B_UT0_V)<<(MCPWM_GEN0_B_UT0_S)) -#define MCPWM_GEN0_B_UT0_V 0x3 -#define MCPWM_GEN0_B_UT0_S 8 -/* MCPWM_GEN0_B_UTEB : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: Action on PWM0B triggered by event TEB when timer increasing*/ -#define MCPWM_GEN0_B_UTEB 0x00000003 -#define MCPWM_GEN0_B_UTEB_M ((MCPWM_GEN0_B_UTEB_V)<<(MCPWM_GEN0_B_UTEB_S)) -#define MCPWM_GEN0_B_UTEB_V 0x3 -#define MCPWM_GEN0_B_UTEB_S 6 -/* MCPWM_GEN0_B_UTEA : R/W ;bitpos:[5:4] ;default: 2'd0 ; */ -/*description: Action on PWM0B triggered by event TEA when timer increasing*/ -#define MCPWM_GEN0_B_UTEA 0x00000003 -#define MCPWM_GEN0_B_UTEA_M ((MCPWM_GEN0_B_UTEA_V)<<(MCPWM_GEN0_B_UTEA_S)) -#define MCPWM_GEN0_B_UTEA_V 0x3 -#define MCPWM_GEN0_B_UTEA_S 4 -/* MCPWM_GEN0_B_UTEP : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: Action on PWM0B triggered by event TEP when timer increasing*/ -#define MCPWM_GEN0_B_UTEP 0x00000003 -#define MCPWM_GEN0_B_UTEP_M ((MCPWM_GEN0_B_UTEP_V)<<(MCPWM_GEN0_B_UTEP_S)) -#define MCPWM_GEN0_B_UTEP_V 0x3 -#define MCPWM_GEN0_B_UTEP_S 2 -/* MCPWM_GEN0_B_UTEZ : R/W ;bitpos:[1:0] ;default: 2'd0 ; */ -/*description: Action on PWM0B triggered by event TEZ when timer increasing*/ -#define MCPWM_GEN0_B_UTEZ 0x00000003 -#define MCPWM_GEN0_B_UTEZ_M ((MCPWM_GEN0_B_UTEZ_V)<<(MCPWM_GEN0_B_UTEZ_S)) -#define MCPWM_GEN0_B_UTEZ_V 0x3 +/** MCPWM_GEN0_B_REG register + * Actions triggered by events on PWM0B + */ +#define MCPWM_GEN0_B_REG(i) (DR_REG_MCPWM_BASE(i) + 0x54) +/** MCPWM_GEN0_B_UTEZ : R/W; bitpos: [1:0]; default: 0; + * Action on PWM0B triggered by event TEZ when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_UTEZ 0x00000003U +#define MCPWM_GEN0_B_UTEZ_M (MCPWM_GEN0_B_UTEZ_V << MCPWM_GEN0_B_UTEZ_S) +#define MCPWM_GEN0_B_UTEZ_V 0x00000003U #define MCPWM_GEN0_B_UTEZ_S 0 +/** MCPWM_GEN0_B_UTEP : R/W; bitpos: [3:2]; default: 0; + * Action on PWM0B triggered by event TEP when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_UTEP 0x00000003U +#define MCPWM_GEN0_B_UTEP_M (MCPWM_GEN0_B_UTEP_V << MCPWM_GEN0_B_UTEP_S) +#define MCPWM_GEN0_B_UTEP_V 0x00000003U +#define MCPWM_GEN0_B_UTEP_S 2 +/** MCPWM_GEN0_B_UTEA : R/W; bitpos: [5:4]; default: 0; + * Action on PWM0B triggered by event TEA when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_UTEA 0x00000003U +#define MCPWM_GEN0_B_UTEA_M (MCPWM_GEN0_B_UTEA_V << MCPWM_GEN0_B_UTEA_S) +#define MCPWM_GEN0_B_UTEA_V 0x00000003U +#define MCPWM_GEN0_B_UTEA_S 4 +/** MCPWM_GEN0_B_UTEB : R/W; bitpos: [7:6]; default: 0; + * Action on PWM0B triggered by event TEB when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_UTEB 0x00000003U +#define MCPWM_GEN0_B_UTEB_M (MCPWM_GEN0_B_UTEB_V << MCPWM_GEN0_B_UTEB_S) +#define MCPWM_GEN0_B_UTEB_V 0x00000003U +#define MCPWM_GEN0_B_UTEB_S 6 +/** MCPWM_GEN0_B_UT0 : R/W; bitpos: [9:8]; default: 0; + * Action on PWM0B triggered by event_t0 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_UT0 0x00000003U +#define MCPWM_GEN0_B_UT0_M (MCPWM_GEN0_B_UT0_V << MCPWM_GEN0_B_UT0_S) +#define MCPWM_GEN0_B_UT0_V 0x00000003U +#define MCPWM_GEN0_B_UT0_S 8 +/** MCPWM_GEN0_B_UT1 : R/W; bitpos: [11:10]; default: 0; + * Action on PWM0B triggered by event_t1 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_UT1 0x00000003U +#define MCPWM_GEN0_B_UT1_M (MCPWM_GEN0_B_UT1_V << MCPWM_GEN0_B_UT1_S) +#define MCPWM_GEN0_B_UT1_V 0x00000003U +#define MCPWM_GEN0_B_UT1_S 10 +/** MCPWM_GEN0_B_DTEZ : R/W; bitpos: [13:12]; default: 0; + * Action on PWM0B triggered by event TEZ when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_DTEZ 0x00000003U +#define MCPWM_GEN0_B_DTEZ_M (MCPWM_GEN0_B_DTEZ_V << MCPWM_GEN0_B_DTEZ_S) +#define MCPWM_GEN0_B_DTEZ_V 0x00000003U +#define MCPWM_GEN0_B_DTEZ_S 12 +/** MCPWM_GEN0_B_DTEP : R/W; bitpos: [15:14]; default: 0; + * Action on PWM0B triggered by event TEP when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_DTEP 0x00000003U +#define MCPWM_GEN0_B_DTEP_M (MCPWM_GEN0_B_DTEP_V << MCPWM_GEN0_B_DTEP_S) +#define MCPWM_GEN0_B_DTEP_V 0x00000003U +#define MCPWM_GEN0_B_DTEP_S 14 +/** MCPWM_GEN0_B_DTEA : R/W; bitpos: [17:16]; default: 0; + * Action on PWM0B triggered by event TEA when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_DTEA 0x00000003U +#define MCPWM_GEN0_B_DTEA_M (MCPWM_GEN0_B_DTEA_V << MCPWM_GEN0_B_DTEA_S) +#define MCPWM_GEN0_B_DTEA_V 0x00000003U +#define MCPWM_GEN0_B_DTEA_S 16 +/** MCPWM_GEN0_B_DTEB : R/W; bitpos: [19:18]; default: 0; + * Action on PWM0B triggered by event TEB when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_DTEB 0x00000003U +#define MCPWM_GEN0_B_DTEB_M (MCPWM_GEN0_B_DTEB_V << MCPWM_GEN0_B_DTEB_S) +#define MCPWM_GEN0_B_DTEB_V 0x00000003U +#define MCPWM_GEN0_B_DTEB_S 18 +/** MCPWM_GEN0_B_DT0 : R/W; bitpos: [21:20]; default: 0; + * Action on PWM0B triggered by event_t0 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_DT0 0x00000003U +#define MCPWM_GEN0_B_DT0_M (MCPWM_GEN0_B_DT0_V << MCPWM_GEN0_B_DT0_S) +#define MCPWM_GEN0_B_DT0_V 0x00000003U +#define MCPWM_GEN0_B_DT0_S 20 +/** MCPWM_GEN0_B_DT1 : R/W; bitpos: [23:22]; default: 0; + * Action on PWM0B triggered by event_t1 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_DT1 0x00000003U +#define MCPWM_GEN0_B_DT1_M (MCPWM_GEN0_B_DT1_V << MCPWM_GEN0_B_DT1_S) +#define MCPWM_GEN0_B_DT1_V 0x00000003U +#define MCPWM_GEN0_B_DT1_S 22 -#define MCPWM_DT0_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x0058) -/* MCPWM_DT0_CLK_SEL : R/W ;bitpos:[17] ;default: 1'd0 ; */ -/*description: Dead time generator 0 clock selection. 0: PWM_clk 1: PT_clk*/ -#define MCPWM_DT0_CLK_SEL (BIT(17)) -#define MCPWM_DT0_CLK_SEL_M (BIT(17)) -#define MCPWM_DT0_CLK_SEL_V 0x1 -#define MCPWM_DT0_CLK_SEL_S 17 -/* MCPWM_DT0_B_OUTBYPASS : R/W ;bitpos:[16] ;default: 1'd1 ; */ -/*description: S0 in documentation*/ -#define MCPWM_DT0_B_OUTBYPASS (BIT(16)) -#define MCPWM_DT0_B_OUTBYPASS_M (BIT(16)) -#define MCPWM_DT0_B_OUTBYPASS_V 0x1 -#define MCPWM_DT0_B_OUTBYPASS_S 16 -/* MCPWM_DT0_A_OUTBYPASS : R/W ;bitpos:[15] ;default: 1'd1 ; */ -/*description: S1 in documentation*/ -#define MCPWM_DT0_A_OUTBYPASS (BIT(15)) -#define MCPWM_DT0_A_OUTBYPASS_M (BIT(15)) -#define MCPWM_DT0_A_OUTBYPASS_V 0x1 -#define MCPWM_DT0_A_OUTBYPASS_S 15 -/* MCPWM_DT0_FED_OUTINVERT : R/W ;bitpos:[14] ;default: 1'd0 ; */ -/*description: S3 in documentation*/ -#define MCPWM_DT0_FED_OUTINVERT (BIT(14)) -#define MCPWM_DT0_FED_OUTINVERT_M (BIT(14)) -#define MCPWM_DT0_FED_OUTINVERT_V 0x1 -#define MCPWM_DT0_FED_OUTINVERT_S 14 -/* MCPWM_DT0_RED_OUTINVERT : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: S2 in documentation*/ -#define MCPWM_DT0_RED_OUTINVERT (BIT(13)) -#define MCPWM_DT0_RED_OUTINVERT_M (BIT(13)) -#define MCPWM_DT0_RED_OUTINVERT_V 0x1 -#define MCPWM_DT0_RED_OUTINVERT_S 13 -/* MCPWM_DT0_FED_INSEL : R/W ;bitpos:[12] ;default: 1'd0 ; */ -/*description: S5 in documentation*/ -#define MCPWM_DT0_FED_INSEL (BIT(12)) -#define MCPWM_DT0_FED_INSEL_M (BIT(12)) -#define MCPWM_DT0_FED_INSEL_V 0x1 -#define MCPWM_DT0_FED_INSEL_S 12 -/* MCPWM_DT0_RED_INSEL : R/W ;bitpos:[11] ;default: 1'd0 ; */ -/*description: S4 in documentation*/ -#define MCPWM_DT0_RED_INSEL (BIT(11)) -#define MCPWM_DT0_RED_INSEL_M (BIT(11)) -#define MCPWM_DT0_RED_INSEL_V 0x1 -#define MCPWM_DT0_RED_INSEL_S 11 -/* MCPWM_DT0_B_OUTSWAP : R/W ;bitpos:[10] ;default: 1'd0 ; */ -/*description: S7 in documentation*/ -#define MCPWM_DT0_B_OUTSWAP (BIT(10)) -#define MCPWM_DT0_B_OUTSWAP_M (BIT(10)) -#define MCPWM_DT0_B_OUTSWAP_V 0x1 -#define MCPWM_DT0_B_OUTSWAP_S 10 -/* MCPWM_DT0_A_OUTSWAP : R/W ;bitpos:[9] ;default: 1'd0 ; */ -/*description: S6 in documentation*/ -#define MCPWM_DT0_A_OUTSWAP (BIT(9)) -#define MCPWM_DT0_A_OUTSWAP_M (BIT(9)) -#define MCPWM_DT0_A_OUTSWAP_V 0x1 -#define MCPWM_DT0_A_OUTSWAP_S 9 -/* MCPWM_DT0_DEB_MODE : R/W ;bitpos:[8] ;default: 1'd0 ; */ -/*description: S8 in documentation dual-edge B mode 0: FED/RED take effect - on different path separately 1: FED/RED take effect on B path A out is in bypass or normal operation mode*/ -#define MCPWM_DT0_DEB_MODE (BIT(8)) -#define MCPWM_DT0_DEB_MODE_M (BIT(8)) -#define MCPWM_DT0_DEB_MODE_V 0x1 -#define MCPWM_DT0_DEB_MODE_S 8 -/* MCPWM_DT0_RED_UPMETHOD : R/W ;bitpos:[7:4] ;default: 4'd0 ; */ -/*description: Update method for RED (rising edge delay) active reg. 0: immediate - bit0: TEZ bit1: TEP bit2: sync bit3: disable update*/ -#define MCPWM_DT0_RED_UPMETHOD 0x0000000F -#define MCPWM_DT0_RED_UPMETHOD_M ((MCPWM_DT0_RED_UPMETHOD_V)<<(MCPWM_DT0_RED_UPMETHOD_S)) -#define MCPWM_DT0_RED_UPMETHOD_V 0xF -#define MCPWM_DT0_RED_UPMETHOD_S 4 -/* MCPWM_DT0_FED_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: Update method for FED (falling edge delay) active reg. 0: immediate - bit0: TEZ bit1: TEP bit2: sync bit3: disable update*/ -#define MCPWM_DT0_FED_UPMETHOD 0x0000000F -#define MCPWM_DT0_FED_UPMETHOD_M ((MCPWM_DT0_FED_UPMETHOD_V)<<(MCPWM_DT0_FED_UPMETHOD_S)) -#define MCPWM_DT0_FED_UPMETHOD_V 0xF +/** MCPWM_DT0_CFG_REG register + * PWM generator 0 dead time type selection and configuration + */ +#define MCPWM_DT0_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x58) +/** MCPWM_DT0_FED_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for FED (rising edge delay) active register. 0: immediate, when bit0 + * is set to 1: tez, when bit1 is set to 1:tep, when bit2 is set to 1: sync, when + * bit3 is set to 1: disable the update + */ +#define MCPWM_DT0_FED_UPMETHOD 0x0000000FU +#define MCPWM_DT0_FED_UPMETHOD_M (MCPWM_DT0_FED_UPMETHOD_V << MCPWM_DT0_FED_UPMETHOD_S) +#define MCPWM_DT0_FED_UPMETHOD_V 0x0000000FU #define MCPWM_DT0_FED_UPMETHOD_S 0 +/** MCPWM_DT0_RED_UPMETHOD : R/W; bitpos: [7:4]; default: 0; + * Update method for RED (rising edge delay) active register. 0: immediate, when bit0 + * is set to 1: tez, when bit1 is set to 1:tep, when bit2 is set to 1: sync, when + * bit3 is set to 1: disable the update + */ +#define MCPWM_DT0_RED_UPMETHOD 0x0000000FU +#define MCPWM_DT0_RED_UPMETHOD_M (MCPWM_DT0_RED_UPMETHOD_V << MCPWM_DT0_RED_UPMETHOD_S) +#define MCPWM_DT0_RED_UPMETHOD_V 0x0000000FU +#define MCPWM_DT0_RED_UPMETHOD_S 4 +/** MCPWM_DT0_DEB_MODE : R/W; bitpos: [8]; default: 0; + * S8 in table, dual-edge B mode, 0: fed/red take effect on different path separately, + * 1: fed/red take effect on B path, A out is in bypass or dulpB mode + */ +#define MCPWM_DT0_DEB_MODE (BIT(8)) +#define MCPWM_DT0_DEB_MODE_M (MCPWM_DT0_DEB_MODE_V << MCPWM_DT0_DEB_MODE_S) +#define MCPWM_DT0_DEB_MODE_V 0x00000001U +#define MCPWM_DT0_DEB_MODE_S 8 +/** MCPWM_DT0_A_OUTSWAP : R/W; bitpos: [9]; default: 0; + * S6 in table + */ +#define MCPWM_DT0_A_OUTSWAP (BIT(9)) +#define MCPWM_DT0_A_OUTSWAP_M (MCPWM_DT0_A_OUTSWAP_V << MCPWM_DT0_A_OUTSWAP_S) +#define MCPWM_DT0_A_OUTSWAP_V 0x00000001U +#define MCPWM_DT0_A_OUTSWAP_S 9 +/** MCPWM_DT0_B_OUTSWAP : R/W; bitpos: [10]; default: 0; + * S7 in table + */ +#define MCPWM_DT0_B_OUTSWAP (BIT(10)) +#define MCPWM_DT0_B_OUTSWAP_M (MCPWM_DT0_B_OUTSWAP_V << MCPWM_DT0_B_OUTSWAP_S) +#define MCPWM_DT0_B_OUTSWAP_V 0x00000001U +#define MCPWM_DT0_B_OUTSWAP_S 10 +/** MCPWM_DT0_RED_INSEL : R/W; bitpos: [11]; default: 0; + * S4 in table + */ +#define MCPWM_DT0_RED_INSEL (BIT(11)) +#define MCPWM_DT0_RED_INSEL_M (MCPWM_DT0_RED_INSEL_V << MCPWM_DT0_RED_INSEL_S) +#define MCPWM_DT0_RED_INSEL_V 0x00000001U +#define MCPWM_DT0_RED_INSEL_S 11 +/** MCPWM_DT0_FED_INSEL : R/W; bitpos: [12]; default: 0; + * S5 in table + */ +#define MCPWM_DT0_FED_INSEL (BIT(12)) +#define MCPWM_DT0_FED_INSEL_M (MCPWM_DT0_FED_INSEL_V << MCPWM_DT0_FED_INSEL_S) +#define MCPWM_DT0_FED_INSEL_V 0x00000001U +#define MCPWM_DT0_FED_INSEL_S 12 +/** MCPWM_DT0_RED_OUTINVERT : R/W; bitpos: [13]; default: 0; + * S2 in table + */ +#define MCPWM_DT0_RED_OUTINVERT (BIT(13)) +#define MCPWM_DT0_RED_OUTINVERT_M (MCPWM_DT0_RED_OUTINVERT_V << MCPWM_DT0_RED_OUTINVERT_S) +#define MCPWM_DT0_RED_OUTINVERT_V 0x00000001U +#define MCPWM_DT0_RED_OUTINVERT_S 13 +/** MCPWM_DT0_FED_OUTINVERT : R/W; bitpos: [14]; default: 0; + * S3 in table + */ +#define MCPWM_DT0_FED_OUTINVERT (BIT(14)) +#define MCPWM_DT0_FED_OUTINVERT_M (MCPWM_DT0_FED_OUTINVERT_V << MCPWM_DT0_FED_OUTINVERT_S) +#define MCPWM_DT0_FED_OUTINVERT_V 0x00000001U +#define MCPWM_DT0_FED_OUTINVERT_S 14 +/** MCPWM_DT0_A_OUTBYPASS : R/W; bitpos: [15]; default: 1; + * S1 in table + */ +#define MCPWM_DT0_A_OUTBYPASS (BIT(15)) +#define MCPWM_DT0_A_OUTBYPASS_M (MCPWM_DT0_A_OUTBYPASS_V << MCPWM_DT0_A_OUTBYPASS_S) +#define MCPWM_DT0_A_OUTBYPASS_V 0x00000001U +#define MCPWM_DT0_A_OUTBYPASS_S 15 +/** MCPWM_DT0_B_OUTBYPASS : R/W; bitpos: [16]; default: 1; + * S0 in table + */ +#define MCPWM_DT0_B_OUTBYPASS (BIT(16)) +#define MCPWM_DT0_B_OUTBYPASS_M (MCPWM_DT0_B_OUTBYPASS_V << MCPWM_DT0_B_OUTBYPASS_S) +#define MCPWM_DT0_B_OUTBYPASS_V 0x00000001U +#define MCPWM_DT0_B_OUTBYPASS_S 16 +/** MCPWM_DT0_CLK_SEL : R/W; bitpos: [17]; default: 0; + * Dead time clock selection. 0: PWM_clk, 1: PT_clk + */ +#define MCPWM_DT0_CLK_SEL (BIT(17)) +#define MCPWM_DT0_CLK_SEL_M (MCPWM_DT0_CLK_SEL_V << MCPWM_DT0_CLK_SEL_S) +#define MCPWM_DT0_CLK_SEL_V 0x00000001U +#define MCPWM_DT0_CLK_SEL_S 17 -#define MCPWM_DT0_FED_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x005c) -/* MCPWM_DT0_FED : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: Shadow reg for FED*/ -#define MCPWM_DT0_FED 0x0000FFFF -#define MCPWM_DT0_FED_M ((MCPWM_DT0_FED_V)<<(MCPWM_DT0_FED_S)) -#define MCPWM_DT0_FED_V 0xFFFF +/** MCPWM_DT0_FED_CFG_REG register + * PWM generator 0 shadow register for falling edge delay (FED). + */ +#define MCPWM_DT0_FED_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x5c) +/** MCPWM_DT0_FED : R/W; bitpos: [15:0]; default: 0; + * Shadow register for FED + */ +#define MCPWM_DT0_FED 0x0000FFFFU +#define MCPWM_DT0_FED_M (MCPWM_DT0_FED_V << MCPWM_DT0_FED_S) +#define MCPWM_DT0_FED_V 0x0000FFFFU #define MCPWM_DT0_FED_S 0 -#define MCPWM_DT0_RED_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x0060) -/* MCPWM_DT0_RED : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: Shadow reg for RED*/ -#define MCPWM_DT0_RED 0x0000FFFF -#define MCPWM_DT0_RED_M ((MCPWM_DT0_RED_V)<<(MCPWM_DT0_RED_S)) -#define MCPWM_DT0_RED_V 0xFFFF +/** MCPWM_DT0_RED_CFG_REG register + * PWM generator 0 shadow register for rising edge delay (RED). + */ +#define MCPWM_DT0_RED_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x60) +/** MCPWM_DT0_RED : R/W; bitpos: [15:0]; default: 0; + * Shadow register for RED + */ +#define MCPWM_DT0_RED 0x0000FFFFU +#define MCPWM_DT0_RED_M (MCPWM_DT0_RED_V << MCPWM_DT0_RED_S) +#define MCPWM_DT0_RED_V 0x0000FFFFU #define MCPWM_DT0_RED_S 0 -#define MCPWM_CARRIER0_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x0064) -/* MCPWM_CARRIER0_IN_INVERT : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: When set invert the input of PWM0A and PWM0B for this submodule*/ -#define MCPWM_CARRIER0_IN_INVERT (BIT(13)) -#define MCPWM_CARRIER0_IN_INVERT_M (BIT(13)) -#define MCPWM_CARRIER0_IN_INVERT_V 0x1 -#define MCPWM_CARRIER0_IN_INVERT_S 13 -/* MCPWM_CARRIER0_OUT_INVERT : R/W ;bitpos:[12] ;default: 1'd0 ; */ -/*description: When set invert the output of PWM0A and PWM0B for this submodule*/ -#define MCPWM_CARRIER0_OUT_INVERT (BIT(12)) -#define MCPWM_CARRIER0_OUT_INVERT_M (BIT(12)) -#define MCPWM_CARRIER0_OUT_INVERT_V 0x1 -#define MCPWM_CARRIER0_OUT_INVERT_S 12 -/* MCPWM_CARRIER0_OSHWTH : R/W ;bitpos:[11:8] ;default: 4'd0 ; */ -/*description: Width of the fist pulse in number of periods of the carrier*/ -#define MCPWM_CARRIER0_OSHWTH 0x0000000F -#define MCPWM_CARRIER0_OSHWTH_M ((MCPWM_CARRIER0_OSHWTH_V)<<(MCPWM_CARRIER0_OSHWTH_S)) -#define MCPWM_CARRIER0_OSHWTH_V 0xF -#define MCPWM_CARRIER0_OSHWTH_S 8 -/* MCPWM_CARRIER0_DUTY : R/W ;bitpos:[7:5] ;default: 3'd0 ; */ -/*description: Carrier duty selection. Duty = PWM_CARRIER0_DUTY / 8*/ -#define MCPWM_CARRIER0_DUTY 0x00000007 -#define MCPWM_CARRIER0_DUTY_M ((MCPWM_CARRIER0_DUTY_V)<<(MCPWM_CARRIER0_DUTY_S)) -#define MCPWM_CARRIER0_DUTY_V 0x7 -#define MCPWM_CARRIER0_DUTY_S 5 -/* MCPWM_CARRIER0_PRESCALE : R/W ;bitpos:[4:1] ;default: 4'd0 ; */ -/*description: PWM carrier0 clock (PC_clk) prescale value. Period of PC_clk - = period of PWM_clk * (PWM_CARRIER0_PRESCALE + 1)*/ -#define MCPWM_CARRIER0_PRESCALE 0x0000000F -#define MCPWM_CARRIER0_PRESCALE_M ((MCPWM_CARRIER0_PRESCALE_V)<<(MCPWM_CARRIER0_PRESCALE_S)) -#define MCPWM_CARRIER0_PRESCALE_V 0xF -#define MCPWM_CARRIER0_PRESCALE_S 1 -/* MCPWM_CARRIER0_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: When set carrier0 function is enabled. When cleared carrier0 is bypassed*/ -#define MCPWM_CARRIER0_EN (BIT(0)) -#define MCPWM_CARRIER0_EN_M (BIT(0)) -#define MCPWM_CARRIER0_EN_V 0x1 +/** MCPWM_CARRIER0_CFG_REG register + * PWM generator 0 carrier enable and configuratoin + */ +#define MCPWM_CARRIER0_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x64) +/** MCPWM_CARRIER0_EN : R/W; bitpos: [0]; default: 0; + * When set, carrier0 function is enabled. When cleared, carrier0 is bypassed + */ +#define MCPWM_CARRIER0_EN (BIT(0)) +#define MCPWM_CARRIER0_EN_M (MCPWM_CARRIER0_EN_V << MCPWM_CARRIER0_EN_S) +#define MCPWM_CARRIER0_EN_V 0x00000001U #define MCPWM_CARRIER0_EN_S 0 +/** MCPWM_CARRIER0_PRESCALE : R/W; bitpos: [4:1]; default: 0; + * PWM carrier0 clock (PC_clk) prescale value. Period of PC_clk = period of PWM_clk * + * (PWM_CARRIER0_PRESCALE + 1) + */ +#define MCPWM_CARRIER0_PRESCALE 0x0000000FU +#define MCPWM_CARRIER0_PRESCALE_M (MCPWM_CARRIER0_PRESCALE_V << MCPWM_CARRIER0_PRESCALE_S) +#define MCPWM_CARRIER0_PRESCALE_V 0x0000000FU +#define MCPWM_CARRIER0_PRESCALE_S 1 +/** MCPWM_CARRIER0_DUTY : R/W; bitpos: [7:5]; default: 0; + * carrier duty selection. Duty = PWM_CARRIER0_DUTY / 8 + */ +#define MCPWM_CARRIER0_DUTY 0x00000007U +#define MCPWM_CARRIER0_DUTY_M (MCPWM_CARRIER0_DUTY_V << MCPWM_CARRIER0_DUTY_S) +#define MCPWM_CARRIER0_DUTY_V 0x00000007U +#define MCPWM_CARRIER0_DUTY_S 5 +/** MCPWM_CARRIER0_OSHTWTH : R/W; bitpos: [11:8]; default: 0; + * width of the first pulse in number of periods of the carrier + */ +#define MCPWM_CARRIER0_OSHTWTH 0x0000000FU +#define MCPWM_CARRIER0_OSHTWTH_M (MCPWM_CARRIER0_OSHTWTH_V << MCPWM_CARRIER0_OSHTWTH_S) +#define MCPWM_CARRIER0_OSHTWTH_V 0x0000000FU +#define MCPWM_CARRIER0_OSHTWTH_S 8 +/** MCPWM_CARRIER0_OUT_INVERT : R/W; bitpos: [12]; default: 0; + * when set, invert the output of PWM0A and PWM0B for this submodule + */ +#define MCPWM_CARRIER0_OUT_INVERT (BIT(12)) +#define MCPWM_CARRIER0_OUT_INVERT_M (MCPWM_CARRIER0_OUT_INVERT_V << MCPWM_CARRIER0_OUT_INVERT_S) +#define MCPWM_CARRIER0_OUT_INVERT_V 0x00000001U +#define MCPWM_CARRIER0_OUT_INVERT_S 12 +/** MCPWM_CARRIER0_IN_INVERT : R/W; bitpos: [13]; default: 0; + * when set, invert the input of PWM0A and PWM0B for this submodule + */ +#define MCPWM_CARRIER0_IN_INVERT (BIT(13)) +#define MCPWM_CARRIER0_IN_INVERT_M (MCPWM_CARRIER0_IN_INVERT_V << MCPWM_CARRIER0_IN_INVERT_S) +#define MCPWM_CARRIER0_IN_INVERT_V 0x00000001U +#define MCPWM_CARRIER0_IN_INVERT_S 13 -#define MCPWM_FH0_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0x0068) -/* MCPWM_FH0_B_OST_U : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: One-shot mode action on PWM0B when fault event occurs and timer - is increasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH0_B_OST_U 0x00000003 -#define MCPWM_FH0_B_OST_U_M ((MCPWM_FH0_B_OST_U_V)<<(MCPWM_FH0_B_OST_U_S)) -#define MCPWM_FH0_B_OST_U_V 0x3 -#define MCPWM_FH0_B_OST_U_S 22 -/* MCPWM_FH0_B_OST_D : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: One-shot mode action on PWM0B when fault event occurs and timer - is decreasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH0_B_OST_D 0x00000003 -#define MCPWM_FH0_B_OST_D_M ((MCPWM_FH0_B_OST_D_V)<<(MCPWM_FH0_B_OST_D_S)) -#define MCPWM_FH0_B_OST_D_V 0x3 -#define MCPWM_FH0_B_OST_D_S 20 -/* MCPWM_FH0_B_CBC_U : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: Cycle-by-cycle mode action on PWM0B when fault event occurs and - timer is increasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH0_B_CBC_U 0x00000003 -#define MCPWM_FH0_B_CBC_U_M ((MCPWM_FH0_B_CBC_U_V)<<(MCPWM_FH0_B_CBC_U_S)) -#define MCPWM_FH0_B_CBC_U_V 0x3 -#define MCPWM_FH0_B_CBC_U_S 18 -/* MCPWM_FH0_B_CBC_D : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: Cycle-by-cycle mode action on PWM0B when fault event occurs and - timer is decreasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH0_B_CBC_D 0x00000003 -#define MCPWM_FH0_B_CBC_D_M ((MCPWM_FH0_B_CBC_D_V)<<(MCPWM_FH0_B_CBC_D_S)) -#define MCPWM_FH0_B_CBC_D_V 0x3 -#define MCPWM_FH0_B_CBC_D_S 16 -/* MCPWM_FH0_A_OST_U : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: One-shot mode action on PWM0A when fault event occurs and timer - is increasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH0_A_OST_U 0x00000003 -#define MCPWM_FH0_A_OST_U_M ((MCPWM_FH0_A_OST_U_V)<<(MCPWM_FH0_A_OST_U_S)) -#define MCPWM_FH0_A_OST_U_V 0x3 -#define MCPWM_FH0_A_OST_U_S 14 -/* MCPWM_FH0_A_OST_D : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: One-shot mode action on PWM0A when fault event occurs and timer - is decreasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH0_A_OST_D 0x00000003 -#define MCPWM_FH0_A_OST_D_M ((MCPWM_FH0_A_OST_D_V)<<(MCPWM_FH0_A_OST_D_S)) -#define MCPWM_FH0_A_OST_D_V 0x3 -#define MCPWM_FH0_A_OST_D_S 12 -/* MCPWM_FH0_A_CBC_U : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: Cycle-by-cycle mode action on PWM0A when fault event occurs and - timer is increasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH0_A_CBC_U 0x00000003 -#define MCPWM_FH0_A_CBC_U_M ((MCPWM_FH0_A_CBC_U_V)<<(MCPWM_FH0_A_CBC_U_S)) -#define MCPWM_FH0_A_CBC_U_V 0x3 -#define MCPWM_FH0_A_CBC_U_S 10 -/* MCPWM_FH0_A_CBC_D : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: Cycle-by-cycle mode action on PWM0A when fault event occurs and - timer is decreasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH0_A_CBC_D 0x00000003 -#define MCPWM_FH0_A_CBC_D_M ((MCPWM_FH0_A_CBC_D_V)<<(MCPWM_FH0_A_CBC_D_S)) -#define MCPWM_FH0_A_CBC_D_V 0x3 -#define MCPWM_FH0_A_CBC_D_S 8 -/* MCPWM_FH0_F0_OST : R/W ;bitpos:[7] ;default: 1'd0 ; */ -/*description: event_f0 will trigger one-shot mode action. 0: disable 1: enable*/ -#define MCPWM_FH0_F0_OST (BIT(7)) -#define MCPWM_FH0_F0_OST_M (BIT(7)) -#define MCPWM_FH0_F0_OST_V 0x1 -#define MCPWM_FH0_F0_OST_S 7 -/* MCPWM_FH0_F1_OST : R/W ;bitpos:[6] ;default: 1'd0 ; */ -/*description: event_f1 will trigger one-shot mode action. 0: disable 1: enable*/ -#define MCPWM_FH0_F1_OST (BIT(6)) -#define MCPWM_FH0_F1_OST_M (BIT(6)) -#define MCPWM_FH0_F1_OST_V 0x1 -#define MCPWM_FH0_F1_OST_S 6 -/* MCPWM_FH0_F2_OST : R/W ;bitpos:[5] ;default: 1'd0 ; */ -/*description: event_f2 will trigger one-shot mode action. 0: disable 1: enable*/ -#define MCPWM_FH0_F2_OST (BIT(5)) -#define MCPWM_FH0_F2_OST_M (BIT(5)) -#define MCPWM_FH0_F2_OST_V 0x1 -#define MCPWM_FH0_F2_OST_S 5 -/* MCPWM_FH0_SW_OST : R/W ;bitpos:[4] ;default: 1'd0 ; */ -/*description: Enable register for software force one-shot mode action. 0: disable 1: enable*/ -#define MCPWM_FH0_SW_OST (BIT(4)) -#define MCPWM_FH0_SW_OST_M (BIT(4)) -#define MCPWM_FH0_SW_OST_V 0x1 -#define MCPWM_FH0_SW_OST_S 4 -/* MCPWM_FH0_F0_CBC : R/W ;bitpos:[3] ;default: 1'd0 ; */ -/*description: event_f0 will trigger cycle-by-cycle mode action. 0: disable 1: enable*/ -#define MCPWM_FH0_F0_CBC (BIT(3)) -#define MCPWM_FH0_F0_CBC_M (BIT(3)) -#define MCPWM_FH0_F0_CBC_V 0x1 -#define MCPWM_FH0_F0_CBC_S 3 -/* MCPWM_FH0_F1_CBC : R/W ;bitpos:[2] ;default: 1'd0 ; */ -/*description: event_f1 will trigger cycle-by-cycle mode action. 0: disable 1: enable*/ -#define MCPWM_FH0_F1_CBC (BIT(2)) -#define MCPWM_FH0_F1_CBC_M (BIT(2)) -#define MCPWM_FH0_F1_CBC_V 0x1 -#define MCPWM_FH0_F1_CBC_S 2 -/* MCPWM_FH0_F2_CBC : R/W ;bitpos:[1] ;default: 1'd0 ; */ -/*description: event_f2 will trigger cycle-by-cycle mode action. 0: disable 1: enable*/ -#define MCPWM_FH0_F2_CBC (BIT(1)) -#define MCPWM_FH0_F2_CBC_M (BIT(1)) -#define MCPWM_FH0_F2_CBC_V 0x1 -#define MCPWM_FH0_F2_CBC_S 1 -/* MCPWM_FH0_SW_CBC : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: Enable register for software force cycle-by-cycle mode action. - 0: disable 1: enable*/ -#define MCPWM_FH0_SW_CBC (BIT(0)) -#define MCPWM_FH0_SW_CBC_M (BIT(0)) -#define MCPWM_FH0_SW_CBC_V 0x1 +/** MCPWM_FH0_CFG0_REG register + * Actions on PWM0A and PWM0B trip events + */ +#define MCPWM_FH0_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0x68) +/** MCPWM_FH0_SW_CBC : R/W; bitpos: [0]; default: 0; + * Enable register for software force cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH0_SW_CBC (BIT(0)) +#define MCPWM_FH0_SW_CBC_M (MCPWM_FH0_SW_CBC_V << MCPWM_FH0_SW_CBC_S) +#define MCPWM_FH0_SW_CBC_V 0x00000001U #define MCPWM_FH0_SW_CBC_S 0 +/** MCPWM_FH0_F2_CBC : R/W; bitpos: [1]; default: 0; + * fault_event2 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH0_F2_CBC (BIT(1)) +#define MCPWM_FH0_F2_CBC_M (MCPWM_FH0_F2_CBC_V << MCPWM_FH0_F2_CBC_S) +#define MCPWM_FH0_F2_CBC_V 0x00000001U +#define MCPWM_FH0_F2_CBC_S 1 +/** MCPWM_FH0_F1_CBC : R/W; bitpos: [2]; default: 0; + * fault_event1 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH0_F1_CBC (BIT(2)) +#define MCPWM_FH0_F1_CBC_M (MCPWM_FH0_F1_CBC_V << MCPWM_FH0_F1_CBC_S) +#define MCPWM_FH0_F1_CBC_V 0x00000001U +#define MCPWM_FH0_F1_CBC_S 2 +/** MCPWM_FH0_F0_CBC : R/W; bitpos: [3]; default: 0; + * fault_event0 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH0_F0_CBC (BIT(3)) +#define MCPWM_FH0_F0_CBC_M (MCPWM_FH0_F0_CBC_V << MCPWM_FH0_F0_CBC_S) +#define MCPWM_FH0_F0_CBC_V 0x00000001U +#define MCPWM_FH0_F0_CBC_S 3 +/** MCPWM_FH0_SW_OST : R/W; bitpos: [4]; default: 0; + * Enable register for software force one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH0_SW_OST (BIT(4)) +#define MCPWM_FH0_SW_OST_M (MCPWM_FH0_SW_OST_V << MCPWM_FH0_SW_OST_S) +#define MCPWM_FH0_SW_OST_V 0x00000001U +#define MCPWM_FH0_SW_OST_S 4 +/** MCPWM_FH0_F2_OST : R/W; bitpos: [5]; default: 0; + * fault_event2 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH0_F2_OST (BIT(5)) +#define MCPWM_FH0_F2_OST_M (MCPWM_FH0_F2_OST_V << MCPWM_FH0_F2_OST_S) +#define MCPWM_FH0_F2_OST_V 0x00000001U +#define MCPWM_FH0_F2_OST_S 5 +/** MCPWM_FH0_F1_OST : R/W; bitpos: [6]; default: 0; + * fault_event1 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH0_F1_OST (BIT(6)) +#define MCPWM_FH0_F1_OST_M (MCPWM_FH0_F1_OST_V << MCPWM_FH0_F1_OST_S) +#define MCPWM_FH0_F1_OST_V 0x00000001U +#define MCPWM_FH0_F1_OST_S 6 +/** MCPWM_FH0_F0_OST : R/W; bitpos: [7]; default: 0; + * fault_event0 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH0_F0_OST (BIT(7)) +#define MCPWM_FH0_F0_OST_M (MCPWM_FH0_F0_OST_V << MCPWM_FH0_F0_OST_S) +#define MCPWM_FH0_F0_OST_V 0x00000001U +#define MCPWM_FH0_F0_OST_S 7 +/** MCPWM_FH0_A_CBC_D : R/W; bitpos: [9:8]; default: 0; + * Cycle-by-cycle mode action on PWM0A when fault event occurs and timer is + * decreasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH0_A_CBC_D 0x00000003U +#define MCPWM_FH0_A_CBC_D_M (MCPWM_FH0_A_CBC_D_V << MCPWM_FH0_A_CBC_D_S) +#define MCPWM_FH0_A_CBC_D_V 0x00000003U +#define MCPWM_FH0_A_CBC_D_S 8 +/** MCPWM_FH0_A_CBC_U : R/W; bitpos: [11:10]; default: 0; + * Cycle-by-cycle mode action on PWM0A when fault event occurs and timer is + * increasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH0_A_CBC_U 0x00000003U +#define MCPWM_FH0_A_CBC_U_M (MCPWM_FH0_A_CBC_U_V << MCPWM_FH0_A_CBC_U_S) +#define MCPWM_FH0_A_CBC_U_V 0x00000003U +#define MCPWM_FH0_A_CBC_U_S 10 +/** MCPWM_FH0_A_OST_D : R/W; bitpos: [13:12]; default: 0; + * One-shot mode action on PWM0A when fault event occurs and timer is decreasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH0_A_OST_D 0x00000003U +#define MCPWM_FH0_A_OST_D_M (MCPWM_FH0_A_OST_D_V << MCPWM_FH0_A_OST_D_S) +#define MCPWM_FH0_A_OST_D_V 0x00000003U +#define MCPWM_FH0_A_OST_D_S 12 +/** MCPWM_FH0_A_OST_U : R/W; bitpos: [15:14]; default: 0; + * One-shot mode action on PWM0A when fault event occurs and timer is increasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH0_A_OST_U 0x00000003U +#define MCPWM_FH0_A_OST_U_M (MCPWM_FH0_A_OST_U_V << MCPWM_FH0_A_OST_U_S) +#define MCPWM_FH0_A_OST_U_V 0x00000003U +#define MCPWM_FH0_A_OST_U_S 14 +/** MCPWM_FH0_B_CBC_D : R/W; bitpos: [17:16]; default: 0; + * Cycle-by-cycle mode action on PWM0B when fault event occurs and timer is + * decreasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH0_B_CBC_D 0x00000003U +#define MCPWM_FH0_B_CBC_D_M (MCPWM_FH0_B_CBC_D_V << MCPWM_FH0_B_CBC_D_S) +#define MCPWM_FH0_B_CBC_D_V 0x00000003U +#define MCPWM_FH0_B_CBC_D_S 16 +/** MCPWM_FH0_B_CBC_U : R/W; bitpos: [19:18]; default: 0; + * Cycle-by-cycle mode action on PWM0B when fault event occurs and timer is + * increasing. 0: do nothing,1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH0_B_CBC_U 0x00000003U +#define MCPWM_FH0_B_CBC_U_M (MCPWM_FH0_B_CBC_U_V << MCPWM_FH0_B_CBC_U_S) +#define MCPWM_FH0_B_CBC_U_V 0x00000003U +#define MCPWM_FH0_B_CBC_U_S 18 +/** MCPWM_FH0_B_OST_D : R/W; bitpos: [21:20]; default: 0; + * One-shot mode action on PWM0B when fault event occurs and timer is decreasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH0_B_OST_D 0x00000003U +#define MCPWM_FH0_B_OST_D_M (MCPWM_FH0_B_OST_D_V << MCPWM_FH0_B_OST_D_S) +#define MCPWM_FH0_B_OST_D_V 0x00000003U +#define MCPWM_FH0_B_OST_D_S 20 +/** MCPWM_FH0_B_OST_U : R/W; bitpos: [23:22]; default: 0; + * One-shot mode action on PWM0B when fault event occurs and timer is increasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH0_B_OST_U 0x00000003U +#define MCPWM_FH0_B_OST_U_M (MCPWM_FH0_B_OST_U_V << MCPWM_FH0_B_OST_U_S) +#define MCPWM_FH0_B_OST_U_V 0x00000003U +#define MCPWM_FH0_B_OST_U_S 22 -#define MCPWM_FH0_CFG1_REG(i) (REG_MCPWM_BASE(i) + 0x006c) -/* MCPWM_FH0_FORCE_OST : R/W ;bitpos:[4] ;default: 1'd0 ; */ -/*description: A toggle (software negation of value of this bit) triggers a - one-shot mode action*/ -#define MCPWM_FH0_FORCE_OST (BIT(4)) -#define MCPWM_FH0_FORCE_OST_M (BIT(4)) -#define MCPWM_FH0_FORCE_OST_V 0x1 -#define MCPWM_FH0_FORCE_OST_S 4 -/* MCPWM_FH0_FORCE_CBC : R/W ;bitpos:[3] ;default: 1'd0 ; */ -/*description: A toggle triggers a cycle-by-cycle mode action*/ -#define MCPWM_FH0_FORCE_CBC (BIT(3)) -#define MCPWM_FH0_FORCE_CBC_M (BIT(3)) -#define MCPWM_FH0_FORCE_CBC_V 0x1 -#define MCPWM_FH0_FORCE_CBC_S 3 -/* MCPWM_FH0_CBCPULSE : R/W ;bitpos:[2:1] ;default: 2'd0 ; */ -/*description: The cycle-by-cycle mode action refresh moment selection. Bit0: TEZ bit1:TEP*/ -#define MCPWM_FH0_CBCPULSE 0x00000003 -#define MCPWM_FH0_CBCPULSE_M ((MCPWM_FH0_CBCPULSE_V)<<(MCPWM_FH0_CBCPULSE_S)) -#define MCPWM_FH0_CBCPULSE_V 0x3 -#define MCPWM_FH0_CBCPULSE_S 1 -/* MCPWM_FH0_CLR_OST : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: A toggle will clear on going one-shot mode action*/ -#define MCPWM_FH0_CLR_OST (BIT(0)) -#define MCPWM_FH0_CLR_OST_M (BIT(0)) -#define MCPWM_FH0_CLR_OST_V 0x1 +/** MCPWM_FH0_CFG1_REG register + * Software triggers for fault handler actions + */ +#define MCPWM_FH0_CFG1_REG(i) (DR_REG_MCPWM_BASE(i) + 0x6c) +/** MCPWM_FH0_CLR_OST : R/W; bitpos: [0]; default: 0; + * a rising edge will clear on going one-shot mode action + */ +#define MCPWM_FH0_CLR_OST (BIT(0)) +#define MCPWM_FH0_CLR_OST_M (MCPWM_FH0_CLR_OST_V << MCPWM_FH0_CLR_OST_S) +#define MCPWM_FH0_CLR_OST_V 0x00000001U #define MCPWM_FH0_CLR_OST_S 0 +/** MCPWM_FH0_CBCPULSE : R/W; bitpos: [2:1]; default: 0; + * cycle-by-cycle mode action refresh moment selection. When bit0 is set to 1: TEZ, + * when bit1 is set to 1:TEP, when bit0 and bit1 both set to 0: stop refresh, when + * bit0 and bit1 both set to 1: refresh at TEP/TEZ + */ +#define MCPWM_FH0_CBCPULSE 0x00000003U +#define MCPWM_FH0_CBCPULSE_M (MCPWM_FH0_CBCPULSE_V << MCPWM_FH0_CBCPULSE_S) +#define MCPWM_FH0_CBCPULSE_V 0x00000003U +#define MCPWM_FH0_CBCPULSE_S 1 +/** MCPWM_FH0_FORCE_CBC : R/W; bitpos: [3]; default: 0; + * a toggle trigger a cycle-by-cycle mode action + */ +#define MCPWM_FH0_FORCE_CBC (BIT(3)) +#define MCPWM_FH0_FORCE_CBC_M (MCPWM_FH0_FORCE_CBC_V << MCPWM_FH0_FORCE_CBC_S) +#define MCPWM_FH0_FORCE_CBC_V 0x00000001U +#define MCPWM_FH0_FORCE_CBC_S 3 +/** MCPWM_FH0_FORCE_OST : R/W; bitpos: [4]; default: 0; + * a toggle (software negate its value) triggers a one-shot mode action + */ +#define MCPWM_FH0_FORCE_OST (BIT(4)) +#define MCPWM_FH0_FORCE_OST_M (MCPWM_FH0_FORCE_OST_V << MCPWM_FH0_FORCE_OST_S) +#define MCPWM_FH0_FORCE_OST_V 0x00000001U +#define MCPWM_FH0_FORCE_OST_S 4 -#define MCPWM_FH0_STATUS_REG(i) (REG_MCPWM_BASE(i) + 0x0070) -/* MCPWM_FH0_OST_ON : RO ;bitpos:[1] ;default: 1'd0 ; */ -/*description: Set and reset by hardware. If set an one-shot mode action is on going*/ -#define MCPWM_FH0_OST_ON (BIT(1)) -#define MCPWM_FH0_OST_ON_M (BIT(1)) -#define MCPWM_FH0_OST_ON_V 0x1 -#define MCPWM_FH0_OST_ON_S 1 -/* MCPWM_FH0_CBC_ON : RO ;bitpos:[0] ;default: 1'd0 ; */ -/*description: Set and reset by hardware. If set an cycle-by-cycle mode action is on going*/ -#define MCPWM_FH0_CBC_ON (BIT(0)) -#define MCPWM_FH0_CBC_ON_M (BIT(0)) -#define MCPWM_FH0_CBC_ON_V 0x1 +/** MCPWM_FH0_STATUS_REG register + * Status of fault events. + */ +#define MCPWM_FH0_STATUS_REG(i) (DR_REG_MCPWM_BASE(i) + 0x70) +/** MCPWM_FH0_CBC_ON : RO; bitpos: [0]; default: 0; + * Set and reset by hardware. If set, a cycle-by-cycle mode action is on going + */ +#define MCPWM_FH0_CBC_ON (BIT(0)) +#define MCPWM_FH0_CBC_ON_M (MCPWM_FH0_CBC_ON_V << MCPWM_FH0_CBC_ON_S) +#define MCPWM_FH0_CBC_ON_V 0x00000001U #define MCPWM_FH0_CBC_ON_S 0 +/** MCPWM_FH0_OST_ON : RO; bitpos: [1]; default: 0; + * Set and reset by hardware. If set, an one-shot mode action is on going + */ +#define MCPWM_FH0_OST_ON (BIT(1)) +#define MCPWM_FH0_OST_ON_M (MCPWM_FH0_OST_ON_V << MCPWM_FH0_OST_ON_S) +#define MCPWM_FH0_OST_ON_V 0x00000001U +#define MCPWM_FH0_OST_ON_S 1 -#define MCPWM_GEN1_STMP_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x0074) -/* MCPWM_GEN1_B_SHDW_FULL : RO ;bitpos:[9] ;default: 1'd0 ; */ -/*description: Set and reset by hardware. If set PWM generator 1 time stamp - B's shadow reg is filled and waiting to be transferred to B's active reg. If cleared B's active reg has been updated with shadow reg latest value*/ -#define MCPWM_GEN1_B_SHDW_FULL (BIT(9)) -#define MCPWM_GEN1_B_SHDW_FULL_M (BIT(9)) -#define MCPWM_GEN1_B_SHDW_FULL_V 0x1 -#define MCPWM_GEN1_B_SHDW_FULL_S 9 -/* MCPWM_GEN1_A_SHDW_FULL : RO ;bitpos:[8] ;default: 1'd0 ; */ -/*description: Set and reset by hardware. If set PWM generator 1 time stamp - A's shadow reg is filled and waiting to be transferred to A's active reg. If cleared A's active reg has been updated with shadow reg latest value*/ -#define MCPWM_GEN1_A_SHDW_FULL (BIT(8)) -#define MCPWM_GEN1_A_SHDW_FULL_M (BIT(8)) -#define MCPWM_GEN1_A_SHDW_FULL_V 0x1 -#define MCPWM_GEN1_A_SHDW_FULL_S 8 -/* MCPWM_GEN1_B_UPMETHOD : R/W ;bitpos:[7:4] ;default: 4'd0 ; */ -/*description: Update method for PWM generator 1 time stamp B's active reg. - 0: immediate bit0: TEZ bit1: TEP bit2: sync bit3: disable update*/ -#define MCPWM_GEN1_B_UPMETHOD 0x0000000F -#define MCPWM_GEN1_B_UPMETHOD_M ((MCPWM_GEN1_B_UPMETHOD_V)<<(MCPWM_GEN1_B_UPMETHOD_S)) -#define MCPWM_GEN1_B_UPMETHOD_V 0xF -#define MCPWM_GEN1_B_UPMETHOD_S 4 -/* MCPWM_GEN1_A_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: Update method for PWM generator 1 time stamp A's active reg. - 0: immediate bit0: TEZ bit1: TEP bit2: sync bit3: disable update*/ -#define MCPWM_GEN1_A_UPMETHOD 0x0000000F -#define MCPWM_GEN1_A_UPMETHOD_M ((MCPWM_GEN1_A_UPMETHOD_V)<<(MCPWM_GEN1_A_UPMETHOD_S)) -#define MCPWM_GEN1_A_UPMETHOD_V 0xF +/** MCPWM_GEN1_STMP_CFG_REG register + * Transfer status and update method for time stamp registers A and B + */ +#define MCPWM_GEN1_STMP_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x74) +/** MCPWM_GEN1_A_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for PWM generator 1 time stamp A's active register. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when + * bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + */ +#define MCPWM_GEN1_A_UPMETHOD 0x0000000FU +#define MCPWM_GEN1_A_UPMETHOD_M (MCPWM_GEN1_A_UPMETHOD_V << MCPWM_GEN1_A_UPMETHOD_S) +#define MCPWM_GEN1_A_UPMETHOD_V 0x0000000FU #define MCPWM_GEN1_A_UPMETHOD_S 0 +/** MCPWM_GEN1_B_UPMETHOD : R/W; bitpos: [7:4]; default: 0; + * Update method for PWM generator 1 time stamp B's active register. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when + * bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + */ +#define MCPWM_GEN1_B_UPMETHOD 0x0000000FU +#define MCPWM_GEN1_B_UPMETHOD_M (MCPWM_GEN1_B_UPMETHOD_V << MCPWM_GEN1_B_UPMETHOD_S) +#define MCPWM_GEN1_B_UPMETHOD_V 0x0000000FU +#define MCPWM_GEN1_B_UPMETHOD_S 4 +/** MCPWM_GEN1_A_SHDW_FULL : R/W/WTC/SC; bitpos: [8]; default: 0; + * Set and reset by hardware. If set, PWM generator 1 time stamp A's shadow reg is + * filled and waiting to be transferred to A's active reg. If cleared, A's active reg + * has been updated with shadow register latest value + */ +#define MCPWM_GEN1_A_SHDW_FULL (BIT(8)) +#define MCPWM_GEN1_A_SHDW_FULL_M (MCPWM_GEN1_A_SHDW_FULL_V << MCPWM_GEN1_A_SHDW_FULL_S) +#define MCPWM_GEN1_A_SHDW_FULL_V 0x00000001U +#define MCPWM_GEN1_A_SHDW_FULL_S 8 +/** MCPWM_GEN1_B_SHDW_FULL : R/W/WTC/SC; bitpos: [9]; default: 0; + * Set and reset by hardware. If set, PWM generator 1 time stamp B's shadow reg is + * filled and waiting to be transferred to B's active reg. If cleared, B's active reg + * has been updated with shadow register latest value + */ +#define MCPWM_GEN1_B_SHDW_FULL (BIT(9)) +#define MCPWM_GEN1_B_SHDW_FULL_M (MCPWM_GEN1_B_SHDW_FULL_V << MCPWM_GEN1_B_SHDW_FULL_S) +#define MCPWM_GEN1_B_SHDW_FULL_V 0x00000001U +#define MCPWM_GEN1_B_SHDW_FULL_S 9 -#define MCPWM_GEN1_TSTMP_A_REG(i) (REG_MCPWM_BASE(i) + 0x0078) -/* MCPWM_GEN1_A : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: PWM generator 1 time stamp A's shadow reg*/ -#define MCPWM_GEN1_A 0x0000FFFF -#define MCPWM_GEN1_A_M ((MCPWM_GEN1_A_V)<<(MCPWM_GEN1_A_S)) -#define MCPWM_GEN1_A_V 0xFFFF +/** MCPWM_GEN1_TSTMP_A_REG register + * PWM generator 1 shadow register for timer stamp A. + */ +#define MCPWM_GEN1_TSTMP_A_REG(i) (DR_REG_MCPWM_BASE(i) + 0x78) +/** MCPWM_GEN1_A : R/W; bitpos: [15:0]; default: 0; + * PWM generator 1 time stamp A's shadow register + */ +#define MCPWM_GEN1_A 0x0000FFFFU +#define MCPWM_GEN1_A_M (MCPWM_GEN1_A_V << MCPWM_GEN1_A_S) +#define MCPWM_GEN1_A_V 0x0000FFFFU #define MCPWM_GEN1_A_S 0 -#define MCPWM_GEN1_TSTMP_B_REG(i) (REG_MCPWM_BASE(i) + 0x007c) -/* MCPWM_GEN1_B : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: PWM generator 1 time stamp B's shadow reg*/ -#define MCPWM_GEN1_B 0x0000FFFF -#define MCPWM_GEN1_B_M ((MCPWM_GEN1_B_V)<<(MCPWM_GEN1_B_S)) -#define MCPWM_GEN1_B_V 0xFFFF +/** MCPWM_GEN1_TSTMP_B_REG register + * PWM generator 1 shadow register for timer stamp B. + */ +#define MCPWM_GEN1_TSTMP_B_REG(i) (DR_REG_MCPWM_BASE(i) + 0x7c) +/** MCPWM_GEN1_B : R/W; bitpos: [15:0]; default: 0; + * PWM generator 1 time stamp B's shadow register + */ +#define MCPWM_GEN1_B 0x0000FFFFU +#define MCPWM_GEN1_B_M (MCPWM_GEN1_B_V << MCPWM_GEN1_B_S) +#define MCPWM_GEN1_B_V 0x0000FFFFU #define MCPWM_GEN1_B_S 0 -#define MCPWM_GEN1_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0x0080) -/* MCPWM_GEN1_T1_SEL : R/W ;bitpos:[9:7] ;default: 3'd0 ; */ -/*description: Source selection for PWM generate1 event_t1 take effect immediately - 0: fault_event0 1: fault_event1 2: fault_event2 3: sync_taken 4: none*/ -#define MCPWM_GEN1_T1_SEL 0x00000007 -#define MCPWM_GEN1_T1_SEL_M ((MCPWM_GEN1_T1_SEL_V)<<(MCPWM_GEN1_T1_SEL_S)) -#define MCPWM_GEN1_T1_SEL_V 0x7 -#define MCPWM_GEN1_T1_SEL_S 7 -/* MCPWM_GEN1_T0_SEL : R/W ;bitpos:[6:4] ;default: 3'd0 ; */ -/*description: Source selection for PWM generate1 event_t0 take effect immediately - 0: fault_event0 1: fault_event1 2: fault_event2 3: sync_taken 4: none*/ -#define MCPWM_GEN1_T0_SEL 0x00000007 -#define MCPWM_GEN1_T0_SEL_M ((MCPWM_GEN1_T0_SEL_V)<<(MCPWM_GEN1_T0_SEL_S)) -#define MCPWM_GEN1_T0_SEL_V 0x7 -#define MCPWM_GEN1_T0_SEL_S 4 -/* MCPWM_GEN1_CFG_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: Update method for PWM generate1's active reg of configuration. - 0: immediate bit0: TEZ bit1: TEP bit2: sync. bit3: disable update*/ -#define MCPWM_GEN1_CFG_UPMETHOD 0x0000000F -#define MCPWM_GEN1_CFG_UPMETHOD_M ((MCPWM_GEN1_CFG_UPMETHOD_V)<<(MCPWM_GEN1_CFG_UPMETHOD_S)) -#define MCPWM_GEN1_CFG_UPMETHOD_V 0xF +/** MCPWM_GEN1_CFG0_REG register + * PWM generator 1 event T0 and T1 handling + */ +#define MCPWM_GEN1_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0x80) +/** MCPWM_GEN1_CFG_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for PWM generator 1's active register of configuration. When all bits + * are set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to + * 1:sync;when bit3 is set to 1:disable the update. + */ +#define MCPWM_GEN1_CFG_UPMETHOD 0x0000000FU +#define MCPWM_GEN1_CFG_UPMETHOD_M (MCPWM_GEN1_CFG_UPMETHOD_V << MCPWM_GEN1_CFG_UPMETHOD_S) +#define MCPWM_GEN1_CFG_UPMETHOD_V 0x0000000FU #define MCPWM_GEN1_CFG_UPMETHOD_S 0 +/** MCPWM_GEN1_T0_SEL : R/W; bitpos: [6:4]; default: 0; + * Source selection for PWM generator 1 event_t0, take effect immediately, 0: + * fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + */ +#define MCPWM_GEN1_T0_SEL 0x00000007U +#define MCPWM_GEN1_T0_SEL_M (MCPWM_GEN1_T0_SEL_V << MCPWM_GEN1_T0_SEL_S) +#define MCPWM_GEN1_T0_SEL_V 0x00000007U +#define MCPWM_GEN1_T0_SEL_S 4 +/** MCPWM_GEN1_T1_SEL : R/W; bitpos: [9:7]; default: 0; + * Source selection for PWM generator 1 event_t1, take effect immediately, 0: + * fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + */ +#define MCPWM_GEN1_T1_SEL 0x00000007U +#define MCPWM_GEN1_T1_SEL_M (MCPWM_GEN1_T1_SEL_V << MCPWM_GEN1_T1_SEL_S) +#define MCPWM_GEN1_T1_SEL_V 0x00000007U +#define MCPWM_GEN1_T1_SEL_S 7 -#define MCPWM_GEN1_FORCE_REG(i) (REG_MCPWM_BASE(i) + 0x0084) -/* MCPWM_GEN1_B_NCIFORCE_MODE : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: Non-continuous immediate software force mode for PWM1B 0: disabled - 1: low 2: high 3: disabled*/ -#define MCPWM_GEN1_B_NCIFORCE_MODE 0x00000003 -#define MCPWM_GEN1_B_NCIFORCE_MODE_M ((MCPWM_GEN1_B_NCIFORCE_MODE_V)<<(MCPWM_GEN1_B_NCIFORCE_MODE_S)) -#define MCPWM_GEN1_B_NCIFORCE_MODE_V 0x3 -#define MCPWM_GEN1_B_NCIFORCE_MODE_S 14 -/* MCPWM_GEN1_B_NCIFORCE : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: Non-continuous immediate software force trigger for PWM1B a - toggle will trigger a force event*/ -#define MCPWM_GEN1_B_NCIFORCE (BIT(13)) -#define MCPWM_GEN1_B_NCIFORCE_M (BIT(13)) -#define MCPWM_GEN1_B_NCIFORCE_V 0x1 -#define MCPWM_GEN1_B_NCIFORCE_S 13 -/* MCPWM_GEN1_A_NCIFORCE_MODE : R/W ;bitpos:[12:11] ;default: 2'd0 ; */ -/*description: Non-continuous immediate software force mode for PWM1A 0: disabled - 1: low 2: high 3: disabled*/ -#define MCPWM_GEN1_A_NCIFORCE_MODE 0x00000003 -#define MCPWM_GEN1_A_NCIFORCE_MODE_M ((MCPWM_GEN1_A_NCIFORCE_MODE_V)<<(MCPWM_GEN1_A_NCIFORCE_MODE_S)) -#define MCPWM_GEN1_A_NCIFORCE_MODE_V 0x3 -#define MCPWM_GEN1_A_NCIFORCE_MODE_S 11 -/* MCPWM_GEN1_A_NCIFORCE : R/W ;bitpos:[10] ;default: 1'd0 ; */ -/*description: Non-continuous immediate software force trigger for PWM1A a - toggle will trigger a force event*/ -#define MCPWM_GEN1_A_NCIFORCE (BIT(10)) -#define MCPWM_GEN1_A_NCIFORCE_M (BIT(10)) -#define MCPWM_GEN1_A_NCIFORCE_V 0x1 -#define MCPWM_GEN1_A_NCIFORCE_S 10 -/* MCPWM_GEN1_B_CNTUFORCE_MODE : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: Continuous software force mode for PWM1B. 0: disabled 1: low - 2: high 3: disabled*/ -#define MCPWM_GEN1_B_CNTUFORCE_MODE 0x00000003 -#define MCPWM_GEN1_B_CNTUFORCE_MODE_M ((MCPWM_GEN1_B_CNTUFORCE_MODE_V)<<(MCPWM_GEN1_B_CNTUFORCE_MODE_S)) -#define MCPWM_GEN1_B_CNTUFORCE_MODE_V 0x3 -#define MCPWM_GEN1_B_CNTUFORCE_MODE_S 8 -/* MCPWM_GEN1_A_CNTUFORCE_MODE : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: Continuous software force mode for PWM1A. 0: disabled 1: low - 2: high 3: disabled*/ -#define MCPWM_GEN1_A_CNTUFORCE_MODE 0x00000003 -#define MCPWM_GEN1_A_CNTUFORCE_MODE_M ((MCPWM_GEN1_A_CNTUFORCE_MODE_V)<<(MCPWM_GEN1_A_CNTUFORCE_MODE_S)) -#define MCPWM_GEN1_A_CNTUFORCE_MODE_V 0x3 -#define MCPWM_GEN1_A_CNTUFORCE_MODE_S 6 -/* MCPWM_GEN1_CNTUFORCE_UPMETHOD : R/W ;bitpos:[5:0] ;default: 6'h20 ; */ -/*description: Update method for continuous software force of PWM generator1. - 0: immediate bit0: TEZ bit1: TEP bit2: TEA bit3: TEB bit4: sync bit5: disable update. (TEA/B here and below means an event generated when timer value equals A/B register)*/ -#define MCPWM_GEN1_CNTUFORCE_UPMETHOD 0x0000003F -#define MCPWM_GEN1_CNTUFORCE_UPMETHOD_M ((MCPWM_GEN1_CNTUFORCE_UPMETHOD_V)<<(MCPWM_GEN1_CNTUFORCE_UPMETHOD_S)) -#define MCPWM_GEN1_CNTUFORCE_UPMETHOD_V 0x3F +/** MCPWM_GEN1_FORCE_REG register + * Permissives to force PWM1A and PWM1B outputs by software + */ +#define MCPWM_GEN1_FORCE_REG(i) (DR_REG_MCPWM_BASE(i) + 0x84) +/** MCPWM_GEN1_CNTUFORCE_UPMETHOD : R/W; bitpos: [5:0]; default: 32; + * Updating method for continuous software force of PWM generator 1. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ,when bit1 is set to 1: TEP, when + * bit2 is set to 1: TEA, when bit3 is set to 1: TEB, when bit4 is set to 1: sync, + * when bit5 is set to 1: disable update. (TEA/B here and below means an event + * generated when the timer's value equals to that of register A/B.) + */ +#define MCPWM_GEN1_CNTUFORCE_UPMETHOD 0x0000003FU +#define MCPWM_GEN1_CNTUFORCE_UPMETHOD_M (MCPWM_GEN1_CNTUFORCE_UPMETHOD_V << MCPWM_GEN1_CNTUFORCE_UPMETHOD_S) +#define MCPWM_GEN1_CNTUFORCE_UPMETHOD_V 0x0000003FU #define MCPWM_GEN1_CNTUFORCE_UPMETHOD_S 0 +/** MCPWM_GEN1_A_CNTUFORCE_MODE : R/W; bitpos: [7:6]; default: 0; + * Continuous software force mode for PWM1A. 0: disabled, 1: low, 2: high, 3: disabled + */ +#define MCPWM_GEN1_A_CNTUFORCE_MODE 0x00000003U +#define MCPWM_GEN1_A_CNTUFORCE_MODE_M (MCPWM_GEN1_A_CNTUFORCE_MODE_V << MCPWM_GEN1_A_CNTUFORCE_MODE_S) +#define MCPWM_GEN1_A_CNTUFORCE_MODE_V 0x00000003U +#define MCPWM_GEN1_A_CNTUFORCE_MODE_S 6 +/** MCPWM_GEN1_B_CNTUFORCE_MODE : R/W; bitpos: [9:8]; default: 0; + * Continuous software force mode for PWM1B. 0: disabled, 1: low, 2: high, 3: disabled + */ +#define MCPWM_GEN1_B_CNTUFORCE_MODE 0x00000003U +#define MCPWM_GEN1_B_CNTUFORCE_MODE_M (MCPWM_GEN1_B_CNTUFORCE_MODE_V << MCPWM_GEN1_B_CNTUFORCE_MODE_S) +#define MCPWM_GEN1_B_CNTUFORCE_MODE_V 0x00000003U +#define MCPWM_GEN1_B_CNTUFORCE_MODE_S 8 +/** MCPWM_GEN1_A_NCIFORCE : R/W; bitpos: [10]; default: 0; + * Trigger of non-continuous immediate software-force event for PWM1A, a toggle will + * trigger a force event. + */ +#define MCPWM_GEN1_A_NCIFORCE (BIT(10)) +#define MCPWM_GEN1_A_NCIFORCE_M (MCPWM_GEN1_A_NCIFORCE_V << MCPWM_GEN1_A_NCIFORCE_S) +#define MCPWM_GEN1_A_NCIFORCE_V 0x00000001U +#define MCPWM_GEN1_A_NCIFORCE_S 10 +/** MCPWM_GEN1_A_NCIFORCE_MODE : R/W; bitpos: [12:11]; default: 0; + * non-continuous immediate software force mode for PWM1A, 0: disabled, 1: low, 2: + * high, 3: disabled + */ +#define MCPWM_GEN1_A_NCIFORCE_MODE 0x00000003U +#define MCPWM_GEN1_A_NCIFORCE_MODE_M (MCPWM_GEN1_A_NCIFORCE_MODE_V << MCPWM_GEN1_A_NCIFORCE_MODE_S) +#define MCPWM_GEN1_A_NCIFORCE_MODE_V 0x00000003U +#define MCPWM_GEN1_A_NCIFORCE_MODE_S 11 +/** MCPWM_GEN1_B_NCIFORCE : R/W; bitpos: [13]; default: 0; + * Trigger of non-continuous immediate software-force event for PWM1B, a toggle will + * trigger a force event. + */ +#define MCPWM_GEN1_B_NCIFORCE (BIT(13)) +#define MCPWM_GEN1_B_NCIFORCE_M (MCPWM_GEN1_B_NCIFORCE_V << MCPWM_GEN1_B_NCIFORCE_S) +#define MCPWM_GEN1_B_NCIFORCE_V 0x00000001U +#define MCPWM_GEN1_B_NCIFORCE_S 13 +/** MCPWM_GEN1_B_NCIFORCE_MODE : R/W; bitpos: [15:14]; default: 0; + * non-continuous immediate software force mode for PWM1B, 0: disabled, 1: low, 2: + * high, 3: disabled + */ +#define MCPWM_GEN1_B_NCIFORCE_MODE 0x00000003U +#define MCPWM_GEN1_B_NCIFORCE_MODE_M (MCPWM_GEN1_B_NCIFORCE_MODE_V << MCPWM_GEN1_B_NCIFORCE_MODE_S) +#define MCPWM_GEN1_B_NCIFORCE_MODE_V 0x00000003U +#define MCPWM_GEN1_B_NCIFORCE_MODE_S 14 -#define MCPWM_GEN1_A_REG(i) (REG_MCPWM_BASE(i) + 0x0088) -/* MCPWM_GEN1_A_DT1 : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: Action on PWM1A triggered by event_t1 when timer decreasing. - 0: no change 1: low 2: high 3: toggle*/ -#define MCPWM_GEN1_A_DT1 0x00000003 -#define MCPWM_GEN1_A_DT1_M ((MCPWM_GEN1_A_DT1_V)<<(MCPWM_GEN1_A_DT1_S)) -#define MCPWM_GEN1_A_DT1_V 0x3 -#define MCPWM_GEN1_A_DT1_S 22 -/* MCPWM_GEN1_A_DT0 : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: Action on PWM1A triggered by event_t0 when timer decreasing*/ -#define MCPWM_GEN1_A_DT0 0x00000003 -#define MCPWM_GEN1_A_DT0_M ((MCPWM_GEN1_A_DT0_V)<<(MCPWM_GEN1_A_DT0_S)) -#define MCPWM_GEN1_A_DT0_V 0x3 -#define MCPWM_GEN1_A_DT0_S 20 -/* MCPWM_GEN1_A_DTEB : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: Action on PWM1A triggered by event TEB when timer decreasing*/ -#define MCPWM_GEN1_A_DTEB 0x00000003 -#define MCPWM_GEN1_A_DTEB_M ((MCPWM_GEN1_A_DTEB_V)<<(MCPWM_GEN1_A_DTEB_S)) -#define MCPWM_GEN1_A_DTEB_V 0x3 -#define MCPWM_GEN1_A_DTEB_S 18 -/* MCPWM_GEN1_A_DTEA : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: Action on PWM1A triggered by event TEA when timer decreasing*/ -#define MCPWM_GEN1_A_DTEA 0x00000003 -#define MCPWM_GEN1_A_DTEA_M ((MCPWM_GEN1_A_DTEA_V)<<(MCPWM_GEN1_A_DTEA_S)) -#define MCPWM_GEN1_A_DTEA_V 0x3 -#define MCPWM_GEN1_A_DTEA_S 16 -/* MCPWM_GEN1_A_DTEP : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: Action on PWM1A triggered by event TEP when timer decreasing*/ -#define MCPWM_GEN1_A_DTEP 0x00000003 -#define MCPWM_GEN1_A_DTEP_M ((MCPWM_GEN1_A_DTEP_V)<<(MCPWM_GEN1_A_DTEP_S)) -#define MCPWM_GEN1_A_DTEP_V 0x3 -#define MCPWM_GEN1_A_DTEP_S 14 -/* MCPWM_GEN1_A_DTEZ : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: Action on PWM1A triggered by event TEZ when timer decreasing*/ -#define MCPWM_GEN1_A_DTEZ 0x00000003 -#define MCPWM_GEN1_A_DTEZ_M ((MCPWM_GEN1_A_DTEZ_V)<<(MCPWM_GEN1_A_DTEZ_S)) -#define MCPWM_GEN1_A_DTEZ_V 0x3 -#define MCPWM_GEN1_A_DTEZ_S 12 -/* MCPWM_GEN1_A_UT1 : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: Action on PWM1A triggered by event_t1 when timer increasing*/ -#define MCPWM_GEN1_A_UT1 0x00000003 -#define MCPWM_GEN1_A_UT1_M ((MCPWM_GEN1_A_UT1_V)<<(MCPWM_GEN1_A_UT1_S)) -#define MCPWM_GEN1_A_UT1_V 0x3 -#define MCPWM_GEN1_A_UT1_S 10 -/* MCPWM_GEN1_A_UT0 : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: Action on PWM1A triggered by event_t0 when timer increasing*/ -#define MCPWM_GEN1_A_UT0 0x00000003 -#define MCPWM_GEN1_A_UT0_M ((MCPWM_GEN1_A_UT0_V)<<(MCPWM_GEN1_A_UT0_S)) -#define MCPWM_GEN1_A_UT0_V 0x3 -#define MCPWM_GEN1_A_UT0_S 8 -/* MCPWM_GEN1_A_UTEB : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: Action on PWM1A triggered by event TEB when timer increasing*/ -#define MCPWM_GEN1_A_UTEB 0x00000003 -#define MCPWM_GEN1_A_UTEB_M ((MCPWM_GEN1_A_UTEB_V)<<(MCPWM_GEN1_A_UTEB_S)) -#define MCPWM_GEN1_A_UTEB_V 0x3 -#define MCPWM_GEN1_A_UTEB_S 6 -/* MCPWM_GEN1_A_UTEA : R/W ;bitpos:[5:4] ;default: 2'd0 ; */ -/*description: Action on PWM1A triggered by event TEA when timer increasing*/ -#define MCPWM_GEN1_A_UTEA 0x00000003 -#define MCPWM_GEN1_A_UTEA_M ((MCPWM_GEN1_A_UTEA_V)<<(MCPWM_GEN1_A_UTEA_S)) -#define MCPWM_GEN1_A_UTEA_V 0x3 -#define MCPWM_GEN1_A_UTEA_S 4 -/* MCPWM_GEN1_A_UTEP : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: Action on PWM1A triggered by event TEP when timer increasing*/ -#define MCPWM_GEN1_A_UTEP 0x00000003 -#define MCPWM_GEN1_A_UTEP_M ((MCPWM_GEN1_A_UTEP_V)<<(MCPWM_GEN1_A_UTEP_S)) -#define MCPWM_GEN1_A_UTEP_V 0x3 -#define MCPWM_GEN1_A_UTEP_S 2 -/* MCPWM_GEN1_A_UTEZ : R/W ;bitpos:[1:0] ;default: 2'd0 ; */ -/*description: Action on PWM1A triggered by event TEZ when timer increasing*/ -#define MCPWM_GEN1_A_UTEZ 0x00000003 -#define MCPWM_GEN1_A_UTEZ_M ((MCPWM_GEN1_A_UTEZ_V)<<(MCPWM_GEN1_A_UTEZ_S)) -#define MCPWM_GEN1_A_UTEZ_V 0x3 +/** MCPWM_GEN1_A_REG register + * Actions triggered by events on PWM1A + */ +#define MCPWM_GEN1_A_REG(i) (DR_REG_MCPWM_BASE(i) + 0x88) +/** MCPWM_GEN1_A_UTEZ : R/W; bitpos: [1:0]; default: 0; + * Action on PWM1A triggered by event TEZ when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_UTEZ 0x00000003U +#define MCPWM_GEN1_A_UTEZ_M (MCPWM_GEN1_A_UTEZ_V << MCPWM_GEN1_A_UTEZ_S) +#define MCPWM_GEN1_A_UTEZ_V 0x00000003U #define MCPWM_GEN1_A_UTEZ_S 0 +/** MCPWM_GEN1_A_UTEP : R/W; bitpos: [3:2]; default: 0; + * Action on PWM1A triggered by event TEP when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_UTEP 0x00000003U +#define MCPWM_GEN1_A_UTEP_M (MCPWM_GEN1_A_UTEP_V << MCPWM_GEN1_A_UTEP_S) +#define MCPWM_GEN1_A_UTEP_V 0x00000003U +#define MCPWM_GEN1_A_UTEP_S 2 +/** MCPWM_GEN1_A_UTEA : R/W; bitpos: [5:4]; default: 0; + * Action on PWM1A triggered by event TEA when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_UTEA 0x00000003U +#define MCPWM_GEN1_A_UTEA_M (MCPWM_GEN1_A_UTEA_V << MCPWM_GEN1_A_UTEA_S) +#define MCPWM_GEN1_A_UTEA_V 0x00000003U +#define MCPWM_GEN1_A_UTEA_S 4 +/** MCPWM_GEN1_A_UTEB : R/W; bitpos: [7:6]; default: 0; + * Action on PWM1A triggered by event TEB when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_UTEB 0x00000003U +#define MCPWM_GEN1_A_UTEB_M (MCPWM_GEN1_A_UTEB_V << MCPWM_GEN1_A_UTEB_S) +#define MCPWM_GEN1_A_UTEB_V 0x00000003U +#define MCPWM_GEN1_A_UTEB_S 6 +/** MCPWM_GEN1_A_UT0 : R/W; bitpos: [9:8]; default: 0; + * Action on PWM1A triggered by event_t0 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_UT0 0x00000003U +#define MCPWM_GEN1_A_UT0_M (MCPWM_GEN1_A_UT0_V << MCPWM_GEN1_A_UT0_S) +#define MCPWM_GEN1_A_UT0_V 0x00000003U +#define MCPWM_GEN1_A_UT0_S 8 +/** MCPWM_GEN1_A_UT1 : R/W; bitpos: [11:10]; default: 0; + * Action on PWM1A triggered by event_t1 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_UT1 0x00000003U +#define MCPWM_GEN1_A_UT1_M (MCPWM_GEN1_A_UT1_V << MCPWM_GEN1_A_UT1_S) +#define MCPWM_GEN1_A_UT1_V 0x00000003U +#define MCPWM_GEN1_A_UT1_S 10 +/** MCPWM_GEN1_A_DTEZ : R/W; bitpos: [13:12]; default: 0; + * Action on PWM1A triggered by event TEZ when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_DTEZ 0x00000003U +#define MCPWM_GEN1_A_DTEZ_M (MCPWM_GEN1_A_DTEZ_V << MCPWM_GEN1_A_DTEZ_S) +#define MCPWM_GEN1_A_DTEZ_V 0x00000003U +#define MCPWM_GEN1_A_DTEZ_S 12 +/** MCPWM_GEN1_A_DTEP : R/W; bitpos: [15:14]; default: 0; + * Action on PWM1A triggered by event TEP when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_DTEP 0x00000003U +#define MCPWM_GEN1_A_DTEP_M (MCPWM_GEN1_A_DTEP_V << MCPWM_GEN1_A_DTEP_S) +#define MCPWM_GEN1_A_DTEP_V 0x00000003U +#define MCPWM_GEN1_A_DTEP_S 14 +/** MCPWM_GEN1_A_DTEA : R/W; bitpos: [17:16]; default: 0; + * Action on PWM1A triggered by event TEA when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_DTEA 0x00000003U +#define MCPWM_GEN1_A_DTEA_M (MCPWM_GEN1_A_DTEA_V << MCPWM_GEN1_A_DTEA_S) +#define MCPWM_GEN1_A_DTEA_V 0x00000003U +#define MCPWM_GEN1_A_DTEA_S 16 +/** MCPWM_GEN1_A_DTEB : R/W; bitpos: [19:18]; default: 0; + * Action on PWM1A triggered by event TEB when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_DTEB 0x00000003U +#define MCPWM_GEN1_A_DTEB_M (MCPWM_GEN1_A_DTEB_V << MCPWM_GEN1_A_DTEB_S) +#define MCPWM_GEN1_A_DTEB_V 0x00000003U +#define MCPWM_GEN1_A_DTEB_S 18 +/** MCPWM_GEN1_A_DT0 : R/W; bitpos: [21:20]; default: 0; + * Action on PWM1A triggered by event_t0 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_DT0 0x00000003U +#define MCPWM_GEN1_A_DT0_M (MCPWM_GEN1_A_DT0_V << MCPWM_GEN1_A_DT0_S) +#define MCPWM_GEN1_A_DT0_V 0x00000003U +#define MCPWM_GEN1_A_DT0_S 20 +/** MCPWM_GEN1_A_DT1 : R/W; bitpos: [23:22]; default: 0; + * Action on PWM1A triggered by event_t1 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_DT1 0x00000003U +#define MCPWM_GEN1_A_DT1_M (MCPWM_GEN1_A_DT1_V << MCPWM_GEN1_A_DT1_S) +#define MCPWM_GEN1_A_DT1_V 0x00000003U +#define MCPWM_GEN1_A_DT1_S 22 -#define MCPWM_GEN1_B_REG(i) (REG_MCPWM_BASE(i) + 0x008c) -/* MCPWM_GEN1_B_DT1 : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: Action on PWM1B triggered by event_t1 when timer decreasing. - 0: no change 1: low 2: high 3: toggle*/ -#define MCPWM_GEN1_B_DT1 0x00000003 -#define MCPWM_GEN1_B_DT1_M ((MCPWM_GEN1_B_DT1_V)<<(MCPWM_GEN1_B_DT1_S)) -#define MCPWM_GEN1_B_DT1_V 0x3 -#define MCPWM_GEN1_B_DT1_S 22 -/* MCPWM_GEN1_B_DT0 : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: Action on PWM1B triggered by event_t0 when timer decreasing*/ -#define MCPWM_GEN1_B_DT0 0x00000003 -#define MCPWM_GEN1_B_DT0_M ((MCPWM_GEN1_B_DT0_V)<<(MCPWM_GEN1_B_DT0_S)) -#define MCPWM_GEN1_B_DT0_V 0x3 -#define MCPWM_GEN1_B_DT0_S 20 -/* MCPWM_GEN1_B_DTEB : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: Action on PWM1B triggered by event TEB when timer decreasing*/ -#define MCPWM_GEN1_B_DTEB 0x00000003 -#define MCPWM_GEN1_B_DTEB_M ((MCPWM_GEN1_B_DTEB_V)<<(MCPWM_GEN1_B_DTEB_S)) -#define MCPWM_GEN1_B_DTEB_V 0x3 -#define MCPWM_GEN1_B_DTEB_S 18 -/* MCPWM_GEN1_B_DTEA : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: Action on PWM1B triggered by event TEA when timer decreasing*/ -#define MCPWM_GEN1_B_DTEA 0x00000003 -#define MCPWM_GEN1_B_DTEA_M ((MCPWM_GEN1_B_DTEA_V)<<(MCPWM_GEN1_B_DTEA_S)) -#define MCPWM_GEN1_B_DTEA_V 0x3 -#define MCPWM_GEN1_B_DTEA_S 16 -/* MCPWM_GEN1_B_DTEP : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: Action on PWM1B triggered by event TEP when timer decreasing*/ -#define MCPWM_GEN1_B_DTEP 0x00000003 -#define MCPWM_GEN1_B_DTEP_M ((MCPWM_GEN1_B_DTEP_V)<<(MCPWM_GEN1_B_DTEP_S)) -#define MCPWM_GEN1_B_DTEP_V 0x3 -#define MCPWM_GEN1_B_DTEP_S 14 -/* MCPWM_GEN1_B_DTEZ : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: Action on PWM1B triggered by event TEZ when timer decreasing*/ -#define MCPWM_GEN1_B_DTEZ 0x00000003 -#define MCPWM_GEN1_B_DTEZ_M ((MCPWM_GEN1_B_DTEZ_V)<<(MCPWM_GEN1_B_DTEZ_S)) -#define MCPWM_GEN1_B_DTEZ_V 0x3 -#define MCPWM_GEN1_B_DTEZ_S 12 -/* MCPWM_GEN1_B_UT1 : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: Action on PWM1B triggered by event_t1 when timer increasing*/ -#define MCPWM_GEN1_B_UT1 0x00000003 -#define MCPWM_GEN1_B_UT1_M ((MCPWM_GEN1_B_UT1_V)<<(MCPWM_GEN1_B_UT1_S)) -#define MCPWM_GEN1_B_UT1_V 0x3 -#define MCPWM_GEN1_B_UT1_S 10 -/* MCPWM_GEN1_B_UT0 : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: Action on PWM1B triggered by event_t0 when timer increasing*/ -#define MCPWM_GEN1_B_UT0 0x00000003 -#define MCPWM_GEN1_B_UT0_M ((MCPWM_GEN1_B_UT0_V)<<(MCPWM_GEN1_B_UT0_S)) -#define MCPWM_GEN1_B_UT0_V 0x3 -#define MCPWM_GEN1_B_UT0_S 8 -/* MCPWM_GEN1_B_UTEB : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: Action on PWM1B triggered by event TEB when timer increasing*/ -#define MCPWM_GEN1_B_UTEB 0x00000003 -#define MCPWM_GEN1_B_UTEB_M ((MCPWM_GEN1_B_UTEB_V)<<(MCPWM_GEN1_B_UTEB_S)) -#define MCPWM_GEN1_B_UTEB_V 0x3 -#define MCPWM_GEN1_B_UTEB_S 6 -/* MCPWM_GEN1_B_UTEA : R/W ;bitpos:[5:4] ;default: 2'd0 ; */ -/*description: Action on PWM1B triggered by event TEA when timer increasing*/ -#define MCPWM_GEN1_B_UTEA 0x00000003 -#define MCPWM_GEN1_B_UTEA_M ((MCPWM_GEN1_B_UTEA_V)<<(MCPWM_GEN1_B_UTEA_S)) -#define MCPWM_GEN1_B_UTEA_V 0x3 -#define MCPWM_GEN1_B_UTEA_S 4 -/* MCPWM_GEN1_B_UTEP : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: Action on PWM1B triggered by event TEP when timer increasing*/ -#define MCPWM_GEN1_B_UTEP 0x00000003 -#define MCPWM_GEN1_B_UTEP_M ((MCPWM_GEN1_B_UTEP_V)<<(MCPWM_GEN1_B_UTEP_S)) -#define MCPWM_GEN1_B_UTEP_V 0x3 -#define MCPWM_GEN1_B_UTEP_S 2 -/* MCPWM_GEN1_B_UTEZ : R/W ;bitpos:[1:0] ;default: 2'd0 ; */ -/*description: Action on PWM1B triggered by event TEZ when timer increasing*/ -#define MCPWM_GEN1_B_UTEZ 0x00000003 -#define MCPWM_GEN1_B_UTEZ_M ((MCPWM_GEN1_B_UTEZ_V)<<(MCPWM_GEN1_B_UTEZ_S)) -#define MCPWM_GEN1_B_UTEZ_V 0x3 +/** MCPWM_GEN1_B_REG register + * Actions triggered by events on PWM1B + */ +#define MCPWM_GEN1_B_REG(i) (DR_REG_MCPWM_BASE(i) + 0x8c) +/** MCPWM_GEN1_B_UTEZ : R/W; bitpos: [1:0]; default: 0; + * Action on PWM1B triggered by event TEZ when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_UTEZ 0x00000003U +#define MCPWM_GEN1_B_UTEZ_M (MCPWM_GEN1_B_UTEZ_V << MCPWM_GEN1_B_UTEZ_S) +#define MCPWM_GEN1_B_UTEZ_V 0x00000003U #define MCPWM_GEN1_B_UTEZ_S 0 +/** MCPWM_GEN1_B_UTEP : R/W; bitpos: [3:2]; default: 0; + * Action on PWM1B triggered by event TEP when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_UTEP 0x00000003U +#define MCPWM_GEN1_B_UTEP_M (MCPWM_GEN1_B_UTEP_V << MCPWM_GEN1_B_UTEP_S) +#define MCPWM_GEN1_B_UTEP_V 0x00000003U +#define MCPWM_GEN1_B_UTEP_S 2 +/** MCPWM_GEN1_B_UTEA : R/W; bitpos: [5:4]; default: 0; + * Action on PWM1B triggered by event TEA when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_UTEA 0x00000003U +#define MCPWM_GEN1_B_UTEA_M (MCPWM_GEN1_B_UTEA_V << MCPWM_GEN1_B_UTEA_S) +#define MCPWM_GEN1_B_UTEA_V 0x00000003U +#define MCPWM_GEN1_B_UTEA_S 4 +/** MCPWM_GEN1_B_UTEB : R/W; bitpos: [7:6]; default: 0; + * Action on PWM1B triggered by event TEB when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_UTEB 0x00000003U +#define MCPWM_GEN1_B_UTEB_M (MCPWM_GEN1_B_UTEB_V << MCPWM_GEN1_B_UTEB_S) +#define MCPWM_GEN1_B_UTEB_V 0x00000003U +#define MCPWM_GEN1_B_UTEB_S 6 +/** MCPWM_GEN1_B_UT0 : R/W; bitpos: [9:8]; default: 0; + * Action on PWM1B triggered by event_t0 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_UT0 0x00000003U +#define MCPWM_GEN1_B_UT0_M (MCPWM_GEN1_B_UT0_V << MCPWM_GEN1_B_UT0_S) +#define MCPWM_GEN1_B_UT0_V 0x00000003U +#define MCPWM_GEN1_B_UT0_S 8 +/** MCPWM_GEN1_B_UT1 : R/W; bitpos: [11:10]; default: 0; + * Action on PWM1B triggered by event_t1 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_UT1 0x00000003U +#define MCPWM_GEN1_B_UT1_M (MCPWM_GEN1_B_UT1_V << MCPWM_GEN1_B_UT1_S) +#define MCPWM_GEN1_B_UT1_V 0x00000003U +#define MCPWM_GEN1_B_UT1_S 10 +/** MCPWM_GEN1_B_DTEZ : R/W; bitpos: [13:12]; default: 0; + * Action on PWM1B triggered by event TEZ when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_DTEZ 0x00000003U +#define MCPWM_GEN1_B_DTEZ_M (MCPWM_GEN1_B_DTEZ_V << MCPWM_GEN1_B_DTEZ_S) +#define MCPWM_GEN1_B_DTEZ_V 0x00000003U +#define MCPWM_GEN1_B_DTEZ_S 12 +/** MCPWM_GEN1_B_DTEP : R/W; bitpos: [15:14]; default: 0; + * Action on PWM1B triggered by event TEP when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_DTEP 0x00000003U +#define MCPWM_GEN1_B_DTEP_M (MCPWM_GEN1_B_DTEP_V << MCPWM_GEN1_B_DTEP_S) +#define MCPWM_GEN1_B_DTEP_V 0x00000003U +#define MCPWM_GEN1_B_DTEP_S 14 +/** MCPWM_GEN1_B_DTEA : R/W; bitpos: [17:16]; default: 0; + * Action on PWM1B triggered by event TEA when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_DTEA 0x00000003U +#define MCPWM_GEN1_B_DTEA_M (MCPWM_GEN1_B_DTEA_V << MCPWM_GEN1_B_DTEA_S) +#define MCPWM_GEN1_B_DTEA_V 0x00000003U +#define MCPWM_GEN1_B_DTEA_S 16 +/** MCPWM_GEN1_B_DTEB : R/W; bitpos: [19:18]; default: 0; + * Action on PWM1B triggered by event TEB when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_DTEB 0x00000003U +#define MCPWM_GEN1_B_DTEB_M (MCPWM_GEN1_B_DTEB_V << MCPWM_GEN1_B_DTEB_S) +#define MCPWM_GEN1_B_DTEB_V 0x00000003U +#define MCPWM_GEN1_B_DTEB_S 18 +/** MCPWM_GEN1_B_DT0 : R/W; bitpos: [21:20]; default: 0; + * Action on PWM1B triggered by event_t0 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_DT0 0x00000003U +#define MCPWM_GEN1_B_DT0_M (MCPWM_GEN1_B_DT0_V << MCPWM_GEN1_B_DT0_S) +#define MCPWM_GEN1_B_DT0_V 0x00000003U +#define MCPWM_GEN1_B_DT0_S 20 +/** MCPWM_GEN1_B_DT1 : R/W; bitpos: [23:22]; default: 0; + * Action on PWM1B triggered by event_t1 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_DT1 0x00000003U +#define MCPWM_GEN1_B_DT1_M (MCPWM_GEN1_B_DT1_V << MCPWM_GEN1_B_DT1_S) +#define MCPWM_GEN1_B_DT1_V 0x00000003U +#define MCPWM_GEN1_B_DT1_S 22 -#define MCPWM_DT1_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x0090) -/* MCPWM_DT1_CLK_SEL : R/W ;bitpos:[17] ;default: 1'd0 ; */ -/*description: Dead time generator 1 clock selection. 0: PWM_clk 1: PT_clk*/ -#define MCPWM_DT1_CLK_SEL (BIT(17)) -#define MCPWM_DT1_CLK_SEL_M (BIT(17)) -#define MCPWM_DT1_CLK_SEL_V 0x1 -#define MCPWM_DT1_CLK_SEL_S 17 -/* MCPWM_DT1_B_OUTBYPASS : R/W ;bitpos:[16] ;default: 1'd1 ; */ -/*description: S0 in documentation*/ -#define MCPWM_DT1_B_OUTBYPASS (BIT(16)) -#define MCPWM_DT1_B_OUTBYPASS_M (BIT(16)) -#define MCPWM_DT1_B_OUTBYPASS_V 0x1 -#define MCPWM_DT1_B_OUTBYPASS_S 16 -/* MCPWM_DT1_A_OUTBYPASS : R/W ;bitpos:[15] ;default: 1'd1 ; */ -/*description: S1 in documentation*/ -#define MCPWM_DT1_A_OUTBYPASS (BIT(15)) -#define MCPWM_DT1_A_OUTBYPASS_M (BIT(15)) -#define MCPWM_DT1_A_OUTBYPASS_V 0x1 -#define MCPWM_DT1_A_OUTBYPASS_S 15 -/* MCPWM_DT1_FED_OUTINVERT : R/W ;bitpos:[14] ;default: 1'd0 ; */ -/*description: S3 in documentation*/ -#define MCPWM_DT1_FED_OUTINVERT (BIT(14)) -#define MCPWM_DT1_FED_OUTINVERT_M (BIT(14)) -#define MCPWM_DT1_FED_OUTINVERT_V 0x1 -#define MCPWM_DT1_FED_OUTINVERT_S 14 -/* MCPWM_DT1_RED_OUTINVERT : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: S2 in documentation*/ -#define MCPWM_DT1_RED_OUTINVERT (BIT(13)) -#define MCPWM_DT1_RED_OUTINVERT_M (BIT(13)) -#define MCPWM_DT1_RED_OUTINVERT_V 0x1 -#define MCPWM_DT1_RED_OUTINVERT_S 13 -/* MCPWM_DT1_FED_INSEL : R/W ;bitpos:[12] ;default: 1'd0 ; */ -/*description: S5 in documentation*/ -#define MCPWM_DT1_FED_INSEL (BIT(12)) -#define MCPWM_DT1_FED_INSEL_M (BIT(12)) -#define MCPWM_DT1_FED_INSEL_V 0x1 -#define MCPWM_DT1_FED_INSEL_S 12 -/* MCPWM_DT1_RED_INSEL : R/W ;bitpos:[11] ;default: 1'd0 ; */ -/*description: S4 in documentation*/ -#define MCPWM_DT1_RED_INSEL (BIT(11)) -#define MCPWM_DT1_RED_INSEL_M (BIT(11)) -#define MCPWM_DT1_RED_INSEL_V 0x1 -#define MCPWM_DT1_RED_INSEL_S 11 -/* MCPWM_DT1_B_OUTSWAP : R/W ;bitpos:[10] ;default: 1'd0 ; */ -/*description: S7 in documentation*/ -#define MCPWM_DT1_B_OUTSWAP (BIT(10)) -#define MCPWM_DT1_B_OUTSWAP_M (BIT(10)) -#define MCPWM_DT1_B_OUTSWAP_V 0x1 -#define MCPWM_DT1_B_OUTSWAP_S 10 -/* MCPWM_DT1_A_OUTSWAP : R/W ;bitpos:[9] ;default: 1'd0 ; */ -/*description: S6 in documentation*/ -#define MCPWM_DT1_A_OUTSWAP (BIT(9)) -#define MCPWM_DT1_A_OUTSWAP_M (BIT(9)) -#define MCPWM_DT1_A_OUTSWAP_V 0x1 -#define MCPWM_DT1_A_OUTSWAP_S 9 -/* MCPWM_DT1_DEB_MODE : R/W ;bitpos:[8] ;default: 1'd0 ; */ -/*description: S8 in documentation dual-edge B mode 0: FED/RED take effect - on different path separately 1: FED/RED take effect on B path A out is in bypass or normal operation mode*/ -#define MCPWM_DT1_DEB_MODE (BIT(8)) -#define MCPWM_DT1_DEB_MODE_M (BIT(8)) -#define MCPWM_DT1_DEB_MODE_V 0x1 -#define MCPWM_DT1_DEB_MODE_S 8 -/* MCPWM_DT1_RED_UPMETHOD : R/W ;bitpos:[7:4] ;default: 4'd0 ; */ -/*description: Update method for RED (rising edge delay) active reg. 0: immediate - bit0: TEZ bit1: TEP bit2: sync bit3: disable update*/ -#define MCPWM_DT1_RED_UPMETHOD 0x0000000F -#define MCPWM_DT1_RED_UPMETHOD_M ((MCPWM_DT1_RED_UPMETHOD_V)<<(MCPWM_DT1_RED_UPMETHOD_S)) -#define MCPWM_DT1_RED_UPMETHOD_V 0xF -#define MCPWM_DT1_RED_UPMETHOD_S 4 -/* MCPWM_DT1_FED_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: Update method for FED (falling edge delay) active reg. 0: immediate - bit0: TEZ bit1: TEP bit2: sync bit3: disable update*/ -#define MCPWM_DT1_FED_UPMETHOD 0x0000000F -#define MCPWM_DT1_FED_UPMETHOD_M ((MCPWM_DT1_FED_UPMETHOD_V)<<(MCPWM_DT1_FED_UPMETHOD_S)) -#define MCPWM_DT1_FED_UPMETHOD_V 0xF +/** MCPWM_DT1_CFG_REG register + * PWM generator 1 dead time type selection and configuration + */ +#define MCPWM_DT1_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x90) +/** MCPWM_DT1_FED_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for FED (falling edge delay) active register. 0: immediate, when bit0 + * is set to 1: tez, when bit1 is set to 1:tep, when bit2 is set to 1: sync, when + * bit3 is set to 1: disable the update + */ +#define MCPWM_DT1_FED_UPMETHOD 0x0000000FU +#define MCPWM_DT1_FED_UPMETHOD_M (MCPWM_DT1_FED_UPMETHOD_V << MCPWM_DT1_FED_UPMETHOD_S) +#define MCPWM_DT1_FED_UPMETHOD_V 0x0000000FU #define MCPWM_DT1_FED_UPMETHOD_S 0 +/** MCPWM_DT1_RED_UPMETHOD : R/W; bitpos: [7:4]; default: 0; + * Update method for RED (rising edge delay) active register. 0: immediate,when bit0 + * is set to 1: tez, when bit1 is set to 1:tep, when bit2 is set to 1: sync, when + * bit3 is set to 1: disable the update + */ +#define MCPWM_DT1_RED_UPMETHOD 0x0000000FU +#define MCPWM_DT1_RED_UPMETHOD_M (MCPWM_DT1_RED_UPMETHOD_V << MCPWM_DT1_RED_UPMETHOD_S) +#define MCPWM_DT1_RED_UPMETHOD_V 0x0000000FU +#define MCPWM_DT1_RED_UPMETHOD_S 4 +/** MCPWM_DT1_DEB_MODE : R/W; bitpos: [8]; default: 0; + * S8 in table, dual-edge B mode, 0: fed/red take effect on different path separately, + * 1: fed/red take effect on B path, A out is in bypass or dulpB mode + */ +#define MCPWM_DT1_DEB_MODE (BIT(8)) +#define MCPWM_DT1_DEB_MODE_M (MCPWM_DT1_DEB_MODE_V << MCPWM_DT1_DEB_MODE_S) +#define MCPWM_DT1_DEB_MODE_V 0x00000001U +#define MCPWM_DT1_DEB_MODE_S 8 +/** MCPWM_DT1_A_OUTSWAP : R/W; bitpos: [9]; default: 0; + * S6 in table + */ +#define MCPWM_DT1_A_OUTSWAP (BIT(9)) +#define MCPWM_DT1_A_OUTSWAP_M (MCPWM_DT1_A_OUTSWAP_V << MCPWM_DT1_A_OUTSWAP_S) +#define MCPWM_DT1_A_OUTSWAP_V 0x00000001U +#define MCPWM_DT1_A_OUTSWAP_S 9 +/** MCPWM_DT1_B_OUTSWAP : R/W; bitpos: [10]; default: 0; + * S7 in table + */ +#define MCPWM_DT1_B_OUTSWAP (BIT(10)) +#define MCPWM_DT1_B_OUTSWAP_M (MCPWM_DT1_B_OUTSWAP_V << MCPWM_DT1_B_OUTSWAP_S) +#define MCPWM_DT1_B_OUTSWAP_V 0x00000001U +#define MCPWM_DT1_B_OUTSWAP_S 10 +/** MCPWM_DT1_RED_INSEL : R/W; bitpos: [11]; default: 0; + * S4 in table + */ +#define MCPWM_DT1_RED_INSEL (BIT(11)) +#define MCPWM_DT1_RED_INSEL_M (MCPWM_DT1_RED_INSEL_V << MCPWM_DT1_RED_INSEL_S) +#define MCPWM_DT1_RED_INSEL_V 0x00000001U +#define MCPWM_DT1_RED_INSEL_S 11 +/** MCPWM_DT1_FED_INSEL : R/W; bitpos: [12]; default: 0; + * S5 in table + */ +#define MCPWM_DT1_FED_INSEL (BIT(12)) +#define MCPWM_DT1_FED_INSEL_M (MCPWM_DT1_FED_INSEL_V << MCPWM_DT1_FED_INSEL_S) +#define MCPWM_DT1_FED_INSEL_V 0x00000001U +#define MCPWM_DT1_FED_INSEL_S 12 +/** MCPWM_DT1_RED_OUTINVERT : R/W; bitpos: [13]; default: 0; + * S2 in table + */ +#define MCPWM_DT1_RED_OUTINVERT (BIT(13)) +#define MCPWM_DT1_RED_OUTINVERT_M (MCPWM_DT1_RED_OUTINVERT_V << MCPWM_DT1_RED_OUTINVERT_S) +#define MCPWM_DT1_RED_OUTINVERT_V 0x00000001U +#define MCPWM_DT1_RED_OUTINVERT_S 13 +/** MCPWM_DT1_FED_OUTINVERT : R/W; bitpos: [14]; default: 0; + * S3 in table + */ +#define MCPWM_DT1_FED_OUTINVERT (BIT(14)) +#define MCPWM_DT1_FED_OUTINVERT_M (MCPWM_DT1_FED_OUTINVERT_V << MCPWM_DT1_FED_OUTINVERT_S) +#define MCPWM_DT1_FED_OUTINVERT_V 0x00000001U +#define MCPWM_DT1_FED_OUTINVERT_S 14 +/** MCPWM_DT1_A_OUTBYPASS : R/W; bitpos: [15]; default: 1; + * S1 in table + */ +#define MCPWM_DT1_A_OUTBYPASS (BIT(15)) +#define MCPWM_DT1_A_OUTBYPASS_M (MCPWM_DT1_A_OUTBYPASS_V << MCPWM_DT1_A_OUTBYPASS_S) +#define MCPWM_DT1_A_OUTBYPASS_V 0x00000001U +#define MCPWM_DT1_A_OUTBYPASS_S 15 +/** MCPWM_DT1_B_OUTBYPASS : R/W; bitpos: [16]; default: 1; + * S0 in table + */ +#define MCPWM_DT1_B_OUTBYPASS (BIT(16)) +#define MCPWM_DT1_B_OUTBYPASS_M (MCPWM_DT1_B_OUTBYPASS_V << MCPWM_DT1_B_OUTBYPASS_S) +#define MCPWM_DT1_B_OUTBYPASS_V 0x00000001U +#define MCPWM_DT1_B_OUTBYPASS_S 16 +/** MCPWM_DT1_CLK_SEL : R/W; bitpos: [17]; default: 0; + * Dead time clock selection. 0: PWM_clk, 1: PT_clk + */ +#define MCPWM_DT1_CLK_SEL (BIT(17)) +#define MCPWM_DT1_CLK_SEL_M (MCPWM_DT1_CLK_SEL_V << MCPWM_DT1_CLK_SEL_S) +#define MCPWM_DT1_CLK_SEL_V 0x00000001U +#define MCPWM_DT1_CLK_SEL_S 17 -#define MCPWM_DT1_FED_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x0094) -/* MCPWM_DT1_FED : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: Shadow reg for FED*/ -#define MCPWM_DT1_FED 0x0000FFFF -#define MCPWM_DT1_FED_M ((MCPWM_DT1_FED_V)<<(MCPWM_DT1_FED_S)) -#define MCPWM_DT1_FED_V 0xFFFF +/** MCPWM_DT1_FED_CFG_REG register + * PWM generator 1 shadow register for falling edge delay (FED). + */ +#define MCPWM_DT1_FED_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x94) +/** MCPWM_DT1_FED : R/W; bitpos: [15:0]; default: 0; + * Shadow register for FED + */ +#define MCPWM_DT1_FED 0x0000FFFFU +#define MCPWM_DT1_FED_M (MCPWM_DT1_FED_V << MCPWM_DT1_FED_S) +#define MCPWM_DT1_FED_V 0x0000FFFFU #define MCPWM_DT1_FED_S 0 -#define MCPWM_DT1_RED_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x0098) -/* MCPWM_DT1_RED : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: Shadow reg for RED*/ -#define MCPWM_DT1_RED 0x0000FFFF -#define MCPWM_DT1_RED_M ((MCPWM_DT1_RED_V)<<(MCPWM_DT1_RED_S)) -#define MCPWM_DT1_RED_V 0xFFFF +/** MCPWM_DT1_RED_CFG_REG register + * PWM generator 1 shadow register for rising edge delay (RED). + */ +#define MCPWM_DT1_RED_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x98) +/** MCPWM_DT1_RED : R/W; bitpos: [15:0]; default: 0; + * Shadow register for RED + */ +#define MCPWM_DT1_RED 0x0000FFFFU +#define MCPWM_DT1_RED_M (MCPWM_DT1_RED_V << MCPWM_DT1_RED_S) +#define MCPWM_DT1_RED_V 0x0000FFFFU #define MCPWM_DT1_RED_S 0 -#define MCPWM_CARRIER1_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x009c) -/* MCPWM_CARRIER1_IN_INVERT : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: When set invert the input of PWM1A and PWM1B for this submodule*/ -#define MCPWM_CARRIER1_IN_INVERT (BIT(13)) -#define MCPWM_CARRIER1_IN_INVERT_M (BIT(13)) -#define MCPWM_CARRIER1_IN_INVERT_V 0x1 -#define MCPWM_CARRIER1_IN_INVERT_S 13 -/* MCPWM_CARRIER1_OUT_INVERT : R/W ;bitpos:[12] ;default: 1'd0 ; */ -/*description: When set invert the output of PWM1A and PWM1B for this submodule*/ -#define MCPWM_CARRIER1_OUT_INVERT (BIT(12)) -#define MCPWM_CARRIER1_OUT_INVERT_M (BIT(12)) -#define MCPWM_CARRIER1_OUT_INVERT_V 0x1 -#define MCPWM_CARRIER1_OUT_INVERT_S 12 -/* MCPWM_CARRIER1_OSHWTH : R/W ;bitpos:[11:8] ;default: 4'd0 ; */ -/*description: Width of the fist pulse in number of periods of the carrier*/ -#define MCPWM_CARRIER1_OSHWTH 0x0000000F -#define MCPWM_CARRIER1_OSHWTH_M ((MCPWM_CARRIER1_OSHWTH_V)<<(MCPWM_CARRIER1_OSHWTH_S)) -#define MCPWM_CARRIER1_OSHWTH_V 0xF -#define MCPWM_CARRIER1_OSHWTH_S 8 -/* MCPWM_CARRIER1_DUTY : R/W ;bitpos:[7:5] ;default: 3'd0 ; */ -/*description: Carrier duty selection. Duty = PWM_CARRIER1_DUTY / 8*/ -#define MCPWM_CARRIER1_DUTY 0x00000007 -#define MCPWM_CARRIER1_DUTY_M ((MCPWM_CARRIER1_DUTY_V)<<(MCPWM_CARRIER1_DUTY_S)) -#define MCPWM_CARRIER1_DUTY_V 0x7 -#define MCPWM_CARRIER1_DUTY_S 5 -/* MCPWM_CARRIER1_PRESCALE : R/W ;bitpos:[4:1] ;default: 4'd0 ; */ -/*description: PWM carrier1 clock (PC_clk) prescale value. Period of PC_clk - = period of PWM_clk * (PWM_CARRIER1_PRESCALE + 1)*/ -#define MCPWM_CARRIER1_PRESCALE 0x0000000F -#define MCPWM_CARRIER1_PRESCALE_M ((MCPWM_CARRIER1_PRESCALE_V)<<(MCPWM_CARRIER1_PRESCALE_S)) -#define MCPWM_CARRIER1_PRESCALE_V 0xF -#define MCPWM_CARRIER1_PRESCALE_S 1 -/* MCPWM_CARRIER1_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: When set carrier1 function is enabled. When cleared carrier1 is bypassed*/ -#define MCPWM_CARRIER1_EN (BIT(0)) -#define MCPWM_CARRIER1_EN_M (BIT(0)) -#define MCPWM_CARRIER1_EN_V 0x1 +/** MCPWM_CARRIER1_CFG_REG register + * PWM generator 1 carrier enable and configuratoin + */ +#define MCPWM_CARRIER1_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x9c) +/** MCPWM_CARRIER1_EN : R/W; bitpos: [0]; default: 0; + * When set, carrier1 function is enabled. When cleared, carrier1 is bypassed + */ +#define MCPWM_CARRIER1_EN (BIT(0)) +#define MCPWM_CARRIER1_EN_M (MCPWM_CARRIER1_EN_V << MCPWM_CARRIER1_EN_S) +#define MCPWM_CARRIER1_EN_V 0x00000001U #define MCPWM_CARRIER1_EN_S 0 +/** MCPWM_CARRIER1_PRESCALE : R/W; bitpos: [4:1]; default: 0; + * PWM carrier1 clock (PC_clk) prescale value. Period of PC_clk = period of PWM_clk * + * (PWM_CARRIER0_PRESCALE + 1) + */ +#define MCPWM_CARRIER1_PRESCALE 0x0000000FU +#define MCPWM_CARRIER1_PRESCALE_M (MCPWM_CARRIER1_PRESCALE_V << MCPWM_CARRIER1_PRESCALE_S) +#define MCPWM_CARRIER1_PRESCALE_V 0x0000000FU +#define MCPWM_CARRIER1_PRESCALE_S 1 +/** MCPWM_CARRIER1_DUTY : R/W; bitpos: [7:5]; default: 0; + * carrier duty selection. Duty = PWM_CARRIER0_DUTY / 8 + */ +#define MCPWM_CARRIER1_DUTY 0x00000007U +#define MCPWM_CARRIER1_DUTY_M (MCPWM_CARRIER1_DUTY_V << MCPWM_CARRIER1_DUTY_S) +#define MCPWM_CARRIER1_DUTY_V 0x00000007U +#define MCPWM_CARRIER1_DUTY_S 5 +/** MCPWM_CARRIER1_OSHTWTH : R/W; bitpos: [11:8]; default: 0; + * width of the first pulse in number of periods of the carrier + */ +#define MCPWM_CARRIER1_OSHTWTH 0x0000000FU +#define MCPWM_CARRIER1_OSHTWTH_M (MCPWM_CARRIER1_OSHTWTH_V << MCPWM_CARRIER1_OSHTWTH_S) +#define MCPWM_CARRIER1_OSHTWTH_V 0x0000000FU +#define MCPWM_CARRIER1_OSHTWTH_S 8 +/** MCPWM_CARRIER1_OUT_INVERT : R/W; bitpos: [12]; default: 0; + * when set, invert the output of PWM1A and PWM1B for this submodule + */ +#define MCPWM_CARRIER1_OUT_INVERT (BIT(12)) +#define MCPWM_CARRIER1_OUT_INVERT_M (MCPWM_CARRIER1_OUT_INVERT_V << MCPWM_CARRIER1_OUT_INVERT_S) +#define MCPWM_CARRIER1_OUT_INVERT_V 0x00000001U +#define MCPWM_CARRIER1_OUT_INVERT_S 12 +/** MCPWM_CARRIER1_IN_INVERT : R/W; bitpos: [13]; default: 0; + * when set, invert the input of PWM1A and PWM1B for this submodule + */ +#define MCPWM_CARRIER1_IN_INVERT (BIT(13)) +#define MCPWM_CARRIER1_IN_INVERT_M (MCPWM_CARRIER1_IN_INVERT_V << MCPWM_CARRIER1_IN_INVERT_S) +#define MCPWM_CARRIER1_IN_INVERT_V 0x00000001U +#define MCPWM_CARRIER1_IN_INVERT_S 13 -#define MCPWM_FH1_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0x00a0) -/* MCPWM_FH1_B_OST_U : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: One-shot mode action on PWM1B when fault event occurs and timer - is increasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH1_B_OST_U 0x00000003 -#define MCPWM_FH1_B_OST_U_M ((MCPWM_FH1_B_OST_U_V)<<(MCPWM_FH1_B_OST_U_S)) -#define MCPWM_FH1_B_OST_U_V 0x3 -#define MCPWM_FH1_B_OST_U_S 22 -/* MCPWM_FH1_B_OST_D : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: One-shot mode action on PWM1B when fault event occurs and timer - is decreasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH1_B_OST_D 0x00000003 -#define MCPWM_FH1_B_OST_D_M ((MCPWM_FH1_B_OST_D_V)<<(MCPWM_FH1_B_OST_D_S)) -#define MCPWM_FH1_B_OST_D_V 0x3 -#define MCPWM_FH1_B_OST_D_S 20 -/* MCPWM_FH1_B_CBC_U : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: Cycle-by-cycle mode action on PWM1B when fault event occurs and - timer is increasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH1_B_CBC_U 0x00000003 -#define MCPWM_FH1_B_CBC_U_M ((MCPWM_FH1_B_CBC_U_V)<<(MCPWM_FH1_B_CBC_U_S)) -#define MCPWM_FH1_B_CBC_U_V 0x3 -#define MCPWM_FH1_B_CBC_U_S 18 -/* MCPWM_FH1_B_CBC_D : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: Cycle-by-cycle mode action on PWM1B when fault event occurs and - timer is decreasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH1_B_CBC_D 0x00000003 -#define MCPWM_FH1_B_CBC_D_M ((MCPWM_FH1_B_CBC_D_V)<<(MCPWM_FH1_B_CBC_D_S)) -#define MCPWM_FH1_B_CBC_D_V 0x3 -#define MCPWM_FH1_B_CBC_D_S 16 -/* MCPWM_FH1_A_OST_U : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: One-shot mode action on PWM1A when fault event occurs and timer - is increasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH1_A_OST_U 0x00000003 -#define MCPWM_FH1_A_OST_U_M ((MCPWM_FH1_A_OST_U_V)<<(MCPWM_FH1_A_OST_U_S)) -#define MCPWM_FH1_A_OST_U_V 0x3 -#define MCPWM_FH1_A_OST_U_S 14 -/* MCPWM_FH1_A_OST_D : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: One-shot mode action on PWM1A when fault event occurs and timer - is decreasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH1_A_OST_D 0x00000003 -#define MCPWM_FH1_A_OST_D_M ((MCPWM_FH1_A_OST_D_V)<<(MCPWM_FH1_A_OST_D_S)) -#define MCPWM_FH1_A_OST_D_V 0x3 -#define MCPWM_FH1_A_OST_D_S 12 -/* MCPWM_FH1_A_CBC_U : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: Cycle-by-cycle mode action on PWM1A when fault event occurs and - timer is increasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH1_A_CBC_U 0x00000003 -#define MCPWM_FH1_A_CBC_U_M ((MCPWM_FH1_A_CBC_U_V)<<(MCPWM_FH1_A_CBC_U_S)) -#define MCPWM_FH1_A_CBC_U_V 0x3 -#define MCPWM_FH1_A_CBC_U_S 10 -/* MCPWM_FH1_A_CBC_D : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: Cycle-by-cycle mode action on PWM1A when fault event occurs and - timer is decreasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH1_A_CBC_D 0x00000003 -#define MCPWM_FH1_A_CBC_D_M ((MCPWM_FH1_A_CBC_D_V)<<(MCPWM_FH1_A_CBC_D_S)) -#define MCPWM_FH1_A_CBC_D_V 0x3 -#define MCPWM_FH1_A_CBC_D_S 8 -/* MCPWM_FH1_F0_OST : R/W ;bitpos:[7] ;default: 1'd0 ; */ -/*description: event_f0 will trigger one-shot mode action. 0: disable 1: enable*/ -#define MCPWM_FH1_F0_OST (BIT(7)) -#define MCPWM_FH1_F0_OST_M (BIT(7)) -#define MCPWM_FH1_F0_OST_V 0x1 -#define MCPWM_FH1_F0_OST_S 7 -/* MCPWM_FH1_F1_OST : R/W ;bitpos:[6] ;default: 1'd0 ; */ -/*description: event_f1 will trigger one-shot mode action. 0: disable 1: enable*/ -#define MCPWM_FH1_F1_OST (BIT(6)) -#define MCPWM_FH1_F1_OST_M (BIT(6)) -#define MCPWM_FH1_F1_OST_V 0x1 -#define MCPWM_FH1_F1_OST_S 6 -/* MCPWM_FH1_F2_OST : R/W ;bitpos:[5] ;default: 1'd0 ; */ -/*description: event_f2 will trigger one-shot mode action. 0: disable 1: enable*/ -#define MCPWM_FH1_F2_OST (BIT(5)) -#define MCPWM_FH1_F2_OST_M (BIT(5)) -#define MCPWM_FH1_F2_OST_V 0x1 -#define MCPWM_FH1_F2_OST_S 5 -/* MCPWM_FH1_SW_OST : R/W ;bitpos:[4] ;default: 1'd0 ; */ -/*description: Enable register for software force one-shot mode action. 0: disable 1: enable*/ -#define MCPWM_FH1_SW_OST (BIT(4)) -#define MCPWM_FH1_SW_OST_M (BIT(4)) -#define MCPWM_FH1_SW_OST_V 0x1 -#define MCPWM_FH1_SW_OST_S 4 -/* MCPWM_FH1_F0_CBC : R/W ;bitpos:[3] ;default: 1'd0 ; */ -/*description: event_f0 will trigger cycle-by-cycle mode action. 0: disable 1: enable*/ -#define MCPWM_FH1_F0_CBC (BIT(3)) -#define MCPWM_FH1_F0_CBC_M (BIT(3)) -#define MCPWM_FH1_F0_CBC_V 0x1 -#define MCPWM_FH1_F0_CBC_S 3 -/* MCPWM_FH1_F1_CBC : R/W ;bitpos:[2] ;default: 1'd0 ; */ -/*description: event_f1 will trigger cycle-by-cycle mode action. 0: disable 1: enable*/ -#define MCPWM_FH1_F1_CBC (BIT(2)) -#define MCPWM_FH1_F1_CBC_M (BIT(2)) -#define MCPWM_FH1_F1_CBC_V 0x1 -#define MCPWM_FH1_F1_CBC_S 2 -/* MCPWM_FH1_F2_CBC : R/W ;bitpos:[1] ;default: 1'd0 ; */ -/*description: event_f2 will trigger cycle-by-cycle mode action. 0: disable 1: enable*/ -#define MCPWM_FH1_F2_CBC (BIT(1)) -#define MCPWM_FH1_F2_CBC_M (BIT(1)) -#define MCPWM_FH1_F2_CBC_V 0x1 -#define MCPWM_FH1_F2_CBC_S 1 -/* MCPWM_FH1_SW_CBC : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: Enable register for software force cycle-by-cycle mode action. - 0: disable 1: enable*/ -#define MCPWM_FH1_SW_CBC (BIT(0)) -#define MCPWM_FH1_SW_CBC_M (BIT(0)) -#define MCPWM_FH1_SW_CBC_V 0x1 +/** MCPWM_FH1_CFG0_REG register + * Actions on PWM1A and PWM1B trip events + */ +#define MCPWM_FH1_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0xa0) +/** MCPWM_FH1_SW_CBC : R/W; bitpos: [0]; default: 0; + * Enable register for software force cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH1_SW_CBC (BIT(0)) +#define MCPWM_FH1_SW_CBC_M (MCPWM_FH1_SW_CBC_V << MCPWM_FH1_SW_CBC_S) +#define MCPWM_FH1_SW_CBC_V 0x00000001U #define MCPWM_FH1_SW_CBC_S 0 +/** MCPWM_FH1_F2_CBC : R/W; bitpos: [1]; default: 0; + * fault_event2 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH1_F2_CBC (BIT(1)) +#define MCPWM_FH1_F2_CBC_M (MCPWM_FH1_F2_CBC_V << MCPWM_FH1_F2_CBC_S) +#define MCPWM_FH1_F2_CBC_V 0x00000001U +#define MCPWM_FH1_F2_CBC_S 1 +/** MCPWM_FH1_F1_CBC : R/W; bitpos: [2]; default: 0; + * fault_event1 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH1_F1_CBC (BIT(2)) +#define MCPWM_FH1_F1_CBC_M (MCPWM_FH1_F1_CBC_V << MCPWM_FH1_F1_CBC_S) +#define MCPWM_FH1_F1_CBC_V 0x00000001U +#define MCPWM_FH1_F1_CBC_S 2 +/** MCPWM_FH1_F0_CBC : R/W; bitpos: [3]; default: 0; + * fault_event0 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH1_F0_CBC (BIT(3)) +#define MCPWM_FH1_F0_CBC_M (MCPWM_FH1_F0_CBC_V << MCPWM_FH1_F0_CBC_S) +#define MCPWM_FH1_F0_CBC_V 0x00000001U +#define MCPWM_FH1_F0_CBC_S 3 +/** MCPWM_FH1_SW_OST : R/W; bitpos: [4]; default: 0; + * Enable register for software force one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH1_SW_OST (BIT(4)) +#define MCPWM_FH1_SW_OST_M (MCPWM_FH1_SW_OST_V << MCPWM_FH1_SW_OST_S) +#define MCPWM_FH1_SW_OST_V 0x00000001U +#define MCPWM_FH1_SW_OST_S 4 +/** MCPWM_FH1_F2_OST : R/W; bitpos: [5]; default: 0; + * fault_event2 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH1_F2_OST (BIT(5)) +#define MCPWM_FH1_F2_OST_M (MCPWM_FH1_F2_OST_V << MCPWM_FH1_F2_OST_S) +#define MCPWM_FH1_F2_OST_V 0x00000001U +#define MCPWM_FH1_F2_OST_S 5 +/** MCPWM_FH1_F1_OST : R/W; bitpos: [6]; default: 0; + * fault_event1 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH1_F1_OST (BIT(6)) +#define MCPWM_FH1_F1_OST_M (MCPWM_FH1_F1_OST_V << MCPWM_FH1_F1_OST_S) +#define MCPWM_FH1_F1_OST_V 0x00000001U +#define MCPWM_FH1_F1_OST_S 6 +/** MCPWM_FH1_F0_OST : R/W; bitpos: [7]; default: 0; + * fault_event0 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH1_F0_OST (BIT(7)) +#define MCPWM_FH1_F0_OST_M (MCPWM_FH1_F0_OST_V << MCPWM_FH1_F0_OST_S) +#define MCPWM_FH1_F0_OST_V 0x00000001U +#define MCPWM_FH1_F0_OST_S 7 +/** MCPWM_FH1_A_CBC_D : R/W; bitpos: [9:8]; default: 0; + * Cycle-by-cycle mode action on PWM1A when fault event occurs and timer is + * decreasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH1_A_CBC_D 0x00000003U +#define MCPWM_FH1_A_CBC_D_M (MCPWM_FH1_A_CBC_D_V << MCPWM_FH1_A_CBC_D_S) +#define MCPWM_FH1_A_CBC_D_V 0x00000003U +#define MCPWM_FH1_A_CBC_D_S 8 +/** MCPWM_FH1_A_CBC_U : R/W; bitpos: [11:10]; default: 0; + * Cycle-by-cycle mode action on PWM1A when fault event occurs and timer is + * increasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH1_A_CBC_U 0x00000003U +#define MCPWM_FH1_A_CBC_U_M (MCPWM_FH1_A_CBC_U_V << MCPWM_FH1_A_CBC_U_S) +#define MCPWM_FH1_A_CBC_U_V 0x00000003U +#define MCPWM_FH1_A_CBC_U_S 10 +/** MCPWM_FH1_A_OST_D : R/W; bitpos: [13:12]; default: 0; + * One-shot mode action on PWM1A when fault event occurs and timer is decreasing. 0: + * do nothing,1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH1_A_OST_D 0x00000003U +#define MCPWM_FH1_A_OST_D_M (MCPWM_FH1_A_OST_D_V << MCPWM_FH1_A_OST_D_S) +#define MCPWM_FH1_A_OST_D_V 0x00000003U +#define MCPWM_FH1_A_OST_D_S 12 +/** MCPWM_FH1_A_OST_U : R/W; bitpos: [15:14]; default: 0; + * One-shot mode action on PWM1A when fault event occurs and timer is increasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH1_A_OST_U 0x00000003U +#define MCPWM_FH1_A_OST_U_M (MCPWM_FH1_A_OST_U_V << MCPWM_FH1_A_OST_U_S) +#define MCPWM_FH1_A_OST_U_V 0x00000003U +#define MCPWM_FH1_A_OST_U_S 14 +/** MCPWM_FH1_B_CBC_D : R/W; bitpos: [17:16]; default: 0; + * Cycle-by-cycle mode action on PWM1B when fault event occurs and timer is + * decreasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH1_B_CBC_D 0x00000003U +#define MCPWM_FH1_B_CBC_D_M (MCPWM_FH1_B_CBC_D_V << MCPWM_FH1_B_CBC_D_S) +#define MCPWM_FH1_B_CBC_D_V 0x00000003U +#define MCPWM_FH1_B_CBC_D_S 16 +/** MCPWM_FH1_B_CBC_U : R/W; bitpos: [19:18]; default: 0; + * Cycle-by-cycle mode action on PWM1B when fault event occurs and timer is + * increasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH1_B_CBC_U 0x00000003U +#define MCPWM_FH1_B_CBC_U_M (MCPWM_FH1_B_CBC_U_V << MCPWM_FH1_B_CBC_U_S) +#define MCPWM_FH1_B_CBC_U_V 0x00000003U +#define MCPWM_FH1_B_CBC_U_S 18 +/** MCPWM_FH1_B_OST_D : R/W; bitpos: [21:20]; default: 0; + * One-shot mode action on PWM1B when fault event occurs and timer is decreasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH1_B_OST_D 0x00000003U +#define MCPWM_FH1_B_OST_D_M (MCPWM_FH1_B_OST_D_V << MCPWM_FH1_B_OST_D_S) +#define MCPWM_FH1_B_OST_D_V 0x00000003U +#define MCPWM_FH1_B_OST_D_S 20 +/** MCPWM_FH1_B_OST_U : R/W; bitpos: [23:22]; default: 0; + * One-shot mode action on PWM1B when fault event occurs and timer is increasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH1_B_OST_U 0x00000003U +#define MCPWM_FH1_B_OST_U_M (MCPWM_FH1_B_OST_U_V << MCPWM_FH1_B_OST_U_S) +#define MCPWM_FH1_B_OST_U_V 0x00000003U +#define MCPWM_FH1_B_OST_U_S 22 -#define MCPWM_FH1_CFG1_REG(i) (REG_MCPWM_BASE(i) + 0x00a4) -/* MCPWM_FH1_FORCE_OST : R/W ;bitpos:[4] ;default: 1'd0 ; */ -/*description: A toggle (software negation of value of this bit) triggers a - one-shot mode action*/ -#define MCPWM_FH1_FORCE_OST (BIT(4)) -#define MCPWM_FH1_FORCE_OST_M (BIT(4)) -#define MCPWM_FH1_FORCE_OST_V 0x1 -#define MCPWM_FH1_FORCE_OST_S 4 -/* MCPWM_FH1_FORCE_CBC : R/W ;bitpos:[3] ;default: 1'd0 ; */ -/*description: A toggle triggers a cycle-by-cycle mode action*/ -#define MCPWM_FH1_FORCE_CBC (BIT(3)) -#define MCPWM_FH1_FORCE_CBC_M (BIT(3)) -#define MCPWM_FH1_FORCE_CBC_V 0x1 -#define MCPWM_FH1_FORCE_CBC_S 3 -/* MCPWM_FH1_CBCPULSE : R/W ;bitpos:[2:1] ;default: 2'd0 ; */ -/*description: The cycle-by-cycle mode action refresh moment selection. Bit0: TEZ bit1:TEP*/ -#define MCPWM_FH1_CBCPULSE 0x00000003 -#define MCPWM_FH1_CBCPULSE_M ((MCPWM_FH1_CBCPULSE_V)<<(MCPWM_FH1_CBCPULSE_S)) -#define MCPWM_FH1_CBCPULSE_V 0x3 -#define MCPWM_FH1_CBCPULSE_S 1 -/* MCPWM_FH1_CLR_OST : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: A toggle will clear on going one-shot mode action*/ -#define MCPWM_FH1_CLR_OST (BIT(0)) -#define MCPWM_FH1_CLR_OST_M (BIT(0)) -#define MCPWM_FH1_CLR_OST_V 0x1 +/** MCPWM_FH1_CFG1_REG register + * Software triggers for fault handler actions + */ +#define MCPWM_FH1_CFG1_REG(i) (DR_REG_MCPWM_BASE(i) + 0xa4) +/** MCPWM_FH1_CLR_OST : R/W; bitpos: [0]; default: 0; + * a rising edge will clear on going one-shot mode action + */ +#define MCPWM_FH1_CLR_OST (BIT(0)) +#define MCPWM_FH1_CLR_OST_M (MCPWM_FH1_CLR_OST_V << MCPWM_FH1_CLR_OST_S) +#define MCPWM_FH1_CLR_OST_V 0x00000001U #define MCPWM_FH1_CLR_OST_S 0 +/** MCPWM_FH1_CBCPULSE : R/W; bitpos: [2:1]; default: 0; + * cycle-by-cycle mode action refresh moment selection. When bit0 is set to 1: TEZ, + * when bit1 is set to 1:TEP + */ +#define MCPWM_FH1_CBCPULSE 0x00000003U +#define MCPWM_FH1_CBCPULSE_M (MCPWM_FH1_CBCPULSE_V << MCPWM_FH1_CBCPULSE_S) +#define MCPWM_FH1_CBCPULSE_V 0x00000003U +#define MCPWM_FH1_CBCPULSE_S 1 +/** MCPWM_FH1_FORCE_CBC : R/W; bitpos: [3]; default: 0; + * a toggle trigger a cycle-by-cycle mode action + */ +#define MCPWM_FH1_FORCE_CBC (BIT(3)) +#define MCPWM_FH1_FORCE_CBC_M (MCPWM_FH1_FORCE_CBC_V << MCPWM_FH1_FORCE_CBC_S) +#define MCPWM_FH1_FORCE_CBC_V 0x00000001U +#define MCPWM_FH1_FORCE_CBC_S 3 +/** MCPWM_FH1_FORCE_OST : R/W; bitpos: [4]; default: 0; + * a toggle (software negate its value) triggers a one-shot mode action + */ +#define MCPWM_FH1_FORCE_OST (BIT(4)) +#define MCPWM_FH1_FORCE_OST_M (MCPWM_FH1_FORCE_OST_V << MCPWM_FH1_FORCE_OST_S) +#define MCPWM_FH1_FORCE_OST_V 0x00000001U +#define MCPWM_FH1_FORCE_OST_S 4 -#define MCPWM_FH1_STATUS_REG(i) (REG_MCPWM_BASE(i) + 0x00a8) -/* MCPWM_FH1_OST_ON : RO ;bitpos:[1] ;default: 1'd0 ; */ -/*description: Set and reset by hardware. If set an one-shot mode action is on going*/ -#define MCPWM_FH1_OST_ON (BIT(1)) -#define MCPWM_FH1_OST_ON_M (BIT(1)) -#define MCPWM_FH1_OST_ON_V 0x1 -#define MCPWM_FH1_OST_ON_S 1 -/* MCPWM_FH1_CBC_ON : RO ;bitpos:[0] ;default: 1'd0 ; */ -/*description: Set and reset by hardware. If set an cycle-by-cycle mode action is on going*/ -#define MCPWM_FH1_CBC_ON (BIT(0)) -#define MCPWM_FH1_CBC_ON_M (BIT(0)) -#define MCPWM_FH1_CBC_ON_V 0x1 +/** MCPWM_FH1_STATUS_REG register + * Status of fault events. + */ +#define MCPWM_FH1_STATUS_REG(i) (DR_REG_MCPWM_BASE(i) + 0xa8) +/** MCPWM_FH1_CBC_ON : RO; bitpos: [0]; default: 0; + * Set and reset by hardware. If set, a cycle-by-cycle mode action is on going + */ +#define MCPWM_FH1_CBC_ON (BIT(0)) +#define MCPWM_FH1_CBC_ON_M (MCPWM_FH1_CBC_ON_V << MCPWM_FH1_CBC_ON_S) +#define MCPWM_FH1_CBC_ON_V 0x00000001U #define MCPWM_FH1_CBC_ON_S 0 +/** MCPWM_FH1_OST_ON : RO; bitpos: [1]; default: 0; + * Set and reset by hardware. If set, an one-shot mode action is on going + */ +#define MCPWM_FH1_OST_ON (BIT(1)) +#define MCPWM_FH1_OST_ON_M (MCPWM_FH1_OST_ON_V << MCPWM_FH1_OST_ON_S) +#define MCPWM_FH1_OST_ON_V 0x00000001U +#define MCPWM_FH1_OST_ON_S 1 -#define MCPWM_GEN2_STMP_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x00ac) -/* MCPWM_GEN2_B_SHDW_FULL : RO ;bitpos:[9] ;default: 1'd0 ; */ -/*description: Set and reset by hardware. If set PWM generator 2 time stamp - B's shadow reg is filled and waiting to be transferred to B's active reg. If cleared B's active reg has been updated with shadow reg latest value*/ -#define MCPWM_GEN2_B_SHDW_FULL (BIT(9)) -#define MCPWM_GEN2_B_SHDW_FULL_M (BIT(9)) -#define MCPWM_GEN2_B_SHDW_FULL_V 0x1 -#define MCPWM_GEN2_B_SHDW_FULL_S 9 -/* MCPWM_GEN2_A_SHDW_FULL : RO ;bitpos:[8] ;default: 1'd0 ; */ -/*description: Set and reset by hardware. If set PWM generator 2 time stamp - A's shadow reg is filled and waiting to be transferred to A's active reg. If cleared A's active reg has been updated with shadow reg latest value*/ -#define MCPWM_GEN2_A_SHDW_FULL (BIT(8)) -#define MCPWM_GEN2_A_SHDW_FULL_M (BIT(8)) -#define MCPWM_GEN2_A_SHDW_FULL_V 0x1 -#define MCPWM_GEN2_A_SHDW_FULL_S 8 -/* MCPWM_GEN2_B_UPMETHOD : R/W ;bitpos:[7:4] ;default: 4'd0 ; */ -/*description: Update method for PWM generator 2 time stamp B's active reg. - 0: immediate bit0: TEZ bit1: TEP bit2: sync bit3: disable update*/ -#define MCPWM_GEN2_B_UPMETHOD 0x0000000F -#define MCPWM_GEN2_B_UPMETHOD_M ((MCPWM_GEN2_B_UPMETHOD_V)<<(MCPWM_GEN2_B_UPMETHOD_S)) -#define MCPWM_GEN2_B_UPMETHOD_V 0xF -#define MCPWM_GEN2_B_UPMETHOD_S 4 -/* MCPWM_GEN2_A_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: Update method for PWM generator 2 time stamp A's active reg. - 0: immediate bit0: TEZ bit1: TEP bit2: sync bit3: disable update*/ -#define MCPWM_GEN2_A_UPMETHOD 0x0000000F -#define MCPWM_GEN2_A_UPMETHOD_M ((MCPWM_GEN2_A_UPMETHOD_V)<<(MCPWM_GEN2_A_UPMETHOD_S)) -#define MCPWM_GEN2_A_UPMETHOD_V 0xF +/** MCPWM_GEN2_STMP_CFG_REG register + * Transfer status and update method for time stamp registers A and B + */ +#define MCPWM_GEN2_STMP_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xac) +/** MCPWM_GEN2_A_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for PWM generator 2 time stamp A's active register. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when + * bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + */ +#define MCPWM_GEN2_A_UPMETHOD 0x0000000FU +#define MCPWM_GEN2_A_UPMETHOD_M (MCPWM_GEN2_A_UPMETHOD_V << MCPWM_GEN2_A_UPMETHOD_S) +#define MCPWM_GEN2_A_UPMETHOD_V 0x0000000FU #define MCPWM_GEN2_A_UPMETHOD_S 0 +/** MCPWM_GEN2_B_UPMETHOD : R/W; bitpos: [7:4]; default: 0; + * Update method for PWM generator 2 time stamp B's active register. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when + * bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + */ +#define MCPWM_GEN2_B_UPMETHOD 0x0000000FU +#define MCPWM_GEN2_B_UPMETHOD_M (MCPWM_GEN2_B_UPMETHOD_V << MCPWM_GEN2_B_UPMETHOD_S) +#define MCPWM_GEN2_B_UPMETHOD_V 0x0000000FU +#define MCPWM_GEN2_B_UPMETHOD_S 4 +/** MCPWM_GEN2_A_SHDW_FULL : R/W/WTC/SC; bitpos: [8]; default: 0; + * Set and reset by hardware. If set, PWM generator 2 time stamp A's shadow reg is + * filled and waiting to be transferred to A's active reg. If cleared, A's active reg + * has been updated with shadow register latest value + */ +#define MCPWM_GEN2_A_SHDW_FULL (BIT(8)) +#define MCPWM_GEN2_A_SHDW_FULL_M (MCPWM_GEN2_A_SHDW_FULL_V << MCPWM_GEN2_A_SHDW_FULL_S) +#define MCPWM_GEN2_A_SHDW_FULL_V 0x00000001U +#define MCPWM_GEN2_A_SHDW_FULL_S 8 +/** MCPWM_GEN2_B_SHDW_FULL : R/W/WTC/SC; bitpos: [9]; default: 0; + * Set and reset by hardware. If set, PWM generator 2 time stamp B's shadow reg is + * filled and waiting to be transferred to B's active reg. If cleared, B's active reg + * has been updated with shadow register latest value + */ +#define MCPWM_GEN2_B_SHDW_FULL (BIT(9)) +#define MCPWM_GEN2_B_SHDW_FULL_M (MCPWM_GEN2_B_SHDW_FULL_V << MCPWM_GEN2_B_SHDW_FULL_S) +#define MCPWM_GEN2_B_SHDW_FULL_V 0x00000001U +#define MCPWM_GEN2_B_SHDW_FULL_S 9 -#define MCPWM_GEN2_TSTMP_A_REG(i) (REG_MCPWM_BASE(i) + 0x00b0) -/* MCPWM_GEN2_A : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: PWM generator 2 time stamp A's shadow reg*/ -#define MCPWM_GEN2_A 0x0000FFFF -#define MCPWM_GEN2_A_M ((MCPWM_GEN2_A_V)<<(MCPWM_GEN2_A_S)) -#define MCPWM_GEN2_A_V 0xFFFF +/** MCPWM_GEN2_TSTMP_A_REG register + * PWM generator 2 shadow register for timer stamp A. + */ +#define MCPWM_GEN2_TSTMP_A_REG(i) (DR_REG_MCPWM_BASE(i) + 0xb0) +/** MCPWM_GEN2_A : R/W; bitpos: [15:0]; default: 0; + * PWM generator 2 time stamp A's shadow register + */ +#define MCPWM_GEN2_A 0x0000FFFFU +#define MCPWM_GEN2_A_M (MCPWM_GEN2_A_V << MCPWM_GEN2_A_S) +#define MCPWM_GEN2_A_V 0x0000FFFFU #define MCPWM_GEN2_A_S 0 -#define MCPWM_GEN2_TSTMP_B_REG(i) (REG_MCPWM_BASE(i) + 0x00b4) -/* MCPWM_GEN2_B : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: PWM generator 2 time stamp B's shadow reg*/ -#define MCPWM_GEN2_B 0x0000FFFF -#define MCPWM_GEN2_B_M ((MCPWM_GEN2_B_V)<<(MCPWM_GEN2_B_S)) -#define MCPWM_GEN2_B_V 0xFFFF +/** MCPWM_GEN2_TSTMP_B_REG register + * PWM generator 2 shadow register for timer stamp A. + */ +#define MCPWM_GEN2_TSTMP_B_REG(i) (DR_REG_MCPWM_BASE(i) + 0xb4) +/** MCPWM_GEN2_B : R/W; bitpos: [15:0]; default: 0; + * PWM generator 2 time stamp B's shadow register + */ +#define MCPWM_GEN2_B 0x0000FFFFU +#define MCPWM_GEN2_B_M (MCPWM_GEN2_B_V << MCPWM_GEN2_B_S) +#define MCPWM_GEN2_B_V 0x0000FFFFU #define MCPWM_GEN2_B_S 0 -#define MCPWM_GEN2_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0x00b8) -/* MCPWM_GEN2_T1_SEL : R/W ;bitpos:[9:7] ;default: 3'd0 ; */ -/*description: Source selection for PWM generate2 event_t1 take effect immediately - 0: fault_event0 1: fault_event1 2: fault_event2 3: sync_taken 4: none*/ -#define MCPWM_GEN2_T1_SEL 0x00000007 -#define MCPWM_GEN2_T1_SEL_M ((MCPWM_GEN2_T1_SEL_V)<<(MCPWM_GEN2_T1_SEL_S)) -#define MCPWM_GEN2_T1_SEL_V 0x7 -#define MCPWM_GEN2_T1_SEL_S 7 -/* MCPWM_GEN2_T0_SEL : R/W ;bitpos:[6:4] ;default: 3'd0 ; */ -/*description: Source selection for PWM generate2 event_t0 take effect immediately - 0: fault_event0 1: fault_event1 2: fault_event2 3: sync_taken 4: none*/ -#define MCPWM_GEN2_T0_SEL 0x00000007 -#define MCPWM_GEN2_T0_SEL_M ((MCPWM_GEN2_T0_SEL_V)<<(MCPWM_GEN2_T0_SEL_S)) -#define MCPWM_GEN2_T0_SEL_V 0x7 -#define MCPWM_GEN2_T0_SEL_S 4 -/* MCPWM_GEN2_CFG_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: Update method for PWM generate2's active reg of configuration. - 0: immediate bit0: TEZ bit1: TEP bit2: sync. bit3: disable update*/ -#define MCPWM_GEN2_CFG_UPMETHOD 0x0000000F -#define MCPWM_GEN2_CFG_UPMETHOD_M ((MCPWM_GEN2_CFG_UPMETHOD_V)<<(MCPWM_GEN2_CFG_UPMETHOD_S)) -#define MCPWM_GEN2_CFG_UPMETHOD_V 0xF +/** MCPWM_GEN2_CFG0_REG register + * PWM generator 2 event T0 and T1 handling + */ +#define MCPWM_GEN2_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0xb8) +/** MCPWM_GEN2_CFG_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for PWM generator 2's active register of configuration. 0: + * immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1:sync;when bit3 is + * set to 1:disable the update. + */ +#define MCPWM_GEN2_CFG_UPMETHOD 0x0000000FU +#define MCPWM_GEN2_CFG_UPMETHOD_M (MCPWM_GEN2_CFG_UPMETHOD_V << MCPWM_GEN2_CFG_UPMETHOD_S) +#define MCPWM_GEN2_CFG_UPMETHOD_V 0x0000000FU #define MCPWM_GEN2_CFG_UPMETHOD_S 0 +/** MCPWM_GEN2_T0_SEL : R/W; bitpos: [6:4]; default: 0; + * Source selection for PWM generator 2 event_t0, take effect immediately, 0: + * fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + */ +#define MCPWM_GEN2_T0_SEL 0x00000007U +#define MCPWM_GEN2_T0_SEL_M (MCPWM_GEN2_T0_SEL_V << MCPWM_GEN2_T0_SEL_S) +#define MCPWM_GEN2_T0_SEL_V 0x00000007U +#define MCPWM_GEN2_T0_SEL_S 4 +/** MCPWM_GEN2_T1_SEL : R/W; bitpos: [9:7]; default: 0; + * Source selection for PWM generator 2 event_t1, take effect immediately, 0: + * fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + */ +#define MCPWM_GEN2_T1_SEL 0x00000007U +#define MCPWM_GEN2_T1_SEL_M (MCPWM_GEN2_T1_SEL_V << MCPWM_GEN2_T1_SEL_S) +#define MCPWM_GEN2_T1_SEL_V 0x00000007U +#define MCPWM_GEN2_T1_SEL_S 7 -#define MCPWM_GEN2_FORCE_REG(i) (REG_MCPWM_BASE(i) + 0x00bc) -/* MCPWM_GEN2_B_NCIFORCE_MODE : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: Non-continuous immediate software force mode for PWM2B 0: disabled - 1: low 2: high 3: disabled*/ -#define MCPWM_GEN2_B_NCIFORCE_MODE 0x00000003 -#define MCPWM_GEN2_B_NCIFORCE_MODE_M ((MCPWM_GEN2_B_NCIFORCE_MODE_V)<<(MCPWM_GEN2_B_NCIFORCE_MODE_S)) -#define MCPWM_GEN2_B_NCIFORCE_MODE_V 0x3 -#define MCPWM_GEN2_B_NCIFORCE_MODE_S 14 -/* MCPWM_GEN2_B_NCIFORCE : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: Non-continuous immediate software force trigger for PWM2B a - toggle will trigger a force event*/ -#define MCPWM_GEN2_B_NCIFORCE (BIT(13)) -#define MCPWM_GEN2_B_NCIFORCE_M (BIT(13)) -#define MCPWM_GEN2_B_NCIFORCE_V 0x1 -#define MCPWM_GEN2_B_NCIFORCE_S 13 -/* MCPWM_GEN2_A_NCIFORCE_MODE : R/W ;bitpos:[12:11] ;default: 2'd0 ; */ -/*description: Non-continuous immediate software force mode for PWM2A 0: disabled - 1: low 2: high 3: disabled*/ -#define MCPWM_GEN2_A_NCIFORCE_MODE 0x00000003 -#define MCPWM_GEN2_A_NCIFORCE_MODE_M ((MCPWM_GEN2_A_NCIFORCE_MODE_V)<<(MCPWM_GEN2_A_NCIFORCE_MODE_S)) -#define MCPWM_GEN2_A_NCIFORCE_MODE_V 0x3 -#define MCPWM_GEN2_A_NCIFORCE_MODE_S 11 -/* MCPWM_GEN2_A_NCIFORCE : R/W ;bitpos:[10] ;default: 1'd0 ; */ -/*description: Non-continuous immediate software force trigger for PWM2A a - toggle will trigger a force event*/ -#define MCPWM_GEN2_A_NCIFORCE (BIT(10)) -#define MCPWM_GEN2_A_NCIFORCE_M (BIT(10)) -#define MCPWM_GEN2_A_NCIFORCE_V 0x1 -#define MCPWM_GEN2_A_NCIFORCE_S 10 -/* MCPWM_GEN2_B_CNTUFORCE_MODE : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: Continuous software force mode for PWM2B. 0: disabled 1: low - 2: high 3: disabled*/ -#define MCPWM_GEN2_B_CNTUFORCE_MODE 0x00000003 -#define MCPWM_GEN2_B_CNTUFORCE_MODE_M ((MCPWM_GEN2_B_CNTUFORCE_MODE_V)<<(MCPWM_GEN2_B_CNTUFORCE_MODE_S)) -#define MCPWM_GEN2_B_CNTUFORCE_MODE_V 0x3 -#define MCPWM_GEN2_B_CNTUFORCE_MODE_S 8 -/* MCPWM_GEN2_A_CNTUFORCE_MODE : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: Continuous software force mode for PWM2A. 0: disabled 1: low - 2: high 3: disabled*/ -#define MCPWM_GEN2_A_CNTUFORCE_MODE 0x00000003 -#define MCPWM_GEN2_A_CNTUFORCE_MODE_M ((MCPWM_GEN2_A_CNTUFORCE_MODE_V)<<(MCPWM_GEN2_A_CNTUFORCE_MODE_S)) -#define MCPWM_GEN2_A_CNTUFORCE_MODE_V 0x3 -#define MCPWM_GEN2_A_CNTUFORCE_MODE_S 6 -/* MCPWM_GEN2_CNTUFORCE_UPMETHOD : R/W ;bitpos:[5:0] ;default: 6'h20 ; */ -/*description: Update method for continuous software force of PWM generator2. - 0: immediate bit0: TEZ bit1: TEP bit2: TEA bit3: TEB bit4: sync bit5: disable update. (TEA/B here and below means an event generated when timer value equals A/B register)*/ -#define MCPWM_GEN2_CNTUFORCE_UPMETHOD 0x0000003F -#define MCPWM_GEN2_CNTUFORCE_UPMETHOD_M ((MCPWM_GEN2_CNTUFORCE_UPMETHOD_V)<<(MCPWM_GEN2_CNTUFORCE_UPMETHOD_S)) -#define MCPWM_GEN2_CNTUFORCE_UPMETHOD_V 0x3F +/** MCPWM_GEN2_FORCE_REG register + * Permissives to force PWM2A and PWM2B outputs by software + */ +#define MCPWM_GEN2_FORCE_REG(i) (DR_REG_MCPWM_BASE(i) + 0xbc) +/** MCPWM_GEN2_CNTUFORCE_UPMETHOD : R/W; bitpos: [5:0]; default: 32; + * Updating method for continuous software force of PWM generator 2. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ,when bit1 is set to 1: TEP, when + * bit2 is set to 1: TEA, when bit3 is set to 1: TEB, when bit4 is set to 1: sync, + * when bit5 is set to 1: disable update. (TEA/B here and below means an event + * generated when the timer's value equals to that of register A/B.) + */ +#define MCPWM_GEN2_CNTUFORCE_UPMETHOD 0x0000003FU +#define MCPWM_GEN2_CNTUFORCE_UPMETHOD_M (MCPWM_GEN2_CNTUFORCE_UPMETHOD_V << MCPWM_GEN2_CNTUFORCE_UPMETHOD_S) +#define MCPWM_GEN2_CNTUFORCE_UPMETHOD_V 0x0000003FU #define MCPWM_GEN2_CNTUFORCE_UPMETHOD_S 0 +/** MCPWM_GEN2_A_CNTUFORCE_MODE : R/W; bitpos: [7:6]; default: 0; + * Continuous software force mode for PWM2A. 0: disabled, 1: low, 2: high, 3: disabled + */ +#define MCPWM_GEN2_A_CNTUFORCE_MODE 0x00000003U +#define MCPWM_GEN2_A_CNTUFORCE_MODE_M (MCPWM_GEN2_A_CNTUFORCE_MODE_V << MCPWM_GEN2_A_CNTUFORCE_MODE_S) +#define MCPWM_GEN2_A_CNTUFORCE_MODE_V 0x00000003U +#define MCPWM_GEN2_A_CNTUFORCE_MODE_S 6 +/** MCPWM_GEN2_B_CNTUFORCE_MODE : R/W; bitpos: [9:8]; default: 0; + * Continuous software force mode for PWM2B. 0: disabled, 1: low, 2: high, 3: disabled + */ +#define MCPWM_GEN2_B_CNTUFORCE_MODE 0x00000003U +#define MCPWM_GEN2_B_CNTUFORCE_MODE_M (MCPWM_GEN2_B_CNTUFORCE_MODE_V << MCPWM_GEN2_B_CNTUFORCE_MODE_S) +#define MCPWM_GEN2_B_CNTUFORCE_MODE_V 0x00000003U +#define MCPWM_GEN2_B_CNTUFORCE_MODE_S 8 +/** MCPWM_GEN2_A_NCIFORCE : R/W; bitpos: [10]; default: 0; + * Trigger of non-continuous immediate software-force event for PWM2A, a toggle will + * trigger a force event. + */ +#define MCPWM_GEN2_A_NCIFORCE (BIT(10)) +#define MCPWM_GEN2_A_NCIFORCE_M (MCPWM_GEN2_A_NCIFORCE_V << MCPWM_GEN2_A_NCIFORCE_S) +#define MCPWM_GEN2_A_NCIFORCE_V 0x00000001U +#define MCPWM_GEN2_A_NCIFORCE_S 10 +/** MCPWM_GEN2_A_NCIFORCE_MODE : R/W; bitpos: [12:11]; default: 0; + * non-continuous immediate software force mode for PWM2A, 0: disabled, 1: low, 2: + * high, 3: disabled + */ +#define MCPWM_GEN2_A_NCIFORCE_MODE 0x00000003U +#define MCPWM_GEN2_A_NCIFORCE_MODE_M (MCPWM_GEN2_A_NCIFORCE_MODE_V << MCPWM_GEN2_A_NCIFORCE_MODE_S) +#define MCPWM_GEN2_A_NCIFORCE_MODE_V 0x00000003U +#define MCPWM_GEN2_A_NCIFORCE_MODE_S 11 +/** MCPWM_GEN2_B_NCIFORCE : R/W; bitpos: [13]; default: 0; + * Trigger of non-continuous immediate software-force event for PWM2B, a toggle will + * trigger a force event. + */ +#define MCPWM_GEN2_B_NCIFORCE (BIT(13)) +#define MCPWM_GEN2_B_NCIFORCE_M (MCPWM_GEN2_B_NCIFORCE_V << MCPWM_GEN2_B_NCIFORCE_S) +#define MCPWM_GEN2_B_NCIFORCE_V 0x00000001U +#define MCPWM_GEN2_B_NCIFORCE_S 13 +/** MCPWM_GEN2_B_NCIFORCE_MODE : R/W; bitpos: [15:14]; default: 0; + * non-continuous immediate software force mode for PWM2B, 0: disabled, 1: low, 2: + * high, 3: disabled + */ +#define MCPWM_GEN2_B_NCIFORCE_MODE 0x00000003U +#define MCPWM_GEN2_B_NCIFORCE_MODE_M (MCPWM_GEN2_B_NCIFORCE_MODE_V << MCPWM_GEN2_B_NCIFORCE_MODE_S) +#define MCPWM_GEN2_B_NCIFORCE_MODE_V 0x00000003U +#define MCPWM_GEN2_B_NCIFORCE_MODE_S 14 -#define MCPWM_GEN2_A_REG(i) (REG_MCPWM_BASE(i) + 0x00c0) -/* MCPWM_GEN2_A_DT1 : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: Action on PWM2A triggered by event_t1 when timer decreasing. - 0: no change 1: low 2: high 3: toggle*/ -#define MCPWM_GEN2_A_DT1 0x00000003 -#define MCPWM_GEN2_A_DT1_M ((MCPWM_GEN2_A_DT1_V)<<(MCPWM_GEN2_A_DT1_S)) -#define MCPWM_GEN2_A_DT1_V 0x3 -#define MCPWM_GEN2_A_DT1_S 22 -/* MCPWM_GEN2_A_DT0 : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: Action on PWM2A triggered by event_t0 when timer decreasing*/ -#define MCPWM_GEN2_A_DT0 0x00000003 -#define MCPWM_GEN2_A_DT0_M ((MCPWM_GEN2_A_DT0_V)<<(MCPWM_GEN2_A_DT0_S)) -#define MCPWM_GEN2_A_DT0_V 0x3 -#define MCPWM_GEN2_A_DT0_S 20 -/* MCPWM_GEN2_A_DTEB : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: Action on PWM2A triggered by event TEB when timer decreasing*/ -#define MCPWM_GEN2_A_DTEB 0x00000003 -#define MCPWM_GEN2_A_DTEB_M ((MCPWM_GEN2_A_DTEB_V)<<(MCPWM_GEN2_A_DTEB_S)) -#define MCPWM_GEN2_A_DTEB_V 0x3 -#define MCPWM_GEN2_A_DTEB_S 18 -/* MCPWM_GEN2_A_DTEA : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: Action on PWM2A triggered by event TEA when timer decreasing*/ -#define MCPWM_GEN2_A_DTEA 0x00000003 -#define MCPWM_GEN2_A_DTEA_M ((MCPWM_GEN2_A_DTEA_V)<<(MCPWM_GEN2_A_DTEA_S)) -#define MCPWM_GEN2_A_DTEA_V 0x3 -#define MCPWM_GEN2_A_DTEA_S 16 -/* MCPWM_GEN2_A_DTEP : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: Action on PWM2A triggered by event TEP when timer decreasing*/ -#define MCPWM_GEN2_A_DTEP 0x00000003 -#define MCPWM_GEN2_A_DTEP_M ((MCPWM_GEN2_A_DTEP_V)<<(MCPWM_GEN2_A_DTEP_S)) -#define MCPWM_GEN2_A_DTEP_V 0x3 -#define MCPWM_GEN2_A_DTEP_S 14 -/* MCPWM_GEN2_A_DTEZ : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: Action on PWM2A triggered by event TEZ when timer decreasing*/ -#define MCPWM_GEN2_A_DTEZ 0x00000003 -#define MCPWM_GEN2_A_DTEZ_M ((MCPWM_GEN2_A_DTEZ_V)<<(MCPWM_GEN2_A_DTEZ_S)) -#define MCPWM_GEN2_A_DTEZ_V 0x3 -#define MCPWM_GEN2_A_DTEZ_S 12 -/* MCPWM_GEN2_A_UT1 : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: Action on PWM2A triggered by event_t1 when timer increasing*/ -#define MCPWM_GEN2_A_UT1 0x00000003 -#define MCPWM_GEN2_A_UT1_M ((MCPWM_GEN2_A_UT1_V)<<(MCPWM_GEN2_A_UT1_S)) -#define MCPWM_GEN2_A_UT1_V 0x3 -#define MCPWM_GEN2_A_UT1_S 10 -/* MCPWM_GEN2_A_UT0 : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: Action on PWM2A triggered by event_t0 when timer increasing*/ -#define MCPWM_GEN2_A_UT0 0x00000003 -#define MCPWM_GEN2_A_UT0_M ((MCPWM_GEN2_A_UT0_V)<<(MCPWM_GEN2_A_UT0_S)) -#define MCPWM_GEN2_A_UT0_V 0x3 -#define MCPWM_GEN2_A_UT0_S 8 -/* MCPWM_GEN2_A_UTEB : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: Action on PWM2A triggered by event TEB when timer increasing*/ -#define MCPWM_GEN2_A_UTEB 0x00000003 -#define MCPWM_GEN2_A_UTEB_M ((MCPWM_GEN2_A_UTEB_V)<<(MCPWM_GEN2_A_UTEB_S)) -#define MCPWM_GEN2_A_UTEB_V 0x3 -#define MCPWM_GEN2_A_UTEB_S 6 -/* MCPWM_GEN2_A_UTEA : R/W ;bitpos:[5:4] ;default: 2'd0 ; */ -/*description: Action on PWM2A triggered by event TEA when timer increasing*/ -#define MCPWM_GEN2_A_UTEA 0x00000003 -#define MCPWM_GEN2_A_UTEA_M ((MCPWM_GEN2_A_UTEA_V)<<(MCPWM_GEN2_A_UTEA_S)) -#define MCPWM_GEN2_A_UTEA_V 0x3 -#define MCPWM_GEN2_A_UTEA_S 4 -/* MCPWM_GEN2_A_UTEP : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: Action on PWM2A triggered by event TEP when timer increasing*/ -#define MCPWM_GEN2_A_UTEP 0x00000003 -#define MCPWM_GEN2_A_UTEP_M ((MCPWM_GEN2_A_UTEP_V)<<(MCPWM_GEN2_A_UTEP_S)) -#define MCPWM_GEN2_A_UTEP_V 0x3 -#define MCPWM_GEN2_A_UTEP_S 2 -/* MCPWM_GEN2_A_UTEZ : R/W ;bitpos:[1:0] ;default: 2'd0 ; */ -/*description: Action on PWM2A triggered by event TEZ when timer increasing*/ -#define MCPWM_GEN2_A_UTEZ 0x00000003 -#define MCPWM_GEN2_A_UTEZ_M ((MCPWM_GEN2_A_UTEZ_V)<<(MCPWM_GEN2_A_UTEZ_S)) -#define MCPWM_GEN2_A_UTEZ_V 0x3 +/** MCPWM_GEN2_A_REG register + * Actions triggered by events on PWM2A + */ +#define MCPWM_GEN2_A_REG(i) (DR_REG_MCPWM_BASE(i) + 0xc0) +/** MCPWM_GEN2_A_UTEZ : R/W; bitpos: [1:0]; default: 0; + * Action on PWM2A triggered by event TEZ when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_UTEZ 0x00000003U +#define MCPWM_GEN2_A_UTEZ_M (MCPWM_GEN2_A_UTEZ_V << MCPWM_GEN2_A_UTEZ_S) +#define MCPWM_GEN2_A_UTEZ_V 0x00000003U #define MCPWM_GEN2_A_UTEZ_S 0 +/** MCPWM_GEN2_A_UTEP : R/W; bitpos: [3:2]; default: 0; + * Action on PWM2A triggered by event TEP when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_UTEP 0x00000003U +#define MCPWM_GEN2_A_UTEP_M (MCPWM_GEN2_A_UTEP_V << MCPWM_GEN2_A_UTEP_S) +#define MCPWM_GEN2_A_UTEP_V 0x00000003U +#define MCPWM_GEN2_A_UTEP_S 2 +/** MCPWM_GEN2_A_UTEA : R/W; bitpos: [5:4]; default: 0; + * Action on PWM2A triggered by event TEA when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_UTEA 0x00000003U +#define MCPWM_GEN2_A_UTEA_M (MCPWM_GEN2_A_UTEA_V << MCPWM_GEN2_A_UTEA_S) +#define MCPWM_GEN2_A_UTEA_V 0x00000003U +#define MCPWM_GEN2_A_UTEA_S 4 +/** MCPWM_GEN2_A_UTEB : R/W; bitpos: [7:6]; default: 0; + * Action on PWM2A triggered by event TEB when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_UTEB 0x00000003U +#define MCPWM_GEN2_A_UTEB_M (MCPWM_GEN2_A_UTEB_V << MCPWM_GEN2_A_UTEB_S) +#define MCPWM_GEN2_A_UTEB_V 0x00000003U +#define MCPWM_GEN2_A_UTEB_S 6 +/** MCPWM_GEN2_A_UT0 : R/W; bitpos: [9:8]; default: 0; + * Action on PWM2A triggered by event_t0 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_UT0 0x00000003U +#define MCPWM_GEN2_A_UT0_M (MCPWM_GEN2_A_UT0_V << MCPWM_GEN2_A_UT0_S) +#define MCPWM_GEN2_A_UT0_V 0x00000003U +#define MCPWM_GEN2_A_UT0_S 8 +/** MCPWM_GEN2_A_UT1 : R/W; bitpos: [11:10]; default: 0; + * Action on PWM2A triggered by event_t1 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_UT1 0x00000003U +#define MCPWM_GEN2_A_UT1_M (MCPWM_GEN2_A_UT1_V << MCPWM_GEN2_A_UT1_S) +#define MCPWM_GEN2_A_UT1_V 0x00000003U +#define MCPWM_GEN2_A_UT1_S 10 +/** MCPWM_GEN2_A_DTEZ : R/W; bitpos: [13:12]; default: 0; + * Action on PWM2A triggered by event TEZ when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_DTEZ 0x00000003U +#define MCPWM_GEN2_A_DTEZ_M (MCPWM_GEN2_A_DTEZ_V << MCPWM_GEN2_A_DTEZ_S) +#define MCPWM_GEN2_A_DTEZ_V 0x00000003U +#define MCPWM_GEN2_A_DTEZ_S 12 +/** MCPWM_GEN2_A_DTEP : R/W; bitpos: [15:14]; default: 0; + * Action on PWM2A triggered by event TEP when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_DTEP 0x00000003U +#define MCPWM_GEN2_A_DTEP_M (MCPWM_GEN2_A_DTEP_V << MCPWM_GEN2_A_DTEP_S) +#define MCPWM_GEN2_A_DTEP_V 0x00000003U +#define MCPWM_GEN2_A_DTEP_S 14 +/** MCPWM_GEN2_A_DTEA : R/W; bitpos: [17:16]; default: 0; + * Action on PWM2A triggered by event TEA when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_DTEA 0x00000003U +#define MCPWM_GEN2_A_DTEA_M (MCPWM_GEN2_A_DTEA_V << MCPWM_GEN2_A_DTEA_S) +#define MCPWM_GEN2_A_DTEA_V 0x00000003U +#define MCPWM_GEN2_A_DTEA_S 16 +/** MCPWM_GEN2_A_DTEB : R/W; bitpos: [19:18]; default: 0; + * Action on PWM2A triggered by event TEB when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_DTEB 0x00000003U +#define MCPWM_GEN2_A_DTEB_M (MCPWM_GEN2_A_DTEB_V << MCPWM_GEN2_A_DTEB_S) +#define MCPWM_GEN2_A_DTEB_V 0x00000003U +#define MCPWM_GEN2_A_DTEB_S 18 +/** MCPWM_GEN2_A_DT0 : R/W; bitpos: [21:20]; default: 0; + * Action on PWM2A triggered by event_t0 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_DT0 0x00000003U +#define MCPWM_GEN2_A_DT0_M (MCPWM_GEN2_A_DT0_V << MCPWM_GEN2_A_DT0_S) +#define MCPWM_GEN2_A_DT0_V 0x00000003U +#define MCPWM_GEN2_A_DT0_S 20 +/** MCPWM_GEN2_A_DT1 : R/W; bitpos: [23:22]; default: 0; + * Action on PWM2A triggered by event_t1 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_DT1 0x00000003U +#define MCPWM_GEN2_A_DT1_M (MCPWM_GEN2_A_DT1_V << MCPWM_GEN2_A_DT1_S) +#define MCPWM_GEN2_A_DT1_V 0x00000003U +#define MCPWM_GEN2_A_DT1_S 22 -#define MCPWM_GEN2_B_REG(i) (REG_MCPWM_BASE(i) + 0x00c4) -/* MCPWM_GEN2_B_DT1 : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: Action on PWM2B triggered by event_t1 when timer decreasing. - 0: no change 1: low 2: high 3: toggle*/ -#define MCPWM_GEN2_B_DT1 0x00000003 -#define MCPWM_GEN2_B_DT1_M ((MCPWM_GEN2_B_DT1_V)<<(MCPWM_GEN2_B_DT1_S)) -#define MCPWM_GEN2_B_DT1_V 0x3 -#define MCPWM_GEN2_B_DT1_S 22 -/* MCPWM_GEN2_B_DT0 : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: Action on PWM2B triggered by event_t0 when timer decreasing*/ -#define MCPWM_GEN2_B_DT0 0x00000003 -#define MCPWM_GEN2_B_DT0_M ((MCPWM_GEN2_B_DT0_V)<<(MCPWM_GEN2_B_DT0_S)) -#define MCPWM_GEN2_B_DT0_V 0x3 -#define MCPWM_GEN2_B_DT0_S 20 -/* MCPWM_GEN2_B_DTEB : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: Action on PWM2B triggered by event TEB when timer decreasing*/ -#define MCPWM_GEN2_B_DTEB 0x00000003 -#define MCPWM_GEN2_B_DTEB_M ((MCPWM_GEN2_B_DTEB_V)<<(MCPWM_GEN2_B_DTEB_S)) -#define MCPWM_GEN2_B_DTEB_V 0x3 -#define MCPWM_GEN2_B_DTEB_S 18 -/* MCPWM_GEN2_B_DTEA : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: Action on PWM2B triggered by event TEA when timer decreasing*/ -#define MCPWM_GEN2_B_DTEA 0x00000003 -#define MCPWM_GEN2_B_DTEA_M ((MCPWM_GEN2_B_DTEA_V)<<(MCPWM_GEN2_B_DTEA_S)) -#define MCPWM_GEN2_B_DTEA_V 0x3 -#define MCPWM_GEN2_B_DTEA_S 16 -/* MCPWM_GEN2_B_DTEP : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: Action on PWM2B triggered by event TEP when timer decreasing*/ -#define MCPWM_GEN2_B_DTEP 0x00000003 -#define MCPWM_GEN2_B_DTEP_M ((MCPWM_GEN2_B_DTEP_V)<<(MCPWM_GEN2_B_DTEP_S)) -#define MCPWM_GEN2_B_DTEP_V 0x3 -#define MCPWM_GEN2_B_DTEP_S 14 -/* MCPWM_GEN2_B_DTEZ : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: Action on PWM2B triggered by event TEZ when timer decreasing*/ -#define MCPWM_GEN2_B_DTEZ 0x00000003 -#define MCPWM_GEN2_B_DTEZ_M ((MCPWM_GEN2_B_DTEZ_V)<<(MCPWM_GEN2_B_DTEZ_S)) -#define MCPWM_GEN2_B_DTEZ_V 0x3 -#define MCPWM_GEN2_B_DTEZ_S 12 -/* MCPWM_GEN2_B_UT1 : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: Action on PWM2B triggered by event_t1 when timer increasing*/ -#define MCPWM_GEN2_B_UT1 0x00000003 -#define MCPWM_GEN2_B_UT1_M ((MCPWM_GEN2_B_UT1_V)<<(MCPWM_GEN2_B_UT1_S)) -#define MCPWM_GEN2_B_UT1_V 0x3 -#define MCPWM_GEN2_B_UT1_S 10 -/* MCPWM_GEN2_B_UT0 : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: Action on PWM2B triggered by event_t0 when timer increasing*/ -#define MCPWM_GEN2_B_UT0 0x00000003 -#define MCPWM_GEN2_B_UT0_M ((MCPWM_GEN2_B_UT0_V)<<(MCPWM_GEN2_B_UT0_S)) -#define MCPWM_GEN2_B_UT0_V 0x3 -#define MCPWM_GEN2_B_UT0_S 8 -/* MCPWM_GEN2_B_UTEB : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: Action on PWM2B triggered by event TEB when timer increasing*/ -#define MCPWM_GEN2_B_UTEB 0x00000003 -#define MCPWM_GEN2_B_UTEB_M ((MCPWM_GEN2_B_UTEB_V)<<(MCPWM_GEN2_B_UTEB_S)) -#define MCPWM_GEN2_B_UTEB_V 0x3 -#define MCPWM_GEN2_B_UTEB_S 6 -/* MCPWM_GEN2_B_UTEA : R/W ;bitpos:[5:4] ;default: 2'd0 ; */ -/*description: Action on PWM2B triggered by event TEA when timer increasing*/ -#define MCPWM_GEN2_B_UTEA 0x00000003 -#define MCPWM_GEN2_B_UTEA_M ((MCPWM_GEN2_B_UTEA_V)<<(MCPWM_GEN2_B_UTEA_S)) -#define MCPWM_GEN2_B_UTEA_V 0x3 -#define MCPWM_GEN2_B_UTEA_S 4 -/* MCPWM_GEN2_B_UTEP : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: Action on PWM2B triggered by event TEP when timer increasing*/ -#define MCPWM_GEN2_B_UTEP 0x00000003 -#define MCPWM_GEN2_B_UTEP_M ((MCPWM_GEN2_B_UTEP_V)<<(MCPWM_GEN2_B_UTEP_S)) -#define MCPWM_GEN2_B_UTEP_V 0x3 -#define MCPWM_GEN2_B_UTEP_S 2 -/* MCPWM_GEN2_B_UTEZ : R/W ;bitpos:[1:0] ;default: 2'd0 ; */ -/*description: Action on PWM2B triggered by event TEZ when timer increasing*/ -#define MCPWM_GEN2_B_UTEZ 0x00000003 -#define MCPWM_GEN2_B_UTEZ_M ((MCPWM_GEN2_B_UTEZ_V)<<(MCPWM_GEN2_B_UTEZ_S)) -#define MCPWM_GEN2_B_UTEZ_V 0x3 +/** MCPWM_GEN2_B_REG register + * Actions triggered by events on PWM2B + */ +#define MCPWM_GEN2_B_REG(i) (DR_REG_MCPWM_BASE(i) + 0xc4) +/** MCPWM_GEN2_B_UTEZ : R/W; bitpos: [1:0]; default: 0; + * Action on PWM2B triggered by event TEZ when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_UTEZ 0x00000003U +#define MCPWM_GEN2_B_UTEZ_M (MCPWM_GEN2_B_UTEZ_V << MCPWM_GEN2_B_UTEZ_S) +#define MCPWM_GEN2_B_UTEZ_V 0x00000003U #define MCPWM_GEN2_B_UTEZ_S 0 +/** MCPWM_GEN2_B_UTEP : R/W; bitpos: [3:2]; default: 0; + * Action on PWM2B triggered by event TEP when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_UTEP 0x00000003U +#define MCPWM_GEN2_B_UTEP_M (MCPWM_GEN2_B_UTEP_V << MCPWM_GEN2_B_UTEP_S) +#define MCPWM_GEN2_B_UTEP_V 0x00000003U +#define MCPWM_GEN2_B_UTEP_S 2 +/** MCPWM_GEN2_B_UTEA : R/W; bitpos: [5:4]; default: 0; + * Action on PWM2B triggered by event TEA when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_UTEA 0x00000003U +#define MCPWM_GEN2_B_UTEA_M (MCPWM_GEN2_B_UTEA_V << MCPWM_GEN2_B_UTEA_S) +#define MCPWM_GEN2_B_UTEA_V 0x00000003U +#define MCPWM_GEN2_B_UTEA_S 4 +/** MCPWM_GEN2_B_UTEB : R/W; bitpos: [7:6]; default: 0; + * Action on PWM2B triggered by event TEB when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_UTEB 0x00000003U +#define MCPWM_GEN2_B_UTEB_M (MCPWM_GEN2_B_UTEB_V << MCPWM_GEN2_B_UTEB_S) +#define MCPWM_GEN2_B_UTEB_V 0x00000003U +#define MCPWM_GEN2_B_UTEB_S 6 +/** MCPWM_GEN2_B_UT0 : R/W; bitpos: [9:8]; default: 0; + * Action on PWM2B triggered by event_t0 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_UT0 0x00000003U +#define MCPWM_GEN2_B_UT0_M (MCPWM_GEN2_B_UT0_V << MCPWM_GEN2_B_UT0_S) +#define MCPWM_GEN2_B_UT0_V 0x00000003U +#define MCPWM_GEN2_B_UT0_S 8 +/** MCPWM_GEN2_B_UT1 : R/W; bitpos: [11:10]; default: 0; + * Action on PWM2B triggered by event_t1 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_UT1 0x00000003U +#define MCPWM_GEN2_B_UT1_M (MCPWM_GEN2_B_UT1_V << MCPWM_GEN2_B_UT1_S) +#define MCPWM_GEN2_B_UT1_V 0x00000003U +#define MCPWM_GEN2_B_UT1_S 10 +/** MCPWM_GEN2_B_DTEZ : R/W; bitpos: [13:12]; default: 0; + * Action on PWM2B triggered by event TEZ when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_DTEZ 0x00000003U +#define MCPWM_GEN2_B_DTEZ_M (MCPWM_GEN2_B_DTEZ_V << MCPWM_GEN2_B_DTEZ_S) +#define MCPWM_GEN2_B_DTEZ_V 0x00000003U +#define MCPWM_GEN2_B_DTEZ_S 12 +/** MCPWM_GEN2_B_DTEP : R/W; bitpos: [15:14]; default: 0; + * Action on PWM2B triggered by event TEP when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_DTEP 0x00000003U +#define MCPWM_GEN2_B_DTEP_M (MCPWM_GEN2_B_DTEP_V << MCPWM_GEN2_B_DTEP_S) +#define MCPWM_GEN2_B_DTEP_V 0x00000003U +#define MCPWM_GEN2_B_DTEP_S 14 +/** MCPWM_GEN2_B_DTEA : R/W; bitpos: [17:16]; default: 0; + * Action on PWM2B triggered by event TEA when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_DTEA 0x00000003U +#define MCPWM_GEN2_B_DTEA_M (MCPWM_GEN2_B_DTEA_V << MCPWM_GEN2_B_DTEA_S) +#define MCPWM_GEN2_B_DTEA_V 0x00000003U +#define MCPWM_GEN2_B_DTEA_S 16 +/** MCPWM_GEN2_B_DTEB : R/W; bitpos: [19:18]; default: 0; + * Action on PWM2B triggered by event TEB when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_DTEB 0x00000003U +#define MCPWM_GEN2_B_DTEB_M (MCPWM_GEN2_B_DTEB_V << MCPWM_GEN2_B_DTEB_S) +#define MCPWM_GEN2_B_DTEB_V 0x00000003U +#define MCPWM_GEN2_B_DTEB_S 18 +/** MCPWM_GEN2_B_DT0 : R/W; bitpos: [21:20]; default: 0; + * Action on PWM2B triggered by event_t0 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_DT0 0x00000003U +#define MCPWM_GEN2_B_DT0_M (MCPWM_GEN2_B_DT0_V << MCPWM_GEN2_B_DT0_S) +#define MCPWM_GEN2_B_DT0_V 0x00000003U +#define MCPWM_GEN2_B_DT0_S 20 +/** MCPWM_GEN2_B_DT1 : R/W; bitpos: [23:22]; default: 0; + * Action on PWM2B triggered by event_t1 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_DT1 0x00000003U +#define MCPWM_GEN2_B_DT1_M (MCPWM_GEN2_B_DT1_V << MCPWM_GEN2_B_DT1_S) +#define MCPWM_GEN2_B_DT1_V 0x00000003U +#define MCPWM_GEN2_B_DT1_S 22 -#define MCPWM_DT2_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x00c8) -/* MCPWM_DT2_CLK_SEL : R/W ;bitpos:[17] ;default: 1'd0 ; */ -/*description: Dead time generator 1 clock selection. 0: PWM_clk 1: PT_clk*/ -#define MCPWM_DT2_CLK_SEL (BIT(17)) -#define MCPWM_DT2_CLK_SEL_M (BIT(17)) -#define MCPWM_DT2_CLK_SEL_V 0x1 -#define MCPWM_DT2_CLK_SEL_S 17 -/* MCPWM_DT2_B_OUTBYPASS : R/W ;bitpos:[16] ;default: 1'd1 ; */ -/*description: S0 in documentation*/ -#define MCPWM_DT2_B_OUTBYPASS (BIT(16)) -#define MCPWM_DT2_B_OUTBYPASS_M (BIT(16)) -#define MCPWM_DT2_B_OUTBYPASS_V 0x1 -#define MCPWM_DT2_B_OUTBYPASS_S 16 -/* MCPWM_DT2_A_OUTBYPASS : R/W ;bitpos:[15] ;default: 1'd1 ; */ -/*description: S1 in documentation*/ -#define MCPWM_DT2_A_OUTBYPASS (BIT(15)) -#define MCPWM_DT2_A_OUTBYPASS_M (BIT(15)) -#define MCPWM_DT2_A_OUTBYPASS_V 0x1 -#define MCPWM_DT2_A_OUTBYPASS_S 15 -/* MCPWM_DT2_FED_OUTINVERT : R/W ;bitpos:[14] ;default: 1'd0 ; */ -/*description: S3 in documentation*/ -#define MCPWM_DT2_FED_OUTINVERT (BIT(14)) -#define MCPWM_DT2_FED_OUTINVERT_M (BIT(14)) -#define MCPWM_DT2_FED_OUTINVERT_V 0x1 -#define MCPWM_DT2_FED_OUTINVERT_S 14 -/* MCPWM_DT2_RED_OUTINVERT : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: S2 in documentation*/ -#define MCPWM_DT2_RED_OUTINVERT (BIT(13)) -#define MCPWM_DT2_RED_OUTINVERT_M (BIT(13)) -#define MCPWM_DT2_RED_OUTINVERT_V 0x1 -#define MCPWM_DT2_RED_OUTINVERT_S 13 -/* MCPWM_DT2_FED_INSEL : R/W ;bitpos:[12] ;default: 1'd0 ; */ -/*description: S5 in documentation*/ -#define MCPWM_DT2_FED_INSEL (BIT(12)) -#define MCPWM_DT2_FED_INSEL_M (BIT(12)) -#define MCPWM_DT2_FED_INSEL_V 0x1 -#define MCPWM_DT2_FED_INSEL_S 12 -/* MCPWM_DT2_RED_INSEL : R/W ;bitpos:[11] ;default: 1'd0 ; */ -/*description: S4 in documentation*/ -#define MCPWM_DT2_RED_INSEL (BIT(11)) -#define MCPWM_DT2_RED_INSEL_M (BIT(11)) -#define MCPWM_DT2_RED_INSEL_V 0x1 -#define MCPWM_DT2_RED_INSEL_S 11 -/* MCPWM_DT2_B_OUTSWAP : R/W ;bitpos:[10] ;default: 1'd0 ; */ -/*description: S7 in documentation*/ -#define MCPWM_DT2_B_OUTSWAP (BIT(10)) -#define MCPWM_DT2_B_OUTSWAP_M (BIT(10)) -#define MCPWM_DT2_B_OUTSWAP_V 0x1 -#define MCPWM_DT2_B_OUTSWAP_S 10 -/* MCPWM_DT2_A_OUTSWAP : R/W ;bitpos:[9] ;default: 1'd0 ; */ -/*description: S6 in documentation*/ -#define MCPWM_DT2_A_OUTSWAP (BIT(9)) -#define MCPWM_DT2_A_OUTSWAP_M (BIT(9)) -#define MCPWM_DT2_A_OUTSWAP_V 0x1 -#define MCPWM_DT2_A_OUTSWAP_S 9 -/* MCPWM_DT2_DEB_MODE : R/W ;bitpos:[8] ;default: 1'd0 ; */ -/*description: S8 in documentation dual-edge B mode 0: FED/RED take effect - on different path separately 1: FED/RED take effect on B path A out is in bypass or normal operation mode*/ -#define MCPWM_DT2_DEB_MODE (BIT(8)) -#define MCPWM_DT2_DEB_MODE_M (BIT(8)) -#define MCPWM_DT2_DEB_MODE_V 0x1 -#define MCPWM_DT2_DEB_MODE_S 8 -/* MCPWM_DT2_RED_UPMETHOD : R/W ;bitpos:[7:4] ;default: 4'd0 ; */ -/*description: Update method for RED (rising edge delay) active reg. 0: immediate - bit0: TEZ bit1: TEP bit2: sync bit3: disable update*/ -#define MCPWM_DT2_RED_UPMETHOD 0x0000000F -#define MCPWM_DT2_RED_UPMETHOD_M ((MCPWM_DT2_RED_UPMETHOD_V)<<(MCPWM_DT2_RED_UPMETHOD_S)) -#define MCPWM_DT2_RED_UPMETHOD_V 0xF -#define MCPWM_DT2_RED_UPMETHOD_S 4 -/* MCPWM_DT2_FED_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: Update method for FED (falling edge delay) active reg. 0: immediate - bit0: TEZ bit1: TEP bit2: sync bit3: disable update*/ -#define MCPWM_DT2_FED_UPMETHOD 0x0000000F -#define MCPWM_DT2_FED_UPMETHOD_M ((MCPWM_DT2_FED_UPMETHOD_V)<<(MCPWM_DT2_FED_UPMETHOD_S)) -#define MCPWM_DT2_FED_UPMETHOD_V 0xF +/** MCPWM_DT2_CFG_REG register + * PWM generator 2 dead time type selection and configuration + */ +#define MCPWM_DT2_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xc8) +/** MCPWM_DT2_FED_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for FED (falling edge delay) active register. 0: immediate,when bit0 + * is set to 1: tez, when bit1 is set to 1:tep, when bit2 is set to 1: sync, when + * bit3 is set to 1: disable the update + */ +#define MCPWM_DT2_FED_UPMETHOD 0x0000000FU +#define MCPWM_DT2_FED_UPMETHOD_M (MCPWM_DT2_FED_UPMETHOD_V << MCPWM_DT2_FED_UPMETHOD_S) +#define MCPWM_DT2_FED_UPMETHOD_V 0x0000000FU #define MCPWM_DT2_FED_UPMETHOD_S 0 +/** MCPWM_DT2_RED_UPMETHOD : R/W; bitpos: [7:4]; default: 0; + * Update method for RED (rising edge delay) active register. 0: immediate,when bit0 + * is set to 1: tez, when bit1 is set to 1:tep, when bit2 is set to 1: sync, when + * bit3 is set to 1: disable the update + */ +#define MCPWM_DT2_RED_UPMETHOD 0x0000000FU +#define MCPWM_DT2_RED_UPMETHOD_M (MCPWM_DT2_RED_UPMETHOD_V << MCPWM_DT2_RED_UPMETHOD_S) +#define MCPWM_DT2_RED_UPMETHOD_V 0x0000000FU +#define MCPWM_DT2_RED_UPMETHOD_S 4 +/** MCPWM_DT2_DEB_MODE : R/W; bitpos: [8]; default: 0; + * S8 in table, dual-edge B mode, 0: fed/red take effect on different path separately, + * 1: fed/red take effect on B path, A out is in bypass or dulpB mode + */ +#define MCPWM_DT2_DEB_MODE (BIT(8)) +#define MCPWM_DT2_DEB_MODE_M (MCPWM_DT2_DEB_MODE_V << MCPWM_DT2_DEB_MODE_S) +#define MCPWM_DT2_DEB_MODE_V 0x00000001U +#define MCPWM_DT2_DEB_MODE_S 8 +/** MCPWM_DT2_A_OUTSWAP : R/W; bitpos: [9]; default: 0; + * S6 in table + */ +#define MCPWM_DT2_A_OUTSWAP (BIT(9)) +#define MCPWM_DT2_A_OUTSWAP_M (MCPWM_DT2_A_OUTSWAP_V << MCPWM_DT2_A_OUTSWAP_S) +#define MCPWM_DT2_A_OUTSWAP_V 0x00000001U +#define MCPWM_DT2_A_OUTSWAP_S 9 +/** MCPWM_DT2_B_OUTSWAP : R/W; bitpos: [10]; default: 0; + * S7 in table + */ +#define MCPWM_DT2_B_OUTSWAP (BIT(10)) +#define MCPWM_DT2_B_OUTSWAP_M (MCPWM_DT2_B_OUTSWAP_V << MCPWM_DT2_B_OUTSWAP_S) +#define MCPWM_DT2_B_OUTSWAP_V 0x00000001U +#define MCPWM_DT2_B_OUTSWAP_S 10 +/** MCPWM_DT2_RED_INSEL : R/W; bitpos: [11]; default: 0; + * S4 in table + */ +#define MCPWM_DT2_RED_INSEL (BIT(11)) +#define MCPWM_DT2_RED_INSEL_M (MCPWM_DT2_RED_INSEL_V << MCPWM_DT2_RED_INSEL_S) +#define MCPWM_DT2_RED_INSEL_V 0x00000001U +#define MCPWM_DT2_RED_INSEL_S 11 +/** MCPWM_DT2_FED_INSEL : R/W; bitpos: [12]; default: 0; + * S5 in table + */ +#define MCPWM_DT2_FED_INSEL (BIT(12)) +#define MCPWM_DT2_FED_INSEL_M (MCPWM_DT2_FED_INSEL_V << MCPWM_DT2_FED_INSEL_S) +#define MCPWM_DT2_FED_INSEL_V 0x00000001U +#define MCPWM_DT2_FED_INSEL_S 12 +/** MCPWM_DT2_RED_OUTINVERT : R/W; bitpos: [13]; default: 0; + * S2 in table + */ +#define MCPWM_DT2_RED_OUTINVERT (BIT(13)) +#define MCPWM_DT2_RED_OUTINVERT_M (MCPWM_DT2_RED_OUTINVERT_V << MCPWM_DT2_RED_OUTINVERT_S) +#define MCPWM_DT2_RED_OUTINVERT_V 0x00000001U +#define MCPWM_DT2_RED_OUTINVERT_S 13 +/** MCPWM_DT2_FED_OUTINVERT : R/W; bitpos: [14]; default: 0; + * S3 in table + */ +#define MCPWM_DT2_FED_OUTINVERT (BIT(14)) +#define MCPWM_DT2_FED_OUTINVERT_M (MCPWM_DT2_FED_OUTINVERT_V << MCPWM_DT2_FED_OUTINVERT_S) +#define MCPWM_DT2_FED_OUTINVERT_V 0x00000001U +#define MCPWM_DT2_FED_OUTINVERT_S 14 +/** MCPWM_DT2_A_OUTBYPASS : R/W; bitpos: [15]; default: 1; + * S1 in table + */ +#define MCPWM_DT2_A_OUTBYPASS (BIT(15)) +#define MCPWM_DT2_A_OUTBYPASS_M (MCPWM_DT2_A_OUTBYPASS_V << MCPWM_DT2_A_OUTBYPASS_S) +#define MCPWM_DT2_A_OUTBYPASS_V 0x00000001U +#define MCPWM_DT2_A_OUTBYPASS_S 15 +/** MCPWM_DT2_B_OUTBYPASS : R/W; bitpos: [16]; default: 1; + * S0 in table + */ +#define MCPWM_DT2_B_OUTBYPASS (BIT(16)) +#define MCPWM_DT2_B_OUTBYPASS_M (MCPWM_DT2_B_OUTBYPASS_V << MCPWM_DT2_B_OUTBYPASS_S) +#define MCPWM_DT2_B_OUTBYPASS_V 0x00000001U +#define MCPWM_DT2_B_OUTBYPASS_S 16 +/** MCPWM_DT2_CLK_SEL : R/W; bitpos: [17]; default: 0; + * Dead time clock selection. 0: PWM_clk, 1: PT_clk + */ +#define MCPWM_DT2_CLK_SEL (BIT(17)) +#define MCPWM_DT2_CLK_SEL_M (MCPWM_DT2_CLK_SEL_V << MCPWM_DT2_CLK_SEL_S) +#define MCPWM_DT2_CLK_SEL_V 0x00000001U +#define MCPWM_DT2_CLK_SEL_S 17 -#define MCPWM_DT2_FED_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x00cc) -/* MCPWM_DT2_FED : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: Shadow reg for FED*/ -#define MCPWM_DT2_FED 0x0000FFFF -#define MCPWM_DT2_FED_M ((MCPWM_DT2_FED_V)<<(MCPWM_DT2_FED_S)) -#define MCPWM_DT2_FED_V 0xFFFF +/** MCPWM_DT2_FED_CFG_REG register + * PWM generator 2 shadow register for falling edge delay (FED). + */ +#define MCPWM_DT2_FED_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xcc) +/** MCPWM_DT2_FED : R/W; bitpos: [15:0]; default: 0; + * Shadow register for FED + */ +#define MCPWM_DT2_FED 0x0000FFFFU +#define MCPWM_DT2_FED_M (MCPWM_DT2_FED_V << MCPWM_DT2_FED_S) +#define MCPWM_DT2_FED_V 0x0000FFFFU #define MCPWM_DT2_FED_S 0 -#define MCPWM_DT2_RED_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x00d0) -/* MCPWM_DT2_RED : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: Shadow reg for RED*/ -#define MCPWM_DT2_RED 0x0000FFFF -#define MCPWM_DT2_RED_M ((MCPWM_DT2_RED_V)<<(MCPWM_DT2_RED_S)) -#define MCPWM_DT2_RED_V 0xFFFF +/** MCPWM_DT2_RED_CFG_REG register + * PWM generator 2 shadow register for rising edge delay (RED). + */ +#define MCPWM_DT2_RED_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xd0) +/** MCPWM_DT2_RED : R/W; bitpos: [15:0]; default: 0; + * Shadow register for RED + */ +#define MCPWM_DT2_RED 0x0000FFFFU +#define MCPWM_DT2_RED_M (MCPWM_DT2_RED_V << MCPWM_DT2_RED_S) +#define MCPWM_DT2_RED_V 0x0000FFFFU #define MCPWM_DT2_RED_S 0 -#define MCPWM_CARRIER2_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x00d4) -/* MCPWM_CARRIER2_IN_INVERT : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: When set invert the input of PWM2A and PWM2B for this submodule*/ -#define MCPWM_CARRIER2_IN_INVERT (BIT(13)) -#define MCPWM_CARRIER2_IN_INVERT_M (BIT(13)) -#define MCPWM_CARRIER2_IN_INVERT_V 0x1 -#define MCPWM_CARRIER2_IN_INVERT_S 13 -/* MCPWM_CARRIER2_OUT_INVERT : R/W ;bitpos:[12] ;default: 1'd0 ; */ -/*description: When set invert the output of PWM2A and PWM2B for this submodule*/ -#define MCPWM_CARRIER2_OUT_INVERT (BIT(12)) -#define MCPWM_CARRIER2_OUT_INVERT_M (BIT(12)) -#define MCPWM_CARRIER2_OUT_INVERT_V 0x1 -#define MCPWM_CARRIER2_OUT_INVERT_S 12 -/* MCPWM_CARRIER2_OSHWTH : R/W ;bitpos:[11:8] ;default: 4'd0 ; */ -/*description: Width of the fist pulse in number of periods of the carrier*/ -#define MCPWM_CARRIER2_OSHWTH 0x0000000F -#define MCPWM_CARRIER2_OSHWTH_M ((MCPWM_CARRIER2_OSHWTH_V)<<(MCPWM_CARRIER2_OSHWTH_S)) -#define MCPWM_CARRIER2_OSHWTH_V 0xF -#define MCPWM_CARRIER2_OSHWTH_S 8 -/* MCPWM_CARRIER2_DUTY : R/W ;bitpos:[7:5] ;default: 3'd0 ; */ -/*description: Carrier duty selection. Duty = PWM_CARRIER2_DUTY / 8*/ -#define MCPWM_CARRIER2_DUTY 0x00000007 -#define MCPWM_CARRIER2_DUTY_M ((MCPWM_CARRIER2_DUTY_V)<<(MCPWM_CARRIER2_DUTY_S)) -#define MCPWM_CARRIER2_DUTY_V 0x7 -#define MCPWM_CARRIER2_DUTY_S 5 -/* MCPWM_CARRIER2_PRESCALE : R/W ;bitpos:[4:1] ;default: 4'd0 ; */ -/*description: PWM carrier2 clock (PC_clk) prescale value. Period of PC_clk - = period of PWM_clk * (PWM_CARRIER2_PRESCALE + 1)*/ -#define MCPWM_CARRIER2_PRESCALE 0x0000000F -#define MCPWM_CARRIER2_PRESCALE_M ((MCPWM_CARRIER2_PRESCALE_V)<<(MCPWM_CARRIER2_PRESCALE_S)) -#define MCPWM_CARRIER2_PRESCALE_V 0xF -#define MCPWM_CARRIER2_PRESCALE_S 1 -/* MCPWM_CARRIER2_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: When set carrier2 function is enabled. When cleared carrier2 is bypassed*/ -#define MCPWM_CARRIER2_EN (BIT(0)) -#define MCPWM_CARRIER2_EN_M (BIT(0)) -#define MCPWM_CARRIER2_EN_V 0x1 +/** MCPWM_CARRIER2_CFG_REG register + * PWM generator 2 carrier enable and configuratoin + */ +#define MCPWM_CARRIER2_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xd4) +/** MCPWM_CARRIER2_EN : R/W; bitpos: [0]; default: 0; + * When set, carrier2 function is enabled. When cleared, carrier2 is bypassed + */ +#define MCPWM_CARRIER2_EN (BIT(0)) +#define MCPWM_CARRIER2_EN_M (MCPWM_CARRIER2_EN_V << MCPWM_CARRIER2_EN_S) +#define MCPWM_CARRIER2_EN_V 0x00000001U #define MCPWM_CARRIER2_EN_S 0 +/** MCPWM_CARRIER2_PRESCALE : R/W; bitpos: [4:1]; default: 0; + * PWM carrier2 clock (PC_clk) prescale value. Period of PC_clk = period of PWM_clk * + * (PWM_CARRIER0_PRESCALE + 1) + */ +#define MCPWM_CARRIER2_PRESCALE 0x0000000FU +#define MCPWM_CARRIER2_PRESCALE_M (MCPWM_CARRIER2_PRESCALE_V << MCPWM_CARRIER2_PRESCALE_S) +#define MCPWM_CARRIER2_PRESCALE_V 0x0000000FU +#define MCPWM_CARRIER2_PRESCALE_S 1 +/** MCPWM_CARRIER2_DUTY : R/W; bitpos: [7:5]; default: 0; + * carrier duty selection. Duty = PWM_CARRIER0_DUTY / 8 + */ +#define MCPWM_CARRIER2_DUTY 0x00000007U +#define MCPWM_CARRIER2_DUTY_M (MCPWM_CARRIER2_DUTY_V << MCPWM_CARRIER2_DUTY_S) +#define MCPWM_CARRIER2_DUTY_V 0x00000007U +#define MCPWM_CARRIER2_DUTY_S 5 +/** MCPWM_CARRIER2_OSHTWTH : R/W; bitpos: [11:8]; default: 0; + * width of the first pulse in number of periods of the carrier + */ +#define MCPWM_CARRIER2_OSHTWTH 0x0000000FU +#define MCPWM_CARRIER2_OSHTWTH_M (MCPWM_CARRIER2_OSHTWTH_V << MCPWM_CARRIER2_OSHTWTH_S) +#define MCPWM_CARRIER2_OSHTWTH_V 0x0000000FU +#define MCPWM_CARRIER2_OSHTWTH_S 8 +/** MCPWM_CARRIER2_OUT_INVERT : R/W; bitpos: [12]; default: 0; + * when set, invert the output of PWM2A and PWM2B for this submodule + */ +#define MCPWM_CARRIER2_OUT_INVERT (BIT(12)) +#define MCPWM_CARRIER2_OUT_INVERT_M (MCPWM_CARRIER2_OUT_INVERT_V << MCPWM_CARRIER2_OUT_INVERT_S) +#define MCPWM_CARRIER2_OUT_INVERT_V 0x00000001U +#define MCPWM_CARRIER2_OUT_INVERT_S 12 +/** MCPWM_CARRIER2_IN_INVERT : R/W; bitpos: [13]; default: 0; + * when set, invert the input of PWM2A and PWM2B for this submodule + */ +#define MCPWM_CARRIER2_IN_INVERT (BIT(13)) +#define MCPWM_CARRIER2_IN_INVERT_M (MCPWM_CARRIER2_IN_INVERT_V << MCPWM_CARRIER2_IN_INVERT_S) +#define MCPWM_CARRIER2_IN_INVERT_V 0x00000001U +#define MCPWM_CARRIER2_IN_INVERT_S 13 -#define MCPWM_FH2_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0x00d8) -/* MCPWM_FH2_B_OST_U : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: One-shot mode action on PWM2B when fault event occurs and timer - is increasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH2_B_OST_U 0x00000003 -#define MCPWM_FH2_B_OST_U_M ((MCPWM_FH2_B_OST_U_V)<<(MCPWM_FH2_B_OST_U_S)) -#define MCPWM_FH2_B_OST_U_V 0x3 -#define MCPWM_FH2_B_OST_U_S 22 -/* MCPWM_FH2_B_OST_D : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: One-shot mode action on PWM2B when fault event occurs and timer - is decreasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH2_B_OST_D 0x00000003 -#define MCPWM_FH2_B_OST_D_M ((MCPWM_FH2_B_OST_D_V)<<(MCPWM_FH2_B_OST_D_S)) -#define MCPWM_FH2_B_OST_D_V 0x3 -#define MCPWM_FH2_B_OST_D_S 20 -/* MCPWM_FH2_B_CBC_U : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: Cycle-by-cycle mode action on PWM2B when fault event occurs and - timer is increasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH2_B_CBC_U 0x00000003 -#define MCPWM_FH2_B_CBC_U_M ((MCPWM_FH2_B_CBC_U_V)<<(MCPWM_FH2_B_CBC_U_S)) -#define MCPWM_FH2_B_CBC_U_V 0x3 -#define MCPWM_FH2_B_CBC_U_S 18 -/* MCPWM_FH2_B_CBC_D : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: Cycle-by-cycle mode action on PWM2B when fault event occurs and - timer is decreasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH2_B_CBC_D 0x00000003 -#define MCPWM_FH2_B_CBC_D_M ((MCPWM_FH2_B_CBC_D_V)<<(MCPWM_FH2_B_CBC_D_S)) -#define MCPWM_FH2_B_CBC_D_V 0x3 -#define MCPWM_FH2_B_CBC_D_S 16 -/* MCPWM_FH2_A_OST_U : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: One-shot mode action on PWM2A when fault event occurs and timer - is increasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH2_A_OST_U 0x00000003 -#define MCPWM_FH2_A_OST_U_M ((MCPWM_FH2_A_OST_U_V)<<(MCPWM_FH2_A_OST_U_S)) -#define MCPWM_FH2_A_OST_U_V 0x3 -#define MCPWM_FH2_A_OST_U_S 14 -/* MCPWM_FH2_A_OST_D : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: One-shot mode action on PWM2A when fault event occurs and timer - is decreasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH2_A_OST_D 0x00000003 -#define MCPWM_FH2_A_OST_D_M ((MCPWM_FH2_A_OST_D_V)<<(MCPWM_FH2_A_OST_D_S)) -#define MCPWM_FH2_A_OST_D_V 0x3 -#define MCPWM_FH2_A_OST_D_S 12 -/* MCPWM_FH2_A_CBC_U : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: Cycle-by-cycle mode action on PWM2A when fault event occurs and - timer is increasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH2_A_CBC_U 0x00000003 -#define MCPWM_FH2_A_CBC_U_M ((MCPWM_FH2_A_CBC_U_V)<<(MCPWM_FH2_A_CBC_U_S)) -#define MCPWM_FH2_A_CBC_U_V 0x3 -#define MCPWM_FH2_A_CBC_U_S 10 -/* MCPWM_FH2_A_CBC_D : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: Cycle-by-cycle mode action on PWM2A when fault event occurs and - timer is decreasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ -#define MCPWM_FH2_A_CBC_D 0x00000003 -#define MCPWM_FH2_A_CBC_D_M ((MCPWM_FH2_A_CBC_D_V)<<(MCPWM_FH2_A_CBC_D_S)) -#define MCPWM_FH2_A_CBC_D_V 0x3 -#define MCPWM_FH2_A_CBC_D_S 8 -/* MCPWM_FH2_F0_OST : R/W ;bitpos:[7] ;default: 1'd0 ; */ -/*description: event_f0 will trigger one-shot mode action. 0: disable 1: enable*/ -#define MCPWM_FH2_F0_OST (BIT(7)) -#define MCPWM_FH2_F0_OST_M (BIT(7)) -#define MCPWM_FH2_F0_OST_V 0x1 -#define MCPWM_FH2_F0_OST_S 7 -/* MCPWM_FH2_F1_OST : R/W ;bitpos:[6] ;default: 1'd0 ; */ -/*description: event_f1 will trigger one-shot mode action. 0: disable 1: enable*/ -#define MCPWM_FH2_F1_OST (BIT(6)) -#define MCPWM_FH2_F1_OST_M (BIT(6)) -#define MCPWM_FH2_F1_OST_V 0x1 -#define MCPWM_FH2_F1_OST_S 6 -/* MCPWM_FH2_F2_OST : R/W ;bitpos:[5] ;default: 1'd0 ; */ -/*description: event_f2 will trigger one-shot mode action. 0: disable 1: enable*/ -#define MCPWM_FH2_F2_OST (BIT(5)) -#define MCPWM_FH2_F2_OST_M (BIT(5)) -#define MCPWM_FH2_F2_OST_V 0x1 -#define MCPWM_FH2_F2_OST_S 5 -/* MCPWM_FH2_SW_OST : R/W ;bitpos:[4] ;default: 1'd0 ; */ -/*description: Enable register for software force one-shot mode action. 0: disable 1: enable*/ -#define MCPWM_FH2_SW_OST (BIT(4)) -#define MCPWM_FH2_SW_OST_M (BIT(4)) -#define MCPWM_FH2_SW_OST_V 0x1 -#define MCPWM_FH2_SW_OST_S 4 -/* MCPWM_FH2_F0_CBC : R/W ;bitpos:[3] ;default: 1'd0 ; */ -/*description: event_f0 will trigger cycle-by-cycle mode action. 0: disable 1: enable*/ -#define MCPWM_FH2_F0_CBC (BIT(3)) -#define MCPWM_FH2_F0_CBC_M (BIT(3)) -#define MCPWM_FH2_F0_CBC_V 0x1 -#define MCPWM_FH2_F0_CBC_S 3 -/* MCPWM_FH2_F1_CBC : R/W ;bitpos:[2] ;default: 1'd0 ; */ -/*description: event_f1 will trigger cycle-by-cycle mode action. 0: disable 1: enable*/ -#define MCPWM_FH2_F1_CBC (BIT(2)) -#define MCPWM_FH2_F1_CBC_M (BIT(2)) -#define MCPWM_FH2_F1_CBC_V 0x1 -#define MCPWM_FH2_F1_CBC_S 2 -/* MCPWM_FH2_F2_CBC : R/W ;bitpos:[1] ;default: 1'd0 ; */ -/*description: event_f2 will trigger cycle-by-cycle mode action. 0: disable 1: enable*/ -#define MCPWM_FH2_F2_CBC (BIT(1)) -#define MCPWM_FH2_F2_CBC_M (BIT(1)) -#define MCPWM_FH2_F2_CBC_V 0x1 -#define MCPWM_FH2_F2_CBC_S 1 -/* MCPWM_FH2_SW_CBC : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: Enable register for software force cycle-by-cycle mode action. - 0: disable 1: enable*/ -#define MCPWM_FH2_SW_CBC (BIT(0)) -#define MCPWM_FH2_SW_CBC_M (BIT(0)) -#define MCPWM_FH2_SW_CBC_V 0x1 +/** MCPWM_FH2_CFG0_REG register + * Actions on PWM2A and PWM2B trip events + */ +#define MCPWM_FH2_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0xd8) +/** MCPWM_FH2_SW_CBC : R/W; bitpos: [0]; default: 0; + * Enable register for software force cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH2_SW_CBC (BIT(0)) +#define MCPWM_FH2_SW_CBC_M (MCPWM_FH2_SW_CBC_V << MCPWM_FH2_SW_CBC_S) +#define MCPWM_FH2_SW_CBC_V 0x00000001U #define MCPWM_FH2_SW_CBC_S 0 +/** MCPWM_FH2_F2_CBC : R/W; bitpos: [1]; default: 0; + * fault_event2 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH2_F2_CBC (BIT(1)) +#define MCPWM_FH2_F2_CBC_M (MCPWM_FH2_F2_CBC_V << MCPWM_FH2_F2_CBC_S) +#define MCPWM_FH2_F2_CBC_V 0x00000001U +#define MCPWM_FH2_F2_CBC_S 1 +/** MCPWM_FH2_F1_CBC : R/W; bitpos: [2]; default: 0; + * fault_event1 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH2_F1_CBC (BIT(2)) +#define MCPWM_FH2_F1_CBC_M (MCPWM_FH2_F1_CBC_V << MCPWM_FH2_F1_CBC_S) +#define MCPWM_FH2_F1_CBC_V 0x00000001U +#define MCPWM_FH2_F1_CBC_S 2 +/** MCPWM_FH2_F0_CBC : R/W; bitpos: [3]; default: 0; + * fault_event0 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH2_F0_CBC (BIT(3)) +#define MCPWM_FH2_F0_CBC_M (MCPWM_FH2_F0_CBC_V << MCPWM_FH2_F0_CBC_S) +#define MCPWM_FH2_F0_CBC_V 0x00000001U +#define MCPWM_FH2_F0_CBC_S 3 +/** MCPWM_FH2_SW_OST : R/W; bitpos: [4]; default: 0; + * Enable register for software force one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH2_SW_OST (BIT(4)) +#define MCPWM_FH2_SW_OST_M (MCPWM_FH2_SW_OST_V << MCPWM_FH2_SW_OST_S) +#define MCPWM_FH2_SW_OST_V 0x00000001U +#define MCPWM_FH2_SW_OST_S 4 +/** MCPWM_FH2_F2_OST : R/W; bitpos: [5]; default: 0; + * fault_event2 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH2_F2_OST (BIT(5)) +#define MCPWM_FH2_F2_OST_M (MCPWM_FH2_F2_OST_V << MCPWM_FH2_F2_OST_S) +#define MCPWM_FH2_F2_OST_V 0x00000001U +#define MCPWM_FH2_F2_OST_S 5 +/** MCPWM_FH2_F1_OST : R/W; bitpos: [6]; default: 0; + * fault_event1 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH2_F1_OST (BIT(6)) +#define MCPWM_FH2_F1_OST_M (MCPWM_FH2_F1_OST_V << MCPWM_FH2_F1_OST_S) +#define MCPWM_FH2_F1_OST_V 0x00000001U +#define MCPWM_FH2_F1_OST_S 6 +/** MCPWM_FH2_F0_OST : R/W; bitpos: [7]; default: 0; + * fault_event0 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH2_F0_OST (BIT(7)) +#define MCPWM_FH2_F0_OST_M (MCPWM_FH2_F0_OST_V << MCPWM_FH2_F0_OST_S) +#define MCPWM_FH2_F0_OST_V 0x00000001U +#define MCPWM_FH2_F0_OST_S 7 +/** MCPWM_FH2_A_CBC_D : R/W; bitpos: [9:8]; default: 0; + * Cycle-by-cycle mode action on PWM2A when fault event occurs and timer is + * decreasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH2_A_CBC_D 0x00000003U +#define MCPWM_FH2_A_CBC_D_M (MCPWM_FH2_A_CBC_D_V << MCPWM_FH2_A_CBC_D_S) +#define MCPWM_FH2_A_CBC_D_V 0x00000003U +#define MCPWM_FH2_A_CBC_D_S 8 +/** MCPWM_FH2_A_CBC_U : R/W; bitpos: [11:10]; default: 0; + * Cycle-by-cycle mode action on PWM2A when fault event occurs and timer is + * increasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH2_A_CBC_U 0x00000003U +#define MCPWM_FH2_A_CBC_U_M (MCPWM_FH2_A_CBC_U_V << MCPWM_FH2_A_CBC_U_S) +#define MCPWM_FH2_A_CBC_U_V 0x00000003U +#define MCPWM_FH2_A_CBC_U_S 10 +/** MCPWM_FH2_A_OST_D : R/W; bitpos: [13:12]; default: 0; + * One-shot mode action on PWM2A when fault event occurs and timer is decreasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH2_A_OST_D 0x00000003U +#define MCPWM_FH2_A_OST_D_M (MCPWM_FH2_A_OST_D_V << MCPWM_FH2_A_OST_D_S) +#define MCPWM_FH2_A_OST_D_V 0x00000003U +#define MCPWM_FH2_A_OST_D_S 12 +/** MCPWM_FH2_A_OST_U : R/W; bitpos: [15:14]; default: 0; + * One-shot mode action on PWM2A when fault event occurs and timer is increasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH2_A_OST_U 0x00000003U +#define MCPWM_FH2_A_OST_U_M (MCPWM_FH2_A_OST_U_V << MCPWM_FH2_A_OST_U_S) +#define MCPWM_FH2_A_OST_U_V 0x00000003U +#define MCPWM_FH2_A_OST_U_S 14 +/** MCPWM_FH2_B_CBC_D : R/W; bitpos: [17:16]; default: 0; + * Cycle-by-cycle mode action on PWM2B when fault event occurs and timer is + * decreasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH2_B_CBC_D 0x00000003U +#define MCPWM_FH2_B_CBC_D_M (MCPWM_FH2_B_CBC_D_V << MCPWM_FH2_B_CBC_D_S) +#define MCPWM_FH2_B_CBC_D_V 0x00000003U +#define MCPWM_FH2_B_CBC_D_S 16 +/** MCPWM_FH2_B_CBC_U : R/W; bitpos: [19:18]; default: 0; + * Cycle-by-cycle mode action on PWM2B when fault event occurs and timer is + * increasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH2_B_CBC_U 0x00000003U +#define MCPWM_FH2_B_CBC_U_M (MCPWM_FH2_B_CBC_U_V << MCPWM_FH2_B_CBC_U_S) +#define MCPWM_FH2_B_CBC_U_V 0x00000003U +#define MCPWM_FH2_B_CBC_U_S 18 +/** MCPWM_FH2_B_OST_D : R/W; bitpos: [21:20]; default: 0; + * One-shot mode action on PWM2B when fault event occurs and timer is decreasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH2_B_OST_D 0x00000003U +#define MCPWM_FH2_B_OST_D_M (MCPWM_FH2_B_OST_D_V << MCPWM_FH2_B_OST_D_S) +#define MCPWM_FH2_B_OST_D_V 0x00000003U +#define MCPWM_FH2_B_OST_D_S 20 +/** MCPWM_FH2_B_OST_U : R/W; bitpos: [23:22]; default: 0; + * One-shot mode action on PWM2B when fault event occurs and timer is increasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH2_B_OST_U 0x00000003U +#define MCPWM_FH2_B_OST_U_M (MCPWM_FH2_B_OST_U_V << MCPWM_FH2_B_OST_U_S) +#define MCPWM_FH2_B_OST_U_V 0x00000003U +#define MCPWM_FH2_B_OST_U_S 22 -#define MCPWM_FH2_CFG1_REG(i) (REG_MCPWM_BASE(i) + 0x00dc) -/* MCPWM_FH2_FORCE_OST : R/W ;bitpos:[4] ;default: 1'd0 ; */ -/*description: A toggle (software negation of value of this bit) triggers a - one-shot mode action*/ -#define MCPWM_FH2_FORCE_OST (BIT(4)) -#define MCPWM_FH2_FORCE_OST_M (BIT(4)) -#define MCPWM_FH2_FORCE_OST_V 0x1 -#define MCPWM_FH2_FORCE_OST_S 4 -/* MCPWM_FH2_FORCE_CBC : R/W ;bitpos:[3] ;default: 1'd0 ; */ -/*description: A toggle triggers a cycle-by-cycle mode action*/ -#define MCPWM_FH2_FORCE_CBC (BIT(3)) -#define MCPWM_FH2_FORCE_CBC_M (BIT(3)) -#define MCPWM_FH2_FORCE_CBC_V 0x1 -#define MCPWM_FH2_FORCE_CBC_S 3 -/* MCPWM_FH2_CBCPULSE : R/W ;bitpos:[2:1] ;default: 2'd0 ; */ -/*description: The cycle-by-cycle mode action refresh moment selection. Bit0: TEZ bit1:TEP*/ -#define MCPWM_FH2_CBCPULSE 0x00000003 -#define MCPWM_FH2_CBCPULSE_M ((MCPWM_FH2_CBCPULSE_V)<<(MCPWM_FH2_CBCPULSE_S)) -#define MCPWM_FH2_CBCPULSE_V 0x3 -#define MCPWM_FH2_CBCPULSE_S 1 -/* MCPWM_FH2_CLR_OST : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: A toggle will clear on going one-shot mode action*/ -#define MCPWM_FH2_CLR_OST (BIT(0)) -#define MCPWM_FH2_CLR_OST_M (BIT(0)) -#define MCPWM_FH2_CLR_OST_V 0x1 +/** MCPWM_FH2_CFG1_REG register + * Software triggers for fault handler actions + */ +#define MCPWM_FH2_CFG1_REG(i) (DR_REG_MCPWM_BASE(i) + 0xdc) +/** MCPWM_FH2_CLR_OST : R/W; bitpos: [0]; default: 0; + * a rising edge will clear on going one-shot mode action + */ +#define MCPWM_FH2_CLR_OST (BIT(0)) +#define MCPWM_FH2_CLR_OST_M (MCPWM_FH2_CLR_OST_V << MCPWM_FH2_CLR_OST_S) +#define MCPWM_FH2_CLR_OST_V 0x00000001U #define MCPWM_FH2_CLR_OST_S 0 +/** MCPWM_FH2_CBCPULSE : R/W; bitpos: [2:1]; default: 0; + * cycle-by-cycle mode action refresh moment selection. When bit0 is set to 1: TEZ, + * when bit1 is set to 1:TEP + */ +#define MCPWM_FH2_CBCPULSE 0x00000003U +#define MCPWM_FH2_CBCPULSE_M (MCPWM_FH2_CBCPULSE_V << MCPWM_FH2_CBCPULSE_S) +#define MCPWM_FH2_CBCPULSE_V 0x00000003U +#define MCPWM_FH2_CBCPULSE_S 1 +/** MCPWM_FH2_FORCE_CBC : R/W; bitpos: [3]; default: 0; + * a toggle trigger a cycle-by-cycle mode action + */ +#define MCPWM_FH2_FORCE_CBC (BIT(3)) +#define MCPWM_FH2_FORCE_CBC_M (MCPWM_FH2_FORCE_CBC_V << MCPWM_FH2_FORCE_CBC_S) +#define MCPWM_FH2_FORCE_CBC_V 0x00000001U +#define MCPWM_FH2_FORCE_CBC_S 3 +/** MCPWM_FH2_FORCE_OST : R/W; bitpos: [4]; default: 0; + * a toggle (software negate its value) triggers a one-shot mode action + */ +#define MCPWM_FH2_FORCE_OST (BIT(4)) +#define MCPWM_FH2_FORCE_OST_M (MCPWM_FH2_FORCE_OST_V << MCPWM_FH2_FORCE_OST_S) +#define MCPWM_FH2_FORCE_OST_V 0x00000001U +#define MCPWM_FH2_FORCE_OST_S 4 -#define MCPWM_FH2_STATUS_REG(i) (REG_MCPWM_BASE(i) + 0x00e0) -/* MCPWM_FH2_OST_ON : RO ;bitpos:[1] ;default: 1'd0 ; */ -/*description: Set and reset by hardware. If set an one-shot mode action is on going*/ -#define MCPWM_FH2_OST_ON (BIT(1)) -#define MCPWM_FH2_OST_ON_M (BIT(1)) -#define MCPWM_FH2_OST_ON_V 0x1 -#define MCPWM_FH2_OST_ON_S 1 -/* MCPWM_FH2_CBC_ON : RO ;bitpos:[0] ;default: 1'd0 ; */ -/*description: Set and reset by hardware. If set an cycle-by-cycle mode action is on going*/ -#define MCPWM_FH2_CBC_ON (BIT(0)) -#define MCPWM_FH2_CBC_ON_M (BIT(0)) -#define MCPWM_FH2_CBC_ON_V 0x1 +/** MCPWM_FH2_STATUS_REG register + * Status of fault events. + */ +#define MCPWM_FH2_STATUS_REG(i) (DR_REG_MCPWM_BASE(i) + 0xe0) +/** MCPWM_FH2_CBC_ON : RO; bitpos: [0]; default: 0; + * Set and reset by hardware. If set, a cycle-by-cycle mode action is on going + */ +#define MCPWM_FH2_CBC_ON (BIT(0)) +#define MCPWM_FH2_CBC_ON_M (MCPWM_FH2_CBC_ON_V << MCPWM_FH2_CBC_ON_S) +#define MCPWM_FH2_CBC_ON_V 0x00000001U #define MCPWM_FH2_CBC_ON_S 0 +/** MCPWM_FH2_OST_ON : RO; bitpos: [1]; default: 0; + * Set and reset by hardware. If set, an one-shot mode action is on going + */ +#define MCPWM_FH2_OST_ON (BIT(1)) +#define MCPWM_FH2_OST_ON_M (MCPWM_FH2_OST_ON_V << MCPWM_FH2_OST_ON_S) +#define MCPWM_FH2_OST_ON_V 0x00000001U +#define MCPWM_FH2_OST_ON_S 1 -#define MCPWM_FAULT_DETECT_REG(i) (REG_MCPWM_BASE(i) + 0x00e4) -/* MCPWM_EVENT_F2 : RO ;bitpos:[8] ;default: 1'd0 ; */ -/*description: Set and reset by hardware. If set event_f2 is on going*/ -#define MCPWM_EVENT_F2 (BIT(8)) -#define MCPWM_EVENT_F2_M (BIT(8)) -#define MCPWM_EVENT_F2_V 0x1 -#define MCPWM_EVENT_F2_S 8 -/* MCPWM_EVENT_F1 : RO ;bitpos:[7] ;default: 1'd0 ; */ -/*description: Set and reset by hardware. If set event_f1 is on going*/ -#define MCPWM_EVENT_F1 (BIT(7)) -#define MCPWM_EVENT_F1_M (BIT(7)) -#define MCPWM_EVENT_F1_V 0x1 -#define MCPWM_EVENT_F1_S 7 -/* MCPWM_EVENT_F0 : RO ;bitpos:[6] ;default: 1'd0 ; */ -/*description: Set and reset by hardware. If set event_f0 is on going*/ -#define MCPWM_EVENT_F0 (BIT(6)) -#define MCPWM_EVENT_F0_M (BIT(6)) -#define MCPWM_EVENT_F0_V 0x1 -#define MCPWM_EVENT_F0_S 6 -/* MCPWM_F2_POLE : R/W ;bitpos:[5] ;default: 1'd0 ; */ -/*description: Set event_f2 trigger polarity on FAULT2 source from GPIO matrix. - 0: level low 1: level high*/ -#define MCPWM_F2_POLE (BIT(5)) -#define MCPWM_F2_POLE_M (BIT(5)) -#define MCPWM_F2_POLE_V 0x1 -#define MCPWM_F2_POLE_S 5 -/* MCPWM_F1_POLE : R/W ;bitpos:[4] ;default: 1'd0 ; */ -/*description: Set event_f1 trigger polarity on FAULT2 source from GPIO matrix. - 0: level low 1: level high*/ -#define MCPWM_F1_POLE (BIT(4)) -#define MCPWM_F1_POLE_M (BIT(4)) -#define MCPWM_F1_POLE_V 0x1 -#define MCPWM_F1_POLE_S 4 -/* MCPWM_F0_POLE : R/W ;bitpos:[3] ;default: 1'd0 ; */ -/*description: Set event_f0 trigger polarity on FAULT2 source from GPIO matrix. - 0: level low 1: level high*/ -#define MCPWM_F0_POLE (BIT(3)) -#define MCPWM_F0_POLE_M (BIT(3)) -#define MCPWM_F0_POLE_V 0x1 -#define MCPWM_F0_POLE_S 3 -/* MCPWM_F2_EN : R/W ;bitpos:[2] ;default: 1'd0 ; */ -/*description: Set to enable generation of event_f2*/ -#define MCPWM_F2_EN (BIT(2)) -#define MCPWM_F2_EN_M (BIT(2)) -#define MCPWM_F2_EN_V 0x1 -#define MCPWM_F2_EN_S 2 -/* MCPWM_F1_EN : R/W ;bitpos:[1] ;default: 1'd0 ; */ -/*description: Set to enable generation of event_f1*/ -#define MCPWM_F1_EN (BIT(1)) -#define MCPWM_F1_EN_M (BIT(1)) -#define MCPWM_F1_EN_V 0x1 -#define MCPWM_F1_EN_S 1 -/* MCPWM_F0_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: Set to enable generation of event_f0*/ -#define MCPWM_F0_EN (BIT(0)) -#define MCPWM_F0_EN_M (BIT(0)) -#define MCPWM_F0_EN_V 0x1 +/** MCPWM_FAULT_DETECT_REG register + * Fault detection configuration and status + */ +#define MCPWM_FAULT_DETECT_REG(i) (DR_REG_MCPWM_BASE(i) + 0xe4) +/** MCPWM_F0_EN : R/W; bitpos: [0]; default: 0; + * When set, fault_event0 generation is enabled + */ +#define MCPWM_F0_EN (BIT(0)) +#define MCPWM_F0_EN_M (MCPWM_F0_EN_V << MCPWM_F0_EN_S) +#define MCPWM_F0_EN_V 0x00000001U #define MCPWM_F0_EN_S 0 +/** MCPWM_F1_EN : R/W; bitpos: [1]; default: 0; + * When set, fault_event1 generation is enabled + */ +#define MCPWM_F1_EN (BIT(1)) +#define MCPWM_F1_EN_M (MCPWM_F1_EN_V << MCPWM_F1_EN_S) +#define MCPWM_F1_EN_V 0x00000001U +#define MCPWM_F1_EN_S 1 +/** MCPWM_F2_EN : R/W; bitpos: [2]; default: 0; + * When set, fault_event2 generation is enabled + */ +#define MCPWM_F2_EN (BIT(2)) +#define MCPWM_F2_EN_M (MCPWM_F2_EN_V << MCPWM_F2_EN_S) +#define MCPWM_F2_EN_V 0x00000001U +#define MCPWM_F2_EN_S 2 +/** MCPWM_F0_POLE : R/W; bitpos: [3]; default: 0; + * Set fault_event0 trigger polarity on FAULT2 source from GPIO matrix. 0: level low, + * 1: level high + */ +#define MCPWM_F0_POLE (BIT(3)) +#define MCPWM_F0_POLE_M (MCPWM_F0_POLE_V << MCPWM_F0_POLE_S) +#define MCPWM_F0_POLE_V 0x00000001U +#define MCPWM_F0_POLE_S 3 +/** MCPWM_F1_POLE : R/W; bitpos: [4]; default: 0; + * Set fault_event1 trigger polarity on FAULT2 source from GPIO matrix. 0: level low, + * 1: level high + */ +#define MCPWM_F1_POLE (BIT(4)) +#define MCPWM_F1_POLE_M (MCPWM_F1_POLE_V << MCPWM_F1_POLE_S) +#define MCPWM_F1_POLE_V 0x00000001U +#define MCPWM_F1_POLE_S 4 +/** MCPWM_F2_POLE : R/W; bitpos: [5]; default: 0; + * Set fault_event2 trigger polarity on FAULT2 source from GPIO matrix. 0: level low, + * 1: level high + */ +#define MCPWM_F2_POLE (BIT(5)) +#define MCPWM_F2_POLE_M (MCPWM_F2_POLE_V << MCPWM_F2_POLE_S) +#define MCPWM_F2_POLE_V 0x00000001U +#define MCPWM_F2_POLE_S 5 +/** MCPWM_EVENT_F0 : RO; bitpos: [6]; default: 0; + * Set and reset by hardware. If set, fault_event0 is on going + */ +#define MCPWM_EVENT_F0 (BIT(6)) +#define MCPWM_EVENT_F0_M (MCPWM_EVENT_F0_V << MCPWM_EVENT_F0_S) +#define MCPWM_EVENT_F0_V 0x00000001U +#define MCPWM_EVENT_F0_S 6 +/** MCPWM_EVENT_F1 : RO; bitpos: [7]; default: 0; + * Set and reset by hardware. If set, fault_event1 is on going + */ +#define MCPWM_EVENT_F1 (BIT(7)) +#define MCPWM_EVENT_F1_M (MCPWM_EVENT_F1_V << MCPWM_EVENT_F1_S) +#define MCPWM_EVENT_F1_V 0x00000001U +#define MCPWM_EVENT_F1_S 7 +/** MCPWM_EVENT_F2 : RO; bitpos: [8]; default: 0; + * Set and reset by hardware. If set, fault_event2 is on going + */ +#define MCPWM_EVENT_F2 (BIT(8)) +#define MCPWM_EVENT_F2_M (MCPWM_EVENT_F2_V << MCPWM_EVENT_F2_S) +#define MCPWM_EVENT_F2_V 0x00000001U +#define MCPWM_EVENT_F2_S 8 -#define MCPWM_CAP_TIMER_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x00e8) -/* MCPWM_CAP_SYNC_SW : WO ;bitpos:[5] ;default: 1'd0 ; */ -/*description: Set this bit to force a capture timer sync capture timer is - loaded with value in phase register.*/ -#define MCPWM_CAP_SYNC_SW (BIT(5)) -#define MCPWM_CAP_SYNC_SW_M (BIT(5)) -#define MCPWM_CAP_SYNC_SW_V 0x1 -#define MCPWM_CAP_SYNC_SW_S 5 -/* MCPWM_CAP_SYNCI_SEL : R/W ;bitpos:[4:2] ;default: 3'd0 ; */ -/*description: Capture module sync input selection. 0: none 1: timer0 synco - 2: timer1 synco 3: timer2 synco 4: SYNC0 from GPIO matrix 5: SYNC1 from GPIO matrix 6: SYNC2 from GPIO matrix*/ -#define MCPWM_CAP_SYNCI_SEL 0x00000007 -#define MCPWM_CAP_SYNCI_SEL_M ((MCPWM_CAP_SYNCI_SEL_V)<<(MCPWM_CAP_SYNCI_SEL_S)) -#define MCPWM_CAP_SYNCI_SEL_V 0x7 -#define MCPWM_CAP_SYNCI_SEL_S 2 -/* MCPWM_CAP_SYNCI_EN : R/W ;bitpos:[1] ;default: 1'd0 ; */ -/*description: When set capture timer sync is enabled.*/ -#define MCPWM_CAP_SYNCI_EN (BIT(1)) -#define MCPWM_CAP_SYNCI_EN_M (BIT(1)) -#define MCPWM_CAP_SYNCI_EN_V 0x1 -#define MCPWM_CAP_SYNCI_EN_S 1 -/* MCPWM_CAP_TIMER_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: When set capture timer incrementing under APB_clk is enabled.*/ -#define MCPWM_CAP_TIMER_EN (BIT(0)) -#define MCPWM_CAP_TIMER_EN_M (BIT(0)) -#define MCPWM_CAP_TIMER_EN_V 0x1 +/** MCPWM_CAP_TIMER_CFG_REG register + * Configure capture timer + */ +#define MCPWM_CAP_TIMER_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xe8) +/** MCPWM_CAP_TIMER_EN : R/W; bitpos: [0]; default: 0; + * When set, capture timer incrementing under APB_clk is enabled. + */ +#define MCPWM_CAP_TIMER_EN (BIT(0)) +#define MCPWM_CAP_TIMER_EN_M (MCPWM_CAP_TIMER_EN_V << MCPWM_CAP_TIMER_EN_S) +#define MCPWM_CAP_TIMER_EN_V 0x00000001U #define MCPWM_CAP_TIMER_EN_S 0 +/** MCPWM_CAP_SYNCI_EN : R/W; bitpos: [1]; default: 0; + * When set, capture timer sync is enabled. + */ +#define MCPWM_CAP_SYNCI_EN (BIT(1)) +#define MCPWM_CAP_SYNCI_EN_M (MCPWM_CAP_SYNCI_EN_V << MCPWM_CAP_SYNCI_EN_S) +#define MCPWM_CAP_SYNCI_EN_V 0x00000001U +#define MCPWM_CAP_SYNCI_EN_S 1 +/** MCPWM_CAP_SYNCI_SEL : R/W; bitpos: [4:2]; default: 0; + * capture module sync input selection. 0: none, 1: timer0 sync_out, 2: timer1 + * sync_out, 3: timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, + * 6: SYNC2 from GPIO matrix + */ +#define MCPWM_CAP_SYNCI_SEL 0x00000007U +#define MCPWM_CAP_SYNCI_SEL_M (MCPWM_CAP_SYNCI_SEL_V << MCPWM_CAP_SYNCI_SEL_S) +#define MCPWM_CAP_SYNCI_SEL_V 0x00000007U +#define MCPWM_CAP_SYNCI_SEL_S 2 +/** MCPWM_CAP_SYNC_SW : WT; bitpos: [5]; default: 0; + * When reg_cap_synci_en is 1, write 1 will trigger a capture timer sync, capture + * timer is loaded with value in phase register. + */ +#define MCPWM_CAP_SYNC_SW (BIT(5)) +#define MCPWM_CAP_SYNC_SW_M (MCPWM_CAP_SYNC_SW_V << MCPWM_CAP_SYNC_SW_S) +#define MCPWM_CAP_SYNC_SW_V 0x00000001U +#define MCPWM_CAP_SYNC_SW_S 5 -#define MCPWM_CAP_TIMER_PHASE_REG(i) (REG_MCPWM_BASE(i) + 0x00ec) -/* MCPWM_CAP_PHASE : R/W ;bitpos:[31:0] ;default: 32'd0 ; */ -/*description: Phase value for capture timer sync operation.*/ -#define MCPWM_CAP_PHASE 0xFFFFFFFF -#define MCPWM_CAP_PHASE_M ((MCPWM_CAP_PHASE_V)<<(MCPWM_CAP_PHASE_S)) -#define MCPWM_CAP_PHASE_V 0xFFFFFFFF -#define MCPWM_CAP_PHASE_S 0 +/** MCPWM_CAP_TIMER_PHASE_REG register + * Phase for capture timer sync + */ +#define MCPWM_CAP_TIMER_PHASE_REG(i) (DR_REG_MCPWM_BASE(i) + 0xec) +/** MCPWM_CAP_TIMER_PHASE : R/W; bitpos: [31:0]; default: 0; + * Phase value for capture timer sync operation. + */ +#define MCPWM_CAP_TIMER_PHASE 0xFFFFFFFFU +#define MCPWM_CAP_TIMER_PHASE_M (MCPWM_CAP_TIMER_PHASE_V << MCPWM_CAP_TIMER_PHASE_S) +#define MCPWM_CAP_TIMER_PHASE_V 0xFFFFFFFFU +#define MCPWM_CAP_TIMER_PHASE_S 0 -#define MCPWM_CAP_CH0_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x00f0) -/* MCPWM_CAP0_SW : WO ;bitpos:[12] ;default: 1'd0 ; */ -/*description: Write 1 will trigger a software forced capture on channel 0*/ -#define MCPWM_CAP0_SW (BIT(12)) -#define MCPWM_CAP0_SW_M (BIT(12)) -#define MCPWM_CAP0_SW_V 0x1 -#define MCPWM_CAP0_SW_S 12 -/* MCPWM_CAP0_IN_INVERT : R/W ;bitpos:[11] ;default: 1'd0 ; */ -/*description: When set CAP0 form GPIO matrix is inverted before prescale*/ -#define MCPWM_CAP0_IN_INVERT (BIT(11)) -#define MCPWM_CAP0_IN_INVERT_M (BIT(11)) -#define MCPWM_CAP0_IN_INVERT_V 0x1 -#define MCPWM_CAP0_IN_INVERT_S 11 -/* MCPWM_CAP0_PRESCALE : R/W ;bitpos:[10:3] ;default: 8'd0 ; */ -/*description: Value of prescale on possitive edge of CAP0. Prescale value = - PWM_CAP0_PRESCALE + 1*/ -#define MCPWM_CAP0_PRESCALE 0x000000FF -#define MCPWM_CAP0_PRESCALE_M ((MCPWM_CAP0_PRESCALE_V)<<(MCPWM_CAP0_PRESCALE_S)) -#define MCPWM_CAP0_PRESCALE_V 0xFF -#define MCPWM_CAP0_PRESCALE_S 3 -/* MCPWM_CAP0_MODE : R/W ;bitpos:[2:1] ;default: 2'd0 ; */ -/*description: Edge of capture on channel 0 after prescale. bit0: negedge cap - en bit1: posedge cap en*/ -#define MCPWM_CAP0_MODE 0x00000003 -#define MCPWM_CAP0_MODE_M ((MCPWM_CAP0_MODE_V)<<(MCPWM_CAP0_MODE_S)) -#define MCPWM_CAP0_MODE_V 0x3 -#define MCPWM_CAP0_MODE_S 1 -/* MCPWM_CAP0_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: When set capture on channel 0 is enabled*/ -#define MCPWM_CAP0_EN (BIT(0)) -#define MCPWM_CAP0_EN_M (BIT(0)) -#define MCPWM_CAP0_EN_V 0x1 +/** MCPWM_CAP_CH0_CFG_REG register + * Capture channel 0 configuration and enable + */ +#define MCPWM_CAP_CH0_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xf0) +/** MCPWM_CAP0_EN : R/W; bitpos: [0]; default: 0; + * When set, capture on channel 0 is enabled + */ +#define MCPWM_CAP0_EN (BIT(0)) +#define MCPWM_CAP0_EN_M (MCPWM_CAP0_EN_V << MCPWM_CAP0_EN_S) +#define MCPWM_CAP0_EN_V 0x00000001U #define MCPWM_CAP0_EN_S 0 +/** MCPWM_CAP0_MODE : R/W; bitpos: [2:1]; default: 0; + * Edge of capture on channel 0 after prescaling. When bit0 is set to 1: enable + * capture on the negative edge, When bit1 is set to 1: enable capture on the positive + * edge. + */ +#define MCPWM_CAP0_MODE 0x00000003U +#define MCPWM_CAP0_MODE_M (MCPWM_CAP0_MODE_V << MCPWM_CAP0_MODE_S) +#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 + + * 1 + */ +#define MCPWM_CAP0_PRESCALE 0x000000FFU +#define MCPWM_CAP0_PRESCALE_M (MCPWM_CAP0_PRESCALE_V << MCPWM_CAP0_PRESCALE_S) +#define MCPWM_CAP0_PRESCALE_V 0x000000FFU +#define MCPWM_CAP0_PRESCALE_S 3 +/** MCPWM_CAP0_IN_INVERT : R/W; bitpos: [11]; default: 0; + * when set, CAP0 form GPIO matrix is inverted before prescale + */ +#define MCPWM_CAP0_IN_INVERT (BIT(11)) +#define MCPWM_CAP0_IN_INVERT_M (MCPWM_CAP0_IN_INVERT_V << MCPWM_CAP0_IN_INVERT_S) +#define MCPWM_CAP0_IN_INVERT_V 0x00000001U +#define MCPWM_CAP0_IN_INVERT_S 11 +/** MCPWM_CAP0_SW : WT; bitpos: [12]; default: 0; + * Write 1 will trigger a software forced capture on channel 0 + */ +#define MCPWM_CAP0_SW (BIT(12)) +#define MCPWM_CAP0_SW_M (MCPWM_CAP0_SW_V << MCPWM_CAP0_SW_S) +#define MCPWM_CAP0_SW_V 0x00000001U +#define MCPWM_CAP0_SW_S 12 -#define MCPWM_CAP_CH1_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x00f4) -/* MCPWM_CAP1_SW : WO ;bitpos:[12] ;default: 1'd0 ; */ -/*description: Write 1 will trigger a software forced capture on channel 1*/ -#define MCPWM_CAP1_SW (BIT(12)) -#define MCPWM_CAP1_SW_M (BIT(12)) -#define MCPWM_CAP1_SW_V 0x1 -#define MCPWM_CAP1_SW_S 12 -/* MCPWM_CAP1_IN_INVERT : R/W ;bitpos:[11] ;default: 1'd0 ; */ -/*description: When set CAP1 form GPIO matrix is inverted before prescale*/ -#define MCPWM_CAP1_IN_INVERT (BIT(11)) -#define MCPWM_CAP1_IN_INVERT_M (BIT(11)) -#define MCPWM_CAP1_IN_INVERT_V 0x1 -#define MCPWM_CAP1_IN_INVERT_S 11 -/* MCPWM_CAP1_PRESCALE : R/W ;bitpos:[10:3] ;default: 8'd0 ; */ -/*description: Value of prescale on possitive edge of CAP1. Prescale value = - PWM_CAP1_PRESCALE + 1*/ -#define MCPWM_CAP1_PRESCALE 0x000000FF -#define MCPWM_CAP1_PRESCALE_M ((MCPWM_CAP1_PRESCALE_V)<<(MCPWM_CAP1_PRESCALE_S)) -#define MCPWM_CAP1_PRESCALE_V 0xFF -#define MCPWM_CAP1_PRESCALE_S 3 -/* MCPWM_CAP1_MODE : R/W ;bitpos:[2:1] ;default: 2'd0 ; */ -/*description: Edge of capture on channel 1 after prescale. bit0: negedge cap - en bit1: posedge cap en*/ -#define MCPWM_CAP1_MODE 0x00000003 -#define MCPWM_CAP1_MODE_M ((MCPWM_CAP1_MODE_V)<<(MCPWM_CAP1_MODE_S)) -#define MCPWM_CAP1_MODE_V 0x3 -#define MCPWM_CAP1_MODE_S 1 -/* MCPWM_CAP1_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: When set capture on channel 1 is enabled*/ -#define MCPWM_CAP1_EN (BIT(0)) -#define MCPWM_CAP1_EN_M (BIT(0)) -#define MCPWM_CAP1_EN_V 0x1 +/** MCPWM_CAP_CH1_CFG_REG register + * Capture channel 1 configuration and enable + */ +#define MCPWM_CAP_CH1_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xf4) +/** MCPWM_CAP1_EN : R/W; bitpos: [0]; default: 0; + * When set, capture on channel 2 is enabled + */ +#define MCPWM_CAP1_EN (BIT(0)) +#define MCPWM_CAP1_EN_M (MCPWM_CAP1_EN_V << MCPWM_CAP1_EN_S) +#define MCPWM_CAP1_EN_V 0x00000001U #define MCPWM_CAP1_EN_S 0 +/** MCPWM_CAP1_MODE : R/W; bitpos: [2:1]; default: 0; + * Edge of capture on channel 1 after prescaling. When bit0 is set to 1: enable + * capture on the negative edge, When bit1 is set to 1: enable capture on the positive + * edge. + */ +#define MCPWM_CAP1_MODE 0x00000003U +#define MCPWM_CAP1_MODE_M (MCPWM_CAP1_MODE_V << MCPWM_CAP1_MODE_S) +#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 + + * 1 + */ +#define MCPWM_CAP1_PRESCALE 0x000000FFU +#define MCPWM_CAP1_PRESCALE_M (MCPWM_CAP1_PRESCALE_V << MCPWM_CAP1_PRESCALE_S) +#define MCPWM_CAP1_PRESCALE_V 0x000000FFU +#define MCPWM_CAP1_PRESCALE_S 3 +/** MCPWM_CAP1_IN_INVERT : R/W; bitpos: [11]; default: 0; + * when set, CAP1 form GPIO matrix is inverted before prescale + */ +#define MCPWM_CAP1_IN_INVERT (BIT(11)) +#define MCPWM_CAP1_IN_INVERT_M (MCPWM_CAP1_IN_INVERT_V << MCPWM_CAP1_IN_INVERT_S) +#define MCPWM_CAP1_IN_INVERT_V 0x00000001U +#define MCPWM_CAP1_IN_INVERT_S 11 +/** MCPWM_CAP1_SW : WT; bitpos: [12]; default: 0; + * Write 1 will trigger a software forced capture on channel 1 + */ +#define MCPWM_CAP1_SW (BIT(12)) +#define MCPWM_CAP1_SW_M (MCPWM_CAP1_SW_V << MCPWM_CAP1_SW_S) +#define MCPWM_CAP1_SW_V 0x00000001U +#define MCPWM_CAP1_SW_S 12 -#define MCPWM_CAP_CH2_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x00f8) -/* MCPWM_CAP2_SW : WO ;bitpos:[12] ;default: 1'd0 ; */ -/*description: Write 1 will trigger a software forced capture on channel 2*/ -#define MCPWM_CAP2_SW (BIT(12)) -#define MCPWM_CAP2_SW_M (BIT(12)) -#define MCPWM_CAP2_SW_V 0x1 -#define MCPWM_CAP2_SW_S 12 -/* MCPWM_CAP2_IN_INVERT : R/W ;bitpos:[11] ;default: 1'd0 ; */ -/*description: When set CAP2 form GPIO matrix is inverted before prescale*/ -#define MCPWM_CAP2_IN_INVERT (BIT(11)) -#define MCPWM_CAP2_IN_INVERT_M (BIT(11)) -#define MCPWM_CAP2_IN_INVERT_V 0x1 -#define MCPWM_CAP2_IN_INVERT_S 11 -/* MCPWM_CAP2_PRESCALE : R/W ;bitpos:[10:3] ;default: 8'd0 ; */ -/*description: Value of prescale on possitive edge of CAP2. Prescale value = - PWM_CAP2_PRESCALE + 1*/ -#define MCPWM_CAP2_PRESCALE 0x000000FF -#define MCPWM_CAP2_PRESCALE_M ((MCPWM_CAP2_PRESCALE_V)<<(MCPWM_CAP2_PRESCALE_S)) -#define MCPWM_CAP2_PRESCALE_V 0xFF -#define MCPWM_CAP2_PRESCALE_S 3 -/* MCPWM_CAP2_MODE : R/W ;bitpos:[2:1] ;default: 2'd0 ; */ -/*description: Edge of capture on channel 2 after prescale. bit0: negedge cap - en bit1: posedge cap en*/ -#define MCPWM_CAP2_MODE 0x00000003 -#define MCPWM_CAP2_MODE_M ((MCPWM_CAP2_MODE_V)<<(MCPWM_CAP2_MODE_S)) -#define MCPWM_CAP2_MODE_V 0x3 -#define MCPWM_CAP2_MODE_S 1 -/* MCPWM_CAP2_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: When set capture on channel 2 is enabled*/ -#define MCPWM_CAP2_EN (BIT(0)) -#define MCPWM_CAP2_EN_M (BIT(0)) -#define MCPWM_CAP2_EN_V 0x1 +/** MCPWM_CAP_CH2_CFG_REG register + * Capture channel 2 configuration and enable + */ +#define MCPWM_CAP_CH2_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xf8) +/** MCPWM_CAP2_EN : R/W; bitpos: [0]; default: 0; + * When set, capture on channel 2 is enabled + */ +#define MCPWM_CAP2_EN (BIT(0)) +#define MCPWM_CAP2_EN_M (MCPWM_CAP2_EN_V << MCPWM_CAP2_EN_S) +#define MCPWM_CAP2_EN_V 0x00000001U #define MCPWM_CAP2_EN_S 0 +/** MCPWM_CAP2_MODE : R/W; bitpos: [2:1]; default: 0; + * Edge of capture on channel 2 after prescaling. When bit0 is set to 1: enable + * capture on the negative edge, When bit1 is set to 1: enable capture on the positive + * edge. + */ +#define MCPWM_CAP2_MODE 0x00000003U +#define MCPWM_CAP2_MODE_M (MCPWM_CAP2_MODE_V << MCPWM_CAP2_MODE_S) +#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 + + * 1 + */ +#define MCPWM_CAP2_PRESCALE 0x000000FFU +#define MCPWM_CAP2_PRESCALE_M (MCPWM_CAP2_PRESCALE_V << MCPWM_CAP2_PRESCALE_S) +#define MCPWM_CAP2_PRESCALE_V 0x000000FFU +#define MCPWM_CAP2_PRESCALE_S 3 +/** MCPWM_CAP2_IN_INVERT : R/W; bitpos: [11]; default: 0; + * when set, CAP2 form GPIO matrix is inverted before prescale + */ +#define MCPWM_CAP2_IN_INVERT (BIT(11)) +#define MCPWM_CAP2_IN_INVERT_M (MCPWM_CAP2_IN_INVERT_V << MCPWM_CAP2_IN_INVERT_S) +#define MCPWM_CAP2_IN_INVERT_V 0x00000001U +#define MCPWM_CAP2_IN_INVERT_S 11 +/** MCPWM_CAP2_SW : WT; bitpos: [12]; default: 0; + * Write 1 will trigger a software forced capture on channel 2 + */ +#define MCPWM_CAP2_SW (BIT(12)) +#define MCPWM_CAP2_SW_M (MCPWM_CAP2_SW_V << MCPWM_CAP2_SW_S) +#define MCPWM_CAP2_SW_V 0x00000001U +#define MCPWM_CAP2_SW_S 12 -#define MCPWM_CAP_CH0_REG(i) (REG_MCPWM_BASE(i) + 0x00fc) -/* MCPWM_CAP0_VALUE : RO ;bitpos:[31:0] ;default: 32'd0 ; */ -/*description: Value of last capture on channel 0*/ -#define MCPWM_CAP0_VALUE 0xFFFFFFFF -#define MCPWM_CAP0_VALUE_M ((MCPWM_CAP0_VALUE_V)<<(MCPWM_CAP0_VALUE_S)) -#define MCPWM_CAP0_VALUE_V 0xFFFFFFFF +/** MCPWM_CAP_CH0_REG register + * ch0 capture value status register + */ +#define MCPWM_CAP_CH0_REG(i) (DR_REG_MCPWM_BASE(i) + 0xfc) +/** MCPWM_CAP0_VALUE : RO; bitpos: [31:0]; default: 0; + * Value of last capture on channel 0 + */ +#define MCPWM_CAP0_VALUE 0xFFFFFFFFU +#define MCPWM_CAP0_VALUE_M (MCPWM_CAP0_VALUE_V << MCPWM_CAP0_VALUE_S) +#define MCPWM_CAP0_VALUE_V 0xFFFFFFFFU #define MCPWM_CAP0_VALUE_S 0 -#define MCPWM_CAP_CH1_REG(i) (REG_MCPWM_BASE(i) + 0x0100) -/* MCPWM_CAP1_VALUE : RO ;bitpos:[31:0] ;default: 32'd0 ; */ -/*description: Value of last capture on channel 1*/ -#define MCPWM_CAP1_VALUE 0xFFFFFFFF -#define MCPWM_CAP1_VALUE_M ((MCPWM_CAP1_VALUE_V)<<(MCPWM_CAP1_VALUE_S)) -#define MCPWM_CAP1_VALUE_V 0xFFFFFFFF +/** MCPWM_CAP_CH1_REG register + * ch1 capture value status register + */ +#define MCPWM_CAP_CH1_REG(i) (DR_REG_MCPWM_BASE(i) + 0x100) +/** MCPWM_CAP1_VALUE : RO; bitpos: [31:0]; default: 0; + * Value of last capture on channel 1 + */ +#define MCPWM_CAP1_VALUE 0xFFFFFFFFU +#define MCPWM_CAP1_VALUE_M (MCPWM_CAP1_VALUE_V << MCPWM_CAP1_VALUE_S) +#define MCPWM_CAP1_VALUE_V 0xFFFFFFFFU #define MCPWM_CAP1_VALUE_S 0 -#define MCPWM_CAP_CH2_REG(i) (REG_MCPWM_BASE(i) + 0x0104) -/* MCPWM_CAP2_VALUE : RO ;bitpos:[31:0] ;default: 32'd0 ; */ -/*description: Value of last capture on channel 2*/ -#define MCPWM_CAP2_VALUE 0xFFFFFFFF -#define MCPWM_CAP2_VALUE_M ((MCPWM_CAP2_VALUE_V)<<(MCPWM_CAP2_VALUE_S)) -#define MCPWM_CAP2_VALUE_V 0xFFFFFFFF +/** MCPWM_CAP_CH2_REG register + * ch2 capture value status register + */ +#define MCPWM_CAP_CH2_REG(i) (DR_REG_MCPWM_BASE(i) + 0x104) +/** MCPWM_CAP2_VALUE : RO; bitpos: [31:0]; default: 0; + * Value of last capture on channel 2 + */ +#define MCPWM_CAP2_VALUE 0xFFFFFFFFU +#define MCPWM_CAP2_VALUE_M (MCPWM_CAP2_VALUE_V << MCPWM_CAP2_VALUE_S) +#define MCPWM_CAP2_VALUE_V 0xFFFFFFFFU #define MCPWM_CAP2_VALUE_S 0 -#define MCPWM_CAP_STATUS_REG(i) (REG_MCPWM_BASE(i) + 0x0108) -/* MCPWM_CAP2_EDGE : RO ;bitpos:[2] ;default: 1'd0 ; */ -/*description: Edge of last capture trigger on channel 2 0: posedge 1: negedge*/ -#define MCPWM_CAP2_EDGE (BIT(2)) -#define MCPWM_CAP2_EDGE_M (BIT(2)) -#define MCPWM_CAP2_EDGE_V 0x1 -#define MCPWM_CAP2_EDGE_S 2 -/* MCPWM_CAP1_EDGE : RO ;bitpos:[1] ;default: 1'd0 ; */ -/*description: Edge of last capture trigger on channel 1 0: posedge 1: negedge*/ -#define MCPWM_CAP1_EDGE (BIT(1)) -#define MCPWM_CAP1_EDGE_M (BIT(1)) -#define MCPWM_CAP1_EDGE_V 0x1 -#define MCPWM_CAP1_EDGE_S 1 -/* MCPWM_CAP0_EDGE : RO ;bitpos:[0] ;default: 1'd0 ; */ -/*description: Edge of last capture trigger on channel 0 0: posedge 1: negedge*/ -#define MCPWM_CAP0_EDGE (BIT(0)) -#define MCPWM_CAP0_EDGE_M (BIT(0)) -#define MCPWM_CAP0_EDGE_V 0x1 +/** MCPWM_CAP_STATUS_REG register + * Edge of last capture trigger + */ +#define MCPWM_CAP_STATUS_REG(i) (DR_REG_MCPWM_BASE(i) + 0x108) +/** MCPWM_CAP0_EDGE : RO; bitpos: [0]; default: 0; + * Edge of last capture trigger on channel 0, 0: posedge, 1: negedge + */ +#define MCPWM_CAP0_EDGE (BIT(0)) +#define MCPWM_CAP0_EDGE_M (MCPWM_CAP0_EDGE_V << MCPWM_CAP0_EDGE_S) +#define MCPWM_CAP0_EDGE_V 0x00000001U #define MCPWM_CAP0_EDGE_S 0 +/** MCPWM_CAP1_EDGE : RO; bitpos: [1]; default: 0; + * Edge of last capture trigger on channel 1, 0: posedge, 1: negedge + */ +#define MCPWM_CAP1_EDGE (BIT(1)) +#define MCPWM_CAP1_EDGE_M (MCPWM_CAP1_EDGE_V << MCPWM_CAP1_EDGE_S) +#define MCPWM_CAP1_EDGE_V 0x00000001U +#define MCPWM_CAP1_EDGE_S 1 +/** MCPWM_CAP2_EDGE : RO; bitpos: [2]; default: 0; + * Edge of last capture trigger on channel 2, 0: posedge, 1: negedge + */ +#define MCPWM_CAP2_EDGE (BIT(2)) +#define MCPWM_CAP2_EDGE_M (MCPWM_CAP2_EDGE_V << MCPWM_CAP2_EDGE_S) +#define MCPWM_CAP2_EDGE_V 0x00000001U +#define MCPWM_CAP2_EDGE_S 2 -#define MCPWM_UPDATE_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x010c) -/* MCPWM_OP2_FORCE_UP : R/W ;bitpos:[7] ;default: 1'd0 ; */ -/*description: A toggle (software negation of value of this bit) will trigger - a forced update of active registers in PWM operator 2*/ -#define MCPWM_OP2_FORCE_UP (BIT(7)) -#define MCPWM_OP2_FORCE_UP_M (BIT(7)) -#define MCPWM_OP2_FORCE_UP_V 0x1 -#define MCPWM_OP2_FORCE_UP_S 7 -/* MCPWM_OP2_UP_EN : R/W ;bitpos:[6] ;default: 1'd1 ; */ -/*description: When set and PWM_GLOBAL_UP_EN is set update of active registers - in PWM operator 2 are enabled*/ -#define MCPWM_OP2_UP_EN (BIT(6)) -#define MCPWM_OP2_UP_EN_M (BIT(6)) -#define MCPWM_OP2_UP_EN_V 0x1 -#define MCPWM_OP2_UP_EN_S 6 -/* MCPWM_OP1_FORCE_UP : R/W ;bitpos:[5] ;default: 1'd0 ; */ -/*description: A toggle (software negation of value of this bit) will trigger - a forced update of active registers in PWM operator 1*/ -#define MCPWM_OP1_FORCE_UP (BIT(5)) -#define MCPWM_OP1_FORCE_UP_M (BIT(5)) -#define MCPWM_OP1_FORCE_UP_V 0x1 -#define MCPWM_OP1_FORCE_UP_S 5 -/* MCPWM_OP1_UP_EN : R/W ;bitpos:[4] ;default: 1'd1 ; */ -/*description: When set and PWM_GLOBAL_UP_EN is set update of active registers - in PWM operator 1 are enabled*/ -#define MCPWM_OP1_UP_EN (BIT(4)) -#define MCPWM_OP1_UP_EN_M (BIT(4)) -#define MCPWM_OP1_UP_EN_V 0x1 -#define MCPWM_OP1_UP_EN_S 4 -/* MCPWM_OP0_FORCE_UP : R/W ;bitpos:[3] ;default: 1'd0 ; */ -/*description: A toggle (software negation of value of this bit) will trigger - a forced update of active registers in PWM operator 0*/ -#define MCPWM_OP0_FORCE_UP (BIT(3)) -#define MCPWM_OP0_FORCE_UP_M (BIT(3)) -#define MCPWM_OP0_FORCE_UP_V 0x1 -#define MCPWM_OP0_FORCE_UP_S 3 -/* MCPWM_OP0_UP_EN : R/W ;bitpos:[2] ;default: 1'd1 ; */ -/*description: When set and PWM_GLOBAL_UP_EN is set update of active registers - in PWM operator 0 are enabled*/ -#define MCPWM_OP0_UP_EN (BIT(2)) -#define MCPWM_OP0_UP_EN_M (BIT(2)) -#define MCPWM_OP0_UP_EN_V 0x1 -#define MCPWM_OP0_UP_EN_S 2 -/* MCPWM_GLOBAL_FORCE_UP : R/W ;bitpos:[1] ;default: 1'd0 ; */ -/*description: A toggle (software negation of value of this bit) will trigger - a forced update of all active registers in MCPWM module*/ -#define MCPWM_GLOBAL_FORCE_UP (BIT(1)) -#define MCPWM_GLOBAL_FORCE_UP_M (BIT(1)) -#define MCPWM_GLOBAL_FORCE_UP_V 0x1 -#define MCPWM_GLOBAL_FORCE_UP_S 1 -/* MCPWM_GLOBAL_UP_EN : R/W ;bitpos:[0] ;default: 1'd1 ; */ -/*description: The global enable of update of all active registers in MCPWM module*/ -#define MCPWM_GLOBAL_UP_EN (BIT(0)) -#define MCPWM_GLOBAL_UP_EN_M (BIT(0)) -#define MCPWM_GLOBAL_UP_EN_V 0x1 +/** MCPWM_UPDATE_CFG_REG register + * Enable update. + */ +#define MCPWM_UPDATE_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x10c) +/** MCPWM_GLOBAL_UP_EN : R/W; bitpos: [0]; default: 1; + * The global enable of update of all active registers in MCPWM module + */ +#define MCPWM_GLOBAL_UP_EN (BIT(0)) +#define MCPWM_GLOBAL_UP_EN_M (MCPWM_GLOBAL_UP_EN_V << MCPWM_GLOBAL_UP_EN_S) +#define MCPWM_GLOBAL_UP_EN_V 0x00000001U #define MCPWM_GLOBAL_UP_EN_S 0 +/** MCPWM_GLOBAL_FORCE_UP : R/W; bitpos: [1]; default: 0; + * a toggle (software invert its value) will trigger a forced update of all active + * registers in MCPWM module + */ +#define MCPWM_GLOBAL_FORCE_UP (BIT(1)) +#define MCPWM_GLOBAL_FORCE_UP_M (MCPWM_GLOBAL_FORCE_UP_V << MCPWM_GLOBAL_FORCE_UP_S) +#define MCPWM_GLOBAL_FORCE_UP_V 0x00000001U +#define MCPWM_GLOBAL_FORCE_UP_S 1 +/** MCPWM_OP0_UP_EN : R/W; bitpos: [2]; default: 1; + * When set and PWM_GLOBAL_UP_EN is set, update of active registers in PWM operator 0 + * are enabled + */ +#define MCPWM_OP0_UP_EN (BIT(2)) +#define MCPWM_OP0_UP_EN_M (MCPWM_OP0_UP_EN_V << MCPWM_OP0_UP_EN_S) +#define MCPWM_OP0_UP_EN_V 0x00000001U +#define MCPWM_OP0_UP_EN_S 2 +/** MCPWM_OP0_FORCE_UP : R/W; bitpos: [3]; default: 0; + * a toggle (software invert its value) will trigger a forced update of active + * registers in PWM operator 0 + */ +#define MCPWM_OP0_FORCE_UP (BIT(3)) +#define MCPWM_OP0_FORCE_UP_M (MCPWM_OP0_FORCE_UP_V << MCPWM_OP0_FORCE_UP_S) +#define MCPWM_OP0_FORCE_UP_V 0x00000001U +#define MCPWM_OP0_FORCE_UP_S 3 +/** MCPWM_OP1_UP_EN : R/W; bitpos: [4]; default: 1; + * When set and PWM_GLOBAL_UP_EN is set, update of active registers in PWM operator 1 + * are enabled + */ +#define MCPWM_OP1_UP_EN (BIT(4)) +#define MCPWM_OP1_UP_EN_M (MCPWM_OP1_UP_EN_V << MCPWM_OP1_UP_EN_S) +#define MCPWM_OP1_UP_EN_V 0x00000001U +#define MCPWM_OP1_UP_EN_S 4 +/** MCPWM_OP1_FORCE_UP : R/W; bitpos: [5]; default: 0; + * a toggle (software invert its value) will trigger a forced update of active + * registers in PWM operator 1 + */ +#define MCPWM_OP1_FORCE_UP (BIT(5)) +#define MCPWM_OP1_FORCE_UP_M (MCPWM_OP1_FORCE_UP_V << MCPWM_OP1_FORCE_UP_S) +#define MCPWM_OP1_FORCE_UP_V 0x00000001U +#define MCPWM_OP1_FORCE_UP_S 5 +/** MCPWM_OP2_UP_EN : R/W; bitpos: [6]; default: 1; + * When set and PWM_GLOBAL_UP_EN is set, update of active registers in PWM operator 2 + * are enabled + */ +#define MCPWM_OP2_UP_EN (BIT(6)) +#define MCPWM_OP2_UP_EN_M (MCPWM_OP2_UP_EN_V << MCPWM_OP2_UP_EN_S) +#define MCPWM_OP2_UP_EN_V 0x00000001U +#define MCPWM_OP2_UP_EN_S 6 +/** MCPWM_OP2_FORCE_UP : R/W; bitpos: [7]; default: 0; + * a toggle (software invert its value) will trigger a forced update of active + * registers in PWM operator 2 + */ +#define MCPWM_OP2_FORCE_UP (BIT(7)) +#define MCPWM_OP2_FORCE_UP_M (MCPWM_OP2_FORCE_UP_V << MCPWM_OP2_FORCE_UP_S) +#define MCPWM_OP2_FORCE_UP_V 0x00000001U +#define MCPWM_OP2_FORCE_UP_S 7 -#define MCMCPWM_INT_ENA_MCPWM_REG(i) (REG_MCPWM_BASE(i) + 0x0110) -/* MCPWM_CAP2_INT_ENA : R/W ;bitpos:[29] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered by captureon channel 2*/ -#define MCPWM_CAP2_INT_ENA (BIT(29)) -#define MCPWM_CAP2_INT_ENA_M (BIT(29)) -#define MCPWM_CAP2_INT_ENA_V 0x1 -#define MCPWM_CAP2_INT_ENA_S 29 -/* MCPWM_CAP1_INT_ENA : R/W ;bitpos:[28] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered by captureon channel 1*/ -#define MCPWM_CAP1_INT_ENA (BIT(28)) -#define MCPWM_CAP1_INT_ENA_M (BIT(28)) -#define MCPWM_CAP1_INT_ENA_V 0x1 -#define MCPWM_CAP1_INT_ENA_S 28 -/* MCPWM_CAP0_INT_ENA : R/W ;bitpos:[27] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered by captureon channel 0*/ -#define MCPWM_CAP0_INT_ENA (BIT(27)) -#define MCPWM_CAP0_INT_ENA_M (BIT(27)) -#define MCPWM_CAP0_INT_ENA_V 0x1 -#define MCPWM_CAP0_INT_ENA_S 27 -/* MCPWM_FH2_OST_INT_ENA : R/W ;bitpos:[26] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered by an one-shot mode action on PWM2*/ -#define MCPWM_FH2_OST_INT_ENA (BIT(26)) -#define MCPWM_FH2_OST_INT_ENA_M (BIT(26)) -#define MCPWM_FH2_OST_INT_ENA_V 0x1 -#define MCPWM_FH2_OST_INT_ENA_S 26 -/* MCPWM_FH1_OST_INT_ENA : R/W ;bitpos:[25] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered by an one-shot mode action on PWM0*/ -#define MCPWM_FH1_OST_INT_ENA (BIT(25)) -#define MCPWM_FH1_OST_INT_ENA_M (BIT(25)) -#define MCPWM_FH1_OST_INT_ENA_V 0x1 -#define MCPWM_FH1_OST_INT_ENA_S 25 -/* MCPWM_FH0_OST_INT_ENA : R/W ;bitpos:[24] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered by an one-shot mode action on PWM0*/ -#define MCPWM_FH0_OST_INT_ENA (BIT(24)) -#define MCPWM_FH0_OST_INT_ENA_M (BIT(24)) -#define MCPWM_FH0_OST_INT_ENA_V 0x1 -#define MCPWM_FH0_OST_INT_ENA_S 24 -/* MCPWM_FH2_CBC_INT_ENA : R/W ;bitpos:[23] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered by an cycle-by-cycle mode action on PWM2*/ -#define MCPWM_FH2_CBC_INT_ENA (BIT(23)) -#define MCPWM_FH2_CBC_INT_ENA_M (BIT(23)) -#define MCPWM_FH2_CBC_INT_ENA_V 0x1 -#define MCPWM_FH2_CBC_INT_ENA_S 23 -/* MCPWM_FH1_CBC_INT_ENA : R/W ;bitpos:[22] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered by an cycle-by-cycle mode action on PWM1*/ -#define MCPWM_FH1_CBC_INT_ENA (BIT(22)) -#define MCPWM_FH1_CBC_INT_ENA_M (BIT(22)) -#define MCPWM_FH1_CBC_INT_ENA_V 0x1 -#define MCPWM_FH1_CBC_INT_ENA_S 22 -/* MCPWM_FH0_CBC_INT_ENA : R/W ;bitpos:[21] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered by an cycle-by-cycle mode action on PWM0*/ -#define MCPWM_FH0_CBC_INT_ENA (BIT(21)) -#define MCPWM_FH0_CBC_INT_ENA_M (BIT(21)) -#define MCPWM_FH0_CBC_INT_ENA_V 0x1 -#define MCPWM_FH0_CBC_INT_ENA_S 21 -/* MCPWM_OP2_TEB_INT_ENA : R/W ;bitpos:[20] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered by a PWM operator 2 TEB event*/ -#define MCPWM_OP2_TEB_INT_ENA (BIT(20)) -#define MCPWM_OP2_TEB_INT_ENA_M (BIT(20)) -#define MCPWM_OP2_TEB_INT_ENA_V 0x1 -#define MCPWM_OP2_TEB_INT_ENA_S 20 -/* MCPWM_OP1_TEB_INT_ENA : R/W ;bitpos:[19] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered by a PWM operator 1 TEB event*/ -#define MCPWM_OP1_TEB_INT_ENA (BIT(19)) -#define MCPWM_OP1_TEB_INT_ENA_M (BIT(19)) -#define MCPWM_OP1_TEB_INT_ENA_V 0x1 -#define MCPWM_OP1_TEB_INT_ENA_S 19 -/* MCPWM_OP0_TEB_INT_ENA : R/W ;bitpos:[18] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered by a PWM operator 0 TEB event*/ -#define MCPWM_OP0_TEB_INT_ENA (BIT(18)) -#define MCPWM_OP0_TEB_INT_ENA_M (BIT(18)) -#define MCPWM_OP0_TEB_INT_ENA_V 0x1 -#define MCPWM_OP0_TEB_INT_ENA_S 18 -/* MCPWM_OP2_TEA_INT_ENA : R/W ;bitpos:[17] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered by a PWM operator 2 TEA event*/ -#define MCPWM_OP2_TEA_INT_ENA (BIT(17)) -#define MCPWM_OP2_TEA_INT_ENA_M (BIT(17)) -#define MCPWM_OP2_TEA_INT_ENA_V 0x1 -#define MCPWM_OP2_TEA_INT_ENA_S 17 -/* MCPWM_OP1_TEA_INT_ENA : R/W ;bitpos:[16] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered by a PWM operator 1 TEA event*/ -#define MCPWM_OP1_TEA_INT_ENA (BIT(16)) -#define MCPWM_OP1_TEA_INT_ENA_M (BIT(16)) -#define MCPWM_OP1_TEA_INT_ENA_V 0x1 -#define MCPWM_OP1_TEA_INT_ENA_S 16 -/* MCPWM_OP0_TEA_INT_ENA : R/W ;bitpos:[15] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered by a PWM operator 0 TEA event*/ -#define MCPWM_OP0_TEA_INT_ENA (BIT(15)) -#define MCPWM_OP0_TEA_INT_ENA_M (BIT(15)) -#define MCPWM_OP0_TEA_INT_ENA_V 0x1 -#define MCPWM_OP0_TEA_INT_ENA_S 15 -/* MCPWM_FAULT2_CLR_INT_ENA : R/W ;bitpos:[14] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered when event_f2 ends*/ -#define MCPWM_FAULT2_CLR_INT_ENA (BIT(14)) -#define MCPWM_FAULT2_CLR_INT_ENA_M (BIT(14)) -#define MCPWM_FAULT2_CLR_INT_ENA_V 0x1 -#define MCPWM_FAULT2_CLR_INT_ENA_S 14 -/* MCPWM_FAULT1_CLR_INT_ENA : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered when event_f1 ends*/ -#define MCPWM_FAULT1_CLR_INT_ENA (BIT(13)) -#define MCPWM_FAULT1_CLR_INT_ENA_M (BIT(13)) -#define MCPWM_FAULT1_CLR_INT_ENA_V 0x1 -#define MCPWM_FAULT1_CLR_INT_ENA_S 13 -/* MCPWM_FAULT0_CLR_INT_ENA : R/W ;bitpos:[12] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered when event_f0 ends*/ -#define MCPWM_FAULT0_CLR_INT_ENA (BIT(12)) -#define MCPWM_FAULT0_CLR_INT_ENA_M (BIT(12)) -#define MCPWM_FAULT0_CLR_INT_ENA_V 0x1 -#define MCPWM_FAULT0_CLR_INT_ENA_S 12 -/* MCPWM_FAULT2_INT_ENA : R/W ;bitpos:[11] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered when event_f2 starts*/ -#define MCPWM_FAULT2_INT_ENA (BIT(11)) -#define MCPWM_FAULT2_INT_ENA_M (BIT(11)) -#define MCPWM_FAULT2_INT_ENA_V 0x1 -#define MCPWM_FAULT2_INT_ENA_S 11 -/* MCPWM_FAULT1_INT_ENA : R/W ;bitpos:[10] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered when event_f1 starts*/ -#define MCPWM_FAULT1_INT_ENA (BIT(10)) -#define MCPWM_FAULT1_INT_ENA_M (BIT(10)) -#define MCPWM_FAULT1_INT_ENA_V 0x1 -#define MCPWM_FAULT1_INT_ENA_S 10 -/* MCPWM_FAULT0_INT_ENA : R/W ;bitpos:[9] ;default: 1'd0 ; */ -/*description: The enable bit for interrupt triggered when event_f0 starts*/ -#define MCPWM_FAULT0_INT_ENA (BIT(9)) -#define MCPWM_FAULT0_INT_ENA_M (BIT(9)) -#define MCPWM_FAULT0_INT_ENA_V 0x1 -#define MCPWM_FAULT0_INT_ENA_S 9 -/* MCPWM_TIMER2_TEP_INT_ENA : R/W ;bitpos:[8] ;default: 1'h0 ; */ -/*description: The enable bit for interrupt triggered by a PWM timer 2 TEP event*/ -#define MCPWM_TIMER2_TEP_INT_ENA (BIT(8)) -#define MCPWM_TIMER2_TEP_INT_ENA_M (BIT(8)) -#define MCPWM_TIMER2_TEP_INT_ENA_V 0x1 -#define MCPWM_TIMER2_TEP_INT_ENA_S 8 -/* MCPWM_TIMER1_TEP_INT_ENA : R/W ;bitpos:[7] ;default: 1'h0 ; */ -/*description: The enable bit for interrupt triggered by a PWM timer 1 TEP event*/ -#define MCPWM_TIMER1_TEP_INT_ENA (BIT(7)) -#define MCPWM_TIMER1_TEP_INT_ENA_M (BIT(7)) -#define MCPWM_TIMER1_TEP_INT_ENA_V 0x1 -#define MCPWM_TIMER1_TEP_INT_ENA_S 7 -/* MCPWM_TIMER0_TEP_INT_ENA : R/W ;bitpos:[6] ;default: 1'h0 ; */ -/*description: The enable bit for interrupt triggered by a PWM timer 0 TEP event*/ -#define MCPWM_TIMER0_TEP_INT_ENA (BIT(6)) -#define MCPWM_TIMER0_TEP_INT_ENA_M (BIT(6)) -#define MCPWM_TIMER0_TEP_INT_ENA_V 0x1 -#define MCPWM_TIMER0_TEP_INT_ENA_S 6 -/* MCPWM_TIMER2_TEZ_INT_ENA : R/W ;bitpos:[5] ;default: 1'h0 ; */ -/*description: The enable bit for interrupt triggered by a PWM timer 2 TEZ event*/ -#define MCPWM_TIMER2_TEZ_INT_ENA (BIT(5)) -#define MCPWM_TIMER2_TEZ_INT_ENA_M (BIT(5)) -#define MCPWM_TIMER2_TEZ_INT_ENA_V 0x1 -#define MCPWM_TIMER2_TEZ_INT_ENA_S 5 -/* MCPWM_TIMER1_TEZ_INT_ENA : R/W ;bitpos:[4] ;default: 1'h0 ; */ -/*description: The enable bit for interrupt triggered by a PWM timer 1 TEZ event*/ -#define MCPWM_TIMER1_TEZ_INT_ENA (BIT(4)) -#define MCPWM_TIMER1_TEZ_INT_ENA_M (BIT(4)) -#define MCPWM_TIMER1_TEZ_INT_ENA_V 0x1 -#define MCPWM_TIMER1_TEZ_INT_ENA_S 4 -/* MCPWM_TIMER0_TEZ_INT_ENA : R/W ;bitpos:[3] ;default: 1'h0 ; */ -/*description: The enable bit for interrupt triggered by a PWM timer 0 TEZ event*/ -#define MCPWM_TIMER0_TEZ_INT_ENA (BIT(3)) -#define MCPWM_TIMER0_TEZ_INT_ENA_M (BIT(3)) -#define MCPWM_TIMER0_TEZ_INT_ENA_V 0x1 -#define MCPWM_TIMER0_TEZ_INT_ENA_S 3 -/* MCPWM_TIMER2_STOP_INT_ENA : R/W ;bitpos:[2] ;default: 1'h0 ; */ -/*description: The enable bit for interrupt triggered when timer 2 stops*/ -#define MCPWM_TIMER2_STOP_INT_ENA (BIT(2)) -#define MCPWM_TIMER2_STOP_INT_ENA_M (BIT(2)) -#define MCPWM_TIMER2_STOP_INT_ENA_V 0x1 -#define MCPWM_TIMER2_STOP_INT_ENA_S 2 -/* MCPWM_TIMER1_STOP_INT_ENA : R/W ;bitpos:[1] ;default: 1'h0 ; */ -/*description: The enable bit for interrupt triggered when timer 1 stops*/ -#define MCPWM_TIMER1_STOP_INT_ENA (BIT(1)) -#define MCPWM_TIMER1_STOP_INT_ENA_M (BIT(1)) -#define MCPWM_TIMER1_STOP_INT_ENA_V 0x1 -#define MCPWM_TIMER1_STOP_INT_ENA_S 1 -/* MCPWM_TIMER0_STOP_INT_ENA : R/W ;bitpos:[0] ;default: 1'h0 ; */ -/*description: The enable bit for interrupt triggered when timer 0 stops*/ -#define MCPWM_TIMER0_STOP_INT_ENA (BIT(0)) -#define MCPWM_TIMER0_STOP_INT_ENA_M (BIT(0)) -#define MCPWM_TIMER0_STOP_INT_ENA_V 0x1 +/** MCPWM_INT_ENA_REG register + * Interrupt enable bits + */ +#define MCPWM_INT_ENA_REG(i) (DR_REG_MCPWM_BASE(i) + 0x110) +/** MCPWM_TIMER0_STOP_INT_ENA : R/W; bitpos: [0]; default: 0; + * The enable bit for the interrupt triggered when the timer 0 stops. + */ +#define MCPWM_TIMER0_STOP_INT_ENA (BIT(0)) +#define MCPWM_TIMER0_STOP_INT_ENA_M (MCPWM_TIMER0_STOP_INT_ENA_V << MCPWM_TIMER0_STOP_INT_ENA_S) +#define MCPWM_TIMER0_STOP_INT_ENA_V 0x00000001U #define MCPWM_TIMER0_STOP_INT_ENA_S 0 +/** MCPWM_TIMER1_STOP_INT_ENA : R/W; bitpos: [1]; default: 0; + * The enable bit for the interrupt triggered when the timer 1 stops. + */ +#define MCPWM_TIMER1_STOP_INT_ENA (BIT(1)) +#define MCPWM_TIMER1_STOP_INT_ENA_M (MCPWM_TIMER1_STOP_INT_ENA_V << MCPWM_TIMER1_STOP_INT_ENA_S) +#define MCPWM_TIMER1_STOP_INT_ENA_V 0x00000001U +#define MCPWM_TIMER1_STOP_INT_ENA_S 1 +/** MCPWM_TIMER2_STOP_INT_ENA : R/W; bitpos: [2]; default: 0; + * The enable bit for the interrupt triggered when the timer 2 stops. + */ +#define MCPWM_TIMER2_STOP_INT_ENA (BIT(2)) +#define MCPWM_TIMER2_STOP_INT_ENA_M (MCPWM_TIMER2_STOP_INT_ENA_V << MCPWM_TIMER2_STOP_INT_ENA_S) +#define MCPWM_TIMER2_STOP_INT_ENA_V 0x00000001U +#define MCPWM_TIMER2_STOP_INT_ENA_S 2 +/** MCPWM_TIMER0_TEZ_INT_ENA : R/W; bitpos: [3]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 0 TEZ event. + */ +#define MCPWM_TIMER0_TEZ_INT_ENA (BIT(3)) +#define MCPWM_TIMER0_TEZ_INT_ENA_M (MCPWM_TIMER0_TEZ_INT_ENA_V << MCPWM_TIMER0_TEZ_INT_ENA_S) +#define MCPWM_TIMER0_TEZ_INT_ENA_V 0x00000001U +#define MCPWM_TIMER0_TEZ_INT_ENA_S 3 +/** MCPWM_TIMER1_TEZ_INT_ENA : R/W; bitpos: [4]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 1 TEZ event. + */ +#define MCPWM_TIMER1_TEZ_INT_ENA (BIT(4)) +#define MCPWM_TIMER1_TEZ_INT_ENA_M (MCPWM_TIMER1_TEZ_INT_ENA_V << MCPWM_TIMER1_TEZ_INT_ENA_S) +#define MCPWM_TIMER1_TEZ_INT_ENA_V 0x00000001U +#define MCPWM_TIMER1_TEZ_INT_ENA_S 4 +/** MCPWM_TIMER2_TEZ_INT_ENA : R/W; bitpos: [5]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 2 TEZ event. + */ +#define MCPWM_TIMER2_TEZ_INT_ENA (BIT(5)) +#define MCPWM_TIMER2_TEZ_INT_ENA_M (MCPWM_TIMER2_TEZ_INT_ENA_V << MCPWM_TIMER2_TEZ_INT_ENA_S) +#define MCPWM_TIMER2_TEZ_INT_ENA_V 0x00000001U +#define MCPWM_TIMER2_TEZ_INT_ENA_S 5 +/** MCPWM_TIMER0_TEP_INT_ENA : R/W; bitpos: [6]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 0 TEP event. + */ +#define MCPWM_TIMER0_TEP_INT_ENA (BIT(6)) +#define MCPWM_TIMER0_TEP_INT_ENA_M (MCPWM_TIMER0_TEP_INT_ENA_V << MCPWM_TIMER0_TEP_INT_ENA_S) +#define MCPWM_TIMER0_TEP_INT_ENA_V 0x00000001U +#define MCPWM_TIMER0_TEP_INT_ENA_S 6 +/** MCPWM_TIMER1_TEP_INT_ENA : R/W; bitpos: [7]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 1 TEP event. + */ +#define MCPWM_TIMER1_TEP_INT_ENA (BIT(7)) +#define MCPWM_TIMER1_TEP_INT_ENA_M (MCPWM_TIMER1_TEP_INT_ENA_V << MCPWM_TIMER1_TEP_INT_ENA_S) +#define MCPWM_TIMER1_TEP_INT_ENA_V 0x00000001U +#define MCPWM_TIMER1_TEP_INT_ENA_S 7 +/** MCPWM_TIMER2_TEP_INT_ENA : R/W; bitpos: [8]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 2 TEP event. + */ +#define MCPWM_TIMER2_TEP_INT_ENA (BIT(8)) +#define MCPWM_TIMER2_TEP_INT_ENA_M (MCPWM_TIMER2_TEP_INT_ENA_V << MCPWM_TIMER2_TEP_INT_ENA_S) +#define MCPWM_TIMER2_TEP_INT_ENA_V 0x00000001U +#define MCPWM_TIMER2_TEP_INT_ENA_S 8 +/** MCPWM_FAULT0_INT_ENA : R/W; bitpos: [9]; default: 0; + * The enable bit for the interrupt triggered when fault_event0 starts. + */ +#define MCPWM_FAULT0_INT_ENA (BIT(9)) +#define MCPWM_FAULT0_INT_ENA_M (MCPWM_FAULT0_INT_ENA_V << MCPWM_FAULT0_INT_ENA_S) +#define MCPWM_FAULT0_INT_ENA_V 0x00000001U +#define MCPWM_FAULT0_INT_ENA_S 9 +/** MCPWM_FAULT1_INT_ENA : R/W; bitpos: [10]; default: 0; + * The enable bit for the interrupt triggered when fault_event1 starts. + */ +#define MCPWM_FAULT1_INT_ENA (BIT(10)) +#define MCPWM_FAULT1_INT_ENA_M (MCPWM_FAULT1_INT_ENA_V << MCPWM_FAULT1_INT_ENA_S) +#define MCPWM_FAULT1_INT_ENA_V 0x00000001U +#define MCPWM_FAULT1_INT_ENA_S 10 +/** MCPWM_FAULT2_INT_ENA : R/W; bitpos: [11]; default: 0; + * The enable bit for the interrupt triggered when fault_event2 starts. + */ +#define MCPWM_FAULT2_INT_ENA (BIT(11)) +#define MCPWM_FAULT2_INT_ENA_M (MCPWM_FAULT2_INT_ENA_V << MCPWM_FAULT2_INT_ENA_S) +#define MCPWM_FAULT2_INT_ENA_V 0x00000001U +#define MCPWM_FAULT2_INT_ENA_S 11 +/** MCPWM_FAULT0_CLR_INT_ENA : R/W; bitpos: [12]; default: 0; + * The enable bit for the interrupt triggered when fault_event0 ends. + */ +#define MCPWM_FAULT0_CLR_INT_ENA (BIT(12)) +#define MCPWM_FAULT0_CLR_INT_ENA_M (MCPWM_FAULT0_CLR_INT_ENA_V << MCPWM_FAULT0_CLR_INT_ENA_S) +#define MCPWM_FAULT0_CLR_INT_ENA_V 0x00000001U +#define MCPWM_FAULT0_CLR_INT_ENA_S 12 +/** MCPWM_FAULT1_CLR_INT_ENA : R/W; bitpos: [13]; default: 0; + * The enable bit for the interrupt triggered when fault_event1 ends. + */ +#define MCPWM_FAULT1_CLR_INT_ENA (BIT(13)) +#define MCPWM_FAULT1_CLR_INT_ENA_M (MCPWM_FAULT1_CLR_INT_ENA_V << MCPWM_FAULT1_CLR_INT_ENA_S) +#define MCPWM_FAULT1_CLR_INT_ENA_V 0x00000001U +#define MCPWM_FAULT1_CLR_INT_ENA_S 13 +/** MCPWM_FAULT2_CLR_INT_ENA : R/W; bitpos: [14]; default: 0; + * The enable bit for the interrupt triggered when fault_event2 ends. + */ +#define MCPWM_FAULT2_CLR_INT_ENA (BIT(14)) +#define MCPWM_FAULT2_CLR_INT_ENA_M (MCPWM_FAULT2_CLR_INT_ENA_V << MCPWM_FAULT2_CLR_INT_ENA_S) +#define MCPWM_FAULT2_CLR_INT_ENA_V 0x00000001U +#define MCPWM_FAULT2_CLR_INT_ENA_S 14 +/** MCPWM_OP0_TEA_INT_ENA : R/W; bitpos: [15]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 0 TEA event + */ +#define MCPWM_OP0_TEA_INT_ENA (BIT(15)) +#define MCPWM_OP0_TEA_INT_ENA_M (MCPWM_OP0_TEA_INT_ENA_V << MCPWM_OP0_TEA_INT_ENA_S) +#define MCPWM_OP0_TEA_INT_ENA_V 0x00000001U +#define MCPWM_OP0_TEA_INT_ENA_S 15 +/** MCPWM_OP1_TEA_INT_ENA : R/W; bitpos: [16]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 1 TEA event + */ +#define MCPWM_OP1_TEA_INT_ENA (BIT(16)) +#define MCPWM_OP1_TEA_INT_ENA_M (MCPWM_OP1_TEA_INT_ENA_V << MCPWM_OP1_TEA_INT_ENA_S) +#define MCPWM_OP1_TEA_INT_ENA_V 0x00000001U +#define MCPWM_OP1_TEA_INT_ENA_S 16 +/** MCPWM_OP2_TEA_INT_ENA : R/W; bitpos: [17]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 2 TEA event + */ +#define MCPWM_OP2_TEA_INT_ENA (BIT(17)) +#define MCPWM_OP2_TEA_INT_ENA_M (MCPWM_OP2_TEA_INT_ENA_V << MCPWM_OP2_TEA_INT_ENA_S) +#define MCPWM_OP2_TEA_INT_ENA_V 0x00000001U +#define MCPWM_OP2_TEA_INT_ENA_S 17 +/** MCPWM_OP0_TEB_INT_ENA : R/W; bitpos: [18]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 0 TEB event + */ +#define MCPWM_OP0_TEB_INT_ENA (BIT(18)) +#define MCPWM_OP0_TEB_INT_ENA_M (MCPWM_OP0_TEB_INT_ENA_V << MCPWM_OP0_TEB_INT_ENA_S) +#define MCPWM_OP0_TEB_INT_ENA_V 0x00000001U +#define MCPWM_OP0_TEB_INT_ENA_S 18 +/** MCPWM_OP1_TEB_INT_ENA : R/W; bitpos: [19]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 1 TEB event + */ +#define MCPWM_OP1_TEB_INT_ENA (BIT(19)) +#define MCPWM_OP1_TEB_INT_ENA_M (MCPWM_OP1_TEB_INT_ENA_V << MCPWM_OP1_TEB_INT_ENA_S) +#define MCPWM_OP1_TEB_INT_ENA_V 0x00000001U +#define MCPWM_OP1_TEB_INT_ENA_S 19 +/** MCPWM_OP2_TEB_INT_ENA : R/W; bitpos: [20]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 2 TEB event + */ +#define MCPWM_OP2_TEB_INT_ENA (BIT(20)) +#define MCPWM_OP2_TEB_INT_ENA_M (MCPWM_OP2_TEB_INT_ENA_V << MCPWM_OP2_TEB_INT_ENA_S) +#define MCPWM_OP2_TEB_INT_ENA_V 0x00000001U +#define MCPWM_OP2_TEB_INT_ENA_S 20 +/** MCPWM_FH0_CBC_INT_ENA : R/W; bitpos: [21]; default: 0; + * The enable bit for the interrupt triggered by a cycle-by-cycle mode action on PWM0. + */ +#define MCPWM_FH0_CBC_INT_ENA (BIT(21)) +#define MCPWM_FH0_CBC_INT_ENA_M (MCPWM_FH0_CBC_INT_ENA_V << MCPWM_FH0_CBC_INT_ENA_S) +#define MCPWM_FH0_CBC_INT_ENA_V 0x00000001U +#define MCPWM_FH0_CBC_INT_ENA_S 21 +/** MCPWM_FH1_CBC_INT_ENA : R/W; bitpos: [22]; default: 0; + * The enable bit for the interrupt triggered by a cycle-by-cycle mode action on PWM1. + */ +#define MCPWM_FH1_CBC_INT_ENA (BIT(22)) +#define MCPWM_FH1_CBC_INT_ENA_M (MCPWM_FH1_CBC_INT_ENA_V << MCPWM_FH1_CBC_INT_ENA_S) +#define MCPWM_FH1_CBC_INT_ENA_V 0x00000001U +#define MCPWM_FH1_CBC_INT_ENA_S 22 +/** MCPWM_FH2_CBC_INT_ENA : R/W; bitpos: [23]; default: 0; + * The enable bit for the interrupt triggered by a cycle-by-cycle mode action on PWM2. + */ +#define MCPWM_FH2_CBC_INT_ENA (BIT(23)) +#define MCPWM_FH2_CBC_INT_ENA_M (MCPWM_FH2_CBC_INT_ENA_V << MCPWM_FH2_CBC_INT_ENA_S) +#define MCPWM_FH2_CBC_INT_ENA_V 0x00000001U +#define MCPWM_FH2_CBC_INT_ENA_S 23 +/** MCPWM_FH0_OST_INT_ENA : R/W; bitpos: [24]; default: 0; + * The enable bit for the interrupt triggered by a one-shot mode action on PWM0. + */ +#define MCPWM_FH0_OST_INT_ENA (BIT(24)) +#define MCPWM_FH0_OST_INT_ENA_M (MCPWM_FH0_OST_INT_ENA_V << MCPWM_FH0_OST_INT_ENA_S) +#define MCPWM_FH0_OST_INT_ENA_V 0x00000001U +#define MCPWM_FH0_OST_INT_ENA_S 24 +/** MCPWM_FH1_OST_INT_ENA : R/W; bitpos: [25]; default: 0; + * The enable bit for the interrupt triggered by a one-shot mode action on PWM1. + */ +#define MCPWM_FH1_OST_INT_ENA (BIT(25)) +#define MCPWM_FH1_OST_INT_ENA_M (MCPWM_FH1_OST_INT_ENA_V << MCPWM_FH1_OST_INT_ENA_S) +#define MCPWM_FH1_OST_INT_ENA_V 0x00000001U +#define MCPWM_FH1_OST_INT_ENA_S 25 +/** MCPWM_FH2_OST_INT_ENA : R/W; bitpos: [26]; default: 0; + * The enable bit for the interrupt triggered by a one-shot mode action on PWM2. + */ +#define MCPWM_FH2_OST_INT_ENA (BIT(26)) +#define MCPWM_FH2_OST_INT_ENA_M (MCPWM_FH2_OST_INT_ENA_V << MCPWM_FH2_OST_INT_ENA_S) +#define MCPWM_FH2_OST_INT_ENA_V 0x00000001U +#define MCPWM_FH2_OST_INT_ENA_S 26 +/** MCPWM_CAP0_INT_ENA : R/W; bitpos: [27]; default: 0; + * The enable bit for the interrupt triggered by capture on channel 0. + */ +#define MCPWM_CAP0_INT_ENA (BIT(27)) +#define MCPWM_CAP0_INT_ENA_M (MCPWM_CAP0_INT_ENA_V << MCPWM_CAP0_INT_ENA_S) +#define MCPWM_CAP0_INT_ENA_V 0x00000001U +#define MCPWM_CAP0_INT_ENA_S 27 +/** MCPWM_CAP1_INT_ENA : R/W; bitpos: [28]; default: 0; + * The enable bit for the interrupt triggered by capture on channel 1. + */ +#define MCPWM_CAP1_INT_ENA (BIT(28)) +#define MCPWM_CAP1_INT_ENA_M (MCPWM_CAP1_INT_ENA_V << MCPWM_CAP1_INT_ENA_S) +#define MCPWM_CAP1_INT_ENA_V 0x00000001U +#define MCPWM_CAP1_INT_ENA_S 28 +/** MCPWM_CAP2_INT_ENA : R/W; bitpos: [29]; default: 0; + * The enable bit for the interrupt triggered by capture on channel 2. + */ +#define MCPWM_CAP2_INT_ENA (BIT(29)) +#define MCPWM_CAP2_INT_ENA_M (MCPWM_CAP2_INT_ENA_V << MCPWM_CAP2_INT_ENA_S) +#define MCPWM_CAP2_INT_ENA_V 0x00000001U +#define MCPWM_CAP2_INT_ENA_S 29 -#define MCMCPWM_INT_RAW_MCPWM_REG(i) (REG_MCPWM_BASE(i) + 0x0114) -/* MCPWM_CAP2_INT_RAW : RO ;bitpos:[29] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered by captureon channel 2*/ -#define MCPWM_CAP2_INT_RAW (BIT(29)) -#define MCPWM_CAP2_INT_RAW_M (BIT(29)) -#define MCPWM_CAP2_INT_RAW_V 0x1 -#define MCPWM_CAP2_INT_RAW_S 29 -/* MCPWM_CAP1_INT_RAW : RO ;bitpos:[28] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered by captureon channel 1*/ -#define MCPWM_CAP1_INT_RAW (BIT(28)) -#define MCPWM_CAP1_INT_RAW_M (BIT(28)) -#define MCPWM_CAP1_INT_RAW_V 0x1 -#define MCPWM_CAP1_INT_RAW_S 28 -/* MCPWM_CAP0_INT_RAW : RO ;bitpos:[27] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered by captureon channel 0*/ -#define MCPWM_CAP0_INT_RAW (BIT(27)) -#define MCPWM_CAP0_INT_RAW_M (BIT(27)) -#define MCPWM_CAP0_INT_RAW_V 0x1 -#define MCPWM_CAP0_INT_RAW_S 27 -/* MCPWM_FH2_OST_INT_RAW : RO ;bitpos:[26] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered by an one-shot mode action on PWM2*/ -#define MCPWM_FH2_OST_INT_RAW (BIT(26)) -#define MCPWM_FH2_OST_INT_RAW_M (BIT(26)) -#define MCPWM_FH2_OST_INT_RAW_V 0x1 -#define MCPWM_FH2_OST_INT_RAW_S 26 -/* MCPWM_FH1_OST_INT_RAW : RO ;bitpos:[25] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered by an one-shot mode action on PWM0*/ -#define MCPWM_FH1_OST_INT_RAW (BIT(25)) -#define MCPWM_FH1_OST_INT_RAW_M (BIT(25)) -#define MCPWM_FH1_OST_INT_RAW_V 0x1 -#define MCPWM_FH1_OST_INT_RAW_S 25 -/* MCPWM_FH0_OST_INT_RAW : RO ;bitpos:[24] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered by an one-shot mode action on PWM0*/ -#define MCPWM_FH0_OST_INT_RAW (BIT(24)) -#define MCPWM_FH0_OST_INT_RAW_M (BIT(24)) -#define MCPWM_FH0_OST_INT_RAW_V 0x1 -#define MCPWM_FH0_OST_INT_RAW_S 24 -/* MCPWM_FH2_CBC_INT_RAW : RO ;bitpos:[23] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered by an cycle-by-cycle - mode action on PWM2*/ -#define MCPWM_FH2_CBC_INT_RAW (BIT(23)) -#define MCPWM_FH2_CBC_INT_RAW_M (BIT(23)) -#define MCPWM_FH2_CBC_INT_RAW_V 0x1 -#define MCPWM_FH2_CBC_INT_RAW_S 23 -/* MCPWM_FH1_CBC_INT_RAW : RO ;bitpos:[22] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered by an cycle-by-cycle - mode action on PWM1*/ -#define MCPWM_FH1_CBC_INT_RAW (BIT(22)) -#define MCPWM_FH1_CBC_INT_RAW_M (BIT(22)) -#define MCPWM_FH1_CBC_INT_RAW_V 0x1 -#define MCPWM_FH1_CBC_INT_RAW_S 22 -/* MCPWM_FH0_CBC_INT_RAW : RO ;bitpos:[21] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered by an cycle-by-cycle - mode action on PWM0*/ -#define MCPWM_FH0_CBC_INT_RAW (BIT(21)) -#define MCPWM_FH0_CBC_INT_RAW_M (BIT(21)) -#define MCPWM_FH0_CBC_INT_RAW_V 0x1 -#define MCPWM_FH0_CBC_INT_RAW_S 21 -/* MCPWM_OP2_TEB_INT_RAW : RO ;bitpos:[20] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered by a PWM operator 2 TEB event*/ -#define MCPWM_OP2_TEB_INT_RAW (BIT(20)) -#define MCPWM_OP2_TEB_INT_RAW_M (BIT(20)) -#define MCPWM_OP2_TEB_INT_RAW_V 0x1 -#define MCPWM_OP2_TEB_INT_RAW_S 20 -/* MCPWM_OP1_TEB_INT_RAW : RO ;bitpos:[19] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered by a PWM operator 1 TEB event*/ -#define MCPWM_OP1_TEB_INT_RAW (BIT(19)) -#define MCPWM_OP1_TEB_INT_RAW_M (BIT(19)) -#define MCPWM_OP1_TEB_INT_RAW_V 0x1 -#define MCPWM_OP1_TEB_INT_RAW_S 19 -/* MCPWM_OP0_TEB_INT_RAW : RO ;bitpos:[18] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered by a PWM operator 0 TEB event*/ -#define MCPWM_OP0_TEB_INT_RAW (BIT(18)) -#define MCPWM_OP0_TEB_INT_RAW_M (BIT(18)) -#define MCPWM_OP0_TEB_INT_RAW_V 0x1 -#define MCPWM_OP0_TEB_INT_RAW_S 18 -/* MCPWM_OP2_TEA_INT_RAW : RO ;bitpos:[17] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered by a PWM operator 2 TEA event*/ -#define MCPWM_OP2_TEA_INT_RAW (BIT(17)) -#define MCPWM_OP2_TEA_INT_RAW_M (BIT(17)) -#define MCPWM_OP2_TEA_INT_RAW_V 0x1 -#define MCPWM_OP2_TEA_INT_RAW_S 17 -/* MCPWM_OP1_TEA_INT_RAW : RO ;bitpos:[16] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered by a PWM operator 1 TEA event*/ -#define MCPWM_OP1_TEA_INT_RAW (BIT(16)) -#define MCPWM_OP1_TEA_INT_RAW_M (BIT(16)) -#define MCPWM_OP1_TEA_INT_RAW_V 0x1 -#define MCPWM_OP1_TEA_INT_RAW_S 16 -/* MCPWM_OP0_TEA_INT_RAW : RO ;bitpos:[15] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered by a PWM operator 0 TEA event*/ -#define MCPWM_OP0_TEA_INT_RAW (BIT(15)) -#define MCPWM_OP0_TEA_INT_RAW_M (BIT(15)) -#define MCPWM_OP0_TEA_INT_RAW_V 0x1 -#define MCPWM_OP0_TEA_INT_RAW_S 15 -/* MCPWM_FAULT2_CLR_INT_RAW : RO ;bitpos:[14] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered when event_f2 ends*/ -#define MCPWM_FAULT2_CLR_INT_RAW (BIT(14)) -#define MCPWM_FAULT2_CLR_INT_RAW_M (BIT(14)) -#define MCPWM_FAULT2_CLR_INT_RAW_V 0x1 -#define MCPWM_FAULT2_CLR_INT_RAW_S 14 -/* MCPWM_FAULT1_CLR_INT_RAW : RO ;bitpos:[13] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered when event_f1 ends*/ -#define MCPWM_FAULT1_CLR_INT_RAW (BIT(13)) -#define MCPWM_FAULT1_CLR_INT_RAW_M (BIT(13)) -#define MCPWM_FAULT1_CLR_INT_RAW_V 0x1 -#define MCPWM_FAULT1_CLR_INT_RAW_S 13 -/* MCPWM_FAULT0_CLR_INT_RAW : RO ;bitpos:[12] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered when event_f0 ends*/ -#define MCPWM_FAULT0_CLR_INT_RAW (BIT(12)) -#define MCPWM_FAULT0_CLR_INT_RAW_M (BIT(12)) -#define MCPWM_FAULT0_CLR_INT_RAW_V 0x1 -#define MCPWM_FAULT0_CLR_INT_RAW_S 12 -/* MCPWM_FAULT2_INT_RAW : RO ;bitpos:[11] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered when event_f2 starts*/ -#define MCPWM_FAULT2_INT_RAW (BIT(11)) -#define MCPWM_FAULT2_INT_RAW_M (BIT(11)) -#define MCPWM_FAULT2_INT_RAW_V 0x1 -#define MCPWM_FAULT2_INT_RAW_S 11 -/* MCPWM_FAULT1_INT_RAW : RO ;bitpos:[10] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered when event_f1 starts*/ -#define MCPWM_FAULT1_INT_RAW (BIT(10)) -#define MCPWM_FAULT1_INT_RAW_M (BIT(10)) -#define MCPWM_FAULT1_INT_RAW_V 0x1 -#define MCPWM_FAULT1_INT_RAW_S 10 -/* MCPWM_FAULT0_INT_RAW : RO ;bitpos:[9] ;default: 1'd0 ; */ -/*description: The raw status bit for interrupt triggered when event_f0 starts*/ -#define MCPWM_FAULT0_INT_RAW (BIT(9)) -#define MCPWM_FAULT0_INT_RAW_M (BIT(9)) -#define MCPWM_FAULT0_INT_RAW_V 0x1 -#define MCPWM_FAULT0_INT_RAW_S 9 -/* MCPWM_TIMER2_TEP_INT_RAW : RO ;bitpos:[8] ;default: 1'h0 ; */ -/*description: The raw status bit for interrupt triggered by a PWM timer 2 TEP event*/ -#define MCPWM_TIMER2_TEP_INT_RAW (BIT(8)) -#define MCPWM_TIMER2_TEP_INT_RAW_M (BIT(8)) -#define MCPWM_TIMER2_TEP_INT_RAW_V 0x1 -#define MCPWM_TIMER2_TEP_INT_RAW_S 8 -/* MCPWM_TIMER1_TEP_INT_RAW : RO ;bitpos:[7] ;default: 1'h0 ; */ -/*description: The raw status bit for interrupt triggered by a PWM timer 1 TEP event*/ -#define MCPWM_TIMER1_TEP_INT_RAW (BIT(7)) -#define MCPWM_TIMER1_TEP_INT_RAW_M (BIT(7)) -#define MCPWM_TIMER1_TEP_INT_RAW_V 0x1 -#define MCPWM_TIMER1_TEP_INT_RAW_S 7 -/* MCPWM_TIMER0_TEP_INT_RAW : RO ;bitpos:[6] ;default: 1'h0 ; */ -/*description: The raw status bit for interrupt triggered by a PWM timer 0 TEP event*/ -#define MCPWM_TIMER0_TEP_INT_RAW (BIT(6)) -#define MCPWM_TIMER0_TEP_INT_RAW_M (BIT(6)) -#define MCPWM_TIMER0_TEP_INT_RAW_V 0x1 -#define MCPWM_TIMER0_TEP_INT_RAW_S 6 -/* MCPWM_TIMER2_TEZ_INT_RAW : RO ;bitpos:[5] ;default: 1'h0 ; */ -/*description: The raw status bit for interrupt triggered by a PWM timer 2 TEZ event*/ -#define MCPWM_TIMER2_TEZ_INT_RAW (BIT(5)) -#define MCPWM_TIMER2_TEZ_INT_RAW_M (BIT(5)) -#define MCPWM_TIMER2_TEZ_INT_RAW_V 0x1 -#define MCPWM_TIMER2_TEZ_INT_RAW_S 5 -/* MCPWM_TIMER1_TEZ_INT_RAW : RO ;bitpos:[4] ;default: 1'h0 ; */ -/*description: The raw status bit for interrupt triggered by a PWM timer 1 TEZ event*/ -#define MCPWM_TIMER1_TEZ_INT_RAW (BIT(4)) -#define MCPWM_TIMER1_TEZ_INT_RAW_M (BIT(4)) -#define MCPWM_TIMER1_TEZ_INT_RAW_V 0x1 -#define MCPWM_TIMER1_TEZ_INT_RAW_S 4 -/* MCPWM_TIMER0_TEZ_INT_RAW : RO ;bitpos:[3] ;default: 1'h0 ; */ -/*description: The raw status bit for interrupt triggered by a PWM timer 0 TEZ event*/ -#define MCPWM_TIMER0_TEZ_INT_RAW (BIT(3)) -#define MCPWM_TIMER0_TEZ_INT_RAW_M (BIT(3)) -#define MCPWM_TIMER0_TEZ_INT_RAW_V 0x1 -#define MCPWM_TIMER0_TEZ_INT_RAW_S 3 -/* MCPWM_TIMER2_STOP_INT_RAW : RO ;bitpos:[2] ;default: 1'h0 ; */ -/*description: The raw status bit for interrupt triggered when timer 2 stops*/ -#define MCPWM_TIMER2_STOP_INT_RAW (BIT(2)) -#define MCPWM_TIMER2_STOP_INT_RAW_M (BIT(2)) -#define MCPWM_TIMER2_STOP_INT_RAW_V 0x1 -#define MCPWM_TIMER2_STOP_INT_RAW_S 2 -/* MCPWM_TIMER1_STOP_INT_RAW : RO ;bitpos:[1] ;default: 1'h0 ; */ -/*description: The raw status bit for interrupt triggered when timer 1 stops*/ -#define MCPWM_TIMER1_STOP_INT_RAW (BIT(1)) -#define MCPWM_TIMER1_STOP_INT_RAW_M (BIT(1)) -#define MCPWM_TIMER1_STOP_INT_RAW_V 0x1 -#define MCPWM_TIMER1_STOP_INT_RAW_S 1 -/* MCPWM_TIMER0_STOP_INT_RAW : RO ;bitpos:[0] ;default: 1'h0 ; */ -/*description: The raw status bit for interrupt triggered when timer 0 stops*/ -#define MCPWM_TIMER0_STOP_INT_RAW (BIT(0)) -#define MCPWM_TIMER0_STOP_INT_RAW_M (BIT(0)) -#define MCPWM_TIMER0_STOP_INT_RAW_V 0x1 +/** MCPWM_INT_RAW_REG register + * Raw interrupt status + */ +#define MCPWM_INT_RAW_REG(i) (DR_REG_MCPWM_BASE(i) + 0x114) +/** MCPWM_TIMER0_STOP_INT_RAW : R/WTC/SS; bitpos: [0]; default: 0; + * The raw status bit for the interrupt triggered when the timer 0 stops. + */ +#define MCPWM_TIMER0_STOP_INT_RAW (BIT(0)) +#define MCPWM_TIMER0_STOP_INT_RAW_M (MCPWM_TIMER0_STOP_INT_RAW_V << MCPWM_TIMER0_STOP_INT_RAW_S) +#define MCPWM_TIMER0_STOP_INT_RAW_V 0x00000001U #define MCPWM_TIMER0_STOP_INT_RAW_S 0 +/** MCPWM_TIMER1_STOP_INT_RAW : R/WTC/SS; bitpos: [1]; default: 0; + * The raw status bit for the interrupt triggered when the timer 1 stops. + */ +#define MCPWM_TIMER1_STOP_INT_RAW (BIT(1)) +#define MCPWM_TIMER1_STOP_INT_RAW_M (MCPWM_TIMER1_STOP_INT_RAW_V << MCPWM_TIMER1_STOP_INT_RAW_S) +#define MCPWM_TIMER1_STOP_INT_RAW_V 0x00000001U +#define MCPWM_TIMER1_STOP_INT_RAW_S 1 +/** MCPWM_TIMER2_STOP_INT_RAW : R/WTC/SS; bitpos: [2]; default: 0; + * The raw status bit for the interrupt triggered when the timer 2 stops. + */ +#define MCPWM_TIMER2_STOP_INT_RAW (BIT(2)) +#define MCPWM_TIMER2_STOP_INT_RAW_M (MCPWM_TIMER2_STOP_INT_RAW_V << MCPWM_TIMER2_STOP_INT_RAW_S) +#define MCPWM_TIMER2_STOP_INT_RAW_V 0x00000001U +#define MCPWM_TIMER2_STOP_INT_RAW_S 2 +/** MCPWM_TIMER0_TEZ_INT_RAW : R/WTC/SS; bitpos: [3]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 0 TEZ event. + */ +#define MCPWM_TIMER0_TEZ_INT_RAW (BIT(3)) +#define MCPWM_TIMER0_TEZ_INT_RAW_M (MCPWM_TIMER0_TEZ_INT_RAW_V << MCPWM_TIMER0_TEZ_INT_RAW_S) +#define MCPWM_TIMER0_TEZ_INT_RAW_V 0x00000001U +#define MCPWM_TIMER0_TEZ_INT_RAW_S 3 +/** MCPWM_TIMER1_TEZ_INT_RAW : R/WTC/SS; bitpos: [4]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 1 TEZ event. + */ +#define MCPWM_TIMER1_TEZ_INT_RAW (BIT(4)) +#define MCPWM_TIMER1_TEZ_INT_RAW_M (MCPWM_TIMER1_TEZ_INT_RAW_V << MCPWM_TIMER1_TEZ_INT_RAW_S) +#define MCPWM_TIMER1_TEZ_INT_RAW_V 0x00000001U +#define MCPWM_TIMER1_TEZ_INT_RAW_S 4 +/** MCPWM_TIMER2_TEZ_INT_RAW : R/WTC/SS; bitpos: [5]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 2 TEZ event. + */ +#define MCPWM_TIMER2_TEZ_INT_RAW (BIT(5)) +#define MCPWM_TIMER2_TEZ_INT_RAW_M (MCPWM_TIMER2_TEZ_INT_RAW_V << MCPWM_TIMER2_TEZ_INT_RAW_S) +#define MCPWM_TIMER2_TEZ_INT_RAW_V 0x00000001U +#define MCPWM_TIMER2_TEZ_INT_RAW_S 5 +/** MCPWM_TIMER0_TEP_INT_RAW : R/WTC/SS; bitpos: [6]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 0 TEP event. + */ +#define MCPWM_TIMER0_TEP_INT_RAW (BIT(6)) +#define MCPWM_TIMER0_TEP_INT_RAW_M (MCPWM_TIMER0_TEP_INT_RAW_V << MCPWM_TIMER0_TEP_INT_RAW_S) +#define MCPWM_TIMER0_TEP_INT_RAW_V 0x00000001U +#define MCPWM_TIMER0_TEP_INT_RAW_S 6 +/** MCPWM_TIMER1_TEP_INT_RAW : R/WTC/SS; bitpos: [7]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 1 TEP event. + */ +#define MCPWM_TIMER1_TEP_INT_RAW (BIT(7)) +#define MCPWM_TIMER1_TEP_INT_RAW_M (MCPWM_TIMER1_TEP_INT_RAW_V << MCPWM_TIMER1_TEP_INT_RAW_S) +#define MCPWM_TIMER1_TEP_INT_RAW_V 0x00000001U +#define MCPWM_TIMER1_TEP_INT_RAW_S 7 +/** MCPWM_TIMER2_TEP_INT_RAW : R/WTC/SS; bitpos: [8]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 2 TEP event. + */ +#define MCPWM_TIMER2_TEP_INT_RAW (BIT(8)) +#define MCPWM_TIMER2_TEP_INT_RAW_M (MCPWM_TIMER2_TEP_INT_RAW_V << MCPWM_TIMER2_TEP_INT_RAW_S) +#define MCPWM_TIMER2_TEP_INT_RAW_V 0x00000001U +#define MCPWM_TIMER2_TEP_INT_RAW_S 8 +/** MCPWM_FAULT0_INT_RAW : R/WTC/SS; bitpos: [9]; default: 0; + * The raw status bit for the interrupt triggered when fault_event0 starts. + */ +#define MCPWM_FAULT0_INT_RAW (BIT(9)) +#define MCPWM_FAULT0_INT_RAW_M (MCPWM_FAULT0_INT_RAW_V << MCPWM_FAULT0_INT_RAW_S) +#define MCPWM_FAULT0_INT_RAW_V 0x00000001U +#define MCPWM_FAULT0_INT_RAW_S 9 +/** MCPWM_FAULT1_INT_RAW : R/WTC/SS; bitpos: [10]; default: 0; + * The raw status bit for the interrupt triggered when fault_event1 starts. + */ +#define MCPWM_FAULT1_INT_RAW (BIT(10)) +#define MCPWM_FAULT1_INT_RAW_M (MCPWM_FAULT1_INT_RAW_V << MCPWM_FAULT1_INT_RAW_S) +#define MCPWM_FAULT1_INT_RAW_V 0x00000001U +#define MCPWM_FAULT1_INT_RAW_S 10 +/** MCPWM_FAULT2_INT_RAW : R/WTC/SS; bitpos: [11]; default: 0; + * The raw status bit for the interrupt triggered when fault_event2 starts. + */ +#define MCPWM_FAULT2_INT_RAW (BIT(11)) +#define MCPWM_FAULT2_INT_RAW_M (MCPWM_FAULT2_INT_RAW_V << MCPWM_FAULT2_INT_RAW_S) +#define MCPWM_FAULT2_INT_RAW_V 0x00000001U +#define MCPWM_FAULT2_INT_RAW_S 11 +/** MCPWM_FAULT0_CLR_INT_RAW : R/WTC/SS; bitpos: [12]; default: 0; + * The raw status bit for the interrupt triggered when fault_event0 ends. + */ +#define MCPWM_FAULT0_CLR_INT_RAW (BIT(12)) +#define MCPWM_FAULT0_CLR_INT_RAW_M (MCPWM_FAULT0_CLR_INT_RAW_V << MCPWM_FAULT0_CLR_INT_RAW_S) +#define MCPWM_FAULT0_CLR_INT_RAW_V 0x00000001U +#define MCPWM_FAULT0_CLR_INT_RAW_S 12 +/** MCPWM_FAULT1_CLR_INT_RAW : R/WTC/SS; bitpos: [13]; default: 0; + * The raw status bit for the interrupt triggered when fault_event1 ends. + */ +#define MCPWM_FAULT1_CLR_INT_RAW (BIT(13)) +#define MCPWM_FAULT1_CLR_INT_RAW_M (MCPWM_FAULT1_CLR_INT_RAW_V << MCPWM_FAULT1_CLR_INT_RAW_S) +#define MCPWM_FAULT1_CLR_INT_RAW_V 0x00000001U +#define MCPWM_FAULT1_CLR_INT_RAW_S 13 +/** MCPWM_FAULT2_CLR_INT_RAW : R/WTC/SS; bitpos: [14]; default: 0; + * The raw status bit for the interrupt triggered when fault_event2 ends. + */ +#define MCPWM_FAULT2_CLR_INT_RAW (BIT(14)) +#define MCPWM_FAULT2_CLR_INT_RAW_M (MCPWM_FAULT2_CLR_INT_RAW_V << MCPWM_FAULT2_CLR_INT_RAW_S) +#define MCPWM_FAULT2_CLR_INT_RAW_V 0x00000001U +#define MCPWM_FAULT2_CLR_INT_RAW_S 14 +/** MCPWM_OP0_TEA_INT_RAW : R/WTC/SS; bitpos: [15]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 0 TEA event + */ +#define MCPWM_OP0_TEA_INT_RAW (BIT(15)) +#define MCPWM_OP0_TEA_INT_RAW_M (MCPWM_OP0_TEA_INT_RAW_V << MCPWM_OP0_TEA_INT_RAW_S) +#define MCPWM_OP0_TEA_INT_RAW_V 0x00000001U +#define MCPWM_OP0_TEA_INT_RAW_S 15 +/** MCPWM_OP1_TEA_INT_RAW : R/WTC/SS; bitpos: [16]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 1 TEA event + */ +#define MCPWM_OP1_TEA_INT_RAW (BIT(16)) +#define MCPWM_OP1_TEA_INT_RAW_M (MCPWM_OP1_TEA_INT_RAW_V << MCPWM_OP1_TEA_INT_RAW_S) +#define MCPWM_OP1_TEA_INT_RAW_V 0x00000001U +#define MCPWM_OP1_TEA_INT_RAW_S 16 +/** MCPWM_OP2_TEA_INT_RAW : R/WTC/SS; bitpos: [17]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 2 TEA event + */ +#define MCPWM_OP2_TEA_INT_RAW (BIT(17)) +#define MCPWM_OP2_TEA_INT_RAW_M (MCPWM_OP2_TEA_INT_RAW_V << MCPWM_OP2_TEA_INT_RAW_S) +#define MCPWM_OP2_TEA_INT_RAW_V 0x00000001U +#define MCPWM_OP2_TEA_INT_RAW_S 17 +/** MCPWM_OP0_TEB_INT_RAW : R/WTC/SS; bitpos: [18]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 0 TEB event + */ +#define MCPWM_OP0_TEB_INT_RAW (BIT(18)) +#define MCPWM_OP0_TEB_INT_RAW_M (MCPWM_OP0_TEB_INT_RAW_V << MCPWM_OP0_TEB_INT_RAW_S) +#define MCPWM_OP0_TEB_INT_RAW_V 0x00000001U +#define MCPWM_OP0_TEB_INT_RAW_S 18 +/** MCPWM_OP1_TEB_INT_RAW : R/WTC/SS; bitpos: [19]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 1 TEB event + */ +#define MCPWM_OP1_TEB_INT_RAW (BIT(19)) +#define MCPWM_OP1_TEB_INT_RAW_M (MCPWM_OP1_TEB_INT_RAW_V << MCPWM_OP1_TEB_INT_RAW_S) +#define MCPWM_OP1_TEB_INT_RAW_V 0x00000001U +#define MCPWM_OP1_TEB_INT_RAW_S 19 +/** MCPWM_OP2_TEB_INT_RAW : R/WTC/SS; bitpos: [20]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 2 TEB event + */ +#define MCPWM_OP2_TEB_INT_RAW (BIT(20)) +#define MCPWM_OP2_TEB_INT_RAW_M (MCPWM_OP2_TEB_INT_RAW_V << MCPWM_OP2_TEB_INT_RAW_S) +#define MCPWM_OP2_TEB_INT_RAW_V 0x00000001U +#define MCPWM_OP2_TEB_INT_RAW_S 20 +/** MCPWM_FH0_CBC_INT_RAW : R/WTC/SS; bitpos: [21]; default: 0; + * The raw status bit for the interrupt triggered by a cycle-by-cycle mode action on + * PWM0. + */ +#define MCPWM_FH0_CBC_INT_RAW (BIT(21)) +#define MCPWM_FH0_CBC_INT_RAW_M (MCPWM_FH0_CBC_INT_RAW_V << MCPWM_FH0_CBC_INT_RAW_S) +#define MCPWM_FH0_CBC_INT_RAW_V 0x00000001U +#define MCPWM_FH0_CBC_INT_RAW_S 21 +/** MCPWM_FH1_CBC_INT_RAW : R/WTC/SS; bitpos: [22]; default: 0; + * The raw status bit for the interrupt triggered by a cycle-by-cycle mode action on + * PWM1. + */ +#define MCPWM_FH1_CBC_INT_RAW (BIT(22)) +#define MCPWM_FH1_CBC_INT_RAW_M (MCPWM_FH1_CBC_INT_RAW_V << MCPWM_FH1_CBC_INT_RAW_S) +#define MCPWM_FH1_CBC_INT_RAW_V 0x00000001U +#define MCPWM_FH1_CBC_INT_RAW_S 22 +/** MCPWM_FH2_CBC_INT_RAW : R/WTC/SS; bitpos: [23]; default: 0; + * The raw status bit for the interrupt triggered by a cycle-by-cycle mode action on + * PWM2. + */ +#define MCPWM_FH2_CBC_INT_RAW (BIT(23)) +#define MCPWM_FH2_CBC_INT_RAW_M (MCPWM_FH2_CBC_INT_RAW_V << MCPWM_FH2_CBC_INT_RAW_S) +#define MCPWM_FH2_CBC_INT_RAW_V 0x00000001U +#define MCPWM_FH2_CBC_INT_RAW_S 23 +/** MCPWM_FH0_OST_INT_RAW : R/WTC/SS; bitpos: [24]; default: 0; + * The raw status bit for the interrupt triggered by a one-shot mode action on PWM0. + */ +#define MCPWM_FH0_OST_INT_RAW (BIT(24)) +#define MCPWM_FH0_OST_INT_RAW_M (MCPWM_FH0_OST_INT_RAW_V << MCPWM_FH0_OST_INT_RAW_S) +#define MCPWM_FH0_OST_INT_RAW_V 0x00000001U +#define MCPWM_FH0_OST_INT_RAW_S 24 +/** MCPWM_FH1_OST_INT_RAW : R/WTC/SS; bitpos: [25]; default: 0; + * The raw status bit for the interrupt triggered by a one-shot mode action on PWM1. + */ +#define MCPWM_FH1_OST_INT_RAW (BIT(25)) +#define MCPWM_FH1_OST_INT_RAW_M (MCPWM_FH1_OST_INT_RAW_V << MCPWM_FH1_OST_INT_RAW_S) +#define MCPWM_FH1_OST_INT_RAW_V 0x00000001U +#define MCPWM_FH1_OST_INT_RAW_S 25 +/** MCPWM_FH2_OST_INT_RAW : R/WTC/SS; bitpos: [26]; default: 0; + * The raw status bit for the interrupt triggered by a one-shot mode action on PWM2. + */ +#define MCPWM_FH2_OST_INT_RAW (BIT(26)) +#define MCPWM_FH2_OST_INT_RAW_M (MCPWM_FH2_OST_INT_RAW_V << MCPWM_FH2_OST_INT_RAW_S) +#define MCPWM_FH2_OST_INT_RAW_V 0x00000001U +#define MCPWM_FH2_OST_INT_RAW_S 26 +/** MCPWM_CAP0_INT_RAW : R/WTC/SS; bitpos: [27]; default: 0; + * The raw status bit for the interrupt triggered by capture on channel 0. + */ +#define MCPWM_CAP0_INT_RAW (BIT(27)) +#define MCPWM_CAP0_INT_RAW_M (MCPWM_CAP0_INT_RAW_V << MCPWM_CAP0_INT_RAW_S) +#define MCPWM_CAP0_INT_RAW_V 0x00000001U +#define MCPWM_CAP0_INT_RAW_S 27 +/** MCPWM_CAP1_INT_RAW : R/WTC/SS; bitpos: [28]; default: 0; + * The raw status bit for the interrupt triggered by capture on channel 1. + */ +#define MCPWM_CAP1_INT_RAW (BIT(28)) +#define MCPWM_CAP1_INT_RAW_M (MCPWM_CAP1_INT_RAW_V << MCPWM_CAP1_INT_RAW_S) +#define MCPWM_CAP1_INT_RAW_V 0x00000001U +#define MCPWM_CAP1_INT_RAW_S 28 +/** MCPWM_CAP2_INT_RAW : R/WTC/SS; bitpos: [29]; default: 0; + * The raw status bit for the interrupt triggered by capture on channel 2. + */ +#define MCPWM_CAP2_INT_RAW (BIT(29)) +#define MCPWM_CAP2_INT_RAW_M (MCPWM_CAP2_INT_RAW_V << MCPWM_CAP2_INT_RAW_S) +#define MCPWM_CAP2_INT_RAW_V 0x00000001U +#define MCPWM_CAP2_INT_RAW_S 29 -#define MCMCPWM_INT_ST_MCPWM_REG(i) (REG_MCPWM_BASE(i) + 0x0118) -/* MCPWM_CAP2_INT_ST : RO ;bitpos:[29] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered by captureon channel 2*/ -#define MCPWM_CAP2_INT_ST (BIT(29)) -#define MCPWM_CAP2_INT_ST_M (BIT(29)) -#define MCPWM_CAP2_INT_ST_V 0x1 -#define MCPWM_CAP2_INT_ST_S 29 -/* MCPWM_CAP1_INT_ST : RO ;bitpos:[28] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered by captureon channel 1*/ -#define MCPWM_CAP1_INT_ST (BIT(28)) -#define MCPWM_CAP1_INT_ST_M (BIT(28)) -#define MCPWM_CAP1_INT_ST_V 0x1 -#define MCPWM_CAP1_INT_ST_S 28 -/* MCPWM_CAP0_INT_ST : RO ;bitpos:[27] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered by captureon channel 0*/ -#define MCPWM_CAP0_INT_ST (BIT(27)) -#define MCPWM_CAP0_INT_ST_M (BIT(27)) -#define MCPWM_CAP0_INT_ST_V 0x1 -#define MCPWM_CAP0_INT_ST_S 27 -/* MCPWM_FH2_OST_INT_ST : RO ;bitpos:[26] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered by an one-shot mode action on PWM2*/ -#define MCPWM_FH2_OST_INT_ST (BIT(26)) -#define MCPWM_FH2_OST_INT_ST_M (BIT(26)) -#define MCPWM_FH2_OST_INT_ST_V 0x1 -#define MCPWM_FH2_OST_INT_ST_S 26 -/* MCPWM_FH1_OST_INT_ST : RO ;bitpos:[25] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered by an one-shot mode action on PWM0*/ -#define MCPWM_FH1_OST_INT_ST (BIT(25)) -#define MCPWM_FH1_OST_INT_ST_M (BIT(25)) -#define MCPWM_FH1_OST_INT_ST_V 0x1 -#define MCPWM_FH1_OST_INT_ST_S 25 -/* MCPWM_FH0_OST_INT_ST : RO ;bitpos:[24] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered by an one-shot mode action on PWM0*/ -#define MCPWM_FH0_OST_INT_ST (BIT(24)) -#define MCPWM_FH0_OST_INT_ST_M (BIT(24)) -#define MCPWM_FH0_OST_INT_ST_V 0x1 -#define MCPWM_FH0_OST_INT_ST_S 24 -/* MCPWM_FH2_CBC_INT_ST : RO ;bitpos:[23] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered by an cycle-by-cycle - mode action on PWM2*/ -#define MCPWM_FH2_CBC_INT_ST (BIT(23)) -#define MCPWM_FH2_CBC_INT_ST_M (BIT(23)) -#define MCPWM_FH2_CBC_INT_ST_V 0x1 -#define MCPWM_FH2_CBC_INT_ST_S 23 -/* MCPWM_FH1_CBC_INT_ST : RO ;bitpos:[22] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered by an cycle-by-cycle - mode action on PWM1*/ -#define MCPWM_FH1_CBC_INT_ST (BIT(22)) -#define MCPWM_FH1_CBC_INT_ST_M (BIT(22)) -#define MCPWM_FH1_CBC_INT_ST_V 0x1 -#define MCPWM_FH1_CBC_INT_ST_S 22 -/* MCPWM_FH0_CBC_INT_ST : RO ;bitpos:[21] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered by an cycle-by-cycle - mode action on PWM0*/ -#define MCPWM_FH0_CBC_INT_ST (BIT(21)) -#define MCPWM_FH0_CBC_INT_ST_M (BIT(21)) -#define MCPWM_FH0_CBC_INT_ST_V 0x1 -#define MCPWM_FH0_CBC_INT_ST_S 21 -/* MCPWM_OP2_TEB_INT_ST : RO ;bitpos:[20] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered by a PWM operator 2 TEB event*/ -#define MCPWM_OP2_TEB_INT_ST (BIT(20)) -#define MCPWM_OP2_TEB_INT_ST_M (BIT(20)) -#define MCPWM_OP2_TEB_INT_ST_V 0x1 -#define MCPWM_OP2_TEB_INT_ST_S 20 -/* MCPWM_OP1_TEB_INT_ST : RO ;bitpos:[19] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered by a PWM operator 1 TEB event*/ -#define MCPWM_OP1_TEB_INT_ST (BIT(19)) -#define MCPWM_OP1_TEB_INT_ST_M (BIT(19)) -#define MCPWM_OP1_TEB_INT_ST_V 0x1 -#define MCPWM_OP1_TEB_INT_ST_S 19 -/* MCPWM_OP0_TEB_INT_ST : RO ;bitpos:[18] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered by a PWM operator 0 TEB event*/ -#define MCPWM_OP0_TEB_INT_ST (BIT(18)) -#define MCPWM_OP0_TEB_INT_ST_M (BIT(18)) -#define MCPWM_OP0_TEB_INT_ST_V 0x1 -#define MCPWM_OP0_TEB_INT_ST_S 18 -/* MCPWM_OP2_TEA_INT_ST : RO ;bitpos:[17] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered by a PWM operator 2 TEA event*/ -#define MCPWM_OP2_TEA_INT_ST (BIT(17)) -#define MCPWM_OP2_TEA_INT_ST_M (BIT(17)) -#define MCPWM_OP2_TEA_INT_ST_V 0x1 -#define MCPWM_OP2_TEA_INT_ST_S 17 -/* MCPWM_OP1_TEA_INT_ST : RO ;bitpos:[16] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered by a PWM operator 1 TEA event*/ -#define MCPWM_OP1_TEA_INT_ST (BIT(16)) -#define MCPWM_OP1_TEA_INT_ST_M (BIT(16)) -#define MCPWM_OP1_TEA_INT_ST_V 0x1 -#define MCPWM_OP1_TEA_INT_ST_S 16 -/* MCPWM_OP0_TEA_INT_ST : RO ;bitpos:[15] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered by a PWM operator 0 TEA event*/ -#define MCPWM_OP0_TEA_INT_ST (BIT(15)) -#define MCPWM_OP0_TEA_INT_ST_M (BIT(15)) -#define MCPWM_OP0_TEA_INT_ST_V 0x1 -#define MCPWM_OP0_TEA_INT_ST_S 15 -/* MCPWM_FAULT2_CLR_INT_ST : RO ;bitpos:[14] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered when event_f2 ends*/ -#define MCPWM_FAULT2_CLR_INT_ST (BIT(14)) -#define MCPWM_FAULT2_CLR_INT_ST_M (BIT(14)) -#define MCPWM_FAULT2_CLR_INT_ST_V 0x1 -#define MCPWM_FAULT2_CLR_INT_ST_S 14 -/* MCPWM_FAULT1_CLR_INT_ST : RO ;bitpos:[13] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered when event_f1 ends*/ -#define MCPWM_FAULT1_CLR_INT_ST (BIT(13)) -#define MCPWM_FAULT1_CLR_INT_ST_M (BIT(13)) -#define MCPWM_FAULT1_CLR_INT_ST_V 0x1 -#define MCPWM_FAULT1_CLR_INT_ST_S 13 -/* MCPWM_FAULT0_CLR_INT_ST : RO ;bitpos:[12] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered when event_f0 ends*/ -#define MCPWM_FAULT0_CLR_INT_ST (BIT(12)) -#define MCPWM_FAULT0_CLR_INT_ST_M (BIT(12)) -#define MCPWM_FAULT0_CLR_INT_ST_V 0x1 -#define MCPWM_FAULT0_CLR_INT_ST_S 12 -/* MCPWM_FAULT2_INT_ST : RO ;bitpos:[11] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered when event_f2 starts*/ -#define MCPWM_FAULT2_INT_ST (BIT(11)) -#define MCPWM_FAULT2_INT_ST_M (BIT(11)) -#define MCPWM_FAULT2_INT_ST_V 0x1 -#define MCPWM_FAULT2_INT_ST_S 11 -/* MCPWM_FAULT1_INT_ST : RO ;bitpos:[10] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered when event_f1 starts*/ -#define MCPWM_FAULT1_INT_ST (BIT(10)) -#define MCPWM_FAULT1_INT_ST_M (BIT(10)) -#define MCPWM_FAULT1_INT_ST_V 0x1 -#define MCPWM_FAULT1_INT_ST_S 10 -/* MCPWM_FAULT0_INT_ST : RO ;bitpos:[9] ;default: 1'd0 ; */ -/*description: The masked status bit for interrupt triggered when event_f0 starts*/ -#define MCPWM_FAULT0_INT_ST (BIT(9)) -#define MCPWM_FAULT0_INT_ST_M (BIT(9)) -#define MCPWM_FAULT0_INT_ST_V 0x1 -#define MCPWM_FAULT0_INT_ST_S 9 -/* MCPWM_TIMER2_TEP_INT_ST : RO ;bitpos:[8] ;default: 1'h0 ; */ -/*description: The masked status bit for interrupt triggered by a PWM timer 2 TEP event*/ -#define MCPWM_TIMER2_TEP_INT_ST (BIT(8)) -#define MCPWM_TIMER2_TEP_INT_ST_M (BIT(8)) -#define MCPWM_TIMER2_TEP_INT_ST_V 0x1 -#define MCPWM_TIMER2_TEP_INT_ST_S 8 -/* MCPWM_TIMER1_TEP_INT_ST : RO ;bitpos:[7] ;default: 1'h0 ; */ -/*description: The masked status bit for interrupt triggered by a PWM timer 1 TEP event*/ -#define MCPWM_TIMER1_TEP_INT_ST (BIT(7)) -#define MCPWM_TIMER1_TEP_INT_ST_M (BIT(7)) -#define MCPWM_TIMER1_TEP_INT_ST_V 0x1 -#define MCPWM_TIMER1_TEP_INT_ST_S 7 -/* MCPWM_TIMER0_TEP_INT_ST : RO ;bitpos:[6] ;default: 1'h0 ; */ -/*description: The masked status bit for interrupt triggered by a PWM timer 0 TEP event*/ -#define MCPWM_TIMER0_TEP_INT_ST (BIT(6)) -#define MCPWM_TIMER0_TEP_INT_ST_M (BIT(6)) -#define MCPWM_TIMER0_TEP_INT_ST_V 0x1 -#define MCPWM_TIMER0_TEP_INT_ST_S 6 -/* MCPWM_TIMER2_TEZ_INT_ST : RO ;bitpos:[5] ;default: 1'h0 ; */ -/*description: The masked status bit for interrupt triggered by a PWM timer 2 TEZ event*/ -#define MCPWM_TIMER2_TEZ_INT_ST (BIT(5)) -#define MCPWM_TIMER2_TEZ_INT_ST_M (BIT(5)) -#define MCPWM_TIMER2_TEZ_INT_ST_V 0x1 -#define MCPWM_TIMER2_TEZ_INT_ST_S 5 -/* MCPWM_TIMER1_TEZ_INT_ST : RO ;bitpos:[4] ;default: 1'h0 ; */ -/*description: The masked status bit for interrupt triggered by a PWM timer 1 TEZ event*/ -#define MCPWM_TIMER1_TEZ_INT_ST (BIT(4)) -#define MCPWM_TIMER1_TEZ_INT_ST_M (BIT(4)) -#define MCPWM_TIMER1_TEZ_INT_ST_V 0x1 -#define MCPWM_TIMER1_TEZ_INT_ST_S 4 -/* MCPWM_TIMER0_TEZ_INT_ST : RO ;bitpos:[3] ;default: 1'h0 ; */ -/*description: The masked status bit for interrupt triggered by a PWM timer 0 TEZ event*/ -#define MCPWM_TIMER0_TEZ_INT_ST (BIT(3)) -#define MCPWM_TIMER0_TEZ_INT_ST_M (BIT(3)) -#define MCPWM_TIMER0_TEZ_INT_ST_V 0x1 -#define MCPWM_TIMER0_TEZ_INT_ST_S 3 -/* MCPWM_TIMER2_STOP_INT_ST : RO ;bitpos:[2] ;default: 1'h0 ; */ -/*description: The masked status bit for interrupt triggered when timer 2 stops*/ -#define MCPWM_TIMER2_STOP_INT_ST (BIT(2)) -#define MCPWM_TIMER2_STOP_INT_ST_M (BIT(2)) -#define MCPWM_TIMER2_STOP_INT_ST_V 0x1 -#define MCPWM_TIMER2_STOP_INT_ST_S 2 -/* MCPWM_TIMER1_STOP_INT_ST : RO ;bitpos:[1] ;default: 1'h0 ; */ -/*description: The masked status bit for interrupt triggered when timer 1 stops*/ -#define MCPWM_TIMER1_STOP_INT_ST (BIT(1)) -#define MCPWM_TIMER1_STOP_INT_ST_M (BIT(1)) -#define MCPWM_TIMER1_STOP_INT_ST_V 0x1 -#define MCPWM_TIMER1_STOP_INT_ST_S 1 -/* MCPWM_TIMER0_STOP_INT_ST : RO ;bitpos:[0] ;default: 1'h0 ; */ -/*description: The masked status bit for interrupt triggered when timer 0 stops*/ -#define MCPWM_TIMER0_STOP_INT_ST (BIT(0)) -#define MCPWM_TIMER0_STOP_INT_ST_M (BIT(0)) -#define MCPWM_TIMER0_STOP_INT_ST_V 0x1 +/** MCPWM_INT_ST_REG register + * Masked interrupt status + */ +#define MCPWM_INT_ST_REG(i) (DR_REG_MCPWM_BASE(i) + 0x118) +/** MCPWM_TIMER0_STOP_INT_ST : RO; bitpos: [0]; default: 0; + * The masked status bit for the interrupt triggered when the timer 0 stops. + */ +#define MCPWM_TIMER0_STOP_INT_ST (BIT(0)) +#define MCPWM_TIMER0_STOP_INT_ST_M (MCPWM_TIMER0_STOP_INT_ST_V << MCPWM_TIMER0_STOP_INT_ST_S) +#define MCPWM_TIMER0_STOP_INT_ST_V 0x00000001U #define MCPWM_TIMER0_STOP_INT_ST_S 0 +/** MCPWM_TIMER1_STOP_INT_ST : RO; bitpos: [1]; default: 0; + * The masked status bit for the interrupt triggered when the timer 1 stops. + */ +#define MCPWM_TIMER1_STOP_INT_ST (BIT(1)) +#define MCPWM_TIMER1_STOP_INT_ST_M (MCPWM_TIMER1_STOP_INT_ST_V << MCPWM_TIMER1_STOP_INT_ST_S) +#define MCPWM_TIMER1_STOP_INT_ST_V 0x00000001U +#define MCPWM_TIMER1_STOP_INT_ST_S 1 +/** MCPWM_TIMER2_STOP_INT_ST : RO; bitpos: [2]; default: 0; + * The masked status bit for the interrupt triggered when the timer 2 stops. + */ +#define MCPWM_TIMER2_STOP_INT_ST (BIT(2)) +#define MCPWM_TIMER2_STOP_INT_ST_M (MCPWM_TIMER2_STOP_INT_ST_V << MCPWM_TIMER2_STOP_INT_ST_S) +#define MCPWM_TIMER2_STOP_INT_ST_V 0x00000001U +#define MCPWM_TIMER2_STOP_INT_ST_S 2 +/** MCPWM_TIMER0_TEZ_INT_ST : RO; bitpos: [3]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 0 TEZ event. + */ +#define MCPWM_TIMER0_TEZ_INT_ST (BIT(3)) +#define MCPWM_TIMER0_TEZ_INT_ST_M (MCPWM_TIMER0_TEZ_INT_ST_V << MCPWM_TIMER0_TEZ_INT_ST_S) +#define MCPWM_TIMER0_TEZ_INT_ST_V 0x00000001U +#define MCPWM_TIMER0_TEZ_INT_ST_S 3 +/** MCPWM_TIMER1_TEZ_INT_ST : RO; bitpos: [4]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 1 TEZ event. + */ +#define MCPWM_TIMER1_TEZ_INT_ST (BIT(4)) +#define MCPWM_TIMER1_TEZ_INT_ST_M (MCPWM_TIMER1_TEZ_INT_ST_V << MCPWM_TIMER1_TEZ_INT_ST_S) +#define MCPWM_TIMER1_TEZ_INT_ST_V 0x00000001U +#define MCPWM_TIMER1_TEZ_INT_ST_S 4 +/** MCPWM_TIMER2_TEZ_INT_ST : RO; bitpos: [5]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 2 TEZ event. + */ +#define MCPWM_TIMER2_TEZ_INT_ST (BIT(5)) +#define MCPWM_TIMER2_TEZ_INT_ST_M (MCPWM_TIMER2_TEZ_INT_ST_V << MCPWM_TIMER2_TEZ_INT_ST_S) +#define MCPWM_TIMER2_TEZ_INT_ST_V 0x00000001U +#define MCPWM_TIMER2_TEZ_INT_ST_S 5 +/** MCPWM_TIMER0_TEP_INT_ST : RO; bitpos: [6]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 0 TEP event. + */ +#define MCPWM_TIMER0_TEP_INT_ST (BIT(6)) +#define MCPWM_TIMER0_TEP_INT_ST_M (MCPWM_TIMER0_TEP_INT_ST_V << MCPWM_TIMER0_TEP_INT_ST_S) +#define MCPWM_TIMER0_TEP_INT_ST_V 0x00000001U +#define MCPWM_TIMER0_TEP_INT_ST_S 6 +/** MCPWM_TIMER1_TEP_INT_ST : RO; bitpos: [7]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 1 TEP event. + */ +#define MCPWM_TIMER1_TEP_INT_ST (BIT(7)) +#define MCPWM_TIMER1_TEP_INT_ST_M (MCPWM_TIMER1_TEP_INT_ST_V << MCPWM_TIMER1_TEP_INT_ST_S) +#define MCPWM_TIMER1_TEP_INT_ST_V 0x00000001U +#define MCPWM_TIMER1_TEP_INT_ST_S 7 +/** MCPWM_TIMER2_TEP_INT_ST : RO; bitpos: [8]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 2 TEP event. + */ +#define MCPWM_TIMER2_TEP_INT_ST (BIT(8)) +#define MCPWM_TIMER2_TEP_INT_ST_M (MCPWM_TIMER2_TEP_INT_ST_V << MCPWM_TIMER2_TEP_INT_ST_S) +#define MCPWM_TIMER2_TEP_INT_ST_V 0x00000001U +#define MCPWM_TIMER2_TEP_INT_ST_S 8 +/** MCPWM_FAULT0_INT_ST : RO; bitpos: [9]; default: 0; + * The masked status bit for the interrupt triggered when fault_event0 starts. + */ +#define MCPWM_FAULT0_INT_ST (BIT(9)) +#define MCPWM_FAULT0_INT_ST_M (MCPWM_FAULT0_INT_ST_V << MCPWM_FAULT0_INT_ST_S) +#define MCPWM_FAULT0_INT_ST_V 0x00000001U +#define MCPWM_FAULT0_INT_ST_S 9 +/** MCPWM_FAULT1_INT_ST : RO; bitpos: [10]; default: 0; + * The masked status bit for the interrupt triggered when fault_event1 starts. + */ +#define MCPWM_FAULT1_INT_ST (BIT(10)) +#define MCPWM_FAULT1_INT_ST_M (MCPWM_FAULT1_INT_ST_V << MCPWM_FAULT1_INT_ST_S) +#define MCPWM_FAULT1_INT_ST_V 0x00000001U +#define MCPWM_FAULT1_INT_ST_S 10 +/** MCPWM_FAULT2_INT_ST : RO; bitpos: [11]; default: 0; + * The masked status bit for the interrupt triggered when fault_event2 starts. + */ +#define MCPWM_FAULT2_INT_ST (BIT(11)) +#define MCPWM_FAULT2_INT_ST_M (MCPWM_FAULT2_INT_ST_V << MCPWM_FAULT2_INT_ST_S) +#define MCPWM_FAULT2_INT_ST_V 0x00000001U +#define MCPWM_FAULT2_INT_ST_S 11 +/** MCPWM_FAULT0_CLR_INT_ST : RO; bitpos: [12]; default: 0; + * The masked status bit for the interrupt triggered when fault_event0 ends. + */ +#define MCPWM_FAULT0_CLR_INT_ST (BIT(12)) +#define MCPWM_FAULT0_CLR_INT_ST_M (MCPWM_FAULT0_CLR_INT_ST_V << MCPWM_FAULT0_CLR_INT_ST_S) +#define MCPWM_FAULT0_CLR_INT_ST_V 0x00000001U +#define MCPWM_FAULT0_CLR_INT_ST_S 12 +/** MCPWM_FAULT1_CLR_INT_ST : RO; bitpos: [13]; default: 0; + * The masked status bit for the interrupt triggered when fault_event1 ends. + */ +#define MCPWM_FAULT1_CLR_INT_ST (BIT(13)) +#define MCPWM_FAULT1_CLR_INT_ST_M (MCPWM_FAULT1_CLR_INT_ST_V << MCPWM_FAULT1_CLR_INT_ST_S) +#define MCPWM_FAULT1_CLR_INT_ST_V 0x00000001U +#define MCPWM_FAULT1_CLR_INT_ST_S 13 +/** MCPWM_FAULT2_CLR_INT_ST : RO; bitpos: [14]; default: 0; + * The masked status bit for the interrupt triggered when fault_event2 ends. + */ +#define MCPWM_FAULT2_CLR_INT_ST (BIT(14)) +#define MCPWM_FAULT2_CLR_INT_ST_M (MCPWM_FAULT2_CLR_INT_ST_V << MCPWM_FAULT2_CLR_INT_ST_S) +#define MCPWM_FAULT2_CLR_INT_ST_V 0x00000001U +#define MCPWM_FAULT2_CLR_INT_ST_S 14 +/** MCPWM_OP0_TEA_INT_ST : RO; bitpos: [15]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 0 TEA event + */ +#define MCPWM_OP0_TEA_INT_ST (BIT(15)) +#define MCPWM_OP0_TEA_INT_ST_M (MCPWM_OP0_TEA_INT_ST_V << MCPWM_OP0_TEA_INT_ST_S) +#define MCPWM_OP0_TEA_INT_ST_V 0x00000001U +#define MCPWM_OP0_TEA_INT_ST_S 15 +/** MCPWM_OP1_TEA_INT_ST : RO; bitpos: [16]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 1 TEA event + */ +#define MCPWM_OP1_TEA_INT_ST (BIT(16)) +#define MCPWM_OP1_TEA_INT_ST_M (MCPWM_OP1_TEA_INT_ST_V << MCPWM_OP1_TEA_INT_ST_S) +#define MCPWM_OP1_TEA_INT_ST_V 0x00000001U +#define MCPWM_OP1_TEA_INT_ST_S 16 +/** MCPWM_OP2_TEA_INT_ST : RO; bitpos: [17]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 2 TEA event + */ +#define MCPWM_OP2_TEA_INT_ST (BIT(17)) +#define MCPWM_OP2_TEA_INT_ST_M (MCPWM_OP2_TEA_INT_ST_V << MCPWM_OP2_TEA_INT_ST_S) +#define MCPWM_OP2_TEA_INT_ST_V 0x00000001U +#define MCPWM_OP2_TEA_INT_ST_S 17 +/** MCPWM_OP0_TEB_INT_ST : RO; bitpos: [18]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 0 TEB event + */ +#define MCPWM_OP0_TEB_INT_ST (BIT(18)) +#define MCPWM_OP0_TEB_INT_ST_M (MCPWM_OP0_TEB_INT_ST_V << MCPWM_OP0_TEB_INT_ST_S) +#define MCPWM_OP0_TEB_INT_ST_V 0x00000001U +#define MCPWM_OP0_TEB_INT_ST_S 18 +/** MCPWM_OP1_TEB_INT_ST : RO; bitpos: [19]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 1 TEB event + */ +#define MCPWM_OP1_TEB_INT_ST (BIT(19)) +#define MCPWM_OP1_TEB_INT_ST_M (MCPWM_OP1_TEB_INT_ST_V << MCPWM_OP1_TEB_INT_ST_S) +#define MCPWM_OP1_TEB_INT_ST_V 0x00000001U +#define MCPWM_OP1_TEB_INT_ST_S 19 +/** MCPWM_OP2_TEB_INT_ST : RO; bitpos: [20]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 2 TEB event + */ +#define MCPWM_OP2_TEB_INT_ST (BIT(20)) +#define MCPWM_OP2_TEB_INT_ST_M (MCPWM_OP2_TEB_INT_ST_V << MCPWM_OP2_TEB_INT_ST_S) +#define MCPWM_OP2_TEB_INT_ST_V 0x00000001U +#define MCPWM_OP2_TEB_INT_ST_S 20 +/** MCPWM_FH0_CBC_INT_ST : RO; bitpos: [21]; default: 0; + * The masked status bit for the interrupt triggered by a cycle-by-cycle mode action + * on PWM0. + */ +#define MCPWM_FH0_CBC_INT_ST (BIT(21)) +#define MCPWM_FH0_CBC_INT_ST_M (MCPWM_FH0_CBC_INT_ST_V << MCPWM_FH0_CBC_INT_ST_S) +#define MCPWM_FH0_CBC_INT_ST_V 0x00000001U +#define MCPWM_FH0_CBC_INT_ST_S 21 +/** MCPWM_FH1_CBC_INT_ST : RO; bitpos: [22]; default: 0; + * The masked status bit for the interrupt triggered by a cycle-by-cycle mode action + * on PWM1. + */ +#define MCPWM_FH1_CBC_INT_ST (BIT(22)) +#define MCPWM_FH1_CBC_INT_ST_M (MCPWM_FH1_CBC_INT_ST_V << MCPWM_FH1_CBC_INT_ST_S) +#define MCPWM_FH1_CBC_INT_ST_V 0x00000001U +#define MCPWM_FH1_CBC_INT_ST_S 22 +/** MCPWM_FH2_CBC_INT_ST : RO; bitpos: [23]; default: 0; + * The masked status bit for the interrupt triggered by a cycle-by-cycle mode action + * on PWM2. + */ +#define MCPWM_FH2_CBC_INT_ST (BIT(23)) +#define MCPWM_FH2_CBC_INT_ST_M (MCPWM_FH2_CBC_INT_ST_V << MCPWM_FH2_CBC_INT_ST_S) +#define MCPWM_FH2_CBC_INT_ST_V 0x00000001U +#define MCPWM_FH2_CBC_INT_ST_S 23 +/** MCPWM_FH0_OST_INT_ST : RO; bitpos: [24]; default: 0; + * The masked status bit for the interrupt triggered by a one-shot mode action on PWM0. + */ +#define MCPWM_FH0_OST_INT_ST (BIT(24)) +#define MCPWM_FH0_OST_INT_ST_M (MCPWM_FH0_OST_INT_ST_V << MCPWM_FH0_OST_INT_ST_S) +#define MCPWM_FH0_OST_INT_ST_V 0x00000001U +#define MCPWM_FH0_OST_INT_ST_S 24 +/** MCPWM_FH1_OST_INT_ST : RO; bitpos: [25]; default: 0; + * The masked status bit for the interrupt triggered by a one-shot mode action on PWM1. + */ +#define MCPWM_FH1_OST_INT_ST (BIT(25)) +#define MCPWM_FH1_OST_INT_ST_M (MCPWM_FH1_OST_INT_ST_V << MCPWM_FH1_OST_INT_ST_S) +#define MCPWM_FH1_OST_INT_ST_V 0x00000001U +#define MCPWM_FH1_OST_INT_ST_S 25 +/** MCPWM_FH2_OST_INT_ST : RO; bitpos: [26]; default: 0; + * The masked status bit for the interrupt triggered by a one-shot mode action on PWM2. + */ +#define MCPWM_FH2_OST_INT_ST (BIT(26)) +#define MCPWM_FH2_OST_INT_ST_M (MCPWM_FH2_OST_INT_ST_V << MCPWM_FH2_OST_INT_ST_S) +#define MCPWM_FH2_OST_INT_ST_V 0x00000001U +#define MCPWM_FH2_OST_INT_ST_S 26 +/** MCPWM_CAP0_INT_ST : RO; bitpos: [27]; default: 0; + * The masked status bit for the interrupt triggered by capture on channel 0. + */ +#define MCPWM_CAP0_INT_ST (BIT(27)) +#define MCPWM_CAP0_INT_ST_M (MCPWM_CAP0_INT_ST_V << MCPWM_CAP0_INT_ST_S) +#define MCPWM_CAP0_INT_ST_V 0x00000001U +#define MCPWM_CAP0_INT_ST_S 27 +/** MCPWM_CAP1_INT_ST : RO; bitpos: [28]; default: 0; + * The masked status bit for the interrupt triggered by capture on channel 1. + */ +#define MCPWM_CAP1_INT_ST (BIT(28)) +#define MCPWM_CAP1_INT_ST_M (MCPWM_CAP1_INT_ST_V << MCPWM_CAP1_INT_ST_S) +#define MCPWM_CAP1_INT_ST_V 0x00000001U +#define MCPWM_CAP1_INT_ST_S 28 +/** MCPWM_CAP2_INT_ST : RO; bitpos: [29]; default: 0; + * The masked status bit for the interrupt triggered by capture on channel 2. + */ +#define MCPWM_CAP2_INT_ST (BIT(29)) +#define MCPWM_CAP2_INT_ST_M (MCPWM_CAP2_INT_ST_V << MCPWM_CAP2_INT_ST_S) +#define MCPWM_CAP2_INT_ST_V 0x00000001U +#define MCPWM_CAP2_INT_ST_S 29 -#define MCMCPWM_INT_CLR_MCPWM_REG(i) (REG_MCPWM_BASE(i) + 0x011c) -/* MCPWM_CAP2_INT_CLR : WO ;bitpos:[29] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered by captureon channel 2*/ -#define MCPWM_CAP2_INT_CLR (BIT(29)) -#define MCPWM_CAP2_INT_CLR_M (BIT(29)) -#define MCPWM_CAP2_INT_CLR_V 0x1 -#define MCPWM_CAP2_INT_CLR_S 29 -/* MCPWM_CAP1_INT_CLR : WO ;bitpos:[28] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered by captureon channel 1*/ -#define MCPWM_CAP1_INT_CLR (BIT(28)) -#define MCPWM_CAP1_INT_CLR_M (BIT(28)) -#define MCPWM_CAP1_INT_CLR_V 0x1 -#define MCPWM_CAP1_INT_CLR_S 28 -/* MCPWM_CAP0_INT_CLR : WO ;bitpos:[27] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered by captureon channel 0*/ -#define MCPWM_CAP0_INT_CLR (BIT(27)) -#define MCPWM_CAP0_INT_CLR_M (BIT(27)) -#define MCPWM_CAP0_INT_CLR_V 0x1 -#define MCPWM_CAP0_INT_CLR_S 27 -/* MCPWM_FH2_OST_INT_CLR : WO ;bitpos:[26] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered by an one-shot mode action on PWM2*/ -#define MCPWM_FH2_OST_INT_CLR (BIT(26)) -#define MCPWM_FH2_OST_INT_CLR_M (BIT(26)) -#define MCPWM_FH2_OST_INT_CLR_V 0x1 -#define MCPWM_FH2_OST_INT_CLR_S 26 -/* MCPWM_FH1_OST_INT_CLR : WO ;bitpos:[25] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered by an one-shot mode action on PWM0*/ -#define MCPWM_FH1_OST_INT_CLR (BIT(25)) -#define MCPWM_FH1_OST_INT_CLR_M (BIT(25)) -#define MCPWM_FH1_OST_INT_CLR_V 0x1 -#define MCPWM_FH1_OST_INT_CLR_S 25 -/* MCPWM_FH0_OST_INT_CLR : WO ;bitpos:[24] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered by an one-shot mode action on PWM0*/ -#define MCPWM_FH0_OST_INT_CLR (BIT(24)) -#define MCPWM_FH0_OST_INT_CLR_M (BIT(24)) -#define MCPWM_FH0_OST_INT_CLR_V 0x1 -#define MCPWM_FH0_OST_INT_CLR_S 24 -/* MCPWM_FH2_CBC_INT_CLR : WO ;bitpos:[23] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered by an cycle-by-cycle - mode action on PWM2*/ -#define MCPWM_FH2_CBC_INT_CLR (BIT(23)) -#define MCPWM_FH2_CBC_INT_CLR_M (BIT(23)) -#define MCPWM_FH2_CBC_INT_CLR_V 0x1 -#define MCPWM_FH2_CBC_INT_CLR_S 23 -/* MCPWM_FH1_CBC_INT_CLR : WO ;bitpos:[22] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered by an cycle-by-cycle - mode action on PWM1*/ -#define MCPWM_FH1_CBC_INT_CLR (BIT(22)) -#define MCPWM_FH1_CBC_INT_CLR_M (BIT(22)) -#define MCPWM_FH1_CBC_INT_CLR_V 0x1 -#define MCPWM_FH1_CBC_INT_CLR_S 22 -/* MCPWM_FH0_CBC_INT_CLR : WO ;bitpos:[21] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered by an cycle-by-cycle - mode action on PWM0*/ -#define MCPWM_FH0_CBC_INT_CLR (BIT(21)) -#define MCPWM_FH0_CBC_INT_CLR_M (BIT(21)) -#define MCPWM_FH0_CBC_INT_CLR_V 0x1 -#define MCPWM_FH0_CBC_INT_CLR_S 21 -/* MCPWM_OP2_TEB_INT_CLR : WO ;bitpos:[20] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered by a PWM operator 2 TEB event*/ -#define MCPWM_OP2_TEB_INT_CLR (BIT(20)) -#define MCPWM_OP2_TEB_INT_CLR_M (BIT(20)) -#define MCPWM_OP2_TEB_INT_CLR_V 0x1 -#define MCPWM_OP2_TEB_INT_CLR_S 20 -/* MCPWM_OP1_TEB_INT_CLR : WO ;bitpos:[19] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered by a PWM operator 1 TEB event*/ -#define MCPWM_OP1_TEB_INT_CLR (BIT(19)) -#define MCPWM_OP1_TEB_INT_CLR_M (BIT(19)) -#define MCPWM_OP1_TEB_INT_CLR_V 0x1 -#define MCPWM_OP1_TEB_INT_CLR_S 19 -/* MCPWM_OP0_TEB_INT_CLR : WO ;bitpos:[18] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered by a PWM operator 0 TEB event*/ -#define MCPWM_OP0_TEB_INT_CLR (BIT(18)) -#define MCPWM_OP0_TEB_INT_CLR_M (BIT(18)) -#define MCPWM_OP0_TEB_INT_CLR_V 0x1 -#define MCPWM_OP0_TEB_INT_CLR_S 18 -/* MCPWM_OP2_TEA_INT_CLR : WO ;bitpos:[17] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered by a PWM operator 2 TEA event*/ -#define MCPWM_OP2_TEA_INT_CLR (BIT(17)) -#define MCPWM_OP2_TEA_INT_CLR_M (BIT(17)) -#define MCPWM_OP2_TEA_INT_CLR_V 0x1 -#define MCPWM_OP2_TEA_INT_CLR_S 17 -/* MCPWM_OP1_TEA_INT_CLR : WO ;bitpos:[16] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered by a PWM operator 1 TEA event*/ -#define MCPWM_OP1_TEA_INT_CLR (BIT(16)) -#define MCPWM_OP1_TEA_INT_CLR_M (BIT(16)) -#define MCPWM_OP1_TEA_INT_CLR_V 0x1 -#define MCPWM_OP1_TEA_INT_CLR_S 16 -/* MCPWM_OP0_TEA_INT_CLR : WO ;bitpos:[15] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered by a PWM operator 0 TEA event*/ -#define MCPWM_OP0_TEA_INT_CLR (BIT(15)) -#define MCPWM_OP0_TEA_INT_CLR_M (BIT(15)) -#define MCPWM_OP0_TEA_INT_CLR_V 0x1 -#define MCPWM_OP0_TEA_INT_CLR_S 15 -/* MCPWM_FAULT2_CLR_INT_CLR : WO ;bitpos:[14] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered when event_f2 ends*/ -#define MCPWM_FAULT2_CLR_INT_CLR (BIT(14)) -#define MCPWM_FAULT2_CLR_INT_CLR_M (BIT(14)) -#define MCPWM_FAULT2_CLR_INT_CLR_V 0x1 -#define MCPWM_FAULT2_CLR_INT_CLR_S 14 -/* MCPWM_FAULT1_CLR_INT_CLR : WO ;bitpos:[13] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered when event_f1 ends*/ -#define MCPWM_FAULT1_CLR_INT_CLR (BIT(13)) -#define MCPWM_FAULT1_CLR_INT_CLR_M (BIT(13)) -#define MCPWM_FAULT1_CLR_INT_CLR_V 0x1 -#define MCPWM_FAULT1_CLR_INT_CLR_S 13 -/* MCPWM_FAULT0_CLR_INT_CLR : WO ;bitpos:[12] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered when event_f0 ends*/ -#define MCPWM_FAULT0_CLR_INT_CLR (BIT(12)) -#define MCPWM_FAULT0_CLR_INT_CLR_M (BIT(12)) -#define MCPWM_FAULT0_CLR_INT_CLR_V 0x1 -#define MCPWM_FAULT0_CLR_INT_CLR_S 12 -/* MCPWM_FAULT2_INT_CLR : WO ;bitpos:[11] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered when event_f2 starts*/ -#define MCPWM_FAULT2_INT_CLR (BIT(11)) -#define MCPWM_FAULT2_INT_CLR_M (BIT(11)) -#define MCPWM_FAULT2_INT_CLR_V 0x1 -#define MCPWM_FAULT2_INT_CLR_S 11 -/* MCPWM_FAULT1_INT_CLR : WO ;bitpos:[10] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered when event_f1 starts*/ -#define MCPWM_FAULT1_INT_CLR (BIT(10)) -#define MCPWM_FAULT1_INT_CLR_M (BIT(10)) -#define MCPWM_FAULT1_INT_CLR_V 0x1 -#define MCPWM_FAULT1_INT_CLR_S 10 -/* MCPWM_FAULT0_INT_CLR : WO ;bitpos:[9] ;default: 1'd0 ; */ -/*description: Set this bit to clear interrupt triggered when event_f0 starts*/ -#define MCPWM_FAULT0_INT_CLR (BIT(9)) -#define MCPWM_FAULT0_INT_CLR_M (BIT(9)) -#define MCPWM_FAULT0_INT_CLR_V 0x1 -#define MCPWM_FAULT0_INT_CLR_S 9 -/* MCPWM_TIMER2_TEP_INT_CLR : WO ;bitpos:[8] ;default: 1'h0 ; */ -/*description: Set this bit to clear interrupt triggered by a PWM timer 2 TEP event*/ -#define MCPWM_TIMER2_TEP_INT_CLR (BIT(8)) -#define MCPWM_TIMER2_TEP_INT_CLR_M (BIT(8)) -#define MCPWM_TIMER2_TEP_INT_CLR_V 0x1 -#define MCPWM_TIMER2_TEP_INT_CLR_S 8 -/* MCPWM_TIMER1_TEP_INT_CLR : WO ;bitpos:[7] ;default: 1'h0 ; */ -/*description: Set this bit to clear interrupt triggered by a PWM timer 1 TEP event*/ -#define MCPWM_TIMER1_TEP_INT_CLR (BIT(7)) -#define MCPWM_TIMER1_TEP_INT_CLR_M (BIT(7)) -#define MCPWM_TIMER1_TEP_INT_CLR_V 0x1 -#define MCPWM_TIMER1_TEP_INT_CLR_S 7 -/* MCPWM_TIMER0_TEP_INT_CLR : WO ;bitpos:[6] ;default: 1'h0 ; */ -/*description: Set this bit to clear interrupt triggered by a PWM timer 0 TEP event*/ -#define MCPWM_TIMER0_TEP_INT_CLR (BIT(6)) -#define MCPWM_TIMER0_TEP_INT_CLR_M (BIT(6)) -#define MCPWM_TIMER0_TEP_INT_CLR_V 0x1 -#define MCPWM_TIMER0_TEP_INT_CLR_S 6 -/* MCPWM_TIMER2_TEZ_INT_CLR : WO ;bitpos:[5] ;default: 1'h0 ; */ -/*description: Set this bit to clear interrupt triggered by a PWM timer 2 TEZ event*/ -#define MCPWM_TIMER2_TEZ_INT_CLR (BIT(5)) -#define MCPWM_TIMER2_TEZ_INT_CLR_M (BIT(5)) -#define MCPWM_TIMER2_TEZ_INT_CLR_V 0x1 -#define MCPWM_TIMER2_TEZ_INT_CLR_S 5 -/* MCPWM_TIMER1_TEZ_INT_CLR : WO ;bitpos:[4] ;default: 1'h0 ; */ -/*description: Set this bit to clear interrupt triggered by a PWM timer 1 TEZ event*/ -#define MCPWM_TIMER1_TEZ_INT_CLR (BIT(4)) -#define MCPWM_TIMER1_TEZ_INT_CLR_M (BIT(4)) -#define MCPWM_TIMER1_TEZ_INT_CLR_V 0x1 -#define MCPWM_TIMER1_TEZ_INT_CLR_S 4 -/* MCPWM_TIMER0_TEZ_INT_CLR : WO ;bitpos:[3] ;default: 1'h0 ; */ -/*description: Set this bit to clear interrupt triggered by a PWM timer 0 TEZ event*/ -#define MCPWM_TIMER0_TEZ_INT_CLR (BIT(3)) -#define MCPWM_TIMER0_TEZ_INT_CLR_M (BIT(3)) -#define MCPWM_TIMER0_TEZ_INT_CLR_V 0x1 -#define MCPWM_TIMER0_TEZ_INT_CLR_S 3 -/* MCPWM_TIMER2_STOP_INT_CLR : WO ;bitpos:[2] ;default: 1'h0 ; */ -/*description: Set this bit to clear interrupt triggered when timer 2 stops*/ -#define MCPWM_TIMER2_STOP_INT_CLR (BIT(2)) -#define MCPWM_TIMER2_STOP_INT_CLR_M (BIT(2)) -#define MCPWM_TIMER2_STOP_INT_CLR_V 0x1 -#define MCPWM_TIMER2_STOP_INT_CLR_S 2 -/* MCPWM_TIMER1_STOP_INT_CLR : WO ;bitpos:[1] ;default: 1'h0 ; */ -/*description: Set this bit to clear interrupt triggered when timer 1 stops*/ -#define MCPWM_TIMER1_STOP_INT_CLR (BIT(1)) -#define MCPWM_TIMER1_STOP_INT_CLR_M (BIT(1)) -#define MCPWM_TIMER1_STOP_INT_CLR_V 0x1 -#define MCPWM_TIMER1_STOP_INT_CLR_S 1 -/* MCPWM_TIMER0_STOP_INT_CLR : WO ;bitpos:[0] ;default: 1'h0 ; */ -/*description: Set this bit to clear interrupt triggered when timer 0 stops*/ -#define MCPWM_TIMER0_STOP_INT_CLR (BIT(0)) -#define MCPWM_TIMER0_STOP_INT_CLR_M (BIT(0)) -#define MCPWM_TIMER0_STOP_INT_CLR_V 0x1 +/** MCPWM_INT_CLR_REG register + * Interrupt clear bits + */ +#define MCPWM_INT_CLR_REG(i) (DR_REG_MCPWM_BASE(i) + 0x11c) +/** MCPWM_TIMER0_STOP_INT_CLR : WT; bitpos: [0]; default: 0; + * Set this bit to clear the interrupt triggered when the timer 0 stops. + */ +#define MCPWM_TIMER0_STOP_INT_CLR (BIT(0)) +#define MCPWM_TIMER0_STOP_INT_CLR_M (MCPWM_TIMER0_STOP_INT_CLR_V << MCPWM_TIMER0_STOP_INT_CLR_S) +#define MCPWM_TIMER0_STOP_INT_CLR_V 0x00000001U #define MCPWM_TIMER0_STOP_INT_CLR_S 0 +/** MCPWM_TIMER1_STOP_INT_CLR : WT; bitpos: [1]; default: 0; + * Set this bit to clear the interrupt triggered when the timer 1 stops. + */ +#define MCPWM_TIMER1_STOP_INT_CLR (BIT(1)) +#define MCPWM_TIMER1_STOP_INT_CLR_M (MCPWM_TIMER1_STOP_INT_CLR_V << MCPWM_TIMER1_STOP_INT_CLR_S) +#define MCPWM_TIMER1_STOP_INT_CLR_V 0x00000001U +#define MCPWM_TIMER1_STOP_INT_CLR_S 1 +/** MCPWM_TIMER2_STOP_INT_CLR : WT; bitpos: [2]; default: 0; + * Set this bit to clear the interrupt triggered when the timer 2 stops. + */ +#define MCPWM_TIMER2_STOP_INT_CLR (BIT(2)) +#define MCPWM_TIMER2_STOP_INT_CLR_M (MCPWM_TIMER2_STOP_INT_CLR_V << MCPWM_TIMER2_STOP_INT_CLR_S) +#define MCPWM_TIMER2_STOP_INT_CLR_V 0x00000001U +#define MCPWM_TIMER2_STOP_INT_CLR_S 2 +/** MCPWM_TIMER0_TEZ_INT_CLR : WT; bitpos: [3]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 0 TEZ event. + */ +#define MCPWM_TIMER0_TEZ_INT_CLR (BIT(3)) +#define MCPWM_TIMER0_TEZ_INT_CLR_M (MCPWM_TIMER0_TEZ_INT_CLR_V << MCPWM_TIMER0_TEZ_INT_CLR_S) +#define MCPWM_TIMER0_TEZ_INT_CLR_V 0x00000001U +#define MCPWM_TIMER0_TEZ_INT_CLR_S 3 +/** MCPWM_TIMER1_TEZ_INT_CLR : WT; bitpos: [4]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 1 TEZ event. + */ +#define MCPWM_TIMER1_TEZ_INT_CLR (BIT(4)) +#define MCPWM_TIMER1_TEZ_INT_CLR_M (MCPWM_TIMER1_TEZ_INT_CLR_V << MCPWM_TIMER1_TEZ_INT_CLR_S) +#define MCPWM_TIMER1_TEZ_INT_CLR_V 0x00000001U +#define MCPWM_TIMER1_TEZ_INT_CLR_S 4 +/** MCPWM_TIMER2_TEZ_INT_CLR : WT; bitpos: [5]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 2 TEZ event. + */ +#define MCPWM_TIMER2_TEZ_INT_CLR (BIT(5)) +#define MCPWM_TIMER2_TEZ_INT_CLR_M (MCPWM_TIMER2_TEZ_INT_CLR_V << MCPWM_TIMER2_TEZ_INT_CLR_S) +#define MCPWM_TIMER2_TEZ_INT_CLR_V 0x00000001U +#define MCPWM_TIMER2_TEZ_INT_CLR_S 5 +/** MCPWM_TIMER0_TEP_INT_CLR : WT; bitpos: [6]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 0 TEP event. + */ +#define MCPWM_TIMER0_TEP_INT_CLR (BIT(6)) +#define MCPWM_TIMER0_TEP_INT_CLR_M (MCPWM_TIMER0_TEP_INT_CLR_V << MCPWM_TIMER0_TEP_INT_CLR_S) +#define MCPWM_TIMER0_TEP_INT_CLR_V 0x00000001U +#define MCPWM_TIMER0_TEP_INT_CLR_S 6 +/** MCPWM_TIMER1_TEP_INT_CLR : WT; bitpos: [7]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 1 TEP event. + */ +#define MCPWM_TIMER1_TEP_INT_CLR (BIT(7)) +#define MCPWM_TIMER1_TEP_INT_CLR_M (MCPWM_TIMER1_TEP_INT_CLR_V << MCPWM_TIMER1_TEP_INT_CLR_S) +#define MCPWM_TIMER1_TEP_INT_CLR_V 0x00000001U +#define MCPWM_TIMER1_TEP_INT_CLR_S 7 +/** MCPWM_TIMER2_TEP_INT_CLR : WT; bitpos: [8]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 2 TEP event. + */ +#define MCPWM_TIMER2_TEP_INT_CLR (BIT(8)) +#define MCPWM_TIMER2_TEP_INT_CLR_M (MCPWM_TIMER2_TEP_INT_CLR_V << MCPWM_TIMER2_TEP_INT_CLR_S) +#define MCPWM_TIMER2_TEP_INT_CLR_V 0x00000001U +#define MCPWM_TIMER2_TEP_INT_CLR_S 8 +/** MCPWM_FAULT0_INT_CLR : WT; bitpos: [9]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event0 starts. + */ +#define MCPWM_FAULT0_INT_CLR (BIT(9)) +#define MCPWM_FAULT0_INT_CLR_M (MCPWM_FAULT0_INT_CLR_V << MCPWM_FAULT0_INT_CLR_S) +#define MCPWM_FAULT0_INT_CLR_V 0x00000001U +#define MCPWM_FAULT0_INT_CLR_S 9 +/** MCPWM_FAULT1_INT_CLR : WT; bitpos: [10]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event1 starts. + */ +#define MCPWM_FAULT1_INT_CLR (BIT(10)) +#define MCPWM_FAULT1_INT_CLR_M (MCPWM_FAULT1_INT_CLR_V << MCPWM_FAULT1_INT_CLR_S) +#define MCPWM_FAULT1_INT_CLR_V 0x00000001U +#define MCPWM_FAULT1_INT_CLR_S 10 +/** MCPWM_FAULT2_INT_CLR : WT; bitpos: [11]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event2 starts. + */ +#define MCPWM_FAULT2_INT_CLR (BIT(11)) +#define MCPWM_FAULT2_INT_CLR_M (MCPWM_FAULT2_INT_CLR_V << MCPWM_FAULT2_INT_CLR_S) +#define MCPWM_FAULT2_INT_CLR_V 0x00000001U +#define MCPWM_FAULT2_INT_CLR_S 11 +/** MCPWM_FAULT0_CLR_INT_CLR : WT; bitpos: [12]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event0 ends. + */ +#define MCPWM_FAULT0_CLR_INT_CLR (BIT(12)) +#define MCPWM_FAULT0_CLR_INT_CLR_M (MCPWM_FAULT0_CLR_INT_CLR_V << MCPWM_FAULT0_CLR_INT_CLR_S) +#define MCPWM_FAULT0_CLR_INT_CLR_V 0x00000001U +#define MCPWM_FAULT0_CLR_INT_CLR_S 12 +/** MCPWM_FAULT1_CLR_INT_CLR : WT; bitpos: [13]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event1 ends. + */ +#define MCPWM_FAULT1_CLR_INT_CLR (BIT(13)) +#define MCPWM_FAULT1_CLR_INT_CLR_M (MCPWM_FAULT1_CLR_INT_CLR_V << MCPWM_FAULT1_CLR_INT_CLR_S) +#define MCPWM_FAULT1_CLR_INT_CLR_V 0x00000001U +#define MCPWM_FAULT1_CLR_INT_CLR_S 13 +/** MCPWM_FAULT2_CLR_INT_CLR : WT; bitpos: [14]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event2 ends. + */ +#define MCPWM_FAULT2_CLR_INT_CLR (BIT(14)) +#define MCPWM_FAULT2_CLR_INT_CLR_M (MCPWM_FAULT2_CLR_INT_CLR_V << MCPWM_FAULT2_CLR_INT_CLR_S) +#define MCPWM_FAULT2_CLR_INT_CLR_V 0x00000001U +#define MCPWM_FAULT2_CLR_INT_CLR_S 14 +/** MCPWM_OP0_TEA_INT_CLR : WT; bitpos: [15]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 0 TEA event + */ +#define MCPWM_OP0_TEA_INT_CLR (BIT(15)) +#define MCPWM_OP0_TEA_INT_CLR_M (MCPWM_OP0_TEA_INT_CLR_V << MCPWM_OP0_TEA_INT_CLR_S) +#define MCPWM_OP0_TEA_INT_CLR_V 0x00000001U +#define MCPWM_OP0_TEA_INT_CLR_S 15 +/** MCPWM_OP1_TEA_INT_CLR : WT; bitpos: [16]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 1 TEA event + */ +#define MCPWM_OP1_TEA_INT_CLR (BIT(16)) +#define MCPWM_OP1_TEA_INT_CLR_M (MCPWM_OP1_TEA_INT_CLR_V << MCPWM_OP1_TEA_INT_CLR_S) +#define MCPWM_OP1_TEA_INT_CLR_V 0x00000001U +#define MCPWM_OP1_TEA_INT_CLR_S 16 +/** MCPWM_OP2_TEA_INT_CLR : WT; bitpos: [17]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 2 TEA event + */ +#define MCPWM_OP2_TEA_INT_CLR (BIT(17)) +#define MCPWM_OP2_TEA_INT_CLR_M (MCPWM_OP2_TEA_INT_CLR_V << MCPWM_OP2_TEA_INT_CLR_S) +#define MCPWM_OP2_TEA_INT_CLR_V 0x00000001U +#define MCPWM_OP2_TEA_INT_CLR_S 17 +/** MCPWM_OP0_TEB_INT_CLR : WT; bitpos: [18]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 0 TEB event + */ +#define MCPWM_OP0_TEB_INT_CLR (BIT(18)) +#define MCPWM_OP0_TEB_INT_CLR_M (MCPWM_OP0_TEB_INT_CLR_V << MCPWM_OP0_TEB_INT_CLR_S) +#define MCPWM_OP0_TEB_INT_CLR_V 0x00000001U +#define MCPWM_OP0_TEB_INT_CLR_S 18 +/** MCPWM_OP1_TEB_INT_CLR : WT; bitpos: [19]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 1 TEB event + */ +#define MCPWM_OP1_TEB_INT_CLR (BIT(19)) +#define MCPWM_OP1_TEB_INT_CLR_M (MCPWM_OP1_TEB_INT_CLR_V << MCPWM_OP1_TEB_INT_CLR_S) +#define MCPWM_OP1_TEB_INT_CLR_V 0x00000001U +#define MCPWM_OP1_TEB_INT_CLR_S 19 +/** MCPWM_OP2_TEB_INT_CLR : WT; bitpos: [20]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 2 TEB event + */ +#define MCPWM_OP2_TEB_INT_CLR (BIT(20)) +#define MCPWM_OP2_TEB_INT_CLR_M (MCPWM_OP2_TEB_INT_CLR_V << MCPWM_OP2_TEB_INT_CLR_S) +#define MCPWM_OP2_TEB_INT_CLR_V 0x00000001U +#define MCPWM_OP2_TEB_INT_CLR_S 20 +/** MCPWM_FH0_CBC_INT_CLR : WT; bitpos: [21]; default: 0; + * Set this bit to clear the interrupt triggered by a cycle-by-cycle mode action on + * PWM0. + */ +#define MCPWM_FH0_CBC_INT_CLR (BIT(21)) +#define MCPWM_FH0_CBC_INT_CLR_M (MCPWM_FH0_CBC_INT_CLR_V << MCPWM_FH0_CBC_INT_CLR_S) +#define MCPWM_FH0_CBC_INT_CLR_V 0x00000001U +#define MCPWM_FH0_CBC_INT_CLR_S 21 +/** MCPWM_FH1_CBC_INT_CLR : WT; bitpos: [22]; default: 0; + * Set this bit to clear the interrupt triggered by a cycle-by-cycle mode action on + * PWM1. + */ +#define MCPWM_FH1_CBC_INT_CLR (BIT(22)) +#define MCPWM_FH1_CBC_INT_CLR_M (MCPWM_FH1_CBC_INT_CLR_V << MCPWM_FH1_CBC_INT_CLR_S) +#define MCPWM_FH1_CBC_INT_CLR_V 0x00000001U +#define MCPWM_FH1_CBC_INT_CLR_S 22 +/** MCPWM_FH2_CBC_INT_CLR : WT; bitpos: [23]; default: 0; + * Set this bit to clear the interrupt triggered by a cycle-by-cycle mode action on + * PWM2. + */ +#define MCPWM_FH2_CBC_INT_CLR (BIT(23)) +#define MCPWM_FH2_CBC_INT_CLR_M (MCPWM_FH2_CBC_INT_CLR_V << MCPWM_FH2_CBC_INT_CLR_S) +#define MCPWM_FH2_CBC_INT_CLR_V 0x00000001U +#define MCPWM_FH2_CBC_INT_CLR_S 23 +/** MCPWM_FH0_OST_INT_CLR : WT; bitpos: [24]; default: 0; + * Set this bit to clear the interrupt triggered by a one-shot mode action on PWM0. + */ +#define MCPWM_FH0_OST_INT_CLR (BIT(24)) +#define MCPWM_FH0_OST_INT_CLR_M (MCPWM_FH0_OST_INT_CLR_V << MCPWM_FH0_OST_INT_CLR_S) +#define MCPWM_FH0_OST_INT_CLR_V 0x00000001U +#define MCPWM_FH0_OST_INT_CLR_S 24 +/** MCPWM_FH1_OST_INT_CLR : WT; bitpos: [25]; default: 0; + * Set this bit to clear the interrupt triggered by a one-shot mode action on PWM1. + */ +#define MCPWM_FH1_OST_INT_CLR (BIT(25)) +#define MCPWM_FH1_OST_INT_CLR_M (MCPWM_FH1_OST_INT_CLR_V << MCPWM_FH1_OST_INT_CLR_S) +#define MCPWM_FH1_OST_INT_CLR_V 0x00000001U +#define MCPWM_FH1_OST_INT_CLR_S 25 +/** MCPWM_FH2_OST_INT_CLR : WT; bitpos: [26]; default: 0; + * Set this bit to clear the interrupt triggered by a one-shot mode action on PWM2. + */ +#define MCPWM_FH2_OST_INT_CLR (BIT(26)) +#define MCPWM_FH2_OST_INT_CLR_M (MCPWM_FH2_OST_INT_CLR_V << MCPWM_FH2_OST_INT_CLR_S) +#define MCPWM_FH2_OST_INT_CLR_V 0x00000001U +#define MCPWM_FH2_OST_INT_CLR_S 26 +/** MCPWM_CAP0_INT_CLR : WT; bitpos: [27]; default: 0; + * Set this bit to clear the interrupt triggered by capture on channel 0. + */ +#define MCPWM_CAP0_INT_CLR (BIT(27)) +#define MCPWM_CAP0_INT_CLR_M (MCPWM_CAP0_INT_CLR_V << MCPWM_CAP0_INT_CLR_S) +#define MCPWM_CAP0_INT_CLR_V 0x00000001U +#define MCPWM_CAP0_INT_CLR_S 27 +/** MCPWM_CAP1_INT_CLR : WT; bitpos: [28]; default: 0; + * Set this bit to clear the interrupt triggered by capture on channel 1. + */ +#define MCPWM_CAP1_INT_CLR (BIT(28)) +#define MCPWM_CAP1_INT_CLR_M (MCPWM_CAP1_INT_CLR_V << MCPWM_CAP1_INT_CLR_S) +#define MCPWM_CAP1_INT_CLR_V 0x00000001U +#define MCPWM_CAP1_INT_CLR_S 28 +/** MCPWM_CAP2_INT_CLR : WT; bitpos: [29]; default: 0; + * Set this bit to clear the interrupt triggered by capture on channel 2. + */ +#define MCPWM_CAP2_INT_CLR (BIT(29)) +#define MCPWM_CAP2_INT_CLR_M (MCPWM_CAP2_INT_CLR_V << MCPWM_CAP2_INT_CLR_S) +#define MCPWM_CAP2_INT_CLR_V 0x00000001U +#define MCPWM_CAP2_INT_CLR_S 29 -#define MCPWM_CLK_REG(i) (REG_MCPWM_BASE(i) + 0x0120) -/* MCPWM_CLK_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: Force clock on for this reg file*/ -#define MCPWM_CLK_EN (BIT(0)) -#define MCPWM_CLK_EN_M (BIT(0)) -#define MCPWM_CLK_EN_V 0x1 +/** MCPWM_CLK_REG register + * MCPWM APB configuration register + */ +#define MCPWM_CLK_REG(i) (DR_REG_MCPWM_BASE(i) + 0x120) +/** MCPWM_CLK_EN : R/W; bitpos: [0]; default: 0; + * Force clock on for this register file + */ +#define MCPWM_CLK_EN (BIT(0)) +#define MCPWM_CLK_EN_M (MCPWM_CLK_EN_V << MCPWM_CLK_EN_S) +#define MCPWM_CLK_EN_V 0x00000001U #define MCPWM_CLK_EN_S 0 -#define MCPWM_VERSION_REG(i) (REG_MCPWM_BASE(i) + 0x0124) -/* MCPWM_DATE : R/W ;bitpos:[27:0] ;default: 28'h1509110 ; */ -/*description: Version of this reg file*/ -#define MCPWM_DATE 0x0FFFFFFF -#define MCPWM_DATE_M ((MCPWM_DATE_V)<<(MCPWM_DATE_S)) -#define MCPWM_DATE_V 0xFFFFFFF +/** MCPWM_VERSION_REG register + * Version register. + */ +#define MCPWM_VERSION_REG(i) (DR_REG_MCPWM_BASE(i) + 0x124) +/** MCPWM_DATE : R/W; bitpos: [27:0]; default: 34632240; + * Version of this register file + */ +#define MCPWM_DATE 0x0FFFFFFFU +#define MCPWM_DATE_M (MCPWM_DATE_V << MCPWM_DATE_S) +#define MCPWM_DATE_V 0x0FFFFFFFU #define MCPWM_DATE_S 0 - - - -#endif /*_SOC_MCPWM_REG_H_ */ +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32/include/soc/mcpwm_struct.h b/components/soc/esp32/include/soc/mcpwm_struct.h index 87f3f22727..4e13290fe8 100644 --- a/components/soc/esp32/include/soc/mcpwm_struct.h +++ b/components/soc/esp32/include/soc/mcpwm_struct.h @@ -1,461 +1,1468 @@ -// 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: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once #include - #ifdef __cplusplus extern "C" { #endif -typedef volatile struct mcpwm_dev_s { - union { - struct { - uint32_t prescale : 8; /*Period of PWM_clk = 6.25ns * (PWM_CLK_PRESCALE + 1)*/ - uint32_t reserved8 : 24; - }; - uint32_t val; - } clk_cfg; +/** Group: Prescaler configuration */ +/** Type of clk_cfg register + * PWM clock prescaler register. + */ +typedef union { struct { - union { - struct { - uint32_t prescale : 8; /*period of PT0_clk = Period of PWM_clk * (PWM_TIMER0_PRESCALE + 1)*/ - uint32_t period : 16; /*period shadow reg of PWM timer0*/ - uint32_t upmethod : 2; /*Update method for active reg of PWM timer0 period 0: immediate 1: TEZ 2: sync 3: TEZ | sync. TEZ here and below means timer equal zero event*/ - uint32_t reserved26 : 6; - }; - uint32_t val; - } period; - union { - struct { - uint32_t start : 3; /*PWM timer0 start and stop control. 0: stop @ TEZ 1: stop @ TEP 2: free run 3: start and stop @ next TEZ 4: start and stop @ next TEP. TEP here and below means timer equal period event*/ - uint32_t mode : 2; /*PWM timer0 working mode 0: freeze 1: increase mod 2: decrease mod 3: up-down mod*/ - uint32_t reserved5 : 27; - }; - uint32_t val; - } mode; - union { - struct { - uint32_t in_en : 1; /*when set timer reload with phase on sync input event is enabled*/ - uint32_t sync_sw : 1; /*write the negate value will trigger a software sync*/ - uint32_t out_sel : 2; /*PWM timer0 synco selection 0: synci 1: TEZ 2: TEP else 0*/ - uint32_t timer_phase : 16; /*phase for timer reload on sync event*/ - uint32_t phase_direct : 1; /*counter direction to apply on sync event*/ - uint32_t reserved21 : 11; - }; - uint32_t val; - } sync; - union { - struct { - uint32_t value : 16; /*current PWM timer0 counter value*/ - uint32_t direction : 1; /*current PWM timer0 counter direction 0: increment 1: decrement*/ - uint32_t reserved17 : 15; - }; - uint32_t val; - } status; - } timer[3]; + /** clk_prescale : R/W; bitpos: [7:0]; default: 0; + * Period of PWM_clk = 6.25ns * (PWM_CLK_PRESCALE + 1) + */ + uint32_t clk_prescale: 8; + uint32_t reserved_8: 24; + }; + uint32_t val; +} mcpwm_clk_cfg_reg_t; - union { - struct { - uint32_t t0_in_sel : 3; /*select sync input for PWM timer0 1: PWM timer0 synco 2: PWM timer1 synco 3: PWM timer2 synco 4: SYNC0 from GPIO matrix 5: SYNC1 from GPIO matrix 6: SYNC2 from GPIO matrix else: none*/ - uint32_t t1_in_sel : 3; /*select sync input for PWM timer1 1: PWM timer0 synco 2: PWM timer1 synco 3: PWM timer2 synco 4: SYNC0 from GPIO matrix 5: SYNC1 from GPIO matrix 6: SYNC2 from GPIO matrix else: none*/ - uint32_t t2_in_sel : 3; /*select sync input for PWM timer2 1: PWM timer0 synco 2: PWM timer1 synco 3: PWM timer2 synco 4: SYNC0 from GPIO matrix 5: SYNC1 from GPIO matrix 6: SYNC2 from GPIO matrix else: none*/ - uint32_t ext_in0_inv : 1; /*invert SYNC0 from GPIO matrix*/ - uint32_t ext_in1_inv : 1; /*invert SYNC1 from GPIO matrix*/ - uint32_t ext_in2_inv : 1; /*invert SYNC2 from GPIO matrix*/ - uint32_t reserved12 : 20; - }; - uint32_t val; - } timer_synci_cfg; - union { - struct { - uint32_t operator0_sel : 2; /*Select which PWM timer's is the timing reference for PWM operator0 0: timer0 1: timer1 2: timer2*/ - uint32_t operator1_sel : 2; /*Select which PWM timer's is the timing reference for PWM operator1 0: timer0 1: timer1 2: timer2*/ - uint32_t operator2_sel : 2; /*Select which PWM timer's is the timing reference for PWM operator2 0: timer0 1: timer1 2: timer2*/ - uint32_t reserved6 : 26; - }; - uint32_t val; - } timer_sel; +/** Group: MCPWM Timer Configuration and status */ +/** Type of timer_cfg0 register + * PWM timer period and update method configuration register. + */ +typedef union { struct { - union { - struct { - uint32_t a_upmethod : 4; /*Update method for PWM compare0 A's active reg. 0: immediate bit0: TEZ bit1: TEP bit2: sync bit3: freeze*/ - uint32_t b_upmethod : 4; /*Update method for PWM compare0 B's active reg. 0: immediate bit0: TEZ bit1: TEP bit2: sync bit3: freeze*/ - uint32_t a_shdw_full : 1; /*Set and reset by hardware. If set PWM compare0 A's shadow reg is filled and waiting to be transferred to A's active reg. If cleared A's active reg has been updated with shadow reg latest value*/ - uint32_t b_shdw_full : 1; /*Set and reset by hardware. If set PWM compare0 B's shadow reg is filled and waiting to be transferred to B's active reg. If cleared B's active reg has been updated with shadow reg latest value*/ - uint32_t reserved10 : 22; - }; - uint32_t val; - } cmpr_cfg; - union { - struct { - uint32_t cmpr_val : 16; /*PWM compare0 A's shadow reg*/ - uint32_t reserved16 : 16; - }; - uint32_t val; - } cmpr_value[2]; - union { - struct { - uint32_t upmethod : 4; /*Update method for PWM generate0's active reg of configuration. 0: immediate bit0: TEZ bit1: TEP bit2: sync. bit3: freeze*/ - uint32_t t0_sel : 3; /*Source selection for PWM generate0 event_t0 take effect immediately 0: fault_event0 1: fault_event1 2: fault_event2 3: sync_taken 4: none*/ - uint32_t t1_sel : 3; /*Source selection for PWM generate0 event_t1 take effect immediately 0: fault_event0 1: fault_event1 2: fault_event2 3: sync_taken 4: none*/ - uint32_t reserved10 : 22; - }; - uint32_t val; - } gen_cfg0; - union { - struct { - uint32_t cntu_force_upmethod : 6; /*Update method for continuous software force of PWM generate0. 0: immediate bit0: TEZ bit1: TEP bit2: TEA bit3: TEB bit4: sync bit5: freeze. (TEA/B here and below means timer equals A/B event)*/ - uint32_t a_cntuforce_mode : 2; /*Continuous software force mode for PWM0A. 0: disabled 1: low 2: high 3: disabled*/ - uint32_t b_cntuforce_mode : 2; /*Continuous software force mode for PWM0B. 0: disabled 1: low 2: high 3: disabled*/ - uint32_t a_nciforce : 1; /*non-continuous immediate software force trigger for PWM0A a toggle will trigger a force event*/ - uint32_t a_nciforce_mode : 2; /*non-continuous immediate software force mode for PWM0A 0: disabled 1: low 2: high 3: disabled*/ - uint32_t b_nciforce : 1; /*non-continuous immediate software force trigger for PWM0B a toggle will trigger a force event*/ - uint32_t b_nciforce_mode : 2; /*non-continuous immediate software force mode for PWM0B 0: disabled 1: low 2: high 3: disabled*/ - uint32_t reserved16 : 16; - }; - uint32_t val; - } gen_force; - union { - struct { - uint32_t utez : 2; /*Action on PWM0A triggered by event TEZ when timer increasing*/ - uint32_t utep : 2; /*Action on PWM0A triggered by event TEP when timer increasing*/ - uint32_t utea : 2; /*Action on PWM0A triggered by event TEA when timer increasing*/ - uint32_t uteb : 2; /*Action on PWM0A triggered by event TEB when timer increasing*/ - uint32_t ut0 : 2; /*Action on PWM0A triggered by event_t0 when timer increasing*/ - uint32_t ut1 : 2; /*Action on PWM0A triggered by event_t1 when timer increasing*/ - uint32_t dtez : 2; /*Action on PWM0A triggered by event TEZ when timer decreasing*/ - uint32_t dtep : 2; /*Action on PWM0A triggered by event TEP when timer decreasing*/ - uint32_t dtea : 2; /*Action on PWM0A triggered by event TEA when timer decreasing*/ - uint32_t dteb : 2; /*Action on PWM0A triggered by event TEB when timer decreasing*/ - uint32_t dt0 : 2; /*Action on PWM0A triggered by event_t0 when timer decreasing*/ - uint32_t dt1 : 2; /*Action on PWM0A triggered by event_t1 when timer decreasing. 0: no change 1: low 2: high 3: toggle*/ - uint32_t reserved24 : 8; - }; - uint32_t val; - } generator[2]; - union { - struct { - uint32_t fed_upmethod : 4; /*Update method for FED (falling edge delay) active reg. 0: immediate bit0: tez bit1: tep bit2: sync bit3: freeze*/ - uint32_t red_upmethod : 4; /*Update method for RED (rising edge delay) active reg. 0: immediate bit0: tez bit1: tep bit2: sync bit3: freeze*/ - uint32_t deb_mode : 1; /*S8 in documentation dual-edge B mode 0: fed/red take effect on different path separately 1: fed/red take effect on B path A out is in bypass or dulpB mode*/ - uint32_t a_outswap : 1; /*S6 in documentation*/ - uint32_t b_outswap : 1; /*S7 in documentation*/ - uint32_t red_insel : 1; /*S4 in documentation*/ - uint32_t fed_insel : 1; /*S5 in documentation*/ - uint32_t red_outinvert : 1; /*S2 in documentation*/ - uint32_t fed_outinvert : 1; /*S3 in documentation*/ - uint32_t a_outbypass : 1; /*S1 in documentation*/ - uint32_t b_outbypass : 1; /*S0 in documentation*/ - uint32_t clk_sel : 1; /*Dead band0 clock selection. 0: PWM_clk 1: PT_clk*/ - uint32_t reserved18 : 14; - }; - uint32_t val; - } db_cfg; - union { - struct { - uint32_t fed : 16; /*Shadow reg for FED*/ - uint32_t reserved16 : 16; - }; - uint32_t val; - } db_fed_cfg; - union { - struct { - uint32_t red : 16; /*Shadow reg for RED*/ - uint32_t reserved16 : 16; - }; - uint32_t val; - } db_red_cfg; - union { - struct { - uint32_t en : 1; /*When set carrier0 function is enabled. When reset carrier0 is bypassed*/ - uint32_t prescale : 4; /*carrier0 clk (CP_clk) prescale value. Period of CP_clk = period of PWM_clk * (PWM_CARRIER0_PRESCALE + 1)*/ - uint32_t duty : 3; /*carrier duty selection. Duty = PWM_CARRIER0_DUTY / 8*/ - uint32_t oshtwth : 4; /*width of the fist pulse in number of periods of the carrier*/ - uint32_t out_invert : 1; /*when set invert the output of PWM0A and PWM0B for this submodule*/ - uint32_t in_invert : 1; /*when set invert the input of PWM0A and PWM0B for this submodule*/ - uint32_t reserved14 : 18; - }; - uint32_t val; - } carrier_cfg; - union { - struct { - uint32_t sw_cbc : 1; /*Cycle-by-cycle tripping software force event will trigger cycle-by-cycle trip event. 0: disable 1: enable*/ - uint32_t f2_cbc : 1; /*event_f2 will trigger cycle-by-cycle trip event. 0: disable 1: enable*/ - uint32_t f1_cbc : 1; /*event_f1 will trigger cycle-by-cycle trip event. 0: disable 1: enable*/ - uint32_t f0_cbc : 1; /*event_f0 will trigger cycle-by-cycle trip event. 0: disable 1: enable*/ - uint32_t sw_ost : 1; /*one-shot tripping software force event will trigger one-shot trip event. 0: disable 1: enable*/ - uint32_t f2_ost : 1; /*event_f2 will trigger one-shot trip event. 0: disable 1: enable*/ - uint32_t f1_ost : 1; /*event_f1 will trigger one-shot trip event. 0: disable 1: enable*/ - uint32_t f0_ost : 1; /*event_f0 will trigger one-shot trip event. 0: disable 1: enable*/ - uint32_t a_cbc_d : 2; /*Action on PWM0A when cycle-by-cycle trip event occurs and timer is decreasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ - uint32_t a_cbc_u : 2; /*Action on PWM0A when cycle-by-cycle trip event occurs and timer is increasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ - uint32_t a_ost_d : 2; /*Action on PWM0A when one-shot trip event occurs and timer is decreasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ - uint32_t a_ost_u : 2; /*Action on PWM0A when one-shot trip event occurs and timer is increasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ - uint32_t b_cbc_d : 2; /*Action on PWM0B when cycle-by-cycle trip event occurs and timer is decreasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ - uint32_t b_cbc_u : 2; /*Action on PWM0B when cycle-by-cycle trip event occurs and timer is increasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ - uint32_t b_ost_d : 2; /*Action on PWM0B when one-shot trip event occurs and timer is decreasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ - uint32_t b_ost_u : 2; /*Action on PWM0B when one-shot trip event occurs and timer is increasing. 0: do nothing 1: force lo 2: force hi 3: toggle*/ - uint32_t reserved24 : 8; - }; - uint32_t val; - } tz_cfg0; - union { - struct { - uint32_t clr_ost : 1; /*a posedge will clear on going one-shot tripping*/ - uint32_t cbcpulse : 2; /*cycle-by-cycle tripping refresh moment selection. Bit0: TEZ bit1:TEP*/ - uint32_t force_cbc : 1; /*a toggle trigger a cycle-by-cycle tripping software force event*/ - uint32_t force_ost : 1; /*a toggle (software negate its value) trigger a one-shot tripping software force event*/ - uint32_t reserved5 : 27; - }; - uint32_t val; - } tz_cfg1; - union { - struct { - uint32_t cbc_on : 1; /*Set and reset by hardware. If set an cycle-by-cycle trip event is on going*/ - uint32_t ost_on : 1; /*Set and reset by hardware. If set an one-shot trip event is on going*/ - uint32_t reserved2 : 30; - }; - uint32_t val; - } tz_status; - } channel[3]; + /** timer_prescale : R/W; bitpos: [7:0]; default: 0; + * Configure the divisor of PT0_clk, takes effect when PWM timer stops and starts + * agsin. period of PT0_clk = Period of PWM_clk * (PWM_TIMER_PRESCALE + 1) + */ + uint32_t timer_prescale: 8; + /** timer_period : R/W; bitpos: [23:8]; default: 255; + * period shadow register of PWM timer + */ + uint32_t timer_period: 16; + /** timer_period_upmethod : R/W; bitpos: [25:24]; default: 0; + * Update method for active register of PWM timer period, 0: immediate, 1: TEZ, 2: + * sync, 3: TEZ or sync. TEZ here and below means timer equal zero event + */ + uint32_t timer_period_upmethod: 2; + uint32_t reserved_26: 6; + }; + uint32_t val; +} mcpwm_timer_cfg0_reg_t; - union { - struct { - uint32_t f0_en : 1; /*When set event_f0 generation is enabled*/ - uint32_t f1_en : 1; /*When set event_f1 generation is enabled*/ - uint32_t f2_en : 1; /*When set event_f2 generation is enabled*/ - uint32_t f0_pole : 1; /*Set event_f0 trigger polarity on FAULT0 source from GPIO matrix. 0: level low 1: level high*/ - uint32_t f1_pole : 1; /*Set event_f1 trigger polarity on FAULT1 source from GPIO matrix. 0: level low 1: level high*/ - uint32_t f2_pole : 1; /*Set event_f2 trigger polarity on FAULT2 source from GPIO matrix. 0: level low 1: level high*/ - uint32_t event_f0 : 1; /*Set and reset by hardware. If set event_f0 is on going*/ - uint32_t event_f1 : 1; /*Set and reset by hardware. If set event_f1 is on going*/ - uint32_t event_f2 : 1; /*Set and reset by hardware. If set event_f2 is on going*/ - uint32_t reserved9 : 23; - }; - uint32_t val; - } fault_detect; - union { - struct { - uint32_t timer_en : 1; /*When set capture timer incrementing under APB_clk is enabled.*/ - uint32_t synci_en : 1; /*When set capture timer sync is enabled.*/ - uint32_t synci_sel : 3; /*capture module sync input selection. 0: none 1: timer0 synco 2: timer1 synco 3: timer2 synco 4: SYNC0 from GPIO matrix 5: SYNC1 from GPIO matrix 6: SYNC2 from GPIO matrix*/ - uint32_t sync_sw : 1; /*Write 1 will force a capture timer sync capture timer is loaded with value in phase register.*/ - uint32_t reserved6 : 26; - }; - uint32_t val; - } cap_timer_cfg; - uint32_t cap_timer_phase; /*Phase value for capture timer sync operation.*/ - union { - struct { - uint32_t en : 1; /*When set capture on channel 0 is enabled*/ - uint32_t mode : 2; /*Edge of capture on channel 0 after prescale. bit0: negedge cap en bit1: posedge cap en*/ - uint32_t prescale : 8; /*Value of prescale on possitive edge of CAP0. Prescale value = PWM_CAP0_PRESCALE + 1*/ - uint32_t in_invert : 1; /*when set CAP0 form GPIO matrix is inverted before prescale*/ - uint32_t sw : 1; /*Write 1 will trigger a software forced capture on channel 0*/ - uint32_t reserved13 : 19; - }; - uint32_t val; - } cap_cfg_ch[3]; - uint32_t cap_val_ch[3]; /*Value of last capture on channel 0*/ - union { - struct { - uint32_t cap0_edge : 1; /*Edge of last capture trigger on channel 0 0: posedge 1: negedge*/ - uint32_t cap1_edge : 1; /*Edge of last capture trigger on channel 1 0: posedge 1: negedge*/ - uint32_t cap2_edge : 1; /*Edge of last capture trigger on channel 2 0: posedge 1: negedge*/ - uint32_t reserved3 : 29; - }; - uint32_t val; - } cap_status; - union { - struct { - uint32_t global_up_en : 1; /*The global enable of update of all active registers in MCPWM module*/ - uint32_t global_force_up : 1; /*a toggle (software invert its value) will trigger a forced update of all active registers in MCPWM module*/ - uint32_t op0_up_en : 1; /*When set and PWM_GLOBAL_UP_EN is set update of active registers in PWM operator 0 are enabled*/ - uint32_t op0_force_up : 1; /*a toggle (software invert its value) will trigger a forced update of active registers in PWM operator 0*/ - uint32_t op1_up_en : 1; /*When set and PWM_GLOBAL_UP_EN is set update of active registers in PWM operator 1 are enabled*/ - uint32_t op1_force_up : 1; /*a toggle (software invert its value) will trigger a forced update of active registers in PWM operator 1*/ - uint32_t op2_up_en : 1; /*When set and PWM_GLOBAL_UP_EN is set update of active registers in PWM operator 2 are enabled*/ - uint32_t op2_force_up : 1; /*a toggle (software invert its value) will trigger a forced update of active registers in PWM operator 2*/ - uint32_t reserved8 : 24; - }; - uint32_t val; - } update_cfg; - union { - struct { - uint32_t timer0_stop_int_ena : 1; /*Interrupt when timer 0 stops*/ - uint32_t timer1_stop_int_ena : 1; /*Interrupt when timer 1 stops*/ - uint32_t timer2_stop_int_ena : 1; /*Interrupt when timer 2 stops*/ - uint32_t timer0_tez_int_ena : 1; /*A PWM timer 0 TEZ event will trigger this interrupt*/ - uint32_t timer1_tez_int_ena : 1; /*A PWM timer 1 TEZ event will trigger this interrupt*/ - uint32_t timer2_tez_int_ena : 1; /*A PWM timer 2 TEZ event will trigger this interrupt*/ - uint32_t timer0_tep_int_ena : 1; /*A PWM timer 0 TEP event will trigger this interrupt*/ - uint32_t timer1_tep_int_ena : 1; /*A PWM timer 1 TEP event will trigger this interrupt*/ - uint32_t timer2_tep_int_ena : 1; /*A PWM timer 2 TEP event will trigger this interrupt*/ - uint32_t fault0_int_ena : 1; /*Interrupt when event_f0 starts*/ - uint32_t fault1_int_ena : 1; /*Interrupt when event_f1 starts*/ - uint32_t fault2_int_ena : 1; /*Interrupt when event_f2 starts*/ - uint32_t fault0_clr_int_ena : 1; /*Interrupt when event_f0 ends*/ - uint32_t fault1_clr_int_ena : 1; /*Interrupt when event_f1 ends*/ - uint32_t fault2_clr_int_ena : 1; /*Interrupt when event_f2 ends*/ - uint32_t cmpr0_tea_int_ena : 1; /*A PWM operator 0 TEA event will trigger this interrupt*/ - uint32_t cmpr1_tea_int_ena : 1; /*A PWM operator 1 TEA event will trigger this interrupt*/ - uint32_t cmpr2_tea_int_ena : 1; /*A PWM operator 2 TEA event will trigger this interrupt*/ - uint32_t cmpr0_teb_int_ena : 1; /*A PWM operator 0 TEB event will trigger this interrupt*/ - uint32_t cmpr1_teb_int_ena : 1; /*A PWM operator 1 TEB event will trigger this interrupt*/ - uint32_t cmpr2_teb_int_ena : 1; /*A PWM operator 2 TEB event will trigger this interrupt*/ - uint32_t tz0_cbc_int_ena : 1; /*An cycle-by-cycle trip event on PWM0 will trigger this interrupt*/ - uint32_t tz1_cbc_int_ena : 1; /*An cycle-by-cycle trip event on PWM1 will trigger this interrupt*/ - uint32_t tz2_cbc_int_ena : 1; /*An cycle-by-cycle trip event on PWM2 will trigger this interrupt*/ - uint32_t tz0_ost_int_ena : 1; /*An one-shot trip event on PWM0 will trigger this interrupt*/ - uint32_t tz1_ost_int_ena : 1; /*An one-shot trip event on PWM1 will trigger this interrupt*/ - uint32_t tz2_ost_int_ena : 1; /*An one-shot trip event on PWM2 will trigger this interrupt*/ - uint32_t cap0_int_ena : 1; /*A capture on channel 0 will trigger this interrupt*/ - uint32_t cap1_int_ena : 1; /*A capture on channel 1 will trigger this interrupt*/ - uint32_t cap2_int_ena : 1; /*A capture on channel 2 will trigger this interrupt*/ - uint32_t reserved30 : 2; - }; - uint32_t val; - } int_ena; - union { - struct { - uint32_t timer0_stop_int_raw : 1; /*Interrupt when timer 0 stops*/ - uint32_t timer1_stop_int_raw : 1; /*Interrupt when timer 1 stops*/ - uint32_t timer2_stop_int_raw : 1; /*Interrupt when timer 2 stops*/ - uint32_t timer0_tez_int_raw : 1; /*A PWM timer 0 TEZ event will trigger this interrupt*/ - uint32_t timer1_tez_int_raw : 1; /*A PWM timer 1 TEZ event will trigger this interrupt*/ - uint32_t timer2_tez_int_raw : 1; /*A PWM timer 2 TEZ event will trigger this interrupt*/ - uint32_t timer0_tep_int_raw : 1; /*A PWM timer 0 TEP event will trigger this interrupt*/ - uint32_t timer1_tep_int_raw : 1; /*A PWM timer 1 TEP event will trigger this interrupt*/ - uint32_t timer2_tep_int_raw : 1; /*A PWM timer 2 TEP event will trigger this interrupt*/ - uint32_t fault0_int_raw : 1; /*Interrupt when event_f0 starts*/ - uint32_t fault1_int_raw : 1; /*Interrupt when event_f1 starts*/ - uint32_t fault2_int_raw : 1; /*Interrupt when event_f2 starts*/ - uint32_t fault0_clr_int_raw : 1; /*Interrupt when event_f0 ends*/ - uint32_t fault1_clr_int_raw : 1; /*Interrupt when event_f1 ends*/ - uint32_t fault2_clr_int_raw : 1; /*Interrupt when event_f2 ends*/ - uint32_t cmpr0_tea_int_raw : 1; /*A PWM operator 0 TEA event will trigger this interrupt*/ - uint32_t cmpr1_tea_int_raw : 1; /*A PWM operator 1 TEA event will trigger this interrupt*/ - uint32_t cmpr2_tea_int_raw : 1; /*A PWM operator 2 TEA event will trigger this interrupt*/ - uint32_t cmpr0_teb_int_raw : 1; /*A PWM operator 0 TEB event will trigger this interrupt*/ - uint32_t cmpr1_teb_int_raw : 1; /*A PWM operator 1 TEB event will trigger this interrupt*/ - uint32_t cmpr2_teb_int_raw : 1; /*A PWM operator 2 TEB event will trigger this interrupt*/ - uint32_t tz0_cbc_int_raw : 1; /*An cycle-by-cycle trip event on PWM0 will trigger this interrupt*/ - uint32_t tz1_cbc_int_raw : 1; /*An cycle-by-cycle trip event on PWM1 will trigger this interrupt*/ - uint32_t tz2_cbc_int_raw : 1; /*An cycle-by-cycle trip event on PWM2 will trigger this interrupt*/ - uint32_t tz0_ost_int_raw : 1; /*An one-shot trip event on PWM0 will trigger this interrupt*/ - uint32_t tz1_ost_int_raw : 1; /*An one-shot trip event on PWM1 will trigger this interrupt*/ - uint32_t tz2_ost_int_raw : 1; /*An one-shot trip event on PWM2 will trigger this interrupt*/ - uint32_t cap0_int_raw : 1; /*A capture on channel 0 will trigger this interrupt*/ - uint32_t cap1_int_raw : 1; /*A capture on channel 1 will trigger this interrupt*/ - uint32_t cap2_int_raw : 1; /*A capture on channel 2 will trigger this interrupt*/ - uint32_t reserved30 : 2; - }; - uint32_t val; - } int_raw; - union { - struct { - uint32_t timer0_stop_int_st : 1; /*Interrupt when timer 0 stops*/ - uint32_t timer1_stop_int_st : 1; /*Interrupt when timer 1 stops*/ - uint32_t timer2_stop_int_st : 1; /*Interrupt when timer 2 stops*/ - uint32_t timer0_tez_int_st : 1; /*A PWM timer 0 TEZ event will trigger this interrupt*/ - uint32_t timer1_tez_int_st : 1; /*A PWM timer 1 TEZ event will trigger this interrupt*/ - uint32_t timer2_tez_int_st : 1; /*A PWM timer 2 TEZ event will trigger this interrupt*/ - uint32_t timer0_tep_int_st : 1; /*A PWM timer 0 TEP event will trigger this interrupt*/ - uint32_t timer1_tep_int_st : 1; /*A PWM timer 1 TEP event will trigger this interrupt*/ - uint32_t timer2_tep_int_st : 1; /*A PWM timer 2 TEP event will trigger this interrupt*/ - uint32_t fault0_int_st : 1; /*Interrupt when event_f0 starts*/ - uint32_t fault1_int_st : 1; /*Interrupt when event_f1 starts*/ - uint32_t fault2_int_st : 1; /*Interrupt when event_f2 starts*/ - uint32_t fault0_clr_int_st : 1; /*Interrupt when event_f0 ends*/ - uint32_t fault1_clr_int_st : 1; /*Interrupt when event_f1 ends*/ - uint32_t fault2_clr_int_st : 1; /*Interrupt when event_f2 ends*/ - uint32_t cmpr0_tea_int_st : 1; /*A PWM operator 0 TEA event will trigger this interrupt*/ - uint32_t cmpr1_tea_int_st : 1; /*A PWM operator 1 TEA event will trigger this interrupt*/ - uint32_t cmpr2_tea_int_st : 1; /*A PWM operator 2 TEA event will trigger this interrupt*/ - uint32_t cmpr0_teb_int_st : 1; /*A PWM operator 0 TEB event will trigger this interrupt*/ - uint32_t cmpr1_teb_int_st : 1; /*A PWM operator 1 TEB event will trigger this interrupt*/ - uint32_t cmpr2_teb_int_st : 1; /*A PWM operator 2 TEB event will trigger this interrupt*/ - uint32_t tz0_cbc_int_st : 1; /*An cycle-by-cycle trip event on PWM0 will trigger this interrupt*/ - uint32_t tz1_cbc_int_st : 1; /*An cycle-by-cycle trip event on PWM1 will trigger this interrupt*/ - uint32_t tz2_cbc_int_st : 1; /*An cycle-by-cycle trip event on PWM2 will trigger this interrupt*/ - uint32_t tz0_ost_int_st : 1; /*An one-shot trip event on PWM0 will trigger this interrupt*/ - uint32_t tz1_ost_int_st : 1; /*An one-shot trip event on PWM1 will trigger this interrupt*/ - uint32_t tz2_ost_int_st : 1; /*An one-shot trip event on PWM2 will trigger this interrupt*/ - uint32_t cap0_int_st : 1; /*A capture on channel 0 will trigger this interrupt*/ - uint32_t cap1_int_st : 1; /*A capture on channel 1 will trigger this interrupt*/ - uint32_t cap2_int_st : 1; /*A capture on channel 2 will trigger this interrupt*/ - uint32_t reserved30 : 2; - }; - uint32_t val; - } int_st; - union { - struct { - uint32_t timer0_stop_int_clr : 1; /*Interrupt when timer 0 stops*/ - uint32_t timer1_stop_int_clr : 1; /*Interrupt when timer 1 stops*/ - uint32_t timer2_stop_int_clr : 1; /*Interrupt when timer 2 stops*/ - uint32_t timer0_tez_int_clr : 1; /*A PWM timer 0 TEZ event will trigger this interrupt*/ - uint32_t timer1_tez_int_clr : 1; /*A PWM timer 1 TEZ event will trigger this interrupt*/ - uint32_t timer2_tez_int_clr : 1; /*A PWM timer 2 TEZ event will trigger this interrupt*/ - uint32_t timer0_tep_int_clr : 1; /*A PWM timer 0 TEP event will trigger this interrupt*/ - uint32_t timer1_tep_int_clr : 1; /*A PWM timer 1 TEP event will trigger this interrupt*/ - uint32_t timer2_tep_int_clr : 1; /*A PWM timer 2 TEP event will trigger this interrupt*/ - uint32_t fault0_int_clr : 1; /*Interrupt when event_f0 starts*/ - uint32_t fault1_int_clr : 1; /*Interrupt when event_f1 starts*/ - uint32_t fault2_int_clr : 1; /*Interrupt when event_f2 starts*/ - uint32_t fault0_clr_int_clr : 1; /*Interrupt when event_f0 ends*/ - uint32_t fault1_clr_int_clr : 1; /*Interrupt when event_f1 ends*/ - uint32_t fault2_clr_int_clr : 1; /*Interrupt when event_f2 ends*/ - uint32_t cmpr0_tea_int_clr : 1; /*A PWM operator 0 TEA event will trigger this interrupt*/ - uint32_t cmpr1_tea_int_clr : 1; /*A PWM operator 1 TEA event will trigger this interrupt*/ - uint32_t cmpr2_tea_int_clr : 1; /*A PWM operator 2 TEA event will trigger this interrupt*/ - uint32_t cmpr0_teb_int_clr : 1; /*A PWM operator 0 TEB event will trigger this interrupt*/ - uint32_t cmpr1_teb_int_clr : 1; /*A PWM operator 1 TEB event will trigger this interrupt*/ - uint32_t cmpr2_teb_int_clr : 1; /*A PWM operator 2 TEB event will trigger this interrupt*/ - uint32_t tz0_cbc_int_clr : 1; /*An cycle-by-cycle trip event on PWM0 will trigger this interrupt*/ - uint32_t tz1_cbc_int_clr : 1; /*An cycle-by-cycle trip event on PWM1 will trigger this interrupt*/ - uint32_t tz2_cbc_int_clr : 1; /*An cycle-by-cycle trip event on PWM2 will trigger this interrupt*/ - uint32_t tz0_ost_int_clr : 1; /*An one-shot trip event on PWM0 will trigger this interrupt*/ - uint32_t tz1_ost_int_clr : 1; /*An one-shot trip event on PWM1 will trigger this interrupt*/ - uint32_t tz2_ost_int_clr : 1; /*An one-shot trip event on PWM2 will trigger this interrupt*/ - uint32_t cap0_int_clr : 1; /*A capture on channel 0 will trigger this interrupt*/ - uint32_t cap1_int_clr : 1; /*A capture on channel 1 will trigger this interrupt*/ - uint32_t cap2_int_clr : 1; /*A capture on channel 2 will trigger this interrupt*/ - uint32_t reserved30 : 2; - }; - uint32_t val; - } int_clr; - union { - struct { - uint32_t clk_en : 1; /*Force clock on for this reg file*/ - uint32_t reserved1 : 31; - }; - uint32_t val; - } reg_clk; - union { - struct { - uint32_t date : 28; /*Version of this reg file*/ - uint32_t reserved28 : 4; - }; - uint32_t val; - } version; +/** Type of timer_cfg1 register + * PWM timer working mode and start/stop control configuration register. + */ +typedef union { + struct { + /** timer_start : R/W/SC; bitpos: [2:0]; default: 0; + * PWM timer start and stop control. 0: if PWM timer starts, then stops at TEZ, 1: + * if timer starts, then stops at TEP, 2: PWM timer starts and runs on, 3: timer + * starts and stops at the next TEZ, 4: timer starts and stops at the next TEP. TEP + * here and below means the event that happens when the timer equals to period + */ + uint32_t timer_start: 3; + /** timer_mod : R/W; bitpos: [4:3]; default: 0; + * PWM timer working mode, 0: freeze, 1: increase mode, 2: decrease mode, 3: up-down + * mode + */ + uint32_t timer_mod: 2; + uint32_t reserved_5: 27; + }; + uint32_t val; +} mcpwm_timer_cfg1_reg_t; + +/** Type of timer_sync register + * PWM timer sync function configuration register. + */ +typedef union { + struct { + /** timer_synci_en : R/W; bitpos: [0]; default: 0; + * When set, timer reloading with phase on sync input event is enabled. + */ + uint32_t timer_synci_en: 1; + /** timer_sync_sw : R/W; bitpos: [1]; default: 0; + * Toggling this bit will trigger a software sync. + */ + uint32_t timer_sync_sw: 1; + /** timer_synco_sel : R/W; bitpos: [3:2]; default: 0; + * PWM timer sync_out selection, 0: sync_in, 1: TEZ, 2: TEP, and sync out will always + * generate when toggling the reg_timer_sync_sw bit + */ + uint32_t timer_synco_sel: 2; + /** timer_phase : R/W; bitpos: [19:4]; default: 0; + * phase for timer reload on sync event + */ + uint32_t timer_phase: 16; + /** timer_phase_direction : R/W; bitpos: [20]; default: 0; + * Configure the PWM timer's direction at the time sync event occurs when timer mode + * is up-down mode: 0-increase,1-decrease + */ + uint32_t timer_phase_direction: 1; + uint32_t reserved_21: 11; + }; + uint32_t val; +} mcpwm_timer_sync_reg_t; + +/** Type of timer_status register + * PWM timer status register. + */ +typedef union { + struct { + /** timer_value : RO; bitpos: [15:0]; default: 0; + * current PWM timer counter value + */ + uint32_t timer_value: 16; + /** timer_direction : RO; bitpos: [16]; default: 0; + * current PWM timer counter direction, 0: increment 1: decrement + */ + uint32_t timer_direction: 1; + uint32_t reserved_17: 15; + }; + uint32_t val; +} mcpwm_timer_status_reg_t; + + +/** Group: Common configuration for MCPWM timers */ +/** Type of timer_synci_cfg register + * Synchronization input selection for three PWM timers. + */ +typedef union { + struct { + /** timer0_syncisel : R/W; bitpos: [2:0]; default: 0; + * select sync input for PWM timer0, 1: PWM timer0 sync_out, 2: PWM timer1 sync_out, + * 3: PWM timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, 6: + * SYNC2 from GPIO matrix, other values: no sync input selected + */ + uint32_t timer0_syncisel: 3; + /** timer1_syncisel : R/W; bitpos: [5:3]; default: 0; + * select sync input for PWM timer1, 1: PWM timer0 sync_out, 2: PWM timer1 sync_out, + * 3: PWM timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, 6: + * SYNC2 from GPIO matrix, other values: no sync input selected + */ + uint32_t timer1_syncisel: 3; + /** timer2_syncisel : R/W; bitpos: [8:6]; default: 0; + * select sync input for PWM timer2, 1: PWM timer0 sync_out, 2: PWM timer1 sync_out, + * 3: PWM timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, 6: + * SYNC2 from GPIO matrix, other values: no sync input selected + */ + uint32_t timer2_syncisel: 3; + /** external_synci0_invert : R/W; bitpos: [9]; default: 0; + * invert SYNC0 from GPIO matrix + */ + uint32_t external_synci0_invert: 1; + /** external_synci1_invert : R/W; bitpos: [10]; default: 0; + * invert SYNC1 from GPIO matrix + */ + uint32_t external_synci1_invert: 1; + /** external_synci2_invert : R/W; bitpos: [11]; default: 0; + * invert SYNC2 from GPIO matrix + */ + uint32_t external_synci2_invert: 1; + uint32_t reserved_12: 20; + }; + uint32_t val; +} mcpwm_timer_synci_cfg_reg_t; + +/** Type of operator_timersel register + * Select specific timer for PWM operators. + */ +typedef union { + struct { + /** operator0_timersel : R/W; bitpos: [1:0]; default: 0; + * Select which PWM timer is the timing reference for PWM operator0, 0: timer0, 1: + * timer1, 2: timer2 + */ + uint32_t operator0_timersel: 2; + /** operator1_timersel : R/W; bitpos: [3:2]; default: 0; + * Select which PWM timer is the timing reference for PWM operator1, 0: timer0, 1: + * timer1, 2: timer2 + */ + uint32_t operator1_timersel: 2; + /** operator2_timersel : R/W; bitpos: [5:4]; default: 0; + * Select which PWM timer is the timing reference for PWM operator2, 0: timer0, 1: + * timer1, 2: timer2 + */ + uint32_t operator2_timersel: 2; + uint32_t reserved_6: 26; + }; + uint32_t val; +} mcpwm_operator_timersel_reg_t; + + +/** Group: MCPWM Operator Configuration and Status */ +/** Type of gen_stmp_cfg register + * Transfer status and update method for time stamp registers A and B + */ +typedef union { + struct { + /** gen_a_upmethod : R/W; bitpos: [3:0]; default: 0; + * Update method for PWM generator time stamp A's active register. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when + * bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + */ + uint32_t gen_a_upmethod: 4; + /** gen_b_upmethod : R/W; bitpos: [7:4]; default: 0; + * Update method for PWM generator time stamp B's active register. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when + * bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + */ + uint32_t gen_b_upmethod: 4; + /** gen_a_shdw_full : R/W/WTC/SC; bitpos: [8]; default: 0; + * Set and reset by hardware. If set, PWM generator time stamp A's shadow reg is + * filled and waiting to be transferred to A's active reg. If cleared, A's active reg + * has been updated with shadow register latest value + */ + uint32_t gen_a_shdw_full: 1; + /** gen_b_shdw_full : R/W/WTC/SC; bitpos: [9]; default: 0; + * Set and reset by hardware. If set, PWM generator time stamp B's shadow reg is + * filled and waiting to be transferred to B's active reg. If cleared, B's active reg + * has been updated with shadow register latest value + */ + uint32_t gen_b_shdw_full: 1; + uint32_t reserved_10: 22; + }; + uint32_t val; +} mcpwm_gen_stmp_cfg_reg_t; + +/** Type of gen_tstmp register + * PWM generator shadow register for timer stamp + */ +typedef union { + struct { + /** gen : R/W; bitpos: [15:0]; default: 0; + * PWM generator time stamp's shadow register + */ + uint32_t gen: 16; + uint32_t reserved_16: 16; + }; + uint32_t val; +} mcpwm_gen_tstmp_reg_t; + +/** Type of gen_cfg0 register + * PWM generator event T0 and T1 handling + */ +typedef union { + struct { + /** gen_cfg_upmethod : R/W; bitpos: [3:0]; default: 0; + * Update method for PWM generator's active register of configuration. When all bits + * are set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to + * 1:TEP,when bit2 is set to 1:sync,when bit3 is set to 1:disable the update + */ + uint32_t gen_cfg_upmethod: 4; + /** gen_t0_sel : R/W; bitpos: [6:4]; default: 0; + * Source selection for PWM generator event_t0, take effect immediately, 0: + * fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + */ + uint32_t gen_t0_sel: 3; + /** gen_t1_sel : R/W; bitpos: [9:7]; default: 0; + * Source selection for PWM generator event_t1, take effect immediately, 0: + * fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + */ + uint32_t gen_t1_sel: 3; + uint32_t reserved_10: 22; + }; + uint32_t val; +} mcpwm_gen_cfg0_reg_t; + +/** Type of gen_force register + * Permissives to force PWM0A and PWM0B outputs by software + */ +typedef union { + struct { + /** gen_cntuforce_upmethod : R/W; bitpos: [5:0]; default: 32; + * Updating method for continuous software force of PWM generator0. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ,,when bit1 is set to 1: TEP, when + * bit2 is set to 1: TEA, when bit3 is set to 1: TEB, when bit4 is set to 1: sync, + * when bit5 is set to 1: disable update. (TEA/B here and below means an event + * generated when the timer's value equals to that of register A/B.) + */ + uint32_t gen_cntuforce_upmethod: 6; + /** gen_a_cntuforce_mode : R/W; bitpos: [7:6]; default: 0; + * Continuous software force mode for PWM0A. 0: disabled, 1: low, 2: high, 3: disabled + */ + uint32_t gen_a_cntuforce_mode: 2; + /** gen_b_cntuforce_mode : R/W; bitpos: [9:8]; default: 0; + * Continuous software force mode for PWM0B. 0: disabled, 1: low, 2: high, 3: disabled + */ + uint32_t gen_b_cntuforce_mode: 2; + /** gen_a_nciforce : R/W; bitpos: [10]; default: 0; + * Trigger of non-continuous immediate software-force event for PWM0A, a toggle will + * trigger a force event. + */ + uint32_t gen_a_nciforce: 1; + /** gen_a_nciforce_mode : R/W; bitpos: [12:11]; default: 0; + * non-continuous immediate software force mode for PWM0A, 0: disabled, 1: low, 2: + * high, 3: disabled + */ + uint32_t gen_a_nciforce_mode: 2; + /** gen_b_nciforce : R/W; bitpos: [13]; default: 0; + * Trigger of non-continuous immediate software-force event for PWM0B, a toggle will + * trigger a force event. + */ + uint32_t gen_b_nciforce: 1; + /** gen_b_nciforce_mode : R/W; bitpos: [15:14]; default: 0; + * non-continuous immediate software force mode for PWM0B, 0: disabled, 1: low, 2: + * high, 3: disabled + */ + uint32_t gen_b_nciforce_mode: 2; + uint32_t reserved_16: 16; + }; + uint32_t val; +} mcpwm_gen_force_reg_t; + +/** Type of generator register + * Actions triggered by events on PWM0A + */ +typedef union { + struct { + /** gen_utez : R/W; bitpos: [1:0]; default: 0; + * Action on PWM0A triggered by event TEZ when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_utez: 2; + /** gen_utep : R/W; bitpos: [3:2]; default: 0; + * Action on PWM0A triggered by event TEP when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_utep: 2; + /** gen_utea : R/W; bitpos: [5:4]; default: 0; + * Action on PWM0A triggered by event TEA when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_utea: 2; + /** gen_uteb : R/W; bitpos: [7:6]; default: 0; + * Action on PWM0A triggered by event TEB when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_uteb: 2; + /** gen_ut0 : R/W; bitpos: [9:8]; default: 0; + * Action on PWM0A triggered by event_t0 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_ut0: 2; + /** gen_ut1 : R/W; bitpos: [11:10]; default: 0; + * Action on PWM0A triggered by event_t1 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_ut1: 2; + /** gen_dtez : R/W; bitpos: [13:12]; default: 0; + * Action on PWM0A triggered by event TEZ when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_dtez: 2; + /** gen_dtep : R/W; bitpos: [15:14]; default: 0; + * Action on PWM0A triggered by event TEP when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_dtep: 2; + /** gen_dtea : R/W; bitpos: [17:16]; default: 0; + * Action on PWM0A triggered by event TEA when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_dtea: 2; + /** gen_dteb : R/W; bitpos: [19:18]; default: 0; + * Action on PWM0A triggered by event TEB when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_dteb: 2; + /** gen_dt0 : R/W; bitpos: [21:20]; default: 0; + * Action on PWM0A triggered by event_t0 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_dt0: 2; + /** gen_dt1 : R/W; bitpos: [23:22]; default: 0; + * Action on PWM0A triggered by event_t1 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_dt1: 2; + uint32_t reserved_24: 8; + }; + uint32_t val; +} mcpwm_gen_reg_t; + +/** Type of dt_cfg register + * PWM generator dead time type selection and configuration + */ +typedef union { + struct { + /** dt_fed_upmethod : R/W; bitpos: [3:0]; default: 0; + * Update method for FED (rising edge delay) active register. 0: immediate, when bit0 + * is set to 1: tez, when bit1 is set to 1:tep, when bit2 is set to 1: sync, when + * bit3 is set to 1: disable the update + */ + uint32_t dt_fed_upmethod: 4; + /** dt_red_upmethod : R/W; bitpos: [7:4]; default: 0; + * Update method for RED (rising edge delay) active register. 0: immediate, when bit0 + * is set to 1: tez, when bit1 is set to 1:tep, when bit2 is set to 1: sync, when + * bit3 is set to 1: disable the update + */ + uint32_t dt_red_upmethod: 4; + /** dt_deb_mode : R/W; bitpos: [8]; default: 0; + * S8 in table, dual-edge B mode, 0: fed/red take effect on different path separately, + * 1: fed/red take effect on B path, A out is in bypass or dulpB mode + */ + uint32_t dt_deb_mode: 1; + /** dt_a_outswap : R/W; bitpos: [9]; default: 0; + * S6 in table + */ + uint32_t dt_a_outswap: 1; + /** dt_b_outswap : R/W; bitpos: [10]; default: 0; + * S7 in table + */ + uint32_t dt_b_outswap: 1; + /** dt_red_insel : R/W; bitpos: [11]; default: 0; + * S4 in table + */ + uint32_t dt_red_insel: 1; + /** dt_fed_insel : R/W; bitpos: [12]; default: 0; + * S5 in table + */ + uint32_t dt_fed_insel: 1; + /** dt_red_outinvert : R/W; bitpos: [13]; default: 0; + * S2 in table + */ + uint32_t dt_red_outinvert: 1; + /** dt_fed_outinvert : R/W; bitpos: [14]; default: 0; + * S3 in table + */ + uint32_t dt_fed_outinvert: 1; + /** dt_a_outbypass : R/W; bitpos: [15]; default: 1; + * S1 in table + */ + uint32_t dt_a_outbypass: 1; + /** dt_b_outbypass : R/W; bitpos: [16]; default: 1; + * S0 in table + */ + uint32_t dt_b_outbypass: 1; + /** dt_clk_sel : R/W; bitpos: [17]; default: 0; + * Dead time clock selection. 0: PWM_clk, 1: PT_clk + */ + uint32_t dt_clk_sel: 1; + uint32_t reserved_18: 14; + }; + uint32_t val; +} mcpwm_dt_cfg_reg_t; + +/** Type of dt_fed_cfg register + * PWM generator shadow register for falling edge delay (FED). + */ +typedef union { + struct { + /** dt_fed : R/W; bitpos: [15:0]; default: 0; + * Shadow register for FED + */ + uint32_t dt_fed: 16; + uint32_t reserved_16: 16; + }; + uint32_t val; +} mcpwm_dt_fed_cfg_reg_t; + +/** Type of dt_red_cfg register + * PWM generator shadow register for rising edge delay (RED). + */ +typedef union { + struct { + /** dt_red : R/W; bitpos: [15:0]; default: 0; + * Shadow register for RED + */ + uint32_t dt_red: 16; + uint32_t reserved_16: 16; + }; + uint32_t val; +} mcpwm_dt_red_cfg_reg_t; + +/** Type of carrier_cfg register + * PWM generator carrier enable and configuratoin + */ +typedef union { + struct { + /** carrier_en : R/W; bitpos: [0]; default: 0; + * When set, carrier function is enabled. When cleared, carrier is bypassed + */ + uint32_t carrier_en: 1; + /** carrier_prescale : R/W; bitpos: [4:1]; default: 0; + * PWM carrier clock (PC_clk) prescale value. Period of PC_clk = period of PWM_clk * + * (PWM_CARRIER_PRESCALE + 1) + */ + uint32_t carrier_prescale: 4; + /** carrier_duty : R/W; bitpos: [7:5]; default: 0; + * carrier duty selection. Duty = PWM_CARRIER_DUTY / 8 + */ + uint32_t carrier_duty: 3; + /** carrier_oshtwth : R/W; bitpos: [11:8]; default: 0; + * width of the first pulse in number of periods of the carrier + */ + uint32_t carrier_oshtwth: 4; + /** carrier_out_invert : R/W; bitpos: [12]; default: 0; + * when set, invert the output of PWM0A and PWM0B for this submodule + */ + uint32_t carrier_out_invert: 1; + /** carrier_in_invert : R/W; bitpos: [13]; default: 0; + * when set, invert the input of PWM0A and PWM0B for this submodule + */ + uint32_t carrier_in_invert: 1; + uint32_t reserved_14: 18; + }; + uint32_t val; +} mcpwm_carrier_cfg_reg_t; + +/** Type of fh_cfg0 register + * Actions on PWM0A and PWM0B trip events + */ +typedef union { + struct { + /** fh_sw_cbc : R/W; bitpos: [0]; default: 0; + * Enable register for software force cycle-by-cycle mode action. 0: disable, 1: enable + */ + uint32_t fh_sw_cbc: 1; + /** fh_f2_cbc : R/W; bitpos: [1]; default: 0; + * fault_event2 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ + uint32_t fh_f2_cbc: 1; + /** fh_f1_cbc : R/W; bitpos: [2]; default: 0; + * fault_event1 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ + uint32_t fh_f1_cbc: 1; + /** fh_f0_cbc : R/W; bitpos: [3]; default: 0; + * fault_event0 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ + uint32_t fh_f0_cbc: 1; + /** fh_sw_ost : R/W; bitpos: [4]; default: 0; + * Enable register for software force one-shot mode action. 0: disable, 1: enable + */ + uint32_t fh_sw_ost: 1; + /** fh_f2_ost : R/W; bitpos: [5]; default: 0; + * fault_event2 will trigger one-shot mode action. 0: disable, 1: enable + */ + uint32_t fh_f2_ost: 1; + /** fh_f1_ost : R/W; bitpos: [6]; default: 0; + * fault_event1 will trigger one-shot mode action. 0: disable, 1: enable + */ + uint32_t fh_f1_ost: 1; + /** fh_f0_ost : R/W; bitpos: [7]; default: 0; + * fault_event0 will trigger one-shot mode action. 0: disable, 1: enable + */ + uint32_t fh_f0_ost: 1; + /** fh_a_cbc_d : R/W; bitpos: [9:8]; default: 0; + * Cycle-by-cycle mode action on PWM0A when fault event occurs and timer is + * decreasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ + uint32_t fh_a_cbc_d: 2; + /** fh_a_cbc_u : R/W; bitpos: [11:10]; default: 0; + * Cycle-by-cycle mode action on PWM0A when fault event occurs and timer is + * increasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ + uint32_t fh_a_cbc_u: 2; + /** fh_a_ost_d : R/W; bitpos: [13:12]; default: 0; + * One-shot mode action on PWM0A when fault event occurs and timer is decreasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ + uint32_t fh_a_ost_d: 2; + /** fh_a_ost_u : R/W; bitpos: [15:14]; default: 0; + * One-shot mode action on PWM0A when fault event occurs and timer is increasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ + uint32_t fh_a_ost_u: 2; + /** fh_b_cbc_d : R/W; bitpos: [17:16]; default: 0; + * Cycle-by-cycle mode action on PWM0B when fault event occurs and timer is + * decreasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ + uint32_t fh_b_cbc_d: 2; + /** fh_b_cbc_u : R/W; bitpos: [19:18]; default: 0; + * Cycle-by-cycle mode action on PWM0B when fault event occurs and timer is + * increasing. 0: do nothing,1: force low, 2: force high, 3: toggle + */ + uint32_t fh_b_cbc_u: 2; + /** fh_b_ost_d : R/W; bitpos: [21:20]; default: 0; + * One-shot mode action on PWM0B when fault event occurs and timer is decreasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ + uint32_t fh_b_ost_d: 2; + /** fh_b_ost_u : R/W; bitpos: [23:22]; default: 0; + * One-shot mode action on PWM0B when fault event occurs and timer is increasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ + uint32_t fh_b_ost_u: 2; + uint32_t reserved_24: 8; + }; + uint32_t val; +} mcpwm_fh_cfg0_reg_t; + +/** Type of fh_cfg1 register + * Software triggers for fault handler actions + */ +typedef union { + struct { + /** fh_clr_ost : R/W; bitpos: [0]; default: 0; + * a rising edge will clear on going one-shot mode action + */ + uint32_t fh_clr_ost: 1; + /** fh_cbcpulse : R/W; bitpos: [2:1]; default: 0; + * cycle-by-cycle mode action refresh moment selection. When bit0 is set to 1: TEZ, + * when bit1 is set to 1:TEP, when bit0 and bit1 both set to 0: stop refresh, when + * bit0 and bit1 both set to 1: refresh at TEP/TEZ + */ + uint32_t fh_cbcpulse: 2; + /** fh_force_cbc : R/W; bitpos: [3]; default: 0; + * a toggle trigger a cycle-by-cycle mode action + */ + uint32_t fh_force_cbc: 1; + /** fh_force_ost : R/W; bitpos: [4]; default: 0; + * a toggle (software negate its value) triggers a one-shot mode action + */ + uint32_t fh_force_ost: 1; + uint32_t reserved_5: 27; + }; + uint32_t val; +} mcpwm_fh_cfg1_reg_t; + +/** Type of fh_status register + * Status of fault events. + */ +typedef union { + struct { + /** fh_cbc_on : RO; bitpos: [0]; default: 0; + * Set and reset by hardware. If set, a cycle-by-cycle mode action is on going + */ + uint32_t fh_cbc_on: 1; + /** fh_ost_on : RO; bitpos: [1]; default: 0; + * Set and reset by hardware. If set, an one-shot mode action is on going + */ + uint32_t fh_ost_on: 1; + uint32_t reserved_2: 30; + }; + uint32_t val; +} mcpwm_fh_status_reg_t; + +/** Group: Fault Detection Configuration and Status */ +/** Type of fault_detect register + * Fault detection configuration and status + */ +typedef union { + struct { + /** f0_en : R/W; bitpos: [0]; default: 0; + * When set, fault_event0 generation is enabled + */ + uint32_t f0_en: 1; + /** f1_en : R/W; bitpos: [1]; default: 0; + * When set, fault_event1 generation is enabled + */ + uint32_t f1_en: 1; + /** f2_en : R/W; bitpos: [2]; default: 0; + * When set, fault_event2 generation is enabled + */ + uint32_t f2_en: 1; + /** f0_pole : R/W; bitpos: [3]; default: 0; + * Set fault_event0 trigger polarity on FAULT2 source from GPIO matrix. 0: level low, + * 1: level high + */ + uint32_t f0_pole: 1; + /** f1_pole : R/W; bitpos: [4]; default: 0; + * Set fault_event1 trigger polarity on FAULT2 source from GPIO matrix. 0: level low, + * 1: level high + */ + uint32_t f1_pole: 1; + /** f2_pole : R/W; bitpos: [5]; default: 0; + * Set fault_event2 trigger polarity on FAULT2 source from GPIO matrix. 0: level low, + * 1: level high + */ + uint32_t f2_pole: 1; + /** event_f0 : RO; bitpos: [6]; default: 0; + * Set and reset by hardware. If set, fault_event0 is on going + */ + uint32_t event_f0: 1; + /** event_f1 : RO; bitpos: [7]; default: 0; + * Set and reset by hardware. If set, fault_event1 is on going + */ + uint32_t event_f1: 1; + /** event_f2 : RO; bitpos: [8]; default: 0; + * Set and reset by hardware. If set, fault_event2 is on going + */ + uint32_t event_f2: 1; + uint32_t reserved_9: 23; + }; + uint32_t val; +} mcpwm_fault_detect_reg_t; + + +/** Group: Capture Configuration and Status */ +/** Type of cap_timer_cfg register + * Configure capture timer + */ +typedef union { + struct { + /** cap_timer_en : R/W; bitpos: [0]; default: 0; + * When set, capture timer incrementing under APB_clk is enabled. + */ + uint32_t cap_timer_en: 1; + /** cap_synci_en : R/W; bitpos: [1]; default: 0; + * When set, capture timer sync is enabled. + */ + uint32_t cap_synci_en: 1; + /** cap_synci_sel : R/W; bitpos: [4:2]; default: 0; + * capture module sync input selection. 0: none, 1: timer0 sync_out, 2: timer1 + * sync_out, 3: timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, + * 6: SYNC2 from GPIO matrix + */ + uint32_t cap_synci_sel: 3; + /** cap_sync_sw : WT; bitpos: [5]; default: 0; + * When reg_cap_synci_en is 1, write 1 will trigger a capture timer sync, capture + * timer is loaded with value in phase register. + */ + uint32_t cap_sync_sw: 1; + uint32_t reserved_6: 26; + }; + uint32_t val; +} mcpwm_cap_timer_cfg_reg_t; + +/** Type of cap_timer_phase register + * Phase for capture timer sync + */ +typedef union { + struct { + /** cap_timer_phase : R/W; bitpos: [31:0]; default: 0; + * Phase value for capture timer sync operation. + */ + uint32_t cap_timer_phase: 32; + }; + uint32_t val; +} mcpwm_cap_timer_phase_reg_t; + +/** Type of cap_chn_cfg register + * Capture channel 0 configuration and enable + */ +typedef union { + struct { + /** capn_en : R/W; bitpos: [0]; default: 0; + * When set, capture on channel 0 is enabled + */ + uint32_t capn_en: 1; + /** capn_mode : R/W; bitpos: [2:1]; default: 0; + * Edge of capture on channel 0 after prescaling. When bit0 is set to 1: enable + * capture on the negative edge, When bit1 is set to 1: enable capture on the positive + * edge. + */ + 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 + + * 1 + */ + uint32_t capn_prescale: 8; + /** capn_in_invert : R/W; bitpos: [11]; default: 0; + * when set, CAPn form GPIO matrix is inverted before prescale + */ + uint32_t capn_in_invert: 1; + /** capn_sw : WT; bitpos: [12]; default: 0; + * Write 1 will trigger a software forced capture on channel 0 + */ + uint32_t capn_sw: 1; + uint32_t reserved_13: 19; + }; + uint32_t val; +} mcpwm_cap_chn_cfg_reg_t; + +/** Type of cap_chn register + * chn capture value status register + */ +typedef union { + struct { + /** capn_value : RO; bitpos: [31:0]; default: 0; + * Value of last capture on channel n + */ + uint32_t capn_value: 32; + }; + uint32_t val; +} mcpwm_cap_chn_reg_t; + +/** Type of cap_status register + * Edge of last capture trigger + */ +typedef union { + struct { + /** cap0_edge : RO; bitpos: [0]; default: 0; + * Edge of last capture trigger on channel 0, 0: posedge, 1: negedge + */ + uint32_t cap0_edge: 1; + /** cap1_edge : RO; bitpos: [1]; default: 0; + * Edge of last capture trigger on channel 1, 0: posedge, 1: negedge + */ + uint32_t cap1_edge: 1; + /** cap2_edge : RO; bitpos: [2]; default: 0; + * Edge of last capture trigger on channel 2, 0: posedge, 1: negedge + */ + uint32_t cap2_edge: 1; + uint32_t reserved_3: 29; + }; + uint32_t val; +} mcpwm_cap_status_reg_t; + + +/** Group: Enable update of active registers */ +/** Type of update_cfg register + * Enable update. + */ +typedef union { + struct { + /** global_up_en : R/W; bitpos: [0]; default: 1; + * The global enable of update of all active registers in MCPWM module + */ + uint32_t global_up_en: 1; + /** global_force_up : R/W; bitpos: [1]; default: 0; + * a toggle (software invert its value) will trigger a forced update of all active + * registers in MCPWM module + */ + uint32_t global_force_up: 1; + /** op0_up_en : R/W; bitpos: [2]; default: 1; + * When set and PWM_GLOBAL_UP_EN is set, update of active registers in PWM operator 0 + * are enabled + */ + uint32_t op0_up_en: 1; + /** op0_force_up : R/W; bitpos: [3]; default: 0; + * a toggle (software invert its value) will trigger a forced update of active + * registers in PWM operator 0 + */ + uint32_t op0_force_up: 1; + /** op1_up_en : R/W; bitpos: [4]; default: 1; + * When set and PWM_GLOBAL_UP_EN is set, update of active registers in PWM operator 1 + * are enabled + */ + uint32_t op1_up_en: 1; + /** op1_force_up : R/W; bitpos: [5]; default: 0; + * a toggle (software invert its value) will trigger a forced update of active + * registers in PWM operator 1 + */ + uint32_t op1_force_up: 1; + /** op2_up_en : R/W; bitpos: [6]; default: 1; + * When set and PWM_GLOBAL_UP_EN is set, update of active registers in PWM operator 2 + * are enabled + */ + uint32_t op2_up_en: 1; + /** op2_force_up : R/W; bitpos: [7]; default: 0; + * a toggle (software invert its value) will trigger a forced update of active + * registers in PWM operator 2 + */ + uint32_t op2_force_up: 1; + uint32_t reserved_8: 24; + }; + uint32_t val; +} mcpwm_update_cfg_reg_t; + + +/** Group: Manage Interrupts */ +/** Type of int_ena register + * Interrupt enable bits + */ +typedef union { + struct { + /** timer0_stop_int_ena : R/W; bitpos: [0]; default: 0; + * The enable bit for the interrupt triggered when the timer 0 stops. + */ + uint32_t timer0_stop_int_ena: 1; + /** timer1_stop_int_ena : R/W; bitpos: [1]; default: 0; + * The enable bit for the interrupt triggered when the timer 1 stops. + */ + uint32_t timer1_stop_int_ena: 1; + /** timer2_stop_int_ena : R/W; bitpos: [2]; default: 0; + * The enable bit for the interrupt triggered when the timer 2 stops. + */ + uint32_t timer2_stop_int_ena: 1; + /** timer0_tez_int_ena : R/W; bitpos: [3]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 0 TEZ event. + */ + uint32_t timer0_tez_int_ena: 1; + /** timer1_tez_int_ena : R/W; bitpos: [4]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 1 TEZ event. + */ + uint32_t timer1_tez_int_ena: 1; + /** timer2_tez_int_ena : R/W; bitpos: [5]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 2 TEZ event. + */ + uint32_t timer2_tez_int_ena: 1; + /** timer0_tep_int_ena : R/W; bitpos: [6]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 0 TEP event. + */ + uint32_t timer0_tep_int_ena: 1; + /** timer1_tep_int_ena : R/W; bitpos: [7]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 1 TEP event. + */ + uint32_t timer1_tep_int_ena: 1; + /** timer2_tep_int_ena : R/W; bitpos: [8]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 2 TEP event. + */ + uint32_t timer2_tep_int_ena: 1; + /** fault0_int_ena : R/W; bitpos: [9]; default: 0; + * The enable bit for the interrupt triggered when fault_event0 starts. + */ + uint32_t fault0_int_ena: 1; + /** fault1_int_ena : R/W; bitpos: [10]; default: 0; + * The enable bit for the interrupt triggered when fault_event1 starts. + */ + uint32_t fault1_int_ena: 1; + /** fault2_int_ena : R/W; bitpos: [11]; default: 0; + * The enable bit for the interrupt triggered when fault_event2 starts. + */ + uint32_t fault2_int_ena: 1; + /** fault0_clr_int_ena : R/W; bitpos: [12]; default: 0; + * The enable bit for the interrupt triggered when fault_event0 ends. + */ + uint32_t fault0_clr_int_ena: 1; + /** fault1_clr_int_ena : R/W; bitpos: [13]; default: 0; + * The enable bit for the interrupt triggered when fault_event1 ends. + */ + uint32_t fault1_clr_int_ena: 1; + /** fault2_clr_int_ena : R/W; bitpos: [14]; default: 0; + * The enable bit for the interrupt triggered when fault_event2 ends. + */ + uint32_t fault2_clr_int_ena: 1; + /** op0_tea_int_ena : R/W; bitpos: [15]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 0 TEA event + */ + uint32_t op0_tea_int_ena: 1; + /** op1_tea_int_ena : R/W; bitpos: [16]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 1 TEA event + */ + uint32_t op1_tea_int_ena: 1; + /** op2_tea_int_ena : R/W; bitpos: [17]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 2 TEA event + */ + uint32_t op2_tea_int_ena: 1; + /** op0_teb_int_ena : R/W; bitpos: [18]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 0 TEB event + */ + uint32_t op0_teb_int_ena: 1; + /** op1_teb_int_ena : R/W; bitpos: [19]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 1 TEB event + */ + uint32_t op1_teb_int_ena: 1; + /** op2_teb_int_ena : R/W; bitpos: [20]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 2 TEB event + */ + uint32_t op2_teb_int_ena: 1; + /** fh0_cbc_int_ena : R/W; bitpos: [21]; default: 0; + * The enable bit for the interrupt triggered by a cycle-by-cycle mode action on PWM0. + */ + uint32_t fh0_cbc_int_ena: 1; + /** fh1_cbc_int_ena : R/W; bitpos: [22]; default: 0; + * The enable bit for the interrupt triggered by a cycle-by-cycle mode action on PWM1. + */ + uint32_t fh1_cbc_int_ena: 1; + /** fh2_cbc_int_ena : R/W; bitpos: [23]; default: 0; + * The enable bit for the interrupt triggered by a cycle-by-cycle mode action on PWM2. + */ + uint32_t fh2_cbc_int_ena: 1; + /** fh0_ost_int_ena : R/W; bitpos: [24]; default: 0; + * The enable bit for the interrupt triggered by a one-shot mode action on PWM0. + */ + uint32_t fh0_ost_int_ena: 1; + /** fh1_ost_int_ena : R/W; bitpos: [25]; default: 0; + * The enable bit for the interrupt triggered by a one-shot mode action on PWM1. + */ + uint32_t fh1_ost_int_ena: 1; + /** fh2_ost_int_ena : R/W; bitpos: [26]; default: 0; + * The enable bit for the interrupt triggered by a one-shot mode action on PWM2. + */ + uint32_t fh2_ost_int_ena: 1; + /** cap0_int_ena : R/W; bitpos: [27]; default: 0; + * The enable bit for the interrupt triggered by capture on channel 0. + */ + uint32_t cap0_int_ena: 1; + /** cap1_int_ena : R/W; bitpos: [28]; default: 0; + * The enable bit for the interrupt triggered by capture on channel 1. + */ + uint32_t cap1_int_ena: 1; + /** cap2_int_ena : R/W; bitpos: [29]; default: 0; + * The enable bit for the interrupt triggered by capture on channel 2. + */ + uint32_t cap2_int_ena: 1; + uint32_t reserved_30: 2; + }; + uint32_t val; +} mcpwm_int_ena_reg_t; + +/** Type of int_raw register + * Raw interrupt status + */ +typedef union { + struct { + /** timer0_stop_int_raw : R/WTC/SS; bitpos: [0]; default: 0; + * The raw status bit for the interrupt triggered when the timer 0 stops. + */ + uint32_t timer0_stop_int_raw: 1; + /** timer1_stop_int_raw : R/WTC/SS; bitpos: [1]; default: 0; + * The raw status bit for the interrupt triggered when the timer 1 stops. + */ + uint32_t timer1_stop_int_raw: 1; + /** timer2_stop_int_raw : R/WTC/SS; bitpos: [2]; default: 0; + * The raw status bit for the interrupt triggered when the timer 2 stops. + */ + uint32_t timer2_stop_int_raw: 1; + /** timer0_tez_int_raw : R/WTC/SS; bitpos: [3]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 0 TEZ event. + */ + uint32_t timer0_tez_int_raw: 1; + /** timer1_tez_int_raw : R/WTC/SS; bitpos: [4]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 1 TEZ event. + */ + uint32_t timer1_tez_int_raw: 1; + /** timer2_tez_int_raw : R/WTC/SS; bitpos: [5]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 2 TEZ event. + */ + uint32_t timer2_tez_int_raw: 1; + /** timer0_tep_int_raw : R/WTC/SS; bitpos: [6]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 0 TEP event. + */ + uint32_t timer0_tep_int_raw: 1; + /** timer1_tep_int_raw : R/WTC/SS; bitpos: [7]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 1 TEP event. + */ + uint32_t timer1_tep_int_raw: 1; + /** timer2_tep_int_raw : R/WTC/SS; bitpos: [8]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 2 TEP event. + */ + uint32_t timer2_tep_int_raw: 1; + /** fault0_int_raw : R/WTC/SS; bitpos: [9]; default: 0; + * The raw status bit for the interrupt triggered when fault_event0 starts. + */ + uint32_t fault0_int_raw: 1; + /** fault1_int_raw : R/WTC/SS; bitpos: [10]; default: 0; + * The raw status bit for the interrupt triggered when fault_event1 starts. + */ + uint32_t fault1_int_raw: 1; + /** fault2_int_raw : R/WTC/SS; bitpos: [11]; default: 0; + * The raw status bit for the interrupt triggered when fault_event2 starts. + */ + uint32_t fault2_int_raw: 1; + /** fault0_clr_int_raw : R/WTC/SS; bitpos: [12]; default: 0; + * The raw status bit for the interrupt triggered when fault_event0 ends. + */ + uint32_t fault0_clr_int_raw: 1; + /** fault1_clr_int_raw : R/WTC/SS; bitpos: [13]; default: 0; + * The raw status bit for the interrupt triggered when fault_event1 ends. + */ + uint32_t fault1_clr_int_raw: 1; + /** fault2_clr_int_raw : R/WTC/SS; bitpos: [14]; default: 0; + * The raw status bit for the interrupt triggered when fault_event2 ends. + */ + uint32_t fault2_clr_int_raw: 1; + /** op0_tea_int_raw : R/WTC/SS; bitpos: [15]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 0 TEA event + */ + uint32_t op0_tea_int_raw: 1; + /** op1_tea_int_raw : R/WTC/SS; bitpos: [16]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 1 TEA event + */ + uint32_t op1_tea_int_raw: 1; + /** op2_tea_int_raw : R/WTC/SS; bitpos: [17]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 2 TEA event + */ + uint32_t op2_tea_int_raw: 1; + /** op0_teb_int_raw : R/WTC/SS; bitpos: [18]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 0 TEB event + */ + uint32_t op0_teb_int_raw: 1; + /** op1_teb_int_raw : R/WTC/SS; bitpos: [19]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 1 TEB event + */ + uint32_t op1_teb_int_raw: 1; + /** op2_teb_int_raw : R/WTC/SS; bitpos: [20]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 2 TEB event + */ + uint32_t op2_teb_int_raw: 1; + /** fh0_cbc_int_raw : R/WTC/SS; bitpos: [21]; default: 0; + * The raw status bit for the interrupt triggered by a cycle-by-cycle mode action on + * PWM0. + */ + uint32_t fh0_cbc_int_raw: 1; + /** fh1_cbc_int_raw : R/WTC/SS; bitpos: [22]; default: 0; + * The raw status bit for the interrupt triggered by a cycle-by-cycle mode action on + * PWM1. + */ + uint32_t fh1_cbc_int_raw: 1; + /** fh2_cbc_int_raw : R/WTC/SS; bitpos: [23]; default: 0; + * The raw status bit for the interrupt triggered by a cycle-by-cycle mode action on + * PWM2. + */ + uint32_t fh2_cbc_int_raw: 1; + /** fh0_ost_int_raw : R/WTC/SS; bitpos: [24]; default: 0; + * The raw status bit for the interrupt triggered by a one-shot mode action on PWM0. + */ + uint32_t fh0_ost_int_raw: 1; + /** fh1_ost_int_raw : R/WTC/SS; bitpos: [25]; default: 0; + * The raw status bit for the interrupt triggered by a one-shot mode action on PWM1. + */ + uint32_t fh1_ost_int_raw: 1; + /** fh2_ost_int_raw : R/WTC/SS; bitpos: [26]; default: 0; + * The raw status bit for the interrupt triggered by a one-shot mode action on PWM2. + */ + uint32_t fh2_ost_int_raw: 1; + /** cap0_int_raw : R/WTC/SS; bitpos: [27]; default: 0; + * The raw status bit for the interrupt triggered by capture on channel 0. + */ + uint32_t cap0_int_raw: 1; + /** cap1_int_raw : R/WTC/SS; bitpos: [28]; default: 0; + * The raw status bit for the interrupt triggered by capture on channel 1. + */ + uint32_t cap1_int_raw: 1; + /** cap2_int_raw : R/WTC/SS; bitpos: [29]; default: 0; + * The raw status bit for the interrupt triggered by capture on channel 2. + */ + uint32_t cap2_int_raw: 1; + uint32_t reserved_30: 2; + }; + uint32_t val; +} mcpwm_int_raw_reg_t; + +/** Type of int_st register + * Masked interrupt status + */ +typedef union { + struct { + /** timer0_stop_int_st : RO; bitpos: [0]; default: 0; + * The masked status bit for the interrupt triggered when the timer 0 stops. + */ + uint32_t timer0_stop_int_st: 1; + /** timer1_stop_int_st : RO; bitpos: [1]; default: 0; + * The masked status bit for the interrupt triggered when the timer 1 stops. + */ + uint32_t timer1_stop_int_st: 1; + /** timer2_stop_int_st : RO; bitpos: [2]; default: 0; + * The masked status bit for the interrupt triggered when the timer 2 stops. + */ + uint32_t timer2_stop_int_st: 1; + /** timer0_tez_int_st : RO; bitpos: [3]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 0 TEZ event. + */ + uint32_t timer0_tez_int_st: 1; + /** timer1_tez_int_st : RO; bitpos: [4]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 1 TEZ event. + */ + uint32_t timer1_tez_int_st: 1; + /** timer2_tez_int_st : RO; bitpos: [5]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 2 TEZ event. + */ + uint32_t timer2_tez_int_st: 1; + /** timer0_tep_int_st : RO; bitpos: [6]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 0 TEP event. + */ + uint32_t timer0_tep_int_st: 1; + /** timer1_tep_int_st : RO; bitpos: [7]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 1 TEP event. + */ + uint32_t timer1_tep_int_st: 1; + /** timer2_tep_int_st : RO; bitpos: [8]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 2 TEP event. + */ + uint32_t timer2_tep_int_st: 1; + /** fault0_int_st : RO; bitpos: [9]; default: 0; + * The masked status bit for the interrupt triggered when fault_event0 starts. + */ + uint32_t fault0_int_st: 1; + /** fault1_int_st : RO; bitpos: [10]; default: 0; + * The masked status bit for the interrupt triggered when fault_event1 starts. + */ + uint32_t fault1_int_st: 1; + /** fault2_int_st : RO; bitpos: [11]; default: 0; + * The masked status bit for the interrupt triggered when fault_event2 starts. + */ + uint32_t fault2_int_st: 1; + /** fault0_clr_int_st : RO; bitpos: [12]; default: 0; + * The masked status bit for the interrupt triggered when fault_event0 ends. + */ + uint32_t fault0_clr_int_st: 1; + /** fault1_clr_int_st : RO; bitpos: [13]; default: 0; + * The masked status bit for the interrupt triggered when fault_event1 ends. + */ + uint32_t fault1_clr_int_st: 1; + /** fault2_clr_int_st : RO; bitpos: [14]; default: 0; + * The masked status bit for the interrupt triggered when fault_event2 ends. + */ + uint32_t fault2_clr_int_st: 1; + /** op0_tea_int_st : RO; bitpos: [15]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 0 TEA event + */ + uint32_t op0_tea_int_st: 1; + /** op1_tea_int_st : RO; bitpos: [16]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 1 TEA event + */ + uint32_t op1_tea_int_st: 1; + /** op2_tea_int_st : RO; bitpos: [17]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 2 TEA event + */ + uint32_t op2_tea_int_st: 1; + /** op0_teb_int_st : RO; bitpos: [18]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 0 TEB event + */ + uint32_t op0_teb_int_st: 1; + /** op1_teb_int_st : RO; bitpos: [19]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 1 TEB event + */ + uint32_t op1_teb_int_st: 1; + /** op2_teb_int_st : RO; bitpos: [20]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 2 TEB event + */ + uint32_t op2_teb_int_st: 1; + /** fh0_cbc_int_st : RO; bitpos: [21]; default: 0; + * The masked status bit for the interrupt triggered by a cycle-by-cycle mode action + * on PWM0. + */ + uint32_t fh0_cbc_int_st: 1; + /** fh1_cbc_int_st : RO; bitpos: [22]; default: 0; + * The masked status bit for the interrupt triggered by a cycle-by-cycle mode action + * on PWM1. + */ + uint32_t fh1_cbc_int_st: 1; + /** fh2_cbc_int_st : RO; bitpos: [23]; default: 0; + * The masked status bit for the interrupt triggered by a cycle-by-cycle mode action + * on PWM2. + */ + uint32_t fh2_cbc_int_st: 1; + /** fh0_ost_int_st : RO; bitpos: [24]; default: 0; + * The masked status bit for the interrupt triggered by a one-shot mode action on PWM0. + */ + uint32_t fh0_ost_int_st: 1; + /** fh1_ost_int_st : RO; bitpos: [25]; default: 0; + * The masked status bit for the interrupt triggered by a one-shot mode action on PWM1. + */ + uint32_t fh1_ost_int_st: 1; + /** fh2_ost_int_st : RO; bitpos: [26]; default: 0; + * The masked status bit for the interrupt triggered by a one-shot mode action on PWM2. + */ + uint32_t fh2_ost_int_st: 1; + /** cap0_int_st : RO; bitpos: [27]; default: 0; + * The masked status bit for the interrupt triggered by capture on channel 0. + */ + uint32_t cap0_int_st: 1; + /** cap1_int_st : RO; bitpos: [28]; default: 0; + * The masked status bit for the interrupt triggered by capture on channel 1. + */ + uint32_t cap1_int_st: 1; + /** cap2_int_st : RO; bitpos: [29]; default: 0; + * The masked status bit for the interrupt triggered by capture on channel 2. + */ + uint32_t cap2_int_st: 1; + uint32_t reserved_30: 2; + }; + uint32_t val; +} mcpwm_int_st_reg_t; + +/** Type of int_clr register + * Interrupt clear bits + */ +typedef union { + struct { + /** timer0_stop_int_clr : WT; bitpos: [0]; default: 0; + * Set this bit to clear the interrupt triggered when the timer 0 stops. + */ + uint32_t timer0_stop_int_clr: 1; + /** timer1_stop_int_clr : WT; bitpos: [1]; default: 0; + * Set this bit to clear the interrupt triggered when the timer 1 stops. + */ + uint32_t timer1_stop_int_clr: 1; + /** timer2_stop_int_clr : WT; bitpos: [2]; default: 0; + * Set this bit to clear the interrupt triggered when the timer 2 stops. + */ + uint32_t timer2_stop_int_clr: 1; + /** timer0_tez_int_clr : WT; bitpos: [3]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 0 TEZ event. + */ + uint32_t timer0_tez_int_clr: 1; + /** timer1_tez_int_clr : WT; bitpos: [4]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 1 TEZ event. + */ + uint32_t timer1_tez_int_clr: 1; + /** timer2_tez_int_clr : WT; bitpos: [5]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 2 TEZ event. + */ + uint32_t timer2_tez_int_clr: 1; + /** timer0_tep_int_clr : WT; bitpos: [6]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 0 TEP event. + */ + uint32_t timer0_tep_int_clr: 1; + /** timer1_tep_int_clr : WT; bitpos: [7]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 1 TEP event. + */ + uint32_t timer1_tep_int_clr: 1; + /** timer2_tep_int_clr : WT; bitpos: [8]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 2 TEP event. + */ + uint32_t timer2_tep_int_clr: 1; + /** fault0_int_clr : WT; bitpos: [9]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event0 starts. + */ + uint32_t fault0_int_clr: 1; + /** fault1_int_clr : WT; bitpos: [10]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event1 starts. + */ + uint32_t fault1_int_clr: 1; + /** fault2_int_clr : WT; bitpos: [11]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event2 starts. + */ + uint32_t fault2_int_clr: 1; + /** fault0_clr_int_clr : WT; bitpos: [12]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event0 ends. + */ + uint32_t fault0_clr_int_clr: 1; + /** fault1_clr_int_clr : WT; bitpos: [13]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event1 ends. + */ + uint32_t fault1_clr_int_clr: 1; + /** fault2_clr_int_clr : WT; bitpos: [14]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event2 ends. + */ + uint32_t fault2_clr_int_clr: 1; + /** op0_tea_int_clr : WT; bitpos: [15]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 0 TEA event + */ + uint32_t op0_tea_int_clr: 1; + /** op1_tea_int_clr : WT; bitpos: [16]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 1 TEA event + */ + uint32_t op1_tea_int_clr: 1; + /** op2_tea_int_clr : WT; bitpos: [17]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 2 TEA event + */ + uint32_t op2_tea_int_clr: 1; + /** op0_teb_int_clr : WT; bitpos: [18]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 0 TEB event + */ + uint32_t op0_teb_int_clr: 1; + /** op1_teb_int_clr : WT; bitpos: [19]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 1 TEB event + */ + uint32_t op1_teb_int_clr: 1; + /** op2_teb_int_clr : WT; bitpos: [20]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 2 TEB event + */ + uint32_t op2_teb_int_clr: 1; + /** fh0_cbc_int_clr : WT; bitpos: [21]; default: 0; + * Set this bit to clear the interrupt triggered by a cycle-by-cycle mode action on + * PWM0. + */ + uint32_t fh0_cbc_int_clr: 1; + /** fh1_cbc_int_clr : WT; bitpos: [22]; default: 0; + * Set this bit to clear the interrupt triggered by a cycle-by-cycle mode action on + * PWM1. + */ + uint32_t fh1_cbc_int_clr: 1; + /** fh2_cbc_int_clr : WT; bitpos: [23]; default: 0; + * Set this bit to clear the interrupt triggered by a cycle-by-cycle mode action on + * PWM2. + */ + uint32_t fh2_cbc_int_clr: 1; + /** fh0_ost_int_clr : WT; bitpos: [24]; default: 0; + * Set this bit to clear the interrupt triggered by a one-shot mode action on PWM0. + */ + uint32_t fh0_ost_int_clr: 1; + /** fh1_ost_int_clr : WT; bitpos: [25]; default: 0; + * Set this bit to clear the interrupt triggered by a one-shot mode action on PWM1. + */ + uint32_t fh1_ost_int_clr: 1; + /** fh2_ost_int_clr : WT; bitpos: [26]; default: 0; + * Set this bit to clear the interrupt triggered by a one-shot mode action on PWM2. + */ + uint32_t fh2_ost_int_clr: 1; + /** cap0_int_clr : WT; bitpos: [27]; default: 0; + * Set this bit to clear the interrupt triggered by capture on channel 0. + */ + uint32_t cap0_int_clr: 1; + /** cap1_int_clr : WT; bitpos: [28]; default: 0; + * Set this bit to clear the interrupt triggered by capture on channel 1. + */ + uint32_t cap1_int_clr: 1; + /** cap2_int_clr : WT; bitpos: [29]; default: 0; + * Set this bit to clear the interrupt triggered by capture on channel 2. + */ + uint32_t cap2_int_clr: 1; + uint32_t reserved_30: 2; + }; + uint32_t val; +} mcpwm_int_clr_reg_t; + + +/** Group: MCMCPWM APB configuration register */ +/** Type of clk register + * MCPWM APB configuration register + */ +typedef union { + struct { + /** clk_en : R/W; bitpos: [0]; default: 0; + * Force clock on for this register file + */ + uint32_t clk_en: 1; + uint32_t reserved_1: 31; + }; + uint32_t val; +} mcpwm_clk_reg_t; + + +/** Group: Version Register */ +/** Type of version register + * Version register. + */ +typedef union { + struct { + /** date : R/W; bitpos: [27:0]; default: 34632240; + * Version of this register file + */ + uint32_t date: 28; + uint32_t reserved_28: 4; + }; + uint32_t val; +} mcpwm_version_reg_t; + + +typedef struct { + mcpwm_timer_cfg0_reg_t timer_cfg0; + mcpwm_timer_cfg1_reg_t timer_cfg1; + mcpwm_timer_sync_reg_t timer_sync; + mcpwm_timer_status_reg_t timer_status; +} mcpwm_timer_regs_t; + +typedef struct { + mcpwm_gen_stmp_cfg_reg_t gen_stmp_cfg; + mcpwm_gen_tstmp_reg_t timestamp[2]; + mcpwm_gen_cfg0_reg_t gen_cfg0; + mcpwm_gen_force_reg_t gen_force; + mcpwm_gen_reg_t generator[2]; + mcpwm_dt_cfg_reg_t dt_cfg; + mcpwm_dt_fed_cfg_reg_t dt_fed_cfg; + mcpwm_dt_red_cfg_reg_t dt_red_cfg; + mcpwm_carrier_cfg_reg_t carrier_cfg; + mcpwm_fh_cfg0_reg_t fh_cfg0; + mcpwm_fh_cfg1_reg_t fh_cfg1; + mcpwm_fh_status_reg_t fh_status; +} mcpwm_operator_reg_t; + +typedef struct { + volatile mcpwm_clk_cfg_reg_t clk_cfg; + volatile mcpwm_timer_regs_t timer[3]; + volatile mcpwm_timer_synci_cfg_reg_t timer_synci_cfg; + volatile mcpwm_operator_timersel_reg_t operator_timersel; + volatile mcpwm_operator_reg_t operators[3]; + volatile mcpwm_fault_detect_reg_t fault_detect; + volatile mcpwm_cap_timer_cfg_reg_t cap_timer_cfg; + volatile mcpwm_cap_timer_phase_reg_t cap_timer_phase; + volatile mcpwm_cap_chn_cfg_reg_t cap_chn_cfg[3]; + volatile mcpwm_cap_chn_reg_t cap_chn[3]; + volatile mcpwm_cap_status_reg_t cap_status; + volatile mcpwm_update_cfg_reg_t update_cfg; + volatile mcpwm_int_ena_reg_t int_ena; + volatile mcpwm_int_raw_reg_t int_raw; + volatile mcpwm_int_st_reg_t int_st; + volatile mcpwm_int_clr_reg_t int_clr; + volatile mcpwm_clk_reg_t clk; + volatile mcpwm_version_reg_t version; } mcpwm_dev_t; extern mcpwm_dev_t MCPWM0; extern mcpwm_dev_t MCPWM1; +#ifndef __cplusplus +_Static_assert(sizeof(mcpwm_dev_t) == 0x128, "Invalid size of mcpwm_dev_t structure"); +#endif + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32/include/soc/pcnt_struct.h b/components/soc/esp32/include/soc/pcnt_struct.h index caeb02ac23..ecb79f3f4f 100644 --- a/components/soc/esp32/include/soc/pcnt_struct.h +++ b/components/soc/esp32/include/soc/pcnt_struct.h @@ -21,7 +21,7 @@ extern "C" { #endif typedef volatile struct pcnt_dev_s { - struct{ + struct { union { struct { uint32_t filter_thres: 10; /*This register is used to filter pulse whose width is smaller than this value for unit0.*/ diff --git a/components/soc/esp32/include/soc/rmt_struct.h b/components/soc/esp32/include/soc/rmt_struct.h index 9736a28a77..fd1815a498 100644 --- a/components/soc/esp32/include/soc/rmt_struct.h +++ b/components/soc/esp32/include/soc/rmt_struct.h @@ -24,7 +24,7 @@ typedef volatile struct rmt_dev_s { uint32_t data_ch[8]; /*The R/W ram address for channel0-7 by apb fifo access. Note that in some circumstances, data read from the FIFO may get lost. As RMT memory area accesses using the RMTMEM method do not have this issue and provide all the functionality that the FIFO register has, it is encouraged to use that instead.*/ - struct{ + struct { union { struct { uint32_t div_cnt: 8; /*This register is used to configure the frequency divider's factor in channel0-7.*/ @@ -250,9 +250,7 @@ typedef struct rmt_item32_s { //Allow access to RMT memory using RMTMEM.chan[0].data32[8] typedef volatile struct rmt_mem_s { struct { - union { - rmt_item32_t data32[64]; - }; + rmt_item32_t data32[64]; } chan[8]; } rmt_mem_t; extern rmt_mem_t RMTMEM; diff --git a/components/soc/esp32/include/soc/rtc.h b/components/soc/esp32/include/soc/rtc.h index 7e4a73a20f..bbbf3c7550 100644 --- a/components/soc/esp32/include/soc/rtc.h +++ b/components/soc/esp32/include/soc/rtc.h @@ -493,6 +493,7 @@ typedef struct rtc_sleep_config_s { uint32_t rtc_slowmem_pd_en : 1; //!< power down RTC slow memory uint32_t rtc_peri_pd_en : 1; //!< power down RTC peripherals uint32_t wifi_pd_en : 1; //!< power down WiFi + uint32_t int_8m_pd_en : 1; //!< Power down Internal 8M oscillator uint32_t rom_mem_pd_en : 1; //!< power down main RAM and ROM uint32_t deep_slp : 1; //!< power down digital domain uint32_t wdt_flashboot_mod_en : 1; //!< enable WDT flashboot mode @@ -513,6 +514,7 @@ typedef struct rtc_sleep_config_s { * * @param RTC_SLEEP_PD_x flags combined using bitwise OR */ +#define is_dslp(pd_flags) ((pd_flags) & RTC_SLEEP_PD_DIG) #define RTC_SLEEP_CONFIG_DEFAULT(sleep_flags) { \ .lslp_mem_inf_fpu = 0, \ .rtc_mem_inf_fpu = 0, \ @@ -521,13 +523,18 @@ typedef struct rtc_sleep_config_s { .rtc_slowmem_pd_en = ((sleep_flags) & RTC_SLEEP_PD_RTC_SLOW_MEM) ? 1 : 0, \ .rtc_peri_pd_en = ((sleep_flags) & RTC_SLEEP_PD_RTC_PERIPH) ? 1 : 0, \ .wifi_pd_en = 0, \ + .int_8m_pd_en = is_dslp(sleep_flags) ? 1 : ((sleep_flags) & RTC_SLEEP_PD_INT_8M) ? 1 : 0, \ .rom_mem_pd_en = 0, \ .deep_slp = ((sleep_flags) & RTC_SLEEP_PD_DIG) ? 1 : 0, \ .wdt_flashboot_mod_en = 0, \ .dig_dbias_wak = RTC_CNTL_DBIAS_1V10, \ - .dig_dbias_slp = RTC_CNTL_DBIAS_0V90, \ + .dig_dbias_slp = is_dslp(sleep_flags) ? RTC_CNTL_DBIAS_0V90 \ + : !((sleep_flags) & RTC_SLEEP_PD_INT_8M) ? RTC_CNTL_DBIAS_1V10 \ + : RTC_CNTL_DBIAS_0V90, \ .rtc_dbias_wak = RTC_CNTL_DBIAS_1V10, \ - .rtc_dbias_slp = RTC_CNTL_DBIAS_0V90, \ + .rtc_dbias_slp = is_dslp(sleep_flags) ? RTC_CNTL_DBIAS_0V90 \ + : !((sleep_flags) & RTC_SLEEP_PD_INT_8M) ? RTC_CNTL_DBIAS_1V10 \ + : RTC_CNTL_DBIAS_0V90, \ .lslp_meminf_pd = 1, \ .vddsdio_pd_en = ((sleep_flags) & RTC_SLEEP_PD_VDDSDIO) ? 1 : 0, \ .xtal_fpu = ((sleep_flags) & RTC_SLEEP_PD_XTAL) ? 0 : 1 \ @@ -540,6 +547,7 @@ typedef struct rtc_sleep_config_s { #define RTC_SLEEP_PD_RTC_MEM_FOLLOW_CPU BIT(4) //!< RTC FAST and SLOW memories are automatically powered up and down along with the CPU #define RTC_SLEEP_PD_VDDSDIO BIT(5) //!< Power down VDDSDIO regulator #define RTC_SLEEP_PD_XTAL BIT(6) //!< Power down main XTAL +#define RTC_SLEEP_PD_INT_8M BIT(7) //!< Power down Internal 8M oscillator /* Various delays to be programmed into power control state machines */ #define RTC_CNTL_XTL_BUF_WAIT_SLP_US (500) diff --git a/components/soc/esp32/include/soc/sdmmc_struct.h b/components/soc/esp32/include/soc/sdmmc_struct.h index 8a3bd8fcf6..814a255249 100644 --- a/components/soc/esp32/include/soc/sdmmc_struct.h +++ b/components/soc/esp32/include/soc/sdmmc_struct.h @@ -23,18 +23,22 @@ extern "C" { #endif typedef struct sdmmc_desc_s { - uint32_t reserved1: 1; - uint32_t disable_int_on_completion: 1; - uint32_t last_descriptor: 1; - uint32_t first_descriptor: 1; - uint32_t second_address_chained: 1; - uint32_t end_of_ring: 1; - uint32_t reserved2: 24; - uint32_t card_error_summary: 1; - uint32_t owned_by_idmac: 1; - uint32_t buffer1_size: 13; - uint32_t buffer2_size: 13; - uint32_t reserved3: 6; + struct { + uint32_t reserved1: 1; + uint32_t disable_int_on_completion: 1; + uint32_t last_descriptor: 1; + uint32_t first_descriptor: 1; + uint32_t second_address_chained: 1; + uint32_t end_of_ring: 1; + uint32_t reserved2: 24; + uint32_t card_error_summary: 1; + uint32_t owned_by_idmac: 1; + }; + struct { + uint32_t buffer1_size: 13; + uint32_t buffer2_size: 13; + uint32_t reserved3: 6; + }; void* buffer1_ptr; union { void* buffer2_ptr; @@ -146,8 +150,10 @@ typedef volatile struct sdmmc_dev_s { uint32_t val; } ctype; - uint32_t blksiz: 16; ///< block size, default 0x200 - uint32_t : 16; + struct { + uint32_t blksiz: 16; ///< block size, default 0x200 + uint32_t reserved: 16; + }; uint32_t bytcnt; ///< number of bytes to be transferred @@ -326,6 +332,7 @@ typedef volatile struct sdmmc_dev_s { uint32_t ces: 1; ///< card error summary uint32_t reserved2: 2; uint32_t nis: 1; ///< normal interrupt summary + uint32_t ais: 1; ///< abnormal interrupt summary uint32_t fbe_code: 3; ///< code of fatal bus error uint32_t fsm: 4; ///< DMAC FSM state uint32_t reserved3: 15; @@ -362,6 +369,7 @@ typedef volatile struct sdmmc_dev_s { uint32_t write_thr_en : 1; ///< equivalent of read_thr_en for writes uint32_t reserved1 : 13; uint32_t card_threshold : 12; ///< threshold value for reads/writes, in bytes + uint32_t reserved28: 4; }; uint32_t val; } cardthrctl; @@ -378,6 +386,7 @@ typedef volatile struct sdmmc_dev_s { uint32_t div_factor_p: 4; ///< controls clock period; it will be (div_factor_p + 1) / 160MHz uint32_t div_factor_h: 4; ///< controls length of high pulse; it will be (div_factor_h + 1) / 160MHz uint32_t div_factor_m: 4; ///< should be equal to div_factor_p + uint32_t reserved21: 11; }; uint32_t val; } clock; diff --git a/components/soc/esp32/include/soc/soc.h b/components/soc/esp32/include/soc/soc.h index 07b1e9c27c..f9e3e87593 100644 --- a/components/soc/esp32/include/soc/soc.h +++ b/components/soc/esp32/include/soc/soc.h @@ -307,8 +307,8 @@ #define ETS_GPIO_NMI_SOURCE 23/**< interrupt of GPIO, NMI*/ #define ETS_FROM_CPU_INTR0_SOURCE 24/**< interrupt0 generated from a CPU, level*/ /* Used for FreeRTOS */ #define ETS_FROM_CPU_INTR1_SOURCE 25/**< interrupt1 generated from a CPU, level*/ /* Used for FreeRTOS */ -#define ETS_FROM_CPU_INTR2_SOURCE 26/**< interrupt2 generated from a CPU, level*/ /* Used for DPORT Access */ -#define ETS_FROM_CPU_INTR3_SOURCE 27/**< interrupt3 generated from a CPU, level*/ /* Used for DPORT Access */ +#define ETS_FROM_CPU_INTR2_SOURCE 26/**< interrupt2 generated from a CPU, level*/ /* Used for IPC_ISR */ +#define ETS_FROM_CPU_INTR3_SOURCE 27/**< interrupt3 generated from a CPU, level*/ /* Used for IPC_ISR */ #define ETS_SPI0_INTR_SOURCE 28/**< interrupt of SPI0, level, SPI0 is for Cache Access, do not use this*/ #define ETS_SPI1_INTR_SOURCE 29/**< interrupt of SPI1, level, SPI1 is for flash read/write, do not use this*/ #define ETS_SPI2_INTR_SOURCE 30/**< interrupt of SPI2, level*/ @@ -351,6 +351,60 @@ #define ETS_CACHE_IA_INTR_SOURCE 68/**< interrupt of Cache Invalied Access, LEVEL*/ #define ETS_MAX_INTR_SOURCE 69/**< total number of interrupt sources*/ +#if CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_5 +//interrupt cpu using table, Please see the core-isa.h +/************************************************************************************************************* + * Intr num Level Type PRO CPU usage APP CPU uasge + * 0 1 extern level WMAC Reserved + * 1 1 extern level BT/BLE Host HCI DMA BT/BLE Host HCI DMA + * 2 1 extern level + * 3 1 extern level + * 4 1 extern level WBB + * 5 1 extern level + * 6 1 timer FreeRTOS Tick(L1) FreeRTOS Tick(L1) + * 7 1 software BT/BLE VHCI BT/BLE VHCI + * 8 1 extern level BT/BLE BB(RX/TX) BT/BLE BB(RX/TX) + * 9 1 extern level + * 10 1 extern edge + * 11 3 profiling + * 12 1 extern level + * 13 1 extern level + * 14 7 nmi Reserved Reserved + * 15 3 timer FreeRTOS Tick(L3) FreeRTOS Tick(L3) + * 16 5 timer Reserved Reserved + * 17 1 extern level + * 18 1 extern level + * 19 2 extern level + * 20 2 extern level + * 21 2 extern level + * 22 3 extern edge + * 23 3 extern level + * 24 4 extern level + * 25 4 extern level BT/BLE Controller BT/BLE Controller + * 26 5 extern level TG1_WDT & CACHEERR + * 27 3 extern level Reserved Reserved + * 28 4 extern edge + * 29 3 software BT/BLE hli BT/BLE hli + * 30 4 extern edge Reserved Reserved + * 31 5 extern level IPC_ISR IPC_ISR + ************************************************************************************************************* + */ + +//CPU0 Interrupt number reserved, not touch this. +#define ETS_WMAC_INUM 0 +#define ETS_BT_HOST_INUM 1 +#define ETS_WBB_INUM 4 +#define ETS_TG0_T1_INUM 10 /**< use edge interrupt*/ +#define ETS_FRC1_INUM 22 +#define ETS_T1_WDT_CACHEERR_INUM 26 +#define ETS_T1_WDT_INUM ETS_T1_WDT_CACHEERR_INUM +#define ETS_MEMACCESS_ERR_INUM ETS_T1_WDT_CACHEERR_INUM +/* backwards compatibility only, use ETS_MEMACCESS_ERR_INUM instead*/ +#define ETS_CACHEERR_INUM ETS_MEMACCESS_ERR_INUM +#define ETS_IPC_ISR_INUM 31 + +#elif CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4 + //interrupt cpu using table, Please see the core-isa.h /************************************************************************************************************* * Intr num Level Type PRO CPU usage APP CPU uasge @@ -382,7 +436,7 @@ * 25 4 extern level CACHEERR * 26 5 extern level * 27 3 extern level Reserved Reserved - * 28 4 extern edge DPORT ACCESS DPORT ACCESS + * 28 4 extern edge IPC_ISR IPC_ISR * 29 3 software Reserved Reserved * 30 4 extern edge Reserved Reserved * 31 5 extern level @@ -399,7 +453,9 @@ #define ETS_MEMACCESS_ERR_INUM 25 /* backwards compatibility only, use ETS_MEMACCESS_ERR_INUM instead*/ #define ETS_CACHEERR_INUM ETS_MEMACCESS_ERR_INUM -#define ETS_DPORT_INUM 28 +#define ETS_IPC_ISR_INUM 28 + +#endif /* CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_5 */ //CPU0 Interrupt number used in ROM, should be cancelled in SDK #define ETS_SLC_INUM 1 diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index dd6f994b1a..f9eef1ce18 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -68,7 +68,6 @@ #define SOC_SDIO_SLAVE_SUPPORTED 1 #define SOC_TWAI_SUPPORTED 1 #define SOC_EMAC_SUPPORTED 1 -#define SOC_RISCV_COPROC_SUPPORTED 0 //TODO: correct the caller and remove this line #define SOC_CPU_CORES_NUM 2 #define SOC_ULP_SUPPORTED 1 #define SOC_RTC_SLOW_MEM_SUPPORTED 1 @@ -76,20 +75,33 @@ #define SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS 1 /*-------------------------- ADC CAPS ----------------------------------------*/ -#define SOC_ADC_PERIPH_NUM (2) -#define SOC_ADC_PATT_LEN_MAX (16) -#define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) ((PERIPH_NUM==0)? 8: 10) -#define SOC_ADC_MAX_CHANNEL_NUM (10) -#define SOC_ADC_MAX_BITWIDTH (12) - /** + * TO BE REMOVED in !14278 * Check if adc support digital controller (DMA) mode. * @value * - 1 : support; * - 0 : not support; */ #define SOC_ADC_SUPPORT_DMA_MODE(PERIPH_NUM) ((PERIPH_NUM==0)? 1: 0) -#define SOC_ADC_SUPPORT_RTC_CTRL 1 + +/*!< SAR ADC Module*/ +#define SOC_ADC_RTC_CTRL_SUPPORTED 1 +#define SOC_ADC_PERIPH_NUM (2) +#define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) ((PERIPH_NUM==0)? 8: 10) +#define SOC_ADC_MAX_CHANNEL_NUM (10) + +/*!< Digital */ +#define SOC_ADC_DIGI_CONTROLLER_NUM (2) +#define SOC_ADC_PATT_LEN_MAX (16) //Two pattern table, each contains 16 items. Each item takes 1 byte. But only support ADC1 using DMA mode +#define SOC_ADC_DIGI_MIN_BITWIDTH (9) +#define SOC_ADC_DIGI_MAX_BITWIDTH (12) +/*!< F_sample = F_digi_con / 2 / interval. F_digi_con = 5M for now. 30 <= interva <= 4095 */ +#define SOC_ADC_SAMPLE_FREQ_THRES_HIGH 83333 +#define SOC_ADC_SAMPLE_FREQ_THRES_LOW 611 + +/*!< RTC */ +#define SOC_ADC_MAX_BITWIDTH (12) + /*-------------------------- BROWNOUT CAPS -----------------------------------*/ #if SOC_CAPS_ECO_VER >= 1 @@ -117,8 +129,8 @@ // set pullup/down/capability via RTC register. On ESP32-S2, Digital IOs have their own registers to // control pullup/down/capability, independent with RTC registers. -// 0~39 except from 20, 24, 28~31 are valid -#define SOC_GPIO_VALID_GPIO_MASK (0xFFFFFFFFFFULL & ~(0ULL | BIT20 | BIT24 | BIT28 | BIT29 | BIT30 | BIT31)) +// 0~39 except from 24, 28~31 are valid +#define SOC_GPIO_VALID_GPIO_MASK (0xFFFFFFFFFFULL & ~(0ULL | BIT24 | BIT28 | BIT29 | BIT30 | BIT31)) // GPIO >= 34 are input only #define SOC_GPIO_VALID_OUTPUT_GPIO_MASK (SOC_GPIO_VALID_GPIO_MASK & ~(0ULL | BIT34 | BIT35 | BIT36 | BIT37 | BIT38 | BIT39)) @@ -136,15 +148,23 @@ /*-------------------------- I2S CAPS ----------------------------------------*/ // ESP32 have 2 I2S #define SOC_I2S_NUM (2) +#define SOC_I2S_SUPPORTS_PDM_TX (1) +#define SOC_I2S_SUPPORTS_PDM_RX (1) +#define SOC_I2S_SUPPORTS_ADC (1) // ESP32 support ADC and DAC +#define SOC_I2S_SUPPORTS_DAC (1) -#define SOC_I2S_SUPPORTS_PDM (1) // ESP32 support PDM -#define SOC_I2S_SUPPORTS_ADC_DAC (1) // ESP32 support ADC and DAC - -#define SOC_I2S_MAX_BUFFER_SIZE (4 * 1024 * 1024) //the maximum RAM can be allocated - +#define SOC_I2S_SUPPORTS_APLL (1)// ESP32 support APLL #define SOC_I2S_APLL_MIN_FREQ (250000000) #define SOC_I2S_APLL_MAX_FREQ (500000000) #define SOC_I2S_APLL_MIN_RATE (10675) //in Hz, I2S Clock rate limited by hardware +#define SOC_I2S_TRANS_SIZE_ALIGN_WORD (1) // I2S DMA transfer size must be aligned to word +#define SOC_I2S_LCD_I80_VARIANT (1) // I2S has a special LCD mode that can generate Intel 8080 TX timing + +/*-------------------------- LCD CAPS ----------------------------------------*/ +/* Notes: On esp32, LCD intel 8080 timing is generated by I2S peripheral */ +#define SOC_LCD_I80_SUPPORTED (1) /*!< Intel 8080 LCD is supported */ +#define SOC_LCD_I80_BUSES (1) /*!< Only I2S0 has LCD mode */ +#define SOC_LCD_I80_BUS_WIDTH (24) /*!< Intel 8080 bus width */ /*-------------------------- LEDC CAPS ---------------------------------------*/ #define SOC_LEDC_SUPPORT_HS_MODE (1) @@ -174,10 +194,10 @@ #define SOC_MPU_REGION_WO_SUPPORTED 0 /*-------------------------- PCNT CAPS ---------------------------------------*/ -// ESP32 have 1 PCNT peripheral -#define SOC_PCNT_PORT_NUM (1) -#define SOC_PCNT_UNIT_NUM (8) -#define SOC_PCNT_UNIT_CHANNEL_NUM (2) +#define SOC_PCNT_GROUPS (1) +#define SOC_PCNT_UNITS_PER_GROUP (8) +#define SOC_PCNT_CHANNELS_PER_UNIT (2) +#define SOC_PCNT_THRES_POINT_PER_UNIT (2) /*-------------------------- RMT CAPS ----------------------------------------*/ #define SOC_RMT_GROUPS (1) /*!< One RMT group */ @@ -293,3 +313,6 @@ */ #define SOC_SDMMC_USE_IOMUX 1 #define SOC_SDMMC_NUM_SLOTS 2 + +/*------------------------------ BLE --------------------------------------------*/ +#define SOC_BLE_DONT_UPDATE_OWN_RPA (1) diff --git a/components/soc/esp32/include/soc/timer_group_struct.h b/components/soc/esp32/include/soc/timer_group_struct.h index 4ea1abe75d..ec43f6d7a3 100644 --- a/components/soc/esp32/include/soc/timer_group_struct.h +++ b/components/soc/esp32/include/soc/timer_group_struct.h @@ -21,7 +21,7 @@ extern "C" { #endif typedef volatile struct timg_dev_s { - struct{ + struct { union { struct { uint32_t reserved0: 10; diff --git a/components/soc/esp32/include/soc/twai_struct.h b/components/soc/esp32/include/soc/twai_struct.h index e9454e1cc5..e4349d33ed 100644 --- a/components/soc/esp32/include/soc/twai_struct.h +++ b/components/soc/esp32/include/soc/twai_struct.h @@ -35,10 +35,10 @@ typedef volatile struct twai_dev_s { uint32_t lom: 1; /* MOD.1 Listen Only Mode */ uint32_t stm: 1; /* MOD.2 Self Test Mode */ uint32_t afm: 1; /* MOD.3 Acceptance Filter Mode */ - uint32_t reserved28: 28; /* Internal Reserved. MOD.4 Sleep Mode not supported */ + uint32_t reserved4: 28; /* Internal Reserved. MOD.4 Sleep Mode not supported */ }; uint32_t val; - } mode_reg; /* Address 0 */ + } mode_reg; /* Address 0x0000 */ union { struct { uint32_t tr: 1; /* CMR.0 Transmission Request */ @@ -46,10 +46,10 @@ typedef volatile struct twai_dev_s { uint32_t rrb: 1; /* CMR.2 Release Receive Buffer */ uint32_t cdo: 1; /* CMR.3 Clear Data Overrun */ uint32_t srr: 1; /* CMR.4 Self Reception Request */ - uint32_t reserved27: 27; /* Internal Reserved */ + uint32_t reserved5: 27; /* Internal Reserved */ }; uint32_t val; - } command_reg; /* Address 1 */ + } command_reg; /* Address 0x0004 */ union { struct { uint32_t rbs: 1; /* SR.0 Receive Buffer Status */ @@ -60,23 +60,24 @@ typedef volatile struct twai_dev_s { uint32_t ts: 1; /* SR.5 Transmit Status */ uint32_t es: 1; /* SR.6 Error Status */ uint32_t bs: 1; /* SR.7 Bus Status */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } status_reg; /* Address 2 */ + } status_reg; /* Address 0x0008 */ union { struct { uint32_t ri: 1; /* IR.0 Receive Interrupt */ uint32_t ti: 1; /* IR.1 Transmit Interrupt */ uint32_t ei: 1; /* IR.2 Error Interrupt */ - uint32_t reserved2: 2; /* Internal Reserved (Data Overrun interrupt and Wake-up not supported) */ + uint32_t doi: 1; /* IR.3 Data Overrun Interrupt */ + uint32_t reserved4: 1; /* Internal Reserved (Wake-up not supported) */ uint32_t epi: 1; /* IR.5 Error Passive Interrupt */ uint32_t ali: 1; /* IR.6 Arbitration Lost Interrupt */ uint32_t bei: 1; /* IR.7 Bus Error Interrupt */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } interrupt_reg; /* Address 3 */ + } interrupt_reg; /* Address 0x000C */ union { struct { uint32_t rie: 1; /* IER.0 Receive Interrupt Enable */ @@ -87,70 +88,70 @@ typedef volatile struct twai_dev_s { uint32_t epie: 1; /* IER.5 Error Passive Interrupt Enable */ uint32_t alie: 1; /* IER.6 Arbitration Lost Interrupt Enable */ uint32_t beie: 1; /* IER.7 Bus Error Interrupt Enable */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } interrupt_enable_reg; /* Address 4 */ - uint32_t reserved_05; /* Address 5 */ + } interrupt_enable_reg; /* Address 0x0010 */ + uint32_t reserved_14; union { struct { uint32_t brp: 6; /* BTR0[5:0] Baud Rate Prescaler */ uint32_t sjw: 2; /* BTR0[7:6] Synchronization Jump Width*/ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } bus_timing_0_reg; /* Address 6 */ + } bus_timing_0_reg; /* Address 0x0018 */ union { struct { uint32_t tseg1: 4; /* BTR1[3:0] Timing Segment 1 */ uint32_t tseg2: 3; /* BTR1[6:4] Timing Segment 2 */ uint32_t sam: 1; /* BTR1.7 Sampling*/ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } bus_timing_1_reg; /* Address 7 */ - uint32_t reserved_08; /* Address 8 (Output control not supported) */ - uint32_t reserved_09; /* Address 9 (Test Register not supported) */ - uint32_t reserved_10; /* Address 10 */ + } bus_timing_1_reg; /* Address 0x001C */ + uint32_t reserved_20; /* Address 0x0020 (Output control not supported) */ + uint32_t reserved_24; /* Address 0x0024 (Test Register not supported) */ + uint32_t reserved_28; /* Address 0x0028 */ //Capture and Counter Registers union { struct { uint32_t alc: 5; /* ALC[4:0] Arbitration lost capture */ - uint32_t reserved27: 27; /* Internal Reserved */ + uint32_t reserved5: 27; /* Internal Reserved */ }; uint32_t val; - } arbitration_lost_captue_reg; /* Address 11 */ + } arbitration_lost_captue_reg; /* Address 0x002C */ union { struct { uint32_t seg: 5; /* ECC[4:0] Error Code Segment 0 to 5 */ uint32_t dir: 1; /* ECC.5 Error Direction (TX/RX) */ uint32_t errc: 2; /* ECC[7:6] Error Code */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } error_code_capture_reg; /* Address 12 */ + } error_code_capture_reg; /* Address 0x0030 */ union { struct { uint32_t ewl: 8; /* EWL[7:0] Error Warning Limit */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } error_warning_limit_reg; /* EWLR[7:0] Error Warning Limit: Address 13 */ + } error_warning_limit_reg; /* Address 0x0034 */ union { struct { uint32_t rxerr: 8; /* RXERR[7:0] Receive Error Counter */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } rx_error_counter_reg; /* Address 12 */ + } rx_error_counter_reg; /* Address 0x0038 */ union { struct { uint32_t txerr: 8; /* TXERR[7:0] Receive Error Counter */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } tx_error_counter_reg; /* Address 15 */ + } tx_error_counter_reg; /* Address 0x003C */ //Shared Registers (TX Buff/RX Buff/Acc Filter) union { @@ -158,47 +159,51 @@ typedef volatile struct twai_dev_s { union { struct { uint32_t byte: 8; /* ACRx[7:0] Acceptance Code */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; } acr[4]; union { struct { uint32_t byte: 8; /* AMRx[7:0] Acceptance Mask */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; } amr[4]; - uint32_t reserved32[5]; + uint32_t reserved_60; + uint32_t reserved_64; + uint32_t reserved_68; + uint32_t reserved_6c; + uint32_t reserved_70; } acceptance_filter; union { struct { - uint32_t byte: 8; - uint32_t reserved24: 24; + uint32_t byte: 8; /* TX/RX Byte X [7:0] */ + uint32_t reserved24: 24; /* Internal Reserved */ }; uint32_t val; } tx_rx_buffer[13]; - }; /* Address 16-28 TX/RX Buffer and Acc Filter*/; + }; /* Address 0x0040 - 0x0070 */ //Misc Registers union { struct { uint32_t rmc: 7; /* RMC[6:0] RX Message Counter */ - uint32_t reserved25: 25; /* Internal Reserved */ + uint32_t reserved7: 25; /* Internal Reserved */ }; uint32_t val; - } rx_message_counter_reg; /* Address 29 */ - uint32_t reserved_30; /* Address 30 (RX Buffer Start Address not supported) */ + } rx_message_counter_reg; /* Address 0x0074 */ + uint32_t reserved_78; /* Address 0x0078 (RX Buffer Start Address not supported) */ union { struct { uint32_t cd: 3; /* CDR[2:0] CLKOUT frequency selector based of fOSC */ uint32_t co: 1; /* CDR.3 CLKOUT enable/disable */ - uint32_t reserved3: 3; /* Internal Reserved. RXINTEN and CBP not supported */ + uint32_t reserved4: 3; /* Internal Reserved. RXINTEN and CBP not supported */ uint32_t cm: 1; /* CDR.7 Register Layout. Basic:0 Extended:1 */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved6: 24; /* Internal Reserved */ }; uint32_t val; - } clock_divider_reg; /* Address 31 */ + } clock_divider_reg; /* Address 0x007C */ } twai_dev_t; _Static_assert(sizeof(twai_dev_t) == 128, "TWAI registers should be 32 * 4 bytes"); diff --git a/components/soc/esp32/include/soc/uart_pins.h b/components/soc/esp32/include/soc/uart_pins.h new file mode 100644 index 0000000000..c84d399768 --- /dev/null +++ b/components/soc/esp32/include/soc/uart_pins.h @@ -0,0 +1,53 @@ +// Copyright 2015-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. + +#pragma once + +#include "soc/io_mux_reg.h" + +/* Specify the number of pins for UART */ +#define SOC_UART_PINS_COUNT (4) + +/* Specify the GPIO pin number for each UART signal in the IOMUX */ +#define U0TXD_GPIO_NUM (1) +#define U0RXD_GPIO_NUM (3) +#define U0CTS_GPIO_NUM (19) +#define U0RTS_GPIO_NUM (22) + +#define U1TXD_GPIO_NUM (10) +#define U1RXD_GPIO_NUM (9) +#define U1CTS_GPIO_NUM (6) +#define U1RTS_GPIO_NUM (11) + +#define U2TXD_GPIO_NUM (17) +#define U2RXD_GPIO_NUM (16) +#define U2CTS_GPIO_NUM (8) +#define U2RTS_GPIO_NUM (7) + +/* The following defines are necessary for reconfiguring the UART + * to use IOMUX, at runtime. */ +#define U0TXD_MUX_FUNC (FUNC_U0TXD_U0TXD) +#define U0RXD_MUX_FUNC (FUNC_U0RXD_U0RXD) +#define U0RTS_MUX_FUNC (FUNC_GPIO22_U0RTS) +#define U0CTS_MUX_FUNC (FUNC_GPIO19_U0CTS) + +#define U1TXD_MUX_FUNC (FUNC_SD_DATA3_U1TXD) +#define U1RXD_MUX_FUNC (FUNC_SD_DATA2_U1RXD) +#define U1RTS_MUX_FUNC (FUNC_SD_CMD_U1RTS) +#define U1CTS_MUX_FUNC (FUNC_SD_CLK_U1CTS) + +#define U2TXD_MUX_FUNC (FUNC_GPIO17_U2TXD) +#define U2RXD_MUX_FUNC (FUNC_GPIO16_U2RXD) +#define U2RTS_MUX_FUNC (FUNC_SD_DATA0_U2RTS) +#define U2CTS_MUX_FUNC (FUNC_SD_DATA1_U2CTS) diff --git a/components/soc/esp32/include/soc/uart_struct.h b/components/soc/esp32/include/soc/uart_struct.h index 7dc9b5144c..9feb0cb353 100644 --- a/components/soc/esp32/include/soc/uart_struct.h +++ b/components/soc/esp32/include/soc/uart_struct.h @@ -23,8 +23,8 @@ extern "C" { typedef volatile struct uart_dev_s { union { struct { - uint8_t rw_byte; /*This register stores one byte data read by rx fifo.*/ - uint8_t reserved[3]; + uint32_t rw_byte: 8; /*This register stores one byte data read by rx fifo.*/ + uint32_t reserved: 24; }; uint32_t val; } fifo; diff --git a/components/soc/esp32/include/soc/uhci_struct.h b/components/soc/esp32/include/soc/uhci_struct.h index 3f42536c31..764268b35a 100644 --- a/components/soc/esp32/include/soc/uhci_struct.h +++ b/components/soc/esp32/include/soc/uhci_struct.h @@ -277,7 +277,7 @@ typedef volatile struct uhci_dev_s { }; uint32_t val; } quick_sent; - struct{ + struct { uint32_t w_data[2]; /*This register stores the content of short packet's dword*/ } q_data[7]; union { diff --git a/components/soc/esp32/lcd_periph.c b/components/soc/esp32/lcd_periph.c new file mode 100644 index 0000000000..4ed419f404 --- /dev/null +++ b/components/soc/esp32/lcd_periph.c @@ -0,0 +1,53 @@ +// Copyright 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. + +#include "soc/soc.h" +#include "soc/lcd_periph.h" +#include "soc/gpio_sig_map.h" + +const lcd_signal_conn_t lcd_periph_signals = { + .buses = { + [0] = { + .module = PERIPH_I2S0_MODULE, + .irq_id = ETS_I2S0_INTR_SOURCE, + .data_sigs = { + I2S0O_DATA_OUT0_IDX, + I2S0O_DATA_OUT1_IDX, + I2S0O_DATA_OUT2_IDX, + I2S0O_DATA_OUT3_IDX, + I2S0O_DATA_OUT4_IDX, + I2S0O_DATA_OUT5_IDX, + I2S0O_DATA_OUT6_IDX, + I2S0O_DATA_OUT7_IDX, + I2S0O_DATA_OUT8_IDX, + I2S0O_DATA_OUT9_IDX, + I2S0O_DATA_OUT10_IDX, + I2S0O_DATA_OUT11_IDX, + I2S0O_DATA_OUT12_IDX, + I2S0O_DATA_OUT13_IDX, + I2S0O_DATA_OUT14_IDX, + I2S0O_DATA_OUT15_IDX, + I2S0O_DATA_OUT16_IDX, + I2S0O_DATA_OUT17_IDX, + I2S0O_DATA_OUT18_IDX, + I2S0O_DATA_OUT19_IDX, + I2S0O_DATA_OUT20_IDX, + I2S0O_DATA_OUT21_IDX, + I2S0O_DATA_OUT22_IDX, + I2S0O_DATA_OUT23_IDX, + }, + .wr_sig = I2S0O_WS_OUT_IDX, + } + } +}; diff --git a/components/soc/esp32/pcnt_periph.c b/components/soc/esp32/pcnt_periph.c index 92d97815c6..23673810b4 100644 --- a/components/soc/esp32/pcnt_periph.c +++ b/components/soc/esp32/pcnt_periph.c @@ -16,102 +16,106 @@ #include "soc/gpio_sig_map.h" const pcnt_signal_conn_t pcnt_periph_signals = { - .module = PERIPH_PCNT_MODULE, - .irq = ETS_PCNT_INTR_SOURCE, - .units = { + .groups = { [0] = { - .channels = { + .module = PERIPH_PCNT_MODULE, + .irq = ETS_PCNT_INTR_SOURCE, + .units = { [0] = { - .control_sig = PCNT_CTRL_CH0_IN0_IDX, - .pulse_sig = PCNT_SIG_CH0_IN0_IDX + .channels = { + [0] = { + .control_sig = PCNT_CTRL_CH0_IN0_IDX, + .pulse_sig = PCNT_SIG_CH0_IN0_IDX + }, + [1] = { + .control_sig = PCNT_CTRL_CH1_IN0_IDX, + .pulse_sig = PCNT_SIG_CH1_IN0_IDX + } + } }, [1] = { - .control_sig = PCNT_CTRL_CH1_IN0_IDX, - .pulse_sig = PCNT_SIG_CH1_IN0_IDX - } - } - }, - [1] = { - .channels = { - [0] = { - .control_sig = PCNT_CTRL_CH0_IN1_IDX, - .pulse_sig = PCNT_SIG_CH0_IN1_IDX + .channels = { + [0] = { + .control_sig = PCNT_CTRL_CH0_IN1_IDX, + .pulse_sig = PCNT_SIG_CH0_IN1_IDX + }, + [1] = { + .control_sig = PCNT_CTRL_CH1_IN1_IDX, + .pulse_sig = PCNT_SIG_CH1_IN1_IDX + } + } }, - [1] = { - .control_sig = PCNT_CTRL_CH1_IN1_IDX, - .pulse_sig = PCNT_SIG_CH1_IN1_IDX - } - } - }, - [2] = { - .channels = { - [0] = { - .control_sig = PCNT_CTRL_CH0_IN2_IDX, - .pulse_sig = PCNT_SIG_CH0_IN2_IDX + [2] = { + .channels = { + [0] = { + .control_sig = PCNT_CTRL_CH0_IN2_IDX, + .pulse_sig = PCNT_SIG_CH0_IN2_IDX + }, + [1] = { + .control_sig = PCNT_CTRL_CH1_IN2_IDX, + .pulse_sig = PCNT_SIG_CH1_IN2_IDX + } + } }, - [1] = { - .control_sig = PCNT_CTRL_CH1_IN2_IDX, - .pulse_sig = PCNT_SIG_CH1_IN2_IDX - } - } - }, - [3] = { - .channels = { - [0] = { - .control_sig = PCNT_CTRL_CH0_IN3_IDX, - .pulse_sig = PCNT_SIG_CH0_IN3_IDX + [3] = { + .channels = { + [0] = { + .control_sig = PCNT_CTRL_CH0_IN3_IDX, + .pulse_sig = PCNT_SIG_CH0_IN3_IDX + }, + [1] = { + .control_sig = PCNT_CTRL_CH1_IN3_IDX, + .pulse_sig = PCNT_SIG_CH1_IN3_IDX + } + } }, - [1] = { - .control_sig = PCNT_CTRL_CH1_IN3_IDX, - .pulse_sig = PCNT_SIG_CH1_IN3_IDX - } - } - }, - [4] = { - .channels = { - [0] = { - .control_sig = PCNT_CTRL_CH0_IN4_IDX, - .pulse_sig = PCNT_SIG_CH0_IN4_IDX + [4] = { + .channels = { + [0] = { + .control_sig = PCNT_CTRL_CH0_IN4_IDX, + .pulse_sig = PCNT_SIG_CH0_IN4_IDX + }, + [1] = { + .control_sig = PCNT_CTRL_CH1_IN4_IDX, + .pulse_sig = PCNT_SIG_CH1_IN4_IDX + } + } }, - [1] = { - .control_sig = PCNT_CTRL_CH1_IN4_IDX, - .pulse_sig = PCNT_SIG_CH1_IN4_IDX - } - } - }, - [5] = { - .channels = { - [0] = { - .control_sig = PCNT_CTRL_CH0_IN5_IDX, - .pulse_sig = PCNT_SIG_CH0_IN5_IDX + [5] = { + .channels = { + [0] = { + .control_sig = PCNT_CTRL_CH0_IN5_IDX, + .pulse_sig = PCNT_SIG_CH0_IN5_IDX + }, + [1] = { + .control_sig = PCNT_CTRL_CH1_IN5_IDX, + .pulse_sig = PCNT_SIG_CH1_IN5_IDX + } + } }, - [1] = { - .control_sig = PCNT_CTRL_CH1_IN5_IDX, - .pulse_sig = PCNT_SIG_CH1_IN5_IDX - } - } - }, - [6] = { - .channels = { - [0] = { - .control_sig = PCNT_CTRL_CH0_IN6_IDX, - .pulse_sig = PCNT_SIG_CH0_IN6_IDX + [6] = { + .channels = { + [0] = { + .control_sig = PCNT_CTRL_CH0_IN6_IDX, + .pulse_sig = PCNT_SIG_CH0_IN6_IDX + }, + [1] = { + .control_sig = PCNT_CTRL_CH1_IN6_IDX, + .pulse_sig = PCNT_SIG_CH1_IN6_IDX + } + } }, - [1] = { - .control_sig = PCNT_CTRL_CH1_IN6_IDX, - .pulse_sig = PCNT_SIG_CH1_IN6_IDX - } - } - }, - [7] = { - .channels = { - [0] = { - .control_sig = PCNT_CTRL_CH0_IN7_IDX, - .pulse_sig = PCNT_SIG_CH0_IN7_IDX - }, - [1] = { - .control_sig = PCNT_CTRL_CH1_IN7_IDX, - .pulse_sig = PCNT_SIG_CH1_IN7_IDX + [7] = { + .channels = { + [0] = { + .control_sig = PCNT_CTRL_CH0_IN7_IDX, + .pulse_sig = PCNT_SIG_CH0_IN7_IDX + }, + [1] = { + .control_sig = PCNT_CTRL_CH1_IN7_IDX, + .pulse_sig = PCNT_SIG_CH1_IN7_IDX + } + } } } } diff --git a/components/soc/esp32/uart_periph.c b/components/soc/esp32/uart_periph.c index 0f931fb7bd..b9a590fe18 100644 --- a/components/soc/esp32/uart_periph.c +++ b/components/soc/esp32/uart_periph.c @@ -19,27 +19,104 @@ */ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { { - .tx_sig = U0TXD_OUT_IDX, - .rx_sig = U0RXD_IN_IDX, - .rts_sig = U0RTS_OUT_IDX, - .cts_sig = U0CTS_IN_IDX, + .pins = { + [SOC_UART_TX_PIN_IDX] = { + .default_gpio = U0TXD_GPIO_NUM, + .iomux_func = U0TXD_MUX_FUNC, + .input = 0, + .signal = U0TXD_OUT_IDX, + }, + + [SOC_UART_RX_PIN_IDX] = { + .default_gpio = U0RXD_GPIO_NUM, + .iomux_func = U0RXD_MUX_FUNC, + .input = 1, + .signal = U0RXD_IN_IDX, + }, + + [SOC_UART_RTS_PIN_IDX] = { + .default_gpio = U0RTS_GPIO_NUM, + .iomux_func = U0RTS_MUX_FUNC, + .input = 0, + .signal = U0RTS_OUT_IDX, + }, + + [SOC_UART_CTS_PIN_IDX] = { + .default_gpio = U0CTS_GPIO_NUM, + .iomux_func = U0CTS_MUX_FUNC, + .input = 1, + .signal = U0CTS_IN_IDX, + } + }, .irq = ETS_UART0_INTR_SOURCE, .module = PERIPH_UART0_MODULE, }, + { - .tx_sig = U1TXD_OUT_IDX, - .rx_sig = U1RXD_IN_IDX, - .rts_sig = U1RTS_OUT_IDX, - .cts_sig = U1CTS_IN_IDX, + .pins = { + [SOC_UART_TX_PIN_IDX] = { + .default_gpio = U1TXD_GPIO_NUM, + .iomux_func = U1TXD_MUX_FUNC, + .input = 0, + .signal = U1TXD_OUT_IDX, + }, + + [SOC_UART_RX_PIN_IDX] = { + .default_gpio = U1RXD_GPIO_NUM, + .iomux_func = U1RXD_MUX_FUNC, + .input = 1, + .signal = U1RXD_IN_IDX, + }, + + [SOC_UART_RTS_PIN_IDX] = { + .default_gpio = U1RTS_GPIO_NUM, + .iomux_func = U1RTS_MUX_FUNC, + .input = 0, + .signal = U1RTS_OUT_IDX, + }, + + [SOC_UART_CTS_PIN_IDX] = { + .default_gpio = U1CTS_GPIO_NUM, + .iomux_func = U1CTS_MUX_FUNC, + .input = 1, + .signal = U1CTS_IN_IDX, + }, + }, .irq = ETS_UART1_INTR_SOURCE, .module = PERIPH_UART1_MODULE, }, + { - .tx_sig = U2TXD_OUT_IDX, - .rx_sig = U2RXD_IN_IDX, - .rts_sig = U2RTS_OUT_IDX, - .cts_sig = U2CTS_IN_IDX, + .pins = { + [SOC_UART_TX_PIN_IDX] = { + .default_gpio = U2TXD_GPIO_NUM, + .iomux_func = U2TXD_MUX_FUNC, + .input = 0, + .signal = U2TXD_OUT_IDX, + }, + + [SOC_UART_RX_PIN_IDX] = { + .default_gpio = U2RXD_GPIO_NUM, + .iomux_func = U2RXD_MUX_FUNC, + .input = 1, + .signal = U2RXD_IN_IDX, + }, + + [SOC_UART_RTS_PIN_IDX] = { + .default_gpio = U2RTS_GPIO_NUM, + .iomux_func = U2RTS_MUX_FUNC, + .input = 0, + .signal = U2RTS_OUT_IDX, + }, + + [SOC_UART_CTS_PIN_IDX] = { + .default_gpio = U2CTS_GPIO_NUM, + .iomux_func = U2CTS_MUX_FUNC, + .input = 1, + .signal = U2CTS_IN_IDX, + } + }, .irq = ETS_UART2_INTR_SOURCE, .module = PERIPH_UART2_MODULE, - }, + } }; diff --git a/components/soc/esp32c3/CMakeLists.txt b/components/soc/esp32c3/CMakeLists.txt index a8eac92c55..a59b5173c1 100644 --- a/components/soc/esp32c3/CMakeLists.txt +++ b/components/soc/esp32c3/CMakeLists.txt @@ -1,5 +1,6 @@ set(srcs "adc_periph.c" + "dedic_gpio_periph.c" "gdma_periph.c" "gpio_periph.c" "interrupts.c" diff --git a/components/soc/esp32c3/dedic_gpio_periph.c b/components/soc/esp32c3/dedic_gpio_periph.c new file mode 100644 index 0000000000..711274f893 --- /dev/null +++ b/components/soc/esp32c3/dedic_gpio_periph.c @@ -0,0 +1,37 @@ +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/gpio_sig_map.h" +#include "soc/dedic_gpio_periph.h" + +const dedic_gpio_signal_conn_t dedic_gpio_periph_signals = { + .module = -1, + .irq = -1, + .cores = { + [0] = { + .in_sig_per_channel = { + [0] = CPU_GPIO_IN0_IDX, + [1] = CPU_GPIO_IN1_IDX, + [2] = CPU_GPIO_IN2_IDX, + [3] = CPU_GPIO_IN3_IDX, + [4] = CPU_GPIO_IN4_IDX, + [5] = CPU_GPIO_IN5_IDX, + [6] = CPU_GPIO_IN6_IDX, + [7] = CPU_GPIO_IN7_IDX, + }, + .out_sig_per_channel = { + [0] = CPU_GPIO_OUT0_IDX, + [1] = CPU_GPIO_OUT1_IDX, + [2] = CPU_GPIO_OUT2_IDX, + [3] = CPU_GPIO_OUT3_IDX, + [4] = CPU_GPIO_OUT4_IDX, + [5] = CPU_GPIO_OUT5_IDX, + [6] = CPU_GPIO_OUT6_IDX, + [7] = CPU_GPIO_OUT7_IDX, + } + }, + }, +}; diff --git a/components/soc/esp32c3/gpio_periph.c b/components/soc/esp32c3/gpio_periph.c index e72f7e20a7..1bdf359819 100644 --- a/components/soc/esp32c3/gpio_periph.c +++ b/components/soc/esp32c3/gpio_periph.c @@ -40,26 +40,26 @@ const uint32_t GPIO_PIN_MUX_REG[SOC_GPIO_PIN_COUNT] = { }; const uint32_t GPIO_HOLD_MASK[SOC_GPIO_PIN_COUNT] = { - BIT(0), //GPIO0 - BIT(1), //GPIO1 - BIT(2), //GPIO2 - BIT(3), //GPIO3 - BIT(4), //GPIO4 - BIT(5), //GPIO5 - BIT(5), //GPIO6 - BIT(6), //GPIO7 - BIT(3), //GPIO8 - BIT(4), //GPIO9 - BIT(0), //GPIO10 - BIT(15), //GPIO11 - BIT(10), //GPIO12 - BIT(12), //GPIO13 - BIT(8), //GPIO14 - BIT(7), //GPIO15 - BIT(9), //GPIO16 - BIT(11), //GPIO17 - BIT(1), //GPIO18 - BIT(2), //GPIO19 - BIT(13), //GPIO20 - BIT(14), //GPIO21 + BIT(0), //GPIO0 + BIT(1), //GPIO1 + BIT(2), //GPIO2 + BIT(3), //GPIO3 + BIT(4), //GPIO4 + BIT(5), //GPIO5 + BIT(6), //GPIO6 + BIT(7), //GPIO7 + BIT(8), //GPIO8 + BIT(9), //GPIO9 + BIT(10), //GPIO10 + BIT(11), //GPIO11 + BIT(12), //GPIO12 + BIT(13), //GPIO13 + BIT(14), //GPIO14 + BIT(15), //GPIO15 + BIT(16), //GPIO16 + BIT(17), //GPIO17 + BIT(18), //GPIO18 + BIT(19), //GPIO19 + BIT(20), //GPIO20 + BIT(21), //GPIO21 }; diff --git a/components/soc/esp32c3/i2s_periph.c b/components/soc/esp32c3/i2s_periph.c index b20ff7fbf8..e852a8e56d 100644 --- a/components/soc/esp32c3/i2s_periph.c +++ b/components/soc/esp32c3/i2s_periph.c @@ -20,19 +20,22 @@ */ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { { - // TODO ESP32-C3 IDF-2098 + .mck_out_sig = I2S_MCLK_OUT_IDX, - // .o_bck_in_sig = I2S0O_BCK_IN_IDX, - // .o_ws_in_sig = I2S0O_WS_IN_IDX, - // .o_bck_out_sig = I2S0O_BCK_OUT_IDX, - // .o_ws_out_sig = I2S0O_WS_OUT_IDX, - // .o_data_out_sig = I2S0O_SD_OUT_IDX, - // .i_bck_in_sig = I2S0I_BCK_OUT_IDX, - // .i_ws_in_sig = I2S0I_WS_OUT_IDX, - // .i_bck_out_sig = I2S0I_BCK_IN_IDX, - // .i_ws_out_sig = I2S0I_WS_IN_IDX, - // .i_data_in_sig = I2S0I_SD_IN_IDX, - .irq = ETS_I2S1_INTR_SOURCE, - .module = PERIPH_I2S1_MODULE, + .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_sig = I2SO_SD_OUT_IDX, + .data_in_sig = I2SI_SD_IN_IDX, + + .irq = -1, + .module = PERIPH_I2S1_MODULE, } }; diff --git a/components/soc/esp32c3/include/soc/apb_ctrl_struct.h b/components/soc/esp32c3/include/soc/apb_ctrl_struct.h index 9b832df8dd..dd20d37894 100644 --- a/components/soc/esp32c3/include/soc/apb_ctrl_struct.h +++ b/components/soc/esp32c3/include/soc/apb_ctrl_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct apb_ctrl_dev_s { union { struct { uint32_t pre_div: 10; diff --git a/components/soc/esp32c3/include/soc/apb_saradc_struct.h b/components/soc/esp32c3/include/soc/apb_saradc_struct.h index c3ea73f150..c75e582f7d 100644 --- a/components/soc/esp32c3/include/soc/apb_saradc_struct.h +++ b/components/soc/esp32c3/include/soc/apb_saradc_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct apb_saradc_dev_s { union { struct { uint32_t start_force: 1; diff --git a/components/soc/esp32c3/include/soc/assist_debug_reg.h b/components/soc/esp32c3/include/soc/assist_debug_reg.h index a0c1e9c9d8..2b13d1f5f4 100644 --- a/components/soc/esp32c3/include/soc/assist_debug_reg.h +++ b/components/soc/esp32c3/include/soc/assist_debug_reg.h @@ -652,7 +652,7 @@ extern "C" { #define ASSIST_DEBUG_LOG_MEM_FULL_FLAG_V 0x1 #define ASSIST_DEBUG_LOG_MEM_FULL_FLAG_S 0 -#define ASSIST_DEBUG_C0RE_0_LASTPC_BEFORE_EXCEPTION_REG (DR_REG_ASSIST_DEBUG_BASE + 0x094) +#define ASSIST_DEBUG_CORE_0_LASTPC_BEFORE_EXCEPTION_REG (DR_REG_ASSIST_DEBUG_BASE + 0x094) /* ASSIST_DEBUG_CORE_0_LASTPC_BEFORE_EXC : RO ;bitpos:[31:0] ;default: 32'b0 ; */ /*description: */ #define ASSIST_DEBUG_CORE_0_LASTPC_BEFORE_EXC 0xFFFFFFFF @@ -660,7 +660,7 @@ extern "C" { #define ASSIST_DEBUG_CORE_0_LASTPC_BEFORE_EXC_V 0xFFFFFFFF #define ASSIST_DEBUG_CORE_0_LASTPC_BEFORE_EXC_S 0 -#define ASSIST_DEBUG_C0RE_0_DEBUG_MODE_REG (DR_REG_ASSIST_DEBUG_BASE + 0x098) +#define ASSIST_DEBUG_CORE_0_DEBUG_MODE_REG (DR_REG_ASSIST_DEBUG_BASE + 0x098) /* ASSIST_DEBUG_CORE_0_DEBUG_MODULE_ACTIVE : RO ;bitpos:[1] ;default: 1'b0 ; */ /*description: */ #define ASSIST_DEBUG_CORE_0_DEBUG_MODULE_ACTIVE (BIT(1)) diff --git a/components/soc/esp32c3/include/soc/efuse_reg.h b/components/soc/esp32c3/include/soc/efuse_reg.h index ddaff7285c..aca7304f53 100644 --- a/components/soc/esp32c3/include/soc/efuse_reg.h +++ b/components/soc/esp32c3/include/soc/efuse_reg.h @@ -141,12 +141,12 @@ extern "C" { #define EFUSE_DIS_ICACHE_M (BIT(8)) #define EFUSE_DIS_ICACHE_V 0x1 #define EFUSE_DIS_ICACHE_S 8 -/* EFUSE_DIS_RTC_RAM_BOOT : R/W ;bitpos:[7] ;default: 1'b0 ; */ -/*description: Set this bit to disable boot from RTC RAM.*/ -#define EFUSE_DIS_RTC_RAM_BOOT (BIT(7)) -#define EFUSE_DIS_RTC_RAM_BOOT_M (BIT(7)) -#define EFUSE_DIS_RTC_RAM_BOOT_V 0x1 -#define EFUSE_DIS_RTC_RAM_BOOT_S 7 +/* EFUSE_RPT4_RESERVED5 : R/W ;bitpos:[7] ;default: 1'b0 ; */ +/*description: Reserved.*/ +#define EFUSE_RPT4_RESERVED5 (BIT(7)) +#define EFUSE_RPT4_RESERVED5_M (BIT(7)) +#define EFUSE_RPT4_RESERVED5_V 0x1 +#define EFUSE_RPT4_RESERVED5_S 7 /* EFUSE_RD_DIS : R/W ;bitpos:[6:0] ;default: 7'h0 ; */ /*description: Set this bit to disable reading from BlOCK4-10.*/ #define EFUSE_RD_DIS 0x0000007F @@ -516,12 +516,12 @@ extern "C" { #define EFUSE_DIS_ICACHE_M (BIT(8)) #define EFUSE_DIS_ICACHE_V 0x1 #define EFUSE_DIS_ICACHE_S 8 -/* EFUSE_DIS_RTC_RAM_BOOT : RO ;bitpos:[7] ;default: 1'b0 ; */ -/*description: The value of DIS_RTC_RAM_BOOT.*/ -#define EFUSE_DIS_RTC_RAM_BOOT (BIT(7)) -#define EFUSE_DIS_RTC_RAM_BOOT_M (BIT(7)) -#define EFUSE_DIS_RTC_RAM_BOOT_V 0x1 -#define EFUSE_DIS_RTC_RAM_BOOT_S 7 +/* EFUSE_RPT4_RESERVED5 : RO ;bitpos:[7] ;default: 1'b0 ; */ +/*description: Reserved.*/ +#define EFUSE_RPT4_RESERVED5 (BIT(7)) +#define EFUSE_RPT4_RESERVED5_M (BIT(7)) +#define EFUSE_RPT4_RESERVED5_V 0x1 +#define EFUSE_RPT4_RESERVED5_S 7 /* EFUSE_RD_DIS : RO ;bitpos:[6:0] ;default: 7'h0 ; */ /*description: The value of RD_DIS.*/ #define EFUSE_RD_DIS 0x0000007F @@ -1486,12 +1486,12 @@ extern "C" { #define EFUSE_DIS_ICACHE_ERR_M (BIT(8)) #define EFUSE_DIS_ICACHE_ERR_V 0x1 #define EFUSE_DIS_ICACHE_ERR_S 8 -/* EFUSE_DIS_RTC_RAM_BOOT_ERR : RO ;bitpos:[7] ;default: 1'b0 ; */ -/*description: If DIS_RTC_RAM_BOOT is 1 then it indicates a programming error.*/ -#define EFUSE_DIS_RTC_RAM_BOOT_ERR (BIT(7)) -#define EFUSE_DIS_RTC_RAM_BOOT_ERR_M (BIT(7)) -#define EFUSE_DIS_RTC_RAM_BOOT_ERR_V 0x1 -#define EFUSE_DIS_RTC_RAM_BOOT_ERR_S 7 +/* EFUSE_RPT4_RESERVED5_ERR : RO ;bitpos:[7] ;default: 1'b0 ; */ +/*description: Reserved..*/ +#define EFUSE_RPT4_RESERVED5_ERR (BIT(7)) +#define EFUSE_RPT4_RESERVED5_ERR_M (BIT(7)) +#define EFUSE_RPT4_RESERVED5_ERR_V 0x1 +#define EFUSE_RPT4_RESERVED5_ERR_S 7 /* EFUSE_RD_DIS_ERR : RO ;bitpos:[6:0] ;default: 7'h0 ; */ /*description: If any bit in RD_DIS is 1 then it indicates a programming error.*/ #define EFUSE_RD_DIS_ERR 0x0000007F @@ -1691,7 +1691,7 @@ extern "C" { #define EFUSE_DIS_DOWNLOAD_MODE_ERR_V 0x1 #define EFUSE_DIS_DOWNLOAD_MODE_ERR_S 0 -#define EFUSE_RD_REPEAT_ERR4_REG (DR_REG_EFUSE_BASE + 0x190) +#define EFUSE_RD_REPEAT_ERR4_REG (DR_REG_EFUSE_BASE + 0x18C) /* EFUSE_RPT4_RESERVED4_ERR : RO ;bitpos:[23:0] ;default: 24'h0 ; */ /*description: Reserved.*/ #define EFUSE_RPT4_RESERVED4_ERR 0x00FFFFFF diff --git a/components/soc/esp32c3/include/soc/efuse_struct.h b/components/soc/esp32c3/include/soc/efuse_struct.h index 1c51e71475..24915ba810 100644 --- a/components/soc/esp32c3/include/soc/efuse_struct.h +++ b/components/soc/esp32c3/include/soc/efuse_struct.h @@ -17,12 +17,12 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct efuse_dev_s { uint32_t pgm_data0; /*Register 0 that stores data to be programmed.*/ union { struct { uint32_t rd_dis: 7; /*Set this bit to disable reading from BlOCK4-10.*/ - uint32_t dis_rtc_ram_boot: 1; /*Set this bit to disable boot from RTC RAM.*/ + uint32_t rpt4_reserved5: 1; /*Reserved*/ uint32_t dis_icache: 1; /*Set this bit to disable Icache.*/ uint32_t dis_usb_jtag: 1; /*Set this bit to disable function of usb switch to jtag in module of usb device.*/ uint32_t dis_download_icache: 1; /*Set this bit to disable Icache in download mode (boot_mode[3:0] is 0 1 2 3 6 7).*/ @@ -106,7 +106,7 @@ typedef volatile struct { union { struct { uint32_t rd_dis: 7; /*The value of RD_DIS.*/ - uint32_t dis_rtc_ram_boot: 1; /*The value of DIS_RTC_RAM_BOOT.*/ + uint32_t rpt4_reserved5: 1; /*Reserved*/ uint32_t dis_icache: 1; /*The value of DIS_ICACHE.*/ uint32_t dis_usb_jtag: 1; /*The value of DIS_USB_JTAG.*/ uint32_t dis_download_icache: 1; /*The value of DIS_DOWNLOAD_ICACHE.*/ @@ -274,7 +274,7 @@ typedef volatile struct { union { struct { uint32_t rd_dis_err: 7; /*If any bit in RD_DIS is 1 then it indicates a programming error.*/ - uint32_t dis_rtc_ram_boot_err: 1; /*If DIS_RTC_RAM_BOOT is 1 then it indicates a programming error.*/ + uint32_t rpt4_reserved5_err: 1; /*Reserved.*/ uint32_t dis_icache_err: 1; /*If DIS_ICACHE is 1 then it indicates a programming error.*/ uint32_t dis_usb_jtag_err: 1; /*If DIS_USB_JTAG is 1 then it indicates a programming error.*/ uint32_t dis_download_icache: 1; /*If DIS_DOWNLOAD_ICACHE is 1 then it indicates a programming error.*/ @@ -342,7 +342,6 @@ typedef volatile struct { }; uint32_t val; } rd_repeat_err3; - uint32_t reserved_18c; union { struct { uint32_t rpt4_reserved4_err:24; /*Reserved.*/ @@ -350,6 +349,7 @@ typedef volatile struct { }; uint32_t val; } rd_repeat_err4; + uint32_t reserved_190; uint32_t reserved_194; uint32_t reserved_198; uint32_t reserved_19c; diff --git a/components/soc/esp32c3/include/soc/gdma_struct.h b/components/soc/esp32c3/include/soc/gdma_struct.h index 446ff4c112..dde520f5ed 100644 --- a/components/soc/esp32c3/include/soc/gdma_struct.h +++ b/components/soc/esp32c3/include/soc/gdma_struct.h @@ -19,7 +19,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct gdma_dev_s { struct { union { struct { diff --git a/components/soc/esp32c3/include/soc/gpio_sd_struct.h b/components/soc/esp32c3/include/soc/gpio_sd_struct.h index cc73cebd03..45e21d58e1 100644 --- a/components/soc/esp32c3/include/soc/gpio_sd_struct.h +++ b/components/soc/esp32c3/include/soc/gpio_sd_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct gpio_sd_dev_s { union { struct { uint32_t duty: 8; diff --git a/components/soc/esp32c3/include/soc/gpio_sig_map.h b/components/soc/esp32c3/include/soc/gpio_sig_map.h index 45be68b3e5..61aa95a3c4 100644 --- a/components/soc/esp32c3/include/soc/gpio_sig_map.h +++ b/components/soc/esp32c3/include/soc/gpio_sig_map.h @@ -53,26 +53,26 @@ #define GPIO_WLAN_PRIO_IDX 18 #define GPIO_BT_ACTIVE_IDX 19 #define GPIO_WLAN_ACTIVE_IDX 19 -#define BB_DIAG0_IDX 20 -#define BB_DIAG1_IDX 21 -#define BB_DIAG2_IDX 22 -#define BB_DIAG3_IDX 23 -#define BB_DIAG4_IDX 24 -#define BB_DIAG5_IDX 25 -#define BB_DIAG6_IDX 26 -#define BB_DIAG7_IDX 27 -#define BB_DIAG8_IDX 28 -#define BB_DIAG9_IDX 29 -#define BB_DIAG10_IDX 30 -#define BB_DIAG11_IDX 31 -#define BB_DIAG12_IDX 32 -#define BB_DIAG13_IDX 33 -#define BB_DIAG14_IDX 34 -#define BB_DIAG15_IDX 35 -#define BB_DIAG16_IDX 36 -#define BB_DIAG17_IDX 37 -#define BB_DIAG18_IDX 38 -#define BB_DIAG19_IDX 39 +#define CPU_GPIO_IN0_IDX 28 +#define CPU_GPIO_OUT0_IDX 28 +#define CPU_GPIO_IN1_IDX 29 +#define CPU_GPIO_OUT1_IDX 29 +#define CPU_GPIO_IN2_IDX 30 +#define CPU_GPIO_OUT2_IDX 30 +#define CPU_GPIO_IN3_IDX 31 +#define CPU_GPIO_OUT3_IDX 31 +#define CPU_GPIO_IN4_IDX 32 +#define CPU_GPIO_OUT4_IDX 32 +#define CPU_GPIO_IN5_IDX 33 +#define CPU_GPIO_OUT5_IDX 33 +#define CPU_GPIO_IN6_IDX 34 +#define CPU_GPIO_OUT6_IDX 34 +#define CPU_GPIO_IN7_IDX 35 +#define CPU_GPIO_OUT7_IDX 35 +#define USB_JTAG_TCK_OUT_IDX 36 +#define USB_JTAG_TMS_OUT_IDX 37 +#define USB_JTAG_TDI_OUT_IDX 38 +#define USB_JTAG_TDO_OUT_IDX 39 #define USB_EXTPHY_VP_IDX 40 #define USB_EXTPHY_OEN_IDX 40 #define USB_EXTPHY_VM_IDX 41 @@ -179,6 +179,7 @@ #define CLK_OUT_OUT2_IDX 124 #define CLK_OUT_OUT3_IDX 125 #define SPICS1_OUT_IDX 126 +#define USB_JTAG_TRST_OUT_IDX 127 #define SIG_GPIO_OUT_IDX 128 #define GPIO_MAP_DATE_IDX 0x2006130 #endif /* _SOC_GPIO_SIG_MAP_H_ */ diff --git a/components/soc/esp32c3/include/soc/gpio_struct.h b/components/soc/esp32c3/include/soc/gpio_struct.h index f260adbd2a..45f5e55412 100644 --- a/components/soc/esp32c3/include/soc/gpio_struct.h +++ b/components/soc/esp32c3/include/soc/gpio_struct.h @@ -18,7 +18,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct gpio_dev_s { uint32_t bt_select; /**/ union { struct { diff --git a/components/soc/esp32c3/include/soc/hwcrypto_reg.h b/components/soc/esp32c3/include/soc/hwcrypto_reg.h index 6844627388..474b07faa3 100644 --- a/components/soc/esp32c3/include/soc/hwcrypto_reg.h +++ b/components/soc/esp32c3/include/soc/hwcrypto_reg.h @@ -133,6 +133,7 @@ #define HMAC_SET_MESSAGE_END_REG ((DR_REG_HMAC_BASE) + 0x58) #define HMAC_SET_RESULT_FINISH_REG ((DR_REG_HMAC_BASE) + 0x5c) #define HMAC_SET_INVALIDATE_JTAG_REG ((DR_REG_HMAC_BASE) + 0x60) +#define HMAC_INVALIDATE_JTAG BIT(0) #define HMAC_SET_INVALIDATE_DS_REG ((DR_REG_HMAC_BASE) + 0x64) #define HMAC_QUERY_ERROR_REG ((DR_REG_HMAC_BASE) + 0x68) #define HMAC_QUERY_BUSY_REG ((DR_REG_HMAC_BASE) + 0x6c) diff --git a/components/soc/esp32c3/include/soc/i2c_struct.h b/components/soc/esp32c3/include/soc/i2c_struct.h index 22c6c47041..ccd5fdb5b0 100644 --- a/components/soc/esp32c3/include/soc/i2c_struct.h +++ b/components/soc/esp32c3/include/soc/i2c_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif #include "soc.h" -typedef volatile struct { +typedef volatile struct i2c_dev_s { union { struct { uint32_t period : 9; diff --git a/components/soc/esp32c3/include/soc/i2s_struct.h b/components/soc/esp32c3/include/soc/i2s_struct.h index 2f9c862b85..44334a8789 100644 --- a/components/soc/esp32c3/include/soc/i2s_struct.h +++ b/components/soc/esp32c3/include/soc/i2s_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct i2s_dev_s { uint32_t reserved_0; uint32_t reserved_4; uint32_t reserved_8; diff --git a/components/soc/esp32c3/include/soc/io_mux_reg.h b/components/soc/esp32c3/include/soc/io_mux_reg.h index 3f338ea92d..e9a0795167 100644 --- a/components/soc/esp32c3/include/soc/io_mux_reg.h +++ b/components/soc/esp32c3/include/soc/io_mux_reg.h @@ -124,9 +124,6 @@ #define GPIO_PAD_PULLDOWN(num) do{PIN_PULLUP_DIS(IOMUX_REG_GPIO##num);PIN_PULLDWN_EN(IOMUX_REG_GPIO##num);}while(0) #define GPIO_PAD_SET_DRV(num, drv) PIN_SET_DRV(IOMUX_REG_GPIO##num, drv) -#define U0RXD_GPIO_NUM 20 -#define U0TXD_GPIO_NUM 21 - #define SPI_HD_GPIO_NUM 12 #define SPI_WP_GPIO_NUM 13 #define SPI_CS0_GPIO_NUM 14 diff --git a/components/soc/esp32c3/include/soc/ledc_struct.h b/components/soc/esp32c3/include/soc/ledc_struct.h index 9e5a2a96c1..0eb8c18268 100644 --- a/components/soc/esp32c3/include/soc/ledc_struct.h +++ b/components/soc/esp32c3/include/soc/ledc_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct ledc_dev_s { struct { struct { union { diff --git a/components/soc/esp32c3/include/soc/periph_defs.h b/components/soc/esp32c3/include/soc/periph_defs.h index bb75b40f44..73c9935273 100644 --- a/components/soc/esp32c3/include/soc/periph_defs.h +++ b/components/soc/esp32c3/include/soc/periph_defs.h @@ -102,8 +102,8 @@ typedef enum { ETS_SHA_INTR_SOURCE, /**< interrupt of SHA accelerator, level*/ ETS_FROM_CPU_INTR0_SOURCE, /**< interrupt0 generated from a CPU, level*/ /* Used for FreeRTOS */ ETS_FROM_CPU_INTR1_SOURCE, /**< interrupt1 generated from a CPU, level*/ /* Used for FreeRTOS */ - ETS_FROM_CPU_INTR2_SOURCE, /**< interrupt2 generated from a CPU, level*/ /* Used for DPORT Access */ - ETS_FROM_CPU_INTR3_SOURCE, /**< interrupt3 generated from a CPU, level*/ /* Used for DPORT Access */ + ETS_FROM_CPU_INTR2_SOURCE, /**< interrupt2 generated from a CPU, level*/ + ETS_FROM_CPU_INTR3_SOURCE, /**< interrupt3 generated from a CPU, level*/ ETS_ASSIST_DEBUG_INTR_SOURCE, /**< interrupt of Assist debug module, LEVEL*/ ETS_DMA_APBPERI_PMS_INTR_SOURCE, ETS_CORE0_IRAM0_PMS_INTR_SOURCE, diff --git a/components/soc/esp32c3/include/soc/reset_reasons.h b/components/soc/esp32c3/include/soc/reset_reasons.h index 0bb99f5851..c624619bb3 100644 --- a/components/soc/esp32c3/include/soc/reset_reasons.h +++ b/components/soc/esp32c3/include/soc/reset_reasons.h @@ -52,6 +52,8 @@ typedef enum { RESET_REASON_SYS_SUPER_WDT = 0x12, // Super watch dog resets the digital core and rtc module RESET_REASON_SYS_CLK_GLITCH = 0x13, // Glitch on clock resets the digital core and rtc module RESET_REASON_CORE_EFUSE_CRC = 0x14, // eFuse CRC error resets the digital core + RESET_REASON_CORE_USB_UART = 0x15, // USB UART resets the digital core + RESET_REASON_CORE_USB_JTAG = 0x16, // USB JTAG resets the digital core RESET_REASON_CORE_PWR_GLITCH = 0x17, // Glitch on power resets the digital core } soc_reset_reason_t; diff --git a/components/soc/esp32c3/include/soc/rmt_struct.h b/components/soc/esp32c3/include/soc/rmt_struct.h index 7fc1890b12..b9b7533b3d 100644 --- a/components/soc/esp32c3/include/soc/rmt_struct.h +++ b/components/soc/esp32c3/include/soc/rmt_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct rmt_dev_s { uint32_t data_ch[4]; /**/ union { struct { @@ -291,11 +291,9 @@ typedef struct { } rmt_item32_t; //Allow access to RMT memory using RMTMEM.chan[0].data32[8] -typedef volatile struct { +typedef volatile struct rmt_mem_s { struct { - union { - rmt_item32_t data32[48]; - }; + rmt_item32_t data32[48]; } chan[4]; } rmt_mem_t; diff --git a/components/soc/esp32c3/include/soc/rtc.h b/components/soc/esp32c3/include/soc/rtc.h index 3fda6cb8a7..db67d3ac51 100644 --- a/components/soc/esp32c3/include/soc/rtc.h +++ b/components/soc/esp32c3/include/soc/rtc.h @@ -114,11 +114,14 @@ extern "C" { set sleep_init default param */ #define RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_DEFAULT 3 +#define RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_NODROP 0 #define RTC_CNTL_DBG_ATTEN_DEEPSLEEP_DEFAULT 15 #define RTC_CNTL_DBG_ATTEN_MONITOR_DEFAULT 0 #define RTC_CNTL_BIASSLP_MONITOR_DEFAULT 0 +#define RTC_CNTL_BIASSLP_SLEEP_ON 0 #define RTC_CNTL_BIASSLP_SLEEP_DEFAULT 1 #define RTC_CNTL_PD_CUR_MONITOR_DEFAULT 0 +#define RTC_CNTL_PD_CUR_SLEEP_ON 0 #define RTC_CNTL_PD_CUR_SLEEP_DEFAULT 1 #define RTC_CNTL_DG_VDD_DRV_B_SLP_DEFAULT 254 @@ -206,7 +209,8 @@ typedef enum { typedef enum { RTC_CAL_RTC_MUX = 0, //!< Currently selected RTC SLOW_CLK RTC_CAL_8MD256 = 1, //!< Internal 8 MHz RC oscillator, divided by 256 - RTC_CAL_32K_XTAL = 2 //!< External 32 kHz XTAL + RTC_CAL_32K_XTAL = 2, //!< External 32 kHz XTAL + RTC_CAL_INTERNAL_OSC = 3 //!< Internal 150 kHz oscillator } rtc_cal_sel_t; /** @@ -638,7 +642,8 @@ typedef struct { uint32_t rtc_peri_pd_en : 1; //!< power down RTC peripherals uint32_t wifi_pd_en : 1; //!< power down WiFi uint32_t bt_pd_en : 1; //!< power down BT - uint32_t cpu_pd_en : 1; //!< power down CPU, but not restart when lightsleep. + uint32_t cpu_pd_en : 1; //!< power down CPU, but not restart when lightsleep. + uint32_t int_8m_pd_en : 1; //!< Power down Internal 8M oscillator uint32_t dig_peri_pd_en : 1; //!< power down digital peripherals uint32_t deep_slp : 1; //!< power down digital domain uint32_t wdt_flashboot_mod_en : 1; //!< enable WDT flashboot mode @@ -647,6 +652,7 @@ typedef struct { uint32_t rtc_dbias_wak : 5; //!< set bias for RTC domain, in active mode uint32_t rtc_dbias_slp : 5; //!< set bias for RTC domain, in sleep mode uint32_t vddsdio_pd_en : 1; //!< power down VDDSDIO regulator + uint32_t xtal_fpu : 1; //!< keep main XTAL powered up in sleep uint32_t deep_slp_reject : 1; uint32_t light_slp_reject : 1; } rtc_sleep_config_t; @@ -659,6 +665,7 @@ typedef struct { * * @param RTC_SLEEP_PD_x flags combined using bitwise OR */ +#define is_dslp(pd_flags) ((pd_flags) & RTC_SLEEP_PD_DIG) #define RTC_SLEEP_CONFIG_DEFAULT(sleep_flags) { \ .lslp_mem_inf_fpu = 0, \ .rtc_mem_inf_follow_cpu = ((sleep_flags) & RTC_SLEEP_PD_RTC_MEM_FOLLOW_CPU) ? 1 : 0, \ @@ -668,14 +675,20 @@ typedef struct { .wifi_pd_en = ((sleep_flags) & RTC_SLEEP_PD_WIFI) ? 1 : 0, \ .bt_pd_en = ((sleep_flags) & RTC_SLEEP_PD_BT) ? 1 : 0, \ .cpu_pd_en = ((sleep_flags) & RTC_SLEEP_PD_CPU) ? 1 : 0, \ + .int_8m_pd_en = is_dslp(sleep_flags) ? 1 : ((sleep_flags) & RTC_SLEEP_PD_INT_8M) ? 1 : 0, \ .dig_peri_pd_en = ((sleep_flags) & RTC_SLEEP_PD_DIG_PERIPH) ? 1 : 0, \ .deep_slp = ((sleep_flags) & RTC_SLEEP_PD_DIG) ? 1 : 0, \ .wdt_flashboot_mod_en = 0, \ .dig_dbias_wak = RTC_CNTL_DBIAS_1V10, \ - .dig_dbias_slp = RTC_CNTL_DBIAS_SLP, \ + .dig_dbias_slp = is_dslp(sleep_flags) ? RTC_CNTL_DBIAS_SLP \ + : !((sleep_flags) & RTC_SLEEP_PD_INT_8M) ? RTC_CNTL_DBIAS_1V10 \ + : RTC_CNTL_DBIAS_SLP, \ .rtc_dbias_wak = RTC_CNTL_DBIAS_1V10, \ - .rtc_dbias_slp = RTC_CNTL_DBIAS_SLP, \ + .rtc_dbias_slp = is_dslp(sleep_flags) ? RTC_CNTL_DBIAS_SLP \ + : !((sleep_flags) & RTC_SLEEP_PD_INT_8M) ? RTC_CNTL_DBIAS_1V10 \ + : RTC_CNTL_DBIAS_SLP, \ .vddsdio_pd_en = ((sleep_flags) & RTC_SLEEP_PD_VDDSDIO) ? 1 : 0, \ + .xtal_fpu = is_dslp(sleep_flags) ? 0 : ((sleep_flags) & RTC_SLEEP_PD_XTAL) ? 0 : 1, \ .deep_slp_reject = 1, \ .light_slp_reject = 1 \ }; @@ -690,6 +703,8 @@ typedef struct { #define RTC_SLEEP_PD_BT BIT(7) //!< Power down BT #define RTC_SLEEP_PD_CPU BIT(8) //!< Power down CPU when in lightsleep, but not restart #define RTC_SLEEP_PD_DIG_PERIPH BIT(9) //!< Power down DIG peripherals +#define RTC_SLEEP_PD_INT_8M BIT(10) //!< Power down Internal 8M oscillator +#define RTC_SLEEP_PD_XTAL BIT(11) //!< Power down main XTAL /** * @brief Prepare the chip to enter sleep mode diff --git a/components/soc/esp32c3/include/soc/rtc_cntl_struct.h b/components/soc/esp32c3/include/soc/rtc_cntl_struct.h index 358ebaded7..9478048648 100644 --- a/components/soc/esp32c3/include/soc/rtc_cntl_struct.h +++ b/components/soc/esp32c3/include/soc/rtc_cntl_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct rtc_cntl_dev_s { union { struct { uint32_t sw_stall_appcpu_c0: 2; /*{reg_sw_stall_appcpu_c1[5:0] reg_sw_stall_appcpu_c0[1:0]} == 0x86 will stall APP CPU*/ diff --git a/components/soc/esp32c3/include/soc/rtc_i2c_struct.h b/components/soc/esp32c3/include/soc/rtc_i2c_struct.h index 5141eebcd6..9f97a70cad 100644 --- a/components/soc/esp32c3/include/soc/rtc_i2c_struct.h +++ b/components/soc/esp32c3/include/soc/rtc_i2c_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct rtc_i2c_dev_s { union { struct { uint32_t period: 20; /*time period that scl = 0*/ diff --git a/components/soc/esp32c3/include/soc/sensitive_struct.h b/components/soc/esp32c3/include/soc/sensitive_struct.h index a24ccf6402..ba860e45cd 100644 --- a/components/soc/esp32c3/include/soc/sensitive_struct.h +++ b/components/soc/esp32c3/include/soc/sensitive_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif #include "soc.h" -typedef volatile struct { +typedef volatile struct sensitive_dev_s { union { struct { uint32_t reg_rom_table_lock : 1; /*rom_table_lock*/ @@ -959,8 +959,7 @@ typedef volatile struct { union { struct { uint32_t reg_clk_en : 1; /*clk_en*/ - uint32_t reserved1 : 31; - uint32_t reservedNone : None; /*SENSITIVE_CLOCK_GATE_REG_REG*/ + uint32_t reserved1 : 31; /*SENSITIVE_CLOCK_GATE_REG_REG*/ }; uint32_t val; } clock_gate; diff --git a/components/soc/esp32c3/include/soc/soc.h b/components/soc/esp32c3/include/soc/soc.h index da55b8661e..72dbb15a60 100644 --- a/components/soc/esp32c3/include/soc/soc.h +++ b/components/soc/esp32c3/include/soc/soc.h @@ -268,57 +268,13 @@ // Start (highest address) of ROM boot stack, only relevant during early boot #define SOC_ROM_STACK_START 0x3fcebf10 -//interrupt cpu using table, Please see the core-isa.h -/************************************************************************************************************* - * Intr num Level Type PRO CPU usage - * 0 1 extern level Panic - * 1 1 extern level WMAC - * 2 1 extern level - * 3 1 extern level - * 4 1 extern level WBB - * 5 1 extern level BT/BLE Controller - * 6 1 timer FreeRTOS Tick(L1) - * 7 1 software - * 8 1 extern level BT/BLE BB(RX/TX) - * 9 1 extern level - * 10 1 extern edge - * 11 3 profiling - * 12 1 extern level - * 13 1 extern level - * 14 7 nmi Reserved - * 15 3 timer FreeRTOS Tick(L3) - * 16 5 timer - * 17 1 extern level - * 18 1 extern level - * 19 2 extern level - * 20 2 extern level - * 21 2 extern level - * 22 3 extern edge - * 23 3 extern level - * 24 4 extern level TG1_WDT - * 25 4 extern level CACHEERR - * 26 5 extern level - * 27 3 extern level Reserved - * 28 4 extern edge Reserved - * 29 3 software Reserved - * 30 4 extern edge Reserved - * 31 5 extern level - ************************************************************************************************************* - */ +//On RISC-V CPUs, the interrupt sources are all external interrupts, whose type, source and priority are configured by SW. +//There is no HW NMI conception. SW should controlled the masked levels through INT_THRESH_REG. -//CPU0 Interrupt number reserved, not touch this. -#define ETS_WMAC_INUM 1 -//#define ETS_BT_HOST_INUM 1 -#define ETS_WBB_INUM 4 -#define ETS_SYSTICK_INUM 9 -#define ETS_TG0_T1_INUM 10 /* use edge interrupt */ -#define ETS_CPU_INTR0_INUM 12 /* used as freertos soft intr */ -#define ETS_FRC1_INUM 22 +//CPU0 Interrupt number reserved in riscv/vector.S, not touch this. #define ETS_T1_WDT_INUM 24 #define ETS_CACHEERR_INUM 25 #define ETS_MEMPROT_ERR_INUM 26 -#define ETS_DPORT_INUM 28 - //CPU0 Max valid interrupt number #define ETS_MAX_INUM 31 diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index c792018c96..0406c5665a 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -6,6 +6,7 @@ #pragma once #define SOC_CPU_CORES_NUM 1 +#define SOC_DEDICATED_GPIO_SUPPORTED 1 #define SOC_GDMA_SUPPORTED 1 #define SOC_TWAI_SUPPORTED 1 #define SOC_BT_SUPPORTED 1 @@ -14,7 +15,9 @@ #define SOC_ASYNC_MEMCPY_SUPPORTED 1 #define SOC_USB_SERIAL_JTAG_SUPPORTED 1 #define SOC_TEMP_SENSOR_SUPPORTED 1 -#define SOC_FLASH_ENCRYPTION_XTS_AES 1 +#define SOC_FLASH_ENCRYPTION_XTS_AES 1 +#define SOC_XT_WDT_SUPPORTED 1 + /*-------------------------- COMMON CAPS ---------------------------------------*/ #define SOC_SUPPORTS_SECURE_DL_MODE 1 @@ -32,19 +35,30 @@ #define SOC_AES_SUPPORT_AES_256 (1) /*-------------------------- ADC CAPS -------------------------------*/ +/*!< SAR ADC Module*/ +#define SOC_ADC_ARBITER_SUPPORTED 1 +#define SOC_ADC_FILTER_SUPPORTED 1 +#define SOC_ADC_MONITOR_SUPPORTED 1 #define SOC_ADC_PERIPH_NUM (2) -#define SOC_ADC_PATT_LEN_MAX (16) #define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) ((PERIPH_NUM==0)? 5 : 1) #define SOC_ADC_MAX_CHANNEL_NUM (5) -#define SOC_ADC_MAX_BITWIDTH (12) + +/*!< Digital */ +#define SOC_ADC_DIGI_CONTROLLER_NUM (1) +#define SOC_ADC_PATT_LEN_MAX (8) /*!< One pattern table, each contains 8 items. Each item takes 1 byte */ +#define SOC_ADC_DIGI_MAX_BITWIDTH (12) #define SOC_ADC_DIGI_FILTER_NUM (2) #define SOC_ADC_DIGI_MONITOR_NUM (2) -#define SOC_ADC_HW_CALIBRATION_V1 (1) /*!< support HW offset calibration */ -#define SOC_ADC_SUPPORT_DMA_MODE(PERIPH_NUM) 1 -//F_sample = F_digi_con / 2 / interval. F_digi_con = 5M for now. 30 <= interva <= 4095 +/*!< F_sample = F_digi_con / 2 / interval. F_digi_con = 5M for now. 30 <= interva <= 4095 */ #define SOC_ADC_SAMPLE_FREQ_THRES_HIGH 83333 #define SOC_ADC_SAMPLE_FREQ_THRES_LOW 611 -#define SOC_ADC_ARBITER_SUPPORTED 1 + +/*!< RTC */ +#define SOC_ADC_MAX_BITWIDTH (12) + +/*!< Calibration */ +#define SOC_ADC_CALIBRATION_V1_SUPPORTED (1) /*!< support HW offset calibration version 1*/ + /*-------------------------- APB BACKUP DMA CAPS -------------------------------*/ #define SOC_APB_BACKUP_DMA (1) @@ -95,6 +109,11 @@ // Support to configure sleep status #define SOC_GPIO_SUPPORT_SLP_SWITCH (1) +/*-------------------------- Dedicated GPIO CAPS -----------------------------*/ +#define SOC_DEDIC_GPIO_OUT_CHANNELS_NUM (8) /*!< 8 outward channels on each CPU core */ +#define SOC_DEDIC_GPIO_IN_CHANNELS_NUM (8) /*!< 8 inward channels on each CPU core */ +#define SOC_DEDIC_PERIPH_AUTO_ENABLE (1) /*!< The dedicated GPIO peripheral is enabled automatically */ + /*-------------------------- I2C CAPS ----------------------------------------*/ // ESP32-C3 have 2 I2C. #define SOC_I2C_NUM (1) @@ -109,11 +128,10 @@ /*-------------------------- I2S CAPS ----------------------------------------*/ #define SOC_I2S_NUM (1) - -#define SOC_I2S_APLL_MIN_FREQ (250000000) -#define SOC_I2S_APLL_MAX_FREQ (500000000) -#define SOC_I2S_APLL_MIN_RATE (10675) //in Hz, I2S Clock rate limited by hardware -#define SOC_I2S_MAX_BUFFER_SIZE (4 * 1024 * 1024) //the maximum RAM can be allocated +#define SOC_I2S_SUPPORTS_PCM (1) +#define SOC_I2S_SUPPORTS_PDM_TX (1) +#define SOC_I2S_SUPPORTS_PDM_CODEC (1) +#define SOC_I2S_SUPPORTS_TDM (1) /*-------------------------- LEDC CAPS ---------------------------------------*/ #define SOC_LEDC_SUPPORT_XTAL_CLOCK (1) @@ -240,7 +258,6 @@ /*-------------------------- UART CAPS ---------------------------------------*/ // ESP32-C3 has 2 UARTs #define SOC_UART_NUM (2) - #define SOC_UART_FIFO_LEN (128) /*!< The UART hardware FIFO length */ #define SOC_UART_BITRATE_MAX (5000000) /*!< Max bit rate supported by UART */ diff --git a/components/soc/esp32c3/include/soc/spi_mem_struct.h b/components/soc/esp32c3/include/soc/spi_mem_struct.h index e0f62b0d15..cde08c0207 100644 --- a/components/soc/esp32c3/include/soc/spi_mem_struct.h +++ b/components/soc/esp32c3/include/soc/spi_mem_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct spi_mem_dev_s { union { struct { uint32_t mst_st: 4; /*The current status of SPI1 master FSM.*/ diff --git a/components/soc/esp32c3/include/soc/spi_struct.h b/components/soc/esp32c3/include/soc/spi_struct.h index cc22595dd0..4011c8fed9 100644 --- a/components/soc/esp32c3/include/soc/spi_struct.h +++ b/components/soc/esp32c3/include/soc/spi_struct.h @@ -19,7 +19,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct spi_dev_s { union { struct { uint32_t conf_bitlen : 18; /*Define the APB cycles of SPI_CONF state. Can be configured in CONF state.*/ diff --git a/components/soc/esp32c3/include/soc/syscon_struct.h b/components/soc/esp32c3/include/soc/syscon_struct.h index 2a9485aa87..b8afdf6ec8 100644 --- a/components/soc/esp32c3/include/soc/syscon_struct.h +++ b/components/soc/esp32c3/include/soc/syscon_struct.h @@ -17,26 +17,26 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct syscon_dev_s { union { struct { - uint32_t apb_ctrl_pre_div_cnt: 10; - uint32_t apb_ctrl_clk_320m_en: 1; - uint32_t clk_en: 1; - uint32_t apb_ctrl_rst_tick_cnt: 1; - uint32_t reserved13: 19; + uint32_t pre_div_cnt: 10; + uint32_t clk_320m_en: 1; + uint32_t clk_en: 1; + uint32_t rst_tick_cnt: 1; + uint32_t reserved13: 19; }; uint32_t val; - } apb_ctrl_sysclk_conf; + } sysclk_conf; union { struct { - uint32_t apb_ctrl_xtal_tick_num: 8; - uint32_t apb_ctrl_ck8m_tick_num: 8; - uint32_t apb_ctrl_tick_enable: 1; - uint32_t reserved17: 15; + uint32_t xtal_tick_num: 8; + uint32_t ck8m_tick_num: 8; + uint32_t tick_enable: 1; + uint32_t reserved17: 15; }; uint32_t val; - } apb_ctrl_tick_conf; + } tick_conf; union { struct { uint32_t clk20_oen: 1; @@ -53,7 +53,7 @@ typedef volatile struct { uint32_t reserved11: 21; }; uint32_t val; - } apb_ctrl_clk_out_en; + } clk_out_en; uint32_t wifi_bb_cfg; /**/ uint32_t wifi_bb_cfg_2; /**/ uint32_t wifi_clk_en; /**/ @@ -161,7 +161,7 @@ typedef volatile struct { uint32_t reserved1: 31; }; uint32_t val; - } apb_ctrl_sdio_ctrl; + } sdio_ctrl; union { struct { uint32_t redcy_sig0: 31; @@ -472,7 +472,7 @@ typedef volatile struct { uint32_t reserved_3f0; uint32_t reserved_3f4; uint32_t reserved_3f8; - uint32_t apb_ctrl_date; /*Version control*/ + uint32_t date; /*Version control*/ } syscon_dev_t; extern syscon_dev_t SYSCON; #ifdef __cplusplus diff --git a/components/soc/esp32c3/include/soc/system_struct.h b/components/soc/esp32c3/include/soc/system_struct.h index f07fab0aff..5e04cec828 100644 --- a/components/soc/esp32c3/include/soc/system_struct.h +++ b/components/soc/esp32c3/include/soc/system_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif #include "soc.h" -typedef volatile struct { +typedef volatile struct system_dev_s { union { struct { uint32_t reserved0 : 6; /*reserved*/ diff --git a/components/soc/esp32c3/include/soc/systimer_struct.h b/components/soc/esp32c3/include/soc/systimer_struct.h index af41b1f3e2..f10bc1f126 100644 --- a/components/soc/esp32c3/include/soc/systimer_struct.h +++ b/components/soc/esp32c3/include/soc/systimer_struct.h @@ -88,6 +88,7 @@ typedef union { * update timer_unit0 */ uint32_t timer_unit_update: 1; + uint32_t reserved31: 1; }; uint32_t val; } systimer_unit_op_reg_t; @@ -102,6 +103,7 @@ typedef struct { * timer unit load high 32 bit */ uint32_t timer_unit_load_hi: 20; + uint32_t reserved20: 12; }; uint32_t val; } hi; @@ -126,6 +128,7 @@ typedef struct { * timer target high 32 bit */ uint32_t timer_target_hi: 20; + uint32_t reserved20: 12; }; uint32_t val; } hi; @@ -172,6 +175,7 @@ typedef struct { * timer read value high 20bit */ uint32_t timer_unit_value_hi: 20; + uint32_t reserved20: 12; }; uint32_t val; } hi; @@ -195,6 +199,7 @@ typedef union { * timer comp load value */ uint32_t timer_comp_load: 1; + uint32_t reserved1: 31; }; uint32_t val; } systimer_comp_load_reg_t; @@ -208,6 +213,7 @@ typedef union { * timer unit load value */ uint32_t timer_unit_load: 1; + uint32_t reserved1: 31; }; uint32_t val; } systimer_unit_load_reg_t; @@ -230,6 +236,7 @@ typedef union { * interupt2 enable */ uint32_t target2_int_ena: 1; + uint32_t reserved3: 29; }; uint32_t val; } systimer_int_ena_reg_t; @@ -251,6 +258,7 @@ typedef union { * interupt2 raw */ uint32_t target2_int_raw: 1; + uint32_t reserved3: 29; }; uint32_t val; } systimer_int_raw_reg_t; @@ -272,6 +280,7 @@ typedef union { * interupt2 clear */ uint32_t target2_int_clr: 1; + uint32_t reserved3: 29; }; uint32_t val; } systimer_int_clr_reg_t; @@ -293,6 +302,7 @@ typedef union { * reg_target2_int_st */ uint32_t target2_int_st: 1; + uint32_t reserved3: 29; }; uint32_t val; } systimer_int_st_reg_t; diff --git a/components/soc/esp32c3/include/soc/timer_group_reg.h b/components/soc/esp32c3/include/soc/timer_group_reg.h index 05ae6fb42e..4d591035fc 100644 --- a/components/soc/esp32c3/include/soc/timer_group_reg.h +++ b/components/soc/esp32c3/include/soc/timer_group_reg.h @@ -1,24 +1,17 @@ -// 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. -#ifndef _SOC_TIMG_REG_H_ -#define _SOC_TIMG_REG_H_ - +/** + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once +#include +#include "soc/soc.h" #ifdef __cplusplus extern "C" { #endif -#include "soc.h" + +#define DR_REG_TIMG_BASE(i) REG_TIMG_BASE(i) /* The value that needs to be written to TIMG_WDT_WKEY to write-enable the wdt registers */ #define TIMG_WDT_WKEY_VALUE 0x50D83AA1 @@ -29,413 +22,559 @@ extern "C" { #define TIMG_WDT_STG_SEL_RESET_CPU 2 #define TIMG_WDT_STG_SEL_RESET_SYSTEM 3 -#define TIMG_WDT_RESET_LENGTH_100_NS 0 -#define TIMG_WDT_RESET_LENGTH_200_NS 1 -#define TIMG_WDT_RESET_LENGTH_300_NS 2 -#define TIMG_WDT_RESET_LENGTH_400_NS 3 -#define TIMG_WDT_RESET_LENGTH_500_NS 4 -#define TIMG_WDT_RESET_LENGTH_800_NS 5 -#define TIMG_WDT_RESET_LENGTH_1600_NS 6 -#define TIMG_WDT_RESET_LENGTH_3200_NS 7 +/* Possible values for TIMG_WDT_CPU_RESET_LENGTH and TIMG_WDT_SYS_RESET_LENGTH */ +#define TIMG_WDT_RESET_LENGTH_100_NS 0 +#define TIMG_WDT_RESET_LENGTH_200_NS 1 +#define TIMG_WDT_RESET_LENGTH_300_NS 2 +#define TIMG_WDT_RESET_LENGTH_400_NS 3 +#define TIMG_WDT_RESET_LENGTH_500_NS 4 +#define TIMG_WDT_RESET_LENGTH_800_NS 5 +#define TIMG_WDT_RESET_LENGTH_1600_NS 6 +#define TIMG_WDT_RESET_LENGTH_3200_NS 7 -#define TIMG_T0CONFIG_REG(i) (REG_TIMG_BASE(i) + 0x0000) -/* TIMG_T0_EN : R/W ;bitpos:[31] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T0_EN (BIT(31)) -#define TIMG_T0_EN_M (BIT(31)) -#define TIMG_T0_EN_V 0x1 -#define TIMG_T0_EN_S 31 -/* TIMG_T0_INCREASE : R/W ;bitpos:[30] ;default: 1'h1 ; */ -/*description: */ -#define TIMG_T0_INCREASE (BIT(30)) -#define TIMG_T0_INCREASE_M (BIT(30)) -#define TIMG_T0_INCREASE_V 0x1 -#define TIMG_T0_INCREASE_S 30 -/* TIMG_T0_AUTORELOAD : R/W ;bitpos:[29] ;default: 1'h1 ; */ -/*description: */ -#define TIMG_T0_AUTORELOAD (BIT(29)) -#define TIMG_T0_AUTORELOAD_M (BIT(29)) -#define TIMG_T0_AUTORELOAD_V 0x1 -#define TIMG_T0_AUTORELOAD_S 29 -/* TIMG_T0_DIVIDER : R/W ;bitpos:[28:13] ;default: 16'h1 ; */ -/*description: */ -#define TIMG_T0_DIVIDER 0x0000FFFF -#define TIMG_T0_DIVIDER_M ((TIMG_T0_DIVIDER_V)<<(TIMG_T0_DIVIDER_S)) -#define TIMG_T0_DIVIDER_V 0xFFFF -#define TIMG_T0_DIVIDER_S 13 -/* TIMG_T0_DIVCNT_RST : WT ;bitpos:[12] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T0_DIVCNT_RST (BIT(12)) -#define TIMG_T0_DIVCNT_RST_M (BIT(12)) -#define TIMG_T0_DIVCNT_RST_V 0x1 -#define TIMG_T0_DIVCNT_RST_S 12 -/* TIMG_T0_ALARM_EN : R/W/SC ;bitpos:[10] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T0_ALARM_EN (BIT(10)) -#define TIMG_T0_ALARM_EN_M (BIT(10)) -#define TIMG_T0_ALARM_EN_V 0x1 -#define TIMG_T0_ALARM_EN_S 10 -/* TIMG_T0_USE_XTAL : R/W ;bitpos:[9] ;default: 1'd0 ; */ -/*description: */ -#define TIMG_T0_USE_XTAL (BIT(9)) -#define TIMG_T0_USE_XTAL_M (BIT(9)) -#define TIMG_T0_USE_XTAL_V 0x1 +/** TIMG_T0CONFIG_REG register + * Timer 0 configuration register + */ +#define TIMG_T0CONFIG_REG(i) (DR_REG_TIMG_BASE(i) + 0x0) +/** TIMG_T0_USE_XTAL : R/W; bitpos: [9]; default: 0; + * 1: Use XTAL_CLK as the source clock of timer group. 0: Use APB_CLK as the source + * clock of timer group. + */ +#define TIMG_T0_USE_XTAL (BIT(9)) +#define TIMG_T0_USE_XTAL_M (TIMG_T0_USE_XTAL_V << TIMG_T0_USE_XTAL_S) +#define TIMG_T0_USE_XTAL_V 0x00000001U #define TIMG_T0_USE_XTAL_S 9 +/** TIMG_T0_ALARM_EN : R/W/SC; bitpos: [10]; default: 0; + * When set, the alarm is enabled. This bit is automatically cleared once an + * alarm occurs. + */ +#define TIMG_T0_ALARM_EN (BIT(10)) +#define TIMG_T0_ALARM_EN_M (TIMG_T0_ALARM_EN_V << TIMG_T0_ALARM_EN_S) +#define TIMG_T0_ALARM_EN_V 0x00000001U +#define TIMG_T0_ALARM_EN_S 10 +/** TIMG_T0_DIVCNT_RST : WT; bitpos: [12]; default: 0; + * When set, Timer 0 's clock divider counter will be reset. + */ +#define TIMG_T0_DIVCNT_RST (BIT(12)) +#define TIMG_T0_DIVCNT_RST_M (TIMG_T0_DIVCNT_RST_V << TIMG_T0_DIVCNT_RST_S) +#define TIMG_T0_DIVCNT_RST_V 0x00000001U +#define TIMG_T0_DIVCNT_RST_S 12 +/** TIMG_T0_DIVIDER : R/W; bitpos: [28:13]; default: 1; + * Timer 0 clock (T0_clk) prescaler value. + */ +#define TIMG_T0_DIVIDER 0x0000FFFFU +#define TIMG_T0_DIVIDER_M (TIMG_T0_DIVIDER_V << TIMG_T0_DIVIDER_S) +#define TIMG_T0_DIVIDER_V 0x0000FFFFU +#define TIMG_T0_DIVIDER_S 13 +/** TIMG_T0_AUTORELOAD : R/W; bitpos: [29]; default: 1; + * When set, timer 0 auto-reload at alarm is enabled. + */ +#define TIMG_T0_AUTORELOAD (BIT(29)) +#define TIMG_T0_AUTORELOAD_M (TIMG_T0_AUTORELOAD_V << TIMG_T0_AUTORELOAD_S) +#define TIMG_T0_AUTORELOAD_V 0x00000001U +#define TIMG_T0_AUTORELOAD_S 29 +/** TIMG_T0_INCREASE : R/W; bitpos: [30]; default: 1; + * When set, the timer 0 time-base counter will increment every clock tick. When + * cleared, the timer 0 time-base counter will decrement. + */ +#define TIMG_T0_INCREASE (BIT(30)) +#define TIMG_T0_INCREASE_M (TIMG_T0_INCREASE_V << TIMG_T0_INCREASE_S) +#define TIMG_T0_INCREASE_V 0x00000001U +#define TIMG_T0_INCREASE_S 30 +/** TIMG_T0_EN : R/W; bitpos: [31]; default: 0; + * When set, the timer 0 time-base counter is enabled. + */ +#define TIMG_T0_EN (BIT(31)) +#define TIMG_T0_EN_M (TIMG_T0_EN_V << TIMG_T0_EN_S) +#define TIMG_T0_EN_V 0x00000001U +#define TIMG_T0_EN_S 31 -#define TIMG_T0LO_REG(i) (REG_TIMG_BASE(i) + 0x0004) -/* TIMG_T0_LO : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define TIMG_T0_LO 0xFFFFFFFF -#define TIMG_T0_LO_M ((TIMG_T0_LO_V)<<(TIMG_T0_LO_S)) -#define TIMG_T0_LO_V 0xFFFFFFFF +/** TIMG_T0LO_REG register + * Timer 0 current value, low 32 bits + */ +#define TIMG_T0LO_REG(i) (DR_REG_TIMG_BASE(i) + 0x4) +/** TIMG_T0_LO : RO; bitpos: [31:0]; default: 0; + * After writing to TIMG_T0UPDATE_REG, the low 32 bits of the time-base counter + * of timer 0 can be read here. + */ +#define TIMG_T0_LO 0xFFFFFFFFU +#define TIMG_T0_LO_M (TIMG_T0_LO_V << TIMG_T0_LO_S) +#define TIMG_T0_LO_V 0xFFFFFFFFU #define TIMG_T0_LO_S 0 -#define TIMG_T0HI_REG(i) (REG_TIMG_BASE(i) + 0x0008) -/* TIMG_T0_HI : RO ;bitpos:[21:0] ;default: 22'h0 ; */ -/*description: */ -#define TIMG_T0_HI 0x003FFFFF -#define TIMG_T0_HI_M ((TIMG_T0_HI_V)<<(TIMG_T0_HI_S)) -#define TIMG_T0_HI_V 0x3FFFFF +/** TIMG_T0HI_REG register + * Timer $x current value, high 22 bits + */ +#define TIMG_T0HI_REG(i) (DR_REG_TIMG_BASE(i) + 0x8) +/** TIMG_T0_HI : RO; bitpos: [21:0]; default: 0; + * After writing to TIMG_T$xUPDATE_REG, the high 22 bits of the time-base counter + * of timer $x can be read here. + */ +#define TIMG_T0_HI 0x003FFFFFU +#define TIMG_T0_HI_M (TIMG_T0_HI_V << TIMG_T0_HI_S) +#define TIMG_T0_HI_V 0x003FFFFFU #define TIMG_T0_HI_S 0 -#define TIMG_T0UPDATE_REG(i) (REG_TIMG_BASE(i) + 0x000c) -/* TIMG_T0_UPDATE : R/W/SC ;bitpos:[31] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T0_UPDATE (BIT(31)) -#define TIMG_T0_UPDATE_M (BIT(31)) -#define TIMG_T0_UPDATE_V 0x1 +/** TIMG_T0UPDATE_REG register + * Write to copy current timer value to TIMGn_T$x_(LO/HI)_REG + */ +#define TIMG_T0UPDATE_REG(i) (DR_REG_TIMG_BASE(i) + 0xc) +/** TIMG_T0_UPDATE : R/W/SC; bitpos: [31]; default: 0; + * After writing 0 or 1 to TIMG_T$xUPDATE_REG, the counter value is latched. + */ +#define TIMG_T0_UPDATE (BIT(31)) +#define TIMG_T0_UPDATE_M (TIMG_T0_UPDATE_V << TIMG_T0_UPDATE_S) +#define TIMG_T0_UPDATE_V 0x00000001U #define TIMG_T0_UPDATE_S 31 -#define TIMG_T0ALARMLO_REG(i) (REG_TIMG_BASE(i) + 0x0010) -/* TIMG_T0_ALARM_LO : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define TIMG_T0_ALARM_LO 0xFFFFFFFF -#define TIMG_T0_ALARM_LO_M ((TIMG_T0_ALARM_LO_V)<<(TIMG_T0_ALARM_LO_S)) -#define TIMG_T0_ALARM_LO_V 0xFFFFFFFF +/** TIMG_T0ALARMLO_REG register + * Timer $x alarm value, low 32 bits + */ +#define TIMG_T0ALARMLO_REG(i) (DR_REG_TIMG_BASE(i) + 0x10) +/** TIMG_T0_ALARM_LO : R/W; bitpos: [31:0]; default: 0; + * Timer $x alarm trigger time-base counter value, low 32 bits. + */ +#define TIMG_T0_ALARM_LO 0xFFFFFFFFU +#define TIMG_T0_ALARM_LO_M (TIMG_T0_ALARM_LO_V << TIMG_T0_ALARM_LO_S) +#define TIMG_T0_ALARM_LO_V 0xFFFFFFFFU #define TIMG_T0_ALARM_LO_S 0 -#define TIMG_T0ALARMHI_REG(i) (REG_TIMG_BASE(i) + 0x0014) -/* TIMG_T0_ALARM_HI : R/W ;bitpos:[21:0] ;default: 22'h0 ; */ -/*description: */ -#define TIMG_T0_ALARM_HI 0x003FFFFF -#define TIMG_T0_ALARM_HI_M ((TIMG_T0_ALARM_HI_V)<<(TIMG_T0_ALARM_HI_S)) -#define TIMG_T0_ALARM_HI_V 0x3FFFFF +/** TIMG_T0ALARMHI_REG register + * Timer $x alarm value, high bits + */ +#define TIMG_T0ALARMHI_REG(i) (DR_REG_TIMG_BASE(i) + 0x14) +/** TIMG_T0_ALARM_HI : R/W; bitpos: [21:0]; default: 0; + * Timer $x alarm trigger time-base counter value, high 22 bits. + */ +#define TIMG_T0_ALARM_HI 0x003FFFFFU +#define TIMG_T0_ALARM_HI_M (TIMG_T0_ALARM_HI_V << TIMG_T0_ALARM_HI_S) +#define TIMG_T0_ALARM_HI_V 0x003FFFFFU #define TIMG_T0_ALARM_HI_S 0 -#define TIMG_T0LOADLO_REG(i) (REG_TIMG_BASE(i) + 0x0018) -/* TIMG_T0_LOAD_LO : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define TIMG_T0_LOAD_LO 0xFFFFFFFF -#define TIMG_T0_LOAD_LO_M ((TIMG_T0_LOAD_LO_V)<<(TIMG_T0_LOAD_LO_S)) -#define TIMG_T0_LOAD_LO_V 0xFFFFFFFF +/** TIMG_T0LOADLO_REG register + * Timer $x reload value, low 32 bits + */ +#define TIMG_T0LOADLO_REG(i) (DR_REG_TIMG_BASE(i) + 0x18) +/** TIMG_T0_LOAD_LO : R/W; bitpos: [31:0]; default: 0; + * Low 32 bits of the value that a reload will load onto timer $x time-base + * Counter. + */ +#define TIMG_T0_LOAD_LO 0xFFFFFFFFU +#define TIMG_T0_LOAD_LO_M (TIMG_T0_LOAD_LO_V << TIMG_T0_LOAD_LO_S) +#define TIMG_T0_LOAD_LO_V 0xFFFFFFFFU #define TIMG_T0_LOAD_LO_S 0 -#define TIMG_T0LOADHI_REG(i) (REG_TIMG_BASE(i) + 0x001c) -/* TIMG_T0_LOAD_HI : R/W ;bitpos:[21:0] ;default: 22'h0 ; */ -/*description: */ -#define TIMG_T0_LOAD_HI 0x003FFFFF -#define TIMG_T0_LOAD_HI_M ((TIMG_T0_LOAD_HI_V)<<(TIMG_T0_LOAD_HI_S)) -#define TIMG_T0_LOAD_HI_V 0x3FFFFF +/** TIMG_T0LOADHI_REG register + * Timer $x reload value, high 22 bits + */ +#define TIMG_T0LOADHI_REG(i) (DR_REG_TIMG_BASE(i) + 0x1c) +/** TIMG_T0_LOAD_HI : R/W; bitpos: [21:0]; default: 0; + * High 22 bits of the value that a reload will load onto timer $x time-base + * counter. + */ +#define TIMG_T0_LOAD_HI 0x003FFFFFU +#define TIMG_T0_LOAD_HI_M (TIMG_T0_LOAD_HI_V << TIMG_T0_LOAD_HI_S) +#define TIMG_T0_LOAD_HI_V 0x003FFFFFU #define TIMG_T0_LOAD_HI_S 0 -#define TIMG_T0LOAD_REG(i) (REG_TIMG_BASE(i) + 0x0020) -/* TIMG_T0_LOAD : WT ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define TIMG_T0_LOAD 0xFFFFFFFF -#define TIMG_T0_LOAD_M ((TIMG_T0_LOAD_V)<<(TIMG_T0_LOAD_S)) -#define TIMG_T0_LOAD_V 0xFFFFFFFF +/** TIMG_T0LOAD_REG register + * Write to reload timer from TIMG_T$x_(LOADLOLOADHI)_REG + */ +#define TIMG_T0LOAD_REG(i) (DR_REG_TIMG_BASE(i) + 0x20) +/** TIMG_T0_LOAD : WT; bitpos: [31:0]; default: 0; + * + * Write any value to trigger a timer $x time-base counter reload. + */ +#define TIMG_T0_LOAD 0xFFFFFFFFU +#define TIMG_T0_LOAD_M (TIMG_T0_LOAD_V << TIMG_T0_LOAD_S) +#define TIMG_T0_LOAD_V 0xFFFFFFFFU #define TIMG_T0_LOAD_S 0 -#define TIMG_WDTCONFIG0_REG(i) (REG_TIMG_BASE(i) + 0x0048) -/* TIMG_WDT_EN : R/W ;bitpos:[31] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_WDT_EN (BIT(31)) -#define TIMG_WDT_EN_M (BIT(31)) -#define TIMG_WDT_EN_V 0x1 -#define TIMG_WDT_EN_S 31 -/* TIMG_WDT_STG0 : R/W ;bitpos:[30:29] ;default: 2'd0 ; */ -/*description: */ -#define TIMG_WDT_STG0 0x00000003 -#define TIMG_WDT_STG0_M ((TIMG_WDT_STG0_V)<<(TIMG_WDT_STG0_S)) -#define TIMG_WDT_STG0_V 0x3 -#define TIMG_WDT_STG0_S 29 -/* TIMG_WDT_STG1 : R/W ;bitpos:[28:27] ;default: 2'd0 ; */ -/*description: */ -#define TIMG_WDT_STG1 0x00000003 -#define TIMG_WDT_STG1_M ((TIMG_WDT_STG1_V)<<(TIMG_WDT_STG1_S)) -#define TIMG_WDT_STG1_V 0x3 -#define TIMG_WDT_STG1_S 27 -/* TIMG_WDT_STG2 : R/W ;bitpos:[26:25] ;default: 2'd0 ; */ -/*description: */ -#define TIMG_WDT_STG2 0x00000003 -#define TIMG_WDT_STG2_M ((TIMG_WDT_STG2_V)<<(TIMG_WDT_STG2_S)) -#define TIMG_WDT_STG2_V 0x3 -#define TIMG_WDT_STG2_S 25 -/* TIMG_WDT_STG3 : R/W ;bitpos:[24:23] ;default: 2'd0 ; */ -/*description: */ -#define TIMG_WDT_STG3 0x00000003 -#define TIMG_WDT_STG3_M ((TIMG_WDT_STG3_V)<<(TIMG_WDT_STG3_S)) -#define TIMG_WDT_STG3_V 0x3 -#define TIMG_WDT_STG3_S 23 -/* TIMG_WDT_CONF_UPDATE_EN : WT ;bitpos:[22] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_WDT_CONF_UPDATE_EN (BIT(22)) -#define TIMG_WDT_CONF_UPDATE_EN_M (BIT(22)) -#define TIMG_WDT_CONF_UPDATE_EN_V 0x1 -#define TIMG_WDT_CONF_UPDATE_EN_S 22 -/* TIMG_WDT_USE_XTAL : R/W ;bitpos:[21] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_WDT_USE_XTAL (BIT(21)) -#define TIMG_WDT_USE_XTAL_M (BIT(21)) -#define TIMG_WDT_USE_XTAL_V 0x1 -#define TIMG_WDT_USE_XTAL_S 21 -/* TIMG_WDT_CPU_RESET_LENGTH : R/W ;bitpos:[20:18] ;default: 3'h1 ; */ -/*description: */ -#define TIMG_WDT_CPU_RESET_LENGTH 0x00000007 -#define TIMG_WDT_CPU_RESET_LENGTH_M ((TIMG_WDT_CPU_RESET_LENGTH_V)<<(TIMG_WDT_CPU_RESET_LENGTH_S)) -#define TIMG_WDT_CPU_RESET_LENGTH_V 0x7 -#define TIMG_WDT_CPU_RESET_LENGTH_S 18 -/* TIMG_WDT_SYS_RESET_LENGTH : R/W ;bitpos:[17:15] ;default: 3'h1 ; */ -/*description: */ -#define TIMG_WDT_SYS_RESET_LENGTH 0x00000007 -#define TIMG_WDT_SYS_RESET_LENGTH_M ((TIMG_WDT_SYS_RESET_LENGTH_V)<<(TIMG_WDT_SYS_RESET_LENGTH_S)) -#define TIMG_WDT_SYS_RESET_LENGTH_V 0x7 -#define TIMG_WDT_SYS_RESET_LENGTH_S 15 -/* TIMG_WDT_FLASHBOOT_MOD_EN : R/W ;bitpos:[14] ;default: 1'h1 ; */ -/*description: */ -#define TIMG_WDT_FLASHBOOT_MOD_EN (BIT(14)) -#define TIMG_WDT_FLASHBOOT_MOD_EN_M (BIT(14)) -#define TIMG_WDT_FLASHBOOT_MOD_EN_V 0x1 -#define TIMG_WDT_FLASHBOOT_MOD_EN_S 14 -/* TIMG_WDT_PROCPU_RESET_EN : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: */ -#define TIMG_WDT_PROCPU_RESET_EN (BIT(13)) -#define TIMG_WDT_PROCPU_RESET_EN_M (BIT(13)) -#define TIMG_WDT_PROCPU_RESET_EN_V 0x1 -#define TIMG_WDT_PROCPU_RESET_EN_S 13 -/* TIMG_WDT_APPCPU_RESET_EN : R/W ;bitpos:[12] ;default: 1'd0 ; */ -/*description: */ -#define TIMG_WDT_APPCPU_RESET_EN (BIT(12)) -#define TIMG_WDT_APPCPU_RESET_EN_M (BIT(12)) -#define TIMG_WDT_APPCPU_RESET_EN_V 0x1 +/** TIMG_WDTCONFIG0_REG register + * Watchdog timer configuration register + */ +#define TIMG_WDTCONFIG0_REG(i) (DR_REG_TIMG_BASE(i) + 0x48) +/** TIMG_WDT_APPCPU_RESET_EN : R/W; bitpos: [12]; default: 0; + * WDT reset CPU enable. + */ +#define TIMG_WDT_APPCPU_RESET_EN (BIT(12)) +#define TIMG_WDT_APPCPU_RESET_EN_M (TIMG_WDT_APPCPU_RESET_EN_V << TIMG_WDT_APPCPU_RESET_EN_S) +#define TIMG_WDT_APPCPU_RESET_EN_V 0x00000001U #define TIMG_WDT_APPCPU_RESET_EN_S 12 +/** TIMG_WDT_PROCPU_RESET_EN : R/W; bitpos: [13]; default: 0; + * WDT reset CPU enable. + */ +#define TIMG_WDT_PROCPU_RESET_EN (BIT(13)) +#define TIMG_WDT_PROCPU_RESET_EN_M (TIMG_WDT_PROCPU_RESET_EN_V << TIMG_WDT_PROCPU_RESET_EN_S) +#define TIMG_WDT_PROCPU_RESET_EN_V 0x00000001U +#define TIMG_WDT_PROCPU_RESET_EN_S 13 +/** TIMG_WDT_FLASHBOOT_MOD_EN : R/W; bitpos: [14]; default: 1; + * When set, Flash boot protection is enabled. + */ +#define TIMG_WDT_FLASHBOOT_MOD_EN (BIT(14)) +#define TIMG_WDT_FLASHBOOT_MOD_EN_M (TIMG_WDT_FLASHBOOT_MOD_EN_V << TIMG_WDT_FLASHBOOT_MOD_EN_S) +#define TIMG_WDT_FLASHBOOT_MOD_EN_V 0x00000001U +#define TIMG_WDT_FLASHBOOT_MOD_EN_S 14 +/** TIMG_WDT_SYS_RESET_LENGTH : R/W; bitpos: [17:15]; default: 1; + * System reset signal length selection. 0: 100 ns, 1: 200 ns, + * 2: 300 ns, 3: 400 ns, 4: 500 ns, 5: 800 ns, 6: 1.6 us, 7: 3.2 us. + */ +#define TIMG_WDT_SYS_RESET_LENGTH 0x00000007U +#define TIMG_WDT_SYS_RESET_LENGTH_M (TIMG_WDT_SYS_RESET_LENGTH_V << TIMG_WDT_SYS_RESET_LENGTH_S) +#define TIMG_WDT_SYS_RESET_LENGTH_V 0x00000007U +#define TIMG_WDT_SYS_RESET_LENGTH_S 15 +/** TIMG_WDT_CPU_RESET_LENGTH : R/W; bitpos: [20:18]; default: 1; + * CPU reset signal length selection. 0: 100 ns, 1: 200 ns, + * 2: 300 ns, 3: 400 ns, 4: 500 ns, 5: 800 ns, 6: 1.6 us, 7: 3.2 us. + */ +#define TIMG_WDT_CPU_RESET_LENGTH 0x00000007U +#define TIMG_WDT_CPU_RESET_LENGTH_M (TIMG_WDT_CPU_RESET_LENGTH_V << TIMG_WDT_CPU_RESET_LENGTH_S) +#define TIMG_WDT_CPU_RESET_LENGTH_V 0x00000007U +#define TIMG_WDT_CPU_RESET_LENGTH_S 18 +/** TIMG_WDT_USE_XTAL : R/W; bitpos: [21]; default: 0; + * choose WDT clock:0-apb_clk; 1-xtal_clk. + */ +#define TIMG_WDT_USE_XTAL (BIT(21)) +#define TIMG_WDT_USE_XTAL_M (TIMG_WDT_USE_XTAL_V << TIMG_WDT_USE_XTAL_S) +#define TIMG_WDT_USE_XTAL_V 0x00000001U +#define TIMG_WDT_USE_XTAL_S 21 +/** TIMG_WDT_CONF_UPDATE_EN : WT; bitpos: [22]; default: 0; + * update the WDT configuration registers + */ +#define TIMG_WDT_CONF_UPDATE_EN (BIT(22)) +#define TIMG_WDT_CONF_UPDATE_EN_M (TIMG_WDT_CONF_UPDATE_EN_V << TIMG_WDT_CONF_UPDATE_EN_S) +#define TIMG_WDT_CONF_UPDATE_EN_V 0x00000001U +#define TIMG_WDT_CONF_UPDATE_EN_S 22 +/** TIMG_WDT_STG3 : R/W; bitpos: [24:23]; default: 0; + * Stage 3 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system. + */ +#define TIMG_WDT_STG3 0x00000003U +#define TIMG_WDT_STG3_M (TIMG_WDT_STG3_V << TIMG_WDT_STG3_S) +#define TIMG_WDT_STG3_V 0x00000003U +#define TIMG_WDT_STG3_S 23 +/** TIMG_WDT_STG2 : R/W; bitpos: [26:25]; default: 0; + * Stage 2 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system. + */ +#define TIMG_WDT_STG2 0x00000003U +#define TIMG_WDT_STG2_M (TIMG_WDT_STG2_V << TIMG_WDT_STG2_S) +#define TIMG_WDT_STG2_V 0x00000003U +#define TIMG_WDT_STG2_S 25 +/** TIMG_WDT_STG1 : R/W; bitpos: [28:27]; default: 0; + * Stage 1 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system. + */ +#define TIMG_WDT_STG1 0x00000003U +#define TIMG_WDT_STG1_M (TIMG_WDT_STG1_V << TIMG_WDT_STG1_S) +#define TIMG_WDT_STG1_V 0x00000003U +#define TIMG_WDT_STG1_S 27 +/** TIMG_WDT_STG0 : R/W; bitpos: [30:29]; default: 0; + * Stage 0 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system. + */ +#define TIMG_WDT_STG0 0x00000003U +#define TIMG_WDT_STG0_M (TIMG_WDT_STG0_V << TIMG_WDT_STG0_S) +#define TIMG_WDT_STG0_V 0x00000003U +#define TIMG_WDT_STG0_S 29 +/** TIMG_WDT_EN : R/W; bitpos: [31]; default: 0; + * When set, MWDT is enabled. + */ +#define TIMG_WDT_EN (BIT(31)) +#define TIMG_WDT_EN_M (TIMG_WDT_EN_V << TIMG_WDT_EN_S) +#define TIMG_WDT_EN_V 0x00000001U +#define TIMG_WDT_EN_S 31 -#define TIMG_WDTCONFIG1_REG(i) (REG_TIMG_BASE(i) + 0x004c) -/* TIMG_WDT_CLK_PRESCALE : R/W ;bitpos:[31:16] ;default: 16'h1 ; */ -/*description: */ -#define TIMG_WDT_CLK_PRESCALE 0x0000FFFF -#define TIMG_WDT_CLK_PRESCALE_M ((TIMG_WDT_CLK_PRESCALE_V)<<(TIMG_WDT_CLK_PRESCALE_S)) -#define TIMG_WDT_CLK_PRESCALE_V 0xFFFF -#define TIMG_WDT_CLK_PRESCALE_S 16 -/* TIMG_WDT_DIVCNT_RST : WT ;bitpos:[0] ;default: 1'b0 ; */ -/*description: */ -#define TIMG_WDT_DIVCNT_RST (BIT(0)) -#define TIMG_WDT_DIVCNT_RST_M (BIT(0)) -#define TIMG_WDT_DIVCNT_RST_V 0x1 +/** TIMG_WDTCONFIG1_REG register + * Watchdog timer prescaler register + */ +#define TIMG_WDTCONFIG1_REG(i) (DR_REG_TIMG_BASE(i) + 0x4c) +/** TIMG_WDT_DIVCNT_RST : WT; bitpos: [0]; default: 0; + * When set, WDT 's clock divider counter will be reset. + */ +#define TIMG_WDT_DIVCNT_RST (BIT(0)) +#define TIMG_WDT_DIVCNT_RST_M (TIMG_WDT_DIVCNT_RST_V << TIMG_WDT_DIVCNT_RST_S) +#define TIMG_WDT_DIVCNT_RST_V 0x00000001U #define TIMG_WDT_DIVCNT_RST_S 0 +/** TIMG_WDT_CLK_PRESCALE : R/W; bitpos: [31:16]; default: 1; + * MWDT clock prescaler value. MWDT clock period = 12.5 ns * + * TIMG_WDT_CLK_PRESCALE. + */ +#define TIMG_WDT_CLK_PRESCALE 0x0000FFFFU +#define TIMG_WDT_CLK_PRESCALE_M (TIMG_WDT_CLK_PRESCALE_V << TIMG_WDT_CLK_PRESCALE_S) +#define TIMG_WDT_CLK_PRESCALE_V 0x0000FFFFU +#define TIMG_WDT_CLK_PRESCALE_S 16 -#define TIMG_WDTCONFIG2_REG(i) (REG_TIMG_BASE(i) + 0x0050) -/* TIMG_WDT_STG0_HOLD : R/W ;bitpos:[31:0] ;default: 32'd26000000 ; */ -/*description: */ -#define TIMG_WDT_STG0_HOLD 0xFFFFFFFF -#define TIMG_WDT_STG0_HOLD_M ((TIMG_WDT_STG0_HOLD_V)<<(TIMG_WDT_STG0_HOLD_S)) -#define TIMG_WDT_STG0_HOLD_V 0xFFFFFFFF +/** TIMG_WDTCONFIG2_REG register + * Watchdog timer stage 0 timeout value + */ +#define TIMG_WDTCONFIG2_REG(i) (DR_REG_TIMG_BASE(i) + 0x50) +/** TIMG_WDT_STG0_HOLD : R/W; bitpos: [31:0]; default: 26000000; + * Stage 0 timeout value, in MWDT clock cycles. + */ +#define TIMG_WDT_STG0_HOLD 0xFFFFFFFFU +#define TIMG_WDT_STG0_HOLD_M (TIMG_WDT_STG0_HOLD_V << TIMG_WDT_STG0_HOLD_S) +#define TIMG_WDT_STG0_HOLD_V 0xFFFFFFFFU #define TIMG_WDT_STG0_HOLD_S 0 -#define TIMG_WDTCONFIG3_REG(i) (REG_TIMG_BASE(i) + 0x0054) -/* TIMG_WDT_STG1_HOLD : R/W ;bitpos:[31:0] ;default: 32'h7ffffff ; */ -/*description: */ -#define TIMG_WDT_STG1_HOLD 0xFFFFFFFF -#define TIMG_WDT_STG1_HOLD_M ((TIMG_WDT_STG1_HOLD_V)<<(TIMG_WDT_STG1_HOLD_S)) -#define TIMG_WDT_STG1_HOLD_V 0xFFFFFFFF +/** TIMG_WDTCONFIG3_REG register + * Watchdog timer stage 1 timeout value + */ +#define TIMG_WDTCONFIG3_REG(i) (DR_REG_TIMG_BASE(i) + 0x54) +/** TIMG_WDT_STG1_HOLD : R/W; bitpos: [31:0]; default: 134217727; + * Stage 1 timeout value, in MWDT clock cycles. + */ +#define TIMG_WDT_STG1_HOLD 0xFFFFFFFFU +#define TIMG_WDT_STG1_HOLD_M (TIMG_WDT_STG1_HOLD_V << TIMG_WDT_STG1_HOLD_S) +#define TIMG_WDT_STG1_HOLD_V 0xFFFFFFFFU #define TIMG_WDT_STG1_HOLD_S 0 -#define TIMG_WDTCONFIG4_REG(i) (REG_TIMG_BASE(i) + 0x0058) -/* TIMG_WDT_STG2_HOLD : R/W ;bitpos:[31:0] ;default: 32'hfffff ; */ -/*description: */ -#define TIMG_WDT_STG2_HOLD 0xFFFFFFFF -#define TIMG_WDT_STG2_HOLD_M ((TIMG_WDT_STG2_HOLD_V)<<(TIMG_WDT_STG2_HOLD_S)) -#define TIMG_WDT_STG2_HOLD_V 0xFFFFFFFF +/** TIMG_WDTCONFIG4_REG register + * Watchdog timer stage 2 timeout value + */ +#define TIMG_WDTCONFIG4_REG(i) (DR_REG_TIMG_BASE(i) + 0x58) +/** TIMG_WDT_STG2_HOLD : R/W; bitpos: [31:0]; default: 1048575; + * Stage 2 timeout value, in MWDT clock cycles. + */ +#define TIMG_WDT_STG2_HOLD 0xFFFFFFFFU +#define TIMG_WDT_STG2_HOLD_M (TIMG_WDT_STG2_HOLD_V << TIMG_WDT_STG2_HOLD_S) +#define TIMG_WDT_STG2_HOLD_V 0xFFFFFFFFU #define TIMG_WDT_STG2_HOLD_S 0 -#define TIMG_WDTCONFIG5_REG(i) (REG_TIMG_BASE(i) + 0x005c) -/* TIMG_WDT_STG3_HOLD : R/W ;bitpos:[31:0] ;default: 32'hfffff ; */ -/*description: */ -#define TIMG_WDT_STG3_HOLD 0xFFFFFFFF -#define TIMG_WDT_STG3_HOLD_M ((TIMG_WDT_STG3_HOLD_V)<<(TIMG_WDT_STG3_HOLD_S)) -#define TIMG_WDT_STG3_HOLD_V 0xFFFFFFFF +/** TIMG_WDTCONFIG5_REG register + * Watchdog timer stage 3 timeout value + */ +#define TIMG_WDTCONFIG5_REG(i) (DR_REG_TIMG_BASE(i) + 0x5c) +/** TIMG_WDT_STG3_HOLD : R/W; bitpos: [31:0]; default: 1048575; + * Stage 3 timeout value, in MWDT clock cycles. + */ +#define TIMG_WDT_STG3_HOLD 0xFFFFFFFFU +#define TIMG_WDT_STG3_HOLD_M (TIMG_WDT_STG3_HOLD_V << TIMG_WDT_STG3_HOLD_S) +#define TIMG_WDT_STG3_HOLD_V 0xFFFFFFFFU #define TIMG_WDT_STG3_HOLD_S 0 -#define TIMG_WDTFEED_REG(i) (REG_TIMG_BASE(i) + 0x0060) -/* TIMG_WDT_FEED : WT ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define TIMG_WDT_FEED 0xFFFFFFFF -#define TIMG_WDT_FEED_M ((TIMG_WDT_FEED_V)<<(TIMG_WDT_FEED_S)) -#define TIMG_WDT_FEED_V 0xFFFFFFFF +/** TIMG_WDTFEED_REG register + * Write to feed the watchdog timer + */ +#define TIMG_WDTFEED_REG(i) (DR_REG_TIMG_BASE(i) + 0x60) +/** TIMG_WDT_FEED : WT; bitpos: [31:0]; default: 0; + * Write any value to feed the MWDT. (WO) + */ +#define TIMG_WDT_FEED 0xFFFFFFFFU +#define TIMG_WDT_FEED_M (TIMG_WDT_FEED_V << TIMG_WDT_FEED_S) +#define TIMG_WDT_FEED_V 0xFFFFFFFFU #define TIMG_WDT_FEED_S 0 -#define TIMG_WDTWPROTECT_REG(i) (REG_TIMG_BASE(i) + 0x0064) -/* TIMG_WDT_WKEY : R/W ;bitpos:[31:0] ;default: 32'h50d83aa1 ; */ -/*description: */ -#define TIMG_WDT_WKEY 0xFFFFFFFF -#define TIMG_WDT_WKEY_M ((TIMG_WDT_WKEY_V)<<(TIMG_WDT_WKEY_S)) -#define TIMG_WDT_WKEY_V 0xFFFFFFFF +/** TIMG_WDTWPROTECT_REG register + * Watchdog write protect register + */ +#define TIMG_WDTWPROTECT_REG(i) (DR_REG_TIMG_BASE(i) + 0x64) +/** TIMG_WDT_WKEY : R/W; bitpos: [31:0]; default: 1356348065; + * If the register contains a different value than its reset value, write + * protection is enabled. + */ +#define TIMG_WDT_WKEY 0xFFFFFFFFU +#define TIMG_WDT_WKEY_M (TIMG_WDT_WKEY_V << TIMG_WDT_WKEY_S) +#define TIMG_WDT_WKEY_V 0xFFFFFFFFU #define TIMG_WDT_WKEY_S 0 -#define TIMG_RTCCALICFG_REG(i) (REG_TIMG_BASE(i) + 0x0068) -/* TIMG_RTC_CALI_START : R/W ;bitpos:[31] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_RTC_CALI_START (BIT(31)) -#define TIMG_RTC_CALI_START_M (BIT(31)) -#define TIMG_RTC_CALI_START_V 0x1 -#define TIMG_RTC_CALI_START_S 31 -/* TIMG_RTC_CALI_MAX : R/W ;bitpos:[30:16] ;default: 15'h1 ; */ -/*description: */ -#define TIMG_RTC_CALI_MAX 0x00007FFF -#define TIMG_RTC_CALI_MAX_M ((TIMG_RTC_CALI_MAX_V)<<(TIMG_RTC_CALI_MAX_S)) -#define TIMG_RTC_CALI_MAX_V 0x7FFF -#define TIMG_RTC_CALI_MAX_S 16 -/* TIMG_RTC_CALI_RDY : RO ;bitpos:[15] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_RTC_CALI_RDY (BIT(15)) -#define TIMG_RTC_CALI_RDY_M (BIT(15)) -#define TIMG_RTC_CALI_RDY_V 0x1 -#define TIMG_RTC_CALI_RDY_S 15 -/* TIMG_RTC_CALI_CLK_SEL : R/W ;bitpos:[14:13] ;default: 2'h1 ; */ -/*description: */ -#define TIMG_RTC_CALI_CLK_SEL 0x00000003 -#define TIMG_RTC_CALI_CLK_SEL_M ((TIMG_RTC_CALI_CLK_SEL_V)<<(TIMG_RTC_CALI_CLK_SEL_S)) -#define TIMG_RTC_CALI_CLK_SEL_V 0x3 -#define TIMG_RTC_CALI_CLK_SEL_S 13 -/* TIMG_RTC_CALI_START_CYCLING : R/W ;bitpos:[12] ;default: 1'd1 ; */ -/*description: */ -#define TIMG_RTC_CALI_START_CYCLING (BIT(12)) -#define TIMG_RTC_CALI_START_CYCLING_M (BIT(12)) -#define TIMG_RTC_CALI_START_CYCLING_V 0x1 +/** TIMG_RTCCALICFG_REG register + * RTC calibration configure register + */ +#define TIMG_RTCCALICFG_REG(i) (DR_REG_TIMG_BASE(i) + 0x68) +/** TIMG_RTC_CALI_START_CYCLING : R/W; bitpos: [12]; default: 1; + * Reserved + */ +#define TIMG_RTC_CALI_START_CYCLING (BIT(12)) +#define TIMG_RTC_CALI_START_CYCLING_M (TIMG_RTC_CALI_START_CYCLING_V << TIMG_RTC_CALI_START_CYCLING_S) +#define TIMG_RTC_CALI_START_CYCLING_V 0x00000001U #define TIMG_RTC_CALI_START_CYCLING_S 12 +/** TIMG_RTC_CALI_CLK_SEL : R/W; bitpos: [14:13]; default: 1; + * 0:rtc slow clock. 1:clk_8m, 2:xtal_32k. + */ +#define TIMG_RTC_CALI_CLK_SEL 0x00000003U +#define TIMG_RTC_CALI_CLK_SEL_M (TIMG_RTC_CALI_CLK_SEL_V << TIMG_RTC_CALI_CLK_SEL_S) +#define TIMG_RTC_CALI_CLK_SEL_V 0x00000003U +#define TIMG_RTC_CALI_CLK_SEL_S 13 +/** TIMG_RTC_CALI_RDY : RO; bitpos: [15]; default: 0; + * Reserved + */ +#define TIMG_RTC_CALI_RDY (BIT(15)) +#define TIMG_RTC_CALI_RDY_M (TIMG_RTC_CALI_RDY_V << TIMG_RTC_CALI_RDY_S) +#define TIMG_RTC_CALI_RDY_V 0x00000001U +#define TIMG_RTC_CALI_RDY_S 15 +/** TIMG_RTC_CALI_MAX : R/W; bitpos: [30:16]; default: 1; + * Reserved + */ +#define TIMG_RTC_CALI_MAX 0x00007FFFU +#define TIMG_RTC_CALI_MAX_M (TIMG_RTC_CALI_MAX_V << TIMG_RTC_CALI_MAX_S) +#define TIMG_RTC_CALI_MAX_V 0x00007FFFU +#define TIMG_RTC_CALI_MAX_S 16 +/** TIMG_RTC_CALI_START : R/W; bitpos: [31]; default: 0; + * Reserved + */ +#define TIMG_RTC_CALI_START (BIT(31)) +#define TIMG_RTC_CALI_START_M (TIMG_RTC_CALI_START_V << TIMG_RTC_CALI_START_S) +#define TIMG_RTC_CALI_START_V 0x00000001U +#define TIMG_RTC_CALI_START_S 31 -#define TIMG_RTCCALICFG1_REG(i) (REG_TIMG_BASE(i) + 0x006c) -/* TIMG_RTC_CALI_VALUE : RO ;bitpos:[31:7] ;default: 25'h0 ; */ -/*description: */ -#define TIMG_RTC_CALI_VALUE 0x01FFFFFF -#define TIMG_RTC_CALI_VALUE_M ((TIMG_RTC_CALI_VALUE_V)<<(TIMG_RTC_CALI_VALUE_S)) -#define TIMG_RTC_CALI_VALUE_V 0x1FFFFFF -#define TIMG_RTC_CALI_VALUE_S 7 -/* TIMG_RTC_CALI_CYCLING_DATA_VLD : RO ;bitpos:[0] ;default: 1'b0 ; */ -/*description: */ -#define TIMG_RTC_CALI_CYCLING_DATA_VLD (BIT(0)) -#define TIMG_RTC_CALI_CYCLING_DATA_VLD_M (BIT(0)) -#define TIMG_RTC_CALI_CYCLING_DATA_VLD_V 0x1 +/** TIMG_RTCCALICFG1_REG register + * RTC calibration configure1 register + */ +#define TIMG_RTCCALICFG1_REG(i) (DR_REG_TIMG_BASE(i) + 0x6c) +/** TIMG_RTC_CALI_CYCLING_DATA_VLD : RO; bitpos: [0]; default: 0; + * Reserved + */ +#define TIMG_RTC_CALI_CYCLING_DATA_VLD (BIT(0)) +#define TIMG_RTC_CALI_CYCLING_DATA_VLD_M (TIMG_RTC_CALI_CYCLING_DATA_VLD_V << TIMG_RTC_CALI_CYCLING_DATA_VLD_S) +#define TIMG_RTC_CALI_CYCLING_DATA_VLD_V 0x00000001U #define TIMG_RTC_CALI_CYCLING_DATA_VLD_S 0 +/** TIMG_RTC_CALI_VALUE : RO; bitpos: [31:7]; default: 0; + * Reserved + */ +#define TIMG_RTC_CALI_VALUE 0x01FFFFFFU +#define TIMG_RTC_CALI_VALUE_M (TIMG_RTC_CALI_VALUE_V << TIMG_RTC_CALI_VALUE_S) +#define TIMG_RTC_CALI_VALUE_V 0x01FFFFFFU +#define TIMG_RTC_CALI_VALUE_S 7 -#define TIMG_INT_ENA_TIMERS_REG(i) (REG_TIMG_BASE(i) + 0x0070) -/* TIMG_WDT_INT_ENA : R/W ;bitpos:[1] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_WDT_INT_ENA (BIT(1)) -#define TIMG_WDT_INT_ENA_M (BIT(1)) -#define TIMG_WDT_INT_ENA_V 0x1 -#define TIMG_WDT_INT_ENA_S 1 -/* TIMG_T0_INT_ENA : R/W ;bitpos:[0] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T0_INT_ENA (BIT(0)) -#define TIMG_T0_INT_ENA_M (BIT(0)) -#define TIMG_T0_INT_ENA_V 0x1 +/** TIMG_INT_ENA_TIMERS_REG register + * Interrupt enable bits + */ +#define TIMG_INT_ENA_TIMERS_REG(i) (DR_REG_TIMG_BASE(i) + 0x70) +/** TIMG_T0_INT_ENA : R/W; bitpos: [0]; default: 0; + * The interrupt enable bit for the TIMG_T$x_INT interrupt. + */ +#define TIMG_T0_INT_ENA (BIT(0)) +#define TIMG_T0_INT_ENA_M (TIMG_T0_INT_ENA_V << TIMG_T0_INT_ENA_S) +#define TIMG_T0_INT_ENA_V 0x00000001U #define TIMG_T0_INT_ENA_S 0 +/** TIMG_WDT_INT_ENA : R/W; bitpos: [1]; default: 0; + * The interrupt enable bit for the TIMG_WDT_INT interrupt. + */ +#define TIMG_WDT_INT_ENA (BIT(1)) +#define TIMG_WDT_INT_ENA_M (TIMG_WDT_INT_ENA_V << TIMG_WDT_INT_ENA_S) +#define TIMG_WDT_INT_ENA_V 0x00000001U +#define TIMG_WDT_INT_ENA_S 1 -#define TIMG_INT_RAW_TIMERS_REG(i) (REG_TIMG_BASE(i) + 0x0074) -/* TIMG_WDT_INT_RAW : R/SS/WTC ;bitpos:[1] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_WDT_INT_RAW (BIT(1)) -#define TIMG_WDT_INT_RAW_M (BIT(1)) -#define TIMG_WDT_INT_RAW_V 0x1 -#define TIMG_WDT_INT_RAW_S 1 -/* TIMG_T0_INT_RAW : R/SS/WTC ;bitpos:[0] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T0_INT_RAW (BIT(0)) -#define TIMG_T0_INT_RAW_M (BIT(0)) -#define TIMG_T0_INT_RAW_V 0x1 +/** TIMG_INT_RAW_TIMERS_REG register + * Raw interrupt status + */ +#define TIMG_INT_RAW_TIMERS_REG(i) (DR_REG_TIMG_BASE(i) + 0x74) +/** TIMG_T0_INT_RAW : R/SS/WTC; bitpos: [0]; default: 0; + * The raw interrupt status bit for the TIMG_T$x_INT interrupt. + */ +#define TIMG_T0_INT_RAW (BIT(0)) +#define TIMG_T0_INT_RAW_M (TIMG_T0_INT_RAW_V << TIMG_T0_INT_RAW_S) +#define TIMG_T0_INT_RAW_V 0x00000001U #define TIMG_T0_INT_RAW_S 0 +/** TIMG_WDT_INT_RAW : R/SS/WTC; bitpos: [1]; default: 0; + * The raw interrupt status bit for the TIMG_WDT_INT interrupt. + */ +#define TIMG_WDT_INT_RAW (BIT(1)) +#define TIMG_WDT_INT_RAW_M (TIMG_WDT_INT_RAW_V << TIMG_WDT_INT_RAW_S) +#define TIMG_WDT_INT_RAW_V 0x00000001U +#define TIMG_WDT_INT_RAW_S 1 -#define TIMG_INT_ST_TIMERS_REG(i) (REG_TIMG_BASE(i) + 0x0078) -/* TIMG_WDT_INT_ST : RO ;bitpos:[1] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_WDT_INT_ST (BIT(1)) -#define TIMG_WDT_INT_ST_M (BIT(1)) -#define TIMG_WDT_INT_ST_V 0x1 -#define TIMG_WDT_INT_ST_S 1 -/* TIMG_T0_INT_ST : RO ;bitpos:[0] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T0_INT_ST (BIT(0)) -#define TIMG_T0_INT_ST_M (BIT(0)) -#define TIMG_T0_INT_ST_V 0x1 +/** TIMG_INT_ST_TIMERS_REG register + * Masked interrupt status + */ +#define TIMG_INT_ST_TIMERS_REG(i) (DR_REG_TIMG_BASE(i) + 0x78) +/** TIMG_T0_INT_ST : RO; bitpos: [0]; default: 0; + * The masked interrupt status bit for the TIMG_T$x_INT interrupt. + */ +#define TIMG_T0_INT_ST (BIT(0)) +#define TIMG_T0_INT_ST_M (TIMG_T0_INT_ST_V << TIMG_T0_INT_ST_S) +#define TIMG_T0_INT_ST_V 0x00000001U #define TIMG_T0_INT_ST_S 0 +/** TIMG_WDT_INT_ST : RO; bitpos: [1]; default: 0; + * The masked interrupt status bit for the TIMG_WDT_INT interrupt. + */ +#define TIMG_WDT_INT_ST (BIT(1)) +#define TIMG_WDT_INT_ST_M (TIMG_WDT_INT_ST_V << TIMG_WDT_INT_ST_S) +#define TIMG_WDT_INT_ST_V 0x00000001U +#define TIMG_WDT_INT_ST_S 1 -#define TIMG_INT_CLR_TIMERS_REG(i) (REG_TIMG_BASE(i) + 0x007c) -/* TIMG_WDT_INT_CLR : WT ;bitpos:[1] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_WDT_INT_CLR (BIT(1)) -#define TIMG_WDT_INT_CLR_M (BIT(1)) -#define TIMG_WDT_INT_CLR_V 0x1 -#define TIMG_WDT_INT_CLR_S 1 -/* TIMG_T0_INT_CLR : WT ;bitpos:[0] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T0_INT_CLR (BIT(0)) -#define TIMG_T0_INT_CLR_M (BIT(0)) -#define TIMG_T0_INT_CLR_V 0x1 +/** TIMG_INT_CLR_TIMERS_REG register + * Interrupt clear bits + */ +#define TIMG_INT_CLR_TIMERS_REG(i) (DR_REG_TIMG_BASE(i) + 0x7c) +/** TIMG_T0_INT_CLR : WT; bitpos: [0]; default: 0; + * Set this bit to clear the TIMG_T$x_INT interrupt. + */ +#define TIMG_T0_INT_CLR (BIT(0)) +#define TIMG_T0_INT_CLR_M (TIMG_T0_INT_CLR_V << TIMG_T0_INT_CLR_S) +#define TIMG_T0_INT_CLR_V 0x00000001U #define TIMG_T0_INT_CLR_S 0 +/** TIMG_WDT_INT_CLR : WT; bitpos: [1]; default: 0; + * Set this bit to clear the TIMG_WDT_INT interrupt. + */ +#define TIMG_WDT_INT_CLR (BIT(1)) +#define TIMG_WDT_INT_CLR_M (TIMG_WDT_INT_CLR_V << TIMG_WDT_INT_CLR_S) +#define TIMG_WDT_INT_CLR_V 0x00000001U +#define TIMG_WDT_INT_CLR_S 1 -#define TIMG_RTCCALICFG2_REG(i) (REG_TIMG_BASE(i) + 0x0080) -/* TIMG_RTC_CALI_TIMEOUT_THRES : R/W ;bitpos:[31:7] ;default: 25'h1ffffff ; */ -/*description: timeout if cali value counts over threshold*/ -#define TIMG_RTC_CALI_TIMEOUT_THRES 0x01FFFFFF -#define TIMG_RTC_CALI_TIMEOUT_THRES_M ((TIMG_RTC_CALI_TIMEOUT_THRES_V)<<(TIMG_RTC_CALI_TIMEOUT_THRES_S)) -#define TIMG_RTC_CALI_TIMEOUT_THRES_V 0x1FFFFFF -#define TIMG_RTC_CALI_TIMEOUT_THRES_S 7 -/* TIMG_RTC_CALI_TIMEOUT_RST_CNT : R/W ;bitpos:[6:3] ;default: 4'd3 ; */ -/*description: Cycles that release calibration timeout reset*/ -#define TIMG_RTC_CALI_TIMEOUT_RST_CNT 0x0000000F -#define TIMG_RTC_CALI_TIMEOUT_RST_CNT_M ((TIMG_RTC_CALI_TIMEOUT_RST_CNT_V)<<(TIMG_RTC_CALI_TIMEOUT_RST_CNT_S)) -#define TIMG_RTC_CALI_TIMEOUT_RST_CNT_V 0xF -#define TIMG_RTC_CALI_TIMEOUT_RST_CNT_S 3 -/* TIMG_RTC_CALI_TIMEOUT : RO ;bitpos:[0] ;default: 1'h0 ; */ -/*description: timeout indicator*/ -#define TIMG_RTC_CALI_TIMEOUT (BIT(0)) -#define TIMG_RTC_CALI_TIMEOUT_M (BIT(0)) -#define TIMG_RTC_CALI_TIMEOUT_V 0x1 +/** TIMG_RTCCALICFG2_REG register + * Timer group calibration register + */ +#define TIMG_RTCCALICFG2_REG(i) (DR_REG_TIMG_BASE(i) + 0x80) +/** TIMG_RTC_CALI_TIMEOUT : RO; bitpos: [0]; default: 0; + * RTC calibration timeout indicator + */ +#define TIMG_RTC_CALI_TIMEOUT (BIT(0)) +#define TIMG_RTC_CALI_TIMEOUT_M (TIMG_RTC_CALI_TIMEOUT_V << TIMG_RTC_CALI_TIMEOUT_S) +#define TIMG_RTC_CALI_TIMEOUT_V 0x00000001U #define TIMG_RTC_CALI_TIMEOUT_S 0 +/** TIMG_RTC_CALI_TIMEOUT_RST_CNT : R/W; bitpos: [6:3]; default: 3; + * Cycles that release calibration timeout reset + */ +#define TIMG_RTC_CALI_TIMEOUT_RST_CNT 0x0000000FU +#define TIMG_RTC_CALI_TIMEOUT_RST_CNT_M (TIMG_RTC_CALI_TIMEOUT_RST_CNT_V << TIMG_RTC_CALI_TIMEOUT_RST_CNT_S) +#define TIMG_RTC_CALI_TIMEOUT_RST_CNT_V 0x0000000FU +#define TIMG_RTC_CALI_TIMEOUT_RST_CNT_S 3 +/** TIMG_RTC_CALI_TIMEOUT_THRES : R/W; bitpos: [31:7]; default: 33554431; + * Threshold value for the RTC calibration timer. If the calibration timer's value + * exceeds this threshold, a timeout is triggered. + */ +#define TIMG_RTC_CALI_TIMEOUT_THRES 0x01FFFFFFU +#define TIMG_RTC_CALI_TIMEOUT_THRES_M (TIMG_RTC_CALI_TIMEOUT_THRES_V << TIMG_RTC_CALI_TIMEOUT_THRES_S) +#define TIMG_RTC_CALI_TIMEOUT_THRES_V 0x01FFFFFFU +#define TIMG_RTC_CALI_TIMEOUT_THRES_S 7 -#define TIMG_NTIMERS_DATE_REG(i) (REG_TIMG_BASE(i) + 0x00f8) -/* TIMG_NTIMERS_DATE : R/W ;bitpos:[27:0] ;default: 28'h2006191 ; */ -/*description: */ -#define TIMG_NTIMERS_DATE 0x0FFFFFFF -#define TIMG_NTIMERS_DATE_M ((TIMG_NTIMERS_DATE_V)<<(TIMG_NTIMERS_DATE_S)) -#define TIMG_NTIMERS_DATE_V 0xFFFFFFF -#define TIMG_NTIMERS_DATE_S 0 +/** TIMG_NTIMERS_DATE_REG register + * Timer version control register + */ +#define TIMG_NTIMERS_DATE_REG(i) (DR_REG_TIMG_BASE(i) + 0xf8) +/** TIMG_NTIMGS_DATE : R/W; bitpos: [27:0]; default: 33579409; + * Timer version control register + */ +#define TIMG_NTIMGS_DATE 0x0FFFFFFFU +#define TIMG_NTIMGS_DATE_M (TIMG_NTIMGS_DATE_V << TIMG_NTIMGS_DATE_S) +#define TIMG_NTIMGS_DATE_V 0x0FFFFFFFU +#define TIMG_NTIMGS_DATE_S 0 -#define TIMG_CLK_REG(i) (REG_TIMG_BASE(i) + 0x00fc) -/* TIMG_CLK_EN : R/W ;bitpos:[31] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_CLK_EN (BIT(31)) -#define TIMG_CLK_EN_M (BIT(31)) -#define TIMG_CLK_EN_V 0x1 -#define TIMG_CLK_EN_S 31 -/* TIMG_TIMER_CLK_IS_ACTIVE : R/W ;bitpos:[30] ;default: 1'h1 ; */ -/*description: */ -#define TIMG_TIMER_CLK_IS_ACTIVE (BIT(30)) -#define TIMG_TIMER_CLK_IS_ACTIVE_M (BIT(30)) -#define TIMG_TIMER_CLK_IS_ACTIVE_V 0x1 -#define TIMG_TIMER_CLK_IS_ACTIVE_S 30 -/* TIMG_WDT_CLK_IS_ACTIVE : R/W ;bitpos:[29] ;default: 1'h1 ; */ -/*description: */ -#define TIMG_WDT_CLK_IS_ACTIVE (BIT(29)) -#define TIMG_WDT_CLK_IS_ACTIVE_M (BIT(29)) -#define TIMG_WDT_CLK_IS_ACTIVE_V 0x1 +/** TIMG_REGCLK_REG register + * Timer group clock gate register + */ +#define TIMG_REGCLK_REG(i) (DR_REG_TIMG_BASE(i) + 0xfc) +/** TIMG_WDT_CLK_IS_ACTIVE : R/W; bitpos: [29]; default: 1; + * enable WDT's clock + */ +#define TIMG_WDT_CLK_IS_ACTIVE (BIT(29)) +#define TIMG_WDT_CLK_IS_ACTIVE_M (TIMG_WDT_CLK_IS_ACTIVE_V << TIMG_WDT_CLK_IS_ACTIVE_S) +#define TIMG_WDT_CLK_IS_ACTIVE_V 0x00000001U #define TIMG_WDT_CLK_IS_ACTIVE_S 29 +/** TIMG_TIMER_CLK_IS_ACTIVE : R/W; bitpos: [30]; default: 1; + * enable Timer $x's clock + */ +#define TIMG_TIMER_CLK_IS_ACTIVE (BIT(30)) +#define TIMG_TIMER_CLK_IS_ACTIVE_M (TIMG_TIMER_CLK_IS_ACTIVE_V << TIMG_TIMER_CLK_IS_ACTIVE_S) +#define TIMG_TIMER_CLK_IS_ACTIVE_V 0x00000001U +#define TIMG_TIMER_CLK_IS_ACTIVE_S 30 +/** TIMG_CLK_EN : R/W; bitpos: [31]; default: 0; + * Register clock gate signal. 1: Registers can be read and written to by software. 0: + * Registers can not be read or written to by software. + */ +#define TIMG_CLK_EN (BIT(31)) +#define TIMG_CLK_EN_M (TIMG_CLK_EN_V << TIMG_CLK_EN_S) +#define TIMG_CLK_EN_V 0x00000001U +#define TIMG_CLK_EN_S 31 #ifdef __cplusplus } #endif - - - -#endif /*_SOC_TIMG_REG_H_ */ diff --git a/components/soc/esp32c3/include/soc/timer_group_struct.h b/components/soc/esp32c3/include/soc/timer_group_struct.h index 6bae30720c..13311b302e 100644 --- a/components/soc/esp32c3/include/soc/timer_group_struct.h +++ b/components/soc/esp32c3/include/soc/timer_group_struct.h @@ -1,222 +1,561 @@ -// 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. -#ifndef _SOC_TIMG_STRUCT_H_ -#define _SOC_TIMG_STRUCT_H_ +/** + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include #ifdef __cplusplus extern "C" { #endif -typedef volatile struct { +/** Group: T0 Control and configuration registers */ +/** Type of txconfig register + * Timer x configuration register + */ +typedef union { struct { - union { - struct { - uint32_t reserved0: 9; - uint32_t use_xtal: 1; - uint32_t alarm_en: 1; - uint32_t reserved11: 1; - uint32_t divcnt_rst: 1; - uint32_t divider: 16; - uint32_t autoreload: 1; - uint32_t increase: 1; - uint32_t enable: 1; - }; - uint32_t val; - } config; - uint32_t cnt_low; /**/ - union { - struct { - uint32_t hi: 22; - uint32_t reserved22:10; - }; - uint32_t val; - } cnt_high; - union { - struct { - uint32_t reserved0: 31; - uint32_t update: 1; - }; - uint32_t val; - } update; - uint32_t alarm_low; /**/ - union { - struct { - uint32_t alarm_hi: 22; - uint32_t reserved22: 10; - }; - uint32_t val; - } alarm_high; - uint32_t load_low; /**/ - union { - struct { - uint32_t load_hi: 22; - uint32_t reserved22:10; - }; - uint32_t val; - } load_high; - uint32_t reload; /**/ - } hw_timer[1]; - uint32_t reserved_24; - uint32_t reserved_28; - uint32_t reserved_2c; - uint32_t reserved_30; - uint32_t reserved_34; - uint32_t reserved_38; - uint32_t reserved_3c; - uint32_t reserved_40; - uint32_t reserved_44; - union { - struct { - uint32_t reserved0: 12; - uint32_t appcpu_reset_en: 1; - uint32_t procpu_reset_en: 1; - uint32_t flashboot_mod_en: 1; - uint32_t sys_reset_length: 3; - uint32_t cpu_reset_length: 3; - uint32_t use_xtal: 1; - uint32_t conf_update_en: 1; - uint32_t stg3: 2; - uint32_t stg2: 2; - uint32_t stg1: 2; - uint32_t stg0: 2; - uint32_t en: 1; - }; - uint32_t val; - } wdt_config0; - union { - struct { - uint32_t divcnt_rst: 1; - uint32_t reserved1: 15; - uint32_t clk_prescale: 16; - }; - uint32_t val; - } wdt_config1; - uint32_t wdt_config2; /**/ - uint32_t wdt_config3; /**/ - uint32_t wdt_config4; /**/ - uint32_t wdt_config5; /**/ - uint32_t wdt_feed; /**/ - uint32_t wdt_wprotect; /**/ - union { - struct { - uint32_t reserved0: 12; - uint32_t start_cycling: 1; - uint32_t clk_sel: 2; - uint32_t rdy: 1; - uint32_t max: 15; - uint32_t start: 1; - }; - uint32_t val; - } rtc_cali_cfg; - union { - struct { - uint32_t cycling_data_vld: 1; - uint32_t reserved1: 6; - uint32_t value: 25; - }; - uint32_t val; - } rtc_cali_cfg1; - union { - struct { - uint32_t t0: 1; - uint32_t wdt: 1; - uint32_t reserved2: 30; - }; - uint32_t val; - } int_ena; - union { - struct { - uint32_t t0: 1; - uint32_t wdt: 1; - uint32_t reserved2: 30; - }; - uint32_t val; - } int_raw; - union { - struct { - uint32_t t0: 1; - uint32_t wdt: 1; - uint32_t reserved2: 30; - }; - uint32_t val; - } int_st; - union { - struct { - uint32_t t0: 1; - uint32_t wdt: 1; - uint32_t reserved2: 30; - }; - uint32_t val; - } int_clr; - union { - struct { - uint32_t timeout: 1; /*timeout indicator*/ - uint32_t reserved1: 2; - uint32_t timeout_rst_cnt: 4; /*Cycles that release calibration timeout reset*/ - uint32_t timeout_thres: 25; /*timeout if cali value counts over threshold*/ - }; - uint32_t val; - } rtc_cali_cfg2; - uint32_t reserved_84; - uint32_t reserved_88; - uint32_t reserved_8c; - uint32_t reserved_90; - uint32_t reserved_94; - uint32_t reserved_98; - uint32_t reserved_9c; - uint32_t reserved_a0; - uint32_t reserved_a4; - uint32_t reserved_a8; - uint32_t reserved_ac; - uint32_t reserved_b0; - uint32_t reserved_b4; - uint32_t reserved_b8; - uint32_t reserved_bc; - uint32_t reserved_c0; - uint32_t reserved_c4; - uint32_t reserved_c8; - uint32_t reserved_cc; - uint32_t reserved_d0; - uint32_t reserved_d4; - uint32_t reserved_d8; - uint32_t reserved_dc; - uint32_t reserved_e0; - uint32_t reserved_e4; - uint32_t reserved_e8; - uint32_t reserved_ec; - uint32_t reserved_f0; - uint32_t reserved_f4; - union { - struct { - uint32_t date: 28; - uint32_t reserved28: 4; - }; - uint32_t val; - } timg_date; - union { - struct { - uint32_t reserved0: 29; - uint32_t wdt_clk_is_active: 1; - uint32_t timer_clk_is_active: 1; - uint32_t en: 1; - }; - uint32_t val; - } clk; + uint32_t reserved_0:9; + /** tx_use_xtal : R/W; bitpos: [9]; default: 0; + * 1: Use XTAL_CLK as the source clock of timer group. 0: Use APB_CLK as the source + * clock of timer group. + */ + uint32_t tx_use_xtal:1; + /** tx_alarm_en : R/W/SC; bitpos: [10]; default: 0; + * When set, the alarm is enabled. This bit is automatically cleared once an + * alarm occurs. + */ + uint32_t tx_alarm_en:1; + uint32_t reserved_11:1; + /** tx_divcnt_rst : WT; bitpos: [12]; default: 0; + * When set, Timer x 's clock divider counter will be reset. + */ + uint32_t tx_divcnt_rst:1; + /** tx_divider : R/W; bitpos: [28:13]; default: 1; + * Timer x clock (Tx_clk) prescaler value. + */ + uint32_t tx_divider:16; + /** tx_autoreload : R/W; bitpos: [29]; default: 1; + * When set, timer x auto-reload at alarm is enabled. + */ + uint32_t tx_autoreload:1; + /** tx_increase : R/W; bitpos: [30]; default: 1; + * When set, the timer x time-base counter will increment every clock tick. When + * cleared, the timer x time-base counter will decrement. + */ + uint32_t tx_increase:1; + /** tx_en : R/W; bitpos: [31]; default: 0; + * When set, the timer x time-base counter is enabled. + */ + uint32_t tx_en:1; + }; + uint32_t val; +} timg_txconfig_reg_t; + +/** Type of txlo register + * Timer x current value, low 32 bits + */ +typedef union { + struct { + /** tx_lo : RO; bitpos: [31:0]; default: 0; + * After writing to TIMG_TxUPDATE_REG, the low 32 bits of the time-base counter + * of timer x can be read here. + */ + uint32_t tx_lo:32; + }; + uint32_t val; +} timg_txlo_reg_t; + +/** Type of txhi register + * Timer $x current value, high 22 bits + */ +typedef union { + struct { + /** tx_hi : RO; bitpos: [21:0]; default: 0; + * After writing to TIMG_T$xUPDATE_REG, the high 22 bits of the time-base counter + * of timer $x can be read here. + */ + uint32_t tx_hi:22; + uint32_t reserved_22:10; + }; + uint32_t val; +} timg_txhi_reg_t; + +/** Type of txupdate register + * Write to copy current timer value to TIMGn_T$x_(LO/HI)_REG + */ +typedef union { + struct { + uint32_t reserved_0:31; + /** tx_update : R/W/SC; bitpos: [31]; default: 0; + * After writing 0 or 1 to TIMG_T$xUPDATE_REG, the counter value is latched. + */ + uint32_t tx_update:1; + }; + uint32_t val; +} timg_txupdate_reg_t; + +/** Type of txalarmlo register + * Timer $x alarm value, low 32 bits + */ +typedef union { + struct { + /** tx_alarm_lo : R/W; bitpos: [31:0]; default: 0; + * Timer $x alarm trigger time-base counter value, low 32 bits. + */ + uint32_t tx_alarm_lo:32; + }; + uint32_t val; +} timg_txalarmlo_reg_t; + +/** Type of txalarmhi register + * Timer $x alarm value, high bits + */ +typedef union { + struct { + /** tx_alarm_hi : R/W; bitpos: [21:0]; default: 0; + * Timer $x alarm trigger time-base counter value, high 22 bits. + */ + uint32_t tx_alarm_hi:22; + uint32_t reserved_22:10; + }; + uint32_t val; +} timg_txalarmhi_reg_t; + +/** Type of txloadlo register + * Timer $x reload value, low 32 bits + */ +typedef union { + struct { + /** tx_load_lo : R/W; bitpos: [31:0]; default: 0; + * Low 32 bits of the value that a reload will load onto timer $x time-base + * Counter. + */ + uint32_t tx_load_lo:32; + }; + uint32_t val; +} timg_txloadlo_reg_t; + +/** Type of txloadhi register + * Timer $x reload value, high 22 bits + */ +typedef union { + struct { + /** tx_load_hi : R/W; bitpos: [21:0]; default: 0; + * High 22 bits of the value that a reload will load onto timer $x time-base + * counter. + */ + uint32_t tx_load_hi:22; + uint32_t reserved_22:10; + }; + uint32_t val; +} timg_txloadhi_reg_t; + +/** Type of txload register + * Write to reload timer from TIMG_T$x_(LOADLOLOADHI)_REG + */ +typedef union { + struct { + /** tx_load : WT; bitpos: [31:0]; default: 0; + * + * Write any value to trigger a timer $x time-base counter reload. + */ + uint32_t tx_load:32; + }; + uint32_t val; +} timg_txload_reg_t; + + +/** Group: WDT Control and configuration registers */ +/** Type of wdtconfig0 register + * Watchdog timer configuration register + */ +typedef union { + struct { + uint32_t reserved_0:12; + /** wdt_appcpu_reset_en : R/W; bitpos: [12]; default: 0; + * WDT reset CPU enable. + */ + uint32_t wdt_appcpu_reset_en:1; + /** wdt_procpu_reset_en : R/W; bitpos: [13]; default: 0; + * WDT reset CPU enable. + */ + uint32_t wdt_procpu_reset_en:1; + /** wdt_flashboot_mod_en : R/W; bitpos: [14]; default: 1; + * When set, Flash boot protection is enabled. + */ + uint32_t wdt_flashboot_mod_en:1; + /** wdt_sys_reset_length : R/W; bitpos: [17:15]; default: 1; + * System reset signal length selection. 0: 100 ns, 1: 200 ns, + * 2: 300 ns, 3: 400 ns, 4: 500 ns, 5: 800 ns, 6: 1.6 us, 7: 3.2 us. + */ + uint32_t wdt_sys_reset_length:3; + /** wdt_cpu_reset_length : R/W; bitpos: [20:18]; default: 1; + * CPU reset signal length selection. 0: 100 ns, 1: 200 ns, + * 2: 300 ns, 3: 400 ns, 4: 500 ns, 5: 800 ns, 6: 1.6 us, 7: 3.2 us. + */ + uint32_t wdt_cpu_reset_length:3; + /** wdt_use_xtal : R/W; bitpos: [21]; default: 0; + * choose WDT clock:0-apb_clk; 1-xtal_clk. + */ + uint32_t wdt_use_xtal:1; + /** wdt_conf_update_en : WT; bitpos: [22]; default: 0; + * update the WDT configuration registers + */ + uint32_t wdt_conf_update_en:1; + /** wdt_stg3 : R/W; bitpos: [24:23]; default: 0; + * Stage 3 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system. + */ + uint32_t wdt_stg3:2; + /** wdt_stg2 : R/W; bitpos: [26:25]; default: 0; + * Stage 2 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system. + */ + uint32_t wdt_stg2:2; + /** wdt_stg1 : R/W; bitpos: [28:27]; default: 0; + * Stage 1 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system. + */ + uint32_t wdt_stg1:2; + /** wdt_stg0 : R/W; bitpos: [30:29]; default: 0; + * Stage 0 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system. + */ + uint32_t wdt_stg0:2; + /** wdt_en : R/W; bitpos: [31]; default: 0; + * When set, MWDT is enabled. + */ + uint32_t wdt_en:1; + }; + uint32_t val; +} timg_wdtconfig0_reg_t; + +/** Type of wdtconfig1 register + * Watchdog timer prescaler register + */ +typedef union { + struct { + /** wdt_divcnt_rst : WT; bitpos: [0]; default: 0; + * When set, WDT 's clock divider counter will be reset. + */ + uint32_t wdt_divcnt_rst:1; + uint32_t reserved_1:15; + /** wdt_clk_prescale : R/W; bitpos: [31:16]; default: 1; + * MWDT clock prescaler value. MWDT clock period = 12.5 ns * + * TIMG_WDT_CLK_PRESCALE. + */ + uint32_t wdt_clk_prescale:16; + }; + uint32_t val; +} timg_wdtconfig1_reg_t; + +/** Type of wdtconfig2 register + * Watchdog timer stage 0 timeout value + */ +typedef union { + struct { + /** wdt_stg0_hold : R/W; bitpos: [31:0]; default: 26000000; + * Stage 0 timeout value, in MWDT clock cycles. + */ + uint32_t wdt_stg0_hold:32; + }; + uint32_t val; +} timg_wdtconfig2_reg_t; + +/** Type of wdtconfig3 register + * Watchdog timer stage 1 timeout value + */ +typedef union { + struct { + /** wdt_stg1_hold : R/W; bitpos: [31:0]; default: 134217727; + * Stage 1 timeout value, in MWDT clock cycles. + */ + uint32_t wdt_stg1_hold:32; + }; + uint32_t val; +} timg_wdtconfig3_reg_t; + +/** Type of wdtconfig4 register + * Watchdog timer stage 2 timeout value + */ +typedef union { + struct { + /** wdt_stg2_hold : R/W; bitpos: [31:0]; default: 1048575; + * Stage 2 timeout value, in MWDT clock cycles. + */ + uint32_t wdt_stg2_hold:32; + }; + uint32_t val; +} timg_wdtconfig4_reg_t; + +/** Type of wdtconfig5 register + * Watchdog timer stage 3 timeout value + */ +typedef union { + struct { + /** wdt_stg3_hold : R/W; bitpos: [31:0]; default: 1048575; + * Stage 3 timeout value, in MWDT clock cycles. + */ + uint32_t wdt_stg3_hold:32; + }; + uint32_t val; +} timg_wdtconfig5_reg_t; + +/** Type of wdtfeed register + * Write to feed the watchdog timer + */ +typedef union { + struct { + /** wdt_feed : WT; bitpos: [31:0]; default: 0; + * Write any value to feed the MWDT. (WO) + */ + uint32_t wdt_feed:32; + }; + uint32_t val; +} timg_wdtfeed_reg_t; + +/** Type of wdtwprotect register + * Watchdog write protect register + */ +typedef union { + struct { + /** wdt_wkey : R/W; bitpos: [31:0]; default: 1356348065; + * If the register contains a different value than its reset value, write + * protection is enabled. + */ + uint32_t wdt_wkey:32; + }; + uint32_t val; +} timg_wdtwprotect_reg_t; + + +/** Group: RTC CALI Control and configuration registers */ +/** Type of rtccalicfg register + * RTC calibration configure register + */ +typedef union { + struct { + uint32_t reserved_0:12; + /** rtc_cali_start_cycling : R/W; bitpos: [12]; default: 1; + * Reserved + */ + uint32_t rtc_cali_start_cycling:1; + /** rtc_cali_clk_sel : R/W; bitpos: [14:13]; default: 1; + * 0:rtc slow clock. 1:clk_8m, 2:xtal_32k. + */ + uint32_t rtc_cali_clk_sel:2; + /** rtc_cali_rdy : RO; bitpos: [15]; default: 0; + * Reserved + */ + uint32_t rtc_cali_rdy:1; + /** rtc_cali_max : R/W; bitpos: [30:16]; default: 1; + * Reserved + */ + uint32_t rtc_cali_max:15; + /** rtc_cali_start : R/W; bitpos: [31]; default: 0; + * Reserved + */ + uint32_t rtc_cali_start:1; + }; + uint32_t val; +} timg_rtccalicfg_reg_t; + +/** Type of rtccalicfg1 register + * RTC calibration configure1 register + */ +typedef union { + struct { + /** rtc_cali_cycling_data_vld : RO; bitpos: [0]; default: 0; + * Reserved + */ + uint32_t rtc_cali_cycling_data_vld:1; + uint32_t reserved_1:6; + /** rtc_cali_value : RO; bitpos: [31:7]; default: 0; + * Reserved + */ + uint32_t rtc_cali_value:25; + }; + uint32_t val; +} timg_rtccalicfg1_reg_t; + +/** Type of rtccalicfg2 register + * Timer group calibration register + */ +typedef union { + struct { + /** rtc_cali_timeout : RO; bitpos: [0]; default: 0; + * RTC calibration timeout indicator + */ + uint32_t rtc_cali_timeout:1; + uint32_t reserved_1:2; + /** rtc_cali_timeout_rst_cnt : R/W; bitpos: [6:3]; default: 3; + * Cycles that release calibration timeout reset + */ + uint32_t rtc_cali_timeout_rst_cnt:4; + /** rtc_cali_timeout_thres : R/W; bitpos: [31:7]; default: 33554431; + * Threshold value for the RTC calibration timer. If the calibration timer's value + * exceeds this threshold, a timeout is triggered. + */ + uint32_t rtc_cali_timeout_thres:25; + }; + uint32_t val; +} timg_rtccalicfg2_reg_t; + + +/** Group: Interrupt registers */ +/** Type of int_ena_timers register + * Interrupt enable bits + */ +typedef union { + struct { + /** t0_int_ena : R/W; bitpos: [0]; default: 0; + * The interrupt enable bit for the TIMG_T$x_INT interrupt. + */ + uint32_t t0_int_ena:1; + /** wdt_int_ena : R/W; bitpos: [1]; default: 0; + * The interrupt enable bit for the TIMG_WDT_INT interrupt. + */ + uint32_t wdt_int_ena:1; + uint32_t reserved_2:30; + }; + uint32_t val; +} timg_int_ena_timers_reg_t; + +/** Type of int_raw_timers register + * Raw interrupt status + */ +typedef union { + struct { + /** t0_int_raw : R/SS/WTC; bitpos: [0]; default: 0; + * The raw interrupt status bit for the TIMG_T$x_INT interrupt. + */ + uint32_t t0_int_raw:1; + /** wdt_int_raw : R/SS/WTC; bitpos: [1]; default: 0; + * The raw interrupt status bit for the TIMG_WDT_INT interrupt. + */ + uint32_t wdt_int_raw:1; + uint32_t reserved_2:30; + }; + uint32_t val; +} timg_int_raw_timers_reg_t; + +/** Type of int_st_timers register + * Masked interrupt status + */ +typedef union { + struct { + /** t0_int_st : RO; bitpos: [0]; default: 0; + * The masked interrupt status bit for the TIMG_T$x_INT interrupt. + */ + uint32_t t0_int_st:1; + /** wdt_int_st : RO; bitpos: [1]; default: 0; + * The masked interrupt status bit for the TIMG_WDT_INT interrupt. + */ + uint32_t wdt_int_st:1; + uint32_t reserved_2:30; + }; + uint32_t val; +} timg_int_st_timers_reg_t; + +/** Type of int_clr_timers register + * Interrupt clear bits + */ +typedef union { + struct { + /** t0_int_clr : WT; bitpos: [0]; default: 0; + * Set this bit to clear the TIMG_T$x_INT interrupt. + */ + uint32_t t0_int_clr:1; + /** wdt_int_clr : WT; bitpos: [1]; default: 0; + * Set this bit to clear the TIMG_WDT_INT interrupt. + */ + uint32_t wdt_int_clr:1; + uint32_t reserved_2:30; + }; + uint32_t val; +} timg_int_clr_timers_reg_t; + + +/** Group: Version register */ +/** Type of ntimers_date register + * Timer version control register + */ +typedef union { + struct { + /** ntimgs_date : R/W; bitpos: [27:0]; default: 33579409; + * Timer version control register + */ + uint32_t ntimgs_date:28; + uint32_t reserved_28:4; + }; + uint32_t val; +} timg_ntimers_date_reg_t; + + +/** Group: Clock configuration registers */ +/** Type of regclk register + * Timer group clock gate register + */ +typedef union { + struct { + uint32_t reserved_0:29; + /** wdt_clk_is_active : R/W; bitpos: [29]; default: 1; + * enable WDT's clock + */ + uint32_t wdt_clk_is_active:1; + /** timer_clk_is_active : R/W; bitpos: [30]; default: 1; + * enable Timer $x's clock + */ + uint32_t timer_clk_is_active:1; + /** clk_en : R/W; bitpos: [31]; default: 0; + * Register clock gate signal. 1: Registers can be read and written to by software. 0: + * Registers can not be read or written to by software. + */ + uint32_t clk_en:1; + }; + uint32_t val; +} timg_regclk_reg_t; + +typedef struct { + volatile timg_txconfig_reg_t config; + volatile timg_txlo_reg_t lo; + volatile timg_txhi_reg_t hi; + volatile timg_txupdate_reg_t update; + volatile timg_txalarmlo_reg_t alarmlo; + volatile timg_txalarmhi_reg_t alarmhi; + volatile timg_txloadlo_reg_t loadlo; + volatile timg_txloadhi_reg_t loadhi; + volatile timg_txload_reg_t load; +} timg_hwtimer_reg_t; + +typedef struct { + volatile timg_hwtimer_reg_t hw_timer[1]; + uint32_t reserved_024[9]; + volatile timg_wdtconfig0_reg_t wdtconfig0; + volatile timg_wdtconfig1_reg_t wdtconfig1; + volatile timg_wdtconfig2_reg_t wdtconfig2; + volatile timg_wdtconfig3_reg_t wdtconfig3; + volatile timg_wdtconfig4_reg_t wdtconfig4; + volatile timg_wdtconfig5_reg_t wdtconfig5; + volatile timg_wdtfeed_reg_t wdtfeed; + volatile timg_wdtwprotect_reg_t wdtwprotect; + volatile timg_rtccalicfg_reg_t rtccalicfg; + volatile timg_rtccalicfg1_reg_t rtccalicfg1; + volatile timg_int_ena_timers_reg_t int_ena_timers; + volatile timg_int_raw_timers_reg_t int_raw_timers; + volatile timg_int_st_timers_reg_t int_st_timers; + volatile timg_int_clr_timers_reg_t int_clr_timers; + volatile timg_rtccalicfg2_reg_t rtccalicfg2; + uint32_t reserved_084[29]; + volatile timg_ntimers_date_reg_t ntimers_date; + volatile timg_regclk_reg_t regclk; } timg_dev_t; + extern timg_dev_t TIMERG0; extern timg_dev_t TIMERG1; + +#ifndef __cplusplus +_Static_assert(sizeof(timg_dev_t) == 0x100, "Invalid size of timg_dev_t structure"); +#endif + #ifdef __cplusplus } #endif - -#endif /* _SOC_TIMG_STRUCT_H_ */ diff --git a/components/soc/esp32c3/include/soc/twai_struct.h b/components/soc/esp32c3/include/soc/twai_struct.h index 64cb80e5ed..fafc36393a 100644 --- a/components/soc/esp32c3/include/soc/twai_struct.h +++ b/components/soc/esp32c3/include/soc/twai_struct.h @@ -35,10 +35,10 @@ typedef volatile struct twai_dev_s { uint32_t lom: 1; /* MOD.1 Listen Only Mode */ uint32_t stm: 1; /* MOD.2 Self Test Mode */ uint32_t afm: 1; /* MOD.3 Acceptance Filter Mode */ - uint32_t reserved28: 28; /* Internal Reserved. MOD.4 Sleep Mode not supported */ + uint32_t reserved4: 28; /* Internal Reserved. MOD.4 Sleep Mode not supported */ }; uint32_t val; - } mode_reg; /* Address 0 */ + } mode_reg; /* Address 0x0000 */ union { struct { uint32_t tr: 1; /* CMR.0 Transmission Request */ @@ -46,10 +46,10 @@ typedef volatile struct twai_dev_s { uint32_t rrb: 1; /* CMR.2 Release Receive Buffer */ uint32_t cdo: 1; /* CMR.3 Clear Data Overrun */ uint32_t srr: 1; /* CMR.4 Self Reception Request */ - uint32_t reserved27: 27; /* Internal Reserved */ + uint32_t reserved5: 27; /* Internal Reserved */ }; uint32_t val; - } command_reg; /* Address 1 */ + } command_reg; /* Address 0x0004 */ union { struct { uint32_t rbs: 1; /* SR.0 Receive Buffer Status */ @@ -61,97 +61,99 @@ typedef volatile struct twai_dev_s { uint32_t es: 1; /* SR.6 Error Status */ uint32_t bs: 1; /* SR.7 Bus Status */ uint32_t ms: 1; /* SR.8 Miss Status */ - uint32_t reserved23: 23; /* Internal Reserved */ + uint32_t reserved9: 23; /* Internal Reserved */ }; uint32_t val; - } status_reg; /* Address 2 */ + } status_reg; /* Address 0x0008 */ union { struct { uint32_t ri: 1; /* IR.0 Receive Interrupt */ uint32_t ti: 1; /* IR.1 Transmit Interrupt */ uint32_t ei: 1; /* IR.2 Error Interrupt */ - uint32_t reserved2: 2; /* Internal Reserved (Data Overrun interrupt and Wake-up not supported) */ + uint32_t doi: 1; /* IR.3 Data Overrun Interrupt */ + uint32_t reserved4: 1; /* Internal Reserved (Wake-up not supported) */ uint32_t epi: 1; /* IR.5 Error Passive Interrupt */ uint32_t ali: 1; /* IR.6 Arbitration Lost Interrupt */ uint32_t bei: 1; /* IR.7 Bus Error Interrupt */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } interrupt_reg; /* Address 3 */ + } interrupt_reg; /* Address 0x000C */ union { struct { uint32_t rie: 1; /* IER.0 Receive Interrupt Enable */ uint32_t tie: 1; /* IER.1 Transmit Interrupt Enable */ uint32_t eie: 1; /* IER.2 Error Interrupt Enable */ - uint32_t reserved2: 2; /* Internal Reserved (Data Overrun interrupt and Wake-up not supported) */ + uint32_t doie: 1; /* IER.3 Data Overrun Interrupt Enable */ + uint32_t reserved4: 1; /* Internal Reserved (Wake-up not supported) */ uint32_t epie: 1; /* IER.5 Error Passive Interrupt Enable */ uint32_t alie: 1; /* IER.6 Arbitration Lost Interrupt Enable */ uint32_t beie: 1; /* IER.7 Bus Error Interrupt Enable */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } interrupt_enable_reg; /* Address 4 */ - uint32_t reserved_05; /* Address 5 */ + } interrupt_enable_reg; /* Address 0x0010 */ + uint32_t reserved_14; union { struct { uint32_t brp: 13; /* BTR0[12:0] Baud Rate Prescaler */ - uint32_t reserved1: 1; /* Internal Reserved */ + uint32_t reserved13: 1; /* Internal Reserved */ uint32_t sjw: 2; /* BTR0[15:14] Synchronization Jump Width*/ uint32_t reserved16: 16; /* Internal Reserved */ }; uint32_t val; - } bus_timing_0_reg; /* Address 6 */ + } bus_timing_0_reg; /* Address 0x0018 */ union { struct { uint32_t tseg1: 4; /* BTR1[3:0] Timing Segment 1 */ uint32_t tseg2: 3; /* BTR1[6:4] Timing Segment 2 */ uint32_t sam: 1; /* BTR1.7 Sampling*/ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } bus_timing_1_reg; /* Address 7 */ - uint32_t reserved_08; /* Address 8 (Output control not supported) */ - uint32_t reserved_09; /* Address 9 (Test Register not supported) */ - uint32_t reserved_10; /* Address 10 */ + } bus_timing_1_reg; /* Address 0x001C */ + uint32_t reserved_20; /* Address 0x0020 (Output control not supported) */ + uint32_t reserved_24; /* Address 0x0024 (Test Register not supported) */ + uint32_t reserved_28; /* Address 0x0028 */ //Capture and Counter Registers union { struct { uint32_t alc: 5; /* ALC[4:0] Arbitration lost capture */ - uint32_t reserved27: 27; /* Internal Reserved */ + uint32_t reserved5: 27; /* Internal Reserved */ }; uint32_t val; - } arbitration_lost_captue_reg; /* Address 11 */ + } arbitration_lost_captue_reg; /* Address 0x002C */ union { struct { uint32_t seg: 5; /* ECC[4:0] Error Code Segment 0 to 5 */ uint32_t dir: 1; /* ECC.5 Error Direction (TX/RX) */ uint32_t errc: 2; /* ECC[7:6] Error Code */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } error_code_capture_reg; /* Address 12 */ + } error_code_capture_reg; /* Address 0x0030 */ union { struct { uint32_t ewl: 8; /* EWL[7:0] Error Warning Limit */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } error_warning_limit_reg; /* EWLR[7:0] Error Warning Limit: Address 13 */ + } error_warning_limit_reg; /* Address 0x0034 */ union { struct { uint32_t rxerr: 8; /* RXERR[7:0] Receive Error Counter */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } rx_error_counter_reg; /* Address 12 */ + } rx_error_counter_reg; /* Address 0x0038 */ union { struct { uint32_t txerr: 8; /* TXERR[7:0] Receive Error Counter */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } tx_error_counter_reg; /* Address 15 */ + } tx_error_counter_reg; /* Address 0x003C */ //Shared Registers (TX Buff/RX Buff/Acc Filter) union { @@ -159,45 +161,49 @@ typedef volatile struct twai_dev_s { union { struct { uint32_t byte: 8; /* ACRx[7:0] Acceptance Code */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; } acr[4]; union { struct { uint32_t byte: 8; /* AMRx[7:0] Acceptance Mask */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; } amr[4]; - uint32_t reserved32[5]; + uint32_t reserved_60; + uint32_t reserved_64; + uint32_t reserved_68; + uint32_t reserved_6c; + uint32_t reserved_70; } acceptance_filter; union { struct { - uint32_t byte: 8; - uint32_t reserved24: 24; + uint32_t byte: 8; /* TX/RX Byte X [7:0] */ + uint32_t reserved24: 24; /* Internal Reserved */ }; uint32_t val; } tx_rx_buffer[13]; - }; /* Address 16-28 TX/RX Buffer and Acc Filter*/; + }; /* Address 0x0040 - 0x0070 */ //Misc Registers union { struct { uint32_t rmc: 7; /* RMC[6:0] RX Message Counter */ - uint32_t reserved25: 25; /* Internal Reserved */ + uint32_t reserved7: 25; /* Internal Reserved */ }; uint32_t val; - } rx_message_counter_reg; /* Address 29 */ - uint32_t reserved_30; /* Address 30 (RX Buffer Start Address not supported) */ + } rx_message_counter_reg; /* Address 0x0074 */ + uint32_t reserved_78; /* Address 0x0078 (RX Buffer Start Address not supported) */ union { struct { uint32_t cd: 8; /* CDR[7:0] CLKOUT frequency selector based of fOSC */ uint32_t co: 1; /* CDR.8 CLKOUT enable/disable */ - uint32_t reserved24: 23; /* Internal Reserved */ + uint32_t reserved9: 23; /* Internal Reserved */ }; uint32_t val; - } clock_divider_reg; /* Address 31 */ + } clock_divider_reg; /* Address 0x007C */ } twai_dev_t; _Static_assert(sizeof(twai_dev_t) == 128, "TWAI registers should be 32 * 4 bytes"); diff --git a/components/soc/esp32c3/include/soc/uart_pins.h b/components/soc/esp32c3/include/soc/uart_pins.h new file mode 100644 index 0000000000..26b225a346 --- /dev/null +++ b/components/soc/esp32c3/include/soc/uart_pins.h @@ -0,0 +1,44 @@ +// Copyright 2015-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. + +#pragma once + +#include "soc/io_mux_reg.h" + +/* Specify the number of pins for UART */ +#define SOC_UART_PINS_COUNT (4) + +/* Specify the GPIO pin number for each UART signal in the IOMUX */ +#define U0RXD_GPIO_NUM 20 +#define U0TXD_GPIO_NUM 21 +#define U0RTS_GPIO_NUM (-1) +#define U0CTS_GPIO_NUM (-1) + +#define U1RXD_GPIO_NUM (-1) +#define U1TXD_GPIO_NUM (-1) +#define U1RTS_GPIO_NUM (-1) +#define U1CTS_GPIO_NUM (-1) + +/* The following defines are necessary for reconfiguring the UART + * to use IOMUX, at runtime. */ +#define U0TXD_MUX_FUNC (FUNC_U0TXD_U0TXD) +#define U0RXD_MUX_FUNC (FUNC_U0RXD_U0RXD) +/* No func for the following pins, they shall not be used */ +#define U0RTS_MUX_FUNC (-1) +#define U0CTS_MUX_FUNC (-1) +/* Same goes for UART1 */ +#define U1TXD_MUX_FUNC (-1) +#define U1RXD_MUX_FUNC (-1) +#define U1RTS_MUX_FUNC (-1) +#define U1CTS_MUX_FUNC (-1) diff --git a/components/soc/esp32c3/include/soc/uart_struct.h b/components/soc/esp32c3/include/soc/uart_struct.h index ad9ca42ff7..82f8ef6686 100644 --- a/components/soc/esp32c3/include/soc/uart_struct.h +++ b/components/soc/esp32c3/include/soc/uart_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct uart_dev_s { union { struct { uint32_t rw_byte; /*a*/ diff --git a/components/soc/esp32c3/include/soc/uhci_struct.h b/components/soc/esp32c3/include/soc/uhci_struct.h index a89c4d0126..164f1a1334 100644 --- a/components/soc/esp32c3/include/soc/uhci_struct.h +++ b/components/soc/esp32c3/include/soc/uhci_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct uhci_dev_s { union { struct { uint32_t tx_rst: 1; /*Write 1 then write 0 to this bit to reset decode state machine.*/ diff --git a/components/soc/esp32c3/include/soc/usb_serial_jtag_struct.h b/components/soc/esp32c3/include/soc/usb_serial_jtag_struct.h index 5ae44587a6..c1cfced04b 100644 --- a/components/soc/esp32c3/include/soc/usb_serial_jtag_struct.h +++ b/components/soc/esp32c3/include/soc/usb_serial_jtag_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif #include "soc.h" -typedef volatile struct { +typedef volatile struct usb_serial_jtag_dev_s { union { struct { uint32_t rdwr_byte : 32; /*Although only low 8-bits is valid, but change it to 32bits to avoid there's no read/modify/write behaviour*/ /*Write and read byte data to/from UART Tx/Rx FIFO through this field. When USB_SERIAL_JTAG_SERIAL_IN_EMPTY_INT is set then user can write data (up to 64 bytes) into UART Tx FIFO. When USB_SERIAL_JTAG_SERIAL_OUT_RECV_PKT_INT is set, user can check USB_SERIAL_JTAG_OUT_EP1_WR_ADDR and USB_SERIAL_JTAG_OUT_EP0_RD_ADDR to know how many data is received, then read that amount of data from UART Rx FIFO. */ diff --git a/components/soc/esp32c3/ld/esp32c3.peripherals.ld b/components/soc/esp32c3/ld/esp32c3.peripherals.ld index 494cbb9b6b..710ae9aeea 100644 --- a/components/soc/esp32c3/ld/esp32c3.peripherals.ld +++ b/components/soc/esp32c3/ld/esp32c3.peripherals.ld @@ -7,7 +7,7 @@ PROVIDE ( SIGMADELTA = 0x60004f00 ); PROVIDE ( RTCCNTL = 0x60008000 ); PROVIDE ( RTCIO = 0x60008400 ); PROVIDE ( HINF = 0x6000B000 ); -PROVIDE ( I2S1 = 0x6002d000 ); +PROVIDE ( I2S0 = 0x6002d000 ); PROVIDE ( I2C0 = 0x60013000 ); PROVIDE ( UHCI0 = 0x60014000 ); PROVIDE ( UHCI1 = 0x6000c000 ); diff --git a/components/soc/esp32c3/uart_periph.c b/components/soc/esp32c3/uart_periph.c index 999eb69fd8..d4262c6776 100644 --- a/components/soc/esp32c3/uart_periph.c +++ b/components/soc/esp32c3/uart_periph.c @@ -18,20 +18,71 @@ Bunch of constants for every UART peripheral: GPIO signals, irqs, hw addr of registers etc */ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { - { - .tx_sig = U0TXD_OUT_IDX, - .rx_sig = U0RXD_IN_IDX, - .rts_sig = U0RTS_OUT_IDX, - .cts_sig = U0CTS_IN_IDX, + { + .pins = { + [SOC_UART_TX_PIN_IDX] = { + .default_gpio = U0TXD_GPIO_NUM, + .iomux_func = U0TXD_MUX_FUNC, + .input = 0, + .signal = U0TXD_OUT_IDX, + }, + + [SOC_UART_RX_PIN_IDX] = { + .default_gpio = U0RXD_GPIO_NUM, + .iomux_func = U0RXD_MUX_FUNC, + .input = 1, + .signal = U0RXD_IN_IDX, + }, + + [SOC_UART_RTS_PIN_IDX] = { + .default_gpio = U0RTS_GPIO_NUM, + .iomux_func = U0RTS_MUX_FUNC, + .input = 0, + .signal = U0RTS_OUT_IDX, + }, + + [SOC_UART_CTS_PIN_IDX] = { + .default_gpio = U0CTS_GPIO_NUM, + .iomux_func = U0CTS_MUX_FUNC, + .input = 1, + .signal = U0CTS_IN_IDX, + } + }, .irq = ETS_UART0_INTR_SOURCE, .module = PERIPH_UART0_MODULE, }, + { - .tx_sig = U1TXD_OUT_IDX, - .rx_sig = U1RXD_IN_IDX, - .rts_sig = U1RTS_OUT_IDX, - .cts_sig = U1CTS_IN_IDX, + .pins = { + [SOC_UART_TX_PIN_IDX] = { + .default_gpio = U1TXD_GPIO_NUM, + .iomux_func = U1TXD_MUX_FUNC, + .input = 0, + .signal = U1TXD_OUT_IDX, + }, + + [SOC_UART_RX_PIN_IDX] = { + .default_gpio = U1RXD_GPIO_NUM, + .iomux_func = U1RXD_MUX_FUNC, + .input = 1, + .signal = U1RXD_IN_IDX, + }, + + [SOC_UART_RTS_PIN_IDX] = { + .default_gpio = U1RTS_GPIO_NUM, + .iomux_func = U1RTS_MUX_FUNC, + .input = 0, + .signal = U1RTS_OUT_IDX, + }, + + [SOC_UART_CTS_PIN_IDX] = { + .default_gpio = U1CTS_GPIO_NUM, + .iomux_func = U1CTS_MUX_FUNC, + .input = 1, + .signal = U1CTS_IN_IDX, + }, + }, .irq = ETS_UART1_INTR_SOURCE, .module = PERIPH_UART1_MODULE, - } + }, }; diff --git a/components/soc/esp32h2/CMakeLists.txt b/components/soc/esp32h2/CMakeLists.txt index a8eac92c55..a59b5173c1 100644 --- a/components/soc/esp32h2/CMakeLists.txt +++ b/components/soc/esp32h2/CMakeLists.txt @@ -1,5 +1,6 @@ set(srcs "adc_periph.c" + "dedic_gpio_periph.c" "gdma_periph.c" "gpio_periph.c" "interrupts.c" diff --git a/components/soc/esp32h2/dedic_gpio_periph.c b/components/soc/esp32h2/dedic_gpio_periph.c new file mode 100644 index 0000000000..711274f893 --- /dev/null +++ b/components/soc/esp32h2/dedic_gpio_periph.c @@ -0,0 +1,37 @@ +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/gpio_sig_map.h" +#include "soc/dedic_gpio_periph.h" + +const dedic_gpio_signal_conn_t dedic_gpio_periph_signals = { + .module = -1, + .irq = -1, + .cores = { + [0] = { + .in_sig_per_channel = { + [0] = CPU_GPIO_IN0_IDX, + [1] = CPU_GPIO_IN1_IDX, + [2] = CPU_GPIO_IN2_IDX, + [3] = CPU_GPIO_IN3_IDX, + [4] = CPU_GPIO_IN4_IDX, + [5] = CPU_GPIO_IN5_IDX, + [6] = CPU_GPIO_IN6_IDX, + [7] = CPU_GPIO_IN7_IDX, + }, + .out_sig_per_channel = { + [0] = CPU_GPIO_OUT0_IDX, + [1] = CPU_GPIO_OUT1_IDX, + [2] = CPU_GPIO_OUT2_IDX, + [3] = CPU_GPIO_OUT3_IDX, + [4] = CPU_GPIO_OUT4_IDX, + [5] = CPU_GPIO_OUT5_IDX, + [6] = CPU_GPIO_OUT6_IDX, + [7] = CPU_GPIO_OUT7_IDX, + } + }, + }, +}; diff --git a/components/soc/esp32h2/i2c_bbpll.h b/components/soc/esp32h2/i2c_bbpll.h index c9d4753f49..2efd12168b 100644 --- a/components/soc/esp32h2/i2c_bbpll.h +++ b/components/soc/esp32h2/i2c_bbpll.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -24,7 +16,8 @@ */ #define I2C_BBPLL 0x66 -#define I2C_BBPLL_HOSTID 1 +#define I2C_BBPLL_HOSTID 0 + #define I2C_BBPLL_IR_CAL_DELAY 0 #define I2C_BBPLL_IR_CAL_DELAY_MSB 3 @@ -58,71 +51,39 @@ #define I2C_BBPLL_OC_REF_DIV_MSB 3 #define I2C_BBPLL_OC_REF_DIV_LSB 0 -#define I2C_BBPLL_OC_DCHGP 2 -#define I2C_BBPLL_OC_DCHGP_MSB 6 -#define I2C_BBPLL_OC_DCHGP_LSB 4 +#define I2C_BBPLL_OC_DIV 3 +#define I2C_BBPLL_OC_DIV_MSB 5 +#define I2C_BBPLL_OC_DIV_LSB 0 -#define I2C_BBPLL_OC_ENB_FCAL 2 +#define I2C_BBPLL_OC_CHGP_DCUR 4 +#define I2C_BBPLL_OC_CHGP_DCUR_MSB 2 +#define I2C_BBPLL_OC_CHGP_DCUR_LSB 0 + +#define I2C_BBPLL_OC_BUFF_DCUR 4 +#define I2C_BBPLL_OC_BUFF_DCUR_MSB 5 +#define I2C_BBPLL_OC_BUFF_DCUR_LSB 3 + +#define I2C_BBPLL_OC_TSCHGP 4 +#define I2C_BBPLL_OC_TSCHGP_MSB 6 +#define I2C_BBPLL_OC_TSCHGP_LSB 6 + +#define I2C_BBPLL_OC_ENB_FCAL 4 #define I2C_BBPLL_OC_ENB_FCAL_MSB 7 #define I2C_BBPLL_OC_ENB_FCAL_LSB 7 -#define I2C_BBPLL_OC_DIV_7_0 3 -#define I2C_BBPLL_OC_DIV_7_0_MSB 7 -#define I2C_BBPLL_OC_DIV_7_0_LSB 0 +#define I2C_BBPLL_OC_LPF_DR 5 +#define I2C_BBPLL_OC_LPF_DR_MSB 1 +#define I2C_BBPLL_OC_LPF_DR_LSB 0 -#define I2C_BBPLL_RSTB_DIV_ADC 4 -#define I2C_BBPLL_RSTB_DIV_ADC_MSB 0 -#define I2C_BBPLL_RSTB_DIV_ADC_LSB 0 +#define I2C_BBPLL_OC_VCO_DCUR 5 +#define I2C_BBPLL_OC_VCO_DCUR_MSB 3 +#define I2C_BBPLL_OC_VCO_DCUR_LSB 2 -#define I2C_BBPLL_MODE_HF 4 -#define I2C_BBPLL_MODE_HF_MSB 1 -#define I2C_BBPLL_MODE_HF_LSB 1 - -#define I2C_BBPLL_DIV_ADC 4 -#define I2C_BBPLL_DIV_ADC_MSB 3 -#define I2C_BBPLL_DIV_ADC_LSB 2 - -#define I2C_BBPLL_DIV_DAC 4 -#define I2C_BBPLL_DIV_DAC_MSB 4 -#define I2C_BBPLL_DIV_DAC_LSB 4 - -#define I2C_BBPLL_DIV_CPU 4 -#define I2C_BBPLL_DIV_CPU_MSB 5 -#define I2C_BBPLL_DIV_CPU_LSB 5 - -#define I2C_BBPLL_OC_ENB_VCON 4 -#define I2C_BBPLL_OC_ENB_VCON_MSB 6 -#define I2C_BBPLL_OC_ENB_VCON_LSB 6 - -#define I2C_BBPLL_OC_TSCHGP 4 -#define I2C_BBPLL_OC_TSCHGP_MSB 7 -#define I2C_BBPLL_OC_TSCHGP_LSB 7 - -#define I2C_BBPLL_OC_DR1 5 -#define I2C_BBPLL_OC_DR1_MSB 2 -#define I2C_BBPLL_OC_DR1_LSB 0 - -#define I2C_BBPLL_OC_DR3 5 -#define I2C_BBPLL_OC_DR3_MSB 6 -#define I2C_BBPLL_OC_DR3_LSB 4 - -#define I2C_BBPLL_EN_USB 5 -#define I2C_BBPLL_EN_USB_MSB 7 -#define I2C_BBPLL_EN_USB_LSB 7 - -#define I2C_BBPLL_OC_DCUR 6 -#define I2C_BBPLL_OC_DCUR_MSB 2 -#define I2C_BBPLL_OC_DCUR_LSB 0 - -#define I2C_BBPLL_INC_CUR 6 -#define I2C_BBPLL_INC_CUR_MSB 3 -#define I2C_BBPLL_INC_CUR_LSB 3 - -#define I2C_BBPLL_OC_DHREF_SEL 6 +#define I2C_BBPLL_OC_DHREF_SEL 5 #define I2C_BBPLL_OC_DHREF_SEL_MSB 5 #define I2C_BBPLL_OC_DHREF_SEL_LSB 4 -#define I2C_BBPLL_OC_DLREF_SEL 6 +#define I2C_BBPLL_OC_DLREF_SEL 5 #define I2C_BBPLL_OC_DLREF_SEL_MSB 7 #define I2C_BBPLL_OC_DLREF_SEL_LSB 6 @@ -146,38 +107,14 @@ #define I2C_BBPLL_OR_LOCK_MSB 7 #define I2C_BBPLL_OR_LOCK_LSB 7 -#define I2C_BBPLL_BBADC_DELAY1 9 -#define I2C_BBPLL_BBADC_DELAY1_MSB 1 -#define I2C_BBPLL_BBADC_DELAY1_LSB 0 - -#define I2C_BBPLL_BBADC_DELAY2 9 -#define I2C_BBPLL_BBADC_DELAY2_MSB 3 -#define I2C_BBPLL_BBADC_DELAY2_LSB 2 - -#define I2C_BBPLL_BBADC_DVDD 9 -#define I2C_BBPLL_BBADC_DVDD_MSB 5 -#define I2C_BBPLL_BBADC_DVDD_LSB 4 - -#define I2C_BBPLL_BBADC_DREF 9 -#define I2C_BBPLL_BBADC_DREF_MSB 7 -#define I2C_BBPLL_BBADC_DREF_LSB 6 - -#define I2C_BBPLL_BBADC_DCUR 10 -#define I2C_BBPLL_BBADC_DCUR_MSB 1 -#define I2C_BBPLL_BBADC_DCUR_LSB 0 - -#define I2C_BBPLL_BBADC_INPUT_SHORT 10 -#define I2C_BBPLL_BBADC_INPUT_SHORT_MSB 2 -#define I2C_BBPLL_BBADC_INPUT_SHORT_LSB 2 +#define I2C_BBPLL_DTEST 10 +#define I2C_BBPLL_DTEST_MSB 1 +#define I2C_BBPLL_DTEST_LSB 0 #define I2C_BBPLL_ENT_PLL 10 -#define I2C_BBPLL_ENT_PLL_MSB 3 -#define I2C_BBPLL_ENT_PLL_LSB 3 +#define I2C_BBPLL_ENT_PLL_MSB 2 +#define I2C_BBPLL_ENT_PLL_LSB 2 -#define I2C_BBPLL_DTEST 10 -#define I2C_BBPLL_DTEST_MSB 5 -#define I2C_BBPLL_DTEST_LSB 4 - -#define I2C_BBPLL_ENT_ADC 10 -#define I2C_BBPLL_ENT_ADC_MSB 7 -#define I2C_BBPLL_ENT_ADC_LSB 6 +#define I2C_BBPLL_DIV_CPU 10 +#define I2C_BBPLL_DIV_CPU_MSB 3 +#define I2C_BBPLL_DIV_CPU_LSB 3 diff --git a/components/soc/esp32h2/i2c_bias.h b/components/soc/esp32h2/i2c_bias.h new file mode 100644 index 0000000000..a7ea588270 --- /dev/null +++ b/components/soc/esp32h2/i2c_bias.h @@ -0,0 +1,112 @@ +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define I2C_BIAS 0x6a +#define I2C_BIAS_HOSTID 0 + +#define I2C_BIAS_DREG_1P6 0 +#define I2C_BIAS_DREG_1P6_MSB 3 +#define I2C_BIAS_DREG_1P6_LSB 0 + +#define I2C_BIAS_DREG_0P8 0 +#define I2C_BIAS_DREG_0P8_MSB 7 +#define I2C_BIAS_DREG_0P8_LSB 4 + +#define I2C_BIAS_DREG_1P1_PVT 1 +#define I2C_BIAS_DREG_1P1_PVT_MSB 3 +#define I2C_BIAS_DREG_1P1_PVT_LSB 0 + +#define I2C_BIAS_DREG_1P2 1 +#define I2C_BIAS_DREG_1P2_MSB 7 +#define I2C_BIAS_DREG_1P2_LSB 4 + +#define I2C_BIAS_ENT_CPREG 2 +#define I2C_BIAS_ENT_CPREG_MSB 0 +#define I2C_BIAS_ENT_CPREG_LSB 0 + +#define I2C_BIAS_ENT_CGM 2 +#define I2C_BIAS_ENT_CGM_MSB 1 +#define I2C_BIAS_ENT_CGM_LSB 1 + +#define I2C_BIAS_CGM_BIAS 2 +#define I2C_BIAS_CGM_BIAS_MSB 3 +#define I2C_BIAS_CGM_BIAS_LSB 2 + +#define I2C_BIAS_DREF_IGM 2 +#define I2C_BIAS_DREF_IGM_MSB 4 +#define I2C_BIAS_DREF_IGM_LSB 4 + +#define I2C_BIAS_RC_DVREF 2 +#define I2C_BIAS_RC_DVREF_MSB 6 +#define I2C_BIAS_RC_DVREF_LSB 5 + +#define I2C_BIAS_FORCE_DISABLE_BIAS_SLEEP 2 +#define I2C_BIAS_FORCE_DISABLE_BIAS_SLEEP_MSB 7 +#define I2C_BIAS_FORCE_DISABLE_BIAS_SLEEP_LSB 7 + +#define I2C_BIAS_RC_ENX 3 +#define I2C_BIAS_RC_ENX_MSB 0 +#define I2C_BIAS_RC_ENX_LSB 0 + +#define I2C_BIAS_RC_START 3 +#define I2C_BIAS_RC_START_MSB 1 +#define I2C_BIAS_RC_START_LSB 1 + +#define I2C_BIAS_RC_DCAP_EXT 3 +#define I2C_BIAS_RC_DCAP_EXT_MSB 7 +#define I2C_BIAS_RC_DCAP_EXT_LSB 2 + +#define I2C_BIAS_XPD_RC 4 +#define I2C_BIAS_XPD_RC_MSB 0 +#define I2C_BIAS_XPD_RC_LSB 0 + +#define I2C_BIAS_ENT_CONSTI 4 +#define I2C_BIAS_ENT_CONSTI_MSB 1 +#define I2C_BIAS_ENT_CONSTI_LSB 1 + +#define I2C_BIAS_XPD_ICX 4 +#define I2C_BIAS_XPD_ICX_MSB 2 +#define I2C_BIAS_XPD_ICX_LSB 2 + +#define I2C_BIAS_RC_RSTB 4 +#define I2C_BIAS_RC_RSTB_MSB 3 +#define I2C_BIAS_RC_RSTB_LSB 3 + +#define I2C_BIAS_RC_DIV 4 +#define I2C_BIAS_RC_DIV_MSB 7 +#define I2C_BIAS_RC_DIV_LSB 4 + +#define I2C_BIAS_RC_CAP 5 +#define I2C_BIAS_RC_CAP_MSB 5 +#define I2C_BIAS_RC_CAP_LSB 0 + +#define I2C_BIAS_RC_UD 5 +#define I2C_BIAS_RC_UD_MSB 6 +#define I2C_BIAS_RC_UD_LSB 6 + +#define I2C_BIAS_RC_LOCKB 5 +#define I2C_BIAS_RC_LOCKB_MSB 7 +#define I2C_BIAS_RC_LOCKB_LSB 7 + +#define I2C_BIAS_RC_CHG_COUNT 6 +#define I2C_BIAS_RC_CHG_COUNT_MSB 4 +#define I2C_BIAS_RC_CHG_COUNT_LSB 0 + +#define I2C_BIAS_XPD_CPREG 7 +#define I2C_BIAS_XPD_CPREG_MSB 0 +#define I2C_BIAS_XPD_CPREG_LSB 0 + +#define I2C_BIAS_XPD_CGM 7 +#define I2C_BIAS_XPD_CGM_MSB 1 +#define I2C_BIAS_XPD_CGM_LSB 1 + +#define I2C_BIAS_DTEST 7 +#define I2C_BIAS_DTEST_MSB 3 +#define I2C_BIAS_DTEST_LSB 2 + +#define I2C_BIAS_DRES12K 7 +#define I2C_BIAS_DRES12K_MSB 7 +#define I2C_BIAS_DRES12K_LSB 4 diff --git a/components/soc/esp32h2/i2c_pmu.h b/components/soc/esp32h2/i2c_pmu.h new file mode 100644 index 0000000000..de1e7d6aea --- /dev/null +++ b/components/soc/esp32h2/i2c_pmu.h @@ -0,0 +1,280 @@ +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define I2C_PMU 0x6d +#define I2C_PMU_HOSTID 0 + +#define I2C_PMU_THRES_HIGH_7_0 0 +#define I2C_PMU_THRES_HIGH_7_0_MSB 7 +#define I2C_PMU_THRES_HIGH_7_0_LSB 0 + +#define I2C_PMU_THRES_LOW_7_0 1 +#define I2C_PMU_THRES_LOW_7_0_MSB 7 +#define I2C_PMU_THRES_LOW_7_0_LSB 0 + +#define I2C_PMU_THRES_HIGH_11_8 2 +#define I2C_PMU_THRES_HIGH_11_8_MSB 3 +#define I2C_PMU_THRES_HIGH_11_8_LSB 0 + +#define I2C_PMU_THRES_LOW_11_8 2 +#define I2C_PMU_THRES_LOW_11_8_MSB 7 +#define I2C_PMU_THRES_LOW_11_8_LSB 4 + +#define I2C_PMU_PVT_DELAY_INIT 3 +#define I2C_PMU_PVT_DELAY_INIT_MSB 7 +#define I2C_PMU_PVT_DELAY_INIT_LSB 0 + +#define I2C_PMU_PVT_DELAY_COUNT 4 +#define I2C_PMU_PVT_DELAY_COUNT_MSB 5 +#define I2C_PMU_PVT_DELAY_COUNT_LSB 0 + +#define I2C_PMU_OR_EN_CONT_CAL 4 +#define I2C_PMU_OR_EN_CONT_CAL_MSB 7 +#define I2C_PMU_OR_EN_CONT_CAL_LSB 7 + +#define I2C_PMU_I2C_RTC_DREG 5 +#define I2C_PMU_I2C_RTC_DREG_MSB 4 +#define I2C_PMU_I2C_RTC_DREG_LSB 0 + +#define I2C_PMU_I2C_DIG_DREG 6 +#define I2C_PMU_I2C_DIG_DREG_MSB 4 +#define I2C_PMU_I2C_DIG_DREG_LSB 0 + +#define I2C_PMU_I2C_RTC_DREG_SLP 7 +#define I2C_PMU_I2C_RTC_DREG_SLP_MSB 3 +#define I2C_PMU_I2C_RTC_DREG_SLP_LSB 0 + +#define I2C_PMU_I2C_DIG_DREG_SLP 7 +#define I2C_PMU_I2C_DIG_DREG_SLP_MSB 7 +#define I2C_PMU_I2C_DIG_DREG_SLP_LSB 4 + +#define I2C_PMU_EN_I2C_RTC_DREG 10 +#define I2C_PMU_EN_I2C_RTC_DREG_MSB 0 +#define I2C_PMU_EN_I2C_RTC_DREG_LSB 0 + +#define I2C_PMU_EN_I2C_DIG_DREG 10 +#define I2C_PMU_EN_I2C_DIG_DREG_MSB 1 +#define I2C_PMU_EN_I2C_DIG_DREG_LSB 1 + +#define I2C_PMU_EN_I2C_RTC_DREG_SLP 10 +#define I2C_PMU_EN_I2C_RTC_DREG_SLP_MSB 2 +#define I2C_PMU_EN_I2C_RTC_DREG_SLP_LSB 2 + +#define I2C_PMU_EN_I2C_DIG_DREG_SLP 10 +#define I2C_PMU_EN_I2C_DIG_DREG_SLP_MSB 3 +#define I2C_PMU_EN_I2C_DIG_DREG_SLP_LSB 3 + +#define I2C_PMU_ENX_RTC_DREG 11 +#define I2C_PMU_ENX_RTC_DREG_MSB 0 +#define I2C_PMU_ENX_RTC_DREG_LSB 0 + +#define I2C_PMU_ENX_DIG_DREG 11 +#define I2C_PMU_ENX_DIG_DREG_MSB 1 +#define I2C_PMU_ENX_DIG_DREG_LSB 1 + +#define I2C_PMU_OR_XPD_RTC_SLAVE_3P3 11 +#define I2C_PMU_OR_XPD_RTC_SLAVE_3P3_MSB 2 +#define I2C_PMU_OR_XPD_RTC_SLAVE_3P3_LSB 2 + +#define I2C_PMU_OR_XPD_RTC_REG 11 +#define I2C_PMU_OR_XPD_RTC_REG_MSB 4 +#define I2C_PMU_OR_XPD_RTC_REG_LSB 4 + +#define I2C_PMU_OR_XPD_DIG_REG 11 +#define I2C_PMU_OR_XPD_DIG_REG_MSB 5 +#define I2C_PMU_OR_XPD_DIG_REG_LSB 5 + +#define I2C_PMU_OR_PD_RTC_REG_SLP 11 +#define I2C_PMU_OR_PD_RTC_REG_SLP_MSB 6 +#define I2C_PMU_OR_PD_RTC_REG_SLP_LSB 6 + +#define I2C_PMU_OR_PD_DIG_REG_SLP 11 +#define I2C_PMU_OR_PD_DIG_REG_SLP_MSB 7 +#define I2C_PMU_OR_PD_DIG_REG_SLP_LSB 7 + +#define I2C_PMU_INT_DREG 12 +#define I2C_PMU_INT_DREG_MSB 4 +#define I2C_PMU_INT_DREG_LSB 0 + +#define I2C_PMU_O_UDF 12 +#define I2C_PMU_O_UDF_MSB 5 +#define I2C_PMU_O_UDF_LSB 5 + +#define I2C_PMU_O_OVF 12 +#define I2C_PMU_O_OVF_MSB 6 +#define I2C_PMU_O_OVF_LSB 6 + +#define I2C_PMU_O_UPDATE 12 +#define I2C_PMU_O_UPDATE_MSB 7 +#define I2C_PMU_O_UPDATE_LSB 7 + +#define I2C_PMU_PVT_COUNT_7_0 13 +#define I2C_PMU_PVT_COUNT_7_0_MSB 7 +#define I2C_PMU_PVT_COUNT_7_0_LSB 0 + +#define I2C_PMU_PVT_COUNT_11_8 14 +#define I2C_PMU_PVT_COUNT_11_8_MSB 3 +#define I2C_PMU_PVT_COUNT_11_8_LSB 0 + +#define I2C_PMU_IC_VGOOD_LVDET 14 +#define I2C_PMU_IC_VGOOD_LVDET_MSB 4 +#define I2C_PMU_IC_VGOOD_LVDET_LSB 4 + +#define I2C_PMU_IC_POWER_GOOD_DCDC 14 +#define I2C_PMU_IC_POWER_GOOD_DCDC_MSB 5 +#define I2C_PMU_IC_POWER_GOOD_DCDC_LSB 5 + +#define I2C_PMU_IC_VGOOD_DIGDET 14 +#define I2C_PMU_IC_VGOOD_DIGDET_MSB 6 +#define I2C_PMU_IC_VGOOD_DIGDET_LSB 6 + +#define I2C_PMU_OR_XPD_DCDC 15 +#define I2C_PMU_OR_XPD_DCDC_MSB 0 +#define I2C_PMU_OR_XPD_DCDC_LSB 0 + +#define I2C_PMU_OR_DISALBE_DEEP_SLEEP_DCDC 15 +#define I2C_PMU_OR_DISALBE_DEEP_SLEEP_DCDC_MSB 1 +#define I2C_PMU_OR_DISALBE_DEEP_SLEEP_DCDC_LSB 1 + +#define I2C_PMU_OR_DISALBE_LIGHT_SLEEP_DCDC 15 +#define I2C_PMU_OR_DISALBE_LIGHT_SLEEP_DCDC_MSB 2 +#define I2C_PMU_OR_DISALBE_LIGHT_SLEEP_DCDC_LSB 2 + +#define I2C_PMU_OR_ENALBE_TRX_MODE_DCDC 15 +#define I2C_PMU_OR_ENALBE_TRX_MODE_DCDC_MSB 3 +#define I2C_PMU_OR_ENALBE_TRX_MODE_DCDC_LSB 3 + +#define I2C_PMU_OR_ENX_REG_DCDC 15 +#define I2C_PMU_OR_ENX_REG_DCDC_MSB 4 +#define I2C_PMU_OR_ENX_REG_DCDC_LSB 4 + +#define I2C_PMU_OR_UNLOCK_DCDC 15 +#define I2C_PMU_OR_UNLOCK_DCDC_MSB 5 +#define I2C_PMU_OR_UNLOCK_DCDC_LSB 5 + +#define I2C_PMU_OR_FORCE_LOCK_DCDC 15 +#define I2C_PMU_OR_FORCE_LOCK_DCDC_MSB 6 +#define I2C_PMU_OR_FORCE_LOCK_DCDC_LSB 6 + +#define I2C_PMU_OR_ENB_SLOW_CLK 15 +#define I2C_PMU_OR_ENB_SLOW_CLK_MSB 7 +#define I2C_PMU_OR_ENB_SLOW_CLK_LSB 7 + +#define I2C_PMU_OC_SCK_DCAP 16 +#define I2C_PMU_OC_SCK_DCAP_MSB 7 +#define I2C_PMU_OC_SCK_DCAP_LSB 0 + +#define I2C_PMU_OC_XPD_LVDET 17 +#define I2C_PMU_OC_XPD_LVDET_MSB 0 +#define I2C_PMU_OC_XPD_LVDET_LSB 0 + +#define I2C_PMU_OC_MODE_LVDET 17 +#define I2C_PMU_OC_MODE_LVDET_MSB 1 +#define I2C_PMU_OC_MODE_LVDET_LSB 1 + +#define I2C_PMU_OR_XPD_TRX 17 +#define I2C_PMU_OR_XPD_TRX_MSB 2 +#define I2C_PMU_OR_XPD_TRX_LSB 2 + +#define I2C_PMU_OR_EN_RESET_CHIP 17 +#define I2C_PMU_OR_EN_RESET_CHIP_MSB 3 +#define I2C_PMU_OR_EN_RESET_CHIP_LSB 3 + +#define I2C_PMU_OC_DREF_LVDET 17 +#define I2C_PMU_OC_DREF_LVDET_MSB 6 +#define I2C_PMU_OC_DREF_LVDET_LSB 4 + +#define I2C_PMU_OR_FORCE_XPD_REG_SLAVE 17 +#define I2C_PMU_OR_FORCE_XPD_REG_SLAVE_MSB 7 +#define I2C_PMU_OR_FORCE_XPD_REG_SLAVE_LSB 7 + +#define I2C_PMU_DTEST 18 +#define I2C_PMU_DTEST_MSB 1 +#define I2C_PMU_DTEST_LSB 0 + +#define I2C_PMU_ENT_BIAS 18 +#define I2C_PMU_ENT_BIAS_MSB 2 +#define I2C_PMU_ENT_BIAS_LSB 2 + +#define I2C_PMU_ENT_VDD 18 +#define I2C_PMU_ENT_VDD_MSB 5 +#define I2C_PMU_ENT_VDD_LSB 3 + +#define I2C_PMU_EN_DMUX 18 +#define I2C_PMU_EN_DMUX_MSB 6 +#define I2C_PMU_EN_DMUX_LSB 6 + +#define I2C_PMU_WD_DISABLE 18 +#define I2C_PMU_WD_DISABLE_MSB 7 +#define I2C_PMU_WD_DISABLE_LSB 7 + +#define I2C_PMU_DTEST_DCDC 19 +#define I2C_PMU_DTEST_DCDC_MSB 0 +#define I2C_PMU_DTEST_DCDC_LSB 0 + +#define I2C_PMU_TESTEN_DCDC 19 +#define I2C_PMU_TESTEN_DCDC_MSB 1 +#define I2C_PMU_TESTEN_DCDC_LSB 1 + +#define I2C_PMU_ADD_DCDC 19 +#define I2C_PMU_ADD_DCDC_MSB 6 +#define I2C_PMU_ADD_DCDC_LSB 4 + +#define I2C_PMU_OR_POCPENB_DCDC 20 +#define I2C_PMU_OR_POCPENB_DCDC_MSB 0 +#define I2C_PMU_OR_POCPENB_DCDC_LSB 0 + +#define I2C_PMU_OR_SSTIME_DCDC 20 +#define I2C_PMU_OR_SSTIME_DCDC_MSB 1 +#define I2C_PMU_OR_SSTIME_DCDC_LSB 1 + +#define I2C_PMU_OR_CCM_DCDC 20 +#define I2C_PMU_OR_CCM_DCDC_MSB 2 +#define I2C_PMU_OR_CCM_DCDC_LSB 2 + +#define I2C_PMU_OR_VSET_LOW_DCDC 20 +#define I2C_PMU_OR_VSET_LOW_DCDC_MSB 7 +#define I2C_PMU_OR_VSET_LOW_DCDC_LSB 3 + +#define I2C_PMU_OR_FSW_DCDC 21 +#define I2C_PMU_OR_FSW_DCDC_MSB 2 +#define I2C_PMU_OR_FSW_DCDC_LSB 0 + +#define I2C_PMU_OR_DCMLEVEL_DCDC 21 +#define I2C_PMU_OR_DCMLEVEL_DCDC_MSB 4 +#define I2C_PMU_OR_DCMLEVEL_DCDC_LSB 3 + +#define I2C_PMU_OR_DCM2ENB_DCDC 21 +#define I2C_PMU_OR_DCM2ENB_DCDC_MSB 5 +#define I2C_PMU_OR_DCM2ENB_DCDC_LSB 5 + +#define I2C_PMU_OR_RAMP_DCDC 21 +#define I2C_PMU_OR_RAMP_DCDC_MSB 6 +#define I2C_PMU_OR_RAMP_DCDC_LSB 6 + +#define I2C_PMU_OR_RAMPLEVEL_DCDC 21 +#define I2C_PMU_OR_RAMPLEVEL_DCDC_MSB 7 +#define I2C_PMU_OR_RAMPLEVEL_DCDC_LSB 7 + +#define I2C_PMU_OR_VSET_HIGH_DCDC 22 +#define I2C_PMU_OR_VSET_HIGH_DCDC_MSB 4 +#define I2C_PMU_OR_VSET_HIGH_DCDC_LSB 0 + +#define I2C_PMU_OC_DEL_SSEND 22 +#define I2C_PMU_OC_DEL_SSEND_MSB 7 +#define I2C_PMU_OC_DEL_SSEND_LSB 5 + +#define I2C_PMU_OC_XPD_DIGDET 23 +#define I2C_PMU_OC_XPD_DIGDET_MSB 0 +#define I2C_PMU_OC_XPD_DIGDET_LSB 0 + +#define I2C_PMU_OC_MODE_DIGDET 23 +#define I2C_PMU_OC_MODE_DIGDET_MSB 1 +#define I2C_PMU_OC_MODE_DIGDET_LSB 1 + +#define I2C_PMU_OC_DREF_DIGDET 23 +#define I2C_PMU_OC_DREF_DIGDET_MSB 6 +#define I2C_PMU_OC_DREF_DIGDET_LSB 4 diff --git a/components/soc/esp32h2/i2c_ulp.h b/components/soc/esp32h2/i2c_ulp.h new file mode 100644 index 0000000000..5751f01936 --- /dev/null +++ b/components/soc/esp32h2/i2c_ulp.h @@ -0,0 +1,108 @@ +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define I2C_ULP 0x61 +#define I2C_ULP_HOSTID 0 + +#define I2C_ULP_IR_RESETB 0 +#define I2C_ULP_IR_RESETB_MSB 0 +#define I2C_ULP_IR_RESETB_LSB 0 + +#define I2C_ULP_XPD_REG_SLP 0 +#define I2C_ULP_XPD_REG_SLP_MSB 1 +#define I2C_ULP_XPD_REG_SLP_LSB 1 + +#define I2C_ULP_DBIAS_SLP 0 +#define I2C_ULP_DBIAS_SLP_MSB 7 +#define I2C_ULP_DBIAS_SLP_LSB 4 + +#define I2C_ULP_IR_FORCE_XPD_BIAS_BUF 1 +#define I2C_ULP_IR_FORCE_XPD_BIAS_BUF_MSB 1 +#define I2C_ULP_IR_FORCE_XPD_BIAS_BUF_LSB 1 + +#define I2C_ULP_IR_FORCE_XPD_IPH 1 +#define I2C_ULP_IR_FORCE_XPD_IPH_MSB 2 +#define I2C_ULP_IR_FORCE_XPD_IPH_LSB 2 + +#define I2C_ULP_IR_FORCE_XPD_VGATE_BUF 1 +#define I2C_ULP_IR_FORCE_XPD_VGATE_BUF_MSB 3 +#define I2C_ULP_IR_FORCE_XPD_VGATE_BUF_LSB 3 + +#define I2C_ULP_IR_FORCE_DISABLE_BIAS_SLEEP 1 +#define I2C_ULP_IR_FORCE_DISABLE_BIAS_SLEEP_MSB 4 +#define I2C_ULP_IR_FORCE_DISABLE_BIAS_SLEEP_LSB 4 + +#define I2C_ULP_IR_ZOS_XPD 2 +#define I2C_ULP_IR_ZOS_XPD_MSB 0 +#define I2C_ULP_IR_ZOS_XPD_LSB 0 + +#define I2C_ULP_IR_ZOS_RSTB 2 +#define I2C_ULP_IR_ZOS_RSTB_MSB 1 +#define I2C_ULP_IR_ZOS_RSTB_LSB 1 + +#define I2C_ULP_IR_ZOS_RESTART 2 +#define I2C_ULP_IR_ZOS_RESTART_MSB 2 +#define I2C_ULP_IR_ZOS_RESTART_LSB 2 + +#define I2C_ULP_DTEST 3 +#define I2C_ULP_DTEST_MSB 1 +#define I2C_ULP_DTEST_LSB 0 + +#define I2C_ULP_ENT_BG 3 +#define I2C_ULP_ENT_BG_MSB 2 +#define I2C_ULP_ENT_BG_LSB 2 + +#define I2C_ULP_MODE_LVDET 3 +#define I2C_ULP_MODE_LVDET_MSB 3 +#define I2C_ULP_MODE_LVDET_LSB 3 + +#define I2C_ULP_DREF_LVDET 3 +#define I2C_ULP_DREF_LVDET_MSB 6 +#define I2C_ULP_DREF_LVDET_LSB 4 + +#define I2C_ULP_XPD_LVDET 3 +#define I2C_ULP_XPD_LVDET_MSB 7 +#define I2C_ULP_XPD_LVDET_LSB 7 + +#define I2C_ULP_INT_XPD_XTAL_CK_DIG_REG 4 +#define I2C_ULP_INT_XPD_XTAL_CK_DIG_REG_MSB 0 +#define I2C_ULP_INT_XPD_XTAL_CK_DIG_REG_LSB 0 + +#define I2C_ULP_INT_XPD_XTAL_BUF 4 +#define I2C_ULP_INT_XPD_XTAL_BUF_MSB 1 +#define I2C_ULP_INT_XPD_XTAL_BUF_LSB 1 + +#define I2C_ULP_INT_XPD_RC_CK 4 +#define I2C_ULP_INT_XPD_RC_CK_MSB 2 +#define I2C_ULP_INT_XPD_RC_CK_LSB 2 + +#define I2C_ULP_XTAL_DPHASE 4 +#define I2C_ULP_XTAL_DPHASE_MSB 3 +#define I2C_ULP_XTAL_DPHASE_LSB 3 + +#define I2C_ULP_INT_XPD_XTAL_LIN_REG 4 +#define I2C_ULP_INT_XPD_XTAL_LIN_REG_MSB 4 +#define I2C_ULP_INT_XPD_XTAL_LIN_REG_LSB 4 + +#define I2C_ULP_XTAL_RESTART_DC_CAL 4 +#define I2C_ULP_XTAL_RESTART_DC_CAL_MSB 5 +#define I2C_ULP_XTAL_RESTART_DC_CAL_LSB 5 + +#define I2C_ULP_XTAL_DAC 5 +#define I2C_ULP_XTAL_DAC_MSB 3 +#define I2C_ULP_XTAL_DAC_LSB 0 + +#define I2C_ULP_XTAL_DBLEED 6 +#define I2C_ULP_XTAL_DBLEED_MSB 4 +#define I2C_ULP_XTAL_DBLEED_LSB 0 + +#define I2C_ULP_XTAL_CAL_DONE 6 +#define I2C_ULP_XTAL_CAL_DONE_MSB 5 +#define I2C_ULP_XTAL_CAL_DONE_LSB 5 + +#define I2C_ULP_ZOS_DONE 6 +#define I2C_ULP_ZOS_DONE_MSB 6 +#define I2C_ULP_ZOS_DONE_LSB 6 diff --git a/components/soc/esp32h2/include/soc/apb_ctrl_reg.h b/components/soc/esp32h2/include/soc/apb_ctrl_reg.h deleted file mode 100644 index 584be8ecfb..0000000000 --- a/components/soc/esp32h2/include/soc/apb_ctrl_reg.h +++ /dev/null @@ -1,486 +0,0 @@ -// 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. -#ifndef _SOC_APB_CTRL_REG_H_ -#define _SOC_APB_CTRL_REG_H_ - - -#ifdef __cplusplus -extern "C" { -#endif -#include "soc.h" -#define APB_CTRL_WIFI_BB_CFG_REG (DR_REG_APB_CTRL_BASE + 0x00C) -/* APB_CTRL_WIFI_BB_CFG : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define APB_CTRL_WIFI_BB_CFG 0xFFFFFFFF -#define APB_CTRL_WIFI_BB_CFG_M ((APB_CTRL_WIFI_BB_CFG_V)<<(APB_CTRL_WIFI_BB_CFG_S)) -#define APB_CTRL_WIFI_BB_CFG_V 0xFFFFFFFF -#define APB_CTRL_WIFI_BB_CFG_S 0 - -#define APB_CTRL_WIFI_BB_CFG_2_REG (DR_REG_APB_CTRL_BASE + 0x010) -/* APB_CTRL_WIFI_BB_CFG_2 : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define APB_CTRL_WIFI_BB_CFG_2 0xFFFFFFFF -#define APB_CTRL_WIFI_BB_CFG_2_M ((APB_CTRL_WIFI_BB_CFG_2_V)<<(APB_CTRL_WIFI_BB_CFG_2_S)) -#define APB_CTRL_WIFI_BB_CFG_2_V 0xFFFFFFFF -#define APB_CTRL_WIFI_BB_CFG_2_S 0 - -#define APB_CTRL_HOST_INF_SEL_REG (DR_REG_APB_CTRL_BASE + 0x01C) -/* APB_CTRL_PERI_IO_SWAP : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ -/*description: */ -#define APB_CTRL_PERI_IO_SWAP 0x000000FF -#define APB_CTRL_PERI_IO_SWAP_M ((APB_CTRL_PERI_IO_SWAP_V)<<(APB_CTRL_PERI_IO_SWAP_S)) -#define APB_CTRL_PERI_IO_SWAP_V 0xFF -#define APB_CTRL_PERI_IO_SWAP_S 0 - -#define APB_CTRL_EXT_MEM_PMS_LOCK_REG (DR_REG_APB_CTRL_BASE + 0x020) -/* APB_CTRL_EXT_MEM_PMS_LOCK : R/W ;bitpos:[0] ;default: 1'b0 ; */ -/*description: */ -#define APB_CTRL_EXT_MEM_PMS_LOCK (BIT(0)) -#define APB_CTRL_EXT_MEM_PMS_LOCK_M (BIT(0)) -#define APB_CTRL_EXT_MEM_PMS_LOCK_V 0x1 -#define APB_CTRL_EXT_MEM_PMS_LOCK_S 0 - -#define APB_CTRL_FLASH_ACE0_ATTR_REG (DR_REG_APB_CTRL_BASE + 0x028) -/* APB_CTRL_FLASH_ACE0_ATTR : R/W ;bitpos:[1:0] ;default: 2'h3 ; */ -/*description: */ -#define APB_CTRL_FLASH_ACE0_ATTR 0x00000003 -#define APB_CTRL_FLASH_ACE0_ATTR_M ((APB_CTRL_FLASH_ACE0_ATTR_V)<<(APB_CTRL_FLASH_ACE0_ATTR_S)) -#define APB_CTRL_FLASH_ACE0_ATTR_V 0x3 -#define APB_CTRL_FLASH_ACE0_ATTR_S 0 - -#define APB_CTRL_FLASH_ACE1_ATTR_REG (DR_REG_APB_CTRL_BASE + 0x02C) -/* APB_CTRL_FLASH_ACE1_ATTR : R/W ;bitpos:[1:0] ;default: 2'h3 ; */ -/*description: */ -#define APB_CTRL_FLASH_ACE1_ATTR 0x00000003 -#define APB_CTRL_FLASH_ACE1_ATTR_M ((APB_CTRL_FLASH_ACE1_ATTR_V)<<(APB_CTRL_FLASH_ACE1_ATTR_S)) -#define APB_CTRL_FLASH_ACE1_ATTR_V 0x3 -#define APB_CTRL_FLASH_ACE1_ATTR_S 0 - -#define APB_CTRL_FLASH_ACE2_ATTR_REG (DR_REG_APB_CTRL_BASE + 0x030) -/* APB_CTRL_FLASH_ACE2_ATTR : R/W ;bitpos:[1:0] ;default: 2'h3 ; */ -/*description: */ -#define APB_CTRL_FLASH_ACE2_ATTR 0x00000003 -#define APB_CTRL_FLASH_ACE2_ATTR_M ((APB_CTRL_FLASH_ACE2_ATTR_V)<<(APB_CTRL_FLASH_ACE2_ATTR_S)) -#define APB_CTRL_FLASH_ACE2_ATTR_V 0x3 -#define APB_CTRL_FLASH_ACE2_ATTR_S 0 - -#define APB_CTRL_FLASH_ACE3_ATTR_REG (DR_REG_APB_CTRL_BASE + 0x034) -/* APB_CTRL_FLASH_ACE3_ATTR : R/W ;bitpos:[1:0] ;default: 2'h3 ; */ -/*description: */ -#define APB_CTRL_FLASH_ACE3_ATTR 0x00000003 -#define APB_CTRL_FLASH_ACE3_ATTR_M ((APB_CTRL_FLASH_ACE3_ATTR_V)<<(APB_CTRL_FLASH_ACE3_ATTR_S)) -#define APB_CTRL_FLASH_ACE3_ATTR_V 0x3 -#define APB_CTRL_FLASH_ACE3_ATTR_S 0 - -#define APB_CTRL_FLASH_ACE0_ADDR_REG (DR_REG_APB_CTRL_BASE + 0x038) -/* APB_CTRL_FLASH_ACE0_ADDR_S : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define APB_CTRL_FLASH_ACE0_ADDR_S 0xFFFFFFFF -#define APB_CTRL_FLASH_ACE0_ADDR_S_M ((APB_CTRL_FLASH_ACE0_ADDR_S_V)<<(APB_CTRL_FLASH_ACE0_ADDR_S_S)) -#define APB_CTRL_FLASH_ACE0_ADDR_S_V 0xFFFFFFFF -#define APB_CTRL_FLASH_ACE0_ADDR_S_S 0 - -#define APB_CTRL_FLASH_ACE1_ADDR_REG (DR_REG_APB_CTRL_BASE + 0x03C) -/* APB_CTRL_FLASH_ACE1_ADDR_S : R/W ;bitpos:[31:0] ;default: 32'h400000 ; */ -/*description: */ -#define APB_CTRL_FLASH_ACE1_ADDR_S 0xFFFFFFFF -#define APB_CTRL_FLASH_ACE1_ADDR_S_M ((APB_CTRL_FLASH_ACE1_ADDR_S_V)<<(APB_CTRL_FLASH_ACE1_ADDR_S_S)) -#define APB_CTRL_FLASH_ACE1_ADDR_S_V 0xFFFFFFFF -#define APB_CTRL_FLASH_ACE1_ADDR_S_S 0 - -#define APB_CTRL_FLASH_ACE2_ADDR_REG (DR_REG_APB_CTRL_BASE + 0x040) -/* APB_CTRL_FLASH_ACE2_ADDR_S : R/W ;bitpos:[31:0] ;default: 32'h800000 ; */ -/*description: */ -#define APB_CTRL_FLASH_ACE2_ADDR_S 0xFFFFFFFF -#define APB_CTRL_FLASH_ACE2_ADDR_S_M ((APB_CTRL_FLASH_ACE2_ADDR_S_V)<<(APB_CTRL_FLASH_ACE2_ADDR_S_S)) -#define APB_CTRL_FLASH_ACE2_ADDR_S_V 0xFFFFFFFF -#define APB_CTRL_FLASH_ACE2_ADDR_S_S 0 - -#define APB_CTRL_FLASH_ACE3_ADDR_REG (DR_REG_APB_CTRL_BASE + 0x044) -/* APB_CTRL_FLASH_ACE3_ADDR_S : R/W ;bitpos:[31:0] ;default: 32'hC00000 ; */ -/*description: */ -#define APB_CTRL_FLASH_ACE3_ADDR_S 0xFFFFFFFF -#define APB_CTRL_FLASH_ACE3_ADDR_S_M ((APB_CTRL_FLASH_ACE3_ADDR_S_V)<<(APB_CTRL_FLASH_ACE3_ADDR_S_S)) -#define APB_CTRL_FLASH_ACE3_ADDR_S_V 0xFFFFFFFF -#define APB_CTRL_FLASH_ACE3_ADDR_S_S 0 - -#define APB_CTRL_FLASH_ACE0_SIZE_REG (DR_REG_APB_CTRL_BASE + 0x048) -/* APB_CTRL_FLASH_ACE0_SIZE : R/W ;bitpos:[12:0] ;default: 13'h400 ; */ -/*description: */ -#define APB_CTRL_FLASH_ACE0_SIZE 0x00001FFF -#define APB_CTRL_FLASH_ACE0_SIZE_M ((APB_CTRL_FLASH_ACE0_SIZE_V)<<(APB_CTRL_FLASH_ACE0_SIZE_S)) -#define APB_CTRL_FLASH_ACE0_SIZE_V 0x1FFF -#define APB_CTRL_FLASH_ACE0_SIZE_S 0 - -#define APB_CTRL_FLASH_ACE1_SIZE_REG (DR_REG_APB_CTRL_BASE + 0x04C) -/* APB_CTRL_FLASH_ACE1_SIZE : R/W ;bitpos:[12:0] ;default: 13'h400 ; */ -/*description: */ -#define APB_CTRL_FLASH_ACE1_SIZE 0x00001FFF -#define APB_CTRL_FLASH_ACE1_SIZE_M ((APB_CTRL_FLASH_ACE1_SIZE_V)<<(APB_CTRL_FLASH_ACE1_SIZE_S)) -#define APB_CTRL_FLASH_ACE1_SIZE_V 0x1FFF -#define APB_CTRL_FLASH_ACE1_SIZE_S 0 - -#define APB_CTRL_FLASH_ACE2_SIZE_REG (DR_REG_APB_CTRL_BASE + 0x050) -/* APB_CTRL_FLASH_ACE2_SIZE : R/W ;bitpos:[12:0] ;default: 13'h400 ; */ -/*description: */ -#define APB_CTRL_FLASH_ACE2_SIZE 0x00001FFF -#define APB_CTRL_FLASH_ACE2_SIZE_M ((APB_CTRL_FLASH_ACE2_SIZE_V)<<(APB_CTRL_FLASH_ACE2_SIZE_S)) -#define APB_CTRL_FLASH_ACE2_SIZE_V 0x1FFF -#define APB_CTRL_FLASH_ACE2_SIZE_S 0 - -#define APB_CTRL_FLASH_ACE3_SIZE_REG (DR_REG_APB_CTRL_BASE + 0x054) -/* APB_CTRL_FLASH_ACE3_SIZE : R/W ;bitpos:[12:0] ;default: 13'h400 ; */ -/*description: */ -#define APB_CTRL_FLASH_ACE3_SIZE 0x00001FFF -#define APB_CTRL_FLASH_ACE3_SIZE_M ((APB_CTRL_FLASH_ACE3_SIZE_V)<<(APB_CTRL_FLASH_ACE3_SIZE_S)) -#define APB_CTRL_FLASH_ACE3_SIZE_V 0x1FFF -#define APB_CTRL_FLASH_ACE3_SIZE_S 0 - -#define APB_CTRL_SPI_MEM_PMS_CTRL_REG (DR_REG_APB_CTRL_BASE + 0x088) -/* APB_CTRL_SPI_MEM_REJECT_CDE : RO ;bitpos:[6:2] ;default: 5'h0 ; */ -/*description: */ -#define APB_CTRL_SPI_MEM_REJECT_CDE 0x0000001F -#define APB_CTRL_SPI_MEM_REJECT_CDE_M ((APB_CTRL_SPI_MEM_REJECT_CDE_V)<<(APB_CTRL_SPI_MEM_REJECT_CDE_S)) -#define APB_CTRL_SPI_MEM_REJECT_CDE_V 0x1F -#define APB_CTRL_SPI_MEM_REJECT_CDE_S 2 -/* APB_CTRL_SPI_MEM_REJECT_CLR : WOD ;bitpos:[1] ;default: 1'b0 ; */ -/*description: */ -#define APB_CTRL_SPI_MEM_REJECT_CLR (BIT(1)) -#define APB_CTRL_SPI_MEM_REJECT_CLR_M (BIT(1)) -#define APB_CTRL_SPI_MEM_REJECT_CLR_V 0x1 -#define APB_CTRL_SPI_MEM_REJECT_CLR_S 1 -/* APB_CTRL_SPI_MEM_REJECT_INT : RO ;bitpos:[0] ;default: 1'b0 ; */ -/*description: */ -#define APB_CTRL_SPI_MEM_REJECT_INT (BIT(0)) -#define APB_CTRL_SPI_MEM_REJECT_INT_M (BIT(0)) -#define APB_CTRL_SPI_MEM_REJECT_INT_V 0x1 -#define APB_CTRL_SPI_MEM_REJECT_INT_S 0 - -#define APB_CTRL_SPI_MEM_REJECT_ADDR_REG (DR_REG_APB_CTRL_BASE + 0x08C) -/* APB_CTRL_SPI_MEM_REJECT_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define APB_CTRL_SPI_MEM_REJECT_ADDR 0xFFFFFFFF -#define APB_CTRL_SPI_MEM_REJECT_ADDR_M ((APB_CTRL_SPI_MEM_REJECT_ADDR_V)<<(APB_CTRL_SPI_MEM_REJECT_ADDR_S)) -#define APB_CTRL_SPI_MEM_REJECT_ADDR_V 0xFFFFFFFF -#define APB_CTRL_SPI_MEM_REJECT_ADDR_S 0 - -#define APB_CTRL_SDIO_CTRL_REG (DR_REG_APB_CTRL_BASE + 0x090) -/* APB_CTRL_SDIO_WIN_ACCESS_EN : R/W ;bitpos:[0] ;default: 1'h0 ; */ -/*description: */ -#define APB_CTRL_SDIO_WIN_ACCESS_EN (BIT(0)) -#define APB_CTRL_SDIO_WIN_ACCESS_EN_M (BIT(0)) -#define APB_CTRL_SDIO_WIN_ACCESS_EN_V 0x1 -#define APB_CTRL_SDIO_WIN_ACCESS_EN_S 0 - -#define APB_CTRL_REDCY_SIG0_REG (DR_REG_APB_CTRL_BASE + 0x094) -/* APB_CTRL_REDCY_ANDOR : RO ;bitpos:[31] ;default: 1'h0 ; */ -/*description: */ -#define APB_CTRL_REDCY_ANDOR (BIT(31)) -#define APB_CTRL_REDCY_ANDOR_M (BIT(31)) -#define APB_CTRL_REDCY_ANDOR_V 0x1 -#define APB_CTRL_REDCY_ANDOR_S 31 -/* APB_CTRL_REDCY_SIG0 : R/W ;bitpos:[30:0] ;default: 31'h0 ; */ -/*description: */ -#define APB_CTRL_REDCY_SIG0 0x7FFFFFFF -#define APB_CTRL_REDCY_SIG0_M ((APB_CTRL_REDCY_SIG0_V)<<(APB_CTRL_REDCY_SIG0_S)) -#define APB_CTRL_REDCY_SIG0_V 0x7FFFFFFF -#define APB_CTRL_REDCY_SIG0_S 0 - -#define APB_CTRL_REDCY_SIG1_REG (DR_REG_APB_CTRL_BASE + 0x098) -/* APB_CTRL_REDCY_NANDOR : RO ;bitpos:[31] ;default: 1'h0 ; */ -/*description: */ -#define APB_CTRL_REDCY_NANDOR (BIT(31)) -#define APB_CTRL_REDCY_NANDOR_M (BIT(31)) -#define APB_CTRL_REDCY_NANDOR_V 0x1 -#define APB_CTRL_REDCY_NANDOR_S 31 -/* APB_CTRL_REDCY_SIG1 : R/W ;bitpos:[30:0] ;default: 31'h0 ; */ -/*description: */ -#define APB_CTRL_REDCY_SIG1 0x7FFFFFFF -#define APB_CTRL_REDCY_SIG1_M ((APB_CTRL_REDCY_SIG1_V)<<(APB_CTRL_REDCY_SIG1_S)) -#define APB_CTRL_REDCY_SIG1_V 0x7FFFFFFF -#define APB_CTRL_REDCY_SIG1_S 0 - -#define APB_CTRL_FRONT_END_MEM_PD_REG (DR_REG_APB_CTRL_BASE + 0x09C) -/* APB_CTRL_DC_MEM_FORCE_PD : R/W ;bitpos:[5] ;default: 1'b0 ; */ -/*description: */ -#define APB_CTRL_DC_MEM_FORCE_PD (BIT(5)) -#define APB_CTRL_DC_MEM_FORCE_PD_M (BIT(5)) -#define APB_CTRL_DC_MEM_FORCE_PD_V 0x1 -#define APB_CTRL_DC_MEM_FORCE_PD_S 5 -/* APB_CTRL_DC_MEM_FORCE_PU : R/W ;bitpos:[4] ;default: 1'b1 ; */ -/*description: */ -#define APB_CTRL_DC_MEM_FORCE_PU (BIT(4)) -#define APB_CTRL_DC_MEM_FORCE_PU_M (BIT(4)) -#define APB_CTRL_DC_MEM_FORCE_PU_V 0x1 -#define APB_CTRL_DC_MEM_FORCE_PU_S 4 -/* APB_CTRL_PBUS_MEM_FORCE_PD : R/W ;bitpos:[3] ;default: 1'b0 ; */ -/*description: */ -#define APB_CTRL_PBUS_MEM_FORCE_PD (BIT(3)) -#define APB_CTRL_PBUS_MEM_FORCE_PD_M (BIT(3)) -#define APB_CTRL_PBUS_MEM_FORCE_PD_V 0x1 -#define APB_CTRL_PBUS_MEM_FORCE_PD_S 3 -/* APB_CTRL_PBUS_MEM_FORCE_PU : R/W ;bitpos:[2] ;default: 1'b1 ; */ -/*description: */ -#define APB_CTRL_PBUS_MEM_FORCE_PU (BIT(2)) -#define APB_CTRL_PBUS_MEM_FORCE_PU_M (BIT(2)) -#define APB_CTRL_PBUS_MEM_FORCE_PU_V 0x1 -#define APB_CTRL_PBUS_MEM_FORCE_PU_S 2 -/* APB_CTRL_AGC_MEM_FORCE_PD : R/W ;bitpos:[1] ;default: 1'b0 ; */ -/*description: */ -#define APB_CTRL_AGC_MEM_FORCE_PD (BIT(1)) -#define APB_CTRL_AGC_MEM_FORCE_PD_M (BIT(1)) -#define APB_CTRL_AGC_MEM_FORCE_PD_V 0x1 -#define APB_CTRL_AGC_MEM_FORCE_PD_S 1 -/* APB_CTRL_AGC_MEM_FORCE_PU : R/W ;bitpos:[0] ;default: 1'b1 ; */ -/*description: */ -#define APB_CTRL_AGC_MEM_FORCE_PU (BIT(0)) -#define APB_CTRL_AGC_MEM_FORCE_PU_M (BIT(0)) -#define APB_CTRL_AGC_MEM_FORCE_PU_V 0x1 -#define APB_CTRL_AGC_MEM_FORCE_PU_S 0 - -#define APB_CTRL_RETENTION_CTRL_REG (DR_REG_APB_CTRL_BASE + 0x0A0) -/* APB_CTRL_NOBYPASS_CPU_ISO_RST : R/W ;bitpos:[27] ;default: 1'b0 ; */ -/*description: */ -#define APB_CTRL_NOBYPASS_CPU_ISO_RST (BIT(27)) -#define APB_CTRL_NOBYPASS_CPU_ISO_RST_M (BIT(27)) -#define APB_CTRL_NOBYPASS_CPU_ISO_RST_V 0x1 -#define APB_CTRL_NOBYPASS_CPU_ISO_RST_S 27 - -#define APB_CTRL_CLKGATE_FORCE_ON_REG (DR_REG_APB_CTRL_BASE + 0x0A4) -/* APB_CTRL_SRAM_CLKGATE_FORCE_ON : R/W ;bitpos:[5:2] ;default: ~4'b0 ; */ -/*description: */ -#define APB_CTRL_SRAM_CLKGATE_FORCE_ON 0x0000000F -#define APB_CTRL_SRAM_CLKGATE_FORCE_ON_M ((APB_CTRL_SRAM_CLKGATE_FORCE_ON_V)<<(APB_CTRL_SRAM_CLKGATE_FORCE_ON_S)) -#define APB_CTRL_SRAM_CLKGATE_FORCE_ON_V 0xF -#define APB_CTRL_SRAM_CLKGATE_FORCE_ON_S 2 -/* APB_CTRL_ROM_CLKGATE_FORCE_ON : R/W ;bitpos:[1:0] ;default: ~2'b0 ; */ -/*description: */ -#define APB_CTRL_ROM_CLKGATE_FORCE_ON 0x00000003 -#define APB_CTRL_ROM_CLKGATE_FORCE_ON_M ((APB_CTRL_ROM_CLKGATE_FORCE_ON_V)<<(APB_CTRL_ROM_CLKGATE_FORCE_ON_S)) -#define APB_CTRL_ROM_CLKGATE_FORCE_ON_V 0x3 -#define APB_CTRL_ROM_CLKGATE_FORCE_ON_S 0 - -#define APB_CTRL_MEM_POWER_DOWN_REG (DR_REG_APB_CTRL_BASE + 0x0A8) -/* APB_CTRL_SRAM_POWER_DOWN : R/W ;bitpos:[5:2] ;default: 4'b0 ; */ -/*description: */ -#define APB_CTRL_SRAM_POWER_DOWN 0x0000000F -#define APB_CTRL_SRAM_POWER_DOWN_M ((APB_CTRL_SRAM_POWER_DOWN_V)<<(APB_CTRL_SRAM_POWER_DOWN_S)) -#define APB_CTRL_SRAM_POWER_DOWN_V 0xF -#define APB_CTRL_SRAM_POWER_DOWN_S 2 -/* APB_CTRL_ROM_POWER_DOWN : R/W ;bitpos:[1:0] ;default: 2'b0 ; */ -/*description: */ -#define APB_CTRL_ROM_POWER_DOWN 0x00000003 -#define APB_CTRL_ROM_POWER_DOWN_M ((APB_CTRL_ROM_POWER_DOWN_V)<<(APB_CTRL_ROM_POWER_DOWN_S)) -#define APB_CTRL_ROM_POWER_DOWN_V 0x3 -#define APB_CTRL_ROM_POWER_DOWN_S 0 - -#define APB_CTRL_MEM_POWER_UP_REG (DR_REG_APB_CTRL_BASE + 0x0AC) -/* APB_CTRL_SRAM_POWER_UP : R/W ;bitpos:[5:2] ;default: ~4'b0 ; */ -/*description: */ -#define APB_CTRL_SRAM_POWER_UP 0x0000000F -#define APB_CTRL_SRAM_POWER_UP_M ((APB_CTRL_SRAM_POWER_UP_V)<<(APB_CTRL_SRAM_POWER_UP_S)) -#define APB_CTRL_SRAM_POWER_UP_V 0xF -#define APB_CTRL_SRAM_POWER_UP_S 2 -/* APB_CTRL_ROM_POWER_UP : R/W ;bitpos:[1:0] ;default: ~2'b0 ; */ -/*description: */ -#define APB_CTRL_ROM_POWER_UP 0x00000003 -#define APB_CTRL_ROM_POWER_UP_M ((APB_CTRL_ROM_POWER_UP_V)<<(APB_CTRL_ROM_POWER_UP_S)) -#define APB_CTRL_ROM_POWER_UP_V 0x3 -#define APB_CTRL_ROM_POWER_UP_S 0 - -#define APB_CTRL_RND_DATA_REG (DR_REG_APB_CTRL_BASE + 0x0B0) -/* APB_CTRL_RND_DATA : RO ;bitpos:[31:0] ;default: 32'b0 ; */ -/*description: */ -#define APB_CTRL_RND_DATA 0xFFFFFFFF -#define APB_CTRL_RND_DATA_M ((APB_CTRL_RND_DATA_V)<<(APB_CTRL_RND_DATA_S)) -#define APB_CTRL_RND_DATA_V 0xFFFFFFFF -#define APB_CTRL_RND_DATA_S 0 - -#define APB_CTRL_PERI_BACKUP_CONFIG_REG (DR_REG_APB_CTRL_BASE + 0x0B4) -/* APB_CTRL_PERI_BACKUP_ENA : R/W ;bitpos:[31] ;default: 1'b0 ; */ -/*description: */ -#define APB_CTRL_PERI_BACKUP_ENA (BIT(31)) -#define APB_CTRL_PERI_BACKUP_ENA_M (BIT(31)) -#define APB_CTRL_PERI_BACKUP_ENA_V 0x1 -#define APB_CTRL_PERI_BACKUP_ENA_S 31 -/* APB_CTRL_PERI_BACKUP_TO_MEM : R/W ;bitpos:[30] ;default: 1'b0 ; */ -/*description: */ -#define APB_CTRL_PERI_BACKUP_TO_MEM (BIT(30)) -#define APB_CTRL_PERI_BACKUP_TO_MEM_M (BIT(30)) -#define APB_CTRL_PERI_BACKUP_TO_MEM_V 0x1 -#define APB_CTRL_PERI_BACKUP_TO_MEM_S 30 -/* APB_CTRL_PERI_BACKUP_START : WO ;bitpos:[29] ;default: 1'b0 ; */ -/*description: */ -#define APB_CTRL_PERI_BACKUP_START (BIT(29)) -#define APB_CTRL_PERI_BACKUP_START_M (BIT(29)) -#define APB_CTRL_PERI_BACKUP_START_V 0x1 -#define APB_CTRL_PERI_BACKUP_START_S 29 -/* APB_CTRL_PERI_BACKUP_SIZE : R/W ;bitpos:[28:19] ;default: 10'd0 ; */ -/*description: */ -#define APB_CTRL_PERI_BACKUP_SIZE 0x000003FF -#define APB_CTRL_PERI_BACKUP_SIZE_M ((APB_CTRL_PERI_BACKUP_SIZE_V)<<(APB_CTRL_PERI_BACKUP_SIZE_S)) -#define APB_CTRL_PERI_BACKUP_SIZE_V 0x3FF -#define APB_CTRL_PERI_BACKUP_SIZE_S 19 -/* APB_CTRL_PERI_BACKUP_TOUT_THRES : R/W ;bitpos:[18:9] ;default: 10'd50 ; */ -/*description: */ -#define APB_CTRL_PERI_BACKUP_TOUT_THRES 0x000003FF -#define APB_CTRL_PERI_BACKUP_TOUT_THRES_M ((APB_CTRL_PERI_BACKUP_TOUT_THRES_V)<<(APB_CTRL_PERI_BACKUP_TOUT_THRES_S)) -#define APB_CTRL_PERI_BACKUP_TOUT_THRES_V 0x3FF -#define APB_CTRL_PERI_BACKUP_TOUT_THRES_S 9 -/* APB_CTRL_PERI_BACKUP_BURST_LIMIT : R/W ;bitpos:[8:4] ;default: 5'd8 ; */ -/*description: */ -#define APB_CTRL_PERI_BACKUP_BURST_LIMIT 0x0000001F -#define APB_CTRL_PERI_BACKUP_BURST_LIMIT_M ((APB_CTRL_PERI_BACKUP_BURST_LIMIT_V)<<(APB_CTRL_PERI_BACKUP_BURST_LIMIT_S)) -#define APB_CTRL_PERI_BACKUP_BURST_LIMIT_V 0x1F -#define APB_CTRL_PERI_BACKUP_BURST_LIMIT_S 4 -/* APB_CTRL_PERI_BACKUP_ADDR_MAP_MODE : R/W ;bitpos:[3] ;default: 1'b0 ; */ -/*description: */ -#define APB_CTRL_PERI_BACKUP_ADDR_MAP_MODE (BIT(3)) -#define APB_CTRL_PERI_BACKUP_ADDR_MAP_MODE_M (BIT(3)) -#define APB_CTRL_PERI_BACKUP_ADDR_MAP_MODE_V 0x1 -#define APB_CTRL_PERI_BACKUP_ADDR_MAP_MODE_S 3 -/* APB_CTRL_PERI_BACKUP_FLOW_ERR : RO ;bitpos:[2:0] ;default: 3'd0 ; */ -/*description: */ -#define APB_CTRL_PERI_BACKUP_FLOW_ERR 0x00000007 -#define APB_CTRL_PERI_BACKUP_FLOW_ERR_M ((APB_CTRL_PERI_BACKUP_FLOW_ERR_V)<<(APB_CTRL_PERI_BACKUP_FLOW_ERR_S)) -#define APB_CTRL_PERI_BACKUP_FLOW_ERR_V 0x7 -#define APB_CTRL_PERI_BACKUP_FLOW_ERR_S 0 - -#define APB_CTRL_PERI_BACKUP_APB_ADDR_REG (DR_REG_APB_CTRL_BASE + 0x0B8) -/* APB_CTRL_PERI_BACKUP_APB_START_ADDR : R/W ;bitpos:[31:0] ;default: 32'd0 ; */ -/*description: */ -#define APB_CTRL_PERI_BACKUP_APB_START_ADDR 0xFFFFFFFF -#define APB_CTRL_PERI_BACKUP_APB_START_ADDR_M ((APB_CTRL_PERI_BACKUP_APB_START_ADDR_V)<<(APB_CTRL_PERI_BACKUP_APB_START_ADDR_S)) -#define APB_CTRL_PERI_BACKUP_APB_START_ADDR_V 0xFFFFFFFF -#define APB_CTRL_PERI_BACKUP_APB_START_ADDR_S 0 - -#define APB_CTRL_PERI_BACKUP_MEM_ADDR_REG (DR_REG_APB_CTRL_BASE + 0x0BC) -/* APB_CTRL_PERI_BACKUP_MEM_START_ADDR : R/W ;bitpos:[31:0] ;default: 32'd0 ; */ -/*description: */ -#define APB_CTRL_PERI_BACKUP_MEM_START_ADDR 0xFFFFFFFF -#define APB_CTRL_PERI_BACKUP_MEM_START_ADDR_M ((APB_CTRL_PERI_BACKUP_MEM_START_ADDR_V)<<(APB_CTRL_PERI_BACKUP_MEM_START_ADDR_S)) -#define APB_CTRL_PERI_BACKUP_MEM_START_ADDR_V 0xFFFFFFFF -#define APB_CTRL_PERI_BACKUP_MEM_START_ADDR_S 0 - -#define APB_CTRL_PERI_BACKUP_MAP0_REG (DR_REG_APB_CTRL_BASE + 0x0C0) -/* APB_CTRL_PERI_BACKUP_MAP0 : R/W ;bitpos:[31:0] ;default: 32'd0 ; */ -/*description: */ -#define APB_CTRL_PERI_BACKUP_MAP0 0xFFFFFFFF -#define APB_CTRL_PERI_BACKUP_MAP0_M ((APB_CTRL_PERI_BACKUP_MAP0_V)<<(APB_CTRL_PERI_BACKUP_MAP0_S)) -#define APB_CTRL_PERI_BACKUP_MAP0_V 0xFFFFFFFF -#define APB_CTRL_PERI_BACKUP_MAP0_S 0 - -#define APB_CTRL_PERI_BACKUP_MAP1_REG (DR_REG_APB_CTRL_BASE + 0x0C4) -/* APB_CTRL_PERI_BACKUP_MAP1 : R/W ;bitpos:[31:0] ;default: 32'd0 ; */ -/*description: */ -#define APB_CTRL_PERI_BACKUP_MAP1 0xFFFFFFFF -#define APB_CTRL_PERI_BACKUP_MAP1_M ((APB_CTRL_PERI_BACKUP_MAP1_V)<<(APB_CTRL_PERI_BACKUP_MAP1_S)) -#define APB_CTRL_PERI_BACKUP_MAP1_V 0xFFFFFFFF -#define APB_CTRL_PERI_BACKUP_MAP1_S 0 - -#define APB_CTRL_PERI_BACKUP_MAP2_REG (DR_REG_APB_CTRL_BASE + 0x0C8) -/* APB_CTRL_PERI_BACKUP_MAP2 : R/W ;bitpos:[31:0] ;default: 32'd0 ; */ -/*description: */ -#define APB_CTRL_PERI_BACKUP_MAP2 0xFFFFFFFF -#define APB_CTRL_PERI_BACKUP_MAP2_M ((APB_CTRL_PERI_BACKUP_MAP2_V)<<(APB_CTRL_PERI_BACKUP_MAP2_S)) -#define APB_CTRL_PERI_BACKUP_MAP2_V 0xFFFFFFFF -#define APB_CTRL_PERI_BACKUP_MAP2_S 0 - -#define APB_CTRL_PERI_BACKUP_MAP3_REG (DR_REG_APB_CTRL_BASE + 0x0CC) -/* APB_CTRL_PERI_BACKUP_MAP3 : R/W ;bitpos:[31:0] ;default: 32'd0 ; */ -/*description: */ -#define APB_CTRL_PERI_BACKUP_MAP3 0xFFFFFFFF -#define APB_CTRL_PERI_BACKUP_MAP3_M ((APB_CTRL_PERI_BACKUP_MAP3_V)<<(APB_CTRL_PERI_BACKUP_MAP3_S)) -#define APB_CTRL_PERI_BACKUP_MAP3_V 0xFFFFFFFF -#define APB_CTRL_PERI_BACKUP_MAP3_S 0 - -#define APB_CTRL_PERI_BACKUP_INT_RAW_REG (DR_REG_APB_CTRL_BASE + 0x0D0) -/* APB_CTRL_PERI_BACKUP_ERR_INT_RAW : RO ;bitpos:[1] ;default: 1'd0 ; */ -/*description: */ -#define APB_CTRL_PERI_BACKUP_ERR_INT_RAW (BIT(1)) -#define APB_CTRL_PERI_BACKUP_ERR_INT_RAW_M (BIT(1)) -#define APB_CTRL_PERI_BACKUP_ERR_INT_RAW_V 0x1 -#define APB_CTRL_PERI_BACKUP_ERR_INT_RAW_S 1 -/* APB_CTRL_PERI_BACKUP_DONE_INT_RAW : RO ;bitpos:[0] ;default: 1'd0 ; */ -/*description: */ -#define APB_CTRL_PERI_BACKUP_DONE_INT_RAW (BIT(0)) -#define APB_CTRL_PERI_BACKUP_DONE_INT_RAW_M (BIT(0)) -#define APB_CTRL_PERI_BACKUP_DONE_INT_RAW_V 0x1 -#define APB_CTRL_PERI_BACKUP_DONE_INT_RAW_S 0 - -#define APB_CTRL_PERI_BACKUP_INT_ST_REG (DR_REG_APB_CTRL_BASE + 0x0D4) -/* APB_CTRL_PERI_BACKUP_ERR_INT_ST : RO ;bitpos:[1] ;default: 1'd0 ; */ -/*description: */ -#define APB_CTRL_PERI_BACKUP_ERR_INT_ST (BIT(1)) -#define APB_CTRL_PERI_BACKUP_ERR_INT_ST_M (BIT(1)) -#define APB_CTRL_PERI_BACKUP_ERR_INT_ST_V 0x1 -#define APB_CTRL_PERI_BACKUP_ERR_INT_ST_S 1 -/* APB_CTRL_PERI_BACKUP_DONE_INT_ST : RO ;bitpos:[0] ;default: 1'd0 ; */ -/*description: */ -#define APB_CTRL_PERI_BACKUP_DONE_INT_ST (BIT(0)) -#define APB_CTRL_PERI_BACKUP_DONE_INT_ST_M (BIT(0)) -#define APB_CTRL_PERI_BACKUP_DONE_INT_ST_V 0x1 -#define APB_CTRL_PERI_BACKUP_DONE_INT_ST_S 0 - -#define APB_CTRL_PERI_BACKUP_INT_ENA_REG (DR_REG_APB_CTRL_BASE + 0x0D8) -/* APB_CTRL_PERI_BACKUP_ERR_INT_ENA : R/W ;bitpos:[1] ;default: 1'd0 ; */ -/*description: */ -#define APB_CTRL_PERI_BACKUP_ERR_INT_ENA (BIT(1)) -#define APB_CTRL_PERI_BACKUP_ERR_INT_ENA_M (BIT(1)) -#define APB_CTRL_PERI_BACKUP_ERR_INT_ENA_V 0x1 -#define APB_CTRL_PERI_BACKUP_ERR_INT_ENA_S 1 -/* APB_CTRL_PERI_BACKUP_DONE_INT_ENA : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: */ -#define APB_CTRL_PERI_BACKUP_DONE_INT_ENA (BIT(0)) -#define APB_CTRL_PERI_BACKUP_DONE_INT_ENA_M (BIT(0)) -#define APB_CTRL_PERI_BACKUP_DONE_INT_ENA_V 0x1 -#define APB_CTRL_PERI_BACKUP_DONE_INT_ENA_S 0 - -#define APB_CTRL_PERI_BACKUP_INT_CLR_REG (DR_REG_APB_CTRL_BASE + 0x0DC) -/* APB_CTRL_PERI_BACKUP_ERR_INT_CLR : WO ;bitpos:[1] ;default: 1'd0 ; */ -/*description: */ -#define APB_CTRL_PERI_BACKUP_ERR_INT_CLR (BIT(1)) -#define APB_CTRL_PERI_BACKUP_ERR_INT_CLR_M (BIT(1)) -#define APB_CTRL_PERI_BACKUP_ERR_INT_CLR_V 0x1 -#define APB_CTRL_PERI_BACKUP_ERR_INT_CLR_S 1 -/* APB_CTRL_PERI_BACKUP_DONE_INT_CLR : WO ;bitpos:[0] ;default: 1'd0 ; */ -/*description: */ -#define APB_CTRL_PERI_BACKUP_DONE_INT_CLR (BIT(0)) -#define APB_CTRL_PERI_BACKUP_DONE_INT_CLR_M (BIT(0)) -#define APB_CTRL_PERI_BACKUP_DONE_INT_CLR_V 0x1 -#define APB_CTRL_PERI_BACKUP_DONE_INT_CLR_S 0 - -#define APB_CTRL_CLK_CONF_REG (DR_REG_APB_CTRL_BASE + 0x0E0) -/* APB_CTRL_CLK_EN : R/W ;bitpos:[0] ;default: 1'b0 ; */ -/*description: */ -#define APB_CTRL_CLK_EN (BIT(0)) -#define APB_CTRL_CLK_EN_M (BIT(0)) -#define APB_CTRL_CLK_EN_V 0x1 -#define APB_CTRL_CLK_EN_S 0 - -#define APB_CTRL_DATE_REG (DR_REG_APB_CTRL_BASE + 0x3FC) -/* APB_CTRL_DATE : R/W ;bitpos:[31:0] ;default: 32'h2101050 ; */ -/*description: Version control*/ -#define APB_CTRL_DATE 0xFFFFFFFF -#define APB_CTRL_DATE_M ((APB_CTRL_DATE_V)<<(APB_CTRL_DATE_S)) -#define APB_CTRL_DATE_V 0xFFFFFFFF -#define APB_CTRL_DATE_S 0 - -#ifdef __cplusplus -} -#endif - - - -#endif /*_SOC_APB_CTRL_REG_H_ */ diff --git a/components/soc/esp32h2/include/soc/apb_ctrl_struct.h b/components/soc/esp32h2/include/soc/apb_ctrl_struct.h deleted file mode 100644 index 53edfec0dd..0000000000 --- a/components/soc/esp32h2/include/soc/apb_ctrl_struct.h +++ /dev/null @@ -1,454 +0,0 @@ -// 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. -#ifndef _SOC_APB_CTRL_STRUCT_H_ -#define _SOC_APB_CTRL_STRUCT_H_ -#ifdef __cplusplus -extern "C" { -#endif - -typedef volatile struct { - uint32_t reserved_0; - uint32_t reserved_4; - uint32_t reserved_8; - uint32_t wifi_bb_cfg; /**/ - uint32_t wifi_bb_cfg_2; /**/ - uint32_t reserved_14; - uint32_t reserved_18; - union { - struct { - uint32_t peri_io_swap: 8; - uint32_t reserved8: 24; - }; - uint32_t val; - } host_inf_sel; - union { - struct { - uint32_t ext_mem_pms_lock: 1; - uint32_t reserved1: 31; - }; - uint32_t val; - } ext_mem_pms_lock; - uint32_t reserved_24; - union { - struct { - uint32_t flash_ace0_attr: 2; - uint32_t reserved2: 30; - }; - uint32_t val; - } flash_ace0_attr; - union { - struct { - uint32_t flash_ace1_attr: 2; - uint32_t reserved2: 30; - }; - uint32_t val; - } flash_ace1_attr; - union { - struct { - uint32_t flash_ace2_attr: 2; - uint32_t reserved2: 30; - }; - uint32_t val; - } flash_ace2_attr; - union { - struct { - uint32_t flash_ace3_attr: 2; - uint32_t reserved2: 30; - }; - uint32_t val; - } flash_ace3_attr; - uint32_t flash_ace0_addr; /**/ - uint32_t flash_ace1_addr; /**/ - uint32_t flash_ace2_addr; /**/ - uint32_t flash_ace3_addr; /**/ - union { - struct { - uint32_t flash_ace0_size:13; - uint32_t reserved13: 19; - }; - uint32_t val; - } flash_ace0_size; - union { - struct { - uint32_t flash_ace1_size:13; - uint32_t reserved13: 19; - }; - uint32_t val; - } flash_ace1_size; - union { - struct { - uint32_t flash_ace2_size:13; - uint32_t reserved13: 19; - }; - uint32_t val; - } flash_ace2_size; - union { - struct { - uint32_t flash_ace3_size:13; - uint32_t reserved13: 19; - }; - uint32_t val; - } flash_ace3_size; - uint32_t reserved_58; - uint32_t reserved_5c; - uint32_t reserved_60; - uint32_t reserved_64; - uint32_t reserved_68; - uint32_t reserved_6c; - uint32_t reserved_70; - uint32_t reserved_74; - uint32_t reserved_78; - uint32_t reserved_7c; - uint32_t reserved_80; - uint32_t reserved_84; - union { - struct { - uint32_t spi_mem_reject_int: 1; - uint32_t spi_mem_reject_clr: 1; - uint32_t spi_mem_reject_cde: 5; - uint32_t reserved7: 25; - }; - uint32_t val; - } spi_mem_pms_ctrl; - uint32_t spi_mem_reject_addr; /**/ - union { - struct { - uint32_t sdio_win_access_en: 1; - uint32_t reserved1: 31; - }; - uint32_t val; - } sdio_ctrl; - union { - struct { - uint32_t redcy_sig0: 31; - uint32_t redcy_andor: 1; - }; - uint32_t val; - } redcy_sig0; - union { - struct { - uint32_t redcy_sig1: 31; - uint32_t redcy_nandor: 1; - }; - uint32_t val; - } redcy_sig1; - union { - struct { - uint32_t agc_mem_force_pu: 1; - uint32_t agc_mem_force_pd: 1; - uint32_t pbus_mem_force_pu: 1; - uint32_t pbus_mem_force_pd: 1; - uint32_t dc_mem_force_pu: 1; - uint32_t dc_mem_force_pd: 1; - uint32_t reserved6: 26; - }; - uint32_t val; - } front_end_mem_pd; - union { - struct { - uint32_t reserved0: 27; - uint32_t nobypass_cpu_iso_rst: 1; - uint32_t reserved28: 4; - }; - uint32_t val; - } retention_ctrl; - union { - struct { - uint32_t rom_clkgate_force_on: 2; - uint32_t sram_clkgate_force_on: 4; - uint32_t reserved6: 26; - }; - uint32_t val; - } clkgate_force_on; - union { - struct { - uint32_t rom_power_down: 2; - uint32_t sram_power_down: 4; - uint32_t reserved6: 26; - }; - uint32_t val; - } mem_power_down; - union { - struct { - uint32_t rom_power_up: 2; - uint32_t sram_power_up: 4; - uint32_t reserved6: 26; - }; - uint32_t val; - } mem_power_up; - uint32_t rnd_data; /**/ - union { - struct { - uint32_t peri_backup_flow_err: 3; - uint32_t peri_backup_addr_map_mode: 1; - uint32_t peri_backup_burst_limit: 5; - uint32_t peri_backup_tout_thres: 10; - uint32_t peri_backup_size: 10; - uint32_t peri_backup_start: 1; - uint32_t peri_backup_to_mem: 1; - uint32_t peri_backup_ena: 1; - }; - uint32_t val; - } peri_backup_config; - uint32_t peri_backup_addr; /**/ - uint32_t peri_backup_mem_addr; /**/ - uint32_t peri_backup_map0; /**/ - uint32_t peri_backup_map1; /**/ - uint32_t peri_backup_map2; /**/ - uint32_t peri_backup_map3; /**/ - union { - struct { - uint32_t peri_backup_done: 1; - uint32_t peri_backup_err: 1; - uint32_t reserved2: 30; - }; - uint32_t val; - } peri_backup_int_raw; - union { - struct { - uint32_t peri_backup_done: 1; - uint32_t peri_backup_err: 1; - uint32_t reserved2: 30; - }; - uint32_t val; - } peri_backup_int_st; - union { - struct { - uint32_t peri_backup_done: 1; - uint32_t peri_backup_err: 1; - uint32_t reserved2: 30; - }; - uint32_t val; - } peri_backup_int_ena; - union { - struct { - uint32_t peri_backup_done: 1; - uint32_t peri_backup_err: 1; - uint32_t reserved2: 30; - }; - uint32_t val; - } peri_backup_int_clr; - union { - struct { - uint32_t clk_en: 1; - uint32_t reserved1: 31; - }; - uint32_t val; - } ctrlclk_conf; - uint32_t reserved_e4; - uint32_t reserved_e8; - uint32_t reserved_ec; - uint32_t reserved_f0; - uint32_t reserved_f4; - uint32_t reserved_f8; - uint32_t reserved_fc; - uint32_t reserved_100; - uint32_t reserved_104; - uint32_t reserved_108; - uint32_t reserved_10c; - uint32_t reserved_110; - uint32_t reserved_114; - uint32_t reserved_118; - uint32_t reserved_11c; - uint32_t reserved_120; - uint32_t reserved_124; - uint32_t reserved_128; - uint32_t reserved_12c; - uint32_t reserved_130; - uint32_t reserved_134; - uint32_t reserved_138; - uint32_t reserved_13c; - uint32_t reserved_140; - uint32_t reserved_144; - uint32_t reserved_148; - uint32_t reserved_14c; - 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 date; /*Version control*/ -} apb_ctrl_dev_t; -extern apb_ctrl_dev_t APB_CTRL; -#ifdef __cplusplus -} -#endif - -#endif /* _SOC_APB_CTRL_STRUCT_H_ */ diff --git a/components/soc/esp32h2/include/soc/apb_saradc_struct.h b/components/soc/esp32h2/include/soc/apb_saradc_struct.h index 67242d822d..a286c3c557 100644 --- a/components/soc/esp32h2/include/soc/apb_saradc_struct.h +++ b/components/soc/esp32h2/include/soc/apb_saradc_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct apb_saradc_dev_s { union { struct { uint32_t start_force: 1; diff --git a/components/soc/esp32h2/include/soc/assist_debug_reg.h b/components/soc/esp32h2/include/soc/assist_debug_reg.h index a0c1e9c9d8..2b13d1f5f4 100644 --- a/components/soc/esp32h2/include/soc/assist_debug_reg.h +++ b/components/soc/esp32h2/include/soc/assist_debug_reg.h @@ -652,7 +652,7 @@ extern "C" { #define ASSIST_DEBUG_LOG_MEM_FULL_FLAG_V 0x1 #define ASSIST_DEBUG_LOG_MEM_FULL_FLAG_S 0 -#define ASSIST_DEBUG_C0RE_0_LASTPC_BEFORE_EXCEPTION_REG (DR_REG_ASSIST_DEBUG_BASE + 0x094) +#define ASSIST_DEBUG_CORE_0_LASTPC_BEFORE_EXCEPTION_REG (DR_REG_ASSIST_DEBUG_BASE + 0x094) /* ASSIST_DEBUG_CORE_0_LASTPC_BEFORE_EXC : RO ;bitpos:[31:0] ;default: 32'b0 ; */ /*description: */ #define ASSIST_DEBUG_CORE_0_LASTPC_BEFORE_EXC 0xFFFFFFFF @@ -660,7 +660,7 @@ extern "C" { #define ASSIST_DEBUG_CORE_0_LASTPC_BEFORE_EXC_V 0xFFFFFFFF #define ASSIST_DEBUG_CORE_0_LASTPC_BEFORE_EXC_S 0 -#define ASSIST_DEBUG_C0RE_0_DEBUG_MODE_REG (DR_REG_ASSIST_DEBUG_BASE + 0x098) +#define ASSIST_DEBUG_CORE_0_DEBUG_MODE_REG (DR_REG_ASSIST_DEBUG_BASE + 0x098) /* ASSIST_DEBUG_CORE_0_DEBUG_MODULE_ACTIVE : RO ;bitpos:[1] ;default: 1'b0 ; */ /*description: */ #define ASSIST_DEBUG_CORE_0_DEBUG_MODULE_ACTIVE (BIT(1)) diff --git a/components/soc/esp32h2/include/soc/efuse_reg.h b/components/soc/esp32h2/include/soc/efuse_reg.h index b7b11b9852..fc55f2938e 100644 --- a/components/soc/esp32h2/include/soc/efuse_reg.h +++ b/components/soc/esp32h2/include/soc/efuse_reg.h @@ -141,12 +141,12 @@ extern "C" { #define EFUSE_DIS_ICACHE_M (BIT(8)) #define EFUSE_DIS_ICACHE_V 0x1 #define EFUSE_DIS_ICACHE_S 8 -/* EFUSE_DIS_RTC_RAM_BOOT : R/W ;bitpos:[7] ;default: 1'b0 ; */ -/*description: Set this bit to disable boot from RTC RAM.*/ -#define EFUSE_DIS_RTC_RAM_BOOT (BIT(7)) -#define EFUSE_DIS_RTC_RAM_BOOT_M (BIT(7)) -#define EFUSE_DIS_RTC_RAM_BOOT_V 0x1 -#define EFUSE_DIS_RTC_RAM_BOOT_S 7 +/* EFUSE_RPT4_RESERVED5 : R/W ;bitpos:[7] ;default: 1'b0 ; */ +/*description: Reserved*/ +#define EFUSE_RPT4_RESERVED5 (BIT(7)) +#define EFUSE_RPT4_RESERVED5_M (BIT(7)) +#define EFUSE_RPT4_RESERVED5_V 0x1 +#define EFUSE_RPT4_RESERVED5_S 7 /* EFUSE_RD_DIS : R/W ;bitpos:[6:0] ;default: 7'h0 ; */ /*description: Set this bit to disable reading from BlOCK4-10.*/ #define EFUSE_RD_DIS 0x0000007F @@ -516,12 +516,12 @@ extern "C" { #define EFUSE_DIS_ICACHE_M (BIT(8)) #define EFUSE_DIS_ICACHE_V 0x1 #define EFUSE_DIS_ICACHE_S 8 -/* EFUSE_DIS_RTC_RAM_BOOT : RO ;bitpos:[7] ;default: 1'b0 ; */ -/*description: The value of DIS_RTC_RAM_BOOT.*/ -#define EFUSE_DIS_RTC_RAM_BOOT (BIT(7)) -#define EFUSE_DIS_RTC_RAM_BOOT_M (BIT(7)) -#define EFUSE_DIS_RTC_RAM_BOOT_V 0x1 -#define EFUSE_DIS_RTC_RAM_BOOT_S 7 +/* EFUSE_RPT4_RESERVED5 : RO ;bitpos:[7] ;default: 1'b0 ; */ +/*description: Reserved*/ +#define EFUSE_RPT4_RESERVED5 (BIT(7)) +#define EFUSE_RPT4_RESERVED5_M (BIT(7)) +#define EFUSE_RPT4_RESERVED5_V 0x1 +#define EFUSE_RPT4_RESERVED5_S 7 /* EFUSE_RD_DIS : RO ;bitpos:[6:0] ;default: 7'h0 ; */ /*description: The value of RD_DIS.*/ #define EFUSE_RD_DIS 0x0000007F @@ -1486,12 +1486,12 @@ extern "C" { #define EFUSE_DIS_ICACHE_ERR_M (BIT(8)) #define EFUSE_DIS_ICACHE_ERR_V 0x1 #define EFUSE_DIS_ICACHE_ERR_S 8 -/* EFUSE_DIS_RTC_RAM_BOOT_ERR : RO ;bitpos:[7] ;default: 1'b0 ; */ -/*description: If DIS_RTC_RAM_BOOT is 1 then it indicates a programming error.*/ -#define EFUSE_DIS_RTC_RAM_BOOT_ERR (BIT(7)) -#define EFUSE_DIS_RTC_RAM_BOOT_ERR_M (BIT(7)) -#define EFUSE_DIS_RTC_RAM_BOOT_ERR_V 0x1 -#define EFUSE_DIS_RTC_RAM_BOOT_ERR_S 7 +/* EFUSE_RPT4_RESERVED5_ERR : RO ;bitpos:[7] ;default: 1'b0 ; */ +/*description: Reserved*/ +#define EFUSE_RPT4_RESERVED5_ERR (BIT(7)) +#define EFUSE_RPT4_RESERVED5_ERR_M (BIT(7)) +#define EFUSE_RPT4_RESERVED5_ERR_V 0x1 +#define EFUSE_RPT4_RESERVED5_ERR_S 7 /* EFUSE_RD_DIS_ERR : RO ;bitpos:[6:0] ;default: 7'h0 ; */ /*description: If any bit in RD_DIS is 1 then it indicates a programming error.*/ #define EFUSE_RD_DIS_ERR 0x0000007F @@ -1691,7 +1691,7 @@ extern "C" { #define EFUSE_DIS_DOWNLOAD_MODE_ERR_V 0x1 #define EFUSE_DIS_DOWNLOAD_MODE_ERR_S 0 -#define EFUSE_RD_REPEAT_ERR4_REG (DR_REG_EFUSE_BASE + 0x190) +#define EFUSE_RD_REPEAT_ERR4_REG (DR_REG_EFUSE_BASE + 0x18C) /* EFUSE_RPT4_RESERVED4_ERR : RO ;bitpos:[23:0] ;default: 24'h0 ; */ /*description: Reserved.*/ #define EFUSE_RPT4_RESERVED4_ERR 0x00FFFFFF diff --git a/components/soc/esp32h2/include/soc/efuse_struct.h b/components/soc/esp32h2/include/soc/efuse_struct.h index 1c51e71475..4c5af9d8c7 100644 --- a/components/soc/esp32h2/include/soc/efuse_struct.h +++ b/components/soc/esp32h2/include/soc/efuse_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct efuse_dev_s { uint32_t pgm_data0; /*Register 0 that stores data to be programmed.*/ union { struct { @@ -106,7 +106,7 @@ typedef volatile struct { union { struct { uint32_t rd_dis: 7; /*The value of RD_DIS.*/ - uint32_t dis_rtc_ram_boot: 1; /*The value of DIS_RTC_RAM_BOOT.*/ + uint32_t rpt4_reserved5: 1; /*Reserved*/ uint32_t dis_icache: 1; /*The value of DIS_ICACHE.*/ uint32_t dis_usb_jtag: 1; /*The value of DIS_USB_JTAG.*/ uint32_t dis_download_icache: 1; /*The value of DIS_DOWNLOAD_ICACHE.*/ @@ -274,7 +274,7 @@ typedef volatile struct { union { struct { uint32_t rd_dis_err: 7; /*If any bit in RD_DIS is 1 then it indicates a programming error.*/ - uint32_t dis_rtc_ram_boot_err: 1; /*If DIS_RTC_RAM_BOOT is 1 then it indicates a programming error.*/ + uint32_t rpt4_reserved5_err: 1; /*If RPT4_RESERVED5 is 1 then it indicates a programming error.*/ uint32_t dis_icache_err: 1; /*If DIS_ICACHE is 1 then it indicates a programming error.*/ uint32_t dis_usb_jtag_err: 1; /*If DIS_USB_JTAG is 1 then it indicates a programming error.*/ uint32_t dis_download_icache: 1; /*If DIS_DOWNLOAD_ICACHE is 1 then it indicates a programming error.*/ @@ -342,7 +342,6 @@ typedef volatile struct { }; uint32_t val; } rd_repeat_err3; - uint32_t reserved_18c; union { struct { uint32_t rpt4_reserved4_err:24; /*Reserved.*/ @@ -350,6 +349,7 @@ typedef volatile struct { }; uint32_t val; } rd_repeat_err4; + uint32_t reserved_190; uint32_t reserved_194; uint32_t reserved_198; uint32_t reserved_19c; diff --git a/components/soc/esp32h2/include/soc/gdma_struct.h b/components/soc/esp32h2/include/soc/gdma_struct.h index 446ff4c112..dde520f5ed 100644 --- a/components/soc/esp32h2/include/soc/gdma_struct.h +++ b/components/soc/esp32h2/include/soc/gdma_struct.h @@ -19,7 +19,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct gdma_dev_s { struct { union { struct { diff --git a/components/soc/esp32h2/include/soc/gpio_sd_struct.h b/components/soc/esp32h2/include/soc/gpio_sd_struct.h index cc73cebd03..45e21d58e1 100644 --- a/components/soc/esp32h2/include/soc/gpio_sd_struct.h +++ b/components/soc/esp32h2/include/soc/gpio_sd_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct gpio_sd_dev_s { union { struct { uint32_t duty: 8; diff --git a/components/soc/esp32h2/include/soc/gpio_struct.h b/components/soc/esp32h2/include/soc/gpio_struct.h index f260adbd2a..45f5e55412 100644 --- a/components/soc/esp32h2/include/soc/gpio_struct.h +++ b/components/soc/esp32h2/include/soc/gpio_struct.h @@ -18,7 +18,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct gpio_dev_s { uint32_t bt_select; /**/ union { struct { diff --git a/components/soc/esp32h2/include/soc/hwcrypto_reg.h b/components/soc/esp32h2/include/soc/hwcrypto_reg.h index 6844627388..474b07faa3 100644 --- a/components/soc/esp32h2/include/soc/hwcrypto_reg.h +++ b/components/soc/esp32h2/include/soc/hwcrypto_reg.h @@ -133,6 +133,7 @@ #define HMAC_SET_MESSAGE_END_REG ((DR_REG_HMAC_BASE) + 0x58) #define HMAC_SET_RESULT_FINISH_REG ((DR_REG_HMAC_BASE) + 0x5c) #define HMAC_SET_INVALIDATE_JTAG_REG ((DR_REG_HMAC_BASE) + 0x60) +#define HMAC_INVALIDATE_JTAG BIT(0) #define HMAC_SET_INVALIDATE_DS_REG ((DR_REG_HMAC_BASE) + 0x64) #define HMAC_QUERY_ERROR_REG ((DR_REG_HMAC_BASE) + 0x68) #define HMAC_QUERY_BUSY_REG ((DR_REG_HMAC_BASE) + 0x6c) diff --git a/components/soc/esp32h2/include/soc/i2c_struct.h b/components/soc/esp32h2/include/soc/i2c_struct.h index 22c6c47041..ccd5fdb5b0 100644 --- a/components/soc/esp32h2/include/soc/i2c_struct.h +++ b/components/soc/esp32h2/include/soc/i2c_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif #include "soc.h" -typedef volatile struct { +typedef volatile struct i2c_dev_s { union { struct { uint32_t period : 9; diff --git a/components/soc/esp32h2/include/soc/i2s_struct.h b/components/soc/esp32h2/include/soc/i2s_struct.h index 9d3537004c..9ea88c5a12 100644 --- a/components/soc/esp32h2/include/soc/i2s_struct.h +++ b/components/soc/esp32h2/include/soc/i2s_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct i2s_dev_s { uint32_t reserved_0; uint32_t reserved_4; uint32_t reserved_8; diff --git a/components/soc/esp32h2/include/soc/io_mux_reg.h b/components/soc/esp32h2/include/soc/io_mux_reg.h index 3f338ea92d..e9a0795167 100644 --- a/components/soc/esp32h2/include/soc/io_mux_reg.h +++ b/components/soc/esp32h2/include/soc/io_mux_reg.h @@ -124,9 +124,6 @@ #define GPIO_PAD_PULLDOWN(num) do{PIN_PULLUP_DIS(IOMUX_REG_GPIO##num);PIN_PULLDWN_EN(IOMUX_REG_GPIO##num);}while(0) #define GPIO_PAD_SET_DRV(num, drv) PIN_SET_DRV(IOMUX_REG_GPIO##num, drv) -#define U0RXD_GPIO_NUM 20 -#define U0TXD_GPIO_NUM 21 - #define SPI_HD_GPIO_NUM 12 #define SPI_WP_GPIO_NUM 13 #define SPI_CS0_GPIO_NUM 14 diff --git a/components/soc/esp32h2/include/soc/ledc_struct.h b/components/soc/esp32h2/include/soc/ledc_struct.h index 9e5a2a96c1..0eb8c18268 100644 --- a/components/soc/esp32h2/include/soc/ledc_struct.h +++ b/components/soc/esp32h2/include/soc/ledc_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct ledc_dev_s { struct { struct { union { diff --git a/components/soc/esp32h2/include/soc/periph_defs.h b/components/soc/esp32h2/include/soc/periph_defs.h index fe14929998..4b0fc00ea4 100644 --- a/components/soc/esp32h2/include/soc/periph_defs.h +++ b/components/soc/esp32h2/include/soc/periph_defs.h @@ -102,8 +102,8 @@ typedef enum { ETS_SHA_INTR_SOURCE, /**< interrupt of SHA accelerator, level*/ ETS_FROM_CPU_INTR0_SOURCE, /**< interrupt0 generated from a CPU, level*/ /* Used for FreeRTOS */ ETS_FROM_CPU_INTR1_SOURCE, /**< interrupt1 generated from a CPU, level*/ /* Used for FreeRTOS */ - ETS_FROM_CPU_INTR2_SOURCE, /**< interrupt2 generated from a CPU, level*/ /* Used for DPORT Access */ - ETS_FROM_CPU_INTR3_SOURCE, /**< interrupt3 generated from a CPU, level*/ /* Used for DPORT Access */ + ETS_FROM_CPU_INTR2_SOURCE, /**< interrupt2 generated from a CPU, level*/ + ETS_FROM_CPU_INTR3_SOURCE, /**< interrupt3 generated from a CPU, level*/ ETS_ASSIST_DEBUG_INTR_SOURCE, /**< interrupt of Assist debug module, LEVEL*/ ETS_DMA_APBPERI_PMS_INTR_SOURCE, ETS_CORE0_IRAM0_PMS_INTR_SOURCE, diff --git a/components/soc/esp32h2/include/soc/reset_reasons.h b/components/soc/esp32h2/include/soc/reset_reasons.h index 0bb99f5851..b11a6ee52a 100644 --- a/components/soc/esp32h2/include/soc/reset_reasons.h +++ b/components/soc/esp32h2/include/soc/reset_reasons.h @@ -52,7 +52,10 @@ typedef enum { RESET_REASON_SYS_SUPER_WDT = 0x12, // Super watch dog resets the digital core and rtc module RESET_REASON_SYS_CLK_GLITCH = 0x13, // Glitch on clock resets the digital core and rtc module RESET_REASON_CORE_EFUSE_CRC = 0x14, // eFuse CRC error resets the digital core + RESET_REASON_CORE_USB_UART = 0x15, // USB UART resets the digital core + RESET_REASON_CORE_USB_JTAG = 0x16, // USB JTAG resets the digital core RESET_REASON_CORE_PWR_GLITCH = 0x17, // Glitch on power resets the digital core + RESET_REASON_CPU_JTAG = 0x18, // JTAG resets the CPU } soc_reset_reason_t; diff --git a/components/soc/esp32h2/include/soc/rmt_struct.h b/components/soc/esp32h2/include/soc/rmt_struct.h index 7fc1890b12..b9b7533b3d 100644 --- a/components/soc/esp32h2/include/soc/rmt_struct.h +++ b/components/soc/esp32h2/include/soc/rmt_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct rmt_dev_s { uint32_t data_ch[4]; /**/ union { struct { @@ -291,11 +291,9 @@ typedef struct { } rmt_item32_t; //Allow access to RMT memory using RMTMEM.chan[0].data32[8] -typedef volatile struct { +typedef volatile struct rmt_mem_s { struct { - union { - rmt_item32_t data32[48]; - }; + rmt_item32_t data32[48]; } chan[4]; } rmt_mem_t; diff --git a/components/soc/esp32h2/include/soc/rtc.h b/components/soc/esp32h2/include/soc/rtc.h index e117bdbb92..5585986ed2 100644 --- a/components/soc/esp32h2/include/soc/rtc.h +++ b/components/soc/esp32h2/include/soc/rtc.h @@ -54,12 +54,12 @@ extern "C" { #define MHZ (1000000) #define RTC_SLOW_CLK_X32K_CAL_TIMEOUT_THRES(cycles) (cycles << 12) -#define RTC_SLOW_CLK_8MD256_CAL_TIMEOUT_THRES(cycles) (cycles << 12) +#define RTC_SLOW_CLK_RC32K_CAL_TIMEOUT_THRES(cycles) (cycles << 12) #define RTC_SLOW_CLK_150K_CAL_TIMEOUT_THRES(cycles) (cycles << 10) -#define RTC_SLOW_CLK_FREQ_150K 150000 -#define RTC_SLOW_CLK_FREQ_8MD256 (RTC_FAST_CLK_FREQ_APPROX / 256) +#define RTC_SLOW_CLK_FREQ_150K 130000 #define RTC_SLOW_CLK_FREQ_32K 32768 +#define RTC_SLOW_CLK_FREQ_RC32 32768 #define OTHER_BLOCKS_POWERUP 1 #define OTHER_BLOCKS_WAIT 1 @@ -68,14 +68,27 @@ extern "C" { * RTC_CNTL_DIG_DBIAS_WAK, RTC_CNTL_DIG_DBIAS_SLP values. * Valid if RTC_CNTL_DBG_ATTEN is 0. */ -#define RTC_CNTL_DBIAS_SLP 0 //sleep dig_dbias & rtc_dbias -#define RTC_CNTL_DBIAS_1V00 0 -#define RTC_CNTL_DBIAS_1V05 4 -#define RTC_CNTL_DBIAS_1V10 5 -#define RTC_CNTL_DBIAS_1V15 6 -#define RTC_CNTL_DBIAS_1V20 7 +#define RTC_CNTL_DBIAS_SLP 0 //sleep dig_dbias & rtc_dbias +#define RTC_CNTL_DBIAS_1V00 0 +#define RTC_CNTL_DBIAS_1V05 4 +#define RTC_CNTL_DBIAS_1V10 5 +#define RTC_CNTL_DBIAS_1V15 6 +#define RTC_CNTL_DBIAS_1V20 7 +#define RTC_CNTL_DBIAS_DEFAULT 8 /* The value of 1V00 can be adjusted between 0~3*/ + +/* dcdc mode + */ +#define RTC_CNTL_DCDC_TRX_MODE 0b100 +#define RTC_CNTL_DCDC_LSLP_MODE 0b110 +#define RTC_CNTL_DCDC_DSLP_MODE 0b101 +#define RTC_CNTL_DCDC_FREQ_DEFAULT 3 + +#define DCDC_SLP_TRX_MODE 0 +#define DCDC_SLP_LSLP_MODE 1 +#define DCDC_SLP_DSLP_MODE 2 + #define RTC_CNTL_DIG_DBIAS_0V85 0 #define RTC_CNTL_DIG_DBIAS_0V90 1 #define RTC_CNTL_DIG_DBIAS_0V95 2 @@ -105,8 +118,10 @@ extern "C" { #define RTC_CNTL_CK8M_WAIT_DEFAULT 20 #define RTC_CK8M_ENABLE_WAIT_DEFAULT 5 -#define RTC_CNTL_CK8M_DFREQ_DEFAULT 100 -#define RTC_CNTL_SCK_DCAP_DEFAULT 255 +#define RTC_CNTL_CK8M_DFREQ_DEFAULT 600 +#define RTC_CNTL_SCK_DCAP_DEFAULT 128 +#define RTC_CNTL_RC32K_DFREQ_DEFAULT 707 + /* Various delays to be programmed into power control state machines */ #define RTC_CNTL_XTL_BUF_WAIT_SLP_US (250) @@ -120,6 +135,7 @@ extern "C" { set sleep_init default param */ #define RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_DEFAULT 3 +#define RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_NODROP 0 #define RTC_CNTL_DBG_ATTEN_DEEPSLEEP_DEFAULT 15 #define RTC_CNTL_DBG_ATTEN_MONITOR_DEFAULT 0 #define RTC_CNTL_BIASSLP_MONITOR_DEFAULT 0 @@ -138,28 +154,14 @@ typedef enum { RTC_XTAL_FREQ_40M = 40, //!< 40 MHz XTAL } rtc_xtal_freq_t; -/** - * @brief CPU frequency values - */ -typedef enum { - RTC_CPU_FREQ_XTAL = 0, //!< Main XTAL frequency - RTC_CPU_FREQ_80M = 1, //!< 80 MHz - RTC_CPU_FREQ_160M = 2, //!< 160 MHz - RTC_CPU_FREQ_240M = 3, //!< 240 MHz - RTC_CPU_FREQ_2M = 4, //!< 2 MHz - RTC_CPU_320M_80M = 5, //!< for test - RTC_CPU_320M_160M = 6, //!< for test - RTC_CPU_FREQ_XTAL_DIV2 = 7, //!< XTAL/2 after reset -} rtc_cpu_freq_t; - /** * @brief CPU clock source */ typedef enum { RTC_CPU_FREQ_SRC_XTAL, //!< XTAL - RTC_CPU_FREQ_SRC_PLL, //!< PLL (480M or 320M) - RTC_CPU_FREQ_SRC_8M, //!< Internal 8M RTC oscillator - RTC_CPU_FREQ_SRC_APLL //!< APLL + RTC_CPU_FREQ_SRC_PLL, //!< PLL (96M) + RTC_CPU_FREQ_SRC_8M, //!< Internal 18M RTC oscillator + RTC_CPU_FREQ_SRC_XTAL_D2 //!< XTAL/2 } rtc_cpu_freq_src_t; /** @@ -178,7 +180,7 @@ typedef struct rtc_cpu_freq_config_s { typedef enum { RTC_SLOW_FREQ_RTC = 0, //!< Internal 150 kHz RC oscillator RTC_SLOW_FREQ_32K_XTAL = 1, //!< External 32 kHz XTAL - RTC_SLOW_FREQ_8MD256 = 2, //!< Internal 8 MHz RC oscillator, divided by 256 + RTC_SLOW_FREQ_RC32K = 2, //!< Internal 32 KHz RC oscillator } rtc_slow_freq_t; /** @@ -202,7 +204,7 @@ typedef enum { */ typedef enum { RTC_CAL_RTC_MUX = 0, //!< Currently selected RTC SLOW_CLK - RTC_CAL_8MD256 = 1, //!< Internal 8 MHz RC oscillator, divided by 256 + RTC_CAL_RC32K = 1, //!< Internal 32 kHz RC oscillator RTC_CAL_32K_XTAL = 2 //!< External 32 kHz XTAL } rtc_cal_sel_t; @@ -217,21 +219,23 @@ typedef struct { uint32_t clk_rtc_clk_div : 8; uint32_t clk_8m_clk_div : 3; //!< RTC 8M clock divider (division is by clk_8m_div+1, i.e. 0 means 8MHz frequency) uint32_t slow_clk_dcap : 8; //!< RTC 150k clock adjustment parameter (higher value leads to lower frequency) - uint32_t clk_8m_dfreq : 8; //!< RTC 8m clock adjustment parameter (higher value leads to higher frequency) + uint32_t clk_8m_dfreq : 10; //!< RTC 8m clock adjustment parameter (higher value leads to higher frequency) + uint32_t root_clk_slt : 2; //!< Select clock root source for esp32h2 (default 0: xtal_32M) } rtc_clk_config_t; /** * Default initializer for rtc_clk_config_t */ #define RTC_CLK_CONFIG_DEFAULT() { \ - .xtal_freq = RTC_XTAL_FREQ_40M, \ - .cpu_freq_mhz = 80, \ + .xtal_freq = RTC_XTAL_FREQ_32M, \ + .cpu_freq_mhz = 32, \ .fast_freq = RTC_FAST_FREQ_8M, \ .slow_freq = RTC_SLOW_FREQ_RTC, \ - .clk_rtc_clk_div = 0, \ - .clk_8m_clk_div = 0, \ + .clk_rtc_clk_div = 1, \ + .clk_8m_clk_div = 1, \ .slow_clk_dcap = RTC_CNTL_SCK_DCAP_DEFAULT, \ .clk_8m_dfreq = RTC_CNTL_CK8M_DFREQ_DEFAULT, \ + .root_clk_slt = 0, \ } typedef struct { @@ -241,6 +245,7 @@ typedef struct { uint32_t dbuf: 1; } x32k_config_t; + #define X32K_CONFIG_DEFAULT() { \ .dac = 3, \ .dres = 3, \ @@ -248,6 +253,14 @@ typedef struct { .dbuf = 1, \ } +typedef struct { + uint32_t dfreq : 10; +} rc32k_config_t; + +#define RC32K_CONFIG_DEFAULT() {\ + .dfreq = RTC_CNTL_RC32K_DFREQ_DEFAULT,\ +} + typedef struct { uint16_t wifi_powerup_cycles : 7; uint16_t wifi_wait_cycles : 9; @@ -499,6 +512,10 @@ void rtc_clk_apb_freq_update(uint32_t apb_freq); */ uint32_t rtc_clk_apb_freq_get(void); +void rtc_clk_cpu_freq_set(uint32_t source, uint32_t div); +uint32_t rtc_clk_ahb_freq_get(void); + + uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles); /** @@ -633,9 +650,10 @@ typedef struct { uint32_t rtc_fastmem_pd_en : 1; //!< power down RTC fast memory uint32_t rtc_slowmem_pd_en : 1; //!< power down RTC slow memory uint32_t rtc_peri_pd_en : 1; //!< power down RTC peripherals - uint32_t wifi_pd_en : 1; //!< power down WiFi + uint32_t dig_ret_pd_en : 1; //!< power down dig_ret uint32_t bt_pd_en : 1; //!< power down BT - uint32_t cpu_pd_en : 1; //!< power down CPU, but not restart when lightsleep. + uint32_t cpu_pd_en : 1; //!< power down CPU, but not restart when lightsleep. + uint32_t int_8m_pd_en : 1; //!< Power down Internal 8M oscillator uint32_t dig_peri_pd_en : 1; //!< power down digital peripherals uint32_t deep_slp : 1; //!< power down digital domain uint32_t wdt_flashboot_mod_en : 1; //!< enable WDT flashboot mode @@ -644,6 +662,7 @@ typedef struct { uint32_t rtc_dbias_wak : 5; //!< set bias for RTC domain, in active mode uint32_t rtc_dbias_slp : 5; //!< set bias for RTC domain, in sleep mode uint32_t vddsdio_pd_en : 1; //!< power down VDDSDIO regulator + uint32_t xtal_fpu : 1; //!< keep main XTAL powered up in sleep uint32_t deep_slp_reject : 1; uint32_t light_slp_reject : 1; } rtc_sleep_config_t; @@ -656,23 +675,30 @@ typedef struct { * * @param RTC_SLEEP_PD_x flags combined using bitwise OR */ +#define is_dslp(pd_flags) ((pd_flags) & RTC_SLEEP_PD_DIG) #define RTC_SLEEP_CONFIG_DEFAULT(sleep_flags) { \ .lslp_mem_inf_fpu = 0, \ .rtc_mem_inf_follow_cpu = ((sleep_flags) & RTC_SLEEP_PD_RTC_MEM_FOLLOW_CPU) ? 1 : 0, \ .rtc_fastmem_pd_en = ((sleep_flags) & RTC_SLEEP_PD_RTC_FAST_MEM) ? 1 : 0, \ .rtc_slowmem_pd_en = ((sleep_flags) & RTC_SLEEP_PD_RTC_SLOW_MEM) ? 1 : 0, \ .rtc_peri_pd_en = ((sleep_flags) & RTC_SLEEP_PD_RTC_PERIPH) ? 1 : 0, \ - .wifi_pd_en = ((sleep_flags) & RTC_SLEEP_PD_WIFI) ? 1 : 0, \ + .dig_ret_pd_en = ((sleep_flags) & RTC_SLEEP_PD_DIG_RET) ? 1 : 0, \ .bt_pd_en = ((sleep_flags) & RTC_SLEEP_PD_BT) ? 1 : 0, \ .cpu_pd_en = ((sleep_flags) & RTC_SLEEP_PD_CPU) ? 1 : 0, \ + .int_8m_pd_en = is_dslp(sleep_flags) ? 1 : ((sleep_flags) & RTC_SLEEP_PD_INT_8M) ? 1 : 0, \ .dig_peri_pd_en = ((sleep_flags) & RTC_SLEEP_PD_DIG_PERIPH) ? 1 : 0, \ .deep_slp = ((sleep_flags) & RTC_SLEEP_PD_DIG) ? 1 : 0, \ .wdt_flashboot_mod_en = 0, \ .dig_dbias_wak = RTC_CNTL_DBIAS_1V10, \ - .dig_dbias_slp = RTC_CNTL_DBIAS_SLP, \ + .dig_dbias_slp = is_dslp(sleep_flags) ? RTC_CNTL_DBIAS_SLP \ + : !((sleep_flags) & RTC_SLEEP_PD_INT_8M) ? RTC_CNTL_DBIAS_1V10 \ + : RTC_CNTL_DBIAS_SLP, \ .rtc_dbias_wak = RTC_CNTL_DBIAS_1V10, \ - .rtc_dbias_slp = RTC_CNTL_DBIAS_SLP, \ + .rtc_dbias_slp = is_dslp(sleep_flags) ? RTC_CNTL_DBIAS_SLP \ + : !((sleep_flags) & RTC_SLEEP_PD_INT_8M) ? RTC_CNTL_DBIAS_1V10 \ + : RTC_CNTL_DBIAS_SLP, \ .vddsdio_pd_en = ((sleep_flags) & RTC_SLEEP_PD_VDDSDIO) ? 1 : 0, \ + .xtal_fpu = is_dslp(sleep_flags) ? 0 : ((sleep_flags) & RTC_SLEEP_PD_XTAL) ? 0 : 1, \ .deep_slp_reject = 1, \ .light_slp_reject = 1 \ }; @@ -683,10 +709,12 @@ typedef struct { #define RTC_SLEEP_PD_RTC_FAST_MEM BIT(3) //!< Power down RTC FAST memory #define RTC_SLEEP_PD_RTC_MEM_FOLLOW_CPU BIT(4) //!< RTC FAST and SLOW memories are automatically powered up and down along with the CPU #define RTC_SLEEP_PD_VDDSDIO BIT(5) //!< Power down VDDSDIO regulator -#define RTC_SLEEP_PD_WIFI BIT(6) //!< Power down WIFI +#define RTC_SLEEP_PD_DIG_RET BIT(6) //!< Power down WIFI #define RTC_SLEEP_PD_BT BIT(7) //!< Power down BT #define RTC_SLEEP_PD_CPU BIT(8) //!< Power down CPU when in lightsleep, but not restart #define RTC_SLEEP_PD_DIG_PERIPH BIT(9) //!< Power down DIG peripherals +#define RTC_SLEEP_PD_INT_8M BIT(10) //!< Power down Internal 8M oscillator +#define RTC_SLEEP_PD_XTAL BIT(11) //!< Power down main XTAL /** * @brief Prepare the chip to enter sleep mode @@ -791,11 +819,11 @@ typedef struct { uint32_t pll_wait : 8; //!< Number of rtc_fast_clk cycles to wait for PLL to be ready uint32_t clkctl_init : 1; //!< Perform clock control related initialization uint32_t pwrctl_init : 1; //!< Perform power control related initialization - uint32_t rtc_dboost_fpd : 1; //!< Force power down RTC_DBOOST uint32_t xtal_fpu : 1; uint32_t bbpll_fpu : 1; uint32_t cpu_waiti_clk_gate : 1; uint32_t cali_ocode : 1; //!< Calibrate Ocode to make bangap voltage more precise. + uint32_t pmu_ctl : 1; } rtc_config_t; /** @@ -810,17 +838,93 @@ typedef struct { .pll_wait = RTC_CNTL_PLL_BUF_WAIT_DEFAULT, \ .clkctl_init = 1, \ .pwrctl_init = 1, \ - .rtc_dboost_fpd = 1, \ .xtal_fpu = 0, \ .bbpll_fpu = 0, \ .cpu_waiti_clk_gate = 1, \ - .cali_ocode = 0\ + .cali_ocode = 0, \ + .pmu_ctl = 1\ +} +typedef struct { + /* data */ + uint32_t or_en_cont_cal : 1; //!< default:0 rtc_init:0 pvt can be enable by either this register or digital -- if_en_cont_cal + uint32_t enx_rtc_dreg : 1; //!< default:1 rtc_init:1 use i2c registers to configure rtc regulator voltage level instead of pvt result -- int_dreg + uint32_t enx_dig_dreg : 1; //!< default:1 rtc_init:1 use i2c registers to configure dig regulator voltage level instead of pvt result -- int_dreg + uint32_t en_i2c_rtc_dreg : 1; //!< default:1 rtc_init:0 1: i2c_rtc_dreg; 0: if_rtc_dreg + uint32_t en_i2c_dig_dreg : 1; //!< default:1 rtc_init:0 1: i2c_dig_dreg; 0: if_dig_dreg + uint32_t en_i2c_rtc_dreg_slp : 1; //!< default:1 rtc_init:0 1: i2c_rtc_dreg_slp; 0: if_rtc_dreg_slp + uint32_t en_i2c_dig_dreg_slp : 1; //!< default:1 rtc_init:0 1: i2c_dig_dreg_slp; 0: if_dig_dreg_slp + uint32_t or_xpd_rtc_slave_3p3 : 1; //!< default:1 rtc_init:0 to turn off rtc slave, which is only required before DCDC running + uint32_t or_xpd_rtc_reg : 1; //!< default:1 rtc_init:0 handover control to digital -- if_xpd_rtc_reg + uint32_t or_xpd_dig_reg : 1; //!< default:1 rtc_init:0 handover control to digital -- if_xpd_dig_reg + uint32_t or_pd_rtc_reg_slp : 1; //!< default:0 rtc_init:1 configure this i2c to control rtc_sleep_regulator on off, no coressponding digital control signal + uint32_t or_pd_dig_reg_slp : 1; //!< default:0 rtc_init:0 default value 0 puts dig_sleep_regulator controlled by digital -- if_xpd_dig_reg_slp + uint32_t or_xpd_dcdc : 1; //!< default:1 rtc_init:0 handover control to digital -- if_xpd_dcdc + uint32_t or_disalbe_deep_sleep_dcdc : 1; //!< default:1 rtc_init:0 handover control to digital -- if_enable_deep_sleep_dcdc + uint32_t or_disalbe_light_sleep_dcdc : 1; //!< default:1 rtc_init:0 handover control to digital -- if_enable_light_sleep_dcdc + uint32_t or_enalbe_trx_mode_dcdc : 1; //!< default:1 rtc_init:0 handover control to digital -- if_enable_trx_mode_dcdc + uint32_t or_enx_reg_dcdc : 1; //!< default:0 rtc_init:1 handover dcdc configuration registers to digital control signals, including popenb, sstime, ccm, vset, fsw, dcmlevel, dcm2enb, ramp, ramplevel + uint32_t or_unlock_dcdc : 1; //!< default:0 rtc_init:0 not used in this version of silicon, can be unleashed if metal change if_vgood_lock_dcdc signal to high + uint32_t or_force_lock_dcdc : 1; //!< default:0 rtc_init:0 dcdc will be locked and shut-off if this register sets to 1 + uint32_t or_enb_slow_clk : 1; //!< default:0 rtc_init:1 handover slow clock control to digital -- if_enb_slow_clk + uint32_t or_xpd_trx : 1; //!< default:1 rtc_init:0 handover trx control to digital -- if_xpd_trx + uint32_t or_en_reset_chip : 1; //!< default:0 rtc_init:1 handover reset chip control to digital -- if_reset_chip + uint32_t or_force_xpd_reg_slave : 1; //!< default:0 rtc_init:1 set this reg to 1 after DCDC ready, to have rtc & dig slave control independent of DCDC status +} pmu_config_t; + +#define PMU_CONFIG_DEFAULT() {\ + .or_en_cont_cal = 0, \ + .enx_rtc_dreg = 1, \ + .enx_dig_dreg = 1, \ + .en_i2c_rtc_dreg = 0, \ + .en_i2c_dig_dreg = 0, \ + .en_i2c_rtc_dreg_slp = 0, \ + .en_i2c_dig_dreg_slp = 0, \ + .or_xpd_rtc_slave_3p3 = 0, \ + .or_xpd_rtc_reg = 0, \ + .or_xpd_dig_reg = 0, \ + .or_pd_rtc_reg_slp = 0, \ + .or_pd_dig_reg_slp = 0, \ + .or_xpd_dcdc = 0, \ + .or_disalbe_deep_sleep_dcdc = 0, \ + .or_disalbe_light_sleep_dcdc = 0, \ + .or_enalbe_trx_mode_dcdc = 0, \ + .or_enx_reg_dcdc = 1, \ + .or_unlock_dcdc = 0, \ + .or_force_lock_dcdc = 0, \ + .or_xpd_trx = 0, \ + .or_en_reset_chip = 1, \ + .or_force_xpd_reg_slave = 1\ +} + +typedef struct { + uint32_t swt_idle: 1; //!< If 1, swt_idle is sleep mode ; if 0, swt_idle is active mode + uint32_t swt_monitor: 1; //!< If 1, swt_monitor is sleep mode ; if 0, swt_monitor is active mode + uint32_t swt_slp: 1; //!< If 1, swt_slp is sleep mode ; if 0, swt_slp is active mode +} dbias_swt_cfg_t; + +#define DBIAS_SWITCH_CONFIG_DEFAULT(){\ + .swt_idle = 0, \ + .swt_monitor = 1, \ + .swt_slp = 1\ +} + +typedef struct { + /* data */ + uint32_t dig_regul0_en: 1; //!< If 1, dig_regulator0 is ctl by fsm; if 0, dig_regulator0 force pd. + uint32_t dig_regul1_en: 1; //!< If 1, dig_regulator1 is ctl by fsm; if 0, dig_regulator1 force pd. + uint32_t rtc_regul0_en: 1; //!< If 1, rtc_regulator0 is ctl by fsm; if 0, rtc_regulator0 force pd. +} regulator_cfg_t; + +#define REGULATOR_SET_DEFAULT(){\ + .dig_regul0_en = 1, \ + .dig_regul1_en = 1, \ + .rtc_regul0_en = 1, \ } /** - * Initialize RTC clock and power control related functions - * @param cfg configuration options as rtc_config_t - */ +* Initialize RTC clock and power control related functions +* @param cfg configuration options as rtc_config_t +*/ void rtc_init(rtc_config_t cfg); /** @@ -853,6 +957,47 @@ rtc_vddsdio_config_t rtc_vddsdio_get_config(void); */ void rtc_vddsdio_set_config(rtc_vddsdio_config_t config); + +/* Select clock root source for esp32h2. return source clk freq_mhz + */ +uint32_t root_clk_slt(uint32_t source); +uint32_t root_clk_get(void); + +/** + * Regulator config + */ +typedef struct { + uint32_t dig_source : 1; + uint32_t dig_active_dbias : 5; + uint32_t dig_slp_dbias : 5; + uint32_t rtc_source : 1; + uint32_t rtc_active_dbias : 5; + uint32_t rtc_slp_dbias : 5; +} regulator_config_t; + +#define REGULATOR0_CONFIG_DEFAULT() {\ + .dig_source = 0, \ + .dig_active_dbias = 20, \ + .dig_slp_dbias = 8, \ + .rtc_source = 0, \ + .rtc_active_dbias = 20, \ + .rtc_slp_dbias = 8 \ +} +#define REGULATOR1_CONFIG_DEFAULT() {\ + .dig_source = 1, \ + .dig_active_dbias = 15, \ + .dig_slp_dbias = 8, \ + .rtc_source = 1, \ + .rtc_active_dbias = 15, \ + .rtc_slp_dbias = 8 \ +} + + +/** + * gpio hangup + */ +void rtc_gpio_hangup(uint32_t gpio_no); + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32h2/include/soc/rtc_cntl_struct.h b/components/soc/esp32h2/include/soc/rtc_cntl_struct.h index 68100c9cee..473f236249 100644 --- a/components/soc/esp32h2/include/soc/rtc_cntl_struct.h +++ b/components/soc/esp32h2/include/soc/rtc_cntl_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct rtc_cntl_dev_s { union { struct { uint32_t sw_stall_appcpu_c0: 2; /*{reg_sw_stall_appcpu_c1[5:0] reg_sw_stall_appcpu_c0[1:0]} == 0x86 will stall APP CPU*/ diff --git a/components/soc/esp32h2/include/soc/rtc_i2c_struct.h b/components/soc/esp32h2/include/soc/rtc_i2c_struct.h index 5141eebcd6..9f97a70cad 100644 --- a/components/soc/esp32h2/include/soc/rtc_i2c_struct.h +++ b/components/soc/esp32h2/include/soc/rtc_i2c_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct rtc_i2c_dev_s { union { struct { uint32_t period: 20; /*time period that scl = 0*/ diff --git a/components/soc/esp32h2/include/soc/sensitive_struct.h b/components/soc/esp32h2/include/soc/sensitive_struct.h index cf27320a79..8747c8a5e0 100644 --- a/components/soc/esp32h2/include/soc/sensitive_struct.h +++ b/components/soc/esp32h2/include/soc/sensitive_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif #include "soc.h" -typedef volatile struct { +typedef volatile struct sensitive_dev_s { union { struct { uint32_t reg_rom_table_lock : 1; /*rom_table_lock*/ diff --git a/components/soc/esp32h2/include/soc/soc.h b/components/soc/esp32h2/include/soc/soc.h index 4590fb39b7..68854d35d5 100644 --- a/components/soc/esp32h2/include/soc/soc.h +++ b/components/soc/esp32h2/include/soc/soc.h @@ -66,7 +66,6 @@ #define DR_REG_UHCI0_BASE 0x60014000 #define DR_REG_SLCHOST_BASE 0x60019000 #define DR_REG_RMT_BASE 0x60016000 -#define DR_REG_PCNT_BASE 0x60017000 #define DR_REG_SLC_BASE 0x6002D000 #define DR_REG_LEDC_BASE 0x60019000 #define DR_REG_EFUSE_BASE 0x6001A000 @@ -80,7 +79,6 @@ #define DR_REG_SPI2_BASE 0x60024000 #define DR_REG_SPI3_BASE 0x60025000 #define DR_REG_SYSCON_BASE 0x60026000 -#define DR_REG_APB_CTRL_BASE 0x60026000 /* Old name for SYSCON, to be removed */ #define DR_REG_I2C1_EXT_BASE 0x60027000 #define DR_REG_SDMMC_BASE 0x60028000 #define DR_REG_CAN_BASE 0x6002B000 @@ -229,10 +227,10 @@ #if CONFIG_IDF_ENV_FPGA #define APB_CLK_FREQ ( 32*1000000 ) #else -#define APB_CLK_FREQ ( 80*1000000 ) +#define APB_CLK_FREQ ( 48*1000000 ) //ESP32H2-TODO: IDF-3786 #endif #define REF_CLK_FREQ ( 1000000 ) -#define RTC_CLK_FREQ (20*1000000) +#define RTC_CLK_FREQ (17.5*1000000) #define XTAL_CLK_FREQ (32*1000000) #define UART_CLK_FREQ APB_CLK_FREQ #define WDT_CLK_FREQ APB_CLK_FREQ @@ -298,57 +296,13 @@ // Start (highest address) of ROM boot stack, only relevant during early boot #define SOC_ROM_STACK_START 0x3fcebf10 -//interrupt cpu using table, Please see the core-isa.h -/************************************************************************************************************* - * Intr num Level Type PRO CPU usage - * 0 1 extern level Panic - * 1 1 extern level WMAC - * 2 1 extern level - * 3 1 extern level - * 4 1 extern level WBB - * 5 1 extern level BT/BLE Controller - * 6 1 timer FreeRTOS Tick(L1) - * 7 1 software - * 8 1 extern level BT/BLE BB(RX/TX) - * 9 1 extern level - * 10 1 extern edge - * 11 3 profiling - * 12 1 extern level - * 13 1 extern level - * 14 7 nmi Reserved - * 15 3 timer FreeRTOS Tick(L3) - * 16 5 timer - * 17 1 extern level - * 18 1 extern level - * 19 2 extern level - * 20 2 extern level - * 21 2 extern level - * 22 3 extern edge - * 23 3 extern level - * 24 4 extern level TG1_WDT - * 25 4 extern level CACHEERR - * 26 5 extern level - * 27 3 extern level Reserved - * 28 4 extern edge Reserved - * 29 3 software Reserved - * 30 4 extern edge Reserved - * 31 5 extern level - ************************************************************************************************************* - */ +//On RISC-V CPUs, the interrupt sources are all external interrupts, whose type, source and priority are configured by SW. +//There is no HW NMI conception. SW should controlled the masked levels through INT_THRESH_REG. -//CPU0 Interrupt number reserved, not touch this. -#define ETS_WMAC_INUM 1 -//#define ETS_BT_HOST_INUM 1 -#define ETS_WBB_INUM 4 -#define ETS_SYSTICK_INUM 9 -#define ETS_TG0_T1_INUM 10 /* use edge interrupt */ -#define ETS_CPU_INTR0_INUM 12 /* used as freertos soft intr */ -#define ETS_FRC1_INUM 22 +//CPU0 Interrupt number reserved in riscv/vector.S, not touch this. #define ETS_T1_WDT_INUM 24 #define ETS_CACHEERR_INUM 25 #define ETS_MEMPROT_ERR_INUM 26 -#define ETS_DPORT_INUM 28 - //CPU0 Max valid interrupt number #define ETS_MAX_INUM 31 diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index 64fa8dd3b9..3c69d5360e 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -6,6 +6,7 @@ #pragma once #define SOC_CPU_CORES_NUM 1 +#define SOC_DEDICATED_GPIO_SUPPORTED 1 #define SOC_GDMA_SUPPORTED 1 #define SOC_TWAI_SUPPORTED 1 #define SOC_BT_SUPPORTED 1 @@ -37,7 +38,7 @@ #define SOC_ADC_MAX_BITWIDTH (12) #define SOC_ADC_DIGI_FILTER_NUM (2) #define SOC_ADC_DIGI_MONITOR_NUM (2) -#define SOC_ADC_HW_CALIBRATION_V1 (1) /*!< support HW offset calibration */ +#define SOC_ADC_CALIBRATION_V1_SUPPORTED (1) /*!< support HW offset calibration version 1*/ #define SOC_ADC_SUPPORT_DMA_MODE(PERIPH_NUM) 1 //F_sample = F_digi_con / 2 / interval. F_digi_con = 5M for now. 30 <= interva <= 4095 #define SOC_ADC_SAMPLE_FREQ_THRES_HIGH 83333 @@ -92,6 +93,11 @@ // Support to configure sleep status #define SOC_GPIO_SUPPORT_SLP_SWITCH (1) +/*-------------------------- Dedicated GPIO CAPS -----------------------------*/ +#define SOC_DEDIC_GPIO_OUT_CHANNELS_NUM (8) /*!< 8 outward channels on each CPU core */ +#define SOC_DEDIC_GPIO_IN_CHANNELS_NUM (8) /*!< 8 inward channels on each CPU core */ +#define SOC_DEDIC_PERIPH_AUTO_ENABLE (1) /*!< The dedicated GPIO peripheral is enabled automatically */ + /*-------------------------- I2C CAPS ----------------------------------------*/ // ESP32-C3 have 2 I2C. #define SOC_I2C_NUM (1) @@ -106,11 +112,10 @@ /*-------------------------- I2S CAPS ----------------------------------------*/ #define SOC_I2S_NUM (1) - -#define SOC_I2S_APLL_MIN_FREQ (250000000) -#define SOC_I2S_APLL_MAX_FREQ (500000000) -#define SOC_I2S_APLL_MIN_RATE (10675) //in Hz, I2S Clock rate limited by hardware -#define SOC_I2S_MAX_BUFFER_SIZE (4 * 1024 * 1024) //the maximum RAM can be allocated +#define SOC_I2S_SUPPORTS_PCM (1) +#define SOC_I2S_SUPPORTS_PDM_TX (1) +#define SOC_I2S_SUPPORTS_PDM_CODEC (1) +#define SOC_I2S_SUPPORTS_TDM (1) /*-------------------------- LEDC CAPS ---------------------------------------*/ #define SOC_LEDC_SUPPORT_XTAL_CLOCK (1) @@ -235,9 +240,8 @@ #define SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX (32) /*-------------------------- UART CAPS ---------------------------------------*/ -// ESP32-C3 has 2 UARTs +// ESP32-H2 has 2 UARTs #define SOC_UART_NUM (2) - #define SOC_UART_FIFO_LEN (128) /*!< The UART hardware FIFO length */ #define SOC_UART_BITRATE_MAX (5000000) /*!< Max bit rate supported by UART */ @@ -247,9 +251,6 @@ // 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) -/*-------------------------- WI-FI HARDWARE TSF CAPS -------------------------------*/ -#define SOC_WIFI_HW_TSF (1) - /*-------------------------- COEXISTENCE HARDWARE PTI CAPS -------------------------------*/ #define SOC_COEX_HW_PTI (1) @@ -257,16 +258,9 @@ #define SOC_PHY_DIG_REGS_MEM_SIZE (21*4) #define SOC_MAC_BB_PD_MEM_SIZE (192*4) -/*--------------- WIFI LIGHT SLEEP CLOCK WIDTH CAPS --------------------------*/ -#define SOC_WIFI_LIGHT_SLEEP_CLK_WIDTH (12) - /*-------------------------- Power Management CAPS ----------------------------*/ -#define SOC_PM_SUPPORT_WIFI_WAKEUP (1) - #define SOC_PM_SUPPORT_BT_WAKEUP (1) #define SOC_PM_SUPPORT_CPU_PD (1) -#define SOC_PM_SUPPORT_WIFI_PD (1) - #define SOC_PM_SUPPORT_BT_PD (1) diff --git a/components/soc/esp32h2/include/soc/spi_mem_struct.h b/components/soc/esp32h2/include/soc/spi_mem_struct.h index e0f62b0d15..cde08c0207 100644 --- a/components/soc/esp32h2/include/soc/spi_mem_struct.h +++ b/components/soc/esp32h2/include/soc/spi_mem_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct spi_mem_dev_s { union { struct { uint32_t mst_st: 4; /*The current status of SPI1 master FSM.*/ diff --git a/components/soc/esp32h2/include/soc/spi_struct.h b/components/soc/esp32h2/include/soc/spi_struct.h index 867510549d..dcdec116ad 100644 --- a/components/soc/esp32h2/include/soc/spi_struct.h +++ b/components/soc/esp32h2/include/soc/spi_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif #include "soc.h" -typedef volatile struct { +typedef volatile struct spi_dev_s { union { struct { uint32_t conf_bitlen : 18; /*Define the APB cycles of SPI_CONF state. Can be configured in CONF state.*/ diff --git a/components/soc/esp32h2/include/soc/syscon_struct.h b/components/soc/esp32h2/include/soc/syscon_struct.h index e25e44179f..be70d31cab 100644 --- a/components/soc/esp32h2/include/soc/syscon_struct.h +++ b/components/soc/esp32h2/include/soc/syscon_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct syscon_dev_s { uint32_t reserved_0; uint32_t reserved_4; uint32_t reserved_8; @@ -128,7 +128,7 @@ typedef volatile struct { uint32_t reserved1: 31; }; uint32_t val; - } apb_ctrl_sdio_ctrl; + } sdio_ctrl; union { struct { uint32_t redcy_sig0: 31; @@ -245,7 +245,7 @@ typedef volatile struct { uint32_t reserved1: 31; }; uint32_t val; - } apb_ctrlclk_conf; + } clk_conf; uint32_t reserved_e4; uint32_t reserved_e8; uint32_t reserved_ec; @@ -444,7 +444,7 @@ typedef volatile struct { uint32_t reserved_3f0; uint32_t reserved_3f4; uint32_t reserved_3f8; - uint32_t apb_ctrl_date; /*Version control*/ + uint32_t date; /*Version control*/ } syscon_dev_t; extern syscon_dev_t SYSCON; #ifdef __cplusplus diff --git a/components/soc/esp32h2/include/soc/system_struct.h b/components/soc/esp32h2/include/soc/system_struct.h index 58c1c6b99f..8b9d4892bb 100644 --- a/components/soc/esp32h2/include/soc/system_struct.h +++ b/components/soc/esp32h2/include/soc/system_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif #include "soc.h" -typedef volatile struct { +typedef volatile struct system_dev_s { union { struct { uint32_t reserved0 : 6; /*reserved*/ diff --git a/components/soc/esp32h2/include/soc/systimer_struct.h b/components/soc/esp32h2/include/soc/systimer_struct.h index af41b1f3e2..f10bc1f126 100644 --- a/components/soc/esp32h2/include/soc/systimer_struct.h +++ b/components/soc/esp32h2/include/soc/systimer_struct.h @@ -88,6 +88,7 @@ typedef union { * update timer_unit0 */ uint32_t timer_unit_update: 1; + uint32_t reserved31: 1; }; uint32_t val; } systimer_unit_op_reg_t; @@ -102,6 +103,7 @@ typedef struct { * timer unit load high 32 bit */ uint32_t timer_unit_load_hi: 20; + uint32_t reserved20: 12; }; uint32_t val; } hi; @@ -126,6 +128,7 @@ typedef struct { * timer target high 32 bit */ uint32_t timer_target_hi: 20; + uint32_t reserved20: 12; }; uint32_t val; } hi; @@ -172,6 +175,7 @@ typedef struct { * timer read value high 20bit */ uint32_t timer_unit_value_hi: 20; + uint32_t reserved20: 12; }; uint32_t val; } hi; @@ -195,6 +199,7 @@ typedef union { * timer comp load value */ uint32_t timer_comp_load: 1; + uint32_t reserved1: 31; }; uint32_t val; } systimer_comp_load_reg_t; @@ -208,6 +213,7 @@ typedef union { * timer unit load value */ uint32_t timer_unit_load: 1; + uint32_t reserved1: 31; }; uint32_t val; } systimer_unit_load_reg_t; @@ -230,6 +236,7 @@ typedef union { * interupt2 enable */ uint32_t target2_int_ena: 1; + uint32_t reserved3: 29; }; uint32_t val; } systimer_int_ena_reg_t; @@ -251,6 +258,7 @@ typedef union { * interupt2 raw */ uint32_t target2_int_raw: 1; + uint32_t reserved3: 29; }; uint32_t val; } systimer_int_raw_reg_t; @@ -272,6 +280,7 @@ typedef union { * interupt2 clear */ uint32_t target2_int_clr: 1; + uint32_t reserved3: 29; }; uint32_t val; } systimer_int_clr_reg_t; @@ -293,6 +302,7 @@ typedef union { * reg_target2_int_st */ uint32_t target2_int_st: 1; + uint32_t reserved3: 29; }; uint32_t val; } systimer_int_st_reg_t; diff --git a/components/soc/esp32h2/include/soc/timer_group_reg.h b/components/soc/esp32h2/include/soc/timer_group_reg.h index ba8cba2bbe..4d591035fc 100644 --- a/components/soc/esp32h2/include/soc/timer_group_reg.h +++ b/components/soc/esp32h2/include/soc/timer_group_reg.h @@ -1,24 +1,17 @@ -// 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. -#ifndef _SOC_TIMG_REG_H_ -#define _SOC_TIMG_REG_H_ - +/** + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once +#include +#include "soc/soc.h" #ifdef __cplusplus extern "C" { #endif -#include "soc.h" + +#define DR_REG_TIMG_BASE(i) REG_TIMG_BASE(i) /* The value that needs to be written to TIMG_WDT_WKEY to write-enable the wdt registers */ #define TIMG_WDT_WKEY_VALUE 0x50D83AA1 @@ -29,418 +22,559 @@ extern "C" { #define TIMG_WDT_STG_SEL_RESET_CPU 2 #define TIMG_WDT_STG_SEL_RESET_SYSTEM 3 -#define TIMG_WDT_RESET_LENGTH_100_NS 0 -#define TIMG_WDT_RESET_LENGTH_200_NS 1 -#define TIMG_WDT_RESET_LENGTH_300_NS 2 -#define TIMG_WDT_RESET_LENGTH_400_NS 3 -#define TIMG_WDT_RESET_LENGTH_500_NS 4 -#define TIMG_WDT_RESET_LENGTH_800_NS 5 -#define TIMG_WDT_RESET_LENGTH_1600_NS 6 -#define TIMG_WDT_RESET_LENGTH_3200_NS 7 -/* Possible values for TIMG_WDT_STGx */ -#define TIMG_WDT_STG_SEL_OFF 0 -#define TIMG_WDT_STG_SEL_INT 1 -#define TIMG_WDT_STG_SEL_RESET_CPU 2 -#define TIMG_WDT_STG_SEL_RESET_SYSTEM 3 +/* Possible values for TIMG_WDT_CPU_RESET_LENGTH and TIMG_WDT_SYS_RESET_LENGTH */ +#define TIMG_WDT_RESET_LENGTH_100_NS 0 +#define TIMG_WDT_RESET_LENGTH_200_NS 1 +#define TIMG_WDT_RESET_LENGTH_300_NS 2 +#define TIMG_WDT_RESET_LENGTH_400_NS 3 +#define TIMG_WDT_RESET_LENGTH_500_NS 4 +#define TIMG_WDT_RESET_LENGTH_800_NS 5 +#define TIMG_WDT_RESET_LENGTH_1600_NS 6 +#define TIMG_WDT_RESET_LENGTH_3200_NS 7 -#define TIMG_T0CONFIG_REG(i) (REG_TIMG_BASE(i) + 0x0000) -/* TIMG_T0_EN : R/W ;bitpos:[31] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T0_EN (BIT(31)) -#define TIMG_T0_EN_M (BIT(31)) -#define TIMG_T0_EN_V 0x1 -#define TIMG_T0_EN_S 31 -/* TIMG_T0_INCREASE : R/W ;bitpos:[30] ;default: 1'h1 ; */ -/*description: */ -#define TIMG_T0_INCREASE (BIT(30)) -#define TIMG_T0_INCREASE_M (BIT(30)) -#define TIMG_T0_INCREASE_V 0x1 -#define TIMG_T0_INCREASE_S 30 -/* TIMG_T0_AUTORELOAD : R/W ;bitpos:[29] ;default: 1'h1 ; */ -/*description: */ -#define TIMG_T0_AUTORELOAD (BIT(29)) -#define TIMG_T0_AUTORELOAD_M (BIT(29)) -#define TIMG_T0_AUTORELOAD_V 0x1 -#define TIMG_T0_AUTORELOAD_S 29 -/* TIMG_T0_DIVIDER : R/W ;bitpos:[28:13] ;default: 16'h1 ; */ -/*description: */ -#define TIMG_T0_DIVIDER 0x0000FFFF -#define TIMG_T0_DIVIDER_M ((TIMG_T0_DIVIDER_V)<<(TIMG_T0_DIVIDER_S)) -#define TIMG_T0_DIVIDER_V 0xFFFF -#define TIMG_T0_DIVIDER_S 13 -/* TIMG_T0_DIVCNT_RST : WT ;bitpos:[12] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T0_DIVCNT_RST (BIT(12)) -#define TIMG_T0_DIVCNT_RST_M (BIT(12)) -#define TIMG_T0_DIVCNT_RST_V 0x1 -#define TIMG_T0_DIVCNT_RST_S 12 -/* TIMG_T0_ALARM_EN : R/W/SC ;bitpos:[10] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T0_ALARM_EN (BIT(10)) -#define TIMG_T0_ALARM_EN_M (BIT(10)) -#define TIMG_T0_ALARM_EN_V 0x1 -#define TIMG_T0_ALARM_EN_S 10 -/* TIMG_T0_USE_XTAL : R/W ;bitpos:[9] ;default: 1'd0 ; */ -/*description: */ -#define TIMG_T0_USE_XTAL (BIT(9)) -#define TIMG_T0_USE_XTAL_M (BIT(9)) -#define TIMG_T0_USE_XTAL_V 0x1 +/** TIMG_T0CONFIG_REG register + * Timer 0 configuration register + */ +#define TIMG_T0CONFIG_REG(i) (DR_REG_TIMG_BASE(i) + 0x0) +/** TIMG_T0_USE_XTAL : R/W; bitpos: [9]; default: 0; + * 1: Use XTAL_CLK as the source clock of timer group. 0: Use APB_CLK as the source + * clock of timer group. + */ +#define TIMG_T0_USE_XTAL (BIT(9)) +#define TIMG_T0_USE_XTAL_M (TIMG_T0_USE_XTAL_V << TIMG_T0_USE_XTAL_S) +#define TIMG_T0_USE_XTAL_V 0x00000001U #define TIMG_T0_USE_XTAL_S 9 +/** TIMG_T0_ALARM_EN : R/W/SC; bitpos: [10]; default: 0; + * When set, the alarm is enabled. This bit is automatically cleared once an + * alarm occurs. + */ +#define TIMG_T0_ALARM_EN (BIT(10)) +#define TIMG_T0_ALARM_EN_M (TIMG_T0_ALARM_EN_V << TIMG_T0_ALARM_EN_S) +#define TIMG_T0_ALARM_EN_V 0x00000001U +#define TIMG_T0_ALARM_EN_S 10 +/** TIMG_T0_DIVCNT_RST : WT; bitpos: [12]; default: 0; + * When set, Timer 0 's clock divider counter will be reset. + */ +#define TIMG_T0_DIVCNT_RST (BIT(12)) +#define TIMG_T0_DIVCNT_RST_M (TIMG_T0_DIVCNT_RST_V << TIMG_T0_DIVCNT_RST_S) +#define TIMG_T0_DIVCNT_RST_V 0x00000001U +#define TIMG_T0_DIVCNT_RST_S 12 +/** TIMG_T0_DIVIDER : R/W; bitpos: [28:13]; default: 1; + * Timer 0 clock (T0_clk) prescaler value. + */ +#define TIMG_T0_DIVIDER 0x0000FFFFU +#define TIMG_T0_DIVIDER_M (TIMG_T0_DIVIDER_V << TIMG_T0_DIVIDER_S) +#define TIMG_T0_DIVIDER_V 0x0000FFFFU +#define TIMG_T0_DIVIDER_S 13 +/** TIMG_T0_AUTORELOAD : R/W; bitpos: [29]; default: 1; + * When set, timer 0 auto-reload at alarm is enabled. + */ +#define TIMG_T0_AUTORELOAD (BIT(29)) +#define TIMG_T0_AUTORELOAD_M (TIMG_T0_AUTORELOAD_V << TIMG_T0_AUTORELOAD_S) +#define TIMG_T0_AUTORELOAD_V 0x00000001U +#define TIMG_T0_AUTORELOAD_S 29 +/** TIMG_T0_INCREASE : R/W; bitpos: [30]; default: 1; + * When set, the timer 0 time-base counter will increment every clock tick. When + * cleared, the timer 0 time-base counter will decrement. + */ +#define TIMG_T0_INCREASE (BIT(30)) +#define TIMG_T0_INCREASE_M (TIMG_T0_INCREASE_V << TIMG_T0_INCREASE_S) +#define TIMG_T0_INCREASE_V 0x00000001U +#define TIMG_T0_INCREASE_S 30 +/** TIMG_T0_EN : R/W; bitpos: [31]; default: 0; + * When set, the timer 0 time-base counter is enabled. + */ +#define TIMG_T0_EN (BIT(31)) +#define TIMG_T0_EN_M (TIMG_T0_EN_V << TIMG_T0_EN_S) +#define TIMG_T0_EN_V 0x00000001U +#define TIMG_T0_EN_S 31 -#define TIMG_T0LO_REG(i) (REG_TIMG_BASE(i) + 0x0004) -/* TIMG_T0_LO : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define TIMG_T0_LO 0xFFFFFFFF -#define TIMG_T0_LO_M ((TIMG_T0_LO_V)<<(TIMG_T0_LO_S)) -#define TIMG_T0_LO_V 0xFFFFFFFF +/** TIMG_T0LO_REG register + * Timer 0 current value, low 32 bits + */ +#define TIMG_T0LO_REG(i) (DR_REG_TIMG_BASE(i) + 0x4) +/** TIMG_T0_LO : RO; bitpos: [31:0]; default: 0; + * After writing to TIMG_T0UPDATE_REG, the low 32 bits of the time-base counter + * of timer 0 can be read here. + */ +#define TIMG_T0_LO 0xFFFFFFFFU +#define TIMG_T0_LO_M (TIMG_T0_LO_V << TIMG_T0_LO_S) +#define TIMG_T0_LO_V 0xFFFFFFFFU #define TIMG_T0_LO_S 0 -#define TIMG_T0HI_REG(i) (REG_TIMG_BASE(i) + 0x0008) -/* TIMG_T0_HI : RO ;bitpos:[21:0] ;default: 22'h0 ; */ -/*description: */ -#define TIMG_T0_HI 0x003FFFFF -#define TIMG_T0_HI_M ((TIMG_T0_HI_V)<<(TIMG_T0_HI_S)) -#define TIMG_T0_HI_V 0x3FFFFF +/** TIMG_T0HI_REG register + * Timer $x current value, high 22 bits + */ +#define TIMG_T0HI_REG(i) (DR_REG_TIMG_BASE(i) + 0x8) +/** TIMG_T0_HI : RO; bitpos: [21:0]; default: 0; + * After writing to TIMG_T$xUPDATE_REG, the high 22 bits of the time-base counter + * of timer $x can be read here. + */ +#define TIMG_T0_HI 0x003FFFFFU +#define TIMG_T0_HI_M (TIMG_T0_HI_V << TIMG_T0_HI_S) +#define TIMG_T0_HI_V 0x003FFFFFU #define TIMG_T0_HI_S 0 -#define TIMG_T0UPDATE_REG(i) (REG_TIMG_BASE(i) + 0x000c) -/* TIMG_T0_UPDATE : R/W/SC ;bitpos:[31] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T0_UPDATE (BIT(31)) -#define TIMG_T0_UPDATE_M (BIT(31)) -#define TIMG_T0_UPDATE_V 0x1 +/** TIMG_T0UPDATE_REG register + * Write to copy current timer value to TIMGn_T$x_(LO/HI)_REG + */ +#define TIMG_T0UPDATE_REG(i) (DR_REG_TIMG_BASE(i) + 0xc) +/** TIMG_T0_UPDATE : R/W/SC; bitpos: [31]; default: 0; + * After writing 0 or 1 to TIMG_T$xUPDATE_REG, the counter value is latched. + */ +#define TIMG_T0_UPDATE (BIT(31)) +#define TIMG_T0_UPDATE_M (TIMG_T0_UPDATE_V << TIMG_T0_UPDATE_S) +#define TIMG_T0_UPDATE_V 0x00000001U #define TIMG_T0_UPDATE_S 31 -#define TIMG_T0ALARMLO_REG(i) (REG_TIMG_BASE(i) + 0x0010) -/* TIMG_T0_ALARM_LO : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define TIMG_T0_ALARM_LO 0xFFFFFFFF -#define TIMG_T0_ALARM_LO_M ((TIMG_T0_ALARM_LO_V)<<(TIMG_T0_ALARM_LO_S)) -#define TIMG_T0_ALARM_LO_V 0xFFFFFFFF +/** TIMG_T0ALARMLO_REG register + * Timer $x alarm value, low 32 bits + */ +#define TIMG_T0ALARMLO_REG(i) (DR_REG_TIMG_BASE(i) + 0x10) +/** TIMG_T0_ALARM_LO : R/W; bitpos: [31:0]; default: 0; + * Timer $x alarm trigger time-base counter value, low 32 bits. + */ +#define TIMG_T0_ALARM_LO 0xFFFFFFFFU +#define TIMG_T0_ALARM_LO_M (TIMG_T0_ALARM_LO_V << TIMG_T0_ALARM_LO_S) +#define TIMG_T0_ALARM_LO_V 0xFFFFFFFFU #define TIMG_T0_ALARM_LO_S 0 -#define TIMG_T0ALARMHI_REG(i) (REG_TIMG_BASE(i) + 0x0014) -/* TIMG_T0_ALARM_HI : R/W ;bitpos:[21:0] ;default: 22'h0 ; */ -/*description: */ -#define TIMG_T0_ALARM_HI 0x003FFFFF -#define TIMG_T0_ALARM_HI_M ((TIMG_T0_ALARM_HI_V)<<(TIMG_T0_ALARM_HI_S)) -#define TIMG_T0_ALARM_HI_V 0x3FFFFF +/** TIMG_T0ALARMHI_REG register + * Timer $x alarm value, high bits + */ +#define TIMG_T0ALARMHI_REG(i) (DR_REG_TIMG_BASE(i) + 0x14) +/** TIMG_T0_ALARM_HI : R/W; bitpos: [21:0]; default: 0; + * Timer $x alarm trigger time-base counter value, high 22 bits. + */ +#define TIMG_T0_ALARM_HI 0x003FFFFFU +#define TIMG_T0_ALARM_HI_M (TIMG_T0_ALARM_HI_V << TIMG_T0_ALARM_HI_S) +#define TIMG_T0_ALARM_HI_V 0x003FFFFFU #define TIMG_T0_ALARM_HI_S 0 -#define TIMG_T0LOADLO_REG(i) (REG_TIMG_BASE(i) + 0x0018) -/* TIMG_T0_LOAD_LO : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define TIMG_T0_LOAD_LO 0xFFFFFFFF -#define TIMG_T0_LOAD_LO_M ((TIMG_T0_LOAD_LO_V)<<(TIMG_T0_LOAD_LO_S)) -#define TIMG_T0_LOAD_LO_V 0xFFFFFFFF +/** TIMG_T0LOADLO_REG register + * Timer $x reload value, low 32 bits + */ +#define TIMG_T0LOADLO_REG(i) (DR_REG_TIMG_BASE(i) + 0x18) +/** TIMG_T0_LOAD_LO : R/W; bitpos: [31:0]; default: 0; + * Low 32 bits of the value that a reload will load onto timer $x time-base + * Counter. + */ +#define TIMG_T0_LOAD_LO 0xFFFFFFFFU +#define TIMG_T0_LOAD_LO_M (TIMG_T0_LOAD_LO_V << TIMG_T0_LOAD_LO_S) +#define TIMG_T0_LOAD_LO_V 0xFFFFFFFFU #define TIMG_T0_LOAD_LO_S 0 -#define TIMG_T0LOADHI_REG(i) (REG_TIMG_BASE(i) + 0x001c) -/* TIMG_T0_LOAD_HI : R/W ;bitpos:[21:0] ;default: 22'h0 ; */ -/*description: */ -#define TIMG_T0_LOAD_HI 0x003FFFFF -#define TIMG_T0_LOAD_HI_M ((TIMG_T0_LOAD_HI_V)<<(TIMG_T0_LOAD_HI_S)) -#define TIMG_T0_LOAD_HI_V 0x3FFFFF +/** TIMG_T0LOADHI_REG register + * Timer $x reload value, high 22 bits + */ +#define TIMG_T0LOADHI_REG(i) (DR_REG_TIMG_BASE(i) + 0x1c) +/** TIMG_T0_LOAD_HI : R/W; bitpos: [21:0]; default: 0; + * High 22 bits of the value that a reload will load onto timer $x time-base + * counter. + */ +#define TIMG_T0_LOAD_HI 0x003FFFFFU +#define TIMG_T0_LOAD_HI_M (TIMG_T0_LOAD_HI_V << TIMG_T0_LOAD_HI_S) +#define TIMG_T0_LOAD_HI_V 0x003FFFFFU #define TIMG_T0_LOAD_HI_S 0 -#define TIMG_T0LOAD_REG(i) (REG_TIMG_BASE(i) + 0x0020) -/* TIMG_T0_LOAD : WT ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define TIMG_T0_LOAD 0xFFFFFFFF -#define TIMG_T0_LOAD_M ((TIMG_T0_LOAD_V)<<(TIMG_T0_LOAD_S)) -#define TIMG_T0_LOAD_V 0xFFFFFFFF +/** TIMG_T0LOAD_REG register + * Write to reload timer from TIMG_T$x_(LOADLOLOADHI)_REG + */ +#define TIMG_T0LOAD_REG(i) (DR_REG_TIMG_BASE(i) + 0x20) +/** TIMG_T0_LOAD : WT; bitpos: [31:0]; default: 0; + * + * Write any value to trigger a timer $x time-base counter reload. + */ +#define TIMG_T0_LOAD 0xFFFFFFFFU +#define TIMG_T0_LOAD_M (TIMG_T0_LOAD_V << TIMG_T0_LOAD_S) +#define TIMG_T0_LOAD_V 0xFFFFFFFFU #define TIMG_T0_LOAD_S 0 -#define TIMG_WDTCONFIG0_REG(i) (REG_TIMG_BASE(i) + 0x0048) -/* TIMG_WDT_EN : R/W ;bitpos:[31] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_WDT_EN (BIT(31)) -#define TIMG_WDT_EN_M (BIT(31)) -#define TIMG_WDT_EN_V 0x1 -#define TIMG_WDT_EN_S 31 -/* TIMG_WDT_STG0 : R/W ;bitpos:[30:29] ;default: 2'd0 ; */ -/*description: */ -#define TIMG_WDT_STG0 0x00000003 -#define TIMG_WDT_STG0_M ((TIMG_WDT_STG0_V)<<(TIMG_WDT_STG0_S)) -#define TIMG_WDT_STG0_V 0x3 -#define TIMG_WDT_STG0_S 29 -/* TIMG_WDT_STG1 : R/W ;bitpos:[28:27] ;default: 2'd0 ; */ -/*description: */ -#define TIMG_WDT_STG1 0x00000003 -#define TIMG_WDT_STG1_M ((TIMG_WDT_STG1_V)<<(TIMG_WDT_STG1_S)) -#define TIMG_WDT_STG1_V 0x3 -#define TIMG_WDT_STG1_S 27 -/* TIMG_WDT_STG2 : R/W ;bitpos:[26:25] ;default: 2'd0 ; */ -/*description: */ -#define TIMG_WDT_STG2 0x00000003 -#define TIMG_WDT_STG2_M ((TIMG_WDT_STG2_V)<<(TIMG_WDT_STG2_S)) -#define TIMG_WDT_STG2_V 0x3 -#define TIMG_WDT_STG2_S 25 -/* TIMG_WDT_STG3 : R/W ;bitpos:[24:23] ;default: 2'd0 ; */ -/*description: */ -#define TIMG_WDT_STG3 0x00000003 -#define TIMG_WDT_STG3_M ((TIMG_WDT_STG3_V)<<(TIMG_WDT_STG3_S)) -#define TIMG_WDT_STG3_V 0x3 -#define TIMG_WDT_STG3_S 23 -/* TIMG_WDT_CONF_UPDATE_EN : WT ;bitpos:[22] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_WDT_CONF_UPDATE_EN (BIT(22)) -#define TIMG_WDT_CONF_UPDATE_EN_M (BIT(22)) -#define TIMG_WDT_CONF_UPDATE_EN_V 0x1 -#define TIMG_WDT_CONF_UPDATE_EN_S 22 -/* TIMG_WDT_USE_XTAL : R/W ;bitpos:[21] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_WDT_USE_XTAL (BIT(21)) -#define TIMG_WDT_USE_XTAL_M (BIT(21)) -#define TIMG_WDT_USE_XTAL_V 0x1 -#define TIMG_WDT_USE_XTAL_S 21 -/* TIMG_WDT_CPU_RESET_LENGTH : R/W ;bitpos:[20:18] ;default: 3'h1 ; */ -/*description: */ -#define TIMG_WDT_CPU_RESET_LENGTH 0x00000007 -#define TIMG_WDT_CPU_RESET_LENGTH_M ((TIMG_WDT_CPU_RESET_LENGTH_V)<<(TIMG_WDT_CPU_RESET_LENGTH_S)) -#define TIMG_WDT_CPU_RESET_LENGTH_V 0x7 -#define TIMG_WDT_CPU_RESET_LENGTH_S 18 -/* TIMG_WDT_SYS_RESET_LENGTH : R/W ;bitpos:[17:15] ;default: 3'h1 ; */ -/*description: */ -#define TIMG_WDT_SYS_RESET_LENGTH 0x00000007 -#define TIMG_WDT_SYS_RESET_LENGTH_M ((TIMG_WDT_SYS_RESET_LENGTH_V)<<(TIMG_WDT_SYS_RESET_LENGTH_S)) -#define TIMG_WDT_SYS_RESET_LENGTH_V 0x7 -#define TIMG_WDT_SYS_RESET_LENGTH_S 15 -/* TIMG_WDT_FLASHBOOT_MOD_EN : R/W ;bitpos:[14] ;default: 1'h1 ; */ -/*description: */ -#define TIMG_WDT_FLASHBOOT_MOD_EN (BIT(14)) -#define TIMG_WDT_FLASHBOOT_MOD_EN_M (BIT(14)) -#define TIMG_WDT_FLASHBOOT_MOD_EN_V 0x1 -#define TIMG_WDT_FLASHBOOT_MOD_EN_S 14 -/* TIMG_WDT_PROCPU_RESET_EN : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: */ -#define TIMG_WDT_PROCPU_RESET_EN (BIT(13)) -#define TIMG_WDT_PROCPU_RESET_EN_M (BIT(13)) -#define TIMG_WDT_PROCPU_RESET_EN_V 0x1 -#define TIMG_WDT_PROCPU_RESET_EN_S 13 -/* TIMG_WDT_APPCPU_RESET_EN : R/W ;bitpos:[12] ;default: 1'd0 ; */ -/*description: */ -#define TIMG_WDT_APPCPU_RESET_EN (BIT(12)) -#define TIMG_WDT_APPCPU_RESET_EN_M (BIT(12)) -#define TIMG_WDT_APPCPU_RESET_EN_V 0x1 +/** TIMG_WDTCONFIG0_REG register + * Watchdog timer configuration register + */ +#define TIMG_WDTCONFIG0_REG(i) (DR_REG_TIMG_BASE(i) + 0x48) +/** TIMG_WDT_APPCPU_RESET_EN : R/W; bitpos: [12]; default: 0; + * WDT reset CPU enable. + */ +#define TIMG_WDT_APPCPU_RESET_EN (BIT(12)) +#define TIMG_WDT_APPCPU_RESET_EN_M (TIMG_WDT_APPCPU_RESET_EN_V << TIMG_WDT_APPCPU_RESET_EN_S) +#define TIMG_WDT_APPCPU_RESET_EN_V 0x00000001U #define TIMG_WDT_APPCPU_RESET_EN_S 12 +/** TIMG_WDT_PROCPU_RESET_EN : R/W; bitpos: [13]; default: 0; + * WDT reset CPU enable. + */ +#define TIMG_WDT_PROCPU_RESET_EN (BIT(13)) +#define TIMG_WDT_PROCPU_RESET_EN_M (TIMG_WDT_PROCPU_RESET_EN_V << TIMG_WDT_PROCPU_RESET_EN_S) +#define TIMG_WDT_PROCPU_RESET_EN_V 0x00000001U +#define TIMG_WDT_PROCPU_RESET_EN_S 13 +/** TIMG_WDT_FLASHBOOT_MOD_EN : R/W; bitpos: [14]; default: 1; + * When set, Flash boot protection is enabled. + */ +#define TIMG_WDT_FLASHBOOT_MOD_EN (BIT(14)) +#define TIMG_WDT_FLASHBOOT_MOD_EN_M (TIMG_WDT_FLASHBOOT_MOD_EN_V << TIMG_WDT_FLASHBOOT_MOD_EN_S) +#define TIMG_WDT_FLASHBOOT_MOD_EN_V 0x00000001U +#define TIMG_WDT_FLASHBOOT_MOD_EN_S 14 +/** TIMG_WDT_SYS_RESET_LENGTH : R/W; bitpos: [17:15]; default: 1; + * System reset signal length selection. 0: 100 ns, 1: 200 ns, + * 2: 300 ns, 3: 400 ns, 4: 500 ns, 5: 800 ns, 6: 1.6 us, 7: 3.2 us. + */ +#define TIMG_WDT_SYS_RESET_LENGTH 0x00000007U +#define TIMG_WDT_SYS_RESET_LENGTH_M (TIMG_WDT_SYS_RESET_LENGTH_V << TIMG_WDT_SYS_RESET_LENGTH_S) +#define TIMG_WDT_SYS_RESET_LENGTH_V 0x00000007U +#define TIMG_WDT_SYS_RESET_LENGTH_S 15 +/** TIMG_WDT_CPU_RESET_LENGTH : R/W; bitpos: [20:18]; default: 1; + * CPU reset signal length selection. 0: 100 ns, 1: 200 ns, + * 2: 300 ns, 3: 400 ns, 4: 500 ns, 5: 800 ns, 6: 1.6 us, 7: 3.2 us. + */ +#define TIMG_WDT_CPU_RESET_LENGTH 0x00000007U +#define TIMG_WDT_CPU_RESET_LENGTH_M (TIMG_WDT_CPU_RESET_LENGTH_V << TIMG_WDT_CPU_RESET_LENGTH_S) +#define TIMG_WDT_CPU_RESET_LENGTH_V 0x00000007U +#define TIMG_WDT_CPU_RESET_LENGTH_S 18 +/** TIMG_WDT_USE_XTAL : R/W; bitpos: [21]; default: 0; + * choose WDT clock:0-apb_clk; 1-xtal_clk. + */ +#define TIMG_WDT_USE_XTAL (BIT(21)) +#define TIMG_WDT_USE_XTAL_M (TIMG_WDT_USE_XTAL_V << TIMG_WDT_USE_XTAL_S) +#define TIMG_WDT_USE_XTAL_V 0x00000001U +#define TIMG_WDT_USE_XTAL_S 21 +/** TIMG_WDT_CONF_UPDATE_EN : WT; bitpos: [22]; default: 0; + * update the WDT configuration registers + */ +#define TIMG_WDT_CONF_UPDATE_EN (BIT(22)) +#define TIMG_WDT_CONF_UPDATE_EN_M (TIMG_WDT_CONF_UPDATE_EN_V << TIMG_WDT_CONF_UPDATE_EN_S) +#define TIMG_WDT_CONF_UPDATE_EN_V 0x00000001U +#define TIMG_WDT_CONF_UPDATE_EN_S 22 +/** TIMG_WDT_STG3 : R/W; bitpos: [24:23]; default: 0; + * Stage 3 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system. + */ +#define TIMG_WDT_STG3 0x00000003U +#define TIMG_WDT_STG3_M (TIMG_WDT_STG3_V << TIMG_WDT_STG3_S) +#define TIMG_WDT_STG3_V 0x00000003U +#define TIMG_WDT_STG3_S 23 +/** TIMG_WDT_STG2 : R/W; bitpos: [26:25]; default: 0; + * Stage 2 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system. + */ +#define TIMG_WDT_STG2 0x00000003U +#define TIMG_WDT_STG2_M (TIMG_WDT_STG2_V << TIMG_WDT_STG2_S) +#define TIMG_WDT_STG2_V 0x00000003U +#define TIMG_WDT_STG2_S 25 +/** TIMG_WDT_STG1 : R/W; bitpos: [28:27]; default: 0; + * Stage 1 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system. + */ +#define TIMG_WDT_STG1 0x00000003U +#define TIMG_WDT_STG1_M (TIMG_WDT_STG1_V << TIMG_WDT_STG1_S) +#define TIMG_WDT_STG1_V 0x00000003U +#define TIMG_WDT_STG1_S 27 +/** TIMG_WDT_STG0 : R/W; bitpos: [30:29]; default: 0; + * Stage 0 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system. + */ +#define TIMG_WDT_STG0 0x00000003U +#define TIMG_WDT_STG0_M (TIMG_WDT_STG0_V << TIMG_WDT_STG0_S) +#define TIMG_WDT_STG0_V 0x00000003U +#define TIMG_WDT_STG0_S 29 +/** TIMG_WDT_EN : R/W; bitpos: [31]; default: 0; + * When set, MWDT is enabled. + */ +#define TIMG_WDT_EN (BIT(31)) +#define TIMG_WDT_EN_M (TIMG_WDT_EN_V << TIMG_WDT_EN_S) +#define TIMG_WDT_EN_V 0x00000001U +#define TIMG_WDT_EN_S 31 -#define TIMG_WDTCONFIG1_REG(i) (REG_TIMG_BASE(i) + 0x004c) -/* TIMG_WDT_CLK_PRESCALE : R/W ;bitpos:[31:16] ;default: 16'h1 ; */ -/*description: */ -#define TIMG_WDT_CLK_PRESCALE 0x0000FFFF -#define TIMG_WDT_CLK_PRESCALE_M ((TIMG_WDT_CLK_PRESCALE_V)<<(TIMG_WDT_CLK_PRESCALE_S)) -#define TIMG_WDT_CLK_PRESCALE_V 0xFFFF -#define TIMG_WDT_CLK_PRESCALE_S 16 -/* TIMG_WDT_DIVCNT_RST : WT ;bitpos:[0] ;default: 1'b0 ; */ -/*description: */ -#define TIMG_WDT_DIVCNT_RST (BIT(0)) -#define TIMG_WDT_DIVCNT_RST_M (BIT(0)) -#define TIMG_WDT_DIVCNT_RST_V 0x1 +/** TIMG_WDTCONFIG1_REG register + * Watchdog timer prescaler register + */ +#define TIMG_WDTCONFIG1_REG(i) (DR_REG_TIMG_BASE(i) + 0x4c) +/** TIMG_WDT_DIVCNT_RST : WT; bitpos: [0]; default: 0; + * When set, WDT 's clock divider counter will be reset. + */ +#define TIMG_WDT_DIVCNT_RST (BIT(0)) +#define TIMG_WDT_DIVCNT_RST_M (TIMG_WDT_DIVCNT_RST_V << TIMG_WDT_DIVCNT_RST_S) +#define TIMG_WDT_DIVCNT_RST_V 0x00000001U #define TIMG_WDT_DIVCNT_RST_S 0 +/** TIMG_WDT_CLK_PRESCALE : R/W; bitpos: [31:16]; default: 1; + * MWDT clock prescaler value. MWDT clock period = 12.5 ns * + * TIMG_WDT_CLK_PRESCALE. + */ +#define TIMG_WDT_CLK_PRESCALE 0x0000FFFFU +#define TIMG_WDT_CLK_PRESCALE_M (TIMG_WDT_CLK_PRESCALE_V << TIMG_WDT_CLK_PRESCALE_S) +#define TIMG_WDT_CLK_PRESCALE_V 0x0000FFFFU +#define TIMG_WDT_CLK_PRESCALE_S 16 -#define TIMG_WDTCONFIG2_REG(i) (REG_TIMG_BASE(i) + 0x0050) -/* TIMG_WDT_STG0_HOLD : R/W ;bitpos:[31:0] ;default: 32'd26000000 ; */ -/*description: */ -#define TIMG_WDT_STG0_HOLD 0xFFFFFFFF -#define TIMG_WDT_STG0_HOLD_M ((TIMG_WDT_STG0_HOLD_V)<<(TIMG_WDT_STG0_HOLD_S)) -#define TIMG_WDT_STG0_HOLD_V 0xFFFFFFFF +/** TIMG_WDTCONFIG2_REG register + * Watchdog timer stage 0 timeout value + */ +#define TIMG_WDTCONFIG2_REG(i) (DR_REG_TIMG_BASE(i) + 0x50) +/** TIMG_WDT_STG0_HOLD : R/W; bitpos: [31:0]; default: 26000000; + * Stage 0 timeout value, in MWDT clock cycles. + */ +#define TIMG_WDT_STG0_HOLD 0xFFFFFFFFU +#define TIMG_WDT_STG0_HOLD_M (TIMG_WDT_STG0_HOLD_V << TIMG_WDT_STG0_HOLD_S) +#define TIMG_WDT_STG0_HOLD_V 0xFFFFFFFFU #define TIMG_WDT_STG0_HOLD_S 0 -#define TIMG_WDTCONFIG3_REG(i) (REG_TIMG_BASE(i) + 0x0054) -/* TIMG_WDT_STG1_HOLD : R/W ;bitpos:[31:0] ;default: 32'h7ffffff ; */ -/*description: */ -#define TIMG_WDT_STG1_HOLD 0xFFFFFFFF -#define TIMG_WDT_STG1_HOLD_M ((TIMG_WDT_STG1_HOLD_V)<<(TIMG_WDT_STG1_HOLD_S)) -#define TIMG_WDT_STG1_HOLD_V 0xFFFFFFFF +/** TIMG_WDTCONFIG3_REG register + * Watchdog timer stage 1 timeout value + */ +#define TIMG_WDTCONFIG3_REG(i) (DR_REG_TIMG_BASE(i) + 0x54) +/** TIMG_WDT_STG1_HOLD : R/W; bitpos: [31:0]; default: 134217727; + * Stage 1 timeout value, in MWDT clock cycles. + */ +#define TIMG_WDT_STG1_HOLD 0xFFFFFFFFU +#define TIMG_WDT_STG1_HOLD_M (TIMG_WDT_STG1_HOLD_V << TIMG_WDT_STG1_HOLD_S) +#define TIMG_WDT_STG1_HOLD_V 0xFFFFFFFFU #define TIMG_WDT_STG1_HOLD_S 0 -#define TIMG_WDTCONFIG4_REG(i) (REG_TIMG_BASE(i) + 0x0058) -/* TIMG_WDT_STG2_HOLD : R/W ;bitpos:[31:0] ;default: 32'hfffff ; */ -/*description: */ -#define TIMG_WDT_STG2_HOLD 0xFFFFFFFF -#define TIMG_WDT_STG2_HOLD_M ((TIMG_WDT_STG2_HOLD_V)<<(TIMG_WDT_STG2_HOLD_S)) -#define TIMG_WDT_STG2_HOLD_V 0xFFFFFFFF +/** TIMG_WDTCONFIG4_REG register + * Watchdog timer stage 2 timeout value + */ +#define TIMG_WDTCONFIG4_REG(i) (DR_REG_TIMG_BASE(i) + 0x58) +/** TIMG_WDT_STG2_HOLD : R/W; bitpos: [31:0]; default: 1048575; + * Stage 2 timeout value, in MWDT clock cycles. + */ +#define TIMG_WDT_STG2_HOLD 0xFFFFFFFFU +#define TIMG_WDT_STG2_HOLD_M (TIMG_WDT_STG2_HOLD_V << TIMG_WDT_STG2_HOLD_S) +#define TIMG_WDT_STG2_HOLD_V 0xFFFFFFFFU #define TIMG_WDT_STG2_HOLD_S 0 -#define TIMG_WDTCONFIG5_REG(i) (REG_TIMG_BASE(i) + 0x005c) -/* TIMG_WDT_STG3_HOLD : R/W ;bitpos:[31:0] ;default: 32'hfffff ; */ -/*description: */ -#define TIMG_WDT_STG3_HOLD 0xFFFFFFFF -#define TIMG_WDT_STG3_HOLD_M ((TIMG_WDT_STG3_HOLD_V)<<(TIMG_WDT_STG3_HOLD_S)) -#define TIMG_WDT_STG3_HOLD_V 0xFFFFFFFF +/** TIMG_WDTCONFIG5_REG register + * Watchdog timer stage 3 timeout value + */ +#define TIMG_WDTCONFIG5_REG(i) (DR_REG_TIMG_BASE(i) + 0x5c) +/** TIMG_WDT_STG3_HOLD : R/W; bitpos: [31:0]; default: 1048575; + * Stage 3 timeout value, in MWDT clock cycles. + */ +#define TIMG_WDT_STG3_HOLD 0xFFFFFFFFU +#define TIMG_WDT_STG3_HOLD_M (TIMG_WDT_STG3_HOLD_V << TIMG_WDT_STG3_HOLD_S) +#define TIMG_WDT_STG3_HOLD_V 0xFFFFFFFFU #define TIMG_WDT_STG3_HOLD_S 0 -#define TIMG_WDTFEED_REG(i) (REG_TIMG_BASE(i) + 0x0060) -/* TIMG_WDT_FEED : WT ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define TIMG_WDT_FEED 0xFFFFFFFF -#define TIMG_WDT_FEED_M ((TIMG_WDT_FEED_V)<<(TIMG_WDT_FEED_S)) -#define TIMG_WDT_FEED_V 0xFFFFFFFF +/** TIMG_WDTFEED_REG register + * Write to feed the watchdog timer + */ +#define TIMG_WDTFEED_REG(i) (DR_REG_TIMG_BASE(i) + 0x60) +/** TIMG_WDT_FEED : WT; bitpos: [31:0]; default: 0; + * Write any value to feed the MWDT. (WO) + */ +#define TIMG_WDT_FEED 0xFFFFFFFFU +#define TIMG_WDT_FEED_M (TIMG_WDT_FEED_V << TIMG_WDT_FEED_S) +#define TIMG_WDT_FEED_V 0xFFFFFFFFU #define TIMG_WDT_FEED_S 0 -#define TIMG_WDTWPROTECT_REG(i) (REG_TIMG_BASE(i) + 0x0064) -/* TIMG_WDT_WKEY : R/W ;bitpos:[31:0] ;default: 32'h50d83aa1 ; */ -/*description: */ -#define TIMG_WDT_WKEY 0xFFFFFFFF -#define TIMG_WDT_WKEY_M ((TIMG_WDT_WKEY_V)<<(TIMG_WDT_WKEY_S)) -#define TIMG_WDT_WKEY_V 0xFFFFFFFF +/** TIMG_WDTWPROTECT_REG register + * Watchdog write protect register + */ +#define TIMG_WDTWPROTECT_REG(i) (DR_REG_TIMG_BASE(i) + 0x64) +/** TIMG_WDT_WKEY : R/W; bitpos: [31:0]; default: 1356348065; + * If the register contains a different value than its reset value, write + * protection is enabled. + */ +#define TIMG_WDT_WKEY 0xFFFFFFFFU +#define TIMG_WDT_WKEY_M (TIMG_WDT_WKEY_V << TIMG_WDT_WKEY_S) +#define TIMG_WDT_WKEY_V 0xFFFFFFFFU #define TIMG_WDT_WKEY_S 0 -#define TIMG_RTCCALICFG_REG(i) (REG_TIMG_BASE(i) + 0x0068) -/* TIMG_RTC_CALI_START : R/W ;bitpos:[31] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_RTC_CALI_START (BIT(31)) -#define TIMG_RTC_CALI_START_M (BIT(31)) -#define TIMG_RTC_CALI_START_V 0x1 -#define TIMG_RTC_CALI_START_S 31 -/* TIMG_RTC_CALI_MAX : R/W ;bitpos:[30:16] ;default: 15'h1 ; */ -/*description: */ -#define TIMG_RTC_CALI_MAX 0x00007FFF -#define TIMG_RTC_CALI_MAX_M ((TIMG_RTC_CALI_MAX_V)<<(TIMG_RTC_CALI_MAX_S)) -#define TIMG_RTC_CALI_MAX_V 0x7FFF -#define TIMG_RTC_CALI_MAX_S 16 -/* TIMG_RTC_CALI_RDY : RO ;bitpos:[15] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_RTC_CALI_RDY (BIT(15)) -#define TIMG_RTC_CALI_RDY_M (BIT(15)) -#define TIMG_RTC_CALI_RDY_V 0x1 -#define TIMG_RTC_CALI_RDY_S 15 -/* TIMG_RTC_CALI_CLK_SEL : R/W ;bitpos:[14:13] ;default: 2'h1 ; */ -/*description: */ -#define TIMG_RTC_CALI_CLK_SEL 0x00000003 -#define TIMG_RTC_CALI_CLK_SEL_M ((TIMG_RTC_CALI_CLK_SEL_V)<<(TIMG_RTC_CALI_CLK_SEL_S)) -#define TIMG_RTC_CALI_CLK_SEL_V 0x3 -#define TIMG_RTC_CALI_CLK_SEL_S 13 -/* TIMG_RTC_CALI_START_CYCLING : R/W ;bitpos:[12] ;default: 1'd1 ; */ -/*description: */ -#define TIMG_RTC_CALI_START_CYCLING (BIT(12)) -#define TIMG_RTC_CALI_START_CYCLING_M (BIT(12)) -#define TIMG_RTC_CALI_START_CYCLING_V 0x1 +/** TIMG_RTCCALICFG_REG register + * RTC calibration configure register + */ +#define TIMG_RTCCALICFG_REG(i) (DR_REG_TIMG_BASE(i) + 0x68) +/** TIMG_RTC_CALI_START_CYCLING : R/W; bitpos: [12]; default: 1; + * Reserved + */ +#define TIMG_RTC_CALI_START_CYCLING (BIT(12)) +#define TIMG_RTC_CALI_START_CYCLING_M (TIMG_RTC_CALI_START_CYCLING_V << TIMG_RTC_CALI_START_CYCLING_S) +#define TIMG_RTC_CALI_START_CYCLING_V 0x00000001U #define TIMG_RTC_CALI_START_CYCLING_S 12 +/** TIMG_RTC_CALI_CLK_SEL : R/W; bitpos: [14:13]; default: 1; + * 0:rtc slow clock. 1:clk_8m, 2:xtal_32k. + */ +#define TIMG_RTC_CALI_CLK_SEL 0x00000003U +#define TIMG_RTC_CALI_CLK_SEL_M (TIMG_RTC_CALI_CLK_SEL_V << TIMG_RTC_CALI_CLK_SEL_S) +#define TIMG_RTC_CALI_CLK_SEL_V 0x00000003U +#define TIMG_RTC_CALI_CLK_SEL_S 13 +/** TIMG_RTC_CALI_RDY : RO; bitpos: [15]; default: 0; + * Reserved + */ +#define TIMG_RTC_CALI_RDY (BIT(15)) +#define TIMG_RTC_CALI_RDY_M (TIMG_RTC_CALI_RDY_V << TIMG_RTC_CALI_RDY_S) +#define TIMG_RTC_CALI_RDY_V 0x00000001U +#define TIMG_RTC_CALI_RDY_S 15 +/** TIMG_RTC_CALI_MAX : R/W; bitpos: [30:16]; default: 1; + * Reserved + */ +#define TIMG_RTC_CALI_MAX 0x00007FFFU +#define TIMG_RTC_CALI_MAX_M (TIMG_RTC_CALI_MAX_V << TIMG_RTC_CALI_MAX_S) +#define TIMG_RTC_CALI_MAX_V 0x00007FFFU +#define TIMG_RTC_CALI_MAX_S 16 +/** TIMG_RTC_CALI_START : R/W; bitpos: [31]; default: 0; + * Reserved + */ +#define TIMG_RTC_CALI_START (BIT(31)) +#define TIMG_RTC_CALI_START_M (TIMG_RTC_CALI_START_V << TIMG_RTC_CALI_START_S) +#define TIMG_RTC_CALI_START_V 0x00000001U +#define TIMG_RTC_CALI_START_S 31 -#define TIMG_RTCCALICFG1_REG(i) (REG_TIMG_BASE(i) + 0x006c) -/* TIMG_RTC_CALI_VALUE : RO ;bitpos:[31:7] ;default: 25'h0 ; */ -/*description: */ -#define TIMG_RTC_CALI_VALUE 0x01FFFFFF -#define TIMG_RTC_CALI_VALUE_M ((TIMG_RTC_CALI_VALUE_V)<<(TIMG_RTC_CALI_VALUE_S)) -#define TIMG_RTC_CALI_VALUE_V 0x1FFFFFF -#define TIMG_RTC_CALI_VALUE_S 7 -/* TIMG_RTC_CALI_CYCLING_DATA_VLD : RO ;bitpos:[0] ;default: 1'b0 ; */ -/*description: */ -#define TIMG_RTC_CALI_CYCLING_DATA_VLD (BIT(0)) -#define TIMG_RTC_CALI_CYCLING_DATA_VLD_M (BIT(0)) -#define TIMG_RTC_CALI_CYCLING_DATA_VLD_V 0x1 +/** TIMG_RTCCALICFG1_REG register + * RTC calibration configure1 register + */ +#define TIMG_RTCCALICFG1_REG(i) (DR_REG_TIMG_BASE(i) + 0x6c) +/** TIMG_RTC_CALI_CYCLING_DATA_VLD : RO; bitpos: [0]; default: 0; + * Reserved + */ +#define TIMG_RTC_CALI_CYCLING_DATA_VLD (BIT(0)) +#define TIMG_RTC_CALI_CYCLING_DATA_VLD_M (TIMG_RTC_CALI_CYCLING_DATA_VLD_V << TIMG_RTC_CALI_CYCLING_DATA_VLD_S) +#define TIMG_RTC_CALI_CYCLING_DATA_VLD_V 0x00000001U #define TIMG_RTC_CALI_CYCLING_DATA_VLD_S 0 +/** TIMG_RTC_CALI_VALUE : RO; bitpos: [31:7]; default: 0; + * Reserved + */ +#define TIMG_RTC_CALI_VALUE 0x01FFFFFFU +#define TIMG_RTC_CALI_VALUE_M (TIMG_RTC_CALI_VALUE_V << TIMG_RTC_CALI_VALUE_S) +#define TIMG_RTC_CALI_VALUE_V 0x01FFFFFFU +#define TIMG_RTC_CALI_VALUE_S 7 -#define TIMG_INT_ENA_TIMERS_REG(i) (REG_TIMG_BASE(i) + 0x0070) -/* TIMG_WDT_INT_ENA : R/W ;bitpos:[1] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_WDT_INT_ENA (BIT(1)) -#define TIMG_WDT_INT_ENA_M (BIT(1)) -#define TIMG_WDT_INT_ENA_V 0x1 -#define TIMG_WDT_INT_ENA_S 1 -/* TIMG_T0_INT_ENA : R/W ;bitpos:[0] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T0_INT_ENA (BIT(0)) -#define TIMG_T0_INT_ENA_M (BIT(0)) -#define TIMG_T0_INT_ENA_V 0x1 +/** TIMG_INT_ENA_TIMERS_REG register + * Interrupt enable bits + */ +#define TIMG_INT_ENA_TIMERS_REG(i) (DR_REG_TIMG_BASE(i) + 0x70) +/** TIMG_T0_INT_ENA : R/W; bitpos: [0]; default: 0; + * The interrupt enable bit for the TIMG_T$x_INT interrupt. + */ +#define TIMG_T0_INT_ENA (BIT(0)) +#define TIMG_T0_INT_ENA_M (TIMG_T0_INT_ENA_V << TIMG_T0_INT_ENA_S) +#define TIMG_T0_INT_ENA_V 0x00000001U #define TIMG_T0_INT_ENA_S 0 +/** TIMG_WDT_INT_ENA : R/W; bitpos: [1]; default: 0; + * The interrupt enable bit for the TIMG_WDT_INT interrupt. + */ +#define TIMG_WDT_INT_ENA (BIT(1)) +#define TIMG_WDT_INT_ENA_M (TIMG_WDT_INT_ENA_V << TIMG_WDT_INT_ENA_S) +#define TIMG_WDT_INT_ENA_V 0x00000001U +#define TIMG_WDT_INT_ENA_S 1 -#define TIMG_INT_RAW_TIMERS_REG(i) (REG_TIMG_BASE(i) + 0x0074) -/* TIMG_WDT_INT_RAW : R/SS/WTC ;bitpos:[1] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_WDT_INT_RAW (BIT(1)) -#define TIMG_WDT_INT_RAW_M (BIT(1)) -#define TIMG_WDT_INT_RAW_V 0x1 -#define TIMG_WDT_INT_RAW_S 1 -/* TIMG_T0_INT_RAW : R/SS/WTC ;bitpos:[0] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T0_INT_RAW (BIT(0)) -#define TIMG_T0_INT_RAW_M (BIT(0)) -#define TIMG_T0_INT_RAW_V 0x1 +/** TIMG_INT_RAW_TIMERS_REG register + * Raw interrupt status + */ +#define TIMG_INT_RAW_TIMERS_REG(i) (DR_REG_TIMG_BASE(i) + 0x74) +/** TIMG_T0_INT_RAW : R/SS/WTC; bitpos: [0]; default: 0; + * The raw interrupt status bit for the TIMG_T$x_INT interrupt. + */ +#define TIMG_T0_INT_RAW (BIT(0)) +#define TIMG_T0_INT_RAW_M (TIMG_T0_INT_RAW_V << TIMG_T0_INT_RAW_S) +#define TIMG_T0_INT_RAW_V 0x00000001U #define TIMG_T0_INT_RAW_S 0 +/** TIMG_WDT_INT_RAW : R/SS/WTC; bitpos: [1]; default: 0; + * The raw interrupt status bit for the TIMG_WDT_INT interrupt. + */ +#define TIMG_WDT_INT_RAW (BIT(1)) +#define TIMG_WDT_INT_RAW_M (TIMG_WDT_INT_RAW_V << TIMG_WDT_INT_RAW_S) +#define TIMG_WDT_INT_RAW_V 0x00000001U +#define TIMG_WDT_INT_RAW_S 1 -#define TIMG_INT_ST_TIMERS_REG(i) (REG_TIMG_BASE(i) + 0x0078) -/* TIMG_WDT_INT_ST : RO ;bitpos:[1] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_WDT_INT_ST (BIT(1)) -#define TIMG_WDT_INT_ST_M (BIT(1)) -#define TIMG_WDT_INT_ST_V 0x1 -#define TIMG_WDT_INT_ST_S 1 -/* TIMG_T0_INT_ST : RO ;bitpos:[0] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T0_INT_ST (BIT(0)) -#define TIMG_T0_INT_ST_M (BIT(0)) -#define TIMG_T0_INT_ST_V 0x1 +/** TIMG_INT_ST_TIMERS_REG register + * Masked interrupt status + */ +#define TIMG_INT_ST_TIMERS_REG(i) (DR_REG_TIMG_BASE(i) + 0x78) +/** TIMG_T0_INT_ST : RO; bitpos: [0]; default: 0; + * The masked interrupt status bit for the TIMG_T$x_INT interrupt. + */ +#define TIMG_T0_INT_ST (BIT(0)) +#define TIMG_T0_INT_ST_M (TIMG_T0_INT_ST_V << TIMG_T0_INT_ST_S) +#define TIMG_T0_INT_ST_V 0x00000001U #define TIMG_T0_INT_ST_S 0 +/** TIMG_WDT_INT_ST : RO; bitpos: [1]; default: 0; + * The masked interrupt status bit for the TIMG_WDT_INT interrupt. + */ +#define TIMG_WDT_INT_ST (BIT(1)) +#define TIMG_WDT_INT_ST_M (TIMG_WDT_INT_ST_V << TIMG_WDT_INT_ST_S) +#define TIMG_WDT_INT_ST_V 0x00000001U +#define TIMG_WDT_INT_ST_S 1 -#define TIMG_INT_CLR_TIMERS_REG(i) (REG_TIMG_BASE(i) + 0x007c) -/* TIMG_WDT_INT_CLR : WT ;bitpos:[1] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_WDT_INT_CLR (BIT(1)) -#define TIMG_WDT_INT_CLR_M (BIT(1)) -#define TIMG_WDT_INT_CLR_V 0x1 -#define TIMG_WDT_INT_CLR_S 1 -/* TIMG_T0_INT_CLR : WT ;bitpos:[0] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T0_INT_CLR (BIT(0)) -#define TIMG_T0_INT_CLR_M (BIT(0)) -#define TIMG_T0_INT_CLR_V 0x1 +/** TIMG_INT_CLR_TIMERS_REG register + * Interrupt clear bits + */ +#define TIMG_INT_CLR_TIMERS_REG(i) (DR_REG_TIMG_BASE(i) + 0x7c) +/** TIMG_T0_INT_CLR : WT; bitpos: [0]; default: 0; + * Set this bit to clear the TIMG_T$x_INT interrupt. + */ +#define TIMG_T0_INT_CLR (BIT(0)) +#define TIMG_T0_INT_CLR_M (TIMG_T0_INT_CLR_V << TIMG_T0_INT_CLR_S) +#define TIMG_T0_INT_CLR_V 0x00000001U #define TIMG_T0_INT_CLR_S 0 +/** TIMG_WDT_INT_CLR : WT; bitpos: [1]; default: 0; + * Set this bit to clear the TIMG_WDT_INT interrupt. + */ +#define TIMG_WDT_INT_CLR (BIT(1)) +#define TIMG_WDT_INT_CLR_M (TIMG_WDT_INT_CLR_V << TIMG_WDT_INT_CLR_S) +#define TIMG_WDT_INT_CLR_V 0x00000001U +#define TIMG_WDT_INT_CLR_S 1 -#define TIMG_RTCCALICFG2_REG(i) (REG_TIMG_BASE(i) + 0x0080) -/* TIMG_RTC_CALI_TIMEOUT_THRES : R/W ;bitpos:[31:7] ;default: 25'h1ffffff ; */ -/*description: timeout if cali value counts over threshold*/ -#define TIMG_RTC_CALI_TIMEOUT_THRES 0x01FFFFFF -#define TIMG_RTC_CALI_TIMEOUT_THRES_M ((TIMG_RTC_CALI_TIMEOUT_THRES_V)<<(TIMG_RTC_CALI_TIMEOUT_THRES_S)) -#define TIMG_RTC_CALI_TIMEOUT_THRES_V 0x1FFFFFF -#define TIMG_RTC_CALI_TIMEOUT_THRES_S 7 -/* TIMG_RTC_CALI_TIMEOUT_RST_CNT : R/W ;bitpos:[6:3] ;default: 4'd3 ; */ -/*description: Cycles that release calibration timeout reset*/ -#define TIMG_RTC_CALI_TIMEOUT_RST_CNT 0x0000000F -#define TIMG_RTC_CALI_TIMEOUT_RST_CNT_M ((TIMG_RTC_CALI_TIMEOUT_RST_CNT_V)<<(TIMG_RTC_CALI_TIMEOUT_RST_CNT_S)) -#define TIMG_RTC_CALI_TIMEOUT_RST_CNT_V 0xF -#define TIMG_RTC_CALI_TIMEOUT_RST_CNT_S 3 -/* TIMG_RTC_CALI_TIMEOUT : RO ;bitpos:[0] ;default: 1'h0 ; */ -/*description: timeout indicator*/ -#define TIMG_RTC_CALI_TIMEOUT (BIT(0)) -#define TIMG_RTC_CALI_TIMEOUT_M (BIT(0)) -#define TIMG_RTC_CALI_TIMEOUT_V 0x1 +/** TIMG_RTCCALICFG2_REG register + * Timer group calibration register + */ +#define TIMG_RTCCALICFG2_REG(i) (DR_REG_TIMG_BASE(i) + 0x80) +/** TIMG_RTC_CALI_TIMEOUT : RO; bitpos: [0]; default: 0; + * RTC calibration timeout indicator + */ +#define TIMG_RTC_CALI_TIMEOUT (BIT(0)) +#define TIMG_RTC_CALI_TIMEOUT_M (TIMG_RTC_CALI_TIMEOUT_V << TIMG_RTC_CALI_TIMEOUT_S) +#define TIMG_RTC_CALI_TIMEOUT_V 0x00000001U #define TIMG_RTC_CALI_TIMEOUT_S 0 +/** TIMG_RTC_CALI_TIMEOUT_RST_CNT : R/W; bitpos: [6:3]; default: 3; + * Cycles that release calibration timeout reset + */ +#define TIMG_RTC_CALI_TIMEOUT_RST_CNT 0x0000000FU +#define TIMG_RTC_CALI_TIMEOUT_RST_CNT_M (TIMG_RTC_CALI_TIMEOUT_RST_CNT_V << TIMG_RTC_CALI_TIMEOUT_RST_CNT_S) +#define TIMG_RTC_CALI_TIMEOUT_RST_CNT_V 0x0000000FU +#define TIMG_RTC_CALI_TIMEOUT_RST_CNT_S 3 +/** TIMG_RTC_CALI_TIMEOUT_THRES : R/W; bitpos: [31:7]; default: 33554431; + * Threshold value for the RTC calibration timer. If the calibration timer's value + * exceeds this threshold, a timeout is triggered. + */ +#define TIMG_RTC_CALI_TIMEOUT_THRES 0x01FFFFFFU +#define TIMG_RTC_CALI_TIMEOUT_THRES_M (TIMG_RTC_CALI_TIMEOUT_THRES_V << TIMG_RTC_CALI_TIMEOUT_THRES_S) +#define TIMG_RTC_CALI_TIMEOUT_THRES_V 0x01FFFFFFU +#define TIMG_RTC_CALI_TIMEOUT_THRES_S 7 -#define TIMG_NTIMERS_DATE_REG(i) (REG_TIMG_BASE(i) + 0x00f8) -/* TIMG_NTIMERS_DATE : R/W ;bitpos:[27:0] ;default: 28'h2006191 ; */ -/*description: */ -#define TIMG_NTIMERS_DATE 0x0FFFFFFF -#define TIMG_NTIMERS_DATE_M ((TIMG_NTIMERS_DATE_V)<<(TIMG_NTIMERS_DATE_S)) -#define TIMG_NTIMERS_DATE_V 0xFFFFFFF -#define TIMG_NTIMERS_DATE_S 0 +/** TIMG_NTIMERS_DATE_REG register + * Timer version control register + */ +#define TIMG_NTIMERS_DATE_REG(i) (DR_REG_TIMG_BASE(i) + 0xf8) +/** TIMG_NTIMGS_DATE : R/W; bitpos: [27:0]; default: 33579409; + * Timer version control register + */ +#define TIMG_NTIMGS_DATE 0x0FFFFFFFU +#define TIMG_NTIMGS_DATE_M (TIMG_NTIMGS_DATE_V << TIMG_NTIMGS_DATE_S) +#define TIMG_NTIMGS_DATE_V 0x0FFFFFFFU +#define TIMG_NTIMGS_DATE_S 0 -#define TIMG_CLK_REG(i) (REG_TIMG_BASE(i) + 0x00fc) -/* TIMG_CLK_EN : R/W ;bitpos:[31] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_CLK_EN (BIT(31)) -#define TIMG_CLK_EN_M (BIT(31)) -#define TIMG_CLK_EN_V 0x1 -#define TIMG_CLK_EN_S 31 -/* TIMG_TIMER_CLK_IS_ACTIVE : R/W ;bitpos:[30] ;default: 1'h1 ; */ -/*description: */ -#define TIMG_TIMER_CLK_IS_ACTIVE (BIT(30)) -#define TIMG_TIMER_CLK_IS_ACTIVE_M (BIT(30)) -#define TIMG_TIMER_CLK_IS_ACTIVE_V 0x1 -#define TIMG_TIMER_CLK_IS_ACTIVE_S 30 -/* TIMG_WDT_CLK_IS_ACTIVE : R/W ;bitpos:[29] ;default: 1'h1 ; */ -/*description: */ -#define TIMG_WDT_CLK_IS_ACTIVE (BIT(29)) -#define TIMG_WDT_CLK_IS_ACTIVE_M (BIT(29)) -#define TIMG_WDT_CLK_IS_ACTIVE_V 0x1 +/** TIMG_REGCLK_REG register + * Timer group clock gate register + */ +#define TIMG_REGCLK_REG(i) (DR_REG_TIMG_BASE(i) + 0xfc) +/** TIMG_WDT_CLK_IS_ACTIVE : R/W; bitpos: [29]; default: 1; + * enable WDT's clock + */ +#define TIMG_WDT_CLK_IS_ACTIVE (BIT(29)) +#define TIMG_WDT_CLK_IS_ACTIVE_M (TIMG_WDT_CLK_IS_ACTIVE_V << TIMG_WDT_CLK_IS_ACTIVE_S) +#define TIMG_WDT_CLK_IS_ACTIVE_V 0x00000001U #define TIMG_WDT_CLK_IS_ACTIVE_S 29 +/** TIMG_TIMER_CLK_IS_ACTIVE : R/W; bitpos: [30]; default: 1; + * enable Timer $x's clock + */ +#define TIMG_TIMER_CLK_IS_ACTIVE (BIT(30)) +#define TIMG_TIMER_CLK_IS_ACTIVE_M (TIMG_TIMER_CLK_IS_ACTIVE_V << TIMG_TIMER_CLK_IS_ACTIVE_S) +#define TIMG_TIMER_CLK_IS_ACTIVE_V 0x00000001U +#define TIMG_TIMER_CLK_IS_ACTIVE_S 30 +/** TIMG_CLK_EN : R/W; bitpos: [31]; default: 0; + * Register clock gate signal. 1: Registers can be read and written to by software. 0: + * Registers can not be read or written to by software. + */ +#define TIMG_CLK_EN (BIT(31)) +#define TIMG_CLK_EN_M (TIMG_CLK_EN_V << TIMG_CLK_EN_S) +#define TIMG_CLK_EN_V 0x00000001U +#define TIMG_CLK_EN_S 31 #ifdef __cplusplus } #endif - - - -#endif /*_SOC_TIMG_REG_H_ */ diff --git a/components/soc/esp32h2/include/soc/timer_group_struct.h b/components/soc/esp32h2/include/soc/timer_group_struct.h index 6bae30720c..13311b302e 100644 --- a/components/soc/esp32h2/include/soc/timer_group_struct.h +++ b/components/soc/esp32h2/include/soc/timer_group_struct.h @@ -1,222 +1,561 @@ -// 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. -#ifndef _SOC_TIMG_STRUCT_H_ -#define _SOC_TIMG_STRUCT_H_ +/** + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include #ifdef __cplusplus extern "C" { #endif -typedef volatile struct { +/** Group: T0 Control and configuration registers */ +/** Type of txconfig register + * Timer x configuration register + */ +typedef union { struct { - union { - struct { - uint32_t reserved0: 9; - uint32_t use_xtal: 1; - uint32_t alarm_en: 1; - uint32_t reserved11: 1; - uint32_t divcnt_rst: 1; - uint32_t divider: 16; - uint32_t autoreload: 1; - uint32_t increase: 1; - uint32_t enable: 1; - }; - uint32_t val; - } config; - uint32_t cnt_low; /**/ - union { - struct { - uint32_t hi: 22; - uint32_t reserved22:10; - }; - uint32_t val; - } cnt_high; - union { - struct { - uint32_t reserved0: 31; - uint32_t update: 1; - }; - uint32_t val; - } update; - uint32_t alarm_low; /**/ - union { - struct { - uint32_t alarm_hi: 22; - uint32_t reserved22: 10; - }; - uint32_t val; - } alarm_high; - uint32_t load_low; /**/ - union { - struct { - uint32_t load_hi: 22; - uint32_t reserved22:10; - }; - uint32_t val; - } load_high; - uint32_t reload; /**/ - } hw_timer[1]; - uint32_t reserved_24; - uint32_t reserved_28; - uint32_t reserved_2c; - uint32_t reserved_30; - uint32_t reserved_34; - uint32_t reserved_38; - uint32_t reserved_3c; - uint32_t reserved_40; - uint32_t reserved_44; - union { - struct { - uint32_t reserved0: 12; - uint32_t appcpu_reset_en: 1; - uint32_t procpu_reset_en: 1; - uint32_t flashboot_mod_en: 1; - uint32_t sys_reset_length: 3; - uint32_t cpu_reset_length: 3; - uint32_t use_xtal: 1; - uint32_t conf_update_en: 1; - uint32_t stg3: 2; - uint32_t stg2: 2; - uint32_t stg1: 2; - uint32_t stg0: 2; - uint32_t en: 1; - }; - uint32_t val; - } wdt_config0; - union { - struct { - uint32_t divcnt_rst: 1; - uint32_t reserved1: 15; - uint32_t clk_prescale: 16; - }; - uint32_t val; - } wdt_config1; - uint32_t wdt_config2; /**/ - uint32_t wdt_config3; /**/ - uint32_t wdt_config4; /**/ - uint32_t wdt_config5; /**/ - uint32_t wdt_feed; /**/ - uint32_t wdt_wprotect; /**/ - union { - struct { - uint32_t reserved0: 12; - uint32_t start_cycling: 1; - uint32_t clk_sel: 2; - uint32_t rdy: 1; - uint32_t max: 15; - uint32_t start: 1; - }; - uint32_t val; - } rtc_cali_cfg; - union { - struct { - uint32_t cycling_data_vld: 1; - uint32_t reserved1: 6; - uint32_t value: 25; - }; - uint32_t val; - } rtc_cali_cfg1; - union { - struct { - uint32_t t0: 1; - uint32_t wdt: 1; - uint32_t reserved2: 30; - }; - uint32_t val; - } int_ena; - union { - struct { - uint32_t t0: 1; - uint32_t wdt: 1; - uint32_t reserved2: 30; - }; - uint32_t val; - } int_raw; - union { - struct { - uint32_t t0: 1; - uint32_t wdt: 1; - uint32_t reserved2: 30; - }; - uint32_t val; - } int_st; - union { - struct { - uint32_t t0: 1; - uint32_t wdt: 1; - uint32_t reserved2: 30; - }; - uint32_t val; - } int_clr; - union { - struct { - uint32_t timeout: 1; /*timeout indicator*/ - uint32_t reserved1: 2; - uint32_t timeout_rst_cnt: 4; /*Cycles that release calibration timeout reset*/ - uint32_t timeout_thres: 25; /*timeout if cali value counts over threshold*/ - }; - uint32_t val; - } rtc_cali_cfg2; - uint32_t reserved_84; - uint32_t reserved_88; - uint32_t reserved_8c; - uint32_t reserved_90; - uint32_t reserved_94; - uint32_t reserved_98; - uint32_t reserved_9c; - uint32_t reserved_a0; - uint32_t reserved_a4; - uint32_t reserved_a8; - uint32_t reserved_ac; - uint32_t reserved_b0; - uint32_t reserved_b4; - uint32_t reserved_b8; - uint32_t reserved_bc; - uint32_t reserved_c0; - uint32_t reserved_c4; - uint32_t reserved_c8; - uint32_t reserved_cc; - uint32_t reserved_d0; - uint32_t reserved_d4; - uint32_t reserved_d8; - uint32_t reserved_dc; - uint32_t reserved_e0; - uint32_t reserved_e4; - uint32_t reserved_e8; - uint32_t reserved_ec; - uint32_t reserved_f0; - uint32_t reserved_f4; - union { - struct { - uint32_t date: 28; - uint32_t reserved28: 4; - }; - uint32_t val; - } timg_date; - union { - struct { - uint32_t reserved0: 29; - uint32_t wdt_clk_is_active: 1; - uint32_t timer_clk_is_active: 1; - uint32_t en: 1; - }; - uint32_t val; - } clk; + uint32_t reserved_0:9; + /** tx_use_xtal : R/W; bitpos: [9]; default: 0; + * 1: Use XTAL_CLK as the source clock of timer group. 0: Use APB_CLK as the source + * clock of timer group. + */ + uint32_t tx_use_xtal:1; + /** tx_alarm_en : R/W/SC; bitpos: [10]; default: 0; + * When set, the alarm is enabled. This bit is automatically cleared once an + * alarm occurs. + */ + uint32_t tx_alarm_en:1; + uint32_t reserved_11:1; + /** tx_divcnt_rst : WT; bitpos: [12]; default: 0; + * When set, Timer x 's clock divider counter will be reset. + */ + uint32_t tx_divcnt_rst:1; + /** tx_divider : R/W; bitpos: [28:13]; default: 1; + * Timer x clock (Tx_clk) prescaler value. + */ + uint32_t tx_divider:16; + /** tx_autoreload : R/W; bitpos: [29]; default: 1; + * When set, timer x auto-reload at alarm is enabled. + */ + uint32_t tx_autoreload:1; + /** tx_increase : R/W; bitpos: [30]; default: 1; + * When set, the timer x time-base counter will increment every clock tick. When + * cleared, the timer x time-base counter will decrement. + */ + uint32_t tx_increase:1; + /** tx_en : R/W; bitpos: [31]; default: 0; + * When set, the timer x time-base counter is enabled. + */ + uint32_t tx_en:1; + }; + uint32_t val; +} timg_txconfig_reg_t; + +/** Type of txlo register + * Timer x current value, low 32 bits + */ +typedef union { + struct { + /** tx_lo : RO; bitpos: [31:0]; default: 0; + * After writing to TIMG_TxUPDATE_REG, the low 32 bits of the time-base counter + * of timer x can be read here. + */ + uint32_t tx_lo:32; + }; + uint32_t val; +} timg_txlo_reg_t; + +/** Type of txhi register + * Timer $x current value, high 22 bits + */ +typedef union { + struct { + /** tx_hi : RO; bitpos: [21:0]; default: 0; + * After writing to TIMG_T$xUPDATE_REG, the high 22 bits of the time-base counter + * of timer $x can be read here. + */ + uint32_t tx_hi:22; + uint32_t reserved_22:10; + }; + uint32_t val; +} timg_txhi_reg_t; + +/** Type of txupdate register + * Write to copy current timer value to TIMGn_T$x_(LO/HI)_REG + */ +typedef union { + struct { + uint32_t reserved_0:31; + /** tx_update : R/W/SC; bitpos: [31]; default: 0; + * After writing 0 or 1 to TIMG_T$xUPDATE_REG, the counter value is latched. + */ + uint32_t tx_update:1; + }; + uint32_t val; +} timg_txupdate_reg_t; + +/** Type of txalarmlo register + * Timer $x alarm value, low 32 bits + */ +typedef union { + struct { + /** tx_alarm_lo : R/W; bitpos: [31:0]; default: 0; + * Timer $x alarm trigger time-base counter value, low 32 bits. + */ + uint32_t tx_alarm_lo:32; + }; + uint32_t val; +} timg_txalarmlo_reg_t; + +/** Type of txalarmhi register + * Timer $x alarm value, high bits + */ +typedef union { + struct { + /** tx_alarm_hi : R/W; bitpos: [21:0]; default: 0; + * Timer $x alarm trigger time-base counter value, high 22 bits. + */ + uint32_t tx_alarm_hi:22; + uint32_t reserved_22:10; + }; + uint32_t val; +} timg_txalarmhi_reg_t; + +/** Type of txloadlo register + * Timer $x reload value, low 32 bits + */ +typedef union { + struct { + /** tx_load_lo : R/W; bitpos: [31:0]; default: 0; + * Low 32 bits of the value that a reload will load onto timer $x time-base + * Counter. + */ + uint32_t tx_load_lo:32; + }; + uint32_t val; +} timg_txloadlo_reg_t; + +/** Type of txloadhi register + * Timer $x reload value, high 22 bits + */ +typedef union { + struct { + /** tx_load_hi : R/W; bitpos: [21:0]; default: 0; + * High 22 bits of the value that a reload will load onto timer $x time-base + * counter. + */ + uint32_t tx_load_hi:22; + uint32_t reserved_22:10; + }; + uint32_t val; +} timg_txloadhi_reg_t; + +/** Type of txload register + * Write to reload timer from TIMG_T$x_(LOADLOLOADHI)_REG + */ +typedef union { + struct { + /** tx_load : WT; bitpos: [31:0]; default: 0; + * + * Write any value to trigger a timer $x time-base counter reload. + */ + uint32_t tx_load:32; + }; + uint32_t val; +} timg_txload_reg_t; + + +/** Group: WDT Control and configuration registers */ +/** Type of wdtconfig0 register + * Watchdog timer configuration register + */ +typedef union { + struct { + uint32_t reserved_0:12; + /** wdt_appcpu_reset_en : R/W; bitpos: [12]; default: 0; + * WDT reset CPU enable. + */ + uint32_t wdt_appcpu_reset_en:1; + /** wdt_procpu_reset_en : R/W; bitpos: [13]; default: 0; + * WDT reset CPU enable. + */ + uint32_t wdt_procpu_reset_en:1; + /** wdt_flashboot_mod_en : R/W; bitpos: [14]; default: 1; + * When set, Flash boot protection is enabled. + */ + uint32_t wdt_flashboot_mod_en:1; + /** wdt_sys_reset_length : R/W; bitpos: [17:15]; default: 1; + * System reset signal length selection. 0: 100 ns, 1: 200 ns, + * 2: 300 ns, 3: 400 ns, 4: 500 ns, 5: 800 ns, 6: 1.6 us, 7: 3.2 us. + */ + uint32_t wdt_sys_reset_length:3; + /** wdt_cpu_reset_length : R/W; bitpos: [20:18]; default: 1; + * CPU reset signal length selection. 0: 100 ns, 1: 200 ns, + * 2: 300 ns, 3: 400 ns, 4: 500 ns, 5: 800 ns, 6: 1.6 us, 7: 3.2 us. + */ + uint32_t wdt_cpu_reset_length:3; + /** wdt_use_xtal : R/W; bitpos: [21]; default: 0; + * choose WDT clock:0-apb_clk; 1-xtal_clk. + */ + uint32_t wdt_use_xtal:1; + /** wdt_conf_update_en : WT; bitpos: [22]; default: 0; + * update the WDT configuration registers + */ + uint32_t wdt_conf_update_en:1; + /** wdt_stg3 : R/W; bitpos: [24:23]; default: 0; + * Stage 3 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system. + */ + uint32_t wdt_stg3:2; + /** wdt_stg2 : R/W; bitpos: [26:25]; default: 0; + * Stage 2 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system. + */ + uint32_t wdt_stg2:2; + /** wdt_stg1 : R/W; bitpos: [28:27]; default: 0; + * Stage 1 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system. + */ + uint32_t wdt_stg1:2; + /** wdt_stg0 : R/W; bitpos: [30:29]; default: 0; + * Stage 0 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system. + */ + uint32_t wdt_stg0:2; + /** wdt_en : R/W; bitpos: [31]; default: 0; + * When set, MWDT is enabled. + */ + uint32_t wdt_en:1; + }; + uint32_t val; +} timg_wdtconfig0_reg_t; + +/** Type of wdtconfig1 register + * Watchdog timer prescaler register + */ +typedef union { + struct { + /** wdt_divcnt_rst : WT; bitpos: [0]; default: 0; + * When set, WDT 's clock divider counter will be reset. + */ + uint32_t wdt_divcnt_rst:1; + uint32_t reserved_1:15; + /** wdt_clk_prescale : R/W; bitpos: [31:16]; default: 1; + * MWDT clock prescaler value. MWDT clock period = 12.5 ns * + * TIMG_WDT_CLK_PRESCALE. + */ + uint32_t wdt_clk_prescale:16; + }; + uint32_t val; +} timg_wdtconfig1_reg_t; + +/** Type of wdtconfig2 register + * Watchdog timer stage 0 timeout value + */ +typedef union { + struct { + /** wdt_stg0_hold : R/W; bitpos: [31:0]; default: 26000000; + * Stage 0 timeout value, in MWDT clock cycles. + */ + uint32_t wdt_stg0_hold:32; + }; + uint32_t val; +} timg_wdtconfig2_reg_t; + +/** Type of wdtconfig3 register + * Watchdog timer stage 1 timeout value + */ +typedef union { + struct { + /** wdt_stg1_hold : R/W; bitpos: [31:0]; default: 134217727; + * Stage 1 timeout value, in MWDT clock cycles. + */ + uint32_t wdt_stg1_hold:32; + }; + uint32_t val; +} timg_wdtconfig3_reg_t; + +/** Type of wdtconfig4 register + * Watchdog timer stage 2 timeout value + */ +typedef union { + struct { + /** wdt_stg2_hold : R/W; bitpos: [31:0]; default: 1048575; + * Stage 2 timeout value, in MWDT clock cycles. + */ + uint32_t wdt_stg2_hold:32; + }; + uint32_t val; +} timg_wdtconfig4_reg_t; + +/** Type of wdtconfig5 register + * Watchdog timer stage 3 timeout value + */ +typedef union { + struct { + /** wdt_stg3_hold : R/W; bitpos: [31:0]; default: 1048575; + * Stage 3 timeout value, in MWDT clock cycles. + */ + uint32_t wdt_stg3_hold:32; + }; + uint32_t val; +} timg_wdtconfig5_reg_t; + +/** Type of wdtfeed register + * Write to feed the watchdog timer + */ +typedef union { + struct { + /** wdt_feed : WT; bitpos: [31:0]; default: 0; + * Write any value to feed the MWDT. (WO) + */ + uint32_t wdt_feed:32; + }; + uint32_t val; +} timg_wdtfeed_reg_t; + +/** Type of wdtwprotect register + * Watchdog write protect register + */ +typedef union { + struct { + /** wdt_wkey : R/W; bitpos: [31:0]; default: 1356348065; + * If the register contains a different value than its reset value, write + * protection is enabled. + */ + uint32_t wdt_wkey:32; + }; + uint32_t val; +} timg_wdtwprotect_reg_t; + + +/** Group: RTC CALI Control and configuration registers */ +/** Type of rtccalicfg register + * RTC calibration configure register + */ +typedef union { + struct { + uint32_t reserved_0:12; + /** rtc_cali_start_cycling : R/W; bitpos: [12]; default: 1; + * Reserved + */ + uint32_t rtc_cali_start_cycling:1; + /** rtc_cali_clk_sel : R/W; bitpos: [14:13]; default: 1; + * 0:rtc slow clock. 1:clk_8m, 2:xtal_32k. + */ + uint32_t rtc_cali_clk_sel:2; + /** rtc_cali_rdy : RO; bitpos: [15]; default: 0; + * Reserved + */ + uint32_t rtc_cali_rdy:1; + /** rtc_cali_max : R/W; bitpos: [30:16]; default: 1; + * Reserved + */ + uint32_t rtc_cali_max:15; + /** rtc_cali_start : R/W; bitpos: [31]; default: 0; + * Reserved + */ + uint32_t rtc_cali_start:1; + }; + uint32_t val; +} timg_rtccalicfg_reg_t; + +/** Type of rtccalicfg1 register + * RTC calibration configure1 register + */ +typedef union { + struct { + /** rtc_cali_cycling_data_vld : RO; bitpos: [0]; default: 0; + * Reserved + */ + uint32_t rtc_cali_cycling_data_vld:1; + uint32_t reserved_1:6; + /** rtc_cali_value : RO; bitpos: [31:7]; default: 0; + * Reserved + */ + uint32_t rtc_cali_value:25; + }; + uint32_t val; +} timg_rtccalicfg1_reg_t; + +/** Type of rtccalicfg2 register + * Timer group calibration register + */ +typedef union { + struct { + /** rtc_cali_timeout : RO; bitpos: [0]; default: 0; + * RTC calibration timeout indicator + */ + uint32_t rtc_cali_timeout:1; + uint32_t reserved_1:2; + /** rtc_cali_timeout_rst_cnt : R/W; bitpos: [6:3]; default: 3; + * Cycles that release calibration timeout reset + */ + uint32_t rtc_cali_timeout_rst_cnt:4; + /** rtc_cali_timeout_thres : R/W; bitpos: [31:7]; default: 33554431; + * Threshold value for the RTC calibration timer. If the calibration timer's value + * exceeds this threshold, a timeout is triggered. + */ + uint32_t rtc_cali_timeout_thres:25; + }; + uint32_t val; +} timg_rtccalicfg2_reg_t; + + +/** Group: Interrupt registers */ +/** Type of int_ena_timers register + * Interrupt enable bits + */ +typedef union { + struct { + /** t0_int_ena : R/W; bitpos: [0]; default: 0; + * The interrupt enable bit for the TIMG_T$x_INT interrupt. + */ + uint32_t t0_int_ena:1; + /** wdt_int_ena : R/W; bitpos: [1]; default: 0; + * The interrupt enable bit for the TIMG_WDT_INT interrupt. + */ + uint32_t wdt_int_ena:1; + uint32_t reserved_2:30; + }; + uint32_t val; +} timg_int_ena_timers_reg_t; + +/** Type of int_raw_timers register + * Raw interrupt status + */ +typedef union { + struct { + /** t0_int_raw : R/SS/WTC; bitpos: [0]; default: 0; + * The raw interrupt status bit for the TIMG_T$x_INT interrupt. + */ + uint32_t t0_int_raw:1; + /** wdt_int_raw : R/SS/WTC; bitpos: [1]; default: 0; + * The raw interrupt status bit for the TIMG_WDT_INT interrupt. + */ + uint32_t wdt_int_raw:1; + uint32_t reserved_2:30; + }; + uint32_t val; +} timg_int_raw_timers_reg_t; + +/** Type of int_st_timers register + * Masked interrupt status + */ +typedef union { + struct { + /** t0_int_st : RO; bitpos: [0]; default: 0; + * The masked interrupt status bit for the TIMG_T$x_INT interrupt. + */ + uint32_t t0_int_st:1; + /** wdt_int_st : RO; bitpos: [1]; default: 0; + * The masked interrupt status bit for the TIMG_WDT_INT interrupt. + */ + uint32_t wdt_int_st:1; + uint32_t reserved_2:30; + }; + uint32_t val; +} timg_int_st_timers_reg_t; + +/** Type of int_clr_timers register + * Interrupt clear bits + */ +typedef union { + struct { + /** t0_int_clr : WT; bitpos: [0]; default: 0; + * Set this bit to clear the TIMG_T$x_INT interrupt. + */ + uint32_t t0_int_clr:1; + /** wdt_int_clr : WT; bitpos: [1]; default: 0; + * Set this bit to clear the TIMG_WDT_INT interrupt. + */ + uint32_t wdt_int_clr:1; + uint32_t reserved_2:30; + }; + uint32_t val; +} timg_int_clr_timers_reg_t; + + +/** Group: Version register */ +/** Type of ntimers_date register + * Timer version control register + */ +typedef union { + struct { + /** ntimgs_date : R/W; bitpos: [27:0]; default: 33579409; + * Timer version control register + */ + uint32_t ntimgs_date:28; + uint32_t reserved_28:4; + }; + uint32_t val; +} timg_ntimers_date_reg_t; + + +/** Group: Clock configuration registers */ +/** Type of regclk register + * Timer group clock gate register + */ +typedef union { + struct { + uint32_t reserved_0:29; + /** wdt_clk_is_active : R/W; bitpos: [29]; default: 1; + * enable WDT's clock + */ + uint32_t wdt_clk_is_active:1; + /** timer_clk_is_active : R/W; bitpos: [30]; default: 1; + * enable Timer $x's clock + */ + uint32_t timer_clk_is_active:1; + /** clk_en : R/W; bitpos: [31]; default: 0; + * Register clock gate signal. 1: Registers can be read and written to by software. 0: + * Registers can not be read or written to by software. + */ + uint32_t clk_en:1; + }; + uint32_t val; +} timg_regclk_reg_t; + +typedef struct { + volatile timg_txconfig_reg_t config; + volatile timg_txlo_reg_t lo; + volatile timg_txhi_reg_t hi; + volatile timg_txupdate_reg_t update; + volatile timg_txalarmlo_reg_t alarmlo; + volatile timg_txalarmhi_reg_t alarmhi; + volatile timg_txloadlo_reg_t loadlo; + volatile timg_txloadhi_reg_t loadhi; + volatile timg_txload_reg_t load; +} timg_hwtimer_reg_t; + +typedef struct { + volatile timg_hwtimer_reg_t hw_timer[1]; + uint32_t reserved_024[9]; + volatile timg_wdtconfig0_reg_t wdtconfig0; + volatile timg_wdtconfig1_reg_t wdtconfig1; + volatile timg_wdtconfig2_reg_t wdtconfig2; + volatile timg_wdtconfig3_reg_t wdtconfig3; + volatile timg_wdtconfig4_reg_t wdtconfig4; + volatile timg_wdtconfig5_reg_t wdtconfig5; + volatile timg_wdtfeed_reg_t wdtfeed; + volatile timg_wdtwprotect_reg_t wdtwprotect; + volatile timg_rtccalicfg_reg_t rtccalicfg; + volatile timg_rtccalicfg1_reg_t rtccalicfg1; + volatile timg_int_ena_timers_reg_t int_ena_timers; + volatile timg_int_raw_timers_reg_t int_raw_timers; + volatile timg_int_st_timers_reg_t int_st_timers; + volatile timg_int_clr_timers_reg_t int_clr_timers; + volatile timg_rtccalicfg2_reg_t rtccalicfg2; + uint32_t reserved_084[29]; + volatile timg_ntimers_date_reg_t ntimers_date; + volatile timg_regclk_reg_t regclk; } timg_dev_t; + extern timg_dev_t TIMERG0; extern timg_dev_t TIMERG1; + +#ifndef __cplusplus +_Static_assert(sizeof(timg_dev_t) == 0x100, "Invalid size of timg_dev_t structure"); +#endif + #ifdef __cplusplus } #endif - -#endif /* _SOC_TIMG_STRUCT_H_ */ diff --git a/components/soc/esp32h2/include/soc/twai_struct.h b/components/soc/esp32h2/include/soc/twai_struct.h index a2c72e5afa..8c9b60059c 100644 --- a/components/soc/esp32h2/include/soc/twai_struct.h +++ b/components/soc/esp32h2/include/soc/twai_struct.h @@ -35,10 +35,10 @@ typedef volatile struct twai_dev_s { uint32_t lom: 1; /* MOD.1 Listen Only Mode */ uint32_t stm: 1; /* MOD.2 Self Test Mode */ uint32_t afm: 1; /* MOD.3 Acceptance Filter Mode */ - uint32_t reserved28: 28; /* Internal Reserved. MOD.4 Sleep Mode not supported */ + uint32_t reserved4: 28; /* Internal Reserved. MOD.4 Sleep Mode not supported */ }; uint32_t val; - } mode_reg; /* Address 0 */ + } mode_reg; /* Address 0x0000 */ union { struct { uint32_t tr: 1; /* CMR.0 Transmission Request */ @@ -46,10 +46,10 @@ typedef volatile struct twai_dev_s { uint32_t rrb: 1; /* CMR.2 Release Receive Buffer */ uint32_t cdo: 1; /* CMR.3 Clear Data Overrun */ uint32_t srr: 1; /* CMR.4 Self Reception Request */ - uint32_t reserved27: 27; /* Internal Reserved */ + uint32_t reserved5: 27; /* Internal Reserved */ }; uint32_t val; - } command_reg; /* Address 1 */ + } command_reg; /* Address 0x0004 */ union { struct { uint32_t rbs: 1; /* SR.0 Receive Buffer Status */ @@ -61,97 +61,99 @@ typedef volatile struct twai_dev_s { uint32_t es: 1; /* SR.6 Error Status */ uint32_t bs: 1; /* SR.7 Bus Status */ uint32_t ms: 1; /* SR.8 Miss Status */ - uint32_t reserved23: 23; /* Internal Reserved */ + uint32_t reserved9: 23; /* Internal Reserved */ }; uint32_t val; - } status_reg; /* Address 2 */ + } status_reg; /* Address 0x0008 */ union { struct { uint32_t ri: 1; /* IR.0 Receive Interrupt */ uint32_t ti: 1; /* IR.1 Transmit Interrupt */ uint32_t ei: 1; /* IR.2 Error Interrupt */ - uint32_t reserved2: 2; /* Internal Reserved (Data Overrun interrupt and Wake-up not supported) */ + uint32_t doi: 1; /* IR.3 Data Overrun Interrupt */ + uint32_t reserved4: 1; /* Internal Reserved (Wake-up not supported) */ uint32_t epi: 1; /* IR.5 Error Passive Interrupt */ uint32_t ali: 1; /* IR.6 Arbitration Lost Interrupt */ uint32_t bei: 1; /* IR.7 Bus Error Interrupt */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } interrupt_reg; /* Address 3 */ + } interrupt_reg; /* Address 0x000C */ union { struct { uint32_t rie: 1; /* IER.0 Receive Interrupt Enable */ uint32_t tie: 1; /* IER.1 Transmit Interrupt Enable */ uint32_t eie: 1; /* IER.2 Error Interrupt Enable */ - uint32_t reserved2: 2; /* Internal Reserved (Data Overrun interrupt and Wake-up not supported) */ + uint32_t doie: 1; /* IER.3 Data Overrun Interrupt Enable */ + uint32_t reserved4: 1; /* Internal Reserved (Wake-up not supported) */ uint32_t epie: 1; /* IER.5 Error Passive Interrupt Enable */ uint32_t alie: 1; /* IER.6 Arbitration Lost Interrupt Enable */ uint32_t beie: 1; /* IER.7 Bus Error Interrupt Enable */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } interrupt_enable_reg; /* Address 4 */ - uint32_t reserved_05; /* Address 5 */ + } interrupt_enable_reg; /* Address 0x0010 */ + uint32_t reserved_14; union { struct { uint32_t brp: 13; /* BTR0[12:0] Baud Rate Prescaler */ - uint32_t reserved1: 1; /* Internal Reserved */ + uint32_t reserved13: 1; /* Internal Reserved */ uint32_t sjw: 2; /* BTR0[15:14] Synchronization Jump Width*/ uint32_t reserved16: 16; /* Internal Reserved */ }; uint32_t val; - } bus_timing_0_reg; /* Address 6 */ + } bus_timing_0_reg; /* Address 0x0018 */ union { struct { uint32_t tseg1: 4; /* BTR1[3:0] Timing Segment 1 */ uint32_t tseg2: 3; /* BTR1[6:4] Timing Segment 2 */ uint32_t sam: 1; /* BTR1.7 Sampling*/ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } bus_timing_1_reg; /* Address 7 */ - uint32_t reserved_08; /* Address 8 (Output control not supported) */ - uint32_t reserved_09; /* Address 9 (Test Register not supported) */ - uint32_t reserved_10; /* Address 10 */ + } bus_timing_1_reg; /* Address 0x001C */ + uint32_t reserved_20; /* Address 0x0020 (Output control not supported) */ + uint32_t reserved_24; /* Address 0x0024 (Test Register not supported) */ + uint32_t reserved_28; /* Address 0x0028 */ //Capture and Counter Registers union { struct { uint32_t alc: 5; /* ALC[4:0] Arbitration lost capture */ - uint32_t reserved27: 27; /* Internal Reserved */ + uint32_t reserved5: 27; /* Internal Reserved */ }; uint32_t val; - } arbitration_lost_captue_reg; /* Address 11 */ + } arbitration_lost_captue_reg; /* Address 0x002C */ union { struct { uint32_t seg: 5; /* ECC[4:0] Error Code Segment 0 to 5 */ uint32_t dir: 1; /* ECC.5 Error Direction (TX/RX) */ uint32_t errc: 2; /* ECC[7:6] Error Code */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } error_code_capture_reg; /* Address 12 */ + } error_code_capture_reg; /* Address 0x0030 */ union { struct { uint32_t ewl: 8; /* EWL[7:0] Error Warning Limit */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } error_warning_limit_reg; /* EWLR[7:0] Error Warning Limit: Address 13 */ + } error_warning_limit_reg; /* Address 0x0034 */ union { struct { uint32_t rxerr: 8; /* RXERR[7:0] Receive Error Counter */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } rx_error_counter_reg; /* Address 12 */ + } rx_error_counter_reg; /* Address 0x0038 */ union { struct { uint32_t txerr: 8; /* TXERR[7:0] Receive Error Counter */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } tx_error_counter_reg; /* Address 15 */ + } tx_error_counter_reg; /* Address 0x003C */ //Shared Registers (TX Buff/RX Buff/Acc Filter) union { @@ -159,45 +161,49 @@ typedef volatile struct twai_dev_s { union { struct { uint32_t byte: 8; /* ACRx[7:0] Acceptance Code */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; } acr[4]; union { struct { uint32_t byte: 8; /* AMRx[7:0] Acceptance Mask */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; } amr[4]; - uint32_t reserved32[5]; + uint32_t reserved_60; + uint32_t reserved_64; + uint32_t reserved_68; + uint32_t reserved_6c; + uint32_t reserved_70; } acceptance_filter; union { struct { - uint32_t byte: 8; - uint32_t reserved24: 24; + uint32_t byte: 8; /* TX/RX Byte X [7:0] */ + uint32_t reserved24: 24; /* Internal Reserved */ }; uint32_t val; } tx_rx_buffer[13]; - }; /* Address 16-28 TX/RX Buffer and Acc Filter*/; + }; /* Address 0x0040 - 0x0070 */ //Misc Registers union { struct { uint32_t rmc: 7; /* RMC[6:0] RX Message Counter */ - uint32_t reserved25: 25; /* Internal Reserved */ + uint32_t reserved7: 25; /* Internal Reserved */ }; uint32_t val; - } rx_message_counter_reg; /* Address 29 */ - uint32_t reserved_30; /* Address 30 (RX Buffer Start Address not supported) */ + } rx_message_counter_reg; /* Address 0x0074 */ + uint32_t reserved_78; /* Address 0x0078 (RX Buffer Start Address not supported) */ union { struct { uint32_t cd: 8; /* CDR[7:0] CLKOUT frequency selector based of fOSC */ uint32_t co: 1; /* CDR.8 CLKOUT enable/disable */ - uint32_t reserved24: 23; /* Internal Reserved */ + uint32_t reserved9: 23; /* Internal Reserved */ }; uint32_t val; - } clock_divider_reg; /* Address 31 */ + } clock_divider_reg; /* Address 0x007C */ } twai_dev_t; _Static_assert(sizeof(twai_dev_t) == 128, "TWAI registers should be 32 * 4 bytes"); diff --git a/components/soc/esp32h2/include/soc/uart_pins.h b/components/soc/esp32h2/include/soc/uart_pins.h new file mode 100644 index 0000000000..26b225a346 --- /dev/null +++ b/components/soc/esp32h2/include/soc/uart_pins.h @@ -0,0 +1,44 @@ +// Copyright 2015-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. + +#pragma once + +#include "soc/io_mux_reg.h" + +/* Specify the number of pins for UART */ +#define SOC_UART_PINS_COUNT (4) + +/* Specify the GPIO pin number for each UART signal in the IOMUX */ +#define U0RXD_GPIO_NUM 20 +#define U0TXD_GPIO_NUM 21 +#define U0RTS_GPIO_NUM (-1) +#define U0CTS_GPIO_NUM (-1) + +#define U1RXD_GPIO_NUM (-1) +#define U1TXD_GPIO_NUM (-1) +#define U1RTS_GPIO_NUM (-1) +#define U1CTS_GPIO_NUM (-1) + +/* The following defines are necessary for reconfiguring the UART + * to use IOMUX, at runtime. */ +#define U0TXD_MUX_FUNC (FUNC_U0TXD_U0TXD) +#define U0RXD_MUX_FUNC (FUNC_U0RXD_U0RXD) +/* No func for the following pins, they shall not be used */ +#define U0RTS_MUX_FUNC (-1) +#define U0CTS_MUX_FUNC (-1) +/* Same goes for UART1 */ +#define U1TXD_MUX_FUNC (-1) +#define U1RXD_MUX_FUNC (-1) +#define U1RTS_MUX_FUNC (-1) +#define U1CTS_MUX_FUNC (-1) diff --git a/components/soc/esp32h2/include/soc/uart_struct.h b/components/soc/esp32h2/include/soc/uart_struct.h index ad9ca42ff7..82f8ef6686 100644 --- a/components/soc/esp32h2/include/soc/uart_struct.h +++ b/components/soc/esp32h2/include/soc/uart_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct uart_dev_s { union { struct { uint32_t rw_byte; /*a*/ diff --git a/components/soc/esp32h2/include/soc/uhci_struct.h b/components/soc/esp32h2/include/soc/uhci_struct.h index a89c4d0126..164f1a1334 100644 --- a/components/soc/esp32h2/include/soc/uhci_struct.h +++ b/components/soc/esp32h2/include/soc/uhci_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct uhci_dev_s { union { struct { uint32_t tx_rst: 1; /*Write 1 then write 0 to this bit to reset decode state machine.*/ diff --git a/components/soc/esp32h2/include/soc/usb_serial_jtag_struct.h b/components/soc/esp32h2/include/soc/usb_serial_jtag_struct.h index 72c1005d30..e9e4b8b8ea 100644 --- a/components/soc/esp32h2/include/soc/usb_serial_jtag_struct.h +++ b/components/soc/esp32h2/include/soc/usb_serial_jtag_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif #include "soc.h" -typedef volatile struct { +typedef volatile struct usb_serial_jtag_dev_s { union { struct { uint32_t rdwr_byte : 8; /*Write and read byte data to/from UART Tx/Rx FIFO through this field. When USB_SERIAL_JTAG_SERIAL_IN_EMPTY_INT is set then user can write data (up to 64 bytes) into UART Tx FIFO. When USB_SERIAL_JTAG_SERIAL_OUT_RECV_PKT_INT is set, user can check USB_SERIAL_JTAG_OUT_EP1_WR_ADDR and USB_SERIAL_JTAG_OUT_EP0_RD_ADDR to know how many data is received, then read that amount of data from UART Rx FIFO. */ diff --git a/components/soc/esp32h2/ld/esp32h2.peripherals.ld b/components/soc/esp32h2/ld/esp32h2.peripherals.ld index 38e6b58258..ee3154ad43 100644 --- a/components/soc/esp32h2/ld/esp32h2.peripherals.ld +++ b/components/soc/esp32h2/ld/esp32h2.peripherals.ld @@ -7,7 +7,7 @@ PROVIDE ( SIGMADELTA = 0x60004f00 ); PROVIDE ( RTCCNTL = 0x60008000 ); PROVIDE ( RTCIO = 0x60008400 ); PROVIDE ( HINF = 0x6000B000 ); -PROVIDE ( I2S1 = 0x6002d000 ); +PROVIDE ( I2S0 = 0x6002d000 ); PROVIDE ( I2C0 = 0x60013000 ); PROVIDE ( UHCI0 = 0x60014000 ); PROVIDE ( UHCI1 = 0x6000c000 ); diff --git a/components/soc/esp32h2/uart_periph.c b/components/soc/esp32h2/uart_periph.c index 999eb69fd8..d4262c6776 100644 --- a/components/soc/esp32h2/uart_periph.c +++ b/components/soc/esp32h2/uart_periph.c @@ -18,20 +18,71 @@ Bunch of constants for every UART peripheral: GPIO signals, irqs, hw addr of registers etc */ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { - { - .tx_sig = U0TXD_OUT_IDX, - .rx_sig = U0RXD_IN_IDX, - .rts_sig = U0RTS_OUT_IDX, - .cts_sig = U0CTS_IN_IDX, + { + .pins = { + [SOC_UART_TX_PIN_IDX] = { + .default_gpio = U0TXD_GPIO_NUM, + .iomux_func = U0TXD_MUX_FUNC, + .input = 0, + .signal = U0TXD_OUT_IDX, + }, + + [SOC_UART_RX_PIN_IDX] = { + .default_gpio = U0RXD_GPIO_NUM, + .iomux_func = U0RXD_MUX_FUNC, + .input = 1, + .signal = U0RXD_IN_IDX, + }, + + [SOC_UART_RTS_PIN_IDX] = { + .default_gpio = U0RTS_GPIO_NUM, + .iomux_func = U0RTS_MUX_FUNC, + .input = 0, + .signal = U0RTS_OUT_IDX, + }, + + [SOC_UART_CTS_PIN_IDX] = { + .default_gpio = U0CTS_GPIO_NUM, + .iomux_func = U0CTS_MUX_FUNC, + .input = 1, + .signal = U0CTS_IN_IDX, + } + }, .irq = ETS_UART0_INTR_SOURCE, .module = PERIPH_UART0_MODULE, }, + { - .tx_sig = U1TXD_OUT_IDX, - .rx_sig = U1RXD_IN_IDX, - .rts_sig = U1RTS_OUT_IDX, - .cts_sig = U1CTS_IN_IDX, + .pins = { + [SOC_UART_TX_PIN_IDX] = { + .default_gpio = U1TXD_GPIO_NUM, + .iomux_func = U1TXD_MUX_FUNC, + .input = 0, + .signal = U1TXD_OUT_IDX, + }, + + [SOC_UART_RX_PIN_IDX] = { + .default_gpio = U1RXD_GPIO_NUM, + .iomux_func = U1RXD_MUX_FUNC, + .input = 1, + .signal = U1RXD_IN_IDX, + }, + + [SOC_UART_RTS_PIN_IDX] = { + .default_gpio = U1RTS_GPIO_NUM, + .iomux_func = U1RTS_MUX_FUNC, + .input = 0, + .signal = U1RTS_OUT_IDX, + }, + + [SOC_UART_CTS_PIN_IDX] = { + .default_gpio = U1CTS_GPIO_NUM, + .iomux_func = U1CTS_MUX_FUNC, + .input = 1, + .signal = U1CTS_IN_IDX, + }, + }, .irq = ETS_UART1_INTR_SOURCE, .module = PERIPH_UART1_MODULE, - } + }, }; diff --git a/components/soc/esp32s2/CMakeLists.txt b/components/soc/esp32s2/CMakeLists.txt index d25d0ce0eb..218b4bdbb8 100644 --- a/components/soc/esp32s2/CMakeLists.txt +++ b/components/soc/esp32s2/CMakeLists.txt @@ -6,6 +6,7 @@ set(srcs "i2c_periph.c" "i2s_periph.c" "interrupts.c" + "lcd_periph.c" "ledc_periph.c" "pcnt_periph.c" "rmt_periph.c" @@ -15,7 +16,8 @@ set(srcs "timer_periph.c" "touch_sensor_periph.c" "uart_periph.c" - "usb_periph.c") + "usb_periph.c" + "usb_phy_periph.c") add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}") diff --git a/components/soc/esp32s2/i2s_periph.c b/components/soc/esp32s2/i2s_periph.c index 5029a68c8a..48c6161d20 100644 --- a/components/soc/esp32s2/i2s_periph.c +++ b/components/soc/esp32s2/i2s_periph.c @@ -1,9 +1,9 @@ -// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// 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 @@ -20,17 +20,22 @@ */ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { { - .o_bck_in_sig = I2S0O_BCK_IN_IDX, - .o_ws_in_sig = I2S0O_WS_IN_IDX, - .o_bck_out_sig = I2S0O_BCK_OUT_IDX, - .o_ws_out_sig = I2S0O_WS_OUT_IDX, - .o_data_out_sig = I2S0O_DATA_OUT23_IDX, - .i_bck_in_sig = I2S0I_BCK_OUT_IDX, - .i_ws_in_sig = I2S0I_WS_OUT_IDX, - .i_bck_out_sig = I2S0I_BCK_IN_IDX, - .i_ws_out_sig = I2S0I_WS_IN_IDX, - .i_data_in_sig = I2S0I_DATA_IN15_IDX, - .irq = ETS_I2S0_INTR_SOURCE, - .module = PERIPH_I2S0_MODULE, + .mck_out_sig = CLK_I2S_MUX_IDX, + + .m_tx_bck_sig = I2S0O_BCK_OUT_IDX, + .m_rx_bck_sig = I2S0I_BCK_OUT_IDX, + .m_tx_ws_sig = I2S0O_WS_OUT_IDX, + .m_rx_ws_sig = I2S0I_WS_OUT_IDX, + + .s_tx_bck_sig = I2S0O_BCK_IN_IDX, + .s_rx_bck_sig = I2S0I_BCK_IN_IDX, + .s_tx_ws_sig = I2S0O_WS_IN_IDX, + .s_rx_ws_sig = I2S0I_WS_IN_IDX, + + .data_out_sig = I2S0O_DATA_OUT23_IDX, + .data_in_sig = I2S0I_DATA_IN15_IDX, + + .irq = ETS_I2S0_INTR_SOURCE, + .module = PERIPH_I2S0_MODULE, } }; diff --git a/components/soc/esp32s2/include/soc/apb_ctrl_struct.h b/components/soc/esp32s2/include/soc/apb_ctrl_struct.h index d05c2c9a00..dbf2e4e3ef 100644 --- a/components/soc/esp32s2/include/soc/apb_ctrl_struct.h +++ b/components/soc/esp32s2/include/soc/apb_ctrl_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct apb_ctrl_dev_s { union { struct { uint32_t pre_div: 10; diff --git a/components/soc/esp32s2/include/soc/apb_saradc_struct.h b/components/soc/esp32s2/include/soc/apb_saradc_struct.h index e9811dab60..505596f994 100644 --- a/components/soc/esp32s2/include/soc/apb_saradc_struct.h +++ b/components/soc/esp32s2/include/soc/apb_saradc_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct apb_saradc_dev_s { union { struct { uint32_t start_force: 1; diff --git a/components/soc/esp32s2/include/soc/cache_memory.h b/components/soc/esp32s2/include/soc/cache_memory.h index 06de5a4323..5c182bd6c4 100644 --- a/components/soc/esp32s2/include/soc/cache_memory.h +++ b/components/soc/esp32s2/include/soc/cache_memory.h @@ -67,7 +67,7 @@ extern "C" { #define BUS_DROM0_CACHE_SIZE BUS_SIZE(DROM0) #define BUS_DRAM0_CACHE_SIZE BUS_SIZE(DRAM0_CACHE) #define BUS_DRAM1_CACHE_SIZE BUS_SIZE(DRAM1) -#define BUS_DPORT_CACHE_SIZE BUS_SIZE(DPORT) +#define BUS_DPORT_CACHE_SIZE BUS_SIZE(DPORT_CACHE) #define PRO_CACHE_IBUS0 0 #define PRO_CACHE_IBUS0_MMU_START 0 diff --git a/components/soc/esp32s2/include/soc/cp_dma_struct.h b/components/soc/esp32s2/include/soc/cp_dma_struct.h index 208c82939c..15fb42e451 100644 --- a/components/soc/esp32s2/include/soc/cp_dma_struct.h +++ b/components/soc/esp32s2/include/soc/cp_dma_struct.h @@ -69,6 +69,7 @@ typedef union { * This is the interrupt raw bit. Triggered when crc calculation is done. */ uint32_t dma_crc_done_int_raw: 1; + uint32_t reserved9: 23; }; uint32_t val; } cp_dma_int_raw_reg_t; @@ -123,6 +124,7 @@ typedef union { * cp_crc_done_int_ena is set to 1. */ uint32_t dma_crc_done_int_st: 1; + uint32_t reserved9: 23; }; uint32_t val; } cp_dma_int_st_reg_t; @@ -168,6 +170,7 @@ typedef union { * This is the interrupt enable bit for cp_crc_done_int interrupt. */ uint32_t dma_crc_done_int_ena: 1; + uint32_t reserved9: 23; }; uint32_t val; } cp_dma_int_ena_reg_t; @@ -213,6 +216,7 @@ typedef union { * Set this bit to clear cp_crc_done_int interrupt. */ uint32_t dma_crc_done_int_clr: 1; + uint32_t reserved9: 23; }; uint32_t val; } cp_dma_int_clr_reg_t; @@ -491,6 +495,7 @@ typedef union { * Copy DMA FIFO empty signal. */ uint32_t dma_fifo_empty: 1; + uint32_t reserved24: 8; }; uint32_t val; } cp_dma_in_st_reg_t; @@ -516,6 +521,7 @@ typedef union { * Copy DMA FIFO full signal. */ uint32_t dma_fifo_full: 1; + uint32_t reserved24: 8; }; uint32_t val; } cp_dma_out_st_reg_t; diff --git a/components/soc/esp32s2/include/soc/dedic_gpio_struct.h b/components/soc/esp32s2/include/soc/dedic_gpio_struct.h index 3ccd588b97..04aae779ad 100644 --- a/components/soc/esp32s2/include/soc/dedic_gpio_struct.h +++ b/components/soc/esp32s2/include/soc/dedic_gpio_struct.h @@ -31,6 +31,7 @@ typedef union { * gpio. */ uint32_t gpio_out_drt_vlaue: 8; + uint32_t reserved8: 24; }; uint32_t val; } dedic_gpio_out_drt_reg_t; @@ -49,6 +50,7 @@ typedef union { * channel's output would be masked. */ uint32_t gpio_out_msk: 8; + uint32_t reserved16: 16; }; uint32_t val; } dedic_gpio_out_msk_reg_t; @@ -98,6 +100,7 @@ typedef union { * clear output value; 3: inverse output value. */ uint32_t gpio_out_idv_ch7: 2; + uint32_t reserved16: 16; }; uint32_t val; } dedic_gpio_out_idv_reg_t; @@ -147,6 +150,7 @@ typedef union { * select CPU instructors. */ uint32_t gpio_out_cpu_sel7: 1; + uint32_t reserved8: 24; }; uint32_t val; } dedic_gpio_out_cpu_reg_t; @@ -196,6 +200,7 @@ typedef union { * 3: three clock delay. */ uint32_t gpio_in_dly_ch7: 2; + uint32_t reserved16: 16; }; uint32_t val; } dedic_gpio_in_dly_reg_t; @@ -285,6 +290,7 @@ typedef union { * 6/7: falling and raising edge trigger. */ uint32_t gpio_intr_mode_ch7: 3; + uint32_t reserved24: 8; }; uint32_t val; } dedic_gpio_intr_rcgn_reg_t; @@ -301,6 +307,7 @@ typedef union { * DEDIC_GPIO_OUT_IDV_REG. */ uint32_t gpio_out_status: 8; + uint32_t reserved8: 24; }; uint32_t val; } dedic_gpio_out_scan_reg_t; @@ -314,6 +321,7 @@ typedef union { * gpio in value after configured by DEDIC_GPIO_IN_DLY_REG. */ uint32_t gpio_in_status: 8; + uint32_t reserved8: 24; }; uint32_t val; } dedic_gpio_in_scan_reg_t; @@ -365,6 +373,7 @@ typedef union { * change configured by DEDIC_GPIO_INTR_RCGN_REG. */ uint32_t gpio7_int_raw: 1; + uint32_t reserved8: 24; }; uint32_t val; } dedic_gpio_intr_raw_reg_t; @@ -406,6 +415,7 @@ typedef union { * This enable bit for reg_gpio7_int_st register. */ uint32_t gpio7_int_ena: 1; + uint32_t reserved8: 24; }; uint32_t val; } dedic_gpio_intr_rls_reg_t; @@ -447,6 +457,7 @@ typedef union { * This is the status bit for reg_gpio7_int_raw when reg_gpio7_int_ena is set to 1. */ uint32_t gpio7_int_st: 1; + uint32_t reserved8: 24; }; uint32_t val; } dedic_gpio_intr_st_reg_t; @@ -488,6 +499,7 @@ typedef union { * Set this bit to clear the reg_gpio7_int_raw interrupt. */ uint32_t gpio7_int_clr: 1; + uint32_t reserved8: 24; }; uint32_t val; } dedic_gpio_intr_clr_reg_t; diff --git a/components/soc/esp32s2/include/soc/efuse_reg.h b/components/soc/esp32s2/include/soc/efuse_reg.h index 4d76d1115c..f7be21c6ed 100644 --- a/components/soc/esp32s2/include/soc/efuse_reg.h +++ b/components/soc/esp32s2/include/soc/efuse_reg.h @@ -917,18 +917,18 @@ extern "C" { #define EFUSE_SPI_PAD_CONF_1_S 0 #define EFUSE_RD_MAC_SPI_SYS_3_REG (DR_REG_EFUSE_BASE + 0x050) -/* EFUSE_SYS_DATA_PART0_0 : RO ;bitpos:[31:25] ;default: 7'h0 ; */ -/*description: Stores the fist 7 bits of the zeroth part of system data.*/ -#define EFUSE_SYS_DATA_PART0_0 0x0000007F -#define EFUSE_SYS_DATA_PART0_0_M ((EFUSE_SYS_DATA_PART0_0_V)<<(EFUSE_SYS_DATA_PART0_0_S)) -#define EFUSE_SYS_DATA_PART0_0_V 0x7F -#define EFUSE_SYS_DATA_PART0_0_S 25 -/* EFUSE_PKG_VERSION : RO ;bitpos:[24:21] ;default: 4'h0 ; */ -/*description: Package version 0:ESP32-S2, 1:ESP32-S2FH16, 2:ESP32-S2FH32 */ -#define EFUSE_PKG_VERSION 0x0000000F -#define EFUSE_PKG_VERSION_M ((EFUSE_PKG_VERSION_V)<<(EFUSE_PKG_VERSION_S)) -#define EFUSE_PKG_VERSION_V 0xF -#define EFUSE_PKG_VERSION_S 21 +/* EFUSE_PSRAM_VERSION : RO ;bitpos:[31:28] ;default: 4'h0 ; */ +/*description: PSRAM version */ +#define EFUSE_PSRAM_VERSION 0x0000000F +#define EFUSE_PSRAM_VERSION_M ((EFUSE_PSRAM_VERSION_V)<<(EFUSE_PSRAM_VERSION_S)) +#define EFUSE_PSRAM_VERSION_V 0xF +#define EFUSE_PSRAM_VERSION_S 28 +/* EFUSE_FLASH_VERSION : RO ;bitpos:[24:21] ;default: 4'h0 ; */ +/*description: Flash version */ +#define EFUSE_FLASH_VERSION 0x0000000F +#define EFUSE_FLASH_VERSION_M ((EFUSE_FLASH_VERSION_V)<<(EFUSE_FLASH_VERSION_S)) +#define EFUSE_FLASH_VERSION_V 0xF +#define EFUSE_FLASH_VERSION_S 21 /* EFUSE_WAFER_VERSION : RO ;bitpos:[20:18] ;default: 3'h0 ; */ /*description: WAFER version 0:A */ #define EFUSE_WAFER_VERSION 0x00000007 @@ -943,12 +943,18 @@ extern "C" { #define EFUSE_SPI_PAD_CONF_2_S 0 #define EFUSE_RD_MAC_SPI_SYS_4_REG (DR_REG_EFUSE_BASE + 0x054) -/* EFUSE_SYS_DATA_PART0_1 : RO ;bitpos:[31:0] ;default: 32'h0 ; */ +/* EFUSE_SYS_DATA_PART0_1 : RO ;bitpos:[31:4] ;default: 28'h0 ; */ /*description: Stores the fist 32 bits of the zeroth part of system data.*/ -#define EFUSE_SYS_DATA_PART0_1 0xFFFFFFFF +#define EFUSE_SYS_DATA_PART0_1 0x0FFFFFFF #define EFUSE_SYS_DATA_PART0_1_M ((EFUSE_SYS_DATA_PART0_1_V)<<(EFUSE_SYS_DATA_PART0_1_S)) -#define EFUSE_SYS_DATA_PART0_1_V 0xFFFFFFFF -#define EFUSE_SYS_DATA_PART0_1_S 0 +#define EFUSE_SYS_DATA_PART0_1_V 0x0FFFFFFF +#define EFUSE_SYS_DATA_PART0_1_S 4 +/* EFUSE_PKG_VERSION : RO ;bitpos:[3:0] ;default: 4'h0 ; */ +/*description: Package version */ +#define EFUSE_PKG_VERSION 0x0000000F +#define EFUSE_PKG_VERSION_M ((EFUSE_PKG_VERSION_V)<<(EFUSE_PKG_VERSION_S)) +#define EFUSE_PKG_VERSION_V 0xF +#define EFUSE_PKG_VERSION_S 0 #define EFUSE_RD_MAC_SPI_SYS_5_REG (DR_REG_EFUSE_BASE + 0x058) /* EFUSE_SYS_DATA_PART0_2 : RO ;bitpos:[31:0] ;default: 32'h0 ; */ @@ -1902,7 +1908,7 @@ extern "C" { #define EFUSE_DIS_DOWNLOAD_MODE_ERR_V 0x1 #define EFUSE_DIS_DOWNLOAD_MODE_ERR_S 0 -#define EFUSE_RD_REPEAT_ERR4_REG (DR_REG_EFUSE_BASE + 0x190) +#define EFUSE_RD_REPEAT_ERR4_REG (DR_REG_EFUSE_BASE + 0x18C) /* EFUSE_RPT1_RESERVED0_ERR : RO ;bitpos:[31:24] ;default: 8'h0 ; */ /*description: Reserved.*/ #define EFUSE_RPT1_RESERVED0_ERR 0x000000FF diff --git a/components/soc/esp32s2/include/soc/efuse_struct.h b/components/soc/esp32s2/include/soc/efuse_struct.h index a9679c267c..d2ef645494 100644 --- a/components/soc/esp32s2/include/soc/efuse_struct.h +++ b/components/soc/esp32s2/include/soc/efuse_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct efuse_dev_s { uint32_t pgm_data0; /**/ union { struct { @@ -357,7 +357,6 @@ typedef volatile struct { }; uint32_t val; } rd_repeat_err3; - uint32_t reserved_18c; union { struct { uint32_t rd_chip_version_err:24; @@ -365,6 +364,18 @@ typedef volatile struct { }; uint32_t val; } rd_repeat_err4; + 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; union { struct { uint32_t rd_mac_spi_8m_err_num: 3; @@ -500,17 +511,6 @@ typedef volatile struct { }; uint32_t val; } wr_tim_conf1; - 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 date; /**/ } efuse_dev_t; diff --git a/components/soc/esp32s2/include/soc/gpio_sd_struct.h b/components/soc/esp32s2/include/soc/gpio_sd_struct.h index 6c28df52a8..71131ae881 100644 --- a/components/soc/esp32s2/include/soc/gpio_sd_struct.h +++ b/components/soc/esp32s2/include/soc/gpio_sd_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct gpio_sd_dev_s { union { struct { uint32_t duty: 8; diff --git a/components/soc/esp32s2/include/soc/gpio_struct.h b/components/soc/esp32s2/include/soc/gpio_struct.h index 70e82ee1fe..0dc1efdfda 100644 --- a/components/soc/esp32s2/include/soc/gpio_struct.h +++ b/components/soc/esp32s2/include/soc/gpio_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct gpio_dev_s { uint32_t bt_select; /**/ uint32_t out; /**/ uint32_t out_w1ts; /**/ diff --git a/components/soc/esp32s2/include/soc/i2c_struct.h b/components/soc/esp32s2/include/soc/i2c_struct.h index e54038aaea..150384992b 100644 --- a/components/soc/esp32s2/include/soc/i2c_struct.h +++ b/components/soc/esp32s2/include/soc/i2c_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct i2c_dev_s { union { struct { uint32_t period: 14; diff --git a/components/soc/esp32s2/include/soc/i2s_struct.h b/components/soc/esp32s2/include/soc/i2s_struct.h index 789f2c21c2..99220407e7 100644 --- a/components/soc/esp32s2/include/soc/i2s_struct.h +++ b/components/soc/esp32s2/include/soc/i2s_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct i2s_dev_s { uint32_t reserved_0; uint32_t reserved_4; union { diff --git a/components/soc/esp32s2/include/soc/io_mux_reg.h b/components/soc/esp32s2/include/soc/io_mux_reg.h index fe480c91e5..f5682eedab 100644 --- a/components/soc/esp32s2/include/soc/io_mux_reg.h +++ b/components/soc/esp32s2/include/soc/io_mux_reg.h @@ -145,11 +145,6 @@ #define GPIO_PAD_PULLUP(num) do{PIN_PULLUP_DIS(IOMUX_REG_GPIO##num);PIN_PULLDWN_EN(IOMUX_REG_GPIO##num);}while(0) #define GPIO_PAD_SET_DRV(num, drv) PIN_SET_DRV(IOMUX_REG_GPIO##num, drv) -#define U1RXD_GPIO_NUM 18 -#define U1TXD_GPIO_NUM 17 -#define U0RXD_GPIO_NUM 44 -#define U0TXD_GPIO_NUM 43 - #define SPI_CS1_GPIO_NUM 26 #define SPI_HD_GPIO_NUM 27 #define SPI_WP_GPIO_NUM 28 diff --git a/components/soc/esp32s2/include/soc/ledc_struct.h b/components/soc/esp32s2/include/soc/ledc_struct.h index a6f02a788b..b38edb0d61 100644 --- a/components/soc/esp32s2/include/soc/ledc_struct.h +++ b/components/soc/esp32s2/include/soc/ledc_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct ledc_dev_s { struct { struct { union { diff --git a/components/soc/esp32s2/include/soc/memprot_defs.h b/components/soc/esp32s2/include/soc/memprot_defs.h new file mode 100644 index 0000000000..f4b4ab9423 --- /dev/null +++ b/components/soc/esp32s2/include/soc/memprot_defs.h @@ -0,0 +1,131 @@ +// 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. +#pragma once + +#include "soc/soc.h" +#include "soc/sensitive_reg.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//IRAM0 interrupt status bitmasks +#define IRAM0_INTR_ST_OP_TYPE_BIT BIT(1) //instruction: 0, data: 1 +#define IRAM0_INTR_ST_OP_RW_BIT BIT(0) //read: 0, write: 1 + +#define CONF_REG_ADDRESS_SHIFT 2 + +//IRAM0 range +#define IRAM0_SRAM_BASE_ADDRESS 0x40000000 +#define IRAM0_SRAM_ADDRESS_LOW 0x40020000 +#define IRAM0_SRAM_ADDRESS_HIGH 0x4006FFFF + +//IRAM0 unified managemnt blocks +#define IRAM0_SRAM_TOTAL_UNI_BLOCKS 4 +#define IRAM0_SRAM_UNI_BLOCK_0 0 +#define IRAM0_SRAM_UNI_BLOCK_1 1 +#define IRAM0_SRAM_UNI_BLOCK_2 2 +#define IRAM0_SRAM_UNI_BLOCK_3 3 + +//unified management addr range (blocks 0-3) +#define IRAM0_SRAM_UNI_BLOCK_0_LOW 0x40020000 +#define IRAM0_SRAM_UNI_BLOCK_1_LOW 0x40022000 +#define IRAM0_SRAM_UNI_BLOCK_2_LOW 0x40024000 +#define IRAM0_SRAM_UNI_BLOCK_3_LOW 0x40026000 + +//split management addr range (blocks 4-21) +#define IRAM0_SRAM_SPL_BLOCK_LOW 0x40028000 //block 4 low +#define IRAM0_SRAM_SPL_BLOCK_HIGH 0x4006FFFF //block 21 high + +#define IRAM0_INTR_ST_FAULTADDR_M 0x003FFFFC //bits 21:6 in the reg, as well as in real address +#define IRAM0_SRAM_INTR_ST_FAULTADDR_HI 0x40000000 //high nonsignificant bits 31:22 of the faulting address - constant + +#define IRAM0_SRAM_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_IRAM0_SRAM_4_SPLTADDR) << DPORT_PMS_PRO_IRAM0_SRAM_4_SPLTADDR_S) + +//IRAM0 RTCFAST +#define IRAM0_RTCFAST_ADDRESS_LOW 0x40070000 +#define IRAM0_RTCFAST_ADDRESS_HIGH 0x40071FFF +#define IRAM0_RTCFAST_INTR_ST_FAULTADDR_HI 0x40070000 //RTCFAST faulting address high bits (31:22, constant) + +#define IRAM0_RTCFAST_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_IRAM0_RTCFAST_SPLTADDR) << DPORT_PMS_PRO_IRAM0_RTCFAST_SPLTADDR_S) + +//DRAM0 interrupt status bitmasks +#define DRAM0_INTR_ST_FAULTADDR_M 0x03FFFFC0 //(bits 25:6 in the reg) +#define DRAM0_INTR_ST_FAULTADDR_S 0x4 //(bits 21:2 of real address) +#define DRAM0_INTR_ST_OP_RW_BIT BIT(4) //read: 0, write: 1 +#define DRAM0_INTR_ST_OP_ATOMIC_BIT BIT(5) //non-atomic: 0, atomic: 1 + +#define DRAM0_SRAM_ADDRESS_LOW 0x3FFB0000 +#define DRAM0_SRAM_ADDRESS_HIGH 0x3FFFFFFF + +#define DRAM0_SRAM_TOTAL_UNI_BLOCKS 4 +#define DRAM0_SRAM_UNI_BLOCK_0 0 +#define DRAM0_SRAM_UNI_BLOCK_1 1 +#define DRAM0_SRAM_UNI_BLOCK_2 2 +#define DRAM0_SRAM_UNI_BLOCK_3 3 + +//unified management (SRAM blocks 0-3) +#define DRAM0_SRAM_UNI_BLOCK_0_LOW 0x3FFB0000 +#define DRAM0_SRAM_UNI_BLOCK_1_LOW 0x3FFB2000 +#define DRAM0_SRAM_UNI_BLOCK_2_LOW 0x3FFB4000 +#define DRAM0_SRAM_UNI_BLOCK_3_LOW 0x3FFB6000 + +//split management (SRAM blocks 4-21) +#define DRAM0_SRAM_SPL_BLOCK_HIGH 0x3FFFFFFF //block 21 high +#define DRAM0_SRAM_INTR_ST_FAULTADDR_HI 0x3FF00000 //SRAM high bits 31:22 of the faulting address - constant + +#define DRAM0_SRAM_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_DRAM0_SRAM_4_SPLTADDR) << DPORT_PMS_PRO_DRAM0_SRAM_4_SPLTADDR_S) + +//DRAM0 RTCFAST +#define DRAM0_RTCFAST_ADDRESS_LOW 0x3FF9E000 +#define DRAM0_RTCFAST_ADDRESS_HIGH 0x3FF9FFFF +#define DRAM0_RTCFAST_INTR_ST_FAULTADDR_HI 0x3FF00000 //RTCFAST high bits 31:22 of the faulting address - constant +#define DRAM0_RTCFAST_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_DRAM0_RTCFAST_SPLTADDR) << DPORT_PMS_PRO_DRAM0_RTCFAST_SPLTADDR_S) + +//RTCSLOW +#define RTCSLOW_MEMORY_SIZE 0x00002000 + +//PeriBus1 interrupt status bitmasks +#define PERI1_INTR_ST_OP_TYPE_BIT BIT(4) //0: non-atomic, 1: atomic +#define PERI1_INTR_ST_OP_HIGH_BITS BIT(5) //0: high bits = unchanged, 1: high bits = 0x03F40000 +#define PERI1_INTR_ST_FAULTADDR_M 0x03FFFFC0 //(bits 25:6 in the reg) +#define PERI1_INTR_ST_FAULTADDR_S 0x4 //(bits 21:2 of real address) + +#define PERI1_RTCSLOW_ADDRESS_BASE 0x3F421000 +#define PERI1_RTCSLOW_ADDRESS_LOW PERI1_RTCSLOW_ADDRESS_BASE +#define PERI1_RTCSLOW_ADDRESS_HIGH PERI1_RTCSLOW_ADDRESS_LOW + RTCSLOW_MEMORY_SIZE +#define PERI1_RTCSLOW_INTR_ST_FAULTADDR_HI_0 0x3F400000 + +#define PERI1_RTCSLOW_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_DPORT_RTCSLOW_SPLTADDR) << DPORT_PMS_PRO_DPORT_RTCSLOW_SPLTADDR_S) + +//PeriBus2 interrupt status bitmasks +#define PERI2_INTR_ST_OP_TYPE_BIT BIT(1) //instruction: 0, data: 1 +#define PERI2_INTR_ST_OP_RW_BIT BIT(0) //read: 0, write: 1 +#define PERI2_INTR_ST_FAULTADDR_M 0xFFFFFFFC //(bits 31:2 in the reg) + +#define PERI2_RTCSLOW_0_ADDRESS_BASE 0x50000000 +#define PERI2_RTCSLOW_0_ADDRESS_LOW PERI2_RTCSLOW_0_ADDRESS_BASE +#define PERI2_RTCSLOW_0_ADDRESS_HIGH PERI2_RTCSLOW_0_ADDRESS_LOW + RTCSLOW_MEMORY_SIZE + +#define PERI2_RTCSLOW_0_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_AHB_RTCSLOW_0_SPLTADDR) << DPORT_PMS_PRO_AHB_RTCSLOW_0_SPLTADDR_S) + +#define PERI2_RTCSLOW_1_ADDRESS_BASE 0x60021000 +#define PERI2_RTCSLOW_1_ADDRESS_LOW PERI2_RTCSLOW_1_ADDRESS_BASE +#define PERI2_RTCSLOW_1_ADDRESS_HIGH PERI2_RTCSLOW_1_ADDRESS_LOW + RTCSLOW_MEMORY_SIZE + +#define PERI2_RTCSLOW_1_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_AHB_RTCSLOW_1_SPLTADDR) << DPORT_PMS_PRO_AHB_RTCSLOW_1_SPLTADDR_S) + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32s2/include/soc/pcnt_reg.h b/components/soc/esp32s2/include/soc/pcnt_reg.h index 7195e1b1fb..b6198c86fb 100644 --- a/components/soc/esp32s2/include/soc/pcnt_reg.h +++ b/components/soc/esp32s2/include/soc/pcnt_reg.h @@ -1,860 +1,1236 @@ -// Copyright 2017-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. -#ifndef _SOC_PCNT_REG_H_ -#define _SOC_PCNT_REG_H_ +/** Copyright 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. + */ +#pragma once +#include +#include "soc/soc.h" #ifdef __cplusplus extern "C" { #endif -#include "soc.h" -#define PCNT_U0_CONF0_REG (DR_REG_PCNT_BASE + 0x0000) -/* PCNT_CH1_LCTRL_MODE_U0 : R/W ;bitpos:[31:30] ;default: 2'd0 ; */ -/*description: */ -#define PCNT_CH1_LCTRL_MODE_U0 0x00000003 -#define PCNT_CH1_LCTRL_MODE_U0_M ((PCNT_CH1_LCTRL_MODE_U0_V)<<(PCNT_CH1_LCTRL_MODE_U0_S)) -#define PCNT_CH1_LCTRL_MODE_U0_V 0x3 -#define PCNT_CH1_LCTRL_MODE_U0_S 30 -/* PCNT_CH1_HCTRL_MODE_U0 : R/W ;bitpos:[29:28] ;default: 2'd0 ; */ -/*description: */ -#define PCNT_CH1_HCTRL_MODE_U0 0x00000003 -#define PCNT_CH1_HCTRL_MODE_U0_M ((PCNT_CH1_HCTRL_MODE_U0_V)<<(PCNT_CH1_HCTRL_MODE_U0_S)) -#define PCNT_CH1_HCTRL_MODE_U0_V 0x3 -#define PCNT_CH1_HCTRL_MODE_U0_S 28 -/* PCNT_CH1_POS_MODE_U0 : R/W ;bitpos:[27:26] ;default: 2'd0 ; */ -/*description: */ -#define PCNT_CH1_POS_MODE_U0 0x00000003 -#define PCNT_CH1_POS_MODE_U0_M ((PCNT_CH1_POS_MODE_U0_V)<<(PCNT_CH1_POS_MODE_U0_S)) -#define PCNT_CH1_POS_MODE_U0_V 0x3 -#define PCNT_CH1_POS_MODE_U0_S 26 -/* PCNT_CH1_NEG_MODE_U0 : R/W ;bitpos:[25:24] ;default: 2'd0 ; */ -/*description: */ -#define PCNT_CH1_NEG_MODE_U0 0x00000003 -#define PCNT_CH1_NEG_MODE_U0_M ((PCNT_CH1_NEG_MODE_U0_V)<<(PCNT_CH1_NEG_MODE_U0_S)) -#define PCNT_CH1_NEG_MODE_U0_V 0x3 -#define PCNT_CH1_NEG_MODE_U0_S 24 -/* PCNT_CH0_LCTRL_MODE_U0 : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: */ -#define PCNT_CH0_LCTRL_MODE_U0 0x00000003 -#define PCNT_CH0_LCTRL_MODE_U0_M ((PCNT_CH0_LCTRL_MODE_U0_V)<<(PCNT_CH0_LCTRL_MODE_U0_S)) -#define PCNT_CH0_LCTRL_MODE_U0_V 0x3 -#define PCNT_CH0_LCTRL_MODE_U0_S 22 -/* PCNT_CH0_HCTRL_MODE_U0 : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: */ -#define PCNT_CH0_HCTRL_MODE_U0 0x00000003 -#define PCNT_CH0_HCTRL_MODE_U0_M ((PCNT_CH0_HCTRL_MODE_U0_V)<<(PCNT_CH0_HCTRL_MODE_U0_S)) -#define PCNT_CH0_HCTRL_MODE_U0_V 0x3 -#define PCNT_CH0_HCTRL_MODE_U0_S 20 -/* PCNT_CH0_POS_MODE_U0 : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: */ -#define PCNT_CH0_POS_MODE_U0 0x00000003 -#define PCNT_CH0_POS_MODE_U0_M ((PCNT_CH0_POS_MODE_U0_V)<<(PCNT_CH0_POS_MODE_U0_S)) -#define PCNT_CH0_POS_MODE_U0_V 0x3 -#define PCNT_CH0_POS_MODE_U0_S 18 -/* PCNT_CH0_NEG_MODE_U0 : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: */ -#define PCNT_CH0_NEG_MODE_U0 0x00000003 -#define PCNT_CH0_NEG_MODE_U0_M ((PCNT_CH0_NEG_MODE_U0_V)<<(PCNT_CH0_NEG_MODE_U0_S)) -#define PCNT_CH0_NEG_MODE_U0_V 0x3 -#define PCNT_CH0_NEG_MODE_U0_S 16 -/* PCNT_THR_THRES1_EN_U0 : R/W ;bitpos:[15] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_THR_THRES1_EN_U0 (BIT(15)) -#define PCNT_THR_THRES1_EN_U0_M (BIT(15)) -#define PCNT_THR_THRES1_EN_U0_V 0x1 -#define PCNT_THR_THRES1_EN_U0_S 15 -/* PCNT_THR_THRES0_EN_U0 : R/W ;bitpos:[14] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_THR_THRES0_EN_U0 (BIT(14)) -#define PCNT_THR_THRES0_EN_U0_M (BIT(14)) -#define PCNT_THR_THRES0_EN_U0_V 0x1 -#define PCNT_THR_THRES0_EN_U0_S 14 -/* PCNT_THR_L_LIM_EN_U0 : R/W ;bitpos:[13] ;default: 1'b1 ; */ -/*description: */ -#define PCNT_THR_L_LIM_EN_U0 (BIT(13)) -#define PCNT_THR_L_LIM_EN_U0_M (BIT(13)) -#define PCNT_THR_L_LIM_EN_U0_V 0x1 -#define PCNT_THR_L_LIM_EN_U0_S 13 -/* PCNT_THR_H_LIM_EN_U0 : R/W ;bitpos:[12] ;default: 1'b1 ; */ -/*description: */ -#define PCNT_THR_H_LIM_EN_U0 (BIT(12)) -#define PCNT_THR_H_LIM_EN_U0_M (BIT(12)) -#define PCNT_THR_H_LIM_EN_U0_V 0x1 -#define PCNT_THR_H_LIM_EN_U0_S 12 -/* PCNT_THR_ZERO_EN_U0 : R/W ;bitpos:[11] ;default: 1'b1 ; */ -/*description: */ -#define PCNT_THR_ZERO_EN_U0 (BIT(11)) -#define PCNT_THR_ZERO_EN_U0_M (BIT(11)) -#define PCNT_THR_ZERO_EN_U0_V 0x1 -#define PCNT_THR_ZERO_EN_U0_S 11 -/* PCNT_FILTER_EN_U0 : R/W ;bitpos:[10] ;default: 1'b1 ; */ -/*description: */ -#define PCNT_FILTER_EN_U0 (BIT(10)) -#define PCNT_FILTER_EN_U0_M (BIT(10)) -#define PCNT_FILTER_EN_U0_V 0x1 -#define PCNT_FILTER_EN_U0_S 10 -/* PCNT_FILTER_THRES_U0 : R/W ;bitpos:[9:0] ;default: 10'h10 ; */ -/*description: */ -#define PCNT_FILTER_THRES_U0 0x000003FF -#define PCNT_FILTER_THRES_U0_M ((PCNT_FILTER_THRES_U0_V)<<(PCNT_FILTER_THRES_U0_S)) -#define PCNT_FILTER_THRES_U0_V 0x3FF + +/** PCNT_U0_CONF0_REG register + * Configuration register 0 for unit 0 + */ +#define PCNT_U0_CONF0_REG (DR_REG_PCNT_BASE + 0x0) +/** PCNT_FILTER_THRES_U0 : R/W; bitpos: [9:0]; default: 16; + * This sets the maximum threshold, in APB_CLK cycles, for the filter. + * + * Any pulses with width less than this will be ignored when the filter is enabled. + */ +#define PCNT_FILTER_THRES_U0 0x000003FFU +#define PCNT_FILTER_THRES_U0_M (PCNT_FILTER_THRES_U0_V << PCNT_FILTER_THRES_U0_S) +#define PCNT_FILTER_THRES_U0_V 0x000003FFU #define PCNT_FILTER_THRES_U0_S 0 +/** PCNT_FILTER_EN_U0 : R/W; bitpos: [10]; default: 1; + * This is the enable bit for unit 0's input filter. + */ +#define PCNT_FILTER_EN_U0 (BIT(10)) +#define PCNT_FILTER_EN_U0_M (PCNT_FILTER_EN_U0_V << PCNT_FILTER_EN_U0_S) +#define PCNT_FILTER_EN_U0_V 0x00000001U +#define PCNT_FILTER_EN_U0_S 10 +/** PCNT_THR_ZERO_EN_U0 : R/W; bitpos: [11]; default: 1; + * This is the enable bit for unit 0's zero comparator. + */ +#define PCNT_THR_ZERO_EN_U0 (BIT(11)) +#define PCNT_THR_ZERO_EN_U0_M (PCNT_THR_ZERO_EN_U0_V << PCNT_THR_ZERO_EN_U0_S) +#define PCNT_THR_ZERO_EN_U0_V 0x00000001U +#define PCNT_THR_ZERO_EN_U0_S 11 +/** PCNT_THR_H_LIM_EN_U0 : R/W; bitpos: [12]; default: 1; + * This is the enable bit for unit 0's thr_h_lim comparator. + */ +#define PCNT_THR_H_LIM_EN_U0 (BIT(12)) +#define PCNT_THR_H_LIM_EN_U0_M (PCNT_THR_H_LIM_EN_U0_V << PCNT_THR_H_LIM_EN_U0_S) +#define PCNT_THR_H_LIM_EN_U0_V 0x00000001U +#define PCNT_THR_H_LIM_EN_U0_S 12 +/** PCNT_THR_L_LIM_EN_U0 : R/W; bitpos: [13]; default: 1; + * This is the enable bit for unit 0's thr_l_lim comparator. + */ +#define PCNT_THR_L_LIM_EN_U0 (BIT(13)) +#define PCNT_THR_L_LIM_EN_U0_M (PCNT_THR_L_LIM_EN_U0_V << PCNT_THR_L_LIM_EN_U0_S) +#define PCNT_THR_L_LIM_EN_U0_V 0x00000001U +#define PCNT_THR_L_LIM_EN_U0_S 13 +/** PCNT_THR_THRES0_EN_U0 : R/W; bitpos: [14]; default: 0; + * This is the enable bit for unit 0's thres0 comparator. + */ +#define PCNT_THR_THRES0_EN_U0 (BIT(14)) +#define PCNT_THR_THRES0_EN_U0_M (PCNT_THR_THRES0_EN_U0_V << PCNT_THR_THRES0_EN_U0_S) +#define PCNT_THR_THRES0_EN_U0_V 0x00000001U +#define PCNT_THR_THRES0_EN_U0_S 14 +/** PCNT_THR_THRES1_EN_U0 : R/W; bitpos: [15]; default: 0; + * This is the enable bit for unit 0's thres1 comparator. + */ +#define PCNT_THR_THRES1_EN_U0 (BIT(15)) +#define PCNT_THR_THRES1_EN_U0_M (PCNT_THR_THRES1_EN_U0_V << PCNT_THR_THRES1_EN_U0_S) +#define PCNT_THR_THRES1_EN_U0_V 0x00000001U +#define PCNT_THR_THRES1_EN_U0_S 15 +/** PCNT_CH0_NEG_MODE_U0 : R/W; bitpos: [17:16]; default: 0; + * This register sets the behavior when the signal input of channel 0 detects a + * negative edge. + * + * 1: Increase the counter;2: Decrease the counter;0, 3: No effect on counter + */ +#define PCNT_CH0_NEG_MODE_U0 0x00000003U +#define PCNT_CH0_NEG_MODE_U0_M (PCNT_CH0_NEG_MODE_U0_V << PCNT_CH0_NEG_MODE_U0_S) +#define PCNT_CH0_NEG_MODE_U0_V 0x00000003U +#define PCNT_CH0_NEG_MODE_U0_S 16 +/** PCNT_CH0_POS_MODE_U0 : R/W; bitpos: [19:18]; default: 0; + * This register sets the behavior when the signal input of channel 0 detects a + * positive edge. + * + * 1: Increase the counter;2: Decrease the counter;0, 3: No effect on counter + */ +#define PCNT_CH0_POS_MODE_U0 0x00000003U +#define PCNT_CH0_POS_MODE_U0_M (PCNT_CH0_POS_MODE_U0_V << PCNT_CH0_POS_MODE_U0_S) +#define PCNT_CH0_POS_MODE_U0_V 0x00000003U +#define PCNT_CH0_POS_MODE_U0_S 18 +/** PCNT_CH0_HCTRL_MODE_U0 : R/W; bitpos: [21:20]; default: 0; + * This register configures how the CH0_POS_MODE/CH0_NEG_MODE settings will be + * modified when the control signal is high. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ +#define PCNT_CH0_HCTRL_MODE_U0 0x00000003U +#define PCNT_CH0_HCTRL_MODE_U0_M (PCNT_CH0_HCTRL_MODE_U0_V << PCNT_CH0_HCTRL_MODE_U0_S) +#define PCNT_CH0_HCTRL_MODE_U0_V 0x00000003U +#define PCNT_CH0_HCTRL_MODE_U0_S 20 +/** PCNT_CH0_LCTRL_MODE_U0 : R/W; bitpos: [23:22]; default: 0; + * This register configures how the CH0_POS_MODE/CH0_NEG_MODE settings will be + * modified when the control signal is low. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ +#define PCNT_CH0_LCTRL_MODE_U0 0x00000003U +#define PCNT_CH0_LCTRL_MODE_U0_M (PCNT_CH0_LCTRL_MODE_U0_V << PCNT_CH0_LCTRL_MODE_U0_S) +#define PCNT_CH0_LCTRL_MODE_U0_V 0x00000003U +#define PCNT_CH0_LCTRL_MODE_U0_S 22 +/** PCNT_CH1_NEG_MODE_U0 : R/W; bitpos: [25:24]; default: 0; + * This register sets the behavior when the signal input of channel 1 detects a + * negative edge. + * + * 1: Increment the counter;2: Decrement the counter;0, 3: No effect on counter + */ +#define PCNT_CH1_NEG_MODE_U0 0x00000003U +#define PCNT_CH1_NEG_MODE_U0_M (PCNT_CH1_NEG_MODE_U0_V << PCNT_CH1_NEG_MODE_U0_S) +#define PCNT_CH1_NEG_MODE_U0_V 0x00000003U +#define PCNT_CH1_NEG_MODE_U0_S 24 +/** PCNT_CH1_POS_MODE_U0 : R/W; bitpos: [27:26]; default: 0; + * This register sets the behavior when the signal input of channel 1 detects a + * positive edge. + * + * 1: Increment the counter;2: Decrement the counter;0, 3: No effect on counter + */ +#define PCNT_CH1_POS_MODE_U0 0x00000003U +#define PCNT_CH1_POS_MODE_U0_M (PCNT_CH1_POS_MODE_U0_V << PCNT_CH1_POS_MODE_U0_S) +#define PCNT_CH1_POS_MODE_U0_V 0x00000003U +#define PCNT_CH1_POS_MODE_U0_S 26 +/** PCNT_CH1_HCTRL_MODE_U0 : R/W; bitpos: [29:28]; default: 0; + * This register configures how the CH0_POS_MODE/CH0_NEG_MODE settings will be + * modified when the control signal is high. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ +#define PCNT_CH1_HCTRL_MODE_U0 0x00000003U +#define PCNT_CH1_HCTRL_MODE_U0_M (PCNT_CH1_HCTRL_MODE_U0_V << PCNT_CH1_HCTRL_MODE_U0_S) +#define PCNT_CH1_HCTRL_MODE_U0_V 0x00000003U +#define PCNT_CH1_HCTRL_MODE_U0_S 28 +/** PCNT_CH1_LCTRL_MODE_U0 : R/W; bitpos: [31:30]; default: 0; + * This register configures how the CH0_POS_MODE/CH0_NEG_MODE settings will be + * modified when the control signal is low. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ +#define PCNT_CH1_LCTRL_MODE_U0 0x00000003U +#define PCNT_CH1_LCTRL_MODE_U0_M (PCNT_CH1_LCTRL_MODE_U0_V << PCNT_CH1_LCTRL_MODE_U0_S) +#define PCNT_CH1_LCTRL_MODE_U0_V 0x00000003U +#define PCNT_CH1_LCTRL_MODE_U0_S 30 -#define PCNT_U0_CONF1_REG (DR_REG_PCNT_BASE + 0x0004) -/* PCNT_CNT_THRES1_U0 : R/W ;bitpos:[31:16] ;default: 10'h0 ; */ -/*description: */ -#define PCNT_CNT_THRES1_U0 0x0000FFFF -#define PCNT_CNT_THRES1_U0_M ((PCNT_CNT_THRES1_U0_V)<<(PCNT_CNT_THRES1_U0_S)) -#define PCNT_CNT_THRES1_U0_V 0xFFFF -#define PCNT_CNT_THRES1_U0_S 16 -/* PCNT_CNT_THRES0_U0 : R/W ;bitpos:[15:0] ;default: 10'h0 ; */ -/*description: */ -#define PCNT_CNT_THRES0_U0 0x0000FFFF -#define PCNT_CNT_THRES0_U0_M ((PCNT_CNT_THRES0_U0_V)<<(PCNT_CNT_THRES0_U0_S)) -#define PCNT_CNT_THRES0_U0_V 0xFFFF +/** PCNT_U0_CONF1_REG register + * Configuration register 1 for unit 0 + */ +#define PCNT_U0_CONF1_REG (DR_REG_PCNT_BASE + 0x4) +/** PCNT_CNT_THRES0_U0 : R/W; bitpos: [15:0]; default: 0; + * This register is used to configure the thres0 value for unit 0. + */ +#define PCNT_CNT_THRES0_U0 0x0000FFFFU +#define PCNT_CNT_THRES0_U0_M (PCNT_CNT_THRES0_U0_V << PCNT_CNT_THRES0_U0_S) +#define PCNT_CNT_THRES0_U0_V 0x0000FFFFU #define PCNT_CNT_THRES0_U0_S 0 +/** PCNT_CNT_THRES1_U0 : R/W; bitpos: [31:16]; default: 0; + * This register is used to configure the thres1 value for unit 0. + */ +#define PCNT_CNT_THRES1_U0 0x0000FFFFU +#define PCNT_CNT_THRES1_U0_M (PCNT_CNT_THRES1_U0_V << PCNT_CNT_THRES1_U0_S) +#define PCNT_CNT_THRES1_U0_V 0x0000FFFFU +#define PCNT_CNT_THRES1_U0_S 16 -#define PCNT_U0_CONF2_REG (DR_REG_PCNT_BASE + 0x0008) -/* PCNT_CNT_L_LIM_U0 : R/W ;bitpos:[31:16] ;default: 10'h0 ; */ -/*description: */ -#define PCNT_CNT_L_LIM_U0 0x0000FFFF -#define PCNT_CNT_L_LIM_U0_M ((PCNT_CNT_L_LIM_U0_V)<<(PCNT_CNT_L_LIM_U0_S)) -#define PCNT_CNT_L_LIM_U0_V 0xFFFF -#define PCNT_CNT_L_LIM_U0_S 16 -/* PCNT_CNT_H_LIM_U0 : R/W ;bitpos:[15:0] ;default: 10'h0 ; */ -/*description: */ -#define PCNT_CNT_H_LIM_U0 0x0000FFFF -#define PCNT_CNT_H_LIM_U0_M ((PCNT_CNT_H_LIM_U0_V)<<(PCNT_CNT_H_LIM_U0_S)) -#define PCNT_CNT_H_LIM_U0_V 0xFFFF +/** PCNT_U0_CONF2_REG register + * Configuration register 2 for unit 0 + */ +#define PCNT_U0_CONF2_REG (DR_REG_PCNT_BASE + 0x8) +/** PCNT_CNT_H_LIM_U0 : R/W; bitpos: [15:0]; default: 0; + * This register is used to configure the thr_h_lim value for unit 0. + */ +#define PCNT_CNT_H_LIM_U0 0x0000FFFFU +#define PCNT_CNT_H_LIM_U0_M (PCNT_CNT_H_LIM_U0_V << PCNT_CNT_H_LIM_U0_S) +#define PCNT_CNT_H_LIM_U0_V 0x0000FFFFU #define PCNT_CNT_H_LIM_U0_S 0 +/** PCNT_CNT_L_LIM_U0 : R/W; bitpos: [31:16]; default: 0; + * This register is used to configure the thr_l_lim value for unit 0. + */ +#define PCNT_CNT_L_LIM_U0 0x0000FFFFU +#define PCNT_CNT_L_LIM_U0_M (PCNT_CNT_L_LIM_U0_V << PCNT_CNT_L_LIM_U0_S) +#define PCNT_CNT_L_LIM_U0_V 0x0000FFFFU +#define PCNT_CNT_L_LIM_U0_S 16 -#define PCNT_U1_CONF0_REG (DR_REG_PCNT_BASE + 0x000c) -/* PCNT_CH1_LCTRL_MODE_U1 : R/W ;bitpos:[31:30] ;default: 2'd0 ; */ -/*description: */ -#define PCNT_CH1_LCTRL_MODE_U1 0x00000003 -#define PCNT_CH1_LCTRL_MODE_U1_M ((PCNT_CH1_LCTRL_MODE_U1_V)<<(PCNT_CH1_LCTRL_MODE_U1_S)) -#define PCNT_CH1_LCTRL_MODE_U1_V 0x3 -#define PCNT_CH1_LCTRL_MODE_U1_S 30 -/* PCNT_CH1_HCTRL_MODE_U1 : R/W ;bitpos:[29:28] ;default: 2'd0 ; */ -/*description: */ -#define PCNT_CH1_HCTRL_MODE_U1 0x00000003 -#define PCNT_CH1_HCTRL_MODE_U1_M ((PCNT_CH1_HCTRL_MODE_U1_V)<<(PCNT_CH1_HCTRL_MODE_U1_S)) -#define PCNT_CH1_HCTRL_MODE_U1_V 0x3 -#define PCNT_CH1_HCTRL_MODE_U1_S 28 -/* PCNT_CH1_POS_MODE_U1 : R/W ;bitpos:[27:26] ;default: 2'd0 ; */ -/*description: */ -#define PCNT_CH1_POS_MODE_U1 0x00000003 -#define PCNT_CH1_POS_MODE_U1_M ((PCNT_CH1_POS_MODE_U1_V)<<(PCNT_CH1_POS_MODE_U1_S)) -#define PCNT_CH1_POS_MODE_U1_V 0x3 -#define PCNT_CH1_POS_MODE_U1_S 26 -/* PCNT_CH1_NEG_MODE_U1 : R/W ;bitpos:[25:24] ;default: 2'd0 ; */ -/*description: */ -#define PCNT_CH1_NEG_MODE_U1 0x00000003 -#define PCNT_CH1_NEG_MODE_U1_M ((PCNT_CH1_NEG_MODE_U1_V)<<(PCNT_CH1_NEG_MODE_U1_S)) -#define PCNT_CH1_NEG_MODE_U1_V 0x3 -#define PCNT_CH1_NEG_MODE_U1_S 24 -/* PCNT_CH0_LCTRL_MODE_U1 : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: */ -#define PCNT_CH0_LCTRL_MODE_U1 0x00000003 -#define PCNT_CH0_LCTRL_MODE_U1_M ((PCNT_CH0_LCTRL_MODE_U1_V)<<(PCNT_CH0_LCTRL_MODE_U1_S)) -#define PCNT_CH0_LCTRL_MODE_U1_V 0x3 -#define PCNT_CH0_LCTRL_MODE_U1_S 22 -/* PCNT_CH0_HCTRL_MODE_U1 : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: */ -#define PCNT_CH0_HCTRL_MODE_U1 0x00000003 -#define PCNT_CH0_HCTRL_MODE_U1_M ((PCNT_CH0_HCTRL_MODE_U1_V)<<(PCNT_CH0_HCTRL_MODE_U1_S)) -#define PCNT_CH0_HCTRL_MODE_U1_V 0x3 -#define PCNT_CH0_HCTRL_MODE_U1_S 20 -/* PCNT_CH0_POS_MODE_U1 : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: */ -#define PCNT_CH0_POS_MODE_U1 0x00000003 -#define PCNT_CH0_POS_MODE_U1_M ((PCNT_CH0_POS_MODE_U1_V)<<(PCNT_CH0_POS_MODE_U1_S)) -#define PCNT_CH0_POS_MODE_U1_V 0x3 -#define PCNT_CH0_POS_MODE_U1_S 18 -/* PCNT_CH0_NEG_MODE_U1 : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: */ -#define PCNT_CH0_NEG_MODE_U1 0x00000003 -#define PCNT_CH0_NEG_MODE_U1_M ((PCNT_CH0_NEG_MODE_U1_V)<<(PCNT_CH0_NEG_MODE_U1_S)) -#define PCNT_CH0_NEG_MODE_U1_V 0x3 -#define PCNT_CH0_NEG_MODE_U1_S 16 -/* PCNT_THR_THRES1_EN_U1 : R/W ;bitpos:[15] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_THR_THRES1_EN_U1 (BIT(15)) -#define PCNT_THR_THRES1_EN_U1_M (BIT(15)) -#define PCNT_THR_THRES1_EN_U1_V 0x1 -#define PCNT_THR_THRES1_EN_U1_S 15 -/* PCNT_THR_THRES0_EN_U1 : R/W ;bitpos:[14] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_THR_THRES0_EN_U1 (BIT(14)) -#define PCNT_THR_THRES0_EN_U1_M (BIT(14)) -#define PCNT_THR_THRES0_EN_U1_V 0x1 -#define PCNT_THR_THRES0_EN_U1_S 14 -/* PCNT_THR_L_LIM_EN_U1 : R/W ;bitpos:[13] ;default: 1'b1 ; */ -/*description: */ -#define PCNT_THR_L_LIM_EN_U1 (BIT(13)) -#define PCNT_THR_L_LIM_EN_U1_M (BIT(13)) -#define PCNT_THR_L_LIM_EN_U1_V 0x1 -#define PCNT_THR_L_LIM_EN_U1_S 13 -/* PCNT_THR_H_LIM_EN_U1 : R/W ;bitpos:[12] ;default: 1'b1 ; */ -/*description: */ -#define PCNT_THR_H_LIM_EN_U1 (BIT(12)) -#define PCNT_THR_H_LIM_EN_U1_M (BIT(12)) -#define PCNT_THR_H_LIM_EN_U1_V 0x1 -#define PCNT_THR_H_LIM_EN_U1_S 12 -/* PCNT_THR_ZERO_EN_U1 : R/W ;bitpos:[11] ;default: 1'b1 ; */ -/*description: */ -#define PCNT_THR_ZERO_EN_U1 (BIT(11)) -#define PCNT_THR_ZERO_EN_U1_M (BIT(11)) -#define PCNT_THR_ZERO_EN_U1_V 0x1 -#define PCNT_THR_ZERO_EN_U1_S 11 -/* PCNT_FILTER_EN_U1 : R/W ;bitpos:[10] ;default: 1'b1 ; */ -/*description: */ -#define PCNT_FILTER_EN_U1 (BIT(10)) -#define PCNT_FILTER_EN_U1_M (BIT(10)) -#define PCNT_FILTER_EN_U1_V 0x1 -#define PCNT_FILTER_EN_U1_S 10 -/* PCNT_FILTER_THRES_U1 : R/W ;bitpos:[9:0] ;default: 10'h10 ; */ -/*description: */ -#define PCNT_FILTER_THRES_U1 0x000003FF -#define PCNT_FILTER_THRES_U1_M ((PCNT_FILTER_THRES_U1_V)<<(PCNT_FILTER_THRES_U1_S)) -#define PCNT_FILTER_THRES_U1_V 0x3FF +/** PCNT_U1_CONF0_REG register + * Configuration register 0 for unit 1 + */ +#define PCNT_U1_CONF0_REG (DR_REG_PCNT_BASE + 0xc) +/** PCNT_FILTER_THRES_U1 : R/W; bitpos: [9:0]; default: 16; + * This sets the maximum threshold, in APB_CLK cycles, for the filter. + * + * Any pulses with width less than this will be ignored when the filter is enabled. + */ +#define PCNT_FILTER_THRES_U1 0x000003FFU +#define PCNT_FILTER_THRES_U1_M (PCNT_FILTER_THRES_U1_V << PCNT_FILTER_THRES_U1_S) +#define PCNT_FILTER_THRES_U1_V 0x000003FFU #define PCNT_FILTER_THRES_U1_S 0 +/** PCNT_FILTER_EN_U1 : R/W; bitpos: [10]; default: 1; + * This is the enable bit for unit 1's input filter. + */ +#define PCNT_FILTER_EN_U1 (BIT(10)) +#define PCNT_FILTER_EN_U1_M (PCNT_FILTER_EN_U1_V << PCNT_FILTER_EN_U1_S) +#define PCNT_FILTER_EN_U1_V 0x00000001U +#define PCNT_FILTER_EN_U1_S 10 +/** PCNT_THR_ZERO_EN_U1 : R/W; bitpos: [11]; default: 1; + * This is the enable bit for unit 1's zero comparator. + */ +#define PCNT_THR_ZERO_EN_U1 (BIT(11)) +#define PCNT_THR_ZERO_EN_U1_M (PCNT_THR_ZERO_EN_U1_V << PCNT_THR_ZERO_EN_U1_S) +#define PCNT_THR_ZERO_EN_U1_V 0x00000001U +#define PCNT_THR_ZERO_EN_U1_S 11 +/** PCNT_THR_H_LIM_EN_U1 : R/W; bitpos: [12]; default: 1; + * This is the enable bit for unit 1's thr_h_lim comparator. + */ +#define PCNT_THR_H_LIM_EN_U1 (BIT(12)) +#define PCNT_THR_H_LIM_EN_U1_M (PCNT_THR_H_LIM_EN_U1_V << PCNT_THR_H_LIM_EN_U1_S) +#define PCNT_THR_H_LIM_EN_U1_V 0x00000001U +#define PCNT_THR_H_LIM_EN_U1_S 12 +/** PCNT_THR_L_LIM_EN_U1 : R/W; bitpos: [13]; default: 1; + * This is the enable bit for unit 1's thr_l_lim comparator. + */ +#define PCNT_THR_L_LIM_EN_U1 (BIT(13)) +#define PCNT_THR_L_LIM_EN_U1_M (PCNT_THR_L_LIM_EN_U1_V << PCNT_THR_L_LIM_EN_U1_S) +#define PCNT_THR_L_LIM_EN_U1_V 0x00000001U +#define PCNT_THR_L_LIM_EN_U1_S 13 +/** PCNT_THR_THRES0_EN_U1 : R/W; bitpos: [14]; default: 0; + * This is the enable bit for unit 1's thres0 comparator. + */ +#define PCNT_THR_THRES0_EN_U1 (BIT(14)) +#define PCNT_THR_THRES0_EN_U1_M (PCNT_THR_THRES0_EN_U1_V << PCNT_THR_THRES0_EN_U1_S) +#define PCNT_THR_THRES0_EN_U1_V 0x00000001U +#define PCNT_THR_THRES0_EN_U1_S 14 +/** PCNT_THR_THRES1_EN_U1 : R/W; bitpos: [15]; default: 0; + * This is the enable bit for unit 1's thres1 comparator. + */ +#define PCNT_THR_THRES1_EN_U1 (BIT(15)) +#define PCNT_THR_THRES1_EN_U1_M (PCNT_THR_THRES1_EN_U1_V << PCNT_THR_THRES1_EN_U1_S) +#define PCNT_THR_THRES1_EN_U1_V 0x00000001U +#define PCNT_THR_THRES1_EN_U1_S 15 +/** PCNT_CH0_NEG_MODE_U1 : R/W; bitpos: [17:16]; default: 0; + * This register sets the behavior when the signal input of channel 0 detects a + * negative edge. + * + * 1: Increase the counter;2: Decrease the counter;0, 3: No effect on counter + */ +#define PCNT_CH0_NEG_MODE_U1 0x00000003U +#define PCNT_CH0_NEG_MODE_U1_M (PCNT_CH0_NEG_MODE_U1_V << PCNT_CH0_NEG_MODE_U1_S) +#define PCNT_CH0_NEG_MODE_U1_V 0x00000003U +#define PCNT_CH0_NEG_MODE_U1_S 16 +/** PCNT_CH0_POS_MODE_U1 : R/W; bitpos: [19:18]; default: 0; + * This register sets the behavior when the signal input of channel 0 detects a + * positive edge. + * + * 1: Increase the counter;2: Decrease the counter;0, 3: No effect on counter + */ +#define PCNT_CH0_POS_MODE_U1 0x00000003U +#define PCNT_CH0_POS_MODE_U1_M (PCNT_CH0_POS_MODE_U1_V << PCNT_CH0_POS_MODE_U1_S) +#define PCNT_CH0_POS_MODE_U1_V 0x00000003U +#define PCNT_CH0_POS_MODE_U1_S 18 +/** PCNT_CH0_HCTRL_MODE_U1 : R/W; bitpos: [21:20]; default: 0; + * This register configures how the CH1_POS_MODE/CH1_NEG_MODE settings will be + * modified when the control signal is high. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ +#define PCNT_CH0_HCTRL_MODE_U1 0x00000003U +#define PCNT_CH0_HCTRL_MODE_U1_M (PCNT_CH0_HCTRL_MODE_U1_V << PCNT_CH0_HCTRL_MODE_U1_S) +#define PCNT_CH0_HCTRL_MODE_U1_V 0x00000003U +#define PCNT_CH0_HCTRL_MODE_U1_S 20 +/** PCNT_CH0_LCTRL_MODE_U1 : R/W; bitpos: [23:22]; default: 0; + * This register configures how the CH1_POS_MODE/CH1_NEG_MODE settings will be + * modified when the control signal is low. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ +#define PCNT_CH0_LCTRL_MODE_U1 0x00000003U +#define PCNT_CH0_LCTRL_MODE_U1_M (PCNT_CH0_LCTRL_MODE_U1_V << PCNT_CH0_LCTRL_MODE_U1_S) +#define PCNT_CH0_LCTRL_MODE_U1_V 0x00000003U +#define PCNT_CH0_LCTRL_MODE_U1_S 22 +/** PCNT_CH1_NEG_MODE_U1 : R/W; bitpos: [25:24]; default: 0; + * This register sets the behavior when the signal input of channel 1 detects a + * negative edge. + * + * 1: Increment the counter;2: Decrement the counter;0, 3: No effect on counter + */ +#define PCNT_CH1_NEG_MODE_U1 0x00000003U +#define PCNT_CH1_NEG_MODE_U1_M (PCNT_CH1_NEG_MODE_U1_V << PCNT_CH1_NEG_MODE_U1_S) +#define PCNT_CH1_NEG_MODE_U1_V 0x00000003U +#define PCNT_CH1_NEG_MODE_U1_S 24 +/** PCNT_CH1_POS_MODE_U1 : R/W; bitpos: [27:26]; default: 0; + * This register sets the behavior when the signal input of channel 1 detects a + * positive edge. + * + * 1: Increment the counter;2: Decrement the counter;0, 3: No effect on counter + */ +#define PCNT_CH1_POS_MODE_U1 0x00000003U +#define PCNT_CH1_POS_MODE_U1_M (PCNT_CH1_POS_MODE_U1_V << PCNT_CH1_POS_MODE_U1_S) +#define PCNT_CH1_POS_MODE_U1_V 0x00000003U +#define PCNT_CH1_POS_MODE_U1_S 26 +/** PCNT_CH1_HCTRL_MODE_U1 : R/W; bitpos: [29:28]; default: 0; + * This register configures how the CH1_POS_MODE/CH1_NEG_MODE settings will be + * modified when the control signal is high. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ +#define PCNT_CH1_HCTRL_MODE_U1 0x00000003U +#define PCNT_CH1_HCTRL_MODE_U1_M (PCNT_CH1_HCTRL_MODE_U1_V << PCNT_CH1_HCTRL_MODE_U1_S) +#define PCNT_CH1_HCTRL_MODE_U1_V 0x00000003U +#define PCNT_CH1_HCTRL_MODE_U1_S 28 +/** PCNT_CH1_LCTRL_MODE_U1 : R/W; bitpos: [31:30]; default: 0; + * This register configures how the CH1_POS_MODE/CH1_NEG_MODE settings will be + * modified when the control signal is low. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ +#define PCNT_CH1_LCTRL_MODE_U1 0x00000003U +#define PCNT_CH1_LCTRL_MODE_U1_M (PCNT_CH1_LCTRL_MODE_U1_V << PCNT_CH1_LCTRL_MODE_U1_S) +#define PCNT_CH1_LCTRL_MODE_U1_V 0x00000003U +#define PCNT_CH1_LCTRL_MODE_U1_S 30 -#define PCNT_U1_CONF1_REG (DR_REG_PCNT_BASE + 0x0010) -/* PCNT_CNT_THRES1_U1 : R/W ;bitpos:[31:16] ;default: 10'h0 ; */ -/*description: */ -#define PCNT_CNT_THRES1_U1 0x0000FFFF -#define PCNT_CNT_THRES1_U1_M ((PCNT_CNT_THRES1_U1_V)<<(PCNT_CNT_THRES1_U1_S)) -#define PCNT_CNT_THRES1_U1_V 0xFFFF -#define PCNT_CNT_THRES1_U1_S 16 -/* PCNT_CNT_THRES0_U1 : R/W ;bitpos:[15:0] ;default: 10'h0 ; */ -/*description: */ -#define PCNT_CNT_THRES0_U1 0x0000FFFF -#define PCNT_CNT_THRES0_U1_M ((PCNT_CNT_THRES0_U1_V)<<(PCNT_CNT_THRES0_U1_S)) -#define PCNT_CNT_THRES0_U1_V 0xFFFF +/** PCNT_U1_CONF1_REG register + * Configuration register 1 for unit 1 + */ +#define PCNT_U1_CONF1_REG (DR_REG_PCNT_BASE + 0x10) +/** PCNT_CNT_THRES0_U1 : R/W; bitpos: [15:0]; default: 0; + * This register is used to configure the thres0 value for unit 1. + */ +#define PCNT_CNT_THRES0_U1 0x0000FFFFU +#define PCNT_CNT_THRES0_U1_M (PCNT_CNT_THRES0_U1_V << PCNT_CNT_THRES0_U1_S) +#define PCNT_CNT_THRES0_U1_V 0x0000FFFFU #define PCNT_CNT_THRES0_U1_S 0 +/** PCNT_CNT_THRES1_U1 : R/W; bitpos: [31:16]; default: 0; + * This register is used to configure the thres1 value for unit 1. + */ +#define PCNT_CNT_THRES1_U1 0x0000FFFFU +#define PCNT_CNT_THRES1_U1_M (PCNT_CNT_THRES1_U1_V << PCNT_CNT_THRES1_U1_S) +#define PCNT_CNT_THRES1_U1_V 0x0000FFFFU +#define PCNT_CNT_THRES1_U1_S 16 -#define PCNT_U1_CONF2_REG (DR_REG_PCNT_BASE + 0x0014) -/* PCNT_CNT_L_LIM_U1 : R/W ;bitpos:[31:16] ;default: 10'h0 ; */ -/*description: */ -#define PCNT_CNT_L_LIM_U1 0x0000FFFF -#define PCNT_CNT_L_LIM_U1_M ((PCNT_CNT_L_LIM_U1_V)<<(PCNT_CNT_L_LIM_U1_S)) -#define PCNT_CNT_L_LIM_U1_V 0xFFFF -#define PCNT_CNT_L_LIM_U1_S 16 -/* PCNT_CNT_H_LIM_U1 : R/W ;bitpos:[15:0] ;default: 10'h0 ; */ -/*description: */ -#define PCNT_CNT_H_LIM_U1 0x0000FFFF -#define PCNT_CNT_H_LIM_U1_M ((PCNT_CNT_H_LIM_U1_V)<<(PCNT_CNT_H_LIM_U1_S)) -#define PCNT_CNT_H_LIM_U1_V 0xFFFF +/** PCNT_U1_CONF2_REG register + * Configuration register 2 for unit 1 + */ +#define PCNT_U1_CONF2_REG (DR_REG_PCNT_BASE + 0x14) +/** PCNT_CNT_H_LIM_U1 : R/W; bitpos: [15:0]; default: 0; + * This register is used to configure the thr_h_lim value for unit 1. + */ +#define PCNT_CNT_H_LIM_U1 0x0000FFFFU +#define PCNT_CNT_H_LIM_U1_M (PCNT_CNT_H_LIM_U1_V << PCNT_CNT_H_LIM_U1_S) +#define PCNT_CNT_H_LIM_U1_V 0x0000FFFFU #define PCNT_CNT_H_LIM_U1_S 0 +/** PCNT_CNT_L_LIM_U1 : R/W; bitpos: [31:16]; default: 0; + * This register is used to configure the thr_l_lim value for unit 1. + */ +#define PCNT_CNT_L_LIM_U1 0x0000FFFFU +#define PCNT_CNT_L_LIM_U1_M (PCNT_CNT_L_LIM_U1_V << PCNT_CNT_L_LIM_U1_S) +#define PCNT_CNT_L_LIM_U1_V 0x0000FFFFU +#define PCNT_CNT_L_LIM_U1_S 16 -#define PCNT_U2_CONF0_REG (DR_REG_PCNT_BASE + 0x0018) -/* PCNT_CH1_LCTRL_MODE_U2 : R/W ;bitpos:[31:30] ;default: 2'd0 ; */ -/*description: */ -#define PCNT_CH1_LCTRL_MODE_U2 0x00000003 -#define PCNT_CH1_LCTRL_MODE_U2_M ((PCNT_CH1_LCTRL_MODE_U2_V)<<(PCNT_CH1_LCTRL_MODE_U2_S)) -#define PCNT_CH1_LCTRL_MODE_U2_V 0x3 -#define PCNT_CH1_LCTRL_MODE_U2_S 30 -/* PCNT_CH1_HCTRL_MODE_U2 : R/W ;bitpos:[29:28] ;default: 2'd0 ; */ -/*description: */ -#define PCNT_CH1_HCTRL_MODE_U2 0x00000003 -#define PCNT_CH1_HCTRL_MODE_U2_M ((PCNT_CH1_HCTRL_MODE_U2_V)<<(PCNT_CH1_HCTRL_MODE_U2_S)) -#define PCNT_CH1_HCTRL_MODE_U2_V 0x3 -#define PCNT_CH1_HCTRL_MODE_U2_S 28 -/* PCNT_CH1_POS_MODE_U2 : R/W ;bitpos:[27:26] ;default: 2'd0 ; */ -/*description: */ -#define PCNT_CH1_POS_MODE_U2 0x00000003 -#define PCNT_CH1_POS_MODE_U2_M ((PCNT_CH1_POS_MODE_U2_V)<<(PCNT_CH1_POS_MODE_U2_S)) -#define PCNT_CH1_POS_MODE_U2_V 0x3 -#define PCNT_CH1_POS_MODE_U2_S 26 -/* PCNT_CH1_NEG_MODE_U2 : R/W ;bitpos:[25:24] ;default: 2'd0 ; */ -/*description: */ -#define PCNT_CH1_NEG_MODE_U2 0x00000003 -#define PCNT_CH1_NEG_MODE_U2_M ((PCNT_CH1_NEG_MODE_U2_V)<<(PCNT_CH1_NEG_MODE_U2_S)) -#define PCNT_CH1_NEG_MODE_U2_V 0x3 -#define PCNT_CH1_NEG_MODE_U2_S 24 -/* PCNT_CH0_LCTRL_MODE_U2 : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: */ -#define PCNT_CH0_LCTRL_MODE_U2 0x00000003 -#define PCNT_CH0_LCTRL_MODE_U2_M ((PCNT_CH0_LCTRL_MODE_U2_V)<<(PCNT_CH0_LCTRL_MODE_U2_S)) -#define PCNT_CH0_LCTRL_MODE_U2_V 0x3 -#define PCNT_CH0_LCTRL_MODE_U2_S 22 -/* PCNT_CH0_HCTRL_MODE_U2 : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: */ -#define PCNT_CH0_HCTRL_MODE_U2 0x00000003 -#define PCNT_CH0_HCTRL_MODE_U2_M ((PCNT_CH0_HCTRL_MODE_U2_V)<<(PCNT_CH0_HCTRL_MODE_U2_S)) -#define PCNT_CH0_HCTRL_MODE_U2_V 0x3 -#define PCNT_CH0_HCTRL_MODE_U2_S 20 -/* PCNT_CH0_POS_MODE_U2 : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: */ -#define PCNT_CH0_POS_MODE_U2 0x00000003 -#define PCNT_CH0_POS_MODE_U2_M ((PCNT_CH0_POS_MODE_U2_V)<<(PCNT_CH0_POS_MODE_U2_S)) -#define PCNT_CH0_POS_MODE_U2_V 0x3 -#define PCNT_CH0_POS_MODE_U2_S 18 -/* PCNT_CH0_NEG_MODE_U2 : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: */ -#define PCNT_CH0_NEG_MODE_U2 0x00000003 -#define PCNT_CH0_NEG_MODE_U2_M ((PCNT_CH0_NEG_MODE_U2_V)<<(PCNT_CH0_NEG_MODE_U2_S)) -#define PCNT_CH0_NEG_MODE_U2_V 0x3 -#define PCNT_CH0_NEG_MODE_U2_S 16 -/* PCNT_THR_THRES1_EN_U2 : R/W ;bitpos:[15] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_THR_THRES1_EN_U2 (BIT(15)) -#define PCNT_THR_THRES1_EN_U2_M (BIT(15)) -#define PCNT_THR_THRES1_EN_U2_V 0x1 -#define PCNT_THR_THRES1_EN_U2_S 15 -/* PCNT_THR_THRES0_EN_U2 : R/W ;bitpos:[14] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_THR_THRES0_EN_U2 (BIT(14)) -#define PCNT_THR_THRES0_EN_U2_M (BIT(14)) -#define PCNT_THR_THRES0_EN_U2_V 0x1 -#define PCNT_THR_THRES0_EN_U2_S 14 -/* PCNT_THR_L_LIM_EN_U2 : R/W ;bitpos:[13] ;default: 1'b1 ; */ -/*description: */ -#define PCNT_THR_L_LIM_EN_U2 (BIT(13)) -#define PCNT_THR_L_LIM_EN_U2_M (BIT(13)) -#define PCNT_THR_L_LIM_EN_U2_V 0x1 -#define PCNT_THR_L_LIM_EN_U2_S 13 -/* PCNT_THR_H_LIM_EN_U2 : R/W ;bitpos:[12] ;default: 1'b1 ; */ -/*description: */ -#define PCNT_THR_H_LIM_EN_U2 (BIT(12)) -#define PCNT_THR_H_LIM_EN_U2_M (BIT(12)) -#define PCNT_THR_H_LIM_EN_U2_V 0x1 -#define PCNT_THR_H_LIM_EN_U2_S 12 -/* PCNT_THR_ZERO_EN_U2 : R/W ;bitpos:[11] ;default: 1'b1 ; */ -/*description: */ -#define PCNT_THR_ZERO_EN_U2 (BIT(11)) -#define PCNT_THR_ZERO_EN_U2_M (BIT(11)) -#define PCNT_THR_ZERO_EN_U2_V 0x1 -#define PCNT_THR_ZERO_EN_U2_S 11 -/* PCNT_FILTER_EN_U2 : R/W ;bitpos:[10] ;default: 1'b1 ; */ -/*description: */ -#define PCNT_FILTER_EN_U2 (BIT(10)) -#define PCNT_FILTER_EN_U2_M (BIT(10)) -#define PCNT_FILTER_EN_U2_V 0x1 -#define PCNT_FILTER_EN_U2_S 10 -/* PCNT_FILTER_THRES_U2 : R/W ;bitpos:[9:0] ;default: 10'h10 ; */ -/*description: */ -#define PCNT_FILTER_THRES_U2 0x000003FF -#define PCNT_FILTER_THRES_U2_M ((PCNT_FILTER_THRES_U2_V)<<(PCNT_FILTER_THRES_U2_S)) -#define PCNT_FILTER_THRES_U2_V 0x3FF +/** PCNT_U2_CONF0_REG register + * Configuration register 0 for unit 2 + */ +#define PCNT_U2_CONF0_REG (DR_REG_PCNT_BASE + 0x18) +/** PCNT_FILTER_THRES_U2 : R/W; bitpos: [9:0]; default: 16; + * This sets the maximum threshold, in APB_CLK cycles, for the filter. + * + * Any pulses with width less than this will be ignored when the filter is enabled. + */ +#define PCNT_FILTER_THRES_U2 0x000003FFU +#define PCNT_FILTER_THRES_U2_M (PCNT_FILTER_THRES_U2_V << PCNT_FILTER_THRES_U2_S) +#define PCNT_FILTER_THRES_U2_V 0x000003FFU #define PCNT_FILTER_THRES_U2_S 0 +/** PCNT_FILTER_EN_U2 : R/W; bitpos: [10]; default: 1; + * This is the enable bit for unit 2's input filter. + */ +#define PCNT_FILTER_EN_U2 (BIT(10)) +#define PCNT_FILTER_EN_U2_M (PCNT_FILTER_EN_U2_V << PCNT_FILTER_EN_U2_S) +#define PCNT_FILTER_EN_U2_V 0x00000001U +#define PCNT_FILTER_EN_U2_S 10 +/** PCNT_THR_ZERO_EN_U2 : R/W; bitpos: [11]; default: 1; + * This is the enable bit for unit 2's zero comparator. + */ +#define PCNT_THR_ZERO_EN_U2 (BIT(11)) +#define PCNT_THR_ZERO_EN_U2_M (PCNT_THR_ZERO_EN_U2_V << PCNT_THR_ZERO_EN_U2_S) +#define PCNT_THR_ZERO_EN_U2_V 0x00000001U +#define PCNT_THR_ZERO_EN_U2_S 11 +/** PCNT_THR_H_LIM_EN_U2 : R/W; bitpos: [12]; default: 1; + * This is the enable bit for unit 2's thr_h_lim comparator. + */ +#define PCNT_THR_H_LIM_EN_U2 (BIT(12)) +#define PCNT_THR_H_LIM_EN_U2_M (PCNT_THR_H_LIM_EN_U2_V << PCNT_THR_H_LIM_EN_U2_S) +#define PCNT_THR_H_LIM_EN_U2_V 0x00000001U +#define PCNT_THR_H_LIM_EN_U2_S 12 +/** PCNT_THR_L_LIM_EN_U2 : R/W; bitpos: [13]; default: 1; + * This is the enable bit for unit 2's thr_l_lim comparator. + */ +#define PCNT_THR_L_LIM_EN_U2 (BIT(13)) +#define PCNT_THR_L_LIM_EN_U2_M (PCNT_THR_L_LIM_EN_U2_V << PCNT_THR_L_LIM_EN_U2_S) +#define PCNT_THR_L_LIM_EN_U2_V 0x00000001U +#define PCNT_THR_L_LIM_EN_U2_S 13 +/** PCNT_THR_THRES0_EN_U2 : R/W; bitpos: [14]; default: 0; + * This is the enable bit for unit 2's thres0 comparator. + */ +#define PCNT_THR_THRES0_EN_U2 (BIT(14)) +#define PCNT_THR_THRES0_EN_U2_M (PCNT_THR_THRES0_EN_U2_V << PCNT_THR_THRES0_EN_U2_S) +#define PCNT_THR_THRES0_EN_U2_V 0x00000001U +#define PCNT_THR_THRES0_EN_U2_S 14 +/** PCNT_THR_THRES1_EN_U2 : R/W; bitpos: [15]; default: 0; + * This is the enable bit for unit 2's thres1 comparator. + */ +#define PCNT_THR_THRES1_EN_U2 (BIT(15)) +#define PCNT_THR_THRES1_EN_U2_M (PCNT_THR_THRES1_EN_U2_V << PCNT_THR_THRES1_EN_U2_S) +#define PCNT_THR_THRES1_EN_U2_V 0x00000001U +#define PCNT_THR_THRES1_EN_U2_S 15 +/** PCNT_CH0_NEG_MODE_U2 : R/W; bitpos: [17:16]; default: 0; + * This register sets the behavior when the signal input of channel 0 detects a + * negative edge. + * + * 1: Increase the counter;2: Decrease the counter;0, 3: No effect on counter + */ +#define PCNT_CH0_NEG_MODE_U2 0x00000003U +#define PCNT_CH0_NEG_MODE_U2_M (PCNT_CH0_NEG_MODE_U2_V << PCNT_CH0_NEG_MODE_U2_S) +#define PCNT_CH0_NEG_MODE_U2_V 0x00000003U +#define PCNT_CH0_NEG_MODE_U2_S 16 +/** PCNT_CH0_POS_MODE_U2 : R/W; bitpos: [19:18]; default: 0; + * This register sets the behavior when the signal input of channel 0 detects a + * positive edge. + * + * 1: Increase the counter;2: Decrease the counter;0, 3: No effect on counter + */ +#define PCNT_CH0_POS_MODE_U2 0x00000003U +#define PCNT_CH0_POS_MODE_U2_M (PCNT_CH0_POS_MODE_U2_V << PCNT_CH0_POS_MODE_U2_S) +#define PCNT_CH0_POS_MODE_U2_V 0x00000003U +#define PCNT_CH0_POS_MODE_U2_S 18 +/** PCNT_CH0_HCTRL_MODE_U2 : R/W; bitpos: [21:20]; default: 0; + * This register configures how the CH2_POS_MODE/CH2_NEG_MODE settings will be + * modified when the control signal is high. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ +#define PCNT_CH0_HCTRL_MODE_U2 0x00000003U +#define PCNT_CH0_HCTRL_MODE_U2_M (PCNT_CH0_HCTRL_MODE_U2_V << PCNT_CH0_HCTRL_MODE_U2_S) +#define PCNT_CH0_HCTRL_MODE_U2_V 0x00000003U +#define PCNT_CH0_HCTRL_MODE_U2_S 20 +/** PCNT_CH0_LCTRL_MODE_U2 : R/W; bitpos: [23:22]; default: 0; + * This register configures how the CH2_POS_MODE/CH2_NEG_MODE settings will be + * modified when the control signal is low. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ +#define PCNT_CH0_LCTRL_MODE_U2 0x00000003U +#define PCNT_CH0_LCTRL_MODE_U2_M (PCNT_CH0_LCTRL_MODE_U2_V << PCNT_CH0_LCTRL_MODE_U2_S) +#define PCNT_CH0_LCTRL_MODE_U2_V 0x00000003U +#define PCNT_CH0_LCTRL_MODE_U2_S 22 +/** PCNT_CH1_NEG_MODE_U2 : R/W; bitpos: [25:24]; default: 0; + * This register sets the behavior when the signal input of channel 1 detects a + * negative edge. + * + * 1: Increment the counter;2: Decrement the counter;0, 3: No effect on counter + */ +#define PCNT_CH1_NEG_MODE_U2 0x00000003U +#define PCNT_CH1_NEG_MODE_U2_M (PCNT_CH1_NEG_MODE_U2_V << PCNT_CH1_NEG_MODE_U2_S) +#define PCNT_CH1_NEG_MODE_U2_V 0x00000003U +#define PCNT_CH1_NEG_MODE_U2_S 24 +/** PCNT_CH1_POS_MODE_U2 : R/W; bitpos: [27:26]; default: 0; + * This register sets the behavior when the signal input of channel 1 detects a + * positive edge. + * + * 1: Increment the counter;2: Decrement the counter;0, 3: No effect on counter + */ +#define PCNT_CH1_POS_MODE_U2 0x00000003U +#define PCNT_CH1_POS_MODE_U2_M (PCNT_CH1_POS_MODE_U2_V << PCNT_CH1_POS_MODE_U2_S) +#define PCNT_CH1_POS_MODE_U2_V 0x00000003U +#define PCNT_CH1_POS_MODE_U2_S 26 +/** PCNT_CH1_HCTRL_MODE_U2 : R/W; bitpos: [29:28]; default: 0; + * This register configures how the CH2_POS_MODE/CH2_NEG_MODE settings will be + * modified when the control signal is high. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ +#define PCNT_CH1_HCTRL_MODE_U2 0x00000003U +#define PCNT_CH1_HCTRL_MODE_U2_M (PCNT_CH1_HCTRL_MODE_U2_V << PCNT_CH1_HCTRL_MODE_U2_S) +#define PCNT_CH1_HCTRL_MODE_U2_V 0x00000003U +#define PCNT_CH1_HCTRL_MODE_U2_S 28 +/** PCNT_CH1_LCTRL_MODE_U2 : R/W; bitpos: [31:30]; default: 0; + * This register configures how the CH2_POS_MODE/CH2_NEG_MODE settings will be + * modified when the control signal is low. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ +#define PCNT_CH1_LCTRL_MODE_U2 0x00000003U +#define PCNT_CH1_LCTRL_MODE_U2_M (PCNT_CH1_LCTRL_MODE_U2_V << PCNT_CH1_LCTRL_MODE_U2_S) +#define PCNT_CH1_LCTRL_MODE_U2_V 0x00000003U +#define PCNT_CH1_LCTRL_MODE_U2_S 30 -#define PCNT_U2_CONF1_REG (DR_REG_PCNT_BASE + 0x001c) -/* PCNT_CNT_THRES1_U2 : R/W ;bitpos:[31:16] ;default: 10'h0 ; */ -/*description: */ -#define PCNT_CNT_THRES1_U2 0x0000FFFF -#define PCNT_CNT_THRES1_U2_M ((PCNT_CNT_THRES1_U2_V)<<(PCNT_CNT_THRES1_U2_S)) -#define PCNT_CNT_THRES1_U2_V 0xFFFF -#define PCNT_CNT_THRES1_U2_S 16 -/* PCNT_CNT_THRES0_U2 : R/W ;bitpos:[15:0] ;default: 10'h0 ; */ -/*description: */ -#define PCNT_CNT_THRES0_U2 0x0000FFFF -#define PCNT_CNT_THRES0_U2_M ((PCNT_CNT_THRES0_U2_V)<<(PCNT_CNT_THRES0_U2_S)) -#define PCNT_CNT_THRES0_U2_V 0xFFFF +/** PCNT_U2_CONF1_REG register + * Configuration register 1 for unit 2 + */ +#define PCNT_U2_CONF1_REG (DR_REG_PCNT_BASE + 0x1c) +/** PCNT_CNT_THRES0_U2 : R/W; bitpos: [15:0]; default: 0; + * This register is used to configure the thres0 value for unit 2. + */ +#define PCNT_CNT_THRES0_U2 0x0000FFFFU +#define PCNT_CNT_THRES0_U2_M (PCNT_CNT_THRES0_U2_V << PCNT_CNT_THRES0_U2_S) +#define PCNT_CNT_THRES0_U2_V 0x0000FFFFU #define PCNT_CNT_THRES0_U2_S 0 +/** PCNT_CNT_THRES1_U2 : R/W; bitpos: [31:16]; default: 0; + * This register is used to configure the thres1 value for unit 2. + */ +#define PCNT_CNT_THRES1_U2 0x0000FFFFU +#define PCNT_CNT_THRES1_U2_M (PCNT_CNT_THRES1_U2_V << PCNT_CNT_THRES1_U2_S) +#define PCNT_CNT_THRES1_U2_V 0x0000FFFFU +#define PCNT_CNT_THRES1_U2_S 16 -#define PCNT_U2_CONF2_REG (DR_REG_PCNT_BASE + 0x0020) -/* PCNT_CNT_L_LIM_U2 : R/W ;bitpos:[31:16] ;default: 10'h0 ; */ -/*description: */ -#define PCNT_CNT_L_LIM_U2 0x0000FFFF -#define PCNT_CNT_L_LIM_U2_M ((PCNT_CNT_L_LIM_U2_V)<<(PCNT_CNT_L_LIM_U2_S)) -#define PCNT_CNT_L_LIM_U2_V 0xFFFF -#define PCNT_CNT_L_LIM_U2_S 16 -/* PCNT_CNT_H_LIM_U2 : R/W ;bitpos:[15:0] ;default: 10'h0 ; */ -/*description: */ -#define PCNT_CNT_H_LIM_U2 0x0000FFFF -#define PCNT_CNT_H_LIM_U2_M ((PCNT_CNT_H_LIM_U2_V)<<(PCNT_CNT_H_LIM_U2_S)) -#define PCNT_CNT_H_LIM_U2_V 0xFFFF +/** PCNT_U2_CONF2_REG register + * Configuration register 2 for unit 2 + */ +#define PCNT_U2_CONF2_REG (DR_REG_PCNT_BASE + 0x20) +/** PCNT_CNT_H_LIM_U2 : R/W; bitpos: [15:0]; default: 0; + * This register is used to configure the thr_h_lim value for unit 2. + */ +#define PCNT_CNT_H_LIM_U2 0x0000FFFFU +#define PCNT_CNT_H_LIM_U2_M (PCNT_CNT_H_LIM_U2_V << PCNT_CNT_H_LIM_U2_S) +#define PCNT_CNT_H_LIM_U2_V 0x0000FFFFU #define PCNT_CNT_H_LIM_U2_S 0 +/** PCNT_CNT_L_LIM_U2 : R/W; bitpos: [31:16]; default: 0; + * This register is used to configure the thr_l_lim value for unit 2. + */ +#define PCNT_CNT_L_LIM_U2 0x0000FFFFU +#define PCNT_CNT_L_LIM_U2_M (PCNT_CNT_L_LIM_U2_V << PCNT_CNT_L_LIM_U2_S) +#define PCNT_CNT_L_LIM_U2_V 0x0000FFFFU +#define PCNT_CNT_L_LIM_U2_S 16 -#define PCNT_U3_CONF0_REG (DR_REG_PCNT_BASE + 0x0024) -/* PCNT_CH1_LCTRL_MODE_U3 : R/W ;bitpos:[31:30] ;default: 2'd0 ; */ -/*description: */ -#define PCNT_CH1_LCTRL_MODE_U3 0x00000003 -#define PCNT_CH1_LCTRL_MODE_U3_M ((PCNT_CH1_LCTRL_MODE_U3_V)<<(PCNT_CH1_LCTRL_MODE_U3_S)) -#define PCNT_CH1_LCTRL_MODE_U3_V 0x3 -#define PCNT_CH1_LCTRL_MODE_U3_S 30 -/* PCNT_CH1_HCTRL_MODE_U3 : R/W ;bitpos:[29:28] ;default: 2'd0 ; */ -/*description: */ -#define PCNT_CH1_HCTRL_MODE_U3 0x00000003 -#define PCNT_CH1_HCTRL_MODE_U3_M ((PCNT_CH1_HCTRL_MODE_U3_V)<<(PCNT_CH1_HCTRL_MODE_U3_S)) -#define PCNT_CH1_HCTRL_MODE_U3_V 0x3 -#define PCNT_CH1_HCTRL_MODE_U3_S 28 -/* PCNT_CH1_POS_MODE_U3 : R/W ;bitpos:[27:26] ;default: 2'd0 ; */ -/*description: */ -#define PCNT_CH1_POS_MODE_U3 0x00000003 -#define PCNT_CH1_POS_MODE_U3_M ((PCNT_CH1_POS_MODE_U3_V)<<(PCNT_CH1_POS_MODE_U3_S)) -#define PCNT_CH1_POS_MODE_U3_V 0x3 -#define PCNT_CH1_POS_MODE_U3_S 26 -/* PCNT_CH1_NEG_MODE_U3 : R/W ;bitpos:[25:24] ;default: 2'd0 ; */ -/*description: */ -#define PCNT_CH1_NEG_MODE_U3 0x00000003 -#define PCNT_CH1_NEG_MODE_U3_M ((PCNT_CH1_NEG_MODE_U3_V)<<(PCNT_CH1_NEG_MODE_U3_S)) -#define PCNT_CH1_NEG_MODE_U3_V 0x3 -#define PCNT_CH1_NEG_MODE_U3_S 24 -/* PCNT_CH0_LCTRL_MODE_U3 : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: */ -#define PCNT_CH0_LCTRL_MODE_U3 0x00000003 -#define PCNT_CH0_LCTRL_MODE_U3_M ((PCNT_CH0_LCTRL_MODE_U3_V)<<(PCNT_CH0_LCTRL_MODE_U3_S)) -#define PCNT_CH0_LCTRL_MODE_U3_V 0x3 -#define PCNT_CH0_LCTRL_MODE_U3_S 22 -/* PCNT_CH0_HCTRL_MODE_U3 : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: */ -#define PCNT_CH0_HCTRL_MODE_U3 0x00000003 -#define PCNT_CH0_HCTRL_MODE_U3_M ((PCNT_CH0_HCTRL_MODE_U3_V)<<(PCNT_CH0_HCTRL_MODE_U3_S)) -#define PCNT_CH0_HCTRL_MODE_U3_V 0x3 -#define PCNT_CH0_HCTRL_MODE_U3_S 20 -/* PCNT_CH0_POS_MODE_U3 : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: */ -#define PCNT_CH0_POS_MODE_U3 0x00000003 -#define PCNT_CH0_POS_MODE_U3_M ((PCNT_CH0_POS_MODE_U3_V)<<(PCNT_CH0_POS_MODE_U3_S)) -#define PCNT_CH0_POS_MODE_U3_V 0x3 -#define PCNT_CH0_POS_MODE_U3_S 18 -/* PCNT_CH0_NEG_MODE_U3 : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: */ -#define PCNT_CH0_NEG_MODE_U3 0x00000003 -#define PCNT_CH0_NEG_MODE_U3_M ((PCNT_CH0_NEG_MODE_U3_V)<<(PCNT_CH0_NEG_MODE_U3_S)) -#define PCNT_CH0_NEG_MODE_U3_V 0x3 -#define PCNT_CH0_NEG_MODE_U3_S 16 -/* PCNT_THR_THRES1_EN_U3 : R/W ;bitpos:[15] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_THR_THRES1_EN_U3 (BIT(15)) -#define PCNT_THR_THRES1_EN_U3_M (BIT(15)) -#define PCNT_THR_THRES1_EN_U3_V 0x1 -#define PCNT_THR_THRES1_EN_U3_S 15 -/* PCNT_THR_THRES0_EN_U3 : R/W ;bitpos:[14] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_THR_THRES0_EN_U3 (BIT(14)) -#define PCNT_THR_THRES0_EN_U3_M (BIT(14)) -#define PCNT_THR_THRES0_EN_U3_V 0x1 -#define PCNT_THR_THRES0_EN_U3_S 14 -/* PCNT_THR_L_LIM_EN_U3 : R/W ;bitpos:[13] ;default: 1'b1 ; */ -/*description: */ -#define PCNT_THR_L_LIM_EN_U3 (BIT(13)) -#define PCNT_THR_L_LIM_EN_U3_M (BIT(13)) -#define PCNT_THR_L_LIM_EN_U3_V 0x1 -#define PCNT_THR_L_LIM_EN_U3_S 13 -/* PCNT_THR_H_LIM_EN_U3 : R/W ;bitpos:[12] ;default: 1'b1 ; */ -/*description: */ -#define PCNT_THR_H_LIM_EN_U3 (BIT(12)) -#define PCNT_THR_H_LIM_EN_U3_M (BIT(12)) -#define PCNT_THR_H_LIM_EN_U3_V 0x1 -#define PCNT_THR_H_LIM_EN_U3_S 12 -/* PCNT_THR_ZERO_EN_U3 : R/W ;bitpos:[11] ;default: 1'b1 ; */ -/*description: */ -#define PCNT_THR_ZERO_EN_U3 (BIT(11)) -#define PCNT_THR_ZERO_EN_U3_M (BIT(11)) -#define PCNT_THR_ZERO_EN_U3_V 0x1 -#define PCNT_THR_ZERO_EN_U3_S 11 -/* PCNT_FILTER_EN_U3 : R/W ;bitpos:[10] ;default: 1'b1 ; */ -/*description: */ -#define PCNT_FILTER_EN_U3 (BIT(10)) -#define PCNT_FILTER_EN_U3_M (BIT(10)) -#define PCNT_FILTER_EN_U3_V 0x1 -#define PCNT_FILTER_EN_U3_S 10 -/* PCNT_FILTER_THRES_U3 : R/W ;bitpos:[9:0] ;default: 10'h10 ; */ -/*description: */ -#define PCNT_FILTER_THRES_U3 0x000003FF -#define PCNT_FILTER_THRES_U3_M ((PCNT_FILTER_THRES_U3_V)<<(PCNT_FILTER_THRES_U3_S)) -#define PCNT_FILTER_THRES_U3_V 0x3FF +/** PCNT_U3_CONF0_REG register + * Configuration register 0 for unit 3 + */ +#define PCNT_U3_CONF0_REG (DR_REG_PCNT_BASE + 0x24) +/** PCNT_FILTER_THRES_U3 : R/W; bitpos: [9:0]; default: 16; + * This sets the maximum threshold, in APB_CLK cycles, for the filter. + * + * Any pulses with width less than this will be ignored when the filter is enabled. + */ +#define PCNT_FILTER_THRES_U3 0x000003FFU +#define PCNT_FILTER_THRES_U3_M (PCNT_FILTER_THRES_U3_V << PCNT_FILTER_THRES_U3_S) +#define PCNT_FILTER_THRES_U3_V 0x000003FFU #define PCNT_FILTER_THRES_U3_S 0 +/** PCNT_FILTER_EN_U3 : R/W; bitpos: [10]; default: 1; + * This is the enable bit for unit 3's input filter. + */ +#define PCNT_FILTER_EN_U3 (BIT(10)) +#define PCNT_FILTER_EN_U3_M (PCNT_FILTER_EN_U3_V << PCNT_FILTER_EN_U3_S) +#define PCNT_FILTER_EN_U3_V 0x00000001U +#define PCNT_FILTER_EN_U3_S 10 +/** PCNT_THR_ZERO_EN_U3 : R/W; bitpos: [11]; default: 1; + * This is the enable bit for unit 3's zero comparator. + */ +#define PCNT_THR_ZERO_EN_U3 (BIT(11)) +#define PCNT_THR_ZERO_EN_U3_M (PCNT_THR_ZERO_EN_U3_V << PCNT_THR_ZERO_EN_U3_S) +#define PCNT_THR_ZERO_EN_U3_V 0x00000001U +#define PCNT_THR_ZERO_EN_U3_S 11 +/** PCNT_THR_H_LIM_EN_U3 : R/W; bitpos: [12]; default: 1; + * This is the enable bit for unit 3's thr_h_lim comparator. + */ +#define PCNT_THR_H_LIM_EN_U3 (BIT(12)) +#define PCNT_THR_H_LIM_EN_U3_M (PCNT_THR_H_LIM_EN_U3_V << PCNT_THR_H_LIM_EN_U3_S) +#define PCNT_THR_H_LIM_EN_U3_V 0x00000001U +#define PCNT_THR_H_LIM_EN_U3_S 12 +/** PCNT_THR_L_LIM_EN_U3 : R/W; bitpos: [13]; default: 1; + * This is the enable bit for unit 3's thr_l_lim comparator. + */ +#define PCNT_THR_L_LIM_EN_U3 (BIT(13)) +#define PCNT_THR_L_LIM_EN_U3_M (PCNT_THR_L_LIM_EN_U3_V << PCNT_THR_L_LIM_EN_U3_S) +#define PCNT_THR_L_LIM_EN_U3_V 0x00000001U +#define PCNT_THR_L_LIM_EN_U3_S 13 +/** PCNT_THR_THRES0_EN_U3 : R/W; bitpos: [14]; default: 0; + * This is the enable bit for unit 3's thres0 comparator. + */ +#define PCNT_THR_THRES0_EN_U3 (BIT(14)) +#define PCNT_THR_THRES0_EN_U3_M (PCNT_THR_THRES0_EN_U3_V << PCNT_THR_THRES0_EN_U3_S) +#define PCNT_THR_THRES0_EN_U3_V 0x00000001U +#define PCNT_THR_THRES0_EN_U3_S 14 +/** PCNT_THR_THRES1_EN_U3 : R/W; bitpos: [15]; default: 0; + * This is the enable bit for unit 3's thres1 comparator. + */ +#define PCNT_THR_THRES1_EN_U3 (BIT(15)) +#define PCNT_THR_THRES1_EN_U3_M (PCNT_THR_THRES1_EN_U3_V << PCNT_THR_THRES1_EN_U3_S) +#define PCNT_THR_THRES1_EN_U3_V 0x00000001U +#define PCNT_THR_THRES1_EN_U3_S 15 +/** PCNT_CH0_NEG_MODE_U3 : R/W; bitpos: [17:16]; default: 0; + * This register sets the behavior when the signal input of channel 0 detects a + * negative edge. + * + * 1: Increase the counter;2: Decrease the counter;0, 3: No effect on counter + */ +#define PCNT_CH0_NEG_MODE_U3 0x00000003U +#define PCNT_CH0_NEG_MODE_U3_M (PCNT_CH0_NEG_MODE_U3_V << PCNT_CH0_NEG_MODE_U3_S) +#define PCNT_CH0_NEG_MODE_U3_V 0x00000003U +#define PCNT_CH0_NEG_MODE_U3_S 16 +/** PCNT_CH0_POS_MODE_U3 : R/W; bitpos: [19:18]; default: 0; + * This register sets the behavior when the signal input of channel 0 detects a + * positive edge. + * + * 1: Increase the counter;2: Decrease the counter;0, 3: No effect on counter + */ +#define PCNT_CH0_POS_MODE_U3 0x00000003U +#define PCNT_CH0_POS_MODE_U3_M (PCNT_CH0_POS_MODE_U3_V << PCNT_CH0_POS_MODE_U3_S) +#define PCNT_CH0_POS_MODE_U3_V 0x00000003U +#define PCNT_CH0_POS_MODE_U3_S 18 +/** PCNT_CH0_HCTRL_MODE_U3 : R/W; bitpos: [21:20]; default: 0; + * This register configures how the CH3_POS_MODE/CH3_NEG_MODE settings will be + * modified when the control signal is high. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ +#define PCNT_CH0_HCTRL_MODE_U3 0x00000003U +#define PCNT_CH0_HCTRL_MODE_U3_M (PCNT_CH0_HCTRL_MODE_U3_V << PCNT_CH0_HCTRL_MODE_U3_S) +#define PCNT_CH0_HCTRL_MODE_U3_V 0x00000003U +#define PCNT_CH0_HCTRL_MODE_U3_S 20 +/** PCNT_CH0_LCTRL_MODE_U3 : R/W; bitpos: [23:22]; default: 0; + * This register configures how the CH3_POS_MODE/CH3_NEG_MODE settings will be + * modified when the control signal is low. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ +#define PCNT_CH0_LCTRL_MODE_U3 0x00000003U +#define PCNT_CH0_LCTRL_MODE_U3_M (PCNT_CH0_LCTRL_MODE_U3_V << PCNT_CH0_LCTRL_MODE_U3_S) +#define PCNT_CH0_LCTRL_MODE_U3_V 0x00000003U +#define PCNT_CH0_LCTRL_MODE_U3_S 22 +/** PCNT_CH1_NEG_MODE_U3 : R/W; bitpos: [25:24]; default: 0; + * This register sets the behavior when the signal input of channel 1 detects a + * negative edge. + * + * 1: Increment the counter;2: Decrement the counter;0, 3: No effect on counter + */ +#define PCNT_CH1_NEG_MODE_U3 0x00000003U +#define PCNT_CH1_NEG_MODE_U3_M (PCNT_CH1_NEG_MODE_U3_V << PCNT_CH1_NEG_MODE_U3_S) +#define PCNT_CH1_NEG_MODE_U3_V 0x00000003U +#define PCNT_CH1_NEG_MODE_U3_S 24 +/** PCNT_CH1_POS_MODE_U3 : R/W; bitpos: [27:26]; default: 0; + * This register sets the behavior when the signal input of channel 1 detects a + * positive edge. + * + * 1: Increment the counter;2: Decrement the counter;0, 3: No effect on counter + */ +#define PCNT_CH1_POS_MODE_U3 0x00000003U +#define PCNT_CH1_POS_MODE_U3_M (PCNT_CH1_POS_MODE_U3_V << PCNT_CH1_POS_MODE_U3_S) +#define PCNT_CH1_POS_MODE_U3_V 0x00000003U +#define PCNT_CH1_POS_MODE_U3_S 26 +/** PCNT_CH1_HCTRL_MODE_U3 : R/W; bitpos: [29:28]; default: 0; + * This register configures how the CH3_POS_MODE/CH3_NEG_MODE settings will be + * modified when the control signal is high. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ +#define PCNT_CH1_HCTRL_MODE_U3 0x00000003U +#define PCNT_CH1_HCTRL_MODE_U3_M (PCNT_CH1_HCTRL_MODE_U3_V << PCNT_CH1_HCTRL_MODE_U3_S) +#define PCNT_CH1_HCTRL_MODE_U3_V 0x00000003U +#define PCNT_CH1_HCTRL_MODE_U3_S 28 +/** PCNT_CH1_LCTRL_MODE_U3 : R/W; bitpos: [31:30]; default: 0; + * This register configures how the CH3_POS_MODE/CH3_NEG_MODE settings will be + * modified when the control signal is low. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ +#define PCNT_CH1_LCTRL_MODE_U3 0x00000003U +#define PCNT_CH1_LCTRL_MODE_U3_M (PCNT_CH1_LCTRL_MODE_U3_V << PCNT_CH1_LCTRL_MODE_U3_S) +#define PCNT_CH1_LCTRL_MODE_U3_V 0x00000003U +#define PCNT_CH1_LCTRL_MODE_U3_S 30 -#define PCNT_U3_CONF1_REG (DR_REG_PCNT_BASE + 0x0028) -/* PCNT_CNT_THRES1_U3 : R/W ;bitpos:[31:16] ;default: 10'h0 ; */ -/*description: */ -#define PCNT_CNT_THRES1_U3 0x0000FFFF -#define PCNT_CNT_THRES1_U3_M ((PCNT_CNT_THRES1_U3_V)<<(PCNT_CNT_THRES1_U3_S)) -#define PCNT_CNT_THRES1_U3_V 0xFFFF -#define PCNT_CNT_THRES1_U3_S 16 -/* PCNT_CNT_THRES0_U3 : R/W ;bitpos:[15:0] ;default: 10'h0 ; */ -/*description: */ -#define PCNT_CNT_THRES0_U3 0x0000FFFF -#define PCNT_CNT_THRES0_U3_M ((PCNT_CNT_THRES0_U3_V)<<(PCNT_CNT_THRES0_U3_S)) -#define PCNT_CNT_THRES0_U3_V 0xFFFF +/** PCNT_U3_CONF1_REG register + * Configuration register 1 for unit 3 + */ +#define PCNT_U3_CONF1_REG (DR_REG_PCNT_BASE + 0x28) +/** PCNT_CNT_THRES0_U3 : R/W; bitpos: [15:0]; default: 0; + * This register is used to configure the thres0 value for unit 3. + */ +#define PCNT_CNT_THRES0_U3 0x0000FFFFU +#define PCNT_CNT_THRES0_U3_M (PCNT_CNT_THRES0_U3_V << PCNT_CNT_THRES0_U3_S) +#define PCNT_CNT_THRES0_U3_V 0x0000FFFFU #define PCNT_CNT_THRES0_U3_S 0 +/** PCNT_CNT_THRES1_U3 : R/W; bitpos: [31:16]; default: 0; + * This register is used to configure the thres1 value for unit 3. + */ +#define PCNT_CNT_THRES1_U3 0x0000FFFFU +#define PCNT_CNT_THRES1_U3_M (PCNT_CNT_THRES1_U3_V << PCNT_CNT_THRES1_U3_S) +#define PCNT_CNT_THRES1_U3_V 0x0000FFFFU +#define PCNT_CNT_THRES1_U3_S 16 -#define PCNT_U3_CONF2_REG (DR_REG_PCNT_BASE + 0x002c) -/* PCNT_CNT_L_LIM_U3 : R/W ;bitpos:[31:16] ;default: 10'h0 ; */ -/*description: */ -#define PCNT_CNT_L_LIM_U3 0x0000FFFF -#define PCNT_CNT_L_LIM_U3_M ((PCNT_CNT_L_LIM_U3_V)<<(PCNT_CNT_L_LIM_U3_S)) -#define PCNT_CNT_L_LIM_U3_V 0xFFFF -#define PCNT_CNT_L_LIM_U3_S 16 -/* PCNT_CNT_H_LIM_U3 : R/W ;bitpos:[15:0] ;default: 10'h0 ; */ -/*description: */ -#define PCNT_CNT_H_LIM_U3 0x0000FFFF -#define PCNT_CNT_H_LIM_U3_M ((PCNT_CNT_H_LIM_U3_V)<<(PCNT_CNT_H_LIM_U3_S)) -#define PCNT_CNT_H_LIM_U3_V 0xFFFF +/** PCNT_U3_CONF2_REG register + * Configuration register 2 for unit 3 + */ +#define PCNT_U3_CONF2_REG (DR_REG_PCNT_BASE + 0x2c) +/** PCNT_CNT_H_LIM_U3 : R/W; bitpos: [15:0]; default: 0; + * This register is used to configure the thr_h_lim value for unit 3. + */ +#define PCNT_CNT_H_LIM_U3 0x0000FFFFU +#define PCNT_CNT_H_LIM_U3_M (PCNT_CNT_H_LIM_U3_V << PCNT_CNT_H_LIM_U3_S) +#define PCNT_CNT_H_LIM_U3_V 0x0000FFFFU #define PCNT_CNT_H_LIM_U3_S 0 +/** PCNT_CNT_L_LIM_U3 : R/W; bitpos: [31:16]; default: 0; + * This register is used to configure the thr_l_lim value for unit 3. + */ +#define PCNT_CNT_L_LIM_U3 0x0000FFFFU +#define PCNT_CNT_L_LIM_U3_M (PCNT_CNT_L_LIM_U3_V << PCNT_CNT_L_LIM_U3_S) +#define PCNT_CNT_L_LIM_U3_V 0x0000FFFFU +#define PCNT_CNT_L_LIM_U3_S 16 -#define PCNT_U0_CNT_REG (DR_REG_PCNT_BASE + 0x0030) -/* PCNT_PULSE_CNT_U0 : RO ;bitpos:[15:0] ;default: 16'h0 ; */ -/*description: */ -#define PCNT_PULSE_CNT_U0 0x0000FFFF -#define PCNT_PULSE_CNT_U0_M ((PCNT_PULSE_CNT_U0_V)<<(PCNT_PULSE_CNT_U0_S)) -#define PCNT_PULSE_CNT_U0_V 0xFFFF +/** PCNT_U0_CNT_REG register + * Counter value for unit 0 + */ +#define PCNT_U0_CNT_REG (DR_REG_PCNT_BASE + 0x30) +/** PCNT_PULSE_CNT_U0 : RO; bitpos: [15:0]; default: 0; + * This register stores the current pulse count value for unit 0. + */ +#define PCNT_PULSE_CNT_U0 0x0000FFFFU +#define PCNT_PULSE_CNT_U0_M (PCNT_PULSE_CNT_U0_V << PCNT_PULSE_CNT_U0_S) +#define PCNT_PULSE_CNT_U0_V 0x0000FFFFU #define PCNT_PULSE_CNT_U0_S 0 -#define PCNT_U1_CNT_REG (DR_REG_PCNT_BASE + 0x0034) -/* PCNT_PULSE_CNT_U1 : RO ;bitpos:[15:0] ;default: 16'h0 ; */ -/*description: */ -#define PCNT_PULSE_CNT_U1 0x0000FFFF -#define PCNT_PULSE_CNT_U1_M ((PCNT_PULSE_CNT_U1_V)<<(PCNT_PULSE_CNT_U1_S)) -#define PCNT_PULSE_CNT_U1_V 0xFFFF +/** PCNT_U1_CNT_REG register + * Counter value for unit 1 + */ +#define PCNT_U1_CNT_REG (DR_REG_PCNT_BASE + 0x34) +/** PCNT_PULSE_CNT_U1 : RO; bitpos: [15:0]; default: 0; + * This register stores the current pulse count value for unit 1. + */ +#define PCNT_PULSE_CNT_U1 0x0000FFFFU +#define PCNT_PULSE_CNT_U1_M (PCNT_PULSE_CNT_U1_V << PCNT_PULSE_CNT_U1_S) +#define PCNT_PULSE_CNT_U1_V 0x0000FFFFU #define PCNT_PULSE_CNT_U1_S 0 -#define PCNT_U2_CNT_REG (DR_REG_PCNT_BASE + 0x0038) -/* PCNT_PULSE_CNT_U2 : RO ;bitpos:[15:0] ;default: 16'h0 ; */ -/*description: */ -#define PCNT_PULSE_CNT_U2 0x0000FFFF -#define PCNT_PULSE_CNT_U2_M ((PCNT_PULSE_CNT_U2_V)<<(PCNT_PULSE_CNT_U2_S)) -#define PCNT_PULSE_CNT_U2_V 0xFFFF +/** PCNT_U2_CNT_REG register + * Counter value for unit 2 + */ +#define PCNT_U2_CNT_REG (DR_REG_PCNT_BASE + 0x38) +/** PCNT_PULSE_CNT_U2 : RO; bitpos: [15:0]; default: 0; + * This register stores the current pulse count value for unit 2. + */ +#define PCNT_PULSE_CNT_U2 0x0000FFFFU +#define PCNT_PULSE_CNT_U2_M (PCNT_PULSE_CNT_U2_V << PCNT_PULSE_CNT_U2_S) +#define PCNT_PULSE_CNT_U2_V 0x0000FFFFU #define PCNT_PULSE_CNT_U2_S 0 -#define PCNT_U3_CNT_REG (DR_REG_PCNT_BASE + 0x003c) -/* PCNT_PULSE_CNT_U3 : RO ;bitpos:[15:0] ;default: 16'h0 ; */ -/*description: */ -#define PCNT_PULSE_CNT_U3 0x0000FFFF -#define PCNT_PULSE_CNT_U3_M ((PCNT_PULSE_CNT_U3_V)<<(PCNT_PULSE_CNT_U3_S)) -#define PCNT_PULSE_CNT_U3_V 0xFFFF +/** PCNT_U3_CNT_REG register + * Counter value for unit 3 + */ +#define PCNT_U3_CNT_REG (DR_REG_PCNT_BASE + 0x3c) +/** PCNT_PULSE_CNT_U3 : RO; bitpos: [15:0]; default: 0; + * This register stores the current pulse count value for unit 3. + */ +#define PCNT_PULSE_CNT_U3 0x0000FFFFU +#define PCNT_PULSE_CNT_U3_M (PCNT_PULSE_CNT_U3_V << PCNT_PULSE_CNT_U3_S) +#define PCNT_PULSE_CNT_U3_V 0x0000FFFFU #define PCNT_PULSE_CNT_U3_S 0 -#define PCNT_INT_RAW_REG (DR_REG_PCNT_BASE + 0x0040) -/* PCNT_CNT_THR_EVENT_U3_INT_RAW : RO ;bitpos:[3] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_EVENT_U3_INT_RAW (BIT(3)) -#define PCNT_CNT_THR_EVENT_U3_INT_RAW_M (BIT(3)) -#define PCNT_CNT_THR_EVENT_U3_INT_RAW_V 0x1 -#define PCNT_CNT_THR_EVENT_U3_INT_RAW_S 3 -/* PCNT_CNT_THR_EVENT_U2_INT_RAW : RO ;bitpos:[2] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_EVENT_U2_INT_RAW (BIT(2)) -#define PCNT_CNT_THR_EVENT_U2_INT_RAW_M (BIT(2)) -#define PCNT_CNT_THR_EVENT_U2_INT_RAW_V 0x1 -#define PCNT_CNT_THR_EVENT_U2_INT_RAW_S 2 -/* PCNT_CNT_THR_EVENT_U1_INT_RAW : RO ;bitpos:[1] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_EVENT_U1_INT_RAW (BIT(1)) -#define PCNT_CNT_THR_EVENT_U1_INT_RAW_M (BIT(1)) -#define PCNT_CNT_THR_EVENT_U1_INT_RAW_V 0x1 -#define PCNT_CNT_THR_EVENT_U1_INT_RAW_S 1 -/* PCNT_CNT_THR_EVENT_U0_INT_RAW : RO ;bitpos:[0] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_EVENT_U0_INT_RAW (BIT(0)) -#define PCNT_CNT_THR_EVENT_U0_INT_RAW_M (BIT(0)) -#define PCNT_CNT_THR_EVENT_U0_INT_RAW_V 0x1 +/** PCNT_INT_RAW_REG register + * Interrupt raw status register + */ +#define PCNT_INT_RAW_REG (DR_REG_PCNT_BASE + 0x40) +/** PCNT_CNT_THR_EVENT_U0_INT_RAW : RO; bitpos: [0]; default: 0; + * The raw interrupt status bit for the PCNT_CNT_THR_EVENT_U0_INT interrupt. + */ +#define PCNT_CNT_THR_EVENT_U0_INT_RAW (BIT(0)) +#define PCNT_CNT_THR_EVENT_U0_INT_RAW_M (PCNT_CNT_THR_EVENT_U0_INT_RAW_V << PCNT_CNT_THR_EVENT_U0_INT_RAW_S) +#define PCNT_CNT_THR_EVENT_U0_INT_RAW_V 0x00000001U #define PCNT_CNT_THR_EVENT_U0_INT_RAW_S 0 +/** PCNT_CNT_THR_EVENT_U1_INT_RAW : RO; bitpos: [1]; default: 0; + * The raw interrupt status bit for the PCNT_CNT_THR_EVENT_U1_INT interrupt. + */ +#define PCNT_CNT_THR_EVENT_U1_INT_RAW (BIT(1)) +#define PCNT_CNT_THR_EVENT_U1_INT_RAW_M (PCNT_CNT_THR_EVENT_U1_INT_RAW_V << PCNT_CNT_THR_EVENT_U1_INT_RAW_S) +#define PCNT_CNT_THR_EVENT_U1_INT_RAW_V 0x00000001U +#define PCNT_CNT_THR_EVENT_U1_INT_RAW_S 1 +/** PCNT_CNT_THR_EVENT_U2_INT_RAW : RO; bitpos: [2]; default: 0; + * The raw interrupt status bit for the PCNT_CNT_THR_EVENT_U2_INT interrupt. + */ +#define PCNT_CNT_THR_EVENT_U2_INT_RAW (BIT(2)) +#define PCNT_CNT_THR_EVENT_U2_INT_RAW_M (PCNT_CNT_THR_EVENT_U2_INT_RAW_V << PCNT_CNT_THR_EVENT_U2_INT_RAW_S) +#define PCNT_CNT_THR_EVENT_U2_INT_RAW_V 0x00000001U +#define PCNT_CNT_THR_EVENT_U2_INT_RAW_S 2 +/** PCNT_CNT_THR_EVENT_U3_INT_RAW : RO; bitpos: [3]; default: 0; + * The raw interrupt status bit for the PCNT_CNT_THR_EVENT_U3_INT interrupt. + */ +#define PCNT_CNT_THR_EVENT_U3_INT_RAW (BIT(3)) +#define PCNT_CNT_THR_EVENT_U3_INT_RAW_M (PCNT_CNT_THR_EVENT_U3_INT_RAW_V << PCNT_CNT_THR_EVENT_U3_INT_RAW_S) +#define PCNT_CNT_THR_EVENT_U3_INT_RAW_V 0x00000001U +#define PCNT_CNT_THR_EVENT_U3_INT_RAW_S 3 -#define PCNT_INT_ST_REG (DR_REG_PCNT_BASE + 0x0044) -/* PCNT_CNT_THR_EVENT_U3_INT_ST : RO ;bitpos:[3] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_EVENT_U3_INT_ST (BIT(3)) -#define PCNT_CNT_THR_EVENT_U3_INT_ST_M (BIT(3)) -#define PCNT_CNT_THR_EVENT_U3_INT_ST_V 0x1 -#define PCNT_CNT_THR_EVENT_U3_INT_ST_S 3 -/* PCNT_CNT_THR_EVENT_U2_INT_ST : RO ;bitpos:[2] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_EVENT_U2_INT_ST (BIT(2)) -#define PCNT_CNT_THR_EVENT_U2_INT_ST_M (BIT(2)) -#define PCNT_CNT_THR_EVENT_U2_INT_ST_V 0x1 -#define PCNT_CNT_THR_EVENT_U2_INT_ST_S 2 -/* PCNT_CNT_THR_EVENT_U1_INT_ST : RO ;bitpos:[1] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_EVENT_U1_INT_ST (BIT(1)) -#define PCNT_CNT_THR_EVENT_U1_INT_ST_M (BIT(1)) -#define PCNT_CNT_THR_EVENT_U1_INT_ST_V 0x1 -#define PCNT_CNT_THR_EVENT_U1_INT_ST_S 1 -/* PCNT_CNT_THR_EVENT_U0_INT_ST : RO ;bitpos:[0] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_EVENT_U0_INT_ST (BIT(0)) -#define PCNT_CNT_THR_EVENT_U0_INT_ST_M (BIT(0)) -#define PCNT_CNT_THR_EVENT_U0_INT_ST_V 0x1 +/** PCNT_INT_ST_REG register + * Interrupt status register + */ +#define PCNT_INT_ST_REG (DR_REG_PCNT_BASE + 0x44) +/** PCNT_CNT_THR_EVENT_U0_INT_ST : RO; bitpos: [0]; default: 0; + * The masked interrupt status bit for the PCNT_CNT_THR_EVENT_U0_INT interrupt. + */ +#define PCNT_CNT_THR_EVENT_U0_INT_ST (BIT(0)) +#define PCNT_CNT_THR_EVENT_U0_INT_ST_M (PCNT_CNT_THR_EVENT_U0_INT_ST_V << PCNT_CNT_THR_EVENT_U0_INT_ST_S) +#define PCNT_CNT_THR_EVENT_U0_INT_ST_V 0x00000001U #define PCNT_CNT_THR_EVENT_U0_INT_ST_S 0 +/** PCNT_CNT_THR_EVENT_U1_INT_ST : RO; bitpos: [1]; default: 0; + * The masked interrupt status bit for the PCNT_CNT_THR_EVENT_U1_INT interrupt. + */ +#define PCNT_CNT_THR_EVENT_U1_INT_ST (BIT(1)) +#define PCNT_CNT_THR_EVENT_U1_INT_ST_M (PCNT_CNT_THR_EVENT_U1_INT_ST_V << PCNT_CNT_THR_EVENT_U1_INT_ST_S) +#define PCNT_CNT_THR_EVENT_U1_INT_ST_V 0x00000001U +#define PCNT_CNT_THR_EVENT_U1_INT_ST_S 1 +/** PCNT_CNT_THR_EVENT_U2_INT_ST : RO; bitpos: [2]; default: 0; + * The masked interrupt status bit for the PCNT_CNT_THR_EVENT_U2_INT interrupt. + */ +#define PCNT_CNT_THR_EVENT_U2_INT_ST (BIT(2)) +#define PCNT_CNT_THR_EVENT_U2_INT_ST_M (PCNT_CNT_THR_EVENT_U2_INT_ST_V << PCNT_CNT_THR_EVENT_U2_INT_ST_S) +#define PCNT_CNT_THR_EVENT_U2_INT_ST_V 0x00000001U +#define PCNT_CNT_THR_EVENT_U2_INT_ST_S 2 +/** PCNT_CNT_THR_EVENT_U3_INT_ST : RO; bitpos: [3]; default: 0; + * The masked interrupt status bit for the PCNT_CNT_THR_EVENT_U3_INT interrupt. + */ +#define PCNT_CNT_THR_EVENT_U3_INT_ST (BIT(3)) +#define PCNT_CNT_THR_EVENT_U3_INT_ST_M (PCNT_CNT_THR_EVENT_U3_INT_ST_V << PCNT_CNT_THR_EVENT_U3_INT_ST_S) +#define PCNT_CNT_THR_EVENT_U3_INT_ST_V 0x00000001U +#define PCNT_CNT_THR_EVENT_U3_INT_ST_S 3 -#define PCNT_INT_ENA_REG (DR_REG_PCNT_BASE + 0x0048) -/* PCNT_CNT_THR_EVENT_U3_INT_ENA : R/W ;bitpos:[3] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_EVENT_U3_INT_ENA (BIT(3)) -#define PCNT_CNT_THR_EVENT_U3_INT_ENA_M (BIT(3)) -#define PCNT_CNT_THR_EVENT_U3_INT_ENA_V 0x1 -#define PCNT_CNT_THR_EVENT_U3_INT_ENA_S 3 -/* PCNT_CNT_THR_EVENT_U2_INT_ENA : R/W ;bitpos:[2] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_EVENT_U2_INT_ENA (BIT(2)) -#define PCNT_CNT_THR_EVENT_U2_INT_ENA_M (BIT(2)) -#define PCNT_CNT_THR_EVENT_U2_INT_ENA_V 0x1 -#define PCNT_CNT_THR_EVENT_U2_INT_ENA_S 2 -/* PCNT_CNT_THR_EVENT_U1_INT_ENA : R/W ;bitpos:[1] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_EVENT_U1_INT_ENA (BIT(1)) -#define PCNT_CNT_THR_EVENT_U1_INT_ENA_M (BIT(1)) -#define PCNT_CNT_THR_EVENT_U1_INT_ENA_V 0x1 -#define PCNT_CNT_THR_EVENT_U1_INT_ENA_S 1 -/* PCNT_CNT_THR_EVENT_U0_INT_ENA : R/W ;bitpos:[0] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_EVENT_U0_INT_ENA (BIT(0)) -#define PCNT_CNT_THR_EVENT_U0_INT_ENA_M (BIT(0)) -#define PCNT_CNT_THR_EVENT_U0_INT_ENA_V 0x1 +/** PCNT_INT_ENA_REG register + * Interrupt enable register + */ +#define PCNT_INT_ENA_REG (DR_REG_PCNT_BASE + 0x48) +/** PCNT_CNT_THR_EVENT_U0_INT_ENA : R/W; bitpos: [0]; default: 0; + * The interrupt enable bit for the PCNT_CNT_THR_EVENT_U0_INT interrupt. + */ +#define PCNT_CNT_THR_EVENT_U0_INT_ENA (BIT(0)) +#define PCNT_CNT_THR_EVENT_U0_INT_ENA_M (PCNT_CNT_THR_EVENT_U0_INT_ENA_V << PCNT_CNT_THR_EVENT_U0_INT_ENA_S) +#define PCNT_CNT_THR_EVENT_U0_INT_ENA_V 0x00000001U #define PCNT_CNT_THR_EVENT_U0_INT_ENA_S 0 +/** PCNT_CNT_THR_EVENT_U1_INT_ENA : R/W; bitpos: [1]; default: 0; + * The interrupt enable bit for the PCNT_CNT_THR_EVENT_U1_INT interrupt. + */ +#define PCNT_CNT_THR_EVENT_U1_INT_ENA (BIT(1)) +#define PCNT_CNT_THR_EVENT_U1_INT_ENA_M (PCNT_CNT_THR_EVENT_U1_INT_ENA_V << PCNT_CNT_THR_EVENT_U1_INT_ENA_S) +#define PCNT_CNT_THR_EVENT_U1_INT_ENA_V 0x00000001U +#define PCNT_CNT_THR_EVENT_U1_INT_ENA_S 1 +/** PCNT_CNT_THR_EVENT_U2_INT_ENA : R/W; bitpos: [2]; default: 0; + * The interrupt enable bit for the PCNT_CNT_THR_EVENT_U2_INT interrupt. + */ +#define PCNT_CNT_THR_EVENT_U2_INT_ENA (BIT(2)) +#define PCNT_CNT_THR_EVENT_U2_INT_ENA_M (PCNT_CNT_THR_EVENT_U2_INT_ENA_V << PCNT_CNT_THR_EVENT_U2_INT_ENA_S) +#define PCNT_CNT_THR_EVENT_U2_INT_ENA_V 0x00000001U +#define PCNT_CNT_THR_EVENT_U2_INT_ENA_S 2 +/** PCNT_CNT_THR_EVENT_U3_INT_ENA : R/W; bitpos: [3]; default: 0; + * The interrupt enable bit for the PCNT_CNT_THR_EVENT_U3_INT interrupt. + */ +#define PCNT_CNT_THR_EVENT_U3_INT_ENA (BIT(3)) +#define PCNT_CNT_THR_EVENT_U3_INT_ENA_M (PCNT_CNT_THR_EVENT_U3_INT_ENA_V << PCNT_CNT_THR_EVENT_U3_INT_ENA_S) +#define PCNT_CNT_THR_EVENT_U3_INT_ENA_V 0x00000001U +#define PCNT_CNT_THR_EVENT_U3_INT_ENA_S 3 -#define PCNT_INT_CLR_REG (DR_REG_PCNT_BASE + 0x004c) -/* PCNT_CNT_THR_EVENT_U3_INT_CLR : WO ;bitpos:[3] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_EVENT_U3_INT_CLR (BIT(3)) -#define PCNT_CNT_THR_EVENT_U3_INT_CLR_M (BIT(3)) -#define PCNT_CNT_THR_EVENT_U3_INT_CLR_V 0x1 -#define PCNT_CNT_THR_EVENT_U3_INT_CLR_S 3 -/* PCNT_CNT_THR_EVENT_U2_INT_CLR : WO ;bitpos:[2] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_EVENT_U2_INT_CLR (BIT(2)) -#define PCNT_CNT_THR_EVENT_U2_INT_CLR_M (BIT(2)) -#define PCNT_CNT_THR_EVENT_U2_INT_CLR_V 0x1 -#define PCNT_CNT_THR_EVENT_U2_INT_CLR_S 2 -/* PCNT_CNT_THR_EVENT_U1_INT_CLR : WO ;bitpos:[1] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_EVENT_U1_INT_CLR (BIT(1)) -#define PCNT_CNT_THR_EVENT_U1_INT_CLR_M (BIT(1)) -#define PCNT_CNT_THR_EVENT_U1_INT_CLR_V 0x1 -#define PCNT_CNT_THR_EVENT_U1_INT_CLR_S 1 -/* PCNT_CNT_THR_EVENT_U0_INT_CLR : WO ;bitpos:[0] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_EVENT_U0_INT_CLR (BIT(0)) -#define PCNT_CNT_THR_EVENT_U0_INT_CLR_M (BIT(0)) -#define PCNT_CNT_THR_EVENT_U0_INT_CLR_V 0x1 +/** PCNT_INT_CLR_REG register + * Interrupt clear register + */ +#define PCNT_INT_CLR_REG (DR_REG_PCNT_BASE + 0x4c) +/** PCNT_CNT_THR_EVENT_U0_INT_CLR : WO; bitpos: [0]; default: 0; + * Set this bit to clear the PCNT_CNT_THR_EVENT_U0_INT interrupt. + */ +#define PCNT_CNT_THR_EVENT_U0_INT_CLR (BIT(0)) +#define PCNT_CNT_THR_EVENT_U0_INT_CLR_M (PCNT_CNT_THR_EVENT_U0_INT_CLR_V << PCNT_CNT_THR_EVENT_U0_INT_CLR_S) +#define PCNT_CNT_THR_EVENT_U0_INT_CLR_V 0x00000001U #define PCNT_CNT_THR_EVENT_U0_INT_CLR_S 0 +/** PCNT_CNT_THR_EVENT_U1_INT_CLR : WO; bitpos: [1]; default: 0; + * Set this bit to clear the PCNT_CNT_THR_EVENT_U1_INT interrupt. + */ +#define PCNT_CNT_THR_EVENT_U1_INT_CLR (BIT(1)) +#define PCNT_CNT_THR_EVENT_U1_INT_CLR_M (PCNT_CNT_THR_EVENT_U1_INT_CLR_V << PCNT_CNT_THR_EVENT_U1_INT_CLR_S) +#define PCNT_CNT_THR_EVENT_U1_INT_CLR_V 0x00000001U +#define PCNT_CNT_THR_EVENT_U1_INT_CLR_S 1 +/** PCNT_CNT_THR_EVENT_U2_INT_CLR : WO; bitpos: [2]; default: 0; + * Set this bit to clear the PCNT_CNT_THR_EVENT_U2_INT interrupt. + */ +#define PCNT_CNT_THR_EVENT_U2_INT_CLR (BIT(2)) +#define PCNT_CNT_THR_EVENT_U2_INT_CLR_M (PCNT_CNT_THR_EVENT_U2_INT_CLR_V << PCNT_CNT_THR_EVENT_U2_INT_CLR_S) +#define PCNT_CNT_THR_EVENT_U2_INT_CLR_V 0x00000001U +#define PCNT_CNT_THR_EVENT_U2_INT_CLR_S 2 +/** PCNT_CNT_THR_EVENT_U3_INT_CLR : WO; bitpos: [3]; default: 0; + * Set this bit to clear the PCNT_CNT_THR_EVENT_U3_INT interrupt. + */ +#define PCNT_CNT_THR_EVENT_U3_INT_CLR (BIT(3)) +#define PCNT_CNT_THR_EVENT_U3_INT_CLR_M (PCNT_CNT_THR_EVENT_U3_INT_CLR_V << PCNT_CNT_THR_EVENT_U3_INT_CLR_S) +#define PCNT_CNT_THR_EVENT_U3_INT_CLR_V 0x00000001U +#define PCNT_CNT_THR_EVENT_U3_INT_CLR_S 3 -#define PCNT_U0_STATUS_REG (DR_REG_PCNT_BASE + 0x0050) -/* PCNT_CNT_THR_ZERO_LAT_U0 : RO ;bitpos:[6] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_ZERO_LAT_U0 (BIT(6)) -#define PCNT_CNT_THR_ZERO_LAT_U0_M (BIT(6)) -#define PCNT_CNT_THR_ZERO_LAT_U0_V 0x1 -#define PCNT_CNT_THR_ZERO_LAT_U0_S 6 -/* PCNT_CNT_THR_H_LIM_LAT_U0 : RO ;bitpos:[5] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_H_LIM_LAT_U0 (BIT(5)) -#define PCNT_CNT_THR_H_LIM_LAT_U0_M (BIT(5)) -#define PCNT_CNT_THR_H_LIM_LAT_U0_V 0x1 -#define PCNT_CNT_THR_H_LIM_LAT_U0_S 5 -/* PCNT_CNT_THR_L_LIM_LAT_U0 : RO ;bitpos:[4] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_L_LIM_LAT_U0 (BIT(4)) -#define PCNT_CNT_THR_L_LIM_LAT_U0_M (BIT(4)) -#define PCNT_CNT_THR_L_LIM_LAT_U0_V 0x1 -#define PCNT_CNT_THR_L_LIM_LAT_U0_S 4 -/* PCNT_CNT_THR_THRES0_LAT_U0 : RO ;bitpos:[3] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_THRES0_LAT_U0 (BIT(3)) -#define PCNT_CNT_THR_THRES0_LAT_U0_M (BIT(3)) -#define PCNT_CNT_THR_THRES0_LAT_U0_V 0x1 -#define PCNT_CNT_THR_THRES0_LAT_U0_S 3 -/* PCNT_CNT_THR_THRES1_LAT_U0 : RO ;bitpos:[2] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_THRES1_LAT_U0 (BIT(2)) -#define PCNT_CNT_THR_THRES1_LAT_U0_M (BIT(2)) -#define PCNT_CNT_THR_THRES1_LAT_U0_V 0x1 -#define PCNT_CNT_THR_THRES1_LAT_U0_S 2 -/* PCNT_CNT_THR_ZERO_MODE_U0 : RO ;bitpos:[1:0] ;default: 2'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_ZERO_MODE_U0 0x00000003 -#define PCNT_CNT_THR_ZERO_MODE_U0_M ((PCNT_CNT_THR_ZERO_MODE_U0_V)<<(PCNT_CNT_THR_ZERO_MODE_U0_S)) -#define PCNT_CNT_THR_ZERO_MODE_U0_V 0x3 +/** PCNT_U0_STATUS_REG register + * PNCT UNIT0 status register + */ +#define PCNT_U0_STATUS_REG (DR_REG_PCNT_BASE + 0x50) +/** PCNT_CNT_THR_ZERO_MODE_U0 : RO; bitpos: [1:0]; default: 0; + * The pulse counter status of PCNT_U0 corresponding to 0. 0: pulse counter decreases + * from positive to 0. 1: pulse counter increases from negative to 0. 2: pulse counter + * is negative. 3: pulse counter is positive. + */ +#define PCNT_CNT_THR_ZERO_MODE_U0 0x00000003U +#define PCNT_CNT_THR_ZERO_MODE_U0_M (PCNT_CNT_THR_ZERO_MODE_U0_V << PCNT_CNT_THR_ZERO_MODE_U0_S) +#define PCNT_CNT_THR_ZERO_MODE_U0_V 0x00000003U #define PCNT_CNT_THR_ZERO_MODE_U0_S 0 +/** PCNT_CNT_THR_THRES1_LAT_U0 : RO; bitpos: [2]; default: 0; + * The latched value of thres1 event of PCNT_U0 when threshold event interrupt is + * valid. 1: the current pulse counter equals to thres1 and thres1 event is valid. 0: + * others + */ +#define PCNT_CNT_THR_THRES1_LAT_U0 (BIT(2)) +#define PCNT_CNT_THR_THRES1_LAT_U0_M (PCNT_CNT_THR_THRES1_LAT_U0_V << PCNT_CNT_THR_THRES1_LAT_U0_S) +#define PCNT_CNT_THR_THRES1_LAT_U0_V 0x00000001U +#define PCNT_CNT_THR_THRES1_LAT_U0_S 2 +/** PCNT_CNT_THR_THRES0_LAT_U0 : RO; bitpos: [3]; default: 0; + * The latched value of thres0 event of PCNT_U0 when threshold event interrupt is + * valid. 1: the current pulse counter equals to thres0 and thres0 event is valid. 0: + * others + */ +#define PCNT_CNT_THR_THRES0_LAT_U0 (BIT(3)) +#define PCNT_CNT_THR_THRES0_LAT_U0_M (PCNT_CNT_THR_THRES0_LAT_U0_V << PCNT_CNT_THR_THRES0_LAT_U0_S) +#define PCNT_CNT_THR_THRES0_LAT_U0_V 0x00000001U +#define PCNT_CNT_THR_THRES0_LAT_U0_S 3 +/** PCNT_CNT_THR_L_LIM_LAT_U0 : RO; bitpos: [4]; default: 0; + * The latched value of low limit event of PCNT_U0 when threshold event interrupt is + * valid. 1: the current pulse counter equals to thr_l_lim and low limit event is + * valid. 0: others + */ +#define PCNT_CNT_THR_L_LIM_LAT_U0 (BIT(4)) +#define PCNT_CNT_THR_L_LIM_LAT_U0_M (PCNT_CNT_THR_L_LIM_LAT_U0_V << PCNT_CNT_THR_L_LIM_LAT_U0_S) +#define PCNT_CNT_THR_L_LIM_LAT_U0_V 0x00000001U +#define PCNT_CNT_THR_L_LIM_LAT_U0_S 4 +/** PCNT_CNT_THR_H_LIM_LAT_U0 : RO; bitpos: [5]; default: 0; + * The latched value of high limit event of PCNT_U0 when threshold event interrupt is + * valid. 1: the current pulse counter equals to thr_h_lim and high limit event is + * valid. 0: others + */ +#define PCNT_CNT_THR_H_LIM_LAT_U0 (BIT(5)) +#define PCNT_CNT_THR_H_LIM_LAT_U0_M (PCNT_CNT_THR_H_LIM_LAT_U0_V << PCNT_CNT_THR_H_LIM_LAT_U0_S) +#define PCNT_CNT_THR_H_LIM_LAT_U0_V 0x00000001U +#define PCNT_CNT_THR_H_LIM_LAT_U0_S 5 +/** PCNT_CNT_THR_ZERO_LAT_U0 : RO; bitpos: [6]; default: 0; + * The latched value of zero threshold event of PCNT_U0 when threshold event interrupt + * is valid. 1: the current pulse counter equals to 0 and zero threshold event is + * valid. 0: others + */ +#define PCNT_CNT_THR_ZERO_LAT_U0 (BIT(6)) +#define PCNT_CNT_THR_ZERO_LAT_U0_M (PCNT_CNT_THR_ZERO_LAT_U0_V << PCNT_CNT_THR_ZERO_LAT_U0_S) +#define PCNT_CNT_THR_ZERO_LAT_U0_V 0x00000001U +#define PCNT_CNT_THR_ZERO_LAT_U0_S 6 -#define PCNT_U1_STATUS_REG (DR_REG_PCNT_BASE + 0x0054) -/* PCNT_CNT_THR_ZERO_LAT_U1 : RO ;bitpos:[6] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_ZERO_LAT_U1 (BIT(6)) -#define PCNT_CNT_THR_ZERO_LAT_U1_M (BIT(6)) -#define PCNT_CNT_THR_ZERO_LAT_U1_V 0x1 -#define PCNT_CNT_THR_ZERO_LAT_U1_S 6 -/* PCNT_CNT_THR_H_LIM_LAT_U1 : RO ;bitpos:[5] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_H_LIM_LAT_U1 (BIT(5)) -#define PCNT_CNT_THR_H_LIM_LAT_U1_M (BIT(5)) -#define PCNT_CNT_THR_H_LIM_LAT_U1_V 0x1 -#define PCNT_CNT_THR_H_LIM_LAT_U1_S 5 -/* PCNT_CNT_THR_L_LIM_LAT_U1 : RO ;bitpos:[4] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_L_LIM_LAT_U1 (BIT(4)) -#define PCNT_CNT_THR_L_LIM_LAT_U1_M (BIT(4)) -#define PCNT_CNT_THR_L_LIM_LAT_U1_V 0x1 -#define PCNT_CNT_THR_L_LIM_LAT_U1_S 4 -/* PCNT_CNT_THR_THRES0_LAT_U1 : RO ;bitpos:[3] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_THRES0_LAT_U1 (BIT(3)) -#define PCNT_CNT_THR_THRES0_LAT_U1_M (BIT(3)) -#define PCNT_CNT_THR_THRES0_LAT_U1_V 0x1 -#define PCNT_CNT_THR_THRES0_LAT_U1_S 3 -/* PCNT_CNT_THR_THRES1_LAT_U1 : RO ;bitpos:[2] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_THRES1_LAT_U1 (BIT(2)) -#define PCNT_CNT_THR_THRES1_LAT_U1_M (BIT(2)) -#define PCNT_CNT_THR_THRES1_LAT_U1_V 0x1 -#define PCNT_CNT_THR_THRES1_LAT_U1_S 2 -/* PCNT_CNT_THR_ZERO_MODE_U1 : RO ;bitpos:[1:0] ;default: 2'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_ZERO_MODE_U1 0x00000003 -#define PCNT_CNT_THR_ZERO_MODE_U1_M ((PCNT_CNT_THR_ZERO_MODE_U1_V)<<(PCNT_CNT_THR_ZERO_MODE_U1_S)) -#define PCNT_CNT_THR_ZERO_MODE_U1_V 0x3 +/** PCNT_U1_STATUS_REG register + * PNCT UNIT1 status register + */ +#define PCNT_U1_STATUS_REG (DR_REG_PCNT_BASE + 0x54) +/** PCNT_CNT_THR_ZERO_MODE_U1 : RO; bitpos: [1:0]; default: 0; + * The pulse counter status of PCNT_U1 corresponding to 0. 0: pulse counter decreases + * from positive to 0. 1: pulse counter increases from negative to 0. 2: pulse counter + * is negative. 3: pulse counter is positive. + */ +#define PCNT_CNT_THR_ZERO_MODE_U1 0x00000003U +#define PCNT_CNT_THR_ZERO_MODE_U1_M (PCNT_CNT_THR_ZERO_MODE_U1_V << PCNT_CNT_THR_ZERO_MODE_U1_S) +#define PCNT_CNT_THR_ZERO_MODE_U1_V 0x00000003U #define PCNT_CNT_THR_ZERO_MODE_U1_S 0 +/** PCNT_CNT_THR_THRES1_LAT_U1 : RO; bitpos: [2]; default: 0; + * The latched value of thres1 event of PCNT_U1 when threshold event interrupt is + * valid. 1: the current pulse counter equals to thres1 and thres1 event is valid. 0: + * others + */ +#define PCNT_CNT_THR_THRES1_LAT_U1 (BIT(2)) +#define PCNT_CNT_THR_THRES1_LAT_U1_M (PCNT_CNT_THR_THRES1_LAT_U1_V << PCNT_CNT_THR_THRES1_LAT_U1_S) +#define PCNT_CNT_THR_THRES1_LAT_U1_V 0x00000001U +#define PCNT_CNT_THR_THRES1_LAT_U1_S 2 +/** PCNT_CNT_THR_THRES0_LAT_U1 : RO; bitpos: [3]; default: 0; + * The latched value of thres0 event of PCNT_U1 when threshold event interrupt is + * valid. 1: the current pulse counter equals to thres0 and thres0 event is valid. 0: + * others + */ +#define PCNT_CNT_THR_THRES0_LAT_U1 (BIT(3)) +#define PCNT_CNT_THR_THRES0_LAT_U1_M (PCNT_CNT_THR_THRES0_LAT_U1_V << PCNT_CNT_THR_THRES0_LAT_U1_S) +#define PCNT_CNT_THR_THRES0_LAT_U1_V 0x00000001U +#define PCNT_CNT_THR_THRES0_LAT_U1_S 3 +/** PCNT_CNT_THR_L_LIM_LAT_U1 : RO; bitpos: [4]; default: 0; + * The latched value of low limit event of PCNT_U1 when threshold event interrupt is + * valid. 1: the current pulse counter equals to thr_l_lim and low limit event is + * valid. 0: others + */ +#define PCNT_CNT_THR_L_LIM_LAT_U1 (BIT(4)) +#define PCNT_CNT_THR_L_LIM_LAT_U1_M (PCNT_CNT_THR_L_LIM_LAT_U1_V << PCNT_CNT_THR_L_LIM_LAT_U1_S) +#define PCNT_CNT_THR_L_LIM_LAT_U1_V 0x00000001U +#define PCNT_CNT_THR_L_LIM_LAT_U1_S 4 +/** PCNT_CNT_THR_H_LIM_LAT_U1 : RO; bitpos: [5]; default: 0; + * The latched value of high limit event of PCNT_U1 when threshold event interrupt is + * valid. 1: the current pulse counter equals to thr_h_lim and high limit event is + * valid. 0: others + */ +#define PCNT_CNT_THR_H_LIM_LAT_U1 (BIT(5)) +#define PCNT_CNT_THR_H_LIM_LAT_U1_M (PCNT_CNT_THR_H_LIM_LAT_U1_V << PCNT_CNT_THR_H_LIM_LAT_U1_S) +#define PCNT_CNT_THR_H_LIM_LAT_U1_V 0x00000001U +#define PCNT_CNT_THR_H_LIM_LAT_U1_S 5 +/** PCNT_CNT_THR_ZERO_LAT_U1 : RO; bitpos: [6]; default: 0; + * The latched value of zero threshold event of PCNT_U1 when threshold event interrupt + * is valid. 1: the current pulse counter equals to 0 and zero threshold event is + * valid. 0: others + */ +#define PCNT_CNT_THR_ZERO_LAT_U1 (BIT(6)) +#define PCNT_CNT_THR_ZERO_LAT_U1_M (PCNT_CNT_THR_ZERO_LAT_U1_V << PCNT_CNT_THR_ZERO_LAT_U1_S) +#define PCNT_CNT_THR_ZERO_LAT_U1_V 0x00000001U +#define PCNT_CNT_THR_ZERO_LAT_U1_S 6 -#define PCNT_U2_STATUS_REG (DR_REG_PCNT_BASE + 0x0058) -/* PCNT_CNT_THR_ZERO_LAT_U2 : RO ;bitpos:[6] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_ZERO_LAT_U2 (BIT(6)) -#define PCNT_CNT_THR_ZERO_LAT_U2_M (BIT(6)) -#define PCNT_CNT_THR_ZERO_LAT_U2_V 0x1 -#define PCNT_CNT_THR_ZERO_LAT_U2_S 6 -/* PCNT_CNT_THR_H_LIM_LAT_U2 : RO ;bitpos:[5] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_H_LIM_LAT_U2 (BIT(5)) -#define PCNT_CNT_THR_H_LIM_LAT_U2_M (BIT(5)) -#define PCNT_CNT_THR_H_LIM_LAT_U2_V 0x1 -#define PCNT_CNT_THR_H_LIM_LAT_U2_S 5 -/* PCNT_CNT_THR_L_LIM_LAT_U2 : RO ;bitpos:[4] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_L_LIM_LAT_U2 (BIT(4)) -#define PCNT_CNT_THR_L_LIM_LAT_U2_M (BIT(4)) -#define PCNT_CNT_THR_L_LIM_LAT_U2_V 0x1 -#define PCNT_CNT_THR_L_LIM_LAT_U2_S 4 -/* PCNT_CNT_THR_THRES0_LAT_U2 : RO ;bitpos:[3] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_THRES0_LAT_U2 (BIT(3)) -#define PCNT_CNT_THR_THRES0_LAT_U2_M (BIT(3)) -#define PCNT_CNT_THR_THRES0_LAT_U2_V 0x1 -#define PCNT_CNT_THR_THRES0_LAT_U2_S 3 -/* PCNT_CNT_THR_THRES1_LAT_U2 : RO ;bitpos:[2] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_THRES1_LAT_U2 (BIT(2)) -#define PCNT_CNT_THR_THRES1_LAT_U2_M (BIT(2)) -#define PCNT_CNT_THR_THRES1_LAT_U2_V 0x1 -#define PCNT_CNT_THR_THRES1_LAT_U2_S 2 -/* PCNT_CNT_THR_ZERO_MODE_U2 : RO ;bitpos:[1:0] ;default: 2'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_ZERO_MODE_U2 0x00000003 -#define PCNT_CNT_THR_ZERO_MODE_U2_M ((PCNT_CNT_THR_ZERO_MODE_U2_V)<<(PCNT_CNT_THR_ZERO_MODE_U2_S)) -#define PCNT_CNT_THR_ZERO_MODE_U2_V 0x3 +/** PCNT_U2_STATUS_REG register + * PNCT UNIT2 status register + */ +#define PCNT_U2_STATUS_REG (DR_REG_PCNT_BASE + 0x58) +/** PCNT_CNT_THR_ZERO_MODE_U2 : RO; bitpos: [1:0]; default: 0; + * The pulse counter status of PCNT_U2 corresponding to 0. 0: pulse counter decreases + * from positive to 0. 1: pulse counter increases from negative to 0. 2: pulse counter + * is negative. 3: pulse counter is positive. + */ +#define PCNT_CNT_THR_ZERO_MODE_U2 0x00000003U +#define PCNT_CNT_THR_ZERO_MODE_U2_M (PCNT_CNT_THR_ZERO_MODE_U2_V << PCNT_CNT_THR_ZERO_MODE_U2_S) +#define PCNT_CNT_THR_ZERO_MODE_U2_V 0x00000003U #define PCNT_CNT_THR_ZERO_MODE_U2_S 0 +/** PCNT_CNT_THR_THRES1_LAT_U2 : RO; bitpos: [2]; default: 0; + * The latched value of thres1 event of PCNT_U2 when threshold event interrupt is + * valid. 1: the current pulse counter equals to thres1 and thres1 event is valid. 0: + * others + */ +#define PCNT_CNT_THR_THRES1_LAT_U2 (BIT(2)) +#define PCNT_CNT_THR_THRES1_LAT_U2_M (PCNT_CNT_THR_THRES1_LAT_U2_V << PCNT_CNT_THR_THRES1_LAT_U2_S) +#define PCNT_CNT_THR_THRES1_LAT_U2_V 0x00000001U +#define PCNT_CNT_THR_THRES1_LAT_U2_S 2 +/** PCNT_CNT_THR_THRES0_LAT_U2 : RO; bitpos: [3]; default: 0; + * The latched value of thres0 event of PCNT_U2 when threshold event interrupt is + * valid. 1: the current pulse counter equals to thres0 and thres0 event is valid. 0: + * others + */ +#define PCNT_CNT_THR_THRES0_LAT_U2 (BIT(3)) +#define PCNT_CNT_THR_THRES0_LAT_U2_M (PCNT_CNT_THR_THRES0_LAT_U2_V << PCNT_CNT_THR_THRES0_LAT_U2_S) +#define PCNT_CNT_THR_THRES0_LAT_U2_V 0x00000001U +#define PCNT_CNT_THR_THRES0_LAT_U2_S 3 +/** PCNT_CNT_THR_L_LIM_LAT_U2 : RO; bitpos: [4]; default: 0; + * The latched value of low limit event of PCNT_U2 when threshold event interrupt is + * valid. 1: the current pulse counter equals to thr_l_lim and low limit event is + * valid. 0: others + */ +#define PCNT_CNT_THR_L_LIM_LAT_U2 (BIT(4)) +#define PCNT_CNT_THR_L_LIM_LAT_U2_M (PCNT_CNT_THR_L_LIM_LAT_U2_V << PCNT_CNT_THR_L_LIM_LAT_U2_S) +#define PCNT_CNT_THR_L_LIM_LAT_U2_V 0x00000001U +#define PCNT_CNT_THR_L_LIM_LAT_U2_S 4 +/** PCNT_CNT_THR_H_LIM_LAT_U2 : RO; bitpos: [5]; default: 0; + * The latched value of high limit event of PCNT_U2 when threshold event interrupt is + * valid. 1: the current pulse counter equals to thr_h_lim and high limit event is + * valid. 0: others + */ +#define PCNT_CNT_THR_H_LIM_LAT_U2 (BIT(5)) +#define PCNT_CNT_THR_H_LIM_LAT_U2_M (PCNT_CNT_THR_H_LIM_LAT_U2_V << PCNT_CNT_THR_H_LIM_LAT_U2_S) +#define PCNT_CNT_THR_H_LIM_LAT_U2_V 0x00000001U +#define PCNT_CNT_THR_H_LIM_LAT_U2_S 5 +/** PCNT_CNT_THR_ZERO_LAT_U2 : RO; bitpos: [6]; default: 0; + * The latched value of zero threshold event of PCNT_U2 when threshold event interrupt + * is valid. 1: the current pulse counter equals to 0 and zero threshold event is + * valid. 0: others + */ +#define PCNT_CNT_THR_ZERO_LAT_U2 (BIT(6)) +#define PCNT_CNT_THR_ZERO_LAT_U2_M (PCNT_CNT_THR_ZERO_LAT_U2_V << PCNT_CNT_THR_ZERO_LAT_U2_S) +#define PCNT_CNT_THR_ZERO_LAT_U2_V 0x00000001U +#define PCNT_CNT_THR_ZERO_LAT_U2_S 6 -#define PCNT_U3_STATUS_REG (DR_REG_PCNT_BASE + 0x005c) -/* PCNT_CNT_THR_ZERO_LAT_U3 : RO ;bitpos:[6] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_ZERO_LAT_U3 (BIT(6)) -#define PCNT_CNT_THR_ZERO_LAT_U3_M (BIT(6)) -#define PCNT_CNT_THR_ZERO_LAT_U3_V 0x1 -#define PCNT_CNT_THR_ZERO_LAT_U3_S 6 -/* PCNT_CNT_THR_H_LIM_LAT_U3 : RO ;bitpos:[5] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_H_LIM_LAT_U3 (BIT(5)) -#define PCNT_CNT_THR_H_LIM_LAT_U3_M (BIT(5)) -#define PCNT_CNT_THR_H_LIM_LAT_U3_V 0x1 -#define PCNT_CNT_THR_H_LIM_LAT_U3_S 5 -/* PCNT_CNT_THR_L_LIM_LAT_U3 : RO ;bitpos:[4] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_L_LIM_LAT_U3 (BIT(4)) -#define PCNT_CNT_THR_L_LIM_LAT_U3_M (BIT(4)) -#define PCNT_CNT_THR_L_LIM_LAT_U3_V 0x1 -#define PCNT_CNT_THR_L_LIM_LAT_U3_S 4 -/* PCNT_CNT_THR_THRES0_LAT_U3 : RO ;bitpos:[3] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_THRES0_LAT_U3 (BIT(3)) -#define PCNT_CNT_THR_THRES0_LAT_U3_M (BIT(3)) -#define PCNT_CNT_THR_THRES0_LAT_U3_V 0x1 -#define PCNT_CNT_THR_THRES0_LAT_U3_S 3 -/* PCNT_CNT_THR_THRES1_LAT_U3 : RO ;bitpos:[2] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_THRES1_LAT_U3 (BIT(2)) -#define PCNT_CNT_THR_THRES1_LAT_U3_M (BIT(2)) -#define PCNT_CNT_THR_THRES1_LAT_U3_V 0x1 -#define PCNT_CNT_THR_THRES1_LAT_U3_S 2 -/* PCNT_CNT_THR_ZERO_MODE_U3 : RO ;bitpos:[1:0] ;default: 2'b0 ; */ -/*description: */ -#define PCNT_CNT_THR_ZERO_MODE_U3 0x00000003 -#define PCNT_CNT_THR_ZERO_MODE_U3_M ((PCNT_CNT_THR_ZERO_MODE_U3_V)<<(PCNT_CNT_THR_ZERO_MODE_U3_S)) -#define PCNT_CNT_THR_ZERO_MODE_U3_V 0x3 +/** PCNT_U3_STATUS_REG register + * PNCT UNIT3 status register + */ +#define PCNT_U3_STATUS_REG (DR_REG_PCNT_BASE + 0x5c) +/** PCNT_CNT_THR_ZERO_MODE_U3 : RO; bitpos: [1:0]; default: 0; + * The pulse counter status of PCNT_U3 corresponding to 0. 0: pulse counter decreases + * from positive to 0. 1: pulse counter increases from negative to 0. 2: pulse counter + * is negative. 3: pulse counter is positive. + */ +#define PCNT_CNT_THR_ZERO_MODE_U3 0x00000003U +#define PCNT_CNT_THR_ZERO_MODE_U3_M (PCNT_CNT_THR_ZERO_MODE_U3_V << PCNT_CNT_THR_ZERO_MODE_U3_S) +#define PCNT_CNT_THR_ZERO_MODE_U3_V 0x00000003U #define PCNT_CNT_THR_ZERO_MODE_U3_S 0 +/** PCNT_CNT_THR_THRES1_LAT_U3 : RO; bitpos: [2]; default: 0; + * The latched value of thres1 event of PCNT_U3 when threshold event interrupt is + * valid. 1: the current pulse counter equals to thres1 and thres1 event is valid. 0: + * others + */ +#define PCNT_CNT_THR_THRES1_LAT_U3 (BIT(2)) +#define PCNT_CNT_THR_THRES1_LAT_U3_M (PCNT_CNT_THR_THRES1_LAT_U3_V << PCNT_CNT_THR_THRES1_LAT_U3_S) +#define PCNT_CNT_THR_THRES1_LAT_U3_V 0x00000001U +#define PCNT_CNT_THR_THRES1_LAT_U3_S 2 +/** PCNT_CNT_THR_THRES0_LAT_U3 : RO; bitpos: [3]; default: 0; + * The latched value of thres0 event of PCNT_U3 when threshold event interrupt is + * valid. 1: the current pulse counter equals to thres0 and thres0 event is valid. 0: + * others + */ +#define PCNT_CNT_THR_THRES0_LAT_U3 (BIT(3)) +#define PCNT_CNT_THR_THRES0_LAT_U3_M (PCNT_CNT_THR_THRES0_LAT_U3_V << PCNT_CNT_THR_THRES0_LAT_U3_S) +#define PCNT_CNT_THR_THRES0_LAT_U3_V 0x00000001U +#define PCNT_CNT_THR_THRES0_LAT_U3_S 3 +/** PCNT_CNT_THR_L_LIM_LAT_U3 : RO; bitpos: [4]; default: 0; + * The latched value of low limit event of PCNT_U3 when threshold event interrupt is + * valid. 1: the current pulse counter equals to thr_l_lim and low limit event is + * valid. 0: others + */ +#define PCNT_CNT_THR_L_LIM_LAT_U3 (BIT(4)) +#define PCNT_CNT_THR_L_LIM_LAT_U3_M (PCNT_CNT_THR_L_LIM_LAT_U3_V << PCNT_CNT_THR_L_LIM_LAT_U3_S) +#define PCNT_CNT_THR_L_LIM_LAT_U3_V 0x00000001U +#define PCNT_CNT_THR_L_LIM_LAT_U3_S 4 +/** PCNT_CNT_THR_H_LIM_LAT_U3 : RO; bitpos: [5]; default: 0; + * The latched value of high limit event of PCNT_U3 when threshold event interrupt is + * valid. 1: the current pulse counter equals to thr_h_lim and high limit event is + * valid. 0: others + */ +#define PCNT_CNT_THR_H_LIM_LAT_U3 (BIT(5)) +#define PCNT_CNT_THR_H_LIM_LAT_U3_M (PCNT_CNT_THR_H_LIM_LAT_U3_V << PCNT_CNT_THR_H_LIM_LAT_U3_S) +#define PCNT_CNT_THR_H_LIM_LAT_U3_V 0x00000001U +#define PCNT_CNT_THR_H_LIM_LAT_U3_S 5 +/** PCNT_CNT_THR_ZERO_LAT_U3 : RO; bitpos: [6]; default: 0; + * The latched value of zero threshold event of PCNT_U3 when threshold event interrupt + * is valid. 1: the current pulse counter equals to 0 and zero threshold event is + * valid. 0: others + */ +#define PCNT_CNT_THR_ZERO_LAT_U3 (BIT(6)) +#define PCNT_CNT_THR_ZERO_LAT_U3_M (PCNT_CNT_THR_ZERO_LAT_U3_V << PCNT_CNT_THR_ZERO_LAT_U3_S) +#define PCNT_CNT_THR_ZERO_LAT_U3_V 0x00000001U +#define PCNT_CNT_THR_ZERO_LAT_U3_S 6 -#define PCNT_CTRL_REG (DR_REG_PCNT_BASE + 0x0060) -/* PCNT_CLK_EN : R/W ;bitpos:[16] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CLK_EN (BIT(16)) -#define PCNT_CLK_EN_M (BIT(16)) -#define PCNT_CLK_EN_V 0x1 -#define PCNT_CLK_EN_S 16 -/* PCNT_CNT_PAUSE_U3 : R/W ;bitpos:[7] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_PAUSE_U3 (BIT(7)) -#define PCNT_CNT_PAUSE_U3_M (BIT(7)) -#define PCNT_CNT_PAUSE_U3_V 0x1 -#define PCNT_CNT_PAUSE_U3_S 7 -/* PCNT_PULSE_CNT_RST_U3 : R/W ;bitpos:[6] ;default: 1'b1 ; */ -/*description: */ -#define PCNT_PULSE_CNT_RST_U3 (BIT(6)) -#define PCNT_PULSE_CNT_RST_U3_M (BIT(6)) -#define PCNT_PULSE_CNT_RST_U3_V 0x1 -#define PCNT_PULSE_CNT_RST_U3_S 6 -/* PCNT_CNT_PAUSE_U2 : R/W ;bitpos:[5] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_PAUSE_U2 (BIT(5)) -#define PCNT_CNT_PAUSE_U2_M (BIT(5)) -#define PCNT_CNT_PAUSE_U2_V 0x1 -#define PCNT_CNT_PAUSE_U2_S 5 -/* PCNT_PULSE_CNT_RST_U2 : R/W ;bitpos:[4] ;default: 1'b1 ; */ -/*description: */ -#define PCNT_PULSE_CNT_RST_U2 (BIT(4)) -#define PCNT_PULSE_CNT_RST_U2_M (BIT(4)) -#define PCNT_PULSE_CNT_RST_U2_V 0x1 -#define PCNT_PULSE_CNT_RST_U2_S 4 -/* PCNT_CNT_PAUSE_U1 : R/W ;bitpos:[3] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_PAUSE_U1 (BIT(3)) -#define PCNT_CNT_PAUSE_U1_M (BIT(3)) -#define PCNT_CNT_PAUSE_U1_V 0x1 -#define PCNT_CNT_PAUSE_U1_S 3 -/* PCNT_PULSE_CNT_RST_U1 : R/W ;bitpos:[2] ;default: 1'b1 ; */ -/*description: */ -#define PCNT_PULSE_CNT_RST_U1 (BIT(2)) -#define PCNT_PULSE_CNT_RST_U1_M (BIT(2)) -#define PCNT_PULSE_CNT_RST_U1_V 0x1 -#define PCNT_PULSE_CNT_RST_U1_S 2 -/* PCNT_CNT_PAUSE_U0 : R/W ;bitpos:[1] ;default: 1'b0 ; */ -/*description: */ -#define PCNT_CNT_PAUSE_U0 (BIT(1)) -#define PCNT_CNT_PAUSE_U0_M (BIT(1)) -#define PCNT_CNT_PAUSE_U0_V 0x1 -#define PCNT_CNT_PAUSE_U0_S 1 -/* PCNT_PULSE_CNT_RST_U0 : R/W ;bitpos:[0] ;default: 1'b1 ; */ -/*description: */ -#define PCNT_PULSE_CNT_RST_U0 (BIT(0)) -#define PCNT_PULSE_CNT_RST_U0_M (BIT(0)) -#define PCNT_PULSE_CNT_RST_U0_V 0x1 +/** PCNT_CTRL_REG register + * Control register for all counters + */ +#define PCNT_CTRL_REG (DR_REG_PCNT_BASE + 0x60) +/** PCNT_PULSE_CNT_RST_U0 : R/W; bitpos: [0]; default: 1; + * Set this bit to clear unit 0's counter. + */ +#define PCNT_PULSE_CNT_RST_U0 (BIT(0)) +#define PCNT_PULSE_CNT_RST_U0_M (PCNT_PULSE_CNT_RST_U0_V << PCNT_PULSE_CNT_RST_U0_S) +#define PCNT_PULSE_CNT_RST_U0_V 0x00000001U #define PCNT_PULSE_CNT_RST_U0_S 0 +/** PCNT_CNT_PAUSE_U0 : R/W; bitpos: [1]; default: 0; + * Set this bit to freeze unit 0's counter. + */ +#define PCNT_CNT_PAUSE_U0 (BIT(1)) +#define PCNT_CNT_PAUSE_U0_M (PCNT_CNT_PAUSE_U0_V << PCNT_CNT_PAUSE_U0_S) +#define PCNT_CNT_PAUSE_U0_V 0x00000001U +#define PCNT_CNT_PAUSE_U0_S 1 +/** PCNT_PULSE_CNT_RST_U1 : R/W; bitpos: [2]; default: 1; + * Set this bit to clear unit 1's counter. + */ +#define PCNT_PULSE_CNT_RST_U1 (BIT(2)) +#define PCNT_PULSE_CNT_RST_U1_M (PCNT_PULSE_CNT_RST_U1_V << PCNT_PULSE_CNT_RST_U1_S) +#define PCNT_PULSE_CNT_RST_U1_V 0x00000001U +#define PCNT_PULSE_CNT_RST_U1_S 2 +/** PCNT_CNT_PAUSE_U1 : R/W; bitpos: [3]; default: 0; + * Set this bit to freeze unit 1's counter. + */ +#define PCNT_CNT_PAUSE_U1 (BIT(3)) +#define PCNT_CNT_PAUSE_U1_M (PCNT_CNT_PAUSE_U1_V << PCNT_CNT_PAUSE_U1_S) +#define PCNT_CNT_PAUSE_U1_V 0x00000001U +#define PCNT_CNT_PAUSE_U1_S 3 +/** PCNT_PULSE_CNT_RST_U2 : R/W; bitpos: [4]; default: 1; + * Set this bit to clear unit 2's counter. + */ +#define PCNT_PULSE_CNT_RST_U2 (BIT(4)) +#define PCNT_PULSE_CNT_RST_U2_M (PCNT_PULSE_CNT_RST_U2_V << PCNT_PULSE_CNT_RST_U2_S) +#define PCNT_PULSE_CNT_RST_U2_V 0x00000001U +#define PCNT_PULSE_CNT_RST_U2_S 4 +/** PCNT_CNT_PAUSE_U2 : R/W; bitpos: [5]; default: 0; + * Set this bit to freeze unit 2's counter. + */ +#define PCNT_CNT_PAUSE_U2 (BIT(5)) +#define PCNT_CNT_PAUSE_U2_M (PCNT_CNT_PAUSE_U2_V << PCNT_CNT_PAUSE_U2_S) +#define PCNT_CNT_PAUSE_U2_V 0x00000001U +#define PCNT_CNT_PAUSE_U2_S 5 +/** PCNT_PULSE_CNT_RST_U3 : R/W; bitpos: [6]; default: 1; + * Set this bit to clear unit 3's counter. + */ +#define PCNT_PULSE_CNT_RST_U3 (BIT(6)) +#define PCNT_PULSE_CNT_RST_U3_M (PCNT_PULSE_CNT_RST_U3_V << PCNT_PULSE_CNT_RST_U3_S) +#define PCNT_PULSE_CNT_RST_U3_V 0x00000001U +#define PCNT_PULSE_CNT_RST_U3_S 6 +/** PCNT_CNT_PAUSE_U3 : R/W; bitpos: [7]; default: 0; + * Set this bit to freeze unit 3's counter. + */ +#define PCNT_CNT_PAUSE_U3 (BIT(7)) +#define PCNT_CNT_PAUSE_U3_M (PCNT_CNT_PAUSE_U3_V << PCNT_CNT_PAUSE_U3_S) +#define PCNT_CNT_PAUSE_U3_V 0x00000001U +#define PCNT_CNT_PAUSE_U3_S 7 +/** PCNT_CLK_EN : R/W; bitpos: [16]; default: 0; + * The registers clock gate enable signal of PCNT module. 1: the registers can be read + * and written by application. 0: the registers can not be read or written by + * application + */ +#define PCNT_CLK_EN (BIT(16)) +#define PCNT_CLK_EN_M (PCNT_CLK_EN_V << PCNT_CLK_EN_S) +#define PCNT_CLK_EN_V 0x00000001U +#define PCNT_CLK_EN_S 16 -#define PCNT_DATE_REG (DR_REG_PCNT_BASE + 0x00fc) -/* PCNT_DATE : R/W ;bitpos:[31:0] ;default: 32'h18072600 ; */ -/*description: */ -#define PCNT_DATE 0xFFFFFFFF -#define PCNT_DATE_M ((PCNT_DATE_V)<<(PCNT_DATE_S)) -#define PCNT_DATE_V 0xFFFFFFFF +/** PCNT_DATE_REG register + * PCNT version control register + */ +#define PCNT_DATE_REG (DR_REG_PCNT_BASE + 0xfc) +/** PCNT_DATE : R/W; bitpos: [31:0]; default: 419898881; + * This is the PCNT version control register. + */ +#define PCNT_DATE 0xFFFFFFFFU +#define PCNT_DATE_M (PCNT_DATE_V << PCNT_DATE_S) +#define PCNT_DATE_V 0xFFFFFFFFU #define PCNT_DATE_S 0 #ifdef __cplusplus } #endif - - - -#endif /*_SOC_PCNT_REG_H_ */ diff --git a/components/soc/esp32s2/include/soc/pcnt_struct.h b/components/soc/esp32s2/include/soc/pcnt_struct.h index b0c811f9cb..1d65a7309b 100644 --- a/components/soc/esp32s2/include/soc/pcnt_struct.h +++ b/components/soc/esp32s2/include/soc/pcnt_struct.h @@ -1,177 +1,416 @@ -// 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. -#ifndef _SOC_PCNT_STRUCT_H_ -#define _SOC_PCNT_STRUCT_H_ +/** Copyright 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. + */ +#pragma once + +#include + #ifdef __cplusplus extern "C" { #endif -typedef volatile struct { +/** Group: Configuration Register */ +/** Type of un_conf0 register + * Configuration register 0 for unit n + */ +typedef union { struct { - union { - struct { - uint32_t filter_thres: 10; - uint32_t filter_en: 1; - uint32_t thr_zero_en: 1; - uint32_t thr_h_lim_en: 1; - uint32_t thr_l_lim_en: 1; - uint32_t thr_thres0_en: 1; - uint32_t thr_thres1_en: 1; - uint32_t ch0_neg_mode: 2; - uint32_t ch0_pos_mode: 2; - uint32_t ch0_hctrl_mode: 2; - uint32_t ch0_lctrl_mode: 2; - uint32_t ch1_neg_mode: 2; - uint32_t ch1_pos_mode: 2; - uint32_t ch1_hctrl_mode: 2; - uint32_t ch1_lctrl_mode: 2; - }; - uint32_t val; - } conf0; - union { - struct { - uint32_t cnt_thres0: 16; - uint32_t cnt_thres1: 16; - }; - uint32_t val; - } conf1; - union { - struct { - uint32_t cnt_h_lim: 16; - uint32_t cnt_l_lim: 16; - }; - uint32_t val; - } conf2; + /** filter_thres_un : R/W; bitpos: [9:0]; default: 16; + * This sets the maximum threshold, in APB_CLK cycles, for the filter. + * + * Any pulses with width less than this will be ignored when the filter is enabled. + */ + uint32_t filter_thres_un: 10; + /** filter_en_un : R/W; bitpos: [10]; default: 1; + * This is the enable bit for unit n's input filter. + */ + uint32_t filter_en_un: 1; + /** thr_zero_en_un : R/W; bitpos: [11]; default: 1; + * This is the enable bit for unit n's zero comparator. + */ + uint32_t thr_zero_en_un: 1; + /** thr_h_lim_en_un : R/W; bitpos: [12]; default: 1; + * This is the enable bit for unit n's thr_h_lim comparator. + */ + uint32_t thr_h_lim_en_un: 1; + /** thr_l_lim_en_un : R/W; bitpos: [13]; default: 1; + * This is the enable bit for unit n's thr_l_lim comparator. + */ + uint32_t thr_l_lim_en_un: 1; + /** thr_thres0_en_un : R/W; bitpos: [14]; default: 0; + * This is the enable bit for unit n's thres0 comparator. + */ + uint32_t thr_thres0_en_un: 1; + /** thr_thres1_en_un : R/W; bitpos: [15]; default: 0; + * This is the enable bit for unit n's thres1 comparator. + */ + uint32_t thr_thres1_en_un: 1; + /** ch0_neg_mode_un : R/W; bitpos: [17:16]; default: 0; + * This register sets the behavior when the signal input of channel 0 detects a + * negative edge. + * + * 1: Increase the counter;2: Decrease the counter;0, 3: No effect on counter + */ + uint32_t ch0_neg_mode_un: 2; + /** ch0_pos_mode_un : R/W; bitpos: [19:18]; default: 0; + * This register sets the behavior when the signal input of channel 0 detects a + * positive edge. + * + * 1: Increase the counter;2: Decrease the counter;0, 3: No effect on counter + */ + uint32_t ch0_pos_mode_un: 2; + /** ch0_hctrl_mode_un : R/W; bitpos: [21:20]; default: 0; + * This register configures how the CHn_POS_MODE/CHn_NEG_MODE settings will be + * modified when the control signal is high. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ + uint32_t ch0_hctrl_mode_un: 2; + /** ch0_lctrl_mode_un : R/W; bitpos: [23:22]; default: 0; + * This register configures how the CHn_POS_MODE/CHn_NEG_MODE settings will be + * modified when the control signal is low. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ + uint32_t ch0_lctrl_mode_un: 2; + /** ch1_neg_mode_un : R/W; bitpos: [25:24]; default: 0; + * This register sets the behavior when the signal input of channel 1 detects a + * negative edge. + * + * 1: Increment the counter;2: Decrement the counter;0, 3: No effect on counter + */ + uint32_t ch1_neg_mode_un: 2; + /** ch1_pos_mode_un : R/W; bitpos: [27:26]; default: 0; + * This register sets the behavior when the signal input of channel 1 detects a + * positive edge. + * + * 1: Increment the counter;2: Decrement the counter;0, 3: No effect on counter + */ + uint32_t ch1_pos_mode_un: 2; + /** ch1_hctrl_mode_un : R/W; bitpos: [29:28]; default: 0; + * This register configures how the CHn_POS_MODE/CHn_NEG_MODE settings will be + * modified when the control signal is high. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ + uint32_t ch1_hctrl_mode_un: 2; + /** ch1_lctrl_mode_un : R/W; bitpos: [31:30]; default: 0; + * This register configures how the CHn_POS_MODE/CHn_NEG_MODE settings will be + * modified when the control signal is low. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ + uint32_t ch1_lctrl_mode_un: 2; + }; + uint32_t val; +} pcnt_un_conf0_reg_t; + +/** Type of un_conf1 register + * Configuration register 1 for unit n + */ +typedef union { + struct { + /** cnt_thres0_un : R/W; bitpos: [15:0]; default: 0; + * This register is used to configure the thres0 value for unit n. + */ + uint32_t cnt_thres0_un: 16; + /** cnt_thres1_un : R/W; bitpos: [31:16]; default: 0; + * This register is used to configure the thres1 value for unit n. + */ + uint32_t cnt_thres1_un: 16; + }; + uint32_t val; +} pcnt_un_conf1_reg_t; + +/** Type of un_conf2 register + * Configuration register 2 for unit n + */ +typedef union { + struct { + /** cnt_h_lim_un : R/W; bitpos: [15:0]; default: 0; + * This register is used to configure the thr_h_lim value for unit n. + */ + uint32_t cnt_h_lim_un: 16; + /** cnt_l_lim_un : R/W; bitpos: [31:16]; default: 0; + * This register is used to configure the thr_l_lim value for unit n. + */ + uint32_t cnt_l_lim_un: 16; + }; + uint32_t val; +} pcnt_un_conf2_reg_t; + + +/** Type of ctrl register + * Control register for all counters + */ +typedef union { + struct { + /** pulse_cnt_rst_u0 : R/W; bitpos: [0]; default: 1; + * Set this bit to clear unit 0's counter. + */ + uint32_t pulse_cnt_rst_u0: 1; + /** cnt_pause_u0 : R/W; bitpos: [1]; default: 0; + * Set this bit to freeze unit 0's counter. + */ + uint32_t cnt_pause_u0: 1; + /** pulse_cnt_rst_u1 : R/W; bitpos: [2]; default: 1; + * Set this bit to clear unit 1's counter. + */ + uint32_t pulse_cnt_rst_u1: 1; + /** cnt_pause_u1 : R/W; bitpos: [3]; default: 0; + * Set this bit to freeze unit 1's counter. + */ + uint32_t cnt_pause_u1: 1; + /** pulse_cnt_rst_u2 : R/W; bitpos: [4]; default: 1; + * Set this bit to clear unit 2's counter. + */ + uint32_t pulse_cnt_rst_u2: 1; + /** cnt_pause_u2 : R/W; bitpos: [5]; default: 0; + * Set this bit to freeze unit 2's counter. + */ + uint32_t cnt_pause_u2: 1; + /** pulse_cnt_rst_u3 : R/W; bitpos: [6]; default: 1; + * Set this bit to clear unit 3's counter. + */ + uint32_t pulse_cnt_rst_u3: 1; + /** cnt_pause_u3 : R/W; bitpos: [7]; default: 0; + * Set this bit to freeze unit 3's counter. + */ + uint32_t cnt_pause_u3: 1; + uint32_t reserved_8: 8; + /** clk_en : R/W; bitpos: [16]; default: 0; + * The registers clock gate enable signal of PCNT module. 1: the registers can be read + * and written by application. 0: the registers can not be read or written by + * application + */ + uint32_t clk_en: 1; + uint32_t reserved_17: 15; + }; + uint32_t val; +} pcnt_ctrl_reg_t; + + +/** Group: Status Register */ +/** Type of un_cnt register + * Counter value for unit n + */ +typedef union { + struct { + /** pulse_cnt_un : RO; bitpos: [15:0]; default: 0; + * This register stores the current pulse count value for unit n. + */ + uint32_t pulse_cnt_un: 16; + uint32_t reserved_16: 16; + }; + uint32_t val; +} pcnt_un_cnt_reg_t; + +/** Type of un_status register + * PNCT UNITn status register + */ +typedef union { + struct { + /** cnt_thr_zero_mode_un : RO; bitpos: [1:0]; default: 0; + * The pulse counter status of PCNT_Un corresponding to 0. 0: pulse counter decreases + * from positive to 0. 1: pulse counter increases from negative to 0. 2: pulse counter + * is negative. 3: pulse counter is positive. + */ + uint32_t cnt_thr_zero_mode_un: 2; + /** cnt_thr_thres1_lat_un : RO; bitpos: [2]; default: 0; + * The latched value of thres1 event of PCNT_Un when threshold event interrupt is + * valid. 1: the current pulse counter equals to thres1 and thres1 event is valid. 0: + * others + */ + uint32_t cnt_thr_thres1_lat_un: 1; + /** cnt_thr_thres0_lat_un : RO; bitpos: [3]; default: 0; + * The latched value of thres0 event of PCNT_Un when threshold event interrupt is + * valid. 1: the current pulse counter equals to thres0 and thres0 event is valid. 0: + * others + */ + uint32_t cnt_thr_thres0_lat_un: 1; + /** cnt_thr_l_lim_lat_un : RO; bitpos: [4]; default: 0; + * The latched value of low limit event of PCNT_Un when threshold event interrupt is + * valid. 1: the current pulse counter equals to thr_l_lim and low limit event is + * valid. 0: others + */ + uint32_t cnt_thr_l_lim_lat_un: 1; + /** cnt_thr_h_lim_lat_un : RO; bitpos: [5]; default: 0; + * The latched value of high limit event of PCNT_Un when threshold event interrupt is + * valid. 1: the current pulse counter equals to thr_h_lim and high limit event is + * valid. 0: others + */ + uint32_t cnt_thr_h_lim_lat_un: 1; + /** cnt_thr_zero_lat_un : RO; bitpos: [6]; default: 0; + * The latched value of zero threshold event of PCNT_Un when threshold event interrupt + * is valid. 1: the current pulse counter equals to 0 and zero threshold event is + * valid. 0: others + */ + uint32_t cnt_thr_zero_lat_un: 1; + uint32_t reserved_7: 25; + }; + uint32_t val; +} pcnt_un_status_reg_t; + + +/** Group: Interrupt Register */ +/** Type of int_raw register + * Interrupt raw status register + */ +typedef union { + struct { + /** cnt_thr_event_u0_int_raw : RO; bitpos: [0]; default: 0; + * The raw interrupt status bit for the PCNT_CNT_THR_EVENT_U0_INT interrupt. + */ + uint32_t cnt_thr_event_u0_int_raw: 1; + /** cnt_thr_event_u1_int_raw : RO; bitpos: [1]; default: 0; + * The raw interrupt status bit for the PCNT_CNT_THR_EVENT_U1_INT interrupt. + */ + uint32_t cnt_thr_event_u1_int_raw: 1; + /** cnt_thr_event_u2_int_raw : RO; bitpos: [2]; default: 0; + * The raw interrupt status bit for the PCNT_CNT_THR_EVENT_U2_INT interrupt. + */ + uint32_t cnt_thr_event_u2_int_raw: 1; + /** cnt_thr_event_u3_int_raw : RO; bitpos: [3]; default: 0; + * The raw interrupt status bit for the PCNT_CNT_THR_EVENT_U3_INT interrupt. + */ + uint32_t cnt_thr_event_u3_int_raw: 1; + uint32_t reserved_4: 28; + }; + uint32_t val; +} pcnt_int_raw_reg_t; + +/** Type of int_st register + * Interrupt status register + */ +typedef union { + struct { + /** cnt_thr_event_u0_int_st : RO; bitpos: [0]; default: 0; + * The masked interrupt status bit for the PCNT_CNT_THR_EVENT_U0_INT interrupt. + */ + uint32_t cnt_thr_event_u0_int_st: 1; + /** cnt_thr_event_u1_int_st : RO; bitpos: [1]; default: 0; + * The masked interrupt status bit for the PCNT_CNT_THR_EVENT_U1_INT interrupt. + */ + uint32_t cnt_thr_event_u1_int_st: 1; + /** cnt_thr_event_u2_int_st : RO; bitpos: [2]; default: 0; + * The masked interrupt status bit for the PCNT_CNT_THR_EVENT_U2_INT interrupt. + */ + uint32_t cnt_thr_event_u2_int_st: 1; + /** cnt_thr_event_u3_int_st : RO; bitpos: [3]; default: 0; + * The masked interrupt status bit for the PCNT_CNT_THR_EVENT_U3_INT interrupt. + */ + uint32_t cnt_thr_event_u3_int_st: 1; + uint32_t reserved_4: 28; + }; + uint32_t val; +} pcnt_int_st_reg_t; + +/** Type of int_ena register + * Interrupt enable register + */ +typedef union { + struct { + /** cnt_thr_event_u0_int_ena : R/W; bitpos: [0]; default: 0; + * The interrupt enable bit for the PCNT_CNT_THR_EVENT_U0_INT interrupt. + */ + uint32_t cnt_thr_event_u0_int_ena: 1; + /** cnt_thr_event_u1_int_ena : R/W; bitpos: [1]; default: 0; + * The interrupt enable bit for the PCNT_CNT_THR_EVENT_U1_INT interrupt. + */ + uint32_t cnt_thr_event_u1_int_ena: 1; + /** cnt_thr_event_u2_int_ena : R/W; bitpos: [2]; default: 0; + * The interrupt enable bit for the PCNT_CNT_THR_EVENT_U2_INT interrupt. + */ + uint32_t cnt_thr_event_u2_int_ena: 1; + /** cnt_thr_event_u3_int_ena : R/W; bitpos: [3]; default: 0; + * The interrupt enable bit for the PCNT_CNT_THR_EVENT_U3_INT interrupt. + */ + uint32_t cnt_thr_event_u3_int_ena: 1; + uint32_t reserved_4: 28; + }; + uint32_t val; +} pcnt_int_ena_reg_t; + +/** Type of int_clr register + * Interrupt clear register + */ +typedef union { + struct { + /** cnt_thr_event_u0_int_clr : WO; bitpos: [0]; default: 0; + * Set this bit to clear the PCNT_CNT_THR_EVENT_U0_INT interrupt. + */ + uint32_t cnt_thr_event_u0_int_clr: 1; + /** cnt_thr_event_u1_int_clr : WO; bitpos: [1]; default: 0; + * Set this bit to clear the PCNT_CNT_THR_EVENT_U1_INT interrupt. + */ + uint32_t cnt_thr_event_u1_int_clr: 1; + /** cnt_thr_event_u2_int_clr : WO; bitpos: [2]; default: 0; + * Set this bit to clear the PCNT_CNT_THR_EVENT_U2_INT interrupt. + */ + uint32_t cnt_thr_event_u2_int_clr: 1; + /** cnt_thr_event_u3_int_clr : WO; bitpos: [3]; default: 0; + * Set this bit to clear the PCNT_CNT_THR_EVENT_U3_INT interrupt. + */ + uint32_t cnt_thr_event_u3_int_clr: 1; + uint32_t reserved_4: 28; + }; + uint32_t val; +} pcnt_int_clr_reg_t; + + +/** Group: Version Register */ +/** Type of date register + * PCNT version control register + */ +typedef union { + struct { + /** date : R/W; bitpos: [31:0]; default: 419898881; + * This is the PCNT version control register. + */ + uint32_t date: 32; + }; + uint32_t val; +} pcnt_date_reg_t; + + +typedef struct { + volatile struct { + pcnt_un_conf0_reg_t conf0; + pcnt_un_conf1_reg_t conf1; + pcnt_un_conf2_reg_t conf2; } conf_unit[4]; - union { - struct { - uint32_t cnt_val: 16; - uint32_t reserved16: 16; - }; - uint32_t val; - } cnt_unit[4]; - union { - struct { - uint32_t cnt_thr_event_u0: 1; - uint32_t cnt_thr_event_u1: 1; - uint32_t cnt_thr_event_u2: 1; - uint32_t cnt_thr_event_u3: 1; - uint32_t reserved4: 28; - }; - uint32_t val; - } int_raw; - union { - struct { - uint32_t cnt_thr_event_u0: 1; - uint32_t cnt_thr_event_u1: 1; - uint32_t cnt_thr_event_u2: 1; - uint32_t cnt_thr_event_u3: 1; - uint32_t reserved4: 28; - }; - uint32_t val; - } int_st; - union { - struct { - uint32_t cnt_thr_event_u0: 1; - uint32_t cnt_thr_event_u1: 1; - uint32_t cnt_thr_event_u2: 1; - uint32_t cnt_thr_event_u3: 1; - uint32_t reserved4: 28; - }; - uint32_t val; - } int_ena; - union { - struct { - uint32_t cnt_thr_event_u0: 1; - uint32_t cnt_thr_event_u1: 1; - uint32_t cnt_thr_event_u2: 1; - uint32_t cnt_thr_event_u3: 1; - uint32_t reserved4: 28; - }; - uint32_t val; - } int_clr; - union { - struct { - uint32_t cnt_mode: 2; - uint32_t thres1_lat: 1; - uint32_t thres0_lat: 1; - uint32_t l_lim_lat: 1; - uint32_t h_lim_lat: 1; - uint32_t zero_lat: 1; - uint32_t reserved7: 25; - }; - uint32_t val; - } status_unit[4]; - union { - struct { - uint32_t cnt_rst_u0: 1; - uint32_t cnt_pause_u0: 1; - uint32_t cnt_rst_u1: 1; - uint32_t cnt_pause_u1: 1; - uint32_t cnt_rst_u2: 1; - uint32_t cnt_pause_u2: 1; - uint32_t cnt_rst_u3: 1; - uint32_t cnt_pause_u3: 1; - uint32_t reserved8: 8; - uint32_t clk_en: 1; - uint32_t reserved17: 15; - }; - uint32_t val; - } ctrl; - uint32_t reserved_64; - uint32_t reserved_68; - uint32_t reserved_6c; - uint32_t reserved_70; - uint32_t reserved_74; - uint32_t reserved_78; - uint32_t reserved_7c; - uint32_t reserved_80; - uint32_t reserved_84; - uint32_t reserved_88; - uint32_t reserved_8c; - uint32_t reserved_90; - uint32_t reserved_94; - uint32_t reserved_98; - uint32_t reserved_9c; - uint32_t reserved_a0; - uint32_t reserved_a4; - uint32_t reserved_a8; - uint32_t reserved_ac; - uint32_t reserved_b0; - uint32_t reserved_b4; - uint32_t reserved_b8; - uint32_t reserved_bc; - uint32_t reserved_c0; - uint32_t reserved_c4; - uint32_t reserved_c8; - uint32_t reserved_cc; - uint32_t reserved_d0; - uint32_t reserved_d4; - uint32_t reserved_d8; - uint32_t reserved_dc; - uint32_t reserved_e0; - uint32_t reserved_e4; - uint32_t reserved_e8; - uint32_t reserved_ec; - uint32_t reserved_f0; - uint32_t reserved_f4; - uint32_t reserved_f8; - uint32_t date; /**/ + volatile pcnt_un_cnt_reg_t cnt_unit[4]; + volatile pcnt_int_raw_reg_t int_raw; + volatile pcnt_int_st_reg_t int_st; + volatile pcnt_int_ena_reg_t int_ena; + volatile pcnt_int_clr_reg_t int_clr; + volatile pcnt_un_status_reg_t status_unit[4]; + volatile pcnt_ctrl_reg_t ctrl; + uint32_t reserved_064[38]; + volatile pcnt_date_reg_t date; } pcnt_dev_t; + +#ifndef __cplusplus +_Static_assert(sizeof(pcnt_dev_t) == 0x100, "Invalid size of pcnt_dev_t structure"); +#endif + extern pcnt_dev_t PCNT; + #ifdef __cplusplus } #endif - -#endif /* _SOC_PCNT_STRUCT_H_ */ diff --git a/components/soc/esp32s2/include/soc/periph_defs.h b/components/soc/esp32s2/include/soc/periph_defs.h index 2bd5071f80..1b8a65c6dc 100644 --- a/components/soc/esp32s2/include/soc/periph_defs.h +++ b/components/soc/esp32s2/include/soc/periph_defs.h @@ -27,7 +27,6 @@ typedef enum { PERIPH_I2C0_MODULE, PERIPH_I2C1_MODULE, PERIPH_I2S0_MODULE, - PERIPH_I2S1_MODULE, PERIPH_TIMG0_MODULE, PERIPH_TIMG1_MODULE, PERIPH_UHCI0_MODULE, @@ -86,15 +85,14 @@ typedef enum { ETS_DEDICATED_GPIO_INTR_SOURCE, /**< interrupt of dedicated GPIO, level*/ ETS_FROM_CPU_INTR0_SOURCE, /**< interrupt0 generated from a CPU, level*/ /* Used for FreeRTOS */ ETS_FROM_CPU_INTR1_SOURCE, /**< interrupt1 generated from a CPU, level*/ /* Used for FreeRTOS */ - ETS_FROM_CPU_INTR2_SOURCE, /**< interrupt2 generated from a CPU, level*/ /* Used for DPORT Access */ - ETS_FROM_CPU_INTR3_SOURCE, /**< interrupt3 generated from a CPU, level*/ /* Used for DPORT Access */ + ETS_FROM_CPU_INTR2_SOURCE, /**< interrupt2 generated from a CPU, level*/ + ETS_FROM_CPU_INTR3_SOURCE, /**< interrupt3 generated from a CPU, level*/ ETS_SPI1_INTR_SOURCE = 32, /**< interrupt of SPI1, level, SPI1 is for flash read/write, do not use this*/ ETS_SPI2_INTR_SOURCE, /**< interrupt of SPI2, level*/ ETS_SPI3_INTR_SOURCE, /**< interrupt of SPI3, level*/ ETS_I2S0_INTR_SOURCE, /**< interrupt of I2S0, level*/ - ETS_I2S1_INTR_SOURCE, /**< interrupt of I2S1, level*/ - ETS_UART0_INTR_SOURCE, /**< interrupt of UART0, level*/ + ETS_UART0_INTR_SOURCE = 37, /**< interrupt of UART0, level*/ ETS_UART1_INTR_SOURCE, /**< interrupt of UART1, level*/ ETS_UART2_INTR_SOURCE, /**< interrupt of UART2, level*/ ETS_SDIO_HOST_INTR_SOURCE, /**< interrupt of SD/SDIO/MMC HOST, level*/ diff --git a/components/soc/esp32s2/include/soc/rmt_struct.h b/components/soc/esp32s2/include/soc/rmt_struct.h index b92c42a775..5e43004093 100644 --- a/components/soc/esp32s2/include/soc/rmt_struct.h +++ b/components/soc/esp32s2/include/soc/rmt_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct rmt_dev_s { uint32_t data_ch[4]; /* Data FIFO, Can only be accessed by PeriBus2 */ struct { union { @@ -300,11 +300,9 @@ typedef struct { } rmt_item32_t; //Allow access to RMT memory using RMTMEM.chan[0].data32[8] -typedef volatile struct { +typedef volatile struct rmt_mem_s { struct { - union { - rmt_item32_t data32[64]; - }; + rmt_item32_t data32[64]; } chan[4]; } rmt_mem_t; extern rmt_mem_t RMTMEM; diff --git a/components/soc/esp32s2/include/soc/rtc.h b/components/soc/esp32s2/include/soc/rtc.h index 52322db983..11b13fb6aa 100644 --- a/components/soc/esp32s2/include/soc/rtc.h +++ b/components/soc/esp32s2/include/soc/rtc.h @@ -120,11 +120,14 @@ extern "C" { set sleep_init default param */ #define RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_DEFAULT 6 +#define RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_NODROP 0 #define RTC_CNTL_DBG_ATTEN_DEEPSLEEP_DEFAULT 15 #define RTC_CNTL_DBG_ATTEN_MONITOR_DEFAULT 0 #define RTC_CNTL_BIASSLP_MONITOR_DEFAULT 0 +#define RTC_CNTL_BIASSLP_SLEEP_ON 0 #define RTC_CNTL_BIASSLP_SLEEP_DEFAULT 1 #define RTC_CNTL_PD_CUR_MONITOR_DEFAULT 1 +#define RTC_CNTL_PD_CUR_SLEEP_ON 0 #define RTC_CNTL_PD_CUR_SLEEP_DEFAULT 1 #define APLL_SDM_STOP_VAL_1 0x09 @@ -215,7 +218,8 @@ typedef enum { typedef enum { RTC_CAL_RTC_MUX = 0, //!< Currently selected RTC SLOW_CLK RTC_CAL_8MD256 = 1, //!< Internal 8 MHz RC oscillator, divided by 256 - RTC_CAL_32K_XTAL = 2 //!< External 32 kHz XTAL + RTC_CAL_32K_XTAL = 2, //!< External 32 kHz XTAL + RTC_CAL_INTERNAL_OSC = 3 //!< Internal 150 kHz oscillator } rtc_cal_sel_t; /** @@ -657,6 +661,7 @@ typedef struct { uint32_t rtc_slowmem_pd_en : 1; //!< power down RTC slow memory uint32_t rtc_peri_pd_en : 1; //!< power down RTC peripherals uint32_t wifi_pd_en : 1; //!< power down WiFi + uint32_t int_8m_pd_en : 1; //!< Power down Internal 8M oscillator uint32_t deep_slp : 1; //!< power down digital domain uint32_t wdt_flashboot_mod_en : 1; //!< enable WDT flashboot mode uint32_t dig_dbias_wak : 3; //!< set bias for digital domain, in active mode @@ -664,6 +669,7 @@ typedef struct { uint32_t rtc_dbias_wak : 3; //!< set bias for RTC domain, in active mode uint32_t rtc_dbias_slp : 3; //!< set bias for RTC domain, in sleep mode uint32_t vddsdio_pd_en : 1; //!< power down VDDSDIO regulator + uint32_t xtal_fpu : 1; //!< keep main XTAL powered up in sleep uint32_t deep_slp_reject : 1; uint32_t light_slp_reject : 1; } rtc_sleep_config_t; @@ -676,6 +682,7 @@ typedef struct { * * @param RTC_SLEEP_PD_x flags combined using bitwise OR */ +#define is_dslp(pd_flags) ((pd_flags) & RTC_SLEEP_PD_DIG) #define RTC_SLEEP_CONFIG_DEFAULT(sleep_flags) { \ .lslp_mem_inf_fpu = 0, \ .rtc_mem_inf_follow_cpu = ((sleep_flags) & RTC_SLEEP_PD_RTC_MEM_FOLLOW_CPU) ? 1 : 0, \ @@ -683,13 +690,21 @@ typedef struct { .rtc_slowmem_pd_en = ((sleep_flags) & RTC_SLEEP_PD_RTC_SLOW_MEM) ? 1 : 0, \ .rtc_peri_pd_en = ((sleep_flags) & RTC_SLEEP_PD_RTC_PERIPH) ? 1 : 0, \ .wifi_pd_en = ((sleep_flags) & RTC_SLEEP_PD_WIFI) ? 1 : 0, \ + .int_8m_pd_en = is_dslp(sleep_flags) ? 1 : ((sleep_flags) & RTC_SLEEP_PD_INT_8M) ? 1 : 0, \ .deep_slp = ((sleep_flags) & RTC_SLEEP_PD_DIG) ? 1 : 0, \ .wdt_flashboot_mod_en = 0, \ .dig_dbias_wak = RTC_CNTL_DIG_DBIAS_1V10, \ - .dig_dbias_slp = RTC_CNTL_DIG_DBIAS_0V90, \ + .dig_dbias_slp = is_dslp(sleep_flags) ? RTC_CNTL_DIG_DBIAS_0V90 \ + : !((sleep_flags) & RTC_SLEEP_PD_INT_8M) ? RTC_CNTL_DIG_DBIAS_1V10 \ + : !((sleep_flags) & RTC_SLEEP_PD_XTAL) ? RTC_CNTL_DIG_DBIAS_1V10 \ + : RTC_CNTL_DIG_DBIAS_0V90, \ .rtc_dbias_wak = RTC_CNTL_DBIAS_1V10, \ - .rtc_dbias_slp = RTC_CNTL_DBIAS_1V00, \ + .rtc_dbias_slp = is_dslp(sleep_flags) ? RTC_CNTL_DBIAS_1V00 \ + : !((sleep_flags) & RTC_SLEEP_PD_INT_8M) ? RTC_CNTL_DBIAS_1V10 \ + : !((sleep_flags) & RTC_SLEEP_PD_XTAL) ? RTC_CNTL_DBIAS_1V10 \ + : RTC_CNTL_DBIAS_1V00, \ .vddsdio_pd_en = ((sleep_flags) & RTC_SLEEP_PD_VDDSDIO) ? 1 : 0, \ + .xtal_fpu = is_dslp(sleep_flags) ? 0 : ((sleep_flags) & RTC_SLEEP_PD_XTAL) ? 0 : 1, \ .deep_slp_reject = 1, \ .light_slp_reject = 1 \ }; @@ -701,6 +716,8 @@ typedef struct { #define RTC_SLEEP_PD_RTC_MEM_FOLLOW_CPU BIT(4) //!< RTC FAST and SLOW memories are automatically powered up and down along with the CPU #define RTC_SLEEP_PD_VDDSDIO BIT(5) //!< Power down VDDSDIO regulator #define RTC_SLEEP_PD_WIFI BIT(6) +#define RTC_SLEEP_PD_INT_8M BIT(7) //!< Power down Internal 8M oscillator +#define RTC_SLEEP_PD_XTAL BIT(8) //!< Power down main XTAL /** * @brief Prepare the chip to enter sleep mode diff --git a/components/soc/esp32s2/include/soc/rtc_cntl_struct.h b/components/soc/esp32s2/include/soc/rtc_cntl_struct.h index 4a901a3231..695d18c616 100644 --- a/components/soc/esp32s2/include/soc/rtc_cntl_struct.h +++ b/components/soc/esp32s2/include/soc/rtc_cntl_struct.h @@ -19,7 +19,7 @@ extern "C" { #include -typedef volatile struct { +typedef volatile struct rtc_cntl_dev_s { union { struct { uint32_t sw_stall_appcpu_c0: 2; /*{reg_sw_stall_appcpu_c1[5:0] reg_sw_stall_appcpu_c0[1:0]} == 0x86 will stall APP CPU*/ diff --git a/components/soc/esp32s2/include/soc/rtc_i2c_struct.h b/components/soc/esp32s2/include/soc/rtc_i2c_struct.h index 2b9e6532d6..8f46d82fa3 100644 --- a/components/soc/esp32s2/include/soc/rtc_i2c_struct.h +++ b/components/soc/esp32s2/include/soc/rtc_i2c_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct rtc_i2c_dev_s { union { struct { uint32_t period: 20; /*time period that scl = 0*/ diff --git a/components/soc/esp32s2/include/soc/rtc_io_struct.h b/components/soc/esp32s2/include/soc/rtc_io_struct.h index c38c9fd4ab..6d4c883ed0 100644 --- a/components/soc/esp32s2/include/soc/rtc_io_struct.h +++ b/components/soc/esp32s2/include/soc/rtc_io_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct rtc_io_dev_s { union { struct { uint32_t reserved0: 10; diff --git a/components/soc/esp32s2/include/soc/sens_struct.h b/components/soc/esp32s2/include/soc/sens_struct.h index 5f56714ee6..5a029dd9fe 100644 --- a/components/soc/esp32s2/include/soc/sens_struct.h +++ b/components/soc/esp32s2/include/soc/sens_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct sens_dev_s { union { struct { uint32_t sar1_clk_div: 8; /*clock divider*/ diff --git a/components/soc/esp32s2/include/soc/soc.h b/components/soc/esp32s2/include/soc/soc.h index 5084c23c50..ae4cf0103a 100644 --- a/components/soc/esp32s2/include/soc/soc.h +++ b/components/soc/esp32s2/include/soc/soc.h @@ -299,23 +299,23 @@ //interrupt cpu using table, Please see the core-isa.h /************************************************************************************************************* - * Intr num Level Type PRO CPU usage APP CPU uasge - * 0 1 extern level WMAC Reserved - * 1 1 extern level BT/BLE Host HCI DMA BT/BLE Host HCI DMA + * Intr num Level Type PRO CPU usage + * 0 1 extern level WMAC + * 1 1 extern level BT/BLE Host HCI DMA * 2 1 extern level * 3 1 extern level * 4 1 extern level WBB - * 5 1 extern level BT/BLE Controller BT/BLE Controller - * 6 1 timer FreeRTOS Tick(L1) FreeRTOS Tick(L1) - * 7 1 software BT/BLE VHCI BT/BLE VHCI - * 8 1 extern level BT/BLE BB(RX/TX) BT/BLE BB(RX/TX) + * 5 1 extern level BT/BLE Controller + * 6 1 timer FreeRTOS Tick(L1) + * 7 1 software BT/BLE VHCI + * 8 1 extern level BT/BLE BB(RX/TX) * 9 1 extern level * 10 1 extern edge * 11 3 profiling * 12 1 extern level * 13 1 extern level - * 14 7 nmi Reserved Reserved - * 15 3 timer FreeRTOS Tick(L3) FreeRTOS Tick(L3) + * 14 7 nmi Reserved + * 15 3 timer FreeRTOS Tick(L3) * 16 5 timer * 17 1 extern level * 18 1 extern level @@ -327,10 +327,10 @@ * 24 4 extern level TG1_WDT * 25 4 extern level CACHEERR * 26 5 extern level - * 27 3 extern level Reserved Reserved - * 28 4 extern edge DPORT ACCESS DPORT ACCESS - * 29 3 software Reserved Reserved - * 30 4 extern edge Reserved Reserved + * 27 3 extern level Reserved + * 28 4 extern edge Reserved + * 29 3 software Reserved + * 30 4 extern edge Reserved * 31 5 extern level ************************************************************************************************************* */ @@ -343,7 +343,6 @@ #define ETS_FRC1_INUM 22 #define ETS_T1_WDT_INUM 24 #define ETS_MEMACCESS_ERR_INUM 25 -#define ETS_DPORT_INUM 28 //CPU0 Interrupt number used in ROM, should be cancelled in SDK #define ETS_SLC_INUM 1 diff --git a/components/soc/esp32s2/include/soc/soc_caps.h b/components/soc/esp32s2/include/soc/soc_caps.h index 0f633b8ef7..ac99759a96 100644 --- a/components/soc/esp32s2/include/soc/soc_caps.h +++ b/components/soc/esp32s2/include/soc/soc_caps.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ /* * Soc capabilities file, describing the following chip attributes: @@ -59,25 +51,32 @@ #define SOC_FLASH_ENCRYPTION_XTS_AES 1 #define SOC_FLASH_ENCRYPTION_XTS_AES_256 1 #define SOC_PSRAM_DMA_CAPABLE 1 +#define SOC_XT_WDT_SUPPORTED 1 /*-------------------------- ADC CAPS ----------------------------------------*/ -#define SOC_ADC_PERIPH_NUM (2) -#define SOC_ADC_PATT_LEN_MAX (16) -#define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) (10) -#define SOC_ADC_MAX_CHANNEL_NUM (10) -#define SOC_ADC_MAX_BITWIDTH (13) -#define SOC_ADC_HW_CALIBRATION_V1 (1) /*!< support HW offset calibration */ +/*!< SAR ADC Module*/ +#define SOC_ADC_RTC_CTRL_SUPPORTED 1 +#define SOC_ADC_ARBITER_SUPPORTED 1 +#define SOC_ADC_FILTER_SUPPORTED 1 +#define SOC_ADC_MONITOR_SUPPORTED 1 +#define SOC_ADC_PERIPH_NUM (2) +#define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) (10) +#define SOC_ADC_MAX_CHANNEL_NUM (10) +/*!< Digital */ +#define SOC_ADC_DIGI_CONTROLLER_NUM (2) +#define SOC_ADC_PATT_LEN_MAX (32) /*!< Two pattern table, each contains 16 items. Each item takes 1 byte */ +#define SOC_ADC_DIGI_MAX_BITWIDTH (12) +/*!< F_sample = F_digi_con / 2 / interval. F_digi_con = 5M for now. 30 <= interva <= 4095 */ +#define SOC_ADC_SAMPLE_FREQ_THRES_HIGH 83333 +#define SOC_ADC_SAMPLE_FREQ_THRES_LOW 611 + +/*!< RTC */ +#define SOC_ADC_MAX_BITWIDTH (13) + +/*!< Calibration */ +#define SOC_ADC_CALIBRATION_V1_SUPPORTED (1) /*!< support HW offset calibration version 1*/ -/** - * Check if adc support digital controller (DMA) mode. - * @value - * - 1 : support; - * - 0 : not support; - */ -#define SOC_ADC_SUPPORT_DMA_MODE(PERIPH_NUM) ((PERIPH_NUM==0)? 1: 1) -#define SOC_ADC_SUPPORT_RTC_CTRL 1 -#define SOC_ADC_ARBITER_SUPPORTED 1 /*-------------------------- BROWNOUT CAPS -----------------------------------*/ #define SOC_BROWNOUT_RESET_SUPPORTED 1 @@ -119,6 +118,7 @@ #define SOC_DEDIC_GPIO_IN_CHANNELS_NUM (8) /*!< 8 inward channels on each CPU core */ #define SOC_DEDIC_GPIO_ALLOW_REG_ACCESS (1) /*!< Allow access dedicated GPIO channel by register */ #define SOC_DEDIC_GPIO_HAS_INTERRUPT (1) /*!< Dedicated GPIO has its own interrupt source */ +#define SOC_DEDIC_GPIO_OUT_AUTO_ENABLE (1) /*!< Dedicated GPIO output attribution is enabled automatically */ /*-------------------------- I2C CAPS ----------------------------------------*/ // ESP32-S2 have 2 I2C. @@ -135,16 +135,20 @@ #define SOC_I2C_SUPPORT_APB (1) /*-------------------------- I2S CAPS ----------------------------------------*/ -// ESP32-S2 have 2 I2S -#define SOC_I2S_NUM (1) +// ESP32-S2 have 1 I2S +#define SOC_I2S_NUM (1) +#define SOC_I2S_SUPPORTS_APLL (1)// ESP32-S2 support APLL +#define SOC_I2S_SUPPORTS_DMA_EQUAL (1) +#define SOC_I2S_APLL_MIN_FREQ (250000000) +#define SOC_I2S_APLL_MAX_FREQ (500000000) +#define SOC_I2S_APLL_MIN_RATE (10675) //in Hz, I2S Clock rate limited by hardware +#define SOC_I2S_LCD_I80_VARIANT (1) -#define SOC_I2S_SUPPORTS_DMA_EQUAL (1) // ESP32-S2 need dma equal - -#define SOC_I2S_MAX_BUFFER_SIZE (4 * 1024 * 1024) //the maximum RAM can be allocated - -#define SOC_I2S_APLL_MIN_FREQ (250000000) -#define SOC_I2S_APLL_MAX_FREQ (500000000) -#define SOC_I2S_APLL_MIN_RATE (10675) //in Hz, I2S Clock rate limited by hardware +/*-------------------------- LCD CAPS ----------------------------------------*/ +/* Notes: On esp32-s2, LCD intel 8080 timing is generated by I2S peripheral */ +#define SOC_LCD_I80_SUPPORTED (1) /*!< Intel 8080 LCD is supported */ +#define SOC_LCD_I80_BUSES (1) /*!< Only I2S0 has LCD mode */ +#define SOC_LCD_I80_BUS_WIDTH (24) /*!< Intel 8080 bus width */ /*-------------------------- LEDC CAPS ---------------------------------------*/ #define SOC_LEDC_SUPPORT_XTAL_CLOCK (1) @@ -160,10 +164,10 @@ #define SOC_MPU_REGION_WO_SUPPORTED 0 /*-------------------------- PCNT CAPS ---------------------------------------*/ -// ESP32-S2 have 1 PCNT peripheral -#define SOC_PCNT_PORT_NUM (1) -#define SOC_PCNT_UNIT_NUM (4) // ESP32-S2 only have 4 unit -#define SOC_PCNT_UNIT_CHANNEL_NUM (2) +#define SOC_PCNT_GROUPS (1) +#define SOC_PCNT_UNITS_PER_GROUP (4) +#define SOC_PCNT_CHANNELS_PER_UNIT (2) +#define SOC_PCNT_THRES_POINT_PER_UNIT (2) /*-------------------------- RMT CAPS ----------------------------------------*/ #define SOC_RMT_GROUPS (1) /*!< One RMT group */ @@ -214,6 +218,7 @@ #define SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUTPUT 1 #define SOC_MEMSPI_IS_INDEPENDENT 1 +#define SOC_SPI_SUPPORT_OCT 1 /*-------------------------- SYSTIMER CAPS ----------------------------------*/ #define SOC_SYSTIMER_COUNTER_NUM (1) // Number of counter units @@ -242,7 +247,7 @@ #define SOC_TWAI_SUPPORTS_RX_STATUS 1 /*-------------------------- UART CAPS ---------------------------------------*/ -// ESP32-S2 have 2 UART. +// ESP32-S2 has 2 UART. #define SOC_UART_NUM (2) #define SOC_UART_SUPPORT_REF_TICK (1) /*!< Support REF_TICK as the clock source */ #define SOC_UART_FIFO_LEN (128) /*!< The UART hardware FIFO length */ diff --git a/components/soc/esp32s2/include/soc/spi_pins.h b/components/soc/esp32s2/include/soc/spi_pins.h index c334e01fe1..81ea5f0d2a 100644 --- a/components/soc/esp32s2/include/soc/spi_pins.h +++ b/components/soc/esp32s2/include/soc/spi_pins.h @@ -22,21 +22,37 @@ #define SPI_IOMUX_PIN_NUM_MISO 31 #define SPI_IOMUX_PIN_NUM_WP 28 -#define SPI2_FUNC_NUM FSPI_FUNC_NUM -#define SPI2_IOMUX_PIN_NUM_HD FSPI_IOMUX_PIN_NUM_HD -#define SPI2_IOMUX_PIN_NUM_CS FSPI_IOMUX_PIN_NUM_CS -#define SPI2_IOMUX_PIN_NUM_MOSI FSPI_IOMUX_PIN_NUM_MOSI -#define SPI2_IOMUX_PIN_NUM_CLK FSPI_IOMUX_PIN_NUM_CLK -#define SPI2_IOMUX_PIN_NUM_MISO FSPI_IOMUX_PIN_NUM_MISO -#define SPI2_IOMUX_PIN_NUM_WP FSPI_IOMUX_PIN_NUM_WP +// There are 2 sets of GPIO pins which could be routed to FSPICS0, FSPICLK, FSPID, FSPIQ, FSPIHD, FSPIWP. +// However, there is only one set of GPIO pins which could be routed to FSPIIO4, FSPIIO5, FSPIIO6, FSPIIO7. +// As default (when we are not going to use Octal SPI), we make use of SPI2_FUNC_NUM to route one of the 2 sets of GPIO pins to FSPICS0 ~ FSPIWP as follows. +#define SPI2_FUNC_NUM 4 +#define SPI2_IOMUX_PIN_NUM_HD 9 +#define SPI2_IOMUX_PIN_NUM_CS 10 +#define SPI2_IOMUX_PIN_NUM_MOSI 11 +#define SPI2_IOMUX_PIN_NUM_CLK 12 +#define SPI2_IOMUX_PIN_NUM_MISO 13 +#define SPI2_IOMUX_PIN_NUM_WP 14 + +// When using Octal SPI, we make use of SPI2_FUNC_NUM_OCT to route them as follows. +#define SPI2_FUNC_NUM_OCT 2 +#define SPI2_IOMUX_PIN_NUM_HD_OCT 33 +#define SPI2_IOMUX_PIN_NUM_CS_OCT 34 +#define SPI2_IOMUX_PIN_NUM_MOSI_OCT 35 +#define SPI2_IOMUX_PIN_NUM_CLK_OCT 36 +#define SPI2_IOMUX_PIN_NUM_MISO_OCT 37 +#define SPI2_IOMUX_PIN_NUM_WP_OCT 38 +#define SPI2_IOMUX_PIN_NUM_IO4_OCT 10 +#define SPI2_IOMUX_PIN_NUM_IO5_OCT 11 +#define SPI2_IOMUX_PIN_NUM_IO6_OCT 12 +#define SPI2_IOMUX_PIN_NUM_IO7_OCT 13 //SPI3 has no iomux pins //Following Macros are deprecated. Please use the Macros above -#define FSPI_FUNC_NUM 4 -#define FSPI_IOMUX_PIN_NUM_HD 9 -#define FSPI_IOMUX_PIN_NUM_CS 10 -#define FSPI_IOMUX_PIN_NUM_MOSI 11 -#define FSPI_IOMUX_PIN_NUM_CLK 12 -#define FSPI_IOMUX_PIN_NUM_MISO 13 -#define FSPI_IOMUX_PIN_NUM_WP 14 +#define FSPI_FUNC_NUM SPI2_FUNC_NUM +#define FSPI_IOMUX_PIN_NUM_HD SPI2_IOMUX_PIN_NUM_HD +#define FSPI_IOMUX_PIN_NUM_CS SPI2_IOMUX_PIN_NUM_CS +#define FSPI_IOMUX_PIN_NUM_MOSI SPI2_IOMUX_PIN_NUM_MOSI +#define FSPI_IOMUX_PIN_NUM_CLK SPI2_IOMUX_PIN_NUM_CLK +#define FSPI_IOMUX_PIN_NUM_MISO SPI2_IOMUX_PIN_NUM_MISO +#define FSPI_IOMUX_PIN_NUM_WP SPI2_IOMUX_PIN_NUM_WP diff --git a/components/soc/esp32s2/include/soc/syscon_struct.h b/components/soc/esp32s2/include/soc/syscon_struct.h index d40e2dff50..6509b9a751 100644 --- a/components/soc/esp32s2/include/soc/syscon_struct.h +++ b/components/soc/esp32s2/include/soc/syscon_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct syscon_dev_s { union { struct { uint32_t pre_div: 10; @@ -29,7 +29,7 @@ typedef volatile struct { uint32_t reserved16: 16; }; uint32_t val; - } apb_ctrl_sysclk_conf; + } sysclk_conf; union { struct { uint32_t xtal_tick: 8; @@ -38,7 +38,7 @@ typedef volatile struct { uint32_t reserved17: 15; }; uint32_t val; - } apb_ctrl_tick_conf; + } tick_conf; union { struct { uint32_t clk20_oen: 1; @@ -55,7 +55,7 @@ typedef volatile struct { uint32_t reserved11: 21; }; uint32_t val; - } apb_ctrl_clk_out_en; + } clk_out_en; union { struct { uint32_t peri_io_swap: 8; diff --git a/components/soc/esp32s2/include/soc/systimer_struct.h b/components/soc/esp32s2/include/soc/systimer_struct.h index 48b1d79276..23783b39f4 100644 --- a/components/soc/esp32s2/include/soc/systimer_struct.h +++ b/components/soc/esp32s2/include/soc/systimer_struct.h @@ -91,6 +91,7 @@ typedef union { * system timer accumulation step when using PLL */ uint32_t timer_pll_step: 10; + uint32_t reserved20: 12; }; uint32_t val; } systimer_step_reg_t; @@ -201,6 +202,7 @@ typedef union { * system timer target2 interrupt enable */ uint32_t systimer_int2_ena: 1; + uint32_t reserved3: 29; }; uint32_t val; } systimer_int_ena_reg_t; @@ -222,6 +224,7 @@ typedef union { * system timer target2 interrupt raw */ uint32_t systimer_int2_raw: 1; + uint32_t reserved3: 29; }; uint32_t val; } systimer_int_raw_reg_t; @@ -243,6 +246,7 @@ typedef union { * system timer target2 interrupt clear */ uint32_t systimer_int2_clr: 1; + uint32_t reserved3: 29; }; uint32_t val; } systimer_int_clr_reg_t; diff --git a/components/soc/esp32s2/include/soc/timer_group_reg.h b/components/soc/esp32s2/include/soc/timer_group_reg.h index fdef7ff277..a74c3e2e5e 100644 --- a/components/soc/esp32s2/include/soc/timer_group_reg.h +++ b/components/soc/esp32s2/include/soc/timer_group_reg.h @@ -1,24 +1,17 @@ -// Copyright 2017-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. -#ifndef _SOC_TIMG_REG_H_ -#define _SOC_TIMG_REG_H_ - +/** + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once +#include +#include "soc/soc.h" #ifdef __cplusplus extern "C" { #endif -#include "soc.h" + +#define DR_REG_TIMG_BASE(i) REG_TIMG_BASE(i) /* The value that needs to be written to TIMG_WDT_WKEY to write-enable the wdt registers */ #define TIMG_WDT_WKEY_VALUE 0x50D83AA1 @@ -39,694 +32,984 @@ extern "C" { #define TIMG_WDT_RESET_LENGTH_1600_NS 6 #define TIMG_WDT_RESET_LENGTH_3200_NS 7 -#define TIMG_T0CONFIG_REG(i) (REG_TIMG_BASE(i) + 0x0000) -/* TIMG_T0_EN : R/W ;bitpos:[31] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T0_EN (BIT(31)) -#define TIMG_T0_EN_M (BIT(31)) -#define TIMG_T0_EN_V 0x1 -#define TIMG_T0_EN_S 31 -/* TIMG_T0_INCREASE : R/W ;bitpos:[30] ;default: 1'h1 ; */ -/*description: */ -#define TIMG_T0_INCREASE (BIT(30)) -#define TIMG_T0_INCREASE_M (BIT(30)) -#define TIMG_T0_INCREASE_V 0x1 -#define TIMG_T0_INCREASE_S 30 -/* TIMG_T0_AUTORELOAD : R/W ;bitpos:[29] ;default: 1'h1 ; */ -/*description: */ -#define TIMG_T0_AUTORELOAD (BIT(29)) -#define TIMG_T0_AUTORELOAD_M (BIT(29)) -#define TIMG_T0_AUTORELOAD_V 0x1 -#define TIMG_T0_AUTORELOAD_S 29 -/* TIMG_T0_DIVIDER : R/W ;bitpos:[28:13] ;default: 16'h1 ; */ -/*description: */ -#define TIMG_T0_DIVIDER 0x0000FFFF -#define TIMG_T0_DIVIDER_M ((TIMG_T0_DIVIDER_V)<<(TIMG_T0_DIVIDER_S)) -#define TIMG_T0_DIVIDER_V 0xFFFF -#define TIMG_T0_DIVIDER_S 13 -/* TIMG_T0_EDGE_INT_EN : R/W ;bitpos:[12] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T0_EDGE_INT_EN (BIT(12)) -#define TIMG_T0_EDGE_INT_EN_M (BIT(12)) -#define TIMG_T0_EDGE_INT_EN_V 0x1 -#define TIMG_T0_EDGE_INT_EN_S 12 -/* TIMG_T0_LEVEL_INT_EN : R/W ;bitpos:[11] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T0_LEVEL_INT_EN (BIT(11)) -#define TIMG_T0_LEVEL_INT_EN_M (BIT(11)) -#define TIMG_T0_LEVEL_INT_EN_V 0x1 -#define TIMG_T0_LEVEL_INT_EN_S 11 -/* TIMG_T0_ALARM_EN : R/W ;bitpos:[10] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T0_ALARM_EN (BIT(10)) -#define TIMG_T0_ALARM_EN_M (BIT(10)) -#define TIMG_T0_ALARM_EN_V 0x1 -#define TIMG_T0_ALARM_EN_S 10 -/* TIMG_T0_USE_XTAL : R/W ;bitpos:[9] ;default: 1'd0 ; */ -/*description: */ -#define TIMG_T0_USE_XTAL (BIT(9)) -#define TIMG_T0_USE_XTAL_M (BIT(9)) -#define TIMG_T0_USE_XTAL_V 0x1 +/** TIMG_T0CONFIG_REG register + * Timer 0 configuration register + */ +#define TIMG_T0CONFIG_REG(i) (DR_REG_TIMG_BASE(i) + 0x0) +/** TIMG_T0_USE_XTAL : R/W; bitpos: [9]; default: 0; + * 1: Use XTAL_CLK as the source clock of timer group. 0: Use APB_CLK as the source + * clock of timer group. + */ +#define TIMG_T0_USE_XTAL (BIT(9)) +#define TIMG_T0_USE_XTAL_M (TIMG_T0_USE_XTAL_V << TIMG_T0_USE_XTAL_S) +#define TIMG_T0_USE_XTAL_V 0x00000001U #define TIMG_T0_USE_XTAL_S 9 +/** TIMG_T0_ALARM_EN : R/W; bitpos: [10]; default: 0; + * When set, the alarm is enabled. This bit is automatically cleared once an + * + * alarm occurs. + */ +#define TIMG_T0_ALARM_EN (BIT(10)) +#define TIMG_T0_ALARM_EN_M (TIMG_T0_ALARM_EN_V << TIMG_T0_ALARM_EN_S) +#define TIMG_T0_ALARM_EN_V 0x00000001U +#define TIMG_T0_ALARM_EN_S 10 +/** TIMG_T0_LEVEL_INT_EN : R/W; bitpos: [11]; default: 0; + * When set, an alarm will generate a level type interrupt. + */ +#define TIMG_T0_LEVEL_INT_EN (BIT(11)) +#define TIMG_T0_LEVEL_INT_EN_M (TIMG_T0_LEVEL_INT_EN_V << TIMG_T0_LEVEL_INT_EN_S) +#define TIMG_T0_LEVEL_INT_EN_V 0x00000001U +#define TIMG_T0_LEVEL_INT_EN_S 11 +/** TIMG_T0_EDGE_INT_EN : R/W; bitpos: [12]; default: 0; + * When set, an alarm will generate an edge type interrupt. + */ +#define TIMG_T0_EDGE_INT_EN (BIT(12)) +#define TIMG_T0_EDGE_INT_EN_M (TIMG_T0_EDGE_INT_EN_V << TIMG_T0_EDGE_INT_EN_S) +#define TIMG_T0_EDGE_INT_EN_V 0x00000001U +#define TIMG_T0_EDGE_INT_EN_S 12 +/** TIMG_T0_DIVIDER : R/W; bitpos: [28:13]; default: 1; + * Timer 0 clock (T0_clk) prescaler value. + */ +#define TIMG_T0_DIVIDER 0x0000FFFFU +#define TIMG_T0_DIVIDER_M (TIMG_T0_DIVIDER_V << TIMG_T0_DIVIDER_S) +#define TIMG_T0_DIVIDER_V 0x0000FFFFU +#define TIMG_T0_DIVIDER_S 13 +/** TIMG_T0_AUTORELOAD : R/W; bitpos: [29]; default: 1; + * When set, timer 0 auto-reload at alarm is enabled. + */ +#define TIMG_T0_AUTORELOAD (BIT(29)) +#define TIMG_T0_AUTORELOAD_M (TIMG_T0_AUTORELOAD_V << TIMG_T0_AUTORELOAD_S) +#define TIMG_T0_AUTORELOAD_V 0x00000001U +#define TIMG_T0_AUTORELOAD_S 29 +/** TIMG_T0_INCREASE : R/W; bitpos: [30]; default: 1; + * When set, the timer 0 time-base counter will increment every clock tick. When + * + * cleared, the timer 0 time-base counter will decrement. + */ +#define TIMG_T0_INCREASE (BIT(30)) +#define TIMG_T0_INCREASE_M (TIMG_T0_INCREASE_V << TIMG_T0_INCREASE_S) +#define TIMG_T0_INCREASE_V 0x00000001U +#define TIMG_T0_INCREASE_S 30 +/** TIMG_T0_EN : R/W; bitpos: [31]; default: 0; + * When set, the timer 0 time-base counter is enabled. + */ +#define TIMG_T0_EN (BIT(31)) +#define TIMG_T0_EN_M (TIMG_T0_EN_V << TIMG_T0_EN_S) +#define TIMG_T0_EN_V 0x00000001U +#define TIMG_T0_EN_S 31 -#define TIMG_T0LO_REG(i) (REG_TIMG_BASE(i) + 0x0004) -/* TIMG_T0_LO : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define TIMG_T0_LO 0xFFFFFFFF -#define TIMG_T0_LO_M ((TIMG_T0_LO_V)<<(TIMG_T0_LO_S)) -#define TIMG_T0_LO_V 0xFFFFFFFF +/** TIMG_T0LO_REG register + * Timer 0 current value, low 32 bits + */ +#define TIMG_T0LO_REG(i) (DR_REG_TIMG_BASE(i) + 0x4) +/** TIMG_T0_LO : RO; bitpos: [31:0]; default: 0; + * After writing to TIMG_T0UPDATE_REG, the low 32 bits of the time-base counter + * + * of timer 0 can be read here. + */ +#define TIMG_T0_LO 0xFFFFFFFFU +#define TIMG_T0_LO_M (TIMG_T0_LO_V << TIMG_T0_LO_S) +#define TIMG_T0_LO_V 0xFFFFFFFFU #define TIMG_T0_LO_S 0 -#define TIMG_T0HI_REG(i) (REG_TIMG_BASE(i) + 0x0008) -/* TIMG_T0_HI : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define TIMG_T0_HI 0xFFFFFFFF -#define TIMG_T0_HI_M ((TIMG_T0_HI_V)<<(TIMG_T0_HI_S)) -#define TIMG_T0_HI_V 0xFFFFFFFF +/** TIMG_T0HI_REG register + * Timer 0 current value, high 32 bits + */ +#define TIMG_T0HI_REG(i) (DR_REG_TIMG_BASE(i) + 0x8) +/** TIMG_T0_HI : RO; bitpos: [31:0]; default: 0; + * After writing to TIMG_T0UPDATE_REG, the high 32 bits of the time-base counter + * + * of timer 0 can be read here. + */ +#define TIMG_T0_HI 0xFFFFFFFFU +#define TIMG_T0_HI_M (TIMG_T0_HI_V << TIMG_T0_HI_S) +#define TIMG_T0_HI_V 0xFFFFFFFFU #define TIMG_T0_HI_S 0 -#define TIMG_T0UPDATE_REG(i) (REG_TIMG_BASE(i) + 0x000c) -/* TIMG_T0_UPDATE : R/W ;bitpos:[31] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T0_UPDATE (BIT(31)) -#define TIMG_T0_UPDATE_M (BIT(31)) -#define TIMG_T0_UPDATE_V 0x1 +/** TIMG_T0UPDATE_REG register + * Write to copy current timer value to TIMGn_T0_(LO/HI)_REG + */ +#define TIMG_T0UPDATE_REG(i) (DR_REG_TIMG_BASE(i) + 0xc) +/** TIMG_T0_UPDATE : R/W; bitpos: [31]; default: 0; + * After writing 0 or 1 to TIMG_T0UPDATE_REG, the counter value is latched. + */ +#define TIMG_T0_UPDATE (BIT(31)) +#define TIMG_T0_UPDATE_M (TIMG_T0_UPDATE_V << TIMG_T0_UPDATE_S) +#define TIMG_T0_UPDATE_V 0x00000001U #define TIMG_T0_UPDATE_S 31 -#define TIMG_T0ALARMLO_REG(i) (REG_TIMG_BASE(i) + 0x0010) -/* TIMG_T0_ALARM_LO : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define TIMG_T0_ALARM_LO 0xFFFFFFFF -#define TIMG_T0_ALARM_LO_M ((TIMG_T0_ALARM_LO_V)<<(TIMG_T0_ALARM_LO_S)) -#define TIMG_T0_ALARM_LO_V 0xFFFFFFFF +/** TIMG_T0ALARMLO_REG register + * Timer 0 alarm value, low 32 bits + */ +#define TIMG_T0ALARMLO_REG(i) (DR_REG_TIMG_BASE(i) + 0x10) +/** TIMG_T0_ALARM_LO : R/W; bitpos: [31:0]; default: 0; + * Timer 0 alarm trigger time-base counter value, low 32 bits. + */ +#define TIMG_T0_ALARM_LO 0xFFFFFFFFU +#define TIMG_T0_ALARM_LO_M (TIMG_T0_ALARM_LO_V << TIMG_T0_ALARM_LO_S) +#define TIMG_T0_ALARM_LO_V 0xFFFFFFFFU #define TIMG_T0_ALARM_LO_S 0 -#define TIMG_T0ALARMHI_REG(i) (REG_TIMG_BASE(i) + 0x0014) -/* TIMG_T0_ALARM_HI : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define TIMG_T0_ALARM_HI 0xFFFFFFFF -#define TIMG_T0_ALARM_HI_M ((TIMG_T0_ALARM_HI_V)<<(TIMG_T0_ALARM_HI_S)) -#define TIMG_T0_ALARM_HI_V 0xFFFFFFFF +/** TIMG_T0ALARMHI_REG register + * Timer 0 alarm value, high bits + */ +#define TIMG_T0ALARMHI_REG(i) (DR_REG_TIMG_BASE(i) + 0x14) +/** TIMG_T0_ALARM_HI : R/W; bitpos: [31:0]; default: 0; + * + * + * Timer 0 alarm trigger time-base counter value, high 32 bits. + */ +#define TIMG_T0_ALARM_HI 0xFFFFFFFFU +#define TIMG_T0_ALARM_HI_M (TIMG_T0_ALARM_HI_V << TIMG_T0_ALARM_HI_S) +#define TIMG_T0_ALARM_HI_V 0xFFFFFFFFU #define TIMG_T0_ALARM_HI_S 0 -#define TIMG_T0LOADLO_REG(i) (REG_TIMG_BASE(i) + 0x0018) -/* TIMG_T0_LOAD_LO : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define TIMG_T0_LOAD_LO 0xFFFFFFFF -#define TIMG_T0_LOAD_LO_M ((TIMG_T0_LOAD_LO_V)<<(TIMG_T0_LOAD_LO_S)) -#define TIMG_T0_LOAD_LO_V 0xFFFFFFFF +/** TIMG_T0LOADLO_REG register + * Timer 0 reload value, low 32 bits + */ +#define TIMG_T0LOADLO_REG(i) (DR_REG_TIMG_BASE(i) + 0x18) +/** TIMG_T0_LOAD_LO : R/W; bitpos: [31:0]; default: 0; + * + * + * Low 32 bits of the value that a reload will load onto timer 0 time-base + * + * Counter. + */ +#define TIMG_T0_LOAD_LO 0xFFFFFFFFU +#define TIMG_T0_LOAD_LO_M (TIMG_T0_LOAD_LO_V << TIMG_T0_LOAD_LO_S) +#define TIMG_T0_LOAD_LO_V 0xFFFFFFFFU #define TIMG_T0_LOAD_LO_S 0 -#define TIMG_T0LOADHI_REG(i) (REG_TIMG_BASE(i) + 0x001c) -/* TIMG_T0_LOAD_HI : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define TIMG_T0_LOAD_HI 0xFFFFFFFF -#define TIMG_T0_LOAD_HI_M ((TIMG_T0_LOAD_HI_V)<<(TIMG_T0_LOAD_HI_S)) -#define TIMG_T0_LOAD_HI_V 0xFFFFFFFF +/** TIMG_T0LOADHI_REG register + * Timer 0 reload value, high 32 bits + */ +#define TIMG_T0LOADHI_REG(i) (DR_REG_TIMG_BASE(i) + 0x1c) +/** TIMG_T0_LOAD_HI : R/W; bitpos: [31:0]; default: 0; + * + * + * High 32 bits of the value that a reload will load onto timer 0 time-base + * + * counter. + */ +#define TIMG_T0_LOAD_HI 0xFFFFFFFFU +#define TIMG_T0_LOAD_HI_M (TIMG_T0_LOAD_HI_V << TIMG_T0_LOAD_HI_S) +#define TIMG_T0_LOAD_HI_V 0xFFFFFFFFU #define TIMG_T0_LOAD_HI_S 0 -#define TIMG_T0LOAD_REG(i) (REG_TIMG_BASE(i) + 0x0020) -/* TIMG_T0_LOAD : WO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define TIMG_T0_LOAD 0xFFFFFFFF -#define TIMG_T0_LOAD_M ((TIMG_T0_LOAD_V)<<(TIMG_T0_LOAD_S)) -#define TIMG_T0_LOAD_V 0xFFFFFFFF +/** TIMG_T0LOAD_REG register + * Write to reload timer from TIMG_T0_(LOADLOLOADHI)_REG + */ +#define TIMG_T0LOAD_REG(i) (DR_REG_TIMG_BASE(i) + 0x20) +/** TIMG_T0_LOAD : WO; bitpos: [31:0]; default: 0; + * + * + * Write any value to trigger a timer 0 time-base counter reload. + */ +#define TIMG_T0_LOAD 0xFFFFFFFFU +#define TIMG_T0_LOAD_M (TIMG_T0_LOAD_V << TIMG_T0_LOAD_S) +#define TIMG_T0_LOAD_V 0xFFFFFFFFU #define TIMG_T0_LOAD_S 0 -#define TIMG_T1CONFIG_REG(i) (REG_TIMG_BASE(i) + 0x0024) -/* TIMG_T1_EN : R/W ;bitpos:[31] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T1_EN (BIT(31)) -#define TIMG_T1_EN_M (BIT(31)) -#define TIMG_T1_EN_V 0x1 -#define TIMG_T1_EN_S 31 -/* TIMG_T1_INCREASE : R/W ;bitpos:[30] ;default: 1'h1 ; */ -/*description: */ -#define TIMG_T1_INCREASE (BIT(30)) -#define TIMG_T1_INCREASE_M (BIT(30)) -#define TIMG_T1_INCREASE_V 0x1 -#define TIMG_T1_INCREASE_S 30 -/* TIMG_T1_AUTORELOAD : R/W ;bitpos:[29] ;default: 1'h1 ; */ -/*description: */ -#define TIMG_T1_AUTORELOAD (BIT(29)) -#define TIMG_T1_AUTORELOAD_M (BIT(29)) -#define TIMG_T1_AUTORELOAD_V 0x1 -#define TIMG_T1_AUTORELOAD_S 29 -/* TIMG_T1_DIVIDER : R/W ;bitpos:[28:13] ;default: 16'h1 ; */ -/*description: */ -#define TIMG_T1_DIVIDER 0x0000FFFF -#define TIMG_T1_DIVIDER_M ((TIMG_T1_DIVIDER_V)<<(TIMG_T1_DIVIDER_S)) -#define TIMG_T1_DIVIDER_V 0xFFFF -#define TIMG_T1_DIVIDER_S 13 -/* TIMG_T1_EDGE_INT_EN : R/W ;bitpos:[12] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T1_EDGE_INT_EN (BIT(12)) -#define TIMG_T1_EDGE_INT_EN_M (BIT(12)) -#define TIMG_T1_EDGE_INT_EN_V 0x1 -#define TIMG_T1_EDGE_INT_EN_S 12 -/* TIMG_T1_LEVEL_INT_EN : R/W ;bitpos:[11] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T1_LEVEL_INT_EN (BIT(11)) -#define TIMG_T1_LEVEL_INT_EN_M (BIT(11)) -#define TIMG_T1_LEVEL_INT_EN_V 0x1 -#define TIMG_T1_LEVEL_INT_EN_S 11 -/* TIMG_T1_ALARM_EN : R/W ;bitpos:[10] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T1_ALARM_EN (BIT(10)) -#define TIMG_T1_ALARM_EN_M (BIT(10)) -#define TIMG_T1_ALARM_EN_V 0x1 -#define TIMG_T1_ALARM_EN_S 10 -/* TIMG_T1_USE_XTAL : R/W ;bitpos:[9] ;default: 1'd0 ; */ -/*description: */ -#define TIMG_T1_USE_XTAL (BIT(9)) -#define TIMG_T1_USE_XTAL_M (BIT(9)) -#define TIMG_T1_USE_XTAL_V 0x1 -#define TIMG_T1_USE_XTAL_S 9 +/** TIMG_T1CONFIG_REG register + * Timer 1 configuration register + */ +#define TIMG_T1CONFIG_REG(i) (DR_REG_TIMG_BASE(i) + 0x24) +/** TIMG_T0_USE_XTAL : R/W; bitpos: [9]; default: 0; + * 1: Use XTAL_CLK as the source clock of timer group. 0: Use APB_CLK as the source + * clock of timer group. + */ +#define TIMG_T0_USE_XTAL (BIT(9)) +#define TIMG_T0_USE_XTAL_M (TIMG_T0_USE_XTAL_V << TIMG_T0_USE_XTAL_S) +#define TIMG_T0_USE_XTAL_V 0x00000001U +#define TIMG_T0_USE_XTAL_S 9 +/** TIMG_T0_ALARM_EN : R/W; bitpos: [10]; default: 0; + * When set, the alarm is enabled. This bit is automatically cleared once an + * + * alarm occurs. + */ +#define TIMG_T0_ALARM_EN (BIT(10)) +#define TIMG_T0_ALARM_EN_M (TIMG_T0_ALARM_EN_V << TIMG_T0_ALARM_EN_S) +#define TIMG_T0_ALARM_EN_V 0x00000001U +#define TIMG_T0_ALARM_EN_S 10 +/** TIMG_T0_LEVEL_INT_EN : R/W; bitpos: [11]; default: 0; + * When set, an alarm will generate a level type interrupt. + */ +#define TIMG_T0_LEVEL_INT_EN (BIT(11)) +#define TIMG_T0_LEVEL_INT_EN_M (TIMG_T0_LEVEL_INT_EN_V << TIMG_T0_LEVEL_INT_EN_S) +#define TIMG_T0_LEVEL_INT_EN_V 0x00000001U +#define TIMG_T0_LEVEL_INT_EN_S 11 +/** TIMG_T0_EDGE_INT_EN : R/W; bitpos: [12]; default: 0; + * When set, an alarm will generate an edge type interrupt. + */ +#define TIMG_T0_EDGE_INT_EN (BIT(12)) +#define TIMG_T0_EDGE_INT_EN_M (TIMG_T0_EDGE_INT_EN_V << TIMG_T0_EDGE_INT_EN_S) +#define TIMG_T0_EDGE_INT_EN_V 0x00000001U +#define TIMG_T0_EDGE_INT_EN_S 12 +/** TIMG_T0_DIVIDER : R/W; bitpos: [28:13]; default: 1; + * Timer 1 clock (T1_clk) prescaler value. + */ +#define TIMG_T0_DIVIDER 0x0000FFFFU +#define TIMG_T0_DIVIDER_M (TIMG_T0_DIVIDER_V << TIMG_T0_DIVIDER_S) +#define TIMG_T0_DIVIDER_V 0x0000FFFFU +#define TIMG_T0_DIVIDER_S 13 +/** TIMG_T0_AUTORELOAD : R/W; bitpos: [29]; default: 1; + * When set, timer 1 auto-reload at alarm is enabled. + */ +#define TIMG_T0_AUTORELOAD (BIT(29)) +#define TIMG_T0_AUTORELOAD_M (TIMG_T0_AUTORELOAD_V << TIMG_T0_AUTORELOAD_S) +#define TIMG_T0_AUTORELOAD_V 0x00000001U +#define TIMG_T0_AUTORELOAD_S 29 +/** TIMG_T0_INCREASE : R/W; bitpos: [30]; default: 1; + * When set, the timer 1 time-base counter will increment every clock tick. When + * + * cleared, the timer 1 time-base counter will decrement. + */ +#define TIMG_T0_INCREASE (BIT(30)) +#define TIMG_T0_INCREASE_M (TIMG_T0_INCREASE_V << TIMG_T0_INCREASE_S) +#define TIMG_T0_INCREASE_V 0x00000001U +#define TIMG_T0_INCREASE_S 30 +/** TIMG_T0_EN : R/W; bitpos: [31]; default: 0; + * When set, the timer 1 time-base counter is enabled. + */ +#define TIMG_T0_EN (BIT(31)) +#define TIMG_T0_EN_M (TIMG_T0_EN_V << TIMG_T0_EN_S) +#define TIMG_T0_EN_V 0x00000001U +#define TIMG_T0_EN_S 31 -#define TIMG_T1LO_REG(i) (REG_TIMG_BASE(i) + 0x0028) -/* TIMG_T1_LO : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define TIMG_T1_LO 0xFFFFFFFF -#define TIMG_T1_LO_M ((TIMG_T1_LO_V)<<(TIMG_T1_LO_S)) -#define TIMG_T1_LO_V 0xFFFFFFFF -#define TIMG_T1_LO_S 0 +/** TIMG_T1LO_REG register + * Timer 1 current value, low 32 bits + */ +#define TIMG_T1LO_REG(i) (DR_REG_TIMG_BASE(i) + 0x28) +/** TIMG_T0_LO : RO; bitpos: [31:0]; default: 0; + * After writing to TIMG_T1UPDATE_REG, the low 32 bits of the time-base counter + * + * of timer 1 can be read here. + */ +#define TIMG_T0_LO 0xFFFFFFFFU +#define TIMG_T0_LO_M (TIMG_T0_LO_V << TIMG_T0_LO_S) +#define TIMG_T0_LO_V 0xFFFFFFFFU +#define TIMG_T0_LO_S 0 -#define TIMG_T1HI_REG(i) (REG_TIMG_BASE(i) + 0x002c) -/* TIMG_T1_HI : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define TIMG_T1_HI 0xFFFFFFFF -#define TIMG_T1_HI_M ((TIMG_T1_HI_V)<<(TIMG_T1_HI_S)) -#define TIMG_T1_HI_V 0xFFFFFFFF -#define TIMG_T1_HI_S 0 +/** TIMG_T1HI_REG register + * Timer 1 current value, high 32 bits + */ +#define TIMG_T1HI_REG(i) (DR_REG_TIMG_BASE(i) + 0x2c) +/** TIMG_T0_HI : RO; bitpos: [31:0]; default: 0; + * After writing to TIMG_T1UPDATE_REG, the high 32 bits of the time-base counter + * + * of timer 1 can be read here. + */ +#define TIMG_T0_HI 0xFFFFFFFFU +#define TIMG_T0_HI_M (TIMG_T0_HI_V << TIMG_T0_HI_S) +#define TIMG_T0_HI_V 0xFFFFFFFFU +#define TIMG_T0_HI_S 0 -#define TIMG_T1UPDATE_REG(i) (REG_TIMG_BASE(i) + 0x0030) -/* TIMG_T1_UPDATE : R/W ;bitpos:[31] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T1_UPDATE (BIT(31)) -#define TIMG_T1_UPDATE_M (BIT(31)) -#define TIMG_T1_UPDATE_V 0x1 -#define TIMG_T1_UPDATE_S 31 +/** TIMG_T1UPDATE_REG register + * Write to copy current timer value to TIMGn_T1_(LO/HI)_REG + */ +#define TIMG_T1UPDATE_REG(i) (DR_REG_TIMG_BASE(i) + 0x30) +/** TIMG_T0_UPDATE : R/W; bitpos: [31]; default: 0; + * After writing 0 or 1 to TIMG_T1UPDATE_REG, the counter value is latched. + */ +#define TIMG_T0_UPDATE (BIT(31)) +#define TIMG_T0_UPDATE_M (TIMG_T0_UPDATE_V << TIMG_T0_UPDATE_S) +#define TIMG_T0_UPDATE_V 0x00000001U +#define TIMG_T0_UPDATE_S 31 -#define TIMG_T1ALARMLO_REG(i) (REG_TIMG_BASE(i) + 0x0034) -/* TIMG_T1_ALARM_LO : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define TIMG_T1_ALARM_LO 0xFFFFFFFF -#define TIMG_T1_ALARM_LO_M ((TIMG_T1_ALARM_LO_V)<<(TIMG_T1_ALARM_LO_S)) -#define TIMG_T1_ALARM_LO_V 0xFFFFFFFF -#define TIMG_T1_ALARM_LO_S 0 +/** TIMG_T1ALARMLO_REG register + * Timer 1 alarm value, low 32 bits + */ +#define TIMG_T1ALARMLO_REG(i) (DR_REG_TIMG_BASE(i) + 0x34) +/** TIMG_T0_ALARM_LO : R/W; bitpos: [31:0]; default: 0; + * Timer 1 alarm trigger time-base counter value, low 32 bits. + */ +#define TIMG_T0_ALARM_LO 0xFFFFFFFFU +#define TIMG_T0_ALARM_LO_M (TIMG_T0_ALARM_LO_V << TIMG_T0_ALARM_LO_S) +#define TIMG_T0_ALARM_LO_V 0xFFFFFFFFU +#define TIMG_T0_ALARM_LO_S 0 -#define TIMG_T1ALARMHI_REG(i) (REG_TIMG_BASE(i) + 0x0038) -/* TIMG_T1_ALARM_HI : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define TIMG_T1_ALARM_HI 0xFFFFFFFF -#define TIMG_T1_ALARM_HI_M ((TIMG_T1_ALARM_HI_V)<<(TIMG_T1_ALARM_HI_S)) -#define TIMG_T1_ALARM_HI_V 0xFFFFFFFF -#define TIMG_T1_ALARM_HI_S 0 +/** TIMG_T1ALARMHI_REG register + * Timer 1 alarm value, high bits + */ +#define TIMG_T1ALARMHI_REG(i) (DR_REG_TIMG_BASE(i) + 0x38) +/** TIMG_T0_ALARM_HI : R/W; bitpos: [31:0]; default: 0; + * + * + * Timer 1 alarm trigger time-base counter value, high 32 bits. + */ +#define TIMG_T0_ALARM_HI 0xFFFFFFFFU +#define TIMG_T0_ALARM_HI_M (TIMG_T0_ALARM_HI_V << TIMG_T0_ALARM_HI_S) +#define TIMG_T0_ALARM_HI_V 0xFFFFFFFFU +#define TIMG_T0_ALARM_HI_S 0 -#define TIMG_T1LOADLO_REG(i) (REG_TIMG_BASE(i) + 0x003c) -/* TIMG_T1_LOAD_LO : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define TIMG_T1_LOAD_LO 0xFFFFFFFF -#define TIMG_T1_LOAD_LO_M ((TIMG_T1_LOAD_LO_V)<<(TIMG_T1_LOAD_LO_S)) -#define TIMG_T1_LOAD_LO_V 0xFFFFFFFF -#define TIMG_T1_LOAD_LO_S 0 +/** TIMG_T1LOADLO_REG register + * Timer 1 reload value, low 32 bits + */ +#define TIMG_T1LOADLO_REG(i) (DR_REG_TIMG_BASE(i) + 0x3c) +/** TIMG_T0_LOAD_LO : R/W; bitpos: [31:0]; default: 0; + * + * + * Low 32 bits of the value that a reload will load onto timer 1 time-base + * + * Counter. + */ +#define TIMG_T0_LOAD_LO 0xFFFFFFFFU +#define TIMG_T0_LOAD_LO_M (TIMG_T0_LOAD_LO_V << TIMG_T0_LOAD_LO_S) +#define TIMG_T0_LOAD_LO_V 0xFFFFFFFFU +#define TIMG_T0_LOAD_LO_S 0 -#define TIMG_T1LOADHI_REG(i) (REG_TIMG_BASE(i) + 0x0040) -/* TIMG_T1_LOAD_HI : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define TIMG_T1_LOAD_HI 0xFFFFFFFF -#define TIMG_T1_LOAD_HI_M ((TIMG_T1_LOAD_HI_V)<<(TIMG_T1_LOAD_HI_S)) -#define TIMG_T1_LOAD_HI_V 0xFFFFFFFF -#define TIMG_T1_LOAD_HI_S 0 +/** TIMG_T1LOADHI_REG register + * Timer 1 reload value, high 32 bits + */ +#define TIMG_T1LOADHI_REG(i) (DR_REG_TIMG_BASE(i) + 0x40) +/** TIMG_T0_LOAD_HI : R/W; bitpos: [31:0]; default: 0; + * + * + * High 32 bits of the value that a reload will load onto timer 1 time-base + * + * counter. + */ +#define TIMG_T0_LOAD_HI 0xFFFFFFFFU +#define TIMG_T0_LOAD_HI_M (TIMG_T0_LOAD_HI_V << TIMG_T0_LOAD_HI_S) +#define TIMG_T0_LOAD_HI_V 0xFFFFFFFFU +#define TIMG_T0_LOAD_HI_S 0 -#define TIMG_T1LOAD_REG(i) (REG_TIMG_BASE(i) + 0x0044) -/* TIMG_T1_LOAD : WO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define TIMG_T1_LOAD 0xFFFFFFFF -#define TIMG_T1_LOAD_M ((TIMG_T1_LOAD_V)<<(TIMG_T1_LOAD_S)) -#define TIMG_T1_LOAD_V 0xFFFFFFFF -#define TIMG_T1_LOAD_S 0 +/** TIMG_T1LOAD_REG register + * Write to reload timer from TIMG_T0_(LOADLOLOADHI)_REG + */ +#define TIMG_T1LOAD_REG(i) (DR_REG_TIMG_BASE(i) + 0x44) +/** TIMG_T0_LOAD : WO; bitpos: [31:0]; default: 0; + * + * + * Write any value to trigger a timer 1 time-base counter reload. + */ +#define TIMG_T0_LOAD 0xFFFFFFFFU +#define TIMG_T0_LOAD_M (TIMG_T0_LOAD_V << TIMG_T0_LOAD_S) +#define TIMG_T0_LOAD_V 0xFFFFFFFFU +#define TIMG_T0_LOAD_S 0 -#define TIMG_WDTCONFIG0_REG(i) (REG_TIMG_BASE(i) + 0x0048) -/* TIMG_WDT_EN : R/W ;bitpos:[31] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_WDT_EN (BIT(31)) -#define TIMG_WDT_EN_M (BIT(31)) -#define TIMG_WDT_EN_V 0x1 -#define TIMG_WDT_EN_S 31 -/* TIMG_WDT_STG0 : R/W ;bitpos:[30:29] ;default: 1'd0 ; */ -/*description: */ -#define TIMG_WDT_STG0 0x00000003 -#define TIMG_WDT_STG0_M ((TIMG_WDT_STG0_V)<<(TIMG_WDT_STG0_S)) -#define TIMG_WDT_STG0_V 0x3 -#define TIMG_WDT_STG0_S 29 -/* TIMG_WDT_STG1 : R/W ;bitpos:[28:27] ;default: 1'd0 ; */ -/*description: */ -#define TIMG_WDT_STG1 0x00000003 -#define TIMG_WDT_STG1_M ((TIMG_WDT_STG1_V)<<(TIMG_WDT_STG1_S)) -#define TIMG_WDT_STG1_V 0x3 -#define TIMG_WDT_STG1_S 27 -/* TIMG_WDT_STG2 : R/W ;bitpos:[26:25] ;default: 1'd0 ; */ -/*description: */ -#define TIMG_WDT_STG2 0x00000003 -#define TIMG_WDT_STG2_M ((TIMG_WDT_STG2_V)<<(TIMG_WDT_STG2_S)) -#define TIMG_WDT_STG2_V 0x3 -#define TIMG_WDT_STG2_S 25 -/* TIMG_WDT_STG3 : R/W ;bitpos:[24:23] ;default: 1'd0 ; */ -/*description: */ -#define TIMG_WDT_STG3 0x00000003 -#define TIMG_WDT_STG3_M ((TIMG_WDT_STG3_V)<<(TIMG_WDT_STG3_S)) -#define TIMG_WDT_STG3_V 0x3 -#define TIMG_WDT_STG3_S 23 -/* TIMG_WDT_EDGE_INT_EN : R/W ;bitpos:[22] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_WDT_EDGE_INT_EN (BIT(22)) -#define TIMG_WDT_EDGE_INT_EN_M (BIT(22)) -#define TIMG_WDT_EDGE_INT_EN_V 0x1 -#define TIMG_WDT_EDGE_INT_EN_S 22 -/* TIMG_WDT_LEVEL_INT_EN : R/W ;bitpos:[21] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_WDT_LEVEL_INT_EN (BIT(21)) -#define TIMG_WDT_LEVEL_INT_EN_M (BIT(21)) -#define TIMG_WDT_LEVEL_INT_EN_V 0x1 -#define TIMG_WDT_LEVEL_INT_EN_S 21 -/* TIMG_WDT_CPU_RESET_LENGTH : R/W ;bitpos:[20:18] ;default: 3'h1 ; */ -/*description: */ -#define TIMG_WDT_CPU_RESET_LENGTH 0x00000007 -#define TIMG_WDT_CPU_RESET_LENGTH_M ((TIMG_WDT_CPU_RESET_LENGTH_V)<<(TIMG_WDT_CPU_RESET_LENGTH_S)) -#define TIMG_WDT_CPU_RESET_LENGTH_V 0x7 -#define TIMG_WDT_CPU_RESET_LENGTH_S 18 -/* TIMG_WDT_SYS_RESET_LENGTH : R/W ;bitpos:[17:15] ;default: 3'h1 ; */ -/*description: */ -#define TIMG_WDT_SYS_RESET_LENGTH 0x00000007 -#define TIMG_WDT_SYS_RESET_LENGTH_M ((TIMG_WDT_SYS_RESET_LENGTH_V)<<(TIMG_WDT_SYS_RESET_LENGTH_S)) -#define TIMG_WDT_SYS_RESET_LENGTH_V 0x7 -#define TIMG_WDT_SYS_RESET_LENGTH_S 15 -/* TIMG_WDT_FLASHBOOT_MOD_EN : R/W ;bitpos:[14] ;default: 1'h1 ; */ -/*description: */ -#define TIMG_WDT_FLASHBOOT_MOD_EN (BIT(14)) -#define TIMG_WDT_FLASHBOOT_MOD_EN_M (BIT(14)) -#define TIMG_WDT_FLASHBOOT_MOD_EN_V 0x1 -#define TIMG_WDT_FLASHBOOT_MOD_EN_S 14 -/* TIMG_WDT_PROCPU_RESET_EN : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: */ -#define TIMG_WDT_PROCPU_RESET_EN (BIT(13)) -#define TIMG_WDT_PROCPU_RESET_EN_M (BIT(13)) -#define TIMG_WDT_PROCPU_RESET_EN_V 0x1 -#define TIMG_WDT_PROCPU_RESET_EN_S 13 -/* TIMG_WDT_APPCPU_RESET_EN : R/W ;bitpos:[12] ;default: 1'd0 ; */ -/*description: */ -#define TIMG_WDT_APPCPU_RESET_EN (BIT(12)) -#define TIMG_WDT_APPCPU_RESET_EN_M (BIT(12)) -#define TIMG_WDT_APPCPU_RESET_EN_V 0x1 +/** TIMG_WDTCONFIG0_REG register + * Watchdog timer configuration register + */ +#define TIMG_WDTCONFIG0_REG(i) (DR_REG_TIMG_BASE(i) + 0x48) +/** TIMG_WDT_APPCPU_RESET_EN : R/W; bitpos: [12]; default: 0; + * Reserved + */ +#define TIMG_WDT_APPCPU_RESET_EN (BIT(12)) +#define TIMG_WDT_APPCPU_RESET_EN_M (TIMG_WDT_APPCPU_RESET_EN_V << TIMG_WDT_APPCPU_RESET_EN_S) +#define TIMG_WDT_APPCPU_RESET_EN_V 0x00000001U #define TIMG_WDT_APPCPU_RESET_EN_S 12 +/** TIMG_WDT_PROCPU_RESET_EN : R/W; bitpos: [13]; default: 0; + * WDT reset CPU enable. + */ +#define TIMG_WDT_PROCPU_RESET_EN (BIT(13)) +#define TIMG_WDT_PROCPU_RESET_EN_M (TIMG_WDT_PROCPU_RESET_EN_V << TIMG_WDT_PROCPU_RESET_EN_S) +#define TIMG_WDT_PROCPU_RESET_EN_V 0x00000001U +#define TIMG_WDT_PROCPU_RESET_EN_S 13 +/** TIMG_WDT_FLASHBOOT_MOD_EN : R/W; bitpos: [14]; default: 1; + * When set, Flash boot protection is enabled. + */ +#define TIMG_WDT_FLASHBOOT_MOD_EN (BIT(14)) +#define TIMG_WDT_FLASHBOOT_MOD_EN_M (TIMG_WDT_FLASHBOOT_MOD_EN_V << TIMG_WDT_FLASHBOOT_MOD_EN_S) +#define TIMG_WDT_FLASHBOOT_MOD_EN_V 0x00000001U +#define TIMG_WDT_FLASHBOOT_MOD_EN_S 14 +/** TIMG_WDT_SYS_RESET_LENGTH : R/W; bitpos: [17:15]; default: 1; + * System reset signal length selection. 0: 100 ns, 1: 200 ns, + * + * 2: 300 ns, 3: 400 ns, 4: 500 ns, 5: 800 ns, 6: 1.6 us, 7: 3.2 us. + */ +#define TIMG_WDT_SYS_RESET_LENGTH 0x00000007U +#define TIMG_WDT_SYS_RESET_LENGTH_M (TIMG_WDT_SYS_RESET_LENGTH_V << TIMG_WDT_SYS_RESET_LENGTH_S) +#define TIMG_WDT_SYS_RESET_LENGTH_V 0x00000007U +#define TIMG_WDT_SYS_RESET_LENGTH_S 15 +/** TIMG_WDT_CPU_RESET_LENGTH : R/W; bitpos: [20:18]; default: 1; + * CPU reset signal length selection. 0: 100 ns, 1: 200 ns, + * + * 2: 300 ns, 3: 400 ns, 4: 500 ns, 5: 800 ns, 6: 1.6 us, 7: 3.2 us. + */ +#define TIMG_WDT_CPU_RESET_LENGTH 0x00000007U +#define TIMG_WDT_CPU_RESET_LENGTH_M (TIMG_WDT_CPU_RESET_LENGTH_V << TIMG_WDT_CPU_RESET_LENGTH_S) +#define TIMG_WDT_CPU_RESET_LENGTH_V 0x00000007U +#define TIMG_WDT_CPU_RESET_LENGTH_S 18 +/** TIMG_WDT_LEVEL_INT_EN : R/W; bitpos: [21]; default: 0; + * When set, a level type interrupt will occur at the timeout of a stage + * + * configured to generate an interrupt. + */ +#define TIMG_WDT_LEVEL_INT_EN (BIT(21)) +#define TIMG_WDT_LEVEL_INT_EN_M (TIMG_WDT_LEVEL_INT_EN_V << TIMG_WDT_LEVEL_INT_EN_S) +#define TIMG_WDT_LEVEL_INT_EN_V 0x00000001U +#define TIMG_WDT_LEVEL_INT_EN_S 21 +/** TIMG_WDT_EDGE_INT_EN : R/W; bitpos: [22]; default: 0; + * When set, an edge type interrupt will occur at the timeout of a stage + * + * configured to generate an interrupt. + */ +#define TIMG_WDT_EDGE_INT_EN (BIT(22)) +#define TIMG_WDT_EDGE_INT_EN_M (TIMG_WDT_EDGE_INT_EN_V << TIMG_WDT_EDGE_INT_EN_S) +#define TIMG_WDT_EDGE_INT_EN_V 0x00000001U +#define TIMG_WDT_EDGE_INT_EN_S 22 +/** TIMG_WDT_STG3 : R/W; bitpos: [24:23]; default: 0; + * Stage 3 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system. + * + */ +#define TIMG_WDT_STG3 0x00000003U +#define TIMG_WDT_STG3_M (TIMG_WDT_STG3_V << TIMG_WDT_STG3_S) +#define TIMG_WDT_STG3_V 0x00000003U +#define TIMG_WDT_STG3_S 23 +/** TIMG_WDT_STG2 : R/W; bitpos: [26:25]; default: 0; + * Stage 2 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system. + * + */ +#define TIMG_WDT_STG2 0x00000003U +#define TIMG_WDT_STG2_M (TIMG_WDT_STG2_V << TIMG_WDT_STG2_S) +#define TIMG_WDT_STG2_V 0x00000003U +#define TIMG_WDT_STG2_S 25 +/** TIMG_WDT_STG1 : R/W; bitpos: [28:27]; default: 0; + * Stage 1 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system. + * + */ +#define TIMG_WDT_STG1 0x00000003U +#define TIMG_WDT_STG1_M (TIMG_WDT_STG1_V << TIMG_WDT_STG1_S) +#define TIMG_WDT_STG1_V 0x00000003U +#define TIMG_WDT_STG1_S 27 +/** TIMG_WDT_STG0 : R/W; bitpos: [30:29]; default: 0; + * Stage 0 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system. + * + */ +#define TIMG_WDT_STG0 0x00000003U +#define TIMG_WDT_STG0_M (TIMG_WDT_STG0_V << TIMG_WDT_STG0_S) +#define TIMG_WDT_STG0_V 0x00000003U +#define TIMG_WDT_STG0_S 29 +/** TIMG_WDT_EN : R/W; bitpos: [31]; default: 0; + * When set, MWDT is enabled. + */ +#define TIMG_WDT_EN (BIT(31)) +#define TIMG_WDT_EN_M (TIMG_WDT_EN_V << TIMG_WDT_EN_S) +#define TIMG_WDT_EN_V 0x00000001U +#define TIMG_WDT_EN_S 31 -#define TIMG_WDTCONFIG1_REG(i) (REG_TIMG_BASE(i) + 0x004c) -/* TIMG_WDT_CLK_PRESCALE : R/W ;bitpos:[31:16] ;default: 16'h1 ; */ -/*description: */ -#define TIMG_WDT_CLK_PRESCALE 0x0000FFFF -#define TIMG_WDT_CLK_PRESCALE_M ((TIMG_WDT_CLK_PRESCALE_V)<<(TIMG_WDT_CLK_PRESCALE_S)) -#define TIMG_WDT_CLK_PRESCALE_V 0xFFFF -#define TIMG_WDT_CLK_PRESCALE_S 16 +/** TIMG_WDTCONFIG1_REG register + * Watchdog timer prescaler register + */ +#define TIMG_WDTCONFIG1_REG(i) (DR_REG_TIMG_BASE(i) + 0x4c) +/** TIMG_WDT_CLK_PRESCALER : R/W; bitpos: [31:16]; default: 1; + * MWDT clock prescaler value. MWDT clock period = 12.5 ns * + * + * TIMG_WDT_CLK_PRESCALE. + */ +#define TIMG_WDT_CLK_PRESCALER 0x0000FFFFU +#define TIMG_WDT_CLK_PRESCALER_M (TIMG_WDT_CLK_PRESCALER_V << TIMG_WDT_CLK_PRESCALER_S) +#define TIMG_WDT_CLK_PRESCALER_V 0x0000FFFFU +#define TIMG_WDT_CLK_PRESCALER_S 16 -#define TIMG_WDTCONFIG2_REG(i) (REG_TIMG_BASE(i) + 0x0050) -/* TIMG_WDT_STG0_HOLD : R/W ;bitpos:[31:0] ;default: 32'd26000000 ; */ -/*description: */ -#define TIMG_WDT_STG0_HOLD 0xFFFFFFFF -#define TIMG_WDT_STG0_HOLD_M ((TIMG_WDT_STG0_HOLD_V)<<(TIMG_WDT_STG0_HOLD_S)) -#define TIMG_WDT_STG0_HOLD_V 0xFFFFFFFF +/** TIMG_WDTCONFIG2_REG register + * Watchdog timer stage 0 timeout value + */ +#define TIMG_WDTCONFIG2_REG(i) (DR_REG_TIMG_BASE(i) + 0x50) +/** TIMG_WDT_STG0_HOLD : R/W; bitpos: [31:0]; default: 26000000; + * Stage 0 timeout value, in MWDT clock cycles. + */ +#define TIMG_WDT_STG0_HOLD 0xFFFFFFFFU +#define TIMG_WDT_STG0_HOLD_M (TIMG_WDT_STG0_HOLD_V << TIMG_WDT_STG0_HOLD_S) +#define TIMG_WDT_STG0_HOLD_V 0xFFFFFFFFU #define TIMG_WDT_STG0_HOLD_S 0 -#define TIMG_WDTCONFIG3_REG(i) (REG_TIMG_BASE(i) + 0x0054) -/* TIMG_WDT_STG1_HOLD : R/W ;bitpos:[31:0] ;default: 32'h7ffffff ; */ -/*description: */ -#define TIMG_WDT_STG1_HOLD 0xFFFFFFFF -#define TIMG_WDT_STG1_HOLD_M ((TIMG_WDT_STG1_HOLD_V)<<(TIMG_WDT_STG1_HOLD_S)) -#define TIMG_WDT_STG1_HOLD_V 0xFFFFFFFF +/** TIMG_WDTCONFIG3_REG register + * Watchdog timer stage 1 timeout value + */ +#define TIMG_WDTCONFIG3_REG(i) (DR_REG_TIMG_BASE(i) + 0x54) +/** TIMG_WDT_STG1_HOLD : R/W; bitpos: [31:0]; default: 134217727; + * Stage 1 timeout value, in MWDT clock cycles. + */ +#define TIMG_WDT_STG1_HOLD 0xFFFFFFFFU +#define TIMG_WDT_STG1_HOLD_M (TIMG_WDT_STG1_HOLD_V << TIMG_WDT_STG1_HOLD_S) +#define TIMG_WDT_STG1_HOLD_V 0xFFFFFFFFU #define TIMG_WDT_STG1_HOLD_S 0 -#define TIMG_WDTCONFIG4_REG(i) (REG_TIMG_BASE(i) + 0x0058) -/* TIMG_WDT_STG2_HOLD : R/W ;bitpos:[31:0] ;default: 32'hfffff ; */ -/*description: */ -#define TIMG_WDT_STG2_HOLD 0xFFFFFFFF -#define TIMG_WDT_STG2_HOLD_M ((TIMG_WDT_STG2_HOLD_V)<<(TIMG_WDT_STG2_HOLD_S)) -#define TIMG_WDT_STG2_HOLD_V 0xFFFFFFFF +/** TIMG_WDTCONFIG4_REG register + * Watchdog timer stage 2 timeout value + */ +#define TIMG_WDTCONFIG4_REG(i) (DR_REG_TIMG_BASE(i) + 0x58) +/** TIMG_WDT_STG2_HOLD : R/W; bitpos: [31:0]; default: 1048575; + * Stage 2 timeout value, in MWDT clock cycles. + */ +#define TIMG_WDT_STG2_HOLD 0xFFFFFFFFU +#define TIMG_WDT_STG2_HOLD_M (TIMG_WDT_STG2_HOLD_V << TIMG_WDT_STG2_HOLD_S) +#define TIMG_WDT_STG2_HOLD_V 0xFFFFFFFFU #define TIMG_WDT_STG2_HOLD_S 0 -#define TIMG_WDTCONFIG5_REG(i) (REG_TIMG_BASE(i) + 0x005c) -/* TIMG_WDT_STG3_HOLD : R/W ;bitpos:[31:0] ;default: 32'hfffff ; */ -/*description: */ -#define TIMG_WDT_STG3_HOLD 0xFFFFFFFF -#define TIMG_WDT_STG3_HOLD_M ((TIMG_WDT_STG3_HOLD_V)<<(TIMG_WDT_STG3_HOLD_S)) -#define TIMG_WDT_STG3_HOLD_V 0xFFFFFFFF +/** TIMG_WDTCONFIG5_REG register + * Watchdog timer stage 3 timeout value + */ +#define TIMG_WDTCONFIG5_REG(i) (DR_REG_TIMG_BASE(i) + 0x5c) +/** TIMG_WDT_STG3_HOLD : R/W; bitpos: [31:0]; default: 1048575; + * Stage 3 timeout value, in MWDT clock cycles. + */ +#define TIMG_WDT_STG3_HOLD 0xFFFFFFFFU +#define TIMG_WDT_STG3_HOLD_M (TIMG_WDT_STG3_HOLD_V << TIMG_WDT_STG3_HOLD_S) +#define TIMG_WDT_STG3_HOLD_V 0xFFFFFFFFU #define TIMG_WDT_STG3_HOLD_S 0 -#define TIMG_WDTFEED_REG(i) (REG_TIMG_BASE(i) + 0x0060) -/* TIMG_WDT_FEED : WO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define TIMG_WDT_FEED 0xFFFFFFFF -#define TIMG_WDT_FEED_M ((TIMG_WDT_FEED_V)<<(TIMG_WDT_FEED_S)) -#define TIMG_WDT_FEED_V 0xFFFFFFFF +/** TIMG_WDTFEED_REG register + * Write to feed the watchdog timer + */ +#define TIMG_WDTFEED_REG(i) (DR_REG_TIMG_BASE(i) + 0x60) +/** TIMG_WDT_FEED : WO; bitpos: [31:0]; default: 0; + * Write any value to feed the MWDT. (WO) + */ +#define TIMG_WDT_FEED 0xFFFFFFFFU +#define TIMG_WDT_FEED_M (TIMG_WDT_FEED_V << TIMG_WDT_FEED_S) +#define TIMG_WDT_FEED_V 0xFFFFFFFFU #define TIMG_WDT_FEED_S 0 -#define TIMG_WDTWPROTECT_REG(i) (REG_TIMG_BASE(i) + 0x0064) -/* TIMG_WDT_WKEY : R/W ;bitpos:[31:0] ;default: 32'h50d83aa1 ; */ -/*description: */ -#define TIMG_WDT_WKEY 0xFFFFFFFF -#define TIMG_WDT_WKEY_M ((TIMG_WDT_WKEY_V)<<(TIMG_WDT_WKEY_S)) -#define TIMG_WDT_WKEY_V 0xFFFFFFFF +/** TIMG_WDTWPROTECT_REG register + * Watchdog write protect register + */ +#define TIMG_WDTWPROTECT_REG(i) (DR_REG_TIMG_BASE(i) + 0x64) +/** TIMG_WDT_WKEY : R/W; bitpos: [31:0]; default: 1356348065; + * If the register contains a different value than its reset value, write + * + * protection is enabled. + */ +#define TIMG_WDT_WKEY 0xFFFFFFFFU +#define TIMG_WDT_WKEY_M (TIMG_WDT_WKEY_V << TIMG_WDT_WKEY_S) +#define TIMG_WDT_WKEY_V 0xFFFFFFFFU #define TIMG_WDT_WKEY_S 0 -#define TIMG_RTCCALICFG_REG(i) (REG_TIMG_BASE(i) + 0x0068) -/* TIMG_RTC_CALI_START : R/W ;bitpos:[31] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_RTC_CALI_START (BIT(31)) -#define TIMG_RTC_CALI_START_M (BIT(31)) -#define TIMG_RTC_CALI_START_V 0x1 -#define TIMG_RTC_CALI_START_S 31 -/* TIMG_RTC_CALI_MAX : R/W ;bitpos:[30:16] ;default: 15'h1 ; */ -/*description: */ -#define TIMG_RTC_CALI_MAX 0x00007FFF -#define TIMG_RTC_CALI_MAX_M ((TIMG_RTC_CALI_MAX_V)<<(TIMG_RTC_CALI_MAX_S)) -#define TIMG_RTC_CALI_MAX_V 0x7FFF -#define TIMG_RTC_CALI_MAX_S 16 -/* TIMG_RTC_CALI_RDY : RO ;bitpos:[15] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_RTC_CALI_RDY (BIT(15)) -#define TIMG_RTC_CALI_RDY_M (BIT(15)) -#define TIMG_RTC_CALI_RDY_V 0x1 -#define TIMG_RTC_CALI_RDY_S 15 -/* TIMG_RTC_CALI_CLK_SEL : R/W ;bitpos:[14:13] ;default: 2'h1 ; */ -/*description: */ -#define TIMG_RTC_CALI_CLK_SEL 0x00000003 -#define TIMG_RTC_CALI_CLK_SEL_M ((TIMG_RTC_CALI_CLK_SEL_V)<<(TIMG_RTC_CALI_CLK_SEL_S)) -#define TIMG_RTC_CALI_CLK_SEL_V 0x3 -#define TIMG_RTC_CALI_CLK_SEL_S 13 -/* TIMG_RTC_CALI_START_CYCLING : R/W ;bitpos:[12] ;default: 1'd1 ; */ -/*description: */ -#define TIMG_RTC_CALI_START_CYCLING (BIT(12)) -#define TIMG_RTC_CALI_START_CYCLING_M (BIT(12)) -#define TIMG_RTC_CALI_START_CYCLING_V 0x1 +/** TIMG_RTCCALICFG_REG register + * RTC calibration configuration register + */ +#define TIMG_RTCCALICFG_REG(i) (DR_REG_TIMG_BASE(i) + 0x68) +/** TIMG_RTC_CALI_START_CYCLING : R/W; bitpos: [12]; default: 1; + * Reserved + */ +#define TIMG_RTC_CALI_START_CYCLING (BIT(12)) +#define TIMG_RTC_CALI_START_CYCLING_M (TIMG_RTC_CALI_START_CYCLING_V << TIMG_RTC_CALI_START_CYCLING_S) +#define TIMG_RTC_CALI_START_CYCLING_V 0x00000001U #define TIMG_RTC_CALI_START_CYCLING_S 12 +/** TIMG_RTC_CALI_CLK_SEL : R/W; bitpos: [14:13]; default: 1; + * 0:rtcslowclock. 1:clk_80m. 2:xtal_32k. + */ +#define TIMG_RTC_CALI_CLK_SEL 0x00000003U +#define TIMG_RTC_CALI_CLK_SEL_M (TIMG_RTC_CALI_CLK_SEL_V << TIMG_RTC_CALI_CLK_SEL_S) +#define TIMG_RTC_CALI_CLK_SEL_V 0x00000003U +#define TIMG_RTC_CALI_CLK_SEL_S 13 +/** TIMG_RTC_CALI_RDY : RO; bitpos: [15]; default: 0; + * Reserved + */ +#define TIMG_RTC_CALI_RDY (BIT(15)) +#define TIMG_RTC_CALI_RDY_M (TIMG_RTC_CALI_RDY_V << TIMG_RTC_CALI_RDY_S) +#define TIMG_RTC_CALI_RDY_V 0x00000001U +#define TIMG_RTC_CALI_RDY_S 15 +/** TIMG_RTC_CALI_MAX : R/W; bitpos: [30:16]; default: 1; + * Reserved + */ +#define TIMG_RTC_CALI_MAX 0x00007FFFU +#define TIMG_RTC_CALI_MAX_M (TIMG_RTC_CALI_MAX_V << TIMG_RTC_CALI_MAX_S) +#define TIMG_RTC_CALI_MAX_V 0x00007FFFU +#define TIMG_RTC_CALI_MAX_S 16 +/** TIMG_RTC_CALI_START : R/W; bitpos: [31]; default: 0; + * Reserved + */ +#define TIMG_RTC_CALI_START (BIT(31)) +#define TIMG_RTC_CALI_START_M (TIMG_RTC_CALI_START_V << TIMG_RTC_CALI_START_S) +#define TIMG_RTC_CALI_START_V 0x00000001U +#define TIMG_RTC_CALI_START_S 31 -#define TIMG_RTCCALICFG1_REG(i) (REG_TIMG_BASE(i) + 0x006c) -/* TIMG_RTC_CALI_VALUE : RO ;bitpos:[31:7] ;default: 25'h0 ; */ -/*description: */ -#define TIMG_RTC_CALI_VALUE 0x01FFFFFF -#define TIMG_RTC_CALI_VALUE_M ((TIMG_RTC_CALI_VALUE_V)<<(TIMG_RTC_CALI_VALUE_S)) -#define TIMG_RTC_CALI_VALUE_V 0x1FFFFFF -#define TIMG_RTC_CALI_VALUE_S 7 -/* TIMG_RTC_CALI_CYCLING_DATA_VLD : RO ;bitpos:[0] ;default: 1'b0 ; */ -/*description: */ -#define TIMG_RTC_CALI_CYCLING_DATA_VLD (BIT(0)) -#define TIMG_RTC_CALI_CYCLING_DATA_VLD_M (BIT(0)) -#define TIMG_RTC_CALI_CYCLING_DATA_VLD_V 0x1 +/** TIMG_RTCCALICFG1_REG register + * RTC calibration configuration1 register + */ +#define TIMG_RTCCALICFG1_REG(i) (DR_REG_TIMG_BASE(i) + 0x6c) +/** TIMG_RTC_CALI_CYCLING_DATA_VLD : RO; bitpos: [0]; default: 0; + * Reserved + */ +#define TIMG_RTC_CALI_CYCLING_DATA_VLD (BIT(0)) +#define TIMG_RTC_CALI_CYCLING_DATA_VLD_M (TIMG_RTC_CALI_CYCLING_DATA_VLD_V << TIMG_RTC_CALI_CYCLING_DATA_VLD_S) +#define TIMG_RTC_CALI_CYCLING_DATA_VLD_V 0x00000001U #define TIMG_RTC_CALI_CYCLING_DATA_VLD_S 0 +/** TIMG_RTC_CALI_VALUE : RO; bitpos: [31:7]; default: 0; + * Reserved + */ +#define TIMG_RTC_CALI_VALUE 0x01FFFFFFU +#define TIMG_RTC_CALI_VALUE_M (TIMG_RTC_CALI_VALUE_V << TIMG_RTC_CALI_VALUE_S) +#define TIMG_RTC_CALI_VALUE_V 0x01FFFFFFU +#define TIMG_RTC_CALI_VALUE_S 7 -#define TIMG_LACTCONFIG_REG(i) (REG_TIMG_BASE(i) + 0x0070) -/* TIMG_LACT_EN : R/W ;bitpos:[31] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_LACT_EN (BIT(31)) -#define TIMG_LACT_EN_M (BIT(31)) -#define TIMG_LACT_EN_V 0x1 -#define TIMG_LACT_EN_S 31 -/* TIMG_LACT_INCREASE : R/W ;bitpos:[30] ;default: 1'h1 ; */ -/*description: */ -#define TIMG_LACT_INCREASE (BIT(30)) -#define TIMG_LACT_INCREASE_M (BIT(30)) -#define TIMG_LACT_INCREASE_V 0x1 -#define TIMG_LACT_INCREASE_S 30 -/* TIMG_LACT_AUTORELOAD : R/W ;bitpos:[29] ;default: 1'h1 ; */ -/*description: */ -#define TIMG_LACT_AUTORELOAD (BIT(29)) -#define TIMG_LACT_AUTORELOAD_M (BIT(29)) -#define TIMG_LACT_AUTORELOAD_V 0x1 -#define TIMG_LACT_AUTORELOAD_S 29 -/* TIMG_LACT_DIVIDER : R/W ;bitpos:[28:13] ;default: 16'h1 ; */ -/*description: */ -#define TIMG_LACT_DIVIDER 0x0000FFFF -#define TIMG_LACT_DIVIDER_M ((TIMG_LACT_DIVIDER_V)<<(TIMG_LACT_DIVIDER_S)) -#define TIMG_LACT_DIVIDER_V 0xFFFF -#define TIMG_LACT_DIVIDER_S 13 -/* TIMG_LACT_EDGE_INT_EN : R/W ;bitpos:[12] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_LACT_EDGE_INT_EN (BIT(12)) -#define TIMG_LACT_EDGE_INT_EN_M (BIT(12)) -#define TIMG_LACT_EDGE_INT_EN_V 0x1 -#define TIMG_LACT_EDGE_INT_EN_S 12 -/* TIMG_LACT_LEVEL_INT_EN : R/W ;bitpos:[11] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_LACT_LEVEL_INT_EN (BIT(11)) -#define TIMG_LACT_LEVEL_INT_EN_M (BIT(11)) -#define TIMG_LACT_LEVEL_INT_EN_V 0x1 -#define TIMG_LACT_LEVEL_INT_EN_S 11 -/* TIMG_LACT_ALARM_EN : R/W ;bitpos:[10] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_LACT_ALARM_EN (BIT(10)) -#define TIMG_LACT_ALARM_EN_M (BIT(10)) -#define TIMG_LACT_ALARM_EN_V 0x1 -#define TIMG_LACT_ALARM_EN_S 10 -/* TIMG_LACT_LAC_EN : R/W ;bitpos:[9] ;default: 1'h1 ; */ -/*description: */ -#define TIMG_LACT_LAC_EN (BIT(9)) -#define TIMG_LACT_LAC_EN_M (BIT(9)) -#define TIMG_LACT_LAC_EN_V 0x1 -#define TIMG_LACT_LAC_EN_S 9 -/* TIMG_LACT_CPST_EN : R/W ;bitpos:[8] ;default: 1'h1 ; */ -/*description: */ -#define TIMG_LACT_CPST_EN (BIT(8)) -#define TIMG_LACT_CPST_EN_M (BIT(8)) -#define TIMG_LACT_CPST_EN_V 0x1 -#define TIMG_LACT_CPST_EN_S 8 -/* TIMG_LACT_RTC_ONLY : R/W ;bitpos:[7] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_LACT_RTC_ONLY (BIT(7)) -#define TIMG_LACT_RTC_ONLY_M (BIT(7)) -#define TIMG_LACT_RTC_ONLY_V 0x1 -#define TIMG_LACT_RTC_ONLY_S 7 -/* TIMG_LACT_USE_REFTICK : R/W ;bitpos:[6] ;default: 1'd0 ; */ -/*description: */ -#define TIMG_LACT_USE_REFTICK (BIT(6)) -#define TIMG_LACT_USE_REFTICK_M (BIT(6)) -#define TIMG_LACT_USE_REFTICK_V 0x1 +/** TIMG_LACTCONFIG_REG register + * LACT configuration register + */ +#define TIMG_LACTCONFIG_REG(i) (DR_REG_TIMG_BASE(i) + 0x70) +/** TIMG_LACT_USE_REFTICK : R/W; bitpos: [6]; default: 0; + * Reserved + */ +#define TIMG_LACT_USE_REFTICK (BIT(6)) +#define TIMG_LACT_USE_REFTICK_M (TIMG_LACT_USE_REFTICK_V << TIMG_LACT_USE_REFTICK_S) +#define TIMG_LACT_USE_REFTICK_V 0x00000001U #define TIMG_LACT_USE_REFTICK_S 6 +/** TIMG_LACT_RTC_ONLY : R/W; bitpos: [7]; default: 0; + * Reserved + */ +#define TIMG_LACT_RTC_ONLY (BIT(7)) +#define TIMG_LACT_RTC_ONLY_M (TIMG_LACT_RTC_ONLY_V << TIMG_LACT_RTC_ONLY_S) +#define TIMG_LACT_RTC_ONLY_V 0x00000001U +#define TIMG_LACT_RTC_ONLY_S 7 +/** TIMG_LACT_CPST_EN : R/W; bitpos: [8]; default: 1; + * Reserved + */ +#define TIMG_LACT_CPST_EN (BIT(8)) +#define TIMG_LACT_CPST_EN_M (TIMG_LACT_CPST_EN_V << TIMG_LACT_CPST_EN_S) +#define TIMG_LACT_CPST_EN_V 0x00000001U +#define TIMG_LACT_CPST_EN_S 8 +/** TIMG_LACT_LAC_EN : R/W; bitpos: [9]; default: 1; + * Reserved + */ +#define TIMG_LACT_LAC_EN (BIT(9)) +#define TIMG_LACT_LAC_EN_M (TIMG_LACT_LAC_EN_V << TIMG_LACT_LAC_EN_S) +#define TIMG_LACT_LAC_EN_V 0x00000001U +#define TIMG_LACT_LAC_EN_S 9 +/** TIMG_LACT_ALARM_EN : R/W; bitpos: [10]; default: 0; + * Reserved + */ +#define TIMG_LACT_ALARM_EN (BIT(10)) +#define TIMG_LACT_ALARM_EN_M (TIMG_LACT_ALARM_EN_V << TIMG_LACT_ALARM_EN_S) +#define TIMG_LACT_ALARM_EN_V 0x00000001U +#define TIMG_LACT_ALARM_EN_S 10 +/** TIMG_LACT_LEVEL_INT_EN : R/W; bitpos: [11]; default: 0; + * Reserved + */ +#define TIMG_LACT_LEVEL_INT_EN (BIT(11)) +#define TIMG_LACT_LEVEL_INT_EN_M (TIMG_LACT_LEVEL_INT_EN_V << TIMG_LACT_LEVEL_INT_EN_S) +#define TIMG_LACT_LEVEL_INT_EN_V 0x00000001U +#define TIMG_LACT_LEVEL_INT_EN_S 11 +/** TIMG_LACT_EDGE_INT_EN : R/W; bitpos: [12]; default: 0; + * Reserved + */ +#define TIMG_LACT_EDGE_INT_EN (BIT(12)) +#define TIMG_LACT_EDGE_INT_EN_M (TIMG_LACT_EDGE_INT_EN_V << TIMG_LACT_EDGE_INT_EN_S) +#define TIMG_LACT_EDGE_INT_EN_V 0x00000001U +#define TIMG_LACT_EDGE_INT_EN_S 12 +/** TIMG_LACT_DIVIDER : R/W; bitpos: [28:13]; default: 1; + * Reserved + */ +#define TIMG_LACT_DIVIDER 0x0000FFFFU +#define TIMG_LACT_DIVIDER_M (TIMG_LACT_DIVIDER_V << TIMG_LACT_DIVIDER_S) +#define TIMG_LACT_DIVIDER_V 0x0000FFFFU +#define TIMG_LACT_DIVIDER_S 13 +/** TIMG_LACT_AUTORELOAD : R/W; bitpos: [29]; default: 1; + * Reserved + */ +#define TIMG_LACT_AUTORELOAD (BIT(29)) +#define TIMG_LACT_AUTORELOAD_M (TIMG_LACT_AUTORELOAD_V << TIMG_LACT_AUTORELOAD_S) +#define TIMG_LACT_AUTORELOAD_V 0x00000001U +#define TIMG_LACT_AUTORELOAD_S 29 +/** TIMG_LACT_INCREASE : R/W; bitpos: [30]; default: 1; + * Reserved + */ +#define TIMG_LACT_INCREASE (BIT(30)) +#define TIMG_LACT_INCREASE_M (TIMG_LACT_INCREASE_V << TIMG_LACT_INCREASE_S) +#define TIMG_LACT_INCREASE_V 0x00000001U +#define TIMG_LACT_INCREASE_S 30 +/** TIMG_LACT_EN : R/W; bitpos: [31]; default: 0; + * Reserved + */ +#define TIMG_LACT_EN (BIT(31)) +#define TIMG_LACT_EN_M (TIMG_LACT_EN_V << TIMG_LACT_EN_S) +#define TIMG_LACT_EN_V 0x00000001U +#define TIMG_LACT_EN_S 31 -#define TIMG_LACTRTC_REG(i) (REG_TIMG_BASE(i) + 0x0074) -/* TIMG_LACT_RTC_STEP_LEN : R/W ;bitpos:[31:6] ;default: 26'h0 ; */ -/*description: */ -#define TIMG_LACT_RTC_STEP_LEN 0x03FFFFFF -#define TIMG_LACT_RTC_STEP_LEN_M ((TIMG_LACT_RTC_STEP_LEN_V)<<(TIMG_LACT_RTC_STEP_LEN_S)) -#define TIMG_LACT_RTC_STEP_LEN_V 0x3FFFFFF +/** TIMG_LACTRTC_REG register + * LACT RTC register + */ +#define TIMG_LACTRTC_REG(i) (DR_REG_TIMG_BASE(i) + 0x74) +/** TIMG_LACT_RTC_STEP_LEN : R/W; bitpos: [31:6]; default: 0; + * Reserved + */ +#define TIMG_LACT_RTC_STEP_LEN 0x03FFFFFFU +#define TIMG_LACT_RTC_STEP_LEN_M (TIMG_LACT_RTC_STEP_LEN_V << TIMG_LACT_RTC_STEP_LEN_S) +#define TIMG_LACT_RTC_STEP_LEN_V 0x03FFFFFFU #define TIMG_LACT_RTC_STEP_LEN_S 6 -#define TIMG_LACTLO_REG(i) (REG_TIMG_BASE(i) + 0x0078) -/* TIMG_LACT_LO : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define TIMG_LACT_LO 0xFFFFFFFF -#define TIMG_LACT_LO_M ((TIMG_LACT_LO_V)<<(TIMG_LACT_LO_S)) -#define TIMG_LACT_LO_V 0xFFFFFFFF +/** TIMG_LACTLO_REG register + * LACT low register + */ +#define TIMG_LACTLO_REG(i) (DR_REG_TIMG_BASE(i) + 0x78) +/** TIMG_LACT_LO : RO; bitpos: [31:0]; default: 0; + * Reserved + */ +#define TIMG_LACT_LO 0xFFFFFFFFU +#define TIMG_LACT_LO_M (TIMG_LACT_LO_V << TIMG_LACT_LO_S) +#define TIMG_LACT_LO_V 0xFFFFFFFFU #define TIMG_LACT_LO_S 0 -#define TIMG_LACTHI_REG(i) (REG_TIMG_BASE(i) + 0x007c) -/* TIMG_LACT_HI : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define TIMG_LACT_HI 0xFFFFFFFF -#define TIMG_LACT_HI_M ((TIMG_LACT_HI_V)<<(TIMG_LACT_HI_S)) -#define TIMG_LACT_HI_V 0xFFFFFFFF +/** TIMG_LACTHI_REG register + * LACT high register + */ +#define TIMG_LACTHI_REG(i) (DR_REG_TIMG_BASE(i) + 0x7c) +/** TIMG_LACT_HI : RO; bitpos: [31:0]; default: 0; + * Reserved + */ +#define TIMG_LACT_HI 0xFFFFFFFFU +#define TIMG_LACT_HI_M (TIMG_LACT_HI_V << TIMG_LACT_HI_S) +#define TIMG_LACT_HI_V 0xFFFFFFFFU #define TIMG_LACT_HI_S 0 -#define TIMG_LACTUPDATE_REG(i) (REG_TIMG_BASE(i) + 0x0080) -/* TIMG_LACT_UPDATE : WO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define TIMG_LACT_UPDATE 0xFFFFFFFF -#define TIMG_LACT_UPDATE_M ((TIMG_LACT_UPDATE_V)<<(TIMG_LACT_UPDATE_S)) -#define TIMG_LACT_UPDATE_V 0xFFFFFFFF +/** TIMG_LACTUPDATE_REG register + * LACT update register + */ +#define TIMG_LACTUPDATE_REG(i) (DR_REG_TIMG_BASE(i) + 0x80) +/** TIMG_LACT_UPDATE : WO; bitpos: [31:0]; default: 0; + * Reserved + */ +#define TIMG_LACT_UPDATE 0xFFFFFFFFU +#define TIMG_LACT_UPDATE_M (TIMG_LACT_UPDATE_V << TIMG_LACT_UPDATE_S) +#define TIMG_LACT_UPDATE_V 0xFFFFFFFFU #define TIMG_LACT_UPDATE_S 0 -#define TIMG_LACTALARMLO_REG(i) (REG_TIMG_BASE(i) + 0x0084) -/* TIMG_LACT_ALARM_LO : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define TIMG_LACT_ALARM_LO 0xFFFFFFFF -#define TIMG_LACT_ALARM_LO_M ((TIMG_LACT_ALARM_LO_V)<<(TIMG_LACT_ALARM_LO_S)) -#define TIMG_LACT_ALARM_LO_V 0xFFFFFFFF +/** TIMG_LACTALARMLO_REG register + * LACT alarm low register + */ +#define TIMG_LACTALARMLO_REG(i) (DR_REG_TIMG_BASE(i) + 0x84) +/** TIMG_LACT_ALARM_LO : R/W; bitpos: [31:0]; default: 0; + * Reserved + */ +#define TIMG_LACT_ALARM_LO 0xFFFFFFFFU +#define TIMG_LACT_ALARM_LO_M (TIMG_LACT_ALARM_LO_V << TIMG_LACT_ALARM_LO_S) +#define TIMG_LACT_ALARM_LO_V 0xFFFFFFFFU #define TIMG_LACT_ALARM_LO_S 0 -#define TIMG_LACTALARMHI_REG(i) (REG_TIMG_BASE(i) + 0x0088) -/* TIMG_LACT_ALARM_HI : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define TIMG_LACT_ALARM_HI 0xFFFFFFFF -#define TIMG_LACT_ALARM_HI_M ((TIMG_LACT_ALARM_HI_V)<<(TIMG_LACT_ALARM_HI_S)) -#define TIMG_LACT_ALARM_HI_V 0xFFFFFFFF +/** TIMG_LACTALARMHI_REG register + * LACT alarm high register + */ +#define TIMG_LACTALARMHI_REG(i) (DR_REG_TIMG_BASE(i) + 0x88) +/** TIMG_LACT_ALARM_HI : R/W; bitpos: [31:0]; default: 0; + * Reserved + */ +#define TIMG_LACT_ALARM_HI 0xFFFFFFFFU +#define TIMG_LACT_ALARM_HI_M (TIMG_LACT_ALARM_HI_V << TIMG_LACT_ALARM_HI_S) +#define TIMG_LACT_ALARM_HI_V 0xFFFFFFFFU #define TIMG_LACT_ALARM_HI_S 0 -#define TIMG_LACTLOADLO_REG(i) (REG_TIMG_BASE(i) + 0x008c) -/* TIMG_LACT_LOAD_LO : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define TIMG_LACT_LOAD_LO 0xFFFFFFFF -#define TIMG_LACT_LOAD_LO_M ((TIMG_LACT_LOAD_LO_V)<<(TIMG_LACT_LOAD_LO_S)) -#define TIMG_LACT_LOAD_LO_V 0xFFFFFFFF +/** TIMG_LACTLOADLO_REG register + * LACT load low register + */ +#define TIMG_LACTLOADLO_REG(i) (DR_REG_TIMG_BASE(i) + 0x8c) +/** TIMG_LACT_LOAD_LO : R/W; bitpos: [31:0]; default: 0; + * Reserved + */ +#define TIMG_LACT_LOAD_LO 0xFFFFFFFFU +#define TIMG_LACT_LOAD_LO_M (TIMG_LACT_LOAD_LO_V << TIMG_LACT_LOAD_LO_S) +#define TIMG_LACT_LOAD_LO_V 0xFFFFFFFFU #define TIMG_LACT_LOAD_LO_S 0 -#define TIMG_LACTLOADHI_REG(i) (REG_TIMG_BASE(i) + 0x0090) -/* TIMG_LACT_LOAD_HI : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define TIMG_LACT_LOAD_HI 0xFFFFFFFF -#define TIMG_LACT_LOAD_HI_M ((TIMG_LACT_LOAD_HI_V)<<(TIMG_LACT_LOAD_HI_S)) -#define TIMG_LACT_LOAD_HI_V 0xFFFFFFFF +/** TIMG_LACTLOADHI_REG register + * Timer LACT load high register + */ +#define TIMG_LACTLOADHI_REG(i) (DR_REG_TIMG_BASE(i) + 0x90) +/** TIMG_LACT_LOAD_HI : R/W; bitpos: [31:0]; default: 0; + * Reserved + */ +#define TIMG_LACT_LOAD_HI 0xFFFFFFFFU +#define TIMG_LACT_LOAD_HI_M (TIMG_LACT_LOAD_HI_V << TIMG_LACT_LOAD_HI_S) +#define TIMG_LACT_LOAD_HI_V 0xFFFFFFFFU #define TIMG_LACT_LOAD_HI_S 0 -#define TIMG_LACTLOAD_REG(i) (REG_TIMG_BASE(i) + 0x0094) -/* TIMG_LACT_LOAD : WO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define TIMG_LACT_LOAD 0xFFFFFFFF -#define TIMG_LACT_LOAD_M ((TIMG_LACT_LOAD_V)<<(TIMG_LACT_LOAD_S)) -#define TIMG_LACT_LOAD_V 0xFFFFFFFF +/** TIMG_LACTLOAD_REG register + * Timer LACT load register + */ +#define TIMG_LACTLOAD_REG(i) (DR_REG_TIMG_BASE(i) + 0x94) +/** TIMG_LACT_LOAD : WO; bitpos: [31:0]; default: 0; + * Reserved + */ +#define TIMG_LACT_LOAD 0xFFFFFFFFU +#define TIMG_LACT_LOAD_M (TIMG_LACT_LOAD_V << TIMG_LACT_LOAD_S) +#define TIMG_LACT_LOAD_V 0xFFFFFFFFU #define TIMG_LACT_LOAD_S 0 -#define TIMG_INT_ENA_TIMERS_REG(i) (REG_TIMG_BASE(i) + 0x0098) -/* TIMG_LACT_INT_ENA : R/W ;bitpos:[3] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_LACT_INT_ENA (BIT(3)) -#define TIMG_LACT_INT_ENA_M (BIT(3)) -#define TIMG_LACT_INT_ENA_V 0x1 -#define TIMG_LACT_INT_ENA_S 3 -/* TIMG_WDT_INT_ENA : R/W ;bitpos:[2] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_WDT_INT_ENA (BIT(2)) -#define TIMG_WDT_INT_ENA_M (BIT(2)) -#define TIMG_WDT_INT_ENA_V 0x1 -#define TIMG_WDT_INT_ENA_S 2 -/* TIMG_T1_INT_ENA : R/W ;bitpos:[1] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T1_INT_ENA (BIT(1)) -#define TIMG_T1_INT_ENA_M (BIT(1)) -#define TIMG_T1_INT_ENA_V 0x1 -#define TIMG_T1_INT_ENA_S 1 -/* TIMG_T0_INT_ENA : R/W ;bitpos:[0] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T0_INT_ENA (BIT(0)) -#define TIMG_T0_INT_ENA_M (BIT(0)) -#define TIMG_T0_INT_ENA_V 0x1 +/** TIMG_INT_ENA_TIMERS_REG register + * Interrupt enable bits + */ +#define TIMG_INT_ENA_TIMERS_REG(i) (DR_REG_TIMG_BASE(i) + 0x98) +/** TIMG_T0_INT_ENA : R/W; bitpos: [0]; default: 0; + * The interrupt enable bit for the TIMG_T0_INT interrupt. + */ +#define TIMG_T0_INT_ENA (BIT(0)) +#define TIMG_T0_INT_ENA_M (TIMG_T0_INT_ENA_V << TIMG_T0_INT_ENA_S) +#define TIMG_T0_INT_ENA_V 0x00000001U #define TIMG_T0_INT_ENA_S 0 +/** TIMG_T1_INT_ENA : R/W; bitpos: [1]; default: 0; + * The interrupt enable bit for the TIMG_T1_INT interrupt. + */ +#define TIMG_T1_INT_ENA (BIT(1)) +#define TIMG_T1_INT_ENA_M (TIMG_T1_INT_ENA_V << TIMG_T1_INT_ENA_S) +#define TIMG_T1_INT_ENA_V 0x00000001U +#define TIMG_T1_INT_ENA_S 1 +/** TIMG_WDT_INT_ENA : R/W; bitpos: [2]; default: 0; + * The interrupt enable bit for the TIMG_WDT_INT interrupt. + */ +#define TIMG_WDT_INT_ENA (BIT(2)) +#define TIMG_WDT_INT_ENA_M (TIMG_WDT_INT_ENA_V << TIMG_WDT_INT_ENA_S) +#define TIMG_WDT_INT_ENA_V 0x00000001U +#define TIMG_WDT_INT_ENA_S 2 +/** TIMG_LACT_INT_ENA : R/W; bitpos: [3]; default: 0; + * The interrupt enable bit for the TIMG_LACT_INT interrupt. + */ +#define TIMG_LACT_INT_ENA (BIT(3)) +#define TIMG_LACT_INT_ENA_M (TIMG_LACT_INT_ENA_V << TIMG_LACT_INT_ENA_S) +#define TIMG_LACT_INT_ENA_V 0x00000001U +#define TIMG_LACT_INT_ENA_S 3 -#define TIMG_INT_RAW_TIMERS_REG(i) (REG_TIMG_BASE(i) + 0x009c) -/* TIMG_LACT_INT_RAW : RO ;bitpos:[3] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_LACT_INT_RAW (BIT(3)) -#define TIMG_LACT_INT_RAW_M (BIT(3)) -#define TIMG_LACT_INT_RAW_V 0x1 -#define TIMG_LACT_INT_RAW_S 3 -/* TIMG_WDT_INT_RAW : RO ;bitpos:[2] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_WDT_INT_RAW (BIT(2)) -#define TIMG_WDT_INT_RAW_M (BIT(2)) -#define TIMG_WDT_INT_RAW_V 0x1 -#define TIMG_WDT_INT_RAW_S 2 -/* TIMG_T1_INT_RAW : RO ;bitpos:[1] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T1_INT_RAW (BIT(1)) -#define TIMG_T1_INT_RAW_M (BIT(1)) -#define TIMG_T1_INT_RAW_V 0x1 -#define TIMG_T1_INT_RAW_S 1 -/* TIMG_T0_INT_RAW : RO ;bitpos:[0] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T0_INT_RAW (BIT(0)) -#define TIMG_T0_INT_RAW_M (BIT(0)) -#define TIMG_T0_INT_RAW_V 0x1 +/** TIMG_INT_RAW_TIMERS_REG register + * Raw interrupt status + */ +#define TIMG_INT_RAW_TIMERS_REG(i) (DR_REG_TIMG_BASE(i) + 0x9c) +/** TIMG_T0_INT_RAW : RO; bitpos: [0]; default: 0; + * The raw interrupt status bit for the TIMG_T0_INT interrupt. + */ +#define TIMG_T0_INT_RAW (BIT(0)) +#define TIMG_T0_INT_RAW_M (TIMG_T0_INT_RAW_V << TIMG_T0_INT_RAW_S) +#define TIMG_T0_INT_RAW_V 0x00000001U #define TIMG_T0_INT_RAW_S 0 +/** TIMG_T1_INT_RAW : RO; bitpos: [1]; default: 0; + * The raw interrupt status bit for the TIMG_T1_INT interrupt. + */ +#define TIMG_T1_INT_RAW (BIT(1)) +#define TIMG_T1_INT_RAW_M (TIMG_T1_INT_RAW_V << TIMG_T1_INT_RAW_S) +#define TIMG_T1_INT_RAW_V 0x00000001U +#define TIMG_T1_INT_RAW_S 1 +/** TIMG_WDT_INT_RAW : RO; bitpos: [2]; default: 0; + * The raw interrupt status bit for the TIMG_WDT_INT interrupt. + */ +#define TIMG_WDT_INT_RAW (BIT(2)) +#define TIMG_WDT_INT_RAW_M (TIMG_WDT_INT_RAW_V << TIMG_WDT_INT_RAW_S) +#define TIMG_WDT_INT_RAW_V 0x00000001U +#define TIMG_WDT_INT_RAW_S 2 +/** TIMG_LACT_INT_RAW : RO; bitpos: [3]; default: 0; + * The raw interrupt status bit for the TIMG_LACT_INT interrupt. + */ +#define TIMG_LACT_INT_RAW (BIT(3)) +#define TIMG_LACT_INT_RAW_M (TIMG_LACT_INT_RAW_V << TIMG_LACT_INT_RAW_S) +#define TIMG_LACT_INT_RAW_V 0x00000001U +#define TIMG_LACT_INT_RAW_S 3 -#define TIMG_INT_ST_TIMERS_REG(i) (REG_TIMG_BASE(i) + 0x00a0) -/* TIMG_LACT_INT_ST : RO ;bitpos:[3] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_LACT_INT_ST (BIT(3)) -#define TIMG_LACT_INT_ST_M (BIT(3)) -#define TIMG_LACT_INT_ST_V 0x1 -#define TIMG_LACT_INT_ST_S 3 -/* TIMG_WDT_INT_ST : RO ;bitpos:[2] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_WDT_INT_ST (BIT(2)) -#define TIMG_WDT_INT_ST_M (BIT(2)) -#define TIMG_WDT_INT_ST_V 0x1 -#define TIMG_WDT_INT_ST_S 2 -/* TIMG_T1_INT_ST : RO ;bitpos:[1] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T1_INT_ST (BIT(1)) -#define TIMG_T1_INT_ST_M (BIT(1)) -#define TIMG_T1_INT_ST_V 0x1 -#define TIMG_T1_INT_ST_S 1 -/* TIMG_T0_INT_ST : RO ;bitpos:[0] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T0_INT_ST (BIT(0)) -#define TIMG_T0_INT_ST_M (BIT(0)) -#define TIMG_T0_INT_ST_V 0x1 +/** TIMG_INT_ST_TIMERS_REG register + * Masked interrupt status + */ +#define TIMG_INT_ST_TIMERS_REG(i) (DR_REG_TIMG_BASE(i) + 0xa0) +/** TIMG_T0_INT_ST : RO; bitpos: [0]; default: 0; + * The masked interrupt status bit for the TIMG_T0_INT interrupt. + */ +#define TIMG_T0_INT_ST (BIT(0)) +#define TIMG_T0_INT_ST_M (TIMG_T0_INT_ST_V << TIMG_T0_INT_ST_S) +#define TIMG_T0_INT_ST_V 0x00000001U #define TIMG_T0_INT_ST_S 0 +/** TIMG_T1_INT_ST : RO; bitpos: [1]; default: 0; + * The masked interrupt status bit for the TIMG_T1_INT interrupt. + */ +#define TIMG_T1_INT_ST (BIT(1)) +#define TIMG_T1_INT_ST_M (TIMG_T1_INT_ST_V << TIMG_T1_INT_ST_S) +#define TIMG_T1_INT_ST_V 0x00000001U +#define TIMG_T1_INT_ST_S 1 +/** TIMG_WDT_INT_ST : RO; bitpos: [2]; default: 0; + * The masked interrupt status bit for the TIMG_WDT_INT interrupt. + */ +#define TIMG_WDT_INT_ST (BIT(2)) +#define TIMG_WDT_INT_ST_M (TIMG_WDT_INT_ST_V << TIMG_WDT_INT_ST_S) +#define TIMG_WDT_INT_ST_V 0x00000001U +#define TIMG_WDT_INT_ST_S 2 +/** TIMG_LACT_INT_ST : RO; bitpos: [3]; default: 0; + * The masked interrupt status bit for the TIMG_LACT_INT interrupt. + */ +#define TIMG_LACT_INT_ST (BIT(3)) +#define TIMG_LACT_INT_ST_M (TIMG_LACT_INT_ST_V << TIMG_LACT_INT_ST_S) +#define TIMG_LACT_INT_ST_V 0x00000001U +#define TIMG_LACT_INT_ST_S 3 -#define TIMG_INT_CLR_TIMERS_REG(i) (REG_TIMG_BASE(i) + 0x00a4) -/* TIMG_LACT_INT_CLR : WO ;bitpos:[3] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_LACT_INT_CLR (BIT(3)) -#define TIMG_LACT_INT_CLR_M (BIT(3)) -#define TIMG_LACT_INT_CLR_V 0x1 -#define TIMG_LACT_INT_CLR_S 3 -/* TIMG_WDT_INT_CLR : WO ;bitpos:[2] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_WDT_INT_CLR (BIT(2)) -#define TIMG_WDT_INT_CLR_M (BIT(2)) -#define TIMG_WDT_INT_CLR_V 0x1 -#define TIMG_WDT_INT_CLR_S 2 -/* TIMG_T1_INT_CLR : WO ;bitpos:[1] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T1_INT_CLR (BIT(1)) -#define TIMG_T1_INT_CLR_M (BIT(1)) -#define TIMG_T1_INT_CLR_V 0x1 -#define TIMG_T1_INT_CLR_S 1 -/* TIMG_T0_INT_CLR : WO ;bitpos:[0] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_T0_INT_CLR (BIT(0)) -#define TIMG_T0_INT_CLR_M (BIT(0)) -#define TIMG_T0_INT_CLR_V 0x1 +/** TIMG_INT_CLR_TIMERS_REG register + * Interrupt clear bits + */ +#define TIMG_INT_CLR_TIMERS_REG(i) (DR_REG_TIMG_BASE(i) + 0xa4) +/** TIMG_T0_INT_CLR : WO; bitpos: [0]; default: 0; + * Set this bit to clear the TIMG_T0_INT interrupt. + */ +#define TIMG_T0_INT_CLR (BIT(0)) +#define TIMG_T0_INT_CLR_M (TIMG_T0_INT_CLR_V << TIMG_T0_INT_CLR_S) +#define TIMG_T0_INT_CLR_V 0x00000001U #define TIMG_T0_INT_CLR_S 0 +/** TIMG_T1_INT_CLR : WO; bitpos: [1]; default: 0; + * Set this bit to clear the TIMG_T1_INT interrupt. + */ +#define TIMG_T1_INT_CLR (BIT(1)) +#define TIMG_T1_INT_CLR_M (TIMG_T1_INT_CLR_V << TIMG_T1_INT_CLR_S) +#define TIMG_T1_INT_CLR_V 0x00000001U +#define TIMG_T1_INT_CLR_S 1 +/** TIMG_WDT_INT_CLR : WO; bitpos: [2]; default: 0; + * Set this bit to clear the TIMG_WDT_INT interrupt. + */ +#define TIMG_WDT_INT_CLR (BIT(2)) +#define TIMG_WDT_INT_CLR_M (TIMG_WDT_INT_CLR_V << TIMG_WDT_INT_CLR_S) +#define TIMG_WDT_INT_CLR_V 0x00000001U +#define TIMG_WDT_INT_CLR_S 2 +/** TIMG_LACT_INT_CLR : WO; bitpos: [3]; default: 0; + * Set this bit to clear the TIMG_LACT_INT interrupt. + */ +#define TIMG_LACT_INT_CLR (BIT(3)) +#define TIMG_LACT_INT_CLR_M (TIMG_LACT_INT_CLR_V << TIMG_LACT_INT_CLR_S) +#define TIMG_LACT_INT_CLR_V 0x00000001U +#define TIMG_LACT_INT_CLR_S 3 -#define TIMG_RTCCALICFG2_REG(i) (REG_TIMG_BASE(i) + 0x00a8) -/* TIMG_RTC_CALI_TIMEOUT_THRES : R/W ;bitpos:[31:7] ;default: 25'h1ffffff ; */ -/*description: timeout if cali value counts over threshold*/ -#define TIMG_RTC_CALI_TIMEOUT_THRES 0x01FFFFFF -#define TIMG_RTC_CALI_TIMEOUT_THRES_M ((TIMG_RTC_CALI_TIMEOUT_THRES_V)<<(TIMG_RTC_CALI_TIMEOUT_THRES_S)) -#define TIMG_RTC_CALI_TIMEOUT_THRES_V 0x1FFFFFF -#define TIMG_RTC_CALI_TIMEOUT_THRES_S 7 -/* TIMG_RTC_CALI_TIMEOUT_RST_CNT : R/W ;bitpos:[6:3] ;default: 4'd3 ; */ -/*description: Cycles that release calibration timeout reset*/ -#define TIMG_RTC_CALI_TIMEOUT_RST_CNT 0x0000000F -#define TIMG_RTC_CALI_TIMEOUT_RST_CNT_M ((TIMG_RTC_CALI_TIMEOUT_RST_CNT_V)<<(TIMG_RTC_CALI_TIMEOUT_RST_CNT_S)) -#define TIMG_RTC_CALI_TIMEOUT_RST_CNT_V 0xF -#define TIMG_RTC_CALI_TIMEOUT_RST_CNT_S 3 -/* TIMG_RTC_CALI_TIMEOUT : RO ;bitpos:[0] ;default: 1'h0 ; */ -/*description: timeout indicator*/ -#define TIMG_RTC_CALI_TIMEOUT (BIT(0)) -#define TIMG_RTC_CALI_TIMEOUT_M (BIT(0)) -#define TIMG_RTC_CALI_TIMEOUT_V 0x1 +/** TIMG_RTCCALICFG2_REG register + * Timer group calibration register + */ +#define TIMG_RTCCALICFG2_REG(i) (DR_REG_TIMG_BASE(i) + 0xa8) +/** TIMG_RTC_CALI_TIMEOUT : RO; bitpos: [0]; default: 0; + * RTC calibration timeout indicator + */ +#define TIMG_RTC_CALI_TIMEOUT (BIT(0)) +#define TIMG_RTC_CALI_TIMEOUT_M (TIMG_RTC_CALI_TIMEOUT_V << TIMG_RTC_CALI_TIMEOUT_S) +#define TIMG_RTC_CALI_TIMEOUT_V 0x00000001U #define TIMG_RTC_CALI_TIMEOUT_S 0 +/** TIMG_RTC_CALI_TIMEOUT_RST_CNT : R/W; bitpos: [6:3]; default: 3; + * Cycles that release calibration timeout reset + */ +#define TIMG_RTC_CALI_TIMEOUT_RST_CNT 0x0000000FU +#define TIMG_RTC_CALI_TIMEOUT_RST_CNT_M (TIMG_RTC_CALI_TIMEOUT_RST_CNT_V << TIMG_RTC_CALI_TIMEOUT_RST_CNT_S) +#define TIMG_RTC_CALI_TIMEOUT_RST_CNT_V 0x0000000FU +#define TIMG_RTC_CALI_TIMEOUT_RST_CNT_S 3 +/** TIMG_RTC_CALI_TIMEOUT_THRES : R/W; bitpos: [31:7]; default: 33554431; + * Threshold value for the RTC calibration timer. If the calibration timer's value + * exceeds this threshold, a timeout is triggered. + */ +#define TIMG_RTC_CALI_TIMEOUT_THRES 0x01FFFFFFU +#define TIMG_RTC_CALI_TIMEOUT_THRES_M (TIMG_RTC_CALI_TIMEOUT_THRES_V << TIMG_RTC_CALI_TIMEOUT_THRES_S) +#define TIMG_RTC_CALI_TIMEOUT_THRES_V 0x01FFFFFFU +#define TIMG_RTC_CALI_TIMEOUT_THRES_S 7 -#define TIMG_NTIMERS_DATE_REG(i) (REG_TIMG_BASE(i) + 0x00f8) -/* TIMG_NTIMERS_DATE : R/W ;bitpos:[27:0] ;default: 28'h1810190 ; */ -/*description: */ -#define TIMG_NTIMERS_DATE 0x0FFFFFFF -#define TIMG_NTIMERS_DATE_M ((TIMG_NTIMERS_DATE_V)<<(TIMG_NTIMERS_DATE_S)) -#define TIMG_NTIMERS_DATE_V 0xFFFFFFF -#define TIMG_NTIMERS_DATE_S 0 +/** TIMG_TIMERS_DATE_REG register + * Version control register + */ +#define TIMG_TIMERS_DATE_REG(i) (DR_REG_TIMG_BASE(i) + 0xf8) +/** TIMG_TIMERS_DATE : R/W; bitpos: [27:0]; default: 26243681; + * Version control register. + */ +#define TIMG_TIMERS_DATE 0x0FFFFFFFU +#define TIMG_TIMERS_DATE_M (TIMG_TIMERS_DATE_V << TIMG_TIMERS_DATE_S) +#define TIMG_TIMERS_DATE_V 0x0FFFFFFFU +#define TIMG_TIMERS_DATE_S 0 -#define TIMG_CLK_REG(i) (REG_TIMG_BASE(i) + 0x00fc) -/* TIMG_CLK_EN : R/W ;bitpos:[31] ;default: 1'h0 ; */ -/*description: */ -#define TIMG_CLK_EN (BIT(31)) -#define TIMG_CLK_EN_M (BIT(31)) -#define TIMG_CLK_EN_V 0x1 +/** TIMG_REGCLK_REG register + * Timer group clock gate register + */ +#define TIMG_REGCLK_REG(i) (DR_REG_TIMG_BASE(i) + 0xfc) +/** TIMG_CLK_EN : R/W; bitpos: [31]; default: 0; + * Register clock gate signal. 1: Registers can be read and written to by software. 0: + * Registers can not be read or written to by software. + */ +#define TIMG_CLK_EN (BIT(31)) +#define TIMG_CLK_EN_M (TIMG_CLK_EN_V << TIMG_CLK_EN_S) +#define TIMG_CLK_EN_V 0x00000001U #define TIMG_CLK_EN_S 31 #ifdef __cplusplus } #endif - - - -#endif /*_SOC_TIMG_REG_H_ */ diff --git a/components/soc/esp32s2/include/soc/timer_group_struct.h b/components/soc/esp32s2/include/soc/timer_group_struct.h index 55d6befeae..d4bb5ebe63 100644 --- a/components/soc/esp32s2/include/soc/timer_group_struct.h +++ b/components/soc/esp32s2/include/soc/timer_group_struct.h @@ -1,225 +1,789 @@ -// 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. -#ifndef _SOC_TIMG_STRUCT_H_ -#define _SOC_TIMG_STRUCT_H_ +/** + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once #include - #ifdef __cplusplus extern "C" { #endif -typedef volatile struct { +/** Group: Configuration and Control Register */ +/** Type of txconfig register + * Timer x configuration register + */ +typedef union { struct { - union { - struct { - uint32_t reserved0: 9; - uint32_t use_xtal: 1; - uint32_t alarm_en: 1; - uint32_t level_int_en: 1; - uint32_t edge_int_en: 1; - uint32_t divider: 16; - uint32_t autoreload: 1; - uint32_t increase: 1; - uint32_t enable: 1; - }; - uint32_t val; - } config; - uint32_t cnt_low; /**/ - uint32_t cnt_high; /**/ - union { - struct { - uint32_t reserved0: 31; - uint32_t update: 1; - }; - uint32_t val; - } update; - uint32_t alarm_low; /**/ - uint32_t alarm_high; /**/ - uint32_t load_low; /**/ - uint32_t load_high; /**/ - uint32_t reload; /**/ - } hw_timer[2]; - union { - struct { - uint32_t reserved0: 12; - uint32_t appcpu_reset_en: 1; - uint32_t procpu_reset_en: 1; - uint32_t flashboot_mod_en: 1; - uint32_t sys_reset_length: 3; - uint32_t cpu_reset_length: 3; - uint32_t level_int_en: 1; - uint32_t edge_int_en: 1; - uint32_t stg3: 2; - uint32_t stg2: 2; - uint32_t stg1: 2; - uint32_t stg0: 2; - uint32_t en: 1; - }; - uint32_t val; - } wdt_config0; - union { - struct { - uint32_t reserved0: 16; - uint32_t clk_prescale: 16; - }; - uint32_t val; - } wdt_config1; - uint32_t wdt_config2; /**/ - uint32_t wdt_config3; /**/ - uint32_t wdt_config4; /**/ - uint32_t wdt_config5; /**/ - uint32_t wdt_feed; /**/ - uint32_t wdt_wprotect; /**/ - union { - struct { - uint32_t reserved0: 12; - uint32_t start_cycling: 1; - uint32_t clk_sel: 2; - uint32_t rdy: 1; - uint32_t max: 15; - uint32_t start: 1; - }; - uint32_t val; - } rtc_cali_cfg; - union { - struct { - uint32_t cycling_data_vld: 1; - uint32_t reserved1: 6; - uint32_t value: 25; - }; - uint32_t val; - } rtc_cali_cfg1; - union { - struct { - uint32_t reserved0: 6; - uint32_t use_reftick: 1; - uint32_t rtc_only: 1; - uint32_t cpst_en: 1; - uint32_t lac_en: 1; - uint32_t alarm_en: 1; - uint32_t level_int_en: 1; - uint32_t edge_int_en: 1; - uint32_t divider: 16; - uint32_t autoreload: 1; - uint32_t increase: 1; - uint32_t en: 1; - }; - uint32_t val; - } lactconfig; - union { - struct { - uint32_t reserved0: 6; - uint32_t step_len: 26; - }; - uint32_t val; - } lactrtc; - uint32_t lactlo; /**/ - uint32_t lacthi; /**/ - uint32_t lactupdate; /**/ - uint32_t lactalarmlo; /**/ - uint32_t lactalarmhi; /**/ - uint32_t lactloadlo; /**/ - uint32_t lactloadhi; /**/ - uint32_t lactload; /**/ - union { - struct { - uint32_t t0: 1; - uint32_t t1: 1; - uint32_t wdt: 1; - uint32_t lact: 1; - uint32_t reserved4: 28; - }; - uint32_t val; - } int_ena; - union { - struct { - uint32_t t0: 1; - uint32_t t1: 1; - uint32_t wdt: 1; - uint32_t lact: 1; - uint32_t reserved4: 28; - }; - uint32_t val; - } int_raw; - union { - struct { - uint32_t t0: 1; - uint32_t t1: 1; - uint32_t wdt: 1; - uint32_t lact: 1; - uint32_t reserved4: 28; - }; - uint32_t val; - } int_st; - union { - struct { - uint32_t t0: 1; - uint32_t t1: 1; - uint32_t wdt: 1; - uint32_t lact: 1; - uint32_t reserved4: 28; - }; - uint32_t val; - } int_clr; - union { - struct { - uint32_t timeout: 1; /*timeout indicator*/ - uint32_t reserved1: 2; - uint32_t timeout_rst_cnt: 4; /*Cycles that release calibration timeout reset*/ - uint32_t timeout_thres: 25; /*timeout if cali value counts over threshold*/ - }; - uint32_t val; - } rtc_cali_cfg2; - uint32_t reserved_ac; - uint32_t reserved_b0; - uint32_t reserved_b4; - uint32_t reserved_b8; - uint32_t reserved_bc; - uint32_t reserved_c0; - uint32_t reserved_c4; - uint32_t reserved_c8; - uint32_t reserved_cc; - uint32_t reserved_d0; - uint32_t reserved_d4; - uint32_t reserved_d8; - uint32_t reserved_dc; - uint32_t reserved_e0; - uint32_t reserved_e4; - uint32_t reserved_e8; - uint32_t reserved_ec; - uint32_t reserved_f0; - uint32_t reserved_f4; - union { - struct { - uint32_t date: 28; - uint32_t reserved28: 4; - }; - uint32_t val; - } timg_date; - union { - struct { - uint32_t reserved0: 31; - uint32_t en: 1; - }; - uint32_t val; - } clk; + uint32_t reserved_0:9; + /** tx_use_xtal : R/W; bitpos: [9]; default: 0; + * 1: Use XTAL_CLK as the source clock of timer group. 0: Use APB_CLK as the source + * clock of timer group. + */ + uint32_t tx_use_xtal:1; + /** tx_alarm_en : R/W; bitpos: [10]; default: 0; + * When set, the alarm is enabled. This bit is automatically cleared once an + * + * alarm occurs. + */ + uint32_t tx_alarm_en:1; + /** tx_level_int_en : R/W; bitpos: [11]; default: 0; + * When set, an alarm will generate a level type interrupt. + */ + uint32_t tx_level_int_en:1; + /** tx_edge_int_en : R/W; bitpos: [12]; default: 0; + * When set, an alarm will generate an edge type interrupt. + */ + uint32_t tx_edge_int_en:1; + /** tx_divider : R/W; bitpos: [28:13]; default: 1; + * Timer x clock (Tx_clk) prescaler value. + */ + uint32_t tx_divider:16; + /** tx_autoreload : R/W; bitpos: [29]; default: 1; + * When set, timer x auto-reload at alarm is enabled. + */ + uint32_t tx_autoreload:1; + /** tx_increase : R/W; bitpos: [30]; default: 1; + * When set, the timer x time-base counter will increment every clock tick. When + * + * cleared, the timer x time-base counter will decrement. + */ + uint32_t tx_increase:1; + /** tx_en : R/W; bitpos: [31]; default: 0; + * When set, the timer x time-base counter is enabled. + */ + uint32_t tx_en:1; + }; + uint32_t val; +} timg_txconfig_reg_t; + +/** Type of txlo register + * Timer x current value, low 32 bits + */ +typedef union { + struct { + /** tx_lo : RO; bitpos: [31:0]; default: 0; + * After writing to TIMG_TxUPDATE_REG, the low 32 bits of the time-base counter + * + * of timer x can be read here. + */ + uint32_t tx_lo:32; + }; + uint32_t val; +} timg_txlo_reg_t; + +/** Type of txhi register + * Timer x current value, high 32 bits + */ +typedef union { + struct { + /** tx_hi : RO; bitpos: [31:0]; default: 0; + * After writing to TIMG_TxUPDATE_REG, the high 32 bits of the time-base counter + * + * of timer x can be read here. + */ + uint32_t tx_hi:32; + }; + uint32_t val; +} timg_txhi_reg_t; + +/** Type of txupdate register + * Write to copy current timer value to TIMGn_Tx_(LO/HI)_REG + */ +typedef union { + struct { + uint32_t reserved_0:31; + /** tx_update : R/W; bitpos: [31]; default: 0; + * After writing 0 or 1 to TIMG_TxUPDATE_REG, the counter value is latched. + */ + uint32_t tx_update:1; + }; + uint32_t val; +} timg_txupdate_reg_t; + +/** Type of txalarmlo register + * Timer x alarm value, low 32 bits + */ +typedef union { + struct { + /** tx_alarm_lo : R/W; bitpos: [31:0]; default: 0; + * Timer x alarm trigger time-base counter value, low 32 bits. + */ + uint32_t tx_alarm_lo:32; + }; + uint32_t val; +} timg_txalarmlo_reg_t; + +/** Type of txalarmhi register + * Timer x alarm value, high bits + */ +typedef union { + struct { + /** tx_alarm_hi : R/W; bitpos: [31:0]; default: 0; + * + * + * Timer x alarm trigger time-base counter value, high 32 bits. + */ + uint32_t tx_alarm_hi:32; + }; + uint32_t val; +} timg_txalarmhi_reg_t; + +/** Type of txloadlo register + * Timer x reload value, low 32 bits + */ +typedef union { + struct { + /** tx_load_lo : R/W; bitpos: [31:0]; default: 0; + * + * + * Low 32 bits of the value that a reload will load onto timer x time-base + * + * Counter. + */ + uint32_t tx_load_lo:32; + }; + uint32_t val; +} timg_txloadlo_reg_t; + +/** Type of txloadhi register + * Timer x reload value, high 32 bits + */ +typedef union { + struct { + /** tx_load_hi : R/W; bitpos: [31:0]; default: 0; + * + * + * High 32 bits of the value that a reload will load onto timer x time-base + * + * counter. + */ + uint32_t tx_load_hi:32; + }; + uint32_t val; +} timg_txloadhi_reg_t; + +/** Type of txload register + * Write to reload timer from TIMG_T0_(LOADLOLOADHI)_REG + */ +typedef union { + struct { + /** tx_load : WO; bitpos: [31:0]; default: 0; + * + * + * Write any value to trigger a timer x time-base counter reload. + */ + uint32_t tx_load:32; + }; + uint32_t val; +} timg_txload_reg_t; + + +/** Group: Configuration and Control Register for WDT */ +/** Type of wdtconfig0 register + * Watchdog timer configuration register + */ +typedef union { + struct { + uint32_t reserved_0:12; + /** wdt_appcpu_reset_en : R/W; bitpos: [12]; default: 0; + * Reserved + */ + uint32_t wdt_appcpu_reset_en:1; + /** wdt_procpu_reset_en : R/W; bitpos: [13]; default: 0; + * WDT reset CPU enable. + */ + uint32_t wdt_procpu_reset_en:1; + /** wdt_flashboot_mod_en : R/W; bitpos: [14]; default: 1; + * When set, Flash boot protection is enabled. + */ + uint32_t wdt_flashboot_mod_en:1; + /** wdt_sys_reset_length : R/W; bitpos: [17:15]; default: 1; + * System reset signal length selection. 0: 100 ns, 1: 200 ns, + * + * 2: 300 ns, 3: 400 ns, 4: 500 ns, 5: 800 ns, 6: 1.6 us, 7: 3.2 us. + */ + uint32_t wdt_sys_reset_length:3; + /** wdt_cpu_reset_length : R/W; bitpos: [20:18]; default: 1; + * CPU reset signal length selection. 0: 100 ns, 1: 200 ns, + * + * 2: 300 ns, 3: 400 ns, 4: 500 ns, 5: 800 ns, 6: 1.6 us, 7: 3.2 us. + */ + uint32_t wdt_cpu_reset_length:3; + /** wdt_level_int_en : R/W; bitpos: [21]; default: 0; + * When set, a level type interrupt will occur at the timeout of a stage + * + * configured to generate an interrupt. + */ + uint32_t wdt_level_int_en:1; + /** wdt_edge_int_en : R/W; bitpos: [22]; default: 0; + * When set, an edge type interrupt will occur at the timeout of a stage + * + * configured to generate an interrupt. + */ + uint32_t wdt_edge_int_en:1; + /** wdt_stg3 : R/W; bitpos: [24:23]; default: 0; + * Stage 3 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system. + * + */ + uint32_t wdt_stg3:2; + /** wdt_stg2 : R/W; bitpos: [26:25]; default: 0; + * Stage 2 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system. + * + */ + uint32_t wdt_stg2:2; + /** wdt_stg1 : R/W; bitpos: [28:27]; default: 0; + * Stage 1 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system. + * + */ + uint32_t wdt_stg1:2; + /** wdt_stg0 : R/W; bitpos: [30:29]; default: 0; + * Stage 0 configuration. 0: off, 1: interrupt, 2: reset CPU, 3: reset system. + * + */ + uint32_t wdt_stg0:2; + /** wdt_en : R/W; bitpos: [31]; default: 0; + * When set, MWDT is enabled. + */ + uint32_t wdt_en:1; + }; + uint32_t val; +} timg_wdtconfig0_reg_t; + +/** Type of wdtconfig1 register + * Watchdog timer prescaler register + */ +typedef union { + struct { + uint32_t reserved_0:16; + /** wdt_clk_prescaler : R/W; bitpos: [31:16]; default: 1; + * MWDT clock prescaler value. MWDT clock period = 12.5 ns * + * + * TIMG_WDT_CLK_PRESCALE. + */ + uint32_t wdt_clk_prescaler:16; + }; + uint32_t val; +} timg_wdtconfig1_reg_t; + +/** Type of wdtconfig2 register + * Watchdog timer stage 0 timeout value + */ +typedef union { + struct { + /** wdt_stg0_hold : R/W; bitpos: [31:0]; default: 26000000; + * Stage 0 timeout value, in MWDT clock cycles. + */ + uint32_t wdt_stg0_hold:32; + }; + uint32_t val; +} timg_wdtconfig2_reg_t; + +/** Type of wdtconfig3 register + * Watchdog timer stage 1 timeout value + */ +typedef union { + struct { + /** wdt_stg1_hold : R/W; bitpos: [31:0]; default: 134217727; + * Stage 1 timeout value, in MWDT clock cycles. + */ + uint32_t wdt_stg1_hold:32; + }; + uint32_t val; +} timg_wdtconfig3_reg_t; + +/** Type of wdtconfig4 register + * Watchdog timer stage 2 timeout value + */ +typedef union { + struct { + /** wdt_stg2_hold : R/W; bitpos: [31:0]; default: 1048575; + * Stage 2 timeout value, in MWDT clock cycles. + */ + uint32_t wdt_stg2_hold:32; + }; + uint32_t val; +} timg_wdtconfig4_reg_t; + +/** Type of wdtconfig5 register + * Watchdog timer stage 3 timeout value + */ +typedef union { + struct { + /** wdt_stg3_hold : R/W; bitpos: [31:0]; default: 1048575; + * Stage 3 timeout value, in MWDT clock cycles. + */ + uint32_t wdt_stg3_hold:32; + }; + uint32_t val; +} timg_wdtconfig5_reg_t; + +/** Type of wdtfeed register + * Write to feed the watchdog timer + */ +typedef union { + struct { + /** wdt_feed : WO; bitpos: [31:0]; default: 0; + * Write any value to feed the MWDT. (WO) + */ + uint32_t wdt_feed:32; + }; + uint32_t val; +} timg_wdtfeed_reg_t; + +/** Type of wdtwprotect register + * Watchdog write protect register + */ +typedef union { + struct { + /** wdt_wkey : R/W; bitpos: [31:0]; default: 1356348065; + * If the register contains a different value than its reset value, write + * + * protection is enabled. + */ + uint32_t wdt_wkey:32; + }; + uint32_t val; +} timg_wdtwprotect_reg_t; + + +/** Group: Configuration and Control Register for RTC CALI */ +/** Type of rtccalicfg register + * RTC calibration configuration register + */ +typedef union { + struct { + uint32_t reserved_0:12; + /** rtc_cali_start_cycling : R/W; bitpos: [12]; default: 1; + * Reserved + */ + uint32_t rtc_cali_start_cycling:1; + /** rtc_cali_clk_sel : R/W; bitpos: [14:13]; default: 1; + * 0:rtcslowclock. 1:clk_80m. 2:xtal_32k. + */ + uint32_t rtc_cali_clk_sel:2; + /** rtc_cali_rdy : RO; bitpos: [15]; default: 0; + * Reserved + */ + uint32_t rtc_cali_rdy:1; + /** rtc_cali_max : R/W; bitpos: [30:16]; default: 1; + * Reserved + */ + uint32_t rtc_cali_max:15; + /** rtc_cali_start : R/W; bitpos: [31]; default: 0; + * Reserved + */ + uint32_t rtc_cali_start:1; + }; + uint32_t val; +} timg_rtccalicfg_reg_t; + +/** Type of rtccalicfg1 register + * RTC calibration configuration1 register + */ +typedef union { + struct { + /** rtc_cali_cycling_data_vld : RO; bitpos: [0]; default: 0; + * Reserved + */ + uint32_t rtc_cali_cycling_data_vld:1; + uint32_t reserved_1:6; + /** rtc_cali_value : RO; bitpos: [31:7]; default: 0; + * Reserved + */ + uint32_t rtc_cali_value:25; + }; + uint32_t val; +} timg_rtccalicfg1_reg_t; + +/** Type of rtccalicfg2 register + * Timer group calibration register + */ +typedef union { + struct { + /** rtc_cali_timeout : RO; bitpos: [0]; default: 0; + * RTC calibration timeout indicator + */ + uint32_t rtc_cali_timeout:1; + uint32_t reserved_1:2; + /** rtc_cali_timeout_rst_cnt : R/W; bitpos: [6:3]; default: 3; + * Cycles that release calibration timeout reset + */ + uint32_t rtc_cali_timeout_rst_cnt:4; + /** rtc_cali_timeout_thres : R/W; bitpos: [31:7]; default: 33554431; + * Threshold value for the RTC calibration timer. If the calibration timer's value + * exceeds this threshold, a timeout is triggered. + */ + uint32_t rtc_cali_timeout_thres:25; + }; + uint32_t val; +} timg_rtccalicfg2_reg_t; + + +/** Group: Configuration and Control Register for LACT */ +/** Type of lactconfig register + * LACT configuration register + */ +typedef union { + struct { + uint32_t reserved_0:6; + /** lact_use_reftick : R/W; bitpos: [6]; default: 0; + * Reserved + */ + uint32_t lact_use_reftick:1; + /** lact_rtc_only : R/W; bitpos: [7]; default: 0; + * Reserved + */ + uint32_t lact_rtc_only:1; + /** lact_cpst_en : R/W; bitpos: [8]; default: 1; + * Reserved + */ + uint32_t lact_cpst_en:1; + /** lact_lac_en : R/W; bitpos: [9]; default: 1; + * Reserved + */ + uint32_t lact_lac_en:1; + /** lact_alarm_en : R/W; bitpos: [10]; default: 0; + * Reserved + */ + uint32_t lact_alarm_en:1; + /** lact_level_int_en : R/W; bitpos: [11]; default: 0; + * Reserved + */ + uint32_t lact_level_int_en:1; + /** lact_edge_int_en : R/W; bitpos: [12]; default: 0; + * Reserved + */ + uint32_t lact_edge_int_en:1; + /** lact_divider : R/W; bitpos: [28:13]; default: 1; + * Reserved + */ + uint32_t lact_divider:16; + /** lact_autoreload : R/W; bitpos: [29]; default: 1; + * Reserved + */ + uint32_t lact_autoreload:1; + /** lact_increase : R/W; bitpos: [30]; default: 1; + * Reserved + */ + uint32_t lact_increase:1; + /** lact_en : R/W; bitpos: [31]; default: 0; + * Reserved + */ + uint32_t lact_en:1; + }; + uint32_t val; +} timg_lactconfig_reg_t; + +/** Type of lactrtc register + * LACT RTC register + */ +typedef union { + struct { + uint32_t reserved_0:6; + /** lact_rtc_step_len : R/W; bitpos: [31:6]; default: 0; + * Reserved + */ + uint32_t lact_rtc_step_len:26; + }; + uint32_t val; +} timg_lactrtc_reg_t; + +/** Type of lactlo register + * LACT low register + */ +typedef union { + struct { + /** lact_lo : RO; bitpos: [31:0]; default: 0; + * Reserved + */ + uint32_t lact_lo:32; + }; + uint32_t val; +} timg_lactlo_reg_t; + +/** Type of lacthi register + * LACT high register + */ +typedef union { + struct { + /** lact_hi : RO; bitpos: [31:0]; default: 0; + * Reserved + */ + uint32_t lact_hi:32; + }; + uint32_t val; +} timg_lacthi_reg_t; + +/** Type of lactupdate register + * LACT update register + */ +typedef union { + struct { + /** lact_update : WO; bitpos: [31:0]; default: 0; + * Reserved + */ + uint32_t lact_update:32; + }; + uint32_t val; +} timg_lactupdate_reg_t; + +/** Type of lactalarmlo register + * LACT alarm low register + */ +typedef union { + struct { + /** lact_alarm_lo : R/W; bitpos: [31:0]; default: 0; + * Reserved + */ + uint32_t lact_alarm_lo:32; + }; + uint32_t val; +} timg_lactalarmlo_reg_t; + +/** Type of lactalarmhi register + * LACT alarm high register + */ +typedef union { + struct { + /** lact_alarm_hi : R/W; bitpos: [31:0]; default: 0; + * Reserved + */ + uint32_t lact_alarm_hi:32; + }; + uint32_t val; +} timg_lactalarmhi_reg_t; + +/** Type of lactloadlo register + * LACT load low register + */ +typedef union { + struct { + /** lact_load_lo : R/W; bitpos: [31:0]; default: 0; + * Reserved + */ + uint32_t lact_load_lo:32; + }; + uint32_t val; +} timg_lactloadlo_reg_t; + +/** Type of lactloadhi register + * Timer LACT load high register + */ +typedef union { + struct { + /** lact_load_hi : R/W; bitpos: [31:0]; default: 0; + * Reserved + */ + uint32_t lact_load_hi:32; + }; + uint32_t val; +} timg_lactloadhi_reg_t; + +/** Type of lactload register + * Timer LACT load register + */ +typedef union { + struct { + /** lact_load : WO; bitpos: [31:0]; default: 0; + * Reserved + */ + uint32_t lact_load:32; + }; + uint32_t val; +} timg_lactload_reg_t; + + +/** Group: Interrupt Register */ +/** Type of int_ena_timers register + * Interrupt enable bits + */ +typedef union { + struct { + /** tx_int_ena : R/W; bitpos: [0]; default: 0; + * The interrupt enable bit for the TIMG_T0_INT interrupt. + */ + uint32_t tx_int_ena:1; + /** t1_int_ena : R/W; bitpos: [1]; default: 0; + * The interrupt enable bit for the TIMG_T1_INT interrupt. + */ + uint32_t t1_int_ena:1; + /** wdt_int_ena : R/W; bitpos: [2]; default: 0; + * The interrupt enable bit for the TIMG_WDT_INT interrupt. + */ + uint32_t wdt_int_ena:1; + /** lact_int_ena : R/W; bitpos: [3]; default: 0; + * The interrupt enable bit for the TIMG_LACT_INT interrupt. + */ + uint32_t lact_int_ena:1; + uint32_t reserved_4:28; + }; + uint32_t val; +} timg_int_ena_timers_reg_t; + +/** Type of int_raw_timers register + * Raw interrupt status + */ +typedef union { + struct { + /** t0_int_raw : RO; bitpos: [0]; default: 0; + * The raw interrupt status bit for the TIMG_T0_INT interrupt. + */ + uint32_t t0_int_raw:1; + /** t1_int_raw : RO; bitpos: [1]; default: 0; + * The raw interrupt status bit for the TIMG_T1_INT interrupt. + */ + uint32_t t1_int_raw:1; + /** wdt_int_raw : RO; bitpos: [2]; default: 0; + * The raw interrupt status bit for the TIMG_WDT_INT interrupt. + */ + uint32_t wdt_int_raw:1; + /** lact_int_raw : RO; bitpos: [3]; default: 0; + * The raw interrupt status bit for the TIMG_LACT_INT interrupt. + */ + uint32_t lact_int_raw:1; + uint32_t reserved_4:28; + }; + uint32_t val; +} timg_int_raw_timers_reg_t; + +/** Type of int_st_timers register + * Masked interrupt status + */ +typedef union { + struct { + /** t0_int_st : RO; bitpos: [0]; default: 0; + * The masked interrupt status bit for the TIMG_T0_INT interrupt. + */ + uint32_t t0_int_st:1; + /** t1_int_st : RO; bitpos: [1]; default: 0; + * The masked interrupt status bit for the TIMG_T1_INT interrupt. + */ + uint32_t t1_int_st:1; + /** wdt_int_st : RO; bitpos: [2]; default: 0; + * The masked interrupt status bit for the TIMG_WDT_INT interrupt. + */ + uint32_t wdt_int_st:1; + /** lact_int_st : RO; bitpos: [3]; default: 0; + * The masked interrupt status bit for the TIMG_LACT_INT interrupt. + */ + uint32_t lact_int_st:1; + uint32_t reserved_4:28; + }; + uint32_t val; +} timg_int_st_timers_reg_t; + +/** Type of int_clr_timers register + * Interrupt clear bits + */ +typedef union { + struct { + /** t0_int_clr : WO; bitpos: [0]; default: 0; + * Set this bit to clear the TIMG_T0_INT interrupt. + */ + uint32_t t0_int_clr:1; + /** t1_int_clr : WO; bitpos: [1]; default: 0; + * Set this bit to clear the TIMG_T1_INT interrupt. + */ + uint32_t t1_int_clr:1; + /** wdt_int_clr : WO; bitpos: [2]; default: 0; + * Set this bit to clear the TIMG_WDT_INT interrupt. + */ + uint32_t wdt_int_clr:1; + /** lact_int_clr : WO; bitpos: [3]; default: 0; + * Set this bit to clear the TIMG_LACT_INT interrupt. + */ + uint32_t lact_int_clr:1; + uint32_t reserved_4:28; + }; + uint32_t val; +} timg_int_clr_timers_reg_t; + + +/** Group: Version Register */ +/** Type of timers_date register + * Version control register + */ +typedef union { + struct { + /** timers_date : R/W; bitpos: [27:0]; default: 26243681; + * Version control register. + */ + uint32_t timers_date:28; + uint32_t reserved_28:4; + }; + uint32_t val; +} timg_timers_date_reg_t; + + +/** Group: Configuration Register */ +/** Type of regclk register + * Timer group clock gate register + */ +typedef union { + struct { + uint32_t reserved_0:31; + /** clk_en : R/W; bitpos: [31]; default: 0; + * Register clock gate signal. 1: Registers can be read and written to by software. 0: + * Registers can not be read or written to by software. + */ + uint32_t clk_en:1; + }; + uint32_t val; +} timg_regclk_reg_t; + +typedef struct { + volatile timg_txconfig_reg_t config; + volatile timg_txlo_reg_t lo; + volatile timg_txhi_reg_t hi; + volatile timg_txupdate_reg_t update; + volatile timg_txalarmlo_reg_t alarmlo; + volatile timg_txalarmhi_reg_t alarmhi; + volatile timg_txloadlo_reg_t loadlo; + volatile timg_txloadhi_reg_t loadhi; + volatile timg_txload_reg_t load; +} timg_hwtimer_reg_t; + +typedef struct { + volatile timg_hwtimer_reg_t hw_timer[2]; + volatile timg_wdtconfig0_reg_t wdtconfig0; + volatile timg_wdtconfig1_reg_t wdtconfig1; + volatile timg_wdtconfig2_reg_t wdtconfig2; + volatile timg_wdtconfig3_reg_t wdtconfig3; + volatile timg_wdtconfig4_reg_t wdtconfig4; + volatile timg_wdtconfig5_reg_t wdtconfig5; + volatile timg_wdtfeed_reg_t wdtfeed; + volatile timg_wdtwprotect_reg_t wdtwprotect; + volatile timg_rtccalicfg_reg_t rtccalicfg; + volatile timg_rtccalicfg1_reg_t rtccalicfg1; + volatile timg_lactconfig_reg_t lactconfig; + volatile timg_lactrtc_reg_t lactrtc; + volatile timg_lactlo_reg_t lactlo; + volatile timg_lacthi_reg_t lacthi; + volatile timg_lactupdate_reg_t lactupdate; + volatile timg_lactalarmlo_reg_t lactalarmlo; + volatile timg_lactalarmhi_reg_t lactalarmhi; + volatile timg_lactloadlo_reg_t lactloadlo; + volatile timg_lactloadhi_reg_t lactloadhi; + volatile timg_lactload_reg_t lactload; + volatile timg_int_ena_timers_reg_t int_ena_timers; + volatile timg_int_raw_timers_reg_t int_raw_timers; + volatile timg_int_st_timers_reg_t int_st_timers; + volatile timg_int_clr_timers_reg_t int_clr_timers; + volatile timg_rtccalicfg2_reg_t rtccalicfg2; + uint32_t reserved_0ac[19]; + volatile timg_timers_date_reg_t timers_date; + volatile timg_regclk_reg_t regclk; } timg_dev_t; + extern timg_dev_t TIMERG0; extern timg_dev_t TIMERG1; + +#ifndef __cplusplus +_Static_assert(sizeof(timg_dev_t) == 0x100, "Invalid size of timg_dev_t structure"); +#endif + #ifdef __cplusplus } #endif - -#endif /* _SOC_TIMG_STRUCT_H_ */ diff --git a/components/soc/esp32s2/include/soc/twai_struct.h b/components/soc/esp32s2/include/soc/twai_struct.h index 5cba4d409a..00a006501c 100644 --- a/components/soc/esp32s2/include/soc/twai_struct.h +++ b/components/soc/esp32s2/include/soc/twai_struct.h @@ -35,10 +35,10 @@ typedef volatile struct twai_dev_s { uint32_t lom: 1; /* MOD.1 Listen Only Mode */ uint32_t stm: 1; /* MOD.2 Self Test Mode */ uint32_t afm: 1; /* MOD.3 Acceptance Filter Mode */ - uint32_t reserved28: 28; /* Internal Reserved. MOD.4 Sleep Mode not supported */ + uint32_t reserved4: 28; /* Internal Reserved. MOD.4 Sleep Mode not supported */ }; uint32_t val; - } mode_reg; /* Address 0 */ + } mode_reg; /* Address 0x0000 */ union { struct { uint32_t tr: 1; /* CMR.0 Transmission Request */ @@ -46,10 +46,10 @@ typedef volatile struct twai_dev_s { uint32_t rrb: 1; /* CMR.2 Release Receive Buffer */ uint32_t cdo: 1; /* CMR.3 Clear Data Overrun */ uint32_t srr: 1; /* CMR.4 Self Reception Request */ - uint32_t reserved27: 27; /* Internal Reserved */ + uint32_t reserved5: 27; /* Internal Reserved */ }; uint32_t val; - } command_reg; /* Address 1 */ + } command_reg; /* Address 0x0004 */ union { struct { uint32_t rbs: 1; /* SR.0 Receive Buffer Status */ @@ -61,37 +61,39 @@ typedef volatile struct twai_dev_s { uint32_t es: 1; /* SR.6 Error Status */ uint32_t bs: 1; /* SR.7 Bus Status */ uint32_t ms: 1; /* SR.8 Miss Status */ - uint32_t reserved23: 23; /* Internal Reserved */ + uint32_t reserved9: 23; /* Internal Reserved */ }; uint32_t val; - } status_reg; /* Address 2 */ + } status_reg; /* Address 0x0008 */ union { struct { uint32_t ri: 1; /* IR.0 Receive Interrupt */ uint32_t ti: 1; /* IR.1 Transmit Interrupt */ uint32_t ei: 1; /* IR.2 Error Interrupt */ - uint32_t reserved2: 2; /* Internal Reserved (Data Overrun interrupt and Wake-up not supported) */ + uint32_t doi: 1; /* IR.3 Data Overrun Interrupt */ + uint32_t reserved4: 1; /* Internal Reserved (Wake-up not supported) */ uint32_t epi: 1; /* IR.5 Error Passive Interrupt */ uint32_t ali: 1; /* IR.6 Arbitration Lost Interrupt */ uint32_t bei: 1; /* IR.7 Bus Error Interrupt */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } interrupt_reg; /* Address 3 */ + } interrupt_reg; /* Address 0x000C */ union { struct { uint32_t rie: 1; /* IER.0 Receive Interrupt Enable */ uint32_t tie: 1; /* IER.1 Transmit Interrupt Enable */ uint32_t eie: 1; /* IER.2 Error Interrupt Enable */ - uint32_t reserved2: 2; /* Internal Reserved (Data Overrun interrupt and Wake-up not supported) */ + uint32_t doie: 1; /* IER.3 Data Overrun Interrupt Enable */ + uint32_t reserved4: 1; /* Internal Reserved (Wake-up not supported) */ uint32_t epie: 1; /* IER.5 Error Passive Interrupt Enable */ uint32_t alie: 1; /* IER.6 Arbitration Lost Interrupt Enable */ uint32_t beie: 1; /* IER.7 Bus Error Interrupt Enable */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } interrupt_enable_reg; /* Address 4 */ - uint32_t reserved_05; /* Address 5 */ + } interrupt_enable_reg; /* Address 0x0010 */ + uint32_t reserved_14; union { struct { uint32_t brp: 14; /* BTR0[13:0] Baud Rate Prescaler */ @@ -99,58 +101,58 @@ typedef volatile struct twai_dev_s { uint32_t reserved16: 16; /* Internal Reserved */ }; uint32_t val; - } bus_timing_0_reg; /* Address 6 */ + } bus_timing_0_reg; /* Address 0x0018 */ union { struct { uint32_t tseg1: 4; /* BTR1[3:0] Timing Segment 1 */ uint32_t tseg2: 3; /* BTR1[6:4] Timing Segment 2 */ uint32_t sam: 1; /* BTR1.7 Sampling*/ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } bus_timing_1_reg; /* Address 7 */ - uint32_t reserved_08; /* Address 8 (Output control not supported) */ - uint32_t reserved_09; /* Address 9 (Test Register not supported) */ - uint32_t reserved_10; /* Address 10 */ + } bus_timing_1_reg; /* Address 0x001C */ + uint32_t reserved_20; /* Address 0x0020 (Output control not supported) */ + uint32_t reserved_24; /* Address 0x0024 (Test Register not supported) */ + uint32_t reserved_28; /* Address 0x0028 */ //Capture and Counter Registers union { struct { uint32_t alc: 5; /* ALC[4:0] Arbitration lost capture */ - uint32_t reserved27: 27; /* Internal Reserved */ + uint32_t reserved5: 27; /* Internal Reserved */ }; uint32_t val; - } arbitration_lost_captue_reg; /* Address 11 */ + } arbitration_lost_captue_reg; /* Address 0x002C */ union { struct { uint32_t seg: 5; /* ECC[4:0] Error Code Segment 0 to 5 */ uint32_t dir: 1; /* ECC.5 Error Direction (TX/RX) */ uint32_t errc: 2; /* ECC[7:6] Error Code */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } error_code_capture_reg; /* Address 12 */ + } error_code_capture_reg; /* Address 0x0030 */ union { struct { uint32_t ewl: 8; /* EWL[7:0] Error Warning Limit */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } error_warning_limit_reg; /* EWLR[7:0] Error Warning Limit: Address 13 */ + } error_warning_limit_reg; /* Address 0x0034 */ union { struct { uint32_t rxerr: 8; /* RXERR[7:0] Receive Error Counter */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } rx_error_counter_reg; /* Address 12 */ + } rx_error_counter_reg; /* Address 0x0038 */ union { struct { uint32_t txerr: 8; /* TXERR[7:0] Receive Error Counter */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } tx_error_counter_reg; /* Address 15 */ + } tx_error_counter_reg; /* Address 0x003C */ //Shared Registers (TX Buff/RX Buff/Acc Filter) union { @@ -158,45 +160,49 @@ typedef volatile struct twai_dev_s { union { struct { uint32_t byte: 8; /* ACRx[7:0] Acceptance Code */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; } acr[4]; union { struct { uint32_t byte: 8; /* AMRx[7:0] Acceptance Mask */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; } amr[4]; - uint32_t reserved32[5]; + uint32_t reserved_60; + uint32_t reserved_64; + uint32_t reserved_68; + uint32_t reserved_6c; + uint32_t reserved_70; } acceptance_filter; union { struct { - uint32_t byte: 8; - uint32_t reserved24: 24; + uint32_t byte: 8; /* TX/RX Byte X [7:0] */ + uint32_t reserved24: 24; /* Internal Reserved */ }; uint32_t val; } tx_rx_buffer[13]; - }; /* Address 16-28 TX/RX Buffer and Acc Filter*/; + }; /* Address 0x0040 - 0x0070 */ //Misc Registers union { struct { uint32_t rmc: 7; /* RMC[6:0] RX Message Counter */ - uint32_t reserved25: 25; /* Internal Reserved */ + uint32_t reserved7: 25; /* Internal Reserved */ }; uint32_t val; - } rx_message_counter_reg; /* Address 29 */ - uint32_t reserved_30; /* Address 30 (RX Buffer Start Address not supported) */ + } rx_message_counter_reg; /* Address 0x0074 */ + uint32_t reserved_78; /* Address 0x0078 (RX Buffer Start Address not supported) */ union { struct { uint32_t cd: 8; /* CDR[7:0] CLKOUT frequency selector based of fOSC */ uint32_t co: 1; /* CDR.8 CLKOUT enable/disable */ - uint32_t reserved24: 23; /* Internal Reserved */ + uint32_t reserved9: 23; /* Internal Reserved */ }; uint32_t val; - } clock_divider_reg; /* Address 31 */ + } clock_divider_reg; /* Address 0x007C */ } twai_dev_t; _Static_assert(sizeof(twai_dev_t) == 128, "TWAI registers should be 32 * 4 bytes"); diff --git a/components/soc/esp32s2/include/soc/uart_pins.h b/components/soc/esp32s2/include/soc/uart_pins.h new file mode 100644 index 0000000000..a6a7d18724 --- /dev/null +++ b/components/soc/esp32s2/include/soc/uart_pins.h @@ -0,0 +1,43 @@ +// Copyright 2015-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. + +#pragma once + +#include "soc/io_mux_reg.h" + +/* Specify the number of pins for UART */ +#define SOC_UART_PINS_COUNT (4) + +/* Specify the GPIO pin number for each UART signal in the IOMUX */ +#define U0RXD_GPIO_NUM (44) +#define U0TXD_GPIO_NUM (43) +#define U0RTS_GPIO_NUM (15) +#define U0CTS_GPIO_NUM (16) + +#define U1RXD_GPIO_NUM (18) +#define U1TXD_GPIO_NUM (17) +#define U1RTS_GPIO_NUM (19) +#define U1CTS_GPIO_NUM (20) + +/* The following defines are necessary for reconfiguring the UART + * to use IOMUX, at runtime. */ +#define U0TXD_MUX_FUNC (FUNC_U0TXD_U0TXD) +#define U0RXD_MUX_FUNC (FUNC_U0RXD_U0RXD) +#define U0RTS_MUX_FUNC (FUNC_XTAL_32K_P_U0RTS) +#define U0CTS_MUX_FUNC (FUNC_XTAL_32K_N_U0CTS) + +#define U1TXD_MUX_FUNC (FUNC_DAC_1_U1TXD) +#define U1RXD_MUX_FUNC (FUNC_DAC_2_U1RXD) +#define U1RTS_MUX_FUNC (FUNC_GPIO19_U1RTS) +#define U1CTS_MUX_FUNC (FUNC_GPIO20_U1CTS) diff --git a/components/soc/esp32s2/include/soc/uart_struct.h b/components/soc/esp32s2/include/soc/uart_struct.h index a470b6b968..5eb977825b 100644 --- a/components/soc/esp32s2/include/soc/uart_struct.h +++ b/components/soc/esp32s2/include/soc/uart_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct uart_dev_s { union { struct { uint32_t rw_byte;/*note: rw_byte is a uint8_t field, however, ESP32-S2 do not support 8 bits read/write*/ diff --git a/components/soc/esp32s2/include/soc/uhci_struct.h b/components/soc/esp32s2/include/soc/uhci_struct.h index aadc2a6303..63cc074161 100644 --- a/components/soc/esp32s2/include/soc/uhci_struct.h +++ b/components/soc/esp32s2/include/soc/uhci_struct.h @@ -17,7 +17,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct uhci_dev_s { union { struct { uint32_t in_rst: 1; diff --git a/components/soc/esp32s2/include/soc/usb_wrap_struct.h b/components/soc/esp32s2/include/soc/usb_wrap_struct.h index 147afc3228..c196743ec0 100644 --- a/components/soc/esp32s2/include/soc/usb_wrap_struct.h +++ b/components/soc/esp32s2/include/soc/usb_wrap_struct.h @@ -153,6 +153,7 @@ typedef union { * USB D- rx value in test. */ uint32_t test_rx_dm:1; + uint32_t reserved:25; }; uint32_t val; } usb_wrap_test_conf_reg_t; diff --git a/components/soc/esp32s2/include/soc/usbh_struct.h b/components/soc/esp32s2/include/soc/usbh_struct.h index ace84d7fa9..182a6034d1 100644 --- a/components/soc/esp32s2/include/soc/usbh_struct.h +++ b/components/soc/esp32s2/include/soc/usbh_struct.h @@ -830,7 +830,7 @@ typedef union { uint32_t bbleerr: 1; uint32_t nakintrpt: 1; uint32_t nyetintrpt: 1; - uint32_t reserved16: 16; + uint32_t reserved15: 17; }; uint32_t val; } usb_diepint_reg_t; diff --git a/components/soc/esp32s2/lcd_periph.c b/components/soc/esp32s2/lcd_periph.c new file mode 100644 index 0000000000..7ca1157e29 --- /dev/null +++ b/components/soc/esp32s2/lcd_periph.c @@ -0,0 +1,52 @@ +// Copyright 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. + +#include "soc/lcd_periph.h" +#include "soc/gpio_sig_map.h" + +const lcd_signal_conn_t lcd_periph_signals = { + .buses = { + [0] = { + .module = PERIPH_I2S0_MODULE, + .irq_id = ETS_I2S0_INTR_SOURCE, + .data_sigs = { + I2S0O_DATA_OUT0_IDX, + I2S0O_DATA_OUT1_IDX, + I2S0O_DATA_OUT2_IDX, + I2S0O_DATA_OUT3_IDX, + I2S0O_DATA_OUT4_IDX, + I2S0O_DATA_OUT5_IDX, + I2S0O_DATA_OUT6_IDX, + I2S0O_DATA_OUT7_IDX, + I2S0O_DATA_OUT8_IDX, + I2S0O_DATA_OUT9_IDX, + I2S0O_DATA_OUT10_IDX, + I2S0O_DATA_OUT11_IDX, + I2S0O_DATA_OUT12_IDX, + I2S0O_DATA_OUT13_IDX, + I2S0O_DATA_OUT14_IDX, + I2S0O_DATA_OUT15_IDX, + I2S0O_DATA_OUT16_IDX, + I2S0O_DATA_OUT17_IDX, + I2S0O_DATA_OUT18_IDX, + I2S0O_DATA_OUT19_IDX, + I2S0O_DATA_OUT20_IDX, + I2S0O_DATA_OUT21_IDX, + I2S0O_DATA_OUT22_IDX, + I2S0O_DATA_OUT23_IDX, + }, + .wr_sig = I2S0O_WS_OUT_IDX, + } + } +}; diff --git a/components/soc/esp32s2/ld/esp32s2.peripherals.ld b/components/soc/esp32s2/ld/esp32s2.peripherals.ld index 48aa0414ca..bd1d00c5b7 100644 --- a/components/soc/esp32s2/ld/esp32s2.peripherals.ld +++ b/components/soc/esp32s2/ld/esp32s2.peripherals.ld @@ -1,3 +1,8 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ PROVIDE ( UART0 = 0x3f400000 ); PROVIDE ( SPIMEM1 = 0x3f402000 ); PROVIDE ( SPIMEM0 = 0x3f403000 ); diff --git a/components/soc/esp32s2/pcnt_periph.c b/components/soc/esp32s2/pcnt_periph.c index a411187dee..bb163ccd62 100644 --- a/components/soc/esp32s2/pcnt_periph.c +++ b/components/soc/esp32s2/pcnt_periph.c @@ -16,54 +16,58 @@ #include "soc/gpio_sig_map.h" const pcnt_signal_conn_t pcnt_periph_signals = { - .module = PERIPH_PCNT_MODULE, - .irq = ETS_PCNT_INTR_SOURCE, - .units = { + .groups = { [0] = { - .channels = { + .module = PERIPH_PCNT_MODULE, + .irq = ETS_PCNT_INTR_SOURCE, + .units = { [0] = { - .control_sig = PCNT_CTRL_CH0_IN0_IDX, - .pulse_sig = PCNT_SIG_CH0_IN0_IDX + .channels = { + [0] = { + .control_sig = PCNT_CTRL_CH0_IN0_IDX, + .pulse_sig = PCNT_SIG_CH0_IN0_IDX + }, + [1] = { + .control_sig = PCNT_CTRL_CH1_IN0_IDX, + .pulse_sig = PCNT_SIG_CH1_IN0_IDX + } + } }, [1] = { - .control_sig = PCNT_CTRL_CH1_IN0_IDX, - .pulse_sig = PCNT_SIG_CH1_IN0_IDX - } - } - }, - [1] = { - .channels = { - [0] = { - .control_sig = PCNT_CTRL_CH0_IN1_IDX, - .pulse_sig = PCNT_SIG_CH0_IN1_IDX + .channels = { + [0] = { + .control_sig = PCNT_CTRL_CH0_IN1_IDX, + .pulse_sig = PCNT_SIG_CH0_IN1_IDX + }, + [1] = { + .control_sig = PCNT_CTRL_CH1_IN1_IDX, + .pulse_sig = PCNT_SIG_CH1_IN1_IDX + } + } }, - [1] = { - .control_sig = PCNT_CTRL_CH1_IN1_IDX, - .pulse_sig = PCNT_SIG_CH1_IN1_IDX - } - } - }, - [2] = { - .channels = { - [0] = { - .control_sig = PCNT_CTRL_CH0_IN2_IDX, - .pulse_sig = PCNT_SIG_CH0_IN2_IDX + [2] = { + .channels = { + [0] = { + .control_sig = PCNT_CTRL_CH0_IN2_IDX, + .pulse_sig = PCNT_SIG_CH0_IN2_IDX + }, + [1] = { + .control_sig = PCNT_CTRL_CH1_IN2_IDX, + .pulse_sig = PCNT_SIG_CH1_IN2_IDX + } + } }, - [1] = { - .control_sig = PCNT_CTRL_CH1_IN2_IDX, - .pulse_sig = PCNT_SIG_CH1_IN2_IDX - } - } - }, - [3] = { - .channels = { - [0] = { - .control_sig = PCNT_CTRL_CH0_IN3_IDX, - .pulse_sig = PCNT_SIG_CH0_IN3_IDX - }, - [1] = { - .control_sig = PCNT_CTRL_CH1_IN3_IDX, - .pulse_sig = PCNT_SIG_CH1_IN3_IDX + [3] = { + .channels = { + [0] = { + .control_sig = PCNT_CTRL_CH0_IN3_IDX, + .pulse_sig = PCNT_SIG_CH0_IN3_IDX + }, + [1] = { + .control_sig = PCNT_CTRL_CH1_IN3_IDX, + .pulse_sig = PCNT_SIG_CH1_IN3_IDX + } + } } } } diff --git a/components/soc/esp32s2/spi_periph.c b/components/soc/esp32s2/spi_periph.c index 08a8a10483..8e4373bf5f 100644 --- a/components/soc/esp32s2/spi_periph.c +++ b/components/soc/esp32s2/spi_periph.c @@ -50,10 +50,18 @@ const spi_signal_conn_t spi_periph_signal[SOC_SPI_PERIPH_NUM] = { .spiq_out = FSPIQ_OUT_IDX, .spiwp_out = FSPIWP_OUT_IDX, .spihd_out = FSPIHD_OUT_IDX, + .spid4_out = FSPIIO4_OUT_IDX, + .spid5_out = FSPIIO5_OUT_IDX, + .spid6_out = FSPIIO6_OUT_IDX, + .spid7_out = FSPIIO7_OUT_IDX, .spid_in = FSPID_IN_IDX, .spiq_in = FSPIQ_IN_IDX, .spiwp_in = FSPIWP_IN_IDX, .spihd_in = FSPIHD_IN_IDX, + .spid4_in = FSPIIO4_IN_IDX, + .spid5_in = FSPIIO5_IN_IDX, + .spid6_in = FSPIIO6_IN_IDX, + .spid7_in = FSPIIO7_IN_IDX, .spics_out = {FSPICS0_OUT_IDX, FSPICS1_OUT_IDX, FSPICS2_OUT_IDX}, .spics_in = FSPICS0_IN_IDX, .spiclk_iomux_pin = FSPI_IOMUX_PIN_NUM_CLK, diff --git a/components/soc/esp32s2/uart_periph.c b/components/soc/esp32s2/uart_periph.c index b3f484d763..8360cae082 100644 --- a/components/soc/esp32s2/uart_periph.c +++ b/components/soc/esp32s2/uart_periph.c @@ -19,18 +19,69 @@ */ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { { - .tx_sig = U0TXD_OUT_IDX, - .rx_sig = U0RXD_IN_IDX, - .rts_sig = U0RTS_OUT_IDX, - .cts_sig = U0CTS_IN_IDX, + .pins = { + [SOC_UART_TX_PIN_IDX] = { + .default_gpio = U0TXD_GPIO_NUM, + .iomux_func = U0TXD_MUX_FUNC, + .input = 0, + .signal = U0TXD_OUT_IDX, + }, + + [SOC_UART_RX_PIN_IDX] = { + .default_gpio = U0RXD_GPIO_NUM, + .iomux_func = U0RXD_MUX_FUNC, + .input = 1, + .signal = U0RXD_IN_IDX, + }, + + [SOC_UART_RTS_PIN_IDX] = { + .default_gpio = U0RTS_GPIO_NUM, + .iomux_func = U0RTS_MUX_FUNC, + .input = 0, + .signal = U0RTS_OUT_IDX, + }, + + [SOC_UART_CTS_PIN_IDX] = { + .default_gpio = U0CTS_GPIO_NUM, + .iomux_func = U0CTS_MUX_FUNC, + .input = 1, + .signal = U0CTS_IN_IDX, + } + }, .irq = ETS_UART0_INTR_SOURCE, .module = PERIPH_UART0_MODULE, }, + { - .tx_sig = U1TXD_OUT_IDX, - .rx_sig = U1RXD_IN_IDX, - .rts_sig = U1RTS_OUT_IDX, - .cts_sig = U1CTS_IN_IDX, + .pins = { + [SOC_UART_TX_PIN_IDX] = { + .default_gpio = U1TXD_GPIO_NUM, + .iomux_func = U1TXD_MUX_FUNC, + .input = 0, + .signal = U1TXD_OUT_IDX, + }, + + [SOC_UART_RX_PIN_IDX] = { + .default_gpio = U1RXD_GPIO_NUM, + .iomux_func = U1RXD_MUX_FUNC, + .input = 1, + .signal = U1RXD_IN_IDX, + }, + + [SOC_UART_RTS_PIN_IDX] = { + .default_gpio = U1RTS_GPIO_NUM, + .iomux_func = U1RTS_MUX_FUNC, + .input = 0, + .signal = U1RTS_OUT_IDX, + }, + + [SOC_UART_CTS_PIN_IDX] = { + .default_gpio = U1CTS_GPIO_NUM, + .iomux_func = U1CTS_MUX_FUNC, + .input = 1, + .signal = U1CTS_IN_IDX, + }, + }, .irq = ETS_UART1_INTR_SOURCE, .module = PERIPH_UART1_MODULE, }, diff --git a/components/soc/esp32s2/usb_phy_periph.c b/components/soc/esp32s2/usb_phy_periph.c new file mode 100644 index 0000000000..596db0417c --- /dev/null +++ b/components/soc/esp32s2/usb_phy_periph.c @@ -0,0 +1,23 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/usb_phy_periph.h" +#include "soc/gpio_sig_map.h" + +/* + Bunch of constants for USB peripheral: GPIO signals +*/ +const usb_phy_signal_conn_t usb_phy_periph_signal = { + .extphy_vp_in = USB_EXTPHY_VP_IDX, + .extphy_vm_in = USB_EXTPHY_VM_IDX, + .extphy_rcv_in = USB_EXTPHY_RCV_IDX, + .extphy_oen_out = USB_EXTPHY_OEN_IDX, + .extphy_vpo_out = USB_EXTPHY_VPO_IDX, + .extphy_vmo_out = USB_EXTPHY_VMO_IDX, + .extphy_suspend_in = USB_EXTPHY_SUSPND_IDX, + .extphy_speed_in = USB_EXTPHY_SPEED_IDX, + .module = PERIPH_USB_MODULE +}; diff --git a/components/soc/esp32s3/CMakeLists.txt b/components/soc/esp32s3/CMakeLists.txt index 99ed3ecc79..53914f113e 100644 --- a/components/soc/esp32s3/CMakeLists.txt +++ b/components/soc/esp32s3/CMakeLists.txt @@ -19,7 +19,8 @@ set(srcs "timer_periph.c" "touch_sensor_periph.c" "uart_periph.c" - "usb_periph.c") + "usb_periph.c" + "usb_phy_periph.c") add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}") diff --git a/components/soc/esp32s3/i2s_periph.c b/components/soc/esp32s3/i2s_periph.c index 52f714edf7..79a8308e21 100644 --- a/components/soc/esp32s3/i2s_periph.c +++ b/components/soc/esp32s3/i2s_periph.c @@ -1,4 +1,4 @@ -// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD +// 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. @@ -20,17 +20,41 @@ */ const i2s_signal_conn_t i2s_periph_signal[SOC_I2S_NUM] = { { - .o_bck_in_sig = I2S0O_BCK_IN_IDX, - .o_ws_in_sig = I2S0O_WS_IN_IDX, - .o_bck_out_sig = I2S0O_BCK_OUT_IDX, - .o_ws_out_sig = I2S0O_WS_OUT_IDX, - .o_data_out_sig = I2S0O_SD_OUT_IDX, - .i_bck_in_sig = I2S0I_BCK_OUT_IDX, - .i_ws_in_sig = I2S0I_WS_OUT_IDX, - .i_bck_out_sig = I2S0I_BCK_IN_IDX, - .i_ws_out_sig = I2S0I_WS_IN_IDX, - .i_data_in_sig = I2S0I_SD_IN_IDX, - .irq = ETS_I2S0_INTR_SOURCE, - .module = PERIPH_I2S0_MODULE, + .mck_out_sig = I2S0_MCLK_OUT_IDX, + + .m_tx_bck_sig = I2S0O_BCK_OUT_IDX, + .m_rx_bck_sig = I2S0I_BCK_OUT_IDX, + .m_tx_ws_sig = I2S0O_WS_OUT_IDX, + .m_rx_ws_sig = I2S0I_WS_OUT_IDX, + + .s_tx_bck_sig = I2S0O_BCK_IN_IDX, + .s_rx_bck_sig = I2S0I_BCK_IN_IDX, + .s_tx_ws_sig = I2S0O_WS_IN_IDX, + .s_rx_ws_sig = I2S0I_WS_IN_IDX, + + .data_out_sig = I2S0O_SD_OUT_IDX, + .data_in_sig = I2S0I_SD_IN_IDX, + + .irq = -1, + .module = PERIPH_I2S0_MODULE, + }, + { + .mck_out_sig = I2S1_MCLK_OUT_IDX, + + .m_tx_bck_sig = I2S1O_BCK_OUT_IDX, + .m_rx_bck_sig = I2S1I_BCK_OUT_IDX, + .m_tx_ws_sig = I2S1O_WS_OUT_IDX, + .m_rx_ws_sig = I2S1I_WS_OUT_IDX, + + .s_tx_bck_sig = I2S1O_BCK_IN_IDX, + .s_rx_bck_sig = I2S1I_BCK_IN_IDX, + .s_tx_ws_sig = I2S1O_WS_IN_IDX, + .s_rx_ws_sig = I2S1I_WS_IN_IDX, + + .data_out_sig = I2S1O_SD_OUT_IDX, + .data_in_sig = I2S1I_SD_IN_IDX, + + .irq = -1, + .module = PERIPH_I2S1_MODULE, } }; diff --git a/components/soc/esp32s3/include/soc/apb_ctrl_struct.h b/components/soc/esp32s3/include/soc/apb_ctrl_struct.h index cf4d08a6c8..b47dff1739 100644 --- a/components/soc/esp32s3/include/soc/apb_ctrl_struct.h +++ b/components/soc/esp32s3/include/soc/apb_ctrl_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct apb_ctrl_dev_s { union { struct { uint32_t pre_div : 10; diff --git a/components/soc/esp32s3/include/soc/apb_saradc_struct.h b/components/soc/esp32s3/include/soc/apb_saradc_struct.h index 9c4637e31a..d6684c5387 100644 --- a/components/soc/esp32s3/include/soc/apb_saradc_struct.h +++ b/components/soc/esp32s3/include/soc/apb_saradc_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct apb_saradc_dev_s { union { struct { uint32_t start_force : 1; diff --git a/components/soc/esp32s3/include/soc/assist_debug_struct.h b/components/soc/esp32s3/include/soc/assist_debug_struct.h index a9cedd804c..a6152af468 100644 --- a/components/soc/esp32s3/include/soc/assist_debug_struct.h +++ b/components/soc/esp32s3/include/soc/assist_debug_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct assist_debug_dev_s { union { struct { uint32_t core_0_area_dram0_0_rd : 1; diff --git a/components/soc/esp32s3/include/soc/efuse_reg.h b/components/soc/esp32s3/include/soc/efuse_reg.h index 4326389a26..65ec6a3eaf 100644 --- a/components/soc/esp32s3/include/soc/efuse_reg.h +++ b/components/soc/esp32s3/include/soc/efuse_reg.h @@ -230,12 +230,12 @@ AG can be enabled in HMAC module..*/ #define EFUSE_DIS_ICACHE_M (BIT(8)) #define EFUSE_DIS_ICACHE_V 0x1 #define EFUSE_DIS_ICACHE_S 8 -/* EFUSE_DIS_RTC_RAM_BOOT : RO ;bitpos:[7] ;default: 1'b0 ; */ -/*description: Set this bit to disable boot from RTC RAM..*/ -#define EFUSE_DIS_RTC_RAM_BOOT (BIT(7)) -#define EFUSE_DIS_RTC_RAM_BOOT_M (BIT(7)) -#define EFUSE_DIS_RTC_RAM_BOOT_V 0x1 -#define EFUSE_DIS_RTC_RAM_BOOT_S 7 +/* EFUSE_RPT4_RESERVED5 : RO ;bitpos:[7] ;default: 1'b0 ; */ +/*description: Reserved */ +#define EFUSE_RPT4_RESERVED5 (BIT(7)) +#define EFUSE_RPT4_RESERVED5_M (BIT(7)) +#define EFUSE_RPT4_RESERVED5_V 0x1 +#define EFUSE_RPT4_RESERVED5_S 7 /* EFUSE_RD_DIS : RO ;bitpos:[6:0] ;default: 7'h0 ; */ /*description: Set this bit to disable reading from BlOCK4-10..*/ #define EFUSE_RD_DIS 0x0000007F @@ -1283,12 +1283,12 @@ apping gpio10 when both reg_dis_usb_jtag and reg_dis_pad_jtag are equal to 0..*/ #define EFUSE_DIS_ICACHE_ERR_M (BIT(8)) #define EFUSE_DIS_ICACHE_ERR_V 0x1 #define EFUSE_DIS_ICACHE_ERR_S 8 -/* EFUSE_DIS_RTC_RAM_BOOT_ERR : RO ;bitpos:[7] ;default: 1'b0 ; */ -/*description: If any bits in this filed are 1, then it indicates a programming error..*/ -#define EFUSE_DIS_RTC_RAM_BOOT_ERR (BIT(7)) -#define EFUSE_DIS_RTC_RAM_BOOT_ERR_M (BIT(7)) -#define EFUSE_DIS_RTC_RAM_BOOT_ERR_V 0x1 -#define EFUSE_DIS_RTC_RAM_BOOT_ERR_S 7 +/* EFUSE_RPT4_RESERVED5_ERR : RO ;bitpos:[7] ;default: 1'b0 ; */ +/*description: Reserved*/ +#define EFUSE_RPT4_RESERVED5_ERR (BIT(7)) +#define EFUSE_RPT4_RESERVED5_ERR_M (BIT(7)) +#define EFUSE_RPT4_RESERVED5_ERR_V 0x1 +#define EFUSE_RPT4_RESERVED5_ERR_S 7 /* EFUSE_RD_DIS_ERR : RO ;bitpos:[6:0] ;default: 7'h0 ; */ /*description: If any bits in this filed are 1, then it indicates a programming error..*/ #define EFUSE_RD_DIS_ERR 0x0000007F @@ -1572,7 +1572,7 @@ apping gpio10 when both reg_dis_usb_jtag and reg_dis_pad_jtag are equal to 0..*/ #define EFUSE_DIS_DOWNLOAD_MODE_ERR_V 0x1 #define EFUSE_DIS_DOWNLOAD_MODE_ERR_S 0 -#define EFUSE_RD_REPEAT_ERR4_REG (DR_REG_EFUSE_BASE + 0x190) +#define EFUSE_RD_REPEAT_ERR4_REG (DR_REG_EFUSE_BASE + 0x18C) /* EFUSE_RPT4_RESERVED2_ERR : RO ;bitpos:[23:0] ;default: 24'h0 ; */ /*description: If any bits in this filed are 1, then it indicates a programming error..*/ #define EFUSE_RPT4_RESERVED2_ERR 0x00FFFFFF diff --git a/components/soc/esp32s3/include/soc/efuse_struct.h b/components/soc/esp32s3/include/soc/efuse_struct.h index 908f07ea64..bd45983ba2 100644 --- a/components/soc/esp32s3/include/soc/efuse_struct.h +++ b/components/soc/esp32s3/include/soc/efuse_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct efuse_dev_s { uint32_t pgm_data0; uint32_t pgm_data1; uint32_t pgm_data2; @@ -36,7 +36,7 @@ typedef volatile struct { union { struct { uint32_t reg_rd_dis : 7; /*Set this bit to disable reading from BlOCK4-10.*/ - uint32_t reg_dis_rtc_ram_boot : 1; /*Set this bit to disable boot from RTC RAM.*/ + uint32_t reg_rpt4_reserved5 : 1; /*Reserved*/ uint32_t reg_dis_icache : 1; /*Set this bit to disable Icache.*/ uint32_t reg_dis_dcache : 1; /*Set this bit to disable Dcache.*/ uint32_t reg_dis_download_icache : 1; /*Set this bit to disable Icache in download mode (boot_mode[3:0] is 0, 1, 2, 3, 6, 7).*/ @@ -218,7 +218,7 @@ typedef volatile struct { union { struct { uint32_t reg_rd_dis_err : 7; /*If any bits in this filed are 1, then it indicates a programming error.*/ - uint32_t reg_dis_rtc_ram_boot_err : 1; /*If any bits in this filed are 1, then it indicates a programming error.*/ + uint32_t reg_rpt4_reserved5_err : 1; /*If any bits in this filed are 1, then it indicates a programming error.*/ uint32_t reg_dis_icache_err : 1; /*If any bits in this filed are 1, then it indicates a programming error.*/ uint32_t reg_dis_dcache_err : 1; /*If any bits in this filed are 1, then it indicates a programming error.*/ uint32_t reg_dis_download_icache_err : 1; /*If any bits in this filed are 1, then it indicates a programming error.*/ @@ -300,7 +300,6 @@ typedef volatile struct { }; uint32_t val; } rd_repeat_err3; - uint32_t reserved_18c; union { struct { uint32_t reg_rpt4_reserved2_err : 24; /*If any bits in this filed are 1, then it indicates a programming error.*/ @@ -308,6 +307,7 @@ typedef volatile struct { }; uint32_t val; } rd_repeat_err4; + uint32_t reserved_190; uint32_t reserved_194; uint32_t reserved_198; uint32_t reserved_19c; diff --git a/components/soc/esp32s3/include/soc/extmem_struct.h b/components/soc/esp32s3/include/soc/extmem_struct.h index e27283b702..58ca646294 100644 --- a/components/soc/esp32s3/include/soc/extmem_struct.h +++ b/components/soc/esp32s3/include/soc/extmem_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct extmem_dev_s { union { struct { uint32_t dcache_enable : 1; /*The bit is used to activate the data cache. 0: disable, 1: enable*/ diff --git a/components/soc/esp32s3/include/soc/gdma_struct.h b/components/soc/esp32s3/include/soc/gdma_struct.h index ebb2b79e1d..730333e67d 100644 --- a/components/soc/esp32s3/include/soc/gdma_struct.h +++ b/components/soc/esp32s3/include/soc/gdma_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct gdma_dev_s { struct { struct { union { diff --git a/components/soc/esp32s3/include/soc/gpio_sd_struct.h b/components/soc/esp32s3/include/soc/gpio_sd_struct.h index bb71322294..7bb05aafb5 100644 --- a/components/soc/esp32s3/include/soc/gpio_sd_struct.h +++ b/components/soc/esp32s3/include/soc/gpio_sd_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct gpio_sd_dev_s { union { struct { uint32_t duty : 8; diff --git a/components/soc/esp32s3/include/soc/gpio_struct.h b/components/soc/esp32s3/include/soc/gpio_struct.h index cd2711531c..be1c3223dd 100644 --- a/components/soc/esp32s3/include/soc/gpio_struct.h +++ b/components/soc/esp32s3/include/soc/gpio_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct gpio_dev_s { uint32_t bt_select; uint32_t out; uint32_t out_w1ts; diff --git a/components/soc/esp32s3/include/soc/hinf_struct.h b/components/soc/esp32s3/include/soc/hinf_struct.h index 7accb59330..965f8bd43c 100644 --- a/components/soc/esp32s3/include/soc/hinf_struct.h +++ b/components/soc/esp32s3/include/soc/hinf_struct.h @@ -20,7 +20,7 @@ extern "C" { #include -typedef volatile struct { +typedef volatile struct hinf_dev_s { union { struct { uint32_t user_id_fn1: 16; diff --git a/components/soc/esp32s3/include/soc/host_struct.h b/components/soc/esp32s3/include/soc/host_struct.h index b6dad107a5..1a6b89e281 100644 --- a/components/soc/esp32s3/include/soc/host_struct.h +++ b/components/soc/esp32s3/include/soc/host_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct host_dev_s { uint32_t reserved_0; uint32_t reserved_4; uint32_t reserved_8; diff --git a/components/soc/esp32s3/include/soc/hwcrypto_reg.h b/components/soc/esp32s3/include/soc/hwcrypto_reg.h index 9e16b742e7..a4b93fb81b 100644 --- a/components/soc/esp32s3/include/soc/hwcrypto_reg.h +++ b/components/soc/esp32s3/include/soc/hwcrypto_reg.h @@ -1,16 +1,9 @@ -// 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: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + #pragma once #include "soc.h" @@ -106,6 +99,7 @@ #define HMAC_SET_MESSAGE_END_REG ((DR_REG_HMAC_BASE) + 0x58) #define HMAC_SET_RESULT_FINISH_REG ((DR_REG_HMAC_BASE) + 0x5c) #define HMAC_SET_INVALIDATE_JTAG_REG ((DR_REG_HMAC_BASE) + 0x60) +#define HMAC_INVALIDATE_JTAG BIT(0) #define HMAC_SET_INVALIDATE_DS_REG ((DR_REG_HMAC_BASE) + 0x64) #define HMAC_QUERY_ERROR_REG ((DR_REG_HMAC_BASE) + 0x68) #define HMAC_QUERY_BUSY_REG ((DR_REG_HMAC_BASE) + 0x6c) @@ -114,6 +108,9 @@ #define HMAC_RDATA_BASE ((DR_REG_HMAC_BASE) + 0xC0) #define HMAC_SET_MESSAGE_PAD_REG ((DR_REG_HMAC_BASE) + 0xF0) #define HMAC_ONE_BLOCK_REG ((DR_REG_HMAC_BASE) + 0xF4) +#define HMAC_SOFT_JTAG_CTRL_REG ((DR_REG_HMAC_BASE) + 0xF8) +#define HMAC_SOFT_JTAG_CTRL BIT((0) +#define HMAC_WR_JTAG_REG ((DR_REG_HMAC_BASE) + 0xFC) /* AES-XTS registers */ #define AES_XTS_PLAIN_BASE ((DR_REG_EXT_MEM_ENC) + 0x00) @@ -129,6 +126,10 @@ /* Digital Signature registers*/ #define DS_C_BASE ((DR_REG_DIGITAL_SIGNATURE_BASE) + 0x000 ) +#define DS_C_Y_BASE ((DR_REG_DIGITAL_SIGNATURE_BASE) + 0x000 ) +#define DS_C_M_BASE ((DR_REG_DIGITAL_SIGNATURE_BASE) + 0x200 ) +#define DS_C_RB_BASE ((DR_REG_DIGITAL_SIGNATURE_BASE) + 0x400 ) +#define DS_C_BOX_BASE ((DR_REG_DIGITAL_SIGNATURE_BASE) + 0x600 ) #define DS_IV_BASE ((DR_REG_DIGITAL_SIGNATURE_BASE) + 0x630 ) #define DS_X_BASE ((DR_REG_DIGITAL_SIGNATURE_BASE) + 0x800 ) #define DS_Z_BASE ((DR_REG_DIGITAL_SIGNATURE_BASE) + 0xA00 ) diff --git a/components/soc/esp32s3/include/soc/i2s_struct.h b/components/soc/esp32s3/include/soc/i2s_struct.h index eff11a9ca6..553580d32c 100644 --- a/components/soc/esp32s3/include/soc/i2s_struct.h +++ b/components/soc/esp32s3/include/soc/i2s_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct i2s_dev_s { uint32_t reserved_0; uint32_t reserved_4; uint32_t reserved_8; @@ -318,8 +318,8 @@ typedef volatile struct { uint32_t reserved12 : 20; /* Reserved*/ }; uint32_t val; - } rxeof_num; - uint32_t conf_sigle_data; + } rx_eof_num; + uint32_t conf_single_data; /*the right channel or left channel put out constant value stored in this register according to tx_chan_mod and reg_tx_msb_right*/ union { struct { uint32_t tx_idle : 1; /*1: i2s_tx is idle state. 0: i2s_tx is working.*/ diff --git a/components/soc/esp32s3/include/soc/interrupt_core0_struct.h b/components/soc/esp32s3/include/soc/interrupt_core0_struct.h index 54ff95b47b..aa27462fb0 100644 --- a/components/soc/esp32s3/include/soc/interrupt_core0_struct.h +++ b/components/soc/esp32s3/include/soc/interrupt_core0_struct.h @@ -18,7 +18,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct interrupt_core0_dev_s { union { struct { uint32_t core0_mac_intr_map: 5; diff --git a/components/soc/esp32s3/include/soc/interrupt_core1_struct.h b/components/soc/esp32s3/include/soc/interrupt_core1_struct.h index ba60403aa8..d4dee29ae5 100644 --- a/components/soc/esp32s3/include/soc/interrupt_core1_struct.h +++ b/components/soc/esp32s3/include/soc/interrupt_core1_struct.h @@ -18,7 +18,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct interrupt_core1_dev_s { uint32_t reserved_0; uint32_t reserved_4; uint32_t reserved_8; diff --git a/components/soc/esp32s3/include/soc/interrupt_struct.h b/components/soc/esp32s3/include/soc/interrupt_struct.h index 48a595047f..03bf5df953 100644 --- a/components/soc/esp32s3/include/soc/interrupt_struct.h +++ b/components/soc/esp32s3/include/soc/interrupt_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct interrupt_dev_s { } interrupt_dev_t; extern interrupt_dev_t INTERRUPT; #ifdef __cplusplus diff --git a/components/soc/esp32s3/include/soc/io_mux_reg.h b/components/soc/esp32s3/include/soc/io_mux_reg.h index 84fa443647..4b9057400c 100644 --- a/components/soc/esp32s3/include/soc/io_mux_reg.h +++ b/components/soc/esp32s3/include/soc/io_mux_reg.h @@ -145,11 +145,6 @@ #define GPIO_PAD_PULLUP(num) do{PIN_PULLUP_DIS(IOMUX_REG_GPIO##num);PIN_PULLDWN_EN(IOMUX_REG_GPIO##num);}while(0) #define GPIO_PAD_SET_DRV(num, drv) PIN_SET_DRV(IOMUX_REG_GPIO##num, drv) -#define U1RXD_GPIO_NUM 18 -#define U1TXD_GPIO_NUM 17 -#define U0RXD_GPIO_NUM 44 -#define U0TXD_GPIO_NUM 43 - #define SPI_CS1_GPIO_NUM 26 #define SPI_HD_GPIO_NUM 27 #define SPI_WP_GPIO_NUM 28 diff --git a/components/soc/esp32s3/include/soc/lcd_cam_struct.h b/components/soc/esp32s3/include/soc/lcd_cam_struct.h index 83d9e11fc3..0a78e323cc 100644 --- a/components/soc/esp32s3/include/soc/lcd_cam_struct.h +++ b/components/soc/esp32s3/include/soc/lcd_cam_struct.h @@ -762,7 +762,7 @@ typedef union { } lcd_cam_lc_reg_date_reg_t; -typedef struct { +typedef struct lcd_cam_dev_t { volatile lcd_cam_lcd_clock_reg_t lcd_clock; volatile lcd_cam_cam_ctrl_reg_t cam_ctrl; volatile lcd_cam_cam_ctrl1_reg_t cam_ctrl1; diff --git a/components/soc/esp32s3/include/soc/ledc_struct.h b/components/soc/esp32s3/include/soc/ledc_struct.h index 5713035056..85cea78e58 100644 --- a/components/soc/esp32s3/include/soc/ledc_struct.h +++ b/components/soc/esp32s3/include/soc/ledc_struct.h @@ -20,7 +20,7 @@ extern "C" { #include -typedef volatile struct { +typedef volatile struct ledc_dev_s { struct { struct { union { diff --git a/components/soc/esp32s3/include/soc/mcpwm_reg.h b/components/soc/esp32s3/include/soc/mcpwm_reg.h index 5ca6eadd7f..6a370aa691 100644 --- a/components/soc/esp32s3/include/soc/mcpwm_reg.h +++ b/components/soc/esp32s3/include/soc/mcpwm_reg.h @@ -1,2910 +1,3829 @@ -// 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. -#ifndef _SOC_MCPWM_REG_H_ -#define _SOC_MCPWM_REG_H_ +/** + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once - -#include "soc.h" +#include +#include "soc/soc.h" #ifdef __cplusplus extern "C" { #endif -#define REG_MCPWM_BASE(i) (DR_REG_PWM0_BASE + i * (0xE000)) +#define DR_REG_MCPWM_BASE(i) (DR_REG_PWM0_BASE + i * (0xE000)) -#define MCPWM_CLK_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x0) -/* MCPWM_CLK_PRESCALE : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ -/*description: .*/ -#define MCPWM_CLK_PRESCALE 0x000000FF -#define MCPWM_CLK_PRESCALE_M ((MCPWM_CLK_PRESCALE_V)<<(MCPWM_CLK_PRESCALE_S)) -#define MCPWM_CLK_PRESCALE_V 0xFF +/** MCPWM_CLK_CFG_REG register + * PWM clock prescaler register. + */ +#define MCPWM_CLK_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x0) +/** MCPWM_CLK_PRESCALE : R/W; bitpos: [7:0]; default: 0; + * Period of PWM_clk = 6.25ns * (PWM_CLK_PRESCALE + 1) + */ +#define MCPWM_CLK_PRESCALE 0x000000FFU +#define MCPWM_CLK_PRESCALE_M (MCPWM_CLK_PRESCALE_V << MCPWM_CLK_PRESCALE_S) +#define MCPWM_CLK_PRESCALE_V 0x000000FFU #define MCPWM_CLK_PRESCALE_S 0 -#define MCPWM_TIMER0_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0x4) -/* MCPWM_TIMER0_PERIOD_UPMETHOD : R/W ;bitpos:[25:24] ;default: 2'd0 ; */ -/*description: 0: immediate, 1: eqz, 2: sync, 3: eqz | sync.*/ -#define MCPWM_TIMER0_PERIOD_UPMETHOD 0x00000003 -#define MCPWM_TIMER0_PERIOD_UPMETHOD_M ((MCPWM_TIMER0_PERIOD_UPMETHOD_V)<<(MCPWM_TIMER0_PERIOD_UPMETHOD_S)) -#define MCPWM_TIMER0_PERIOD_UPMETHOD_V 0x3 -#define MCPWM_TIMER0_PERIOD_UPMETHOD_S 24 -/* MCPWM_TIMER0_PERIOD : R/W ;bitpos:[23:8] ;default: 16'h00ff ; */ -/*description: .*/ -#define MCPWM_TIMER0_PERIOD 0x0000FFFF -#define MCPWM_TIMER0_PERIOD_M ((MCPWM_TIMER0_PERIOD_V)<<(MCPWM_TIMER0_PERIOD_S)) -#define MCPWM_TIMER0_PERIOD_V 0xFFFF -#define MCPWM_TIMER0_PERIOD_S 8 -/* MCPWM_TIMER0_PRESCALE : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER0_PRESCALE 0x000000FF -#define MCPWM_TIMER0_PRESCALE_M ((MCPWM_TIMER0_PRESCALE_V)<<(MCPWM_TIMER0_PRESCALE_S)) -#define MCPWM_TIMER0_PRESCALE_V 0xFF +/** MCPWM_TIMER0_CFG0_REG register + * PWM timer0 period and update method configuration register. + */ +#define MCPWM_TIMER0_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0x4) +/** MCPWM_TIMER0_PRESCALE : R/W; bitpos: [7:0]; default: 0; + * Configure the divisor of PT0_clk, takes effect when PWM timer0 stops and starts + * agsin. period of PT0_clk = Period of PWM_clk * (PWM_TIMER0_PRESCALE + 1) + */ +#define MCPWM_TIMER0_PRESCALE 0x000000FFU +#define MCPWM_TIMER0_PRESCALE_M (MCPWM_TIMER0_PRESCALE_V << MCPWM_TIMER0_PRESCALE_S) +#define MCPWM_TIMER0_PRESCALE_V 0x000000FFU #define MCPWM_TIMER0_PRESCALE_S 0 +/** MCPWM_TIMER0_PERIOD : R/W; bitpos: [23:8]; default: 255; + * period shadow register of PWM timer0 + */ +#define MCPWM_TIMER0_PERIOD 0x0000FFFFU +#define MCPWM_TIMER0_PERIOD_M (MCPWM_TIMER0_PERIOD_V << MCPWM_TIMER0_PERIOD_S) +#define MCPWM_TIMER0_PERIOD_V 0x0000FFFFU +#define MCPWM_TIMER0_PERIOD_S 8 +/** MCPWM_TIMER0_PERIOD_UPMETHOD : R/W; bitpos: [25:24]; default: 0; + * Update method for active register of PWM timer0 period, 0: immediate, 1: TEZ, 2: + * sync, 3: TEZ or sync. TEZ here and below means timer equal zero event + */ +#define MCPWM_TIMER0_PERIOD_UPMETHOD 0x00000003U +#define MCPWM_TIMER0_PERIOD_UPMETHOD_M (MCPWM_TIMER0_PERIOD_UPMETHOD_V << MCPWM_TIMER0_PERIOD_UPMETHOD_S) +#define MCPWM_TIMER0_PERIOD_UPMETHOD_V 0x00000003U +#define MCPWM_TIMER0_PERIOD_UPMETHOD_S 24 -#define MCPWM_TIMER0_CFG1_REG(i) (REG_MCPWM_BASE(i) + 0x8) -/* MCPWM_TIMER0_MOD : R/W ;bitpos:[4:3] ;default: 2'h0 ; */ -/*description: 0: freeze, 1: inc, 2: dec, 3: up-down.*/ -#define MCPWM_TIMER0_MOD 0x00000003 -#define MCPWM_TIMER0_MOD_M ((MCPWM_TIMER0_MOD_V)<<(MCPWM_TIMER0_MOD_S)) -#define MCPWM_TIMER0_MOD_V 0x3 -#define MCPWM_TIMER0_MOD_S 3 -/* MCPWM_TIMER0_START : R/W ;bitpos:[2:0] ;default: 3'h0 ; */ -/*description: 0: stop @ eqz, 1: stop @ eqp, 2: free run, 3: start and stop @ next eqz, 4: star -t and stop @ next eqp,.*/ -#define MCPWM_TIMER0_START 0x00000007 -#define MCPWM_TIMER0_START_M ((MCPWM_TIMER0_START_V)<<(MCPWM_TIMER0_START_S)) -#define MCPWM_TIMER0_START_V 0x7 +/** MCPWM_TIMER0_CFG1_REG register + * PWM timer0 working mode and start/stop control configuration register. + */ +#define MCPWM_TIMER0_CFG1_REG(i) (DR_REG_MCPWM_BASE(i) + 0x8) +/** MCPWM_TIMER0_START : R/W/SC; bitpos: [2:0]; default: 0; + * PWM timer0 start and stop control. 0: if PWM timer0 starts, then stops at TEZ, 1: + * if timer0 starts, then stops at TEP, 2: PWM timer0 starts and runs on, 3: timer0 + * starts and stops at the next TEZ, 4: timer0 starts and stops at the next TEP. TEP + * here and below means the event that happens when the timer equals to period + */ +#define MCPWM_TIMER0_START 0x00000007U +#define MCPWM_TIMER0_START_M (MCPWM_TIMER0_START_V << MCPWM_TIMER0_START_S) +#define MCPWM_TIMER0_START_V 0x00000007U #define MCPWM_TIMER0_START_S 0 +/** MCPWM_TIMER0_MOD : R/W; bitpos: [4:3]; default: 0; + * PWM timer0 working mode, 0: freeze, 1: increase mode, 2: decrease mode, 3: up-down + * mode + */ +#define MCPWM_TIMER0_MOD 0x00000003U +#define MCPWM_TIMER0_MOD_M (MCPWM_TIMER0_MOD_V << MCPWM_TIMER0_MOD_S) +#define MCPWM_TIMER0_MOD_V 0x00000003U +#define MCPWM_TIMER0_MOD_S 3 -#define MCPWM_TIMER0_SYNC_REG(i) (REG_MCPWM_BASE(i) + 0xC) -/* MCPWM_TIMER0_PHASE : R/W ;bitpos:[20:4] ;default: 17'd0 ; */ -/*description: .*/ -#define MCPWM_TIMER0_PHASE 0x0001FFFF -#define MCPWM_TIMER0_PHASE_M ((MCPWM_TIMER0_PHASE_V)<<(MCPWM_TIMER0_PHASE_S)) -#define MCPWM_TIMER0_PHASE_V 0x1FFFF -#define MCPWM_TIMER0_PHASE_S 4 -/* MCPWM_TIMER0_SYNCO_SEL : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_TIMER0_SYNCO_SEL 0x00000003 -#define MCPWM_TIMER0_SYNCO_SEL_M ((MCPWM_TIMER0_SYNCO_SEL_V)<<(MCPWM_TIMER0_SYNCO_SEL_S)) -#define MCPWM_TIMER0_SYNCO_SEL_V 0x3 -#define MCPWM_TIMER0_SYNCO_SEL_S 2 -/* MCPWM_TIMER0_SYNC_SW : R/W ;bitpos:[1] ;default: 1'h0 ; */ -/*description: write the negate value will trigger a sw sync.*/ -#define MCPWM_TIMER0_SYNC_SW (BIT(1)) -#define MCPWM_TIMER0_SYNC_SW_M (BIT(1)) -#define MCPWM_TIMER0_SYNC_SW_V 0x1 -#define MCPWM_TIMER0_SYNC_SW_S 1 -/* MCPWM_TIMER0_SYNCI_EN : R/W ;bitpos:[0] ;default: 1'h0 ; */ -/*description: .*/ +/** MCPWM_TIMER0_SYNC_REG register + * PWM timer0 sync function configuration register. + */ +#define MCPWM_TIMER0_SYNC_REG(i) (DR_REG_MCPWM_BASE(i) + 0xc) +/** MCPWM_TIMER0_SYNCI_EN : R/W; bitpos: [0]; default: 0; + * When set, timer reloading with phase on sync input event is enabled. + */ #define MCPWM_TIMER0_SYNCI_EN (BIT(0)) -#define MCPWM_TIMER0_SYNCI_EN_M (BIT(0)) -#define MCPWM_TIMER0_SYNCI_EN_V 0x1 +#define MCPWM_TIMER0_SYNCI_EN_M (MCPWM_TIMER0_SYNCI_EN_V << MCPWM_TIMER0_SYNCI_EN_S) +#define MCPWM_TIMER0_SYNCI_EN_V 0x00000001U #define MCPWM_TIMER0_SYNCI_EN_S 0 +/** MCPWM_TIMER0_SYNC_SW : R/W; bitpos: [1]; default: 0; + * Toggling this bit will trigger a software sync. + */ +#define MCPWM_TIMER0_SYNC_SW (BIT(1)) +#define MCPWM_TIMER0_SYNC_SW_M (MCPWM_TIMER0_SYNC_SW_V << MCPWM_TIMER0_SYNC_SW_S) +#define MCPWM_TIMER0_SYNC_SW_V 0x00000001U +#define MCPWM_TIMER0_SYNC_SW_S 1 +/** MCPWM_TIMER0_SYNCO_SEL : R/W; bitpos: [3:2]; default: 0; + * PWM timer0 sync_out selection, 0: sync_in, 1: TEZ, 2: TEP, and sync out will always + * generate when toggling the reg_timer0_sync_sw bit + */ +#define MCPWM_TIMER0_SYNCO_SEL 0x00000003U +#define MCPWM_TIMER0_SYNCO_SEL_M (MCPWM_TIMER0_SYNCO_SEL_V << MCPWM_TIMER0_SYNCO_SEL_S) +#define MCPWM_TIMER0_SYNCO_SEL_V 0x00000003U +#define MCPWM_TIMER0_SYNCO_SEL_S 2 +/** MCPWM_TIMER0_PHASE : R/W; bitpos: [19:4]; default: 0; + * phase for timer reload on sync event + */ +#define MCPWM_TIMER0_PHASE 0x0000FFFFU +#define MCPWM_TIMER0_PHASE_M (MCPWM_TIMER0_PHASE_V << MCPWM_TIMER0_PHASE_S) +#define MCPWM_TIMER0_PHASE_V 0x0000FFFFU +#define MCPWM_TIMER0_PHASE_S 4 +/** MCPWM_TIMER0_PHASE_DIRECTION : R/W; bitpos: [20]; default: 0; + * Configure the PWM timer0's direction at the time sync event occurs when timer0 mode + * is up-down mode: 0-increase,1-decrease + */ +#define MCPWM_TIMER0_PHASE_DIRECTION (BIT(20)) +#define MCPWM_TIMER0_PHASE_DIRECTION_M (MCPWM_TIMER0_PHASE_DIRECTION_V << MCPWM_TIMER0_PHASE_DIRECTION_S) +#define MCPWM_TIMER0_PHASE_DIRECTION_V 0x00000001U +#define MCPWM_TIMER0_PHASE_DIRECTION_S 20 -#define MCPWM_TIMER0_STATUS_REG(i) (REG_MCPWM_BASE(i) + 0x10) -/* MCPWM_TIMER0_DIRECTION : RO ;bitpos:[16] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TIMER0_DIRECTION (BIT(16)) -#define MCPWM_TIMER0_DIRECTION_M (BIT(16)) -#define MCPWM_TIMER0_DIRECTION_V 0x1 -#define MCPWM_TIMER0_DIRECTION_S 16 -/* MCPWM_TIMER0_VALUE : RO ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: .*/ -#define MCPWM_TIMER0_VALUE 0x0000FFFF -#define MCPWM_TIMER0_VALUE_M ((MCPWM_TIMER0_VALUE_V)<<(MCPWM_TIMER0_VALUE_S)) -#define MCPWM_TIMER0_VALUE_V 0xFFFF +/** MCPWM_TIMER0_STATUS_REG register + * PWM timer0 status register. + */ +#define MCPWM_TIMER0_STATUS_REG(i) (DR_REG_MCPWM_BASE(i) + 0x10) +/** MCPWM_TIMER0_VALUE : RO; bitpos: [15:0]; default: 0; + * current PWM timer0 counter value + */ +#define MCPWM_TIMER0_VALUE 0x0000FFFFU +#define MCPWM_TIMER0_VALUE_M (MCPWM_TIMER0_VALUE_V << MCPWM_TIMER0_VALUE_S) +#define MCPWM_TIMER0_VALUE_V 0x0000FFFFU #define MCPWM_TIMER0_VALUE_S 0 +/** MCPWM_TIMER0_DIRECTION : RO; bitpos: [16]; default: 0; + * current PWM timer0 counter direction, 0: increment 1: decrement + */ +#define MCPWM_TIMER0_DIRECTION (BIT(16)) +#define MCPWM_TIMER0_DIRECTION_M (MCPWM_TIMER0_DIRECTION_V << MCPWM_TIMER0_DIRECTION_S) +#define MCPWM_TIMER0_DIRECTION_V 0x00000001U +#define MCPWM_TIMER0_DIRECTION_S 16 -#define MCPWM_TIMER1_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0x14) -/* MCPWM_TIMER1_PERIOD_UPMETHOD : R/W ;bitpos:[25:24] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_PERIOD_UPMETHOD 0x00000003 -#define MCPWM_TIMER1_PERIOD_UPMETHOD_M ((MCPWM_TIMER1_PERIOD_UPMETHOD_V)<<(MCPWM_TIMER1_PERIOD_UPMETHOD_S)) -#define MCPWM_TIMER1_PERIOD_UPMETHOD_V 0x3 -#define MCPWM_TIMER1_PERIOD_UPMETHOD_S 24 -/* MCPWM_TIMER1_PERIOD : R/W ;bitpos:[23:8] ;default: 16'h00ff ; */ -/*description: .*/ -#define MCPWM_TIMER1_PERIOD 0x0000FFFF -#define MCPWM_TIMER1_PERIOD_M ((MCPWM_TIMER1_PERIOD_V)<<(MCPWM_TIMER1_PERIOD_S)) -#define MCPWM_TIMER1_PERIOD_V 0xFFFF -#define MCPWM_TIMER1_PERIOD_S 8 -/* MCPWM_TIMER1_PRESCALE : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_PRESCALE 0x000000FF -#define MCPWM_TIMER1_PRESCALE_M ((MCPWM_TIMER1_PRESCALE_V)<<(MCPWM_TIMER1_PRESCALE_S)) -#define MCPWM_TIMER1_PRESCALE_V 0xFF +/** MCPWM_TIMER1_CFG0_REG register + * PWM timer1 period and update method configuration register. + */ +#define MCPWM_TIMER1_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0x14) +/** MCPWM_TIMER1_PRESCALE : R/W; bitpos: [7:0]; default: 0; + * Configure the divisor of PT1_clk, takes effect when PWM timer1 stops and starts + * agsin. period of PT1_clk = Period of PWM_clk * (PWM_TIMER1_PRESCALE + 1) + */ +#define MCPWM_TIMER1_PRESCALE 0x000000FFU +#define MCPWM_TIMER1_PRESCALE_M (MCPWM_TIMER1_PRESCALE_V << MCPWM_TIMER1_PRESCALE_S) +#define MCPWM_TIMER1_PRESCALE_V 0x000000FFU #define MCPWM_TIMER1_PRESCALE_S 0 +/** MCPWM_TIMER1_PERIOD : R/W; bitpos: [23:8]; default: 255; + * period shadow register of PWM timer1 + */ +#define MCPWM_TIMER1_PERIOD 0x0000FFFFU +#define MCPWM_TIMER1_PERIOD_M (MCPWM_TIMER1_PERIOD_V << MCPWM_TIMER1_PERIOD_S) +#define MCPWM_TIMER1_PERIOD_V 0x0000FFFFU +#define MCPWM_TIMER1_PERIOD_S 8 +/** MCPWM_TIMER1_PERIOD_UPMETHOD : R/W; bitpos: [25:24]; default: 0; + * Update method for active register of PWM timer1 period, 0: immediate, 1: TEZ, 2: + * sync, 3: TEZ | sync. TEZ here and below means timer equal zero event + */ +#define MCPWM_TIMER1_PERIOD_UPMETHOD 0x00000003U +#define MCPWM_TIMER1_PERIOD_UPMETHOD_M (MCPWM_TIMER1_PERIOD_UPMETHOD_V << MCPWM_TIMER1_PERIOD_UPMETHOD_S) +#define MCPWM_TIMER1_PERIOD_UPMETHOD_V 0x00000003U +#define MCPWM_TIMER1_PERIOD_UPMETHOD_S 24 -#define MCPWM_TIMER1_CFG1_REG(i) (REG_MCPWM_BASE(i) + 0x18) -/* MCPWM_TIMER1_MOD : R/W ;bitpos:[4:3] ;default: 2'h0 ; */ -/*description: 0: freeze, 1: inc, 2: dec, 3: up-down.*/ -#define MCPWM_TIMER1_MOD 0x00000003 -#define MCPWM_TIMER1_MOD_M ((MCPWM_TIMER1_MOD_V)<<(MCPWM_TIMER1_MOD_S)) -#define MCPWM_TIMER1_MOD_V 0x3 -#define MCPWM_TIMER1_MOD_S 3 -/* MCPWM_TIMER1_START : R/W ;bitpos:[2:0] ;default: 3'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_START 0x00000007 -#define MCPWM_TIMER1_START_M ((MCPWM_TIMER1_START_V)<<(MCPWM_TIMER1_START_S)) -#define MCPWM_TIMER1_START_V 0x7 +/** MCPWM_TIMER1_CFG1_REG register + * PWM timer1 working mode and start/stop control configuration register. + */ +#define MCPWM_TIMER1_CFG1_REG(i) (DR_REG_MCPWM_BASE(i) + 0x18) +/** MCPWM_TIMER1_START : R/W/SC; bitpos: [2:0]; default: 0; + * PWM timer1 start and stop control. 0: if PWM timer1 starts, then stops at TEZ, 1: + * if timer1 starts, then stops at TEP, 2: PWM timer1 starts and runs on, 3: timer1 + * starts and stops at the next TEZ, 4: timer1 starts and stops at the next TEP. TEP + * here and below means the event that happens when the timer equals to period + */ +#define MCPWM_TIMER1_START 0x00000007U +#define MCPWM_TIMER1_START_M (MCPWM_TIMER1_START_V << MCPWM_TIMER1_START_S) +#define MCPWM_TIMER1_START_V 0x00000007U #define MCPWM_TIMER1_START_S 0 +/** MCPWM_TIMER1_MOD : R/W; bitpos: [4:3]; default: 0; + * PWM timer1 working mode, 0: freeze, 1: increase mode, 2: decrease mode, 3: up-down + * mode + */ +#define MCPWM_TIMER1_MOD 0x00000003U +#define MCPWM_TIMER1_MOD_M (MCPWM_TIMER1_MOD_V << MCPWM_TIMER1_MOD_S) +#define MCPWM_TIMER1_MOD_V 0x00000003U +#define MCPWM_TIMER1_MOD_S 3 -#define MCPWM_TIMER1_SYNC_REG(i) (REG_MCPWM_BASE(i) + 0x1C) -/* MCPWM_TIMER1_PHASE : R/W ;bitpos:[20:4] ;default: 17'd0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_PHASE 0x0001FFFF -#define MCPWM_TIMER1_PHASE_M ((MCPWM_TIMER1_PHASE_V)<<(MCPWM_TIMER1_PHASE_S)) -#define MCPWM_TIMER1_PHASE_V 0x1FFFF -#define MCPWM_TIMER1_PHASE_S 4 -/* MCPWM_TIMER1_SYNCO_SEL : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: 0: synci, 1: tez, 2: tep, else 0.*/ -#define MCPWM_TIMER1_SYNCO_SEL 0x00000003 -#define MCPWM_TIMER1_SYNCO_SEL_M ((MCPWM_TIMER1_SYNCO_SEL_V)<<(MCPWM_TIMER1_SYNCO_SEL_S)) -#define MCPWM_TIMER1_SYNCO_SEL_V 0x3 -#define MCPWM_TIMER1_SYNCO_SEL_S 2 -/* MCPWM_TIMER1_SYNC_SW : R/W ;bitpos:[1] ;default: 1'h0 ; */ -/*description: write the negate value will trigger a sw sync.*/ -#define MCPWM_TIMER1_SYNC_SW (BIT(1)) -#define MCPWM_TIMER1_SYNC_SW_M (BIT(1)) -#define MCPWM_TIMER1_SYNC_SW_V 0x1 -#define MCPWM_TIMER1_SYNC_SW_S 1 -/* MCPWM_TIMER1_SYNCI_EN : R/W ;bitpos:[0] ;default: 1'h0 ; */ -/*description: .*/ +/** MCPWM_TIMER1_SYNC_REG register + * PWM timer1 sync function configuration register. + */ +#define MCPWM_TIMER1_SYNC_REG(i) (DR_REG_MCPWM_BASE(i) + 0x1c) +/** MCPWM_TIMER1_SYNCI_EN : R/W; bitpos: [0]; default: 0; + * When set, timer reloading with phase on sync input event is enabled. + */ #define MCPWM_TIMER1_SYNCI_EN (BIT(0)) -#define MCPWM_TIMER1_SYNCI_EN_M (BIT(0)) -#define MCPWM_TIMER1_SYNCI_EN_V 0x1 +#define MCPWM_TIMER1_SYNCI_EN_M (MCPWM_TIMER1_SYNCI_EN_V << MCPWM_TIMER1_SYNCI_EN_S) +#define MCPWM_TIMER1_SYNCI_EN_V 0x00000001U #define MCPWM_TIMER1_SYNCI_EN_S 0 +/** MCPWM_TIMER1_SYNC_SW : R/W; bitpos: [1]; default: 0; + * Toggling this bit will trigger a software sync. + */ +#define MCPWM_TIMER1_SYNC_SW (BIT(1)) +#define MCPWM_TIMER1_SYNC_SW_M (MCPWM_TIMER1_SYNC_SW_V << MCPWM_TIMER1_SYNC_SW_S) +#define MCPWM_TIMER1_SYNC_SW_V 0x00000001U +#define MCPWM_TIMER1_SYNC_SW_S 1 +/** MCPWM_TIMER1_SYNCO_SEL : R/W; bitpos: [3:2]; default: 0; + * PWM timer1 sync_out selection, 0: sync_in, 1: TEZ, 2: TEP, and sync out will always + * generate when toggling the reg_timer1_sync_sw bit + */ +#define MCPWM_TIMER1_SYNCO_SEL 0x00000003U +#define MCPWM_TIMER1_SYNCO_SEL_M (MCPWM_TIMER1_SYNCO_SEL_V << MCPWM_TIMER1_SYNCO_SEL_S) +#define MCPWM_TIMER1_SYNCO_SEL_V 0x00000003U +#define MCPWM_TIMER1_SYNCO_SEL_S 2 +/** MCPWM_TIMER1_PHASE : R/W; bitpos: [19:4]; default: 0; + * phase for timer reload on sync event + */ +#define MCPWM_TIMER1_PHASE 0x0000FFFFU +#define MCPWM_TIMER1_PHASE_M (MCPWM_TIMER1_PHASE_V << MCPWM_TIMER1_PHASE_S) +#define MCPWM_TIMER1_PHASE_V 0x0000FFFFU +#define MCPWM_TIMER1_PHASE_S 4 +/** MCPWM_TIMER1_PHASE_DIRECTION : R/W; bitpos: [20]; default: 0; + * Configure the PWM timer1's direction at the time sync event occurs when timer1 mode + * is up-down mode: 0-increase,1-decrease + */ +#define MCPWM_TIMER1_PHASE_DIRECTION (BIT(20)) +#define MCPWM_TIMER1_PHASE_DIRECTION_M (MCPWM_TIMER1_PHASE_DIRECTION_V << MCPWM_TIMER1_PHASE_DIRECTION_S) +#define MCPWM_TIMER1_PHASE_DIRECTION_V 0x00000001U +#define MCPWM_TIMER1_PHASE_DIRECTION_S 20 -#define MCPWM_TIMER1_STATUS_REG(i) (REG_MCPWM_BASE(i) + 0x20) -/* MCPWM_TIMER1_DIRECTION : RO ;bitpos:[16] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_DIRECTION (BIT(16)) -#define MCPWM_TIMER1_DIRECTION_M (BIT(16)) -#define MCPWM_TIMER1_DIRECTION_V 0x1 -#define MCPWM_TIMER1_DIRECTION_S 16 -/* MCPWM_TIMER1_VALUE : RO ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_VALUE 0x0000FFFF -#define MCPWM_TIMER1_VALUE_M ((MCPWM_TIMER1_VALUE_V)<<(MCPWM_TIMER1_VALUE_S)) -#define MCPWM_TIMER1_VALUE_V 0xFFFF +/** MCPWM_TIMER1_STATUS_REG register + * PWM timer1 status register. + */ +#define MCPWM_TIMER1_STATUS_REG(i) (DR_REG_MCPWM_BASE(i) + 0x20) +/** MCPWM_TIMER1_VALUE : RO; bitpos: [15:0]; default: 0; + * current PWM timer1 counter value + */ +#define MCPWM_TIMER1_VALUE 0x0000FFFFU +#define MCPWM_TIMER1_VALUE_M (MCPWM_TIMER1_VALUE_V << MCPWM_TIMER1_VALUE_S) +#define MCPWM_TIMER1_VALUE_V 0x0000FFFFU #define MCPWM_TIMER1_VALUE_S 0 +/** MCPWM_TIMER1_DIRECTION : RO; bitpos: [16]; default: 0; + * current PWM timer1 counter direction, 0: increment 1: decrement + */ +#define MCPWM_TIMER1_DIRECTION (BIT(16)) +#define MCPWM_TIMER1_DIRECTION_M (MCPWM_TIMER1_DIRECTION_V << MCPWM_TIMER1_DIRECTION_S) +#define MCPWM_TIMER1_DIRECTION_V 0x00000001U +#define MCPWM_TIMER1_DIRECTION_S 16 -#define MCPWM_TIMER2_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0x24) -/* MCPWM_TIMER2_PERIOD_UPMETHOD : R/W ;bitpos:[25:24] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_PERIOD_UPMETHOD 0x00000003 -#define MCPWM_TIMER2_PERIOD_UPMETHOD_M ((MCPWM_TIMER2_PERIOD_UPMETHOD_V)<<(MCPWM_TIMER2_PERIOD_UPMETHOD_S)) -#define MCPWM_TIMER2_PERIOD_UPMETHOD_V 0x3 -#define MCPWM_TIMER2_PERIOD_UPMETHOD_S 24 -/* MCPWM_TIMER2_PERIOD : R/W ;bitpos:[23:8] ;default: 16'h00ff ; */ -/*description: .*/ -#define MCPWM_TIMER2_PERIOD 0x0000FFFF -#define MCPWM_TIMER2_PERIOD_M ((MCPWM_TIMER2_PERIOD_V)<<(MCPWM_TIMER2_PERIOD_S)) -#define MCPWM_TIMER2_PERIOD_V 0xFFFF -#define MCPWM_TIMER2_PERIOD_S 8 -/* MCPWM_TIMER2_PRESCALE : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_PRESCALE 0x000000FF -#define MCPWM_TIMER2_PRESCALE_M ((MCPWM_TIMER2_PRESCALE_V)<<(MCPWM_TIMER2_PRESCALE_S)) -#define MCPWM_TIMER2_PRESCALE_V 0xFF +/** MCPWM_TIMER2_CFG0_REG register + * PWM timer2 period and update method configuration register. + */ +#define MCPWM_TIMER2_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0x24) +/** MCPWM_TIMER2_PRESCALE : R/W; bitpos: [7:0]; default: 0; + * Configure the divisor of PT2_clk, takes effect when PWM timer2 stops and starts + * agsin. period of PT2_clk = Period of PWM_clk * (PWM_TIMER2_PRESCALE + 1) + */ +#define MCPWM_TIMER2_PRESCALE 0x000000FFU +#define MCPWM_TIMER2_PRESCALE_M (MCPWM_TIMER2_PRESCALE_V << MCPWM_TIMER2_PRESCALE_S) +#define MCPWM_TIMER2_PRESCALE_V 0x000000FFU #define MCPWM_TIMER2_PRESCALE_S 0 +/** MCPWM_TIMER2_PERIOD : R/W; bitpos: [23:8]; default: 255; + * period shadow register of PWM timer2 + */ +#define MCPWM_TIMER2_PERIOD 0x0000FFFFU +#define MCPWM_TIMER2_PERIOD_M (MCPWM_TIMER2_PERIOD_V << MCPWM_TIMER2_PERIOD_S) +#define MCPWM_TIMER2_PERIOD_V 0x0000FFFFU +#define MCPWM_TIMER2_PERIOD_S 8 +/** MCPWM_TIMER2_PERIOD_UPMETHOD : R/W; bitpos: [25:24]; default: 0; + * Update method for active register of PWM timer2 period, 0: immediate, 1: TEZ, 2: + * sync, 3: TEZ | sync. TEZ here and below means timer equal zero event + */ +#define MCPWM_TIMER2_PERIOD_UPMETHOD 0x00000003U +#define MCPWM_TIMER2_PERIOD_UPMETHOD_M (MCPWM_TIMER2_PERIOD_UPMETHOD_V << MCPWM_TIMER2_PERIOD_UPMETHOD_S) +#define MCPWM_TIMER2_PERIOD_UPMETHOD_V 0x00000003U +#define MCPWM_TIMER2_PERIOD_UPMETHOD_S 24 -#define MCPWM_TIMER2_CFG1_REG(i) (REG_MCPWM_BASE(i) + 0x28) -/* MCPWM_TIMER2_MOD : R/W ;bitpos:[4:3] ;default: 2'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_MOD 0x00000003 -#define MCPWM_TIMER2_MOD_M ((MCPWM_TIMER2_MOD_V)<<(MCPWM_TIMER2_MOD_S)) -#define MCPWM_TIMER2_MOD_V 0x3 -#define MCPWM_TIMER2_MOD_S 3 -/* MCPWM_TIMER2_START : R/W ;bitpos:[2:0] ;default: 3'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_START 0x00000007 -#define MCPWM_TIMER2_START_M ((MCPWM_TIMER2_START_V)<<(MCPWM_TIMER2_START_S)) -#define MCPWM_TIMER2_START_V 0x7 +/** MCPWM_TIMER2_CFG1_REG register + * PWM timer2 working mode and start/stop control configuration register. + */ +#define MCPWM_TIMER2_CFG1_REG(i) (DR_REG_MCPWM_BASE(i) + 0x28) +/** MCPWM_TIMER2_START : R/W/SC; bitpos: [2:0]; default: 0; + * PWM timer2 start and stop control. 0: if PWM timer2 starts, then stops at TEZ, 1: + * if timer2 starts, then stops at TEP, 2: PWM timer2 starts and runs on, 3: timer2 + * starts and stops at the next TEZ, 4: timer2 starts and stops at the next TEP. TEP + * here and below means the event that happens when the timer equals to period + */ +#define MCPWM_TIMER2_START 0x00000007U +#define MCPWM_TIMER2_START_M (MCPWM_TIMER2_START_V << MCPWM_TIMER2_START_S) +#define MCPWM_TIMER2_START_V 0x00000007U #define MCPWM_TIMER2_START_S 0 +/** MCPWM_TIMER2_MOD : R/W; bitpos: [4:3]; default: 0; + * PWM timer2 working mode, 0: freeze, 1: increase mode, 2: decrease mode, 3: up-down + * mode + */ +#define MCPWM_TIMER2_MOD 0x00000003U +#define MCPWM_TIMER2_MOD_M (MCPWM_TIMER2_MOD_V << MCPWM_TIMER2_MOD_S) +#define MCPWM_TIMER2_MOD_V 0x00000003U +#define MCPWM_TIMER2_MOD_S 3 -#define MCPWM_TIMER2_SYNC_REG(i) (REG_MCPWM_BASE(i) + 0x2C) -/* MCPWM_TIMER2_PHASE : R/W ;bitpos:[20:4] ;default: 17'd0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_PHASE 0x0001FFFF -#define MCPWM_TIMER2_PHASE_M ((MCPWM_TIMER2_PHASE_V)<<(MCPWM_TIMER2_PHASE_S)) -#define MCPWM_TIMER2_PHASE_V 0x1FFFF -#define MCPWM_TIMER2_PHASE_S 4 -/* MCPWM_TIMER2_SYNCO_SEL : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_SYNCO_SEL 0x00000003 -#define MCPWM_TIMER2_SYNCO_SEL_M ((MCPWM_TIMER2_SYNCO_SEL_V)<<(MCPWM_TIMER2_SYNCO_SEL_S)) -#define MCPWM_TIMER2_SYNCO_SEL_V 0x3 -#define MCPWM_TIMER2_SYNCO_SEL_S 2 -/* MCPWM_TIMER2_SYNC_SW : R/W ;bitpos:[1] ;default: 1'h0 ; */ -/*description: write the negate value will trigger a sw sync.*/ -#define MCPWM_TIMER2_SYNC_SW (BIT(1)) -#define MCPWM_TIMER2_SYNC_SW_M (BIT(1)) -#define MCPWM_TIMER2_SYNC_SW_V 0x1 -#define MCPWM_TIMER2_SYNC_SW_S 1 -/* MCPWM_TIMER2_SYNCI_EN : R/W ;bitpos:[0] ;default: 1'h0 ; */ -/*description: .*/ +/** MCPWM_TIMER2_SYNC_REG register + * PWM timer2 sync function configuration register. + */ +#define MCPWM_TIMER2_SYNC_REG(i) (DR_REG_MCPWM_BASE(i) + 0x2c) +/** MCPWM_TIMER2_SYNCI_EN : R/W; bitpos: [0]; default: 0; + * When set, timer reloading with phase on sync input event is enabled. + */ #define MCPWM_TIMER2_SYNCI_EN (BIT(0)) -#define MCPWM_TIMER2_SYNCI_EN_M (BIT(0)) -#define MCPWM_TIMER2_SYNCI_EN_V 0x1 +#define MCPWM_TIMER2_SYNCI_EN_M (MCPWM_TIMER2_SYNCI_EN_V << MCPWM_TIMER2_SYNCI_EN_S) +#define MCPWM_TIMER2_SYNCI_EN_V 0x00000001U #define MCPWM_TIMER2_SYNCI_EN_S 0 +/** MCPWM_TIMER2_SYNC_SW : R/W; bitpos: [1]; default: 0; + * Toggling this bit will trigger a software sync. + */ +#define MCPWM_TIMER2_SYNC_SW (BIT(1)) +#define MCPWM_TIMER2_SYNC_SW_M (MCPWM_TIMER2_SYNC_SW_V << MCPWM_TIMER2_SYNC_SW_S) +#define MCPWM_TIMER2_SYNC_SW_V 0x00000001U +#define MCPWM_TIMER2_SYNC_SW_S 1 +/** MCPWM_TIMER2_SYNCO_SEL : R/W; bitpos: [3:2]; default: 0; + * PWM timer2 sync_out selection, 0: sync_in, 1: TEZ, 2: TEP, and sync out will always + * generate when toggling the reg_timer0_sync_sw bit + */ +#define MCPWM_TIMER2_SYNCO_SEL 0x00000003U +#define MCPWM_TIMER2_SYNCO_SEL_M (MCPWM_TIMER2_SYNCO_SEL_V << MCPWM_TIMER2_SYNCO_SEL_S) +#define MCPWM_TIMER2_SYNCO_SEL_V 0x00000003U +#define MCPWM_TIMER2_SYNCO_SEL_S 2 +/** MCPWM_TIMER2_PHASE : R/W; bitpos: [19:4]; default: 0; + * phase for timer reload on sync event + */ +#define MCPWM_TIMER2_PHASE 0x0000FFFFU +#define MCPWM_TIMER2_PHASE_M (MCPWM_TIMER2_PHASE_V << MCPWM_TIMER2_PHASE_S) +#define MCPWM_TIMER2_PHASE_V 0x0000FFFFU +#define MCPWM_TIMER2_PHASE_S 4 +/** MCPWM_TIMER2_PHASE_DIRECTION : R/W; bitpos: [20]; default: 0; + * Configure the PWM timer2's direction at the time sync event occurs when timer2 mode + * is up-down mode: 0-increase,1-decrease + */ +#define MCPWM_TIMER2_PHASE_DIRECTION (BIT(20)) +#define MCPWM_TIMER2_PHASE_DIRECTION_M (MCPWM_TIMER2_PHASE_DIRECTION_V << MCPWM_TIMER2_PHASE_DIRECTION_S) +#define MCPWM_TIMER2_PHASE_DIRECTION_V 0x00000001U +#define MCPWM_TIMER2_PHASE_DIRECTION_S 20 -#define MCPWM_TIMER2_STATUS_REG(i) (REG_MCPWM_BASE(i) + 0x30) -/* MCPWM_TIMER2_DIRECTION : RO ;bitpos:[16] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_DIRECTION (BIT(16)) -#define MCPWM_TIMER2_DIRECTION_M (BIT(16)) -#define MCPWM_TIMER2_DIRECTION_V 0x1 -#define MCPWM_TIMER2_DIRECTION_S 16 -/* MCPWM_TIMER2_VALUE : RO ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_VALUE 0x0000FFFF -#define MCPWM_TIMER2_VALUE_M ((MCPWM_TIMER2_VALUE_V)<<(MCPWM_TIMER2_VALUE_S)) -#define MCPWM_TIMER2_VALUE_V 0xFFFF +/** MCPWM_TIMER2_STATUS_REG register + * PWM timer2 status register. + */ +#define MCPWM_TIMER2_STATUS_REG(i) (DR_REG_MCPWM_BASE(i) + 0x30) +/** MCPWM_TIMER2_VALUE : RO; bitpos: [15:0]; default: 0; + * current PWM timer2 counter value + */ +#define MCPWM_TIMER2_VALUE 0x0000FFFFU +#define MCPWM_TIMER2_VALUE_M (MCPWM_TIMER2_VALUE_V << MCPWM_TIMER2_VALUE_S) +#define MCPWM_TIMER2_VALUE_V 0x0000FFFFU #define MCPWM_TIMER2_VALUE_S 0 +/** MCPWM_TIMER2_DIRECTION : RO; bitpos: [16]; default: 0; + * current PWM timer2 counter direction, 0: increment 1: decrement + */ +#define MCPWM_TIMER2_DIRECTION (BIT(16)) +#define MCPWM_TIMER2_DIRECTION_M (MCPWM_TIMER2_DIRECTION_V << MCPWM_TIMER2_DIRECTION_S) +#define MCPWM_TIMER2_DIRECTION_V 0x00000001U +#define MCPWM_TIMER2_DIRECTION_S 16 -#define MCPWM_TIMER_SYNCI_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x34) -/* MCPWM_EXTERNAL_SYNCI2_INVERT : R/W ;bitpos:[11] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_EXTERNAL_SYNCI2_INVERT (BIT(11)) -#define MCPWM_EXTERNAL_SYNCI2_INVERT_M (BIT(11)) -#define MCPWM_EXTERNAL_SYNCI2_INVERT_V 0x1 -#define MCPWM_EXTERNAL_SYNCI2_INVERT_S 11 -/* MCPWM_EXTERNAL_SYNCI1_INVERT : R/W ;bitpos:[10] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_EXTERNAL_SYNCI1_INVERT (BIT(10)) -#define MCPWM_EXTERNAL_SYNCI1_INVERT_M (BIT(10)) -#define MCPWM_EXTERNAL_SYNCI1_INVERT_V 0x1 -#define MCPWM_EXTERNAL_SYNCI1_INVERT_S 10 -/* MCPWM_EXTERNAL_SYNCI0_INVERT : R/W ;bitpos:[9] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_EXTERNAL_SYNCI0_INVERT (BIT(9)) -#define MCPWM_EXTERNAL_SYNCI0_INVERT_M (BIT(9)) -#define MCPWM_EXTERNAL_SYNCI0_INVERT_V 0x1 -#define MCPWM_EXTERNAL_SYNCI0_INVERT_S 9 -/* MCPWM_TIMER2_SYNCISEL : R/W ;bitpos:[8:6] ;default: 3'd0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_SYNCISEL 0x00000007 -#define MCPWM_TIMER2_SYNCISEL_M ((MCPWM_TIMER2_SYNCISEL_V)<<(MCPWM_TIMER2_SYNCISEL_S)) -#define MCPWM_TIMER2_SYNCISEL_V 0x7 -#define MCPWM_TIMER2_SYNCISEL_S 6 -/* MCPWM_TIMER1_SYNCISEL : R/W ;bitpos:[5:3] ;default: 3'd0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_SYNCISEL 0x00000007 -#define MCPWM_TIMER1_SYNCISEL_M ((MCPWM_TIMER1_SYNCISEL_V)<<(MCPWM_TIMER1_SYNCISEL_S)) -#define MCPWM_TIMER1_SYNCISEL_V 0x7 -#define MCPWM_TIMER1_SYNCISEL_S 3 -/* MCPWM_TIMER0_SYNCISEL : R/W ;bitpos:[2:0] ;default: 3'd0 ; */ -/*description: .*/ -#define MCPWM_TIMER0_SYNCISEL 0x00000007 -#define MCPWM_TIMER0_SYNCISEL_M ((MCPWM_TIMER0_SYNCISEL_V)<<(MCPWM_TIMER0_SYNCISEL_S)) -#define MCPWM_TIMER0_SYNCISEL_V 0x7 +/** MCPWM_TIMER_SYNCI_CFG_REG register + * Synchronization input selection for three PWM timers. + */ +#define MCPWM_TIMER_SYNCI_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x34) +/** MCPWM_TIMER0_SYNCISEL : R/W; bitpos: [2:0]; default: 0; + * select sync input for PWM timer0, 1: PWM timer0 sync_out, 2: PWM timer1 sync_out, + * 3: PWM timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, 6: + * SYNC2 from GPIO matrix, other values: no sync input selected + */ +#define MCPWM_TIMER0_SYNCISEL 0x00000007U +#define MCPWM_TIMER0_SYNCISEL_M (MCPWM_TIMER0_SYNCISEL_V << MCPWM_TIMER0_SYNCISEL_S) +#define MCPWM_TIMER0_SYNCISEL_V 0x00000007U #define MCPWM_TIMER0_SYNCISEL_S 0 +/** MCPWM_TIMER1_SYNCISEL : R/W; bitpos: [5:3]; default: 0; + * select sync input for PWM timer1, 1: PWM timer0 sync_out, 2: PWM timer1 sync_out, + * 3: PWM timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, 6: + * SYNC2 from GPIO matrix, other values: no sync input selected + */ +#define MCPWM_TIMER1_SYNCISEL 0x00000007U +#define MCPWM_TIMER1_SYNCISEL_M (MCPWM_TIMER1_SYNCISEL_V << MCPWM_TIMER1_SYNCISEL_S) +#define MCPWM_TIMER1_SYNCISEL_V 0x00000007U +#define MCPWM_TIMER1_SYNCISEL_S 3 +/** MCPWM_TIMER2_SYNCISEL : R/W; bitpos: [8:6]; default: 0; + * select sync input for PWM timer2, 1: PWM timer0 sync_out, 2: PWM timer1 sync_out, + * 3: PWM timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, 6: + * SYNC2 from GPIO matrix, other values: no sync input selected + */ +#define MCPWM_TIMER2_SYNCISEL 0x00000007U +#define MCPWM_TIMER2_SYNCISEL_M (MCPWM_TIMER2_SYNCISEL_V << MCPWM_TIMER2_SYNCISEL_S) +#define MCPWM_TIMER2_SYNCISEL_V 0x00000007U +#define MCPWM_TIMER2_SYNCISEL_S 6 +/** MCPWM_EXTERNAL_SYNCI0_INVERT : R/W; bitpos: [9]; default: 0; + * invert SYNC0 from GPIO matrix + */ +#define MCPWM_EXTERNAL_SYNCI0_INVERT (BIT(9)) +#define MCPWM_EXTERNAL_SYNCI0_INVERT_M (MCPWM_EXTERNAL_SYNCI0_INVERT_V << MCPWM_EXTERNAL_SYNCI0_INVERT_S) +#define MCPWM_EXTERNAL_SYNCI0_INVERT_V 0x00000001U +#define MCPWM_EXTERNAL_SYNCI0_INVERT_S 9 +/** MCPWM_EXTERNAL_SYNCI1_INVERT : R/W; bitpos: [10]; default: 0; + * invert SYNC1 from GPIO matrix + */ +#define MCPWM_EXTERNAL_SYNCI1_INVERT (BIT(10)) +#define MCPWM_EXTERNAL_SYNCI1_INVERT_M (MCPWM_EXTERNAL_SYNCI1_INVERT_V << MCPWM_EXTERNAL_SYNCI1_INVERT_S) +#define MCPWM_EXTERNAL_SYNCI1_INVERT_V 0x00000001U +#define MCPWM_EXTERNAL_SYNCI1_INVERT_S 10 +/** MCPWM_EXTERNAL_SYNCI2_INVERT : R/W; bitpos: [11]; default: 0; + * invert SYNC2 from GPIO matrix + */ +#define MCPWM_EXTERNAL_SYNCI2_INVERT (BIT(11)) +#define MCPWM_EXTERNAL_SYNCI2_INVERT_M (MCPWM_EXTERNAL_SYNCI2_INVERT_V << MCPWM_EXTERNAL_SYNCI2_INVERT_S) +#define MCPWM_EXTERNAL_SYNCI2_INVERT_V 0x00000001U +#define MCPWM_EXTERNAL_SYNCI2_INVERT_S 11 -#define MCPWM_OPERATOR_TIMERSEL_REG(i) (REG_MCPWM_BASE(i) + 0x38) -/* MCPWM_OPERATOR2_TIMERSEL : R/W ;bitpos:[5:4] ;default: 2'd0 ; */ -/*description: 0: timer0, 1: timer1, 2: timer2.*/ -#define MCPWM_OPERATOR2_TIMERSEL 0x00000003 -#define MCPWM_OPERATOR2_TIMERSEL_M ((MCPWM_OPERATOR2_TIMERSEL_V)<<(MCPWM_OPERATOR2_TIMERSEL_S)) -#define MCPWM_OPERATOR2_TIMERSEL_V 0x3 -#define MCPWM_OPERATOR2_TIMERSEL_S 4 -/* MCPWM_OPERATOR1_TIMERSEL : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: 0: timer0, 1: timer1, 2: timer2.*/ -#define MCPWM_OPERATOR1_TIMERSEL 0x00000003 -#define MCPWM_OPERATOR1_TIMERSEL_M ((MCPWM_OPERATOR1_TIMERSEL_V)<<(MCPWM_OPERATOR1_TIMERSEL_S)) -#define MCPWM_OPERATOR1_TIMERSEL_V 0x3 -#define MCPWM_OPERATOR1_TIMERSEL_S 2 -/* MCPWM_OPERATOR0_TIMERSEL : R/W ;bitpos:[1:0] ;default: 2'd0 ; */ -/*description: 0: timer0, 1: timer1, 2: timer2.*/ -#define MCPWM_OPERATOR0_TIMERSEL 0x00000003 -#define MCPWM_OPERATOR0_TIMERSEL_M ((MCPWM_OPERATOR0_TIMERSEL_V)<<(MCPWM_OPERATOR0_TIMERSEL_S)) -#define MCPWM_OPERATOR0_TIMERSEL_V 0x3 +/** MCPWM_OPERATOR_TIMERSEL_REG register + * Select specific timer for PWM operators. + */ +#define MCPWM_OPERATOR_TIMERSEL_REG(i) (DR_REG_MCPWM_BASE(i) + 0x38) +/** MCPWM_OPERATOR0_TIMERSEL : R/W; bitpos: [1:0]; default: 0; + * Select which PWM timer is the timing reference for PWM operator0, 0: timer0, 1: + * timer1, 2: timer2 + */ +#define MCPWM_OPERATOR0_TIMERSEL 0x00000003U +#define MCPWM_OPERATOR0_TIMERSEL_M (MCPWM_OPERATOR0_TIMERSEL_V << MCPWM_OPERATOR0_TIMERSEL_S) +#define MCPWM_OPERATOR0_TIMERSEL_V 0x00000003U #define MCPWM_OPERATOR0_TIMERSEL_S 0 +/** MCPWM_OPERATOR1_TIMERSEL : R/W; bitpos: [3:2]; default: 0; + * Select which PWM timer is the timing reference for PWM operator1, 0: timer0, 1: + * timer1, 2: timer2 + */ +#define MCPWM_OPERATOR1_TIMERSEL 0x00000003U +#define MCPWM_OPERATOR1_TIMERSEL_M (MCPWM_OPERATOR1_TIMERSEL_V << MCPWM_OPERATOR1_TIMERSEL_S) +#define MCPWM_OPERATOR1_TIMERSEL_V 0x00000003U +#define MCPWM_OPERATOR1_TIMERSEL_S 2 +/** MCPWM_OPERATOR2_TIMERSEL : R/W; bitpos: [5:4]; default: 0; + * Select which PWM timer is the timing reference for PWM operator2, 0: timer0, 1: + * timer1, 2: timer2 + */ +#define MCPWM_OPERATOR2_TIMERSEL 0x00000003U +#define MCPWM_OPERATOR2_TIMERSEL_M (MCPWM_OPERATOR2_TIMERSEL_V << MCPWM_OPERATOR2_TIMERSEL_S) +#define MCPWM_OPERATOR2_TIMERSEL_V 0x00000003U +#define MCPWM_OPERATOR2_TIMERSEL_S 4 -#define MCPWM_CMPR0_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x3C) -/* MCPWM_CMPR0_B_SHDW_FULL : R/W ;bitpos:[9] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR0_B_SHDW_FULL (BIT(9)) -#define MCPWM_CMPR0_B_SHDW_FULL_M (BIT(9)) -#define MCPWM_CMPR0_B_SHDW_FULL_V 0x1 -#define MCPWM_CMPR0_B_SHDW_FULL_S 9 -/* MCPWM_CMPR0_A_SHDW_FULL : R/W ;bitpos:[8] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR0_A_SHDW_FULL (BIT(8)) -#define MCPWM_CMPR0_A_SHDW_FULL_M (BIT(8)) -#define MCPWM_CMPR0_A_SHDW_FULL_V 0x1 -#define MCPWM_CMPR0_A_SHDW_FULL_S 8 -/* MCPWM_CMPR0_B_UPMETHOD : R/W ;bitpos:[7:4] ;default: 4'd0 ; */ -/*description: 0: immediate, bit0: tez, bit1: tep, bit2: sync, bit3: freeze.*/ -#define MCPWM_CMPR0_B_UPMETHOD 0x0000000F -#define MCPWM_CMPR0_B_UPMETHOD_M ((MCPWM_CMPR0_B_UPMETHOD_V)<<(MCPWM_CMPR0_B_UPMETHOD_S)) -#define MCPWM_CMPR0_B_UPMETHOD_V 0xF -#define MCPWM_CMPR0_B_UPMETHOD_S 4 -/* MCPWM_CMPR0_A_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: 0: immediate, bit0: tez, bit1: tep, bit2: sync, bit3: freeze.*/ -#define MCPWM_CMPR0_A_UPMETHOD 0x0000000F -#define MCPWM_CMPR0_A_UPMETHOD_M ((MCPWM_CMPR0_A_UPMETHOD_V)<<(MCPWM_CMPR0_A_UPMETHOD_S)) -#define MCPWM_CMPR0_A_UPMETHOD_V 0xF -#define MCPWM_CMPR0_A_UPMETHOD_S 0 +/** MCPWM_GEN0_STMP_CFG_REG register + * Transfer status and update method for time stamp registers A and B + */ +#define MCPWM_GEN0_STMP_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x3c) +/** MCPWM_GEN0_A_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for PWM generator 0 time stamp A's active register. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when + * bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + */ +#define MCPWM_GEN0_A_UPMETHOD 0x0000000FU +#define MCPWM_GEN0_A_UPMETHOD_M (MCPWM_GEN0_A_UPMETHOD_V << MCPWM_GEN0_A_UPMETHOD_S) +#define MCPWM_GEN0_A_UPMETHOD_V 0x0000000FU +#define MCPWM_GEN0_A_UPMETHOD_S 0 +/** MCPWM_GEN0_B_UPMETHOD : R/W; bitpos: [7:4]; default: 0; + * Update method for PWM generator 0 time stamp B's active register. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when + * bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + */ +#define MCPWM_GEN0_B_UPMETHOD 0x0000000FU +#define MCPWM_GEN0_B_UPMETHOD_M (MCPWM_GEN0_B_UPMETHOD_V << MCPWM_GEN0_B_UPMETHOD_S) +#define MCPWM_GEN0_B_UPMETHOD_V 0x0000000FU +#define MCPWM_GEN0_B_UPMETHOD_S 4 +/** MCPWM_GEN0_A_SHDW_FULL : R/W/WTC/SC; bitpos: [8]; default: 0; + * Set and reset by hardware. If set, PWM generator 0 time stamp A's shadow reg is + * filled and waiting to be transferred to A's active reg. If cleared, A's active reg + * has been updated with shadow register latest value + */ +#define MCPWM_GEN0_A_SHDW_FULL (BIT(8)) +#define MCPWM_GEN0_A_SHDW_FULL_M (MCPWM_GEN0_A_SHDW_FULL_V << MCPWM_GEN0_A_SHDW_FULL_S) +#define MCPWM_GEN0_A_SHDW_FULL_V 0x00000001U +#define MCPWM_GEN0_A_SHDW_FULL_S 8 +/** MCPWM_GEN0_B_SHDW_FULL : R/W/WTC/SC; bitpos: [9]; default: 0; + * Set and reset by hardware. If set, PWM generator 0 time stamp B's shadow reg is + * filled and waiting to be transferred to B's active reg. If cleared, B's active reg + * has been updated with shadow register latest value + */ +#define MCPWM_GEN0_B_SHDW_FULL (BIT(9)) +#define MCPWM_GEN0_B_SHDW_FULL_M (MCPWM_GEN0_B_SHDW_FULL_V << MCPWM_GEN0_B_SHDW_FULL_S) +#define MCPWM_GEN0_B_SHDW_FULL_V 0x00000001U +#define MCPWM_GEN0_B_SHDW_FULL_S 9 -#define MCPWM_CMPR0_VALUE0_REG(i) (REG_MCPWM_BASE(i) + 0x40) -/* MCPWM_CMPR0_A : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR0_A 0x0000FFFF -#define MCPWM_CMPR0_A_M ((MCPWM_CMPR0_A_V)<<(MCPWM_CMPR0_A_S)) -#define MCPWM_CMPR0_A_V 0xFFFF -#define MCPWM_CMPR0_A_S 0 +/** MCPWM_GEN0_TSTMP_A_REG register + * PWM generator 0 shadow register for timer stamp A. + */ +#define MCPWM_GEN0_TSTMP_A_REG(i) (DR_REG_MCPWM_BASE(i) + 0x40) +/** MCPWM_GEN0_A : R/W; bitpos: [15:0]; default: 0; + * PWM generator 0 time stamp A's shadow register + */ +#define MCPWM_GEN0_A 0x0000FFFFU +#define MCPWM_GEN0_A_M (MCPWM_GEN0_A_V << MCPWM_GEN0_A_S) +#define MCPWM_GEN0_A_V 0x0000FFFFU +#define MCPWM_GEN0_A_S 0 -#define MCPWM_CMPR0_VALUE1_REG(i) (REG_MCPWM_BASE(i) + 0x44) -/* MCPWM_CMPR0_B : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR0_B 0x0000FFFF -#define MCPWM_CMPR0_B_M ((MCPWM_CMPR0_B_V)<<(MCPWM_CMPR0_B_S)) -#define MCPWM_CMPR0_B_V 0xFFFF -#define MCPWM_CMPR0_B_S 0 +/** MCPWM_GEN0_TSTMP_B_REG register + * PWM generator 0 shadow register for timer stamp B. + */ +#define MCPWM_GEN0_TSTMP_B_REG(i) (DR_REG_MCPWM_BASE(i) + 0x44) +/** MCPWM_GEN0_B : R/W; bitpos: [15:0]; default: 0; + * PWM generator 0 time stamp B's shadow register + */ +#define MCPWM_GEN0_B 0x0000FFFFU +#define MCPWM_GEN0_B_M (MCPWM_GEN0_B_V << MCPWM_GEN0_B_S) +#define MCPWM_GEN0_B_V 0x0000FFFFU +#define MCPWM_GEN0_B_S 0 -#define MCPWM_GEN0_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0x48) -/* MCPWM_GEN0_T1_SEL : R/W ;bitpos:[9:7] ;default: 3'd0 ; */ -/*description: take effect immediately, 0: extra0, 1: extra1, 2: extra2, 3: sync_taken, 4: none.*/ -#define MCPWM_GEN0_T1_SEL 0x00000007 -#define MCPWM_GEN0_T1_SEL_M ((MCPWM_GEN0_T1_SEL_V)<<(MCPWM_GEN0_T1_SEL_S)) -#define MCPWM_GEN0_T1_SEL_V 0x7 -#define MCPWM_GEN0_T1_SEL_S 7 -/* MCPWM_GEN0_T0_SEL : R/W ;bitpos:[6:4] ;default: 3'd0 ; */ -/*description: take effect immediately, 0: extra0, 1: extra1, 2: extra2, 3: sync_taken, 4: none.*/ -#define MCPWM_GEN0_T0_SEL 0x00000007 -#define MCPWM_GEN0_T0_SEL_M ((MCPWM_GEN0_T0_SEL_V)<<(MCPWM_GEN0_T0_SEL_S)) -#define MCPWM_GEN0_T0_SEL_V 0x7 -#define MCPWM_GEN0_T0_SEL_S 4 -/* MCPWM_GEN0_CFG_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: 0: immediate, bit0: tez, bit1: tep, bit2: sync. bit3: freeze.*/ -#define MCPWM_GEN0_CFG_UPMETHOD 0x0000000F -#define MCPWM_GEN0_CFG_UPMETHOD_M ((MCPWM_GEN0_CFG_UPMETHOD_V)<<(MCPWM_GEN0_CFG_UPMETHOD_S)) -#define MCPWM_GEN0_CFG_UPMETHOD_V 0xF +/** MCPWM_GEN0_CFG0_REG register + * PWM generator 0 event T0 and T1 handling + */ +#define MCPWM_GEN0_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0x48) +/** MCPWM_GEN0_CFG_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for PWM generator 0's active register of configuration. When all bits + * are set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to + * 1:TEP,when bit2 is set to 1:sync,when bit3 is set to 1:disable the update + */ +#define MCPWM_GEN0_CFG_UPMETHOD 0x0000000FU +#define MCPWM_GEN0_CFG_UPMETHOD_M (MCPWM_GEN0_CFG_UPMETHOD_V << MCPWM_GEN0_CFG_UPMETHOD_S) +#define MCPWM_GEN0_CFG_UPMETHOD_V 0x0000000FU #define MCPWM_GEN0_CFG_UPMETHOD_S 0 +/** MCPWM_GEN0_T0_SEL : R/W; bitpos: [6:4]; default: 0; + * Source selection for PWM generator 0 event_t0, take effect immediately, 0: + * fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + */ +#define MCPWM_GEN0_T0_SEL 0x00000007U +#define MCPWM_GEN0_T0_SEL_M (MCPWM_GEN0_T0_SEL_V << MCPWM_GEN0_T0_SEL_S) +#define MCPWM_GEN0_T0_SEL_V 0x00000007U +#define MCPWM_GEN0_T0_SEL_S 4 +/** MCPWM_GEN0_T1_SEL : R/W; bitpos: [9:7]; default: 0; + * Source selection for PWM generator 0 event_t1, take effect immediately, 0: + * fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + */ +#define MCPWM_GEN0_T1_SEL 0x00000007U +#define MCPWM_GEN0_T1_SEL_M (MCPWM_GEN0_T1_SEL_V << MCPWM_GEN0_T1_SEL_S) +#define MCPWM_GEN0_T1_SEL_V 0x00000007U +#define MCPWM_GEN0_T1_SEL_S 7 -#define MCPWM_GEN0_FORCE_REG(i) (REG_MCPWM_BASE(i) + 0x4C) -/* MCPWM_GEN0_B_NCIFORCE_MODE : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: 0: disabled, 1: low, 2: high, 3: disabled.*/ -#define MCPWM_GEN0_B_NCIFORCE_MODE 0x00000003 -#define MCPWM_GEN0_B_NCIFORCE_MODE_M ((MCPWM_GEN0_B_NCIFORCE_MODE_V)<<(MCPWM_GEN0_B_NCIFORCE_MODE_S)) -#define MCPWM_GEN0_B_NCIFORCE_MODE_V 0x3 -#define MCPWM_GEN0_B_NCIFORCE_MODE_S 14 -/* MCPWM_GEN0_B_NCIFORCE : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: non-continuous immediate sw force, a toggle will trigger a force event.*/ -#define MCPWM_GEN0_B_NCIFORCE (BIT(13)) -#define MCPWM_GEN0_B_NCIFORCE_M (BIT(13)) -#define MCPWM_GEN0_B_NCIFORCE_V 0x1 -#define MCPWM_GEN0_B_NCIFORCE_S 13 -/* MCPWM_GEN0_A_NCIFORCE_MODE : R/W ;bitpos:[12:11] ;default: 2'd0 ; */ -/*description: 0: disabled, 1: low, 2: high, 3: disabled.*/ -#define MCPWM_GEN0_A_NCIFORCE_MODE 0x00000003 -#define MCPWM_GEN0_A_NCIFORCE_MODE_M ((MCPWM_GEN0_A_NCIFORCE_MODE_V)<<(MCPWM_GEN0_A_NCIFORCE_MODE_S)) -#define MCPWM_GEN0_A_NCIFORCE_MODE_V 0x3 -#define MCPWM_GEN0_A_NCIFORCE_MODE_S 11 -/* MCPWM_GEN0_A_NCIFORCE : R/W ;bitpos:[10] ;default: 1'd0 ; */ -/*description: non-continuous immediate sw force, a toggle will trigger a force event.*/ -#define MCPWM_GEN0_A_NCIFORCE (BIT(10)) -#define MCPWM_GEN0_A_NCIFORCE_M (BIT(10)) -#define MCPWM_GEN0_A_NCIFORCE_V 0x1 -#define MCPWM_GEN0_A_NCIFORCE_S 10 -/* MCPWM_GEN0_B_CNTUFORCE_MODE : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: 0: disabled, 1: low, 2: high, 3: disabled.*/ -#define MCPWM_GEN0_B_CNTUFORCE_MODE 0x00000003 -#define MCPWM_GEN0_B_CNTUFORCE_MODE_M ((MCPWM_GEN0_B_CNTUFORCE_MODE_V)<<(MCPWM_GEN0_B_CNTUFORCE_MODE_S)) -#define MCPWM_GEN0_B_CNTUFORCE_MODE_V 0x3 -#define MCPWM_GEN0_B_CNTUFORCE_MODE_S 8 -/* MCPWM_GEN0_A_CNTUFORCE_MODE : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: 0: disabled, 1: low, 2: high, 3: disabled.*/ -#define MCPWM_GEN0_A_CNTUFORCE_MODE 0x00000003 -#define MCPWM_GEN0_A_CNTUFORCE_MODE_M ((MCPWM_GEN0_A_CNTUFORCE_MODE_V)<<(MCPWM_GEN0_A_CNTUFORCE_MODE_S)) -#define MCPWM_GEN0_A_CNTUFORCE_MODE_V 0x3 -#define MCPWM_GEN0_A_CNTUFORCE_MODE_S 6 -/* MCPWM_GEN0_CNTUFORCE_UPMETHOD : R/W ;bitpos:[5:0] ;default: 6'h20 ; */ -/*description: 0: immediate, bit0: tez, bit1: tep, bit2: tea, bit3: teb, bit4: sync, bit5: free -ze.*/ -#define MCPWM_GEN0_CNTUFORCE_UPMETHOD 0x0000003F -#define MCPWM_GEN0_CNTUFORCE_UPMETHOD_M ((MCPWM_GEN0_CNTUFORCE_UPMETHOD_V)<<(MCPWM_GEN0_CNTUFORCE_UPMETHOD_S)) -#define MCPWM_GEN0_CNTUFORCE_UPMETHOD_V 0x3F +/** MCPWM_GEN0_FORCE_REG register + * Permissives to force PWM0A and PWM0B outputs by software + */ +#define MCPWM_GEN0_FORCE_REG(i) (DR_REG_MCPWM_BASE(i) + 0x4c) +/** MCPWM_GEN0_CNTUFORCE_UPMETHOD : R/W; bitpos: [5:0]; default: 32; + * Updating method for continuous software force of PWM generator0. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ,,when bit1 is set to 1: TEP, when + * bit2 is set to 1: TEA, when bit3 is set to 1: TEB, when bit4 is set to 1: sync, + * when bit5 is set to 1: disable update. (TEA/B here and below means an event + * generated when the timer's value equals to that of register A/B.) + */ +#define MCPWM_GEN0_CNTUFORCE_UPMETHOD 0x0000003FU +#define MCPWM_GEN0_CNTUFORCE_UPMETHOD_M (MCPWM_GEN0_CNTUFORCE_UPMETHOD_V << MCPWM_GEN0_CNTUFORCE_UPMETHOD_S) +#define MCPWM_GEN0_CNTUFORCE_UPMETHOD_V 0x0000003FU #define MCPWM_GEN0_CNTUFORCE_UPMETHOD_S 0 +/** MCPWM_GEN0_A_CNTUFORCE_MODE : R/W; bitpos: [7:6]; default: 0; + * Continuous software force mode for PWM0A. 0: disabled, 1: low, 2: high, 3: disabled + */ +#define MCPWM_GEN0_A_CNTUFORCE_MODE 0x00000003U +#define MCPWM_GEN0_A_CNTUFORCE_MODE_M (MCPWM_GEN0_A_CNTUFORCE_MODE_V << MCPWM_GEN0_A_CNTUFORCE_MODE_S) +#define MCPWM_GEN0_A_CNTUFORCE_MODE_V 0x00000003U +#define MCPWM_GEN0_A_CNTUFORCE_MODE_S 6 +/** MCPWM_GEN0_B_CNTUFORCE_MODE : R/W; bitpos: [9:8]; default: 0; + * Continuous software force mode for PWM0B. 0: disabled, 1: low, 2: high, 3: disabled + */ +#define MCPWM_GEN0_B_CNTUFORCE_MODE 0x00000003U +#define MCPWM_GEN0_B_CNTUFORCE_MODE_M (MCPWM_GEN0_B_CNTUFORCE_MODE_V << MCPWM_GEN0_B_CNTUFORCE_MODE_S) +#define MCPWM_GEN0_B_CNTUFORCE_MODE_V 0x00000003U +#define MCPWM_GEN0_B_CNTUFORCE_MODE_S 8 +/** MCPWM_GEN0_A_NCIFORCE : R/W; bitpos: [10]; default: 0; + * Trigger of non-continuous immediate software-force event for PWM0A, a toggle will + * trigger a force event. + */ +#define MCPWM_GEN0_A_NCIFORCE (BIT(10)) +#define MCPWM_GEN0_A_NCIFORCE_M (MCPWM_GEN0_A_NCIFORCE_V << MCPWM_GEN0_A_NCIFORCE_S) +#define MCPWM_GEN0_A_NCIFORCE_V 0x00000001U +#define MCPWM_GEN0_A_NCIFORCE_S 10 +/** MCPWM_GEN0_A_NCIFORCE_MODE : R/W; bitpos: [12:11]; default: 0; + * non-continuous immediate software force mode for PWM0A, 0: disabled, 1: low, 2: + * high, 3: disabled + */ +#define MCPWM_GEN0_A_NCIFORCE_MODE 0x00000003U +#define MCPWM_GEN0_A_NCIFORCE_MODE_M (MCPWM_GEN0_A_NCIFORCE_MODE_V << MCPWM_GEN0_A_NCIFORCE_MODE_S) +#define MCPWM_GEN0_A_NCIFORCE_MODE_V 0x00000003U +#define MCPWM_GEN0_A_NCIFORCE_MODE_S 11 +/** MCPWM_GEN0_B_NCIFORCE : R/W; bitpos: [13]; default: 0; + * Trigger of non-continuous immediate software-force event for PWM0B, a toggle will + * trigger a force event. + */ +#define MCPWM_GEN0_B_NCIFORCE (BIT(13)) +#define MCPWM_GEN0_B_NCIFORCE_M (MCPWM_GEN0_B_NCIFORCE_V << MCPWM_GEN0_B_NCIFORCE_S) +#define MCPWM_GEN0_B_NCIFORCE_V 0x00000001U +#define MCPWM_GEN0_B_NCIFORCE_S 13 +/** MCPWM_GEN0_B_NCIFORCE_MODE : R/W; bitpos: [15:14]; default: 0; + * non-continuous immediate software force mode for PWM0B, 0: disabled, 1: low, 2: + * high, 3: disabled + */ +#define MCPWM_GEN0_B_NCIFORCE_MODE 0x00000003U +#define MCPWM_GEN0_B_NCIFORCE_MODE_M (MCPWM_GEN0_B_NCIFORCE_MODE_V << MCPWM_GEN0_B_NCIFORCE_MODE_S) +#define MCPWM_GEN0_B_NCIFORCE_MODE_V 0x00000003U +#define MCPWM_GEN0_B_NCIFORCE_MODE_S 14 -#define MCPWM_GEN0_A_REG(i) (REG_MCPWM_BASE(i) + 0x50) -/* MCPWM_GEN0_A_DT1 : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: 0: no change, 1: low, 2: high, 3: toggle.*/ -#define MCPWM_GEN0_A_DT1 0x00000003 -#define MCPWM_GEN0_A_DT1_M ((MCPWM_GEN0_A_DT1_V)<<(MCPWM_GEN0_A_DT1_S)) -#define MCPWM_GEN0_A_DT1_V 0x3 -#define MCPWM_GEN0_A_DT1_S 22 -/* MCPWM_GEN0_A_DT0 : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_A_DT0 0x00000003 -#define MCPWM_GEN0_A_DT0_M ((MCPWM_GEN0_A_DT0_V)<<(MCPWM_GEN0_A_DT0_S)) -#define MCPWM_GEN0_A_DT0_V 0x3 -#define MCPWM_GEN0_A_DT0_S 20 -/* MCPWM_GEN0_A_DTEB : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_A_DTEB 0x00000003 -#define MCPWM_GEN0_A_DTEB_M ((MCPWM_GEN0_A_DTEB_V)<<(MCPWM_GEN0_A_DTEB_S)) -#define MCPWM_GEN0_A_DTEB_V 0x3 -#define MCPWM_GEN0_A_DTEB_S 18 -/* MCPWM_GEN0_A_DTEA : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_A_DTEA 0x00000003 -#define MCPWM_GEN0_A_DTEA_M ((MCPWM_GEN0_A_DTEA_V)<<(MCPWM_GEN0_A_DTEA_S)) -#define MCPWM_GEN0_A_DTEA_V 0x3 -#define MCPWM_GEN0_A_DTEA_S 16 -/* MCPWM_GEN0_A_DTEP : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_A_DTEP 0x00000003 -#define MCPWM_GEN0_A_DTEP_M ((MCPWM_GEN0_A_DTEP_V)<<(MCPWM_GEN0_A_DTEP_S)) -#define MCPWM_GEN0_A_DTEP_V 0x3 -#define MCPWM_GEN0_A_DTEP_S 14 -/* MCPWM_GEN0_A_DTEZ : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_A_DTEZ 0x00000003 -#define MCPWM_GEN0_A_DTEZ_M ((MCPWM_GEN0_A_DTEZ_V)<<(MCPWM_GEN0_A_DTEZ_S)) -#define MCPWM_GEN0_A_DTEZ_V 0x3 -#define MCPWM_GEN0_A_DTEZ_S 12 -/* MCPWM_GEN0_A_UT1 : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_A_UT1 0x00000003 -#define MCPWM_GEN0_A_UT1_M ((MCPWM_GEN0_A_UT1_V)<<(MCPWM_GEN0_A_UT1_S)) -#define MCPWM_GEN0_A_UT1_V 0x3 -#define MCPWM_GEN0_A_UT1_S 10 -/* MCPWM_GEN0_A_UT0 : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_A_UT0 0x00000003 -#define MCPWM_GEN0_A_UT0_M ((MCPWM_GEN0_A_UT0_V)<<(MCPWM_GEN0_A_UT0_S)) -#define MCPWM_GEN0_A_UT0_V 0x3 -#define MCPWM_GEN0_A_UT0_S 8 -/* MCPWM_GEN0_A_UTEB : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_A_UTEB 0x00000003 -#define MCPWM_GEN0_A_UTEB_M ((MCPWM_GEN0_A_UTEB_V)<<(MCPWM_GEN0_A_UTEB_S)) -#define MCPWM_GEN0_A_UTEB_V 0x3 -#define MCPWM_GEN0_A_UTEB_S 6 -/* MCPWM_GEN0_A_UTEA : R/W ;bitpos:[5:4] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_A_UTEA 0x00000003 -#define MCPWM_GEN0_A_UTEA_M ((MCPWM_GEN0_A_UTEA_V)<<(MCPWM_GEN0_A_UTEA_S)) -#define MCPWM_GEN0_A_UTEA_V 0x3 -#define MCPWM_GEN0_A_UTEA_S 4 -/* MCPWM_GEN0_A_UTEP : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_A_UTEP 0x00000003 -#define MCPWM_GEN0_A_UTEP_M ((MCPWM_GEN0_A_UTEP_V)<<(MCPWM_GEN0_A_UTEP_S)) -#define MCPWM_GEN0_A_UTEP_V 0x3 -#define MCPWM_GEN0_A_UTEP_S 2 -/* MCPWM_GEN0_A_UTEZ : R/W ;bitpos:[1:0] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_A_UTEZ 0x00000003 -#define MCPWM_GEN0_A_UTEZ_M ((MCPWM_GEN0_A_UTEZ_V)<<(MCPWM_GEN0_A_UTEZ_S)) -#define MCPWM_GEN0_A_UTEZ_V 0x3 +/** MCPWM_GEN0_A_REG register + * Actions triggered by events on PWM0A + */ +#define MCPWM_GEN0_A_REG(i) (DR_REG_MCPWM_BASE(i) + 0x50) +/** MCPWM_GEN0_A_UTEZ : R/W; bitpos: [1:0]; default: 0; + * Action on PWM0A triggered by event TEZ when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_UTEZ 0x00000003U +#define MCPWM_GEN0_A_UTEZ_M (MCPWM_GEN0_A_UTEZ_V << MCPWM_GEN0_A_UTEZ_S) +#define MCPWM_GEN0_A_UTEZ_V 0x00000003U #define MCPWM_GEN0_A_UTEZ_S 0 +/** MCPWM_GEN0_A_UTEP : R/W; bitpos: [3:2]; default: 0; + * Action on PWM0A triggered by event TEP when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_UTEP 0x00000003U +#define MCPWM_GEN0_A_UTEP_M (MCPWM_GEN0_A_UTEP_V << MCPWM_GEN0_A_UTEP_S) +#define MCPWM_GEN0_A_UTEP_V 0x00000003U +#define MCPWM_GEN0_A_UTEP_S 2 +/** MCPWM_GEN0_A_UTEA : R/W; bitpos: [5:4]; default: 0; + * Action on PWM0A triggered by event TEA when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_UTEA 0x00000003U +#define MCPWM_GEN0_A_UTEA_M (MCPWM_GEN0_A_UTEA_V << MCPWM_GEN0_A_UTEA_S) +#define MCPWM_GEN0_A_UTEA_V 0x00000003U +#define MCPWM_GEN0_A_UTEA_S 4 +/** MCPWM_GEN0_A_UTEB : R/W; bitpos: [7:6]; default: 0; + * Action on PWM0A triggered by event TEB when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_UTEB 0x00000003U +#define MCPWM_GEN0_A_UTEB_M (MCPWM_GEN0_A_UTEB_V << MCPWM_GEN0_A_UTEB_S) +#define MCPWM_GEN0_A_UTEB_V 0x00000003U +#define MCPWM_GEN0_A_UTEB_S 6 +/** MCPWM_GEN0_A_UT0 : R/W; bitpos: [9:8]; default: 0; + * Action on PWM0A triggered by event_t0 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_UT0 0x00000003U +#define MCPWM_GEN0_A_UT0_M (MCPWM_GEN0_A_UT0_V << MCPWM_GEN0_A_UT0_S) +#define MCPWM_GEN0_A_UT0_V 0x00000003U +#define MCPWM_GEN0_A_UT0_S 8 +/** MCPWM_GEN0_A_UT1 : R/W; bitpos: [11:10]; default: 0; + * Action on PWM0A triggered by event_t1 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_UT1 0x00000003U +#define MCPWM_GEN0_A_UT1_M (MCPWM_GEN0_A_UT1_V << MCPWM_GEN0_A_UT1_S) +#define MCPWM_GEN0_A_UT1_V 0x00000003U +#define MCPWM_GEN0_A_UT1_S 10 +/** MCPWM_GEN0_A_DTEZ : R/W; bitpos: [13:12]; default: 0; + * Action on PWM0A triggered by event TEZ when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_DTEZ 0x00000003U +#define MCPWM_GEN0_A_DTEZ_M (MCPWM_GEN0_A_DTEZ_V << MCPWM_GEN0_A_DTEZ_S) +#define MCPWM_GEN0_A_DTEZ_V 0x00000003U +#define MCPWM_GEN0_A_DTEZ_S 12 +/** MCPWM_GEN0_A_DTEP : R/W; bitpos: [15:14]; default: 0; + * Action on PWM0A triggered by event TEP when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_DTEP 0x00000003U +#define MCPWM_GEN0_A_DTEP_M (MCPWM_GEN0_A_DTEP_V << MCPWM_GEN0_A_DTEP_S) +#define MCPWM_GEN0_A_DTEP_V 0x00000003U +#define MCPWM_GEN0_A_DTEP_S 14 +/** MCPWM_GEN0_A_DTEA : R/W; bitpos: [17:16]; default: 0; + * Action on PWM0A triggered by event TEA when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_DTEA 0x00000003U +#define MCPWM_GEN0_A_DTEA_M (MCPWM_GEN0_A_DTEA_V << MCPWM_GEN0_A_DTEA_S) +#define MCPWM_GEN0_A_DTEA_V 0x00000003U +#define MCPWM_GEN0_A_DTEA_S 16 +/** MCPWM_GEN0_A_DTEB : R/W; bitpos: [19:18]; default: 0; + * Action on PWM0A triggered by event TEB when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_DTEB 0x00000003U +#define MCPWM_GEN0_A_DTEB_M (MCPWM_GEN0_A_DTEB_V << MCPWM_GEN0_A_DTEB_S) +#define MCPWM_GEN0_A_DTEB_V 0x00000003U +#define MCPWM_GEN0_A_DTEB_S 18 +/** MCPWM_GEN0_A_DT0 : R/W; bitpos: [21:20]; default: 0; + * Action on PWM0A triggered by event_t0 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_DT0 0x00000003U +#define MCPWM_GEN0_A_DT0_M (MCPWM_GEN0_A_DT0_V << MCPWM_GEN0_A_DT0_S) +#define MCPWM_GEN0_A_DT0_V 0x00000003U +#define MCPWM_GEN0_A_DT0_S 20 +/** MCPWM_GEN0_A_DT1 : R/W; bitpos: [23:22]; default: 0; + * Action on PWM0A triggered by event_t1 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_A_DT1 0x00000003U +#define MCPWM_GEN0_A_DT1_M (MCPWM_GEN0_A_DT1_V << MCPWM_GEN0_A_DT1_S) +#define MCPWM_GEN0_A_DT1_V 0x00000003U +#define MCPWM_GEN0_A_DT1_S 22 -#define MCPWM_GEN0_B_REG(i) (REG_MCPWM_BASE(i) + 0x54) -/* MCPWM_GEN0_B_DT1 : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_B_DT1 0x00000003 -#define MCPWM_GEN0_B_DT1_M ((MCPWM_GEN0_B_DT1_V)<<(MCPWM_GEN0_B_DT1_S)) -#define MCPWM_GEN0_B_DT1_V 0x3 -#define MCPWM_GEN0_B_DT1_S 22 -/* MCPWM_GEN0_B_DT0 : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_B_DT0 0x00000003 -#define MCPWM_GEN0_B_DT0_M ((MCPWM_GEN0_B_DT0_V)<<(MCPWM_GEN0_B_DT0_S)) -#define MCPWM_GEN0_B_DT0_V 0x3 -#define MCPWM_GEN0_B_DT0_S 20 -/* MCPWM_GEN0_B_DTEB : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_B_DTEB 0x00000003 -#define MCPWM_GEN0_B_DTEB_M ((MCPWM_GEN0_B_DTEB_V)<<(MCPWM_GEN0_B_DTEB_S)) -#define MCPWM_GEN0_B_DTEB_V 0x3 -#define MCPWM_GEN0_B_DTEB_S 18 -/* MCPWM_GEN0_B_DTEA : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_B_DTEA 0x00000003 -#define MCPWM_GEN0_B_DTEA_M ((MCPWM_GEN0_B_DTEA_V)<<(MCPWM_GEN0_B_DTEA_S)) -#define MCPWM_GEN0_B_DTEA_V 0x3 -#define MCPWM_GEN0_B_DTEA_S 16 -/* MCPWM_GEN0_B_DTEP : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_B_DTEP 0x00000003 -#define MCPWM_GEN0_B_DTEP_M ((MCPWM_GEN0_B_DTEP_V)<<(MCPWM_GEN0_B_DTEP_S)) -#define MCPWM_GEN0_B_DTEP_V 0x3 -#define MCPWM_GEN0_B_DTEP_S 14 -/* MCPWM_GEN0_B_DTEZ : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_B_DTEZ 0x00000003 -#define MCPWM_GEN0_B_DTEZ_M ((MCPWM_GEN0_B_DTEZ_V)<<(MCPWM_GEN0_B_DTEZ_S)) -#define MCPWM_GEN0_B_DTEZ_V 0x3 -#define MCPWM_GEN0_B_DTEZ_S 12 -/* MCPWM_GEN0_B_UT1 : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_B_UT1 0x00000003 -#define MCPWM_GEN0_B_UT1_M ((MCPWM_GEN0_B_UT1_V)<<(MCPWM_GEN0_B_UT1_S)) -#define MCPWM_GEN0_B_UT1_V 0x3 -#define MCPWM_GEN0_B_UT1_S 10 -/* MCPWM_GEN0_B_UT0 : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_B_UT0 0x00000003 -#define MCPWM_GEN0_B_UT0_M ((MCPWM_GEN0_B_UT0_V)<<(MCPWM_GEN0_B_UT0_S)) -#define MCPWM_GEN0_B_UT0_V 0x3 -#define MCPWM_GEN0_B_UT0_S 8 -/* MCPWM_GEN0_B_UTEB : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_B_UTEB 0x00000003 -#define MCPWM_GEN0_B_UTEB_M ((MCPWM_GEN0_B_UTEB_V)<<(MCPWM_GEN0_B_UTEB_S)) -#define MCPWM_GEN0_B_UTEB_V 0x3 -#define MCPWM_GEN0_B_UTEB_S 6 -/* MCPWM_GEN0_B_UTEA : R/W ;bitpos:[5:4] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_B_UTEA 0x00000003 -#define MCPWM_GEN0_B_UTEA_M ((MCPWM_GEN0_B_UTEA_V)<<(MCPWM_GEN0_B_UTEA_S)) -#define MCPWM_GEN0_B_UTEA_V 0x3 -#define MCPWM_GEN0_B_UTEA_S 4 -/* MCPWM_GEN0_B_UTEP : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_B_UTEP 0x00000003 -#define MCPWM_GEN0_B_UTEP_M ((MCPWM_GEN0_B_UTEP_V)<<(MCPWM_GEN0_B_UTEP_S)) -#define MCPWM_GEN0_B_UTEP_V 0x3 -#define MCPWM_GEN0_B_UTEP_S 2 -/* MCPWM_GEN0_B_UTEZ : R/W ;bitpos:[1:0] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN0_B_UTEZ 0x00000003 -#define MCPWM_GEN0_B_UTEZ_M ((MCPWM_GEN0_B_UTEZ_V)<<(MCPWM_GEN0_B_UTEZ_S)) -#define MCPWM_GEN0_B_UTEZ_V 0x3 +/** MCPWM_GEN0_B_REG register + * Actions triggered by events on PWM0B + */ +#define MCPWM_GEN0_B_REG(i) (DR_REG_MCPWM_BASE(i) + 0x54) +/** MCPWM_GEN0_B_UTEZ : R/W; bitpos: [1:0]; default: 0; + * Action on PWM0B triggered by event TEZ when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_UTEZ 0x00000003U +#define MCPWM_GEN0_B_UTEZ_M (MCPWM_GEN0_B_UTEZ_V << MCPWM_GEN0_B_UTEZ_S) +#define MCPWM_GEN0_B_UTEZ_V 0x00000003U #define MCPWM_GEN0_B_UTEZ_S 0 +/** MCPWM_GEN0_B_UTEP : R/W; bitpos: [3:2]; default: 0; + * Action on PWM0B triggered by event TEP when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_UTEP 0x00000003U +#define MCPWM_GEN0_B_UTEP_M (MCPWM_GEN0_B_UTEP_V << MCPWM_GEN0_B_UTEP_S) +#define MCPWM_GEN0_B_UTEP_V 0x00000003U +#define MCPWM_GEN0_B_UTEP_S 2 +/** MCPWM_GEN0_B_UTEA : R/W; bitpos: [5:4]; default: 0; + * Action on PWM0B triggered by event TEA when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_UTEA 0x00000003U +#define MCPWM_GEN0_B_UTEA_M (MCPWM_GEN0_B_UTEA_V << MCPWM_GEN0_B_UTEA_S) +#define MCPWM_GEN0_B_UTEA_V 0x00000003U +#define MCPWM_GEN0_B_UTEA_S 4 +/** MCPWM_GEN0_B_UTEB : R/W; bitpos: [7:6]; default: 0; + * Action on PWM0B triggered by event TEB when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_UTEB 0x00000003U +#define MCPWM_GEN0_B_UTEB_M (MCPWM_GEN0_B_UTEB_V << MCPWM_GEN0_B_UTEB_S) +#define MCPWM_GEN0_B_UTEB_V 0x00000003U +#define MCPWM_GEN0_B_UTEB_S 6 +/** MCPWM_GEN0_B_UT0 : R/W; bitpos: [9:8]; default: 0; + * Action on PWM0B triggered by event_t0 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_UT0 0x00000003U +#define MCPWM_GEN0_B_UT0_M (MCPWM_GEN0_B_UT0_V << MCPWM_GEN0_B_UT0_S) +#define MCPWM_GEN0_B_UT0_V 0x00000003U +#define MCPWM_GEN0_B_UT0_S 8 +/** MCPWM_GEN0_B_UT1 : R/W; bitpos: [11:10]; default: 0; + * Action on PWM0B triggered by event_t1 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_UT1 0x00000003U +#define MCPWM_GEN0_B_UT1_M (MCPWM_GEN0_B_UT1_V << MCPWM_GEN0_B_UT1_S) +#define MCPWM_GEN0_B_UT1_V 0x00000003U +#define MCPWM_GEN0_B_UT1_S 10 +/** MCPWM_GEN0_B_DTEZ : R/W; bitpos: [13:12]; default: 0; + * Action on PWM0B triggered by event TEZ when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_DTEZ 0x00000003U +#define MCPWM_GEN0_B_DTEZ_M (MCPWM_GEN0_B_DTEZ_V << MCPWM_GEN0_B_DTEZ_S) +#define MCPWM_GEN0_B_DTEZ_V 0x00000003U +#define MCPWM_GEN0_B_DTEZ_S 12 +/** MCPWM_GEN0_B_DTEP : R/W; bitpos: [15:14]; default: 0; + * Action on PWM0B triggered by event TEP when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_DTEP 0x00000003U +#define MCPWM_GEN0_B_DTEP_M (MCPWM_GEN0_B_DTEP_V << MCPWM_GEN0_B_DTEP_S) +#define MCPWM_GEN0_B_DTEP_V 0x00000003U +#define MCPWM_GEN0_B_DTEP_S 14 +/** MCPWM_GEN0_B_DTEA : R/W; bitpos: [17:16]; default: 0; + * Action on PWM0B triggered by event TEA when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_DTEA 0x00000003U +#define MCPWM_GEN0_B_DTEA_M (MCPWM_GEN0_B_DTEA_V << MCPWM_GEN0_B_DTEA_S) +#define MCPWM_GEN0_B_DTEA_V 0x00000003U +#define MCPWM_GEN0_B_DTEA_S 16 +/** MCPWM_GEN0_B_DTEB : R/W; bitpos: [19:18]; default: 0; + * Action on PWM0B triggered by event TEB when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_DTEB 0x00000003U +#define MCPWM_GEN0_B_DTEB_M (MCPWM_GEN0_B_DTEB_V << MCPWM_GEN0_B_DTEB_S) +#define MCPWM_GEN0_B_DTEB_V 0x00000003U +#define MCPWM_GEN0_B_DTEB_S 18 +/** MCPWM_GEN0_B_DT0 : R/W; bitpos: [21:20]; default: 0; + * Action on PWM0B triggered by event_t0 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_DT0 0x00000003U +#define MCPWM_GEN0_B_DT0_M (MCPWM_GEN0_B_DT0_V << MCPWM_GEN0_B_DT0_S) +#define MCPWM_GEN0_B_DT0_V 0x00000003U +#define MCPWM_GEN0_B_DT0_S 20 +/** MCPWM_GEN0_B_DT1 : R/W; bitpos: [23:22]; default: 0; + * Action on PWM0B triggered by event_t1 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN0_B_DT1 0x00000003U +#define MCPWM_GEN0_B_DT1_M (MCPWM_GEN0_B_DT1_V << MCPWM_GEN0_B_DT1_S) +#define MCPWM_GEN0_B_DT1_V 0x00000003U +#define MCPWM_GEN0_B_DT1_S 22 -#define MCPWM_DB0_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x58) -/* MCPWM_DB0_CLK_SEL : R/W ;bitpos:[17] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB0_CLK_SEL (BIT(17)) -#define MCPWM_DB0_CLK_SEL_M (BIT(17)) -#define MCPWM_DB0_CLK_SEL_V 0x1 -#define MCPWM_DB0_CLK_SEL_S 17 -/* MCPWM_DB0_B_OUTBYPASS : R/W ;bitpos:[16] ;default: 1'd1 ; */ -/*description: .*/ -#define MCPWM_DB0_B_OUTBYPASS (BIT(16)) -#define MCPWM_DB0_B_OUTBYPASS_M (BIT(16)) -#define MCPWM_DB0_B_OUTBYPASS_V 0x1 -#define MCPWM_DB0_B_OUTBYPASS_S 16 -/* MCPWM_DB0_A_OUTBYPASS : R/W ;bitpos:[15] ;default: 1'd1 ; */ -/*description: .*/ -#define MCPWM_DB0_A_OUTBYPASS (BIT(15)) -#define MCPWM_DB0_A_OUTBYPASS_M (BIT(15)) -#define MCPWM_DB0_A_OUTBYPASS_V 0x1 -#define MCPWM_DB0_A_OUTBYPASS_S 15 -/* MCPWM_DB0_FED_OUTINVERT : R/W ;bitpos:[14] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB0_FED_OUTINVERT (BIT(14)) -#define MCPWM_DB0_FED_OUTINVERT_M (BIT(14)) -#define MCPWM_DB0_FED_OUTINVERT_V 0x1 -#define MCPWM_DB0_FED_OUTINVERT_S 14 -/* MCPWM_DB0_RED_OUTINVERT : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB0_RED_OUTINVERT (BIT(13)) -#define MCPWM_DB0_RED_OUTINVERT_M (BIT(13)) -#define MCPWM_DB0_RED_OUTINVERT_V 0x1 -#define MCPWM_DB0_RED_OUTINVERT_S 13 -/* MCPWM_DB0_FED_INSEL : R/W ;bitpos:[12] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB0_FED_INSEL (BIT(12)) -#define MCPWM_DB0_FED_INSEL_M (BIT(12)) -#define MCPWM_DB0_FED_INSEL_V 0x1 -#define MCPWM_DB0_FED_INSEL_S 12 -/* MCPWM_DB0_RED_INSEL : R/W ;bitpos:[11] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB0_RED_INSEL (BIT(11)) -#define MCPWM_DB0_RED_INSEL_M (BIT(11)) -#define MCPWM_DB0_RED_INSEL_V 0x1 -#define MCPWM_DB0_RED_INSEL_S 11 -/* MCPWM_DB0_B_OUTSWAP : R/W ;bitpos:[10] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB0_B_OUTSWAP (BIT(10)) -#define MCPWM_DB0_B_OUTSWAP_M (BIT(10)) -#define MCPWM_DB0_B_OUTSWAP_V 0x1 -#define MCPWM_DB0_B_OUTSWAP_S 10 -/* MCPWM_DB0_A_OUTSWAP : R/W ;bitpos:[9] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB0_A_OUTSWAP (BIT(9)) -#define MCPWM_DB0_A_OUTSWAP_M (BIT(9)) -#define MCPWM_DB0_A_OUTSWAP_V 0x1 -#define MCPWM_DB0_A_OUTSWAP_S 9 -/* MCPWM_DB0_DEB_MODE : R/W ;bitpos:[8] ;default: 1'd0 ; */ -/*description: immediate, dual-edge B mode, 0: fed/red take effect on different path separately -, 1: fed/red take effect on B path, A out is in bypass or dulpB mode.*/ -#define MCPWM_DB0_DEB_MODE (BIT(8)) -#define MCPWM_DB0_DEB_MODE_M (BIT(8)) -#define MCPWM_DB0_DEB_MODE_V 0x1 -#define MCPWM_DB0_DEB_MODE_S 8 -/* MCPWM_DB0_RED_UPMETHOD : R/W ;bitpos:[7:4] ;default: 4'd0 ; */ -/*description: 0: immediate, bit0: tez, bit1: tep, bit2: sync, bit3: freeze.*/ -#define MCPWM_DB0_RED_UPMETHOD 0x0000000F -#define MCPWM_DB0_RED_UPMETHOD_M ((MCPWM_DB0_RED_UPMETHOD_V)<<(MCPWM_DB0_RED_UPMETHOD_S)) -#define MCPWM_DB0_RED_UPMETHOD_V 0xF -#define MCPWM_DB0_RED_UPMETHOD_S 4 -/* MCPWM_DB0_FED_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: 0: immediate, bit0: tez, bit1: tep, bit2: sync, bit3: freeze.*/ -#define MCPWM_DB0_FED_UPMETHOD 0x0000000F -#define MCPWM_DB0_FED_UPMETHOD_M ((MCPWM_DB0_FED_UPMETHOD_V)<<(MCPWM_DB0_FED_UPMETHOD_S)) -#define MCPWM_DB0_FED_UPMETHOD_V 0xF -#define MCPWM_DB0_FED_UPMETHOD_S 0 +/** MCPWM_DT0_CFG_REG register + * PWM generator 0 dead time type selection and configuration + */ +#define MCPWM_DT0_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x58) +/** MCPWM_DT0_FED_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for FED (rising edge delay) active register. 0: immediate, when bit0 + * is set to 1: tez, when bit1 is set to 1:tep, when bit2 is set to 1: sync, when + * bit3 is set to 1: disable the update + */ +#define MCPWM_DT0_FED_UPMETHOD 0x0000000FU +#define MCPWM_DT0_FED_UPMETHOD_M (MCPWM_DT0_FED_UPMETHOD_V << MCPWM_DT0_FED_UPMETHOD_S) +#define MCPWM_DT0_FED_UPMETHOD_V 0x0000000FU +#define MCPWM_DT0_FED_UPMETHOD_S 0 +/** MCPWM_DT0_RED_UPMETHOD : R/W; bitpos: [7:4]; default: 0; + * Update method for RED (rising edge delay) active register. 0: immediate, when bit0 + * is set to 1: tez, when bit1 is set to 1:tep, when bit2 is set to 1: sync, when + * bit3 is set to 1: disable the update + */ +#define MCPWM_DT0_RED_UPMETHOD 0x0000000FU +#define MCPWM_DT0_RED_UPMETHOD_M (MCPWM_DT0_RED_UPMETHOD_V << MCPWM_DT0_RED_UPMETHOD_S) +#define MCPWM_DT0_RED_UPMETHOD_V 0x0000000FU +#define MCPWM_DT0_RED_UPMETHOD_S 4 +/** MCPWM_DT0_DEB_MODE : R/W; bitpos: [8]; default: 0; + * S8 in table, dual-edge B mode, 0: fed/red take effect on different path separately, + * 1: fed/red take effect on B path, A out is in bypass or dulpB mode + */ +#define MCPWM_DT0_DEB_MODE (BIT(8)) +#define MCPWM_DT0_DEB_MODE_M (MCPWM_DT0_DEB_MODE_V << MCPWM_DT0_DEB_MODE_S) +#define MCPWM_DT0_DEB_MODE_V 0x00000001U +#define MCPWM_DT0_DEB_MODE_S 8 +/** MCPWM_DT0_A_OUTSWAP : R/W; bitpos: [9]; default: 0; + * S6 in table + */ +#define MCPWM_DT0_A_OUTSWAP (BIT(9)) +#define MCPWM_DT0_A_OUTSWAP_M (MCPWM_DT0_A_OUTSWAP_V << MCPWM_DT0_A_OUTSWAP_S) +#define MCPWM_DT0_A_OUTSWAP_V 0x00000001U +#define MCPWM_DT0_A_OUTSWAP_S 9 +/** MCPWM_DT0_B_OUTSWAP : R/W; bitpos: [10]; default: 0; + * S7 in table + */ +#define MCPWM_DT0_B_OUTSWAP (BIT(10)) +#define MCPWM_DT0_B_OUTSWAP_M (MCPWM_DT0_B_OUTSWAP_V << MCPWM_DT0_B_OUTSWAP_S) +#define MCPWM_DT0_B_OUTSWAP_V 0x00000001U +#define MCPWM_DT0_B_OUTSWAP_S 10 +/** MCPWM_DT0_RED_INSEL : R/W; bitpos: [11]; default: 0; + * S4 in table + */ +#define MCPWM_DT0_RED_INSEL (BIT(11)) +#define MCPWM_DT0_RED_INSEL_M (MCPWM_DT0_RED_INSEL_V << MCPWM_DT0_RED_INSEL_S) +#define MCPWM_DT0_RED_INSEL_V 0x00000001U +#define MCPWM_DT0_RED_INSEL_S 11 +/** MCPWM_DT0_FED_INSEL : R/W; bitpos: [12]; default: 0; + * S5 in table + */ +#define MCPWM_DT0_FED_INSEL (BIT(12)) +#define MCPWM_DT0_FED_INSEL_M (MCPWM_DT0_FED_INSEL_V << MCPWM_DT0_FED_INSEL_S) +#define MCPWM_DT0_FED_INSEL_V 0x00000001U +#define MCPWM_DT0_FED_INSEL_S 12 +/** MCPWM_DT0_RED_OUTINVERT : R/W; bitpos: [13]; default: 0; + * S2 in table + */ +#define MCPWM_DT0_RED_OUTINVERT (BIT(13)) +#define MCPWM_DT0_RED_OUTINVERT_M (MCPWM_DT0_RED_OUTINVERT_V << MCPWM_DT0_RED_OUTINVERT_S) +#define MCPWM_DT0_RED_OUTINVERT_V 0x00000001U +#define MCPWM_DT0_RED_OUTINVERT_S 13 +/** MCPWM_DT0_FED_OUTINVERT : R/W; bitpos: [14]; default: 0; + * S3 in table + */ +#define MCPWM_DT0_FED_OUTINVERT (BIT(14)) +#define MCPWM_DT0_FED_OUTINVERT_M (MCPWM_DT0_FED_OUTINVERT_V << MCPWM_DT0_FED_OUTINVERT_S) +#define MCPWM_DT0_FED_OUTINVERT_V 0x00000001U +#define MCPWM_DT0_FED_OUTINVERT_S 14 +/** MCPWM_DT0_A_OUTBYPASS : R/W; bitpos: [15]; default: 1; + * S1 in table + */ +#define MCPWM_DT0_A_OUTBYPASS (BIT(15)) +#define MCPWM_DT0_A_OUTBYPASS_M (MCPWM_DT0_A_OUTBYPASS_V << MCPWM_DT0_A_OUTBYPASS_S) +#define MCPWM_DT0_A_OUTBYPASS_V 0x00000001U +#define MCPWM_DT0_A_OUTBYPASS_S 15 +/** MCPWM_DT0_B_OUTBYPASS : R/W; bitpos: [16]; default: 1; + * S0 in table + */ +#define MCPWM_DT0_B_OUTBYPASS (BIT(16)) +#define MCPWM_DT0_B_OUTBYPASS_M (MCPWM_DT0_B_OUTBYPASS_V << MCPWM_DT0_B_OUTBYPASS_S) +#define MCPWM_DT0_B_OUTBYPASS_V 0x00000001U +#define MCPWM_DT0_B_OUTBYPASS_S 16 +/** MCPWM_DT0_CLK_SEL : R/W; bitpos: [17]; default: 0; + * Dead time clock selection. 0: PWM_clk, 1: PT_clk + */ +#define MCPWM_DT0_CLK_SEL (BIT(17)) +#define MCPWM_DT0_CLK_SEL_M (MCPWM_DT0_CLK_SEL_V << MCPWM_DT0_CLK_SEL_S) +#define MCPWM_DT0_CLK_SEL_V 0x00000001U +#define MCPWM_DT0_CLK_SEL_S 17 -#define MCPWM_DB0_FED_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x5C) -/* MCPWM_DB0_FED : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: .*/ -#define MCPWM_DB0_FED 0x0000FFFF -#define MCPWM_DB0_FED_M ((MCPWM_DB0_FED_V)<<(MCPWM_DB0_FED_S)) -#define MCPWM_DB0_FED_V 0xFFFF -#define MCPWM_DB0_FED_S 0 +/** MCPWM_DT0_FED_CFG_REG register + * PWM generator 0 shadow register for falling edge delay (FED). + */ +#define MCPWM_DT0_FED_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x5c) +/** MCPWM_DT0_FED : R/W; bitpos: [15:0]; default: 0; + * Shadow register for FED + */ +#define MCPWM_DT0_FED 0x0000FFFFU +#define MCPWM_DT0_FED_M (MCPWM_DT0_FED_V << MCPWM_DT0_FED_S) +#define MCPWM_DT0_FED_V 0x0000FFFFU +#define MCPWM_DT0_FED_S 0 -#define MCPWM_DB0_RED_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x60) -/* MCPWM_DB0_RED : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: .*/ -#define MCPWM_DB0_RED 0x0000FFFF -#define MCPWM_DB0_RED_M ((MCPWM_DB0_RED_V)<<(MCPWM_DB0_RED_S)) -#define MCPWM_DB0_RED_V 0xFFFF -#define MCPWM_DB0_RED_S 0 +/** MCPWM_DT0_RED_CFG_REG register + * PWM generator 0 shadow register for rising edge delay (RED). + */ +#define MCPWM_DT0_RED_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x60) +/** MCPWM_DT0_RED : R/W; bitpos: [15:0]; default: 0; + * Shadow register for RED + */ +#define MCPWM_DT0_RED 0x0000FFFFU +#define MCPWM_DT0_RED_M (MCPWM_DT0_RED_V << MCPWM_DT0_RED_S) +#define MCPWM_DT0_RED_V 0x0000FFFFU +#define MCPWM_DT0_RED_S 0 -#define MCPWM_CHOPPER0_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x64) -/* MCPWM_CHOPPER0_IN_INVERT : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER0_IN_INVERT (BIT(13)) -#define MCPWM_CHOPPER0_IN_INVERT_M (BIT(13)) -#define MCPWM_CHOPPER0_IN_INVERT_V 0x1 -#define MCPWM_CHOPPER0_IN_INVERT_S 13 -/* MCPWM_CHOPPER0_OUT_INVERT : R/W ;bitpos:[12] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER0_OUT_INVERT (BIT(12)) -#define MCPWM_CHOPPER0_OUT_INVERT_M (BIT(12)) -#define MCPWM_CHOPPER0_OUT_INVERT_V 0x1 -#define MCPWM_CHOPPER0_OUT_INVERT_S 12 -/* MCPWM_CHOPPER0_OSHTWTH : R/W ;bitpos:[11:8] ;default: 4'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER0_OSHTWTH 0x0000000F -#define MCPWM_CHOPPER0_OSHTWTH_M ((MCPWM_CHOPPER0_OSHTWTH_V)<<(MCPWM_CHOPPER0_OSHTWTH_S)) -#define MCPWM_CHOPPER0_OSHTWTH_V 0xF -#define MCPWM_CHOPPER0_OSHTWTH_S 8 -/* MCPWM_CHOPPER0_DUTY : R/W ;bitpos:[7:5] ;default: 3'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER0_DUTY 0x00000007 -#define MCPWM_CHOPPER0_DUTY_M ((MCPWM_CHOPPER0_DUTY_V)<<(MCPWM_CHOPPER0_DUTY_S)) -#define MCPWM_CHOPPER0_DUTY_V 0x7 -#define MCPWM_CHOPPER0_DUTY_S 5 -/* MCPWM_CHOPPER0_PRESCALE : R/W ;bitpos:[4:1] ;default: 4'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER0_PRESCALE 0x0000000F -#define MCPWM_CHOPPER0_PRESCALE_M ((MCPWM_CHOPPER0_PRESCALE_V)<<(MCPWM_CHOPPER0_PRESCALE_S)) -#define MCPWM_CHOPPER0_PRESCALE_V 0xF -#define MCPWM_CHOPPER0_PRESCALE_S 1 -/* MCPWM_CHOPPER0_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER0_EN (BIT(0)) -#define MCPWM_CHOPPER0_EN_M (BIT(0)) -#define MCPWM_CHOPPER0_EN_V 0x1 -#define MCPWM_CHOPPER0_EN_S 0 +/** MCPWM_CARRIER0_CFG_REG register + * PWM generator 0 carrier enable and configuratoin + */ +#define MCPWM_CARRIER0_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x64) +/** MCPWM_CARRIER0_EN : R/W; bitpos: [0]; default: 0; + * When set, carrier0 function is enabled. When cleared, carrier0 is bypassed + */ +#define MCPWM_CARRIER0_EN (BIT(0)) +#define MCPWM_CARRIER0_EN_M (MCPWM_CARRIER0_EN_V << MCPWM_CARRIER0_EN_S) +#define MCPWM_CARRIER0_EN_V 0x00000001U +#define MCPWM_CARRIER0_EN_S 0 +/** MCPWM_CARRIER0_PRESCALE : R/W; bitpos: [4:1]; default: 0; + * PWM carrier0 clock (PC_clk) prescale value. Period of PC_clk = period of PWM_clk * + * (PWM_CARRIER0_PRESCALE + 1) + */ +#define MCPWM_CARRIER0_PRESCALE 0x0000000FU +#define MCPWM_CARRIER0_PRESCALE_M (MCPWM_CARRIER0_PRESCALE_V << MCPWM_CARRIER0_PRESCALE_S) +#define MCPWM_CARRIER0_PRESCALE_V 0x0000000FU +#define MCPWM_CARRIER0_PRESCALE_S 1 +/** MCPWM_CARRIER0_DUTY : R/W; bitpos: [7:5]; default: 0; + * carrier duty selection. Duty = PWM_CARRIER0_DUTY / 8 + */ +#define MCPWM_CARRIER0_DUTY 0x00000007U +#define MCPWM_CARRIER0_DUTY_M (MCPWM_CARRIER0_DUTY_V << MCPWM_CARRIER0_DUTY_S) +#define MCPWM_CARRIER0_DUTY_V 0x00000007U +#define MCPWM_CARRIER0_DUTY_S 5 +/** MCPWM_CARRIER0_OSHTWTH : R/W; bitpos: [11:8]; default: 0; + * width of the first pulse in number of periods of the carrier + */ +#define MCPWM_CARRIER0_OSHTWTH 0x0000000FU +#define MCPWM_CARRIER0_OSHTWTH_M (MCPWM_CARRIER0_OSHTWTH_V << MCPWM_CARRIER0_OSHTWTH_S) +#define MCPWM_CARRIER0_OSHTWTH_V 0x0000000FU +#define MCPWM_CARRIER0_OSHTWTH_S 8 +/** MCPWM_CARRIER0_OUT_INVERT : R/W; bitpos: [12]; default: 0; + * when set, invert the output of PWM0A and PWM0B for this submodule + */ +#define MCPWM_CARRIER0_OUT_INVERT (BIT(12)) +#define MCPWM_CARRIER0_OUT_INVERT_M (MCPWM_CARRIER0_OUT_INVERT_V << MCPWM_CARRIER0_OUT_INVERT_S) +#define MCPWM_CARRIER0_OUT_INVERT_V 0x00000001U +#define MCPWM_CARRIER0_OUT_INVERT_S 12 +/** MCPWM_CARRIER0_IN_INVERT : R/W; bitpos: [13]; default: 0; + * when set, invert the input of PWM0A and PWM0B for this submodule + */ +#define MCPWM_CARRIER0_IN_INVERT (BIT(13)) +#define MCPWM_CARRIER0_IN_INVERT_M (MCPWM_CARRIER0_IN_INVERT_V << MCPWM_CARRIER0_IN_INVERT_S) +#define MCPWM_CARRIER0_IN_INVERT_V 0x00000001U +#define MCPWM_CARRIER0_IN_INVERT_S 13 -#define MCPWM_TZ0_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0x68) -/* MCPWM_TZ0_B_OST_U : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ0_B_OST_U 0x00000003 -#define MCPWM_TZ0_B_OST_U_M ((MCPWM_TZ0_B_OST_U_V)<<(MCPWM_TZ0_B_OST_U_S)) -#define MCPWM_TZ0_B_OST_U_V 0x3 -#define MCPWM_TZ0_B_OST_U_S 22 -/* MCPWM_TZ0_B_OST_D : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ0_B_OST_D 0x00000003 -#define MCPWM_TZ0_B_OST_D_M ((MCPWM_TZ0_B_OST_D_V)<<(MCPWM_TZ0_B_OST_D_S)) -#define MCPWM_TZ0_B_OST_D_V 0x3 -#define MCPWM_TZ0_B_OST_D_S 20 -/* MCPWM_TZ0_B_CBC_U : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ0_B_CBC_U 0x00000003 -#define MCPWM_TZ0_B_CBC_U_M ((MCPWM_TZ0_B_CBC_U_V)<<(MCPWM_TZ0_B_CBC_U_S)) -#define MCPWM_TZ0_B_CBC_U_V 0x3 -#define MCPWM_TZ0_B_CBC_U_S 18 -/* MCPWM_TZ0_B_CBC_D : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ0_B_CBC_D 0x00000003 -#define MCPWM_TZ0_B_CBC_D_M ((MCPWM_TZ0_B_CBC_D_V)<<(MCPWM_TZ0_B_CBC_D_S)) -#define MCPWM_TZ0_B_CBC_D_V 0x3 -#define MCPWM_TZ0_B_CBC_D_S 16 -/* MCPWM_TZ0_A_OST_U : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ0_A_OST_U 0x00000003 -#define MCPWM_TZ0_A_OST_U_M ((MCPWM_TZ0_A_OST_U_V)<<(MCPWM_TZ0_A_OST_U_S)) -#define MCPWM_TZ0_A_OST_U_V 0x3 -#define MCPWM_TZ0_A_OST_U_S 14 -/* MCPWM_TZ0_A_OST_D : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ0_A_OST_D 0x00000003 -#define MCPWM_TZ0_A_OST_D_M ((MCPWM_TZ0_A_OST_D_V)<<(MCPWM_TZ0_A_OST_D_S)) -#define MCPWM_TZ0_A_OST_D_V 0x3 -#define MCPWM_TZ0_A_OST_D_S 12 -/* MCPWM_TZ0_A_CBC_U : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ0_A_CBC_U 0x00000003 -#define MCPWM_TZ0_A_CBC_U_M ((MCPWM_TZ0_A_CBC_U_V)<<(MCPWM_TZ0_A_CBC_U_S)) -#define MCPWM_TZ0_A_CBC_U_V 0x3 -#define MCPWM_TZ0_A_CBC_U_S 10 -/* MCPWM_TZ0_A_CBC_D : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ0_A_CBC_D 0x00000003 -#define MCPWM_TZ0_A_CBC_D_M ((MCPWM_TZ0_A_CBC_D_V)<<(MCPWM_TZ0_A_CBC_D_S)) -#define MCPWM_TZ0_A_CBC_D_V 0x3 -#define MCPWM_TZ0_A_CBC_D_S 8 -/* MCPWM_TZ0_F0_OST : R/W ;bitpos:[7] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ0_F0_OST (BIT(7)) -#define MCPWM_TZ0_F0_OST_M (BIT(7)) -#define MCPWM_TZ0_F0_OST_V 0x1 -#define MCPWM_TZ0_F0_OST_S 7 -/* MCPWM_TZ0_F1_OST : R/W ;bitpos:[6] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ0_F1_OST (BIT(6)) -#define MCPWM_TZ0_F1_OST_M (BIT(6)) -#define MCPWM_TZ0_F1_OST_V 0x1 -#define MCPWM_TZ0_F1_OST_S 6 -/* MCPWM_TZ0_F2_OST : R/W ;bitpos:[5] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ0_F2_OST (BIT(5)) -#define MCPWM_TZ0_F2_OST_M (BIT(5)) -#define MCPWM_TZ0_F2_OST_V 0x1 -#define MCPWM_TZ0_F2_OST_S 5 -/* MCPWM_TZ0_SW_OST : R/W ;bitpos:[4] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ0_SW_OST (BIT(4)) -#define MCPWM_TZ0_SW_OST_M (BIT(4)) -#define MCPWM_TZ0_SW_OST_V 0x1 -#define MCPWM_TZ0_SW_OST_S 4 -/* MCPWM_TZ0_F0_CBC : R/W ;bitpos:[3] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ0_F0_CBC (BIT(3)) -#define MCPWM_TZ0_F0_CBC_M (BIT(3)) -#define MCPWM_TZ0_F0_CBC_V 0x1 -#define MCPWM_TZ0_F0_CBC_S 3 -/* MCPWM_TZ0_F1_CBC : R/W ;bitpos:[2] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ0_F1_CBC (BIT(2)) -#define MCPWM_TZ0_F1_CBC_M (BIT(2)) -#define MCPWM_TZ0_F1_CBC_V 0x1 -#define MCPWM_TZ0_F1_CBC_S 2 -/* MCPWM_TZ0_F2_CBC : R/W ;bitpos:[1] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ0_F2_CBC (BIT(1)) -#define MCPWM_TZ0_F2_CBC_M (BIT(1)) -#define MCPWM_TZ0_F2_CBC_V 0x1 -#define MCPWM_TZ0_F2_CBC_S 1 -/* MCPWM_TZ0_SW_CBC : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ0_SW_CBC (BIT(0)) -#define MCPWM_TZ0_SW_CBC_M (BIT(0)) -#define MCPWM_TZ0_SW_CBC_V 0x1 -#define MCPWM_TZ0_SW_CBC_S 0 +/** MCPWM_FH0_CFG0_REG register + * Actions on PWM0A and PWM0B trip events + */ +#define MCPWM_FH0_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0x68) +/** MCPWM_FH0_SW_CBC : R/W; bitpos: [0]; default: 0; + * Enable register for software force cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH0_SW_CBC (BIT(0)) +#define MCPWM_FH0_SW_CBC_M (MCPWM_FH0_SW_CBC_V << MCPWM_FH0_SW_CBC_S) +#define MCPWM_FH0_SW_CBC_V 0x00000001U +#define MCPWM_FH0_SW_CBC_S 0 +/** MCPWM_FH0_F2_CBC : R/W; bitpos: [1]; default: 0; + * fault_event2 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH0_F2_CBC (BIT(1)) +#define MCPWM_FH0_F2_CBC_M (MCPWM_FH0_F2_CBC_V << MCPWM_FH0_F2_CBC_S) +#define MCPWM_FH0_F2_CBC_V 0x00000001U +#define MCPWM_FH0_F2_CBC_S 1 +/** MCPWM_FH0_F1_CBC : R/W; bitpos: [2]; default: 0; + * fault_event1 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH0_F1_CBC (BIT(2)) +#define MCPWM_FH0_F1_CBC_M (MCPWM_FH0_F1_CBC_V << MCPWM_FH0_F1_CBC_S) +#define MCPWM_FH0_F1_CBC_V 0x00000001U +#define MCPWM_FH0_F1_CBC_S 2 +/** MCPWM_FH0_F0_CBC : R/W; bitpos: [3]; default: 0; + * fault_event0 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH0_F0_CBC (BIT(3)) +#define MCPWM_FH0_F0_CBC_M (MCPWM_FH0_F0_CBC_V << MCPWM_FH0_F0_CBC_S) +#define MCPWM_FH0_F0_CBC_V 0x00000001U +#define MCPWM_FH0_F0_CBC_S 3 +/** MCPWM_FH0_SW_OST : R/W; bitpos: [4]; default: 0; + * Enable register for software force one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH0_SW_OST (BIT(4)) +#define MCPWM_FH0_SW_OST_M (MCPWM_FH0_SW_OST_V << MCPWM_FH0_SW_OST_S) +#define MCPWM_FH0_SW_OST_V 0x00000001U +#define MCPWM_FH0_SW_OST_S 4 +/** MCPWM_FH0_F2_OST : R/W; bitpos: [5]; default: 0; + * fault_event2 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH0_F2_OST (BIT(5)) +#define MCPWM_FH0_F2_OST_M (MCPWM_FH0_F2_OST_V << MCPWM_FH0_F2_OST_S) +#define MCPWM_FH0_F2_OST_V 0x00000001U +#define MCPWM_FH0_F2_OST_S 5 +/** MCPWM_FH0_F1_OST : R/W; bitpos: [6]; default: 0; + * fault_event1 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH0_F1_OST (BIT(6)) +#define MCPWM_FH0_F1_OST_M (MCPWM_FH0_F1_OST_V << MCPWM_FH0_F1_OST_S) +#define MCPWM_FH0_F1_OST_V 0x00000001U +#define MCPWM_FH0_F1_OST_S 6 +/** MCPWM_FH0_F0_OST : R/W; bitpos: [7]; default: 0; + * fault_event0 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH0_F0_OST (BIT(7)) +#define MCPWM_FH0_F0_OST_M (MCPWM_FH0_F0_OST_V << MCPWM_FH0_F0_OST_S) +#define MCPWM_FH0_F0_OST_V 0x00000001U +#define MCPWM_FH0_F0_OST_S 7 +/** MCPWM_FH0_A_CBC_D : R/W; bitpos: [9:8]; default: 0; + * Cycle-by-cycle mode action on PWM0A when fault event occurs and timer is + * decreasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH0_A_CBC_D 0x00000003U +#define MCPWM_FH0_A_CBC_D_M (MCPWM_FH0_A_CBC_D_V << MCPWM_FH0_A_CBC_D_S) +#define MCPWM_FH0_A_CBC_D_V 0x00000003U +#define MCPWM_FH0_A_CBC_D_S 8 +/** MCPWM_FH0_A_CBC_U : R/W; bitpos: [11:10]; default: 0; + * Cycle-by-cycle mode action on PWM0A when fault event occurs and timer is + * increasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH0_A_CBC_U 0x00000003U +#define MCPWM_FH0_A_CBC_U_M (MCPWM_FH0_A_CBC_U_V << MCPWM_FH0_A_CBC_U_S) +#define MCPWM_FH0_A_CBC_U_V 0x00000003U +#define MCPWM_FH0_A_CBC_U_S 10 +/** MCPWM_FH0_A_OST_D : R/W; bitpos: [13:12]; default: 0; + * One-shot mode action on PWM0A when fault event occurs and timer is decreasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH0_A_OST_D 0x00000003U +#define MCPWM_FH0_A_OST_D_M (MCPWM_FH0_A_OST_D_V << MCPWM_FH0_A_OST_D_S) +#define MCPWM_FH0_A_OST_D_V 0x00000003U +#define MCPWM_FH0_A_OST_D_S 12 +/** MCPWM_FH0_A_OST_U : R/W; bitpos: [15:14]; default: 0; + * One-shot mode action on PWM0A when fault event occurs and timer is increasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH0_A_OST_U 0x00000003U +#define MCPWM_FH0_A_OST_U_M (MCPWM_FH0_A_OST_U_V << MCPWM_FH0_A_OST_U_S) +#define MCPWM_FH0_A_OST_U_V 0x00000003U +#define MCPWM_FH0_A_OST_U_S 14 +/** MCPWM_FH0_B_CBC_D : R/W; bitpos: [17:16]; default: 0; + * Cycle-by-cycle mode action on PWM0B when fault event occurs and timer is + * decreasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH0_B_CBC_D 0x00000003U +#define MCPWM_FH0_B_CBC_D_M (MCPWM_FH0_B_CBC_D_V << MCPWM_FH0_B_CBC_D_S) +#define MCPWM_FH0_B_CBC_D_V 0x00000003U +#define MCPWM_FH0_B_CBC_D_S 16 +/** MCPWM_FH0_B_CBC_U : R/W; bitpos: [19:18]; default: 0; + * Cycle-by-cycle mode action on PWM0B when fault event occurs and timer is + * increasing. 0: do nothing,1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH0_B_CBC_U 0x00000003U +#define MCPWM_FH0_B_CBC_U_M (MCPWM_FH0_B_CBC_U_V << MCPWM_FH0_B_CBC_U_S) +#define MCPWM_FH0_B_CBC_U_V 0x00000003U +#define MCPWM_FH0_B_CBC_U_S 18 +/** MCPWM_FH0_B_OST_D : R/W; bitpos: [21:20]; default: 0; + * One-shot mode action on PWM0B when fault event occurs and timer is decreasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH0_B_OST_D 0x00000003U +#define MCPWM_FH0_B_OST_D_M (MCPWM_FH0_B_OST_D_V << MCPWM_FH0_B_OST_D_S) +#define MCPWM_FH0_B_OST_D_V 0x00000003U +#define MCPWM_FH0_B_OST_D_S 20 +/** MCPWM_FH0_B_OST_U : R/W; bitpos: [23:22]; default: 0; + * One-shot mode action on PWM0B when fault event occurs and timer is increasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH0_B_OST_U 0x00000003U +#define MCPWM_FH0_B_OST_U_M (MCPWM_FH0_B_OST_U_V << MCPWM_FH0_B_OST_U_S) +#define MCPWM_FH0_B_OST_U_V 0x00000003U +#define MCPWM_FH0_B_OST_U_S 22 -#define MCPWM_TZ0_CFG1_REG(i) (REG_MCPWM_BASE(i) + 0x6C) -/* MCPWM_TZ0_FORCE_OST : R/W ;bitpos:[4] ;default: 1'd0 ; */ -/*description: a toggle trigger a oneshot tripping.*/ -#define MCPWM_TZ0_FORCE_OST (BIT(4)) -#define MCPWM_TZ0_FORCE_OST_M (BIT(4)) -#define MCPWM_TZ0_FORCE_OST_V 0x1 -#define MCPWM_TZ0_FORCE_OST_S 4 -/* MCPWM_TZ0_FORCE_CBC : R/W ;bitpos:[3] ;default: 1'd0 ; */ -/*description: a toggle trigger a cycle-by-cycle tripping.*/ -#define MCPWM_TZ0_FORCE_CBC (BIT(3)) -#define MCPWM_TZ0_FORCE_CBC_M (BIT(3)) -#define MCPWM_TZ0_FORCE_CBC_V 0x1 -#define MCPWM_TZ0_FORCE_CBC_S 3 -/* MCPWM_TZ0_CBCPULSE : R/W ;bitpos:[2:1] ;default: 2'd0 ; */ -/*description: bit0: tez, bit1: tep.*/ -#define MCPWM_TZ0_CBCPULSE 0x00000003 -#define MCPWM_TZ0_CBCPULSE_M ((MCPWM_TZ0_CBCPULSE_V)<<(MCPWM_TZ0_CBCPULSE_S)) -#define MCPWM_TZ0_CBCPULSE_V 0x3 -#define MCPWM_TZ0_CBCPULSE_S 1 -/* MCPWM_TZ0_CLR_OST : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: a toggle will clear oneshot tripping.*/ -#define MCPWM_TZ0_CLR_OST (BIT(0)) -#define MCPWM_TZ0_CLR_OST_M (BIT(0)) -#define MCPWM_TZ0_CLR_OST_V 0x1 -#define MCPWM_TZ0_CLR_OST_S 0 +/** MCPWM_FH0_CFG1_REG register + * Software triggers for fault handler actions + */ +#define MCPWM_FH0_CFG1_REG(i) (DR_REG_MCPWM_BASE(i) + 0x6c) +/** MCPWM_FH0_CLR_OST : R/W; bitpos: [0]; default: 0; + * a rising edge will clear on going one-shot mode action + */ +#define MCPWM_FH0_CLR_OST (BIT(0)) +#define MCPWM_FH0_CLR_OST_M (MCPWM_FH0_CLR_OST_V << MCPWM_FH0_CLR_OST_S) +#define MCPWM_FH0_CLR_OST_V 0x00000001U +#define MCPWM_FH0_CLR_OST_S 0 +/** MCPWM_FH0_CBCPULSE : R/W; bitpos: [2:1]; default: 0; + * cycle-by-cycle mode action refresh moment selection. When bit0 is set to 1: TEZ, + * when bit1 is set to 1:TEP, when bit0 and bit1 both set to 0: stop refresh, when + * bit0 and bit1 both set to 1: refresh at TEP/TEZ + */ +#define MCPWM_FH0_CBCPULSE 0x00000003U +#define MCPWM_FH0_CBCPULSE_M (MCPWM_FH0_CBCPULSE_V << MCPWM_FH0_CBCPULSE_S) +#define MCPWM_FH0_CBCPULSE_V 0x00000003U +#define MCPWM_FH0_CBCPULSE_S 1 +/** MCPWM_FH0_FORCE_CBC : R/W; bitpos: [3]; default: 0; + * a toggle trigger a cycle-by-cycle mode action + */ +#define MCPWM_FH0_FORCE_CBC (BIT(3)) +#define MCPWM_FH0_FORCE_CBC_M (MCPWM_FH0_FORCE_CBC_V << MCPWM_FH0_FORCE_CBC_S) +#define MCPWM_FH0_FORCE_CBC_V 0x00000001U +#define MCPWM_FH0_FORCE_CBC_S 3 +/** MCPWM_FH0_FORCE_OST : R/W; bitpos: [4]; default: 0; + * a toggle (software negate its value) triggers a one-shot mode action + */ +#define MCPWM_FH0_FORCE_OST (BIT(4)) +#define MCPWM_FH0_FORCE_OST_M (MCPWM_FH0_FORCE_OST_V << MCPWM_FH0_FORCE_OST_S) +#define MCPWM_FH0_FORCE_OST_V 0x00000001U +#define MCPWM_FH0_FORCE_OST_S 4 -#define MCPWM_TZ0_STATUS_REG(i) (REG_MCPWM_BASE(i) + 0x70) -/* MCPWM_TZ0_OST_ON : RO ;bitpos:[1] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ0_OST_ON (BIT(1)) -#define MCPWM_TZ0_OST_ON_M (BIT(1)) -#define MCPWM_TZ0_OST_ON_V 0x1 -#define MCPWM_TZ0_OST_ON_S 1 -/* MCPWM_TZ0_CBC_ON : RO ;bitpos:[0] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ0_CBC_ON (BIT(0)) -#define MCPWM_TZ0_CBC_ON_M (BIT(0)) -#define MCPWM_TZ0_CBC_ON_V 0x1 -#define MCPWM_TZ0_CBC_ON_S 0 +/** MCPWM_FH0_STATUS_REG register + * Status of fault events. + */ +#define MCPWM_FH0_STATUS_REG(i) (DR_REG_MCPWM_BASE(i) + 0x70) +/** MCPWM_FH0_CBC_ON : RO; bitpos: [0]; default: 0; + * Set and reset by hardware. If set, a cycle-by-cycle mode action is on going + */ +#define MCPWM_FH0_CBC_ON (BIT(0)) +#define MCPWM_FH0_CBC_ON_M (MCPWM_FH0_CBC_ON_V << MCPWM_FH0_CBC_ON_S) +#define MCPWM_FH0_CBC_ON_V 0x00000001U +#define MCPWM_FH0_CBC_ON_S 0 +/** MCPWM_FH0_OST_ON : RO; bitpos: [1]; default: 0; + * Set and reset by hardware. If set, an one-shot mode action is on going + */ +#define MCPWM_FH0_OST_ON (BIT(1)) +#define MCPWM_FH0_OST_ON_M (MCPWM_FH0_OST_ON_V << MCPWM_FH0_OST_ON_S) +#define MCPWM_FH0_OST_ON_V 0x00000001U +#define MCPWM_FH0_OST_ON_S 1 -#define MCPWM_CMPR1_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x74) -/* MCPWM_CMPR1_B_SHDW_FULL : R/W ;bitpos:[9] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR1_B_SHDW_FULL (BIT(9)) -#define MCPWM_CMPR1_B_SHDW_FULL_M (BIT(9)) -#define MCPWM_CMPR1_B_SHDW_FULL_V 0x1 -#define MCPWM_CMPR1_B_SHDW_FULL_S 9 -/* MCPWM_CMPR1_A_SHDW_FULL : R/W ;bitpos:[8] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR1_A_SHDW_FULL (BIT(8)) -#define MCPWM_CMPR1_A_SHDW_FULL_M (BIT(8)) -#define MCPWM_CMPR1_A_SHDW_FULL_V 0x1 -#define MCPWM_CMPR1_A_SHDW_FULL_S 8 -/* MCPWM_CMPR1_B_UPMETHOD : R/W ;bitpos:[7:4] ;default: 4'd0 ; */ -/*description: 0: immediate, bit0: tez, bit1: tep, bit2: sync, bit3: freeze.*/ -#define MCPWM_CMPR1_B_UPMETHOD 0x0000000F -#define MCPWM_CMPR1_B_UPMETHOD_M ((MCPWM_CMPR1_B_UPMETHOD_V)<<(MCPWM_CMPR1_B_UPMETHOD_S)) -#define MCPWM_CMPR1_B_UPMETHOD_V 0xF -#define MCPWM_CMPR1_B_UPMETHOD_S 4 -/* MCPWM_CMPR1_A_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: 0: immediate, bit0: tez, bit1: tep, bit2: sync, bit3: freeze.*/ -#define MCPWM_CMPR1_A_UPMETHOD 0x0000000F -#define MCPWM_CMPR1_A_UPMETHOD_M ((MCPWM_CMPR1_A_UPMETHOD_V)<<(MCPWM_CMPR1_A_UPMETHOD_S)) -#define MCPWM_CMPR1_A_UPMETHOD_V 0xF -#define MCPWM_CMPR1_A_UPMETHOD_S 0 +/** MCPWM_GEN1_STMP_CFG_REG register + * Transfer status and update method for time stamp registers A and B + */ +#define MCPWM_GEN1_STMP_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x74) +/** MCPWM_GEN1_A_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for PWM generator 1 time stamp A's active register. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when + * bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + */ +#define MCPWM_GEN1_A_UPMETHOD 0x0000000FU +#define MCPWM_GEN1_A_UPMETHOD_M (MCPWM_GEN1_A_UPMETHOD_V << MCPWM_GEN1_A_UPMETHOD_S) +#define MCPWM_GEN1_A_UPMETHOD_V 0x0000000FU +#define MCPWM_GEN1_A_UPMETHOD_S 0 +/** MCPWM_GEN1_B_UPMETHOD : R/W; bitpos: [7:4]; default: 0; + * Update method for PWM generator 1 time stamp B's active register. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when + * bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + */ +#define MCPWM_GEN1_B_UPMETHOD 0x0000000FU +#define MCPWM_GEN1_B_UPMETHOD_M (MCPWM_GEN1_B_UPMETHOD_V << MCPWM_GEN1_B_UPMETHOD_S) +#define MCPWM_GEN1_B_UPMETHOD_V 0x0000000FU +#define MCPWM_GEN1_B_UPMETHOD_S 4 +/** MCPWM_GEN1_A_SHDW_FULL : R/W/WTC/SC; bitpos: [8]; default: 0; + * Set and reset by hardware. If set, PWM generator 1 time stamp A's shadow reg is + * filled and waiting to be transferred to A's active reg. If cleared, A's active reg + * has been updated with shadow register latest value + */ +#define MCPWM_GEN1_A_SHDW_FULL (BIT(8)) +#define MCPWM_GEN1_A_SHDW_FULL_M (MCPWM_GEN1_A_SHDW_FULL_V << MCPWM_GEN1_A_SHDW_FULL_S) +#define MCPWM_GEN1_A_SHDW_FULL_V 0x00000001U +#define MCPWM_GEN1_A_SHDW_FULL_S 8 +/** MCPWM_GEN1_B_SHDW_FULL : R/W/WTC/SC; bitpos: [9]; default: 0; + * Set and reset by hardware. If set, PWM generator 1 time stamp B's shadow reg is + * filled and waiting to be transferred to B's active reg. If cleared, B's active reg + * has been updated with shadow register latest value + */ +#define MCPWM_GEN1_B_SHDW_FULL (BIT(9)) +#define MCPWM_GEN1_B_SHDW_FULL_M (MCPWM_GEN1_B_SHDW_FULL_V << MCPWM_GEN1_B_SHDW_FULL_S) +#define MCPWM_GEN1_B_SHDW_FULL_V 0x00000001U +#define MCPWM_GEN1_B_SHDW_FULL_S 9 -#define MCPWM_CMPR1_VALUE0_REG(i) (REG_MCPWM_BASE(i) + 0x78) -/* MCPWM_CMPR1_A : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR1_A 0x0000FFFF -#define MCPWM_CMPR1_A_M ((MCPWM_CMPR1_A_V)<<(MCPWM_CMPR1_A_S)) -#define MCPWM_CMPR1_A_V 0xFFFF -#define MCPWM_CMPR1_A_S 0 +/** MCPWM_GEN1_TSTMP_A_REG register + * PWM generator 1 shadow register for timer stamp A. + */ +#define MCPWM_GEN1_TSTMP_A_REG(i) (DR_REG_MCPWM_BASE(i) + 0x78) +/** MCPWM_GEN1_A : R/W; bitpos: [15:0]; default: 0; + * PWM generator 1 time stamp A's shadow register + */ +#define MCPWM_GEN1_A 0x0000FFFFU +#define MCPWM_GEN1_A_M (MCPWM_GEN1_A_V << MCPWM_GEN1_A_S) +#define MCPWM_GEN1_A_V 0x0000FFFFU +#define MCPWM_GEN1_A_S 0 -#define MCPWM_CMPR1_VALUE1_REG(i) (REG_MCPWM_BASE(i) + 0x7C) -/* MCPWM_CMPR1_B : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR1_B 0x0000FFFF -#define MCPWM_CMPR1_B_M ((MCPWM_CMPR1_B_V)<<(MCPWM_CMPR1_B_S)) -#define MCPWM_CMPR1_B_V 0xFFFF -#define MCPWM_CMPR1_B_S 0 +/** MCPWM_GEN1_TSTMP_B_REG register + * PWM generator 1 shadow register for timer stamp B. + */ +#define MCPWM_GEN1_TSTMP_B_REG(i) (DR_REG_MCPWM_BASE(i) + 0x7c) +/** MCPWM_GEN1_B : R/W; bitpos: [15:0]; default: 0; + * PWM generator 1 time stamp B's shadow register + */ +#define MCPWM_GEN1_B 0x0000FFFFU +#define MCPWM_GEN1_B_M (MCPWM_GEN1_B_V << MCPWM_GEN1_B_S) +#define MCPWM_GEN1_B_V 0x0000FFFFU +#define MCPWM_GEN1_B_S 0 -#define MCPWM_GEN1_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0x80) -/* MCPWM_GEN1_T1_SEL : R/W ;bitpos:[9:7] ;default: 3'd0 ; */ -/*description: take effect immediately, 0: extra0, 1: extra1, 2: extra2, 3: sync_taken, 4: none.*/ -#define MCPWM_GEN1_T1_SEL 0x00000007 -#define MCPWM_GEN1_T1_SEL_M ((MCPWM_GEN1_T1_SEL_V)<<(MCPWM_GEN1_T1_SEL_S)) -#define MCPWM_GEN1_T1_SEL_V 0x7 -#define MCPWM_GEN1_T1_SEL_S 7 -/* MCPWM_GEN1_T0_SEL : R/W ;bitpos:[6:4] ;default: 3'd0 ; */ -/*description: take effect immediately, 0: extra0, 1: extra1, 2: extra2, 3: sync_taken, 4: none.*/ -#define MCPWM_GEN1_T0_SEL 0x00000007 -#define MCPWM_GEN1_T0_SEL_M ((MCPWM_GEN1_T0_SEL_V)<<(MCPWM_GEN1_T0_SEL_S)) -#define MCPWM_GEN1_T0_SEL_V 0x7 -#define MCPWM_GEN1_T0_SEL_S 4 -/* MCPWM_GEN1_CFG_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: 0: immediate, bit0: tez, bit1: tep, bit2: sync. bit3: freeze.*/ -#define MCPWM_GEN1_CFG_UPMETHOD 0x0000000F -#define MCPWM_GEN1_CFG_UPMETHOD_M ((MCPWM_GEN1_CFG_UPMETHOD_V)<<(MCPWM_GEN1_CFG_UPMETHOD_S)) -#define MCPWM_GEN1_CFG_UPMETHOD_V 0xF +/** MCPWM_GEN1_CFG0_REG register + * PWM generator 1 event T0 and T1 handling + */ +#define MCPWM_GEN1_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0x80) +/** MCPWM_GEN1_CFG_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for PWM generator 1's active register of configuration. When all bits + * are set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to + * 1:sync;when bit3 is set to 1:disable the update. + */ +#define MCPWM_GEN1_CFG_UPMETHOD 0x0000000FU +#define MCPWM_GEN1_CFG_UPMETHOD_M (MCPWM_GEN1_CFG_UPMETHOD_V << MCPWM_GEN1_CFG_UPMETHOD_S) +#define MCPWM_GEN1_CFG_UPMETHOD_V 0x0000000FU #define MCPWM_GEN1_CFG_UPMETHOD_S 0 +/** MCPWM_GEN1_T0_SEL : R/W; bitpos: [6:4]; default: 0; + * Source selection for PWM generator 1 event_t0, take effect immediately, 0: + * fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + */ +#define MCPWM_GEN1_T0_SEL 0x00000007U +#define MCPWM_GEN1_T0_SEL_M (MCPWM_GEN1_T0_SEL_V << MCPWM_GEN1_T0_SEL_S) +#define MCPWM_GEN1_T0_SEL_V 0x00000007U +#define MCPWM_GEN1_T0_SEL_S 4 +/** MCPWM_GEN1_T1_SEL : R/W; bitpos: [9:7]; default: 0; + * Source selection for PWM generator 1 event_t1, take effect immediately, 0: + * fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + */ +#define MCPWM_GEN1_T1_SEL 0x00000007U +#define MCPWM_GEN1_T1_SEL_M (MCPWM_GEN1_T1_SEL_V << MCPWM_GEN1_T1_SEL_S) +#define MCPWM_GEN1_T1_SEL_V 0x00000007U +#define MCPWM_GEN1_T1_SEL_S 7 -#define MCPWM_GEN1_FORCE_REG(i) (REG_MCPWM_BASE(i) + 0x84) -/* MCPWM_GEN1_B_NCIFORCE_MODE : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: 0: disabled, 1: low, 2: high, 3: disabled.*/ -#define MCPWM_GEN1_B_NCIFORCE_MODE 0x00000003 -#define MCPWM_GEN1_B_NCIFORCE_MODE_M ((MCPWM_GEN1_B_NCIFORCE_MODE_V)<<(MCPWM_GEN1_B_NCIFORCE_MODE_S)) -#define MCPWM_GEN1_B_NCIFORCE_MODE_V 0x3 -#define MCPWM_GEN1_B_NCIFORCE_MODE_S 14 -/* MCPWM_GEN1_B_NCIFORCE : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: non-continuous immediate sw force, a toggle will trigger a force event.*/ -#define MCPWM_GEN1_B_NCIFORCE (BIT(13)) -#define MCPWM_GEN1_B_NCIFORCE_M (BIT(13)) -#define MCPWM_GEN1_B_NCIFORCE_V 0x1 -#define MCPWM_GEN1_B_NCIFORCE_S 13 -/* MCPWM_GEN1_A_NCIFORCE_MODE : R/W ;bitpos:[12:11] ;default: 2'd0 ; */ -/*description: 0: disabled, 1: low, 2: high, 3: disabled.*/ -#define MCPWM_GEN1_A_NCIFORCE_MODE 0x00000003 -#define MCPWM_GEN1_A_NCIFORCE_MODE_M ((MCPWM_GEN1_A_NCIFORCE_MODE_V)<<(MCPWM_GEN1_A_NCIFORCE_MODE_S)) -#define MCPWM_GEN1_A_NCIFORCE_MODE_V 0x3 -#define MCPWM_GEN1_A_NCIFORCE_MODE_S 11 -/* MCPWM_GEN1_A_NCIFORCE : R/W ;bitpos:[10] ;default: 1'd0 ; */ -/*description: non-continuous immediate sw force, a toggle will trigger a force event.*/ -#define MCPWM_GEN1_A_NCIFORCE (BIT(10)) -#define MCPWM_GEN1_A_NCIFORCE_M (BIT(10)) -#define MCPWM_GEN1_A_NCIFORCE_V 0x1 -#define MCPWM_GEN1_A_NCIFORCE_S 10 -/* MCPWM_GEN1_B_CNTUFORCE_MODE : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: 0: disabled, 1: low, 2: high, 3: disabled.*/ -#define MCPWM_GEN1_B_CNTUFORCE_MODE 0x00000003 -#define MCPWM_GEN1_B_CNTUFORCE_MODE_M ((MCPWM_GEN1_B_CNTUFORCE_MODE_V)<<(MCPWM_GEN1_B_CNTUFORCE_MODE_S)) -#define MCPWM_GEN1_B_CNTUFORCE_MODE_V 0x3 -#define MCPWM_GEN1_B_CNTUFORCE_MODE_S 8 -/* MCPWM_GEN1_A_CNTUFORCE_MODE : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: 0: disabled, 1: low, 2: high, 3: disabled.*/ -#define MCPWM_GEN1_A_CNTUFORCE_MODE 0x00000003 -#define MCPWM_GEN1_A_CNTUFORCE_MODE_M ((MCPWM_GEN1_A_CNTUFORCE_MODE_V)<<(MCPWM_GEN1_A_CNTUFORCE_MODE_S)) -#define MCPWM_GEN1_A_CNTUFORCE_MODE_V 0x3 -#define MCPWM_GEN1_A_CNTUFORCE_MODE_S 6 -/* MCPWM_GEN1_CNTUFORCE_UPMETHOD : R/W ;bitpos:[5:0] ;default: 6'h20 ; */ -/*description: 0: immediate, bit0: tez, bit1: tep, bit2: tea, bit3: teb, bit4: sync, bit5: free -ze.*/ -#define MCPWM_GEN1_CNTUFORCE_UPMETHOD 0x0000003F -#define MCPWM_GEN1_CNTUFORCE_UPMETHOD_M ((MCPWM_GEN1_CNTUFORCE_UPMETHOD_V)<<(MCPWM_GEN1_CNTUFORCE_UPMETHOD_S)) -#define MCPWM_GEN1_CNTUFORCE_UPMETHOD_V 0x3F +/** MCPWM_GEN1_FORCE_REG register + * Permissives to force PWM1A and PWM1B outputs by software + */ +#define MCPWM_GEN1_FORCE_REG(i) (DR_REG_MCPWM_BASE(i) + 0x84) +/** MCPWM_GEN1_CNTUFORCE_UPMETHOD : R/W; bitpos: [5:0]; default: 32; + * Updating method for continuous software force of PWM generator 1. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ,when bit1 is set to 1: TEP, when + * bit2 is set to 1: TEA, when bit3 is set to 1: TEB, when bit4 is set to 1: sync, + * when bit5 is set to 1: disable update. (TEA/B here and below means an event + * generated when the timer's value equals to that of register A/B.) + */ +#define MCPWM_GEN1_CNTUFORCE_UPMETHOD 0x0000003FU +#define MCPWM_GEN1_CNTUFORCE_UPMETHOD_M (MCPWM_GEN1_CNTUFORCE_UPMETHOD_V << MCPWM_GEN1_CNTUFORCE_UPMETHOD_S) +#define MCPWM_GEN1_CNTUFORCE_UPMETHOD_V 0x0000003FU #define MCPWM_GEN1_CNTUFORCE_UPMETHOD_S 0 +/** MCPWM_GEN1_A_CNTUFORCE_MODE : R/W; bitpos: [7:6]; default: 0; + * Continuous software force mode for PWM1A. 0: disabled, 1: low, 2: high, 3: disabled + */ +#define MCPWM_GEN1_A_CNTUFORCE_MODE 0x00000003U +#define MCPWM_GEN1_A_CNTUFORCE_MODE_M (MCPWM_GEN1_A_CNTUFORCE_MODE_V << MCPWM_GEN1_A_CNTUFORCE_MODE_S) +#define MCPWM_GEN1_A_CNTUFORCE_MODE_V 0x00000003U +#define MCPWM_GEN1_A_CNTUFORCE_MODE_S 6 +/** MCPWM_GEN1_B_CNTUFORCE_MODE : R/W; bitpos: [9:8]; default: 0; + * Continuous software force mode for PWM1B. 0: disabled, 1: low, 2: high, 3: disabled + */ +#define MCPWM_GEN1_B_CNTUFORCE_MODE 0x00000003U +#define MCPWM_GEN1_B_CNTUFORCE_MODE_M (MCPWM_GEN1_B_CNTUFORCE_MODE_V << MCPWM_GEN1_B_CNTUFORCE_MODE_S) +#define MCPWM_GEN1_B_CNTUFORCE_MODE_V 0x00000003U +#define MCPWM_GEN1_B_CNTUFORCE_MODE_S 8 +/** MCPWM_GEN1_A_NCIFORCE : R/W; bitpos: [10]; default: 0; + * Trigger of non-continuous immediate software-force event for PWM1A, a toggle will + * trigger a force event. + */ +#define MCPWM_GEN1_A_NCIFORCE (BIT(10)) +#define MCPWM_GEN1_A_NCIFORCE_M (MCPWM_GEN1_A_NCIFORCE_V << MCPWM_GEN1_A_NCIFORCE_S) +#define MCPWM_GEN1_A_NCIFORCE_V 0x00000001U +#define MCPWM_GEN1_A_NCIFORCE_S 10 +/** MCPWM_GEN1_A_NCIFORCE_MODE : R/W; bitpos: [12:11]; default: 0; + * non-continuous immediate software force mode for PWM1A, 0: disabled, 1: low, 2: + * high, 3: disabled + */ +#define MCPWM_GEN1_A_NCIFORCE_MODE 0x00000003U +#define MCPWM_GEN1_A_NCIFORCE_MODE_M (MCPWM_GEN1_A_NCIFORCE_MODE_V << MCPWM_GEN1_A_NCIFORCE_MODE_S) +#define MCPWM_GEN1_A_NCIFORCE_MODE_V 0x00000003U +#define MCPWM_GEN1_A_NCIFORCE_MODE_S 11 +/** MCPWM_GEN1_B_NCIFORCE : R/W; bitpos: [13]; default: 0; + * Trigger of non-continuous immediate software-force event for PWM1B, a toggle will + * trigger a force event. + */ +#define MCPWM_GEN1_B_NCIFORCE (BIT(13)) +#define MCPWM_GEN1_B_NCIFORCE_M (MCPWM_GEN1_B_NCIFORCE_V << MCPWM_GEN1_B_NCIFORCE_S) +#define MCPWM_GEN1_B_NCIFORCE_V 0x00000001U +#define MCPWM_GEN1_B_NCIFORCE_S 13 +/** MCPWM_GEN1_B_NCIFORCE_MODE : R/W; bitpos: [15:14]; default: 0; + * non-continuous immediate software force mode for PWM1B, 0: disabled, 1: low, 2: + * high, 3: disabled + */ +#define MCPWM_GEN1_B_NCIFORCE_MODE 0x00000003U +#define MCPWM_GEN1_B_NCIFORCE_MODE_M (MCPWM_GEN1_B_NCIFORCE_MODE_V << MCPWM_GEN1_B_NCIFORCE_MODE_S) +#define MCPWM_GEN1_B_NCIFORCE_MODE_V 0x00000003U +#define MCPWM_GEN1_B_NCIFORCE_MODE_S 14 -#define MCPWM_GEN1_A_REG(i) (REG_MCPWM_BASE(i) + 0x88) -/* MCPWM_GEN1_A_DT1 : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: 0: no change, 1: low, 2: high, 3: toggle.*/ -#define MCPWM_GEN1_A_DT1 0x00000003 -#define MCPWM_GEN1_A_DT1_M ((MCPWM_GEN1_A_DT1_V)<<(MCPWM_GEN1_A_DT1_S)) -#define MCPWM_GEN1_A_DT1_V 0x3 -#define MCPWM_GEN1_A_DT1_S 22 -/* MCPWM_GEN1_A_DT0 : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_A_DT0 0x00000003 -#define MCPWM_GEN1_A_DT0_M ((MCPWM_GEN1_A_DT0_V)<<(MCPWM_GEN1_A_DT0_S)) -#define MCPWM_GEN1_A_DT0_V 0x3 -#define MCPWM_GEN1_A_DT0_S 20 -/* MCPWM_GEN1_A_DTEB : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_A_DTEB 0x00000003 -#define MCPWM_GEN1_A_DTEB_M ((MCPWM_GEN1_A_DTEB_V)<<(MCPWM_GEN1_A_DTEB_S)) -#define MCPWM_GEN1_A_DTEB_V 0x3 -#define MCPWM_GEN1_A_DTEB_S 18 -/* MCPWM_GEN1_A_DTEA : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_A_DTEA 0x00000003 -#define MCPWM_GEN1_A_DTEA_M ((MCPWM_GEN1_A_DTEA_V)<<(MCPWM_GEN1_A_DTEA_S)) -#define MCPWM_GEN1_A_DTEA_V 0x3 -#define MCPWM_GEN1_A_DTEA_S 16 -/* MCPWM_GEN1_A_DTEP : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_A_DTEP 0x00000003 -#define MCPWM_GEN1_A_DTEP_M ((MCPWM_GEN1_A_DTEP_V)<<(MCPWM_GEN1_A_DTEP_S)) -#define MCPWM_GEN1_A_DTEP_V 0x3 -#define MCPWM_GEN1_A_DTEP_S 14 -/* MCPWM_GEN1_A_DTEZ : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_A_DTEZ 0x00000003 -#define MCPWM_GEN1_A_DTEZ_M ((MCPWM_GEN1_A_DTEZ_V)<<(MCPWM_GEN1_A_DTEZ_S)) -#define MCPWM_GEN1_A_DTEZ_V 0x3 -#define MCPWM_GEN1_A_DTEZ_S 12 -/* MCPWM_GEN1_A_UT1 : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_A_UT1 0x00000003 -#define MCPWM_GEN1_A_UT1_M ((MCPWM_GEN1_A_UT1_V)<<(MCPWM_GEN1_A_UT1_S)) -#define MCPWM_GEN1_A_UT1_V 0x3 -#define MCPWM_GEN1_A_UT1_S 10 -/* MCPWM_GEN1_A_UT0 : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_A_UT0 0x00000003 -#define MCPWM_GEN1_A_UT0_M ((MCPWM_GEN1_A_UT0_V)<<(MCPWM_GEN1_A_UT0_S)) -#define MCPWM_GEN1_A_UT0_V 0x3 -#define MCPWM_GEN1_A_UT0_S 8 -/* MCPWM_GEN1_A_UTEB : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_A_UTEB 0x00000003 -#define MCPWM_GEN1_A_UTEB_M ((MCPWM_GEN1_A_UTEB_V)<<(MCPWM_GEN1_A_UTEB_S)) -#define MCPWM_GEN1_A_UTEB_V 0x3 -#define MCPWM_GEN1_A_UTEB_S 6 -/* MCPWM_GEN1_A_UTEA : R/W ;bitpos:[5:4] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_A_UTEA 0x00000003 -#define MCPWM_GEN1_A_UTEA_M ((MCPWM_GEN1_A_UTEA_V)<<(MCPWM_GEN1_A_UTEA_S)) -#define MCPWM_GEN1_A_UTEA_V 0x3 -#define MCPWM_GEN1_A_UTEA_S 4 -/* MCPWM_GEN1_A_UTEP : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_A_UTEP 0x00000003 -#define MCPWM_GEN1_A_UTEP_M ((MCPWM_GEN1_A_UTEP_V)<<(MCPWM_GEN1_A_UTEP_S)) -#define MCPWM_GEN1_A_UTEP_V 0x3 -#define MCPWM_GEN1_A_UTEP_S 2 -/* MCPWM_GEN1_A_UTEZ : R/W ;bitpos:[1:0] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_A_UTEZ 0x00000003 -#define MCPWM_GEN1_A_UTEZ_M ((MCPWM_GEN1_A_UTEZ_V)<<(MCPWM_GEN1_A_UTEZ_S)) -#define MCPWM_GEN1_A_UTEZ_V 0x3 +/** MCPWM_GEN1_A_REG register + * Actions triggered by events on PWM1A + */ +#define MCPWM_GEN1_A_REG(i) (DR_REG_MCPWM_BASE(i) + 0x88) +/** MCPWM_GEN1_A_UTEZ : R/W; bitpos: [1:0]; default: 0; + * Action on PWM1A triggered by event TEZ when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_UTEZ 0x00000003U +#define MCPWM_GEN1_A_UTEZ_M (MCPWM_GEN1_A_UTEZ_V << MCPWM_GEN1_A_UTEZ_S) +#define MCPWM_GEN1_A_UTEZ_V 0x00000003U #define MCPWM_GEN1_A_UTEZ_S 0 +/** MCPWM_GEN1_A_UTEP : R/W; bitpos: [3:2]; default: 0; + * Action on PWM1A triggered by event TEP when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_UTEP 0x00000003U +#define MCPWM_GEN1_A_UTEP_M (MCPWM_GEN1_A_UTEP_V << MCPWM_GEN1_A_UTEP_S) +#define MCPWM_GEN1_A_UTEP_V 0x00000003U +#define MCPWM_GEN1_A_UTEP_S 2 +/** MCPWM_GEN1_A_UTEA : R/W; bitpos: [5:4]; default: 0; + * Action on PWM1A triggered by event TEA when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_UTEA 0x00000003U +#define MCPWM_GEN1_A_UTEA_M (MCPWM_GEN1_A_UTEA_V << MCPWM_GEN1_A_UTEA_S) +#define MCPWM_GEN1_A_UTEA_V 0x00000003U +#define MCPWM_GEN1_A_UTEA_S 4 +/** MCPWM_GEN1_A_UTEB : R/W; bitpos: [7:6]; default: 0; + * Action on PWM1A triggered by event TEB when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_UTEB 0x00000003U +#define MCPWM_GEN1_A_UTEB_M (MCPWM_GEN1_A_UTEB_V << MCPWM_GEN1_A_UTEB_S) +#define MCPWM_GEN1_A_UTEB_V 0x00000003U +#define MCPWM_GEN1_A_UTEB_S 6 +/** MCPWM_GEN1_A_UT0 : R/W; bitpos: [9:8]; default: 0; + * Action on PWM1A triggered by event_t0 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_UT0 0x00000003U +#define MCPWM_GEN1_A_UT0_M (MCPWM_GEN1_A_UT0_V << MCPWM_GEN1_A_UT0_S) +#define MCPWM_GEN1_A_UT0_V 0x00000003U +#define MCPWM_GEN1_A_UT0_S 8 +/** MCPWM_GEN1_A_UT1 : R/W; bitpos: [11:10]; default: 0; + * Action on PWM1A triggered by event_t1 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_UT1 0x00000003U +#define MCPWM_GEN1_A_UT1_M (MCPWM_GEN1_A_UT1_V << MCPWM_GEN1_A_UT1_S) +#define MCPWM_GEN1_A_UT1_V 0x00000003U +#define MCPWM_GEN1_A_UT1_S 10 +/** MCPWM_GEN1_A_DTEZ : R/W; bitpos: [13:12]; default: 0; + * Action on PWM1A triggered by event TEZ when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_DTEZ 0x00000003U +#define MCPWM_GEN1_A_DTEZ_M (MCPWM_GEN1_A_DTEZ_V << MCPWM_GEN1_A_DTEZ_S) +#define MCPWM_GEN1_A_DTEZ_V 0x00000003U +#define MCPWM_GEN1_A_DTEZ_S 12 +/** MCPWM_GEN1_A_DTEP : R/W; bitpos: [15:14]; default: 0; + * Action on PWM1A triggered by event TEP when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_DTEP 0x00000003U +#define MCPWM_GEN1_A_DTEP_M (MCPWM_GEN1_A_DTEP_V << MCPWM_GEN1_A_DTEP_S) +#define MCPWM_GEN1_A_DTEP_V 0x00000003U +#define MCPWM_GEN1_A_DTEP_S 14 +/** MCPWM_GEN1_A_DTEA : R/W; bitpos: [17:16]; default: 0; + * Action on PWM1A triggered by event TEA when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_DTEA 0x00000003U +#define MCPWM_GEN1_A_DTEA_M (MCPWM_GEN1_A_DTEA_V << MCPWM_GEN1_A_DTEA_S) +#define MCPWM_GEN1_A_DTEA_V 0x00000003U +#define MCPWM_GEN1_A_DTEA_S 16 +/** MCPWM_GEN1_A_DTEB : R/W; bitpos: [19:18]; default: 0; + * Action on PWM1A triggered by event TEB when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_DTEB 0x00000003U +#define MCPWM_GEN1_A_DTEB_M (MCPWM_GEN1_A_DTEB_V << MCPWM_GEN1_A_DTEB_S) +#define MCPWM_GEN1_A_DTEB_V 0x00000003U +#define MCPWM_GEN1_A_DTEB_S 18 +/** MCPWM_GEN1_A_DT0 : R/W; bitpos: [21:20]; default: 0; + * Action on PWM1A triggered by event_t0 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_DT0 0x00000003U +#define MCPWM_GEN1_A_DT0_M (MCPWM_GEN1_A_DT0_V << MCPWM_GEN1_A_DT0_S) +#define MCPWM_GEN1_A_DT0_V 0x00000003U +#define MCPWM_GEN1_A_DT0_S 20 +/** MCPWM_GEN1_A_DT1 : R/W; bitpos: [23:22]; default: 0; + * Action on PWM1A triggered by event_t1 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_A_DT1 0x00000003U +#define MCPWM_GEN1_A_DT1_M (MCPWM_GEN1_A_DT1_V << MCPWM_GEN1_A_DT1_S) +#define MCPWM_GEN1_A_DT1_V 0x00000003U +#define MCPWM_GEN1_A_DT1_S 22 -#define MCPWM_GEN1_B_REG(i) (REG_MCPWM_BASE(i) + 0x8C) -/* MCPWM_GEN1_B_DT1 : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_B_DT1 0x00000003 -#define MCPWM_GEN1_B_DT1_M ((MCPWM_GEN1_B_DT1_V)<<(MCPWM_GEN1_B_DT1_S)) -#define MCPWM_GEN1_B_DT1_V 0x3 -#define MCPWM_GEN1_B_DT1_S 22 -/* MCPWM_GEN1_B_DT0 : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_B_DT0 0x00000003 -#define MCPWM_GEN1_B_DT0_M ((MCPWM_GEN1_B_DT0_V)<<(MCPWM_GEN1_B_DT0_S)) -#define MCPWM_GEN1_B_DT0_V 0x3 -#define MCPWM_GEN1_B_DT0_S 20 -/* MCPWM_GEN1_B_DTEB : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_B_DTEB 0x00000003 -#define MCPWM_GEN1_B_DTEB_M ((MCPWM_GEN1_B_DTEB_V)<<(MCPWM_GEN1_B_DTEB_S)) -#define MCPWM_GEN1_B_DTEB_V 0x3 -#define MCPWM_GEN1_B_DTEB_S 18 -/* MCPWM_GEN1_B_DTEA : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_B_DTEA 0x00000003 -#define MCPWM_GEN1_B_DTEA_M ((MCPWM_GEN1_B_DTEA_V)<<(MCPWM_GEN1_B_DTEA_S)) -#define MCPWM_GEN1_B_DTEA_V 0x3 -#define MCPWM_GEN1_B_DTEA_S 16 -/* MCPWM_GEN1_B_DTEP : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_B_DTEP 0x00000003 -#define MCPWM_GEN1_B_DTEP_M ((MCPWM_GEN1_B_DTEP_V)<<(MCPWM_GEN1_B_DTEP_S)) -#define MCPWM_GEN1_B_DTEP_V 0x3 -#define MCPWM_GEN1_B_DTEP_S 14 -/* MCPWM_GEN1_B_DTEZ : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_B_DTEZ 0x00000003 -#define MCPWM_GEN1_B_DTEZ_M ((MCPWM_GEN1_B_DTEZ_V)<<(MCPWM_GEN1_B_DTEZ_S)) -#define MCPWM_GEN1_B_DTEZ_V 0x3 -#define MCPWM_GEN1_B_DTEZ_S 12 -/* MCPWM_GEN1_B_UT1 : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_B_UT1 0x00000003 -#define MCPWM_GEN1_B_UT1_M ((MCPWM_GEN1_B_UT1_V)<<(MCPWM_GEN1_B_UT1_S)) -#define MCPWM_GEN1_B_UT1_V 0x3 -#define MCPWM_GEN1_B_UT1_S 10 -/* MCPWM_GEN1_B_UT0 : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_B_UT0 0x00000003 -#define MCPWM_GEN1_B_UT0_M ((MCPWM_GEN1_B_UT0_V)<<(MCPWM_GEN1_B_UT0_S)) -#define MCPWM_GEN1_B_UT0_V 0x3 -#define MCPWM_GEN1_B_UT0_S 8 -/* MCPWM_GEN1_B_UTEB : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_B_UTEB 0x00000003 -#define MCPWM_GEN1_B_UTEB_M ((MCPWM_GEN1_B_UTEB_V)<<(MCPWM_GEN1_B_UTEB_S)) -#define MCPWM_GEN1_B_UTEB_V 0x3 -#define MCPWM_GEN1_B_UTEB_S 6 -/* MCPWM_GEN1_B_UTEA : R/W ;bitpos:[5:4] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_B_UTEA 0x00000003 -#define MCPWM_GEN1_B_UTEA_M ((MCPWM_GEN1_B_UTEA_V)<<(MCPWM_GEN1_B_UTEA_S)) -#define MCPWM_GEN1_B_UTEA_V 0x3 -#define MCPWM_GEN1_B_UTEA_S 4 -/* MCPWM_GEN1_B_UTEP : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_B_UTEP 0x00000003 -#define MCPWM_GEN1_B_UTEP_M ((MCPWM_GEN1_B_UTEP_V)<<(MCPWM_GEN1_B_UTEP_S)) -#define MCPWM_GEN1_B_UTEP_V 0x3 -#define MCPWM_GEN1_B_UTEP_S 2 -/* MCPWM_GEN1_B_UTEZ : R/W ;bitpos:[1:0] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN1_B_UTEZ 0x00000003 -#define MCPWM_GEN1_B_UTEZ_M ((MCPWM_GEN1_B_UTEZ_V)<<(MCPWM_GEN1_B_UTEZ_S)) -#define MCPWM_GEN1_B_UTEZ_V 0x3 +/** MCPWM_GEN1_B_REG register + * Actions triggered by events on PWM1B + */ +#define MCPWM_GEN1_B_REG(i) (DR_REG_MCPWM_BASE(i) + 0x8c) +/** MCPWM_GEN1_B_UTEZ : R/W; bitpos: [1:0]; default: 0; + * Action on PWM1B triggered by event TEZ when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_UTEZ 0x00000003U +#define MCPWM_GEN1_B_UTEZ_M (MCPWM_GEN1_B_UTEZ_V << MCPWM_GEN1_B_UTEZ_S) +#define MCPWM_GEN1_B_UTEZ_V 0x00000003U #define MCPWM_GEN1_B_UTEZ_S 0 +/** MCPWM_GEN1_B_UTEP : R/W; bitpos: [3:2]; default: 0; + * Action on PWM1B triggered by event TEP when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_UTEP 0x00000003U +#define MCPWM_GEN1_B_UTEP_M (MCPWM_GEN1_B_UTEP_V << MCPWM_GEN1_B_UTEP_S) +#define MCPWM_GEN1_B_UTEP_V 0x00000003U +#define MCPWM_GEN1_B_UTEP_S 2 +/** MCPWM_GEN1_B_UTEA : R/W; bitpos: [5:4]; default: 0; + * Action on PWM1B triggered by event TEA when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_UTEA 0x00000003U +#define MCPWM_GEN1_B_UTEA_M (MCPWM_GEN1_B_UTEA_V << MCPWM_GEN1_B_UTEA_S) +#define MCPWM_GEN1_B_UTEA_V 0x00000003U +#define MCPWM_GEN1_B_UTEA_S 4 +/** MCPWM_GEN1_B_UTEB : R/W; bitpos: [7:6]; default: 0; + * Action on PWM1B triggered by event TEB when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_UTEB 0x00000003U +#define MCPWM_GEN1_B_UTEB_M (MCPWM_GEN1_B_UTEB_V << MCPWM_GEN1_B_UTEB_S) +#define MCPWM_GEN1_B_UTEB_V 0x00000003U +#define MCPWM_GEN1_B_UTEB_S 6 +/** MCPWM_GEN1_B_UT0 : R/W; bitpos: [9:8]; default: 0; + * Action on PWM1B triggered by event_t0 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_UT0 0x00000003U +#define MCPWM_GEN1_B_UT0_M (MCPWM_GEN1_B_UT0_V << MCPWM_GEN1_B_UT0_S) +#define MCPWM_GEN1_B_UT0_V 0x00000003U +#define MCPWM_GEN1_B_UT0_S 8 +/** MCPWM_GEN1_B_UT1 : R/W; bitpos: [11:10]; default: 0; + * Action on PWM1B triggered by event_t1 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_UT1 0x00000003U +#define MCPWM_GEN1_B_UT1_M (MCPWM_GEN1_B_UT1_V << MCPWM_GEN1_B_UT1_S) +#define MCPWM_GEN1_B_UT1_V 0x00000003U +#define MCPWM_GEN1_B_UT1_S 10 +/** MCPWM_GEN1_B_DTEZ : R/W; bitpos: [13:12]; default: 0; + * Action on PWM1B triggered by event TEZ when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_DTEZ 0x00000003U +#define MCPWM_GEN1_B_DTEZ_M (MCPWM_GEN1_B_DTEZ_V << MCPWM_GEN1_B_DTEZ_S) +#define MCPWM_GEN1_B_DTEZ_V 0x00000003U +#define MCPWM_GEN1_B_DTEZ_S 12 +/** MCPWM_GEN1_B_DTEP : R/W; bitpos: [15:14]; default: 0; + * Action on PWM1B triggered by event TEP when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_DTEP 0x00000003U +#define MCPWM_GEN1_B_DTEP_M (MCPWM_GEN1_B_DTEP_V << MCPWM_GEN1_B_DTEP_S) +#define MCPWM_GEN1_B_DTEP_V 0x00000003U +#define MCPWM_GEN1_B_DTEP_S 14 +/** MCPWM_GEN1_B_DTEA : R/W; bitpos: [17:16]; default: 0; + * Action on PWM1B triggered by event TEA when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_DTEA 0x00000003U +#define MCPWM_GEN1_B_DTEA_M (MCPWM_GEN1_B_DTEA_V << MCPWM_GEN1_B_DTEA_S) +#define MCPWM_GEN1_B_DTEA_V 0x00000003U +#define MCPWM_GEN1_B_DTEA_S 16 +/** MCPWM_GEN1_B_DTEB : R/W; bitpos: [19:18]; default: 0; + * Action on PWM1B triggered by event TEB when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_DTEB 0x00000003U +#define MCPWM_GEN1_B_DTEB_M (MCPWM_GEN1_B_DTEB_V << MCPWM_GEN1_B_DTEB_S) +#define MCPWM_GEN1_B_DTEB_V 0x00000003U +#define MCPWM_GEN1_B_DTEB_S 18 +/** MCPWM_GEN1_B_DT0 : R/W; bitpos: [21:20]; default: 0; + * Action on PWM1B triggered by event_t0 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_DT0 0x00000003U +#define MCPWM_GEN1_B_DT0_M (MCPWM_GEN1_B_DT0_V << MCPWM_GEN1_B_DT0_S) +#define MCPWM_GEN1_B_DT0_V 0x00000003U +#define MCPWM_GEN1_B_DT0_S 20 +/** MCPWM_GEN1_B_DT1 : R/W; bitpos: [23:22]; default: 0; + * Action on PWM1B triggered by event_t1 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN1_B_DT1 0x00000003U +#define MCPWM_GEN1_B_DT1_M (MCPWM_GEN1_B_DT1_V << MCPWM_GEN1_B_DT1_S) +#define MCPWM_GEN1_B_DT1_V 0x00000003U +#define MCPWM_GEN1_B_DT1_S 22 -#define MCPWM_DB1_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x90) -/* MCPWM_DB1_CLK_SEL : R/W ;bitpos:[17] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB1_CLK_SEL (BIT(17)) -#define MCPWM_DB1_CLK_SEL_M (BIT(17)) -#define MCPWM_DB1_CLK_SEL_V 0x1 -#define MCPWM_DB1_CLK_SEL_S 17 -/* MCPWM_DB1_B_OUTBYPASS : R/W ;bitpos:[16] ;default: 1'd1 ; */ -/*description: .*/ -#define MCPWM_DB1_B_OUTBYPASS (BIT(16)) -#define MCPWM_DB1_B_OUTBYPASS_M (BIT(16)) -#define MCPWM_DB1_B_OUTBYPASS_V 0x1 -#define MCPWM_DB1_B_OUTBYPASS_S 16 -/* MCPWM_DB1_A_OUTBYPASS : R/W ;bitpos:[15] ;default: 1'd1 ; */ -/*description: .*/ -#define MCPWM_DB1_A_OUTBYPASS (BIT(15)) -#define MCPWM_DB1_A_OUTBYPASS_M (BIT(15)) -#define MCPWM_DB1_A_OUTBYPASS_V 0x1 -#define MCPWM_DB1_A_OUTBYPASS_S 15 -/* MCPWM_DB1_FED_OUTINVERT : R/W ;bitpos:[14] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB1_FED_OUTINVERT (BIT(14)) -#define MCPWM_DB1_FED_OUTINVERT_M (BIT(14)) -#define MCPWM_DB1_FED_OUTINVERT_V 0x1 -#define MCPWM_DB1_FED_OUTINVERT_S 14 -/* MCPWM_DB1_RED_OUTINVERT : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB1_RED_OUTINVERT (BIT(13)) -#define MCPWM_DB1_RED_OUTINVERT_M (BIT(13)) -#define MCPWM_DB1_RED_OUTINVERT_V 0x1 -#define MCPWM_DB1_RED_OUTINVERT_S 13 -/* MCPWM_DB1_FED_INSEL : R/W ;bitpos:[12] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB1_FED_INSEL (BIT(12)) -#define MCPWM_DB1_FED_INSEL_M (BIT(12)) -#define MCPWM_DB1_FED_INSEL_V 0x1 -#define MCPWM_DB1_FED_INSEL_S 12 -/* MCPWM_DB1_RED_INSEL : R/W ;bitpos:[11] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB1_RED_INSEL (BIT(11)) -#define MCPWM_DB1_RED_INSEL_M (BIT(11)) -#define MCPWM_DB1_RED_INSEL_V 0x1 -#define MCPWM_DB1_RED_INSEL_S 11 -/* MCPWM_DB1_B_OUTSWAP : R/W ;bitpos:[10] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB1_B_OUTSWAP (BIT(10)) -#define MCPWM_DB1_B_OUTSWAP_M (BIT(10)) -#define MCPWM_DB1_B_OUTSWAP_V 0x1 -#define MCPWM_DB1_B_OUTSWAP_S 10 -/* MCPWM_DB1_A_OUTSWAP : R/W ;bitpos:[9] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB1_A_OUTSWAP (BIT(9)) -#define MCPWM_DB1_A_OUTSWAP_M (BIT(9)) -#define MCPWM_DB1_A_OUTSWAP_V 0x1 -#define MCPWM_DB1_A_OUTSWAP_S 9 -/* MCPWM_DB1_DEB_MODE : R/W ;bitpos:[8] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB1_DEB_MODE (BIT(8)) -#define MCPWM_DB1_DEB_MODE_M (BIT(8)) -#define MCPWM_DB1_DEB_MODE_V 0x1 -#define MCPWM_DB1_DEB_MODE_S 8 -/* MCPWM_DB1_RED_UPMETHOD : R/W ;bitpos:[7:4] ;default: 4'd0 ; */ -/*description: .*/ -#define MCPWM_DB1_RED_UPMETHOD 0x0000000F -#define MCPWM_DB1_RED_UPMETHOD_M ((MCPWM_DB1_RED_UPMETHOD_V)<<(MCPWM_DB1_RED_UPMETHOD_S)) -#define MCPWM_DB1_RED_UPMETHOD_V 0xF -#define MCPWM_DB1_RED_UPMETHOD_S 4 -/* MCPWM_DB1_FED_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: .*/ -#define MCPWM_DB1_FED_UPMETHOD 0x0000000F -#define MCPWM_DB1_FED_UPMETHOD_M ((MCPWM_DB1_FED_UPMETHOD_V)<<(MCPWM_DB1_FED_UPMETHOD_S)) -#define MCPWM_DB1_FED_UPMETHOD_V 0xF -#define MCPWM_DB1_FED_UPMETHOD_S 0 +/** MCPWM_DT1_CFG_REG register + * PWM generator 1 dead time type selection and configuration + */ +#define MCPWM_DT1_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x90) +/** MCPWM_DT1_FED_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for FED (falling edge delay) active register. 0: immediate, when bit0 + * is set to 1: tez, when bit1 is set to 1:tep, when bit2 is set to 1: sync, when + * bit3 is set to 1: disable the update + */ +#define MCPWM_DT1_FED_UPMETHOD 0x0000000FU +#define MCPWM_DT1_FED_UPMETHOD_M (MCPWM_DT1_FED_UPMETHOD_V << MCPWM_DT1_FED_UPMETHOD_S) +#define MCPWM_DT1_FED_UPMETHOD_V 0x0000000FU +#define MCPWM_DT1_FED_UPMETHOD_S 0 +/** MCPWM_DT1_RED_UPMETHOD : R/W; bitpos: [7:4]; default: 0; + * Update method for RED (rising edge delay) active register. 0: immediate,when bit0 + * is set to 1: tez, when bit1 is set to 1:tep, when bit2 is set to 1: sync, when + * bit3 is set to 1: disable the update + */ +#define MCPWM_DT1_RED_UPMETHOD 0x0000000FU +#define MCPWM_DT1_RED_UPMETHOD_M (MCPWM_DT1_RED_UPMETHOD_V << MCPWM_DT1_RED_UPMETHOD_S) +#define MCPWM_DT1_RED_UPMETHOD_V 0x0000000FU +#define MCPWM_DT1_RED_UPMETHOD_S 4 +/** MCPWM_DT1_DEB_MODE : R/W; bitpos: [8]; default: 0; + * S8 in table, dual-edge B mode, 0: fed/red take effect on different path separately, + * 1: fed/red take effect on B path, A out is in bypass or dulpB mode + */ +#define MCPWM_DT1_DEB_MODE (BIT(8)) +#define MCPWM_DT1_DEB_MODE_M (MCPWM_DT1_DEB_MODE_V << MCPWM_DT1_DEB_MODE_S) +#define MCPWM_DT1_DEB_MODE_V 0x00000001U +#define MCPWM_DT1_DEB_MODE_S 8 +/** MCPWM_DT1_A_OUTSWAP : R/W; bitpos: [9]; default: 0; + * S6 in table + */ +#define MCPWM_DT1_A_OUTSWAP (BIT(9)) +#define MCPWM_DT1_A_OUTSWAP_M (MCPWM_DT1_A_OUTSWAP_V << MCPWM_DT1_A_OUTSWAP_S) +#define MCPWM_DT1_A_OUTSWAP_V 0x00000001U +#define MCPWM_DT1_A_OUTSWAP_S 9 +/** MCPWM_DT1_B_OUTSWAP : R/W; bitpos: [10]; default: 0; + * S7 in table + */ +#define MCPWM_DT1_B_OUTSWAP (BIT(10)) +#define MCPWM_DT1_B_OUTSWAP_M (MCPWM_DT1_B_OUTSWAP_V << MCPWM_DT1_B_OUTSWAP_S) +#define MCPWM_DT1_B_OUTSWAP_V 0x00000001U +#define MCPWM_DT1_B_OUTSWAP_S 10 +/** MCPWM_DT1_RED_INSEL : R/W; bitpos: [11]; default: 0; + * S4 in table + */ +#define MCPWM_DT1_RED_INSEL (BIT(11)) +#define MCPWM_DT1_RED_INSEL_M (MCPWM_DT1_RED_INSEL_V << MCPWM_DT1_RED_INSEL_S) +#define MCPWM_DT1_RED_INSEL_V 0x00000001U +#define MCPWM_DT1_RED_INSEL_S 11 +/** MCPWM_DT1_FED_INSEL : R/W; bitpos: [12]; default: 0; + * S5 in table + */ +#define MCPWM_DT1_FED_INSEL (BIT(12)) +#define MCPWM_DT1_FED_INSEL_M (MCPWM_DT1_FED_INSEL_V << MCPWM_DT1_FED_INSEL_S) +#define MCPWM_DT1_FED_INSEL_V 0x00000001U +#define MCPWM_DT1_FED_INSEL_S 12 +/** MCPWM_DT1_RED_OUTINVERT : R/W; bitpos: [13]; default: 0; + * S2 in table + */ +#define MCPWM_DT1_RED_OUTINVERT (BIT(13)) +#define MCPWM_DT1_RED_OUTINVERT_M (MCPWM_DT1_RED_OUTINVERT_V << MCPWM_DT1_RED_OUTINVERT_S) +#define MCPWM_DT1_RED_OUTINVERT_V 0x00000001U +#define MCPWM_DT1_RED_OUTINVERT_S 13 +/** MCPWM_DT1_FED_OUTINVERT : R/W; bitpos: [14]; default: 0; + * S3 in table + */ +#define MCPWM_DT1_FED_OUTINVERT (BIT(14)) +#define MCPWM_DT1_FED_OUTINVERT_M (MCPWM_DT1_FED_OUTINVERT_V << MCPWM_DT1_FED_OUTINVERT_S) +#define MCPWM_DT1_FED_OUTINVERT_V 0x00000001U +#define MCPWM_DT1_FED_OUTINVERT_S 14 +/** MCPWM_DT1_A_OUTBYPASS : R/W; bitpos: [15]; default: 1; + * S1 in table + */ +#define MCPWM_DT1_A_OUTBYPASS (BIT(15)) +#define MCPWM_DT1_A_OUTBYPASS_M (MCPWM_DT1_A_OUTBYPASS_V << MCPWM_DT1_A_OUTBYPASS_S) +#define MCPWM_DT1_A_OUTBYPASS_V 0x00000001U +#define MCPWM_DT1_A_OUTBYPASS_S 15 +/** MCPWM_DT1_B_OUTBYPASS : R/W; bitpos: [16]; default: 1; + * S0 in table + */ +#define MCPWM_DT1_B_OUTBYPASS (BIT(16)) +#define MCPWM_DT1_B_OUTBYPASS_M (MCPWM_DT1_B_OUTBYPASS_V << MCPWM_DT1_B_OUTBYPASS_S) +#define MCPWM_DT1_B_OUTBYPASS_V 0x00000001U +#define MCPWM_DT1_B_OUTBYPASS_S 16 +/** MCPWM_DT1_CLK_SEL : R/W; bitpos: [17]; default: 0; + * Dead time clock selection. 0: PWM_clk, 1: PT_clk + */ +#define MCPWM_DT1_CLK_SEL (BIT(17)) +#define MCPWM_DT1_CLK_SEL_M (MCPWM_DT1_CLK_SEL_V << MCPWM_DT1_CLK_SEL_S) +#define MCPWM_DT1_CLK_SEL_V 0x00000001U +#define MCPWM_DT1_CLK_SEL_S 17 -#define MCPWM_DB1_FED_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x94) -/* MCPWM_DB1_FED : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: .*/ -#define MCPWM_DB1_FED 0x0000FFFF -#define MCPWM_DB1_FED_M ((MCPWM_DB1_FED_V)<<(MCPWM_DB1_FED_S)) -#define MCPWM_DB1_FED_V 0xFFFF -#define MCPWM_DB1_FED_S 0 +/** MCPWM_DT1_FED_CFG_REG register + * PWM generator 1 shadow register for falling edge delay (FED). + */ +#define MCPWM_DT1_FED_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x94) +/** MCPWM_DT1_FED : R/W; bitpos: [15:0]; default: 0; + * Shadow register for FED + */ +#define MCPWM_DT1_FED 0x0000FFFFU +#define MCPWM_DT1_FED_M (MCPWM_DT1_FED_V << MCPWM_DT1_FED_S) +#define MCPWM_DT1_FED_V 0x0000FFFFU +#define MCPWM_DT1_FED_S 0 -#define MCPWM_DB1_RED_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x98) -/* MCPWM_DB1_RED : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: .*/ -#define MCPWM_DB1_RED 0x0000FFFF -#define MCPWM_DB1_RED_M ((MCPWM_DB1_RED_V)<<(MCPWM_DB1_RED_S)) -#define MCPWM_DB1_RED_V 0xFFFF -#define MCPWM_DB1_RED_S 0 +/** MCPWM_DT1_RED_CFG_REG register + * PWM generator 1 shadow register for rising edge delay (RED). + */ +#define MCPWM_DT1_RED_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x98) +/** MCPWM_DT1_RED : R/W; bitpos: [15:0]; default: 0; + * Shadow register for RED + */ +#define MCPWM_DT1_RED 0x0000FFFFU +#define MCPWM_DT1_RED_M (MCPWM_DT1_RED_V << MCPWM_DT1_RED_S) +#define MCPWM_DT1_RED_V 0x0000FFFFU +#define MCPWM_DT1_RED_S 0 -#define MCPWM_CHOPPER1_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x9C) -/* MCPWM_CHOPPER1_IN_INVERT : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER1_IN_INVERT (BIT(13)) -#define MCPWM_CHOPPER1_IN_INVERT_M (BIT(13)) -#define MCPWM_CHOPPER1_IN_INVERT_V 0x1 -#define MCPWM_CHOPPER1_IN_INVERT_S 13 -/* MCPWM_CHOPPER1_OUT_INVERT : R/W ;bitpos:[12] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER1_OUT_INVERT (BIT(12)) -#define MCPWM_CHOPPER1_OUT_INVERT_M (BIT(12)) -#define MCPWM_CHOPPER1_OUT_INVERT_V 0x1 -#define MCPWM_CHOPPER1_OUT_INVERT_S 12 -/* MCPWM_CHOPPER1_OSHTWTH : R/W ;bitpos:[11:8] ;default: 4'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER1_OSHTWTH 0x0000000F -#define MCPWM_CHOPPER1_OSHTWTH_M ((MCPWM_CHOPPER1_OSHTWTH_V)<<(MCPWM_CHOPPER1_OSHTWTH_S)) -#define MCPWM_CHOPPER1_OSHTWTH_V 0xF -#define MCPWM_CHOPPER1_OSHTWTH_S 8 -/* MCPWM_CHOPPER1_DUTY : R/W ;bitpos:[7:5] ;default: 3'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER1_DUTY 0x00000007 -#define MCPWM_CHOPPER1_DUTY_M ((MCPWM_CHOPPER1_DUTY_V)<<(MCPWM_CHOPPER1_DUTY_S)) -#define MCPWM_CHOPPER1_DUTY_V 0x7 -#define MCPWM_CHOPPER1_DUTY_S 5 -/* MCPWM_CHOPPER1_PRESCALE : R/W ;bitpos:[4:1] ;default: 4'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER1_PRESCALE 0x0000000F -#define MCPWM_CHOPPER1_PRESCALE_M ((MCPWM_CHOPPER1_PRESCALE_V)<<(MCPWM_CHOPPER1_PRESCALE_S)) -#define MCPWM_CHOPPER1_PRESCALE_V 0xF -#define MCPWM_CHOPPER1_PRESCALE_S 1 -/* MCPWM_CHOPPER1_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER1_EN (BIT(0)) -#define MCPWM_CHOPPER1_EN_M (BIT(0)) -#define MCPWM_CHOPPER1_EN_V 0x1 -#define MCPWM_CHOPPER1_EN_S 0 +/** MCPWM_CARRIER1_CFG_REG register + * PWM generator 1 carrier enable and configuratoin + */ +#define MCPWM_CARRIER1_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x9c) +/** MCPWM_CARRIER1_EN : R/W; bitpos: [0]; default: 0; + * When set, carrier1 function is enabled. When cleared, carrier1 is bypassed + */ +#define MCPWM_CARRIER1_EN (BIT(0)) +#define MCPWM_CARRIER1_EN_M (MCPWM_CARRIER1_EN_V << MCPWM_CARRIER1_EN_S) +#define MCPWM_CARRIER1_EN_V 0x00000001U +#define MCPWM_CARRIER1_EN_S 0 +/** MCPWM_CARRIER1_PRESCALE : R/W; bitpos: [4:1]; default: 0; + * PWM carrier1 clock (PC_clk) prescale value. Period of PC_clk = period of PWM_clk * + * (PWM_CARRIER0_PRESCALE + 1) + */ +#define MCPWM_CARRIER1_PRESCALE 0x0000000FU +#define MCPWM_CARRIER1_PRESCALE_M (MCPWM_CARRIER1_PRESCALE_V << MCPWM_CARRIER1_PRESCALE_S) +#define MCPWM_CARRIER1_PRESCALE_V 0x0000000FU +#define MCPWM_CARRIER1_PRESCALE_S 1 +/** MCPWM_CARRIER1_DUTY : R/W; bitpos: [7:5]; default: 0; + * carrier duty selection. Duty = PWM_CARRIER0_DUTY / 8 + */ +#define MCPWM_CARRIER1_DUTY 0x00000007U +#define MCPWM_CARRIER1_DUTY_M (MCPWM_CARRIER1_DUTY_V << MCPWM_CARRIER1_DUTY_S) +#define MCPWM_CARRIER1_DUTY_V 0x00000007U +#define MCPWM_CARRIER1_DUTY_S 5 +/** MCPWM_CARRIER1_OSHTWTH : R/W; bitpos: [11:8]; default: 0; + * width of the first pulse in number of periods of the carrier + */ +#define MCPWM_CARRIER1_OSHTWTH 0x0000000FU +#define MCPWM_CARRIER1_OSHTWTH_M (MCPWM_CARRIER1_OSHTWTH_V << MCPWM_CARRIER1_OSHTWTH_S) +#define MCPWM_CARRIER1_OSHTWTH_V 0x0000000FU +#define MCPWM_CARRIER1_OSHTWTH_S 8 +/** MCPWM_CARRIER1_OUT_INVERT : R/W; bitpos: [12]; default: 0; + * when set, invert the output of PWM1A and PWM1B for this submodule + */ +#define MCPWM_CARRIER1_OUT_INVERT (BIT(12)) +#define MCPWM_CARRIER1_OUT_INVERT_M (MCPWM_CARRIER1_OUT_INVERT_V << MCPWM_CARRIER1_OUT_INVERT_S) +#define MCPWM_CARRIER1_OUT_INVERT_V 0x00000001U +#define MCPWM_CARRIER1_OUT_INVERT_S 12 +/** MCPWM_CARRIER1_IN_INVERT : R/W; bitpos: [13]; default: 0; + * when set, invert the input of PWM1A and PWM1B for this submodule + */ +#define MCPWM_CARRIER1_IN_INVERT (BIT(13)) +#define MCPWM_CARRIER1_IN_INVERT_M (MCPWM_CARRIER1_IN_INVERT_V << MCPWM_CARRIER1_IN_INVERT_S) +#define MCPWM_CARRIER1_IN_INVERT_V 0x00000001U +#define MCPWM_CARRIER1_IN_INVERT_S 13 -#define MCPWM_TZ1_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0xA0) -/* MCPWM_TZ1_B_OST_U : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ1_B_OST_U 0x00000003 -#define MCPWM_TZ1_B_OST_U_M ((MCPWM_TZ1_B_OST_U_V)<<(MCPWM_TZ1_B_OST_U_S)) -#define MCPWM_TZ1_B_OST_U_V 0x3 -#define MCPWM_TZ1_B_OST_U_S 22 -/* MCPWM_TZ1_B_OST_D : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ1_B_OST_D 0x00000003 -#define MCPWM_TZ1_B_OST_D_M ((MCPWM_TZ1_B_OST_D_V)<<(MCPWM_TZ1_B_OST_D_S)) -#define MCPWM_TZ1_B_OST_D_V 0x3 -#define MCPWM_TZ1_B_OST_D_S 20 -/* MCPWM_TZ1_B_CBC_U : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ1_B_CBC_U 0x00000003 -#define MCPWM_TZ1_B_CBC_U_M ((MCPWM_TZ1_B_CBC_U_V)<<(MCPWM_TZ1_B_CBC_U_S)) -#define MCPWM_TZ1_B_CBC_U_V 0x3 -#define MCPWM_TZ1_B_CBC_U_S 18 -/* MCPWM_TZ1_B_CBC_D : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ1_B_CBC_D 0x00000003 -#define MCPWM_TZ1_B_CBC_D_M ((MCPWM_TZ1_B_CBC_D_V)<<(MCPWM_TZ1_B_CBC_D_S)) -#define MCPWM_TZ1_B_CBC_D_V 0x3 -#define MCPWM_TZ1_B_CBC_D_S 16 -/* MCPWM_TZ1_A_OST_U : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ1_A_OST_U 0x00000003 -#define MCPWM_TZ1_A_OST_U_M ((MCPWM_TZ1_A_OST_U_V)<<(MCPWM_TZ1_A_OST_U_S)) -#define MCPWM_TZ1_A_OST_U_V 0x3 -#define MCPWM_TZ1_A_OST_U_S 14 -/* MCPWM_TZ1_A_OST_D : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ1_A_OST_D 0x00000003 -#define MCPWM_TZ1_A_OST_D_M ((MCPWM_TZ1_A_OST_D_V)<<(MCPWM_TZ1_A_OST_D_S)) -#define MCPWM_TZ1_A_OST_D_V 0x3 -#define MCPWM_TZ1_A_OST_D_S 12 -/* MCPWM_TZ1_A_CBC_U : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ1_A_CBC_U 0x00000003 -#define MCPWM_TZ1_A_CBC_U_M ((MCPWM_TZ1_A_CBC_U_V)<<(MCPWM_TZ1_A_CBC_U_S)) -#define MCPWM_TZ1_A_CBC_U_V 0x3 -#define MCPWM_TZ1_A_CBC_U_S 10 -/* MCPWM_TZ1_A_CBC_D : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ1_A_CBC_D 0x00000003 -#define MCPWM_TZ1_A_CBC_D_M ((MCPWM_TZ1_A_CBC_D_V)<<(MCPWM_TZ1_A_CBC_D_S)) -#define MCPWM_TZ1_A_CBC_D_V 0x3 -#define MCPWM_TZ1_A_CBC_D_S 8 -/* MCPWM_TZ1_F0_OST : R/W ;bitpos:[7] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ1_F0_OST (BIT(7)) -#define MCPWM_TZ1_F0_OST_M (BIT(7)) -#define MCPWM_TZ1_F0_OST_V 0x1 -#define MCPWM_TZ1_F0_OST_S 7 -/* MCPWM_TZ1_F1_OST : R/W ;bitpos:[6] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ1_F1_OST (BIT(6)) -#define MCPWM_TZ1_F1_OST_M (BIT(6)) -#define MCPWM_TZ1_F1_OST_V 0x1 -#define MCPWM_TZ1_F1_OST_S 6 -/* MCPWM_TZ1_F2_OST : R/W ;bitpos:[5] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ1_F2_OST (BIT(5)) -#define MCPWM_TZ1_F2_OST_M (BIT(5)) -#define MCPWM_TZ1_F2_OST_V 0x1 -#define MCPWM_TZ1_F2_OST_S 5 -/* MCPWM_TZ1_SW_OST : R/W ;bitpos:[4] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ1_SW_OST (BIT(4)) -#define MCPWM_TZ1_SW_OST_M (BIT(4)) -#define MCPWM_TZ1_SW_OST_V 0x1 -#define MCPWM_TZ1_SW_OST_S 4 -/* MCPWM_TZ1_F0_CBC : R/W ;bitpos:[3] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ1_F0_CBC (BIT(3)) -#define MCPWM_TZ1_F0_CBC_M (BIT(3)) -#define MCPWM_TZ1_F0_CBC_V 0x1 -#define MCPWM_TZ1_F0_CBC_S 3 -/* MCPWM_TZ1_F1_CBC : R/W ;bitpos:[2] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ1_F1_CBC (BIT(2)) -#define MCPWM_TZ1_F1_CBC_M (BIT(2)) -#define MCPWM_TZ1_F1_CBC_V 0x1 -#define MCPWM_TZ1_F1_CBC_S 2 -/* MCPWM_TZ1_F2_CBC : R/W ;bitpos:[1] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ1_F2_CBC (BIT(1)) -#define MCPWM_TZ1_F2_CBC_M (BIT(1)) -#define MCPWM_TZ1_F2_CBC_V 0x1 -#define MCPWM_TZ1_F2_CBC_S 1 -/* MCPWM_TZ1_SW_CBC : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ1_SW_CBC (BIT(0)) -#define MCPWM_TZ1_SW_CBC_M (BIT(0)) -#define MCPWM_TZ1_SW_CBC_V 0x1 -#define MCPWM_TZ1_SW_CBC_S 0 +/** MCPWM_FH1_CFG0_REG register + * Actions on PWM1A and PWM1B trip events + */ +#define MCPWM_FH1_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0xa0) +/** MCPWM_FH1_SW_CBC : R/W; bitpos: [0]; default: 0; + * Enable register for software force cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH1_SW_CBC (BIT(0)) +#define MCPWM_FH1_SW_CBC_M (MCPWM_FH1_SW_CBC_V << MCPWM_FH1_SW_CBC_S) +#define MCPWM_FH1_SW_CBC_V 0x00000001U +#define MCPWM_FH1_SW_CBC_S 0 +/** MCPWM_FH1_F2_CBC : R/W; bitpos: [1]; default: 0; + * fault_event2 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH1_F2_CBC (BIT(1)) +#define MCPWM_FH1_F2_CBC_M (MCPWM_FH1_F2_CBC_V << MCPWM_FH1_F2_CBC_S) +#define MCPWM_FH1_F2_CBC_V 0x00000001U +#define MCPWM_FH1_F2_CBC_S 1 +/** MCPWM_FH1_F1_CBC : R/W; bitpos: [2]; default: 0; + * fault_event1 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH1_F1_CBC (BIT(2)) +#define MCPWM_FH1_F1_CBC_M (MCPWM_FH1_F1_CBC_V << MCPWM_FH1_F1_CBC_S) +#define MCPWM_FH1_F1_CBC_V 0x00000001U +#define MCPWM_FH1_F1_CBC_S 2 +/** MCPWM_FH1_F0_CBC : R/W; bitpos: [3]; default: 0; + * fault_event0 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH1_F0_CBC (BIT(3)) +#define MCPWM_FH1_F0_CBC_M (MCPWM_FH1_F0_CBC_V << MCPWM_FH1_F0_CBC_S) +#define MCPWM_FH1_F0_CBC_V 0x00000001U +#define MCPWM_FH1_F0_CBC_S 3 +/** MCPWM_FH1_SW_OST : R/W; bitpos: [4]; default: 0; + * Enable register for software force one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH1_SW_OST (BIT(4)) +#define MCPWM_FH1_SW_OST_M (MCPWM_FH1_SW_OST_V << MCPWM_FH1_SW_OST_S) +#define MCPWM_FH1_SW_OST_V 0x00000001U +#define MCPWM_FH1_SW_OST_S 4 +/** MCPWM_FH1_F2_OST : R/W; bitpos: [5]; default: 0; + * fault_event2 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH1_F2_OST (BIT(5)) +#define MCPWM_FH1_F2_OST_M (MCPWM_FH1_F2_OST_V << MCPWM_FH1_F2_OST_S) +#define MCPWM_FH1_F2_OST_V 0x00000001U +#define MCPWM_FH1_F2_OST_S 5 +/** MCPWM_FH1_F1_OST : R/W; bitpos: [6]; default: 0; + * fault_event1 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH1_F1_OST (BIT(6)) +#define MCPWM_FH1_F1_OST_M (MCPWM_FH1_F1_OST_V << MCPWM_FH1_F1_OST_S) +#define MCPWM_FH1_F1_OST_V 0x00000001U +#define MCPWM_FH1_F1_OST_S 6 +/** MCPWM_FH1_F0_OST : R/W; bitpos: [7]; default: 0; + * fault_event0 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH1_F0_OST (BIT(7)) +#define MCPWM_FH1_F0_OST_M (MCPWM_FH1_F0_OST_V << MCPWM_FH1_F0_OST_S) +#define MCPWM_FH1_F0_OST_V 0x00000001U +#define MCPWM_FH1_F0_OST_S 7 +/** MCPWM_FH1_A_CBC_D : R/W; bitpos: [9:8]; default: 0; + * Cycle-by-cycle mode action on PWM1A when fault event occurs and timer is + * decreasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH1_A_CBC_D 0x00000003U +#define MCPWM_FH1_A_CBC_D_M (MCPWM_FH1_A_CBC_D_V << MCPWM_FH1_A_CBC_D_S) +#define MCPWM_FH1_A_CBC_D_V 0x00000003U +#define MCPWM_FH1_A_CBC_D_S 8 +/** MCPWM_FH1_A_CBC_U : R/W; bitpos: [11:10]; default: 0; + * Cycle-by-cycle mode action on PWM1A when fault event occurs and timer is + * increasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH1_A_CBC_U 0x00000003U +#define MCPWM_FH1_A_CBC_U_M (MCPWM_FH1_A_CBC_U_V << MCPWM_FH1_A_CBC_U_S) +#define MCPWM_FH1_A_CBC_U_V 0x00000003U +#define MCPWM_FH1_A_CBC_U_S 10 +/** MCPWM_FH1_A_OST_D : R/W; bitpos: [13:12]; default: 0; + * One-shot mode action on PWM1A when fault event occurs and timer is decreasing. 0: + * do nothing,1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH1_A_OST_D 0x00000003U +#define MCPWM_FH1_A_OST_D_M (MCPWM_FH1_A_OST_D_V << MCPWM_FH1_A_OST_D_S) +#define MCPWM_FH1_A_OST_D_V 0x00000003U +#define MCPWM_FH1_A_OST_D_S 12 +/** MCPWM_FH1_A_OST_U : R/W; bitpos: [15:14]; default: 0; + * One-shot mode action on PWM1A when fault event occurs and timer is increasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH1_A_OST_U 0x00000003U +#define MCPWM_FH1_A_OST_U_M (MCPWM_FH1_A_OST_U_V << MCPWM_FH1_A_OST_U_S) +#define MCPWM_FH1_A_OST_U_V 0x00000003U +#define MCPWM_FH1_A_OST_U_S 14 +/** MCPWM_FH1_B_CBC_D : R/W; bitpos: [17:16]; default: 0; + * Cycle-by-cycle mode action on PWM1B when fault event occurs and timer is + * decreasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH1_B_CBC_D 0x00000003U +#define MCPWM_FH1_B_CBC_D_M (MCPWM_FH1_B_CBC_D_V << MCPWM_FH1_B_CBC_D_S) +#define MCPWM_FH1_B_CBC_D_V 0x00000003U +#define MCPWM_FH1_B_CBC_D_S 16 +/** MCPWM_FH1_B_CBC_U : R/W; bitpos: [19:18]; default: 0; + * Cycle-by-cycle mode action on PWM1B when fault event occurs and timer is + * increasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH1_B_CBC_U 0x00000003U +#define MCPWM_FH1_B_CBC_U_M (MCPWM_FH1_B_CBC_U_V << MCPWM_FH1_B_CBC_U_S) +#define MCPWM_FH1_B_CBC_U_V 0x00000003U +#define MCPWM_FH1_B_CBC_U_S 18 +/** MCPWM_FH1_B_OST_D : R/W; bitpos: [21:20]; default: 0; + * One-shot mode action on PWM1B when fault event occurs and timer is decreasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH1_B_OST_D 0x00000003U +#define MCPWM_FH1_B_OST_D_M (MCPWM_FH1_B_OST_D_V << MCPWM_FH1_B_OST_D_S) +#define MCPWM_FH1_B_OST_D_V 0x00000003U +#define MCPWM_FH1_B_OST_D_S 20 +/** MCPWM_FH1_B_OST_U : R/W; bitpos: [23:22]; default: 0; + * One-shot mode action on PWM1B when fault event occurs and timer is increasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH1_B_OST_U 0x00000003U +#define MCPWM_FH1_B_OST_U_M (MCPWM_FH1_B_OST_U_V << MCPWM_FH1_B_OST_U_S) +#define MCPWM_FH1_B_OST_U_V 0x00000003U +#define MCPWM_FH1_B_OST_U_S 22 -#define MCPWM_TZ1_CFG1_REG(i) (REG_MCPWM_BASE(i) + 0xA4) -/* MCPWM_TZ1_FORCE_OST : R/W ;bitpos:[4] ;default: 1'd0 ; */ -/*description: a toggle trigger a oneshot tripping.*/ -#define MCPWM_TZ1_FORCE_OST (BIT(4)) -#define MCPWM_TZ1_FORCE_OST_M (BIT(4)) -#define MCPWM_TZ1_FORCE_OST_V 0x1 -#define MCPWM_TZ1_FORCE_OST_S 4 -/* MCPWM_TZ1_FORCE_CBC : R/W ;bitpos:[3] ;default: 1'd0 ; */ -/*description: a toggle trigger a cycle-by-cycle tripping.*/ -#define MCPWM_TZ1_FORCE_CBC (BIT(3)) -#define MCPWM_TZ1_FORCE_CBC_M (BIT(3)) -#define MCPWM_TZ1_FORCE_CBC_V 0x1 -#define MCPWM_TZ1_FORCE_CBC_S 3 -/* MCPWM_TZ1_CBCPULSE : R/W ;bitpos:[2:1] ;default: 2'd0 ; */ -/*description: bit0: tez, bit1: tep.*/ -#define MCPWM_TZ1_CBCPULSE 0x00000003 -#define MCPWM_TZ1_CBCPULSE_M ((MCPWM_TZ1_CBCPULSE_V)<<(MCPWM_TZ1_CBCPULSE_S)) -#define MCPWM_TZ1_CBCPULSE_V 0x3 -#define MCPWM_TZ1_CBCPULSE_S 1 -/* MCPWM_TZ1_CLR_OST : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: a toggle will clear oneshot tripping.*/ -#define MCPWM_TZ1_CLR_OST (BIT(0)) -#define MCPWM_TZ1_CLR_OST_M (BIT(0)) -#define MCPWM_TZ1_CLR_OST_V 0x1 -#define MCPWM_TZ1_CLR_OST_S 0 +/** MCPWM_FH1_CFG1_REG register + * Software triggers for fault handler actions + */ +#define MCPWM_FH1_CFG1_REG(i) (DR_REG_MCPWM_BASE(i) + 0xa4) +/** MCPWM_FH1_CLR_OST : R/W; bitpos: [0]; default: 0; + * a rising edge will clear on going one-shot mode action + */ +#define MCPWM_FH1_CLR_OST (BIT(0)) +#define MCPWM_FH1_CLR_OST_M (MCPWM_FH1_CLR_OST_V << MCPWM_FH1_CLR_OST_S) +#define MCPWM_FH1_CLR_OST_V 0x00000001U +#define MCPWM_FH1_CLR_OST_S 0 +/** MCPWM_FH1_CBCPULSE : R/W; bitpos: [2:1]; default: 0; + * cycle-by-cycle mode action refresh moment selection. When bit0 is set to 1: TEZ, + * when bit1 is set to 1:TEP + */ +#define MCPWM_FH1_CBCPULSE 0x00000003U +#define MCPWM_FH1_CBCPULSE_M (MCPWM_FH1_CBCPULSE_V << MCPWM_FH1_CBCPULSE_S) +#define MCPWM_FH1_CBCPULSE_V 0x00000003U +#define MCPWM_FH1_CBCPULSE_S 1 +/** MCPWM_FH1_FORCE_CBC : R/W; bitpos: [3]; default: 0; + * a toggle trigger a cycle-by-cycle mode action + */ +#define MCPWM_FH1_FORCE_CBC (BIT(3)) +#define MCPWM_FH1_FORCE_CBC_M (MCPWM_FH1_FORCE_CBC_V << MCPWM_FH1_FORCE_CBC_S) +#define MCPWM_FH1_FORCE_CBC_V 0x00000001U +#define MCPWM_FH1_FORCE_CBC_S 3 +/** MCPWM_FH1_FORCE_OST : R/W; bitpos: [4]; default: 0; + * a toggle (software negate its value) triggers a one-shot mode action + */ +#define MCPWM_FH1_FORCE_OST (BIT(4)) +#define MCPWM_FH1_FORCE_OST_M (MCPWM_FH1_FORCE_OST_V << MCPWM_FH1_FORCE_OST_S) +#define MCPWM_FH1_FORCE_OST_V 0x00000001U +#define MCPWM_FH1_FORCE_OST_S 4 -#define MCPWM_TZ1_STATUS_REG(i) (REG_MCPWM_BASE(i) + 0xA8) -/* MCPWM_TZ1_OST_ON : RO ;bitpos:[1] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ1_OST_ON (BIT(1)) -#define MCPWM_TZ1_OST_ON_M (BIT(1)) -#define MCPWM_TZ1_OST_ON_V 0x1 -#define MCPWM_TZ1_OST_ON_S 1 -/* MCPWM_TZ1_CBC_ON : RO ;bitpos:[0] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ1_CBC_ON (BIT(0)) -#define MCPWM_TZ1_CBC_ON_M (BIT(0)) -#define MCPWM_TZ1_CBC_ON_V 0x1 -#define MCPWM_TZ1_CBC_ON_S 0 +/** MCPWM_FH1_STATUS_REG register + * Status of fault events. + */ +#define MCPWM_FH1_STATUS_REG(i) (DR_REG_MCPWM_BASE(i) + 0xa8) +/** MCPWM_FH1_CBC_ON : RO; bitpos: [0]; default: 0; + * Set and reset by hardware. If set, a cycle-by-cycle mode action is on going + */ +#define MCPWM_FH1_CBC_ON (BIT(0)) +#define MCPWM_FH1_CBC_ON_M (MCPWM_FH1_CBC_ON_V << MCPWM_FH1_CBC_ON_S) +#define MCPWM_FH1_CBC_ON_V 0x00000001U +#define MCPWM_FH1_CBC_ON_S 0 +/** MCPWM_FH1_OST_ON : RO; bitpos: [1]; default: 0; + * Set and reset by hardware. If set, an one-shot mode action is on going + */ +#define MCPWM_FH1_OST_ON (BIT(1)) +#define MCPWM_FH1_OST_ON_M (MCPWM_FH1_OST_ON_V << MCPWM_FH1_OST_ON_S) +#define MCPWM_FH1_OST_ON_V 0x00000001U +#define MCPWM_FH1_OST_ON_S 1 -#define MCPWM_CMPR2_CFG_REG(i) (REG_MCPWM_BASE(i) + 0xAC) -/* MCPWM_CMPR2_B_SHDW_FULL : R/W ;bitpos:[9] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR2_B_SHDW_FULL (BIT(9)) -#define MCPWM_CMPR2_B_SHDW_FULL_M (BIT(9)) -#define MCPWM_CMPR2_B_SHDW_FULL_V 0x1 -#define MCPWM_CMPR2_B_SHDW_FULL_S 9 -/* MCPWM_CMPR2_A_SHDW_FULL : R/W ;bitpos:[8] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR2_A_SHDW_FULL (BIT(8)) -#define MCPWM_CMPR2_A_SHDW_FULL_M (BIT(8)) -#define MCPWM_CMPR2_A_SHDW_FULL_V 0x1 -#define MCPWM_CMPR2_A_SHDW_FULL_S 8 -/* MCPWM_CMPR2_B_UPMETHOD : R/W ;bitpos:[7:4] ;default: 4'd0 ; */ -/*description: 0: immediate, bit0: tez, bit1: tep, bit2: sync, bit3: freeze.*/ -#define MCPWM_CMPR2_B_UPMETHOD 0x0000000F -#define MCPWM_CMPR2_B_UPMETHOD_M ((MCPWM_CMPR2_B_UPMETHOD_V)<<(MCPWM_CMPR2_B_UPMETHOD_S)) -#define MCPWM_CMPR2_B_UPMETHOD_V 0xF -#define MCPWM_CMPR2_B_UPMETHOD_S 4 -/* MCPWM_CMPR2_A_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: 0: immediate, bit0: tez, bit1: tep, bit2: sync, bit3: freeze.*/ -#define MCPWM_CMPR2_A_UPMETHOD 0x0000000F -#define MCPWM_CMPR2_A_UPMETHOD_M ((MCPWM_CMPR2_A_UPMETHOD_V)<<(MCPWM_CMPR2_A_UPMETHOD_S)) -#define MCPWM_CMPR2_A_UPMETHOD_V 0xF -#define MCPWM_CMPR2_A_UPMETHOD_S 0 +/** MCPWM_GEN2_STMP_CFG_REG register + * Transfer status and update method for time stamp registers A and B + */ +#define MCPWM_GEN2_STMP_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xac) +/** MCPWM_GEN2_A_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for PWM generator 2 time stamp A's active register. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when + * bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + */ +#define MCPWM_GEN2_A_UPMETHOD 0x0000000FU +#define MCPWM_GEN2_A_UPMETHOD_M (MCPWM_GEN2_A_UPMETHOD_V << MCPWM_GEN2_A_UPMETHOD_S) +#define MCPWM_GEN2_A_UPMETHOD_V 0x0000000FU +#define MCPWM_GEN2_A_UPMETHOD_S 0 +/** MCPWM_GEN2_B_UPMETHOD : R/W; bitpos: [7:4]; default: 0; + * Update method for PWM generator 2 time stamp B's active register. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when + * bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + */ +#define MCPWM_GEN2_B_UPMETHOD 0x0000000FU +#define MCPWM_GEN2_B_UPMETHOD_M (MCPWM_GEN2_B_UPMETHOD_V << MCPWM_GEN2_B_UPMETHOD_S) +#define MCPWM_GEN2_B_UPMETHOD_V 0x0000000FU +#define MCPWM_GEN2_B_UPMETHOD_S 4 +/** MCPWM_GEN2_A_SHDW_FULL : R/W/WTC/SC; bitpos: [8]; default: 0; + * Set and reset by hardware. If set, PWM generator 2 time stamp A's shadow reg is + * filled and waiting to be transferred to A's active reg. If cleared, A's active reg + * has been updated with shadow register latest value + */ +#define MCPWM_GEN2_A_SHDW_FULL (BIT(8)) +#define MCPWM_GEN2_A_SHDW_FULL_M (MCPWM_GEN2_A_SHDW_FULL_V << MCPWM_GEN2_A_SHDW_FULL_S) +#define MCPWM_GEN2_A_SHDW_FULL_V 0x00000001U +#define MCPWM_GEN2_A_SHDW_FULL_S 8 +/** MCPWM_GEN2_B_SHDW_FULL : R/W/WTC/SC; bitpos: [9]; default: 0; + * Set and reset by hardware. If set, PWM generator 2 time stamp B's shadow reg is + * filled and waiting to be transferred to B's active reg. If cleared, B's active reg + * has been updated with shadow register latest value + */ +#define MCPWM_GEN2_B_SHDW_FULL (BIT(9)) +#define MCPWM_GEN2_B_SHDW_FULL_M (MCPWM_GEN2_B_SHDW_FULL_V << MCPWM_GEN2_B_SHDW_FULL_S) +#define MCPWM_GEN2_B_SHDW_FULL_V 0x00000001U +#define MCPWM_GEN2_B_SHDW_FULL_S 9 -#define MCPWM_CMPR2_VALUE0_REG(i) (REG_MCPWM_BASE(i) + 0xB0) -/* MCPWM_CMPR2_A : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR2_A 0x0000FFFF -#define MCPWM_CMPR2_A_M ((MCPWM_CMPR2_A_V)<<(MCPWM_CMPR2_A_S)) -#define MCPWM_CMPR2_A_V 0xFFFF -#define MCPWM_CMPR2_A_S 0 +/** MCPWM_GEN2_TSTMP_A_REG register + * PWM generator 2 shadow register for timer stamp A. + */ +#define MCPWM_GEN2_TSTMP_A_REG(i) (DR_REG_MCPWM_BASE(i) + 0xb0) +/** MCPWM_GEN2_A : R/W; bitpos: [15:0]; default: 0; + * PWM generator 2 time stamp A's shadow register + */ +#define MCPWM_GEN2_A 0x0000FFFFU +#define MCPWM_GEN2_A_M (MCPWM_GEN2_A_V << MCPWM_GEN2_A_S) +#define MCPWM_GEN2_A_V 0x0000FFFFU +#define MCPWM_GEN2_A_S 0 -#define MCPWM_CMPR2_VALUE1_REG(i) (REG_MCPWM_BASE(i) + 0xB4) -/* MCPWM_CMPR2_B : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR2_B 0x0000FFFF -#define MCPWM_CMPR2_B_M ((MCPWM_CMPR2_B_V)<<(MCPWM_CMPR2_B_S)) -#define MCPWM_CMPR2_B_V 0xFFFF -#define MCPWM_CMPR2_B_S 0 +/** MCPWM_GEN2_TSTMP_B_REG register + * PWM generator 2 shadow register for timer stamp A. + */ +#define MCPWM_GEN2_TSTMP_B_REG(i) (DR_REG_MCPWM_BASE(i) + 0xb4) +/** MCPWM_GEN2_B : R/W; bitpos: [15:0]; default: 0; + * PWM generator 2 time stamp B's shadow register + */ +#define MCPWM_GEN2_B 0x0000FFFFU +#define MCPWM_GEN2_B_M (MCPWM_GEN2_B_V << MCPWM_GEN2_B_S) +#define MCPWM_GEN2_B_V 0x0000FFFFU +#define MCPWM_GEN2_B_S 0 -#define MCPWM_GEN2_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0xB8) -/* MCPWM_GEN2_T1_SEL : R/W ;bitpos:[9:7] ;default: 3'd0 ; */ -/*description: take effect immediately, 0: extra0, 1: extra1, 2: extra2, 3: sync_taken, 4: none.*/ -#define MCPWM_GEN2_T1_SEL 0x00000007 -#define MCPWM_GEN2_T1_SEL_M ((MCPWM_GEN2_T1_SEL_V)<<(MCPWM_GEN2_T1_SEL_S)) -#define MCPWM_GEN2_T1_SEL_V 0x7 -#define MCPWM_GEN2_T1_SEL_S 7 -/* MCPWM_GEN2_T0_SEL : R/W ;bitpos:[6:4] ;default: 3'd0 ; */ -/*description: take effect immediately, 0: extra0, 1: extra1, 2: extra2, 3: sync_taken, 4: none.*/ -#define MCPWM_GEN2_T0_SEL 0x00000007 -#define MCPWM_GEN2_T0_SEL_M ((MCPWM_GEN2_T0_SEL_V)<<(MCPWM_GEN2_T0_SEL_S)) -#define MCPWM_GEN2_T0_SEL_V 0x7 -#define MCPWM_GEN2_T0_SEL_S 4 -/* MCPWM_GEN2_CFG_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: 0: immediate, bit0: tez, bit1: tep, bit2: sync. bit3: freeze.*/ -#define MCPWM_GEN2_CFG_UPMETHOD 0x0000000F -#define MCPWM_GEN2_CFG_UPMETHOD_M ((MCPWM_GEN2_CFG_UPMETHOD_V)<<(MCPWM_GEN2_CFG_UPMETHOD_S)) -#define MCPWM_GEN2_CFG_UPMETHOD_V 0xF +/** MCPWM_GEN2_CFG0_REG register + * PWM generator 2 event T0 and T1 handling + */ +#define MCPWM_GEN2_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0xb8) +/** MCPWM_GEN2_CFG_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for PWM generator 2's active register of configuration. 0: + * immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1:sync;when bit3 is + * set to 1:disable the update. + */ +#define MCPWM_GEN2_CFG_UPMETHOD 0x0000000FU +#define MCPWM_GEN2_CFG_UPMETHOD_M (MCPWM_GEN2_CFG_UPMETHOD_V << MCPWM_GEN2_CFG_UPMETHOD_S) +#define MCPWM_GEN2_CFG_UPMETHOD_V 0x0000000FU #define MCPWM_GEN2_CFG_UPMETHOD_S 0 +/** MCPWM_GEN2_T0_SEL : R/W; bitpos: [6:4]; default: 0; + * Source selection for PWM generator 2 event_t0, take effect immediately, 0: + * fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + */ +#define MCPWM_GEN2_T0_SEL 0x00000007U +#define MCPWM_GEN2_T0_SEL_M (MCPWM_GEN2_T0_SEL_V << MCPWM_GEN2_T0_SEL_S) +#define MCPWM_GEN2_T0_SEL_V 0x00000007U +#define MCPWM_GEN2_T0_SEL_S 4 +/** MCPWM_GEN2_T1_SEL : R/W; bitpos: [9:7]; default: 0; + * Source selection for PWM generator 2 event_t1, take effect immediately, 0: + * fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + */ +#define MCPWM_GEN2_T1_SEL 0x00000007U +#define MCPWM_GEN2_T1_SEL_M (MCPWM_GEN2_T1_SEL_V << MCPWM_GEN2_T1_SEL_S) +#define MCPWM_GEN2_T1_SEL_V 0x00000007U +#define MCPWM_GEN2_T1_SEL_S 7 -#define MCPWM_GEN2_FORCE_REG(i) (REG_MCPWM_BASE(i) + 0xBC) -/* MCPWM_GEN2_B_NCIFORCE_MODE : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: 0: disabled, 1: low, 2: high, 3: disabled.*/ -#define MCPWM_GEN2_B_NCIFORCE_MODE 0x00000003 -#define MCPWM_GEN2_B_NCIFORCE_MODE_M ((MCPWM_GEN2_B_NCIFORCE_MODE_V)<<(MCPWM_GEN2_B_NCIFORCE_MODE_S)) -#define MCPWM_GEN2_B_NCIFORCE_MODE_V 0x3 -#define MCPWM_GEN2_B_NCIFORCE_MODE_S 14 -/* MCPWM_GEN2_B_NCIFORCE : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: non-continuous immediate sw force, a toggle will trigger a force event.*/ -#define MCPWM_GEN2_B_NCIFORCE (BIT(13)) -#define MCPWM_GEN2_B_NCIFORCE_M (BIT(13)) -#define MCPWM_GEN2_B_NCIFORCE_V 0x1 -#define MCPWM_GEN2_B_NCIFORCE_S 13 -/* MCPWM_GEN2_A_NCIFORCE_MODE : R/W ;bitpos:[12:11] ;default: 2'd0 ; */ -/*description: 0: disabled, 1: low, 2: high, 3: disabled.*/ -#define MCPWM_GEN2_A_NCIFORCE_MODE 0x00000003 -#define MCPWM_GEN2_A_NCIFORCE_MODE_M ((MCPWM_GEN2_A_NCIFORCE_MODE_V)<<(MCPWM_GEN2_A_NCIFORCE_MODE_S)) -#define MCPWM_GEN2_A_NCIFORCE_MODE_V 0x3 -#define MCPWM_GEN2_A_NCIFORCE_MODE_S 11 -/* MCPWM_GEN2_A_NCIFORCE : R/W ;bitpos:[10] ;default: 1'd0 ; */ -/*description: non-continuous immediate sw force, a toggle will trigger a force event.*/ -#define MCPWM_GEN2_A_NCIFORCE (BIT(10)) -#define MCPWM_GEN2_A_NCIFORCE_M (BIT(10)) -#define MCPWM_GEN2_A_NCIFORCE_V 0x1 -#define MCPWM_GEN2_A_NCIFORCE_S 10 -/* MCPWM_GEN2_B_CNTUFORCE_MODE : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: 0: disabled, 1: low, 2: high, 3: disabled.*/ -#define MCPWM_GEN2_B_CNTUFORCE_MODE 0x00000003 -#define MCPWM_GEN2_B_CNTUFORCE_MODE_M ((MCPWM_GEN2_B_CNTUFORCE_MODE_V)<<(MCPWM_GEN2_B_CNTUFORCE_MODE_S)) -#define MCPWM_GEN2_B_CNTUFORCE_MODE_V 0x3 -#define MCPWM_GEN2_B_CNTUFORCE_MODE_S 8 -/* MCPWM_GEN2_A_CNTUFORCE_MODE : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: 0: disabled, 1: low, 2: high, 3: disabled.*/ -#define MCPWM_GEN2_A_CNTUFORCE_MODE 0x00000003 -#define MCPWM_GEN2_A_CNTUFORCE_MODE_M ((MCPWM_GEN2_A_CNTUFORCE_MODE_V)<<(MCPWM_GEN2_A_CNTUFORCE_MODE_S)) -#define MCPWM_GEN2_A_CNTUFORCE_MODE_V 0x3 -#define MCPWM_GEN2_A_CNTUFORCE_MODE_S 6 -/* MCPWM_GEN2_CNTUFORCE_UPMETHOD : R/W ;bitpos:[5:0] ;default: 6'h20 ; */ -/*description: 0: immediate, bit0: tez, bit1: tep, bit2: tea, bit3: teb, bit4: sync, bit5: free -ze.*/ -#define MCPWM_GEN2_CNTUFORCE_UPMETHOD 0x0000003F -#define MCPWM_GEN2_CNTUFORCE_UPMETHOD_M ((MCPWM_GEN2_CNTUFORCE_UPMETHOD_V)<<(MCPWM_GEN2_CNTUFORCE_UPMETHOD_S)) -#define MCPWM_GEN2_CNTUFORCE_UPMETHOD_V 0x3F +/** MCPWM_GEN2_FORCE_REG register + * Permissives to force PWM2A and PWM2B outputs by software + */ +#define MCPWM_GEN2_FORCE_REG(i) (DR_REG_MCPWM_BASE(i) + 0xbc) +/** MCPWM_GEN2_CNTUFORCE_UPMETHOD : R/W; bitpos: [5:0]; default: 32; + * Updating method for continuous software force of PWM generator 2. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ,when bit1 is set to 1: TEP, when + * bit2 is set to 1: TEA, when bit3 is set to 1: TEB, when bit4 is set to 1: sync, + * when bit5 is set to 1: disable update. (TEA/B here and below means an event + * generated when the timer's value equals to that of register A/B.) + */ +#define MCPWM_GEN2_CNTUFORCE_UPMETHOD 0x0000003FU +#define MCPWM_GEN2_CNTUFORCE_UPMETHOD_M (MCPWM_GEN2_CNTUFORCE_UPMETHOD_V << MCPWM_GEN2_CNTUFORCE_UPMETHOD_S) +#define MCPWM_GEN2_CNTUFORCE_UPMETHOD_V 0x0000003FU #define MCPWM_GEN2_CNTUFORCE_UPMETHOD_S 0 +/** MCPWM_GEN2_A_CNTUFORCE_MODE : R/W; bitpos: [7:6]; default: 0; + * Continuous software force mode for PWM2A. 0: disabled, 1: low, 2: high, 3: disabled + */ +#define MCPWM_GEN2_A_CNTUFORCE_MODE 0x00000003U +#define MCPWM_GEN2_A_CNTUFORCE_MODE_M (MCPWM_GEN2_A_CNTUFORCE_MODE_V << MCPWM_GEN2_A_CNTUFORCE_MODE_S) +#define MCPWM_GEN2_A_CNTUFORCE_MODE_V 0x00000003U +#define MCPWM_GEN2_A_CNTUFORCE_MODE_S 6 +/** MCPWM_GEN2_B_CNTUFORCE_MODE : R/W; bitpos: [9:8]; default: 0; + * Continuous software force mode for PWM2B. 0: disabled, 1: low, 2: high, 3: disabled + */ +#define MCPWM_GEN2_B_CNTUFORCE_MODE 0x00000003U +#define MCPWM_GEN2_B_CNTUFORCE_MODE_M (MCPWM_GEN2_B_CNTUFORCE_MODE_V << MCPWM_GEN2_B_CNTUFORCE_MODE_S) +#define MCPWM_GEN2_B_CNTUFORCE_MODE_V 0x00000003U +#define MCPWM_GEN2_B_CNTUFORCE_MODE_S 8 +/** MCPWM_GEN2_A_NCIFORCE : R/W; bitpos: [10]; default: 0; + * Trigger of non-continuous immediate software-force event for PWM2A, a toggle will + * trigger a force event. + */ +#define MCPWM_GEN2_A_NCIFORCE (BIT(10)) +#define MCPWM_GEN2_A_NCIFORCE_M (MCPWM_GEN2_A_NCIFORCE_V << MCPWM_GEN2_A_NCIFORCE_S) +#define MCPWM_GEN2_A_NCIFORCE_V 0x00000001U +#define MCPWM_GEN2_A_NCIFORCE_S 10 +/** MCPWM_GEN2_A_NCIFORCE_MODE : R/W; bitpos: [12:11]; default: 0; + * non-continuous immediate software force mode for PWM2A, 0: disabled, 1: low, 2: + * high, 3: disabled + */ +#define MCPWM_GEN2_A_NCIFORCE_MODE 0x00000003U +#define MCPWM_GEN2_A_NCIFORCE_MODE_M (MCPWM_GEN2_A_NCIFORCE_MODE_V << MCPWM_GEN2_A_NCIFORCE_MODE_S) +#define MCPWM_GEN2_A_NCIFORCE_MODE_V 0x00000003U +#define MCPWM_GEN2_A_NCIFORCE_MODE_S 11 +/** MCPWM_GEN2_B_NCIFORCE : R/W; bitpos: [13]; default: 0; + * Trigger of non-continuous immediate software-force event for PWM2B, a toggle will + * trigger a force event. + */ +#define MCPWM_GEN2_B_NCIFORCE (BIT(13)) +#define MCPWM_GEN2_B_NCIFORCE_M (MCPWM_GEN2_B_NCIFORCE_V << MCPWM_GEN2_B_NCIFORCE_S) +#define MCPWM_GEN2_B_NCIFORCE_V 0x00000001U +#define MCPWM_GEN2_B_NCIFORCE_S 13 +/** MCPWM_GEN2_B_NCIFORCE_MODE : R/W; bitpos: [15:14]; default: 0; + * non-continuous immediate software force mode for PWM2B, 0: disabled, 1: low, 2: + * high, 3: disabled + */ +#define MCPWM_GEN2_B_NCIFORCE_MODE 0x00000003U +#define MCPWM_GEN2_B_NCIFORCE_MODE_M (MCPWM_GEN2_B_NCIFORCE_MODE_V << MCPWM_GEN2_B_NCIFORCE_MODE_S) +#define MCPWM_GEN2_B_NCIFORCE_MODE_V 0x00000003U +#define MCPWM_GEN2_B_NCIFORCE_MODE_S 14 -#define MCPWM_GEN2_A_REG(i) (REG_MCPWM_BASE(i) + 0xC0) -/* MCPWM_GEN2_A_DT1 : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: 0: no change, 1: low, 2: high, 3: toggle.*/ -#define MCPWM_GEN2_A_DT1 0x00000003 -#define MCPWM_GEN2_A_DT1_M ((MCPWM_GEN2_A_DT1_V)<<(MCPWM_GEN2_A_DT1_S)) -#define MCPWM_GEN2_A_DT1_V 0x3 -#define MCPWM_GEN2_A_DT1_S 22 -/* MCPWM_GEN2_A_DT0 : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_A_DT0 0x00000003 -#define MCPWM_GEN2_A_DT0_M ((MCPWM_GEN2_A_DT0_V)<<(MCPWM_GEN2_A_DT0_S)) -#define MCPWM_GEN2_A_DT0_V 0x3 -#define MCPWM_GEN2_A_DT0_S 20 -/* MCPWM_GEN2_A_DTEB : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_A_DTEB 0x00000003 -#define MCPWM_GEN2_A_DTEB_M ((MCPWM_GEN2_A_DTEB_V)<<(MCPWM_GEN2_A_DTEB_S)) -#define MCPWM_GEN2_A_DTEB_V 0x3 -#define MCPWM_GEN2_A_DTEB_S 18 -/* MCPWM_GEN2_A_DTEA : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_A_DTEA 0x00000003 -#define MCPWM_GEN2_A_DTEA_M ((MCPWM_GEN2_A_DTEA_V)<<(MCPWM_GEN2_A_DTEA_S)) -#define MCPWM_GEN2_A_DTEA_V 0x3 -#define MCPWM_GEN2_A_DTEA_S 16 -/* MCPWM_GEN2_A_DTEP : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_A_DTEP 0x00000003 -#define MCPWM_GEN2_A_DTEP_M ((MCPWM_GEN2_A_DTEP_V)<<(MCPWM_GEN2_A_DTEP_S)) -#define MCPWM_GEN2_A_DTEP_V 0x3 -#define MCPWM_GEN2_A_DTEP_S 14 -/* MCPWM_GEN2_A_DTEZ : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_A_DTEZ 0x00000003 -#define MCPWM_GEN2_A_DTEZ_M ((MCPWM_GEN2_A_DTEZ_V)<<(MCPWM_GEN2_A_DTEZ_S)) -#define MCPWM_GEN2_A_DTEZ_V 0x3 -#define MCPWM_GEN2_A_DTEZ_S 12 -/* MCPWM_GEN2_A_UT1 : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_A_UT1 0x00000003 -#define MCPWM_GEN2_A_UT1_M ((MCPWM_GEN2_A_UT1_V)<<(MCPWM_GEN2_A_UT1_S)) -#define MCPWM_GEN2_A_UT1_V 0x3 -#define MCPWM_GEN2_A_UT1_S 10 -/* MCPWM_GEN2_A_UT0 : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_A_UT0 0x00000003 -#define MCPWM_GEN2_A_UT0_M ((MCPWM_GEN2_A_UT0_V)<<(MCPWM_GEN2_A_UT0_S)) -#define MCPWM_GEN2_A_UT0_V 0x3 -#define MCPWM_GEN2_A_UT0_S 8 -/* MCPWM_GEN2_A_UTEB : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_A_UTEB 0x00000003 -#define MCPWM_GEN2_A_UTEB_M ((MCPWM_GEN2_A_UTEB_V)<<(MCPWM_GEN2_A_UTEB_S)) -#define MCPWM_GEN2_A_UTEB_V 0x3 -#define MCPWM_GEN2_A_UTEB_S 6 -/* MCPWM_GEN2_A_UTEA : R/W ;bitpos:[5:4] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_A_UTEA 0x00000003 -#define MCPWM_GEN2_A_UTEA_M ((MCPWM_GEN2_A_UTEA_V)<<(MCPWM_GEN2_A_UTEA_S)) -#define MCPWM_GEN2_A_UTEA_V 0x3 -#define MCPWM_GEN2_A_UTEA_S 4 -/* MCPWM_GEN2_A_UTEP : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_A_UTEP 0x00000003 -#define MCPWM_GEN2_A_UTEP_M ((MCPWM_GEN2_A_UTEP_V)<<(MCPWM_GEN2_A_UTEP_S)) -#define MCPWM_GEN2_A_UTEP_V 0x3 -#define MCPWM_GEN2_A_UTEP_S 2 -/* MCPWM_GEN2_A_UTEZ : R/W ;bitpos:[1:0] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_A_UTEZ 0x00000003 -#define MCPWM_GEN2_A_UTEZ_M ((MCPWM_GEN2_A_UTEZ_V)<<(MCPWM_GEN2_A_UTEZ_S)) -#define MCPWM_GEN2_A_UTEZ_V 0x3 +/** MCPWM_GEN2_A_REG register + * Actions triggered by events on PWM2A + */ +#define MCPWM_GEN2_A_REG(i) (DR_REG_MCPWM_BASE(i) + 0xc0) +/** MCPWM_GEN2_A_UTEZ : R/W; bitpos: [1:0]; default: 0; + * Action on PWM2A triggered by event TEZ when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_UTEZ 0x00000003U +#define MCPWM_GEN2_A_UTEZ_M (MCPWM_GEN2_A_UTEZ_V << MCPWM_GEN2_A_UTEZ_S) +#define MCPWM_GEN2_A_UTEZ_V 0x00000003U #define MCPWM_GEN2_A_UTEZ_S 0 +/** MCPWM_GEN2_A_UTEP : R/W; bitpos: [3:2]; default: 0; + * Action on PWM2A triggered by event TEP when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_UTEP 0x00000003U +#define MCPWM_GEN2_A_UTEP_M (MCPWM_GEN2_A_UTEP_V << MCPWM_GEN2_A_UTEP_S) +#define MCPWM_GEN2_A_UTEP_V 0x00000003U +#define MCPWM_GEN2_A_UTEP_S 2 +/** MCPWM_GEN2_A_UTEA : R/W; bitpos: [5:4]; default: 0; + * Action on PWM2A triggered by event TEA when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_UTEA 0x00000003U +#define MCPWM_GEN2_A_UTEA_M (MCPWM_GEN2_A_UTEA_V << MCPWM_GEN2_A_UTEA_S) +#define MCPWM_GEN2_A_UTEA_V 0x00000003U +#define MCPWM_GEN2_A_UTEA_S 4 +/** MCPWM_GEN2_A_UTEB : R/W; bitpos: [7:6]; default: 0; + * Action on PWM2A triggered by event TEB when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_UTEB 0x00000003U +#define MCPWM_GEN2_A_UTEB_M (MCPWM_GEN2_A_UTEB_V << MCPWM_GEN2_A_UTEB_S) +#define MCPWM_GEN2_A_UTEB_V 0x00000003U +#define MCPWM_GEN2_A_UTEB_S 6 +/** MCPWM_GEN2_A_UT0 : R/W; bitpos: [9:8]; default: 0; + * Action on PWM2A triggered by event_t0 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_UT0 0x00000003U +#define MCPWM_GEN2_A_UT0_M (MCPWM_GEN2_A_UT0_V << MCPWM_GEN2_A_UT0_S) +#define MCPWM_GEN2_A_UT0_V 0x00000003U +#define MCPWM_GEN2_A_UT0_S 8 +/** MCPWM_GEN2_A_UT1 : R/W; bitpos: [11:10]; default: 0; + * Action on PWM2A triggered by event_t1 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_UT1 0x00000003U +#define MCPWM_GEN2_A_UT1_M (MCPWM_GEN2_A_UT1_V << MCPWM_GEN2_A_UT1_S) +#define MCPWM_GEN2_A_UT1_V 0x00000003U +#define MCPWM_GEN2_A_UT1_S 10 +/** MCPWM_GEN2_A_DTEZ : R/W; bitpos: [13:12]; default: 0; + * Action on PWM2A triggered by event TEZ when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_DTEZ 0x00000003U +#define MCPWM_GEN2_A_DTEZ_M (MCPWM_GEN2_A_DTEZ_V << MCPWM_GEN2_A_DTEZ_S) +#define MCPWM_GEN2_A_DTEZ_V 0x00000003U +#define MCPWM_GEN2_A_DTEZ_S 12 +/** MCPWM_GEN2_A_DTEP : R/W; bitpos: [15:14]; default: 0; + * Action on PWM2A triggered by event TEP when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_DTEP 0x00000003U +#define MCPWM_GEN2_A_DTEP_M (MCPWM_GEN2_A_DTEP_V << MCPWM_GEN2_A_DTEP_S) +#define MCPWM_GEN2_A_DTEP_V 0x00000003U +#define MCPWM_GEN2_A_DTEP_S 14 +/** MCPWM_GEN2_A_DTEA : R/W; bitpos: [17:16]; default: 0; + * Action on PWM2A triggered by event TEA when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_DTEA 0x00000003U +#define MCPWM_GEN2_A_DTEA_M (MCPWM_GEN2_A_DTEA_V << MCPWM_GEN2_A_DTEA_S) +#define MCPWM_GEN2_A_DTEA_V 0x00000003U +#define MCPWM_GEN2_A_DTEA_S 16 +/** MCPWM_GEN2_A_DTEB : R/W; bitpos: [19:18]; default: 0; + * Action on PWM2A triggered by event TEB when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_DTEB 0x00000003U +#define MCPWM_GEN2_A_DTEB_M (MCPWM_GEN2_A_DTEB_V << MCPWM_GEN2_A_DTEB_S) +#define MCPWM_GEN2_A_DTEB_V 0x00000003U +#define MCPWM_GEN2_A_DTEB_S 18 +/** MCPWM_GEN2_A_DT0 : R/W; bitpos: [21:20]; default: 0; + * Action on PWM2A triggered by event_t0 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_DT0 0x00000003U +#define MCPWM_GEN2_A_DT0_M (MCPWM_GEN2_A_DT0_V << MCPWM_GEN2_A_DT0_S) +#define MCPWM_GEN2_A_DT0_V 0x00000003U +#define MCPWM_GEN2_A_DT0_S 20 +/** MCPWM_GEN2_A_DT1 : R/W; bitpos: [23:22]; default: 0; + * Action on PWM2A triggered by event_t1 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_A_DT1 0x00000003U +#define MCPWM_GEN2_A_DT1_M (MCPWM_GEN2_A_DT1_V << MCPWM_GEN2_A_DT1_S) +#define MCPWM_GEN2_A_DT1_V 0x00000003U +#define MCPWM_GEN2_A_DT1_S 22 -#define MCPWM_GEN2_B_REG(i) (REG_MCPWM_BASE(i) + 0xC4) -/* MCPWM_GEN2_B_DT1 : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_B_DT1 0x00000003 -#define MCPWM_GEN2_B_DT1_M ((MCPWM_GEN2_B_DT1_V)<<(MCPWM_GEN2_B_DT1_S)) -#define MCPWM_GEN2_B_DT1_V 0x3 -#define MCPWM_GEN2_B_DT1_S 22 -/* MCPWM_GEN2_B_DT0 : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_B_DT0 0x00000003 -#define MCPWM_GEN2_B_DT0_M ((MCPWM_GEN2_B_DT0_V)<<(MCPWM_GEN2_B_DT0_S)) -#define MCPWM_GEN2_B_DT0_V 0x3 -#define MCPWM_GEN2_B_DT0_S 20 -/* MCPWM_GEN2_B_DTEB : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_B_DTEB 0x00000003 -#define MCPWM_GEN2_B_DTEB_M ((MCPWM_GEN2_B_DTEB_V)<<(MCPWM_GEN2_B_DTEB_S)) -#define MCPWM_GEN2_B_DTEB_V 0x3 -#define MCPWM_GEN2_B_DTEB_S 18 -/* MCPWM_GEN2_B_DTEA : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_B_DTEA 0x00000003 -#define MCPWM_GEN2_B_DTEA_M ((MCPWM_GEN2_B_DTEA_V)<<(MCPWM_GEN2_B_DTEA_S)) -#define MCPWM_GEN2_B_DTEA_V 0x3 -#define MCPWM_GEN2_B_DTEA_S 16 -/* MCPWM_GEN2_B_DTEP : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_B_DTEP 0x00000003 -#define MCPWM_GEN2_B_DTEP_M ((MCPWM_GEN2_B_DTEP_V)<<(MCPWM_GEN2_B_DTEP_S)) -#define MCPWM_GEN2_B_DTEP_V 0x3 -#define MCPWM_GEN2_B_DTEP_S 14 -/* MCPWM_GEN2_B_DTEZ : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_B_DTEZ 0x00000003 -#define MCPWM_GEN2_B_DTEZ_M ((MCPWM_GEN2_B_DTEZ_V)<<(MCPWM_GEN2_B_DTEZ_S)) -#define MCPWM_GEN2_B_DTEZ_V 0x3 -#define MCPWM_GEN2_B_DTEZ_S 12 -/* MCPWM_GEN2_B_UT1 : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_B_UT1 0x00000003 -#define MCPWM_GEN2_B_UT1_M ((MCPWM_GEN2_B_UT1_V)<<(MCPWM_GEN2_B_UT1_S)) -#define MCPWM_GEN2_B_UT1_V 0x3 -#define MCPWM_GEN2_B_UT1_S 10 -/* MCPWM_GEN2_B_UT0 : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_B_UT0 0x00000003 -#define MCPWM_GEN2_B_UT0_M ((MCPWM_GEN2_B_UT0_V)<<(MCPWM_GEN2_B_UT0_S)) -#define MCPWM_GEN2_B_UT0_V 0x3 -#define MCPWM_GEN2_B_UT0_S 8 -/* MCPWM_GEN2_B_UTEB : R/W ;bitpos:[7:6] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_B_UTEB 0x00000003 -#define MCPWM_GEN2_B_UTEB_M ((MCPWM_GEN2_B_UTEB_V)<<(MCPWM_GEN2_B_UTEB_S)) -#define MCPWM_GEN2_B_UTEB_V 0x3 -#define MCPWM_GEN2_B_UTEB_S 6 -/* MCPWM_GEN2_B_UTEA : R/W ;bitpos:[5:4] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_B_UTEA 0x00000003 -#define MCPWM_GEN2_B_UTEA_M ((MCPWM_GEN2_B_UTEA_V)<<(MCPWM_GEN2_B_UTEA_S)) -#define MCPWM_GEN2_B_UTEA_V 0x3 -#define MCPWM_GEN2_B_UTEA_S 4 -/* MCPWM_GEN2_B_UTEP : R/W ;bitpos:[3:2] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_B_UTEP 0x00000003 -#define MCPWM_GEN2_B_UTEP_M ((MCPWM_GEN2_B_UTEP_V)<<(MCPWM_GEN2_B_UTEP_S)) -#define MCPWM_GEN2_B_UTEP_V 0x3 -#define MCPWM_GEN2_B_UTEP_S 2 -/* MCPWM_GEN2_B_UTEZ : R/W ;bitpos:[1:0] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_GEN2_B_UTEZ 0x00000003 -#define MCPWM_GEN2_B_UTEZ_M ((MCPWM_GEN2_B_UTEZ_V)<<(MCPWM_GEN2_B_UTEZ_S)) -#define MCPWM_GEN2_B_UTEZ_V 0x3 +/** MCPWM_GEN2_B_REG register + * Actions triggered by events on PWM2B + */ +#define MCPWM_GEN2_B_REG(i) (DR_REG_MCPWM_BASE(i) + 0xc4) +/** MCPWM_GEN2_B_UTEZ : R/W; bitpos: [1:0]; default: 0; + * Action on PWM2B triggered by event TEZ when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_UTEZ 0x00000003U +#define MCPWM_GEN2_B_UTEZ_M (MCPWM_GEN2_B_UTEZ_V << MCPWM_GEN2_B_UTEZ_S) +#define MCPWM_GEN2_B_UTEZ_V 0x00000003U #define MCPWM_GEN2_B_UTEZ_S 0 +/** MCPWM_GEN2_B_UTEP : R/W; bitpos: [3:2]; default: 0; + * Action on PWM2B triggered by event TEP when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_UTEP 0x00000003U +#define MCPWM_GEN2_B_UTEP_M (MCPWM_GEN2_B_UTEP_V << MCPWM_GEN2_B_UTEP_S) +#define MCPWM_GEN2_B_UTEP_V 0x00000003U +#define MCPWM_GEN2_B_UTEP_S 2 +/** MCPWM_GEN2_B_UTEA : R/W; bitpos: [5:4]; default: 0; + * Action on PWM2B triggered by event TEA when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_UTEA 0x00000003U +#define MCPWM_GEN2_B_UTEA_M (MCPWM_GEN2_B_UTEA_V << MCPWM_GEN2_B_UTEA_S) +#define MCPWM_GEN2_B_UTEA_V 0x00000003U +#define MCPWM_GEN2_B_UTEA_S 4 +/** MCPWM_GEN2_B_UTEB : R/W; bitpos: [7:6]; default: 0; + * Action on PWM2B triggered by event TEB when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_UTEB 0x00000003U +#define MCPWM_GEN2_B_UTEB_M (MCPWM_GEN2_B_UTEB_V << MCPWM_GEN2_B_UTEB_S) +#define MCPWM_GEN2_B_UTEB_V 0x00000003U +#define MCPWM_GEN2_B_UTEB_S 6 +/** MCPWM_GEN2_B_UT0 : R/W; bitpos: [9:8]; default: 0; + * Action on PWM2B triggered by event_t0 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_UT0 0x00000003U +#define MCPWM_GEN2_B_UT0_M (MCPWM_GEN2_B_UT0_V << MCPWM_GEN2_B_UT0_S) +#define MCPWM_GEN2_B_UT0_V 0x00000003U +#define MCPWM_GEN2_B_UT0_S 8 +/** MCPWM_GEN2_B_UT1 : R/W; bitpos: [11:10]; default: 0; + * Action on PWM2B triggered by event_t1 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_UT1 0x00000003U +#define MCPWM_GEN2_B_UT1_M (MCPWM_GEN2_B_UT1_V << MCPWM_GEN2_B_UT1_S) +#define MCPWM_GEN2_B_UT1_V 0x00000003U +#define MCPWM_GEN2_B_UT1_S 10 +/** MCPWM_GEN2_B_DTEZ : R/W; bitpos: [13:12]; default: 0; + * Action on PWM2B triggered by event TEZ when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_DTEZ 0x00000003U +#define MCPWM_GEN2_B_DTEZ_M (MCPWM_GEN2_B_DTEZ_V << MCPWM_GEN2_B_DTEZ_S) +#define MCPWM_GEN2_B_DTEZ_V 0x00000003U +#define MCPWM_GEN2_B_DTEZ_S 12 +/** MCPWM_GEN2_B_DTEP : R/W; bitpos: [15:14]; default: 0; + * Action on PWM2B triggered by event TEP when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_DTEP 0x00000003U +#define MCPWM_GEN2_B_DTEP_M (MCPWM_GEN2_B_DTEP_V << MCPWM_GEN2_B_DTEP_S) +#define MCPWM_GEN2_B_DTEP_V 0x00000003U +#define MCPWM_GEN2_B_DTEP_S 14 +/** MCPWM_GEN2_B_DTEA : R/W; bitpos: [17:16]; default: 0; + * Action on PWM2B triggered by event TEA when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_DTEA 0x00000003U +#define MCPWM_GEN2_B_DTEA_M (MCPWM_GEN2_B_DTEA_V << MCPWM_GEN2_B_DTEA_S) +#define MCPWM_GEN2_B_DTEA_V 0x00000003U +#define MCPWM_GEN2_B_DTEA_S 16 +/** MCPWM_GEN2_B_DTEB : R/W; bitpos: [19:18]; default: 0; + * Action on PWM2B triggered by event TEB when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_DTEB 0x00000003U +#define MCPWM_GEN2_B_DTEB_M (MCPWM_GEN2_B_DTEB_V << MCPWM_GEN2_B_DTEB_S) +#define MCPWM_GEN2_B_DTEB_V 0x00000003U +#define MCPWM_GEN2_B_DTEB_S 18 +/** MCPWM_GEN2_B_DT0 : R/W; bitpos: [21:20]; default: 0; + * Action on PWM2B triggered by event_t0 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_DT0 0x00000003U +#define MCPWM_GEN2_B_DT0_M (MCPWM_GEN2_B_DT0_V << MCPWM_GEN2_B_DT0_S) +#define MCPWM_GEN2_B_DT0_V 0x00000003U +#define MCPWM_GEN2_B_DT0_S 20 +/** MCPWM_GEN2_B_DT1 : R/W; bitpos: [23:22]; default: 0; + * Action on PWM2B triggered by event_t1 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ +#define MCPWM_GEN2_B_DT1 0x00000003U +#define MCPWM_GEN2_B_DT1_M (MCPWM_GEN2_B_DT1_V << MCPWM_GEN2_B_DT1_S) +#define MCPWM_GEN2_B_DT1_V 0x00000003U +#define MCPWM_GEN2_B_DT1_S 22 -#define MCPWM_DB2_CFG_REG(i) (REG_MCPWM_BASE(i) + 0xC8) -/* MCPWM_DB2_CLK_SEL : R/W ;bitpos:[17] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB2_CLK_SEL (BIT(17)) -#define MCPWM_DB2_CLK_SEL_M (BIT(17)) -#define MCPWM_DB2_CLK_SEL_V 0x1 -#define MCPWM_DB2_CLK_SEL_S 17 -/* MCPWM_DB2_B_OUTBYPASS : R/W ;bitpos:[16] ;default: 1'd1 ; */ -/*description: .*/ -#define MCPWM_DB2_B_OUTBYPASS (BIT(16)) -#define MCPWM_DB2_B_OUTBYPASS_M (BIT(16)) -#define MCPWM_DB2_B_OUTBYPASS_V 0x1 -#define MCPWM_DB2_B_OUTBYPASS_S 16 -/* MCPWM_DB2_A_OUTBYPASS : R/W ;bitpos:[15] ;default: 1'd1 ; */ -/*description: .*/ -#define MCPWM_DB2_A_OUTBYPASS (BIT(15)) -#define MCPWM_DB2_A_OUTBYPASS_M (BIT(15)) -#define MCPWM_DB2_A_OUTBYPASS_V 0x1 -#define MCPWM_DB2_A_OUTBYPASS_S 15 -/* MCPWM_DB2_FED_OUTINVERT : R/W ;bitpos:[14] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB2_FED_OUTINVERT (BIT(14)) -#define MCPWM_DB2_FED_OUTINVERT_M (BIT(14)) -#define MCPWM_DB2_FED_OUTINVERT_V 0x1 -#define MCPWM_DB2_FED_OUTINVERT_S 14 -/* MCPWM_DB2_RED_OUTINVERT : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB2_RED_OUTINVERT (BIT(13)) -#define MCPWM_DB2_RED_OUTINVERT_M (BIT(13)) -#define MCPWM_DB2_RED_OUTINVERT_V 0x1 -#define MCPWM_DB2_RED_OUTINVERT_S 13 -/* MCPWM_DB2_FED_INSEL : R/W ;bitpos:[12] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB2_FED_INSEL (BIT(12)) -#define MCPWM_DB2_FED_INSEL_M (BIT(12)) -#define MCPWM_DB2_FED_INSEL_V 0x1 -#define MCPWM_DB2_FED_INSEL_S 12 -/* MCPWM_DB2_RED_INSEL : R/W ;bitpos:[11] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB2_RED_INSEL (BIT(11)) -#define MCPWM_DB2_RED_INSEL_M (BIT(11)) -#define MCPWM_DB2_RED_INSEL_V 0x1 -#define MCPWM_DB2_RED_INSEL_S 11 -/* MCPWM_DB2_B_OUTSWAP : R/W ;bitpos:[10] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB2_B_OUTSWAP (BIT(10)) -#define MCPWM_DB2_B_OUTSWAP_M (BIT(10)) -#define MCPWM_DB2_B_OUTSWAP_V 0x1 -#define MCPWM_DB2_B_OUTSWAP_S 10 -/* MCPWM_DB2_A_OUTSWAP : R/W ;bitpos:[9] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB2_A_OUTSWAP (BIT(9)) -#define MCPWM_DB2_A_OUTSWAP_M (BIT(9)) -#define MCPWM_DB2_A_OUTSWAP_V 0x1 -#define MCPWM_DB2_A_OUTSWAP_S 9 -/* MCPWM_DB2_DEB_MODE : R/W ;bitpos:[8] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_DB2_DEB_MODE (BIT(8)) -#define MCPWM_DB2_DEB_MODE_M (BIT(8)) -#define MCPWM_DB2_DEB_MODE_V 0x1 -#define MCPWM_DB2_DEB_MODE_S 8 -/* MCPWM_DB2_RED_UPMETHOD : R/W ;bitpos:[7:4] ;default: 4'd0 ; */ -/*description: .*/ -#define MCPWM_DB2_RED_UPMETHOD 0x0000000F -#define MCPWM_DB2_RED_UPMETHOD_M ((MCPWM_DB2_RED_UPMETHOD_V)<<(MCPWM_DB2_RED_UPMETHOD_S)) -#define MCPWM_DB2_RED_UPMETHOD_V 0xF -#define MCPWM_DB2_RED_UPMETHOD_S 4 -/* MCPWM_DB2_FED_UPMETHOD : R/W ;bitpos:[3:0] ;default: 4'd0 ; */ -/*description: .*/ -#define MCPWM_DB2_FED_UPMETHOD 0x0000000F -#define MCPWM_DB2_FED_UPMETHOD_M ((MCPWM_DB2_FED_UPMETHOD_V)<<(MCPWM_DB2_FED_UPMETHOD_S)) -#define MCPWM_DB2_FED_UPMETHOD_V 0xF -#define MCPWM_DB2_FED_UPMETHOD_S 0 +/** MCPWM_DT2_CFG_REG register + * PWM generator 2 dead time type selection and configuration + */ +#define MCPWM_DT2_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xc8) +/** MCPWM_DT2_FED_UPMETHOD : R/W; bitpos: [3:0]; default: 0; + * Update method for FED (falling edge delay) active register. 0: immediate,when bit0 + * is set to 1: tez, when bit1 is set to 1:tep, when bit2 is set to 1: sync, when + * bit3 is set to 1: disable the update + */ +#define MCPWM_DT2_FED_UPMETHOD 0x0000000FU +#define MCPWM_DT2_FED_UPMETHOD_M (MCPWM_DT2_FED_UPMETHOD_V << MCPWM_DT2_FED_UPMETHOD_S) +#define MCPWM_DT2_FED_UPMETHOD_V 0x0000000FU +#define MCPWM_DT2_FED_UPMETHOD_S 0 +/** MCPWM_DT2_RED_UPMETHOD : R/W; bitpos: [7:4]; default: 0; + * Update method for RED (rising edge delay) active register. 0: immediate,when bit0 + * is set to 1: tez, when bit1 is set to 1:tep, when bit2 is set to 1: sync, when + * bit3 is set to 1: disable the update + */ +#define MCPWM_DT2_RED_UPMETHOD 0x0000000FU +#define MCPWM_DT2_RED_UPMETHOD_M (MCPWM_DT2_RED_UPMETHOD_V << MCPWM_DT2_RED_UPMETHOD_S) +#define MCPWM_DT2_RED_UPMETHOD_V 0x0000000FU +#define MCPWM_DT2_RED_UPMETHOD_S 4 +/** MCPWM_DT2_DEB_MODE : R/W; bitpos: [8]; default: 0; + * S8 in table, dual-edge B mode, 0: fed/red take effect on different path separately, + * 1: fed/red take effect on B path, A out is in bypass or dulpB mode + */ +#define MCPWM_DT2_DEB_MODE (BIT(8)) +#define MCPWM_DT2_DEB_MODE_M (MCPWM_DT2_DEB_MODE_V << MCPWM_DT2_DEB_MODE_S) +#define MCPWM_DT2_DEB_MODE_V 0x00000001U +#define MCPWM_DT2_DEB_MODE_S 8 +/** MCPWM_DT2_A_OUTSWAP : R/W; bitpos: [9]; default: 0; + * S6 in table + */ +#define MCPWM_DT2_A_OUTSWAP (BIT(9)) +#define MCPWM_DT2_A_OUTSWAP_M (MCPWM_DT2_A_OUTSWAP_V << MCPWM_DT2_A_OUTSWAP_S) +#define MCPWM_DT2_A_OUTSWAP_V 0x00000001U +#define MCPWM_DT2_A_OUTSWAP_S 9 +/** MCPWM_DT2_B_OUTSWAP : R/W; bitpos: [10]; default: 0; + * S7 in table + */ +#define MCPWM_DT2_B_OUTSWAP (BIT(10)) +#define MCPWM_DT2_B_OUTSWAP_M (MCPWM_DT2_B_OUTSWAP_V << MCPWM_DT2_B_OUTSWAP_S) +#define MCPWM_DT2_B_OUTSWAP_V 0x00000001U +#define MCPWM_DT2_B_OUTSWAP_S 10 +/** MCPWM_DT2_RED_INSEL : R/W; bitpos: [11]; default: 0; + * S4 in table + */ +#define MCPWM_DT2_RED_INSEL (BIT(11)) +#define MCPWM_DT2_RED_INSEL_M (MCPWM_DT2_RED_INSEL_V << MCPWM_DT2_RED_INSEL_S) +#define MCPWM_DT2_RED_INSEL_V 0x00000001U +#define MCPWM_DT2_RED_INSEL_S 11 +/** MCPWM_DT2_FED_INSEL : R/W; bitpos: [12]; default: 0; + * S5 in table + */ +#define MCPWM_DT2_FED_INSEL (BIT(12)) +#define MCPWM_DT2_FED_INSEL_M (MCPWM_DT2_FED_INSEL_V << MCPWM_DT2_FED_INSEL_S) +#define MCPWM_DT2_FED_INSEL_V 0x00000001U +#define MCPWM_DT2_FED_INSEL_S 12 +/** MCPWM_DT2_RED_OUTINVERT : R/W; bitpos: [13]; default: 0; + * S2 in table + */ +#define MCPWM_DT2_RED_OUTINVERT (BIT(13)) +#define MCPWM_DT2_RED_OUTINVERT_M (MCPWM_DT2_RED_OUTINVERT_V << MCPWM_DT2_RED_OUTINVERT_S) +#define MCPWM_DT2_RED_OUTINVERT_V 0x00000001U +#define MCPWM_DT2_RED_OUTINVERT_S 13 +/** MCPWM_DT2_FED_OUTINVERT : R/W; bitpos: [14]; default: 0; + * S3 in table + */ +#define MCPWM_DT2_FED_OUTINVERT (BIT(14)) +#define MCPWM_DT2_FED_OUTINVERT_M (MCPWM_DT2_FED_OUTINVERT_V << MCPWM_DT2_FED_OUTINVERT_S) +#define MCPWM_DT2_FED_OUTINVERT_V 0x00000001U +#define MCPWM_DT2_FED_OUTINVERT_S 14 +/** MCPWM_DT2_A_OUTBYPASS : R/W; bitpos: [15]; default: 1; + * S1 in table + */ +#define MCPWM_DT2_A_OUTBYPASS (BIT(15)) +#define MCPWM_DT2_A_OUTBYPASS_M (MCPWM_DT2_A_OUTBYPASS_V << MCPWM_DT2_A_OUTBYPASS_S) +#define MCPWM_DT2_A_OUTBYPASS_V 0x00000001U +#define MCPWM_DT2_A_OUTBYPASS_S 15 +/** MCPWM_DT2_B_OUTBYPASS : R/W; bitpos: [16]; default: 1; + * S0 in table + */ +#define MCPWM_DT2_B_OUTBYPASS (BIT(16)) +#define MCPWM_DT2_B_OUTBYPASS_M (MCPWM_DT2_B_OUTBYPASS_V << MCPWM_DT2_B_OUTBYPASS_S) +#define MCPWM_DT2_B_OUTBYPASS_V 0x00000001U +#define MCPWM_DT2_B_OUTBYPASS_S 16 +/** MCPWM_DT2_CLK_SEL : R/W; bitpos: [17]; default: 0; + * Dead time clock selection. 0: PWM_clk, 1: PT_clk + */ +#define MCPWM_DT2_CLK_SEL (BIT(17)) +#define MCPWM_DT2_CLK_SEL_M (MCPWM_DT2_CLK_SEL_V << MCPWM_DT2_CLK_SEL_S) +#define MCPWM_DT2_CLK_SEL_V 0x00000001U +#define MCPWM_DT2_CLK_SEL_S 17 -#define MCPWM_DB2_FED_CFG_REG(i) (REG_MCPWM_BASE(i) + 0xCC) -/* MCPWM_DB2_FED : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: .*/ -#define MCPWM_DB2_FED 0x0000FFFF -#define MCPWM_DB2_FED_M ((MCPWM_DB2_FED_V)<<(MCPWM_DB2_FED_S)) -#define MCPWM_DB2_FED_V 0xFFFF -#define MCPWM_DB2_FED_S 0 +/** MCPWM_DT2_FED_CFG_REG register + * PWM generator 2 shadow register for falling edge delay (FED). + */ +#define MCPWM_DT2_FED_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xcc) +/** MCPWM_DT2_FED : R/W; bitpos: [15:0]; default: 0; + * Shadow register for FED + */ +#define MCPWM_DT2_FED 0x0000FFFFU +#define MCPWM_DT2_FED_M (MCPWM_DT2_FED_V << MCPWM_DT2_FED_S) +#define MCPWM_DT2_FED_V 0x0000FFFFU +#define MCPWM_DT2_FED_S 0 -#define MCPWM_DB2_RED_CFG_REG(i) (REG_MCPWM_BASE(i) + 0xD0) -/* MCPWM_DB2_RED : R/W ;bitpos:[15:0] ;default: 16'd0 ; */ -/*description: .*/ -#define MCPWM_DB2_RED 0x0000FFFF -#define MCPWM_DB2_RED_M ((MCPWM_DB2_RED_V)<<(MCPWM_DB2_RED_S)) -#define MCPWM_DB2_RED_V 0xFFFF -#define MCPWM_DB2_RED_S 0 +/** MCPWM_DT2_RED_CFG_REG register + * PWM generator 2 shadow register for rising edge delay (RED). + */ +#define MCPWM_DT2_RED_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xd0) +/** MCPWM_DT2_RED : R/W; bitpos: [15:0]; default: 0; + * Shadow register for RED + */ +#define MCPWM_DT2_RED 0x0000FFFFU +#define MCPWM_DT2_RED_M (MCPWM_DT2_RED_V << MCPWM_DT2_RED_S) +#define MCPWM_DT2_RED_V 0x0000FFFFU +#define MCPWM_DT2_RED_S 0 -#define MCPWM_CHOPPER2_CFG_REG(i) (REG_MCPWM_BASE(i) + 0xD4) -/* MCPWM_CHOPPER2_IN_INVERT : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER2_IN_INVERT (BIT(13)) -#define MCPWM_CHOPPER2_IN_INVERT_M (BIT(13)) -#define MCPWM_CHOPPER2_IN_INVERT_V 0x1 -#define MCPWM_CHOPPER2_IN_INVERT_S 13 -/* MCPWM_CHOPPER2_OUT_INVERT : R/W ;bitpos:[12] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER2_OUT_INVERT (BIT(12)) -#define MCPWM_CHOPPER2_OUT_INVERT_M (BIT(12)) -#define MCPWM_CHOPPER2_OUT_INVERT_V 0x1 -#define MCPWM_CHOPPER2_OUT_INVERT_S 12 -/* MCPWM_CHOPPER2_OSHTWTH : R/W ;bitpos:[11:8] ;default: 4'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER2_OSHTWTH 0x0000000F -#define MCPWM_CHOPPER2_OSHTWTH_M ((MCPWM_CHOPPER2_OSHTWTH_V)<<(MCPWM_CHOPPER2_OSHTWTH_S)) -#define MCPWM_CHOPPER2_OSHTWTH_V 0xF -#define MCPWM_CHOPPER2_OSHTWTH_S 8 -/* MCPWM_CHOPPER2_DUTY : R/W ;bitpos:[7:5] ;default: 3'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER2_DUTY 0x00000007 -#define MCPWM_CHOPPER2_DUTY_M ((MCPWM_CHOPPER2_DUTY_V)<<(MCPWM_CHOPPER2_DUTY_S)) -#define MCPWM_CHOPPER2_DUTY_V 0x7 -#define MCPWM_CHOPPER2_DUTY_S 5 -/* MCPWM_CHOPPER2_PRESCALE : R/W ;bitpos:[4:1] ;default: 4'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER2_PRESCALE 0x0000000F -#define MCPWM_CHOPPER2_PRESCALE_M ((MCPWM_CHOPPER2_PRESCALE_V)<<(MCPWM_CHOPPER2_PRESCALE_S)) -#define MCPWM_CHOPPER2_PRESCALE_V 0xF -#define MCPWM_CHOPPER2_PRESCALE_S 1 -/* MCPWM_CHOPPER2_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CHOPPER2_EN (BIT(0)) -#define MCPWM_CHOPPER2_EN_M (BIT(0)) -#define MCPWM_CHOPPER2_EN_V 0x1 -#define MCPWM_CHOPPER2_EN_S 0 +/** MCPWM_CARRIER2_CFG_REG register + * PWM generator 2 carrier enable and configuratoin + */ +#define MCPWM_CARRIER2_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xd4) +/** MCPWM_CARRIER2_EN : R/W; bitpos: [0]; default: 0; + * When set, carrier2 function is enabled. When cleared, carrier2 is bypassed + */ +#define MCPWM_CARRIER2_EN (BIT(0)) +#define MCPWM_CARRIER2_EN_M (MCPWM_CARRIER2_EN_V << MCPWM_CARRIER2_EN_S) +#define MCPWM_CARRIER2_EN_V 0x00000001U +#define MCPWM_CARRIER2_EN_S 0 +/** MCPWM_CARRIER2_PRESCALE : R/W; bitpos: [4:1]; default: 0; + * PWM carrier2 clock (PC_clk) prescale value. Period of PC_clk = period of PWM_clk * + * (PWM_CARRIER0_PRESCALE + 1) + */ +#define MCPWM_CARRIER2_PRESCALE 0x0000000FU +#define MCPWM_CARRIER2_PRESCALE_M (MCPWM_CARRIER2_PRESCALE_V << MCPWM_CARRIER2_PRESCALE_S) +#define MCPWM_CARRIER2_PRESCALE_V 0x0000000FU +#define MCPWM_CARRIER2_PRESCALE_S 1 +/** MCPWM_CARRIER2_DUTY : R/W; bitpos: [7:5]; default: 0; + * carrier duty selection. Duty = PWM_CARRIER0_DUTY / 8 + */ +#define MCPWM_CARRIER2_DUTY 0x00000007U +#define MCPWM_CARRIER2_DUTY_M (MCPWM_CARRIER2_DUTY_V << MCPWM_CARRIER2_DUTY_S) +#define MCPWM_CARRIER2_DUTY_V 0x00000007U +#define MCPWM_CARRIER2_DUTY_S 5 +/** MCPWM_CARRIER2_OSHTWTH : R/W; bitpos: [11:8]; default: 0; + * width of the first pulse in number of periods of the carrier + */ +#define MCPWM_CARRIER2_OSHTWTH 0x0000000FU +#define MCPWM_CARRIER2_OSHTWTH_M (MCPWM_CARRIER2_OSHTWTH_V << MCPWM_CARRIER2_OSHTWTH_S) +#define MCPWM_CARRIER2_OSHTWTH_V 0x0000000FU +#define MCPWM_CARRIER2_OSHTWTH_S 8 +/** MCPWM_CARRIER2_OUT_INVERT : R/W; bitpos: [12]; default: 0; + * when set, invert the output of PWM2A and PWM2B for this submodule + */ +#define MCPWM_CARRIER2_OUT_INVERT (BIT(12)) +#define MCPWM_CARRIER2_OUT_INVERT_M (MCPWM_CARRIER2_OUT_INVERT_V << MCPWM_CARRIER2_OUT_INVERT_S) +#define MCPWM_CARRIER2_OUT_INVERT_V 0x00000001U +#define MCPWM_CARRIER2_OUT_INVERT_S 12 +/** MCPWM_CARRIER2_IN_INVERT : R/W; bitpos: [13]; default: 0; + * when set, invert the input of PWM2A and PWM2B for this submodule + */ +#define MCPWM_CARRIER2_IN_INVERT (BIT(13)) +#define MCPWM_CARRIER2_IN_INVERT_M (MCPWM_CARRIER2_IN_INVERT_V << MCPWM_CARRIER2_IN_INVERT_S) +#define MCPWM_CARRIER2_IN_INVERT_V 0x00000001U +#define MCPWM_CARRIER2_IN_INVERT_S 13 -#define MCPWM_TZ2_CFG0_REG(i) (REG_MCPWM_BASE(i) + 0xD8) -/* MCPWM_TZ2_B_OST_U : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ2_B_OST_U 0x00000003 -#define MCPWM_TZ2_B_OST_U_M ((MCPWM_TZ2_B_OST_U_V)<<(MCPWM_TZ2_B_OST_U_S)) -#define MCPWM_TZ2_B_OST_U_V 0x3 -#define MCPWM_TZ2_B_OST_U_S 22 -/* MCPWM_TZ2_B_OST_D : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ2_B_OST_D 0x00000003 -#define MCPWM_TZ2_B_OST_D_M ((MCPWM_TZ2_B_OST_D_V)<<(MCPWM_TZ2_B_OST_D_S)) -#define MCPWM_TZ2_B_OST_D_V 0x3 -#define MCPWM_TZ2_B_OST_D_S 20 -/* MCPWM_TZ2_B_CBC_U : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ2_B_CBC_U 0x00000003 -#define MCPWM_TZ2_B_CBC_U_M ((MCPWM_TZ2_B_CBC_U_V)<<(MCPWM_TZ2_B_CBC_U_S)) -#define MCPWM_TZ2_B_CBC_U_V 0x3 -#define MCPWM_TZ2_B_CBC_U_S 18 -/* MCPWM_TZ2_B_CBC_D : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ2_B_CBC_D 0x00000003 -#define MCPWM_TZ2_B_CBC_D_M ((MCPWM_TZ2_B_CBC_D_V)<<(MCPWM_TZ2_B_CBC_D_S)) -#define MCPWM_TZ2_B_CBC_D_V 0x3 -#define MCPWM_TZ2_B_CBC_D_S 16 -/* MCPWM_TZ2_A_OST_U : R/W ;bitpos:[15:14] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ2_A_OST_U 0x00000003 -#define MCPWM_TZ2_A_OST_U_M ((MCPWM_TZ2_A_OST_U_V)<<(MCPWM_TZ2_A_OST_U_S)) -#define MCPWM_TZ2_A_OST_U_V 0x3 -#define MCPWM_TZ2_A_OST_U_S 14 -/* MCPWM_TZ2_A_OST_D : R/W ;bitpos:[13:12] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ2_A_OST_D 0x00000003 -#define MCPWM_TZ2_A_OST_D_M ((MCPWM_TZ2_A_OST_D_V)<<(MCPWM_TZ2_A_OST_D_S)) -#define MCPWM_TZ2_A_OST_D_V 0x3 -#define MCPWM_TZ2_A_OST_D_S 12 -/* MCPWM_TZ2_A_CBC_U : R/W ;bitpos:[11:10] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ2_A_CBC_U 0x00000003 -#define MCPWM_TZ2_A_CBC_U_M ((MCPWM_TZ2_A_CBC_U_V)<<(MCPWM_TZ2_A_CBC_U_S)) -#define MCPWM_TZ2_A_CBC_U_V 0x3 -#define MCPWM_TZ2_A_CBC_U_S 10 -/* MCPWM_TZ2_A_CBC_D : R/W ;bitpos:[9:8] ;default: 2'd0 ; */ -/*description: 0: do nothing, 1: force lo, 2: force hi, 3: toggle.*/ -#define MCPWM_TZ2_A_CBC_D 0x00000003 -#define MCPWM_TZ2_A_CBC_D_M ((MCPWM_TZ2_A_CBC_D_V)<<(MCPWM_TZ2_A_CBC_D_S)) -#define MCPWM_TZ2_A_CBC_D_V 0x3 -#define MCPWM_TZ2_A_CBC_D_S 8 -/* MCPWM_TZ2_F0_OST : R/W ;bitpos:[7] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ2_F0_OST (BIT(7)) -#define MCPWM_TZ2_F0_OST_M (BIT(7)) -#define MCPWM_TZ2_F0_OST_V 0x1 -#define MCPWM_TZ2_F0_OST_S 7 -/* MCPWM_TZ2_F1_OST : R/W ;bitpos:[6] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ2_F1_OST (BIT(6)) -#define MCPWM_TZ2_F1_OST_M (BIT(6)) -#define MCPWM_TZ2_F1_OST_V 0x1 -#define MCPWM_TZ2_F1_OST_S 6 -/* MCPWM_TZ2_F2_OST : R/W ;bitpos:[5] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ2_F2_OST (BIT(5)) -#define MCPWM_TZ2_F2_OST_M (BIT(5)) -#define MCPWM_TZ2_F2_OST_V 0x1 -#define MCPWM_TZ2_F2_OST_S 5 -/* MCPWM_TZ2_SW_OST : R/W ;bitpos:[4] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ2_SW_OST (BIT(4)) -#define MCPWM_TZ2_SW_OST_M (BIT(4)) -#define MCPWM_TZ2_SW_OST_V 0x1 -#define MCPWM_TZ2_SW_OST_S 4 -/* MCPWM_TZ2_F0_CBC : R/W ;bitpos:[3] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ2_F0_CBC (BIT(3)) -#define MCPWM_TZ2_F0_CBC_M (BIT(3)) -#define MCPWM_TZ2_F0_CBC_V 0x1 -#define MCPWM_TZ2_F0_CBC_S 3 -/* MCPWM_TZ2_F1_CBC : R/W ;bitpos:[2] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ2_F1_CBC (BIT(2)) -#define MCPWM_TZ2_F1_CBC_M (BIT(2)) -#define MCPWM_TZ2_F1_CBC_V 0x1 -#define MCPWM_TZ2_F1_CBC_S 2 -/* MCPWM_TZ2_F2_CBC : R/W ;bitpos:[1] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ2_F2_CBC (BIT(1)) -#define MCPWM_TZ2_F2_CBC_M (BIT(1)) -#define MCPWM_TZ2_F2_CBC_V 0x1 -#define MCPWM_TZ2_F2_CBC_S 1 -/* MCPWM_TZ2_SW_CBC : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: 0: disable, 1: enable.*/ -#define MCPWM_TZ2_SW_CBC (BIT(0)) -#define MCPWM_TZ2_SW_CBC_M (BIT(0)) -#define MCPWM_TZ2_SW_CBC_V 0x1 -#define MCPWM_TZ2_SW_CBC_S 0 +/** MCPWM_FH2_CFG0_REG register + * Actions on PWM2A and PWM2B trip events + */ +#define MCPWM_FH2_CFG0_REG(i) (DR_REG_MCPWM_BASE(i) + 0xd8) +/** MCPWM_FH2_SW_CBC : R/W; bitpos: [0]; default: 0; + * Enable register for software force cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH2_SW_CBC (BIT(0)) +#define MCPWM_FH2_SW_CBC_M (MCPWM_FH2_SW_CBC_V << MCPWM_FH2_SW_CBC_S) +#define MCPWM_FH2_SW_CBC_V 0x00000001U +#define MCPWM_FH2_SW_CBC_S 0 +/** MCPWM_FH2_F2_CBC : R/W; bitpos: [1]; default: 0; + * fault_event2 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH2_F2_CBC (BIT(1)) +#define MCPWM_FH2_F2_CBC_M (MCPWM_FH2_F2_CBC_V << MCPWM_FH2_F2_CBC_S) +#define MCPWM_FH2_F2_CBC_V 0x00000001U +#define MCPWM_FH2_F2_CBC_S 1 +/** MCPWM_FH2_F1_CBC : R/W; bitpos: [2]; default: 0; + * fault_event1 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH2_F1_CBC (BIT(2)) +#define MCPWM_FH2_F1_CBC_M (MCPWM_FH2_F1_CBC_V << MCPWM_FH2_F1_CBC_S) +#define MCPWM_FH2_F1_CBC_V 0x00000001U +#define MCPWM_FH2_F1_CBC_S 2 +/** MCPWM_FH2_F0_CBC : R/W; bitpos: [3]; default: 0; + * fault_event0 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ +#define MCPWM_FH2_F0_CBC (BIT(3)) +#define MCPWM_FH2_F0_CBC_M (MCPWM_FH2_F0_CBC_V << MCPWM_FH2_F0_CBC_S) +#define MCPWM_FH2_F0_CBC_V 0x00000001U +#define MCPWM_FH2_F0_CBC_S 3 +/** MCPWM_FH2_SW_OST : R/W; bitpos: [4]; default: 0; + * Enable register for software force one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH2_SW_OST (BIT(4)) +#define MCPWM_FH2_SW_OST_M (MCPWM_FH2_SW_OST_V << MCPWM_FH2_SW_OST_S) +#define MCPWM_FH2_SW_OST_V 0x00000001U +#define MCPWM_FH2_SW_OST_S 4 +/** MCPWM_FH2_F2_OST : R/W; bitpos: [5]; default: 0; + * fault_event2 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH2_F2_OST (BIT(5)) +#define MCPWM_FH2_F2_OST_M (MCPWM_FH2_F2_OST_V << MCPWM_FH2_F2_OST_S) +#define MCPWM_FH2_F2_OST_V 0x00000001U +#define MCPWM_FH2_F2_OST_S 5 +/** MCPWM_FH2_F1_OST : R/W; bitpos: [6]; default: 0; + * fault_event1 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH2_F1_OST (BIT(6)) +#define MCPWM_FH2_F1_OST_M (MCPWM_FH2_F1_OST_V << MCPWM_FH2_F1_OST_S) +#define MCPWM_FH2_F1_OST_V 0x00000001U +#define MCPWM_FH2_F1_OST_S 6 +/** MCPWM_FH2_F0_OST : R/W; bitpos: [7]; default: 0; + * fault_event0 will trigger one-shot mode action. 0: disable, 1: enable + */ +#define MCPWM_FH2_F0_OST (BIT(7)) +#define MCPWM_FH2_F0_OST_M (MCPWM_FH2_F0_OST_V << MCPWM_FH2_F0_OST_S) +#define MCPWM_FH2_F0_OST_V 0x00000001U +#define MCPWM_FH2_F0_OST_S 7 +/** MCPWM_FH2_A_CBC_D : R/W; bitpos: [9:8]; default: 0; + * Cycle-by-cycle mode action on PWM2A when fault event occurs and timer is + * decreasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH2_A_CBC_D 0x00000003U +#define MCPWM_FH2_A_CBC_D_M (MCPWM_FH2_A_CBC_D_V << MCPWM_FH2_A_CBC_D_S) +#define MCPWM_FH2_A_CBC_D_V 0x00000003U +#define MCPWM_FH2_A_CBC_D_S 8 +/** MCPWM_FH2_A_CBC_U : R/W; bitpos: [11:10]; default: 0; + * Cycle-by-cycle mode action on PWM2A when fault event occurs and timer is + * increasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH2_A_CBC_U 0x00000003U +#define MCPWM_FH2_A_CBC_U_M (MCPWM_FH2_A_CBC_U_V << MCPWM_FH2_A_CBC_U_S) +#define MCPWM_FH2_A_CBC_U_V 0x00000003U +#define MCPWM_FH2_A_CBC_U_S 10 +/** MCPWM_FH2_A_OST_D : R/W; bitpos: [13:12]; default: 0; + * One-shot mode action on PWM2A when fault event occurs and timer is decreasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH2_A_OST_D 0x00000003U +#define MCPWM_FH2_A_OST_D_M (MCPWM_FH2_A_OST_D_V << MCPWM_FH2_A_OST_D_S) +#define MCPWM_FH2_A_OST_D_V 0x00000003U +#define MCPWM_FH2_A_OST_D_S 12 +/** MCPWM_FH2_A_OST_U : R/W; bitpos: [15:14]; default: 0; + * One-shot mode action on PWM2A when fault event occurs and timer is increasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH2_A_OST_U 0x00000003U +#define MCPWM_FH2_A_OST_U_M (MCPWM_FH2_A_OST_U_V << MCPWM_FH2_A_OST_U_S) +#define MCPWM_FH2_A_OST_U_V 0x00000003U +#define MCPWM_FH2_A_OST_U_S 14 +/** MCPWM_FH2_B_CBC_D : R/W; bitpos: [17:16]; default: 0; + * Cycle-by-cycle mode action on PWM2B when fault event occurs and timer is + * decreasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH2_B_CBC_D 0x00000003U +#define MCPWM_FH2_B_CBC_D_M (MCPWM_FH2_B_CBC_D_V << MCPWM_FH2_B_CBC_D_S) +#define MCPWM_FH2_B_CBC_D_V 0x00000003U +#define MCPWM_FH2_B_CBC_D_S 16 +/** MCPWM_FH2_B_CBC_U : R/W; bitpos: [19:18]; default: 0; + * Cycle-by-cycle mode action on PWM2B when fault event occurs and timer is + * increasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH2_B_CBC_U 0x00000003U +#define MCPWM_FH2_B_CBC_U_M (MCPWM_FH2_B_CBC_U_V << MCPWM_FH2_B_CBC_U_S) +#define MCPWM_FH2_B_CBC_U_V 0x00000003U +#define MCPWM_FH2_B_CBC_U_S 18 +/** MCPWM_FH2_B_OST_D : R/W; bitpos: [21:20]; default: 0; + * One-shot mode action on PWM2B when fault event occurs and timer is decreasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH2_B_OST_D 0x00000003U +#define MCPWM_FH2_B_OST_D_M (MCPWM_FH2_B_OST_D_V << MCPWM_FH2_B_OST_D_S) +#define MCPWM_FH2_B_OST_D_V 0x00000003U +#define MCPWM_FH2_B_OST_D_S 20 +/** MCPWM_FH2_B_OST_U : R/W; bitpos: [23:22]; default: 0; + * One-shot mode action on PWM2B when fault event occurs and timer is increasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ +#define MCPWM_FH2_B_OST_U 0x00000003U +#define MCPWM_FH2_B_OST_U_M (MCPWM_FH2_B_OST_U_V << MCPWM_FH2_B_OST_U_S) +#define MCPWM_FH2_B_OST_U_V 0x00000003U +#define MCPWM_FH2_B_OST_U_S 22 -#define MCPWM_TZ2_CFG1_REG(i) (REG_MCPWM_BASE(i) + 0xDC) -/* MCPWM_TZ2_FORCE_OST : R/W ;bitpos:[4] ;default: 1'd0 ; */ -/*description: a toggle trigger a oneshot tripping.*/ -#define MCPWM_TZ2_FORCE_OST (BIT(4)) -#define MCPWM_TZ2_FORCE_OST_M (BIT(4)) -#define MCPWM_TZ2_FORCE_OST_V 0x1 -#define MCPWM_TZ2_FORCE_OST_S 4 -/* MCPWM_TZ2_FORCE_CBC : R/W ;bitpos:[3] ;default: 1'd0 ; */ -/*description: a toggle trigger a cycle-by-cycle tripping.*/ -#define MCPWM_TZ2_FORCE_CBC (BIT(3)) -#define MCPWM_TZ2_FORCE_CBC_M (BIT(3)) -#define MCPWM_TZ2_FORCE_CBC_V 0x1 -#define MCPWM_TZ2_FORCE_CBC_S 3 -/* MCPWM_TZ2_CBCPULSE : R/W ;bitpos:[2:1] ;default: 2'd0 ; */ -/*description: bit0: tez, bit1: tep.*/ -#define MCPWM_TZ2_CBCPULSE 0x00000003 -#define MCPWM_TZ2_CBCPULSE_M ((MCPWM_TZ2_CBCPULSE_V)<<(MCPWM_TZ2_CBCPULSE_S)) -#define MCPWM_TZ2_CBCPULSE_V 0x3 -#define MCPWM_TZ2_CBCPULSE_S 1 -/* MCPWM_TZ2_CLR_OST : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: a toggle will clear oneshot tripping.*/ -#define MCPWM_TZ2_CLR_OST (BIT(0)) -#define MCPWM_TZ2_CLR_OST_M (BIT(0)) -#define MCPWM_TZ2_CLR_OST_V 0x1 -#define MCPWM_TZ2_CLR_OST_S 0 +/** MCPWM_FH2_CFG1_REG register + * Software triggers for fault handler actions + */ +#define MCPWM_FH2_CFG1_REG(i) (DR_REG_MCPWM_BASE(i) + 0xdc) +/** MCPWM_FH2_CLR_OST : R/W; bitpos: [0]; default: 0; + * a rising edge will clear on going one-shot mode action + */ +#define MCPWM_FH2_CLR_OST (BIT(0)) +#define MCPWM_FH2_CLR_OST_M (MCPWM_FH2_CLR_OST_V << MCPWM_FH2_CLR_OST_S) +#define MCPWM_FH2_CLR_OST_V 0x00000001U +#define MCPWM_FH2_CLR_OST_S 0 +/** MCPWM_FH2_CBCPULSE : R/W; bitpos: [2:1]; default: 0; + * cycle-by-cycle mode action refresh moment selection. When bit0 is set to 1: TEZ, + * when bit1 is set to 1:TEP + */ +#define MCPWM_FH2_CBCPULSE 0x00000003U +#define MCPWM_FH2_CBCPULSE_M (MCPWM_FH2_CBCPULSE_V << MCPWM_FH2_CBCPULSE_S) +#define MCPWM_FH2_CBCPULSE_V 0x00000003U +#define MCPWM_FH2_CBCPULSE_S 1 +/** MCPWM_FH2_FORCE_CBC : R/W; bitpos: [3]; default: 0; + * a toggle trigger a cycle-by-cycle mode action + */ +#define MCPWM_FH2_FORCE_CBC (BIT(3)) +#define MCPWM_FH2_FORCE_CBC_M (MCPWM_FH2_FORCE_CBC_V << MCPWM_FH2_FORCE_CBC_S) +#define MCPWM_FH2_FORCE_CBC_V 0x00000001U +#define MCPWM_FH2_FORCE_CBC_S 3 +/** MCPWM_FH2_FORCE_OST : R/W; bitpos: [4]; default: 0; + * a toggle (software negate its value) triggers a one-shot mode action + */ +#define MCPWM_FH2_FORCE_OST (BIT(4)) +#define MCPWM_FH2_FORCE_OST_M (MCPWM_FH2_FORCE_OST_V << MCPWM_FH2_FORCE_OST_S) +#define MCPWM_FH2_FORCE_OST_V 0x00000001U +#define MCPWM_FH2_FORCE_OST_S 4 -#define MCPWM_TZ2_STATUS_REG(i) (REG_MCPWM_BASE(i) + 0xE0) -/* MCPWM_TZ2_OST_ON : RO ;bitpos:[1] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ2_OST_ON (BIT(1)) -#define MCPWM_TZ2_OST_ON_M (BIT(1)) -#define MCPWM_TZ2_OST_ON_V 0x1 -#define MCPWM_TZ2_OST_ON_S 1 -/* MCPWM_TZ2_CBC_ON : RO ;bitpos:[0] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ2_CBC_ON (BIT(0)) -#define MCPWM_TZ2_CBC_ON_M (BIT(0)) -#define MCPWM_TZ2_CBC_ON_V 0x1 -#define MCPWM_TZ2_CBC_ON_S 0 +/** MCPWM_FH2_STATUS_REG register + * Status of fault events. + */ +#define MCPWM_FH2_STATUS_REG(i) (DR_REG_MCPWM_BASE(i) + 0xe0) +/** MCPWM_FH2_CBC_ON : RO; bitpos: [0]; default: 0; + * Set and reset by hardware. If set, a cycle-by-cycle mode action is on going + */ +#define MCPWM_FH2_CBC_ON (BIT(0)) +#define MCPWM_FH2_CBC_ON_M (MCPWM_FH2_CBC_ON_V << MCPWM_FH2_CBC_ON_S) +#define MCPWM_FH2_CBC_ON_V 0x00000001U +#define MCPWM_FH2_CBC_ON_S 0 +/** MCPWM_FH2_OST_ON : RO; bitpos: [1]; default: 0; + * Set and reset by hardware. If set, an one-shot mode action is on going + */ +#define MCPWM_FH2_OST_ON (BIT(1)) +#define MCPWM_FH2_OST_ON_M (MCPWM_FH2_OST_ON_V << MCPWM_FH2_OST_ON_S) +#define MCPWM_FH2_OST_ON_V 0x00000001U +#define MCPWM_FH2_OST_ON_S 1 -#define MCPWM_FAULT_DETECT_REG(i) (REG_MCPWM_BASE(i) + 0xE4) -/* MCPWM_EVENT_F2 : RO ;bitpos:[8] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_EVENT_F2 (BIT(8)) -#define MCPWM_EVENT_F2_M (BIT(8)) -#define MCPWM_EVENT_F2_V 0x1 -#define MCPWM_EVENT_F2_S 8 -/* MCPWM_EVENT_F1 : RO ;bitpos:[7] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_EVENT_F1 (BIT(7)) -#define MCPWM_EVENT_F1_M (BIT(7)) -#define MCPWM_EVENT_F1_V 0x1 -#define MCPWM_EVENT_F1_S 7 -/* MCPWM_EVENT_F0 : RO ;bitpos:[6] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_EVENT_F0 (BIT(6)) -#define MCPWM_EVENT_F0_M (BIT(6)) -#define MCPWM_EVENT_F0_V 0x1 -#define MCPWM_EVENT_F0_S 6 -/* MCPWM_F2_POLE : R/W ;bitpos:[5] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_F2_POLE (BIT(5)) -#define MCPWM_F2_POLE_M (BIT(5)) -#define MCPWM_F2_POLE_V 0x1 -#define MCPWM_F2_POLE_S 5 -/* MCPWM_F1_POLE : R/W ;bitpos:[4] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_F1_POLE (BIT(4)) -#define MCPWM_F1_POLE_M (BIT(4)) -#define MCPWM_F1_POLE_V 0x1 -#define MCPWM_F1_POLE_S 4 -/* MCPWM_F0_POLE : R/W ;bitpos:[3] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_F0_POLE (BIT(3)) -#define MCPWM_F0_POLE_M (BIT(3)) -#define MCPWM_F0_POLE_V 0x1 -#define MCPWM_F0_POLE_S 3 -/* MCPWM_F2_EN : R/W ;bitpos:[2] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_F2_EN (BIT(2)) -#define MCPWM_F2_EN_M (BIT(2)) -#define MCPWM_F2_EN_V 0x1 -#define MCPWM_F2_EN_S 2 -/* MCPWM_F1_EN : R/W ;bitpos:[1] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_F1_EN (BIT(1)) -#define MCPWM_F1_EN_M (BIT(1)) -#define MCPWM_F1_EN_V 0x1 -#define MCPWM_F1_EN_S 1 -/* MCPWM_F0_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: .*/ +/** MCPWM_FAULT_DETECT_REG register + * Fault detection configuration and status + */ +#define MCPWM_FAULT_DETECT_REG(i) (DR_REG_MCPWM_BASE(i) + 0xe4) +/** MCPWM_F0_EN : R/W; bitpos: [0]; default: 0; + * When set, fault_event0 generation is enabled + */ #define MCPWM_F0_EN (BIT(0)) -#define MCPWM_F0_EN_M (BIT(0)) -#define MCPWM_F0_EN_V 0x1 +#define MCPWM_F0_EN_M (MCPWM_F0_EN_V << MCPWM_F0_EN_S) +#define MCPWM_F0_EN_V 0x00000001U #define MCPWM_F0_EN_S 0 +/** MCPWM_F1_EN : R/W; bitpos: [1]; default: 0; + * When set, fault_event1 generation is enabled + */ +#define MCPWM_F1_EN (BIT(1)) +#define MCPWM_F1_EN_M (MCPWM_F1_EN_V << MCPWM_F1_EN_S) +#define MCPWM_F1_EN_V 0x00000001U +#define MCPWM_F1_EN_S 1 +/** MCPWM_F2_EN : R/W; bitpos: [2]; default: 0; + * When set, fault_event2 generation is enabled + */ +#define MCPWM_F2_EN (BIT(2)) +#define MCPWM_F2_EN_M (MCPWM_F2_EN_V << MCPWM_F2_EN_S) +#define MCPWM_F2_EN_V 0x00000001U +#define MCPWM_F2_EN_S 2 +/** MCPWM_F0_POLE : R/W; bitpos: [3]; default: 0; + * Set fault_event0 trigger polarity on FAULT2 source from GPIO matrix. 0: level low, + * 1: level high + */ +#define MCPWM_F0_POLE (BIT(3)) +#define MCPWM_F0_POLE_M (MCPWM_F0_POLE_V << MCPWM_F0_POLE_S) +#define MCPWM_F0_POLE_V 0x00000001U +#define MCPWM_F0_POLE_S 3 +/** MCPWM_F1_POLE : R/W; bitpos: [4]; default: 0; + * Set fault_event1 trigger polarity on FAULT2 source from GPIO matrix. 0: level low, + * 1: level high + */ +#define MCPWM_F1_POLE (BIT(4)) +#define MCPWM_F1_POLE_M (MCPWM_F1_POLE_V << MCPWM_F1_POLE_S) +#define MCPWM_F1_POLE_V 0x00000001U +#define MCPWM_F1_POLE_S 4 +/** MCPWM_F2_POLE : R/W; bitpos: [5]; default: 0; + * Set fault_event2 trigger polarity on FAULT2 source from GPIO matrix. 0: level low, + * 1: level high + */ +#define MCPWM_F2_POLE (BIT(5)) +#define MCPWM_F2_POLE_M (MCPWM_F2_POLE_V << MCPWM_F2_POLE_S) +#define MCPWM_F2_POLE_V 0x00000001U +#define MCPWM_F2_POLE_S 5 +/** MCPWM_EVENT_F0 : RO; bitpos: [6]; default: 0; + * Set and reset by hardware. If set, fault_event0 is on going + */ +#define MCPWM_EVENT_F0 (BIT(6)) +#define MCPWM_EVENT_F0_M (MCPWM_EVENT_F0_V << MCPWM_EVENT_F0_S) +#define MCPWM_EVENT_F0_V 0x00000001U +#define MCPWM_EVENT_F0_S 6 +/** MCPWM_EVENT_F1 : RO; bitpos: [7]; default: 0; + * Set and reset by hardware. If set, fault_event1 is on going + */ +#define MCPWM_EVENT_F1 (BIT(7)) +#define MCPWM_EVENT_F1_M (MCPWM_EVENT_F1_V << MCPWM_EVENT_F1_S) +#define MCPWM_EVENT_F1_V 0x00000001U +#define MCPWM_EVENT_F1_S 7 +/** MCPWM_EVENT_F2 : RO; bitpos: [8]; default: 0; + * Set and reset by hardware. If set, fault_event2 is on going + */ +#define MCPWM_EVENT_F2 (BIT(8)) +#define MCPWM_EVENT_F2_M (MCPWM_EVENT_F2_V << MCPWM_EVENT_F2_S) +#define MCPWM_EVENT_F2_V 0x00000001U +#define MCPWM_EVENT_F2_S 8 -#define MCPWM_CAP_TIMER_CFG_REG(i) (REG_MCPWM_BASE(i) + 0xE8) -/* MCPWM_CAP_SYNC_SW : WO ;bitpos:[5] ;default: 1'd0 ; */ -/*description: Write 1 will force a timer sync.*/ -#define MCPWM_CAP_SYNC_SW (BIT(5)) -#define MCPWM_CAP_SYNC_SW_M (BIT(5)) -#define MCPWM_CAP_SYNC_SW_V 0x1 -#define MCPWM_CAP_SYNC_SW_S 5 -/* MCPWM_CAP_SYNCI_SEL : R/W ;bitpos:[4:2] ;default: 3'd0 ; */ -/*description: .*/ -#define MCPWM_CAP_SYNCI_SEL 0x00000007 -#define MCPWM_CAP_SYNCI_SEL_M ((MCPWM_CAP_SYNCI_SEL_V)<<(MCPWM_CAP_SYNCI_SEL_S)) -#define MCPWM_CAP_SYNCI_SEL_V 0x7 -#define MCPWM_CAP_SYNCI_SEL_S 2 -/* MCPWM_CAP_SYNCI_EN : R/W ;bitpos:[1] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP_SYNCI_EN (BIT(1)) -#define MCPWM_CAP_SYNCI_EN_M (BIT(1)) -#define MCPWM_CAP_SYNCI_EN_V 0x1 -#define MCPWM_CAP_SYNCI_EN_S 1 -/* MCPWM_CAP_TIMER_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: .*/ +/** MCPWM_CAP_TIMER_CFG_REG register + * Configure capture timer + */ +#define MCPWM_CAP_TIMER_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xe8) +/** MCPWM_CAP_TIMER_EN : R/W; bitpos: [0]; default: 0; + * When set, capture timer incrementing under APB_clk is enabled. + */ #define MCPWM_CAP_TIMER_EN (BIT(0)) -#define MCPWM_CAP_TIMER_EN_M (BIT(0)) -#define MCPWM_CAP_TIMER_EN_V 0x1 +#define MCPWM_CAP_TIMER_EN_M (MCPWM_CAP_TIMER_EN_V << MCPWM_CAP_TIMER_EN_S) +#define MCPWM_CAP_TIMER_EN_V 0x00000001U #define MCPWM_CAP_TIMER_EN_S 0 +/** MCPWM_CAP_SYNCI_EN : R/W; bitpos: [1]; default: 0; + * When set, capture timer sync is enabled. + */ +#define MCPWM_CAP_SYNCI_EN (BIT(1)) +#define MCPWM_CAP_SYNCI_EN_M (MCPWM_CAP_SYNCI_EN_V << MCPWM_CAP_SYNCI_EN_S) +#define MCPWM_CAP_SYNCI_EN_V 0x00000001U +#define MCPWM_CAP_SYNCI_EN_S 1 +/** MCPWM_CAP_SYNCI_SEL : R/W; bitpos: [4:2]; default: 0; + * capture module sync input selection. 0: none, 1: timer0 sync_out, 2: timer1 + * sync_out, 3: timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, + * 6: SYNC2 from GPIO matrix + */ +#define MCPWM_CAP_SYNCI_SEL 0x00000007U +#define MCPWM_CAP_SYNCI_SEL_M (MCPWM_CAP_SYNCI_SEL_V << MCPWM_CAP_SYNCI_SEL_S) +#define MCPWM_CAP_SYNCI_SEL_V 0x00000007U +#define MCPWM_CAP_SYNCI_SEL_S 2 +/** MCPWM_CAP_SYNC_SW : WT; bitpos: [5]; default: 0; + * When reg_cap_synci_en is 1, write 1 will trigger a capture timer sync, capture + * timer is loaded with value in phase register. + */ +#define MCPWM_CAP_SYNC_SW (BIT(5)) +#define MCPWM_CAP_SYNC_SW_M (MCPWM_CAP_SYNC_SW_V << MCPWM_CAP_SYNC_SW_S) +#define MCPWM_CAP_SYNC_SW_V 0x00000001U +#define MCPWM_CAP_SYNC_SW_S 5 -#define MCPWM_CAP_TIMER_PHASE_REG(i) (REG_MCPWM_BASE(i) + 0xEC) -/* MCPWM_CAP_PHASE : R/W ;bitpos:[31:0] ;default: 32'd0 ; */ -/*description: .*/ -#define MCPWM_CAP_PHASE 0xFFFFFFFF -#define MCPWM_CAP_PHASE_M ((MCPWM_CAP_PHASE_V)<<(MCPWM_CAP_PHASE_S)) -#define MCPWM_CAP_PHASE_V 0xFFFFFFFF -#define MCPWM_CAP_PHASE_S 0 +/** MCPWM_CAP_TIMER_PHASE_REG register + * Phase for capture timer sync + */ +#define MCPWM_CAP_TIMER_PHASE_REG(i) (DR_REG_MCPWM_BASE(i) + 0xec) +/** MCPWM_CAP_TIMER_PHASE : R/W; bitpos: [31:0]; default: 0; + * Phase value for capture timer sync operation. + */ +#define MCPWM_CAP_TIMER_PHASE 0xFFFFFFFFU +#define MCPWM_CAP_TIMER_PHASE_M (MCPWM_CAP_TIMER_PHASE_V << MCPWM_CAP_TIMER_PHASE_S) +#define MCPWM_CAP_TIMER_PHASE_V 0xFFFFFFFFU +#define MCPWM_CAP_TIMER_PHASE_S 0 -#define MCPWM_CAP_CH0_CFG_REG(i) (REG_MCPWM_BASE(i) + 0xF0) -/* MCPWM_CAP0_SW : WO ;bitpos:[12] ;default: 1'd0 ; */ -/*description: Write 1 will trigger a sw capture.*/ -#define MCPWM_CAP0_SW (BIT(12)) -#define MCPWM_CAP0_SW_M (BIT(12)) -#define MCPWM_CAP0_SW_V 0x1 -#define MCPWM_CAP0_SW_S 12 -/* MCPWM_CAP0_IN_INVERT : R/W ;bitpos:[11] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP0_IN_INVERT (BIT(11)) -#define MCPWM_CAP0_IN_INVERT_M (BIT(11)) -#define MCPWM_CAP0_IN_INVERT_V 0x1 -#define MCPWM_CAP0_IN_INVERT_S 11 -/* MCPWM_CAP0_PRESCALE : R/W ;bitpos:[10:3] ;default: 8'd0 ; */ -/*description: .*/ -#define MCPWM_CAP0_PRESCALE 0x000000FF -#define MCPWM_CAP0_PRESCALE_M ((MCPWM_CAP0_PRESCALE_V)<<(MCPWM_CAP0_PRESCALE_S)) -#define MCPWM_CAP0_PRESCALE_V 0xFF -#define MCPWM_CAP0_PRESCALE_S 3 -/* MCPWM_CAP0_MODE : R/W ;bitpos:[2:1] ;default: 2'd0 ; */ -/*description: bit0: negedge cap en, bit1: posedge cap en.*/ -#define MCPWM_CAP0_MODE 0x00000003 -#define MCPWM_CAP0_MODE_M ((MCPWM_CAP0_MODE_V)<<(MCPWM_CAP0_MODE_S)) -#define MCPWM_CAP0_MODE_V 0x3 -#define MCPWM_CAP0_MODE_S 1 -/* MCPWM_CAP0_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: .*/ +/** MCPWM_CAP_CH0_CFG_REG register + * Capture channel 0 configuration and enable + */ +#define MCPWM_CAP_CH0_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xf0) +/** MCPWM_CAP0_EN : R/W; bitpos: [0]; default: 0; + * When set, capture on channel 0 is enabled + */ #define MCPWM_CAP0_EN (BIT(0)) -#define MCPWM_CAP0_EN_M (BIT(0)) -#define MCPWM_CAP0_EN_V 0x1 +#define MCPWM_CAP0_EN_M (MCPWM_CAP0_EN_V << MCPWM_CAP0_EN_S) +#define MCPWM_CAP0_EN_V 0x00000001U #define MCPWM_CAP0_EN_S 0 +/** MCPWM_CAP0_MODE : R/W; bitpos: [2:1]; default: 0; + * Edge of capture on channel 0 after prescaling. When bit0 is set to 1: enable + * capture on the negative edge, When bit1 is set to 1: enable capture on the positive + * edge. + */ +#define MCPWM_CAP0_MODE 0x00000003U +#define MCPWM_CAP0_MODE_M (MCPWM_CAP0_MODE_V << MCPWM_CAP0_MODE_S) +#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 + + * 1 + */ +#define MCPWM_CAP0_PRESCALE 0x000000FFU +#define MCPWM_CAP0_PRESCALE_M (MCPWM_CAP0_PRESCALE_V << MCPWM_CAP0_PRESCALE_S) +#define MCPWM_CAP0_PRESCALE_V 0x000000FFU +#define MCPWM_CAP0_PRESCALE_S 3 +/** MCPWM_CAP0_IN_INVERT : R/W; bitpos: [11]; default: 0; + * when set, CAP0 form GPIO matrix is inverted before prescale + */ +#define MCPWM_CAP0_IN_INVERT (BIT(11)) +#define MCPWM_CAP0_IN_INVERT_M (MCPWM_CAP0_IN_INVERT_V << MCPWM_CAP0_IN_INVERT_S) +#define MCPWM_CAP0_IN_INVERT_V 0x00000001U +#define MCPWM_CAP0_IN_INVERT_S 11 +/** MCPWM_CAP0_SW : WT; bitpos: [12]; default: 0; + * Write 1 will trigger a software forced capture on channel 0 + */ +#define MCPWM_CAP0_SW (BIT(12)) +#define MCPWM_CAP0_SW_M (MCPWM_CAP0_SW_V << MCPWM_CAP0_SW_S) +#define MCPWM_CAP0_SW_V 0x00000001U +#define MCPWM_CAP0_SW_S 12 -#define MCPWM_CAP_CH1_CFG_REG(i) (REG_MCPWM_BASE(i) + 0xF4) -/* MCPWM_CAP1_SW : WO ;bitpos:[12] ;default: 1'd0 ; */ -/*description: Write 1 will trigger a sw capture.*/ -#define MCPWM_CAP1_SW (BIT(12)) -#define MCPWM_CAP1_SW_M (BIT(12)) -#define MCPWM_CAP1_SW_V 0x1 -#define MCPWM_CAP1_SW_S 12 -/* MCPWM_CAP1_IN_INVERT : R/W ;bitpos:[11] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP1_IN_INVERT (BIT(11)) -#define MCPWM_CAP1_IN_INVERT_M (BIT(11)) -#define MCPWM_CAP1_IN_INVERT_V 0x1 -#define MCPWM_CAP1_IN_INVERT_S 11 -/* MCPWM_CAP1_PRESCALE : R/W ;bitpos:[10:3] ;default: 8'd0 ; */ -/*description: .*/ -#define MCPWM_CAP1_PRESCALE 0x000000FF -#define MCPWM_CAP1_PRESCALE_M ((MCPWM_CAP1_PRESCALE_V)<<(MCPWM_CAP1_PRESCALE_S)) -#define MCPWM_CAP1_PRESCALE_V 0xFF -#define MCPWM_CAP1_PRESCALE_S 3 -/* MCPWM_CAP1_MODE : R/W ;bitpos:[2:1] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_CAP1_MODE 0x00000003 -#define MCPWM_CAP1_MODE_M ((MCPWM_CAP1_MODE_V)<<(MCPWM_CAP1_MODE_S)) -#define MCPWM_CAP1_MODE_V 0x3 -#define MCPWM_CAP1_MODE_S 1 -/* MCPWM_CAP1_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: .*/ +/** MCPWM_CAP_CH1_CFG_REG register + * Capture channel 1 configuration and enable + */ +#define MCPWM_CAP_CH1_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xf4) +/** MCPWM_CAP1_EN : R/W; bitpos: [0]; default: 0; + * When set, capture on channel 2 is enabled + */ #define MCPWM_CAP1_EN (BIT(0)) -#define MCPWM_CAP1_EN_M (BIT(0)) -#define MCPWM_CAP1_EN_V 0x1 +#define MCPWM_CAP1_EN_M (MCPWM_CAP1_EN_V << MCPWM_CAP1_EN_S) +#define MCPWM_CAP1_EN_V 0x00000001U #define MCPWM_CAP1_EN_S 0 +/** MCPWM_CAP1_MODE : R/W; bitpos: [2:1]; default: 0; + * Edge of capture on channel 1 after prescaling. When bit0 is set to 1: enable + * capture on the negative edge, When bit1 is set to 1: enable capture on the positive + * edge. + */ +#define MCPWM_CAP1_MODE 0x00000003U +#define MCPWM_CAP1_MODE_M (MCPWM_CAP1_MODE_V << MCPWM_CAP1_MODE_S) +#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 + + * 1 + */ +#define MCPWM_CAP1_PRESCALE 0x000000FFU +#define MCPWM_CAP1_PRESCALE_M (MCPWM_CAP1_PRESCALE_V << MCPWM_CAP1_PRESCALE_S) +#define MCPWM_CAP1_PRESCALE_V 0x000000FFU +#define MCPWM_CAP1_PRESCALE_S 3 +/** MCPWM_CAP1_IN_INVERT : R/W; bitpos: [11]; default: 0; + * when set, CAP1 form GPIO matrix is inverted before prescale + */ +#define MCPWM_CAP1_IN_INVERT (BIT(11)) +#define MCPWM_CAP1_IN_INVERT_M (MCPWM_CAP1_IN_INVERT_V << MCPWM_CAP1_IN_INVERT_S) +#define MCPWM_CAP1_IN_INVERT_V 0x00000001U +#define MCPWM_CAP1_IN_INVERT_S 11 +/** MCPWM_CAP1_SW : WT; bitpos: [12]; default: 0; + * Write 1 will trigger a software forced capture on channel 1 + */ +#define MCPWM_CAP1_SW (BIT(12)) +#define MCPWM_CAP1_SW_M (MCPWM_CAP1_SW_V << MCPWM_CAP1_SW_S) +#define MCPWM_CAP1_SW_V 0x00000001U +#define MCPWM_CAP1_SW_S 12 -#define MCPWM_CAP_CH2_CFG_REG(i) (REG_MCPWM_BASE(i) + 0xF8) -/* MCPWM_CAP2_SW : WO ;bitpos:[12] ;default: 1'd0 ; */ -/*description: Write 1 will trigger a sw capture.*/ -#define MCPWM_CAP2_SW (BIT(12)) -#define MCPWM_CAP2_SW_M (BIT(12)) -#define MCPWM_CAP2_SW_V 0x1 -#define MCPWM_CAP2_SW_S 12 -/* MCPWM_CAP2_IN_INVERT : R/W ;bitpos:[11] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP2_IN_INVERT (BIT(11)) -#define MCPWM_CAP2_IN_INVERT_M (BIT(11)) -#define MCPWM_CAP2_IN_INVERT_V 0x1 -#define MCPWM_CAP2_IN_INVERT_S 11 -/* MCPWM_CAP2_PRESCALE : R/W ;bitpos:[10:3] ;default: 8'd0 ; */ -/*description: .*/ -#define MCPWM_CAP2_PRESCALE 0x000000FF -#define MCPWM_CAP2_PRESCALE_M ((MCPWM_CAP2_PRESCALE_V)<<(MCPWM_CAP2_PRESCALE_S)) -#define MCPWM_CAP2_PRESCALE_V 0xFF -#define MCPWM_CAP2_PRESCALE_S 3 -/* MCPWM_CAP2_MODE : R/W ;bitpos:[2:1] ;default: 2'd0 ; */ -/*description: .*/ -#define MCPWM_CAP2_MODE 0x00000003 -#define MCPWM_CAP2_MODE_M ((MCPWM_CAP2_MODE_V)<<(MCPWM_CAP2_MODE_S)) -#define MCPWM_CAP2_MODE_V 0x3 -#define MCPWM_CAP2_MODE_S 1 -/* MCPWM_CAP2_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: .*/ +/** MCPWM_CAP_CH2_CFG_REG register + * Capture channel 2 configuration and enable + */ +#define MCPWM_CAP_CH2_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0xf8) +/** MCPWM_CAP2_EN : R/W; bitpos: [0]; default: 0; + * When set, capture on channel 2 is enabled + */ #define MCPWM_CAP2_EN (BIT(0)) -#define MCPWM_CAP2_EN_M (BIT(0)) -#define MCPWM_CAP2_EN_V 0x1 +#define MCPWM_CAP2_EN_M (MCPWM_CAP2_EN_V << MCPWM_CAP2_EN_S) +#define MCPWM_CAP2_EN_V 0x00000001U #define MCPWM_CAP2_EN_S 0 +/** MCPWM_CAP2_MODE : R/W; bitpos: [2:1]; default: 0; + * Edge of capture on channel 2 after prescaling. When bit0 is set to 1: enable + * capture on the negative edge, When bit1 is set to 1: enable capture on the positive + * edge. + */ +#define MCPWM_CAP2_MODE 0x00000003U +#define MCPWM_CAP2_MODE_M (MCPWM_CAP2_MODE_V << MCPWM_CAP2_MODE_S) +#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 + + * 1 + */ +#define MCPWM_CAP2_PRESCALE 0x000000FFU +#define MCPWM_CAP2_PRESCALE_M (MCPWM_CAP2_PRESCALE_V << MCPWM_CAP2_PRESCALE_S) +#define MCPWM_CAP2_PRESCALE_V 0x000000FFU +#define MCPWM_CAP2_PRESCALE_S 3 +/** MCPWM_CAP2_IN_INVERT : R/W; bitpos: [11]; default: 0; + * when set, CAP2 form GPIO matrix is inverted before prescale + */ +#define MCPWM_CAP2_IN_INVERT (BIT(11)) +#define MCPWM_CAP2_IN_INVERT_M (MCPWM_CAP2_IN_INVERT_V << MCPWM_CAP2_IN_INVERT_S) +#define MCPWM_CAP2_IN_INVERT_V 0x00000001U +#define MCPWM_CAP2_IN_INVERT_S 11 +/** MCPWM_CAP2_SW : WT; bitpos: [12]; default: 0; + * Write 1 will trigger a software forced capture on channel 2 + */ +#define MCPWM_CAP2_SW (BIT(12)) +#define MCPWM_CAP2_SW_M (MCPWM_CAP2_SW_V << MCPWM_CAP2_SW_S) +#define MCPWM_CAP2_SW_V 0x00000001U +#define MCPWM_CAP2_SW_S 12 -#define MCPWM_CAP_CH0_REG(i) (REG_MCPWM_BASE(i) + 0xFC) -/* MCPWM_CAP0_VALUE : RO ;bitpos:[31:0] ;default: 32'd0 ; */ -/*description: .*/ -#define MCPWM_CAP0_VALUE 0xFFFFFFFF -#define MCPWM_CAP0_VALUE_M ((MCPWM_CAP0_VALUE_V)<<(MCPWM_CAP0_VALUE_S)) -#define MCPWM_CAP0_VALUE_V 0xFFFFFFFF +/** MCPWM_CAP_CH0_REG register + * ch0 capture value status register + */ +#define MCPWM_CAP_CH0_REG(i) (DR_REG_MCPWM_BASE(i) + 0xfc) +/** MCPWM_CAP0_VALUE : RO; bitpos: [31:0]; default: 0; + * Value of last capture on channel 0 + */ +#define MCPWM_CAP0_VALUE 0xFFFFFFFFU +#define MCPWM_CAP0_VALUE_M (MCPWM_CAP0_VALUE_V << MCPWM_CAP0_VALUE_S) +#define MCPWM_CAP0_VALUE_V 0xFFFFFFFFU #define MCPWM_CAP0_VALUE_S 0 -#define MCPWM_CAP_CH1_REG(i) (REG_MCPWM_BASE(i) + 0x100) -/* MCPWM_CAP1_VALUE : RO ;bitpos:[31:0] ;default: 32'd0 ; */ -/*description: .*/ -#define MCPWM_CAP1_VALUE 0xFFFFFFFF -#define MCPWM_CAP1_VALUE_M ((MCPWM_CAP1_VALUE_V)<<(MCPWM_CAP1_VALUE_S)) -#define MCPWM_CAP1_VALUE_V 0xFFFFFFFF +/** MCPWM_CAP_CH1_REG register + * ch1 capture value status register + */ +#define MCPWM_CAP_CH1_REG(i) (DR_REG_MCPWM_BASE(i) + 0x100) +/** MCPWM_CAP1_VALUE : RO; bitpos: [31:0]; default: 0; + * Value of last capture on channel 1 + */ +#define MCPWM_CAP1_VALUE 0xFFFFFFFFU +#define MCPWM_CAP1_VALUE_M (MCPWM_CAP1_VALUE_V << MCPWM_CAP1_VALUE_S) +#define MCPWM_CAP1_VALUE_V 0xFFFFFFFFU #define MCPWM_CAP1_VALUE_S 0 -#define MCPWM_CAP_CH2_REG(i) (REG_MCPWM_BASE(i) + 0x104) -/* MCPWM_CAP2_VALUE : RO ;bitpos:[31:0] ;default: 32'd0 ; */ -/*description: .*/ -#define MCPWM_CAP2_VALUE 0xFFFFFFFF -#define MCPWM_CAP2_VALUE_M ((MCPWM_CAP2_VALUE_V)<<(MCPWM_CAP2_VALUE_S)) -#define MCPWM_CAP2_VALUE_V 0xFFFFFFFF +/** MCPWM_CAP_CH2_REG register + * ch2 capture value status register + */ +#define MCPWM_CAP_CH2_REG(i) (DR_REG_MCPWM_BASE(i) + 0x104) +/** MCPWM_CAP2_VALUE : RO; bitpos: [31:0]; default: 0; + * Value of last capture on channel 2 + */ +#define MCPWM_CAP2_VALUE 0xFFFFFFFFU +#define MCPWM_CAP2_VALUE_M (MCPWM_CAP2_VALUE_V << MCPWM_CAP2_VALUE_S) +#define MCPWM_CAP2_VALUE_V 0xFFFFFFFFU #define MCPWM_CAP2_VALUE_S 0 -#define MCPWM_CAP_STATUS_REG(i) (REG_MCPWM_BASE(i) + 0x108) -/* MCPWM_CAP2_EDGE : RO ;bitpos:[2] ;default: 1'd0 ; */ -/*description: cap trigger's edge, 0: posedge, 1: negedge.*/ -#define MCPWM_CAP2_EDGE (BIT(2)) -#define MCPWM_CAP2_EDGE_M (BIT(2)) -#define MCPWM_CAP2_EDGE_V 0x1 -#define MCPWM_CAP2_EDGE_S 2 -/* MCPWM_CAP1_EDGE : RO ;bitpos:[1] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP1_EDGE (BIT(1)) -#define MCPWM_CAP1_EDGE_M (BIT(1)) -#define MCPWM_CAP1_EDGE_V 0x1 -#define MCPWM_CAP1_EDGE_S 1 -/* MCPWM_CAP0_EDGE : RO ;bitpos:[0] ;default: 1'd0 ; */ -/*description: .*/ +/** MCPWM_CAP_STATUS_REG register + * Edge of last capture trigger + */ +#define MCPWM_CAP_STATUS_REG(i) (DR_REG_MCPWM_BASE(i) + 0x108) +/** MCPWM_CAP0_EDGE : RO; bitpos: [0]; default: 0; + * Edge of last capture trigger on channel 0, 0: posedge, 1: negedge + */ #define MCPWM_CAP0_EDGE (BIT(0)) -#define MCPWM_CAP0_EDGE_M (BIT(0)) -#define MCPWM_CAP0_EDGE_V 0x1 +#define MCPWM_CAP0_EDGE_M (MCPWM_CAP0_EDGE_V << MCPWM_CAP0_EDGE_S) +#define MCPWM_CAP0_EDGE_V 0x00000001U #define MCPWM_CAP0_EDGE_S 0 +/** MCPWM_CAP1_EDGE : RO; bitpos: [1]; default: 0; + * Edge of last capture trigger on channel 1, 0: posedge, 1: negedge + */ +#define MCPWM_CAP1_EDGE (BIT(1)) +#define MCPWM_CAP1_EDGE_M (MCPWM_CAP1_EDGE_V << MCPWM_CAP1_EDGE_S) +#define MCPWM_CAP1_EDGE_V 0x00000001U +#define MCPWM_CAP1_EDGE_S 1 +/** MCPWM_CAP2_EDGE : RO; bitpos: [2]; default: 0; + * Edge of last capture trigger on channel 2, 0: posedge, 1: negedge + */ +#define MCPWM_CAP2_EDGE (BIT(2)) +#define MCPWM_CAP2_EDGE_M (MCPWM_CAP2_EDGE_V << MCPWM_CAP2_EDGE_S) +#define MCPWM_CAP2_EDGE_V 0x00000001U +#define MCPWM_CAP2_EDGE_S 2 -#define MCPWM_UPDATE_CFG_REG(i) (REG_MCPWM_BASE(i) + 0x10C) -/* MCPWM_OP2_FORCE_UP : R/W ;bitpos:[7] ;default: 1'd0 ; */ -/*description: a toggle will trigger a force update.*/ -#define MCPWM_OP2_FORCE_UP (BIT(7)) -#define MCPWM_OP2_FORCE_UP_M (BIT(7)) -#define MCPWM_OP2_FORCE_UP_V 0x1 -#define MCPWM_OP2_FORCE_UP_S 7 -/* MCPWM_OP2_UP_EN : R/W ;bitpos:[6] ;default: 1'd1 ; */ -/*description: reg update local enable.*/ -#define MCPWM_OP2_UP_EN (BIT(6)) -#define MCPWM_OP2_UP_EN_M (BIT(6)) -#define MCPWM_OP2_UP_EN_V 0x1 -#define MCPWM_OP2_UP_EN_S 6 -/* MCPWM_OP1_FORCE_UP : R/W ;bitpos:[5] ;default: 1'd0 ; */ -/*description: a toggle will trigger a force update.*/ -#define MCPWM_OP1_FORCE_UP (BIT(5)) -#define MCPWM_OP1_FORCE_UP_M (BIT(5)) -#define MCPWM_OP1_FORCE_UP_V 0x1 -#define MCPWM_OP1_FORCE_UP_S 5 -/* MCPWM_OP1_UP_EN : R/W ;bitpos:[4] ;default: 1'd1 ; */ -/*description: .*/ -#define MCPWM_OP1_UP_EN (BIT(4)) -#define MCPWM_OP1_UP_EN_M (BIT(4)) -#define MCPWM_OP1_UP_EN_V 0x1 -#define MCPWM_OP1_UP_EN_S 4 -/* MCPWM_OP0_FORCE_UP : R/W ;bitpos:[3] ;default: 1'd0 ; */ -/*description: a toggle will trigger a force update.*/ -#define MCPWM_OP0_FORCE_UP (BIT(3)) -#define MCPWM_OP0_FORCE_UP_M (BIT(3)) -#define MCPWM_OP0_FORCE_UP_V 0x1 -#define MCPWM_OP0_FORCE_UP_S 3 -/* MCPWM_OP0_UP_EN : R/W ;bitpos:[2] ;default: 1'd1 ; */ -/*description: .*/ -#define MCPWM_OP0_UP_EN (BIT(2)) -#define MCPWM_OP0_UP_EN_M (BIT(2)) -#define MCPWM_OP0_UP_EN_V 0x1 -#define MCPWM_OP0_UP_EN_S 2 -/* MCPWM_GLOBAL_FORCE_UP : R/W ;bitpos:[1] ;default: 1'd0 ; */ -/*description: a toggle will trigger a force update, all timers and operators will update their - active regs.*/ -#define MCPWM_GLOBAL_FORCE_UP (BIT(1)) -#define MCPWM_GLOBAL_FORCE_UP_M (BIT(1)) -#define MCPWM_GLOBAL_FORCE_UP_V 0x1 -#define MCPWM_GLOBAL_FORCE_UP_S 1 -/* MCPWM_GLOBAL_UP_EN : R/W ;bitpos:[0] ;default: 1'd1 ; */ -/*description: .*/ +/** MCPWM_UPDATE_CFG_REG register + * Enable update. + */ +#define MCPWM_UPDATE_CFG_REG(i) (DR_REG_MCPWM_BASE(i) + 0x10c) +/** MCPWM_GLOBAL_UP_EN : R/W; bitpos: [0]; default: 1; + * The global enable of update of all active registers in MCPWM module + */ #define MCPWM_GLOBAL_UP_EN (BIT(0)) -#define MCPWM_GLOBAL_UP_EN_M (BIT(0)) -#define MCPWM_GLOBAL_UP_EN_V 0x1 +#define MCPWM_GLOBAL_UP_EN_M (MCPWM_GLOBAL_UP_EN_V << MCPWM_GLOBAL_UP_EN_S) +#define MCPWM_GLOBAL_UP_EN_V 0x00000001U #define MCPWM_GLOBAL_UP_EN_S 0 +/** MCPWM_GLOBAL_FORCE_UP : R/W; bitpos: [1]; default: 0; + * a toggle (software invert its value) will trigger a forced update of all active + * registers in MCPWM module + */ +#define MCPWM_GLOBAL_FORCE_UP (BIT(1)) +#define MCPWM_GLOBAL_FORCE_UP_M (MCPWM_GLOBAL_FORCE_UP_V << MCPWM_GLOBAL_FORCE_UP_S) +#define MCPWM_GLOBAL_FORCE_UP_V 0x00000001U +#define MCPWM_GLOBAL_FORCE_UP_S 1 +/** MCPWM_OP0_UP_EN : R/W; bitpos: [2]; default: 1; + * When set and PWM_GLOBAL_UP_EN is set, update of active registers in PWM operator 0 + * are enabled + */ +#define MCPWM_OP0_UP_EN (BIT(2)) +#define MCPWM_OP0_UP_EN_M (MCPWM_OP0_UP_EN_V << MCPWM_OP0_UP_EN_S) +#define MCPWM_OP0_UP_EN_V 0x00000001U +#define MCPWM_OP0_UP_EN_S 2 +/** MCPWM_OP0_FORCE_UP : R/W; bitpos: [3]; default: 0; + * a toggle (software invert its value) will trigger a forced update of active + * registers in PWM operator 0 + */ +#define MCPWM_OP0_FORCE_UP (BIT(3)) +#define MCPWM_OP0_FORCE_UP_M (MCPWM_OP0_FORCE_UP_V << MCPWM_OP0_FORCE_UP_S) +#define MCPWM_OP0_FORCE_UP_V 0x00000001U +#define MCPWM_OP0_FORCE_UP_S 3 +/** MCPWM_OP1_UP_EN : R/W; bitpos: [4]; default: 1; + * When set and PWM_GLOBAL_UP_EN is set, update of active registers in PWM operator 1 + * are enabled + */ +#define MCPWM_OP1_UP_EN (BIT(4)) +#define MCPWM_OP1_UP_EN_M (MCPWM_OP1_UP_EN_V << MCPWM_OP1_UP_EN_S) +#define MCPWM_OP1_UP_EN_V 0x00000001U +#define MCPWM_OP1_UP_EN_S 4 +/** MCPWM_OP1_FORCE_UP : R/W; bitpos: [5]; default: 0; + * a toggle (software invert its value) will trigger a forced update of active + * registers in PWM operator 1 + */ +#define MCPWM_OP1_FORCE_UP (BIT(5)) +#define MCPWM_OP1_FORCE_UP_M (MCPWM_OP1_FORCE_UP_V << MCPWM_OP1_FORCE_UP_S) +#define MCPWM_OP1_FORCE_UP_V 0x00000001U +#define MCPWM_OP1_FORCE_UP_S 5 +/** MCPWM_OP2_UP_EN : R/W; bitpos: [6]; default: 1; + * When set and PWM_GLOBAL_UP_EN is set, update of active registers in PWM operator 2 + * are enabled + */ +#define MCPWM_OP2_UP_EN (BIT(6)) +#define MCPWM_OP2_UP_EN_M (MCPWM_OP2_UP_EN_V << MCPWM_OP2_UP_EN_S) +#define MCPWM_OP2_UP_EN_V 0x00000001U +#define MCPWM_OP2_UP_EN_S 6 +/** MCPWM_OP2_FORCE_UP : R/W; bitpos: [7]; default: 0; + * a toggle (software invert its value) will trigger a forced update of active + * registers in PWM operator 2 + */ +#define MCPWM_OP2_FORCE_UP (BIT(7)) +#define MCPWM_OP2_FORCE_UP_M (MCPWM_OP2_FORCE_UP_V << MCPWM_OP2_FORCE_UP_S) +#define MCPWM_OP2_FORCE_UP_V 0x00000001U +#define MCPWM_OP2_FORCE_UP_S 7 -#define MCPWM_INT_ENA_PWM_REG(i) (REG_MCPWM_BASE(i) + 0x110) -/* MCPWM_CAP2_INT_ENA : R/W ;bitpos:[29] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP2_INT_ENA (BIT(29)) -#define MCPWM_CAP2_INT_ENA_M (BIT(29)) -#define MCPWM_CAP2_INT_ENA_V 0x1 -#define MCPWM_CAP2_INT_ENA_S 29 -/* MCPWM_CAP1_INT_ENA : R/W ;bitpos:[28] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP1_INT_ENA (BIT(28)) -#define MCPWM_CAP1_INT_ENA_M (BIT(28)) -#define MCPWM_CAP1_INT_ENA_V 0x1 -#define MCPWM_CAP1_INT_ENA_S 28 -/* MCPWM_CAP0_INT_ENA : R/W ;bitpos:[27] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP0_INT_ENA (BIT(27)) -#define MCPWM_CAP0_INT_ENA_M (BIT(27)) -#define MCPWM_CAP0_INT_ENA_V 0x1 -#define MCPWM_CAP0_INT_ENA_S 27 -/* MCPWM_TZ2_OST_INT_ENA : R/W ;bitpos:[26] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ2_OST_INT_ENA (BIT(26)) -#define MCPWM_TZ2_OST_INT_ENA_M (BIT(26)) -#define MCPWM_TZ2_OST_INT_ENA_V 0x1 -#define MCPWM_TZ2_OST_INT_ENA_S 26 -/* MCPWM_TZ1_OST_INT_ENA : R/W ;bitpos:[25] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ1_OST_INT_ENA (BIT(25)) -#define MCPWM_TZ1_OST_INT_ENA_M (BIT(25)) -#define MCPWM_TZ1_OST_INT_ENA_V 0x1 -#define MCPWM_TZ1_OST_INT_ENA_S 25 -/* MCPWM_TZ0_OST_INT_ENA : R/W ;bitpos:[24] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ0_OST_INT_ENA (BIT(24)) -#define MCPWM_TZ0_OST_INT_ENA_M (BIT(24)) -#define MCPWM_TZ0_OST_INT_ENA_V 0x1 -#define MCPWM_TZ0_OST_INT_ENA_S 24 -/* MCPWM_TZ2_CBC_INT_ENA : R/W ;bitpos:[23] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ2_CBC_INT_ENA (BIT(23)) -#define MCPWM_TZ2_CBC_INT_ENA_M (BIT(23)) -#define MCPWM_TZ2_CBC_INT_ENA_V 0x1 -#define MCPWM_TZ2_CBC_INT_ENA_S 23 -/* MCPWM_TZ1_CBC_INT_ENA : R/W ;bitpos:[22] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ1_CBC_INT_ENA (BIT(22)) -#define MCPWM_TZ1_CBC_INT_ENA_M (BIT(22)) -#define MCPWM_TZ1_CBC_INT_ENA_V 0x1 -#define MCPWM_TZ1_CBC_INT_ENA_S 22 -/* MCPWM_TZ0_CBC_INT_ENA : R/W ;bitpos:[21] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ0_CBC_INT_ENA (BIT(21)) -#define MCPWM_TZ0_CBC_INT_ENA_M (BIT(21)) -#define MCPWM_TZ0_CBC_INT_ENA_V 0x1 -#define MCPWM_TZ0_CBC_INT_ENA_S 21 -/* MCPWM_CMPR2_TEB_INT_ENA : R/W ;bitpos:[20] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR2_TEB_INT_ENA (BIT(20)) -#define MCPWM_CMPR2_TEB_INT_ENA_M (BIT(20)) -#define MCPWM_CMPR2_TEB_INT_ENA_V 0x1 -#define MCPWM_CMPR2_TEB_INT_ENA_S 20 -/* MCPWM_CMPR1_TEB_INT_ENA : R/W ;bitpos:[19] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR1_TEB_INT_ENA (BIT(19)) -#define MCPWM_CMPR1_TEB_INT_ENA_M (BIT(19)) -#define MCPWM_CMPR1_TEB_INT_ENA_V 0x1 -#define MCPWM_CMPR1_TEB_INT_ENA_S 19 -/* MCPWM_CMPR0_TEB_INT_ENA : R/W ;bitpos:[18] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR0_TEB_INT_ENA (BIT(18)) -#define MCPWM_CMPR0_TEB_INT_ENA_M (BIT(18)) -#define MCPWM_CMPR0_TEB_INT_ENA_V 0x1 -#define MCPWM_CMPR0_TEB_INT_ENA_S 18 -/* MCPWM_CMPR2_TEA_INT_ENA : R/W ;bitpos:[17] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR2_TEA_INT_ENA (BIT(17)) -#define MCPWM_CMPR2_TEA_INT_ENA_M (BIT(17)) -#define MCPWM_CMPR2_TEA_INT_ENA_V 0x1 -#define MCPWM_CMPR2_TEA_INT_ENA_S 17 -/* MCPWM_CMPR1_TEA_INT_ENA : R/W ;bitpos:[16] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR1_TEA_INT_ENA (BIT(16)) -#define MCPWM_CMPR1_TEA_INT_ENA_M (BIT(16)) -#define MCPWM_CMPR1_TEA_INT_ENA_V 0x1 -#define MCPWM_CMPR1_TEA_INT_ENA_S 16 -/* MCPWM_CMPR0_TEA_INT_ENA : R/W ;bitpos:[15] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR0_TEA_INT_ENA (BIT(15)) -#define MCPWM_CMPR0_TEA_INT_ENA_M (BIT(15)) -#define MCPWM_CMPR0_TEA_INT_ENA_V 0x1 -#define MCPWM_CMPR0_TEA_INT_ENA_S 15 -/* MCPWM_FAULT2_CLR_INT_ENA : R/W ;bitpos:[14] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT2_CLR_INT_ENA (BIT(14)) -#define MCPWM_FAULT2_CLR_INT_ENA_M (BIT(14)) -#define MCPWM_FAULT2_CLR_INT_ENA_V 0x1 -#define MCPWM_FAULT2_CLR_INT_ENA_S 14 -/* MCPWM_FAULT1_CLR_INT_ENA : R/W ;bitpos:[13] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT1_CLR_INT_ENA (BIT(13)) -#define MCPWM_FAULT1_CLR_INT_ENA_M (BIT(13)) -#define MCPWM_FAULT1_CLR_INT_ENA_V 0x1 -#define MCPWM_FAULT1_CLR_INT_ENA_S 13 -/* MCPWM_FAULT0_CLR_INT_ENA : R/W ;bitpos:[12] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT0_CLR_INT_ENA (BIT(12)) -#define MCPWM_FAULT0_CLR_INT_ENA_M (BIT(12)) -#define MCPWM_FAULT0_CLR_INT_ENA_V 0x1 -#define MCPWM_FAULT0_CLR_INT_ENA_S 12 -/* MCPWM_FAULT2_INT_ENA : R/W ;bitpos:[11] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT2_INT_ENA (BIT(11)) -#define MCPWM_FAULT2_INT_ENA_M (BIT(11)) -#define MCPWM_FAULT2_INT_ENA_V 0x1 -#define MCPWM_FAULT2_INT_ENA_S 11 -/* MCPWM_FAULT1_INT_ENA : R/W ;bitpos:[10] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT1_INT_ENA (BIT(10)) -#define MCPWM_FAULT1_INT_ENA_M (BIT(10)) -#define MCPWM_FAULT1_INT_ENA_V 0x1 -#define MCPWM_FAULT1_INT_ENA_S 10 -/* MCPWM_FAULT0_INT_ENA : R/W ;bitpos:[9] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT0_INT_ENA (BIT(9)) -#define MCPWM_FAULT0_INT_ENA_M (BIT(9)) -#define MCPWM_FAULT0_INT_ENA_V 0x1 -#define MCPWM_FAULT0_INT_ENA_S 9 -/* MCPWM_TIMER2_TEP_INT_ENA : R/W ;bitpos:[8] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_TEP_INT_ENA (BIT(8)) -#define MCPWM_TIMER2_TEP_INT_ENA_M (BIT(8)) -#define MCPWM_TIMER2_TEP_INT_ENA_V 0x1 -#define MCPWM_TIMER2_TEP_INT_ENA_S 8 -/* MCPWM_TIMER1_TEP_INT_ENA : R/W ;bitpos:[7] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_TEP_INT_ENA (BIT(7)) -#define MCPWM_TIMER1_TEP_INT_ENA_M (BIT(7)) -#define MCPWM_TIMER1_TEP_INT_ENA_V 0x1 -#define MCPWM_TIMER1_TEP_INT_ENA_S 7 -/* MCPWM_TIMER0_TEP_INT_ENA : R/W ;bitpos:[6] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER0_TEP_INT_ENA (BIT(6)) -#define MCPWM_TIMER0_TEP_INT_ENA_M (BIT(6)) -#define MCPWM_TIMER0_TEP_INT_ENA_V 0x1 -#define MCPWM_TIMER0_TEP_INT_ENA_S 6 -/* MCPWM_TIMER2_TEZ_INT_ENA : R/W ;bitpos:[5] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_TEZ_INT_ENA (BIT(5)) -#define MCPWM_TIMER2_TEZ_INT_ENA_M (BIT(5)) -#define MCPWM_TIMER2_TEZ_INT_ENA_V 0x1 -#define MCPWM_TIMER2_TEZ_INT_ENA_S 5 -/* MCPWM_TIMER1_TEZ_INT_ENA : R/W ;bitpos:[4] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_TEZ_INT_ENA (BIT(4)) -#define MCPWM_TIMER1_TEZ_INT_ENA_M (BIT(4)) -#define MCPWM_TIMER1_TEZ_INT_ENA_V 0x1 -#define MCPWM_TIMER1_TEZ_INT_ENA_S 4 -/* MCPWM_TIMER0_TEZ_INT_ENA : R/W ;bitpos:[3] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER0_TEZ_INT_ENA (BIT(3)) -#define MCPWM_TIMER0_TEZ_INT_ENA_M (BIT(3)) -#define MCPWM_TIMER0_TEZ_INT_ENA_V 0x1 -#define MCPWM_TIMER0_TEZ_INT_ENA_S 3 -/* MCPWM_TIMER2_STOP_INT_ENA : R/W ;bitpos:[2] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_STOP_INT_ENA (BIT(2)) -#define MCPWM_TIMER2_STOP_INT_ENA_M (BIT(2)) -#define MCPWM_TIMER2_STOP_INT_ENA_V 0x1 -#define MCPWM_TIMER2_STOP_INT_ENA_S 2 -/* MCPWM_TIMER1_STOP_INT_ENA : R/W ;bitpos:[1] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_STOP_INT_ENA (BIT(1)) -#define MCPWM_TIMER1_STOP_INT_ENA_M (BIT(1)) -#define MCPWM_TIMER1_STOP_INT_ENA_V 0x1 -#define MCPWM_TIMER1_STOP_INT_ENA_S 1 -/* MCPWM_TIMER0_STOP_INT_ENA : R/W ;bitpos:[0] ;default: 1'h0 ; */ -/*description: .*/ +/** MCPWM_INT_ENA_REG register + * Interrupt enable bits + */ +#define MCPWM_INT_ENA_REG(i) (DR_REG_MCPWM_BASE(i) + 0x110) +/** MCPWM_TIMER0_STOP_INT_ENA : R/W; bitpos: [0]; default: 0; + * The enable bit for the interrupt triggered when the timer 0 stops. + */ #define MCPWM_TIMER0_STOP_INT_ENA (BIT(0)) -#define MCPWM_TIMER0_STOP_INT_ENA_M (BIT(0)) -#define MCPWM_TIMER0_STOP_INT_ENA_V 0x1 +#define MCPWM_TIMER0_STOP_INT_ENA_M (MCPWM_TIMER0_STOP_INT_ENA_V << MCPWM_TIMER0_STOP_INT_ENA_S) +#define MCPWM_TIMER0_STOP_INT_ENA_V 0x00000001U #define MCPWM_TIMER0_STOP_INT_ENA_S 0 +/** MCPWM_TIMER1_STOP_INT_ENA : R/W; bitpos: [1]; default: 0; + * The enable bit for the interrupt triggered when the timer 1 stops. + */ +#define MCPWM_TIMER1_STOP_INT_ENA (BIT(1)) +#define MCPWM_TIMER1_STOP_INT_ENA_M (MCPWM_TIMER1_STOP_INT_ENA_V << MCPWM_TIMER1_STOP_INT_ENA_S) +#define MCPWM_TIMER1_STOP_INT_ENA_V 0x00000001U +#define MCPWM_TIMER1_STOP_INT_ENA_S 1 +/** MCPWM_TIMER2_STOP_INT_ENA : R/W; bitpos: [2]; default: 0; + * The enable bit for the interrupt triggered when the timer 2 stops. + */ +#define MCPWM_TIMER2_STOP_INT_ENA (BIT(2)) +#define MCPWM_TIMER2_STOP_INT_ENA_M (MCPWM_TIMER2_STOP_INT_ENA_V << MCPWM_TIMER2_STOP_INT_ENA_S) +#define MCPWM_TIMER2_STOP_INT_ENA_V 0x00000001U +#define MCPWM_TIMER2_STOP_INT_ENA_S 2 +/** MCPWM_TIMER0_TEZ_INT_ENA : R/W; bitpos: [3]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 0 TEZ event. + */ +#define MCPWM_TIMER0_TEZ_INT_ENA (BIT(3)) +#define MCPWM_TIMER0_TEZ_INT_ENA_M (MCPWM_TIMER0_TEZ_INT_ENA_V << MCPWM_TIMER0_TEZ_INT_ENA_S) +#define MCPWM_TIMER0_TEZ_INT_ENA_V 0x00000001U +#define MCPWM_TIMER0_TEZ_INT_ENA_S 3 +/** MCPWM_TIMER1_TEZ_INT_ENA : R/W; bitpos: [4]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 1 TEZ event. + */ +#define MCPWM_TIMER1_TEZ_INT_ENA (BIT(4)) +#define MCPWM_TIMER1_TEZ_INT_ENA_M (MCPWM_TIMER1_TEZ_INT_ENA_V << MCPWM_TIMER1_TEZ_INT_ENA_S) +#define MCPWM_TIMER1_TEZ_INT_ENA_V 0x00000001U +#define MCPWM_TIMER1_TEZ_INT_ENA_S 4 +/** MCPWM_TIMER2_TEZ_INT_ENA : R/W; bitpos: [5]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 2 TEZ event. + */ +#define MCPWM_TIMER2_TEZ_INT_ENA (BIT(5)) +#define MCPWM_TIMER2_TEZ_INT_ENA_M (MCPWM_TIMER2_TEZ_INT_ENA_V << MCPWM_TIMER2_TEZ_INT_ENA_S) +#define MCPWM_TIMER2_TEZ_INT_ENA_V 0x00000001U +#define MCPWM_TIMER2_TEZ_INT_ENA_S 5 +/** MCPWM_TIMER0_TEP_INT_ENA : R/W; bitpos: [6]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 0 TEP event. + */ +#define MCPWM_TIMER0_TEP_INT_ENA (BIT(6)) +#define MCPWM_TIMER0_TEP_INT_ENA_M (MCPWM_TIMER0_TEP_INT_ENA_V << MCPWM_TIMER0_TEP_INT_ENA_S) +#define MCPWM_TIMER0_TEP_INT_ENA_V 0x00000001U +#define MCPWM_TIMER0_TEP_INT_ENA_S 6 +/** MCPWM_TIMER1_TEP_INT_ENA : R/W; bitpos: [7]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 1 TEP event. + */ +#define MCPWM_TIMER1_TEP_INT_ENA (BIT(7)) +#define MCPWM_TIMER1_TEP_INT_ENA_M (MCPWM_TIMER1_TEP_INT_ENA_V << MCPWM_TIMER1_TEP_INT_ENA_S) +#define MCPWM_TIMER1_TEP_INT_ENA_V 0x00000001U +#define MCPWM_TIMER1_TEP_INT_ENA_S 7 +/** MCPWM_TIMER2_TEP_INT_ENA : R/W; bitpos: [8]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 2 TEP event. + */ +#define MCPWM_TIMER2_TEP_INT_ENA (BIT(8)) +#define MCPWM_TIMER2_TEP_INT_ENA_M (MCPWM_TIMER2_TEP_INT_ENA_V << MCPWM_TIMER2_TEP_INT_ENA_S) +#define MCPWM_TIMER2_TEP_INT_ENA_V 0x00000001U +#define MCPWM_TIMER2_TEP_INT_ENA_S 8 +/** MCPWM_FAULT0_INT_ENA : R/W; bitpos: [9]; default: 0; + * The enable bit for the interrupt triggered when fault_event0 starts. + */ +#define MCPWM_FAULT0_INT_ENA (BIT(9)) +#define MCPWM_FAULT0_INT_ENA_M (MCPWM_FAULT0_INT_ENA_V << MCPWM_FAULT0_INT_ENA_S) +#define MCPWM_FAULT0_INT_ENA_V 0x00000001U +#define MCPWM_FAULT0_INT_ENA_S 9 +/** MCPWM_FAULT1_INT_ENA : R/W; bitpos: [10]; default: 0; + * The enable bit for the interrupt triggered when fault_event1 starts. + */ +#define MCPWM_FAULT1_INT_ENA (BIT(10)) +#define MCPWM_FAULT1_INT_ENA_M (MCPWM_FAULT1_INT_ENA_V << MCPWM_FAULT1_INT_ENA_S) +#define MCPWM_FAULT1_INT_ENA_V 0x00000001U +#define MCPWM_FAULT1_INT_ENA_S 10 +/** MCPWM_FAULT2_INT_ENA : R/W; bitpos: [11]; default: 0; + * The enable bit for the interrupt triggered when fault_event2 starts. + */ +#define MCPWM_FAULT2_INT_ENA (BIT(11)) +#define MCPWM_FAULT2_INT_ENA_M (MCPWM_FAULT2_INT_ENA_V << MCPWM_FAULT2_INT_ENA_S) +#define MCPWM_FAULT2_INT_ENA_V 0x00000001U +#define MCPWM_FAULT2_INT_ENA_S 11 +/** MCPWM_FAULT0_CLR_INT_ENA : R/W; bitpos: [12]; default: 0; + * The enable bit for the interrupt triggered when fault_event0 ends. + */ +#define MCPWM_FAULT0_CLR_INT_ENA (BIT(12)) +#define MCPWM_FAULT0_CLR_INT_ENA_M (MCPWM_FAULT0_CLR_INT_ENA_V << MCPWM_FAULT0_CLR_INT_ENA_S) +#define MCPWM_FAULT0_CLR_INT_ENA_V 0x00000001U +#define MCPWM_FAULT0_CLR_INT_ENA_S 12 +/** MCPWM_FAULT1_CLR_INT_ENA : R/W; bitpos: [13]; default: 0; + * The enable bit for the interrupt triggered when fault_event1 ends. + */ +#define MCPWM_FAULT1_CLR_INT_ENA (BIT(13)) +#define MCPWM_FAULT1_CLR_INT_ENA_M (MCPWM_FAULT1_CLR_INT_ENA_V << MCPWM_FAULT1_CLR_INT_ENA_S) +#define MCPWM_FAULT1_CLR_INT_ENA_V 0x00000001U +#define MCPWM_FAULT1_CLR_INT_ENA_S 13 +/** MCPWM_FAULT2_CLR_INT_ENA : R/W; bitpos: [14]; default: 0; + * The enable bit for the interrupt triggered when fault_event2 ends. + */ +#define MCPWM_FAULT2_CLR_INT_ENA (BIT(14)) +#define MCPWM_FAULT2_CLR_INT_ENA_M (MCPWM_FAULT2_CLR_INT_ENA_V << MCPWM_FAULT2_CLR_INT_ENA_S) +#define MCPWM_FAULT2_CLR_INT_ENA_V 0x00000001U +#define MCPWM_FAULT2_CLR_INT_ENA_S 14 +/** MCPWM_OP0_TEA_INT_ENA : R/W; bitpos: [15]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 0 TEA event + */ +#define MCPWM_OP0_TEA_INT_ENA (BIT(15)) +#define MCPWM_OP0_TEA_INT_ENA_M (MCPWM_OP0_TEA_INT_ENA_V << MCPWM_OP0_TEA_INT_ENA_S) +#define MCPWM_OP0_TEA_INT_ENA_V 0x00000001U +#define MCPWM_OP0_TEA_INT_ENA_S 15 +/** MCPWM_OP1_TEA_INT_ENA : R/W; bitpos: [16]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 1 TEA event + */ +#define MCPWM_OP1_TEA_INT_ENA (BIT(16)) +#define MCPWM_OP1_TEA_INT_ENA_M (MCPWM_OP1_TEA_INT_ENA_V << MCPWM_OP1_TEA_INT_ENA_S) +#define MCPWM_OP1_TEA_INT_ENA_V 0x00000001U +#define MCPWM_OP1_TEA_INT_ENA_S 16 +/** MCPWM_OP2_TEA_INT_ENA : R/W; bitpos: [17]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 2 TEA event + */ +#define MCPWM_OP2_TEA_INT_ENA (BIT(17)) +#define MCPWM_OP2_TEA_INT_ENA_M (MCPWM_OP2_TEA_INT_ENA_V << MCPWM_OP2_TEA_INT_ENA_S) +#define MCPWM_OP2_TEA_INT_ENA_V 0x00000001U +#define MCPWM_OP2_TEA_INT_ENA_S 17 +/** MCPWM_OP0_TEB_INT_ENA : R/W; bitpos: [18]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 0 TEB event + */ +#define MCPWM_OP0_TEB_INT_ENA (BIT(18)) +#define MCPWM_OP0_TEB_INT_ENA_M (MCPWM_OP0_TEB_INT_ENA_V << MCPWM_OP0_TEB_INT_ENA_S) +#define MCPWM_OP0_TEB_INT_ENA_V 0x00000001U +#define MCPWM_OP0_TEB_INT_ENA_S 18 +/** MCPWM_OP1_TEB_INT_ENA : R/W; bitpos: [19]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 1 TEB event + */ +#define MCPWM_OP1_TEB_INT_ENA (BIT(19)) +#define MCPWM_OP1_TEB_INT_ENA_M (MCPWM_OP1_TEB_INT_ENA_V << MCPWM_OP1_TEB_INT_ENA_S) +#define MCPWM_OP1_TEB_INT_ENA_V 0x00000001U +#define MCPWM_OP1_TEB_INT_ENA_S 19 +/** MCPWM_OP2_TEB_INT_ENA : R/W; bitpos: [20]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 2 TEB event + */ +#define MCPWM_OP2_TEB_INT_ENA (BIT(20)) +#define MCPWM_OP2_TEB_INT_ENA_M (MCPWM_OP2_TEB_INT_ENA_V << MCPWM_OP2_TEB_INT_ENA_S) +#define MCPWM_OP2_TEB_INT_ENA_V 0x00000001U +#define MCPWM_OP2_TEB_INT_ENA_S 20 +/** MCPWM_FH0_CBC_INT_ENA : R/W; bitpos: [21]; default: 0; + * The enable bit for the interrupt triggered by a cycle-by-cycle mode action on PWM0. + */ +#define MCPWM_FH0_CBC_INT_ENA (BIT(21)) +#define MCPWM_FH0_CBC_INT_ENA_M (MCPWM_FH0_CBC_INT_ENA_V << MCPWM_FH0_CBC_INT_ENA_S) +#define MCPWM_FH0_CBC_INT_ENA_V 0x00000001U +#define MCPWM_FH0_CBC_INT_ENA_S 21 +/** MCPWM_FH1_CBC_INT_ENA : R/W; bitpos: [22]; default: 0; + * The enable bit for the interrupt triggered by a cycle-by-cycle mode action on PWM1. + */ +#define MCPWM_FH1_CBC_INT_ENA (BIT(22)) +#define MCPWM_FH1_CBC_INT_ENA_M (MCPWM_FH1_CBC_INT_ENA_V << MCPWM_FH1_CBC_INT_ENA_S) +#define MCPWM_FH1_CBC_INT_ENA_V 0x00000001U +#define MCPWM_FH1_CBC_INT_ENA_S 22 +/** MCPWM_FH2_CBC_INT_ENA : R/W; bitpos: [23]; default: 0; + * The enable bit for the interrupt triggered by a cycle-by-cycle mode action on PWM2. + */ +#define MCPWM_FH2_CBC_INT_ENA (BIT(23)) +#define MCPWM_FH2_CBC_INT_ENA_M (MCPWM_FH2_CBC_INT_ENA_V << MCPWM_FH2_CBC_INT_ENA_S) +#define MCPWM_FH2_CBC_INT_ENA_V 0x00000001U +#define MCPWM_FH2_CBC_INT_ENA_S 23 +/** MCPWM_FH0_OST_INT_ENA : R/W; bitpos: [24]; default: 0; + * The enable bit for the interrupt triggered by a one-shot mode action on PWM0. + */ +#define MCPWM_FH0_OST_INT_ENA (BIT(24)) +#define MCPWM_FH0_OST_INT_ENA_M (MCPWM_FH0_OST_INT_ENA_V << MCPWM_FH0_OST_INT_ENA_S) +#define MCPWM_FH0_OST_INT_ENA_V 0x00000001U +#define MCPWM_FH0_OST_INT_ENA_S 24 +/** MCPWM_FH1_OST_INT_ENA : R/W; bitpos: [25]; default: 0; + * The enable bit for the interrupt triggered by a one-shot mode action on PWM1. + */ +#define MCPWM_FH1_OST_INT_ENA (BIT(25)) +#define MCPWM_FH1_OST_INT_ENA_M (MCPWM_FH1_OST_INT_ENA_V << MCPWM_FH1_OST_INT_ENA_S) +#define MCPWM_FH1_OST_INT_ENA_V 0x00000001U +#define MCPWM_FH1_OST_INT_ENA_S 25 +/** MCPWM_FH2_OST_INT_ENA : R/W; bitpos: [26]; default: 0; + * The enable bit for the interrupt triggered by a one-shot mode action on PWM2. + */ +#define MCPWM_FH2_OST_INT_ENA (BIT(26)) +#define MCPWM_FH2_OST_INT_ENA_M (MCPWM_FH2_OST_INT_ENA_V << MCPWM_FH2_OST_INT_ENA_S) +#define MCPWM_FH2_OST_INT_ENA_V 0x00000001U +#define MCPWM_FH2_OST_INT_ENA_S 26 +/** MCPWM_CAP0_INT_ENA : R/W; bitpos: [27]; default: 0; + * The enable bit for the interrupt triggered by capture on channel 0. + */ +#define MCPWM_CAP0_INT_ENA (BIT(27)) +#define MCPWM_CAP0_INT_ENA_M (MCPWM_CAP0_INT_ENA_V << MCPWM_CAP0_INT_ENA_S) +#define MCPWM_CAP0_INT_ENA_V 0x00000001U +#define MCPWM_CAP0_INT_ENA_S 27 +/** MCPWM_CAP1_INT_ENA : R/W; bitpos: [28]; default: 0; + * The enable bit for the interrupt triggered by capture on channel 1. + */ +#define MCPWM_CAP1_INT_ENA (BIT(28)) +#define MCPWM_CAP1_INT_ENA_M (MCPWM_CAP1_INT_ENA_V << MCPWM_CAP1_INT_ENA_S) +#define MCPWM_CAP1_INT_ENA_V 0x00000001U +#define MCPWM_CAP1_INT_ENA_S 28 +/** MCPWM_CAP2_INT_ENA : R/W; bitpos: [29]; default: 0; + * The enable bit for the interrupt triggered by capture on channel 2. + */ +#define MCPWM_CAP2_INT_ENA (BIT(29)) +#define MCPWM_CAP2_INT_ENA_M (MCPWM_CAP2_INT_ENA_V << MCPWM_CAP2_INT_ENA_S) +#define MCPWM_CAP2_INT_ENA_V 0x00000001U +#define MCPWM_CAP2_INT_ENA_S 29 -#define MCPWM_INT_RAW_PWM_REG(i) (REG_MCPWM_BASE(i) + 0x114) -/* MCPWM_CAP2_INT_RAW : RO ;bitpos:[29] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP2_INT_RAW (BIT(29)) -#define MCPWM_CAP2_INT_RAW_M (BIT(29)) -#define MCPWM_CAP2_INT_RAW_V 0x1 -#define MCPWM_CAP2_INT_RAW_S 29 -/* MCPWM_CAP1_INT_RAW : RO ;bitpos:[28] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP1_INT_RAW (BIT(28)) -#define MCPWM_CAP1_INT_RAW_M (BIT(28)) -#define MCPWM_CAP1_INT_RAW_V 0x1 -#define MCPWM_CAP1_INT_RAW_S 28 -/* MCPWM_CAP0_INT_RAW : RO ;bitpos:[27] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP0_INT_RAW (BIT(27)) -#define MCPWM_CAP0_INT_RAW_M (BIT(27)) -#define MCPWM_CAP0_INT_RAW_V 0x1 -#define MCPWM_CAP0_INT_RAW_S 27 -/* MCPWM_TZ2_OST_INT_RAW : RO ;bitpos:[26] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ2_OST_INT_RAW (BIT(26)) -#define MCPWM_TZ2_OST_INT_RAW_M (BIT(26)) -#define MCPWM_TZ2_OST_INT_RAW_V 0x1 -#define MCPWM_TZ2_OST_INT_RAW_S 26 -/* MCPWM_TZ1_OST_INT_RAW : RO ;bitpos:[25] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ1_OST_INT_RAW (BIT(25)) -#define MCPWM_TZ1_OST_INT_RAW_M (BIT(25)) -#define MCPWM_TZ1_OST_INT_RAW_V 0x1 -#define MCPWM_TZ1_OST_INT_RAW_S 25 -/* MCPWM_TZ0_OST_INT_RAW : RO ;bitpos:[24] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ0_OST_INT_RAW (BIT(24)) -#define MCPWM_TZ0_OST_INT_RAW_M (BIT(24)) -#define MCPWM_TZ0_OST_INT_RAW_V 0x1 -#define MCPWM_TZ0_OST_INT_RAW_S 24 -/* MCPWM_TZ2_CBC_INT_RAW : RO ;bitpos:[23] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ2_CBC_INT_RAW (BIT(23)) -#define MCPWM_TZ2_CBC_INT_RAW_M (BIT(23)) -#define MCPWM_TZ2_CBC_INT_RAW_V 0x1 -#define MCPWM_TZ2_CBC_INT_RAW_S 23 -/* MCPWM_TZ1_CBC_INT_RAW : RO ;bitpos:[22] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ1_CBC_INT_RAW (BIT(22)) -#define MCPWM_TZ1_CBC_INT_RAW_M (BIT(22)) -#define MCPWM_TZ1_CBC_INT_RAW_V 0x1 -#define MCPWM_TZ1_CBC_INT_RAW_S 22 -/* MCPWM_TZ0_CBC_INT_RAW : RO ;bitpos:[21] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ0_CBC_INT_RAW (BIT(21)) -#define MCPWM_TZ0_CBC_INT_RAW_M (BIT(21)) -#define MCPWM_TZ0_CBC_INT_RAW_V 0x1 -#define MCPWM_TZ0_CBC_INT_RAW_S 21 -/* MCPWM_CMPR2_TEB_INT_RAW : RO ;bitpos:[20] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR2_TEB_INT_RAW (BIT(20)) -#define MCPWM_CMPR2_TEB_INT_RAW_M (BIT(20)) -#define MCPWM_CMPR2_TEB_INT_RAW_V 0x1 -#define MCPWM_CMPR2_TEB_INT_RAW_S 20 -/* MCPWM_CMPR1_TEB_INT_RAW : RO ;bitpos:[19] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR1_TEB_INT_RAW (BIT(19)) -#define MCPWM_CMPR1_TEB_INT_RAW_M (BIT(19)) -#define MCPWM_CMPR1_TEB_INT_RAW_V 0x1 -#define MCPWM_CMPR1_TEB_INT_RAW_S 19 -/* MCPWM_CMPR0_TEB_INT_RAW : RO ;bitpos:[18] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR0_TEB_INT_RAW (BIT(18)) -#define MCPWM_CMPR0_TEB_INT_RAW_M (BIT(18)) -#define MCPWM_CMPR0_TEB_INT_RAW_V 0x1 -#define MCPWM_CMPR0_TEB_INT_RAW_S 18 -/* MCPWM_CMPR2_TEA_INT_RAW : RO ;bitpos:[17] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR2_TEA_INT_RAW (BIT(17)) -#define MCPWM_CMPR2_TEA_INT_RAW_M (BIT(17)) -#define MCPWM_CMPR2_TEA_INT_RAW_V 0x1 -#define MCPWM_CMPR2_TEA_INT_RAW_S 17 -/* MCPWM_CMPR1_TEA_INT_RAW : RO ;bitpos:[16] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR1_TEA_INT_RAW (BIT(16)) -#define MCPWM_CMPR1_TEA_INT_RAW_M (BIT(16)) -#define MCPWM_CMPR1_TEA_INT_RAW_V 0x1 -#define MCPWM_CMPR1_TEA_INT_RAW_S 16 -/* MCPWM_CMPR0_TEA_INT_RAW : RO ;bitpos:[15] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR0_TEA_INT_RAW (BIT(15)) -#define MCPWM_CMPR0_TEA_INT_RAW_M (BIT(15)) -#define MCPWM_CMPR0_TEA_INT_RAW_V 0x1 -#define MCPWM_CMPR0_TEA_INT_RAW_S 15 -/* MCPWM_FAULT2_CLR_INT_RAW : RO ;bitpos:[14] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT2_CLR_INT_RAW (BIT(14)) -#define MCPWM_FAULT2_CLR_INT_RAW_M (BIT(14)) -#define MCPWM_FAULT2_CLR_INT_RAW_V 0x1 -#define MCPWM_FAULT2_CLR_INT_RAW_S 14 -/* MCPWM_FAULT1_CLR_INT_RAW : RO ;bitpos:[13] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT1_CLR_INT_RAW (BIT(13)) -#define MCPWM_FAULT1_CLR_INT_RAW_M (BIT(13)) -#define MCPWM_FAULT1_CLR_INT_RAW_V 0x1 -#define MCPWM_FAULT1_CLR_INT_RAW_S 13 -/* MCPWM_FAULT0_CLR_INT_RAW : RO ;bitpos:[12] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT0_CLR_INT_RAW (BIT(12)) -#define MCPWM_FAULT0_CLR_INT_RAW_M (BIT(12)) -#define MCPWM_FAULT0_CLR_INT_RAW_V 0x1 -#define MCPWM_FAULT0_CLR_INT_RAW_S 12 -/* MCPWM_FAULT2_INT_RAW : RO ;bitpos:[11] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT2_INT_RAW (BIT(11)) -#define MCPWM_FAULT2_INT_RAW_M (BIT(11)) -#define MCPWM_FAULT2_INT_RAW_V 0x1 -#define MCPWM_FAULT2_INT_RAW_S 11 -/* MCPWM_FAULT1_INT_RAW : RO ;bitpos:[10] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT1_INT_RAW (BIT(10)) -#define MCPWM_FAULT1_INT_RAW_M (BIT(10)) -#define MCPWM_FAULT1_INT_RAW_V 0x1 -#define MCPWM_FAULT1_INT_RAW_S 10 -/* MCPWM_FAULT0_INT_RAW : RO ;bitpos:[9] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT0_INT_RAW (BIT(9)) -#define MCPWM_FAULT0_INT_RAW_M (BIT(9)) -#define MCPWM_FAULT0_INT_RAW_V 0x1 -#define MCPWM_FAULT0_INT_RAW_S 9 -/* MCPWM_TIMER2_TEP_INT_RAW : RO ;bitpos:[8] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_TEP_INT_RAW (BIT(8)) -#define MCPWM_TIMER2_TEP_INT_RAW_M (BIT(8)) -#define MCPWM_TIMER2_TEP_INT_RAW_V 0x1 -#define MCPWM_TIMER2_TEP_INT_RAW_S 8 -/* MCPWM_TIMER1_TEP_INT_RAW : RO ;bitpos:[7] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_TEP_INT_RAW (BIT(7)) -#define MCPWM_TIMER1_TEP_INT_RAW_M (BIT(7)) -#define MCPWM_TIMER1_TEP_INT_RAW_V 0x1 -#define MCPWM_TIMER1_TEP_INT_RAW_S 7 -/* MCPWM_TIMER0_TEP_INT_RAW : RO ;bitpos:[6] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER0_TEP_INT_RAW (BIT(6)) -#define MCPWM_TIMER0_TEP_INT_RAW_M (BIT(6)) -#define MCPWM_TIMER0_TEP_INT_RAW_V 0x1 -#define MCPWM_TIMER0_TEP_INT_RAW_S 6 -/* MCPWM_TIMER2_TEZ_INT_RAW : RO ;bitpos:[5] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_TEZ_INT_RAW (BIT(5)) -#define MCPWM_TIMER2_TEZ_INT_RAW_M (BIT(5)) -#define MCPWM_TIMER2_TEZ_INT_RAW_V 0x1 -#define MCPWM_TIMER2_TEZ_INT_RAW_S 5 -/* MCPWM_TIMER1_TEZ_INT_RAW : RO ;bitpos:[4] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_TEZ_INT_RAW (BIT(4)) -#define MCPWM_TIMER1_TEZ_INT_RAW_M (BIT(4)) -#define MCPWM_TIMER1_TEZ_INT_RAW_V 0x1 -#define MCPWM_TIMER1_TEZ_INT_RAW_S 4 -/* MCPWM_TIMER0_TEZ_INT_RAW : RO ;bitpos:[3] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER0_TEZ_INT_RAW (BIT(3)) -#define MCPWM_TIMER0_TEZ_INT_RAW_M (BIT(3)) -#define MCPWM_TIMER0_TEZ_INT_RAW_V 0x1 -#define MCPWM_TIMER0_TEZ_INT_RAW_S 3 -/* MCPWM_TIMER2_STOP_INT_RAW : RO ;bitpos:[2] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_STOP_INT_RAW (BIT(2)) -#define MCPWM_TIMER2_STOP_INT_RAW_M (BIT(2)) -#define MCPWM_TIMER2_STOP_INT_RAW_V 0x1 -#define MCPWM_TIMER2_STOP_INT_RAW_S 2 -/* MCPWM_TIMER1_STOP_INT_RAW : RO ;bitpos:[1] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_STOP_INT_RAW (BIT(1)) -#define MCPWM_TIMER1_STOP_INT_RAW_M (BIT(1)) -#define MCPWM_TIMER1_STOP_INT_RAW_V 0x1 -#define MCPWM_TIMER1_STOP_INT_RAW_S 1 -/* MCPWM_TIMER0_STOP_INT_RAW : RO ;bitpos:[0] ;default: 1'h0 ; */ -/*description: .*/ +/** MCPWM_INT_RAW_REG register + * Raw interrupt status + */ +#define MCPWM_INT_RAW_REG(i) (DR_REG_MCPWM_BASE(i) + 0x114) +/** MCPWM_TIMER0_STOP_INT_RAW : R/WTC/SS; bitpos: [0]; default: 0; + * The raw status bit for the interrupt triggered when the timer 0 stops. + */ #define MCPWM_TIMER0_STOP_INT_RAW (BIT(0)) -#define MCPWM_TIMER0_STOP_INT_RAW_M (BIT(0)) -#define MCPWM_TIMER0_STOP_INT_RAW_V 0x1 +#define MCPWM_TIMER0_STOP_INT_RAW_M (MCPWM_TIMER0_STOP_INT_RAW_V << MCPWM_TIMER0_STOP_INT_RAW_S) +#define MCPWM_TIMER0_STOP_INT_RAW_V 0x00000001U #define MCPWM_TIMER0_STOP_INT_RAW_S 0 +/** MCPWM_TIMER1_STOP_INT_RAW : R/WTC/SS; bitpos: [1]; default: 0; + * The raw status bit for the interrupt triggered when the timer 1 stops. + */ +#define MCPWM_TIMER1_STOP_INT_RAW (BIT(1)) +#define MCPWM_TIMER1_STOP_INT_RAW_M (MCPWM_TIMER1_STOP_INT_RAW_V << MCPWM_TIMER1_STOP_INT_RAW_S) +#define MCPWM_TIMER1_STOP_INT_RAW_V 0x00000001U +#define MCPWM_TIMER1_STOP_INT_RAW_S 1 +/** MCPWM_TIMER2_STOP_INT_RAW : R/WTC/SS; bitpos: [2]; default: 0; + * The raw status bit for the interrupt triggered when the timer 2 stops. + */ +#define MCPWM_TIMER2_STOP_INT_RAW (BIT(2)) +#define MCPWM_TIMER2_STOP_INT_RAW_M (MCPWM_TIMER2_STOP_INT_RAW_V << MCPWM_TIMER2_STOP_INT_RAW_S) +#define MCPWM_TIMER2_STOP_INT_RAW_V 0x00000001U +#define MCPWM_TIMER2_STOP_INT_RAW_S 2 +/** MCPWM_TIMER0_TEZ_INT_RAW : R/WTC/SS; bitpos: [3]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 0 TEZ event. + */ +#define MCPWM_TIMER0_TEZ_INT_RAW (BIT(3)) +#define MCPWM_TIMER0_TEZ_INT_RAW_M (MCPWM_TIMER0_TEZ_INT_RAW_V << MCPWM_TIMER0_TEZ_INT_RAW_S) +#define MCPWM_TIMER0_TEZ_INT_RAW_V 0x00000001U +#define MCPWM_TIMER0_TEZ_INT_RAW_S 3 +/** MCPWM_TIMER1_TEZ_INT_RAW : R/WTC/SS; bitpos: [4]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 1 TEZ event. + */ +#define MCPWM_TIMER1_TEZ_INT_RAW (BIT(4)) +#define MCPWM_TIMER1_TEZ_INT_RAW_M (MCPWM_TIMER1_TEZ_INT_RAW_V << MCPWM_TIMER1_TEZ_INT_RAW_S) +#define MCPWM_TIMER1_TEZ_INT_RAW_V 0x00000001U +#define MCPWM_TIMER1_TEZ_INT_RAW_S 4 +/** MCPWM_TIMER2_TEZ_INT_RAW : R/WTC/SS; bitpos: [5]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 2 TEZ event. + */ +#define MCPWM_TIMER2_TEZ_INT_RAW (BIT(5)) +#define MCPWM_TIMER2_TEZ_INT_RAW_M (MCPWM_TIMER2_TEZ_INT_RAW_V << MCPWM_TIMER2_TEZ_INT_RAW_S) +#define MCPWM_TIMER2_TEZ_INT_RAW_V 0x00000001U +#define MCPWM_TIMER2_TEZ_INT_RAW_S 5 +/** MCPWM_TIMER0_TEP_INT_RAW : R/WTC/SS; bitpos: [6]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 0 TEP event. + */ +#define MCPWM_TIMER0_TEP_INT_RAW (BIT(6)) +#define MCPWM_TIMER0_TEP_INT_RAW_M (MCPWM_TIMER0_TEP_INT_RAW_V << MCPWM_TIMER0_TEP_INT_RAW_S) +#define MCPWM_TIMER0_TEP_INT_RAW_V 0x00000001U +#define MCPWM_TIMER0_TEP_INT_RAW_S 6 +/** MCPWM_TIMER1_TEP_INT_RAW : R/WTC/SS; bitpos: [7]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 1 TEP event. + */ +#define MCPWM_TIMER1_TEP_INT_RAW (BIT(7)) +#define MCPWM_TIMER1_TEP_INT_RAW_M (MCPWM_TIMER1_TEP_INT_RAW_V << MCPWM_TIMER1_TEP_INT_RAW_S) +#define MCPWM_TIMER1_TEP_INT_RAW_V 0x00000001U +#define MCPWM_TIMER1_TEP_INT_RAW_S 7 +/** MCPWM_TIMER2_TEP_INT_RAW : R/WTC/SS; bitpos: [8]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 2 TEP event. + */ +#define MCPWM_TIMER2_TEP_INT_RAW (BIT(8)) +#define MCPWM_TIMER2_TEP_INT_RAW_M (MCPWM_TIMER2_TEP_INT_RAW_V << MCPWM_TIMER2_TEP_INT_RAW_S) +#define MCPWM_TIMER2_TEP_INT_RAW_V 0x00000001U +#define MCPWM_TIMER2_TEP_INT_RAW_S 8 +/** MCPWM_FAULT0_INT_RAW : R/WTC/SS; bitpos: [9]; default: 0; + * The raw status bit for the interrupt triggered when fault_event0 starts. + */ +#define MCPWM_FAULT0_INT_RAW (BIT(9)) +#define MCPWM_FAULT0_INT_RAW_M (MCPWM_FAULT0_INT_RAW_V << MCPWM_FAULT0_INT_RAW_S) +#define MCPWM_FAULT0_INT_RAW_V 0x00000001U +#define MCPWM_FAULT0_INT_RAW_S 9 +/** MCPWM_FAULT1_INT_RAW : R/WTC/SS; bitpos: [10]; default: 0; + * The raw status bit for the interrupt triggered when fault_event1 starts. + */ +#define MCPWM_FAULT1_INT_RAW (BIT(10)) +#define MCPWM_FAULT1_INT_RAW_M (MCPWM_FAULT1_INT_RAW_V << MCPWM_FAULT1_INT_RAW_S) +#define MCPWM_FAULT1_INT_RAW_V 0x00000001U +#define MCPWM_FAULT1_INT_RAW_S 10 +/** MCPWM_FAULT2_INT_RAW : R/WTC/SS; bitpos: [11]; default: 0; + * The raw status bit for the interrupt triggered when fault_event2 starts. + */ +#define MCPWM_FAULT2_INT_RAW (BIT(11)) +#define MCPWM_FAULT2_INT_RAW_M (MCPWM_FAULT2_INT_RAW_V << MCPWM_FAULT2_INT_RAW_S) +#define MCPWM_FAULT2_INT_RAW_V 0x00000001U +#define MCPWM_FAULT2_INT_RAW_S 11 +/** MCPWM_FAULT0_CLR_INT_RAW : R/WTC/SS; bitpos: [12]; default: 0; + * The raw status bit for the interrupt triggered when fault_event0 ends. + */ +#define MCPWM_FAULT0_CLR_INT_RAW (BIT(12)) +#define MCPWM_FAULT0_CLR_INT_RAW_M (MCPWM_FAULT0_CLR_INT_RAW_V << MCPWM_FAULT0_CLR_INT_RAW_S) +#define MCPWM_FAULT0_CLR_INT_RAW_V 0x00000001U +#define MCPWM_FAULT0_CLR_INT_RAW_S 12 +/** MCPWM_FAULT1_CLR_INT_RAW : R/WTC/SS; bitpos: [13]; default: 0; + * The raw status bit for the interrupt triggered when fault_event1 ends. + */ +#define MCPWM_FAULT1_CLR_INT_RAW (BIT(13)) +#define MCPWM_FAULT1_CLR_INT_RAW_M (MCPWM_FAULT1_CLR_INT_RAW_V << MCPWM_FAULT1_CLR_INT_RAW_S) +#define MCPWM_FAULT1_CLR_INT_RAW_V 0x00000001U +#define MCPWM_FAULT1_CLR_INT_RAW_S 13 +/** MCPWM_FAULT2_CLR_INT_RAW : R/WTC/SS; bitpos: [14]; default: 0; + * The raw status bit for the interrupt triggered when fault_event2 ends. + */ +#define MCPWM_FAULT2_CLR_INT_RAW (BIT(14)) +#define MCPWM_FAULT2_CLR_INT_RAW_M (MCPWM_FAULT2_CLR_INT_RAW_V << MCPWM_FAULT2_CLR_INT_RAW_S) +#define MCPWM_FAULT2_CLR_INT_RAW_V 0x00000001U +#define MCPWM_FAULT2_CLR_INT_RAW_S 14 +/** MCPWM_OP0_TEA_INT_RAW : R/WTC/SS; bitpos: [15]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 0 TEA event + */ +#define MCPWM_OP0_TEA_INT_RAW (BIT(15)) +#define MCPWM_OP0_TEA_INT_RAW_M (MCPWM_OP0_TEA_INT_RAW_V << MCPWM_OP0_TEA_INT_RAW_S) +#define MCPWM_OP0_TEA_INT_RAW_V 0x00000001U +#define MCPWM_OP0_TEA_INT_RAW_S 15 +/** MCPWM_OP1_TEA_INT_RAW : R/WTC/SS; bitpos: [16]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 1 TEA event + */ +#define MCPWM_OP1_TEA_INT_RAW (BIT(16)) +#define MCPWM_OP1_TEA_INT_RAW_M (MCPWM_OP1_TEA_INT_RAW_V << MCPWM_OP1_TEA_INT_RAW_S) +#define MCPWM_OP1_TEA_INT_RAW_V 0x00000001U +#define MCPWM_OP1_TEA_INT_RAW_S 16 +/** MCPWM_OP2_TEA_INT_RAW : R/WTC/SS; bitpos: [17]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 2 TEA event + */ +#define MCPWM_OP2_TEA_INT_RAW (BIT(17)) +#define MCPWM_OP2_TEA_INT_RAW_M (MCPWM_OP2_TEA_INT_RAW_V << MCPWM_OP2_TEA_INT_RAW_S) +#define MCPWM_OP2_TEA_INT_RAW_V 0x00000001U +#define MCPWM_OP2_TEA_INT_RAW_S 17 +/** MCPWM_OP0_TEB_INT_RAW : R/WTC/SS; bitpos: [18]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 0 TEB event + */ +#define MCPWM_OP0_TEB_INT_RAW (BIT(18)) +#define MCPWM_OP0_TEB_INT_RAW_M (MCPWM_OP0_TEB_INT_RAW_V << MCPWM_OP0_TEB_INT_RAW_S) +#define MCPWM_OP0_TEB_INT_RAW_V 0x00000001U +#define MCPWM_OP0_TEB_INT_RAW_S 18 +/** MCPWM_OP1_TEB_INT_RAW : R/WTC/SS; bitpos: [19]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 1 TEB event + */ +#define MCPWM_OP1_TEB_INT_RAW (BIT(19)) +#define MCPWM_OP1_TEB_INT_RAW_M (MCPWM_OP1_TEB_INT_RAW_V << MCPWM_OP1_TEB_INT_RAW_S) +#define MCPWM_OP1_TEB_INT_RAW_V 0x00000001U +#define MCPWM_OP1_TEB_INT_RAW_S 19 +/** MCPWM_OP2_TEB_INT_RAW : R/WTC/SS; bitpos: [20]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 2 TEB event + */ +#define MCPWM_OP2_TEB_INT_RAW (BIT(20)) +#define MCPWM_OP2_TEB_INT_RAW_M (MCPWM_OP2_TEB_INT_RAW_V << MCPWM_OP2_TEB_INT_RAW_S) +#define MCPWM_OP2_TEB_INT_RAW_V 0x00000001U +#define MCPWM_OP2_TEB_INT_RAW_S 20 +/** MCPWM_FH0_CBC_INT_RAW : R/WTC/SS; bitpos: [21]; default: 0; + * The raw status bit for the interrupt triggered by a cycle-by-cycle mode action on + * PWM0. + */ +#define MCPWM_FH0_CBC_INT_RAW (BIT(21)) +#define MCPWM_FH0_CBC_INT_RAW_M (MCPWM_FH0_CBC_INT_RAW_V << MCPWM_FH0_CBC_INT_RAW_S) +#define MCPWM_FH0_CBC_INT_RAW_V 0x00000001U +#define MCPWM_FH0_CBC_INT_RAW_S 21 +/** MCPWM_FH1_CBC_INT_RAW : R/WTC/SS; bitpos: [22]; default: 0; + * The raw status bit for the interrupt triggered by a cycle-by-cycle mode action on + * PWM1. + */ +#define MCPWM_FH1_CBC_INT_RAW (BIT(22)) +#define MCPWM_FH1_CBC_INT_RAW_M (MCPWM_FH1_CBC_INT_RAW_V << MCPWM_FH1_CBC_INT_RAW_S) +#define MCPWM_FH1_CBC_INT_RAW_V 0x00000001U +#define MCPWM_FH1_CBC_INT_RAW_S 22 +/** MCPWM_FH2_CBC_INT_RAW : R/WTC/SS; bitpos: [23]; default: 0; + * The raw status bit for the interrupt triggered by a cycle-by-cycle mode action on + * PWM2. + */ +#define MCPWM_FH2_CBC_INT_RAW (BIT(23)) +#define MCPWM_FH2_CBC_INT_RAW_M (MCPWM_FH2_CBC_INT_RAW_V << MCPWM_FH2_CBC_INT_RAW_S) +#define MCPWM_FH2_CBC_INT_RAW_V 0x00000001U +#define MCPWM_FH2_CBC_INT_RAW_S 23 +/** MCPWM_FH0_OST_INT_RAW : R/WTC/SS; bitpos: [24]; default: 0; + * The raw status bit for the interrupt triggered by a one-shot mode action on PWM0. + */ +#define MCPWM_FH0_OST_INT_RAW (BIT(24)) +#define MCPWM_FH0_OST_INT_RAW_M (MCPWM_FH0_OST_INT_RAW_V << MCPWM_FH0_OST_INT_RAW_S) +#define MCPWM_FH0_OST_INT_RAW_V 0x00000001U +#define MCPWM_FH0_OST_INT_RAW_S 24 +/** MCPWM_FH1_OST_INT_RAW : R/WTC/SS; bitpos: [25]; default: 0; + * The raw status bit for the interrupt triggered by a one-shot mode action on PWM1. + */ +#define MCPWM_FH1_OST_INT_RAW (BIT(25)) +#define MCPWM_FH1_OST_INT_RAW_M (MCPWM_FH1_OST_INT_RAW_V << MCPWM_FH1_OST_INT_RAW_S) +#define MCPWM_FH1_OST_INT_RAW_V 0x00000001U +#define MCPWM_FH1_OST_INT_RAW_S 25 +/** MCPWM_FH2_OST_INT_RAW : R/WTC/SS; bitpos: [26]; default: 0; + * The raw status bit for the interrupt triggered by a one-shot mode action on PWM2. + */ +#define MCPWM_FH2_OST_INT_RAW (BIT(26)) +#define MCPWM_FH2_OST_INT_RAW_M (MCPWM_FH2_OST_INT_RAW_V << MCPWM_FH2_OST_INT_RAW_S) +#define MCPWM_FH2_OST_INT_RAW_V 0x00000001U +#define MCPWM_FH2_OST_INT_RAW_S 26 +/** MCPWM_CAP0_INT_RAW : R/WTC/SS; bitpos: [27]; default: 0; + * The raw status bit for the interrupt triggered by capture on channel 0. + */ +#define MCPWM_CAP0_INT_RAW (BIT(27)) +#define MCPWM_CAP0_INT_RAW_M (MCPWM_CAP0_INT_RAW_V << MCPWM_CAP0_INT_RAW_S) +#define MCPWM_CAP0_INT_RAW_V 0x00000001U +#define MCPWM_CAP0_INT_RAW_S 27 +/** MCPWM_CAP1_INT_RAW : R/WTC/SS; bitpos: [28]; default: 0; + * The raw status bit for the interrupt triggered by capture on channel 1. + */ +#define MCPWM_CAP1_INT_RAW (BIT(28)) +#define MCPWM_CAP1_INT_RAW_M (MCPWM_CAP1_INT_RAW_V << MCPWM_CAP1_INT_RAW_S) +#define MCPWM_CAP1_INT_RAW_V 0x00000001U +#define MCPWM_CAP1_INT_RAW_S 28 +/** MCPWM_CAP2_INT_RAW : R/WTC/SS; bitpos: [29]; default: 0; + * The raw status bit for the interrupt triggered by capture on channel 2. + */ +#define MCPWM_CAP2_INT_RAW (BIT(29)) +#define MCPWM_CAP2_INT_RAW_M (MCPWM_CAP2_INT_RAW_V << MCPWM_CAP2_INT_RAW_S) +#define MCPWM_CAP2_INT_RAW_V 0x00000001U +#define MCPWM_CAP2_INT_RAW_S 29 -#define MCPWM_INT_ST_PWM_REG(i) (REG_MCPWM_BASE(i) + 0x118) -/* MCPWM_CAP2_INT_ST : RO ;bitpos:[29] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP2_INT_ST (BIT(29)) -#define MCPWM_CAP2_INT_ST_M (BIT(29)) -#define MCPWM_CAP2_INT_ST_V 0x1 -#define MCPWM_CAP2_INT_ST_S 29 -/* MCPWM_CAP1_INT_ST : RO ;bitpos:[28] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP1_INT_ST (BIT(28)) -#define MCPWM_CAP1_INT_ST_M (BIT(28)) -#define MCPWM_CAP1_INT_ST_V 0x1 -#define MCPWM_CAP1_INT_ST_S 28 -/* MCPWM_CAP0_INT_ST : RO ;bitpos:[27] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP0_INT_ST (BIT(27)) -#define MCPWM_CAP0_INT_ST_M (BIT(27)) -#define MCPWM_CAP0_INT_ST_V 0x1 -#define MCPWM_CAP0_INT_ST_S 27 -/* MCPWM_TZ2_OST_INT_ST : RO ;bitpos:[26] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ2_OST_INT_ST (BIT(26)) -#define MCPWM_TZ2_OST_INT_ST_M (BIT(26)) -#define MCPWM_TZ2_OST_INT_ST_V 0x1 -#define MCPWM_TZ2_OST_INT_ST_S 26 -/* MCPWM_TZ1_OST_INT_ST : RO ;bitpos:[25] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ1_OST_INT_ST (BIT(25)) -#define MCPWM_TZ1_OST_INT_ST_M (BIT(25)) -#define MCPWM_TZ1_OST_INT_ST_V 0x1 -#define MCPWM_TZ1_OST_INT_ST_S 25 -/* MCPWM_TZ0_OST_INT_ST : RO ;bitpos:[24] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ0_OST_INT_ST (BIT(24)) -#define MCPWM_TZ0_OST_INT_ST_M (BIT(24)) -#define MCPWM_TZ0_OST_INT_ST_V 0x1 -#define MCPWM_TZ0_OST_INT_ST_S 24 -/* MCPWM_TZ2_CBC_INT_ST : RO ;bitpos:[23] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ2_CBC_INT_ST (BIT(23)) -#define MCPWM_TZ2_CBC_INT_ST_M (BIT(23)) -#define MCPWM_TZ2_CBC_INT_ST_V 0x1 -#define MCPWM_TZ2_CBC_INT_ST_S 23 -/* MCPWM_TZ1_CBC_INT_ST : RO ;bitpos:[22] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ1_CBC_INT_ST (BIT(22)) -#define MCPWM_TZ1_CBC_INT_ST_M (BIT(22)) -#define MCPWM_TZ1_CBC_INT_ST_V 0x1 -#define MCPWM_TZ1_CBC_INT_ST_S 22 -/* MCPWM_TZ0_CBC_INT_ST : RO ;bitpos:[21] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ0_CBC_INT_ST (BIT(21)) -#define MCPWM_TZ0_CBC_INT_ST_M (BIT(21)) -#define MCPWM_TZ0_CBC_INT_ST_V 0x1 -#define MCPWM_TZ0_CBC_INT_ST_S 21 -/* MCPWM_CMPR2_TEB_INT_ST : RO ;bitpos:[20] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR2_TEB_INT_ST (BIT(20)) -#define MCPWM_CMPR2_TEB_INT_ST_M (BIT(20)) -#define MCPWM_CMPR2_TEB_INT_ST_V 0x1 -#define MCPWM_CMPR2_TEB_INT_ST_S 20 -/* MCPWM_CMPR1_TEB_INT_ST : RO ;bitpos:[19] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR1_TEB_INT_ST (BIT(19)) -#define MCPWM_CMPR1_TEB_INT_ST_M (BIT(19)) -#define MCPWM_CMPR1_TEB_INT_ST_V 0x1 -#define MCPWM_CMPR1_TEB_INT_ST_S 19 -/* MCPWM_CMPR0_TEB_INT_ST : RO ;bitpos:[18] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR0_TEB_INT_ST (BIT(18)) -#define MCPWM_CMPR0_TEB_INT_ST_M (BIT(18)) -#define MCPWM_CMPR0_TEB_INT_ST_V 0x1 -#define MCPWM_CMPR0_TEB_INT_ST_S 18 -/* MCPWM_CMPR2_TEA_INT_ST : RO ;bitpos:[17] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR2_TEA_INT_ST (BIT(17)) -#define MCPWM_CMPR2_TEA_INT_ST_M (BIT(17)) -#define MCPWM_CMPR2_TEA_INT_ST_V 0x1 -#define MCPWM_CMPR2_TEA_INT_ST_S 17 -/* MCPWM_CMPR1_TEA_INT_ST : RO ;bitpos:[16] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR1_TEA_INT_ST (BIT(16)) -#define MCPWM_CMPR1_TEA_INT_ST_M (BIT(16)) -#define MCPWM_CMPR1_TEA_INT_ST_V 0x1 -#define MCPWM_CMPR1_TEA_INT_ST_S 16 -/* MCPWM_CMPR0_TEA_INT_ST : RO ;bitpos:[15] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR0_TEA_INT_ST (BIT(15)) -#define MCPWM_CMPR0_TEA_INT_ST_M (BIT(15)) -#define MCPWM_CMPR0_TEA_INT_ST_V 0x1 -#define MCPWM_CMPR0_TEA_INT_ST_S 15 -/* MCPWM_FAULT2_CLR_INT_ST : RO ;bitpos:[14] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT2_CLR_INT_ST (BIT(14)) -#define MCPWM_FAULT2_CLR_INT_ST_M (BIT(14)) -#define MCPWM_FAULT2_CLR_INT_ST_V 0x1 -#define MCPWM_FAULT2_CLR_INT_ST_S 14 -/* MCPWM_FAULT1_CLR_INT_ST : RO ;bitpos:[13] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT1_CLR_INT_ST (BIT(13)) -#define MCPWM_FAULT1_CLR_INT_ST_M (BIT(13)) -#define MCPWM_FAULT1_CLR_INT_ST_V 0x1 -#define MCPWM_FAULT1_CLR_INT_ST_S 13 -/* MCPWM_FAULT0_CLR_INT_ST : RO ;bitpos:[12] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT0_CLR_INT_ST (BIT(12)) -#define MCPWM_FAULT0_CLR_INT_ST_M (BIT(12)) -#define MCPWM_FAULT0_CLR_INT_ST_V 0x1 -#define MCPWM_FAULT0_CLR_INT_ST_S 12 -/* MCPWM_FAULT2_INT_ST : RO ;bitpos:[11] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT2_INT_ST (BIT(11)) -#define MCPWM_FAULT2_INT_ST_M (BIT(11)) -#define MCPWM_FAULT2_INT_ST_V 0x1 -#define MCPWM_FAULT2_INT_ST_S 11 -/* MCPWM_FAULT1_INT_ST : RO ;bitpos:[10] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT1_INT_ST (BIT(10)) -#define MCPWM_FAULT1_INT_ST_M (BIT(10)) -#define MCPWM_FAULT1_INT_ST_V 0x1 -#define MCPWM_FAULT1_INT_ST_S 10 -/* MCPWM_FAULT0_INT_ST : RO ;bitpos:[9] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT0_INT_ST (BIT(9)) -#define MCPWM_FAULT0_INT_ST_M (BIT(9)) -#define MCPWM_FAULT0_INT_ST_V 0x1 -#define MCPWM_FAULT0_INT_ST_S 9 -/* MCPWM_TIMER2_TEP_INT_ST : RO ;bitpos:[8] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_TEP_INT_ST (BIT(8)) -#define MCPWM_TIMER2_TEP_INT_ST_M (BIT(8)) -#define MCPWM_TIMER2_TEP_INT_ST_V 0x1 -#define MCPWM_TIMER2_TEP_INT_ST_S 8 -/* MCPWM_TIMER1_TEP_INT_ST : RO ;bitpos:[7] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_TEP_INT_ST (BIT(7)) -#define MCPWM_TIMER1_TEP_INT_ST_M (BIT(7)) -#define MCPWM_TIMER1_TEP_INT_ST_V 0x1 -#define MCPWM_TIMER1_TEP_INT_ST_S 7 -/* MCPWM_TIMER0_TEP_INT_ST : RO ;bitpos:[6] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER0_TEP_INT_ST (BIT(6)) -#define MCPWM_TIMER0_TEP_INT_ST_M (BIT(6)) -#define MCPWM_TIMER0_TEP_INT_ST_V 0x1 -#define MCPWM_TIMER0_TEP_INT_ST_S 6 -/* MCPWM_TIMER2_TEZ_INT_ST : RO ;bitpos:[5] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_TEZ_INT_ST (BIT(5)) -#define MCPWM_TIMER2_TEZ_INT_ST_M (BIT(5)) -#define MCPWM_TIMER2_TEZ_INT_ST_V 0x1 -#define MCPWM_TIMER2_TEZ_INT_ST_S 5 -/* MCPWM_TIMER1_TEZ_INT_ST : RO ;bitpos:[4] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_TEZ_INT_ST (BIT(4)) -#define MCPWM_TIMER1_TEZ_INT_ST_M (BIT(4)) -#define MCPWM_TIMER1_TEZ_INT_ST_V 0x1 -#define MCPWM_TIMER1_TEZ_INT_ST_S 4 -/* MCPWM_TIMER0_TEZ_INT_ST : RO ;bitpos:[3] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER0_TEZ_INT_ST (BIT(3)) -#define MCPWM_TIMER0_TEZ_INT_ST_M (BIT(3)) -#define MCPWM_TIMER0_TEZ_INT_ST_V 0x1 -#define MCPWM_TIMER0_TEZ_INT_ST_S 3 -/* MCPWM_TIMER2_STOP_INT_ST : RO ;bitpos:[2] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_STOP_INT_ST (BIT(2)) -#define MCPWM_TIMER2_STOP_INT_ST_M (BIT(2)) -#define MCPWM_TIMER2_STOP_INT_ST_V 0x1 -#define MCPWM_TIMER2_STOP_INT_ST_S 2 -/* MCPWM_TIMER1_STOP_INT_ST : RO ;bitpos:[1] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_STOP_INT_ST (BIT(1)) -#define MCPWM_TIMER1_STOP_INT_ST_M (BIT(1)) -#define MCPWM_TIMER1_STOP_INT_ST_V 0x1 -#define MCPWM_TIMER1_STOP_INT_ST_S 1 -/* MCPWM_TIMER0_STOP_INT_ST : RO ;bitpos:[0] ;default: 1'h0 ; */ -/*description: .*/ +/** MCPWM_INT_ST_REG register + * Masked interrupt status + */ +#define MCPWM_INT_ST_REG(i) (DR_REG_MCPWM_BASE(i) + 0x118) +/** MCPWM_TIMER0_STOP_INT_ST : RO; bitpos: [0]; default: 0; + * The masked status bit for the interrupt triggered when the timer 0 stops. + */ #define MCPWM_TIMER0_STOP_INT_ST (BIT(0)) -#define MCPWM_TIMER0_STOP_INT_ST_M (BIT(0)) -#define MCPWM_TIMER0_STOP_INT_ST_V 0x1 +#define MCPWM_TIMER0_STOP_INT_ST_M (MCPWM_TIMER0_STOP_INT_ST_V << MCPWM_TIMER0_STOP_INT_ST_S) +#define MCPWM_TIMER0_STOP_INT_ST_V 0x00000001U #define MCPWM_TIMER0_STOP_INT_ST_S 0 +/** MCPWM_TIMER1_STOP_INT_ST : RO; bitpos: [1]; default: 0; + * The masked status bit for the interrupt triggered when the timer 1 stops. + */ +#define MCPWM_TIMER1_STOP_INT_ST (BIT(1)) +#define MCPWM_TIMER1_STOP_INT_ST_M (MCPWM_TIMER1_STOP_INT_ST_V << MCPWM_TIMER1_STOP_INT_ST_S) +#define MCPWM_TIMER1_STOP_INT_ST_V 0x00000001U +#define MCPWM_TIMER1_STOP_INT_ST_S 1 +/** MCPWM_TIMER2_STOP_INT_ST : RO; bitpos: [2]; default: 0; + * The masked status bit for the interrupt triggered when the timer 2 stops. + */ +#define MCPWM_TIMER2_STOP_INT_ST (BIT(2)) +#define MCPWM_TIMER2_STOP_INT_ST_M (MCPWM_TIMER2_STOP_INT_ST_V << MCPWM_TIMER2_STOP_INT_ST_S) +#define MCPWM_TIMER2_STOP_INT_ST_V 0x00000001U +#define MCPWM_TIMER2_STOP_INT_ST_S 2 +/** MCPWM_TIMER0_TEZ_INT_ST : RO; bitpos: [3]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 0 TEZ event. + */ +#define MCPWM_TIMER0_TEZ_INT_ST (BIT(3)) +#define MCPWM_TIMER0_TEZ_INT_ST_M (MCPWM_TIMER0_TEZ_INT_ST_V << MCPWM_TIMER0_TEZ_INT_ST_S) +#define MCPWM_TIMER0_TEZ_INT_ST_V 0x00000001U +#define MCPWM_TIMER0_TEZ_INT_ST_S 3 +/** MCPWM_TIMER1_TEZ_INT_ST : RO; bitpos: [4]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 1 TEZ event. + */ +#define MCPWM_TIMER1_TEZ_INT_ST (BIT(4)) +#define MCPWM_TIMER1_TEZ_INT_ST_M (MCPWM_TIMER1_TEZ_INT_ST_V << MCPWM_TIMER1_TEZ_INT_ST_S) +#define MCPWM_TIMER1_TEZ_INT_ST_V 0x00000001U +#define MCPWM_TIMER1_TEZ_INT_ST_S 4 +/** MCPWM_TIMER2_TEZ_INT_ST : RO; bitpos: [5]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 2 TEZ event. + */ +#define MCPWM_TIMER2_TEZ_INT_ST (BIT(5)) +#define MCPWM_TIMER2_TEZ_INT_ST_M (MCPWM_TIMER2_TEZ_INT_ST_V << MCPWM_TIMER2_TEZ_INT_ST_S) +#define MCPWM_TIMER2_TEZ_INT_ST_V 0x00000001U +#define MCPWM_TIMER2_TEZ_INT_ST_S 5 +/** MCPWM_TIMER0_TEP_INT_ST : RO; bitpos: [6]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 0 TEP event. + */ +#define MCPWM_TIMER0_TEP_INT_ST (BIT(6)) +#define MCPWM_TIMER0_TEP_INT_ST_M (MCPWM_TIMER0_TEP_INT_ST_V << MCPWM_TIMER0_TEP_INT_ST_S) +#define MCPWM_TIMER0_TEP_INT_ST_V 0x00000001U +#define MCPWM_TIMER0_TEP_INT_ST_S 6 +/** MCPWM_TIMER1_TEP_INT_ST : RO; bitpos: [7]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 1 TEP event. + */ +#define MCPWM_TIMER1_TEP_INT_ST (BIT(7)) +#define MCPWM_TIMER1_TEP_INT_ST_M (MCPWM_TIMER1_TEP_INT_ST_V << MCPWM_TIMER1_TEP_INT_ST_S) +#define MCPWM_TIMER1_TEP_INT_ST_V 0x00000001U +#define MCPWM_TIMER1_TEP_INT_ST_S 7 +/** MCPWM_TIMER2_TEP_INT_ST : RO; bitpos: [8]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 2 TEP event. + */ +#define MCPWM_TIMER2_TEP_INT_ST (BIT(8)) +#define MCPWM_TIMER2_TEP_INT_ST_M (MCPWM_TIMER2_TEP_INT_ST_V << MCPWM_TIMER2_TEP_INT_ST_S) +#define MCPWM_TIMER2_TEP_INT_ST_V 0x00000001U +#define MCPWM_TIMER2_TEP_INT_ST_S 8 +/** MCPWM_FAULT0_INT_ST : RO; bitpos: [9]; default: 0; + * The masked status bit for the interrupt triggered when fault_event0 starts. + */ +#define MCPWM_FAULT0_INT_ST (BIT(9)) +#define MCPWM_FAULT0_INT_ST_M (MCPWM_FAULT0_INT_ST_V << MCPWM_FAULT0_INT_ST_S) +#define MCPWM_FAULT0_INT_ST_V 0x00000001U +#define MCPWM_FAULT0_INT_ST_S 9 +/** MCPWM_FAULT1_INT_ST : RO; bitpos: [10]; default: 0; + * The masked status bit for the interrupt triggered when fault_event1 starts. + */ +#define MCPWM_FAULT1_INT_ST (BIT(10)) +#define MCPWM_FAULT1_INT_ST_M (MCPWM_FAULT1_INT_ST_V << MCPWM_FAULT1_INT_ST_S) +#define MCPWM_FAULT1_INT_ST_V 0x00000001U +#define MCPWM_FAULT1_INT_ST_S 10 +/** MCPWM_FAULT2_INT_ST : RO; bitpos: [11]; default: 0; + * The masked status bit for the interrupt triggered when fault_event2 starts. + */ +#define MCPWM_FAULT2_INT_ST (BIT(11)) +#define MCPWM_FAULT2_INT_ST_M (MCPWM_FAULT2_INT_ST_V << MCPWM_FAULT2_INT_ST_S) +#define MCPWM_FAULT2_INT_ST_V 0x00000001U +#define MCPWM_FAULT2_INT_ST_S 11 +/** MCPWM_FAULT0_CLR_INT_ST : RO; bitpos: [12]; default: 0; + * The masked status bit for the interrupt triggered when fault_event0 ends. + */ +#define MCPWM_FAULT0_CLR_INT_ST (BIT(12)) +#define MCPWM_FAULT0_CLR_INT_ST_M (MCPWM_FAULT0_CLR_INT_ST_V << MCPWM_FAULT0_CLR_INT_ST_S) +#define MCPWM_FAULT0_CLR_INT_ST_V 0x00000001U +#define MCPWM_FAULT0_CLR_INT_ST_S 12 +/** MCPWM_FAULT1_CLR_INT_ST : RO; bitpos: [13]; default: 0; + * The masked status bit for the interrupt triggered when fault_event1 ends. + */ +#define MCPWM_FAULT1_CLR_INT_ST (BIT(13)) +#define MCPWM_FAULT1_CLR_INT_ST_M (MCPWM_FAULT1_CLR_INT_ST_V << MCPWM_FAULT1_CLR_INT_ST_S) +#define MCPWM_FAULT1_CLR_INT_ST_V 0x00000001U +#define MCPWM_FAULT1_CLR_INT_ST_S 13 +/** MCPWM_FAULT2_CLR_INT_ST : RO; bitpos: [14]; default: 0; + * The masked status bit for the interrupt triggered when fault_event2 ends. + */ +#define MCPWM_FAULT2_CLR_INT_ST (BIT(14)) +#define MCPWM_FAULT2_CLR_INT_ST_M (MCPWM_FAULT2_CLR_INT_ST_V << MCPWM_FAULT2_CLR_INT_ST_S) +#define MCPWM_FAULT2_CLR_INT_ST_V 0x00000001U +#define MCPWM_FAULT2_CLR_INT_ST_S 14 +/** MCPWM_OP0_TEA_INT_ST : RO; bitpos: [15]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 0 TEA event + */ +#define MCPWM_OP0_TEA_INT_ST (BIT(15)) +#define MCPWM_OP0_TEA_INT_ST_M (MCPWM_OP0_TEA_INT_ST_V << MCPWM_OP0_TEA_INT_ST_S) +#define MCPWM_OP0_TEA_INT_ST_V 0x00000001U +#define MCPWM_OP0_TEA_INT_ST_S 15 +/** MCPWM_OP1_TEA_INT_ST : RO; bitpos: [16]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 1 TEA event + */ +#define MCPWM_OP1_TEA_INT_ST (BIT(16)) +#define MCPWM_OP1_TEA_INT_ST_M (MCPWM_OP1_TEA_INT_ST_V << MCPWM_OP1_TEA_INT_ST_S) +#define MCPWM_OP1_TEA_INT_ST_V 0x00000001U +#define MCPWM_OP1_TEA_INT_ST_S 16 +/** MCPWM_OP2_TEA_INT_ST : RO; bitpos: [17]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 2 TEA event + */ +#define MCPWM_OP2_TEA_INT_ST (BIT(17)) +#define MCPWM_OP2_TEA_INT_ST_M (MCPWM_OP2_TEA_INT_ST_V << MCPWM_OP2_TEA_INT_ST_S) +#define MCPWM_OP2_TEA_INT_ST_V 0x00000001U +#define MCPWM_OP2_TEA_INT_ST_S 17 +/** MCPWM_OP0_TEB_INT_ST : RO; bitpos: [18]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 0 TEB event + */ +#define MCPWM_OP0_TEB_INT_ST (BIT(18)) +#define MCPWM_OP0_TEB_INT_ST_M (MCPWM_OP0_TEB_INT_ST_V << MCPWM_OP0_TEB_INT_ST_S) +#define MCPWM_OP0_TEB_INT_ST_V 0x00000001U +#define MCPWM_OP0_TEB_INT_ST_S 18 +/** MCPWM_OP1_TEB_INT_ST : RO; bitpos: [19]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 1 TEB event + */ +#define MCPWM_OP1_TEB_INT_ST (BIT(19)) +#define MCPWM_OP1_TEB_INT_ST_M (MCPWM_OP1_TEB_INT_ST_V << MCPWM_OP1_TEB_INT_ST_S) +#define MCPWM_OP1_TEB_INT_ST_V 0x00000001U +#define MCPWM_OP1_TEB_INT_ST_S 19 +/** MCPWM_OP2_TEB_INT_ST : RO; bitpos: [20]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 2 TEB event + */ +#define MCPWM_OP2_TEB_INT_ST (BIT(20)) +#define MCPWM_OP2_TEB_INT_ST_M (MCPWM_OP2_TEB_INT_ST_V << MCPWM_OP2_TEB_INT_ST_S) +#define MCPWM_OP2_TEB_INT_ST_V 0x00000001U +#define MCPWM_OP2_TEB_INT_ST_S 20 +/** MCPWM_FH0_CBC_INT_ST : RO; bitpos: [21]; default: 0; + * The masked status bit for the interrupt triggered by a cycle-by-cycle mode action + * on PWM0. + */ +#define MCPWM_FH0_CBC_INT_ST (BIT(21)) +#define MCPWM_FH0_CBC_INT_ST_M (MCPWM_FH0_CBC_INT_ST_V << MCPWM_FH0_CBC_INT_ST_S) +#define MCPWM_FH0_CBC_INT_ST_V 0x00000001U +#define MCPWM_FH0_CBC_INT_ST_S 21 +/** MCPWM_FH1_CBC_INT_ST : RO; bitpos: [22]; default: 0; + * The masked status bit for the interrupt triggered by a cycle-by-cycle mode action + * on PWM1. + */ +#define MCPWM_FH1_CBC_INT_ST (BIT(22)) +#define MCPWM_FH1_CBC_INT_ST_M (MCPWM_FH1_CBC_INT_ST_V << MCPWM_FH1_CBC_INT_ST_S) +#define MCPWM_FH1_CBC_INT_ST_V 0x00000001U +#define MCPWM_FH1_CBC_INT_ST_S 22 +/** MCPWM_FH2_CBC_INT_ST : RO; bitpos: [23]; default: 0; + * The masked status bit for the interrupt triggered by a cycle-by-cycle mode action + * on PWM2. + */ +#define MCPWM_FH2_CBC_INT_ST (BIT(23)) +#define MCPWM_FH2_CBC_INT_ST_M (MCPWM_FH2_CBC_INT_ST_V << MCPWM_FH2_CBC_INT_ST_S) +#define MCPWM_FH2_CBC_INT_ST_V 0x00000001U +#define MCPWM_FH2_CBC_INT_ST_S 23 +/** MCPWM_FH0_OST_INT_ST : RO; bitpos: [24]; default: 0; + * The masked status bit for the interrupt triggered by a one-shot mode action on PWM0. + */ +#define MCPWM_FH0_OST_INT_ST (BIT(24)) +#define MCPWM_FH0_OST_INT_ST_M (MCPWM_FH0_OST_INT_ST_V << MCPWM_FH0_OST_INT_ST_S) +#define MCPWM_FH0_OST_INT_ST_V 0x00000001U +#define MCPWM_FH0_OST_INT_ST_S 24 +/** MCPWM_FH1_OST_INT_ST : RO; bitpos: [25]; default: 0; + * The masked status bit for the interrupt triggered by a one-shot mode action on PWM1. + */ +#define MCPWM_FH1_OST_INT_ST (BIT(25)) +#define MCPWM_FH1_OST_INT_ST_M (MCPWM_FH1_OST_INT_ST_V << MCPWM_FH1_OST_INT_ST_S) +#define MCPWM_FH1_OST_INT_ST_V 0x00000001U +#define MCPWM_FH1_OST_INT_ST_S 25 +/** MCPWM_FH2_OST_INT_ST : RO; bitpos: [26]; default: 0; + * The masked status bit for the interrupt triggered by a one-shot mode action on PWM2. + */ +#define MCPWM_FH2_OST_INT_ST (BIT(26)) +#define MCPWM_FH2_OST_INT_ST_M (MCPWM_FH2_OST_INT_ST_V << MCPWM_FH2_OST_INT_ST_S) +#define MCPWM_FH2_OST_INT_ST_V 0x00000001U +#define MCPWM_FH2_OST_INT_ST_S 26 +/** MCPWM_CAP0_INT_ST : RO; bitpos: [27]; default: 0; + * The masked status bit for the interrupt triggered by capture on channel 0. + */ +#define MCPWM_CAP0_INT_ST (BIT(27)) +#define MCPWM_CAP0_INT_ST_M (MCPWM_CAP0_INT_ST_V << MCPWM_CAP0_INT_ST_S) +#define MCPWM_CAP0_INT_ST_V 0x00000001U +#define MCPWM_CAP0_INT_ST_S 27 +/** MCPWM_CAP1_INT_ST : RO; bitpos: [28]; default: 0; + * The masked status bit for the interrupt triggered by capture on channel 1. + */ +#define MCPWM_CAP1_INT_ST (BIT(28)) +#define MCPWM_CAP1_INT_ST_M (MCPWM_CAP1_INT_ST_V << MCPWM_CAP1_INT_ST_S) +#define MCPWM_CAP1_INT_ST_V 0x00000001U +#define MCPWM_CAP1_INT_ST_S 28 +/** MCPWM_CAP2_INT_ST : RO; bitpos: [29]; default: 0; + * The masked status bit for the interrupt triggered by capture on channel 2. + */ +#define MCPWM_CAP2_INT_ST (BIT(29)) +#define MCPWM_CAP2_INT_ST_M (MCPWM_CAP2_INT_ST_V << MCPWM_CAP2_INT_ST_S) +#define MCPWM_CAP2_INT_ST_V 0x00000001U +#define MCPWM_CAP2_INT_ST_S 29 -#define MCPWM_INT_CLR_PWM_REG(i) (REG_MCPWM_BASE(i) + 0x11C) -/* MCPWM_CAP2_INT_CLR : WO ;bitpos:[29] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP2_INT_CLR (BIT(29)) -#define MCPWM_CAP2_INT_CLR_M (BIT(29)) -#define MCPWM_CAP2_INT_CLR_V 0x1 -#define MCPWM_CAP2_INT_CLR_S 29 -/* MCPWM_CAP1_INT_CLR : WO ;bitpos:[28] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP1_INT_CLR (BIT(28)) -#define MCPWM_CAP1_INT_CLR_M (BIT(28)) -#define MCPWM_CAP1_INT_CLR_V 0x1 -#define MCPWM_CAP1_INT_CLR_S 28 -/* MCPWM_CAP0_INT_CLR : WO ;bitpos:[27] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CAP0_INT_CLR (BIT(27)) -#define MCPWM_CAP0_INT_CLR_M (BIT(27)) -#define MCPWM_CAP0_INT_CLR_V 0x1 -#define MCPWM_CAP0_INT_CLR_S 27 -/* MCPWM_TZ2_OST_INT_CLR : WO ;bitpos:[26] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ2_OST_INT_CLR (BIT(26)) -#define MCPWM_TZ2_OST_INT_CLR_M (BIT(26)) -#define MCPWM_TZ2_OST_INT_CLR_V 0x1 -#define MCPWM_TZ2_OST_INT_CLR_S 26 -/* MCPWM_TZ1_OST_INT_CLR : WO ;bitpos:[25] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ1_OST_INT_CLR (BIT(25)) -#define MCPWM_TZ1_OST_INT_CLR_M (BIT(25)) -#define MCPWM_TZ1_OST_INT_CLR_V 0x1 -#define MCPWM_TZ1_OST_INT_CLR_S 25 -/* MCPWM_TZ0_OST_INT_CLR : WO ;bitpos:[24] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ0_OST_INT_CLR (BIT(24)) -#define MCPWM_TZ0_OST_INT_CLR_M (BIT(24)) -#define MCPWM_TZ0_OST_INT_CLR_V 0x1 -#define MCPWM_TZ0_OST_INT_CLR_S 24 -/* MCPWM_TZ2_CBC_INT_CLR : WO ;bitpos:[23] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ2_CBC_INT_CLR (BIT(23)) -#define MCPWM_TZ2_CBC_INT_CLR_M (BIT(23)) -#define MCPWM_TZ2_CBC_INT_CLR_V 0x1 -#define MCPWM_TZ2_CBC_INT_CLR_S 23 -/* MCPWM_TZ1_CBC_INT_CLR : WO ;bitpos:[22] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ1_CBC_INT_CLR (BIT(22)) -#define MCPWM_TZ1_CBC_INT_CLR_M (BIT(22)) -#define MCPWM_TZ1_CBC_INT_CLR_V 0x1 -#define MCPWM_TZ1_CBC_INT_CLR_S 22 -/* MCPWM_TZ0_CBC_INT_CLR : WO ;bitpos:[21] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_TZ0_CBC_INT_CLR (BIT(21)) -#define MCPWM_TZ0_CBC_INT_CLR_M (BIT(21)) -#define MCPWM_TZ0_CBC_INT_CLR_V 0x1 -#define MCPWM_TZ0_CBC_INT_CLR_S 21 -/* MCPWM_CMPR2_TEB_INT_CLR : WO ;bitpos:[20] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR2_TEB_INT_CLR (BIT(20)) -#define MCPWM_CMPR2_TEB_INT_CLR_M (BIT(20)) -#define MCPWM_CMPR2_TEB_INT_CLR_V 0x1 -#define MCPWM_CMPR2_TEB_INT_CLR_S 20 -/* MCPWM_CMPR1_TEB_INT_CLR : WO ;bitpos:[19] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR1_TEB_INT_CLR (BIT(19)) -#define MCPWM_CMPR1_TEB_INT_CLR_M (BIT(19)) -#define MCPWM_CMPR1_TEB_INT_CLR_V 0x1 -#define MCPWM_CMPR1_TEB_INT_CLR_S 19 -/* MCPWM_CMPR0_TEB_INT_CLR : WO ;bitpos:[18] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR0_TEB_INT_CLR (BIT(18)) -#define MCPWM_CMPR0_TEB_INT_CLR_M (BIT(18)) -#define MCPWM_CMPR0_TEB_INT_CLR_V 0x1 -#define MCPWM_CMPR0_TEB_INT_CLR_S 18 -/* MCPWM_CMPR2_TEA_INT_CLR : WO ;bitpos:[17] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR2_TEA_INT_CLR (BIT(17)) -#define MCPWM_CMPR2_TEA_INT_CLR_M (BIT(17)) -#define MCPWM_CMPR2_TEA_INT_CLR_V 0x1 -#define MCPWM_CMPR2_TEA_INT_CLR_S 17 -/* MCPWM_CMPR1_TEA_INT_CLR : WO ;bitpos:[16] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR1_TEA_INT_CLR (BIT(16)) -#define MCPWM_CMPR1_TEA_INT_CLR_M (BIT(16)) -#define MCPWM_CMPR1_TEA_INT_CLR_V 0x1 -#define MCPWM_CMPR1_TEA_INT_CLR_S 16 -/* MCPWM_CMPR0_TEA_INT_CLR : WO ;bitpos:[15] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_CMPR0_TEA_INT_CLR (BIT(15)) -#define MCPWM_CMPR0_TEA_INT_CLR_M (BIT(15)) -#define MCPWM_CMPR0_TEA_INT_CLR_V 0x1 -#define MCPWM_CMPR0_TEA_INT_CLR_S 15 -/* MCPWM_FAULT2_CLR_INT_CLR : WO ;bitpos:[14] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT2_CLR_INT_CLR (BIT(14)) -#define MCPWM_FAULT2_CLR_INT_CLR_M (BIT(14)) -#define MCPWM_FAULT2_CLR_INT_CLR_V 0x1 -#define MCPWM_FAULT2_CLR_INT_CLR_S 14 -/* MCPWM_FAULT1_CLR_INT_CLR : WO ;bitpos:[13] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT1_CLR_INT_CLR (BIT(13)) -#define MCPWM_FAULT1_CLR_INT_CLR_M (BIT(13)) -#define MCPWM_FAULT1_CLR_INT_CLR_V 0x1 -#define MCPWM_FAULT1_CLR_INT_CLR_S 13 -/* MCPWM_FAULT0_CLR_INT_CLR : WO ;bitpos:[12] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT0_CLR_INT_CLR (BIT(12)) -#define MCPWM_FAULT0_CLR_INT_CLR_M (BIT(12)) -#define MCPWM_FAULT0_CLR_INT_CLR_V 0x1 -#define MCPWM_FAULT0_CLR_INT_CLR_S 12 -/* MCPWM_FAULT2_INT_CLR : WO ;bitpos:[11] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT2_INT_CLR (BIT(11)) -#define MCPWM_FAULT2_INT_CLR_M (BIT(11)) -#define MCPWM_FAULT2_INT_CLR_V 0x1 -#define MCPWM_FAULT2_INT_CLR_S 11 -/* MCPWM_FAULT1_INT_CLR : WO ;bitpos:[10] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT1_INT_CLR (BIT(10)) -#define MCPWM_FAULT1_INT_CLR_M (BIT(10)) -#define MCPWM_FAULT1_INT_CLR_V 0x1 -#define MCPWM_FAULT1_INT_CLR_S 10 -/* MCPWM_FAULT0_INT_CLR : WO ;bitpos:[9] ;default: 1'd0 ; */ -/*description: .*/ -#define MCPWM_FAULT0_INT_CLR (BIT(9)) -#define MCPWM_FAULT0_INT_CLR_M (BIT(9)) -#define MCPWM_FAULT0_INT_CLR_V 0x1 -#define MCPWM_FAULT0_INT_CLR_S 9 -/* MCPWM_TIMER2_TEP_INT_CLR : WO ;bitpos:[8] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_TEP_INT_CLR (BIT(8)) -#define MCPWM_TIMER2_TEP_INT_CLR_M (BIT(8)) -#define MCPWM_TIMER2_TEP_INT_CLR_V 0x1 -#define MCPWM_TIMER2_TEP_INT_CLR_S 8 -/* MCPWM_TIMER1_TEP_INT_CLR : WO ;bitpos:[7] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_TEP_INT_CLR (BIT(7)) -#define MCPWM_TIMER1_TEP_INT_CLR_M (BIT(7)) -#define MCPWM_TIMER1_TEP_INT_CLR_V 0x1 -#define MCPWM_TIMER1_TEP_INT_CLR_S 7 -/* MCPWM_TIMER0_TEP_INT_CLR : WO ;bitpos:[6] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER0_TEP_INT_CLR (BIT(6)) -#define MCPWM_TIMER0_TEP_INT_CLR_M (BIT(6)) -#define MCPWM_TIMER0_TEP_INT_CLR_V 0x1 -#define MCPWM_TIMER0_TEP_INT_CLR_S 6 -/* MCPWM_TIMER2_TEZ_INT_CLR : WO ;bitpos:[5] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_TEZ_INT_CLR (BIT(5)) -#define MCPWM_TIMER2_TEZ_INT_CLR_M (BIT(5)) -#define MCPWM_TIMER2_TEZ_INT_CLR_V 0x1 -#define MCPWM_TIMER2_TEZ_INT_CLR_S 5 -/* MCPWM_TIMER1_TEZ_INT_CLR : WO ;bitpos:[4] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_TEZ_INT_CLR (BIT(4)) -#define MCPWM_TIMER1_TEZ_INT_CLR_M (BIT(4)) -#define MCPWM_TIMER1_TEZ_INT_CLR_V 0x1 -#define MCPWM_TIMER1_TEZ_INT_CLR_S 4 -/* MCPWM_TIMER0_TEZ_INT_CLR : WO ;bitpos:[3] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER0_TEZ_INT_CLR (BIT(3)) -#define MCPWM_TIMER0_TEZ_INT_CLR_M (BIT(3)) -#define MCPWM_TIMER0_TEZ_INT_CLR_V 0x1 -#define MCPWM_TIMER0_TEZ_INT_CLR_S 3 -/* MCPWM_TIMER2_STOP_INT_CLR : WO ;bitpos:[2] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER2_STOP_INT_CLR (BIT(2)) -#define MCPWM_TIMER2_STOP_INT_CLR_M (BIT(2)) -#define MCPWM_TIMER2_STOP_INT_CLR_V 0x1 -#define MCPWM_TIMER2_STOP_INT_CLR_S 2 -/* MCPWM_TIMER1_STOP_INT_CLR : WO ;bitpos:[1] ;default: 1'h0 ; */ -/*description: .*/ -#define MCPWM_TIMER1_STOP_INT_CLR (BIT(1)) -#define MCPWM_TIMER1_STOP_INT_CLR_M (BIT(1)) -#define MCPWM_TIMER1_STOP_INT_CLR_V 0x1 -#define MCPWM_TIMER1_STOP_INT_CLR_S 1 -/* MCPWM_TIMER0_STOP_INT_CLR : WO ;bitpos:[0] ;default: 1'h0 ; */ -/*description: .*/ +/** MCPWM_INT_CLR_REG register + * Interrupt clear bits + */ +#define MCPWM_INT_CLR_REG(i) (DR_REG_MCPWM_BASE(i) + 0x11c) +/** MCPWM_TIMER0_STOP_INT_CLR : WT; bitpos: [0]; default: 0; + * Set this bit to clear the interrupt triggered when the timer 0 stops. + */ #define MCPWM_TIMER0_STOP_INT_CLR (BIT(0)) -#define MCPWM_TIMER0_STOP_INT_CLR_M (BIT(0)) -#define MCPWM_TIMER0_STOP_INT_CLR_V 0x1 +#define MCPWM_TIMER0_STOP_INT_CLR_M (MCPWM_TIMER0_STOP_INT_CLR_V << MCPWM_TIMER0_STOP_INT_CLR_S) +#define MCPWM_TIMER0_STOP_INT_CLR_V 0x00000001U #define MCPWM_TIMER0_STOP_INT_CLR_S 0 +/** MCPWM_TIMER1_STOP_INT_CLR : WT; bitpos: [1]; default: 0; + * Set this bit to clear the interrupt triggered when the timer 1 stops. + */ +#define MCPWM_TIMER1_STOP_INT_CLR (BIT(1)) +#define MCPWM_TIMER1_STOP_INT_CLR_M (MCPWM_TIMER1_STOP_INT_CLR_V << MCPWM_TIMER1_STOP_INT_CLR_S) +#define MCPWM_TIMER1_STOP_INT_CLR_V 0x00000001U +#define MCPWM_TIMER1_STOP_INT_CLR_S 1 +/** MCPWM_TIMER2_STOP_INT_CLR : WT; bitpos: [2]; default: 0; + * Set this bit to clear the interrupt triggered when the timer 2 stops. + */ +#define MCPWM_TIMER2_STOP_INT_CLR (BIT(2)) +#define MCPWM_TIMER2_STOP_INT_CLR_M (MCPWM_TIMER2_STOP_INT_CLR_V << MCPWM_TIMER2_STOP_INT_CLR_S) +#define MCPWM_TIMER2_STOP_INT_CLR_V 0x00000001U +#define MCPWM_TIMER2_STOP_INT_CLR_S 2 +/** MCPWM_TIMER0_TEZ_INT_CLR : WT; bitpos: [3]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 0 TEZ event. + */ +#define MCPWM_TIMER0_TEZ_INT_CLR (BIT(3)) +#define MCPWM_TIMER0_TEZ_INT_CLR_M (MCPWM_TIMER0_TEZ_INT_CLR_V << MCPWM_TIMER0_TEZ_INT_CLR_S) +#define MCPWM_TIMER0_TEZ_INT_CLR_V 0x00000001U +#define MCPWM_TIMER0_TEZ_INT_CLR_S 3 +/** MCPWM_TIMER1_TEZ_INT_CLR : WT; bitpos: [4]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 1 TEZ event. + */ +#define MCPWM_TIMER1_TEZ_INT_CLR (BIT(4)) +#define MCPWM_TIMER1_TEZ_INT_CLR_M (MCPWM_TIMER1_TEZ_INT_CLR_V << MCPWM_TIMER1_TEZ_INT_CLR_S) +#define MCPWM_TIMER1_TEZ_INT_CLR_V 0x00000001U +#define MCPWM_TIMER1_TEZ_INT_CLR_S 4 +/** MCPWM_TIMER2_TEZ_INT_CLR : WT; bitpos: [5]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 2 TEZ event. + */ +#define MCPWM_TIMER2_TEZ_INT_CLR (BIT(5)) +#define MCPWM_TIMER2_TEZ_INT_CLR_M (MCPWM_TIMER2_TEZ_INT_CLR_V << MCPWM_TIMER2_TEZ_INT_CLR_S) +#define MCPWM_TIMER2_TEZ_INT_CLR_V 0x00000001U +#define MCPWM_TIMER2_TEZ_INT_CLR_S 5 +/** MCPWM_TIMER0_TEP_INT_CLR : WT; bitpos: [6]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 0 TEP event. + */ +#define MCPWM_TIMER0_TEP_INT_CLR (BIT(6)) +#define MCPWM_TIMER0_TEP_INT_CLR_M (MCPWM_TIMER0_TEP_INT_CLR_V << MCPWM_TIMER0_TEP_INT_CLR_S) +#define MCPWM_TIMER0_TEP_INT_CLR_V 0x00000001U +#define MCPWM_TIMER0_TEP_INT_CLR_S 6 +/** MCPWM_TIMER1_TEP_INT_CLR : WT; bitpos: [7]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 1 TEP event. + */ +#define MCPWM_TIMER1_TEP_INT_CLR (BIT(7)) +#define MCPWM_TIMER1_TEP_INT_CLR_M (MCPWM_TIMER1_TEP_INT_CLR_V << MCPWM_TIMER1_TEP_INT_CLR_S) +#define MCPWM_TIMER1_TEP_INT_CLR_V 0x00000001U +#define MCPWM_TIMER1_TEP_INT_CLR_S 7 +/** MCPWM_TIMER2_TEP_INT_CLR : WT; bitpos: [8]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 2 TEP event. + */ +#define MCPWM_TIMER2_TEP_INT_CLR (BIT(8)) +#define MCPWM_TIMER2_TEP_INT_CLR_M (MCPWM_TIMER2_TEP_INT_CLR_V << MCPWM_TIMER2_TEP_INT_CLR_S) +#define MCPWM_TIMER2_TEP_INT_CLR_V 0x00000001U +#define MCPWM_TIMER2_TEP_INT_CLR_S 8 +/** MCPWM_FAULT0_INT_CLR : WT; bitpos: [9]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event0 starts. + */ +#define MCPWM_FAULT0_INT_CLR (BIT(9)) +#define MCPWM_FAULT0_INT_CLR_M (MCPWM_FAULT0_INT_CLR_V << MCPWM_FAULT0_INT_CLR_S) +#define MCPWM_FAULT0_INT_CLR_V 0x00000001U +#define MCPWM_FAULT0_INT_CLR_S 9 +/** MCPWM_FAULT1_INT_CLR : WT; bitpos: [10]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event1 starts. + */ +#define MCPWM_FAULT1_INT_CLR (BIT(10)) +#define MCPWM_FAULT1_INT_CLR_M (MCPWM_FAULT1_INT_CLR_V << MCPWM_FAULT1_INT_CLR_S) +#define MCPWM_FAULT1_INT_CLR_V 0x00000001U +#define MCPWM_FAULT1_INT_CLR_S 10 +/** MCPWM_FAULT2_INT_CLR : WT; bitpos: [11]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event2 starts. + */ +#define MCPWM_FAULT2_INT_CLR (BIT(11)) +#define MCPWM_FAULT2_INT_CLR_M (MCPWM_FAULT2_INT_CLR_V << MCPWM_FAULT2_INT_CLR_S) +#define MCPWM_FAULT2_INT_CLR_V 0x00000001U +#define MCPWM_FAULT2_INT_CLR_S 11 +/** MCPWM_FAULT0_CLR_INT_CLR : WT; bitpos: [12]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event0 ends. + */ +#define MCPWM_FAULT0_CLR_INT_CLR (BIT(12)) +#define MCPWM_FAULT0_CLR_INT_CLR_M (MCPWM_FAULT0_CLR_INT_CLR_V << MCPWM_FAULT0_CLR_INT_CLR_S) +#define MCPWM_FAULT0_CLR_INT_CLR_V 0x00000001U +#define MCPWM_FAULT0_CLR_INT_CLR_S 12 +/** MCPWM_FAULT1_CLR_INT_CLR : WT; bitpos: [13]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event1 ends. + */ +#define MCPWM_FAULT1_CLR_INT_CLR (BIT(13)) +#define MCPWM_FAULT1_CLR_INT_CLR_M (MCPWM_FAULT1_CLR_INT_CLR_V << MCPWM_FAULT1_CLR_INT_CLR_S) +#define MCPWM_FAULT1_CLR_INT_CLR_V 0x00000001U +#define MCPWM_FAULT1_CLR_INT_CLR_S 13 +/** MCPWM_FAULT2_CLR_INT_CLR : WT; bitpos: [14]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event2 ends. + */ +#define MCPWM_FAULT2_CLR_INT_CLR (BIT(14)) +#define MCPWM_FAULT2_CLR_INT_CLR_M (MCPWM_FAULT2_CLR_INT_CLR_V << MCPWM_FAULT2_CLR_INT_CLR_S) +#define MCPWM_FAULT2_CLR_INT_CLR_V 0x00000001U +#define MCPWM_FAULT2_CLR_INT_CLR_S 14 +/** MCPWM_OP0_TEA_INT_CLR : WT; bitpos: [15]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 0 TEA event + */ +#define MCPWM_OP0_TEA_INT_CLR (BIT(15)) +#define MCPWM_OP0_TEA_INT_CLR_M (MCPWM_OP0_TEA_INT_CLR_V << MCPWM_OP0_TEA_INT_CLR_S) +#define MCPWM_OP0_TEA_INT_CLR_V 0x00000001U +#define MCPWM_OP0_TEA_INT_CLR_S 15 +/** MCPWM_OP1_TEA_INT_CLR : WT; bitpos: [16]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 1 TEA event + */ +#define MCPWM_OP1_TEA_INT_CLR (BIT(16)) +#define MCPWM_OP1_TEA_INT_CLR_M (MCPWM_OP1_TEA_INT_CLR_V << MCPWM_OP1_TEA_INT_CLR_S) +#define MCPWM_OP1_TEA_INT_CLR_V 0x00000001U +#define MCPWM_OP1_TEA_INT_CLR_S 16 +/** MCPWM_OP2_TEA_INT_CLR : WT; bitpos: [17]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 2 TEA event + */ +#define MCPWM_OP2_TEA_INT_CLR (BIT(17)) +#define MCPWM_OP2_TEA_INT_CLR_M (MCPWM_OP2_TEA_INT_CLR_V << MCPWM_OP2_TEA_INT_CLR_S) +#define MCPWM_OP2_TEA_INT_CLR_V 0x00000001U +#define MCPWM_OP2_TEA_INT_CLR_S 17 +/** MCPWM_OP0_TEB_INT_CLR : WT; bitpos: [18]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 0 TEB event + */ +#define MCPWM_OP0_TEB_INT_CLR (BIT(18)) +#define MCPWM_OP0_TEB_INT_CLR_M (MCPWM_OP0_TEB_INT_CLR_V << MCPWM_OP0_TEB_INT_CLR_S) +#define MCPWM_OP0_TEB_INT_CLR_V 0x00000001U +#define MCPWM_OP0_TEB_INT_CLR_S 18 +/** MCPWM_OP1_TEB_INT_CLR : WT; bitpos: [19]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 1 TEB event + */ +#define MCPWM_OP1_TEB_INT_CLR (BIT(19)) +#define MCPWM_OP1_TEB_INT_CLR_M (MCPWM_OP1_TEB_INT_CLR_V << MCPWM_OP1_TEB_INT_CLR_S) +#define MCPWM_OP1_TEB_INT_CLR_V 0x00000001U +#define MCPWM_OP1_TEB_INT_CLR_S 19 +/** MCPWM_OP2_TEB_INT_CLR : WT; bitpos: [20]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 2 TEB event + */ +#define MCPWM_OP2_TEB_INT_CLR (BIT(20)) +#define MCPWM_OP2_TEB_INT_CLR_M (MCPWM_OP2_TEB_INT_CLR_V << MCPWM_OP2_TEB_INT_CLR_S) +#define MCPWM_OP2_TEB_INT_CLR_V 0x00000001U +#define MCPWM_OP2_TEB_INT_CLR_S 20 +/** MCPWM_FH0_CBC_INT_CLR : WT; bitpos: [21]; default: 0; + * Set this bit to clear the interrupt triggered by a cycle-by-cycle mode action on + * PWM0. + */ +#define MCPWM_FH0_CBC_INT_CLR (BIT(21)) +#define MCPWM_FH0_CBC_INT_CLR_M (MCPWM_FH0_CBC_INT_CLR_V << MCPWM_FH0_CBC_INT_CLR_S) +#define MCPWM_FH0_CBC_INT_CLR_V 0x00000001U +#define MCPWM_FH0_CBC_INT_CLR_S 21 +/** MCPWM_FH1_CBC_INT_CLR : WT; bitpos: [22]; default: 0; + * Set this bit to clear the interrupt triggered by a cycle-by-cycle mode action on + * PWM1. + */ +#define MCPWM_FH1_CBC_INT_CLR (BIT(22)) +#define MCPWM_FH1_CBC_INT_CLR_M (MCPWM_FH1_CBC_INT_CLR_V << MCPWM_FH1_CBC_INT_CLR_S) +#define MCPWM_FH1_CBC_INT_CLR_V 0x00000001U +#define MCPWM_FH1_CBC_INT_CLR_S 22 +/** MCPWM_FH2_CBC_INT_CLR : WT; bitpos: [23]; default: 0; + * Set this bit to clear the interrupt triggered by a cycle-by-cycle mode action on + * PWM2. + */ +#define MCPWM_FH2_CBC_INT_CLR (BIT(23)) +#define MCPWM_FH2_CBC_INT_CLR_M (MCPWM_FH2_CBC_INT_CLR_V << MCPWM_FH2_CBC_INT_CLR_S) +#define MCPWM_FH2_CBC_INT_CLR_V 0x00000001U +#define MCPWM_FH2_CBC_INT_CLR_S 23 +/** MCPWM_FH0_OST_INT_CLR : WT; bitpos: [24]; default: 0; + * Set this bit to clear the interrupt triggered by a one-shot mode action on PWM0. + */ +#define MCPWM_FH0_OST_INT_CLR (BIT(24)) +#define MCPWM_FH0_OST_INT_CLR_M (MCPWM_FH0_OST_INT_CLR_V << MCPWM_FH0_OST_INT_CLR_S) +#define MCPWM_FH0_OST_INT_CLR_V 0x00000001U +#define MCPWM_FH0_OST_INT_CLR_S 24 +/** MCPWM_FH1_OST_INT_CLR : WT; bitpos: [25]; default: 0; + * Set this bit to clear the interrupt triggered by a one-shot mode action on PWM1. + */ +#define MCPWM_FH1_OST_INT_CLR (BIT(25)) +#define MCPWM_FH1_OST_INT_CLR_M (MCPWM_FH1_OST_INT_CLR_V << MCPWM_FH1_OST_INT_CLR_S) +#define MCPWM_FH1_OST_INT_CLR_V 0x00000001U +#define MCPWM_FH1_OST_INT_CLR_S 25 +/** MCPWM_FH2_OST_INT_CLR : WT; bitpos: [26]; default: 0; + * Set this bit to clear the interrupt triggered by a one-shot mode action on PWM2. + */ +#define MCPWM_FH2_OST_INT_CLR (BIT(26)) +#define MCPWM_FH2_OST_INT_CLR_M (MCPWM_FH2_OST_INT_CLR_V << MCPWM_FH2_OST_INT_CLR_S) +#define MCPWM_FH2_OST_INT_CLR_V 0x00000001U +#define MCPWM_FH2_OST_INT_CLR_S 26 +/** MCPWM_CAP0_INT_CLR : WT; bitpos: [27]; default: 0; + * Set this bit to clear the interrupt triggered by capture on channel 0. + */ +#define MCPWM_CAP0_INT_CLR (BIT(27)) +#define MCPWM_CAP0_INT_CLR_M (MCPWM_CAP0_INT_CLR_V << MCPWM_CAP0_INT_CLR_S) +#define MCPWM_CAP0_INT_CLR_V 0x00000001U +#define MCPWM_CAP0_INT_CLR_S 27 +/** MCPWM_CAP1_INT_CLR : WT; bitpos: [28]; default: 0; + * Set this bit to clear the interrupt triggered by capture on channel 1. + */ +#define MCPWM_CAP1_INT_CLR (BIT(28)) +#define MCPWM_CAP1_INT_CLR_M (MCPWM_CAP1_INT_CLR_V << MCPWM_CAP1_INT_CLR_S) +#define MCPWM_CAP1_INT_CLR_V 0x00000001U +#define MCPWM_CAP1_INT_CLR_S 28 +/** MCPWM_CAP2_INT_CLR : WT; bitpos: [29]; default: 0; + * Set this bit to clear the interrupt triggered by capture on channel 2. + */ +#define MCPWM_CAP2_INT_CLR (BIT(29)) +#define MCPWM_CAP2_INT_CLR_M (MCPWM_CAP2_INT_CLR_V << MCPWM_CAP2_INT_CLR_S) +#define MCPWM_CAP2_INT_CLR_V 0x00000001U +#define MCPWM_CAP2_INT_CLR_S 29 -#define MCPWM_CLK_REG(i) (REG_MCPWM_BASE(i) + 0x120) -/* MCPWM_CLK_EN : R/W ;bitpos:[0] ;default: 1'd0 ; */ -/*description: .*/ +/** MCPWM_CLK_REG register + * MCPWM APB configuration register + */ +#define MCPWM_CLK_REG(i) (DR_REG_MCPWM_BASE(i) + 0x120) +/** MCPWM_CLK_EN : R/W; bitpos: [0]; default: 0; + * Force clock on for this register file + */ #define MCPWM_CLK_EN (BIT(0)) -#define MCPWM_CLK_EN_M (BIT(0)) -#define MCPWM_CLK_EN_V 0x1 +#define MCPWM_CLK_EN_M (MCPWM_CLK_EN_V << MCPWM_CLK_EN_S) +#define MCPWM_CLK_EN_V 0x00000001U #define MCPWM_CLK_EN_S 0 -#define MCPWM_VERSION_REG(i) (REG_MCPWM_BASE(i) + 0x124) -/* MCPWM_DATE : R/W ;bitpos:[27:0] ;default: 28'h1509110 ; */ -/*description: .*/ -#define MCPWM_DATE 0x0FFFFFFF -#define MCPWM_DATE_M ((MCPWM_DATE_V)<<(MCPWM_DATE_S)) -#define MCPWM_DATE_V 0xFFFFFFF +/** MCPWM_VERSION_REG register + * Version register. + */ +#define MCPWM_VERSION_REG(i) (DR_REG_MCPWM_BASE(i) + 0x124) +/** MCPWM_DATE : R/W; bitpos: [27:0]; default: 34632240; + * Version of this register file + */ +#define MCPWM_DATE 0x0FFFFFFFU +#define MCPWM_DATE_M (MCPWM_DATE_V << MCPWM_DATE_S) +#define MCPWM_DATE_V 0x0FFFFFFFU #define MCPWM_DATE_S 0 - #ifdef __cplusplus } #endif - - - -#endif /*_SOC_MCPWM_REG_H_ */ diff --git a/components/soc/esp32s3/include/soc/mcpwm_struct.h b/components/soc/esp32s3/include/soc/mcpwm_struct.h index 565e0a9886..4e13290fe8 100644 --- a/components/soc/esp32s3/include/soc/mcpwm_struct.h +++ b/components/soc/esp32s3/include/soc/mcpwm_struct.h @@ -1,461 +1,1468 @@ -// 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. -#ifndef _SOC_MCPWM_STRUCT_H_ -#define _SOC_MCPWM_STRUCT_H_ - +/** + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once #include #ifdef __cplusplus extern "C" { #endif -typedef volatile struct { - union { - struct { - uint32_t prescale : 8; - uint32_t reserved8 : 24; - }; - uint32_t val; - } clk_cfg; +/** Group: Prescaler configuration */ +/** Type of clk_cfg register + * PWM clock prescaler register. + */ +typedef union { struct { - union { - struct { - uint32_t prescale : 8; - uint32_t period : 16; - uint32_t upmethod : 2; /*0: immediate, 1: eqz, 2: sync, 3: eqz | sync*/ - uint32_t reserved26 : 6; - }; - uint32_t val; - } period; - union { - struct { - uint32_t start : 3; /*0: stop @ eqz, 1: stop @ eqp, 2: free run, 3: start and stop @ next eqz, 4: start and stop @ next eqp,*/ - uint32_t mode : 2; /* 0: freeze, 1: inc, 2: dec, 3: up-down*/ - uint32_t reserved5 : 27; - }; - uint32_t val; - } mode; - union { - struct { - uint32_t in_en : 1; - uint32_t sync_sw : 1; /*write the negate value will trigger a sw sync*/ - uint32_t out_sel : 2; - uint32_t timer_phase : 16; /*phase for timer reload on sync event*/ - uint32_t phase_direct : 1; /*counter direction to apply on sync event*/ - uint32_t reserved21 : 11; - }; - uint32_t val; - } sync; - union { - struct { - uint32_t value : 16; - uint32_t direction : 1; - uint32_t reserved17 : 15; - }; - uint32_t val; - } status; - } timer[3]; - union { - struct { - uint32_t t0_in_sel : 3; - uint32_t t1_in_sel : 3; - uint32_t t2_in_sel : 3; - uint32_t ext_in0_inv : 1; - uint32_t ext_in1_inv : 1; - uint32_t ext_in2_inv : 1; - uint32_t reserved12 : 20; - }; - uint32_t val; - } timer_synci_cfg; - union { - struct { - uint32_t operator0_sel : 2; /*0: timer0, 1: timer1, 2: timer2*/ - uint32_t operator1_sel : 2; /*0: timer0, 1: timer1, 2: timer2*/ - uint32_t operator2_sel : 2; /*0: timer0, 1: timer1, 2: timer2*/ - uint32_t reserved6 : 26; - }; - uint32_t val; - } timer_sel; + /** clk_prescale : R/W; bitpos: [7:0]; default: 0; + * Period of PWM_clk = 6.25ns * (PWM_CLK_PRESCALE + 1) + */ + uint32_t clk_prescale: 8; + uint32_t reserved_8: 24; + }; + uint32_t val; +} mcpwm_clk_cfg_reg_t; + + +/** Group: MCPWM Timer Configuration and status */ +/** Type of timer_cfg0 register + * PWM timer period and update method configuration register. + */ +typedef union { struct { - union { - struct { - uint32_t a_upmethod : 4; /*0: immediate, bit0: tez, bit1: tep, bit2: sync, bit3: freeze*/ - uint32_t b_upmethod : 4; /*0: immediate, bit0: tez, bit1: tep, bit2: sync, bit3: freeze*/ - uint32_t a_shdw_full : 1; - uint32_t b_shdw_full : 1; - uint32_t reserved10 : 22; - }; - uint32_t val; - } cmpr_cfg; - union { - struct { - uint32_t cmpr_val : 16; - uint32_t reserved16 : 16; - }; - uint32_t val; - } cmpr_value[2]; - union { - struct { - uint32_t upmethod : 4; /*0: immediate, bit0: tez, bit1: tep, bit2: sync. bit3: freeze*/ - uint32_t t0_sel : 3; /*take effect immediately, 0: extra0, 1: extra1, 2: extra2, 3: sync_taken, 4: none*/ - uint32_t t1_sel : 3; /*take effect immediately, 0: extra0, 1: extra1, 2: extra2, 3: sync_taken, 4: none*/ - uint32_t reserved10 : 22; - }; - uint32_t val; - } gen_cfg0; - union { - struct { - uint32_t cntu_force_upmethod : 6; /*0: immediate, bit0: tez, bit1: tep, bit2: tea, bit3: teb, bit4: sync, bit5: freeze*/ - uint32_t a_cntuforce_mode : 2; /*0: disabled, 1: low, 2: high, 3: disabled*/ - uint32_t b_cntuforce_mode : 2; /*0: disabled, 1: low, 2: high, 3: disabled*/ - uint32_t a_nciforce : 1; /*non-continuous immediate sw force, a toggle will trigger a force event*/ - uint32_t a_nciforce_mode : 2; /*0: disabled, 1: low, 2: high, 3: disabled*/ - uint32_t b_nciforce : 1; /*non-continuous immediate sw force, a toggle will trigger a force event*/ - uint32_t b_nciforce_mode : 2; /*0: disabled, 1: low, 2: high, 3: disabled*/ - uint32_t reserved16 : 16; - }; - uint32_t val; - } gen_force; - union { - struct { - uint32_t utez : 2; - uint32_t utep : 2; - uint32_t utea : 2; - uint32_t uteb : 2; - uint32_t ut0 : 2; - uint32_t ut1 : 2; - uint32_t dtez : 2; - uint32_t dtep : 2; - uint32_t dtea : 2; - uint32_t dteb : 2; - uint32_t dt0 : 2; - uint32_t dt1 : 2; /*0: no change, 1: low, 2: high, 3: toggle*/ - uint32_t reserved24 : 8; - }; - uint32_t val; - } generator[2]; - union { - struct { - uint32_t fed_upmethod : 4; /*0: immediate, bit0: tez, bit1: tep, bit2: sync, bit3: freeze*/ - uint32_t red_upmethod : 4; /*0: immediate, bit0: tez, bit1: tep, bit2: sync, bit3: freeze*/ - uint32_t deb_mode : 1; /*immediate, dual-edge B mode, 0: fed/red take effect on different path separately, 1: fed/red take effect on B path, A out is in bypass or dulpB mode*/ - uint32_t a_outswap : 1; - uint32_t b_outswap : 1; - uint32_t red_insel : 1; - uint32_t fed_insel : 1; - uint32_t red_outinvert : 1; - uint32_t fed_outinvert : 1; - uint32_t a_outbypass : 1; - uint32_t b_outbypass : 1; - uint32_t clk_sel : 1; - uint32_t reserved18 : 14; - }; - uint32_t val; - } db_cfg; - union { - struct { - uint32_t fed : 16; - uint32_t reserved16 : 16; - }; - uint32_t val; - } db_fed_cfg; - union { - struct { - uint32_t red : 16; - uint32_t reserved16 : 16; - }; - uint32_t val; - } db_red_cfg; - union { - struct { - uint32_t en : 1; - uint32_t prescale : 4; - uint32_t duty : 3; - uint32_t oshtwth : 4; - uint32_t out_invert : 1; - uint32_t in_invert : 1; - uint32_t reserved14 : 18; - }; - uint32_t val; - } carrier_cfg; - union { - struct { - uint32_t sw_cbc : 1; /*0: disable, 1: enable*/ - uint32_t f2_cbc : 1; /*0: disable, 1: enable*/ - uint32_t f1_cbc : 1; /*0: disable, 1: enable*/ - uint32_t f0_cbc : 1; /*0: disable, 1: enable*/ - uint32_t sw_ost : 1; /*0: disable, 1: enable*/ - uint32_t f2_ost : 1; /*0: disable, 1: enable*/ - uint32_t f1_ost : 1; /*0: disable, 1: enable*/ - uint32_t f0_ost : 1; /*0: disable, 1: enable*/ - uint32_t a_cbc_d : 2; /*0: do nothing, 1: force lo, 2: force hi, 3: toggle*/ - uint32_t a_cbc_u : 2; /*0: do nothing, 1: force lo, 2: force hi, 3: toggle*/ - uint32_t a_ost_d : 2; /*0: do nothing, 1: force lo, 2: force hi, 3: toggle*/ - uint32_t a_ost_u : 2; /*0: do nothing, 1: force lo, 2: force hi, 3: toggle*/ - uint32_t b_cbc_d : 2; /*0: do nothing, 1: force lo, 2: force hi, 3: toggle*/ - uint32_t b_cbc_u : 2; /*0: do nothing, 1: force lo, 2: force hi, 3: toggle*/ - uint32_t b_ost_d : 2; /*0: do nothing, 1: force lo, 2: force hi, 3: toggle*/ - uint32_t b_ost_u : 2; /*0: do nothing, 1: force lo, 2: force hi, 3: toggle*/ - uint32_t reserved24 : 8; - }; - uint32_t val; - } tz_cfg0; - union { - struct { - uint32_t clr_ost : 1; /*a toggle will clear oneshot tripping*/ - uint32_t cbcpulse : 2; /*bit0: tez, bit1: tep*/ - uint32_t force_cbc : 1; /*a toggle trigger a cycle-by-cycle tripping*/ - uint32_t force_ost : 1; /*a toggle trigger a oneshot tripping*/ - uint32_t reserved5 : 27; - }; - uint32_t val; - } tz_cfg1; - union { - struct { - uint32_t cbc_on : 1; - uint32_t ost_on : 1; - uint32_t reserved2 : 30; - }; - uint32_t val; - } tz_status; - } channel[3]; - union { - struct { - uint32_t f0_en : 1; - uint32_t f1_en : 1; - uint32_t f2_en : 1; - uint32_t f0_pole : 1; - uint32_t f1_pole : 1; - uint32_t f2_pole : 1; - uint32_t event_f0 : 1; - uint32_t event_f1 : 1; - uint32_t event_f2 : 1; - uint32_t reserved9 : 23; - }; - uint32_t val; - } fault_detect; - union { - struct { - uint32_t timer_en : 1; - uint32_t synci_en : 1; - uint32_t synci_sel : 3; - uint32_t sync_sw : 1; /*Write 1 will force a timer sync*/ - uint32_t reserved6 : 26; - }; - uint32_t val; - } cap_timer_cfg; - uint32_t cap_timer_phase; - union { - struct { - uint32_t en : 1; - uint32_t mode : 2; /*bit0: negedge cap en, bit1: posedge cap en*/ - uint32_t prescale : 8; - uint32_t in_invert : 1; - uint32_t sw : 1; /*Write 1 will trigger a sw capture*/ - uint32_t reserved13 : 19; - }; - uint32_t val; - } cap_cfg_ch[3]; - uint32_t cap_val_ch[3]; - union { - struct { - uint32_t cap0_edge : 1; - uint32_t cap1_edge : 1; - uint32_t cap2_edge : 1; /*cap trigger's edge, 0: posedge, 1: negedge*/ - uint32_t reserved3 : 29; - }; - uint32_t val; - } cap_status; - union { - struct { - uint32_t global_up_en : 1; - uint32_t global_force_up : 1; /*a toggle will trigger a force update, all timers and operators will update their active regs*/ - uint32_t op0_up_en : 1; - uint32_t op0_force_up : 1; /*a toggle will trigger a force update*/ - uint32_t op1_up_en : 1; - uint32_t op1_force_up : 1; /*a toggle will trigger a force update*/ - uint32_t op2_up_en : 1; /*reg update local enable*/ - uint32_t op2_force_up : 1; /*a toggle will trigger a force update*/ - uint32_t reserved8 : 24; - }; - uint32_t val; - } update_cfg; - union { - struct { - uint32_t timer0_stop : 1; - uint32_t timer1_stop : 1; - uint32_t timer2_stop : 1; - uint32_t timer0_tez : 1; - uint32_t timer1_tez : 1; - uint32_t timer2_tez : 1; - uint32_t timer0_tep : 1; - uint32_t timer1_tep : 1; - uint32_t timer2_tep : 1; - uint32_t fault0 : 1; - uint32_t fault1 : 1; - uint32_t fault2 : 1; - uint32_t fault0_clr : 1; - uint32_t fault1_clr : 1; - uint32_t fault2_clr : 1; - uint32_t cmpr0_tea : 1; - uint32_t cmpr1_tea : 1; - uint32_t cmpr2_tea : 1; - uint32_t cmpr0_teb : 1; - uint32_t cmpr1_teb : 1; - uint32_t cmpr2_teb : 1; - uint32_t tz0_cbc : 1; - uint32_t tz1_cbc : 1; - uint32_t tz2_cbc : 1; - uint32_t tz0_ost : 1; - uint32_t tz1_ost : 1; - uint32_t tz2_ost : 1; - uint32_t cap0 : 1; - uint32_t cap1 : 1; - uint32_t cap2 : 1; - uint32_t reserved30 : 2; - }; - uint32_t val; - } int_ena; - union { - struct { - uint32_t timer0_stop : 1; - uint32_t timer1_stop : 1; - uint32_t timer2_stop : 1; - uint32_t timer0_tez : 1; - uint32_t timer1_tez : 1; - uint32_t timer2_tez : 1; - uint32_t timer0_tep : 1; - uint32_t timer1_tep : 1; - uint32_t timer2_tep : 1; - uint32_t fault0 : 1; - uint32_t fault1 : 1; - uint32_t fault2 : 1; - uint32_t fault0_clr : 1; - uint32_t fault1_clr : 1; - uint32_t fault2_clr : 1; - uint32_t cmpr0_tea : 1; - uint32_t cmpr1_tea : 1; - uint32_t cmpr2_tea : 1; - uint32_t cmpr0_teb : 1; - uint32_t cmpr1_teb : 1; - uint32_t cmpr2_teb : 1; - uint32_t tz0_cbc : 1; - uint32_t tz1_cbc : 1; - uint32_t tz2_cbc : 1; - uint32_t tz0_ost : 1; - uint32_t tz1_ost : 1; - uint32_t tz2_ost : 1; - uint32_t cap0 : 1; - uint32_t cap1 : 1; - uint32_t cap2 : 1; - uint32_t reserved30 : 2; - }; - uint32_t val; - } int_raw; - union { - struct { - uint32_t timer0_stop : 1; - uint32_t timer1_stop : 1; - uint32_t timer2_stop : 1; - uint32_t timer0_tez : 1; - uint32_t timer1_tez : 1; - uint32_t timer2_tez : 1; - uint32_t timer0_tep : 1; - uint32_t timer1_tep : 1; - uint32_t timer2_tep : 1; - uint32_t fault0 : 1; - uint32_t fault1 : 1; - uint32_t fault2 : 1; - uint32_t fault0_clr : 1; - uint32_t fault1_clr : 1; - uint32_t fault2_clr : 1; - uint32_t cmpr0_tea : 1; - uint32_t cmpr1_tea : 1; - uint32_t cmpr2_tea : 1; - uint32_t cmpr0_teb : 1; - uint32_t cmpr1_teb : 1; - uint32_t cmpr2_teb : 1; - uint32_t tz0_cbc : 1; - uint32_t tz1_cbc : 1; - uint32_t tz2_cbc : 1; - uint32_t tz0_ost : 1; - uint32_t tz1_ost : 1; - uint32_t tz2_ost : 1; - uint32_t cap0 : 1; - uint32_t cap1 : 1; - uint32_t cap2 : 1; - uint32_t reserved30 : 2; - }; - uint32_t val; - } int_st; - union { - struct { - uint32_t timer0_stop : 1; - uint32_t timer1_stop : 1; - uint32_t timer2_stop : 1; - uint32_t timer0_tez : 1; - uint32_t timer1_tez : 1; - uint32_t timer2_tez : 1; - uint32_t timer0_tep : 1; - uint32_t timer1_tep : 1; - uint32_t timer2_tep : 1; - uint32_t fault0 : 1; - uint32_t fault1 : 1; - uint32_t fault2 : 1; - uint32_t fault0_clr : 1; - uint32_t fault1_clr : 1; - uint32_t fault2_clr : 1; - uint32_t cmpr0_tea : 1; - uint32_t cmpr1_tea : 1; - uint32_t cmpr2_tea : 1; - uint32_t cmpr0_teb : 1; - uint32_t cmpr1_teb : 1; - uint32_t cmpr2_teb : 1; - uint32_t tz0_cbc : 1; - uint32_t tz1_cbc : 1; - uint32_t tz2_cbc : 1; - uint32_t tz0_ost : 1; - uint32_t tz1_ost : 1; - uint32_t tz2_ost : 1; - uint32_t cap0 : 1; - uint32_t cap1 : 1; - uint32_t cap2 : 1; - uint32_t reserved30 : 2; - }; - uint32_t val; - } int_clr; - union { - struct { - uint32_t en : 1; - uint32_t reserved1 : 31; - }; - uint32_t val; - } reg_clk; - union { - struct { - uint32_t date : 28; - uint32_t reserved28 : 4; - }; - uint32_t val; - } version; + /** timer_prescale : R/W; bitpos: [7:0]; default: 0; + * Configure the divisor of PT0_clk, takes effect when PWM timer stops and starts + * agsin. period of PT0_clk = Period of PWM_clk * (PWM_TIMER_PRESCALE + 1) + */ + uint32_t timer_prescale: 8; + /** timer_period : R/W; bitpos: [23:8]; default: 255; + * period shadow register of PWM timer + */ + uint32_t timer_period: 16; + /** timer_period_upmethod : R/W; bitpos: [25:24]; default: 0; + * Update method for active register of PWM timer period, 0: immediate, 1: TEZ, 2: + * sync, 3: TEZ or sync. TEZ here and below means timer equal zero event + */ + uint32_t timer_period_upmethod: 2; + uint32_t reserved_26: 6; + }; + uint32_t val; +} mcpwm_timer_cfg0_reg_t; + +/** Type of timer_cfg1 register + * PWM timer working mode and start/stop control configuration register. + */ +typedef union { + struct { + /** timer_start : R/W/SC; bitpos: [2:0]; default: 0; + * PWM timer start and stop control. 0: if PWM timer starts, then stops at TEZ, 1: + * if timer starts, then stops at TEP, 2: PWM timer starts and runs on, 3: timer + * starts and stops at the next TEZ, 4: timer starts and stops at the next TEP. TEP + * here and below means the event that happens when the timer equals to period + */ + uint32_t timer_start: 3; + /** timer_mod : R/W; bitpos: [4:3]; default: 0; + * PWM timer working mode, 0: freeze, 1: increase mode, 2: decrease mode, 3: up-down + * mode + */ + uint32_t timer_mod: 2; + uint32_t reserved_5: 27; + }; + uint32_t val; +} mcpwm_timer_cfg1_reg_t; + +/** Type of timer_sync register + * PWM timer sync function configuration register. + */ +typedef union { + struct { + /** timer_synci_en : R/W; bitpos: [0]; default: 0; + * When set, timer reloading with phase on sync input event is enabled. + */ + uint32_t timer_synci_en: 1; + /** timer_sync_sw : R/W; bitpos: [1]; default: 0; + * Toggling this bit will trigger a software sync. + */ + uint32_t timer_sync_sw: 1; + /** timer_synco_sel : R/W; bitpos: [3:2]; default: 0; + * PWM timer sync_out selection, 0: sync_in, 1: TEZ, 2: TEP, and sync out will always + * generate when toggling the reg_timer_sync_sw bit + */ + uint32_t timer_synco_sel: 2; + /** timer_phase : R/W; bitpos: [19:4]; default: 0; + * phase for timer reload on sync event + */ + uint32_t timer_phase: 16; + /** timer_phase_direction : R/W; bitpos: [20]; default: 0; + * Configure the PWM timer's direction at the time sync event occurs when timer mode + * is up-down mode: 0-increase,1-decrease + */ + uint32_t timer_phase_direction: 1; + uint32_t reserved_21: 11; + }; + uint32_t val; +} mcpwm_timer_sync_reg_t; + +/** Type of timer_status register + * PWM timer status register. + */ +typedef union { + struct { + /** timer_value : RO; bitpos: [15:0]; default: 0; + * current PWM timer counter value + */ + uint32_t timer_value: 16; + /** timer_direction : RO; bitpos: [16]; default: 0; + * current PWM timer counter direction, 0: increment 1: decrement + */ + uint32_t timer_direction: 1; + uint32_t reserved_17: 15; + }; + uint32_t val; +} mcpwm_timer_status_reg_t; + + +/** Group: Common configuration for MCPWM timers */ +/** Type of timer_synci_cfg register + * Synchronization input selection for three PWM timers. + */ +typedef union { + struct { + /** timer0_syncisel : R/W; bitpos: [2:0]; default: 0; + * select sync input for PWM timer0, 1: PWM timer0 sync_out, 2: PWM timer1 sync_out, + * 3: PWM timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, 6: + * SYNC2 from GPIO matrix, other values: no sync input selected + */ + uint32_t timer0_syncisel: 3; + /** timer1_syncisel : R/W; bitpos: [5:3]; default: 0; + * select sync input for PWM timer1, 1: PWM timer0 sync_out, 2: PWM timer1 sync_out, + * 3: PWM timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, 6: + * SYNC2 from GPIO matrix, other values: no sync input selected + */ + uint32_t timer1_syncisel: 3; + /** timer2_syncisel : R/W; bitpos: [8:6]; default: 0; + * select sync input for PWM timer2, 1: PWM timer0 sync_out, 2: PWM timer1 sync_out, + * 3: PWM timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, 6: + * SYNC2 from GPIO matrix, other values: no sync input selected + */ + uint32_t timer2_syncisel: 3; + /** external_synci0_invert : R/W; bitpos: [9]; default: 0; + * invert SYNC0 from GPIO matrix + */ + uint32_t external_synci0_invert: 1; + /** external_synci1_invert : R/W; bitpos: [10]; default: 0; + * invert SYNC1 from GPIO matrix + */ + uint32_t external_synci1_invert: 1; + /** external_synci2_invert : R/W; bitpos: [11]; default: 0; + * invert SYNC2 from GPIO matrix + */ + uint32_t external_synci2_invert: 1; + uint32_t reserved_12: 20; + }; + uint32_t val; +} mcpwm_timer_synci_cfg_reg_t; + +/** Type of operator_timersel register + * Select specific timer for PWM operators. + */ +typedef union { + struct { + /** operator0_timersel : R/W; bitpos: [1:0]; default: 0; + * Select which PWM timer is the timing reference for PWM operator0, 0: timer0, 1: + * timer1, 2: timer2 + */ + uint32_t operator0_timersel: 2; + /** operator1_timersel : R/W; bitpos: [3:2]; default: 0; + * Select which PWM timer is the timing reference for PWM operator1, 0: timer0, 1: + * timer1, 2: timer2 + */ + uint32_t operator1_timersel: 2; + /** operator2_timersel : R/W; bitpos: [5:4]; default: 0; + * Select which PWM timer is the timing reference for PWM operator2, 0: timer0, 1: + * timer1, 2: timer2 + */ + uint32_t operator2_timersel: 2; + uint32_t reserved_6: 26; + }; + uint32_t val; +} mcpwm_operator_timersel_reg_t; + + +/** Group: MCPWM Operator Configuration and Status */ +/** Type of gen_stmp_cfg register + * Transfer status and update method for time stamp registers A and B + */ +typedef union { + struct { + /** gen_a_upmethod : R/W; bitpos: [3:0]; default: 0; + * Update method for PWM generator time stamp A's active register. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when + * bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + */ + uint32_t gen_a_upmethod: 4; + /** gen_b_upmethod : R/W; bitpos: [7:4]; default: 0; + * Update method for PWM generator time stamp B's active register. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to 1: TEP,when + * bit2 is set to 1: sync, when bit3 is set to 1: disable the update. + */ + uint32_t gen_b_upmethod: 4; + /** gen_a_shdw_full : R/W/WTC/SC; bitpos: [8]; default: 0; + * Set and reset by hardware. If set, PWM generator time stamp A's shadow reg is + * filled and waiting to be transferred to A's active reg. If cleared, A's active reg + * has been updated with shadow register latest value + */ + uint32_t gen_a_shdw_full: 1; + /** gen_b_shdw_full : R/W/WTC/SC; bitpos: [9]; default: 0; + * Set and reset by hardware. If set, PWM generator time stamp B's shadow reg is + * filled and waiting to be transferred to B's active reg. If cleared, B's active reg + * has been updated with shadow register latest value + */ + uint32_t gen_b_shdw_full: 1; + uint32_t reserved_10: 22; + }; + uint32_t val; +} mcpwm_gen_stmp_cfg_reg_t; + +/** Type of gen_tstmp register + * PWM generator shadow register for timer stamp + */ +typedef union { + struct { + /** gen : R/W; bitpos: [15:0]; default: 0; + * PWM generator time stamp's shadow register + */ + uint32_t gen: 16; + uint32_t reserved_16: 16; + }; + uint32_t val; +} mcpwm_gen_tstmp_reg_t; + +/** Type of gen_cfg0 register + * PWM generator event T0 and T1 handling + */ +typedef union { + struct { + /** gen_cfg_upmethod : R/W; bitpos: [3:0]; default: 0; + * Update method for PWM generator's active register of configuration. When all bits + * are set to 0: immediately, when bit0 is set to 1: TEZ, when bit1 is set to + * 1:TEP,when bit2 is set to 1:sync,when bit3 is set to 1:disable the update + */ + uint32_t gen_cfg_upmethod: 4; + /** gen_t0_sel : R/W; bitpos: [6:4]; default: 0; + * Source selection for PWM generator event_t0, take effect immediately, 0: + * fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + */ + uint32_t gen_t0_sel: 3; + /** gen_t1_sel : R/W; bitpos: [9:7]; default: 0; + * Source selection for PWM generator event_t1, take effect immediately, 0: + * fault_event0, 1: fault_event1, 2: fault_event2, 3: sync_taken, 4: none + */ + uint32_t gen_t1_sel: 3; + uint32_t reserved_10: 22; + }; + uint32_t val; +} mcpwm_gen_cfg0_reg_t; + +/** Type of gen_force register + * Permissives to force PWM0A and PWM0B outputs by software + */ +typedef union { + struct { + /** gen_cntuforce_upmethod : R/W; bitpos: [5:0]; default: 32; + * Updating method for continuous software force of PWM generator0. When all bits are + * set to 0: immediately, when bit0 is set to 1: TEZ,,when bit1 is set to 1: TEP, when + * bit2 is set to 1: TEA, when bit3 is set to 1: TEB, when bit4 is set to 1: sync, + * when bit5 is set to 1: disable update. (TEA/B here and below means an event + * generated when the timer's value equals to that of register A/B.) + */ + uint32_t gen_cntuforce_upmethod: 6; + /** gen_a_cntuforce_mode : R/W; bitpos: [7:6]; default: 0; + * Continuous software force mode for PWM0A. 0: disabled, 1: low, 2: high, 3: disabled + */ + uint32_t gen_a_cntuforce_mode: 2; + /** gen_b_cntuforce_mode : R/W; bitpos: [9:8]; default: 0; + * Continuous software force mode for PWM0B. 0: disabled, 1: low, 2: high, 3: disabled + */ + uint32_t gen_b_cntuforce_mode: 2; + /** gen_a_nciforce : R/W; bitpos: [10]; default: 0; + * Trigger of non-continuous immediate software-force event for PWM0A, a toggle will + * trigger a force event. + */ + uint32_t gen_a_nciforce: 1; + /** gen_a_nciforce_mode : R/W; bitpos: [12:11]; default: 0; + * non-continuous immediate software force mode for PWM0A, 0: disabled, 1: low, 2: + * high, 3: disabled + */ + uint32_t gen_a_nciforce_mode: 2; + /** gen_b_nciforce : R/W; bitpos: [13]; default: 0; + * Trigger of non-continuous immediate software-force event for PWM0B, a toggle will + * trigger a force event. + */ + uint32_t gen_b_nciforce: 1; + /** gen_b_nciforce_mode : R/W; bitpos: [15:14]; default: 0; + * non-continuous immediate software force mode for PWM0B, 0: disabled, 1: low, 2: + * high, 3: disabled + */ + uint32_t gen_b_nciforce_mode: 2; + uint32_t reserved_16: 16; + }; + uint32_t val; +} mcpwm_gen_force_reg_t; + +/** Type of generator register + * Actions triggered by events on PWM0A + */ +typedef union { + struct { + /** gen_utez : R/W; bitpos: [1:0]; default: 0; + * Action on PWM0A triggered by event TEZ when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_utez: 2; + /** gen_utep : R/W; bitpos: [3:2]; default: 0; + * Action on PWM0A triggered by event TEP when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_utep: 2; + /** gen_utea : R/W; bitpos: [5:4]; default: 0; + * Action on PWM0A triggered by event TEA when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_utea: 2; + /** gen_uteb : R/W; bitpos: [7:6]; default: 0; + * Action on PWM0A triggered by event TEB when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_uteb: 2; + /** gen_ut0 : R/W; bitpos: [9:8]; default: 0; + * Action on PWM0A triggered by event_t0 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_ut0: 2; + /** gen_ut1 : R/W; bitpos: [11:10]; default: 0; + * Action on PWM0A triggered by event_t1 when timer increasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_ut1: 2; + /** gen_dtez : R/W; bitpos: [13:12]; default: 0; + * Action on PWM0A triggered by event TEZ when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_dtez: 2; + /** gen_dtep : R/W; bitpos: [15:14]; default: 0; + * Action on PWM0A triggered by event TEP when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_dtep: 2; + /** gen_dtea : R/W; bitpos: [17:16]; default: 0; + * Action on PWM0A triggered by event TEA when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_dtea: 2; + /** gen_dteb : R/W; bitpos: [19:18]; default: 0; + * Action on PWM0A triggered by event TEB when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_dteb: 2; + /** gen_dt0 : R/W; bitpos: [21:20]; default: 0; + * Action on PWM0A triggered by event_t0 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_dt0: 2; + /** gen_dt1 : R/W; bitpos: [23:22]; default: 0; + * Action on PWM0A triggered by event_t1 when timer decreasing. 0: no change, 1: low, + * 2: high, 3: toggle + */ + uint32_t gen_dt1: 2; + uint32_t reserved_24: 8; + }; + uint32_t val; +} mcpwm_gen_reg_t; + +/** Type of dt_cfg register + * PWM generator dead time type selection and configuration + */ +typedef union { + struct { + /** dt_fed_upmethod : R/W; bitpos: [3:0]; default: 0; + * Update method for FED (rising edge delay) active register. 0: immediate, when bit0 + * is set to 1: tez, when bit1 is set to 1:tep, when bit2 is set to 1: sync, when + * bit3 is set to 1: disable the update + */ + uint32_t dt_fed_upmethod: 4; + /** dt_red_upmethod : R/W; bitpos: [7:4]; default: 0; + * Update method for RED (rising edge delay) active register. 0: immediate, when bit0 + * is set to 1: tez, when bit1 is set to 1:tep, when bit2 is set to 1: sync, when + * bit3 is set to 1: disable the update + */ + uint32_t dt_red_upmethod: 4; + /** dt_deb_mode : R/W; bitpos: [8]; default: 0; + * S8 in table, dual-edge B mode, 0: fed/red take effect on different path separately, + * 1: fed/red take effect on B path, A out is in bypass or dulpB mode + */ + uint32_t dt_deb_mode: 1; + /** dt_a_outswap : R/W; bitpos: [9]; default: 0; + * S6 in table + */ + uint32_t dt_a_outswap: 1; + /** dt_b_outswap : R/W; bitpos: [10]; default: 0; + * S7 in table + */ + uint32_t dt_b_outswap: 1; + /** dt_red_insel : R/W; bitpos: [11]; default: 0; + * S4 in table + */ + uint32_t dt_red_insel: 1; + /** dt_fed_insel : R/W; bitpos: [12]; default: 0; + * S5 in table + */ + uint32_t dt_fed_insel: 1; + /** dt_red_outinvert : R/W; bitpos: [13]; default: 0; + * S2 in table + */ + uint32_t dt_red_outinvert: 1; + /** dt_fed_outinvert : R/W; bitpos: [14]; default: 0; + * S3 in table + */ + uint32_t dt_fed_outinvert: 1; + /** dt_a_outbypass : R/W; bitpos: [15]; default: 1; + * S1 in table + */ + uint32_t dt_a_outbypass: 1; + /** dt_b_outbypass : R/W; bitpos: [16]; default: 1; + * S0 in table + */ + uint32_t dt_b_outbypass: 1; + /** dt_clk_sel : R/W; bitpos: [17]; default: 0; + * Dead time clock selection. 0: PWM_clk, 1: PT_clk + */ + uint32_t dt_clk_sel: 1; + uint32_t reserved_18: 14; + }; + uint32_t val; +} mcpwm_dt_cfg_reg_t; + +/** Type of dt_fed_cfg register + * PWM generator shadow register for falling edge delay (FED). + */ +typedef union { + struct { + /** dt_fed : R/W; bitpos: [15:0]; default: 0; + * Shadow register for FED + */ + uint32_t dt_fed: 16; + uint32_t reserved_16: 16; + }; + uint32_t val; +} mcpwm_dt_fed_cfg_reg_t; + +/** Type of dt_red_cfg register + * PWM generator shadow register for rising edge delay (RED). + */ +typedef union { + struct { + /** dt_red : R/W; bitpos: [15:0]; default: 0; + * Shadow register for RED + */ + uint32_t dt_red: 16; + uint32_t reserved_16: 16; + }; + uint32_t val; +} mcpwm_dt_red_cfg_reg_t; + +/** Type of carrier_cfg register + * PWM generator carrier enable and configuratoin + */ +typedef union { + struct { + /** carrier_en : R/W; bitpos: [0]; default: 0; + * When set, carrier function is enabled. When cleared, carrier is bypassed + */ + uint32_t carrier_en: 1; + /** carrier_prescale : R/W; bitpos: [4:1]; default: 0; + * PWM carrier clock (PC_clk) prescale value. Period of PC_clk = period of PWM_clk * + * (PWM_CARRIER_PRESCALE + 1) + */ + uint32_t carrier_prescale: 4; + /** carrier_duty : R/W; bitpos: [7:5]; default: 0; + * carrier duty selection. Duty = PWM_CARRIER_DUTY / 8 + */ + uint32_t carrier_duty: 3; + /** carrier_oshtwth : R/W; bitpos: [11:8]; default: 0; + * width of the first pulse in number of periods of the carrier + */ + uint32_t carrier_oshtwth: 4; + /** carrier_out_invert : R/W; bitpos: [12]; default: 0; + * when set, invert the output of PWM0A and PWM0B for this submodule + */ + uint32_t carrier_out_invert: 1; + /** carrier_in_invert : R/W; bitpos: [13]; default: 0; + * when set, invert the input of PWM0A and PWM0B for this submodule + */ + uint32_t carrier_in_invert: 1; + uint32_t reserved_14: 18; + }; + uint32_t val; +} mcpwm_carrier_cfg_reg_t; + +/** Type of fh_cfg0 register + * Actions on PWM0A and PWM0B trip events + */ +typedef union { + struct { + /** fh_sw_cbc : R/W; bitpos: [0]; default: 0; + * Enable register for software force cycle-by-cycle mode action. 0: disable, 1: enable + */ + uint32_t fh_sw_cbc: 1; + /** fh_f2_cbc : R/W; bitpos: [1]; default: 0; + * fault_event2 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ + uint32_t fh_f2_cbc: 1; + /** fh_f1_cbc : R/W; bitpos: [2]; default: 0; + * fault_event1 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ + uint32_t fh_f1_cbc: 1; + /** fh_f0_cbc : R/W; bitpos: [3]; default: 0; + * fault_event0 will trigger cycle-by-cycle mode action. 0: disable, 1: enable + */ + uint32_t fh_f0_cbc: 1; + /** fh_sw_ost : R/W; bitpos: [4]; default: 0; + * Enable register for software force one-shot mode action. 0: disable, 1: enable + */ + uint32_t fh_sw_ost: 1; + /** fh_f2_ost : R/W; bitpos: [5]; default: 0; + * fault_event2 will trigger one-shot mode action. 0: disable, 1: enable + */ + uint32_t fh_f2_ost: 1; + /** fh_f1_ost : R/W; bitpos: [6]; default: 0; + * fault_event1 will trigger one-shot mode action. 0: disable, 1: enable + */ + uint32_t fh_f1_ost: 1; + /** fh_f0_ost : R/W; bitpos: [7]; default: 0; + * fault_event0 will trigger one-shot mode action. 0: disable, 1: enable + */ + uint32_t fh_f0_ost: 1; + /** fh_a_cbc_d : R/W; bitpos: [9:8]; default: 0; + * Cycle-by-cycle mode action on PWM0A when fault event occurs and timer is + * decreasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ + uint32_t fh_a_cbc_d: 2; + /** fh_a_cbc_u : R/W; bitpos: [11:10]; default: 0; + * Cycle-by-cycle mode action on PWM0A when fault event occurs and timer is + * increasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ + uint32_t fh_a_cbc_u: 2; + /** fh_a_ost_d : R/W; bitpos: [13:12]; default: 0; + * One-shot mode action on PWM0A when fault event occurs and timer is decreasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ + uint32_t fh_a_ost_d: 2; + /** fh_a_ost_u : R/W; bitpos: [15:14]; default: 0; + * One-shot mode action on PWM0A when fault event occurs and timer is increasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ + uint32_t fh_a_ost_u: 2; + /** fh_b_cbc_d : R/W; bitpos: [17:16]; default: 0; + * Cycle-by-cycle mode action on PWM0B when fault event occurs and timer is + * decreasing. 0: do nothing, 1: force low, 2: force high, 3: toggle + */ + uint32_t fh_b_cbc_d: 2; + /** fh_b_cbc_u : R/W; bitpos: [19:18]; default: 0; + * Cycle-by-cycle mode action on PWM0B when fault event occurs and timer is + * increasing. 0: do nothing,1: force low, 2: force high, 3: toggle + */ + uint32_t fh_b_cbc_u: 2; + /** fh_b_ost_d : R/W; bitpos: [21:20]; default: 0; + * One-shot mode action on PWM0B when fault event occurs and timer is decreasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ + uint32_t fh_b_ost_d: 2; + /** fh_b_ost_u : R/W; bitpos: [23:22]; default: 0; + * One-shot mode action on PWM0B when fault event occurs and timer is increasing. 0: + * do nothing, 1: force low, 2: force high, 3: toggle + */ + uint32_t fh_b_ost_u: 2; + uint32_t reserved_24: 8; + }; + uint32_t val; +} mcpwm_fh_cfg0_reg_t; + +/** Type of fh_cfg1 register + * Software triggers for fault handler actions + */ +typedef union { + struct { + /** fh_clr_ost : R/W; bitpos: [0]; default: 0; + * a rising edge will clear on going one-shot mode action + */ + uint32_t fh_clr_ost: 1; + /** fh_cbcpulse : R/W; bitpos: [2:1]; default: 0; + * cycle-by-cycle mode action refresh moment selection. When bit0 is set to 1: TEZ, + * when bit1 is set to 1:TEP, when bit0 and bit1 both set to 0: stop refresh, when + * bit0 and bit1 both set to 1: refresh at TEP/TEZ + */ + uint32_t fh_cbcpulse: 2; + /** fh_force_cbc : R/W; bitpos: [3]; default: 0; + * a toggle trigger a cycle-by-cycle mode action + */ + uint32_t fh_force_cbc: 1; + /** fh_force_ost : R/W; bitpos: [4]; default: 0; + * a toggle (software negate its value) triggers a one-shot mode action + */ + uint32_t fh_force_ost: 1; + uint32_t reserved_5: 27; + }; + uint32_t val; +} mcpwm_fh_cfg1_reg_t; + +/** Type of fh_status register + * Status of fault events. + */ +typedef union { + struct { + /** fh_cbc_on : RO; bitpos: [0]; default: 0; + * Set and reset by hardware. If set, a cycle-by-cycle mode action is on going + */ + uint32_t fh_cbc_on: 1; + /** fh_ost_on : RO; bitpos: [1]; default: 0; + * Set and reset by hardware. If set, an one-shot mode action is on going + */ + uint32_t fh_ost_on: 1; + uint32_t reserved_2: 30; + }; + uint32_t val; +} mcpwm_fh_status_reg_t; + +/** Group: Fault Detection Configuration and Status */ +/** Type of fault_detect register + * Fault detection configuration and status + */ +typedef union { + struct { + /** f0_en : R/W; bitpos: [0]; default: 0; + * When set, fault_event0 generation is enabled + */ + uint32_t f0_en: 1; + /** f1_en : R/W; bitpos: [1]; default: 0; + * When set, fault_event1 generation is enabled + */ + uint32_t f1_en: 1; + /** f2_en : R/W; bitpos: [2]; default: 0; + * When set, fault_event2 generation is enabled + */ + uint32_t f2_en: 1; + /** f0_pole : R/W; bitpos: [3]; default: 0; + * Set fault_event0 trigger polarity on FAULT2 source from GPIO matrix. 0: level low, + * 1: level high + */ + uint32_t f0_pole: 1; + /** f1_pole : R/W; bitpos: [4]; default: 0; + * Set fault_event1 trigger polarity on FAULT2 source from GPIO matrix. 0: level low, + * 1: level high + */ + uint32_t f1_pole: 1; + /** f2_pole : R/W; bitpos: [5]; default: 0; + * Set fault_event2 trigger polarity on FAULT2 source from GPIO matrix. 0: level low, + * 1: level high + */ + uint32_t f2_pole: 1; + /** event_f0 : RO; bitpos: [6]; default: 0; + * Set and reset by hardware. If set, fault_event0 is on going + */ + uint32_t event_f0: 1; + /** event_f1 : RO; bitpos: [7]; default: 0; + * Set and reset by hardware. If set, fault_event1 is on going + */ + uint32_t event_f1: 1; + /** event_f2 : RO; bitpos: [8]; default: 0; + * Set and reset by hardware. If set, fault_event2 is on going + */ + uint32_t event_f2: 1; + uint32_t reserved_9: 23; + }; + uint32_t val; +} mcpwm_fault_detect_reg_t; + + +/** Group: Capture Configuration and Status */ +/** Type of cap_timer_cfg register + * Configure capture timer + */ +typedef union { + struct { + /** cap_timer_en : R/W; bitpos: [0]; default: 0; + * When set, capture timer incrementing under APB_clk is enabled. + */ + uint32_t cap_timer_en: 1; + /** cap_synci_en : R/W; bitpos: [1]; default: 0; + * When set, capture timer sync is enabled. + */ + uint32_t cap_synci_en: 1; + /** cap_synci_sel : R/W; bitpos: [4:2]; default: 0; + * capture module sync input selection. 0: none, 1: timer0 sync_out, 2: timer1 + * sync_out, 3: timer2 sync_out, 4: SYNC0 from GPIO matrix, 5: SYNC1 from GPIO matrix, + * 6: SYNC2 from GPIO matrix + */ + uint32_t cap_synci_sel: 3; + /** cap_sync_sw : WT; bitpos: [5]; default: 0; + * When reg_cap_synci_en is 1, write 1 will trigger a capture timer sync, capture + * timer is loaded with value in phase register. + */ + uint32_t cap_sync_sw: 1; + uint32_t reserved_6: 26; + }; + uint32_t val; +} mcpwm_cap_timer_cfg_reg_t; + +/** Type of cap_timer_phase register + * Phase for capture timer sync + */ +typedef union { + struct { + /** cap_timer_phase : R/W; bitpos: [31:0]; default: 0; + * Phase value for capture timer sync operation. + */ + uint32_t cap_timer_phase: 32; + }; + uint32_t val; +} mcpwm_cap_timer_phase_reg_t; + +/** Type of cap_chn_cfg register + * Capture channel 0 configuration and enable + */ +typedef union { + struct { + /** capn_en : R/W; bitpos: [0]; default: 0; + * When set, capture on channel 0 is enabled + */ + uint32_t capn_en: 1; + /** capn_mode : R/W; bitpos: [2:1]; default: 0; + * Edge of capture on channel 0 after prescaling. When bit0 is set to 1: enable + * capture on the negative edge, When bit1 is set to 1: enable capture on the positive + * edge. + */ + 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 + + * 1 + */ + uint32_t capn_prescale: 8; + /** capn_in_invert : R/W; bitpos: [11]; default: 0; + * when set, CAPn form GPIO matrix is inverted before prescale + */ + uint32_t capn_in_invert: 1; + /** capn_sw : WT; bitpos: [12]; default: 0; + * Write 1 will trigger a software forced capture on channel 0 + */ + uint32_t capn_sw: 1; + uint32_t reserved_13: 19; + }; + uint32_t val; +} mcpwm_cap_chn_cfg_reg_t; + +/** Type of cap_chn register + * chn capture value status register + */ +typedef union { + struct { + /** capn_value : RO; bitpos: [31:0]; default: 0; + * Value of last capture on channel n + */ + uint32_t capn_value: 32; + }; + uint32_t val; +} mcpwm_cap_chn_reg_t; + +/** Type of cap_status register + * Edge of last capture trigger + */ +typedef union { + struct { + /** cap0_edge : RO; bitpos: [0]; default: 0; + * Edge of last capture trigger on channel 0, 0: posedge, 1: negedge + */ + uint32_t cap0_edge: 1; + /** cap1_edge : RO; bitpos: [1]; default: 0; + * Edge of last capture trigger on channel 1, 0: posedge, 1: negedge + */ + uint32_t cap1_edge: 1; + /** cap2_edge : RO; bitpos: [2]; default: 0; + * Edge of last capture trigger on channel 2, 0: posedge, 1: negedge + */ + uint32_t cap2_edge: 1; + uint32_t reserved_3: 29; + }; + uint32_t val; +} mcpwm_cap_status_reg_t; + + +/** Group: Enable update of active registers */ +/** Type of update_cfg register + * Enable update. + */ +typedef union { + struct { + /** global_up_en : R/W; bitpos: [0]; default: 1; + * The global enable of update of all active registers in MCPWM module + */ + uint32_t global_up_en: 1; + /** global_force_up : R/W; bitpos: [1]; default: 0; + * a toggle (software invert its value) will trigger a forced update of all active + * registers in MCPWM module + */ + uint32_t global_force_up: 1; + /** op0_up_en : R/W; bitpos: [2]; default: 1; + * When set and PWM_GLOBAL_UP_EN is set, update of active registers in PWM operator 0 + * are enabled + */ + uint32_t op0_up_en: 1; + /** op0_force_up : R/W; bitpos: [3]; default: 0; + * a toggle (software invert its value) will trigger a forced update of active + * registers in PWM operator 0 + */ + uint32_t op0_force_up: 1; + /** op1_up_en : R/W; bitpos: [4]; default: 1; + * When set and PWM_GLOBAL_UP_EN is set, update of active registers in PWM operator 1 + * are enabled + */ + uint32_t op1_up_en: 1; + /** op1_force_up : R/W; bitpos: [5]; default: 0; + * a toggle (software invert its value) will trigger a forced update of active + * registers in PWM operator 1 + */ + uint32_t op1_force_up: 1; + /** op2_up_en : R/W; bitpos: [6]; default: 1; + * When set and PWM_GLOBAL_UP_EN is set, update of active registers in PWM operator 2 + * are enabled + */ + uint32_t op2_up_en: 1; + /** op2_force_up : R/W; bitpos: [7]; default: 0; + * a toggle (software invert its value) will trigger a forced update of active + * registers in PWM operator 2 + */ + uint32_t op2_force_up: 1; + uint32_t reserved_8: 24; + }; + uint32_t val; +} mcpwm_update_cfg_reg_t; + + +/** Group: Manage Interrupts */ +/** Type of int_ena register + * Interrupt enable bits + */ +typedef union { + struct { + /** timer0_stop_int_ena : R/W; bitpos: [0]; default: 0; + * The enable bit for the interrupt triggered when the timer 0 stops. + */ + uint32_t timer0_stop_int_ena: 1; + /** timer1_stop_int_ena : R/W; bitpos: [1]; default: 0; + * The enable bit for the interrupt triggered when the timer 1 stops. + */ + uint32_t timer1_stop_int_ena: 1; + /** timer2_stop_int_ena : R/W; bitpos: [2]; default: 0; + * The enable bit for the interrupt triggered when the timer 2 stops. + */ + uint32_t timer2_stop_int_ena: 1; + /** timer0_tez_int_ena : R/W; bitpos: [3]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 0 TEZ event. + */ + uint32_t timer0_tez_int_ena: 1; + /** timer1_tez_int_ena : R/W; bitpos: [4]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 1 TEZ event. + */ + uint32_t timer1_tez_int_ena: 1; + /** timer2_tez_int_ena : R/W; bitpos: [5]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 2 TEZ event. + */ + uint32_t timer2_tez_int_ena: 1; + /** timer0_tep_int_ena : R/W; bitpos: [6]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 0 TEP event. + */ + uint32_t timer0_tep_int_ena: 1; + /** timer1_tep_int_ena : R/W; bitpos: [7]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 1 TEP event. + */ + uint32_t timer1_tep_int_ena: 1; + /** timer2_tep_int_ena : R/W; bitpos: [8]; default: 0; + * The enable bit for the interrupt triggered by a PWM timer 2 TEP event. + */ + uint32_t timer2_tep_int_ena: 1; + /** fault0_int_ena : R/W; bitpos: [9]; default: 0; + * The enable bit for the interrupt triggered when fault_event0 starts. + */ + uint32_t fault0_int_ena: 1; + /** fault1_int_ena : R/W; bitpos: [10]; default: 0; + * The enable bit for the interrupt triggered when fault_event1 starts. + */ + uint32_t fault1_int_ena: 1; + /** fault2_int_ena : R/W; bitpos: [11]; default: 0; + * The enable bit for the interrupt triggered when fault_event2 starts. + */ + uint32_t fault2_int_ena: 1; + /** fault0_clr_int_ena : R/W; bitpos: [12]; default: 0; + * The enable bit for the interrupt triggered when fault_event0 ends. + */ + uint32_t fault0_clr_int_ena: 1; + /** fault1_clr_int_ena : R/W; bitpos: [13]; default: 0; + * The enable bit for the interrupt triggered when fault_event1 ends. + */ + uint32_t fault1_clr_int_ena: 1; + /** fault2_clr_int_ena : R/W; bitpos: [14]; default: 0; + * The enable bit for the interrupt triggered when fault_event2 ends. + */ + uint32_t fault2_clr_int_ena: 1; + /** op0_tea_int_ena : R/W; bitpos: [15]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 0 TEA event + */ + uint32_t op0_tea_int_ena: 1; + /** op1_tea_int_ena : R/W; bitpos: [16]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 1 TEA event + */ + uint32_t op1_tea_int_ena: 1; + /** op2_tea_int_ena : R/W; bitpos: [17]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 2 TEA event + */ + uint32_t op2_tea_int_ena: 1; + /** op0_teb_int_ena : R/W; bitpos: [18]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 0 TEB event + */ + uint32_t op0_teb_int_ena: 1; + /** op1_teb_int_ena : R/W; bitpos: [19]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 1 TEB event + */ + uint32_t op1_teb_int_ena: 1; + /** op2_teb_int_ena : R/W; bitpos: [20]; default: 0; + * The enable bit for the interrupt triggered by a PWM operator 2 TEB event + */ + uint32_t op2_teb_int_ena: 1; + /** fh0_cbc_int_ena : R/W; bitpos: [21]; default: 0; + * The enable bit for the interrupt triggered by a cycle-by-cycle mode action on PWM0. + */ + uint32_t fh0_cbc_int_ena: 1; + /** fh1_cbc_int_ena : R/W; bitpos: [22]; default: 0; + * The enable bit for the interrupt triggered by a cycle-by-cycle mode action on PWM1. + */ + uint32_t fh1_cbc_int_ena: 1; + /** fh2_cbc_int_ena : R/W; bitpos: [23]; default: 0; + * The enable bit for the interrupt triggered by a cycle-by-cycle mode action on PWM2. + */ + uint32_t fh2_cbc_int_ena: 1; + /** fh0_ost_int_ena : R/W; bitpos: [24]; default: 0; + * The enable bit for the interrupt triggered by a one-shot mode action on PWM0. + */ + uint32_t fh0_ost_int_ena: 1; + /** fh1_ost_int_ena : R/W; bitpos: [25]; default: 0; + * The enable bit for the interrupt triggered by a one-shot mode action on PWM1. + */ + uint32_t fh1_ost_int_ena: 1; + /** fh2_ost_int_ena : R/W; bitpos: [26]; default: 0; + * The enable bit for the interrupt triggered by a one-shot mode action on PWM2. + */ + uint32_t fh2_ost_int_ena: 1; + /** cap0_int_ena : R/W; bitpos: [27]; default: 0; + * The enable bit for the interrupt triggered by capture on channel 0. + */ + uint32_t cap0_int_ena: 1; + /** cap1_int_ena : R/W; bitpos: [28]; default: 0; + * The enable bit for the interrupt triggered by capture on channel 1. + */ + uint32_t cap1_int_ena: 1; + /** cap2_int_ena : R/W; bitpos: [29]; default: 0; + * The enable bit for the interrupt triggered by capture on channel 2. + */ + uint32_t cap2_int_ena: 1; + uint32_t reserved_30: 2; + }; + uint32_t val; +} mcpwm_int_ena_reg_t; + +/** Type of int_raw register + * Raw interrupt status + */ +typedef union { + struct { + /** timer0_stop_int_raw : R/WTC/SS; bitpos: [0]; default: 0; + * The raw status bit for the interrupt triggered when the timer 0 stops. + */ + uint32_t timer0_stop_int_raw: 1; + /** timer1_stop_int_raw : R/WTC/SS; bitpos: [1]; default: 0; + * The raw status bit for the interrupt triggered when the timer 1 stops. + */ + uint32_t timer1_stop_int_raw: 1; + /** timer2_stop_int_raw : R/WTC/SS; bitpos: [2]; default: 0; + * The raw status bit for the interrupt triggered when the timer 2 stops. + */ + uint32_t timer2_stop_int_raw: 1; + /** timer0_tez_int_raw : R/WTC/SS; bitpos: [3]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 0 TEZ event. + */ + uint32_t timer0_tez_int_raw: 1; + /** timer1_tez_int_raw : R/WTC/SS; bitpos: [4]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 1 TEZ event. + */ + uint32_t timer1_tez_int_raw: 1; + /** timer2_tez_int_raw : R/WTC/SS; bitpos: [5]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 2 TEZ event. + */ + uint32_t timer2_tez_int_raw: 1; + /** timer0_tep_int_raw : R/WTC/SS; bitpos: [6]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 0 TEP event. + */ + uint32_t timer0_tep_int_raw: 1; + /** timer1_tep_int_raw : R/WTC/SS; bitpos: [7]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 1 TEP event. + */ + uint32_t timer1_tep_int_raw: 1; + /** timer2_tep_int_raw : R/WTC/SS; bitpos: [8]; default: 0; + * The raw status bit for the interrupt triggered by a PWM timer 2 TEP event. + */ + uint32_t timer2_tep_int_raw: 1; + /** fault0_int_raw : R/WTC/SS; bitpos: [9]; default: 0; + * The raw status bit for the interrupt triggered when fault_event0 starts. + */ + uint32_t fault0_int_raw: 1; + /** fault1_int_raw : R/WTC/SS; bitpos: [10]; default: 0; + * The raw status bit for the interrupt triggered when fault_event1 starts. + */ + uint32_t fault1_int_raw: 1; + /** fault2_int_raw : R/WTC/SS; bitpos: [11]; default: 0; + * The raw status bit for the interrupt triggered when fault_event2 starts. + */ + uint32_t fault2_int_raw: 1; + /** fault0_clr_int_raw : R/WTC/SS; bitpos: [12]; default: 0; + * The raw status bit for the interrupt triggered when fault_event0 ends. + */ + uint32_t fault0_clr_int_raw: 1; + /** fault1_clr_int_raw : R/WTC/SS; bitpos: [13]; default: 0; + * The raw status bit for the interrupt triggered when fault_event1 ends. + */ + uint32_t fault1_clr_int_raw: 1; + /** fault2_clr_int_raw : R/WTC/SS; bitpos: [14]; default: 0; + * The raw status bit for the interrupt triggered when fault_event2 ends. + */ + uint32_t fault2_clr_int_raw: 1; + /** op0_tea_int_raw : R/WTC/SS; bitpos: [15]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 0 TEA event + */ + uint32_t op0_tea_int_raw: 1; + /** op1_tea_int_raw : R/WTC/SS; bitpos: [16]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 1 TEA event + */ + uint32_t op1_tea_int_raw: 1; + /** op2_tea_int_raw : R/WTC/SS; bitpos: [17]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 2 TEA event + */ + uint32_t op2_tea_int_raw: 1; + /** op0_teb_int_raw : R/WTC/SS; bitpos: [18]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 0 TEB event + */ + uint32_t op0_teb_int_raw: 1; + /** op1_teb_int_raw : R/WTC/SS; bitpos: [19]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 1 TEB event + */ + uint32_t op1_teb_int_raw: 1; + /** op2_teb_int_raw : R/WTC/SS; bitpos: [20]; default: 0; + * The raw status bit for the interrupt triggered by a PWM operator 2 TEB event + */ + uint32_t op2_teb_int_raw: 1; + /** fh0_cbc_int_raw : R/WTC/SS; bitpos: [21]; default: 0; + * The raw status bit for the interrupt triggered by a cycle-by-cycle mode action on + * PWM0. + */ + uint32_t fh0_cbc_int_raw: 1; + /** fh1_cbc_int_raw : R/WTC/SS; bitpos: [22]; default: 0; + * The raw status bit for the interrupt triggered by a cycle-by-cycle mode action on + * PWM1. + */ + uint32_t fh1_cbc_int_raw: 1; + /** fh2_cbc_int_raw : R/WTC/SS; bitpos: [23]; default: 0; + * The raw status bit for the interrupt triggered by a cycle-by-cycle mode action on + * PWM2. + */ + uint32_t fh2_cbc_int_raw: 1; + /** fh0_ost_int_raw : R/WTC/SS; bitpos: [24]; default: 0; + * The raw status bit for the interrupt triggered by a one-shot mode action on PWM0. + */ + uint32_t fh0_ost_int_raw: 1; + /** fh1_ost_int_raw : R/WTC/SS; bitpos: [25]; default: 0; + * The raw status bit for the interrupt triggered by a one-shot mode action on PWM1. + */ + uint32_t fh1_ost_int_raw: 1; + /** fh2_ost_int_raw : R/WTC/SS; bitpos: [26]; default: 0; + * The raw status bit for the interrupt triggered by a one-shot mode action on PWM2. + */ + uint32_t fh2_ost_int_raw: 1; + /** cap0_int_raw : R/WTC/SS; bitpos: [27]; default: 0; + * The raw status bit for the interrupt triggered by capture on channel 0. + */ + uint32_t cap0_int_raw: 1; + /** cap1_int_raw : R/WTC/SS; bitpos: [28]; default: 0; + * The raw status bit for the interrupt triggered by capture on channel 1. + */ + uint32_t cap1_int_raw: 1; + /** cap2_int_raw : R/WTC/SS; bitpos: [29]; default: 0; + * The raw status bit for the interrupt triggered by capture on channel 2. + */ + uint32_t cap2_int_raw: 1; + uint32_t reserved_30: 2; + }; + uint32_t val; +} mcpwm_int_raw_reg_t; + +/** Type of int_st register + * Masked interrupt status + */ +typedef union { + struct { + /** timer0_stop_int_st : RO; bitpos: [0]; default: 0; + * The masked status bit for the interrupt triggered when the timer 0 stops. + */ + uint32_t timer0_stop_int_st: 1; + /** timer1_stop_int_st : RO; bitpos: [1]; default: 0; + * The masked status bit for the interrupt triggered when the timer 1 stops. + */ + uint32_t timer1_stop_int_st: 1; + /** timer2_stop_int_st : RO; bitpos: [2]; default: 0; + * The masked status bit for the interrupt triggered when the timer 2 stops. + */ + uint32_t timer2_stop_int_st: 1; + /** timer0_tez_int_st : RO; bitpos: [3]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 0 TEZ event. + */ + uint32_t timer0_tez_int_st: 1; + /** timer1_tez_int_st : RO; bitpos: [4]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 1 TEZ event. + */ + uint32_t timer1_tez_int_st: 1; + /** timer2_tez_int_st : RO; bitpos: [5]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 2 TEZ event. + */ + uint32_t timer2_tez_int_st: 1; + /** timer0_tep_int_st : RO; bitpos: [6]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 0 TEP event. + */ + uint32_t timer0_tep_int_st: 1; + /** timer1_tep_int_st : RO; bitpos: [7]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 1 TEP event. + */ + uint32_t timer1_tep_int_st: 1; + /** timer2_tep_int_st : RO; bitpos: [8]; default: 0; + * The masked status bit for the interrupt triggered by a PWM timer 2 TEP event. + */ + uint32_t timer2_tep_int_st: 1; + /** fault0_int_st : RO; bitpos: [9]; default: 0; + * The masked status bit for the interrupt triggered when fault_event0 starts. + */ + uint32_t fault0_int_st: 1; + /** fault1_int_st : RO; bitpos: [10]; default: 0; + * The masked status bit for the interrupt triggered when fault_event1 starts. + */ + uint32_t fault1_int_st: 1; + /** fault2_int_st : RO; bitpos: [11]; default: 0; + * The masked status bit for the interrupt triggered when fault_event2 starts. + */ + uint32_t fault2_int_st: 1; + /** fault0_clr_int_st : RO; bitpos: [12]; default: 0; + * The masked status bit for the interrupt triggered when fault_event0 ends. + */ + uint32_t fault0_clr_int_st: 1; + /** fault1_clr_int_st : RO; bitpos: [13]; default: 0; + * The masked status bit for the interrupt triggered when fault_event1 ends. + */ + uint32_t fault1_clr_int_st: 1; + /** fault2_clr_int_st : RO; bitpos: [14]; default: 0; + * The masked status bit for the interrupt triggered when fault_event2 ends. + */ + uint32_t fault2_clr_int_st: 1; + /** op0_tea_int_st : RO; bitpos: [15]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 0 TEA event + */ + uint32_t op0_tea_int_st: 1; + /** op1_tea_int_st : RO; bitpos: [16]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 1 TEA event + */ + uint32_t op1_tea_int_st: 1; + /** op2_tea_int_st : RO; bitpos: [17]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 2 TEA event + */ + uint32_t op2_tea_int_st: 1; + /** op0_teb_int_st : RO; bitpos: [18]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 0 TEB event + */ + uint32_t op0_teb_int_st: 1; + /** op1_teb_int_st : RO; bitpos: [19]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 1 TEB event + */ + uint32_t op1_teb_int_st: 1; + /** op2_teb_int_st : RO; bitpos: [20]; default: 0; + * The masked status bit for the interrupt triggered by a PWM operator 2 TEB event + */ + uint32_t op2_teb_int_st: 1; + /** fh0_cbc_int_st : RO; bitpos: [21]; default: 0; + * The masked status bit for the interrupt triggered by a cycle-by-cycle mode action + * on PWM0. + */ + uint32_t fh0_cbc_int_st: 1; + /** fh1_cbc_int_st : RO; bitpos: [22]; default: 0; + * The masked status bit for the interrupt triggered by a cycle-by-cycle mode action + * on PWM1. + */ + uint32_t fh1_cbc_int_st: 1; + /** fh2_cbc_int_st : RO; bitpos: [23]; default: 0; + * The masked status bit for the interrupt triggered by a cycle-by-cycle mode action + * on PWM2. + */ + uint32_t fh2_cbc_int_st: 1; + /** fh0_ost_int_st : RO; bitpos: [24]; default: 0; + * The masked status bit for the interrupt triggered by a one-shot mode action on PWM0. + */ + uint32_t fh0_ost_int_st: 1; + /** fh1_ost_int_st : RO; bitpos: [25]; default: 0; + * The masked status bit for the interrupt triggered by a one-shot mode action on PWM1. + */ + uint32_t fh1_ost_int_st: 1; + /** fh2_ost_int_st : RO; bitpos: [26]; default: 0; + * The masked status bit for the interrupt triggered by a one-shot mode action on PWM2. + */ + uint32_t fh2_ost_int_st: 1; + /** cap0_int_st : RO; bitpos: [27]; default: 0; + * The masked status bit for the interrupt triggered by capture on channel 0. + */ + uint32_t cap0_int_st: 1; + /** cap1_int_st : RO; bitpos: [28]; default: 0; + * The masked status bit for the interrupt triggered by capture on channel 1. + */ + uint32_t cap1_int_st: 1; + /** cap2_int_st : RO; bitpos: [29]; default: 0; + * The masked status bit for the interrupt triggered by capture on channel 2. + */ + uint32_t cap2_int_st: 1; + uint32_t reserved_30: 2; + }; + uint32_t val; +} mcpwm_int_st_reg_t; + +/** Type of int_clr register + * Interrupt clear bits + */ +typedef union { + struct { + /** timer0_stop_int_clr : WT; bitpos: [0]; default: 0; + * Set this bit to clear the interrupt triggered when the timer 0 stops. + */ + uint32_t timer0_stop_int_clr: 1; + /** timer1_stop_int_clr : WT; bitpos: [1]; default: 0; + * Set this bit to clear the interrupt triggered when the timer 1 stops. + */ + uint32_t timer1_stop_int_clr: 1; + /** timer2_stop_int_clr : WT; bitpos: [2]; default: 0; + * Set this bit to clear the interrupt triggered when the timer 2 stops. + */ + uint32_t timer2_stop_int_clr: 1; + /** timer0_tez_int_clr : WT; bitpos: [3]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 0 TEZ event. + */ + uint32_t timer0_tez_int_clr: 1; + /** timer1_tez_int_clr : WT; bitpos: [4]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 1 TEZ event. + */ + uint32_t timer1_tez_int_clr: 1; + /** timer2_tez_int_clr : WT; bitpos: [5]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 2 TEZ event. + */ + uint32_t timer2_tez_int_clr: 1; + /** timer0_tep_int_clr : WT; bitpos: [6]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 0 TEP event. + */ + uint32_t timer0_tep_int_clr: 1; + /** timer1_tep_int_clr : WT; bitpos: [7]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 1 TEP event. + */ + uint32_t timer1_tep_int_clr: 1; + /** timer2_tep_int_clr : WT; bitpos: [8]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM timer 2 TEP event. + */ + uint32_t timer2_tep_int_clr: 1; + /** fault0_int_clr : WT; bitpos: [9]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event0 starts. + */ + uint32_t fault0_int_clr: 1; + /** fault1_int_clr : WT; bitpos: [10]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event1 starts. + */ + uint32_t fault1_int_clr: 1; + /** fault2_int_clr : WT; bitpos: [11]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event2 starts. + */ + uint32_t fault2_int_clr: 1; + /** fault0_clr_int_clr : WT; bitpos: [12]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event0 ends. + */ + uint32_t fault0_clr_int_clr: 1; + /** fault1_clr_int_clr : WT; bitpos: [13]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event1 ends. + */ + uint32_t fault1_clr_int_clr: 1; + /** fault2_clr_int_clr : WT; bitpos: [14]; default: 0; + * Set this bit to clear the interrupt triggered when fault_event2 ends. + */ + uint32_t fault2_clr_int_clr: 1; + /** op0_tea_int_clr : WT; bitpos: [15]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 0 TEA event + */ + uint32_t op0_tea_int_clr: 1; + /** op1_tea_int_clr : WT; bitpos: [16]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 1 TEA event + */ + uint32_t op1_tea_int_clr: 1; + /** op2_tea_int_clr : WT; bitpos: [17]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 2 TEA event + */ + uint32_t op2_tea_int_clr: 1; + /** op0_teb_int_clr : WT; bitpos: [18]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 0 TEB event + */ + uint32_t op0_teb_int_clr: 1; + /** op1_teb_int_clr : WT; bitpos: [19]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 1 TEB event + */ + uint32_t op1_teb_int_clr: 1; + /** op2_teb_int_clr : WT; bitpos: [20]; default: 0; + * Set this bit to clear the interrupt triggered by a PWM operator 2 TEB event + */ + uint32_t op2_teb_int_clr: 1; + /** fh0_cbc_int_clr : WT; bitpos: [21]; default: 0; + * Set this bit to clear the interrupt triggered by a cycle-by-cycle mode action on + * PWM0. + */ + uint32_t fh0_cbc_int_clr: 1; + /** fh1_cbc_int_clr : WT; bitpos: [22]; default: 0; + * Set this bit to clear the interrupt triggered by a cycle-by-cycle mode action on + * PWM1. + */ + uint32_t fh1_cbc_int_clr: 1; + /** fh2_cbc_int_clr : WT; bitpos: [23]; default: 0; + * Set this bit to clear the interrupt triggered by a cycle-by-cycle mode action on + * PWM2. + */ + uint32_t fh2_cbc_int_clr: 1; + /** fh0_ost_int_clr : WT; bitpos: [24]; default: 0; + * Set this bit to clear the interrupt triggered by a one-shot mode action on PWM0. + */ + uint32_t fh0_ost_int_clr: 1; + /** fh1_ost_int_clr : WT; bitpos: [25]; default: 0; + * Set this bit to clear the interrupt triggered by a one-shot mode action on PWM1. + */ + uint32_t fh1_ost_int_clr: 1; + /** fh2_ost_int_clr : WT; bitpos: [26]; default: 0; + * Set this bit to clear the interrupt triggered by a one-shot mode action on PWM2. + */ + uint32_t fh2_ost_int_clr: 1; + /** cap0_int_clr : WT; bitpos: [27]; default: 0; + * Set this bit to clear the interrupt triggered by capture on channel 0. + */ + uint32_t cap0_int_clr: 1; + /** cap1_int_clr : WT; bitpos: [28]; default: 0; + * Set this bit to clear the interrupt triggered by capture on channel 1. + */ + uint32_t cap1_int_clr: 1; + /** cap2_int_clr : WT; bitpos: [29]; default: 0; + * Set this bit to clear the interrupt triggered by capture on channel 2. + */ + uint32_t cap2_int_clr: 1; + uint32_t reserved_30: 2; + }; + uint32_t val; +} mcpwm_int_clr_reg_t; + + +/** Group: MCMCPWM APB configuration register */ +/** Type of clk register + * MCPWM APB configuration register + */ +typedef union { + struct { + /** clk_en : R/W; bitpos: [0]; default: 0; + * Force clock on for this register file + */ + uint32_t clk_en: 1; + uint32_t reserved_1: 31; + }; + uint32_t val; +} mcpwm_clk_reg_t; + + +/** Group: Version Register */ +/** Type of version register + * Version register. + */ +typedef union { + struct { + /** date : R/W; bitpos: [27:0]; default: 34632240; + * Version of this register file + */ + uint32_t date: 28; + uint32_t reserved_28: 4; + }; + uint32_t val; +} mcpwm_version_reg_t; + + +typedef struct { + mcpwm_timer_cfg0_reg_t timer_cfg0; + mcpwm_timer_cfg1_reg_t timer_cfg1; + mcpwm_timer_sync_reg_t timer_sync; + mcpwm_timer_status_reg_t timer_status; +} mcpwm_timer_regs_t; + +typedef struct { + mcpwm_gen_stmp_cfg_reg_t gen_stmp_cfg; + mcpwm_gen_tstmp_reg_t timestamp[2]; + mcpwm_gen_cfg0_reg_t gen_cfg0; + mcpwm_gen_force_reg_t gen_force; + mcpwm_gen_reg_t generator[2]; + mcpwm_dt_cfg_reg_t dt_cfg; + mcpwm_dt_fed_cfg_reg_t dt_fed_cfg; + mcpwm_dt_red_cfg_reg_t dt_red_cfg; + mcpwm_carrier_cfg_reg_t carrier_cfg; + mcpwm_fh_cfg0_reg_t fh_cfg0; + mcpwm_fh_cfg1_reg_t fh_cfg1; + mcpwm_fh_status_reg_t fh_status; +} mcpwm_operator_reg_t; + +typedef struct { + volatile mcpwm_clk_cfg_reg_t clk_cfg; + volatile mcpwm_timer_regs_t timer[3]; + volatile mcpwm_timer_synci_cfg_reg_t timer_synci_cfg; + volatile mcpwm_operator_timersel_reg_t operator_timersel; + volatile mcpwm_operator_reg_t operators[3]; + volatile mcpwm_fault_detect_reg_t fault_detect; + volatile mcpwm_cap_timer_cfg_reg_t cap_timer_cfg; + volatile mcpwm_cap_timer_phase_reg_t cap_timer_phase; + volatile mcpwm_cap_chn_cfg_reg_t cap_chn_cfg[3]; + volatile mcpwm_cap_chn_reg_t cap_chn[3]; + volatile mcpwm_cap_status_reg_t cap_status; + volatile mcpwm_update_cfg_reg_t update_cfg; + volatile mcpwm_int_ena_reg_t int_ena; + volatile mcpwm_int_raw_reg_t int_raw; + volatile mcpwm_int_st_reg_t int_st; + volatile mcpwm_int_clr_reg_t int_clr; + volatile mcpwm_clk_reg_t clk; + volatile mcpwm_version_reg_t version; } mcpwm_dev_t; + extern mcpwm_dev_t MCPWM0; extern mcpwm_dev_t MCPWM1; + +#ifndef __cplusplus +_Static_assert(sizeof(mcpwm_dev_t) == 0x128, "Invalid size of mcpwm_dev_t structure"); +#endif + #ifdef __cplusplus } #endif - - - -#endif /*_SOC_MCPWM_STRUCT_H_ */ diff --git a/components/soc/esp32s3/include/soc/pcnt_reg.h b/components/soc/esp32s3/include/soc/pcnt_reg.h index 6cb00b4be4..b6198c86fb 100644 --- a/components/soc/esp32s3/include/soc/pcnt_reg.h +++ b/components/soc/esp32s3/include/soc/pcnt_reg.h @@ -1,862 +1,1236 @@ -// 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. -#ifndef _SOC_PCNT_REG_H_ -#define _SOC_PCNT_REG_H_ +/** Copyright 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. + */ +#pragma once +#include +#include "soc/soc.h" -#include "soc.h" #ifdef __cplusplus extern "C" { #endif -#define PCNT_U0_CONF0_REG (DR_REG_PCNT_BASE + 0x0) -/* PCNT_CH1_LCTRL_MODE_U0 : R/W ;bitpos:[31:30] ;default: 2'd0 ; */ -/*description: .*/ -#define PCNT_CH1_LCTRL_MODE_U0 0x00000003 -#define PCNT_CH1_LCTRL_MODE_U0_M ((PCNT_CH1_LCTRL_MODE_U0_V)<<(PCNT_CH1_LCTRL_MODE_U0_S)) -#define PCNT_CH1_LCTRL_MODE_U0_V 0x3 -#define PCNT_CH1_LCTRL_MODE_U0_S 30 -/* PCNT_CH1_HCTRL_MODE_U0 : R/W ;bitpos:[29:28] ;default: 2'd0 ; */ -/*description: .*/ -#define PCNT_CH1_HCTRL_MODE_U0 0x00000003 -#define PCNT_CH1_HCTRL_MODE_U0_M ((PCNT_CH1_HCTRL_MODE_U0_V)<<(PCNT_CH1_HCTRL_MODE_U0_S)) -#define PCNT_CH1_HCTRL_MODE_U0_V 0x3 -#define PCNT_CH1_HCTRL_MODE_U0_S 28 -/* PCNT_CH1_POS_MODE_U0 : R/W ;bitpos:[27:26] ;default: 2'd0 ; */ -/*description: .*/ -#define PCNT_CH1_POS_MODE_U0 0x00000003 -#define PCNT_CH1_POS_MODE_U0_M ((PCNT_CH1_POS_MODE_U0_V)<<(PCNT_CH1_POS_MODE_U0_S)) -#define PCNT_CH1_POS_MODE_U0_V 0x3 -#define PCNT_CH1_POS_MODE_U0_S 26 -/* PCNT_CH1_NEG_MODE_U0 : R/W ;bitpos:[25:24] ;default: 2'd0 ; */ -/*description: .*/ -#define PCNT_CH1_NEG_MODE_U0 0x00000003 -#define PCNT_CH1_NEG_MODE_U0_M ((PCNT_CH1_NEG_MODE_U0_V)<<(PCNT_CH1_NEG_MODE_U0_S)) -#define PCNT_CH1_NEG_MODE_U0_V 0x3 -#define PCNT_CH1_NEG_MODE_U0_S 24 -/* PCNT_CH0_LCTRL_MODE_U0 : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: .*/ -#define PCNT_CH0_LCTRL_MODE_U0 0x00000003 -#define PCNT_CH0_LCTRL_MODE_U0_M ((PCNT_CH0_LCTRL_MODE_U0_V)<<(PCNT_CH0_LCTRL_MODE_U0_S)) -#define PCNT_CH0_LCTRL_MODE_U0_V 0x3 -#define PCNT_CH0_LCTRL_MODE_U0_S 22 -/* PCNT_CH0_HCTRL_MODE_U0 : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: .*/ -#define PCNT_CH0_HCTRL_MODE_U0 0x00000003 -#define PCNT_CH0_HCTRL_MODE_U0_M ((PCNT_CH0_HCTRL_MODE_U0_V)<<(PCNT_CH0_HCTRL_MODE_U0_S)) -#define PCNT_CH0_HCTRL_MODE_U0_V 0x3 -#define PCNT_CH0_HCTRL_MODE_U0_S 20 -/* PCNT_CH0_POS_MODE_U0 : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: .*/ -#define PCNT_CH0_POS_MODE_U0 0x00000003 -#define PCNT_CH0_POS_MODE_U0_M ((PCNT_CH0_POS_MODE_U0_V)<<(PCNT_CH0_POS_MODE_U0_S)) -#define PCNT_CH0_POS_MODE_U0_V 0x3 -#define PCNT_CH0_POS_MODE_U0_S 18 -/* PCNT_CH0_NEG_MODE_U0 : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: .*/ -#define PCNT_CH0_NEG_MODE_U0 0x00000003 -#define PCNT_CH0_NEG_MODE_U0_M ((PCNT_CH0_NEG_MODE_U0_V)<<(PCNT_CH0_NEG_MODE_U0_S)) -#define PCNT_CH0_NEG_MODE_U0_V 0x3 -#define PCNT_CH0_NEG_MODE_U0_S 16 -/* PCNT_THR_THRES1_EN_U0 : R/W ;bitpos:[15] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_THR_THRES1_EN_U0 (BIT(15)) -#define PCNT_THR_THRES1_EN_U0_M (BIT(15)) -#define PCNT_THR_THRES1_EN_U0_V 0x1 -#define PCNT_THR_THRES1_EN_U0_S 15 -/* PCNT_THR_THRES0_EN_U0 : R/W ;bitpos:[14] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_THR_THRES0_EN_U0 (BIT(14)) -#define PCNT_THR_THRES0_EN_U0_M (BIT(14)) -#define PCNT_THR_THRES0_EN_U0_V 0x1 -#define PCNT_THR_THRES0_EN_U0_S 14 -/* PCNT_THR_L_LIM_EN_U0 : R/W ;bitpos:[13] ;default: 1'b1 ; */ -/*description: .*/ -#define PCNT_THR_L_LIM_EN_U0 (BIT(13)) -#define PCNT_THR_L_LIM_EN_U0_M (BIT(13)) -#define PCNT_THR_L_LIM_EN_U0_V 0x1 -#define PCNT_THR_L_LIM_EN_U0_S 13 -/* PCNT_THR_H_LIM_EN_U0 : R/W ;bitpos:[12] ;default: 1'b1 ; */ -/*description: .*/ -#define PCNT_THR_H_LIM_EN_U0 (BIT(12)) -#define PCNT_THR_H_LIM_EN_U0_M (BIT(12)) -#define PCNT_THR_H_LIM_EN_U0_V 0x1 -#define PCNT_THR_H_LIM_EN_U0_S 12 -/* PCNT_THR_ZERO_EN_U0 : R/W ;bitpos:[11] ;default: 1'b1 ; */ -/*description: .*/ -#define PCNT_THR_ZERO_EN_U0 (BIT(11)) -#define PCNT_THR_ZERO_EN_U0_M (BIT(11)) -#define PCNT_THR_ZERO_EN_U0_V 0x1 -#define PCNT_THR_ZERO_EN_U0_S 11 -/* PCNT_FILTER_EN_U0 : R/W ;bitpos:[10] ;default: 1'b1 ; */ -/*description: .*/ -#define PCNT_FILTER_EN_U0 (BIT(10)) -#define PCNT_FILTER_EN_U0_M (BIT(10)) -#define PCNT_FILTER_EN_U0_V 0x1 -#define PCNT_FILTER_EN_U0_S 10 -/* PCNT_FILTER_THRES_U0 : R/W ;bitpos:[9:0] ;default: 10'h10 ; */ -/*description: .*/ -#define PCNT_FILTER_THRES_U0 0x000003FF -#define PCNT_FILTER_THRES_U0_M ((PCNT_FILTER_THRES_U0_V)<<(PCNT_FILTER_THRES_U0_S)) -#define PCNT_FILTER_THRES_U0_V 0x3FF +/** PCNT_U0_CONF0_REG register + * Configuration register 0 for unit 0 + */ +#define PCNT_U0_CONF0_REG (DR_REG_PCNT_BASE + 0x0) +/** PCNT_FILTER_THRES_U0 : R/W; bitpos: [9:0]; default: 16; + * This sets the maximum threshold, in APB_CLK cycles, for the filter. + * + * Any pulses with width less than this will be ignored when the filter is enabled. + */ +#define PCNT_FILTER_THRES_U0 0x000003FFU +#define PCNT_FILTER_THRES_U0_M (PCNT_FILTER_THRES_U0_V << PCNT_FILTER_THRES_U0_S) +#define PCNT_FILTER_THRES_U0_V 0x000003FFU #define PCNT_FILTER_THRES_U0_S 0 +/** PCNT_FILTER_EN_U0 : R/W; bitpos: [10]; default: 1; + * This is the enable bit for unit 0's input filter. + */ +#define PCNT_FILTER_EN_U0 (BIT(10)) +#define PCNT_FILTER_EN_U0_M (PCNT_FILTER_EN_U0_V << PCNT_FILTER_EN_U0_S) +#define PCNT_FILTER_EN_U0_V 0x00000001U +#define PCNT_FILTER_EN_U0_S 10 +/** PCNT_THR_ZERO_EN_U0 : R/W; bitpos: [11]; default: 1; + * This is the enable bit for unit 0's zero comparator. + */ +#define PCNT_THR_ZERO_EN_U0 (BIT(11)) +#define PCNT_THR_ZERO_EN_U0_M (PCNT_THR_ZERO_EN_U0_V << PCNT_THR_ZERO_EN_U0_S) +#define PCNT_THR_ZERO_EN_U0_V 0x00000001U +#define PCNT_THR_ZERO_EN_U0_S 11 +/** PCNT_THR_H_LIM_EN_U0 : R/W; bitpos: [12]; default: 1; + * This is the enable bit for unit 0's thr_h_lim comparator. + */ +#define PCNT_THR_H_LIM_EN_U0 (BIT(12)) +#define PCNT_THR_H_LIM_EN_U0_M (PCNT_THR_H_LIM_EN_U0_V << PCNT_THR_H_LIM_EN_U0_S) +#define PCNT_THR_H_LIM_EN_U0_V 0x00000001U +#define PCNT_THR_H_LIM_EN_U0_S 12 +/** PCNT_THR_L_LIM_EN_U0 : R/W; bitpos: [13]; default: 1; + * This is the enable bit for unit 0's thr_l_lim comparator. + */ +#define PCNT_THR_L_LIM_EN_U0 (BIT(13)) +#define PCNT_THR_L_LIM_EN_U0_M (PCNT_THR_L_LIM_EN_U0_V << PCNT_THR_L_LIM_EN_U0_S) +#define PCNT_THR_L_LIM_EN_U0_V 0x00000001U +#define PCNT_THR_L_LIM_EN_U0_S 13 +/** PCNT_THR_THRES0_EN_U0 : R/W; bitpos: [14]; default: 0; + * This is the enable bit for unit 0's thres0 comparator. + */ +#define PCNT_THR_THRES0_EN_U0 (BIT(14)) +#define PCNT_THR_THRES0_EN_U0_M (PCNT_THR_THRES0_EN_U0_V << PCNT_THR_THRES0_EN_U0_S) +#define PCNT_THR_THRES0_EN_U0_V 0x00000001U +#define PCNT_THR_THRES0_EN_U0_S 14 +/** PCNT_THR_THRES1_EN_U0 : R/W; bitpos: [15]; default: 0; + * This is the enable bit for unit 0's thres1 comparator. + */ +#define PCNT_THR_THRES1_EN_U0 (BIT(15)) +#define PCNT_THR_THRES1_EN_U0_M (PCNT_THR_THRES1_EN_U0_V << PCNT_THR_THRES1_EN_U0_S) +#define PCNT_THR_THRES1_EN_U0_V 0x00000001U +#define PCNT_THR_THRES1_EN_U0_S 15 +/** PCNT_CH0_NEG_MODE_U0 : R/W; bitpos: [17:16]; default: 0; + * This register sets the behavior when the signal input of channel 0 detects a + * negative edge. + * + * 1: Increase the counter;2: Decrease the counter;0, 3: No effect on counter + */ +#define PCNT_CH0_NEG_MODE_U0 0x00000003U +#define PCNT_CH0_NEG_MODE_U0_M (PCNT_CH0_NEG_MODE_U0_V << PCNT_CH0_NEG_MODE_U0_S) +#define PCNT_CH0_NEG_MODE_U0_V 0x00000003U +#define PCNT_CH0_NEG_MODE_U0_S 16 +/** PCNT_CH0_POS_MODE_U0 : R/W; bitpos: [19:18]; default: 0; + * This register sets the behavior when the signal input of channel 0 detects a + * positive edge. + * + * 1: Increase the counter;2: Decrease the counter;0, 3: No effect on counter + */ +#define PCNT_CH0_POS_MODE_U0 0x00000003U +#define PCNT_CH0_POS_MODE_U0_M (PCNT_CH0_POS_MODE_U0_V << PCNT_CH0_POS_MODE_U0_S) +#define PCNT_CH0_POS_MODE_U0_V 0x00000003U +#define PCNT_CH0_POS_MODE_U0_S 18 +/** PCNT_CH0_HCTRL_MODE_U0 : R/W; bitpos: [21:20]; default: 0; + * This register configures how the CH0_POS_MODE/CH0_NEG_MODE settings will be + * modified when the control signal is high. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ +#define PCNT_CH0_HCTRL_MODE_U0 0x00000003U +#define PCNT_CH0_HCTRL_MODE_U0_M (PCNT_CH0_HCTRL_MODE_U0_V << PCNT_CH0_HCTRL_MODE_U0_S) +#define PCNT_CH0_HCTRL_MODE_U0_V 0x00000003U +#define PCNT_CH0_HCTRL_MODE_U0_S 20 +/** PCNT_CH0_LCTRL_MODE_U0 : R/W; bitpos: [23:22]; default: 0; + * This register configures how the CH0_POS_MODE/CH0_NEG_MODE settings will be + * modified when the control signal is low. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ +#define PCNT_CH0_LCTRL_MODE_U0 0x00000003U +#define PCNT_CH0_LCTRL_MODE_U0_M (PCNT_CH0_LCTRL_MODE_U0_V << PCNT_CH0_LCTRL_MODE_U0_S) +#define PCNT_CH0_LCTRL_MODE_U0_V 0x00000003U +#define PCNT_CH0_LCTRL_MODE_U0_S 22 +/** PCNT_CH1_NEG_MODE_U0 : R/W; bitpos: [25:24]; default: 0; + * This register sets the behavior when the signal input of channel 1 detects a + * negative edge. + * + * 1: Increment the counter;2: Decrement the counter;0, 3: No effect on counter + */ +#define PCNT_CH1_NEG_MODE_U0 0x00000003U +#define PCNT_CH1_NEG_MODE_U0_M (PCNT_CH1_NEG_MODE_U0_V << PCNT_CH1_NEG_MODE_U0_S) +#define PCNT_CH1_NEG_MODE_U0_V 0x00000003U +#define PCNT_CH1_NEG_MODE_U0_S 24 +/** PCNT_CH1_POS_MODE_U0 : R/W; bitpos: [27:26]; default: 0; + * This register sets the behavior when the signal input of channel 1 detects a + * positive edge. + * + * 1: Increment the counter;2: Decrement the counter;0, 3: No effect on counter + */ +#define PCNT_CH1_POS_MODE_U0 0x00000003U +#define PCNT_CH1_POS_MODE_U0_M (PCNT_CH1_POS_MODE_U0_V << PCNT_CH1_POS_MODE_U0_S) +#define PCNT_CH1_POS_MODE_U0_V 0x00000003U +#define PCNT_CH1_POS_MODE_U0_S 26 +/** PCNT_CH1_HCTRL_MODE_U0 : R/W; bitpos: [29:28]; default: 0; + * This register configures how the CH0_POS_MODE/CH0_NEG_MODE settings will be + * modified when the control signal is high. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ +#define PCNT_CH1_HCTRL_MODE_U0 0x00000003U +#define PCNT_CH1_HCTRL_MODE_U0_M (PCNT_CH1_HCTRL_MODE_U0_V << PCNT_CH1_HCTRL_MODE_U0_S) +#define PCNT_CH1_HCTRL_MODE_U0_V 0x00000003U +#define PCNT_CH1_HCTRL_MODE_U0_S 28 +/** PCNT_CH1_LCTRL_MODE_U0 : R/W; bitpos: [31:30]; default: 0; + * This register configures how the CH0_POS_MODE/CH0_NEG_MODE settings will be + * modified when the control signal is low. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ +#define PCNT_CH1_LCTRL_MODE_U0 0x00000003U +#define PCNT_CH1_LCTRL_MODE_U0_M (PCNT_CH1_LCTRL_MODE_U0_V << PCNT_CH1_LCTRL_MODE_U0_S) +#define PCNT_CH1_LCTRL_MODE_U0_V 0x00000003U +#define PCNT_CH1_LCTRL_MODE_U0_S 30 -#define PCNT_U0_CONF1_REG (DR_REG_PCNT_BASE + 0x4) -/* PCNT_CNT_THRES1_U0 : R/W ;bitpos:[31:16] ;default: 10'h0 ; */ -/*description: .*/ -#define PCNT_CNT_THRES1_U0 0x0000FFFF -#define PCNT_CNT_THRES1_U0_M ((PCNT_CNT_THRES1_U0_V)<<(PCNT_CNT_THRES1_U0_S)) -#define PCNT_CNT_THRES1_U0_V 0xFFFF -#define PCNT_CNT_THRES1_U0_S 16 -/* PCNT_CNT_THRES0_U0 : R/W ;bitpos:[15:0] ;default: 10'h0 ; */ -/*description: .*/ -#define PCNT_CNT_THRES0_U0 0x0000FFFF -#define PCNT_CNT_THRES0_U0_M ((PCNT_CNT_THRES0_U0_V)<<(PCNT_CNT_THRES0_U0_S)) -#define PCNT_CNT_THRES0_U0_V 0xFFFF +/** PCNT_U0_CONF1_REG register + * Configuration register 1 for unit 0 + */ +#define PCNT_U0_CONF1_REG (DR_REG_PCNT_BASE + 0x4) +/** PCNT_CNT_THRES0_U0 : R/W; bitpos: [15:0]; default: 0; + * This register is used to configure the thres0 value for unit 0. + */ +#define PCNT_CNT_THRES0_U0 0x0000FFFFU +#define PCNT_CNT_THRES0_U0_M (PCNT_CNT_THRES0_U0_V << PCNT_CNT_THRES0_U0_S) +#define PCNT_CNT_THRES0_U0_V 0x0000FFFFU #define PCNT_CNT_THRES0_U0_S 0 +/** PCNT_CNT_THRES1_U0 : R/W; bitpos: [31:16]; default: 0; + * This register is used to configure the thres1 value for unit 0. + */ +#define PCNT_CNT_THRES1_U0 0x0000FFFFU +#define PCNT_CNT_THRES1_U0_M (PCNT_CNT_THRES1_U0_V << PCNT_CNT_THRES1_U0_S) +#define PCNT_CNT_THRES1_U0_V 0x0000FFFFU +#define PCNT_CNT_THRES1_U0_S 16 -#define PCNT_U0_CONF2_REG (DR_REG_PCNT_BASE + 0x8) -/* PCNT_CNT_L_LIM_U0 : R/W ;bitpos:[31:16] ;default: 10'h0 ; */ -/*description: .*/ -#define PCNT_CNT_L_LIM_U0 0x0000FFFF -#define PCNT_CNT_L_LIM_U0_M ((PCNT_CNT_L_LIM_U0_V)<<(PCNT_CNT_L_LIM_U0_S)) -#define PCNT_CNT_L_LIM_U0_V 0xFFFF -#define PCNT_CNT_L_LIM_U0_S 16 -/* PCNT_CNT_H_LIM_U0 : R/W ;bitpos:[15:0] ;default: 10'h0 ; */ -/*description: .*/ -#define PCNT_CNT_H_LIM_U0 0x0000FFFF -#define PCNT_CNT_H_LIM_U0_M ((PCNT_CNT_H_LIM_U0_V)<<(PCNT_CNT_H_LIM_U0_S)) -#define PCNT_CNT_H_LIM_U0_V 0xFFFF +/** PCNT_U0_CONF2_REG register + * Configuration register 2 for unit 0 + */ +#define PCNT_U0_CONF2_REG (DR_REG_PCNT_BASE + 0x8) +/** PCNT_CNT_H_LIM_U0 : R/W; bitpos: [15:0]; default: 0; + * This register is used to configure the thr_h_lim value for unit 0. + */ +#define PCNT_CNT_H_LIM_U0 0x0000FFFFU +#define PCNT_CNT_H_LIM_U0_M (PCNT_CNT_H_LIM_U0_V << PCNT_CNT_H_LIM_U0_S) +#define PCNT_CNT_H_LIM_U0_V 0x0000FFFFU #define PCNT_CNT_H_LIM_U0_S 0 +/** PCNT_CNT_L_LIM_U0 : R/W; bitpos: [31:16]; default: 0; + * This register is used to configure the thr_l_lim value for unit 0. + */ +#define PCNT_CNT_L_LIM_U0 0x0000FFFFU +#define PCNT_CNT_L_LIM_U0_M (PCNT_CNT_L_LIM_U0_V << PCNT_CNT_L_LIM_U0_S) +#define PCNT_CNT_L_LIM_U0_V 0x0000FFFFU +#define PCNT_CNT_L_LIM_U0_S 16 -#define PCNT_U1_CONF0_REG (DR_REG_PCNT_BASE + 0xC) -/* PCNT_CH1_LCTRL_MODE_U1 : R/W ;bitpos:[31:30] ;default: 2'd0 ; */ -/*description: .*/ -#define PCNT_CH1_LCTRL_MODE_U1 0x00000003 -#define PCNT_CH1_LCTRL_MODE_U1_M ((PCNT_CH1_LCTRL_MODE_U1_V)<<(PCNT_CH1_LCTRL_MODE_U1_S)) -#define PCNT_CH1_LCTRL_MODE_U1_V 0x3 -#define PCNT_CH1_LCTRL_MODE_U1_S 30 -/* PCNT_CH1_HCTRL_MODE_U1 : R/W ;bitpos:[29:28] ;default: 2'd0 ; */ -/*description: .*/ -#define PCNT_CH1_HCTRL_MODE_U1 0x00000003 -#define PCNT_CH1_HCTRL_MODE_U1_M ((PCNT_CH1_HCTRL_MODE_U1_V)<<(PCNT_CH1_HCTRL_MODE_U1_S)) -#define PCNT_CH1_HCTRL_MODE_U1_V 0x3 -#define PCNT_CH1_HCTRL_MODE_U1_S 28 -/* PCNT_CH1_POS_MODE_U1 : R/W ;bitpos:[27:26] ;default: 2'd0 ; */ -/*description: .*/ -#define PCNT_CH1_POS_MODE_U1 0x00000003 -#define PCNT_CH1_POS_MODE_U1_M ((PCNT_CH1_POS_MODE_U1_V)<<(PCNT_CH1_POS_MODE_U1_S)) -#define PCNT_CH1_POS_MODE_U1_V 0x3 -#define PCNT_CH1_POS_MODE_U1_S 26 -/* PCNT_CH1_NEG_MODE_U1 : R/W ;bitpos:[25:24] ;default: 2'd0 ; */ -/*description: .*/ -#define PCNT_CH1_NEG_MODE_U1 0x00000003 -#define PCNT_CH1_NEG_MODE_U1_M ((PCNT_CH1_NEG_MODE_U1_V)<<(PCNT_CH1_NEG_MODE_U1_S)) -#define PCNT_CH1_NEG_MODE_U1_V 0x3 -#define PCNT_CH1_NEG_MODE_U1_S 24 -/* PCNT_CH0_LCTRL_MODE_U1 : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: .*/ -#define PCNT_CH0_LCTRL_MODE_U1 0x00000003 -#define PCNT_CH0_LCTRL_MODE_U1_M ((PCNT_CH0_LCTRL_MODE_U1_V)<<(PCNT_CH0_LCTRL_MODE_U1_S)) -#define PCNT_CH0_LCTRL_MODE_U1_V 0x3 -#define PCNT_CH0_LCTRL_MODE_U1_S 22 -/* PCNT_CH0_HCTRL_MODE_U1 : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: .*/ -#define PCNT_CH0_HCTRL_MODE_U1 0x00000003 -#define PCNT_CH0_HCTRL_MODE_U1_M ((PCNT_CH0_HCTRL_MODE_U1_V)<<(PCNT_CH0_HCTRL_MODE_U1_S)) -#define PCNT_CH0_HCTRL_MODE_U1_V 0x3 -#define PCNT_CH0_HCTRL_MODE_U1_S 20 -/* PCNT_CH0_POS_MODE_U1 : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: .*/ -#define PCNT_CH0_POS_MODE_U1 0x00000003 -#define PCNT_CH0_POS_MODE_U1_M ((PCNT_CH0_POS_MODE_U1_V)<<(PCNT_CH0_POS_MODE_U1_S)) -#define PCNT_CH0_POS_MODE_U1_V 0x3 -#define PCNT_CH0_POS_MODE_U1_S 18 -/* PCNT_CH0_NEG_MODE_U1 : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: .*/ -#define PCNT_CH0_NEG_MODE_U1 0x00000003 -#define PCNT_CH0_NEG_MODE_U1_M ((PCNT_CH0_NEG_MODE_U1_V)<<(PCNT_CH0_NEG_MODE_U1_S)) -#define PCNT_CH0_NEG_MODE_U1_V 0x3 -#define PCNT_CH0_NEG_MODE_U1_S 16 -/* PCNT_THR_THRES1_EN_U1 : R/W ;bitpos:[15] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_THR_THRES1_EN_U1 (BIT(15)) -#define PCNT_THR_THRES1_EN_U1_M (BIT(15)) -#define PCNT_THR_THRES1_EN_U1_V 0x1 -#define PCNT_THR_THRES1_EN_U1_S 15 -/* PCNT_THR_THRES0_EN_U1 : R/W ;bitpos:[14] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_THR_THRES0_EN_U1 (BIT(14)) -#define PCNT_THR_THRES0_EN_U1_M (BIT(14)) -#define PCNT_THR_THRES0_EN_U1_V 0x1 -#define PCNT_THR_THRES0_EN_U1_S 14 -/* PCNT_THR_L_LIM_EN_U1 : R/W ;bitpos:[13] ;default: 1'b1 ; */ -/*description: .*/ -#define PCNT_THR_L_LIM_EN_U1 (BIT(13)) -#define PCNT_THR_L_LIM_EN_U1_M (BIT(13)) -#define PCNT_THR_L_LIM_EN_U1_V 0x1 -#define PCNT_THR_L_LIM_EN_U1_S 13 -/* PCNT_THR_H_LIM_EN_U1 : R/W ;bitpos:[12] ;default: 1'b1 ; */ -/*description: .*/ -#define PCNT_THR_H_LIM_EN_U1 (BIT(12)) -#define PCNT_THR_H_LIM_EN_U1_M (BIT(12)) -#define PCNT_THR_H_LIM_EN_U1_V 0x1 -#define PCNT_THR_H_LIM_EN_U1_S 12 -/* PCNT_THR_ZERO_EN_U1 : R/W ;bitpos:[11] ;default: 1'b1 ; */ -/*description: .*/ -#define PCNT_THR_ZERO_EN_U1 (BIT(11)) -#define PCNT_THR_ZERO_EN_U1_M (BIT(11)) -#define PCNT_THR_ZERO_EN_U1_V 0x1 -#define PCNT_THR_ZERO_EN_U1_S 11 -/* PCNT_FILTER_EN_U1 : R/W ;bitpos:[10] ;default: 1'b1 ; */ -/*description: .*/ -#define PCNT_FILTER_EN_U1 (BIT(10)) -#define PCNT_FILTER_EN_U1_M (BIT(10)) -#define PCNT_FILTER_EN_U1_V 0x1 -#define PCNT_FILTER_EN_U1_S 10 -/* PCNT_FILTER_THRES_U1 : R/W ;bitpos:[9:0] ;default: 10'h10 ; */ -/*description: .*/ -#define PCNT_FILTER_THRES_U1 0x000003FF -#define PCNT_FILTER_THRES_U1_M ((PCNT_FILTER_THRES_U1_V)<<(PCNT_FILTER_THRES_U1_S)) -#define PCNT_FILTER_THRES_U1_V 0x3FF +/** PCNT_U1_CONF0_REG register + * Configuration register 0 for unit 1 + */ +#define PCNT_U1_CONF0_REG (DR_REG_PCNT_BASE + 0xc) +/** PCNT_FILTER_THRES_U1 : R/W; bitpos: [9:0]; default: 16; + * This sets the maximum threshold, in APB_CLK cycles, for the filter. + * + * Any pulses with width less than this will be ignored when the filter is enabled. + */ +#define PCNT_FILTER_THRES_U1 0x000003FFU +#define PCNT_FILTER_THRES_U1_M (PCNT_FILTER_THRES_U1_V << PCNT_FILTER_THRES_U1_S) +#define PCNT_FILTER_THRES_U1_V 0x000003FFU #define PCNT_FILTER_THRES_U1_S 0 +/** PCNT_FILTER_EN_U1 : R/W; bitpos: [10]; default: 1; + * This is the enable bit for unit 1's input filter. + */ +#define PCNT_FILTER_EN_U1 (BIT(10)) +#define PCNT_FILTER_EN_U1_M (PCNT_FILTER_EN_U1_V << PCNT_FILTER_EN_U1_S) +#define PCNT_FILTER_EN_U1_V 0x00000001U +#define PCNT_FILTER_EN_U1_S 10 +/** PCNT_THR_ZERO_EN_U1 : R/W; bitpos: [11]; default: 1; + * This is the enable bit for unit 1's zero comparator. + */ +#define PCNT_THR_ZERO_EN_U1 (BIT(11)) +#define PCNT_THR_ZERO_EN_U1_M (PCNT_THR_ZERO_EN_U1_V << PCNT_THR_ZERO_EN_U1_S) +#define PCNT_THR_ZERO_EN_U1_V 0x00000001U +#define PCNT_THR_ZERO_EN_U1_S 11 +/** PCNT_THR_H_LIM_EN_U1 : R/W; bitpos: [12]; default: 1; + * This is the enable bit for unit 1's thr_h_lim comparator. + */ +#define PCNT_THR_H_LIM_EN_U1 (BIT(12)) +#define PCNT_THR_H_LIM_EN_U1_M (PCNT_THR_H_LIM_EN_U1_V << PCNT_THR_H_LIM_EN_U1_S) +#define PCNT_THR_H_LIM_EN_U1_V 0x00000001U +#define PCNT_THR_H_LIM_EN_U1_S 12 +/** PCNT_THR_L_LIM_EN_U1 : R/W; bitpos: [13]; default: 1; + * This is the enable bit for unit 1's thr_l_lim comparator. + */ +#define PCNT_THR_L_LIM_EN_U1 (BIT(13)) +#define PCNT_THR_L_LIM_EN_U1_M (PCNT_THR_L_LIM_EN_U1_V << PCNT_THR_L_LIM_EN_U1_S) +#define PCNT_THR_L_LIM_EN_U1_V 0x00000001U +#define PCNT_THR_L_LIM_EN_U1_S 13 +/** PCNT_THR_THRES0_EN_U1 : R/W; bitpos: [14]; default: 0; + * This is the enable bit for unit 1's thres0 comparator. + */ +#define PCNT_THR_THRES0_EN_U1 (BIT(14)) +#define PCNT_THR_THRES0_EN_U1_M (PCNT_THR_THRES0_EN_U1_V << PCNT_THR_THRES0_EN_U1_S) +#define PCNT_THR_THRES0_EN_U1_V 0x00000001U +#define PCNT_THR_THRES0_EN_U1_S 14 +/** PCNT_THR_THRES1_EN_U1 : R/W; bitpos: [15]; default: 0; + * This is the enable bit for unit 1's thres1 comparator. + */ +#define PCNT_THR_THRES1_EN_U1 (BIT(15)) +#define PCNT_THR_THRES1_EN_U1_M (PCNT_THR_THRES1_EN_U1_V << PCNT_THR_THRES1_EN_U1_S) +#define PCNT_THR_THRES1_EN_U1_V 0x00000001U +#define PCNT_THR_THRES1_EN_U1_S 15 +/** PCNT_CH0_NEG_MODE_U1 : R/W; bitpos: [17:16]; default: 0; + * This register sets the behavior when the signal input of channel 0 detects a + * negative edge. + * + * 1: Increase the counter;2: Decrease the counter;0, 3: No effect on counter + */ +#define PCNT_CH0_NEG_MODE_U1 0x00000003U +#define PCNT_CH0_NEG_MODE_U1_M (PCNT_CH0_NEG_MODE_U1_V << PCNT_CH0_NEG_MODE_U1_S) +#define PCNT_CH0_NEG_MODE_U1_V 0x00000003U +#define PCNT_CH0_NEG_MODE_U1_S 16 +/** PCNT_CH0_POS_MODE_U1 : R/W; bitpos: [19:18]; default: 0; + * This register sets the behavior when the signal input of channel 0 detects a + * positive edge. + * + * 1: Increase the counter;2: Decrease the counter;0, 3: No effect on counter + */ +#define PCNT_CH0_POS_MODE_U1 0x00000003U +#define PCNT_CH0_POS_MODE_U1_M (PCNT_CH0_POS_MODE_U1_V << PCNT_CH0_POS_MODE_U1_S) +#define PCNT_CH0_POS_MODE_U1_V 0x00000003U +#define PCNT_CH0_POS_MODE_U1_S 18 +/** PCNT_CH0_HCTRL_MODE_U1 : R/W; bitpos: [21:20]; default: 0; + * This register configures how the CH1_POS_MODE/CH1_NEG_MODE settings will be + * modified when the control signal is high. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ +#define PCNT_CH0_HCTRL_MODE_U1 0x00000003U +#define PCNT_CH0_HCTRL_MODE_U1_M (PCNT_CH0_HCTRL_MODE_U1_V << PCNT_CH0_HCTRL_MODE_U1_S) +#define PCNT_CH0_HCTRL_MODE_U1_V 0x00000003U +#define PCNT_CH0_HCTRL_MODE_U1_S 20 +/** PCNT_CH0_LCTRL_MODE_U1 : R/W; bitpos: [23:22]; default: 0; + * This register configures how the CH1_POS_MODE/CH1_NEG_MODE settings will be + * modified when the control signal is low. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ +#define PCNT_CH0_LCTRL_MODE_U1 0x00000003U +#define PCNT_CH0_LCTRL_MODE_U1_M (PCNT_CH0_LCTRL_MODE_U1_V << PCNT_CH0_LCTRL_MODE_U1_S) +#define PCNT_CH0_LCTRL_MODE_U1_V 0x00000003U +#define PCNT_CH0_LCTRL_MODE_U1_S 22 +/** PCNT_CH1_NEG_MODE_U1 : R/W; bitpos: [25:24]; default: 0; + * This register sets the behavior when the signal input of channel 1 detects a + * negative edge. + * + * 1: Increment the counter;2: Decrement the counter;0, 3: No effect on counter + */ +#define PCNT_CH1_NEG_MODE_U1 0x00000003U +#define PCNT_CH1_NEG_MODE_U1_M (PCNT_CH1_NEG_MODE_U1_V << PCNT_CH1_NEG_MODE_U1_S) +#define PCNT_CH1_NEG_MODE_U1_V 0x00000003U +#define PCNT_CH1_NEG_MODE_U1_S 24 +/** PCNT_CH1_POS_MODE_U1 : R/W; bitpos: [27:26]; default: 0; + * This register sets the behavior when the signal input of channel 1 detects a + * positive edge. + * + * 1: Increment the counter;2: Decrement the counter;0, 3: No effect on counter + */ +#define PCNT_CH1_POS_MODE_U1 0x00000003U +#define PCNT_CH1_POS_MODE_U1_M (PCNT_CH1_POS_MODE_U1_V << PCNT_CH1_POS_MODE_U1_S) +#define PCNT_CH1_POS_MODE_U1_V 0x00000003U +#define PCNT_CH1_POS_MODE_U1_S 26 +/** PCNT_CH1_HCTRL_MODE_U1 : R/W; bitpos: [29:28]; default: 0; + * This register configures how the CH1_POS_MODE/CH1_NEG_MODE settings will be + * modified when the control signal is high. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ +#define PCNT_CH1_HCTRL_MODE_U1 0x00000003U +#define PCNT_CH1_HCTRL_MODE_U1_M (PCNT_CH1_HCTRL_MODE_U1_V << PCNT_CH1_HCTRL_MODE_U1_S) +#define PCNT_CH1_HCTRL_MODE_U1_V 0x00000003U +#define PCNT_CH1_HCTRL_MODE_U1_S 28 +/** PCNT_CH1_LCTRL_MODE_U1 : R/W; bitpos: [31:30]; default: 0; + * This register configures how the CH1_POS_MODE/CH1_NEG_MODE settings will be + * modified when the control signal is low. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ +#define PCNT_CH1_LCTRL_MODE_U1 0x00000003U +#define PCNT_CH1_LCTRL_MODE_U1_M (PCNT_CH1_LCTRL_MODE_U1_V << PCNT_CH1_LCTRL_MODE_U1_S) +#define PCNT_CH1_LCTRL_MODE_U1_V 0x00000003U +#define PCNT_CH1_LCTRL_MODE_U1_S 30 -#define PCNT_U1_CONF1_REG (DR_REG_PCNT_BASE + 0x10) -/* PCNT_CNT_THRES1_U1 : R/W ;bitpos:[31:16] ;default: 10'h0 ; */ -/*description: .*/ -#define PCNT_CNT_THRES1_U1 0x0000FFFF -#define PCNT_CNT_THRES1_U1_M ((PCNT_CNT_THRES1_U1_V)<<(PCNT_CNT_THRES1_U1_S)) -#define PCNT_CNT_THRES1_U1_V 0xFFFF -#define PCNT_CNT_THRES1_U1_S 16 -/* PCNT_CNT_THRES0_U1 : R/W ;bitpos:[15:0] ;default: 10'h0 ; */ -/*description: .*/ -#define PCNT_CNT_THRES0_U1 0x0000FFFF -#define PCNT_CNT_THRES0_U1_M ((PCNT_CNT_THRES0_U1_V)<<(PCNT_CNT_THRES0_U1_S)) -#define PCNT_CNT_THRES0_U1_V 0xFFFF +/** PCNT_U1_CONF1_REG register + * Configuration register 1 for unit 1 + */ +#define PCNT_U1_CONF1_REG (DR_REG_PCNT_BASE + 0x10) +/** PCNT_CNT_THRES0_U1 : R/W; bitpos: [15:0]; default: 0; + * This register is used to configure the thres0 value for unit 1. + */ +#define PCNT_CNT_THRES0_U1 0x0000FFFFU +#define PCNT_CNT_THRES0_U1_M (PCNT_CNT_THRES0_U1_V << PCNT_CNT_THRES0_U1_S) +#define PCNT_CNT_THRES0_U1_V 0x0000FFFFU #define PCNT_CNT_THRES0_U1_S 0 +/** PCNT_CNT_THRES1_U1 : R/W; bitpos: [31:16]; default: 0; + * This register is used to configure the thres1 value for unit 1. + */ +#define PCNT_CNT_THRES1_U1 0x0000FFFFU +#define PCNT_CNT_THRES1_U1_M (PCNT_CNT_THRES1_U1_V << PCNT_CNT_THRES1_U1_S) +#define PCNT_CNT_THRES1_U1_V 0x0000FFFFU +#define PCNT_CNT_THRES1_U1_S 16 -#define PCNT_U1_CONF2_REG (DR_REG_PCNT_BASE + 0x14) -/* PCNT_CNT_L_LIM_U1 : R/W ;bitpos:[31:16] ;default: 10'h0 ; */ -/*description: .*/ -#define PCNT_CNT_L_LIM_U1 0x0000FFFF -#define PCNT_CNT_L_LIM_U1_M ((PCNT_CNT_L_LIM_U1_V)<<(PCNT_CNT_L_LIM_U1_S)) -#define PCNT_CNT_L_LIM_U1_V 0xFFFF -#define PCNT_CNT_L_LIM_U1_S 16 -/* PCNT_CNT_H_LIM_U1 : R/W ;bitpos:[15:0] ;default: 10'h0 ; */ -/*description: .*/ -#define PCNT_CNT_H_LIM_U1 0x0000FFFF -#define PCNT_CNT_H_LIM_U1_M ((PCNT_CNT_H_LIM_U1_V)<<(PCNT_CNT_H_LIM_U1_S)) -#define PCNT_CNT_H_LIM_U1_V 0xFFFF +/** PCNT_U1_CONF2_REG register + * Configuration register 2 for unit 1 + */ +#define PCNT_U1_CONF2_REG (DR_REG_PCNT_BASE + 0x14) +/** PCNT_CNT_H_LIM_U1 : R/W; bitpos: [15:0]; default: 0; + * This register is used to configure the thr_h_lim value for unit 1. + */ +#define PCNT_CNT_H_LIM_U1 0x0000FFFFU +#define PCNT_CNT_H_LIM_U1_M (PCNT_CNT_H_LIM_U1_V << PCNT_CNT_H_LIM_U1_S) +#define PCNT_CNT_H_LIM_U1_V 0x0000FFFFU #define PCNT_CNT_H_LIM_U1_S 0 +/** PCNT_CNT_L_LIM_U1 : R/W; bitpos: [31:16]; default: 0; + * This register is used to configure the thr_l_lim value for unit 1. + */ +#define PCNT_CNT_L_LIM_U1 0x0000FFFFU +#define PCNT_CNT_L_LIM_U1_M (PCNT_CNT_L_LIM_U1_V << PCNT_CNT_L_LIM_U1_S) +#define PCNT_CNT_L_LIM_U1_V 0x0000FFFFU +#define PCNT_CNT_L_LIM_U1_S 16 -#define PCNT_U2_CONF0_REG (DR_REG_PCNT_BASE + 0x18) -/* PCNT_CH1_LCTRL_MODE_U2 : R/W ;bitpos:[31:30] ;default: 2'd0 ; */ -/*description: .*/ -#define PCNT_CH1_LCTRL_MODE_U2 0x00000003 -#define PCNT_CH1_LCTRL_MODE_U2_M ((PCNT_CH1_LCTRL_MODE_U2_V)<<(PCNT_CH1_LCTRL_MODE_U2_S)) -#define PCNT_CH1_LCTRL_MODE_U2_V 0x3 -#define PCNT_CH1_LCTRL_MODE_U2_S 30 -/* PCNT_CH1_HCTRL_MODE_U2 : R/W ;bitpos:[29:28] ;default: 2'd0 ; */ -/*description: .*/ -#define PCNT_CH1_HCTRL_MODE_U2 0x00000003 -#define PCNT_CH1_HCTRL_MODE_U2_M ((PCNT_CH1_HCTRL_MODE_U2_V)<<(PCNT_CH1_HCTRL_MODE_U2_S)) -#define PCNT_CH1_HCTRL_MODE_U2_V 0x3 -#define PCNT_CH1_HCTRL_MODE_U2_S 28 -/* PCNT_CH1_POS_MODE_U2 : R/W ;bitpos:[27:26] ;default: 2'd0 ; */ -/*description: .*/ -#define PCNT_CH1_POS_MODE_U2 0x00000003 -#define PCNT_CH1_POS_MODE_U2_M ((PCNT_CH1_POS_MODE_U2_V)<<(PCNT_CH1_POS_MODE_U2_S)) -#define PCNT_CH1_POS_MODE_U2_V 0x3 -#define PCNT_CH1_POS_MODE_U2_S 26 -/* PCNT_CH1_NEG_MODE_U2 : R/W ;bitpos:[25:24] ;default: 2'd0 ; */ -/*description: .*/ -#define PCNT_CH1_NEG_MODE_U2 0x00000003 -#define PCNT_CH1_NEG_MODE_U2_M ((PCNT_CH1_NEG_MODE_U2_V)<<(PCNT_CH1_NEG_MODE_U2_S)) -#define PCNT_CH1_NEG_MODE_U2_V 0x3 -#define PCNT_CH1_NEG_MODE_U2_S 24 -/* PCNT_CH0_LCTRL_MODE_U2 : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: .*/ -#define PCNT_CH0_LCTRL_MODE_U2 0x00000003 -#define PCNT_CH0_LCTRL_MODE_U2_M ((PCNT_CH0_LCTRL_MODE_U2_V)<<(PCNT_CH0_LCTRL_MODE_U2_S)) -#define PCNT_CH0_LCTRL_MODE_U2_V 0x3 -#define PCNT_CH0_LCTRL_MODE_U2_S 22 -/* PCNT_CH0_HCTRL_MODE_U2 : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: .*/ -#define PCNT_CH0_HCTRL_MODE_U2 0x00000003 -#define PCNT_CH0_HCTRL_MODE_U2_M ((PCNT_CH0_HCTRL_MODE_U2_V)<<(PCNT_CH0_HCTRL_MODE_U2_S)) -#define PCNT_CH0_HCTRL_MODE_U2_V 0x3 -#define PCNT_CH0_HCTRL_MODE_U2_S 20 -/* PCNT_CH0_POS_MODE_U2 : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: .*/ -#define PCNT_CH0_POS_MODE_U2 0x00000003 -#define PCNT_CH0_POS_MODE_U2_M ((PCNT_CH0_POS_MODE_U2_V)<<(PCNT_CH0_POS_MODE_U2_S)) -#define PCNT_CH0_POS_MODE_U2_V 0x3 -#define PCNT_CH0_POS_MODE_U2_S 18 -/* PCNT_CH0_NEG_MODE_U2 : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: .*/ -#define PCNT_CH0_NEG_MODE_U2 0x00000003 -#define PCNT_CH0_NEG_MODE_U2_M ((PCNT_CH0_NEG_MODE_U2_V)<<(PCNT_CH0_NEG_MODE_U2_S)) -#define PCNT_CH0_NEG_MODE_U2_V 0x3 -#define PCNT_CH0_NEG_MODE_U2_S 16 -/* PCNT_THR_THRES1_EN_U2 : R/W ;bitpos:[15] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_THR_THRES1_EN_U2 (BIT(15)) -#define PCNT_THR_THRES1_EN_U2_M (BIT(15)) -#define PCNT_THR_THRES1_EN_U2_V 0x1 -#define PCNT_THR_THRES1_EN_U2_S 15 -/* PCNT_THR_THRES0_EN_U2 : R/W ;bitpos:[14] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_THR_THRES0_EN_U2 (BIT(14)) -#define PCNT_THR_THRES0_EN_U2_M (BIT(14)) -#define PCNT_THR_THRES0_EN_U2_V 0x1 -#define PCNT_THR_THRES0_EN_U2_S 14 -/* PCNT_THR_L_LIM_EN_U2 : R/W ;bitpos:[13] ;default: 1'b1 ; */ -/*description: .*/ -#define PCNT_THR_L_LIM_EN_U2 (BIT(13)) -#define PCNT_THR_L_LIM_EN_U2_M (BIT(13)) -#define PCNT_THR_L_LIM_EN_U2_V 0x1 -#define PCNT_THR_L_LIM_EN_U2_S 13 -/* PCNT_THR_H_LIM_EN_U2 : R/W ;bitpos:[12] ;default: 1'b1 ; */ -/*description: .*/ -#define PCNT_THR_H_LIM_EN_U2 (BIT(12)) -#define PCNT_THR_H_LIM_EN_U2_M (BIT(12)) -#define PCNT_THR_H_LIM_EN_U2_V 0x1 -#define PCNT_THR_H_LIM_EN_U2_S 12 -/* PCNT_THR_ZERO_EN_U2 : R/W ;bitpos:[11] ;default: 1'b1 ; */ -/*description: .*/ -#define PCNT_THR_ZERO_EN_U2 (BIT(11)) -#define PCNT_THR_ZERO_EN_U2_M (BIT(11)) -#define PCNT_THR_ZERO_EN_U2_V 0x1 -#define PCNT_THR_ZERO_EN_U2_S 11 -/* PCNT_FILTER_EN_U2 : R/W ;bitpos:[10] ;default: 1'b1 ; */ -/*description: .*/ -#define PCNT_FILTER_EN_U2 (BIT(10)) -#define PCNT_FILTER_EN_U2_M (BIT(10)) -#define PCNT_FILTER_EN_U2_V 0x1 -#define PCNT_FILTER_EN_U2_S 10 -/* PCNT_FILTER_THRES_U2 : R/W ;bitpos:[9:0] ;default: 10'h10 ; */ -/*description: .*/ -#define PCNT_FILTER_THRES_U2 0x000003FF -#define PCNT_FILTER_THRES_U2_M ((PCNT_FILTER_THRES_U2_V)<<(PCNT_FILTER_THRES_U2_S)) -#define PCNT_FILTER_THRES_U2_V 0x3FF +/** PCNT_U2_CONF0_REG register + * Configuration register 0 for unit 2 + */ +#define PCNT_U2_CONF0_REG (DR_REG_PCNT_BASE + 0x18) +/** PCNT_FILTER_THRES_U2 : R/W; bitpos: [9:0]; default: 16; + * This sets the maximum threshold, in APB_CLK cycles, for the filter. + * + * Any pulses with width less than this will be ignored when the filter is enabled. + */ +#define PCNT_FILTER_THRES_U2 0x000003FFU +#define PCNT_FILTER_THRES_U2_M (PCNT_FILTER_THRES_U2_V << PCNT_FILTER_THRES_U2_S) +#define PCNT_FILTER_THRES_U2_V 0x000003FFU #define PCNT_FILTER_THRES_U2_S 0 +/** PCNT_FILTER_EN_U2 : R/W; bitpos: [10]; default: 1; + * This is the enable bit for unit 2's input filter. + */ +#define PCNT_FILTER_EN_U2 (BIT(10)) +#define PCNT_FILTER_EN_U2_M (PCNT_FILTER_EN_U2_V << PCNT_FILTER_EN_U2_S) +#define PCNT_FILTER_EN_U2_V 0x00000001U +#define PCNT_FILTER_EN_U2_S 10 +/** PCNT_THR_ZERO_EN_U2 : R/W; bitpos: [11]; default: 1; + * This is the enable bit for unit 2's zero comparator. + */ +#define PCNT_THR_ZERO_EN_U2 (BIT(11)) +#define PCNT_THR_ZERO_EN_U2_M (PCNT_THR_ZERO_EN_U2_V << PCNT_THR_ZERO_EN_U2_S) +#define PCNT_THR_ZERO_EN_U2_V 0x00000001U +#define PCNT_THR_ZERO_EN_U2_S 11 +/** PCNT_THR_H_LIM_EN_U2 : R/W; bitpos: [12]; default: 1; + * This is the enable bit for unit 2's thr_h_lim comparator. + */ +#define PCNT_THR_H_LIM_EN_U2 (BIT(12)) +#define PCNT_THR_H_LIM_EN_U2_M (PCNT_THR_H_LIM_EN_U2_V << PCNT_THR_H_LIM_EN_U2_S) +#define PCNT_THR_H_LIM_EN_U2_V 0x00000001U +#define PCNT_THR_H_LIM_EN_U2_S 12 +/** PCNT_THR_L_LIM_EN_U2 : R/W; bitpos: [13]; default: 1; + * This is the enable bit for unit 2's thr_l_lim comparator. + */ +#define PCNT_THR_L_LIM_EN_U2 (BIT(13)) +#define PCNT_THR_L_LIM_EN_U2_M (PCNT_THR_L_LIM_EN_U2_V << PCNT_THR_L_LIM_EN_U2_S) +#define PCNT_THR_L_LIM_EN_U2_V 0x00000001U +#define PCNT_THR_L_LIM_EN_U2_S 13 +/** PCNT_THR_THRES0_EN_U2 : R/W; bitpos: [14]; default: 0; + * This is the enable bit for unit 2's thres0 comparator. + */ +#define PCNT_THR_THRES0_EN_U2 (BIT(14)) +#define PCNT_THR_THRES0_EN_U2_M (PCNT_THR_THRES0_EN_U2_V << PCNT_THR_THRES0_EN_U2_S) +#define PCNT_THR_THRES0_EN_U2_V 0x00000001U +#define PCNT_THR_THRES0_EN_U2_S 14 +/** PCNT_THR_THRES1_EN_U2 : R/W; bitpos: [15]; default: 0; + * This is the enable bit for unit 2's thres1 comparator. + */ +#define PCNT_THR_THRES1_EN_U2 (BIT(15)) +#define PCNT_THR_THRES1_EN_U2_M (PCNT_THR_THRES1_EN_U2_V << PCNT_THR_THRES1_EN_U2_S) +#define PCNT_THR_THRES1_EN_U2_V 0x00000001U +#define PCNT_THR_THRES1_EN_U2_S 15 +/** PCNT_CH0_NEG_MODE_U2 : R/W; bitpos: [17:16]; default: 0; + * This register sets the behavior when the signal input of channel 0 detects a + * negative edge. + * + * 1: Increase the counter;2: Decrease the counter;0, 3: No effect on counter + */ +#define PCNT_CH0_NEG_MODE_U2 0x00000003U +#define PCNT_CH0_NEG_MODE_U2_M (PCNT_CH0_NEG_MODE_U2_V << PCNT_CH0_NEG_MODE_U2_S) +#define PCNT_CH0_NEG_MODE_U2_V 0x00000003U +#define PCNT_CH0_NEG_MODE_U2_S 16 +/** PCNT_CH0_POS_MODE_U2 : R/W; bitpos: [19:18]; default: 0; + * This register sets the behavior when the signal input of channel 0 detects a + * positive edge. + * + * 1: Increase the counter;2: Decrease the counter;0, 3: No effect on counter + */ +#define PCNT_CH0_POS_MODE_U2 0x00000003U +#define PCNT_CH0_POS_MODE_U2_M (PCNT_CH0_POS_MODE_U2_V << PCNT_CH0_POS_MODE_U2_S) +#define PCNT_CH0_POS_MODE_U2_V 0x00000003U +#define PCNT_CH0_POS_MODE_U2_S 18 +/** PCNT_CH0_HCTRL_MODE_U2 : R/W; bitpos: [21:20]; default: 0; + * This register configures how the CH2_POS_MODE/CH2_NEG_MODE settings will be + * modified when the control signal is high. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ +#define PCNT_CH0_HCTRL_MODE_U2 0x00000003U +#define PCNT_CH0_HCTRL_MODE_U2_M (PCNT_CH0_HCTRL_MODE_U2_V << PCNT_CH0_HCTRL_MODE_U2_S) +#define PCNT_CH0_HCTRL_MODE_U2_V 0x00000003U +#define PCNT_CH0_HCTRL_MODE_U2_S 20 +/** PCNT_CH0_LCTRL_MODE_U2 : R/W; bitpos: [23:22]; default: 0; + * This register configures how the CH2_POS_MODE/CH2_NEG_MODE settings will be + * modified when the control signal is low. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ +#define PCNT_CH0_LCTRL_MODE_U2 0x00000003U +#define PCNT_CH0_LCTRL_MODE_U2_M (PCNT_CH0_LCTRL_MODE_U2_V << PCNT_CH0_LCTRL_MODE_U2_S) +#define PCNT_CH0_LCTRL_MODE_U2_V 0x00000003U +#define PCNT_CH0_LCTRL_MODE_U2_S 22 +/** PCNT_CH1_NEG_MODE_U2 : R/W; bitpos: [25:24]; default: 0; + * This register sets the behavior when the signal input of channel 1 detects a + * negative edge. + * + * 1: Increment the counter;2: Decrement the counter;0, 3: No effect on counter + */ +#define PCNT_CH1_NEG_MODE_U2 0x00000003U +#define PCNT_CH1_NEG_MODE_U2_M (PCNT_CH1_NEG_MODE_U2_V << PCNT_CH1_NEG_MODE_U2_S) +#define PCNT_CH1_NEG_MODE_U2_V 0x00000003U +#define PCNT_CH1_NEG_MODE_U2_S 24 +/** PCNT_CH1_POS_MODE_U2 : R/W; bitpos: [27:26]; default: 0; + * This register sets the behavior when the signal input of channel 1 detects a + * positive edge. + * + * 1: Increment the counter;2: Decrement the counter;0, 3: No effect on counter + */ +#define PCNT_CH1_POS_MODE_U2 0x00000003U +#define PCNT_CH1_POS_MODE_U2_M (PCNT_CH1_POS_MODE_U2_V << PCNT_CH1_POS_MODE_U2_S) +#define PCNT_CH1_POS_MODE_U2_V 0x00000003U +#define PCNT_CH1_POS_MODE_U2_S 26 +/** PCNT_CH1_HCTRL_MODE_U2 : R/W; bitpos: [29:28]; default: 0; + * This register configures how the CH2_POS_MODE/CH2_NEG_MODE settings will be + * modified when the control signal is high. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ +#define PCNT_CH1_HCTRL_MODE_U2 0x00000003U +#define PCNT_CH1_HCTRL_MODE_U2_M (PCNT_CH1_HCTRL_MODE_U2_V << PCNT_CH1_HCTRL_MODE_U2_S) +#define PCNT_CH1_HCTRL_MODE_U2_V 0x00000003U +#define PCNT_CH1_HCTRL_MODE_U2_S 28 +/** PCNT_CH1_LCTRL_MODE_U2 : R/W; bitpos: [31:30]; default: 0; + * This register configures how the CH2_POS_MODE/CH2_NEG_MODE settings will be + * modified when the control signal is low. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ +#define PCNT_CH1_LCTRL_MODE_U2 0x00000003U +#define PCNT_CH1_LCTRL_MODE_U2_M (PCNT_CH1_LCTRL_MODE_U2_V << PCNT_CH1_LCTRL_MODE_U2_S) +#define PCNT_CH1_LCTRL_MODE_U2_V 0x00000003U +#define PCNT_CH1_LCTRL_MODE_U2_S 30 -#define PCNT_U2_CONF1_REG (DR_REG_PCNT_BASE + 0x1C) -/* PCNT_CNT_THRES1_U2 : R/W ;bitpos:[31:16] ;default: 10'h0 ; */ -/*description: .*/ -#define PCNT_CNT_THRES1_U2 0x0000FFFF -#define PCNT_CNT_THRES1_U2_M ((PCNT_CNT_THRES1_U2_V)<<(PCNT_CNT_THRES1_U2_S)) -#define PCNT_CNT_THRES1_U2_V 0xFFFF -#define PCNT_CNT_THRES1_U2_S 16 -/* PCNT_CNT_THRES0_U2 : R/W ;bitpos:[15:0] ;default: 10'h0 ; */ -/*description: .*/ -#define PCNT_CNT_THRES0_U2 0x0000FFFF -#define PCNT_CNT_THRES0_U2_M ((PCNT_CNT_THRES0_U2_V)<<(PCNT_CNT_THRES0_U2_S)) -#define PCNT_CNT_THRES0_U2_V 0xFFFF +/** PCNT_U2_CONF1_REG register + * Configuration register 1 for unit 2 + */ +#define PCNT_U2_CONF1_REG (DR_REG_PCNT_BASE + 0x1c) +/** PCNT_CNT_THRES0_U2 : R/W; bitpos: [15:0]; default: 0; + * This register is used to configure the thres0 value for unit 2. + */ +#define PCNT_CNT_THRES0_U2 0x0000FFFFU +#define PCNT_CNT_THRES0_U2_M (PCNT_CNT_THRES0_U2_V << PCNT_CNT_THRES0_U2_S) +#define PCNT_CNT_THRES0_U2_V 0x0000FFFFU #define PCNT_CNT_THRES0_U2_S 0 +/** PCNT_CNT_THRES1_U2 : R/W; bitpos: [31:16]; default: 0; + * This register is used to configure the thres1 value for unit 2. + */ +#define PCNT_CNT_THRES1_U2 0x0000FFFFU +#define PCNT_CNT_THRES1_U2_M (PCNT_CNT_THRES1_U2_V << PCNT_CNT_THRES1_U2_S) +#define PCNT_CNT_THRES1_U2_V 0x0000FFFFU +#define PCNT_CNT_THRES1_U2_S 16 -#define PCNT_U2_CONF2_REG (DR_REG_PCNT_BASE + 0x20) -/* PCNT_CNT_L_LIM_U2 : R/W ;bitpos:[31:16] ;default: 10'h0 ; */ -/*description: .*/ -#define PCNT_CNT_L_LIM_U2 0x0000FFFF -#define PCNT_CNT_L_LIM_U2_M ((PCNT_CNT_L_LIM_U2_V)<<(PCNT_CNT_L_LIM_U2_S)) -#define PCNT_CNT_L_LIM_U2_V 0xFFFF -#define PCNT_CNT_L_LIM_U2_S 16 -/* PCNT_CNT_H_LIM_U2 : R/W ;bitpos:[15:0] ;default: 10'h0 ; */ -/*description: .*/ -#define PCNT_CNT_H_LIM_U2 0x0000FFFF -#define PCNT_CNT_H_LIM_U2_M ((PCNT_CNT_H_LIM_U2_V)<<(PCNT_CNT_H_LIM_U2_S)) -#define PCNT_CNT_H_LIM_U2_V 0xFFFF +/** PCNT_U2_CONF2_REG register + * Configuration register 2 for unit 2 + */ +#define PCNT_U2_CONF2_REG (DR_REG_PCNT_BASE + 0x20) +/** PCNT_CNT_H_LIM_U2 : R/W; bitpos: [15:0]; default: 0; + * This register is used to configure the thr_h_lim value for unit 2. + */ +#define PCNT_CNT_H_LIM_U2 0x0000FFFFU +#define PCNT_CNT_H_LIM_U2_M (PCNT_CNT_H_LIM_U2_V << PCNT_CNT_H_LIM_U2_S) +#define PCNT_CNT_H_LIM_U2_V 0x0000FFFFU #define PCNT_CNT_H_LIM_U2_S 0 +/** PCNT_CNT_L_LIM_U2 : R/W; bitpos: [31:16]; default: 0; + * This register is used to configure the thr_l_lim value for unit 2. + */ +#define PCNT_CNT_L_LIM_U2 0x0000FFFFU +#define PCNT_CNT_L_LIM_U2_M (PCNT_CNT_L_LIM_U2_V << PCNT_CNT_L_LIM_U2_S) +#define PCNT_CNT_L_LIM_U2_V 0x0000FFFFU +#define PCNT_CNT_L_LIM_U2_S 16 -#define PCNT_U3_CONF0_REG (DR_REG_PCNT_BASE + 0x24) -/* PCNT_CH1_LCTRL_MODE_U3 : R/W ;bitpos:[31:30] ;default: 2'd0 ; */ -/*description: .*/ -#define PCNT_CH1_LCTRL_MODE_U3 0x00000003 -#define PCNT_CH1_LCTRL_MODE_U3_M ((PCNT_CH1_LCTRL_MODE_U3_V)<<(PCNT_CH1_LCTRL_MODE_U3_S)) -#define PCNT_CH1_LCTRL_MODE_U3_V 0x3 -#define PCNT_CH1_LCTRL_MODE_U3_S 30 -/* PCNT_CH1_HCTRL_MODE_U3 : R/W ;bitpos:[29:28] ;default: 2'd0 ; */ -/*description: .*/ -#define PCNT_CH1_HCTRL_MODE_U3 0x00000003 -#define PCNT_CH1_HCTRL_MODE_U3_M ((PCNT_CH1_HCTRL_MODE_U3_V)<<(PCNT_CH1_HCTRL_MODE_U3_S)) -#define PCNT_CH1_HCTRL_MODE_U3_V 0x3 -#define PCNT_CH1_HCTRL_MODE_U3_S 28 -/* PCNT_CH1_POS_MODE_U3 : R/W ;bitpos:[27:26] ;default: 2'd0 ; */ -/*description: .*/ -#define PCNT_CH1_POS_MODE_U3 0x00000003 -#define PCNT_CH1_POS_MODE_U3_M ((PCNT_CH1_POS_MODE_U3_V)<<(PCNT_CH1_POS_MODE_U3_S)) -#define PCNT_CH1_POS_MODE_U3_V 0x3 -#define PCNT_CH1_POS_MODE_U3_S 26 -/* PCNT_CH1_NEG_MODE_U3 : R/W ;bitpos:[25:24] ;default: 2'd0 ; */ -/*description: .*/ -#define PCNT_CH1_NEG_MODE_U3 0x00000003 -#define PCNT_CH1_NEG_MODE_U3_M ((PCNT_CH1_NEG_MODE_U3_V)<<(PCNT_CH1_NEG_MODE_U3_S)) -#define PCNT_CH1_NEG_MODE_U3_V 0x3 -#define PCNT_CH1_NEG_MODE_U3_S 24 -/* PCNT_CH0_LCTRL_MODE_U3 : R/W ;bitpos:[23:22] ;default: 2'd0 ; */ -/*description: .*/ -#define PCNT_CH0_LCTRL_MODE_U3 0x00000003 -#define PCNT_CH0_LCTRL_MODE_U3_M ((PCNT_CH0_LCTRL_MODE_U3_V)<<(PCNT_CH0_LCTRL_MODE_U3_S)) -#define PCNT_CH0_LCTRL_MODE_U3_V 0x3 -#define PCNT_CH0_LCTRL_MODE_U3_S 22 -/* PCNT_CH0_HCTRL_MODE_U3 : R/W ;bitpos:[21:20] ;default: 2'd0 ; */ -/*description: .*/ -#define PCNT_CH0_HCTRL_MODE_U3 0x00000003 -#define PCNT_CH0_HCTRL_MODE_U3_M ((PCNT_CH0_HCTRL_MODE_U3_V)<<(PCNT_CH0_HCTRL_MODE_U3_S)) -#define PCNT_CH0_HCTRL_MODE_U3_V 0x3 -#define PCNT_CH0_HCTRL_MODE_U3_S 20 -/* PCNT_CH0_POS_MODE_U3 : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: .*/ -#define PCNT_CH0_POS_MODE_U3 0x00000003 -#define PCNT_CH0_POS_MODE_U3_M ((PCNT_CH0_POS_MODE_U3_V)<<(PCNT_CH0_POS_MODE_U3_S)) -#define PCNT_CH0_POS_MODE_U3_V 0x3 -#define PCNT_CH0_POS_MODE_U3_S 18 -/* PCNT_CH0_NEG_MODE_U3 : R/W ;bitpos:[17:16] ;default: 2'd0 ; */ -/*description: .*/ -#define PCNT_CH0_NEG_MODE_U3 0x00000003 -#define PCNT_CH0_NEG_MODE_U3_M ((PCNT_CH0_NEG_MODE_U3_V)<<(PCNT_CH0_NEG_MODE_U3_S)) -#define PCNT_CH0_NEG_MODE_U3_V 0x3 -#define PCNT_CH0_NEG_MODE_U3_S 16 -/* PCNT_THR_THRES1_EN_U3 : R/W ;bitpos:[15] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_THR_THRES1_EN_U3 (BIT(15)) -#define PCNT_THR_THRES1_EN_U3_M (BIT(15)) -#define PCNT_THR_THRES1_EN_U3_V 0x1 -#define PCNT_THR_THRES1_EN_U3_S 15 -/* PCNT_THR_THRES0_EN_U3 : R/W ;bitpos:[14] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_THR_THRES0_EN_U3 (BIT(14)) -#define PCNT_THR_THRES0_EN_U3_M (BIT(14)) -#define PCNT_THR_THRES0_EN_U3_V 0x1 -#define PCNT_THR_THRES0_EN_U3_S 14 -/* PCNT_THR_L_LIM_EN_U3 : R/W ;bitpos:[13] ;default: 1'b1 ; */ -/*description: .*/ -#define PCNT_THR_L_LIM_EN_U3 (BIT(13)) -#define PCNT_THR_L_LIM_EN_U3_M (BIT(13)) -#define PCNT_THR_L_LIM_EN_U3_V 0x1 -#define PCNT_THR_L_LIM_EN_U3_S 13 -/* PCNT_THR_H_LIM_EN_U3 : R/W ;bitpos:[12] ;default: 1'b1 ; */ -/*description: .*/ -#define PCNT_THR_H_LIM_EN_U3 (BIT(12)) -#define PCNT_THR_H_LIM_EN_U3_M (BIT(12)) -#define PCNT_THR_H_LIM_EN_U3_V 0x1 -#define PCNT_THR_H_LIM_EN_U3_S 12 -/* PCNT_THR_ZERO_EN_U3 : R/W ;bitpos:[11] ;default: 1'b1 ; */ -/*description: .*/ -#define PCNT_THR_ZERO_EN_U3 (BIT(11)) -#define PCNT_THR_ZERO_EN_U3_M (BIT(11)) -#define PCNT_THR_ZERO_EN_U3_V 0x1 -#define PCNT_THR_ZERO_EN_U3_S 11 -/* PCNT_FILTER_EN_U3 : R/W ;bitpos:[10] ;default: 1'b1 ; */ -/*description: .*/ -#define PCNT_FILTER_EN_U3 (BIT(10)) -#define PCNT_FILTER_EN_U3_M (BIT(10)) -#define PCNT_FILTER_EN_U3_V 0x1 -#define PCNT_FILTER_EN_U3_S 10 -/* PCNT_FILTER_THRES_U3 : R/W ;bitpos:[9:0] ;default: 10'h10 ; */ -/*description: .*/ -#define PCNT_FILTER_THRES_U3 0x000003FF -#define PCNT_FILTER_THRES_U3_M ((PCNT_FILTER_THRES_U3_V)<<(PCNT_FILTER_THRES_U3_S)) -#define PCNT_FILTER_THRES_U3_V 0x3FF +/** PCNT_U3_CONF0_REG register + * Configuration register 0 for unit 3 + */ +#define PCNT_U3_CONF0_REG (DR_REG_PCNT_BASE + 0x24) +/** PCNT_FILTER_THRES_U3 : R/W; bitpos: [9:0]; default: 16; + * This sets the maximum threshold, in APB_CLK cycles, for the filter. + * + * Any pulses with width less than this will be ignored when the filter is enabled. + */ +#define PCNT_FILTER_THRES_U3 0x000003FFU +#define PCNT_FILTER_THRES_U3_M (PCNT_FILTER_THRES_U3_V << PCNT_FILTER_THRES_U3_S) +#define PCNT_FILTER_THRES_U3_V 0x000003FFU #define PCNT_FILTER_THRES_U3_S 0 +/** PCNT_FILTER_EN_U3 : R/W; bitpos: [10]; default: 1; + * This is the enable bit for unit 3's input filter. + */ +#define PCNT_FILTER_EN_U3 (BIT(10)) +#define PCNT_FILTER_EN_U3_M (PCNT_FILTER_EN_U3_V << PCNT_FILTER_EN_U3_S) +#define PCNT_FILTER_EN_U3_V 0x00000001U +#define PCNT_FILTER_EN_U3_S 10 +/** PCNT_THR_ZERO_EN_U3 : R/W; bitpos: [11]; default: 1; + * This is the enable bit for unit 3's zero comparator. + */ +#define PCNT_THR_ZERO_EN_U3 (BIT(11)) +#define PCNT_THR_ZERO_EN_U3_M (PCNT_THR_ZERO_EN_U3_V << PCNT_THR_ZERO_EN_U3_S) +#define PCNT_THR_ZERO_EN_U3_V 0x00000001U +#define PCNT_THR_ZERO_EN_U3_S 11 +/** PCNT_THR_H_LIM_EN_U3 : R/W; bitpos: [12]; default: 1; + * This is the enable bit for unit 3's thr_h_lim comparator. + */ +#define PCNT_THR_H_LIM_EN_U3 (BIT(12)) +#define PCNT_THR_H_LIM_EN_U3_M (PCNT_THR_H_LIM_EN_U3_V << PCNT_THR_H_LIM_EN_U3_S) +#define PCNT_THR_H_LIM_EN_U3_V 0x00000001U +#define PCNT_THR_H_LIM_EN_U3_S 12 +/** PCNT_THR_L_LIM_EN_U3 : R/W; bitpos: [13]; default: 1; + * This is the enable bit for unit 3's thr_l_lim comparator. + */ +#define PCNT_THR_L_LIM_EN_U3 (BIT(13)) +#define PCNT_THR_L_LIM_EN_U3_M (PCNT_THR_L_LIM_EN_U3_V << PCNT_THR_L_LIM_EN_U3_S) +#define PCNT_THR_L_LIM_EN_U3_V 0x00000001U +#define PCNT_THR_L_LIM_EN_U3_S 13 +/** PCNT_THR_THRES0_EN_U3 : R/W; bitpos: [14]; default: 0; + * This is the enable bit for unit 3's thres0 comparator. + */ +#define PCNT_THR_THRES0_EN_U3 (BIT(14)) +#define PCNT_THR_THRES0_EN_U3_M (PCNT_THR_THRES0_EN_U3_V << PCNT_THR_THRES0_EN_U3_S) +#define PCNT_THR_THRES0_EN_U3_V 0x00000001U +#define PCNT_THR_THRES0_EN_U3_S 14 +/** PCNT_THR_THRES1_EN_U3 : R/W; bitpos: [15]; default: 0; + * This is the enable bit for unit 3's thres1 comparator. + */ +#define PCNT_THR_THRES1_EN_U3 (BIT(15)) +#define PCNT_THR_THRES1_EN_U3_M (PCNT_THR_THRES1_EN_U3_V << PCNT_THR_THRES1_EN_U3_S) +#define PCNT_THR_THRES1_EN_U3_V 0x00000001U +#define PCNT_THR_THRES1_EN_U3_S 15 +/** PCNT_CH0_NEG_MODE_U3 : R/W; bitpos: [17:16]; default: 0; + * This register sets the behavior when the signal input of channel 0 detects a + * negative edge. + * + * 1: Increase the counter;2: Decrease the counter;0, 3: No effect on counter + */ +#define PCNT_CH0_NEG_MODE_U3 0x00000003U +#define PCNT_CH0_NEG_MODE_U3_M (PCNT_CH0_NEG_MODE_U3_V << PCNT_CH0_NEG_MODE_U3_S) +#define PCNT_CH0_NEG_MODE_U3_V 0x00000003U +#define PCNT_CH0_NEG_MODE_U3_S 16 +/** PCNT_CH0_POS_MODE_U3 : R/W; bitpos: [19:18]; default: 0; + * This register sets the behavior when the signal input of channel 0 detects a + * positive edge. + * + * 1: Increase the counter;2: Decrease the counter;0, 3: No effect on counter + */ +#define PCNT_CH0_POS_MODE_U3 0x00000003U +#define PCNT_CH0_POS_MODE_U3_M (PCNT_CH0_POS_MODE_U3_V << PCNT_CH0_POS_MODE_U3_S) +#define PCNT_CH0_POS_MODE_U3_V 0x00000003U +#define PCNT_CH0_POS_MODE_U3_S 18 +/** PCNT_CH0_HCTRL_MODE_U3 : R/W; bitpos: [21:20]; default: 0; + * This register configures how the CH3_POS_MODE/CH3_NEG_MODE settings will be + * modified when the control signal is high. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ +#define PCNT_CH0_HCTRL_MODE_U3 0x00000003U +#define PCNT_CH0_HCTRL_MODE_U3_M (PCNT_CH0_HCTRL_MODE_U3_V << PCNT_CH0_HCTRL_MODE_U3_S) +#define PCNT_CH0_HCTRL_MODE_U3_V 0x00000003U +#define PCNT_CH0_HCTRL_MODE_U3_S 20 +/** PCNT_CH0_LCTRL_MODE_U3 : R/W; bitpos: [23:22]; default: 0; + * This register configures how the CH3_POS_MODE/CH3_NEG_MODE settings will be + * modified when the control signal is low. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ +#define PCNT_CH0_LCTRL_MODE_U3 0x00000003U +#define PCNT_CH0_LCTRL_MODE_U3_M (PCNT_CH0_LCTRL_MODE_U3_V << PCNT_CH0_LCTRL_MODE_U3_S) +#define PCNT_CH0_LCTRL_MODE_U3_V 0x00000003U +#define PCNT_CH0_LCTRL_MODE_U3_S 22 +/** PCNT_CH1_NEG_MODE_U3 : R/W; bitpos: [25:24]; default: 0; + * This register sets the behavior when the signal input of channel 1 detects a + * negative edge. + * + * 1: Increment the counter;2: Decrement the counter;0, 3: No effect on counter + */ +#define PCNT_CH1_NEG_MODE_U3 0x00000003U +#define PCNT_CH1_NEG_MODE_U3_M (PCNT_CH1_NEG_MODE_U3_V << PCNT_CH1_NEG_MODE_U3_S) +#define PCNT_CH1_NEG_MODE_U3_V 0x00000003U +#define PCNT_CH1_NEG_MODE_U3_S 24 +/** PCNT_CH1_POS_MODE_U3 : R/W; bitpos: [27:26]; default: 0; + * This register sets the behavior when the signal input of channel 1 detects a + * positive edge. + * + * 1: Increment the counter;2: Decrement the counter;0, 3: No effect on counter + */ +#define PCNT_CH1_POS_MODE_U3 0x00000003U +#define PCNT_CH1_POS_MODE_U3_M (PCNT_CH1_POS_MODE_U3_V << PCNT_CH1_POS_MODE_U3_S) +#define PCNT_CH1_POS_MODE_U3_V 0x00000003U +#define PCNT_CH1_POS_MODE_U3_S 26 +/** PCNT_CH1_HCTRL_MODE_U3 : R/W; bitpos: [29:28]; default: 0; + * This register configures how the CH3_POS_MODE/CH3_NEG_MODE settings will be + * modified when the control signal is high. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ +#define PCNT_CH1_HCTRL_MODE_U3 0x00000003U +#define PCNT_CH1_HCTRL_MODE_U3_M (PCNT_CH1_HCTRL_MODE_U3_V << PCNT_CH1_HCTRL_MODE_U3_S) +#define PCNT_CH1_HCTRL_MODE_U3_V 0x00000003U +#define PCNT_CH1_HCTRL_MODE_U3_S 28 +/** PCNT_CH1_LCTRL_MODE_U3 : R/W; bitpos: [31:30]; default: 0; + * This register configures how the CH3_POS_MODE/CH3_NEG_MODE settings will be + * modified when the control signal is low. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ +#define PCNT_CH1_LCTRL_MODE_U3 0x00000003U +#define PCNT_CH1_LCTRL_MODE_U3_M (PCNT_CH1_LCTRL_MODE_U3_V << PCNT_CH1_LCTRL_MODE_U3_S) +#define PCNT_CH1_LCTRL_MODE_U3_V 0x00000003U +#define PCNT_CH1_LCTRL_MODE_U3_S 30 -#define PCNT_U3_CONF1_REG (DR_REG_PCNT_BASE + 0x28) -/* PCNT_CNT_THRES1_U3 : R/W ;bitpos:[31:16] ;default: 10'h0 ; */ -/*description: .*/ -#define PCNT_CNT_THRES1_U3 0x0000FFFF -#define PCNT_CNT_THRES1_U3_M ((PCNT_CNT_THRES1_U3_V)<<(PCNT_CNT_THRES1_U3_S)) -#define PCNT_CNT_THRES1_U3_V 0xFFFF -#define PCNT_CNT_THRES1_U3_S 16 -/* PCNT_CNT_THRES0_U3 : R/W ;bitpos:[15:0] ;default: 10'h0 ; */ -/*description: .*/ -#define PCNT_CNT_THRES0_U3 0x0000FFFF -#define PCNT_CNT_THRES0_U3_M ((PCNT_CNT_THRES0_U3_V)<<(PCNT_CNT_THRES0_U3_S)) -#define PCNT_CNT_THRES0_U3_V 0xFFFF +/** PCNT_U3_CONF1_REG register + * Configuration register 1 for unit 3 + */ +#define PCNT_U3_CONF1_REG (DR_REG_PCNT_BASE + 0x28) +/** PCNT_CNT_THRES0_U3 : R/W; bitpos: [15:0]; default: 0; + * This register is used to configure the thres0 value for unit 3. + */ +#define PCNT_CNT_THRES0_U3 0x0000FFFFU +#define PCNT_CNT_THRES0_U3_M (PCNT_CNT_THRES0_U3_V << PCNT_CNT_THRES0_U3_S) +#define PCNT_CNT_THRES0_U3_V 0x0000FFFFU #define PCNT_CNT_THRES0_U3_S 0 +/** PCNT_CNT_THRES1_U3 : R/W; bitpos: [31:16]; default: 0; + * This register is used to configure the thres1 value for unit 3. + */ +#define PCNT_CNT_THRES1_U3 0x0000FFFFU +#define PCNT_CNT_THRES1_U3_M (PCNT_CNT_THRES1_U3_V << PCNT_CNT_THRES1_U3_S) +#define PCNT_CNT_THRES1_U3_V 0x0000FFFFU +#define PCNT_CNT_THRES1_U3_S 16 -#define PCNT_U3_CONF2_REG (DR_REG_PCNT_BASE + 0x2C) -/* PCNT_CNT_L_LIM_U3 : R/W ;bitpos:[31:16] ;default: 10'h0 ; */ -/*description: .*/ -#define PCNT_CNT_L_LIM_U3 0x0000FFFF -#define PCNT_CNT_L_LIM_U3_M ((PCNT_CNT_L_LIM_U3_V)<<(PCNT_CNT_L_LIM_U3_S)) -#define PCNT_CNT_L_LIM_U3_V 0xFFFF -#define PCNT_CNT_L_LIM_U3_S 16 -/* PCNT_CNT_H_LIM_U3 : R/W ;bitpos:[15:0] ;default: 10'h0 ; */ -/*description: .*/ -#define PCNT_CNT_H_LIM_U3 0x0000FFFF -#define PCNT_CNT_H_LIM_U3_M ((PCNT_CNT_H_LIM_U3_V)<<(PCNT_CNT_H_LIM_U3_S)) -#define PCNT_CNT_H_LIM_U3_V 0xFFFF +/** PCNT_U3_CONF2_REG register + * Configuration register 2 for unit 3 + */ +#define PCNT_U3_CONF2_REG (DR_REG_PCNT_BASE + 0x2c) +/** PCNT_CNT_H_LIM_U3 : R/W; bitpos: [15:0]; default: 0; + * This register is used to configure the thr_h_lim value for unit 3. + */ +#define PCNT_CNT_H_LIM_U3 0x0000FFFFU +#define PCNT_CNT_H_LIM_U3_M (PCNT_CNT_H_LIM_U3_V << PCNT_CNT_H_LIM_U3_S) +#define PCNT_CNT_H_LIM_U3_V 0x0000FFFFU #define PCNT_CNT_H_LIM_U3_S 0 +/** PCNT_CNT_L_LIM_U3 : R/W; bitpos: [31:16]; default: 0; + * This register is used to configure the thr_l_lim value for unit 3. + */ +#define PCNT_CNT_L_LIM_U3 0x0000FFFFU +#define PCNT_CNT_L_LIM_U3_M (PCNT_CNT_L_LIM_U3_V << PCNT_CNT_L_LIM_U3_S) +#define PCNT_CNT_L_LIM_U3_V 0x0000FFFFU +#define PCNT_CNT_L_LIM_U3_S 16 -#define PCNT_U0_CNT_REG (DR_REG_PCNT_BASE + 0x30) -/* PCNT_PULSE_CNT_U0 : RO ;bitpos:[15:0] ;default: 16'h0 ; */ -/*description: .*/ -#define PCNT_PULSE_CNT_U0 0x0000FFFF -#define PCNT_PULSE_CNT_U0_M ((PCNT_PULSE_CNT_U0_V)<<(PCNT_PULSE_CNT_U0_S)) -#define PCNT_PULSE_CNT_U0_V 0xFFFF +/** PCNT_U0_CNT_REG register + * Counter value for unit 0 + */ +#define PCNT_U0_CNT_REG (DR_REG_PCNT_BASE + 0x30) +/** PCNT_PULSE_CNT_U0 : RO; bitpos: [15:0]; default: 0; + * This register stores the current pulse count value for unit 0. + */ +#define PCNT_PULSE_CNT_U0 0x0000FFFFU +#define PCNT_PULSE_CNT_U0_M (PCNT_PULSE_CNT_U0_V << PCNT_PULSE_CNT_U0_S) +#define PCNT_PULSE_CNT_U0_V 0x0000FFFFU #define PCNT_PULSE_CNT_U0_S 0 -#define PCNT_U1_CNT_REG (DR_REG_PCNT_BASE + 0x34) -/* PCNT_PULSE_CNT_U1 : RO ;bitpos:[15:0] ;default: 16'h0 ; */ -/*description: .*/ -#define PCNT_PULSE_CNT_U1 0x0000FFFF -#define PCNT_PULSE_CNT_U1_M ((PCNT_PULSE_CNT_U1_V)<<(PCNT_PULSE_CNT_U1_S)) -#define PCNT_PULSE_CNT_U1_V 0xFFFF +/** PCNT_U1_CNT_REG register + * Counter value for unit 1 + */ +#define PCNT_U1_CNT_REG (DR_REG_PCNT_BASE + 0x34) +/** PCNT_PULSE_CNT_U1 : RO; bitpos: [15:0]; default: 0; + * This register stores the current pulse count value for unit 1. + */ +#define PCNT_PULSE_CNT_U1 0x0000FFFFU +#define PCNT_PULSE_CNT_U1_M (PCNT_PULSE_CNT_U1_V << PCNT_PULSE_CNT_U1_S) +#define PCNT_PULSE_CNT_U1_V 0x0000FFFFU #define PCNT_PULSE_CNT_U1_S 0 -#define PCNT_U2_CNT_REG (DR_REG_PCNT_BASE + 0x38) -/* PCNT_PULSE_CNT_U2 : RO ;bitpos:[15:0] ;default: 16'h0 ; */ -/*description: .*/ -#define PCNT_PULSE_CNT_U2 0x0000FFFF -#define PCNT_PULSE_CNT_U2_M ((PCNT_PULSE_CNT_U2_V)<<(PCNT_PULSE_CNT_U2_S)) -#define PCNT_PULSE_CNT_U2_V 0xFFFF +/** PCNT_U2_CNT_REG register + * Counter value for unit 2 + */ +#define PCNT_U2_CNT_REG (DR_REG_PCNT_BASE + 0x38) +/** PCNT_PULSE_CNT_U2 : RO; bitpos: [15:0]; default: 0; + * This register stores the current pulse count value for unit 2. + */ +#define PCNT_PULSE_CNT_U2 0x0000FFFFU +#define PCNT_PULSE_CNT_U2_M (PCNT_PULSE_CNT_U2_V << PCNT_PULSE_CNT_U2_S) +#define PCNT_PULSE_CNT_U2_V 0x0000FFFFU #define PCNT_PULSE_CNT_U2_S 0 -#define PCNT_U3_CNT_REG (DR_REG_PCNT_BASE + 0x3C) -/* PCNT_PULSE_CNT_U3 : RO ;bitpos:[15:0] ;default: 16'h0 ; */ -/*description: .*/ -#define PCNT_PULSE_CNT_U3 0x0000FFFF -#define PCNT_PULSE_CNT_U3_M ((PCNT_PULSE_CNT_U3_V)<<(PCNT_PULSE_CNT_U3_S)) -#define PCNT_PULSE_CNT_U3_V 0xFFFF +/** PCNT_U3_CNT_REG register + * Counter value for unit 3 + */ +#define PCNT_U3_CNT_REG (DR_REG_PCNT_BASE + 0x3c) +/** PCNT_PULSE_CNT_U3 : RO; bitpos: [15:0]; default: 0; + * This register stores the current pulse count value for unit 3. + */ +#define PCNT_PULSE_CNT_U3 0x0000FFFFU +#define PCNT_PULSE_CNT_U3_M (PCNT_PULSE_CNT_U3_V << PCNT_PULSE_CNT_U3_S) +#define PCNT_PULSE_CNT_U3_V 0x0000FFFFU #define PCNT_PULSE_CNT_U3_S 0 -#define PCNT_INT_RAW_REG (DR_REG_PCNT_BASE + 0x40) -/* PCNT_CNT_THR_EVENT_U3_INT_RAW : RO ;bitpos:[3] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_EVENT_U3_INT_RAW (BIT(3)) -#define PCNT_CNT_THR_EVENT_U3_INT_RAW_M (BIT(3)) -#define PCNT_CNT_THR_EVENT_U3_INT_RAW_V 0x1 -#define PCNT_CNT_THR_EVENT_U3_INT_RAW_S 3 -/* PCNT_CNT_THR_EVENT_U2_INT_RAW : RO ;bitpos:[2] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_EVENT_U2_INT_RAW (BIT(2)) -#define PCNT_CNT_THR_EVENT_U2_INT_RAW_M (BIT(2)) -#define PCNT_CNT_THR_EVENT_U2_INT_RAW_V 0x1 -#define PCNT_CNT_THR_EVENT_U2_INT_RAW_S 2 -/* PCNT_CNT_THR_EVENT_U1_INT_RAW : RO ;bitpos:[1] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_EVENT_U1_INT_RAW (BIT(1)) -#define PCNT_CNT_THR_EVENT_U1_INT_RAW_M (BIT(1)) -#define PCNT_CNT_THR_EVENT_U1_INT_RAW_V 0x1 -#define PCNT_CNT_THR_EVENT_U1_INT_RAW_S 1 -/* PCNT_CNT_THR_EVENT_U0_INT_RAW : RO ;bitpos:[0] ;default: 1'b0 ; */ -/*description: .*/ +/** PCNT_INT_RAW_REG register + * Interrupt raw status register + */ +#define PCNT_INT_RAW_REG (DR_REG_PCNT_BASE + 0x40) +/** PCNT_CNT_THR_EVENT_U0_INT_RAW : RO; bitpos: [0]; default: 0; + * The raw interrupt status bit for the PCNT_CNT_THR_EVENT_U0_INT interrupt. + */ #define PCNT_CNT_THR_EVENT_U0_INT_RAW (BIT(0)) -#define PCNT_CNT_THR_EVENT_U0_INT_RAW_M (BIT(0)) -#define PCNT_CNT_THR_EVENT_U0_INT_RAW_V 0x1 +#define PCNT_CNT_THR_EVENT_U0_INT_RAW_M (PCNT_CNT_THR_EVENT_U0_INT_RAW_V << PCNT_CNT_THR_EVENT_U0_INT_RAW_S) +#define PCNT_CNT_THR_EVENT_U0_INT_RAW_V 0x00000001U #define PCNT_CNT_THR_EVENT_U0_INT_RAW_S 0 +/** PCNT_CNT_THR_EVENT_U1_INT_RAW : RO; bitpos: [1]; default: 0; + * The raw interrupt status bit for the PCNT_CNT_THR_EVENT_U1_INT interrupt. + */ +#define PCNT_CNT_THR_EVENT_U1_INT_RAW (BIT(1)) +#define PCNT_CNT_THR_EVENT_U1_INT_RAW_M (PCNT_CNT_THR_EVENT_U1_INT_RAW_V << PCNT_CNT_THR_EVENT_U1_INT_RAW_S) +#define PCNT_CNT_THR_EVENT_U1_INT_RAW_V 0x00000001U +#define PCNT_CNT_THR_EVENT_U1_INT_RAW_S 1 +/** PCNT_CNT_THR_EVENT_U2_INT_RAW : RO; bitpos: [2]; default: 0; + * The raw interrupt status bit for the PCNT_CNT_THR_EVENT_U2_INT interrupt. + */ +#define PCNT_CNT_THR_EVENT_U2_INT_RAW (BIT(2)) +#define PCNT_CNT_THR_EVENT_U2_INT_RAW_M (PCNT_CNT_THR_EVENT_U2_INT_RAW_V << PCNT_CNT_THR_EVENT_U2_INT_RAW_S) +#define PCNT_CNT_THR_EVENT_U2_INT_RAW_V 0x00000001U +#define PCNT_CNT_THR_EVENT_U2_INT_RAW_S 2 +/** PCNT_CNT_THR_EVENT_U3_INT_RAW : RO; bitpos: [3]; default: 0; + * The raw interrupt status bit for the PCNT_CNT_THR_EVENT_U3_INT interrupt. + */ +#define PCNT_CNT_THR_EVENT_U3_INT_RAW (BIT(3)) +#define PCNT_CNT_THR_EVENT_U3_INT_RAW_M (PCNT_CNT_THR_EVENT_U3_INT_RAW_V << PCNT_CNT_THR_EVENT_U3_INT_RAW_S) +#define PCNT_CNT_THR_EVENT_U3_INT_RAW_V 0x00000001U +#define PCNT_CNT_THR_EVENT_U3_INT_RAW_S 3 -#define PCNT_INT_ST_REG (DR_REG_PCNT_BASE + 0x44) -/* PCNT_CNT_THR_EVENT_U3_INT_ST : RO ;bitpos:[3] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_EVENT_U3_INT_ST (BIT(3)) -#define PCNT_CNT_THR_EVENT_U3_INT_ST_M (BIT(3)) -#define PCNT_CNT_THR_EVENT_U3_INT_ST_V 0x1 -#define PCNT_CNT_THR_EVENT_U3_INT_ST_S 3 -/* PCNT_CNT_THR_EVENT_U2_INT_ST : RO ;bitpos:[2] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_EVENT_U2_INT_ST (BIT(2)) -#define PCNT_CNT_THR_EVENT_U2_INT_ST_M (BIT(2)) -#define PCNT_CNT_THR_EVENT_U2_INT_ST_V 0x1 -#define PCNT_CNT_THR_EVENT_U2_INT_ST_S 2 -/* PCNT_CNT_THR_EVENT_U1_INT_ST : RO ;bitpos:[1] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_EVENT_U1_INT_ST (BIT(1)) -#define PCNT_CNT_THR_EVENT_U1_INT_ST_M (BIT(1)) -#define PCNT_CNT_THR_EVENT_U1_INT_ST_V 0x1 -#define PCNT_CNT_THR_EVENT_U1_INT_ST_S 1 -/* PCNT_CNT_THR_EVENT_U0_INT_ST : RO ;bitpos:[0] ;default: 1'b0 ; */ -/*description: .*/ +/** PCNT_INT_ST_REG register + * Interrupt status register + */ +#define PCNT_INT_ST_REG (DR_REG_PCNT_BASE + 0x44) +/** PCNT_CNT_THR_EVENT_U0_INT_ST : RO; bitpos: [0]; default: 0; + * The masked interrupt status bit for the PCNT_CNT_THR_EVENT_U0_INT interrupt. + */ #define PCNT_CNT_THR_EVENT_U0_INT_ST (BIT(0)) -#define PCNT_CNT_THR_EVENT_U0_INT_ST_M (BIT(0)) -#define PCNT_CNT_THR_EVENT_U0_INT_ST_V 0x1 +#define PCNT_CNT_THR_EVENT_U0_INT_ST_M (PCNT_CNT_THR_EVENT_U0_INT_ST_V << PCNT_CNT_THR_EVENT_U0_INT_ST_S) +#define PCNT_CNT_THR_EVENT_U0_INT_ST_V 0x00000001U #define PCNT_CNT_THR_EVENT_U0_INT_ST_S 0 +/** PCNT_CNT_THR_EVENT_U1_INT_ST : RO; bitpos: [1]; default: 0; + * The masked interrupt status bit for the PCNT_CNT_THR_EVENT_U1_INT interrupt. + */ +#define PCNT_CNT_THR_EVENT_U1_INT_ST (BIT(1)) +#define PCNT_CNT_THR_EVENT_U1_INT_ST_M (PCNT_CNT_THR_EVENT_U1_INT_ST_V << PCNT_CNT_THR_EVENT_U1_INT_ST_S) +#define PCNT_CNT_THR_EVENT_U1_INT_ST_V 0x00000001U +#define PCNT_CNT_THR_EVENT_U1_INT_ST_S 1 +/** PCNT_CNT_THR_EVENT_U2_INT_ST : RO; bitpos: [2]; default: 0; + * The masked interrupt status bit for the PCNT_CNT_THR_EVENT_U2_INT interrupt. + */ +#define PCNT_CNT_THR_EVENT_U2_INT_ST (BIT(2)) +#define PCNT_CNT_THR_EVENT_U2_INT_ST_M (PCNT_CNT_THR_EVENT_U2_INT_ST_V << PCNT_CNT_THR_EVENT_U2_INT_ST_S) +#define PCNT_CNT_THR_EVENT_U2_INT_ST_V 0x00000001U +#define PCNT_CNT_THR_EVENT_U2_INT_ST_S 2 +/** PCNT_CNT_THR_EVENT_U3_INT_ST : RO; bitpos: [3]; default: 0; + * The masked interrupt status bit for the PCNT_CNT_THR_EVENT_U3_INT interrupt. + */ +#define PCNT_CNT_THR_EVENT_U3_INT_ST (BIT(3)) +#define PCNT_CNT_THR_EVENT_U3_INT_ST_M (PCNT_CNT_THR_EVENT_U3_INT_ST_V << PCNT_CNT_THR_EVENT_U3_INT_ST_S) +#define PCNT_CNT_THR_EVENT_U3_INT_ST_V 0x00000001U +#define PCNT_CNT_THR_EVENT_U3_INT_ST_S 3 -#define PCNT_INT_ENA_REG (DR_REG_PCNT_BASE + 0x48) -/* PCNT_CNT_THR_EVENT_U3_INT_ENA : R/W ;bitpos:[3] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_EVENT_U3_INT_ENA (BIT(3)) -#define PCNT_CNT_THR_EVENT_U3_INT_ENA_M (BIT(3)) -#define PCNT_CNT_THR_EVENT_U3_INT_ENA_V 0x1 -#define PCNT_CNT_THR_EVENT_U3_INT_ENA_S 3 -/* PCNT_CNT_THR_EVENT_U2_INT_ENA : R/W ;bitpos:[2] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_EVENT_U2_INT_ENA (BIT(2)) -#define PCNT_CNT_THR_EVENT_U2_INT_ENA_M (BIT(2)) -#define PCNT_CNT_THR_EVENT_U2_INT_ENA_V 0x1 -#define PCNT_CNT_THR_EVENT_U2_INT_ENA_S 2 -/* PCNT_CNT_THR_EVENT_U1_INT_ENA : R/W ;bitpos:[1] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_EVENT_U1_INT_ENA (BIT(1)) -#define PCNT_CNT_THR_EVENT_U1_INT_ENA_M (BIT(1)) -#define PCNT_CNT_THR_EVENT_U1_INT_ENA_V 0x1 -#define PCNT_CNT_THR_EVENT_U1_INT_ENA_S 1 -/* PCNT_CNT_THR_EVENT_U0_INT_ENA : R/W ;bitpos:[0] ;default: 1'b0 ; */ -/*description: .*/ +/** PCNT_INT_ENA_REG register + * Interrupt enable register + */ +#define PCNT_INT_ENA_REG (DR_REG_PCNT_BASE + 0x48) +/** PCNT_CNT_THR_EVENT_U0_INT_ENA : R/W; bitpos: [0]; default: 0; + * The interrupt enable bit for the PCNT_CNT_THR_EVENT_U0_INT interrupt. + */ #define PCNT_CNT_THR_EVENT_U0_INT_ENA (BIT(0)) -#define PCNT_CNT_THR_EVENT_U0_INT_ENA_M (BIT(0)) -#define PCNT_CNT_THR_EVENT_U0_INT_ENA_V 0x1 +#define PCNT_CNT_THR_EVENT_U0_INT_ENA_M (PCNT_CNT_THR_EVENT_U0_INT_ENA_V << PCNT_CNT_THR_EVENT_U0_INT_ENA_S) +#define PCNT_CNT_THR_EVENT_U0_INT_ENA_V 0x00000001U #define PCNT_CNT_THR_EVENT_U0_INT_ENA_S 0 +/** PCNT_CNT_THR_EVENT_U1_INT_ENA : R/W; bitpos: [1]; default: 0; + * The interrupt enable bit for the PCNT_CNT_THR_EVENT_U1_INT interrupt. + */ +#define PCNT_CNT_THR_EVENT_U1_INT_ENA (BIT(1)) +#define PCNT_CNT_THR_EVENT_U1_INT_ENA_M (PCNT_CNT_THR_EVENT_U1_INT_ENA_V << PCNT_CNT_THR_EVENT_U1_INT_ENA_S) +#define PCNT_CNT_THR_EVENT_U1_INT_ENA_V 0x00000001U +#define PCNT_CNT_THR_EVENT_U1_INT_ENA_S 1 +/** PCNT_CNT_THR_EVENT_U2_INT_ENA : R/W; bitpos: [2]; default: 0; + * The interrupt enable bit for the PCNT_CNT_THR_EVENT_U2_INT interrupt. + */ +#define PCNT_CNT_THR_EVENT_U2_INT_ENA (BIT(2)) +#define PCNT_CNT_THR_EVENT_U2_INT_ENA_M (PCNT_CNT_THR_EVENT_U2_INT_ENA_V << PCNT_CNT_THR_EVENT_U2_INT_ENA_S) +#define PCNT_CNT_THR_EVENT_U2_INT_ENA_V 0x00000001U +#define PCNT_CNT_THR_EVENT_U2_INT_ENA_S 2 +/** PCNT_CNT_THR_EVENT_U3_INT_ENA : R/W; bitpos: [3]; default: 0; + * The interrupt enable bit for the PCNT_CNT_THR_EVENT_U3_INT interrupt. + */ +#define PCNT_CNT_THR_EVENT_U3_INT_ENA (BIT(3)) +#define PCNT_CNT_THR_EVENT_U3_INT_ENA_M (PCNT_CNT_THR_EVENT_U3_INT_ENA_V << PCNT_CNT_THR_EVENT_U3_INT_ENA_S) +#define PCNT_CNT_THR_EVENT_U3_INT_ENA_V 0x00000001U +#define PCNT_CNT_THR_EVENT_U3_INT_ENA_S 3 -#define PCNT_INT_CLR_REG (DR_REG_PCNT_BASE + 0x4C) -/* PCNT_CNT_THR_EVENT_U3_INT_CLR : WO ;bitpos:[3] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_EVENT_U3_INT_CLR (BIT(3)) -#define PCNT_CNT_THR_EVENT_U3_INT_CLR_M (BIT(3)) -#define PCNT_CNT_THR_EVENT_U3_INT_CLR_V 0x1 -#define PCNT_CNT_THR_EVENT_U3_INT_CLR_S 3 -/* PCNT_CNT_THR_EVENT_U2_INT_CLR : WO ;bitpos:[2] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_EVENT_U2_INT_CLR (BIT(2)) -#define PCNT_CNT_THR_EVENT_U2_INT_CLR_M (BIT(2)) -#define PCNT_CNT_THR_EVENT_U2_INT_CLR_V 0x1 -#define PCNT_CNT_THR_EVENT_U2_INT_CLR_S 2 -/* PCNT_CNT_THR_EVENT_U1_INT_CLR : WO ;bitpos:[1] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_EVENT_U1_INT_CLR (BIT(1)) -#define PCNT_CNT_THR_EVENT_U1_INT_CLR_M (BIT(1)) -#define PCNT_CNT_THR_EVENT_U1_INT_CLR_V 0x1 -#define PCNT_CNT_THR_EVENT_U1_INT_CLR_S 1 -/* PCNT_CNT_THR_EVENT_U0_INT_CLR : WO ;bitpos:[0] ;default: 1'b0 ; */ -/*description: .*/ +/** PCNT_INT_CLR_REG register + * Interrupt clear register + */ +#define PCNT_INT_CLR_REG (DR_REG_PCNT_BASE + 0x4c) +/** PCNT_CNT_THR_EVENT_U0_INT_CLR : WO; bitpos: [0]; default: 0; + * Set this bit to clear the PCNT_CNT_THR_EVENT_U0_INT interrupt. + */ #define PCNT_CNT_THR_EVENT_U0_INT_CLR (BIT(0)) -#define PCNT_CNT_THR_EVENT_U0_INT_CLR_M (BIT(0)) -#define PCNT_CNT_THR_EVENT_U0_INT_CLR_V 0x1 +#define PCNT_CNT_THR_EVENT_U0_INT_CLR_M (PCNT_CNT_THR_EVENT_U0_INT_CLR_V << PCNT_CNT_THR_EVENT_U0_INT_CLR_S) +#define PCNT_CNT_THR_EVENT_U0_INT_CLR_V 0x00000001U #define PCNT_CNT_THR_EVENT_U0_INT_CLR_S 0 +/** PCNT_CNT_THR_EVENT_U1_INT_CLR : WO; bitpos: [1]; default: 0; + * Set this bit to clear the PCNT_CNT_THR_EVENT_U1_INT interrupt. + */ +#define PCNT_CNT_THR_EVENT_U1_INT_CLR (BIT(1)) +#define PCNT_CNT_THR_EVENT_U1_INT_CLR_M (PCNT_CNT_THR_EVENT_U1_INT_CLR_V << PCNT_CNT_THR_EVENT_U1_INT_CLR_S) +#define PCNT_CNT_THR_EVENT_U1_INT_CLR_V 0x00000001U +#define PCNT_CNT_THR_EVENT_U1_INT_CLR_S 1 +/** PCNT_CNT_THR_EVENT_U2_INT_CLR : WO; bitpos: [2]; default: 0; + * Set this bit to clear the PCNT_CNT_THR_EVENT_U2_INT interrupt. + */ +#define PCNT_CNT_THR_EVENT_U2_INT_CLR (BIT(2)) +#define PCNT_CNT_THR_EVENT_U2_INT_CLR_M (PCNT_CNT_THR_EVENT_U2_INT_CLR_V << PCNT_CNT_THR_EVENT_U2_INT_CLR_S) +#define PCNT_CNT_THR_EVENT_U2_INT_CLR_V 0x00000001U +#define PCNT_CNT_THR_EVENT_U2_INT_CLR_S 2 +/** PCNT_CNT_THR_EVENT_U3_INT_CLR : WO; bitpos: [3]; default: 0; + * Set this bit to clear the PCNT_CNT_THR_EVENT_U3_INT interrupt. + */ +#define PCNT_CNT_THR_EVENT_U3_INT_CLR (BIT(3)) +#define PCNT_CNT_THR_EVENT_U3_INT_CLR_M (PCNT_CNT_THR_EVENT_U3_INT_CLR_V << PCNT_CNT_THR_EVENT_U3_INT_CLR_S) +#define PCNT_CNT_THR_EVENT_U3_INT_CLR_V 0x00000001U +#define PCNT_CNT_THR_EVENT_U3_INT_CLR_S 3 -#define PCNT_U0_STATUS_REG (DR_REG_PCNT_BASE + 0x50) -/* PCNT_CNT_THR_ZERO_LAT_U0 : RO ;bitpos:[6] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_ZERO_LAT_U0 (BIT(6)) -#define PCNT_CNT_THR_ZERO_LAT_U0_M (BIT(6)) -#define PCNT_CNT_THR_ZERO_LAT_U0_V 0x1 -#define PCNT_CNT_THR_ZERO_LAT_U0_S 6 -/* PCNT_CNT_THR_H_LIM_LAT_U0 : RO ;bitpos:[5] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_H_LIM_LAT_U0 (BIT(5)) -#define PCNT_CNT_THR_H_LIM_LAT_U0_M (BIT(5)) -#define PCNT_CNT_THR_H_LIM_LAT_U0_V 0x1 -#define PCNT_CNT_THR_H_LIM_LAT_U0_S 5 -/* PCNT_CNT_THR_L_LIM_LAT_U0 : RO ;bitpos:[4] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_L_LIM_LAT_U0 (BIT(4)) -#define PCNT_CNT_THR_L_LIM_LAT_U0_M (BIT(4)) -#define PCNT_CNT_THR_L_LIM_LAT_U0_V 0x1 -#define PCNT_CNT_THR_L_LIM_LAT_U0_S 4 -/* PCNT_CNT_THR_THRES0_LAT_U0 : RO ;bitpos:[3] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_THRES0_LAT_U0 (BIT(3)) -#define PCNT_CNT_THR_THRES0_LAT_U0_M (BIT(3)) -#define PCNT_CNT_THR_THRES0_LAT_U0_V 0x1 -#define PCNT_CNT_THR_THRES0_LAT_U0_S 3 -/* PCNT_CNT_THR_THRES1_LAT_U0 : RO ;bitpos:[2] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_THRES1_LAT_U0 (BIT(2)) -#define PCNT_CNT_THR_THRES1_LAT_U0_M (BIT(2)) -#define PCNT_CNT_THR_THRES1_LAT_U0_V 0x1 -#define PCNT_CNT_THR_THRES1_LAT_U0_S 2 -/* PCNT_CNT_THR_ZERO_MODE_U0 : RO ;bitpos:[1:0] ;default: 2'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_ZERO_MODE_U0 0x00000003 -#define PCNT_CNT_THR_ZERO_MODE_U0_M ((PCNT_CNT_THR_ZERO_MODE_U0_V)<<(PCNT_CNT_THR_ZERO_MODE_U0_S)) -#define PCNT_CNT_THR_ZERO_MODE_U0_V 0x3 +/** PCNT_U0_STATUS_REG register + * PNCT UNIT0 status register + */ +#define PCNT_U0_STATUS_REG (DR_REG_PCNT_BASE + 0x50) +/** PCNT_CNT_THR_ZERO_MODE_U0 : RO; bitpos: [1:0]; default: 0; + * The pulse counter status of PCNT_U0 corresponding to 0. 0: pulse counter decreases + * from positive to 0. 1: pulse counter increases from negative to 0. 2: pulse counter + * is negative. 3: pulse counter is positive. + */ +#define PCNT_CNT_THR_ZERO_MODE_U0 0x00000003U +#define PCNT_CNT_THR_ZERO_MODE_U0_M (PCNT_CNT_THR_ZERO_MODE_U0_V << PCNT_CNT_THR_ZERO_MODE_U0_S) +#define PCNT_CNT_THR_ZERO_MODE_U0_V 0x00000003U #define PCNT_CNT_THR_ZERO_MODE_U0_S 0 +/** PCNT_CNT_THR_THRES1_LAT_U0 : RO; bitpos: [2]; default: 0; + * The latched value of thres1 event of PCNT_U0 when threshold event interrupt is + * valid. 1: the current pulse counter equals to thres1 and thres1 event is valid. 0: + * others + */ +#define PCNT_CNT_THR_THRES1_LAT_U0 (BIT(2)) +#define PCNT_CNT_THR_THRES1_LAT_U0_M (PCNT_CNT_THR_THRES1_LAT_U0_V << PCNT_CNT_THR_THRES1_LAT_U0_S) +#define PCNT_CNT_THR_THRES1_LAT_U0_V 0x00000001U +#define PCNT_CNT_THR_THRES1_LAT_U0_S 2 +/** PCNT_CNT_THR_THRES0_LAT_U0 : RO; bitpos: [3]; default: 0; + * The latched value of thres0 event of PCNT_U0 when threshold event interrupt is + * valid. 1: the current pulse counter equals to thres0 and thres0 event is valid. 0: + * others + */ +#define PCNT_CNT_THR_THRES0_LAT_U0 (BIT(3)) +#define PCNT_CNT_THR_THRES0_LAT_U0_M (PCNT_CNT_THR_THRES0_LAT_U0_V << PCNT_CNT_THR_THRES0_LAT_U0_S) +#define PCNT_CNT_THR_THRES0_LAT_U0_V 0x00000001U +#define PCNT_CNT_THR_THRES0_LAT_U0_S 3 +/** PCNT_CNT_THR_L_LIM_LAT_U0 : RO; bitpos: [4]; default: 0; + * The latched value of low limit event of PCNT_U0 when threshold event interrupt is + * valid. 1: the current pulse counter equals to thr_l_lim and low limit event is + * valid. 0: others + */ +#define PCNT_CNT_THR_L_LIM_LAT_U0 (BIT(4)) +#define PCNT_CNT_THR_L_LIM_LAT_U0_M (PCNT_CNT_THR_L_LIM_LAT_U0_V << PCNT_CNT_THR_L_LIM_LAT_U0_S) +#define PCNT_CNT_THR_L_LIM_LAT_U0_V 0x00000001U +#define PCNT_CNT_THR_L_LIM_LAT_U0_S 4 +/** PCNT_CNT_THR_H_LIM_LAT_U0 : RO; bitpos: [5]; default: 0; + * The latched value of high limit event of PCNT_U0 when threshold event interrupt is + * valid. 1: the current pulse counter equals to thr_h_lim and high limit event is + * valid. 0: others + */ +#define PCNT_CNT_THR_H_LIM_LAT_U0 (BIT(5)) +#define PCNT_CNT_THR_H_LIM_LAT_U0_M (PCNT_CNT_THR_H_LIM_LAT_U0_V << PCNT_CNT_THR_H_LIM_LAT_U0_S) +#define PCNT_CNT_THR_H_LIM_LAT_U0_V 0x00000001U +#define PCNT_CNT_THR_H_LIM_LAT_U0_S 5 +/** PCNT_CNT_THR_ZERO_LAT_U0 : RO; bitpos: [6]; default: 0; + * The latched value of zero threshold event of PCNT_U0 when threshold event interrupt + * is valid. 1: the current pulse counter equals to 0 and zero threshold event is + * valid. 0: others + */ +#define PCNT_CNT_THR_ZERO_LAT_U0 (BIT(6)) +#define PCNT_CNT_THR_ZERO_LAT_U0_M (PCNT_CNT_THR_ZERO_LAT_U0_V << PCNT_CNT_THR_ZERO_LAT_U0_S) +#define PCNT_CNT_THR_ZERO_LAT_U0_V 0x00000001U +#define PCNT_CNT_THR_ZERO_LAT_U0_S 6 -#define PCNT_U1_STATUS_REG (DR_REG_PCNT_BASE + 0x54) -/* PCNT_CNT_THR_ZERO_LAT_U1 : RO ;bitpos:[6] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_ZERO_LAT_U1 (BIT(6)) -#define PCNT_CNT_THR_ZERO_LAT_U1_M (BIT(6)) -#define PCNT_CNT_THR_ZERO_LAT_U1_V 0x1 -#define PCNT_CNT_THR_ZERO_LAT_U1_S 6 -/* PCNT_CNT_THR_H_LIM_LAT_U1 : RO ;bitpos:[5] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_H_LIM_LAT_U1 (BIT(5)) -#define PCNT_CNT_THR_H_LIM_LAT_U1_M (BIT(5)) -#define PCNT_CNT_THR_H_LIM_LAT_U1_V 0x1 -#define PCNT_CNT_THR_H_LIM_LAT_U1_S 5 -/* PCNT_CNT_THR_L_LIM_LAT_U1 : RO ;bitpos:[4] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_L_LIM_LAT_U1 (BIT(4)) -#define PCNT_CNT_THR_L_LIM_LAT_U1_M (BIT(4)) -#define PCNT_CNT_THR_L_LIM_LAT_U1_V 0x1 -#define PCNT_CNT_THR_L_LIM_LAT_U1_S 4 -/* PCNT_CNT_THR_THRES0_LAT_U1 : RO ;bitpos:[3] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_THRES0_LAT_U1 (BIT(3)) -#define PCNT_CNT_THR_THRES0_LAT_U1_M (BIT(3)) -#define PCNT_CNT_THR_THRES0_LAT_U1_V 0x1 -#define PCNT_CNT_THR_THRES0_LAT_U1_S 3 -/* PCNT_CNT_THR_THRES1_LAT_U1 : RO ;bitpos:[2] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_THRES1_LAT_U1 (BIT(2)) -#define PCNT_CNT_THR_THRES1_LAT_U1_M (BIT(2)) -#define PCNT_CNT_THR_THRES1_LAT_U1_V 0x1 -#define PCNT_CNT_THR_THRES1_LAT_U1_S 2 -/* PCNT_CNT_THR_ZERO_MODE_U1 : RO ;bitpos:[1:0] ;default: 2'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_ZERO_MODE_U1 0x00000003 -#define PCNT_CNT_THR_ZERO_MODE_U1_M ((PCNT_CNT_THR_ZERO_MODE_U1_V)<<(PCNT_CNT_THR_ZERO_MODE_U1_S)) -#define PCNT_CNT_THR_ZERO_MODE_U1_V 0x3 +/** PCNT_U1_STATUS_REG register + * PNCT UNIT1 status register + */ +#define PCNT_U1_STATUS_REG (DR_REG_PCNT_BASE + 0x54) +/** PCNT_CNT_THR_ZERO_MODE_U1 : RO; bitpos: [1:0]; default: 0; + * The pulse counter status of PCNT_U1 corresponding to 0. 0: pulse counter decreases + * from positive to 0. 1: pulse counter increases from negative to 0. 2: pulse counter + * is negative. 3: pulse counter is positive. + */ +#define PCNT_CNT_THR_ZERO_MODE_U1 0x00000003U +#define PCNT_CNT_THR_ZERO_MODE_U1_M (PCNT_CNT_THR_ZERO_MODE_U1_V << PCNT_CNT_THR_ZERO_MODE_U1_S) +#define PCNT_CNT_THR_ZERO_MODE_U1_V 0x00000003U #define PCNT_CNT_THR_ZERO_MODE_U1_S 0 +/** PCNT_CNT_THR_THRES1_LAT_U1 : RO; bitpos: [2]; default: 0; + * The latched value of thres1 event of PCNT_U1 when threshold event interrupt is + * valid. 1: the current pulse counter equals to thres1 and thres1 event is valid. 0: + * others + */ +#define PCNT_CNT_THR_THRES1_LAT_U1 (BIT(2)) +#define PCNT_CNT_THR_THRES1_LAT_U1_M (PCNT_CNT_THR_THRES1_LAT_U1_V << PCNT_CNT_THR_THRES1_LAT_U1_S) +#define PCNT_CNT_THR_THRES1_LAT_U1_V 0x00000001U +#define PCNT_CNT_THR_THRES1_LAT_U1_S 2 +/** PCNT_CNT_THR_THRES0_LAT_U1 : RO; bitpos: [3]; default: 0; + * The latched value of thres0 event of PCNT_U1 when threshold event interrupt is + * valid. 1: the current pulse counter equals to thres0 and thres0 event is valid. 0: + * others + */ +#define PCNT_CNT_THR_THRES0_LAT_U1 (BIT(3)) +#define PCNT_CNT_THR_THRES0_LAT_U1_M (PCNT_CNT_THR_THRES0_LAT_U1_V << PCNT_CNT_THR_THRES0_LAT_U1_S) +#define PCNT_CNT_THR_THRES0_LAT_U1_V 0x00000001U +#define PCNT_CNT_THR_THRES0_LAT_U1_S 3 +/** PCNT_CNT_THR_L_LIM_LAT_U1 : RO; bitpos: [4]; default: 0; + * The latched value of low limit event of PCNT_U1 when threshold event interrupt is + * valid. 1: the current pulse counter equals to thr_l_lim and low limit event is + * valid. 0: others + */ +#define PCNT_CNT_THR_L_LIM_LAT_U1 (BIT(4)) +#define PCNT_CNT_THR_L_LIM_LAT_U1_M (PCNT_CNT_THR_L_LIM_LAT_U1_V << PCNT_CNT_THR_L_LIM_LAT_U1_S) +#define PCNT_CNT_THR_L_LIM_LAT_U1_V 0x00000001U +#define PCNT_CNT_THR_L_LIM_LAT_U1_S 4 +/** PCNT_CNT_THR_H_LIM_LAT_U1 : RO; bitpos: [5]; default: 0; + * The latched value of high limit event of PCNT_U1 when threshold event interrupt is + * valid. 1: the current pulse counter equals to thr_h_lim and high limit event is + * valid. 0: others + */ +#define PCNT_CNT_THR_H_LIM_LAT_U1 (BIT(5)) +#define PCNT_CNT_THR_H_LIM_LAT_U1_M (PCNT_CNT_THR_H_LIM_LAT_U1_V << PCNT_CNT_THR_H_LIM_LAT_U1_S) +#define PCNT_CNT_THR_H_LIM_LAT_U1_V 0x00000001U +#define PCNT_CNT_THR_H_LIM_LAT_U1_S 5 +/** PCNT_CNT_THR_ZERO_LAT_U1 : RO; bitpos: [6]; default: 0; + * The latched value of zero threshold event of PCNT_U1 when threshold event interrupt + * is valid. 1: the current pulse counter equals to 0 and zero threshold event is + * valid. 0: others + */ +#define PCNT_CNT_THR_ZERO_LAT_U1 (BIT(6)) +#define PCNT_CNT_THR_ZERO_LAT_U1_M (PCNT_CNT_THR_ZERO_LAT_U1_V << PCNT_CNT_THR_ZERO_LAT_U1_S) +#define PCNT_CNT_THR_ZERO_LAT_U1_V 0x00000001U +#define PCNT_CNT_THR_ZERO_LAT_U1_S 6 -#define PCNT_U2_STATUS_REG (DR_REG_PCNT_BASE + 0x58) -/* PCNT_CNT_THR_ZERO_LAT_U2 : RO ;bitpos:[6] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_ZERO_LAT_U2 (BIT(6)) -#define PCNT_CNT_THR_ZERO_LAT_U2_M (BIT(6)) -#define PCNT_CNT_THR_ZERO_LAT_U2_V 0x1 -#define PCNT_CNT_THR_ZERO_LAT_U2_S 6 -/* PCNT_CNT_THR_H_LIM_LAT_U2 : RO ;bitpos:[5] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_H_LIM_LAT_U2 (BIT(5)) -#define PCNT_CNT_THR_H_LIM_LAT_U2_M (BIT(5)) -#define PCNT_CNT_THR_H_LIM_LAT_U2_V 0x1 -#define PCNT_CNT_THR_H_LIM_LAT_U2_S 5 -/* PCNT_CNT_THR_L_LIM_LAT_U2 : RO ;bitpos:[4] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_L_LIM_LAT_U2 (BIT(4)) -#define PCNT_CNT_THR_L_LIM_LAT_U2_M (BIT(4)) -#define PCNT_CNT_THR_L_LIM_LAT_U2_V 0x1 -#define PCNT_CNT_THR_L_LIM_LAT_U2_S 4 -/* PCNT_CNT_THR_THRES0_LAT_U2 : RO ;bitpos:[3] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_THRES0_LAT_U2 (BIT(3)) -#define PCNT_CNT_THR_THRES0_LAT_U2_M (BIT(3)) -#define PCNT_CNT_THR_THRES0_LAT_U2_V 0x1 -#define PCNT_CNT_THR_THRES0_LAT_U2_S 3 -/* PCNT_CNT_THR_THRES1_LAT_U2 : RO ;bitpos:[2] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_THRES1_LAT_U2 (BIT(2)) -#define PCNT_CNT_THR_THRES1_LAT_U2_M (BIT(2)) -#define PCNT_CNT_THR_THRES1_LAT_U2_V 0x1 -#define PCNT_CNT_THR_THRES1_LAT_U2_S 2 -/* PCNT_CNT_THR_ZERO_MODE_U2 : RO ;bitpos:[1:0] ;default: 2'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_ZERO_MODE_U2 0x00000003 -#define PCNT_CNT_THR_ZERO_MODE_U2_M ((PCNT_CNT_THR_ZERO_MODE_U2_V)<<(PCNT_CNT_THR_ZERO_MODE_U2_S)) -#define PCNT_CNT_THR_ZERO_MODE_U2_V 0x3 +/** PCNT_U2_STATUS_REG register + * PNCT UNIT2 status register + */ +#define PCNT_U2_STATUS_REG (DR_REG_PCNT_BASE + 0x58) +/** PCNT_CNT_THR_ZERO_MODE_U2 : RO; bitpos: [1:0]; default: 0; + * The pulse counter status of PCNT_U2 corresponding to 0. 0: pulse counter decreases + * from positive to 0. 1: pulse counter increases from negative to 0. 2: pulse counter + * is negative. 3: pulse counter is positive. + */ +#define PCNT_CNT_THR_ZERO_MODE_U2 0x00000003U +#define PCNT_CNT_THR_ZERO_MODE_U2_M (PCNT_CNT_THR_ZERO_MODE_U2_V << PCNT_CNT_THR_ZERO_MODE_U2_S) +#define PCNT_CNT_THR_ZERO_MODE_U2_V 0x00000003U #define PCNT_CNT_THR_ZERO_MODE_U2_S 0 +/** PCNT_CNT_THR_THRES1_LAT_U2 : RO; bitpos: [2]; default: 0; + * The latched value of thres1 event of PCNT_U2 when threshold event interrupt is + * valid. 1: the current pulse counter equals to thres1 and thres1 event is valid. 0: + * others + */ +#define PCNT_CNT_THR_THRES1_LAT_U2 (BIT(2)) +#define PCNT_CNT_THR_THRES1_LAT_U2_M (PCNT_CNT_THR_THRES1_LAT_U2_V << PCNT_CNT_THR_THRES1_LAT_U2_S) +#define PCNT_CNT_THR_THRES1_LAT_U2_V 0x00000001U +#define PCNT_CNT_THR_THRES1_LAT_U2_S 2 +/** PCNT_CNT_THR_THRES0_LAT_U2 : RO; bitpos: [3]; default: 0; + * The latched value of thres0 event of PCNT_U2 when threshold event interrupt is + * valid. 1: the current pulse counter equals to thres0 and thres0 event is valid. 0: + * others + */ +#define PCNT_CNT_THR_THRES0_LAT_U2 (BIT(3)) +#define PCNT_CNT_THR_THRES0_LAT_U2_M (PCNT_CNT_THR_THRES0_LAT_U2_V << PCNT_CNT_THR_THRES0_LAT_U2_S) +#define PCNT_CNT_THR_THRES0_LAT_U2_V 0x00000001U +#define PCNT_CNT_THR_THRES0_LAT_U2_S 3 +/** PCNT_CNT_THR_L_LIM_LAT_U2 : RO; bitpos: [4]; default: 0; + * The latched value of low limit event of PCNT_U2 when threshold event interrupt is + * valid. 1: the current pulse counter equals to thr_l_lim and low limit event is + * valid. 0: others + */ +#define PCNT_CNT_THR_L_LIM_LAT_U2 (BIT(4)) +#define PCNT_CNT_THR_L_LIM_LAT_U2_M (PCNT_CNT_THR_L_LIM_LAT_U2_V << PCNT_CNT_THR_L_LIM_LAT_U2_S) +#define PCNT_CNT_THR_L_LIM_LAT_U2_V 0x00000001U +#define PCNT_CNT_THR_L_LIM_LAT_U2_S 4 +/** PCNT_CNT_THR_H_LIM_LAT_U2 : RO; bitpos: [5]; default: 0; + * The latched value of high limit event of PCNT_U2 when threshold event interrupt is + * valid. 1: the current pulse counter equals to thr_h_lim and high limit event is + * valid. 0: others + */ +#define PCNT_CNT_THR_H_LIM_LAT_U2 (BIT(5)) +#define PCNT_CNT_THR_H_LIM_LAT_U2_M (PCNT_CNT_THR_H_LIM_LAT_U2_V << PCNT_CNT_THR_H_LIM_LAT_U2_S) +#define PCNT_CNT_THR_H_LIM_LAT_U2_V 0x00000001U +#define PCNT_CNT_THR_H_LIM_LAT_U2_S 5 +/** PCNT_CNT_THR_ZERO_LAT_U2 : RO; bitpos: [6]; default: 0; + * The latched value of zero threshold event of PCNT_U2 when threshold event interrupt + * is valid. 1: the current pulse counter equals to 0 and zero threshold event is + * valid. 0: others + */ +#define PCNT_CNT_THR_ZERO_LAT_U2 (BIT(6)) +#define PCNT_CNT_THR_ZERO_LAT_U2_M (PCNT_CNT_THR_ZERO_LAT_U2_V << PCNT_CNT_THR_ZERO_LAT_U2_S) +#define PCNT_CNT_THR_ZERO_LAT_U2_V 0x00000001U +#define PCNT_CNT_THR_ZERO_LAT_U2_S 6 -#define PCNT_U3_STATUS_REG (DR_REG_PCNT_BASE + 0x5C) -/* PCNT_CNT_THR_ZERO_LAT_U3 : RO ;bitpos:[6] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_ZERO_LAT_U3 (BIT(6)) -#define PCNT_CNT_THR_ZERO_LAT_U3_M (BIT(6)) -#define PCNT_CNT_THR_ZERO_LAT_U3_V 0x1 -#define PCNT_CNT_THR_ZERO_LAT_U3_S 6 -/* PCNT_CNT_THR_H_LIM_LAT_U3 : RO ;bitpos:[5] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_H_LIM_LAT_U3 (BIT(5)) -#define PCNT_CNT_THR_H_LIM_LAT_U3_M (BIT(5)) -#define PCNT_CNT_THR_H_LIM_LAT_U3_V 0x1 -#define PCNT_CNT_THR_H_LIM_LAT_U3_S 5 -/* PCNT_CNT_THR_L_LIM_LAT_U3 : RO ;bitpos:[4] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_L_LIM_LAT_U3 (BIT(4)) -#define PCNT_CNT_THR_L_LIM_LAT_U3_M (BIT(4)) -#define PCNT_CNT_THR_L_LIM_LAT_U3_V 0x1 -#define PCNT_CNT_THR_L_LIM_LAT_U3_S 4 -/* PCNT_CNT_THR_THRES0_LAT_U3 : RO ;bitpos:[3] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_THRES0_LAT_U3 (BIT(3)) -#define PCNT_CNT_THR_THRES0_LAT_U3_M (BIT(3)) -#define PCNT_CNT_THR_THRES0_LAT_U3_V 0x1 -#define PCNT_CNT_THR_THRES0_LAT_U3_S 3 -/* PCNT_CNT_THR_THRES1_LAT_U3 : RO ;bitpos:[2] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_THRES1_LAT_U3 (BIT(2)) -#define PCNT_CNT_THR_THRES1_LAT_U3_M (BIT(2)) -#define PCNT_CNT_THR_THRES1_LAT_U3_V 0x1 -#define PCNT_CNT_THR_THRES1_LAT_U3_S 2 -/* PCNT_CNT_THR_ZERO_MODE_U3 : RO ;bitpos:[1:0] ;default: 2'b0 ; */ -/*description: .*/ -#define PCNT_CNT_THR_ZERO_MODE_U3 0x00000003 -#define PCNT_CNT_THR_ZERO_MODE_U3_M ((PCNT_CNT_THR_ZERO_MODE_U3_V)<<(PCNT_CNT_THR_ZERO_MODE_U3_S)) -#define PCNT_CNT_THR_ZERO_MODE_U3_V 0x3 +/** PCNT_U3_STATUS_REG register + * PNCT UNIT3 status register + */ +#define PCNT_U3_STATUS_REG (DR_REG_PCNT_BASE + 0x5c) +/** PCNT_CNT_THR_ZERO_MODE_U3 : RO; bitpos: [1:0]; default: 0; + * The pulse counter status of PCNT_U3 corresponding to 0. 0: pulse counter decreases + * from positive to 0. 1: pulse counter increases from negative to 0. 2: pulse counter + * is negative. 3: pulse counter is positive. + */ +#define PCNT_CNT_THR_ZERO_MODE_U3 0x00000003U +#define PCNT_CNT_THR_ZERO_MODE_U3_M (PCNT_CNT_THR_ZERO_MODE_U3_V << PCNT_CNT_THR_ZERO_MODE_U3_S) +#define PCNT_CNT_THR_ZERO_MODE_U3_V 0x00000003U #define PCNT_CNT_THR_ZERO_MODE_U3_S 0 +/** PCNT_CNT_THR_THRES1_LAT_U3 : RO; bitpos: [2]; default: 0; + * The latched value of thres1 event of PCNT_U3 when threshold event interrupt is + * valid. 1: the current pulse counter equals to thres1 and thres1 event is valid. 0: + * others + */ +#define PCNT_CNT_THR_THRES1_LAT_U3 (BIT(2)) +#define PCNT_CNT_THR_THRES1_LAT_U3_M (PCNT_CNT_THR_THRES1_LAT_U3_V << PCNT_CNT_THR_THRES1_LAT_U3_S) +#define PCNT_CNT_THR_THRES1_LAT_U3_V 0x00000001U +#define PCNT_CNT_THR_THRES1_LAT_U3_S 2 +/** PCNT_CNT_THR_THRES0_LAT_U3 : RO; bitpos: [3]; default: 0; + * The latched value of thres0 event of PCNT_U3 when threshold event interrupt is + * valid. 1: the current pulse counter equals to thres0 and thres0 event is valid. 0: + * others + */ +#define PCNT_CNT_THR_THRES0_LAT_U3 (BIT(3)) +#define PCNT_CNT_THR_THRES0_LAT_U3_M (PCNT_CNT_THR_THRES0_LAT_U3_V << PCNT_CNT_THR_THRES0_LAT_U3_S) +#define PCNT_CNT_THR_THRES0_LAT_U3_V 0x00000001U +#define PCNT_CNT_THR_THRES0_LAT_U3_S 3 +/** PCNT_CNT_THR_L_LIM_LAT_U3 : RO; bitpos: [4]; default: 0; + * The latched value of low limit event of PCNT_U3 when threshold event interrupt is + * valid. 1: the current pulse counter equals to thr_l_lim and low limit event is + * valid. 0: others + */ +#define PCNT_CNT_THR_L_LIM_LAT_U3 (BIT(4)) +#define PCNT_CNT_THR_L_LIM_LAT_U3_M (PCNT_CNT_THR_L_LIM_LAT_U3_V << PCNT_CNT_THR_L_LIM_LAT_U3_S) +#define PCNT_CNT_THR_L_LIM_LAT_U3_V 0x00000001U +#define PCNT_CNT_THR_L_LIM_LAT_U3_S 4 +/** PCNT_CNT_THR_H_LIM_LAT_U3 : RO; bitpos: [5]; default: 0; + * The latched value of high limit event of PCNT_U3 when threshold event interrupt is + * valid. 1: the current pulse counter equals to thr_h_lim and high limit event is + * valid. 0: others + */ +#define PCNT_CNT_THR_H_LIM_LAT_U3 (BIT(5)) +#define PCNT_CNT_THR_H_LIM_LAT_U3_M (PCNT_CNT_THR_H_LIM_LAT_U3_V << PCNT_CNT_THR_H_LIM_LAT_U3_S) +#define PCNT_CNT_THR_H_LIM_LAT_U3_V 0x00000001U +#define PCNT_CNT_THR_H_LIM_LAT_U3_S 5 +/** PCNT_CNT_THR_ZERO_LAT_U3 : RO; bitpos: [6]; default: 0; + * The latched value of zero threshold event of PCNT_U3 when threshold event interrupt + * is valid. 1: the current pulse counter equals to 0 and zero threshold event is + * valid. 0: others + */ +#define PCNT_CNT_THR_ZERO_LAT_U3 (BIT(6)) +#define PCNT_CNT_THR_ZERO_LAT_U3_M (PCNT_CNT_THR_ZERO_LAT_U3_V << PCNT_CNT_THR_ZERO_LAT_U3_S) +#define PCNT_CNT_THR_ZERO_LAT_U3_V 0x00000001U +#define PCNT_CNT_THR_ZERO_LAT_U3_S 6 -#define PCNT_CTRL_REG (DR_REG_PCNT_BASE + 0x60) -/* PCNT_CLK_EN : R/W ;bitpos:[16] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CLK_EN (BIT(16)) -#define PCNT_CLK_EN_M (BIT(16)) -#define PCNT_CLK_EN_V 0x1 -#define PCNT_CLK_EN_S 16 -/* PCNT_CNT_PAUSE_U3 : R/W ;bitpos:[7] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_PAUSE_U3 (BIT(7)) -#define PCNT_CNT_PAUSE_U3_M (BIT(7)) -#define PCNT_CNT_PAUSE_U3_V 0x1 -#define PCNT_CNT_PAUSE_U3_S 7 -/* PCNT_PULSE_CNT_RST_U3 : R/W ;bitpos:[6] ;default: 1'b1 ; */ -/*description: .*/ -#define PCNT_PULSE_CNT_RST_U3 (BIT(6)) -#define PCNT_PULSE_CNT_RST_U3_M (BIT(6)) -#define PCNT_PULSE_CNT_RST_U3_V 0x1 -#define PCNT_PULSE_CNT_RST_U3_S 6 -/* PCNT_CNT_PAUSE_U2 : R/W ;bitpos:[5] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_PAUSE_U2 (BIT(5)) -#define PCNT_CNT_PAUSE_U2_M (BIT(5)) -#define PCNT_CNT_PAUSE_U2_V 0x1 -#define PCNT_CNT_PAUSE_U2_S 5 -/* PCNT_PULSE_CNT_RST_U2 : R/W ;bitpos:[4] ;default: 1'b1 ; */ -/*description: .*/ -#define PCNT_PULSE_CNT_RST_U2 (BIT(4)) -#define PCNT_PULSE_CNT_RST_U2_M (BIT(4)) -#define PCNT_PULSE_CNT_RST_U2_V 0x1 -#define PCNT_PULSE_CNT_RST_U2_S 4 -/* PCNT_CNT_PAUSE_U1 : R/W ;bitpos:[3] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_PAUSE_U1 (BIT(3)) -#define PCNT_CNT_PAUSE_U1_M (BIT(3)) -#define PCNT_CNT_PAUSE_U1_V 0x1 -#define PCNT_CNT_PAUSE_U1_S 3 -/* PCNT_PULSE_CNT_RST_U1 : R/W ;bitpos:[2] ;default: 1'b1 ; */ -/*description: .*/ -#define PCNT_PULSE_CNT_RST_U1 (BIT(2)) -#define PCNT_PULSE_CNT_RST_U1_M (BIT(2)) -#define PCNT_PULSE_CNT_RST_U1_V 0x1 -#define PCNT_PULSE_CNT_RST_U1_S 2 -/* PCNT_CNT_PAUSE_U0 : R/W ;bitpos:[1] ;default: 1'b0 ; */ -/*description: .*/ -#define PCNT_CNT_PAUSE_U0 (BIT(1)) -#define PCNT_CNT_PAUSE_U0_M (BIT(1)) -#define PCNT_CNT_PAUSE_U0_V 0x1 -#define PCNT_CNT_PAUSE_U0_S 1 -/* PCNT_PULSE_CNT_RST_U0 : R/W ;bitpos:[0] ;default: 1'b1 ; */ -/*description: .*/ +/** PCNT_CTRL_REG register + * Control register for all counters + */ +#define PCNT_CTRL_REG (DR_REG_PCNT_BASE + 0x60) +/** PCNT_PULSE_CNT_RST_U0 : R/W; bitpos: [0]; default: 1; + * Set this bit to clear unit 0's counter. + */ #define PCNT_PULSE_CNT_RST_U0 (BIT(0)) -#define PCNT_PULSE_CNT_RST_U0_M (BIT(0)) -#define PCNT_PULSE_CNT_RST_U0_V 0x1 +#define PCNT_PULSE_CNT_RST_U0_M (PCNT_PULSE_CNT_RST_U0_V << PCNT_PULSE_CNT_RST_U0_S) +#define PCNT_PULSE_CNT_RST_U0_V 0x00000001U #define PCNT_PULSE_CNT_RST_U0_S 0 +/** PCNT_CNT_PAUSE_U0 : R/W; bitpos: [1]; default: 0; + * Set this bit to freeze unit 0's counter. + */ +#define PCNT_CNT_PAUSE_U0 (BIT(1)) +#define PCNT_CNT_PAUSE_U0_M (PCNT_CNT_PAUSE_U0_V << PCNT_CNT_PAUSE_U0_S) +#define PCNT_CNT_PAUSE_U0_V 0x00000001U +#define PCNT_CNT_PAUSE_U0_S 1 +/** PCNT_PULSE_CNT_RST_U1 : R/W; bitpos: [2]; default: 1; + * Set this bit to clear unit 1's counter. + */ +#define PCNT_PULSE_CNT_RST_U1 (BIT(2)) +#define PCNT_PULSE_CNT_RST_U1_M (PCNT_PULSE_CNT_RST_U1_V << PCNT_PULSE_CNT_RST_U1_S) +#define PCNT_PULSE_CNT_RST_U1_V 0x00000001U +#define PCNT_PULSE_CNT_RST_U1_S 2 +/** PCNT_CNT_PAUSE_U1 : R/W; bitpos: [3]; default: 0; + * Set this bit to freeze unit 1's counter. + */ +#define PCNT_CNT_PAUSE_U1 (BIT(3)) +#define PCNT_CNT_PAUSE_U1_M (PCNT_CNT_PAUSE_U1_V << PCNT_CNT_PAUSE_U1_S) +#define PCNT_CNT_PAUSE_U1_V 0x00000001U +#define PCNT_CNT_PAUSE_U1_S 3 +/** PCNT_PULSE_CNT_RST_U2 : R/W; bitpos: [4]; default: 1; + * Set this bit to clear unit 2's counter. + */ +#define PCNT_PULSE_CNT_RST_U2 (BIT(4)) +#define PCNT_PULSE_CNT_RST_U2_M (PCNT_PULSE_CNT_RST_U2_V << PCNT_PULSE_CNT_RST_U2_S) +#define PCNT_PULSE_CNT_RST_U2_V 0x00000001U +#define PCNT_PULSE_CNT_RST_U2_S 4 +/** PCNT_CNT_PAUSE_U2 : R/W; bitpos: [5]; default: 0; + * Set this bit to freeze unit 2's counter. + */ +#define PCNT_CNT_PAUSE_U2 (BIT(5)) +#define PCNT_CNT_PAUSE_U2_M (PCNT_CNT_PAUSE_U2_V << PCNT_CNT_PAUSE_U2_S) +#define PCNT_CNT_PAUSE_U2_V 0x00000001U +#define PCNT_CNT_PAUSE_U2_S 5 +/** PCNT_PULSE_CNT_RST_U3 : R/W; bitpos: [6]; default: 1; + * Set this bit to clear unit 3's counter. + */ +#define PCNT_PULSE_CNT_RST_U3 (BIT(6)) +#define PCNT_PULSE_CNT_RST_U3_M (PCNT_PULSE_CNT_RST_U3_V << PCNT_PULSE_CNT_RST_U3_S) +#define PCNT_PULSE_CNT_RST_U3_V 0x00000001U +#define PCNT_PULSE_CNT_RST_U3_S 6 +/** PCNT_CNT_PAUSE_U3 : R/W; bitpos: [7]; default: 0; + * Set this bit to freeze unit 3's counter. + */ +#define PCNT_CNT_PAUSE_U3 (BIT(7)) +#define PCNT_CNT_PAUSE_U3_M (PCNT_CNT_PAUSE_U3_V << PCNT_CNT_PAUSE_U3_S) +#define PCNT_CNT_PAUSE_U3_V 0x00000001U +#define PCNT_CNT_PAUSE_U3_S 7 +/** PCNT_CLK_EN : R/W; bitpos: [16]; default: 0; + * The registers clock gate enable signal of PCNT module. 1: the registers can be read + * and written by application. 0: the registers can not be read or written by + * application + */ +#define PCNT_CLK_EN (BIT(16)) +#define PCNT_CLK_EN_M (PCNT_CLK_EN_V << PCNT_CLK_EN_S) +#define PCNT_CLK_EN_V 0x00000001U +#define PCNT_CLK_EN_S 16 -#define PCNT_DATE_REG (DR_REG_PCNT_BASE + 0xFC) -/* PCNT_DATE : R/W ;bitpos:[31:0] ;default: 32'h18072600 ; */ -/*description: .*/ -#define PCNT_DATE 0xFFFFFFFF -#define PCNT_DATE_M ((PCNT_DATE_V)<<(PCNT_DATE_S)) -#define PCNT_DATE_V 0xFFFFFFFF +/** PCNT_DATE_REG register + * PCNT version control register + */ +#define PCNT_DATE_REG (DR_REG_PCNT_BASE + 0xfc) +/** PCNT_DATE : R/W; bitpos: [31:0]; default: 419898881; + * This is the PCNT version control register. + */ +#define PCNT_DATE 0xFFFFFFFFU +#define PCNT_DATE_M (PCNT_DATE_V << PCNT_DATE_S) +#define PCNT_DATE_V 0xFFFFFFFFU #define PCNT_DATE_S 0 - #ifdef __cplusplus } #endif - - - -#endif /*_SOC_PCNT_REG_H_ */ diff --git a/components/soc/esp32s3/include/soc/pcnt_struct.h b/components/soc/esp32s3/include/soc/pcnt_struct.h index 0390695703..1d65a7309b 100644 --- a/components/soc/esp32s3/include/soc/pcnt_struct.h +++ b/components/soc/esp32s3/include/soc/pcnt_struct.h @@ -1,182 +1,416 @@ -// 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. -#ifndef _SOC_PCNT_STRUCT_H_ -#define _SOC_PCNT_STRUCT_H_ - +/** Copyright 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. + */ +#pragma once #include + #ifdef __cplusplus extern "C" { #endif -typedef volatile struct { +/** Group: Configuration Register */ +/** Type of un_conf0 register + * Configuration register 0 for unit n + */ +typedef union { struct { - union { - struct { - uint32_t filter_thres : 10; - uint32_t filter_en : 1; - uint32_t thr_zero_en : 1; - uint32_t thr_h_lim_en : 1; - uint32_t thr_l_lim_en : 1; - uint32_t thr_thres0_en : 1; - uint32_t thr_thres1_en : 1; - uint32_t ch0_neg_mode : 2; - uint32_t ch0_pos_mode : 2; - uint32_t ch0_hctrl_mode : 2; - uint32_t ch0_lctrl_mode : 2; - uint32_t ch1_neg_mode : 2; - uint32_t ch1_pos_mode : 2; - uint32_t ch1_hctrl_mode : 2; - uint32_t ch1_lctrl_mode : 2; - }; - uint32_t val; - } conf0; - union { - struct { - uint32_t cnt_thres0 : 16; - uint32_t cnt_thres1 : 16; - }; - uint32_t val; - } conf1; - union { - struct { - uint32_t cnt_h_lim : 16; - uint32_t cnt_l_lim : 16; - }; - uint32_t val; - } conf2; + /** filter_thres_un : R/W; bitpos: [9:0]; default: 16; + * This sets the maximum threshold, in APB_CLK cycles, for the filter. + * + * Any pulses with width less than this will be ignored when the filter is enabled. + */ + uint32_t filter_thres_un: 10; + /** filter_en_un : R/W; bitpos: [10]; default: 1; + * This is the enable bit for unit n's input filter. + */ + uint32_t filter_en_un: 1; + /** thr_zero_en_un : R/W; bitpos: [11]; default: 1; + * This is the enable bit for unit n's zero comparator. + */ + uint32_t thr_zero_en_un: 1; + /** thr_h_lim_en_un : R/W; bitpos: [12]; default: 1; + * This is the enable bit for unit n's thr_h_lim comparator. + */ + uint32_t thr_h_lim_en_un: 1; + /** thr_l_lim_en_un : R/W; bitpos: [13]; default: 1; + * This is the enable bit for unit n's thr_l_lim comparator. + */ + uint32_t thr_l_lim_en_un: 1; + /** thr_thres0_en_un : R/W; bitpos: [14]; default: 0; + * This is the enable bit for unit n's thres0 comparator. + */ + uint32_t thr_thres0_en_un: 1; + /** thr_thres1_en_un : R/W; bitpos: [15]; default: 0; + * This is the enable bit for unit n's thres1 comparator. + */ + uint32_t thr_thres1_en_un: 1; + /** ch0_neg_mode_un : R/W; bitpos: [17:16]; default: 0; + * This register sets the behavior when the signal input of channel 0 detects a + * negative edge. + * + * 1: Increase the counter;2: Decrease the counter;0, 3: No effect on counter + */ + uint32_t ch0_neg_mode_un: 2; + /** ch0_pos_mode_un : R/W; bitpos: [19:18]; default: 0; + * This register sets the behavior when the signal input of channel 0 detects a + * positive edge. + * + * 1: Increase the counter;2: Decrease the counter;0, 3: No effect on counter + */ + uint32_t ch0_pos_mode_un: 2; + /** ch0_hctrl_mode_un : R/W; bitpos: [21:20]; default: 0; + * This register configures how the CHn_POS_MODE/CHn_NEG_MODE settings will be + * modified when the control signal is high. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ + uint32_t ch0_hctrl_mode_un: 2; + /** ch0_lctrl_mode_un : R/W; bitpos: [23:22]; default: 0; + * This register configures how the CHn_POS_MODE/CHn_NEG_MODE settings will be + * modified when the control signal is low. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ + uint32_t ch0_lctrl_mode_un: 2; + /** ch1_neg_mode_un : R/W; bitpos: [25:24]; default: 0; + * This register sets the behavior when the signal input of channel 1 detects a + * negative edge. + * + * 1: Increment the counter;2: Decrement the counter;0, 3: No effect on counter + */ + uint32_t ch1_neg_mode_un: 2; + /** ch1_pos_mode_un : R/W; bitpos: [27:26]; default: 0; + * This register sets the behavior when the signal input of channel 1 detects a + * positive edge. + * + * 1: Increment the counter;2: Decrement the counter;0, 3: No effect on counter + */ + uint32_t ch1_pos_mode_un: 2; + /** ch1_hctrl_mode_un : R/W; bitpos: [29:28]; default: 0; + * This register configures how the CHn_POS_MODE/CHn_NEG_MODE settings will be + * modified when the control signal is high. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ + uint32_t ch1_hctrl_mode_un: 2; + /** ch1_lctrl_mode_un : R/W; bitpos: [31:30]; default: 0; + * This register configures how the CHn_POS_MODE/CHn_NEG_MODE settings will be + * modified when the control signal is low. + * + * 0: No modification;1: Invert behavior (increase -> decrease, decrease -> + * increase);2, 3: Inhibit counter modification + */ + uint32_t ch1_lctrl_mode_un: 2; + }; + uint32_t val; +} pcnt_un_conf0_reg_t; + +/** Type of un_conf1 register + * Configuration register 1 for unit n + */ +typedef union { + struct { + /** cnt_thres0_un : R/W; bitpos: [15:0]; default: 0; + * This register is used to configure the thres0 value for unit n. + */ + uint32_t cnt_thres0_un: 16; + /** cnt_thres1_un : R/W; bitpos: [31:16]; default: 0; + * This register is used to configure the thres1 value for unit n. + */ + uint32_t cnt_thres1_un: 16; + }; + uint32_t val; +} pcnt_un_conf1_reg_t; + +/** Type of un_conf2 register + * Configuration register 2 for unit n + */ +typedef union { + struct { + /** cnt_h_lim_un : R/W; bitpos: [15:0]; default: 0; + * This register is used to configure the thr_h_lim value for unit n. + */ + uint32_t cnt_h_lim_un: 16; + /** cnt_l_lim_un : R/W; bitpos: [31:16]; default: 0; + * This register is used to configure the thr_l_lim value for unit n. + */ + uint32_t cnt_l_lim_un: 16; + }; + uint32_t val; +} pcnt_un_conf2_reg_t; + + +/** Type of ctrl register + * Control register for all counters + */ +typedef union { + struct { + /** pulse_cnt_rst_u0 : R/W; bitpos: [0]; default: 1; + * Set this bit to clear unit 0's counter. + */ + uint32_t pulse_cnt_rst_u0: 1; + /** cnt_pause_u0 : R/W; bitpos: [1]; default: 0; + * Set this bit to freeze unit 0's counter. + */ + uint32_t cnt_pause_u0: 1; + /** pulse_cnt_rst_u1 : R/W; bitpos: [2]; default: 1; + * Set this bit to clear unit 1's counter. + */ + uint32_t pulse_cnt_rst_u1: 1; + /** cnt_pause_u1 : R/W; bitpos: [3]; default: 0; + * Set this bit to freeze unit 1's counter. + */ + uint32_t cnt_pause_u1: 1; + /** pulse_cnt_rst_u2 : R/W; bitpos: [4]; default: 1; + * Set this bit to clear unit 2's counter. + */ + uint32_t pulse_cnt_rst_u2: 1; + /** cnt_pause_u2 : R/W; bitpos: [5]; default: 0; + * Set this bit to freeze unit 2's counter. + */ + uint32_t cnt_pause_u2: 1; + /** pulse_cnt_rst_u3 : R/W; bitpos: [6]; default: 1; + * Set this bit to clear unit 3's counter. + */ + uint32_t pulse_cnt_rst_u3: 1; + /** cnt_pause_u3 : R/W; bitpos: [7]; default: 0; + * Set this bit to freeze unit 3's counter. + */ + uint32_t cnt_pause_u3: 1; + uint32_t reserved_8: 8; + /** clk_en : R/W; bitpos: [16]; default: 0; + * The registers clock gate enable signal of PCNT module. 1: the registers can be read + * and written by application. 0: the registers can not be read or written by + * application + */ + uint32_t clk_en: 1; + uint32_t reserved_17: 15; + }; + uint32_t val; +} pcnt_ctrl_reg_t; + + +/** Group: Status Register */ +/** Type of un_cnt register + * Counter value for unit n + */ +typedef union { + struct { + /** pulse_cnt_un : RO; bitpos: [15:0]; default: 0; + * This register stores the current pulse count value for unit n. + */ + uint32_t pulse_cnt_un: 16; + uint32_t reserved_16: 16; + }; + uint32_t val; +} pcnt_un_cnt_reg_t; + +/** Type of un_status register + * PNCT UNITn status register + */ +typedef union { + struct { + /** cnt_thr_zero_mode_un : RO; bitpos: [1:0]; default: 0; + * The pulse counter status of PCNT_Un corresponding to 0. 0: pulse counter decreases + * from positive to 0. 1: pulse counter increases from negative to 0. 2: pulse counter + * is negative. 3: pulse counter is positive. + */ + uint32_t cnt_thr_zero_mode_un: 2; + /** cnt_thr_thres1_lat_un : RO; bitpos: [2]; default: 0; + * The latched value of thres1 event of PCNT_Un when threshold event interrupt is + * valid. 1: the current pulse counter equals to thres1 and thres1 event is valid. 0: + * others + */ + uint32_t cnt_thr_thres1_lat_un: 1; + /** cnt_thr_thres0_lat_un : RO; bitpos: [3]; default: 0; + * The latched value of thres0 event of PCNT_Un when threshold event interrupt is + * valid. 1: the current pulse counter equals to thres0 and thres0 event is valid. 0: + * others + */ + uint32_t cnt_thr_thres0_lat_un: 1; + /** cnt_thr_l_lim_lat_un : RO; bitpos: [4]; default: 0; + * The latched value of low limit event of PCNT_Un when threshold event interrupt is + * valid. 1: the current pulse counter equals to thr_l_lim and low limit event is + * valid. 0: others + */ + uint32_t cnt_thr_l_lim_lat_un: 1; + /** cnt_thr_h_lim_lat_un : RO; bitpos: [5]; default: 0; + * The latched value of high limit event of PCNT_Un when threshold event interrupt is + * valid. 1: the current pulse counter equals to thr_h_lim and high limit event is + * valid. 0: others + */ + uint32_t cnt_thr_h_lim_lat_un: 1; + /** cnt_thr_zero_lat_un : RO; bitpos: [6]; default: 0; + * The latched value of zero threshold event of PCNT_Un when threshold event interrupt + * is valid. 1: the current pulse counter equals to 0 and zero threshold event is + * valid. 0: others + */ + uint32_t cnt_thr_zero_lat_un: 1; + uint32_t reserved_7: 25; + }; + uint32_t val; +} pcnt_un_status_reg_t; + + +/** Group: Interrupt Register */ +/** Type of int_raw register + * Interrupt raw status register + */ +typedef union { + struct { + /** cnt_thr_event_u0_int_raw : RO; bitpos: [0]; default: 0; + * The raw interrupt status bit for the PCNT_CNT_THR_EVENT_U0_INT interrupt. + */ + uint32_t cnt_thr_event_u0_int_raw: 1; + /** cnt_thr_event_u1_int_raw : RO; bitpos: [1]; default: 0; + * The raw interrupt status bit for the PCNT_CNT_THR_EVENT_U1_INT interrupt. + */ + uint32_t cnt_thr_event_u1_int_raw: 1; + /** cnt_thr_event_u2_int_raw : RO; bitpos: [2]; default: 0; + * The raw interrupt status bit for the PCNT_CNT_THR_EVENT_U2_INT interrupt. + */ + uint32_t cnt_thr_event_u2_int_raw: 1; + /** cnt_thr_event_u3_int_raw : RO; bitpos: [3]; default: 0; + * The raw interrupt status bit for the PCNT_CNT_THR_EVENT_U3_INT interrupt. + */ + uint32_t cnt_thr_event_u3_int_raw: 1; + uint32_t reserved_4: 28; + }; + uint32_t val; +} pcnt_int_raw_reg_t; + +/** Type of int_st register + * Interrupt status register + */ +typedef union { + struct { + /** cnt_thr_event_u0_int_st : RO; bitpos: [0]; default: 0; + * The masked interrupt status bit for the PCNT_CNT_THR_EVENT_U0_INT interrupt. + */ + uint32_t cnt_thr_event_u0_int_st: 1; + /** cnt_thr_event_u1_int_st : RO; bitpos: [1]; default: 0; + * The masked interrupt status bit for the PCNT_CNT_THR_EVENT_U1_INT interrupt. + */ + uint32_t cnt_thr_event_u1_int_st: 1; + /** cnt_thr_event_u2_int_st : RO; bitpos: [2]; default: 0; + * The masked interrupt status bit for the PCNT_CNT_THR_EVENT_U2_INT interrupt. + */ + uint32_t cnt_thr_event_u2_int_st: 1; + /** cnt_thr_event_u3_int_st : RO; bitpos: [3]; default: 0; + * The masked interrupt status bit for the PCNT_CNT_THR_EVENT_U3_INT interrupt. + */ + uint32_t cnt_thr_event_u3_int_st: 1; + uint32_t reserved_4: 28; + }; + uint32_t val; +} pcnt_int_st_reg_t; + +/** Type of int_ena register + * Interrupt enable register + */ +typedef union { + struct { + /** cnt_thr_event_u0_int_ena : R/W; bitpos: [0]; default: 0; + * The interrupt enable bit for the PCNT_CNT_THR_EVENT_U0_INT interrupt. + */ + uint32_t cnt_thr_event_u0_int_ena: 1; + /** cnt_thr_event_u1_int_ena : R/W; bitpos: [1]; default: 0; + * The interrupt enable bit for the PCNT_CNT_THR_EVENT_U1_INT interrupt. + */ + uint32_t cnt_thr_event_u1_int_ena: 1; + /** cnt_thr_event_u2_int_ena : R/W; bitpos: [2]; default: 0; + * The interrupt enable bit for the PCNT_CNT_THR_EVENT_U2_INT interrupt. + */ + uint32_t cnt_thr_event_u2_int_ena: 1; + /** cnt_thr_event_u3_int_ena : R/W; bitpos: [3]; default: 0; + * The interrupt enable bit for the PCNT_CNT_THR_EVENT_U3_INT interrupt. + */ + uint32_t cnt_thr_event_u3_int_ena: 1; + uint32_t reserved_4: 28; + }; + uint32_t val; +} pcnt_int_ena_reg_t; + +/** Type of int_clr register + * Interrupt clear register + */ +typedef union { + struct { + /** cnt_thr_event_u0_int_clr : WO; bitpos: [0]; default: 0; + * Set this bit to clear the PCNT_CNT_THR_EVENT_U0_INT interrupt. + */ + uint32_t cnt_thr_event_u0_int_clr: 1; + /** cnt_thr_event_u1_int_clr : WO; bitpos: [1]; default: 0; + * Set this bit to clear the PCNT_CNT_THR_EVENT_U1_INT interrupt. + */ + uint32_t cnt_thr_event_u1_int_clr: 1; + /** cnt_thr_event_u2_int_clr : WO; bitpos: [2]; default: 0; + * Set this bit to clear the PCNT_CNT_THR_EVENT_U2_INT interrupt. + */ + uint32_t cnt_thr_event_u2_int_clr: 1; + /** cnt_thr_event_u3_int_clr : WO; bitpos: [3]; default: 0; + * Set this bit to clear the PCNT_CNT_THR_EVENT_U3_INT interrupt. + */ + uint32_t cnt_thr_event_u3_int_clr: 1; + uint32_t reserved_4: 28; + }; + uint32_t val; +} pcnt_int_clr_reg_t; + + +/** Group: Version Register */ +/** Type of date register + * PCNT version control register + */ +typedef union { + struct { + /** date : R/W; bitpos: [31:0]; default: 419898881; + * This is the PCNT version control register. + */ + uint32_t date: 32; + }; + uint32_t val; +} pcnt_date_reg_t; + + +typedef struct { + volatile struct { + pcnt_un_conf0_reg_t conf0; + pcnt_un_conf1_reg_t conf1; + pcnt_un_conf2_reg_t conf2; } conf_unit[4]; - union { - struct { - uint32_t cnt_val : 16; - uint32_t reserved16 : 16; - }; - uint32_t val; - } cnt_unit[4]; - union { - struct { - uint32_t cnt_thr_event_u0 : 1; - uint32_t cnt_thr_event_u1 : 1; - uint32_t cnt_thr_event_u2 : 1; - uint32_t cnt_thr_event_u3 : 1; - uint32_t reserved4 : 28; - }; - uint32_t val; - } int_raw; - union { - struct { - uint32_t cnt_thr_event_u0 : 1; - uint32_t cnt_thr_event_u1 : 1; - uint32_t cnt_thr_event_u2 : 1; - uint32_t cnt_thr_event_u3 : 1; - uint32_t reserved4 : 28; - }; - uint32_t val; - } int_st; - union { - struct { - uint32_t cnt_thr_event_u0 : 1; - uint32_t cnt_thr_event_u1 : 1; - uint32_t cnt_thr_event_u2 : 1; - uint32_t cnt_thr_event_u3 : 1; - uint32_t reserved4 : 28; - }; - uint32_t val; - } int_ena; - union { - struct { - uint32_t cnt_thr_event_u0 : 1; - uint32_t cnt_thr_event_u1 : 1; - uint32_t cnt_thr_event_u2 : 1; - uint32_t cnt_thr_event_u3 : 1; - uint32_t reserved4 : 28; - }; - uint32_t val; - } int_clr; - union { - struct { - uint32_t zero_mode : 2; - uint32_t thres1_lat : 1; - uint32_t thres0_lat : 1; - uint32_t l_lim_lat : 1; - uint32_t h_lim_lat : 1; - uint32_t zero_lat : 1; - uint32_t reserved7 : 25; - }; - uint32_t val; - } status_unit[4]; - union { - struct { - uint32_t cnt_rst_u0 : 1; - uint32_t cnt_pause_u0 : 1; - uint32_t cnt_rst_u1 : 1; - uint32_t cnt_pause_u1 : 1; - uint32_t cnt_rst_u2 : 1; - uint32_t cnt_pause_u2 : 1; - uint32_t cnt_rst_u3 : 1; - uint32_t cnt_pause_u3 : 1; - uint32_t reserved8 : 8; - uint32_t clk_en : 1; - uint32_t reserved17 : 15; - }; - uint32_t val; - } ctrl; - uint32_t reserved_64; - uint32_t reserved_68; - uint32_t reserved_6c; - uint32_t reserved_70; - uint32_t reserved_74; - uint32_t reserved_78; - uint32_t reserved_7c; - uint32_t reserved_80; - uint32_t reserved_84; - uint32_t reserved_88; - uint32_t reserved_8c; - uint32_t reserved_90; - uint32_t reserved_94; - uint32_t reserved_98; - uint32_t reserved_9c; - uint32_t reserved_a0; - uint32_t reserved_a4; - uint32_t reserved_a8; - uint32_t reserved_ac; - uint32_t reserved_b0; - uint32_t reserved_b4; - uint32_t reserved_b8; - uint32_t reserved_bc; - uint32_t reserved_c0; - uint32_t reserved_c4; - uint32_t reserved_c8; - uint32_t reserved_cc; - uint32_t reserved_d0; - uint32_t reserved_d4; - uint32_t reserved_d8; - uint32_t reserved_dc; - uint32_t reserved_e0; - uint32_t reserved_e4; - uint32_t reserved_e8; - uint32_t reserved_ec; - uint32_t reserved_f0; - uint32_t reserved_f4; - uint32_t reserved_f8; - uint32_t date; + volatile pcnt_un_cnt_reg_t cnt_unit[4]; + volatile pcnt_int_raw_reg_t int_raw; + volatile pcnt_int_st_reg_t int_st; + volatile pcnt_int_ena_reg_t int_ena; + volatile pcnt_int_clr_reg_t int_clr; + volatile pcnt_un_status_reg_t status_unit[4]; + volatile pcnt_ctrl_reg_t ctrl; + uint32_t reserved_064[38]; + volatile pcnt_date_reg_t date; } pcnt_dev_t; + +#ifndef __cplusplus +_Static_assert(sizeof(pcnt_dev_t) == 0x100, "Invalid size of pcnt_dev_t structure"); +#endif + extern pcnt_dev_t PCNT; + #ifdef __cplusplus } #endif - - - -#endif /*_SOC_PCNT_STRUCT_H_ */ diff --git a/components/soc/esp32s3/include/soc/peri_backup_struct.h b/components/soc/esp32s3/include/soc/peri_backup_struct.h index 0561bd4c23..20d6673f2e 100644 --- a/components/soc/esp32s3/include/soc/peri_backup_struct.h +++ b/components/soc/esp32s3/include/soc/peri_backup_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct peri_backup_dev_s { union { struct { uint32_t reg_peri_backup_flow_err : 3; diff --git a/components/soc/esp32s3/include/soc/periph_defs.h b/components/soc/esp32s3/include/soc/periph_defs.h index 22d46b62f4..8c1b2aaa8b 100644 --- a/components/soc/esp32s3/include/soc/periph_defs.h +++ b/components/soc/esp32s3/include/soc/periph_defs.h @@ -52,6 +52,8 @@ typedef enum { PERIPH_BT_LC_MODULE, PERIPH_AES_MODULE, PERIPH_SHA_MODULE, + PERIPH_HMAC_MODULE, + PERIPH_DS_MODULE, PERIPH_RSA_MODULE, PERIPH_SYSTIMER_MODULE, PERIPH_GDMA_MODULE, @@ -139,8 +141,8 @@ typedef enum { ETS_SHA_INTR_SOURCE, /**< interrupt of SHA accelerator, level*/ ETS_FROM_CPU_INTR0_SOURCE, /**< interrupt0 generated from a CPU, level*/ /* Used for FreeRTOS */ ETS_FROM_CPU_INTR1_SOURCE, /**< interrupt1 generated from a CPU, level*/ /* Used for FreeRTOS */ - ETS_FROM_CPU_INTR2_SOURCE, /**< interrupt2 generated from a CPU, level*/ /* Used for DPORT Access */ - ETS_FROM_CPU_INTR3_SOURCE, /**< interrupt3 generated from a CPU, level*/ /* Used for DPORT Access */ + ETS_FROM_CPU_INTR2_SOURCE, /**< interrupt2 generated from a CPU, level*/ /* Used for IPC_ISR */ + ETS_FROM_CPU_INTR3_SOURCE, /**< interrupt3 generated from a CPU, level*/ /* Used for IPC_ISR */ ETS_ASSIST_DEBUG_INTR_SOURCE, /**< interrupt of Assist debug module, LEVEL*/ ETS_DMA_APBPERI_PMS_INTR_SOURCE, ETS_CORE0_IRAM0_PMS_INTR_SOURCE, diff --git a/components/soc/esp32s3/include/soc/reset_reasons.h b/components/soc/esp32s3/include/soc/reset_reasons.h index 6fc0a7391a..2c1c34e9fe 100644 --- a/components/soc/esp32s3/include/soc/reset_reasons.h +++ b/components/soc/esp32s3/include/soc/reset_reasons.h @@ -56,6 +56,8 @@ typedef enum { RESET_REASON_SYS_SUPER_WDT = 0x12, // Super watch dog resets the digital core and rtc module RESET_REASON_SYS_CLK_GLITCH = 0x13, // Glitch on clock resets the digital core and rtc module RESET_REASON_CORE_EFUSE_CRC = 0x14, // eFuse CRC error resets the digital core + RESET_REASON_CORE_USB_UART = 0x15, // USB UART resets the digital core + RESET_REASON_CORE_USB_JTAG = 0x16, // USB JTAG resets the digital core RESET_REASON_CORE_PWR_GLITCH = 0x17, // Glitch on power resets the digital core } soc_reset_reason_t; diff --git a/components/soc/esp32s3/include/soc/rmt_struct.h b/components/soc/esp32s3/include/soc/rmt_struct.h index bfdcf33546..275bfebce6 100644 --- a/components/soc/esp32s3/include/soc/rmt_struct.h +++ b/components/soc/esp32s3/include/soc/rmt_struct.h @@ -1103,9 +1103,7 @@ typedef struct { typedef struct { struct { - union { - volatile rmt_item32_t data32[48]; - }; + volatile rmt_item32_t data32[48]; } chan[8]; } rmt_mem_t; diff --git a/components/soc/esp32s3/include/soc/rtc.h b/components/soc/esp32s3/include/soc/rtc.h index ac186e5e93..ac801995d3 100644 --- a/components/soc/esp32s3/include/soc/rtc.h +++ b/components/soc/esp32s3/include/soc/rtc.h @@ -92,7 +92,7 @@ extern "C" { * 1. running at 240 MHz * 2. running with 80MHz Flash frequency */ -#ifdef CONFIG_ESPTOOLPY_FLASHFREQ_80M +#if CONFIG_ESPTOOLPY_FLASHFREQ_80M || CONFIG_ESPTOOLPY_FLASHFREQ_120M #define DIG_DBIAS_80M_160M RTC_CNTL_DBIAS_1V25 #else #define DIG_DBIAS_80M_160M RTC_CNTL_DBIAS_1V10 @@ -119,11 +119,14 @@ extern "C" { set sleep_init default param */ #define RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_DEFAULT 5 +#define RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_NODROP 0 #define RTC_CNTL_DBG_ATTEN_DEEPSLEEP_DEFAULT 15 #define RTC_CNTL_DBG_ATTEN_MONITOR_DEFAULT 0 #define RTC_CNTL_BIASSLP_MONITOR_DEFAULT 0 +#define RTC_CNTL_BIASSLP_SLEEP_ON 0 #define RTC_CNTL_BIASSLP_SLEEP_DEFAULT 1 #define RTC_CNTL_PD_CUR_MONITOR_DEFAULT 1 +#define RTC_CNTL_PD_CUR_SLEEP_ON 0 #define RTC_CNTL_PD_CUR_SLEEP_DEFAULT 1 #define RTC_CNTL_DG_VDD_DRV_B_SLP_DEFAULT 0xf @@ -202,7 +205,8 @@ typedef enum { typedef enum { RTC_CAL_RTC_MUX = 0, //!< Currently selected RTC SLOW_CLK RTC_CAL_8MD256 = 1, //!< Internal 8 MHz RC oscillator, divided by 256 - RTC_CAL_32K_XTAL = 2 //!< External 32 kHz XTAL + RTC_CAL_32K_XTAL = 2, //!< External 32 kHz XTAL + RTC_CAL_INTERNAL_OSC = 3 //!< Internal 150 kHz oscillator } rtc_cal_sel_t; /** @@ -642,6 +646,7 @@ typedef struct { uint32_t wifi_pd_en : 1; //!< power down WiFi uint32_t bt_pd_en : 1; //!< power down BT uint32_t cpu_pd_en : 1; //!< power down CPU, but not restart when lightsleep. + uint32_t int_8m_pd_en : 1; //!< Power down Internal 8M oscillator uint32_t dig_peri_pd_en : 1; //!< power down digital peripherals uint32_t deep_slp : 1; //!< power down digital domain uint32_t wdt_flashboot_mod_en : 1; //!< enable WDT flashboot mode @@ -650,6 +655,7 @@ typedef struct { uint32_t rtc_dbias_wak : 5; //!< set bias for RTC domain, in active mode uint32_t rtc_dbias_slp : 5; //!< set bias for RTC domain, in sleep mode uint32_t vddsdio_pd_en : 1; //!< power down VDDSDIO regulator + uint32_t xtal_fpu : 1; //!< keep main XTAL powered up in sleep uint32_t deep_slp_reject : 1; uint32_t light_slp_reject : 1; } rtc_sleep_config_t; @@ -662,6 +668,7 @@ typedef struct { * * @param RTC_SLEEP_PD_x flags combined using bitwise OR */ +#define is_dslp(pd_flags) ((pd_flags) & RTC_SLEEP_PD_DIG) #define RTC_SLEEP_CONFIG_DEFAULT(sleep_flags) { \ .lslp_mem_inf_fpu = 0, \ .rtc_mem_inf_follow_cpu = ((sleep_flags) & RTC_SLEEP_PD_RTC_MEM_FOLLOW_CPU) ? 1 : 0, \ @@ -671,14 +678,20 @@ typedef struct { .wifi_pd_en = ((sleep_flags) & RTC_SLEEP_PD_WIFI) ? 1 : 0, \ .bt_pd_en = ((sleep_flags) & RTC_SLEEP_PD_BT) ? 1 : 0, \ .cpu_pd_en = ((sleep_flags) & RTC_SLEEP_PD_CPU) ? 1 : 0, \ + .int_8m_pd_en = is_dslp(sleep_flags) ? 1 : ((sleep_flags) & RTC_SLEEP_PD_INT_8M) ? 1 : 0, \ .dig_peri_pd_en = ((sleep_flags) & RTC_SLEEP_PD_DIG_PERIPH) ? 1 : 0, \ .deep_slp = ((sleep_flags) & RTC_SLEEP_PD_DIG) ? 1 : 0, \ .wdt_flashboot_mod_en = 0, \ .dig_dbias_wak = RTC_CNTL_DBIAS_1V10, \ - .dig_dbias_slp = RTC_CNTL_DBIAS_SLP, \ + .dig_dbias_slp = is_dslp(sleep_flags) ? RTC_CNTL_DBIAS_SLP \ + : !((sleep_flags) & RTC_SLEEP_PD_INT_8M) ? RTC_CNTL_DBIAS_1V10 \ + : RTC_CNTL_DBIAS_SLP, \ .rtc_dbias_wak = RTC_CNTL_DBIAS_1V10, \ - .rtc_dbias_slp = RTC_CNTL_DBIAS_SLP, \ + .rtc_dbias_slp = is_dslp(sleep_flags) ? RTC_CNTL_DBIAS_SLP \ + : !((sleep_flags) & RTC_SLEEP_PD_INT_8M) ? RTC_CNTL_DBIAS_1V10 \ + : RTC_CNTL_DBIAS_SLP, \ .vddsdio_pd_en = ((sleep_flags) & RTC_SLEEP_PD_VDDSDIO) ? 1 : 0, \ + .xtal_fpu = is_dslp(sleep_flags) ? 0 : ((sleep_flags) & RTC_SLEEP_PD_XTAL) ? 0 : 1, \ .deep_slp_reject = 1, \ .light_slp_reject = 1 \ }; @@ -693,6 +706,8 @@ typedef struct { #define RTC_SLEEP_PD_BT BIT(7) //!< Power down BT #define RTC_SLEEP_PD_CPU BIT(8) //!< Power down CPU when in lightsleep, but not restart #define RTC_SLEEP_PD_DIG_PERIPH BIT(9) //!< Power down DIG peripherals +#define RTC_SLEEP_PD_INT_8M BIT(10) //!< Power down Internal 8M oscillator +#define RTC_SLEEP_PD_XTAL BIT(11) //!< Power down main XTAL /** * @brief Prepare the chip to enter sleep mode diff --git a/components/soc/esp32s3/include/soc/rtc_cntl_reg.h b/components/soc/esp32s3/include/soc/rtc_cntl_reg.h index 353c0a53e2..4f15782f5b 100644 --- a/components/soc/esp32s3/include/soc/rtc_cntl_reg.h +++ b/components/soc/esp32s3/include/soc/rtc_cntl_reg.h @@ -3584,6 +3584,10 @@ ork.*/ #define RTC_CNTL_FIB_SEL_V 0x7 #define RTC_CNTL_FIB_SEL_S 0 +#define RTC_CNTL_FIB_GLITCH_RST BIT(0) +#define RTC_CNTL_FIB_BOR_RST BIT(1) +#define RTC_CNTL_FIB_SUPER_WDT_RST BIT(2) + #define RTC_CNTL_TOUCH_DAC_REG (DR_REG_RTCCNTL_BASE + 0x14C) /* RTC_CNTL_TOUCH_PAD0_DAC : R/W ;bitpos:[31:29] ;default: 3'd0 ; */ /*description: .*/ diff --git a/components/soc/esp32s3/include/soc/rtc_cntl_struct.h b/components/soc/esp32s3/include/soc/rtc_cntl_struct.h index 32493d8359..d3366dd0f9 100644 --- a/components/soc/esp32s3/include/soc/rtc_cntl_struct.h +++ b/components/soc/esp32s3/include/soc/rtc_cntl_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct rtc_cntl_dev_s { union { struct { uint32_t sw_stall_appcpu_c0 : 2; /*{reg_sw_stall_appcpu_c1[5:0], reg_sw_stall_appcpu_c0[1:0]} == 0x86 will stall APP CPU*/ diff --git a/components/soc/esp32s3/include/soc/rtc_io_struct.h b/components/soc/esp32s3/include/soc/rtc_io_struct.h index c366c65cf2..1154be038b 100644 --- a/components/soc/esp32s3/include/soc/rtc_io_struct.h +++ b/components/soc/esp32s3/include/soc/rtc_io_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct rtc_io_dev_s { union { struct { uint32_t reserved0 : 10; diff --git a/components/soc/esp32s3/include/soc/sdmmc_struct.h b/components/soc/esp32s3/include/soc/sdmmc_struct.h index 78b21aa156..599528a34a 100644 --- a/components/soc/esp32s3/include/soc/sdmmc_struct.h +++ b/components/soc/esp32s3/include/soc/sdmmc_struct.h @@ -21,18 +21,22 @@ extern "C" { #endif typedef struct sdmmc_desc_s { - uint32_t reserved1: 1; - uint32_t disable_int_on_completion: 1; - uint32_t last_descriptor: 1; - uint32_t first_descriptor: 1; - uint32_t second_address_chained: 1; - uint32_t end_of_ring: 1; - uint32_t reserved2: 24; - uint32_t card_error_summary: 1; - uint32_t owned_by_idmac: 1; - uint32_t buffer1_size: 13; - uint32_t buffer2_size: 13; - uint32_t reserved3: 6; + struct { + uint32_t reserved1: 1; + uint32_t disable_int_on_completion: 1; + uint32_t last_descriptor: 1; + uint32_t first_descriptor: 1; + uint32_t second_address_chained: 1; + uint32_t end_of_ring: 1; + uint32_t reserved2: 24; + uint32_t card_error_summary: 1; + uint32_t owned_by_idmac: 1; + }; + struct { + uint32_t buffer1_size: 13; + uint32_t buffer2_size: 13; + uint32_t reserved3: 6; + }; void* buffer1_ptr; union { void* buffer2_ptr; @@ -144,8 +148,10 @@ typedef volatile struct sdmmc_dev_s { uint32_t val; } ctype; - uint32_t blksiz: 16; ///< block size, default 0x200 - uint32_t : 16; + struct { + uint32_t blksiz: 16; ///< block size, default 0x200 + uint32_t reserved: 16; + }; uint32_t bytcnt; ///< number of bytes to be transferred @@ -324,6 +330,7 @@ typedef volatile struct sdmmc_dev_s { uint32_t ces: 1; ///< card error summary uint32_t reserved2: 2; uint32_t nis: 1; ///< normal interrupt summary + uint32_t ais: 1; ///< abnormal interrupt summary uint32_t fbe_code: 3; ///< code of fatal bus error uint32_t fsm: 4; ///< DMAC FSM state uint32_t reserved3: 15; @@ -359,7 +366,7 @@ typedef volatile struct sdmmc_dev_s { uint32_t busy_clr_int_en : 1; ///< enable generation of busy clear interrupts uint32_t write_thr_en : 1; ///< equivalent of read_thr_en for writes uint32_t reserved1 : 13; - uint32_t card_threshold : 12; ///< threshold value for reads/writes, in bytes + uint32_t card_threshold : 16; ///< threshold value for reads/writes, in bytes }; uint32_t val; } cardthrctl; @@ -378,6 +385,7 @@ typedef volatile struct sdmmc_dev_s { uint32_t div_factor_m: 4; ///< should be equal to div_factor_p uint32_t reserved1 : 2; uint32_t clk_sel : 1; ///< clock source select (0: XTAL, 1: 160 MHz from PLL) + uint32_t reserved24: 8; }; uint32_t val; } clock; diff --git a/components/soc/esp32s3/include/soc/sens_struct.h b/components/soc/esp32s3/include/soc/sens_struct.h index 915675bf71..3fee23099d 100644 --- a/components/soc/esp32s3/include/soc/sens_struct.h +++ b/components/soc/esp32s3/include/soc/sens_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct sens_dev_s { union { struct { uint32_t sar1_clk_div : 8; /*clock divider*/ diff --git a/components/soc/esp32s3/include/soc/sensitive_struct.h b/components/soc/esp32s3/include/soc/sensitive_struct.h index 69feaf37b2..e9919cb0a6 100644 --- a/components/soc/esp32s3/include/soc/sensitive_struct.h +++ b/components/soc/esp32s3/include/soc/sensitive_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct sensitive_dev_s { union { struct { uint32_t cache_dataarray_connect_lock : 1; diff --git a/components/soc/esp32s3/include/soc/slc_reg.h b/components/soc/esp32s3/include/soc/slc_reg.h deleted file mode 100644 index 31b1a55e59..0000000000 --- a/components/soc/esp32s3/include/soc/slc_reg.h +++ /dev/null @@ -1,1912 +0,0 @@ -// 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. -#ifndef _SOC_SLC_REG_H_ -#define _SOC_SLC_REG_H_ - - -#include "soc.h" -#ifdef __cplusplus -extern "C" { -#endif - -#define SLC_SLCCONF0_REG (DR_REG_SLC_BASE + 0x0) -/* SLC_SLC0_WR_RETRY_MASK_EN : R/W ;bitpos:[18] ;default: 1'b1 ; */ -/*description: .*/ -#define SLC_SLC0_WR_RETRY_MASK_EN (BIT(18)) -#define SLC_SLC0_WR_RETRY_MASK_EN_M (BIT(18)) -#define SLC_SLC0_WR_RETRY_MASK_EN_V 0x1 -#define SLC_SLC0_WR_RETRY_MASK_EN_S 18 -/* SLC_SLC0_TOKEN_SEL : R/W ;bitpos:[15] ;default: 1'h1 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN_SEL (BIT(15)) -#define SLC_SLC0_TOKEN_SEL_M (BIT(15)) -#define SLC_SLC0_TOKEN_SEL_V 0x1 -#define SLC_SLC0_TOKEN_SEL_S 15 -/* SLC_SLC0_TOKEN_AUTO_CLR : R/W ;bitpos:[14] ;default: 1'h1 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN_AUTO_CLR (BIT(14)) -#define SLC_SLC0_TOKEN_AUTO_CLR_M (BIT(14)) -#define SLC_SLC0_TOKEN_AUTO_CLR_V 0x1 -#define SLC_SLC0_TOKEN_AUTO_CLR_S 14 -/* SLC_SLC0_TXDATA_BURST_EN : R/W ;bitpos:[13] ;default: 1'b1 ; */ -/*description: .*/ -#define SLC_SLC0_TXDATA_BURST_EN (BIT(13)) -#define SLC_SLC0_TXDATA_BURST_EN_M (BIT(13)) -#define SLC_SLC0_TXDATA_BURST_EN_V 0x1 -#define SLC_SLC0_TXDATA_BURST_EN_S 13 -/* SLC_SLC0_TXDSCR_BURST_EN : R/W ;bitpos:[12] ;default: 1'b1 ; */ -/*description: .*/ -#define SLC_SLC0_TXDSCR_BURST_EN (BIT(12)) -#define SLC_SLC0_TXDSCR_BURST_EN_M (BIT(12)) -#define SLC_SLC0_TXDSCR_BURST_EN_V 0x1 -#define SLC_SLC0_TXDSCR_BURST_EN_S 12 -/* SLC_SLC0_TXLINK_AUTO_RET : R/W ;bitpos:[11] ;default: 1'h1 ; */ -/*description: .*/ -#define SLC_SLC0_TXLINK_AUTO_RET (BIT(11)) -#define SLC_SLC0_TXLINK_AUTO_RET_M (BIT(11)) -#define SLC_SLC0_TXLINK_AUTO_RET_V 0x1 -#define SLC_SLC0_TXLINK_AUTO_RET_S 11 -/* SLC_SLC0_RXLINK_AUTO_RET : R/W ;bitpos:[10] ;default: 1'h1 ; */ -/*description: .*/ -#define SLC_SLC0_RXLINK_AUTO_RET (BIT(10)) -#define SLC_SLC0_RXLINK_AUTO_RET_M (BIT(10)) -#define SLC_SLC0_RXLINK_AUTO_RET_V 0x1 -#define SLC_SLC0_RXLINK_AUTO_RET_S 10 -/* SLC_SLC0_RXDATA_BURST_EN : R/W ;bitpos:[9] ;default: 1'b1 ; */ -/*description: .*/ -#define SLC_SLC0_RXDATA_BURST_EN (BIT(9)) -#define SLC_SLC0_RXDATA_BURST_EN_M (BIT(9)) -#define SLC_SLC0_RXDATA_BURST_EN_V 0x1 -#define SLC_SLC0_RXDATA_BURST_EN_S 9 -/* SLC_SLC0_RXDSCR_BURST_EN : R/W ;bitpos:[8] ;default: 1'b1 ; */ -/*description: .*/ -#define SLC_SLC0_RXDSCR_BURST_EN (BIT(8)) -#define SLC_SLC0_RXDSCR_BURST_EN_M (BIT(8)) -#define SLC_SLC0_RXDSCR_BURST_EN_V 0x1 -#define SLC_SLC0_RXDSCR_BURST_EN_S 8 -/* SLC_SLC0_RX_NO_RESTART_CLR : R/W ;bitpos:[7] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_NO_RESTART_CLR (BIT(7)) -#define SLC_SLC0_RX_NO_RESTART_CLR_M (BIT(7)) -#define SLC_SLC0_RX_NO_RESTART_CLR_V 0x1 -#define SLC_SLC0_RX_NO_RESTART_CLR_S 7 -/* SLC_SLC0_RX_AUTO_WRBACK : R/W ;bitpos:[6] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_AUTO_WRBACK (BIT(6)) -#define SLC_SLC0_RX_AUTO_WRBACK_M (BIT(6)) -#define SLC_SLC0_RX_AUTO_WRBACK_V 0x1 -#define SLC_SLC0_RX_AUTO_WRBACK_S 6 -/* SLC_SLC0_RX_LOOP_TEST : R/W ;bitpos:[5] ;default: 1'b1 ; */ -/*description: .*/ -#define SLC_SLC0_RX_LOOP_TEST (BIT(5)) -#define SLC_SLC0_RX_LOOP_TEST_M (BIT(5)) -#define SLC_SLC0_RX_LOOP_TEST_V 0x1 -#define SLC_SLC0_RX_LOOP_TEST_S 5 -/* SLC_SLC0_TX_LOOP_TEST : R/W ;bitpos:[4] ;default: 1'b1 ; */ -/*description: .*/ -#define SLC_SLC0_TX_LOOP_TEST (BIT(4)) -#define SLC_SLC0_TX_LOOP_TEST_M (BIT(4)) -#define SLC_SLC0_TX_LOOP_TEST_V 0x1 -#define SLC_SLC0_TX_LOOP_TEST_S 4 -/* SLC_AHBM_RST : R/W ;bitpos:[3] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_AHBM_RST (BIT(3)) -#define SLC_AHBM_RST_M (BIT(3)) -#define SLC_AHBM_RST_V 0x1 -#define SLC_AHBM_RST_S 3 -/* SLC_AHBM_FIFO_RST : R/W ;bitpos:[2] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_AHBM_FIFO_RST (BIT(2)) -#define SLC_AHBM_FIFO_RST_M (BIT(2)) -#define SLC_AHBM_FIFO_RST_V 0x1 -#define SLC_AHBM_FIFO_RST_S 2 -/* SLC_SLC0_RX_RST : R/W ;bitpos:[1] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_RST (BIT(1)) -#define SLC_SLC0_RX_RST_M (BIT(1)) -#define SLC_SLC0_RX_RST_V 0x1 -#define SLC_SLC0_RX_RST_S 1 -/* SLC_SLC0_TX_RST : R/W ;bitpos:[0] ;default: 1'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_RST (BIT(0)) -#define SLC_SLC0_TX_RST_M (BIT(0)) -#define SLC_SLC0_TX_RST_V 0x1 -#define SLC_SLC0_TX_RST_S 0 - -#define SLC_INT_RAW_REG (DR_REG_SLC_BASE + 0x4) -/* SLC_SLC0_HOST_POP_EOF_ERR_INT_RAW : RO ;bitpos:[27] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_RAW (BIT(27)) -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_RAW_M (BIT(27)) -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_RAW_V 0x1 -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_RAW_S 27 -/* SLC_SLC0_RX_QUICK_EOF_INT_RAW : RO ;bitpos:[26] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_QUICK_EOF_INT_RAW (BIT(26)) -#define SLC_SLC0_RX_QUICK_EOF_INT_RAW_M (BIT(26)) -#define SLC_SLC0_RX_QUICK_EOF_INT_RAW_V 0x1 -#define SLC_SLC0_RX_QUICK_EOF_INT_RAW_S 26 -/* SLC_CMD_DTC_INT_RAW : RO ;bitpos:[25] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_CMD_DTC_INT_RAW (BIT(25)) -#define SLC_CMD_DTC_INT_RAW_M (BIT(25)) -#define SLC_CMD_DTC_INT_RAW_V 0x1 -#define SLC_CMD_DTC_INT_RAW_S 25 -/* SLC_SLC0_TX_ERR_EOF_INT_RAW : RO ;bitpos:[24] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_ERR_EOF_INT_RAW (BIT(24)) -#define SLC_SLC0_TX_ERR_EOF_INT_RAW_M (BIT(24)) -#define SLC_SLC0_TX_ERR_EOF_INT_RAW_V 0x1 -#define SLC_SLC0_TX_ERR_EOF_INT_RAW_S 24 -/* SLC_SLC0_WR_RETRY_DONE_INT_RAW : RO ;bitpos:[23] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_WR_RETRY_DONE_INT_RAW (BIT(23)) -#define SLC_SLC0_WR_RETRY_DONE_INT_RAW_M (BIT(23)) -#define SLC_SLC0_WR_RETRY_DONE_INT_RAW_V 0x1 -#define SLC_SLC0_WR_RETRY_DONE_INT_RAW_S 23 -/* SLC_SLC0_HOST_RD_ACK_INT_RAW : RO ;bitpos:[22] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_HOST_RD_ACK_INT_RAW (BIT(22)) -#define SLC_SLC0_HOST_RD_ACK_INT_RAW_M (BIT(22)) -#define SLC_SLC0_HOST_RD_ACK_INT_RAW_V 0x1 -#define SLC_SLC0_HOST_RD_ACK_INT_RAW_S 22 -/* SLC_SLC0_TX_DSCR_EMPTY_INT_RAW : RO ;bitpos:[21] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DSCR_EMPTY_INT_RAW (BIT(21)) -#define SLC_SLC0_TX_DSCR_EMPTY_INT_RAW_M (BIT(21)) -#define SLC_SLC0_TX_DSCR_EMPTY_INT_RAW_V 0x1 -#define SLC_SLC0_TX_DSCR_EMPTY_INT_RAW_S 21 -/* SLC_SLC0_RX_DSCR_ERR_INT_RAW : RO ;bitpos:[20] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_DSCR_ERR_INT_RAW (BIT(20)) -#define SLC_SLC0_RX_DSCR_ERR_INT_RAW_M (BIT(20)) -#define SLC_SLC0_RX_DSCR_ERR_INT_RAW_V 0x1 -#define SLC_SLC0_RX_DSCR_ERR_INT_RAW_S 20 -/* SLC_SLC0_TX_DSCR_ERR_INT_RAW : RO ;bitpos:[19] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DSCR_ERR_INT_RAW (BIT(19)) -#define SLC_SLC0_TX_DSCR_ERR_INT_RAW_M (BIT(19)) -#define SLC_SLC0_TX_DSCR_ERR_INT_RAW_V 0x1 -#define SLC_SLC0_TX_DSCR_ERR_INT_RAW_S 19 -/* SLC_SLC0_TOHOST_INT_RAW : RO ;bitpos:[18] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOHOST_INT_RAW (BIT(18)) -#define SLC_SLC0_TOHOST_INT_RAW_M (BIT(18)) -#define SLC_SLC0_TOHOST_INT_RAW_V 0x1 -#define SLC_SLC0_TOHOST_INT_RAW_S 18 -/* SLC_SLC0_RX_EOF_INT_RAW : RO ;bitpos:[17] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_EOF_INT_RAW (BIT(17)) -#define SLC_SLC0_RX_EOF_INT_RAW_M (BIT(17)) -#define SLC_SLC0_RX_EOF_INT_RAW_V 0x1 -#define SLC_SLC0_RX_EOF_INT_RAW_S 17 -/* SLC_SLC0_RX_DONE_INT_RAW : RO ;bitpos:[16] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_DONE_INT_RAW (BIT(16)) -#define SLC_SLC0_RX_DONE_INT_RAW_M (BIT(16)) -#define SLC_SLC0_RX_DONE_INT_RAW_V 0x1 -#define SLC_SLC0_RX_DONE_INT_RAW_S 16 -/* SLC_SLC0_TX_SUC_EOF_INT_RAW : RO ;bitpos:[15] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_SUC_EOF_INT_RAW (BIT(15)) -#define SLC_SLC0_TX_SUC_EOF_INT_RAW_M (BIT(15)) -#define SLC_SLC0_TX_SUC_EOF_INT_RAW_V 0x1 -#define SLC_SLC0_TX_SUC_EOF_INT_RAW_S 15 -/* SLC_SLC0_TX_DONE_INT_RAW : RO ;bitpos:[14] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DONE_INT_RAW (BIT(14)) -#define SLC_SLC0_TX_DONE_INT_RAW_M (BIT(14)) -#define SLC_SLC0_TX_DONE_INT_RAW_V 0x1 -#define SLC_SLC0_TX_DONE_INT_RAW_S 14 -/* SLC_SLC0_TOKEN1_1TO0_INT_RAW : RO ;bitpos:[13] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN1_1TO0_INT_RAW (BIT(13)) -#define SLC_SLC0_TOKEN1_1TO0_INT_RAW_M (BIT(13)) -#define SLC_SLC0_TOKEN1_1TO0_INT_RAW_V 0x1 -#define SLC_SLC0_TOKEN1_1TO0_INT_RAW_S 13 -/* SLC_SLC0_TOKEN0_1TO0_INT_RAW : RO ;bitpos:[12] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN0_1TO0_INT_RAW (BIT(12)) -#define SLC_SLC0_TOKEN0_1TO0_INT_RAW_M (BIT(12)) -#define SLC_SLC0_TOKEN0_1TO0_INT_RAW_V 0x1 -#define SLC_SLC0_TOKEN0_1TO0_INT_RAW_S 12 -/* SLC_SLC0_TX_OVF_INT_RAW : RO ;bitpos:[11] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_OVF_INT_RAW (BIT(11)) -#define SLC_SLC0_TX_OVF_INT_RAW_M (BIT(11)) -#define SLC_SLC0_TX_OVF_INT_RAW_V 0x1 -#define SLC_SLC0_TX_OVF_INT_RAW_S 11 -/* SLC_SLC0_RX_UDF_INT_RAW : RO ;bitpos:[10] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_UDF_INT_RAW (BIT(10)) -#define SLC_SLC0_RX_UDF_INT_RAW_M (BIT(10)) -#define SLC_SLC0_RX_UDF_INT_RAW_V 0x1 -#define SLC_SLC0_RX_UDF_INT_RAW_S 10 -/* SLC_SLC0_TX_START_INT_RAW : RO ;bitpos:[9] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_START_INT_RAW (BIT(9)) -#define SLC_SLC0_TX_START_INT_RAW_M (BIT(9)) -#define SLC_SLC0_TX_START_INT_RAW_V 0x1 -#define SLC_SLC0_TX_START_INT_RAW_S 9 -/* SLC_SLC0_RX_START_INT_RAW : RO ;bitpos:[8] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_START_INT_RAW (BIT(8)) -#define SLC_SLC0_RX_START_INT_RAW_M (BIT(8)) -#define SLC_SLC0_RX_START_INT_RAW_V 0x1 -#define SLC_SLC0_RX_START_INT_RAW_S 8 -/* SLC_FRHOST_BIT7_INT_RAW : RO ;bitpos:[7] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT7_INT_RAW (BIT(7)) -#define SLC_FRHOST_BIT7_INT_RAW_M (BIT(7)) -#define SLC_FRHOST_BIT7_INT_RAW_V 0x1 -#define SLC_FRHOST_BIT7_INT_RAW_S 7 -/* SLC_FRHOST_BIT6_INT_RAW : RO ;bitpos:[6] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT6_INT_RAW (BIT(6)) -#define SLC_FRHOST_BIT6_INT_RAW_M (BIT(6)) -#define SLC_FRHOST_BIT6_INT_RAW_V 0x1 -#define SLC_FRHOST_BIT6_INT_RAW_S 6 -/* SLC_FRHOST_BIT5_INT_RAW : RO ;bitpos:[5] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT5_INT_RAW (BIT(5)) -#define SLC_FRHOST_BIT5_INT_RAW_M (BIT(5)) -#define SLC_FRHOST_BIT5_INT_RAW_V 0x1 -#define SLC_FRHOST_BIT5_INT_RAW_S 5 -/* SLC_FRHOST_BIT4_INT_RAW : RO ;bitpos:[4] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT4_INT_RAW (BIT(4)) -#define SLC_FRHOST_BIT4_INT_RAW_M (BIT(4)) -#define SLC_FRHOST_BIT4_INT_RAW_V 0x1 -#define SLC_FRHOST_BIT4_INT_RAW_S 4 -/* SLC_FRHOST_BIT3_INT_RAW : RO ;bitpos:[3] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT3_INT_RAW (BIT(3)) -#define SLC_FRHOST_BIT3_INT_RAW_M (BIT(3)) -#define SLC_FRHOST_BIT3_INT_RAW_V 0x1 -#define SLC_FRHOST_BIT3_INT_RAW_S 3 -/* SLC_FRHOST_BIT2_INT_RAW : RO ;bitpos:[2] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT2_INT_RAW (BIT(2)) -#define SLC_FRHOST_BIT2_INT_RAW_M (BIT(2)) -#define SLC_FRHOST_BIT2_INT_RAW_V 0x1 -#define SLC_FRHOST_BIT2_INT_RAW_S 2 -/* SLC_FRHOST_BIT1_INT_RAW : RO ;bitpos:[1] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT1_INT_RAW (BIT(1)) -#define SLC_FRHOST_BIT1_INT_RAW_M (BIT(1)) -#define SLC_FRHOST_BIT1_INT_RAW_V 0x1 -#define SLC_FRHOST_BIT1_INT_RAW_S 1 -/* SLC_FRHOST_BIT0_INT_RAW : RO ;bitpos:[0] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT0_INT_RAW (BIT(0)) -#define SLC_FRHOST_BIT0_INT_RAW_M (BIT(0)) -#define SLC_FRHOST_BIT0_INT_RAW_V 0x1 -#define SLC_FRHOST_BIT0_INT_RAW_S 0 - -#define SLC_INT_ST_REG (DR_REG_SLC_BASE + 0x8) -/* SLC_SLC0_HOST_POP_EOF_ERR_INT_ST : RO ;bitpos:[27] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_ST (BIT(27)) -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_ST_M (BIT(27)) -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_ST_V 0x1 -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_ST_S 27 -/* SLC_SLC0_RX_QUICK_EOF_INT_ST : RO ;bitpos:[26] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_QUICK_EOF_INT_ST (BIT(26)) -#define SLC_SLC0_RX_QUICK_EOF_INT_ST_M (BIT(26)) -#define SLC_SLC0_RX_QUICK_EOF_INT_ST_V 0x1 -#define SLC_SLC0_RX_QUICK_EOF_INT_ST_S 26 -/* SLC_CMD_DTC_INT_ST : RO ;bitpos:[25] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_CMD_DTC_INT_ST (BIT(25)) -#define SLC_CMD_DTC_INT_ST_M (BIT(25)) -#define SLC_CMD_DTC_INT_ST_V 0x1 -#define SLC_CMD_DTC_INT_ST_S 25 -/* SLC_SLC0_TX_ERR_EOF_INT_ST : RO ;bitpos:[24] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_ERR_EOF_INT_ST (BIT(24)) -#define SLC_SLC0_TX_ERR_EOF_INT_ST_M (BIT(24)) -#define SLC_SLC0_TX_ERR_EOF_INT_ST_V 0x1 -#define SLC_SLC0_TX_ERR_EOF_INT_ST_S 24 -/* SLC_SLC0_WR_RETRY_DONE_INT_ST : RO ;bitpos:[23] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_WR_RETRY_DONE_INT_ST (BIT(23)) -#define SLC_SLC0_WR_RETRY_DONE_INT_ST_M (BIT(23)) -#define SLC_SLC0_WR_RETRY_DONE_INT_ST_V 0x1 -#define SLC_SLC0_WR_RETRY_DONE_INT_ST_S 23 -/* SLC_SLC0_HOST_RD_ACK_INT_ST : RO ;bitpos:[22] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_HOST_RD_ACK_INT_ST (BIT(22)) -#define SLC_SLC0_HOST_RD_ACK_INT_ST_M (BIT(22)) -#define SLC_SLC0_HOST_RD_ACK_INT_ST_V 0x1 -#define SLC_SLC0_HOST_RD_ACK_INT_ST_S 22 -/* SLC_SLC0_TX_DSCR_EMPTY_INT_ST : RO ;bitpos:[21] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DSCR_EMPTY_INT_ST (BIT(21)) -#define SLC_SLC0_TX_DSCR_EMPTY_INT_ST_M (BIT(21)) -#define SLC_SLC0_TX_DSCR_EMPTY_INT_ST_V 0x1 -#define SLC_SLC0_TX_DSCR_EMPTY_INT_ST_S 21 -/* SLC_SLC0_RX_DSCR_ERR_INT_ST : RO ;bitpos:[20] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_DSCR_ERR_INT_ST (BIT(20)) -#define SLC_SLC0_RX_DSCR_ERR_INT_ST_M (BIT(20)) -#define SLC_SLC0_RX_DSCR_ERR_INT_ST_V 0x1 -#define SLC_SLC0_RX_DSCR_ERR_INT_ST_S 20 -/* SLC_SLC0_TX_DSCR_ERR_INT_ST : RO ;bitpos:[19] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DSCR_ERR_INT_ST (BIT(19)) -#define SLC_SLC0_TX_DSCR_ERR_INT_ST_M (BIT(19)) -#define SLC_SLC0_TX_DSCR_ERR_INT_ST_V 0x1 -#define SLC_SLC0_TX_DSCR_ERR_INT_ST_S 19 -/* SLC_SLC0_TOHOST_INT_ST : RO ;bitpos:[18] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOHOST_INT_ST (BIT(18)) -#define SLC_SLC0_TOHOST_INT_ST_M (BIT(18)) -#define SLC_SLC0_TOHOST_INT_ST_V 0x1 -#define SLC_SLC0_TOHOST_INT_ST_S 18 -/* SLC_SLC0_RX_EOF_INT_ST : RO ;bitpos:[17] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_EOF_INT_ST (BIT(17)) -#define SLC_SLC0_RX_EOF_INT_ST_M (BIT(17)) -#define SLC_SLC0_RX_EOF_INT_ST_V 0x1 -#define SLC_SLC0_RX_EOF_INT_ST_S 17 -/* SLC_SLC0_RX_DONE_INT_ST : RO ;bitpos:[16] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_DONE_INT_ST (BIT(16)) -#define SLC_SLC0_RX_DONE_INT_ST_M (BIT(16)) -#define SLC_SLC0_RX_DONE_INT_ST_V 0x1 -#define SLC_SLC0_RX_DONE_INT_ST_S 16 -/* SLC_SLC0_TX_SUC_EOF_INT_ST : RO ;bitpos:[15] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_SUC_EOF_INT_ST (BIT(15)) -#define SLC_SLC0_TX_SUC_EOF_INT_ST_M (BIT(15)) -#define SLC_SLC0_TX_SUC_EOF_INT_ST_V 0x1 -#define SLC_SLC0_TX_SUC_EOF_INT_ST_S 15 -/* SLC_SLC0_TX_DONE_INT_ST : RO ;bitpos:[14] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DONE_INT_ST (BIT(14)) -#define SLC_SLC0_TX_DONE_INT_ST_M (BIT(14)) -#define SLC_SLC0_TX_DONE_INT_ST_V 0x1 -#define SLC_SLC0_TX_DONE_INT_ST_S 14 -/* SLC_SLC0_TOKEN1_1TO0_INT_ST : RO ;bitpos:[13] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN1_1TO0_INT_ST (BIT(13)) -#define SLC_SLC0_TOKEN1_1TO0_INT_ST_M (BIT(13)) -#define SLC_SLC0_TOKEN1_1TO0_INT_ST_V 0x1 -#define SLC_SLC0_TOKEN1_1TO0_INT_ST_S 13 -/* SLC_SLC0_TOKEN0_1TO0_INT_ST : RO ;bitpos:[12] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN0_1TO0_INT_ST (BIT(12)) -#define SLC_SLC0_TOKEN0_1TO0_INT_ST_M (BIT(12)) -#define SLC_SLC0_TOKEN0_1TO0_INT_ST_V 0x1 -#define SLC_SLC0_TOKEN0_1TO0_INT_ST_S 12 -/* SLC_SLC0_TX_OVF_INT_ST : RO ;bitpos:[11] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_OVF_INT_ST (BIT(11)) -#define SLC_SLC0_TX_OVF_INT_ST_M (BIT(11)) -#define SLC_SLC0_TX_OVF_INT_ST_V 0x1 -#define SLC_SLC0_TX_OVF_INT_ST_S 11 -/* SLC_SLC0_RX_UDF_INT_ST : RO ;bitpos:[10] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_UDF_INT_ST (BIT(10)) -#define SLC_SLC0_RX_UDF_INT_ST_M (BIT(10)) -#define SLC_SLC0_RX_UDF_INT_ST_V 0x1 -#define SLC_SLC0_RX_UDF_INT_ST_S 10 -/* SLC_SLC0_TX_START_INT_ST : RO ;bitpos:[9] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_START_INT_ST (BIT(9)) -#define SLC_SLC0_TX_START_INT_ST_M (BIT(9)) -#define SLC_SLC0_TX_START_INT_ST_V 0x1 -#define SLC_SLC0_TX_START_INT_ST_S 9 -/* SLC_SLC0_RX_START_INT_ST : RO ;bitpos:[8] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_START_INT_ST (BIT(8)) -#define SLC_SLC0_RX_START_INT_ST_M (BIT(8)) -#define SLC_SLC0_RX_START_INT_ST_V 0x1 -#define SLC_SLC0_RX_START_INT_ST_S 8 -/* SLC_FRHOST_BIT7_INT_ST : RO ;bitpos:[7] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT7_INT_ST (BIT(7)) -#define SLC_FRHOST_BIT7_INT_ST_M (BIT(7)) -#define SLC_FRHOST_BIT7_INT_ST_V 0x1 -#define SLC_FRHOST_BIT7_INT_ST_S 7 -/* SLC_FRHOST_BIT6_INT_ST : RO ;bitpos:[6] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT6_INT_ST (BIT(6)) -#define SLC_FRHOST_BIT6_INT_ST_M (BIT(6)) -#define SLC_FRHOST_BIT6_INT_ST_V 0x1 -#define SLC_FRHOST_BIT6_INT_ST_S 6 -/* SLC_FRHOST_BIT5_INT_ST : RO ;bitpos:[5] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT5_INT_ST (BIT(5)) -#define SLC_FRHOST_BIT5_INT_ST_M (BIT(5)) -#define SLC_FRHOST_BIT5_INT_ST_V 0x1 -#define SLC_FRHOST_BIT5_INT_ST_S 5 -/* SLC_FRHOST_BIT4_INT_ST : RO ;bitpos:[4] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT4_INT_ST (BIT(4)) -#define SLC_FRHOST_BIT4_INT_ST_M (BIT(4)) -#define SLC_FRHOST_BIT4_INT_ST_V 0x1 -#define SLC_FRHOST_BIT4_INT_ST_S 4 -/* SLC_FRHOST_BIT3_INT_ST : RO ;bitpos:[3] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT3_INT_ST (BIT(3)) -#define SLC_FRHOST_BIT3_INT_ST_M (BIT(3)) -#define SLC_FRHOST_BIT3_INT_ST_V 0x1 -#define SLC_FRHOST_BIT3_INT_ST_S 3 -/* SLC_FRHOST_BIT2_INT_ST : RO ;bitpos:[2] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT2_INT_ST (BIT(2)) -#define SLC_FRHOST_BIT2_INT_ST_M (BIT(2)) -#define SLC_FRHOST_BIT2_INT_ST_V 0x1 -#define SLC_FRHOST_BIT2_INT_ST_S 2 -/* SLC_FRHOST_BIT1_INT_ST : RO ;bitpos:[1] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT1_INT_ST (BIT(1)) -#define SLC_FRHOST_BIT1_INT_ST_M (BIT(1)) -#define SLC_FRHOST_BIT1_INT_ST_V 0x1 -#define SLC_FRHOST_BIT1_INT_ST_S 1 -/* SLC_FRHOST_BIT0_INT_ST : RO ;bitpos:[0] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT0_INT_ST (BIT(0)) -#define SLC_FRHOST_BIT0_INT_ST_M (BIT(0)) -#define SLC_FRHOST_BIT0_INT_ST_V 0x1 -#define SLC_FRHOST_BIT0_INT_ST_S 0 - -#define SLC_INT_ENA_REG (DR_REG_SLC_BASE + 0xC) -/* SLC_SLC0_HOST_POP_EOF_ERR_INT_ENA : R/W ;bitpos:[27] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_ENA (BIT(27)) -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_ENA_M (BIT(27)) -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_ENA_V 0x1 -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_ENA_S 27 -/* SLC_SLC0_RX_QUICK_EOF_INT_ENA : R/W ;bitpos:[26] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_QUICK_EOF_INT_ENA (BIT(26)) -#define SLC_SLC0_RX_QUICK_EOF_INT_ENA_M (BIT(26)) -#define SLC_SLC0_RX_QUICK_EOF_INT_ENA_V 0x1 -#define SLC_SLC0_RX_QUICK_EOF_INT_ENA_S 26 -/* SLC_CMD_DTC_INT_ENA : R/W ;bitpos:[25] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_CMD_DTC_INT_ENA (BIT(25)) -#define SLC_CMD_DTC_INT_ENA_M (BIT(25)) -#define SLC_CMD_DTC_INT_ENA_V 0x1 -#define SLC_CMD_DTC_INT_ENA_S 25 -/* SLC_SLC0_TX_ERR_EOF_INT_ENA : R/W ;bitpos:[24] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_ERR_EOF_INT_ENA (BIT(24)) -#define SLC_SLC0_TX_ERR_EOF_INT_ENA_M (BIT(24)) -#define SLC_SLC0_TX_ERR_EOF_INT_ENA_V 0x1 -#define SLC_SLC0_TX_ERR_EOF_INT_ENA_S 24 -/* SLC_SLC0_WR_RETRY_DONE_INT_ENA : R/W ;bitpos:[23] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_WR_RETRY_DONE_INT_ENA (BIT(23)) -#define SLC_SLC0_WR_RETRY_DONE_INT_ENA_M (BIT(23)) -#define SLC_SLC0_WR_RETRY_DONE_INT_ENA_V 0x1 -#define SLC_SLC0_WR_RETRY_DONE_INT_ENA_S 23 -/* SLC_SLC0_HOST_RD_ACK_INT_ENA : R/W ;bitpos:[22] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_HOST_RD_ACK_INT_ENA (BIT(22)) -#define SLC_SLC0_HOST_RD_ACK_INT_ENA_M (BIT(22)) -#define SLC_SLC0_HOST_RD_ACK_INT_ENA_V 0x1 -#define SLC_SLC0_HOST_RD_ACK_INT_ENA_S 22 -/* SLC_SLC0_TX_DSCR_EMPTY_INT_ENA : R/W ;bitpos:[21] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DSCR_EMPTY_INT_ENA (BIT(21)) -#define SLC_SLC0_TX_DSCR_EMPTY_INT_ENA_M (BIT(21)) -#define SLC_SLC0_TX_DSCR_EMPTY_INT_ENA_V 0x1 -#define SLC_SLC0_TX_DSCR_EMPTY_INT_ENA_S 21 -/* SLC_SLC0_RX_DSCR_ERR_INT_ENA : R/W ;bitpos:[20] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_DSCR_ERR_INT_ENA (BIT(20)) -#define SLC_SLC0_RX_DSCR_ERR_INT_ENA_M (BIT(20)) -#define SLC_SLC0_RX_DSCR_ERR_INT_ENA_V 0x1 -#define SLC_SLC0_RX_DSCR_ERR_INT_ENA_S 20 -/* SLC_SLC0_TX_DSCR_ERR_INT_ENA : R/W ;bitpos:[19] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DSCR_ERR_INT_ENA (BIT(19)) -#define SLC_SLC0_TX_DSCR_ERR_INT_ENA_M (BIT(19)) -#define SLC_SLC0_TX_DSCR_ERR_INT_ENA_V 0x1 -#define SLC_SLC0_TX_DSCR_ERR_INT_ENA_S 19 -/* SLC_SLC0_TOHOST_INT_ENA : R/W ;bitpos:[18] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOHOST_INT_ENA (BIT(18)) -#define SLC_SLC0_TOHOST_INT_ENA_M (BIT(18)) -#define SLC_SLC0_TOHOST_INT_ENA_V 0x1 -#define SLC_SLC0_TOHOST_INT_ENA_S 18 -/* SLC_SLC0_RX_EOF_INT_ENA : R/W ;bitpos:[17] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_EOF_INT_ENA (BIT(17)) -#define SLC_SLC0_RX_EOF_INT_ENA_M (BIT(17)) -#define SLC_SLC0_RX_EOF_INT_ENA_V 0x1 -#define SLC_SLC0_RX_EOF_INT_ENA_S 17 -/* SLC_SLC0_RX_DONE_INT_ENA : R/W ;bitpos:[16] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_DONE_INT_ENA (BIT(16)) -#define SLC_SLC0_RX_DONE_INT_ENA_M (BIT(16)) -#define SLC_SLC0_RX_DONE_INT_ENA_V 0x1 -#define SLC_SLC0_RX_DONE_INT_ENA_S 16 -/* SLC_SLC0_TX_SUC_EOF_INT_ENA : R/W ;bitpos:[15] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_SUC_EOF_INT_ENA (BIT(15)) -#define SLC_SLC0_TX_SUC_EOF_INT_ENA_M (BIT(15)) -#define SLC_SLC0_TX_SUC_EOF_INT_ENA_V 0x1 -#define SLC_SLC0_TX_SUC_EOF_INT_ENA_S 15 -/* SLC_SLC0_TX_DONE_INT_ENA : R/W ;bitpos:[14] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DONE_INT_ENA (BIT(14)) -#define SLC_SLC0_TX_DONE_INT_ENA_M (BIT(14)) -#define SLC_SLC0_TX_DONE_INT_ENA_V 0x1 -#define SLC_SLC0_TX_DONE_INT_ENA_S 14 -/* SLC_SLC0_TOKEN1_1TO0_INT_ENA : R/W ;bitpos:[13] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN1_1TO0_INT_ENA (BIT(13)) -#define SLC_SLC0_TOKEN1_1TO0_INT_ENA_M (BIT(13)) -#define SLC_SLC0_TOKEN1_1TO0_INT_ENA_V 0x1 -#define SLC_SLC0_TOKEN1_1TO0_INT_ENA_S 13 -/* SLC_SLC0_TOKEN0_1TO0_INT_ENA : R/W ;bitpos:[12] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN0_1TO0_INT_ENA (BIT(12)) -#define SLC_SLC0_TOKEN0_1TO0_INT_ENA_M (BIT(12)) -#define SLC_SLC0_TOKEN0_1TO0_INT_ENA_V 0x1 -#define SLC_SLC0_TOKEN0_1TO0_INT_ENA_S 12 -/* SLC_SLC0_TX_OVF_INT_ENA : R/W ;bitpos:[11] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_OVF_INT_ENA (BIT(11)) -#define SLC_SLC0_TX_OVF_INT_ENA_M (BIT(11)) -#define SLC_SLC0_TX_OVF_INT_ENA_V 0x1 -#define SLC_SLC0_TX_OVF_INT_ENA_S 11 -/* SLC_SLC0_RX_UDF_INT_ENA : R/W ;bitpos:[10] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_UDF_INT_ENA (BIT(10)) -#define SLC_SLC0_RX_UDF_INT_ENA_M (BIT(10)) -#define SLC_SLC0_RX_UDF_INT_ENA_V 0x1 -#define SLC_SLC0_RX_UDF_INT_ENA_S 10 -/* SLC_SLC0_TX_START_INT_ENA : R/W ;bitpos:[9] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_START_INT_ENA (BIT(9)) -#define SLC_SLC0_TX_START_INT_ENA_M (BIT(9)) -#define SLC_SLC0_TX_START_INT_ENA_V 0x1 -#define SLC_SLC0_TX_START_INT_ENA_S 9 -/* SLC_SLC0_RX_START_INT_ENA : R/W ;bitpos:[8] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_START_INT_ENA (BIT(8)) -#define SLC_SLC0_RX_START_INT_ENA_M (BIT(8)) -#define SLC_SLC0_RX_START_INT_ENA_V 0x1 -#define SLC_SLC0_RX_START_INT_ENA_S 8 -/* SLC_FRHOST_BIT7_INT_ENA : R/W ;bitpos:[7] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT7_INT_ENA (BIT(7)) -#define SLC_FRHOST_BIT7_INT_ENA_M (BIT(7)) -#define SLC_FRHOST_BIT7_INT_ENA_V 0x1 -#define SLC_FRHOST_BIT7_INT_ENA_S 7 -/* SLC_FRHOST_BIT6_INT_ENA : R/W ;bitpos:[6] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT6_INT_ENA (BIT(6)) -#define SLC_FRHOST_BIT6_INT_ENA_M (BIT(6)) -#define SLC_FRHOST_BIT6_INT_ENA_V 0x1 -#define SLC_FRHOST_BIT6_INT_ENA_S 6 -/* SLC_FRHOST_BIT5_INT_ENA : R/W ;bitpos:[5] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT5_INT_ENA (BIT(5)) -#define SLC_FRHOST_BIT5_INT_ENA_M (BIT(5)) -#define SLC_FRHOST_BIT5_INT_ENA_V 0x1 -#define SLC_FRHOST_BIT5_INT_ENA_S 5 -/* SLC_FRHOST_BIT4_INT_ENA : R/W ;bitpos:[4] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT4_INT_ENA (BIT(4)) -#define SLC_FRHOST_BIT4_INT_ENA_M (BIT(4)) -#define SLC_FRHOST_BIT4_INT_ENA_V 0x1 -#define SLC_FRHOST_BIT4_INT_ENA_S 4 -/* SLC_FRHOST_BIT3_INT_ENA : R/W ;bitpos:[3] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT3_INT_ENA (BIT(3)) -#define SLC_FRHOST_BIT3_INT_ENA_M (BIT(3)) -#define SLC_FRHOST_BIT3_INT_ENA_V 0x1 -#define SLC_FRHOST_BIT3_INT_ENA_S 3 -/* SLC_FRHOST_BIT2_INT_ENA : R/W ;bitpos:[2] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT2_INT_ENA (BIT(2)) -#define SLC_FRHOST_BIT2_INT_ENA_M (BIT(2)) -#define SLC_FRHOST_BIT2_INT_ENA_V 0x1 -#define SLC_FRHOST_BIT2_INT_ENA_S 2 -/* SLC_FRHOST_BIT1_INT_ENA : R/W ;bitpos:[1] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT1_INT_ENA (BIT(1)) -#define SLC_FRHOST_BIT1_INT_ENA_M (BIT(1)) -#define SLC_FRHOST_BIT1_INT_ENA_V 0x1 -#define SLC_FRHOST_BIT1_INT_ENA_S 1 -/* SLC_FRHOST_BIT0_INT_ENA : R/W ;bitpos:[0] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT0_INT_ENA (BIT(0)) -#define SLC_FRHOST_BIT0_INT_ENA_M (BIT(0)) -#define SLC_FRHOST_BIT0_INT_ENA_V 0x1 -#define SLC_FRHOST_BIT0_INT_ENA_S 0 - -#define SLC_INT_CLR_REG (DR_REG_SLC_BASE + 0x10) -/* SLC_SLC0_HOST_POP_EOF_ERR_INT_CLR : WO ;bitpos:[27] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_CLR (BIT(27)) -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_CLR_M (BIT(27)) -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_CLR_V 0x1 -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_CLR_S 27 -/* SLC_SLC0_RX_QUICK_EOF_INT_CLR : WO ;bitpos:[26] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_QUICK_EOF_INT_CLR (BIT(26)) -#define SLC_SLC0_RX_QUICK_EOF_INT_CLR_M (BIT(26)) -#define SLC_SLC0_RX_QUICK_EOF_INT_CLR_V 0x1 -#define SLC_SLC0_RX_QUICK_EOF_INT_CLR_S 26 -/* SLC_CMD_DTC_INT_CLR : WO ;bitpos:[25] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_CMD_DTC_INT_CLR (BIT(25)) -#define SLC_CMD_DTC_INT_CLR_M (BIT(25)) -#define SLC_CMD_DTC_INT_CLR_V 0x1 -#define SLC_CMD_DTC_INT_CLR_S 25 -/* SLC_SLC0_TX_ERR_EOF_INT_CLR : WO ;bitpos:[24] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_ERR_EOF_INT_CLR (BIT(24)) -#define SLC_SLC0_TX_ERR_EOF_INT_CLR_M (BIT(24)) -#define SLC_SLC0_TX_ERR_EOF_INT_CLR_V 0x1 -#define SLC_SLC0_TX_ERR_EOF_INT_CLR_S 24 -/* SLC_SLC0_WR_RETRY_DONE_INT_CLR : WO ;bitpos:[23] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_WR_RETRY_DONE_INT_CLR (BIT(23)) -#define SLC_SLC0_WR_RETRY_DONE_INT_CLR_M (BIT(23)) -#define SLC_SLC0_WR_RETRY_DONE_INT_CLR_V 0x1 -#define SLC_SLC0_WR_RETRY_DONE_INT_CLR_S 23 -/* SLC_SLC0_HOST_RD_ACK_INT_CLR : WO ;bitpos:[22] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_HOST_RD_ACK_INT_CLR (BIT(22)) -#define SLC_SLC0_HOST_RD_ACK_INT_CLR_M (BIT(22)) -#define SLC_SLC0_HOST_RD_ACK_INT_CLR_V 0x1 -#define SLC_SLC0_HOST_RD_ACK_INT_CLR_S 22 -/* SLC_SLC0_TX_DSCR_EMPTY_INT_CLR : WO ;bitpos:[21] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DSCR_EMPTY_INT_CLR (BIT(21)) -#define SLC_SLC0_TX_DSCR_EMPTY_INT_CLR_M (BIT(21)) -#define SLC_SLC0_TX_DSCR_EMPTY_INT_CLR_V 0x1 -#define SLC_SLC0_TX_DSCR_EMPTY_INT_CLR_S 21 -/* SLC_SLC0_RX_DSCR_ERR_INT_CLR : WO ;bitpos:[20] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_DSCR_ERR_INT_CLR (BIT(20)) -#define SLC_SLC0_RX_DSCR_ERR_INT_CLR_M (BIT(20)) -#define SLC_SLC0_RX_DSCR_ERR_INT_CLR_V 0x1 -#define SLC_SLC0_RX_DSCR_ERR_INT_CLR_S 20 -/* SLC_SLC0_TX_DSCR_ERR_INT_CLR : WO ;bitpos:[19] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DSCR_ERR_INT_CLR (BIT(19)) -#define SLC_SLC0_TX_DSCR_ERR_INT_CLR_M (BIT(19)) -#define SLC_SLC0_TX_DSCR_ERR_INT_CLR_V 0x1 -#define SLC_SLC0_TX_DSCR_ERR_INT_CLR_S 19 -/* SLC_SLC0_TOHOST_INT_CLR : WO ;bitpos:[18] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOHOST_INT_CLR (BIT(18)) -#define SLC_SLC0_TOHOST_INT_CLR_M (BIT(18)) -#define SLC_SLC0_TOHOST_INT_CLR_V 0x1 -#define SLC_SLC0_TOHOST_INT_CLR_S 18 -/* SLC_SLC0_RX_EOF_INT_CLR : WO ;bitpos:[17] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_EOF_INT_CLR (BIT(17)) -#define SLC_SLC0_RX_EOF_INT_CLR_M (BIT(17)) -#define SLC_SLC0_RX_EOF_INT_CLR_V 0x1 -#define SLC_SLC0_RX_EOF_INT_CLR_S 17 -/* SLC_SLC0_RX_DONE_INT_CLR : WO ;bitpos:[16] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_DONE_INT_CLR (BIT(16)) -#define SLC_SLC0_RX_DONE_INT_CLR_M (BIT(16)) -#define SLC_SLC0_RX_DONE_INT_CLR_V 0x1 -#define SLC_SLC0_RX_DONE_INT_CLR_S 16 -/* SLC_SLC0_TX_SUC_EOF_INT_CLR : WO ;bitpos:[15] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_SUC_EOF_INT_CLR (BIT(15)) -#define SLC_SLC0_TX_SUC_EOF_INT_CLR_M (BIT(15)) -#define SLC_SLC0_TX_SUC_EOF_INT_CLR_V 0x1 -#define SLC_SLC0_TX_SUC_EOF_INT_CLR_S 15 -/* SLC_SLC0_TX_DONE_INT_CLR : WO ;bitpos:[14] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DONE_INT_CLR (BIT(14)) -#define SLC_SLC0_TX_DONE_INT_CLR_M (BIT(14)) -#define SLC_SLC0_TX_DONE_INT_CLR_V 0x1 -#define SLC_SLC0_TX_DONE_INT_CLR_S 14 -/* SLC_SLC0_TOKEN1_1TO0_INT_CLR : WO ;bitpos:[13] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN1_1TO0_INT_CLR (BIT(13)) -#define SLC_SLC0_TOKEN1_1TO0_INT_CLR_M (BIT(13)) -#define SLC_SLC0_TOKEN1_1TO0_INT_CLR_V 0x1 -#define SLC_SLC0_TOKEN1_1TO0_INT_CLR_S 13 -/* SLC_SLC0_TOKEN0_1TO0_INT_CLR : WO ;bitpos:[12] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN0_1TO0_INT_CLR (BIT(12)) -#define SLC_SLC0_TOKEN0_1TO0_INT_CLR_M (BIT(12)) -#define SLC_SLC0_TOKEN0_1TO0_INT_CLR_V 0x1 -#define SLC_SLC0_TOKEN0_1TO0_INT_CLR_S 12 -/* SLC_SLC0_TX_OVF_INT_CLR : WO ;bitpos:[11] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_OVF_INT_CLR (BIT(11)) -#define SLC_SLC0_TX_OVF_INT_CLR_M (BIT(11)) -#define SLC_SLC0_TX_OVF_INT_CLR_V 0x1 -#define SLC_SLC0_TX_OVF_INT_CLR_S 11 -/* SLC_SLC0_RX_UDF_INT_CLR : WO ;bitpos:[10] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_UDF_INT_CLR (BIT(10)) -#define SLC_SLC0_RX_UDF_INT_CLR_M (BIT(10)) -#define SLC_SLC0_RX_UDF_INT_CLR_V 0x1 -#define SLC_SLC0_RX_UDF_INT_CLR_S 10 -/* SLC_SLC0_TX_START_INT_CLR : WO ;bitpos:[9] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_START_INT_CLR (BIT(9)) -#define SLC_SLC0_TX_START_INT_CLR_M (BIT(9)) -#define SLC_SLC0_TX_START_INT_CLR_V 0x1 -#define SLC_SLC0_TX_START_INT_CLR_S 9 -/* SLC_SLC0_RX_START_INT_CLR : WO ;bitpos:[8] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_START_INT_CLR (BIT(8)) -#define SLC_SLC0_RX_START_INT_CLR_M (BIT(8)) -#define SLC_SLC0_RX_START_INT_CLR_V 0x1 -#define SLC_SLC0_RX_START_INT_CLR_S 8 -/* SLC_FRHOST_BIT7_INT_CLR : WO ;bitpos:[7] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT7_INT_CLR (BIT(7)) -#define SLC_FRHOST_BIT7_INT_CLR_M (BIT(7)) -#define SLC_FRHOST_BIT7_INT_CLR_V 0x1 -#define SLC_FRHOST_BIT7_INT_CLR_S 7 -/* SLC_FRHOST_BIT6_INT_CLR : WO ;bitpos:[6] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT6_INT_CLR (BIT(6)) -#define SLC_FRHOST_BIT6_INT_CLR_M (BIT(6)) -#define SLC_FRHOST_BIT6_INT_CLR_V 0x1 -#define SLC_FRHOST_BIT6_INT_CLR_S 6 -/* SLC_FRHOST_BIT5_INT_CLR : WO ;bitpos:[5] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT5_INT_CLR (BIT(5)) -#define SLC_FRHOST_BIT5_INT_CLR_M (BIT(5)) -#define SLC_FRHOST_BIT5_INT_CLR_V 0x1 -#define SLC_FRHOST_BIT5_INT_CLR_S 5 -/* SLC_FRHOST_BIT4_INT_CLR : WO ;bitpos:[4] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT4_INT_CLR (BIT(4)) -#define SLC_FRHOST_BIT4_INT_CLR_M (BIT(4)) -#define SLC_FRHOST_BIT4_INT_CLR_V 0x1 -#define SLC_FRHOST_BIT4_INT_CLR_S 4 -/* SLC_FRHOST_BIT3_INT_CLR : WO ;bitpos:[3] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT3_INT_CLR (BIT(3)) -#define SLC_FRHOST_BIT3_INT_CLR_M (BIT(3)) -#define SLC_FRHOST_BIT3_INT_CLR_V 0x1 -#define SLC_FRHOST_BIT3_INT_CLR_S 3 -/* SLC_FRHOST_BIT2_INT_CLR : WO ;bitpos:[2] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT2_INT_CLR (BIT(2)) -#define SLC_FRHOST_BIT2_INT_CLR_M (BIT(2)) -#define SLC_FRHOST_BIT2_INT_CLR_V 0x1 -#define SLC_FRHOST_BIT2_INT_CLR_S 2 -/* SLC_FRHOST_BIT1_INT_CLR : WO ;bitpos:[1] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT1_INT_CLR (BIT(1)) -#define SLC_FRHOST_BIT1_INT_CLR_M (BIT(1)) -#define SLC_FRHOST_BIT1_INT_CLR_V 0x1 -#define SLC_FRHOST_BIT1_INT_CLR_S 1 -/* SLC_FRHOST_BIT0_INT_CLR : WO ;bitpos:[0] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT0_INT_CLR (BIT(0)) -#define SLC_FRHOST_BIT0_INT_CLR_M (BIT(0)) -#define SLC_FRHOST_BIT0_INT_CLR_V 0x1 -#define SLC_FRHOST_BIT0_INT_CLR_S 0 - -#define SLC_SLCRX_STATUS_REG (DR_REG_SLC_BASE + 0x24) -/* SLC_SLC0_RX_BUF_LEN : RO ;bitpos:[13:2] ;default: 12'h0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_BUF_LEN 0x00000FFF -#define SLC_SLC0_RX_BUF_LEN_M ((SLC_SLC0_RX_BUF_LEN_V)<<(SLC_SLC0_RX_BUF_LEN_S)) -#define SLC_SLC0_RX_BUF_LEN_V 0xFFF -#define SLC_SLC0_RX_BUF_LEN_S 2 -/* SLC_SLC0_RX_EMPTY : RO ;bitpos:[1] ;default: 1'b1 ; */ -/*description: .*/ -#define SLC_SLC0_RX_EMPTY (BIT(1)) -#define SLC_SLC0_RX_EMPTY_M (BIT(1)) -#define SLC_SLC0_RX_EMPTY_V 0x1 -#define SLC_SLC0_RX_EMPTY_S 1 -/* SLC_SLC0_RX_FULL : RO ;bitpos:[0] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_FULL (BIT(0)) -#define SLC_SLC0_RX_FULL_M (BIT(0)) -#define SLC_SLC0_RX_FULL_V 0x1 -#define SLC_SLC0_RX_FULL_S 0 - -#define SLC_RXFIFO_PUSH_REG (DR_REG_SLC_BASE + 0x28) -/* SLC_SLC0_RXFIFO_PUSH : R/W ;bitpos:[16] ;default: 1'h0 ; */ -/*description: .*/ -#define SLC_SLC0_RXFIFO_PUSH (BIT(16)) -#define SLC_SLC0_RXFIFO_PUSH_M (BIT(16)) -#define SLC_SLC0_RXFIFO_PUSH_V 0x1 -#define SLC_SLC0_RXFIFO_PUSH_S 16 -/* SLC_SLC0_RXFIFO_WDATA : R/W ;bitpos:[8:0] ;default: 9'h0 ; */ -/*description: .*/ -#define SLC_SLC0_RXFIFO_WDATA 0x000001FF -#define SLC_SLC0_RXFIFO_WDATA_M ((SLC_SLC0_RXFIFO_WDATA_V)<<(SLC_SLC0_RXFIFO_WDATA_S)) -#define SLC_SLC0_RXFIFO_WDATA_V 0x1FF -#define SLC_SLC0_RXFIFO_WDATA_S 0 - -#define SLC_SLCTX_STATUS_REG (DR_REG_SLC_BASE + 0x30) -/* SLC_SLC0_TX_EMPTY : RO ;bitpos:[1] ;default: 1'b1 ; */ -/*description: .*/ -#define SLC_SLC0_TX_EMPTY (BIT(1)) -#define SLC_SLC0_TX_EMPTY_M (BIT(1)) -#define SLC_SLC0_TX_EMPTY_V 0x1 -#define SLC_SLC0_TX_EMPTY_S 1 -/* SLC_SLC0_TX_FULL : RO ;bitpos:[0] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_FULL (BIT(0)) -#define SLC_SLC0_TX_FULL_M (BIT(0)) -#define SLC_SLC0_TX_FULL_V 0x1 -#define SLC_SLC0_TX_FULL_S 0 - -#define SLC_TXFIFO_POP_REG (DR_REG_SLC_BASE + 0x34) -/* SLC_SLC0_TXFIFO_POP : R/W ;bitpos:[16] ;default: 1'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TXFIFO_POP (BIT(16)) -#define SLC_SLC0_TXFIFO_POP_M (BIT(16)) -#define SLC_SLC0_TXFIFO_POP_V 0x1 -#define SLC_SLC0_TXFIFO_POP_S 16 -/* SLC_SLC0_TXFIFO_RDATA : RO ;bitpos:[10:0] ;default: 11'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TXFIFO_RDATA 0x000007FF -#define SLC_SLC0_TXFIFO_RDATA_M ((SLC_SLC0_TXFIFO_RDATA_V)<<(SLC_SLC0_TXFIFO_RDATA_S)) -#define SLC_SLC0_TXFIFO_RDATA_V 0x7FF -#define SLC_SLC0_TXFIFO_RDATA_S 0 - -#define SLC_RX_LINK_REG (DR_REG_SLC_BASE + 0x3C) -/* SLC_SLC0_RXLINK_PARK : RO ;bitpos:[31] ;default: 1'h0 ; */ -/*description: .*/ -#define SLC_SLC0_RXLINK_PARK (BIT(31)) -#define SLC_SLC0_RXLINK_PARK_M (BIT(31)) -#define SLC_SLC0_RXLINK_PARK_V 0x1 -#define SLC_SLC0_RXLINK_PARK_S 31 -/* SLC_SLC0_RXLINK_RESTART : R/W ;bitpos:[30] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RXLINK_RESTART (BIT(30)) -#define SLC_SLC0_RXLINK_RESTART_M (BIT(30)) -#define SLC_SLC0_RXLINK_RESTART_V 0x1 -#define SLC_SLC0_RXLINK_RESTART_S 30 -/* SLC_SLC0_RXLINK_START : R/W ;bitpos:[29] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RXLINK_START (BIT(29)) -#define SLC_SLC0_RXLINK_START_M (BIT(29)) -#define SLC_SLC0_RXLINK_START_V 0x1 -#define SLC_SLC0_RXLINK_START_S 29 -/* SLC_SLC0_RXLINK_STOP : R/W ;bitpos:[28] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RXLINK_STOP (BIT(28)) -#define SLC_SLC0_RXLINK_STOP_M (BIT(28)) -#define SLC_SLC0_RXLINK_STOP_V 0x1 -#define SLC_SLC0_RXLINK_STOP_S 28 -/* SLC_SLC0_RXLINK_ADDR : R/W ;bitpos:[19:0] ;default: 20'h0 ; */ -/*description: .*/ -#define SLC_SLC0_RXLINK_ADDR 0x000FFFFF -#define SLC_SLC0_RXLINK_ADDR_M ((SLC_SLC0_RXLINK_ADDR_V)<<(SLC_SLC0_RXLINK_ADDR_S)) -#define SLC_SLC0_RXLINK_ADDR_V 0xFFFFF -#define SLC_SLC0_RXLINK_ADDR_S 0 - -#define SLC_TX_LINK_REG (DR_REG_SLC_BASE + 0x40) -/* SLC_SLC0_TXLINK_PARK : RO ;bitpos:[31] ;default: 1'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TXLINK_PARK (BIT(31)) -#define SLC_SLC0_TXLINK_PARK_M (BIT(31)) -#define SLC_SLC0_TXLINK_PARK_V 0x1 -#define SLC_SLC0_TXLINK_PARK_S 31 -/* SLC_SLC0_TXLINK_RESTART : R/W ;bitpos:[30] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TXLINK_RESTART (BIT(30)) -#define SLC_SLC0_TXLINK_RESTART_M (BIT(30)) -#define SLC_SLC0_TXLINK_RESTART_V 0x1 -#define SLC_SLC0_TXLINK_RESTART_S 30 -/* SLC_SLC0_TXLINK_START : R/W ;bitpos:[29] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TXLINK_START (BIT(29)) -#define SLC_SLC0_TXLINK_START_M (BIT(29)) -#define SLC_SLC0_TXLINK_START_V 0x1 -#define SLC_SLC0_TXLINK_START_S 29 -/* SLC_SLC0_TXLINK_STOP : R/W ;bitpos:[28] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TXLINK_STOP (BIT(28)) -#define SLC_SLC0_TXLINK_STOP_M (BIT(28)) -#define SLC_SLC0_TXLINK_STOP_V 0x1 -#define SLC_SLC0_TXLINK_STOP_S 28 -/* SLC_SLC0_TXLINK_ADDR : R/W ;bitpos:[19:0] ;default: 20'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TXLINK_ADDR 0x000FFFFF -#define SLC_SLC0_TXLINK_ADDR_M ((SLC_SLC0_TXLINK_ADDR_V)<<(SLC_SLC0_TXLINK_ADDR_S)) -#define SLC_SLC0_TXLINK_ADDR_V 0xFFFFF -#define SLC_SLC0_TXLINK_ADDR_S 0 - -#define SLC_SLCINTVEC_TOHOST_REG (DR_REG_SLC_BASE + 0x4C) -/* SLC_SLC0_TOHOST_INTVEC : WO ;bitpos:[7:0] ;default: 8'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TOHOST_INTVEC 0x000000FF -#define SLC_SLC0_TOHOST_INTVEC_M ((SLC_SLC0_TOHOST_INTVEC_V)<<(SLC_SLC0_TOHOST_INTVEC_S)) -#define SLC_SLC0_TOHOST_INTVEC_V 0xFF -#define SLC_SLC0_TOHOST_INTVEC_S 0 - -#define SLC_TOKEN0_REG (DR_REG_SLC_BASE + 0x50) -/* SLC_SLC0_TOKEN0 : RO ;bitpos:[27:16] ;default: 12'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN0 0x00000FFF -#define SLC_SLC0_TOKEN0_M ((SLC_SLC0_TOKEN0_V)<<(SLC_SLC0_TOKEN0_S)) -#define SLC_SLC0_TOKEN0_V 0xFFF -#define SLC_SLC0_TOKEN0_S 16 -/* SLC_SLC0_TOKEN0_INC_MORE : WO ;bitpos:[14] ;default: 1'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN0_INC_MORE (BIT(14)) -#define SLC_SLC0_TOKEN0_INC_MORE_M (BIT(14)) -#define SLC_SLC0_TOKEN0_INC_MORE_V 0x1 -#define SLC_SLC0_TOKEN0_INC_MORE_S 14 -/* SLC_SLC0_TOKEN0_INC : WO ;bitpos:[13] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN0_INC (BIT(13)) -#define SLC_SLC0_TOKEN0_INC_M (BIT(13)) -#define SLC_SLC0_TOKEN0_INC_V 0x1 -#define SLC_SLC0_TOKEN0_INC_S 13 -/* SLC_SLC0_TOKEN0_WR : WO ;bitpos:[12] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN0_WR (BIT(12)) -#define SLC_SLC0_TOKEN0_WR_M (BIT(12)) -#define SLC_SLC0_TOKEN0_WR_V 0x1 -#define SLC_SLC0_TOKEN0_WR_S 12 -/* SLC_SLC0_TOKEN0_WDATA : WO ;bitpos:[11:0] ;default: 12'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN0_WDATA 0x00000FFF -#define SLC_SLC0_TOKEN0_WDATA_M ((SLC_SLC0_TOKEN0_WDATA_V)<<(SLC_SLC0_TOKEN0_WDATA_S)) -#define SLC_SLC0_TOKEN0_WDATA_V 0xFFF -#define SLC_SLC0_TOKEN0_WDATA_S 0 - -#define SLC_TOKEN1_REG (DR_REG_SLC_BASE + 0x54) -/* SLC_SLC0_TOKEN1 : RO ;bitpos:[27:16] ;default: 12'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN1 0x00000FFF -#define SLC_SLC0_TOKEN1_M ((SLC_SLC0_TOKEN1_V)<<(SLC_SLC0_TOKEN1_S)) -#define SLC_SLC0_TOKEN1_V 0xFFF -#define SLC_SLC0_TOKEN1_S 16 -/* SLC_SLC0_TOKEN1_INC_MORE : WO ;bitpos:[14] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN1_INC_MORE (BIT(14)) -#define SLC_SLC0_TOKEN1_INC_MORE_M (BIT(14)) -#define SLC_SLC0_TOKEN1_INC_MORE_V 0x1 -#define SLC_SLC0_TOKEN1_INC_MORE_S 14 -/* SLC_SLC0_TOKEN1_INC : WO ;bitpos:[13] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN1_INC (BIT(13)) -#define SLC_SLC0_TOKEN1_INC_M (BIT(13)) -#define SLC_SLC0_TOKEN1_INC_V 0x1 -#define SLC_SLC0_TOKEN1_INC_S 13 -/* SLC_SLC0_TOKEN1_WR : WO ;bitpos:[12] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN1_WR (BIT(12)) -#define SLC_SLC0_TOKEN1_WR_M (BIT(12)) -#define SLC_SLC0_TOKEN1_WR_V 0x1 -#define SLC_SLC0_TOKEN1_WR_S 12 -/* SLC_SLC0_TOKEN1_WDATA : WO ;bitpos:[11:0] ;default: 12'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN1_WDATA 0x00000FFF -#define SLC_SLC0_TOKEN1_WDATA_M ((SLC_SLC0_TOKEN1_WDATA_V)<<(SLC_SLC0_TOKEN1_WDATA_S)) -#define SLC_SLC0_TOKEN1_WDATA_V 0xFFF -#define SLC_SLC0_TOKEN1_WDATA_S 0 - -#define SLC_SLCCONF1_REG (DR_REG_SLC_BASE + 0x60) -/* SLC_CLK_EN : R/W ;bitpos:[22] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_CLK_EN (BIT(22)) -#define SLC_CLK_EN_M (BIT(22)) -#define SLC_CLK_EN_V 0x1 -#define SLC_CLK_EN_S 22 -/* SLC_HOST_INT_LEVEL_SEL : R/W ;bitpos:[19] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_HOST_INT_LEVEL_SEL (BIT(19)) -#define SLC_HOST_INT_LEVEL_SEL_M (BIT(19)) -#define SLC_HOST_INT_LEVEL_SEL_V 0x1 -#define SLC_HOST_INT_LEVEL_SEL_S 19 -/* SLC_SLC0_RX_STITCH_EN : R/W ;bitpos:[6] ;default: 1'b1 ; */ -/*description: .*/ -#define SLC_SLC0_RX_STITCH_EN (BIT(6)) -#define SLC_SLC0_RX_STITCH_EN_M (BIT(6)) -#define SLC_SLC0_RX_STITCH_EN_V 0x1 -#define SLC_SLC0_RX_STITCH_EN_S 6 -/* SLC_SLC0_TX_STITCH_EN : R/W ;bitpos:[5] ;default: 1'b1 ; */ -/*description: .*/ -#define SLC_SLC0_TX_STITCH_EN (BIT(5)) -#define SLC_SLC0_TX_STITCH_EN_M (BIT(5)) -#define SLC_SLC0_TX_STITCH_EN_V 0x1 -#define SLC_SLC0_TX_STITCH_EN_S 5 -/* SLC_SLC0_LEN_AUTO_CLR : R/W ;bitpos:[4] ;default: 1'b1 ; */ -/*description: .*/ -#define SLC_SLC0_LEN_AUTO_CLR (BIT(4)) -#define SLC_SLC0_LEN_AUTO_CLR_M (BIT(4)) -#define SLC_SLC0_LEN_AUTO_CLR_V 0x1 -#define SLC_SLC0_LEN_AUTO_CLR_S 4 -/* SLC_CMD_HOLD_EN : R/W ;bitpos:[3] ;default: 1'b1 ; */ -/*description: .*/ -#define SLC_CMD_HOLD_EN (BIT(3)) -#define SLC_CMD_HOLD_EN_M (BIT(3)) -#define SLC_CMD_HOLD_EN_V 0x1 -#define SLC_CMD_HOLD_EN_S 3 -/* SLC_SLC0_RX_CHECK_SUM_EN : R/W ;bitpos:[2] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_CHECK_SUM_EN (BIT(2)) -#define SLC_SLC0_RX_CHECK_SUM_EN_M (BIT(2)) -#define SLC_SLC0_RX_CHECK_SUM_EN_V 0x1 -#define SLC_SLC0_RX_CHECK_SUM_EN_S 2 -/* SLC_SLC0_TX_CHECK_SUM_EN : R/W ;bitpos:[1] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_CHECK_SUM_EN (BIT(1)) -#define SLC_SLC0_TX_CHECK_SUM_EN_M (BIT(1)) -#define SLC_SLC0_TX_CHECK_SUM_EN_V 0x1 -#define SLC_SLC0_TX_CHECK_SUM_EN_S 1 -/* SLC_SLC0_CHECK_OWNER : R/W ;bitpos:[0] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_CHECK_OWNER (BIT(0)) -#define SLC_SLC0_CHECK_OWNER_M (BIT(0)) -#define SLC_SLC0_CHECK_OWNER_V 0x1 -#define SLC_SLC0_CHECK_OWNER_S 0 - -#define SLC_STATE0_REG (DR_REG_SLC_BASE + 0x64) -/* SLC_SLC0_STATE0 : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: .*/ -#define SLC_SLC0_STATE0 0xFFFFFFFF -#define SLC_SLC0_STATE0_M ((SLC_SLC0_STATE0_V)<<(SLC_SLC0_STATE0_S)) -#define SLC_SLC0_STATE0_V 0xFFFFFFFF -#define SLC_SLC0_STATE0_S 0 - -#define SLC_STATE1_REG (DR_REG_SLC_BASE + 0x68) -/* SLC_SLC0_STATE1 : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: .*/ -#define SLC_SLC0_STATE1 0xFFFFFFFF -#define SLC_SLC0_STATE1_M ((SLC_SLC0_STATE1_V)<<(SLC_SLC0_STATE1_S)) -#define SLC_SLC0_STATE1_V 0xFFFFFFFF -#define SLC_SLC0_STATE1_S 0 - -#define SLC_SLCBRIDGE_CONF_REG (DR_REG_SLC_BASE + 0x74) -/* SLC_TX_PUSH_IDLE_NUM : R/W ;bitpos:[31:16] ;default: 16'ha ; */ -/*description: .*/ -#define SLC_TX_PUSH_IDLE_NUM 0x0000FFFF -#define SLC_TX_PUSH_IDLE_NUM_M ((SLC_TX_PUSH_IDLE_NUM_V)<<(SLC_TX_PUSH_IDLE_NUM_S)) -#define SLC_TX_PUSH_IDLE_NUM_V 0xFFFF -#define SLC_TX_PUSH_IDLE_NUM_S 16 -/* SLC_HDA_MAP_128K : R/W ;bitpos:[13] ;default: 1'h1 ; */ -/*description: .*/ -#define SLC_HDA_MAP_128K (BIT(13)) -#define SLC_HDA_MAP_128K_M (BIT(13)) -#define SLC_HDA_MAP_128K_V 0x1 -#define SLC_HDA_MAP_128K_S 13 -/* SLC_SLC0_TX_DUMMY_MODE : R/W ;bitpos:[12] ;default: 1'h1 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DUMMY_MODE (BIT(12)) -#define SLC_SLC0_TX_DUMMY_MODE_M (BIT(12)) -#define SLC_SLC0_TX_DUMMY_MODE_V 0x1 -#define SLC_SLC0_TX_DUMMY_MODE_S 12 -/* SLC_FIFO_MAP_ENA : R/W ;bitpos:[11:8] ;default: 4'h7 ; */ -/*description: .*/ -#define SLC_FIFO_MAP_ENA 0x0000000F -#define SLC_FIFO_MAP_ENA_M ((SLC_FIFO_MAP_ENA_V)<<(SLC_FIFO_MAP_ENA_S)) -#define SLC_FIFO_MAP_ENA_V 0xF -#define SLC_FIFO_MAP_ENA_S 8 -/* SLC_TXEOF_ENA : R/W ;bitpos:[5:0] ;default: 6'h20 ; */ -/*description: .*/ -#define SLC_TXEOF_ENA 0x0000003F -#define SLC_TXEOF_ENA_M ((SLC_TXEOF_ENA_V)<<(SLC_TXEOF_ENA_S)) -#define SLC_TXEOF_ENA_V 0x3F -#define SLC_TXEOF_ENA_S 0 - -#define SLC_TO_EOF_DES_ADDR_REG (DR_REG_SLC_BASE + 0x78) -/* SLC_SLC0_TO_EOF_DES_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TO_EOF_DES_ADDR 0xFFFFFFFF -#define SLC_SLC0_TO_EOF_DES_ADDR_M ((SLC_SLC0_TO_EOF_DES_ADDR_V)<<(SLC_SLC0_TO_EOF_DES_ADDR_S)) -#define SLC_SLC0_TO_EOF_DES_ADDR_V 0xFFFFFFFF -#define SLC_SLC0_TO_EOF_DES_ADDR_S 0 - -#define SLC_TX_EOF_DES_ADDR_REG (DR_REG_SLC_BASE + 0x7C) -/* SLC_SLC0_TX_SUC_EOF_DES_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_SUC_EOF_DES_ADDR 0xFFFFFFFF -#define SLC_SLC0_TX_SUC_EOF_DES_ADDR_M ((SLC_SLC0_TX_SUC_EOF_DES_ADDR_V)<<(SLC_SLC0_TX_SUC_EOF_DES_ADDR_S)) -#define SLC_SLC0_TX_SUC_EOF_DES_ADDR_V 0xFFFFFFFF -#define SLC_SLC0_TX_SUC_EOF_DES_ADDR_S 0 - -#define SLC_TO_EOF_BFR_DES_ADDR_REG (DR_REG_SLC_BASE + 0x80) -/* SLC_SLC0_TO_EOF_BFR_DES_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TO_EOF_BFR_DES_ADDR 0xFFFFFFFF -#define SLC_SLC0_TO_EOF_BFR_DES_ADDR_M ((SLC_SLC0_TO_EOF_BFR_DES_ADDR_V)<<(SLC_SLC0_TO_EOF_BFR_DES_ADDR_S)) -#define SLC_SLC0_TO_EOF_BFR_DES_ADDR_V 0xFFFFFFFF -#define SLC_SLC0_TO_EOF_BFR_DES_ADDR_S 0 - -#define SLC_AHB_TEST_REG (DR_REG_SLC_BASE + 0x90) -/* SLC_AHB_TESTADDR : R/W ;bitpos:[5:4] ;default: 2'b0 ; */ -/*description: .*/ -#define SLC_AHB_TESTADDR 0x00000003 -#define SLC_AHB_TESTADDR_M ((SLC_AHB_TESTADDR_V)<<(SLC_AHB_TESTADDR_S)) -#define SLC_AHB_TESTADDR_V 0x3 -#define SLC_AHB_TESTADDR_S 4 -/* SLC_AHB_TESTMODE : R/W ;bitpos:[2:0] ;default: 3'b0 ; */ -/*description: .*/ -#define SLC_AHB_TESTMODE 0x00000007 -#define SLC_AHB_TESTMODE_M ((SLC_AHB_TESTMODE_V)<<(SLC_AHB_TESTMODE_S)) -#define SLC_AHB_TESTMODE_V 0x7 -#define SLC_AHB_TESTMODE_S 0 - -#define SLC_SDIO_ST_REG (DR_REG_SLC_BASE + 0x94) -/* SLC_FUNC1_ACC_STATE : RO ;bitpos:[20:16] ;default: 5'b0 ; */ -/*description: .*/ -#define SLC_FUNC1_ACC_STATE 0x0000001F -#define SLC_FUNC1_ACC_STATE_M ((SLC_FUNC1_ACC_STATE_V)<<(SLC_FUNC1_ACC_STATE_S)) -#define SLC_FUNC1_ACC_STATE_V 0x1F -#define SLC_FUNC1_ACC_STATE_S 16 -/* SLC_BUS_ST : RO ;bitpos:[14:12] ;default: 3'b0 ; */ -/*description: .*/ -#define SLC_BUS_ST 0x00000007 -#define SLC_BUS_ST_M ((SLC_BUS_ST_V)<<(SLC_BUS_ST_S)) -#define SLC_BUS_ST_V 0x7 -#define SLC_BUS_ST_S 12 -/* SLC_SDIO_WAKEUP : RO ;bitpos:[8] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SDIO_WAKEUP (BIT(8)) -#define SLC_SDIO_WAKEUP_M (BIT(8)) -#define SLC_SDIO_WAKEUP_V 0x1 -#define SLC_SDIO_WAKEUP_S 8 -/* SLC_FUNC_ST : RO ;bitpos:[7:4] ;default: 4'b0 ; */ -/*description: .*/ -#define SLC_FUNC_ST 0x0000000F -#define SLC_FUNC_ST_M ((SLC_FUNC_ST_V)<<(SLC_FUNC_ST_S)) -#define SLC_FUNC_ST_V 0xF -#define SLC_FUNC_ST_S 4 -/* SLC_CMD_ST : RO ;bitpos:[2:0] ;default: 3'b0 ; */ -/*description: .*/ -#define SLC_CMD_ST 0x00000007 -#define SLC_CMD_ST_M ((SLC_CMD_ST_V)<<(SLC_CMD_ST_S)) -#define SLC_CMD_ST_V 0x7 -#define SLC_CMD_ST_S 0 - -#define SLC_RX_DSCR_CONF_REG (DR_REG_SLC_BASE + 0x98) -/* SLC_SLC0_RD_RETRY_THRESHOLD : R/W ;bitpos:[15:5] ;default: 11'h80 ; */ -/*description: .*/ -#define SLC_SLC0_RD_RETRY_THRESHOLD 0x000007FF -#define SLC_SLC0_RD_RETRY_THRESHOLD_M ((SLC_SLC0_RD_RETRY_THRESHOLD_V)<<(SLC_SLC0_RD_RETRY_THRESHOLD_S)) -#define SLC_SLC0_RD_RETRY_THRESHOLD_V 0x7FF -#define SLC_SLC0_RD_RETRY_THRESHOLD_S 5 -/* SLC_SLC0_RX_FILL_EN : R/W ;bitpos:[4] ;default: 1'b1 ; */ -/*description: .*/ -#define SLC_SLC0_RX_FILL_EN (BIT(4)) -#define SLC_SLC0_RX_FILL_EN_M (BIT(4)) -#define SLC_SLC0_RX_FILL_EN_V 0x1 -#define SLC_SLC0_RX_FILL_EN_S 4 -/* SLC_SLC0_RX_EOF_MODE : R/W ;bitpos:[3] ;default: 1'b1 ; */ -/*description: .*/ -#define SLC_SLC0_RX_EOF_MODE (BIT(3)) -#define SLC_SLC0_RX_EOF_MODE_M (BIT(3)) -#define SLC_SLC0_RX_EOF_MODE_V 0x1 -#define SLC_SLC0_RX_EOF_MODE_S 3 -/* SLC_SLC0_RX_FILL_MODE : R/W ;bitpos:[2] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_FILL_MODE (BIT(2)) -#define SLC_SLC0_RX_FILL_MODE_M (BIT(2)) -#define SLC_SLC0_RX_FILL_MODE_V 0x1 -#define SLC_SLC0_RX_FILL_MODE_S 2 -/* SLC_SLC0_INFOR_NO_REPLACE : R/W ;bitpos:[1] ;default: 1'b1 ; */ -/*description: .*/ -#define SLC_SLC0_INFOR_NO_REPLACE (BIT(1)) -#define SLC_SLC0_INFOR_NO_REPLACE_M (BIT(1)) -#define SLC_SLC0_INFOR_NO_REPLACE_V 0x1 -#define SLC_SLC0_INFOR_NO_REPLACE_S 1 -/* SLC_SLC0_TOKEN_NO_REPLACE : R/W ;bitpos:[0] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN_NO_REPLACE (BIT(0)) -#define SLC_SLC0_TOKEN_NO_REPLACE_M (BIT(0)) -#define SLC_SLC0_TOKEN_NO_REPLACE_V 0x1 -#define SLC_SLC0_TOKEN_NO_REPLACE_S 0 - -#define SLC_TXLINK_DSCR_REG (DR_REG_SLC_BASE + 0x9C) -/* SLC_SLC0_TXLINK_DSCR : RO ;bitpos:[31:0] ;default: 32'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TXLINK_DSCR 0xFFFFFFFF -#define SLC_SLC0_TXLINK_DSCR_M ((SLC_SLC0_TXLINK_DSCR_V)<<(SLC_SLC0_TXLINK_DSCR_S)) -#define SLC_SLC0_TXLINK_DSCR_V 0xFFFFFFFF -#define SLC_SLC0_TXLINK_DSCR_S 0 - -#define SLC_TXLINK_DSCR_BF0_REG (DR_REG_SLC_BASE + 0xA0) -/* SLC_SLC0_TXLINK_DSCR_BF0 : RO ;bitpos:[31:0] ;default: 32'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TXLINK_DSCR_BF0 0xFFFFFFFF -#define SLC_SLC0_TXLINK_DSCR_BF0_M ((SLC_SLC0_TXLINK_DSCR_BF0_V)<<(SLC_SLC0_TXLINK_DSCR_BF0_S)) -#define SLC_SLC0_TXLINK_DSCR_BF0_V 0xFFFFFFFF -#define SLC_SLC0_TXLINK_DSCR_BF0_S 0 - -#define SLC_TXLINK_DSCR_BF1_REG (DR_REG_SLC_BASE + 0xA4) -/* SLC_SLC0_TXLINK_DSCR_BF1 : RO ;bitpos:[31:0] ;default: 32'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TXLINK_DSCR_BF1 0xFFFFFFFF -#define SLC_SLC0_TXLINK_DSCR_BF1_M ((SLC_SLC0_TXLINK_DSCR_BF1_V)<<(SLC_SLC0_TXLINK_DSCR_BF1_S)) -#define SLC_SLC0_TXLINK_DSCR_BF1_V 0xFFFFFFFF -#define SLC_SLC0_TXLINK_DSCR_BF1_S 0 - -#define SLC_RXLINK_DSCR_REG (DR_REG_SLC_BASE + 0xA8) -/* SLC_SLC0_RXLINK_DSCR : RO ;bitpos:[31:0] ;default: 32'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RXLINK_DSCR 0xFFFFFFFF -#define SLC_SLC0_RXLINK_DSCR_M ((SLC_SLC0_RXLINK_DSCR_V)<<(SLC_SLC0_RXLINK_DSCR_S)) -#define SLC_SLC0_RXLINK_DSCR_V 0xFFFFFFFF -#define SLC_SLC0_RXLINK_DSCR_S 0 - -#define SLC_RXLINK_DSCR_BF0_REG (DR_REG_SLC_BASE + 0xAC) -/* SLC_SLC0_RXLINK_DSCR_BF0 : RO ;bitpos:[31:0] ;default: 32'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RXLINK_DSCR_BF0 0xFFFFFFFF -#define SLC_SLC0_RXLINK_DSCR_BF0_M ((SLC_SLC0_RXLINK_DSCR_BF0_V)<<(SLC_SLC0_RXLINK_DSCR_BF0_S)) -#define SLC_SLC0_RXLINK_DSCR_BF0_V 0xFFFFFFFF -#define SLC_SLC0_RXLINK_DSCR_BF0_S 0 - -#define SLC_RXLINK_DSCR_BF1_REG (DR_REG_SLC_BASE + 0xB0) -/* SLC_SLC0_RXLINK_DSCR_BF1 : RO ;bitpos:[31:0] ;default: 32'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RXLINK_DSCR_BF1 0xFFFFFFFF -#define SLC_SLC0_RXLINK_DSCR_BF1_M ((SLC_SLC0_RXLINK_DSCR_BF1_V)<<(SLC_SLC0_RXLINK_DSCR_BF1_S)) -#define SLC_SLC0_RXLINK_DSCR_BF1_V 0xFFFFFFFF -#define SLC_SLC0_RXLINK_DSCR_BF1_S 0 - -#define SLC_TX_ERREOF_DES_ADDR_REG (DR_REG_SLC_BASE + 0xCC) -/* SLC_SLC0_TX_ERR_EOF_DES_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_ERR_EOF_DES_ADDR 0xFFFFFFFF -#define SLC_SLC0_TX_ERR_EOF_DES_ADDR_M ((SLC_SLC0_TX_ERR_EOF_DES_ADDR_V)<<(SLC_SLC0_TX_ERR_EOF_DES_ADDR_S)) -#define SLC_SLC0_TX_ERR_EOF_DES_ADDR_V 0xFFFFFFFF -#define SLC_SLC0_TX_ERR_EOF_DES_ADDR_S 0 - -#define SLC_TOKEN_LAT_REG (DR_REG_SLC_BASE + 0xD4) -/* SLC_SLC0_TOKEN : RO ;bitpos:[11:0] ;default: 12'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN 0x00000FFF -#define SLC_SLC0_TOKEN_M ((SLC_SLC0_TOKEN_V)<<(SLC_SLC0_TOKEN_S)) -#define SLC_SLC0_TOKEN_V 0xFFF -#define SLC_SLC0_TOKEN_S 0 - -#define SLC_TX_DSCR_CONF_REG (DR_REG_SLC_BASE + 0xD8) -/* SLC_WR_RETRY_THRESHOLD : R/W ;bitpos:[10:0] ;default: 11'h80 ; */ -/*description: .*/ -#define SLC_WR_RETRY_THRESHOLD 0x000007FF -#define SLC_WR_RETRY_THRESHOLD_M ((SLC_WR_RETRY_THRESHOLD_V)<<(SLC_WR_RETRY_THRESHOLD_S)) -#define SLC_WR_RETRY_THRESHOLD_V 0x7FF -#define SLC_WR_RETRY_THRESHOLD_S 0 - -#define SLC_CMD_INFOR0_REG (DR_REG_SLC_BASE + 0xDC) -/* SLC_CMD_CONTENT0 : RO ;bitpos:[31:0] ;default: 32'b0 ; */ -/*description: .*/ -#define SLC_CMD_CONTENT0 0xFFFFFFFF -#define SLC_CMD_CONTENT0_M ((SLC_CMD_CONTENT0_V)<<(SLC_CMD_CONTENT0_S)) -#define SLC_CMD_CONTENT0_V 0xFFFFFFFF -#define SLC_CMD_CONTENT0_S 0 - -#define SLC_CMD_INFOR1_REG (DR_REG_SLC_BASE + 0xE0) -/* SLC_CMD_CONTENT1 : RO ;bitpos:[31:0] ;default: 32'b0 ; */ -/*description: .*/ -#define SLC_CMD_CONTENT1 0xFFFFFFFF -#define SLC_CMD_CONTENT1_M ((SLC_CMD_CONTENT1_V)<<(SLC_CMD_CONTENT1_S)) -#define SLC_CMD_CONTENT1_V 0xFFFFFFFF -#define SLC_CMD_CONTENT1_S 0 - -#define SLC_LEN_CONF_REG (DR_REG_SLC_BASE + 0xE4) -/* SLC_SLC0_TX_NEW_PKT_IND : RO ;bitpos:[28] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_NEW_PKT_IND (BIT(28)) -#define SLC_SLC0_TX_NEW_PKT_IND_M (BIT(28)) -#define SLC_SLC0_TX_NEW_PKT_IND_V 0x1 -#define SLC_SLC0_TX_NEW_PKT_IND_S 28 -/* SLC_SLC0_RX_NEW_PKT_IND : RO ;bitpos:[27] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_NEW_PKT_IND (BIT(27)) -#define SLC_SLC0_RX_NEW_PKT_IND_M (BIT(27)) -#define SLC_SLC0_RX_NEW_PKT_IND_V 0x1 -#define SLC_SLC0_RX_NEW_PKT_IND_S 27 -/* SLC_SLC0_TX_GET_USED_DSCR : WO ;bitpos:[26] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_GET_USED_DSCR (BIT(26)) -#define SLC_SLC0_TX_GET_USED_DSCR_M (BIT(26)) -#define SLC_SLC0_TX_GET_USED_DSCR_V 0x1 -#define SLC_SLC0_TX_GET_USED_DSCR_S 26 -/* SLC_SLC0_RX_GET_USED_DSCR : WO ;bitpos:[25] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_GET_USED_DSCR (BIT(25)) -#define SLC_SLC0_RX_GET_USED_DSCR_M (BIT(25)) -#define SLC_SLC0_RX_GET_USED_DSCR_V 0x1 -#define SLC_SLC0_RX_GET_USED_DSCR_S 25 -/* SLC_SLC0_TX_PACKET_LOAD_EN : R/W ;bitpos:[24] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_PACKET_LOAD_EN (BIT(24)) -#define SLC_SLC0_TX_PACKET_LOAD_EN_M (BIT(24)) -#define SLC_SLC0_TX_PACKET_LOAD_EN_V 0x1 -#define SLC_SLC0_TX_PACKET_LOAD_EN_S 24 -/* SLC_SLC0_RX_PACKET_LOAD_EN : R/W ;bitpos:[23] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_PACKET_LOAD_EN (BIT(23)) -#define SLC_SLC0_RX_PACKET_LOAD_EN_M (BIT(23)) -#define SLC_SLC0_RX_PACKET_LOAD_EN_V 0x1 -#define SLC_SLC0_RX_PACKET_LOAD_EN_S 23 -/* SLC_SLC0_LEN_INC_MORE : WO ;bitpos:[22] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_LEN_INC_MORE (BIT(22)) -#define SLC_SLC0_LEN_INC_MORE_M (BIT(22)) -#define SLC_SLC0_LEN_INC_MORE_V 0x1 -#define SLC_SLC0_LEN_INC_MORE_S 22 -/* SLC_SLC0_LEN_INC : WO ;bitpos:[21] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_LEN_INC (BIT(21)) -#define SLC_SLC0_LEN_INC_M (BIT(21)) -#define SLC_SLC0_LEN_INC_V 0x1 -#define SLC_SLC0_LEN_INC_S 21 -/* SLC_SLC0_LEN_WR : WO ;bitpos:[20] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_LEN_WR (BIT(20)) -#define SLC_SLC0_LEN_WR_M (BIT(20)) -#define SLC_SLC0_LEN_WR_V 0x1 -#define SLC_SLC0_LEN_WR_S 20 -/* SLC_SLC0_LEN_WDATA : WO ;bitpos:[19:0] ;default: 20'h0 ; */ -/*description: .*/ -#define SLC_SLC0_LEN_WDATA 0x000FFFFF -#define SLC_SLC0_LEN_WDATA_M ((SLC_SLC0_LEN_WDATA_V)<<(SLC_SLC0_LEN_WDATA_S)) -#define SLC_SLC0_LEN_WDATA_V 0xFFFFF -#define SLC_SLC0_LEN_WDATA_S 0 - -#define SLC_LENGTH_REG (DR_REG_SLC_BASE + 0xE8) -/* SLC_SLC0_LEN : RO ;bitpos:[19:0] ;default: 20'h0 ; */ -/*description: .*/ -#define SLC_SLC0_LEN 0x000FFFFF -#define SLC_SLC0_LEN_M ((SLC_SLC0_LEN_V)<<(SLC_SLC0_LEN_S)) -#define SLC_SLC0_LEN_V 0xFFFFF -#define SLC_SLC0_LEN_S 0 - -#define SLC_TXPKT_H_DSCR_REG (DR_REG_SLC_BASE + 0xEC) -/* SLC_SLC0_TX_PKT_H_DSCR_ADDR : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_PKT_H_DSCR_ADDR 0xFFFFFFFF -#define SLC_SLC0_TX_PKT_H_DSCR_ADDR_M ((SLC_SLC0_TX_PKT_H_DSCR_ADDR_V)<<(SLC_SLC0_TX_PKT_H_DSCR_ADDR_S)) -#define SLC_SLC0_TX_PKT_H_DSCR_ADDR_V 0xFFFFFFFF -#define SLC_SLC0_TX_PKT_H_DSCR_ADDR_S 0 - -#define SLC_TXPKT_E_DSCR_REG (DR_REG_SLC_BASE + 0xF0) -/* SLC_SLC0_TX_PKT_E_DSCR_ADDR : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_PKT_E_DSCR_ADDR 0xFFFFFFFF -#define SLC_SLC0_TX_PKT_E_DSCR_ADDR_M ((SLC_SLC0_TX_PKT_E_DSCR_ADDR_V)<<(SLC_SLC0_TX_PKT_E_DSCR_ADDR_S)) -#define SLC_SLC0_TX_PKT_E_DSCR_ADDR_V 0xFFFFFFFF -#define SLC_SLC0_TX_PKT_E_DSCR_ADDR_S 0 - -#define SLC_RXPKT_H_DSCR_REG (DR_REG_SLC_BASE + 0xF4) -/* SLC_SLC0_RX_PKT_H_DSCR_ADDR : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_PKT_H_DSCR_ADDR 0xFFFFFFFF -#define SLC_SLC0_RX_PKT_H_DSCR_ADDR_M ((SLC_SLC0_RX_PKT_H_DSCR_ADDR_V)<<(SLC_SLC0_RX_PKT_H_DSCR_ADDR_S)) -#define SLC_SLC0_RX_PKT_H_DSCR_ADDR_V 0xFFFFFFFF -#define SLC_SLC0_RX_PKT_H_DSCR_ADDR_S 0 - -#define SLC_RXPKT_E_DSCR_REG (DR_REG_SLC_BASE + 0xF8) -/* SLC_SLC0_RX_PKT_E_DSCR_ADDR : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_PKT_E_DSCR_ADDR 0xFFFFFFFF -#define SLC_SLC0_RX_PKT_E_DSCR_ADDR_M ((SLC_SLC0_RX_PKT_E_DSCR_ADDR_V)<<(SLC_SLC0_RX_PKT_E_DSCR_ADDR_S)) -#define SLC_SLC0_RX_PKT_E_DSCR_ADDR_V 0xFFFFFFFF -#define SLC_SLC0_RX_PKT_E_DSCR_ADDR_S 0 - -#define SLC_TXPKTU_H_DSCR_REG (DR_REG_SLC_BASE + 0xFC) -/* SLC_SLC0_TX_PKT_START_DSCR_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_PKT_START_DSCR_ADDR 0xFFFFFFFF -#define SLC_SLC0_TX_PKT_START_DSCR_ADDR_M ((SLC_SLC0_TX_PKT_START_DSCR_ADDR_V)<<(SLC_SLC0_TX_PKT_START_DSCR_ADDR_S)) -#define SLC_SLC0_TX_PKT_START_DSCR_ADDR_V 0xFFFFFFFF -#define SLC_SLC0_TX_PKT_START_DSCR_ADDR_S 0 - -#define SLC_TXPKTU_E_DSCR_REG (DR_REG_SLC_BASE + 0x100) -/* SLC_SLC0_TX_PKT_END_DSCR_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_PKT_END_DSCR_ADDR 0xFFFFFFFF -#define SLC_SLC0_TX_PKT_END_DSCR_ADDR_M ((SLC_SLC0_TX_PKT_END_DSCR_ADDR_V)<<(SLC_SLC0_TX_PKT_END_DSCR_ADDR_S)) -#define SLC_SLC0_TX_PKT_END_DSCR_ADDR_V 0xFFFFFFFF -#define SLC_SLC0_TX_PKT_END_DSCR_ADDR_S 0 - -#define SLC_RXPKTU_H_DSCR_REG (DR_REG_SLC_BASE + 0x104) -/* SLC_SLC0_RX_PKT_START_DSCR_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_PKT_START_DSCR_ADDR 0xFFFFFFFF -#define SLC_SLC0_RX_PKT_START_DSCR_ADDR_M ((SLC_SLC0_RX_PKT_START_DSCR_ADDR_V)<<(SLC_SLC0_RX_PKT_START_DSCR_ADDR_S)) -#define SLC_SLC0_RX_PKT_START_DSCR_ADDR_V 0xFFFFFFFF -#define SLC_SLC0_RX_PKT_START_DSCR_ADDR_S 0 - -#define SLC_RXPKTU_E_DSCR_REG (DR_REG_SLC_BASE + 0x108) -/* SLC_SLC0_RX_PKT_END_DSCR_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_PKT_END_DSCR_ADDR 0xFFFFFFFF -#define SLC_SLC0_RX_PKT_END_DSCR_ADDR_M ((SLC_SLC0_RX_PKT_END_DSCR_ADDR_V)<<(SLC_SLC0_RX_PKT_END_DSCR_ADDR_S)) -#define SLC_SLC0_RX_PKT_END_DSCR_ADDR_V 0xFFFFFFFF -#define SLC_SLC0_RX_PKT_END_DSCR_ADDR_S 0 - -#define SLC_SEQ_POSITION_REG (DR_REG_SLC_BASE + 0x114) -/* SLC_SLC0_SEQ_POSITION : R/W ;bitpos:[7:0] ;default: 8'h9 ; */ -/*description: .*/ -#define SLC_SLC0_SEQ_POSITION 0x000000FF -#define SLC_SLC0_SEQ_POSITION_M ((SLC_SLC0_SEQ_POSITION_V)<<(SLC_SLC0_SEQ_POSITION_S)) -#define SLC_SLC0_SEQ_POSITION_V 0xFF -#define SLC_SLC0_SEQ_POSITION_S 0 - -#define SLC_DSCR_REC_CONF_REG (DR_REG_SLC_BASE + 0x118) -/* SLC_SLC0_RX_DSCR_REC_LIM : R/W ;bitpos:[9:0] ;default: 10'h3ff ; */ -/*description: .*/ -#define SLC_SLC0_RX_DSCR_REC_LIM 0x000003FF -#define SLC_SLC0_RX_DSCR_REC_LIM_M ((SLC_SLC0_RX_DSCR_REC_LIM_V)<<(SLC_SLC0_RX_DSCR_REC_LIM_S)) -#define SLC_SLC0_RX_DSCR_REC_LIM_V 0x3FF -#define SLC_SLC0_RX_DSCR_REC_LIM_S 0 - -#define SLC_SDIO_CRC_ST0_REG (DR_REG_SLC_BASE + 0x11C) -/* SLC_DAT3_CRC_ERR_CNT : RO ;bitpos:[31:24] ;default: 8'h0 ; */ -/*description: .*/ -#define SLC_DAT3_CRC_ERR_CNT 0x000000FF -#define SLC_DAT3_CRC_ERR_CNT_M ((SLC_DAT3_CRC_ERR_CNT_V)<<(SLC_DAT3_CRC_ERR_CNT_S)) -#define SLC_DAT3_CRC_ERR_CNT_V 0xFF -#define SLC_DAT3_CRC_ERR_CNT_S 24 -/* SLC_DAT2_CRC_ERR_CNT : RO ;bitpos:[23:16] ;default: 8'h0 ; */ -/*description: .*/ -#define SLC_DAT2_CRC_ERR_CNT 0x000000FF -#define SLC_DAT2_CRC_ERR_CNT_M ((SLC_DAT2_CRC_ERR_CNT_V)<<(SLC_DAT2_CRC_ERR_CNT_S)) -#define SLC_DAT2_CRC_ERR_CNT_V 0xFF -#define SLC_DAT2_CRC_ERR_CNT_S 16 -/* SLC_DAT1_CRC_ERR_CNT : RO ;bitpos:[15:8] ;default: 8'h0 ; */ -/*description: .*/ -#define SLC_DAT1_CRC_ERR_CNT 0x000000FF -#define SLC_DAT1_CRC_ERR_CNT_M ((SLC_DAT1_CRC_ERR_CNT_V)<<(SLC_DAT1_CRC_ERR_CNT_S)) -#define SLC_DAT1_CRC_ERR_CNT_V 0xFF -#define SLC_DAT1_CRC_ERR_CNT_S 8 -/* SLC_DAT0_CRC_ERR_CNT : RO ;bitpos:[7:0] ;default: 8'h0 ; */ -/*description: .*/ -#define SLC_DAT0_CRC_ERR_CNT 0x000000FF -#define SLC_DAT0_CRC_ERR_CNT_M ((SLC_DAT0_CRC_ERR_CNT_V)<<(SLC_DAT0_CRC_ERR_CNT_S)) -#define SLC_DAT0_CRC_ERR_CNT_V 0xFF -#define SLC_DAT0_CRC_ERR_CNT_S 0 - -#define SLC_SDIO_CRC_ST1_REG (DR_REG_SLC_BASE + 0x120) -/* SLC_ERR_CNT_CLR : R/W ;bitpos:[31] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_ERR_CNT_CLR (BIT(31)) -#define SLC_ERR_CNT_CLR_M (BIT(31)) -#define SLC_ERR_CNT_CLR_V 0x1 -#define SLC_ERR_CNT_CLR_S 31 -/* SLC_CMD_CRC_ERR_CNT : RO ;bitpos:[7:0] ;default: 8'h0 ; */ -/*description: .*/ -#define SLC_CMD_CRC_ERR_CNT 0x000000FF -#define SLC_CMD_CRC_ERR_CNT_M ((SLC_CMD_CRC_ERR_CNT_V)<<(SLC_CMD_CRC_ERR_CNT_S)) -#define SLC_CMD_CRC_ERR_CNT_V 0xFF -#define SLC_CMD_CRC_ERR_CNT_S 0 - -#define SLC_EOF_START_DES_REG (DR_REG_SLC_BASE + 0x124) -/* SLC_SLC0_EOF_START_DES_ADDR : RO ;bitpos:[31:0] ;default: 32'b0 ; */ -/*description: .*/ -#define SLC_SLC0_EOF_START_DES_ADDR 0xFFFFFFFF -#define SLC_SLC0_EOF_START_DES_ADDR_M ((SLC_SLC0_EOF_START_DES_ADDR_V)<<(SLC_SLC0_EOF_START_DES_ADDR_S)) -#define SLC_SLC0_EOF_START_DES_ADDR_V 0xFFFFFFFF -#define SLC_SLC0_EOF_START_DES_ADDR_S 0 - -#define SLC_PUSH_DSCR_ADDR_REG (DR_REG_SLC_BASE + 0x128) -/* SLC_SLC0_RX_PUSH_DSCR_ADDR : RO ;bitpos:[31:0] ;default: 32'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_PUSH_DSCR_ADDR 0xFFFFFFFF -#define SLC_SLC0_RX_PUSH_DSCR_ADDR_M ((SLC_SLC0_RX_PUSH_DSCR_ADDR_V)<<(SLC_SLC0_RX_PUSH_DSCR_ADDR_S)) -#define SLC_SLC0_RX_PUSH_DSCR_ADDR_V 0xFFFFFFFF -#define SLC_SLC0_RX_PUSH_DSCR_ADDR_S 0 - -#define SLC_DONE_DSCR_ADDR_REG (DR_REG_SLC_BASE + 0x12C) -/* SLC_SLC0_RX_DONE_DSCR_ADDR : RO ;bitpos:[31:0] ;default: 32'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_DONE_DSCR_ADDR 0xFFFFFFFF -#define SLC_SLC0_RX_DONE_DSCR_ADDR_M ((SLC_SLC0_RX_DONE_DSCR_ADDR_V)<<(SLC_SLC0_RX_DONE_DSCR_ADDR_S)) -#define SLC_SLC0_RX_DONE_DSCR_ADDR_V 0xFFFFFFFF -#define SLC_SLC0_RX_DONE_DSCR_ADDR_S 0 - -#define SLC_SUB_START_DES_REG (DR_REG_SLC_BASE + 0x130) -/* SLC_SLC0_SUB_PAC_START_DSCR_ADDR : RO ;bitpos:[31:0] ;default: 32'b0 ; */ -/*description: .*/ -#define SLC_SLC0_SUB_PAC_START_DSCR_ADDR 0xFFFFFFFF -#define SLC_SLC0_SUB_PAC_START_DSCR_ADDR_M ((SLC_SLC0_SUB_PAC_START_DSCR_ADDR_V)<<(SLC_SLC0_SUB_PAC_START_DSCR_ADDR_S)) -#define SLC_SLC0_SUB_PAC_START_DSCR_ADDR_V 0xFFFFFFFF -#define SLC_SLC0_SUB_PAC_START_DSCR_ADDR_S 0 - -#define SLC_DSCR_CNT_REG (DR_REG_SLC_BASE + 0x134) -/* SLC_SLC0_RX_GET_EOF_OCC : RO ;bitpos:[16] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_GET_EOF_OCC (BIT(16)) -#define SLC_SLC0_RX_GET_EOF_OCC_M (BIT(16)) -#define SLC_SLC0_RX_GET_EOF_OCC_V 0x1 -#define SLC_SLC0_RX_GET_EOF_OCC_S 16 -/* SLC_SLC0_RX_DSCR_CNT_LAT : RO ;bitpos:[9:0] ;default: 10'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_DSCR_CNT_LAT 0x000003FF -#define SLC_SLC0_RX_DSCR_CNT_LAT_M ((SLC_SLC0_RX_DSCR_CNT_LAT_V)<<(SLC_SLC0_RX_DSCR_CNT_LAT_S)) -#define SLC_SLC0_RX_DSCR_CNT_LAT_V 0x3FF -#define SLC_SLC0_RX_DSCR_CNT_LAT_S 0 - -#define SLC_LEN_LIM_CONF_REG (DR_REG_SLC_BASE + 0x138) -/* SLC_SLC0_LEN_LIM : R/W ;bitpos:[19:0] ;default: 20'h5400 ; */ -/*description: .*/ -#define SLC_SLC0_LEN_LIM 0x000FFFFF -#define SLC_SLC0_LEN_LIM_M ((SLC_SLC0_LEN_LIM_V)<<(SLC_SLC0_LEN_LIM_S)) -#define SLC_SLC0_LEN_LIM_V 0xFFFFF -#define SLC_SLC0_LEN_LIM_S 0 - -#define SLC_INT_ST1_REG (DR_REG_SLC_BASE + 0x13C) -/* SLC_SLC0_HOST_POP_EOF_ERR_INT_ST1 : RO ;bitpos:[27] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_ST1 (BIT(27)) -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_ST1_M (BIT(27)) -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_ST1_V 0x1 -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_ST1_S 27 -/* SLC_SLC0_RX_QUICK_EOF_INT_ST1 : RO ;bitpos:[26] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_QUICK_EOF_INT_ST1 (BIT(26)) -#define SLC_SLC0_RX_QUICK_EOF_INT_ST1_M (BIT(26)) -#define SLC_SLC0_RX_QUICK_EOF_INT_ST1_V 0x1 -#define SLC_SLC0_RX_QUICK_EOF_INT_ST1_S 26 -/* SLC_CMD_DTC_INT_ST1 : RO ;bitpos:[25] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_CMD_DTC_INT_ST1 (BIT(25)) -#define SLC_CMD_DTC_INT_ST1_M (BIT(25)) -#define SLC_CMD_DTC_INT_ST1_V 0x1 -#define SLC_CMD_DTC_INT_ST1_S 25 -/* SLC_SLC0_TX_ERR_EOF_INT_ST1 : RO ;bitpos:[24] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_ERR_EOF_INT_ST1 (BIT(24)) -#define SLC_SLC0_TX_ERR_EOF_INT_ST1_M (BIT(24)) -#define SLC_SLC0_TX_ERR_EOF_INT_ST1_V 0x1 -#define SLC_SLC0_TX_ERR_EOF_INT_ST1_S 24 -/* SLC_SLC0_WR_RETRY_DONE_INT_ST1 : RO ;bitpos:[23] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_WR_RETRY_DONE_INT_ST1 (BIT(23)) -#define SLC_SLC0_WR_RETRY_DONE_INT_ST1_M (BIT(23)) -#define SLC_SLC0_WR_RETRY_DONE_INT_ST1_V 0x1 -#define SLC_SLC0_WR_RETRY_DONE_INT_ST1_S 23 -/* SLC_SLC0_HOST_RD_ACK_INT_ST1 : RO ;bitpos:[22] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_HOST_RD_ACK_INT_ST1 (BIT(22)) -#define SLC_SLC0_HOST_RD_ACK_INT_ST1_M (BIT(22)) -#define SLC_SLC0_HOST_RD_ACK_INT_ST1_V 0x1 -#define SLC_SLC0_HOST_RD_ACK_INT_ST1_S 22 -/* SLC_SLC0_TX_DSCR_EMPTY_INT_ST1 : RO ;bitpos:[21] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DSCR_EMPTY_INT_ST1 (BIT(21)) -#define SLC_SLC0_TX_DSCR_EMPTY_INT_ST1_M (BIT(21)) -#define SLC_SLC0_TX_DSCR_EMPTY_INT_ST1_V 0x1 -#define SLC_SLC0_TX_DSCR_EMPTY_INT_ST1_S 21 -/* SLC_SLC0_RX_DSCR_ERR_INT_ST1 : RO ;bitpos:[20] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_DSCR_ERR_INT_ST1 (BIT(20)) -#define SLC_SLC0_RX_DSCR_ERR_INT_ST1_M (BIT(20)) -#define SLC_SLC0_RX_DSCR_ERR_INT_ST1_V 0x1 -#define SLC_SLC0_RX_DSCR_ERR_INT_ST1_S 20 -/* SLC_SLC0_TX_DSCR_ERR_INT_ST1 : RO ;bitpos:[19] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DSCR_ERR_INT_ST1 (BIT(19)) -#define SLC_SLC0_TX_DSCR_ERR_INT_ST1_M (BIT(19)) -#define SLC_SLC0_TX_DSCR_ERR_INT_ST1_V 0x1 -#define SLC_SLC0_TX_DSCR_ERR_INT_ST1_S 19 -/* SLC_SLC0_TOHOST_INT_ST1 : RO ;bitpos:[18] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOHOST_INT_ST1 (BIT(18)) -#define SLC_SLC0_TOHOST_INT_ST1_M (BIT(18)) -#define SLC_SLC0_TOHOST_INT_ST1_V 0x1 -#define SLC_SLC0_TOHOST_INT_ST1_S 18 -/* SLC_SLC0_RX_EOF_INT_ST1 : RO ;bitpos:[17] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_EOF_INT_ST1 (BIT(17)) -#define SLC_SLC0_RX_EOF_INT_ST1_M (BIT(17)) -#define SLC_SLC0_RX_EOF_INT_ST1_V 0x1 -#define SLC_SLC0_RX_EOF_INT_ST1_S 17 -/* SLC_SLC0_RX_DONE_INT_ST1 : RO ;bitpos:[16] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_DONE_INT_ST1 (BIT(16)) -#define SLC_SLC0_RX_DONE_INT_ST1_M (BIT(16)) -#define SLC_SLC0_RX_DONE_INT_ST1_V 0x1 -#define SLC_SLC0_RX_DONE_INT_ST1_S 16 -/* SLC_SLC0_TX_SUC_EOF_INT_ST1 : RO ;bitpos:[15] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_SUC_EOF_INT_ST1 (BIT(15)) -#define SLC_SLC0_TX_SUC_EOF_INT_ST1_M (BIT(15)) -#define SLC_SLC0_TX_SUC_EOF_INT_ST1_V 0x1 -#define SLC_SLC0_TX_SUC_EOF_INT_ST1_S 15 -/* SLC_SLC0_TX_DONE_INT_ST1 : RO ;bitpos:[14] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DONE_INT_ST1 (BIT(14)) -#define SLC_SLC0_TX_DONE_INT_ST1_M (BIT(14)) -#define SLC_SLC0_TX_DONE_INT_ST1_V 0x1 -#define SLC_SLC0_TX_DONE_INT_ST1_S 14 -/* SLC_SLC0_TOKEN1_1TO0_INT_ST1 : RO ;bitpos:[13] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN1_1TO0_INT_ST1 (BIT(13)) -#define SLC_SLC0_TOKEN1_1TO0_INT_ST1_M (BIT(13)) -#define SLC_SLC0_TOKEN1_1TO0_INT_ST1_V 0x1 -#define SLC_SLC0_TOKEN1_1TO0_INT_ST1_S 13 -/* SLC_SLC0_TOKEN0_1TO0_INT_ST1 : RO ;bitpos:[12] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN0_1TO0_INT_ST1 (BIT(12)) -#define SLC_SLC0_TOKEN0_1TO0_INT_ST1_M (BIT(12)) -#define SLC_SLC0_TOKEN0_1TO0_INT_ST1_V 0x1 -#define SLC_SLC0_TOKEN0_1TO0_INT_ST1_S 12 -/* SLC_SLC0_TX_OVF_INT_ST1 : RO ;bitpos:[11] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_OVF_INT_ST1 (BIT(11)) -#define SLC_SLC0_TX_OVF_INT_ST1_M (BIT(11)) -#define SLC_SLC0_TX_OVF_INT_ST1_V 0x1 -#define SLC_SLC0_TX_OVF_INT_ST1_S 11 -/* SLC_SLC0_RX_UDF_INT_ST1 : RO ;bitpos:[10] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_UDF_INT_ST1 (BIT(10)) -#define SLC_SLC0_RX_UDF_INT_ST1_M (BIT(10)) -#define SLC_SLC0_RX_UDF_INT_ST1_V 0x1 -#define SLC_SLC0_RX_UDF_INT_ST1_S 10 -/* SLC_SLC0_TX_START_INT_ST1 : RO ;bitpos:[9] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_START_INT_ST1 (BIT(9)) -#define SLC_SLC0_TX_START_INT_ST1_M (BIT(9)) -#define SLC_SLC0_TX_START_INT_ST1_V 0x1 -#define SLC_SLC0_TX_START_INT_ST1_S 9 -/* SLC_SLC0_RX_START_INT_ST1 : RO ;bitpos:[8] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_START_INT_ST1 (BIT(8)) -#define SLC_SLC0_RX_START_INT_ST1_M (BIT(8)) -#define SLC_SLC0_RX_START_INT_ST1_V 0x1 -#define SLC_SLC0_RX_START_INT_ST1_S 8 -/* SLC_FRHOST_BIT7_INT_ST1 : RO ;bitpos:[7] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT7_INT_ST1 (BIT(7)) -#define SLC_FRHOST_BIT7_INT_ST1_M (BIT(7)) -#define SLC_FRHOST_BIT7_INT_ST1_V 0x1 -#define SLC_FRHOST_BIT7_INT_ST1_S 7 -/* SLC_FRHOST_BIT6_INT_ST1 : RO ;bitpos:[6] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT6_INT_ST1 (BIT(6)) -#define SLC_FRHOST_BIT6_INT_ST1_M (BIT(6)) -#define SLC_FRHOST_BIT6_INT_ST1_V 0x1 -#define SLC_FRHOST_BIT6_INT_ST1_S 6 -/* SLC_FRHOST_BIT5_INT_ST1 : RO ;bitpos:[5] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT5_INT_ST1 (BIT(5)) -#define SLC_FRHOST_BIT5_INT_ST1_M (BIT(5)) -#define SLC_FRHOST_BIT5_INT_ST1_V 0x1 -#define SLC_FRHOST_BIT5_INT_ST1_S 5 -/* SLC_FRHOST_BIT4_INT_ST1 : RO ;bitpos:[4] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT4_INT_ST1 (BIT(4)) -#define SLC_FRHOST_BIT4_INT_ST1_M (BIT(4)) -#define SLC_FRHOST_BIT4_INT_ST1_V 0x1 -#define SLC_FRHOST_BIT4_INT_ST1_S 4 -/* SLC_FRHOST_BIT3_INT_ST1 : RO ;bitpos:[3] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT3_INT_ST1 (BIT(3)) -#define SLC_FRHOST_BIT3_INT_ST1_M (BIT(3)) -#define SLC_FRHOST_BIT3_INT_ST1_V 0x1 -#define SLC_FRHOST_BIT3_INT_ST1_S 3 -/* SLC_FRHOST_BIT2_INT_ST1 : RO ;bitpos:[2] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT2_INT_ST1 (BIT(2)) -#define SLC_FRHOST_BIT2_INT_ST1_M (BIT(2)) -#define SLC_FRHOST_BIT2_INT_ST1_V 0x1 -#define SLC_FRHOST_BIT2_INT_ST1_S 2 -/* SLC_FRHOST_BIT1_INT_ST1 : RO ;bitpos:[1] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT1_INT_ST1 (BIT(1)) -#define SLC_FRHOST_BIT1_INT_ST1_M (BIT(1)) -#define SLC_FRHOST_BIT1_INT_ST1_V 0x1 -#define SLC_FRHOST_BIT1_INT_ST1_S 1 -/* SLC_FRHOST_BIT0_INT_ST1 : RO ;bitpos:[0] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT0_INT_ST1 (BIT(0)) -#define SLC_FRHOST_BIT0_INT_ST1_M (BIT(0)) -#define SLC_FRHOST_BIT0_INT_ST1_V 0x1 -#define SLC_FRHOST_BIT0_INT_ST1_S 0 - -#define SLC_INT_ENA1_REG (DR_REG_SLC_BASE + 0x140) -/* SLC_SLC0_HOST_POP_EOF_ERR_INT_ENA1 : R/W ;bitpos:[27] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_ENA1 (BIT(27)) -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_ENA1_M (BIT(27)) -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_ENA1_V 0x1 -#define SLC_SLC0_HOST_POP_EOF_ERR_INT_ENA1_S 27 -/* SLC_SLC0_RX_QUICK_EOF_INT_ENA1 : R/W ;bitpos:[26] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_QUICK_EOF_INT_ENA1 (BIT(26)) -#define SLC_SLC0_RX_QUICK_EOF_INT_ENA1_M (BIT(26)) -#define SLC_SLC0_RX_QUICK_EOF_INT_ENA1_V 0x1 -#define SLC_SLC0_RX_QUICK_EOF_INT_ENA1_S 26 -/* SLC_CMD_DTC_INT_ENA1 : R/W ;bitpos:[25] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_CMD_DTC_INT_ENA1 (BIT(25)) -#define SLC_CMD_DTC_INT_ENA1_M (BIT(25)) -#define SLC_CMD_DTC_INT_ENA1_V 0x1 -#define SLC_CMD_DTC_INT_ENA1_S 25 -/* SLC_SLC0_TX_ERR_EOF_INT_ENA1 : R/W ;bitpos:[24] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_ERR_EOF_INT_ENA1 (BIT(24)) -#define SLC_SLC0_TX_ERR_EOF_INT_ENA1_M (BIT(24)) -#define SLC_SLC0_TX_ERR_EOF_INT_ENA1_V 0x1 -#define SLC_SLC0_TX_ERR_EOF_INT_ENA1_S 24 -/* SLC_SLC0_WR_RETRY_DONE_INT_ENA1 : R/W ;bitpos:[23] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_WR_RETRY_DONE_INT_ENA1 (BIT(23)) -#define SLC_SLC0_WR_RETRY_DONE_INT_ENA1_M (BIT(23)) -#define SLC_SLC0_WR_RETRY_DONE_INT_ENA1_V 0x1 -#define SLC_SLC0_WR_RETRY_DONE_INT_ENA1_S 23 -/* SLC_SLC0_HOST_RD_ACK_INT_ENA1 : R/W ;bitpos:[22] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_HOST_RD_ACK_INT_ENA1 (BIT(22)) -#define SLC_SLC0_HOST_RD_ACK_INT_ENA1_M (BIT(22)) -#define SLC_SLC0_HOST_RD_ACK_INT_ENA1_V 0x1 -#define SLC_SLC0_HOST_RD_ACK_INT_ENA1_S 22 -/* SLC_SLC0_TX_DSCR_EMPTY_INT_ENA1 : R/W ;bitpos:[21] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DSCR_EMPTY_INT_ENA1 (BIT(21)) -#define SLC_SLC0_TX_DSCR_EMPTY_INT_ENA1_M (BIT(21)) -#define SLC_SLC0_TX_DSCR_EMPTY_INT_ENA1_V 0x1 -#define SLC_SLC0_TX_DSCR_EMPTY_INT_ENA1_S 21 -/* SLC_SLC0_RX_DSCR_ERR_INT_ENA1 : R/W ;bitpos:[20] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_DSCR_ERR_INT_ENA1 (BIT(20)) -#define SLC_SLC0_RX_DSCR_ERR_INT_ENA1_M (BIT(20)) -#define SLC_SLC0_RX_DSCR_ERR_INT_ENA1_V 0x1 -#define SLC_SLC0_RX_DSCR_ERR_INT_ENA1_S 20 -/* SLC_SLC0_TX_DSCR_ERR_INT_ENA1 : R/W ;bitpos:[19] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DSCR_ERR_INT_ENA1 (BIT(19)) -#define SLC_SLC0_TX_DSCR_ERR_INT_ENA1_M (BIT(19)) -#define SLC_SLC0_TX_DSCR_ERR_INT_ENA1_V 0x1 -#define SLC_SLC0_TX_DSCR_ERR_INT_ENA1_S 19 -/* SLC_SLC0_TOHOST_INT_ENA1 : R/W ;bitpos:[18] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOHOST_INT_ENA1 (BIT(18)) -#define SLC_SLC0_TOHOST_INT_ENA1_M (BIT(18)) -#define SLC_SLC0_TOHOST_INT_ENA1_V 0x1 -#define SLC_SLC0_TOHOST_INT_ENA1_S 18 -/* SLC_SLC0_RX_EOF_INT_ENA1 : R/W ;bitpos:[17] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_EOF_INT_ENA1 (BIT(17)) -#define SLC_SLC0_RX_EOF_INT_ENA1_M (BIT(17)) -#define SLC_SLC0_RX_EOF_INT_ENA1_V 0x1 -#define SLC_SLC0_RX_EOF_INT_ENA1_S 17 -/* SLC_SLC0_RX_DONE_INT_ENA1 : R/W ;bitpos:[16] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_DONE_INT_ENA1 (BIT(16)) -#define SLC_SLC0_RX_DONE_INT_ENA1_M (BIT(16)) -#define SLC_SLC0_RX_DONE_INT_ENA1_V 0x1 -#define SLC_SLC0_RX_DONE_INT_ENA1_S 16 -/* SLC_SLC0_TX_SUC_EOF_INT_ENA1 : R/W ;bitpos:[15] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_SUC_EOF_INT_ENA1 (BIT(15)) -#define SLC_SLC0_TX_SUC_EOF_INT_ENA1_M (BIT(15)) -#define SLC_SLC0_TX_SUC_EOF_INT_ENA1_V 0x1 -#define SLC_SLC0_TX_SUC_EOF_INT_ENA1_S 15 -/* SLC_SLC0_TX_DONE_INT_ENA1 : R/W ;bitpos:[14] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_DONE_INT_ENA1 (BIT(14)) -#define SLC_SLC0_TX_DONE_INT_ENA1_M (BIT(14)) -#define SLC_SLC0_TX_DONE_INT_ENA1_V 0x1 -#define SLC_SLC0_TX_DONE_INT_ENA1_S 14 -/* SLC_SLC0_TOKEN1_1TO0_INT_ENA1 : R/W ;bitpos:[13] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN1_1TO0_INT_ENA1 (BIT(13)) -#define SLC_SLC0_TOKEN1_1TO0_INT_ENA1_M (BIT(13)) -#define SLC_SLC0_TOKEN1_1TO0_INT_ENA1_V 0x1 -#define SLC_SLC0_TOKEN1_1TO0_INT_ENA1_S 13 -/* SLC_SLC0_TOKEN0_1TO0_INT_ENA1 : R/W ;bitpos:[12] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TOKEN0_1TO0_INT_ENA1 (BIT(12)) -#define SLC_SLC0_TOKEN0_1TO0_INT_ENA1_M (BIT(12)) -#define SLC_SLC0_TOKEN0_1TO0_INT_ENA1_V 0x1 -#define SLC_SLC0_TOKEN0_1TO0_INT_ENA1_S 12 -/* SLC_SLC0_TX_OVF_INT_ENA1 : R/W ;bitpos:[11] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_OVF_INT_ENA1 (BIT(11)) -#define SLC_SLC0_TX_OVF_INT_ENA1_M (BIT(11)) -#define SLC_SLC0_TX_OVF_INT_ENA1_V 0x1 -#define SLC_SLC0_TX_OVF_INT_ENA1_S 11 -/* SLC_SLC0_RX_UDF_INT_ENA1 : R/W ;bitpos:[10] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_UDF_INT_ENA1 (BIT(10)) -#define SLC_SLC0_RX_UDF_INT_ENA1_M (BIT(10)) -#define SLC_SLC0_RX_UDF_INT_ENA1_V 0x1 -#define SLC_SLC0_RX_UDF_INT_ENA1_S 10 -/* SLC_SLC0_TX_START_INT_ENA1 : R/W ;bitpos:[9] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_TX_START_INT_ENA1 (BIT(9)) -#define SLC_SLC0_TX_START_INT_ENA1_M (BIT(9)) -#define SLC_SLC0_TX_START_INT_ENA1_V 0x1 -#define SLC_SLC0_TX_START_INT_ENA1_S 9 -/* SLC_SLC0_RX_START_INT_ENA1 : R/W ;bitpos:[8] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_SLC0_RX_START_INT_ENA1 (BIT(8)) -#define SLC_SLC0_RX_START_INT_ENA1_M (BIT(8)) -#define SLC_SLC0_RX_START_INT_ENA1_V 0x1 -#define SLC_SLC0_RX_START_INT_ENA1_S 8 -/* SLC_FRHOST_BIT7_INT_ENA1 : R/W ;bitpos:[7] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT7_INT_ENA1 (BIT(7)) -#define SLC_FRHOST_BIT7_INT_ENA1_M (BIT(7)) -#define SLC_FRHOST_BIT7_INT_ENA1_V 0x1 -#define SLC_FRHOST_BIT7_INT_ENA1_S 7 -/* SLC_FRHOST_BIT6_INT_ENA1 : R/W ;bitpos:[6] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT6_INT_ENA1 (BIT(6)) -#define SLC_FRHOST_BIT6_INT_ENA1_M (BIT(6)) -#define SLC_FRHOST_BIT6_INT_ENA1_V 0x1 -#define SLC_FRHOST_BIT6_INT_ENA1_S 6 -/* SLC_FRHOST_BIT5_INT_ENA1 : R/W ;bitpos:[5] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT5_INT_ENA1 (BIT(5)) -#define SLC_FRHOST_BIT5_INT_ENA1_M (BIT(5)) -#define SLC_FRHOST_BIT5_INT_ENA1_V 0x1 -#define SLC_FRHOST_BIT5_INT_ENA1_S 5 -/* SLC_FRHOST_BIT4_INT_ENA1 : R/W ;bitpos:[4] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT4_INT_ENA1 (BIT(4)) -#define SLC_FRHOST_BIT4_INT_ENA1_M (BIT(4)) -#define SLC_FRHOST_BIT4_INT_ENA1_V 0x1 -#define SLC_FRHOST_BIT4_INT_ENA1_S 4 -/* SLC_FRHOST_BIT3_INT_ENA1 : R/W ;bitpos:[3] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT3_INT_ENA1 (BIT(3)) -#define SLC_FRHOST_BIT3_INT_ENA1_M (BIT(3)) -#define SLC_FRHOST_BIT3_INT_ENA1_V 0x1 -#define SLC_FRHOST_BIT3_INT_ENA1_S 3 -/* SLC_FRHOST_BIT2_INT_ENA1 : R/W ;bitpos:[2] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT2_INT_ENA1 (BIT(2)) -#define SLC_FRHOST_BIT2_INT_ENA1_M (BIT(2)) -#define SLC_FRHOST_BIT2_INT_ENA1_V 0x1 -#define SLC_FRHOST_BIT2_INT_ENA1_S 2 -/* SLC_FRHOST_BIT1_INT_ENA1 : R/W ;bitpos:[1] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT1_INT_ENA1 (BIT(1)) -#define SLC_FRHOST_BIT1_INT_ENA1_M (BIT(1)) -#define SLC_FRHOST_BIT1_INT_ENA1_V 0x1 -#define SLC_FRHOST_BIT1_INT_ENA1_S 1 -/* SLC_FRHOST_BIT0_INT_ENA1 : R/W ;bitpos:[0] ;default: 1'b0 ; */ -/*description: .*/ -#define SLC_FRHOST_BIT0_INT_ENA1 (BIT(0)) -#define SLC_FRHOST_BIT0_INT_ENA1_M (BIT(0)) -#define SLC_FRHOST_BIT0_INT_ENA1_V 0x1 -#define SLC_FRHOST_BIT0_INT_ENA1_S 0 - -#define SLC_SLCDATE_REG (DR_REG_SLC_BASE + 0x1F8) -/* SLC_DATE : R/W ;bitpos:[31:0] ;default: 32'h18080700 ; */ -/*description: .*/ -#define SLC_DATE 0xFFFFFFFF -#define SLC_DATE_M ((SLC_DATE_V)<<(SLC_DATE_S)) -#define SLC_DATE_V 0xFFFFFFFF -#define SLC_DATE_S 0 - -#define SLC_SLCID_REG (DR_REG_SLC_BASE + 0x1FC) -/* SLC_ID : R/W ;bitpos:[31:0] ;default: 32'h0100 ; */ -/*description: .*/ -#define SLC_ID 0xFFFFFFFF -#define SLC_ID_M ((SLC_ID_V)<<(SLC_ID_S)) -#define SLC_ID_V 0xFFFFFFFF -#define SLC_ID_S 0 - - -#ifdef __cplusplus -} -#endif - - - -#endif /*_SOC_SLC_REG_H_ */ diff --git a/components/soc/esp32s3/include/soc/slc_struct.h b/components/soc/esp32s3/include/soc/slc_struct.h deleted file mode 100644 index 896e781e7d..0000000000 --- a/components/soc/esp32s3/include/soc/slc_struct.h +++ /dev/null @@ -1,592 +0,0 @@ -// 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. -#ifndef _SOC_SLC_STRUCT_H_ -#define _SOC_SLC_STRUCT_H_ - - -#include -#ifdef __cplusplus -extern "C" { -#endif - -typedef volatile struct { - union { - struct { - uint32_t tx_rst : 1; - uint32_t rx_rst : 1; - uint32_t ahbm_fifo_rst : 1; - uint32_t ahbm_rst : 1; - uint32_t tx_loop_test : 1; - uint32_t rx_loop_test : 1; - uint32_t rx_auto_wrback : 1; - uint32_t rx_no_restart_clr : 1; - uint32_t rxdscr_burst_en : 1; - uint32_t rxdata_burst_en : 1; - uint32_t auto_ret : 1; - uint32_t txdscr_burst_en : 1; - uint32_t txdata_burst_en : 1; - uint32_t token_auto_clr : 1; - uint32_t token_sel : 1; - uint32_t reserved16 : 2; - uint32_t wr_retry_mask_en : 1; - uint32_t reserved19 : 13; - }; - uint32_t val; - } slcconf0; - union { - struct { - uint32_t frhost_bit0 : 1; - uint32_t frhost_bit1 : 1; - uint32_t frhost_bit2 : 1; - uint32_t frhost_bit3 : 1; - uint32_t frhost_bit4 : 1; - uint32_t frhost_bit5 : 1; - uint32_t frhost_bit6 : 1; - uint32_t frhost_bit7 : 1; - uint32_t rx_start : 1; - uint32_t tx_start : 1; - uint32_t rx_udf : 1; - uint32_t tx_ovf : 1; - uint32_t token0_1to0 : 1; - uint32_t token1_1to0 : 1; - uint32_t tx_done : 1; - uint32_t tx_suc_eof : 1; - uint32_t rx_done : 1; - uint32_t rx_eof : 1; - uint32_t tohost : 1; - uint32_t tx_dscr_err : 1; - uint32_t rx_dscr_err : 1; - uint32_t tx_dscr_empty : 1; - uint32_t host_rd_ack : 1; - uint32_t wr_retry_done : 1; - uint32_t tx_err_eof : 1; - uint32_t cmd_dtc : 1; - uint32_t rx_quick_eof : 1; - uint32_t host_pop_eof_err : 1; - uint32_t reserved28 : 4; - }; - uint32_t val; - } slc0_int_raw; - union { - struct { - uint32_t frhost_bit0 : 1; - uint32_t frhost_bit1 : 1; - uint32_t frhost_bit2 : 1; - uint32_t frhost_bit3 : 1; - uint32_t frhost_bit4 : 1; - uint32_t frhost_bit5 : 1; - uint32_t frhost_bit6 : 1; - uint32_t frhost_bit7 : 1; - uint32_t rx_start : 1; - uint32_t tx_start : 1; - uint32_t rx_udf : 1; - uint32_t tx_ovf : 1; - uint32_t token0_1to0 : 1; - uint32_t token1_1to0 : 1; - uint32_t tx_done : 1; - uint32_t tx_suc_eof : 1; - uint32_t rx_done : 1; - uint32_t rx_eof : 1; - uint32_t tohost : 1; - uint32_t tx_dscr_err : 1; - uint32_t rx_dscr_err : 1; - uint32_t tx_dscr_empty : 1; - uint32_t host_rd_ack : 1; - uint32_t wr_retry_done : 1; - uint32_t tx_err_eof : 1; - uint32_t cmd_dtc : 1; - uint32_t rx_quick_eof : 1; - uint32_t host_pop_eof_err : 1; - uint32_t reserved28 : 4; - }; - uint32_t val; - } slc0_int_st; - union { - struct { - uint32_t frhost_bit0 : 1; - uint32_t frhost_bit1 : 1; - uint32_t frhost_bit2 : 1; - uint32_t frhost_bit3 : 1; - uint32_t frhost_bit4 : 1; - uint32_t frhost_bit5 : 1; - uint32_t frhost_bit6 : 1; - uint32_t frhost_bit7 : 1; - uint32_t rx_start : 1; - uint32_t tx_start : 1; - uint32_t rx_udf : 1; - uint32_t tx_ovf : 1; - uint32_t token0_1to0 : 1; - uint32_t token1_1to0 : 1; - uint32_t tx_done : 1; - uint32_t tx_suc_eof : 1; - uint32_t rx_done : 1; - uint32_t rx_eof : 1; - uint32_t tohost : 1; - uint32_t tx_dscr_err : 1; - uint32_t rx_dscr_err : 1; - uint32_t tx_dscr_empty : 1; - uint32_t host_rd_ack : 1; - uint32_t wr_retry_done : 1; - uint32_t tx_err_eof : 1; - uint32_t cmd_dtc : 1; - uint32_t rx_quick_eof : 1; - uint32_t host_pop_eof_err : 1; - uint32_t reserved28 : 4; - }; - uint32_t val; - } slc0_int_ena; - union { - struct { - uint32_t frhost_bit0 : 1; - uint32_t frhost_bit1 : 1; - uint32_t frhost_bit2 : 1; - uint32_t frhost_bit3 : 1; - uint32_t frhost_bit4 : 1; - uint32_t frhost_bit5 : 1; - uint32_t frhost_bit6 : 1; - uint32_t frhost_bit7 : 1; - uint32_t rx_start : 1; - uint32_t tx_start : 1; - uint32_t rx_udf : 1; - uint32_t tx_ovf : 1; - uint32_t token0_1to0 : 1; - uint32_t token1_1to0 : 1; - uint32_t tx_done : 1; - uint32_t tx_suc_eof : 1; - uint32_t rx_done : 1; - uint32_t rx_eof : 1; - uint32_t tohost : 1; - uint32_t tx_dscr_err : 1; - uint32_t rx_dscr_err : 1; - uint32_t tx_dscr_empty : 1; - uint32_t host_rd_ack : 1; - uint32_t wr_retry_done : 1; - uint32_t tx_err_eof : 1; - uint32_t cmd_dtc : 1; - uint32_t rx_quick_eof : 1; - uint32_t host_pop_eof_err : 1; - uint32_t reserved28 : 4; - }; - uint32_t val; - } slc0_int_clr; - uint32_t reserved_14; - uint32_t reserved_18; - uint32_t reserved_1c; - uint32_t reserved_20; - union { - struct { - uint32_t rx_full : 1; - uint32_t rx_empty : 1; - uint32_t rx_buf_len : 12; - uint32_t reserved14 : 18; - }; - uint32_t val; - } rx_status; - union { - struct { - uint32_t rxfifo_wdata : 9; - uint32_t reserved9 : 7; - uint32_t rxfifo_push : 1; - uint32_t reserved17 : 15; - }; - uint32_t val; - } slc0_rxfifo_push; - uint32_t reserved_2c; - union { - struct { - uint32_t tx_full : 1; - uint32_t tx_empty : 1; - uint32_t reserved2 : 30; - }; - uint32_t val; - } tx_status; - union { - struct { - uint32_t txfifo_rdata : 11; - uint32_t reserved11 : 5; - uint32_t txfifo_pop : 1; - uint32_t reserved17 : 15; - }; - uint32_t val; - } slc0_txfifo_pop; - uint32_t reserved_38; - union { - struct { - uint32_t addr : 20; - uint32_t reserved20 : 8; - uint32_t stop : 1; - uint32_t start : 1; - uint32_t restart : 1; - uint32_t park : 1; - }; - uint32_t val; - } slc0_rx_link; - union { - struct { - uint32_t addr : 20; - uint32_t reserved20 : 8; - uint32_t stop : 1; - uint32_t start : 1; - uint32_t restart : 1; - uint32_t park : 1; - }; - uint32_t val; - } slc0_tx_link; - uint32_t reserved_44; - uint32_t reserved_48; - union { - struct { - uint32_t tohost_intvec : 8; - uint32_t reserved8 : 24; - }; - uint32_t val; - } slcintvec_tohost; - union { - struct { - uint32_t wdata : 12; - uint32_t wr : 1; - uint32_t inc : 1; - uint32_t inc_more : 1; - uint32_t reserved15 : 1; - uint32_t token0 : 12; - uint32_t reserved28 : 4; - }; - uint32_t val; - } slc0token0; - union { - struct { - uint32_t wdata : 12; - uint32_t wr : 1; - uint32_t inc : 1; - uint32_t inc_more : 1; - uint32_t reserved15 : 1; - uint32_t token1 : 12; - uint32_t reserved28 : 4; - }; - uint32_t val; - } slc0_token1; - uint32_t reserved_58; - uint32_t reserved_5c; - union { - struct { - uint32_t check_owner : 1; - uint32_t tx_check_sum_en : 1; - uint32_t rx_check_sum_en : 1; - uint32_t reg_cmd_hold_en : 1; - uint32_t len_auto_clr : 1; - uint32_t tx_stitch_en : 1; - uint32_t rx_stitch_en : 1; - uint32_t reserved7 : 12; - uint32_t host_int_level_sel : 1; - uint32_t reserved20 : 2; - uint32_t reg_clk_en : 1; - uint32_t reserved23 : 9; - }; - uint32_t val; - } slcconf1; - uint32_t slc0_state0; - uint32_t slc0_state1; - uint32_t reserved_6c; - uint32_t reserved_70; - union { - struct { - uint32_t txeof_ena : 6; - uint32_t reserved6 : 2; - uint32_t fifo_map_ena : 4; - uint32_t tx_dummy_mode : 1; - uint32_t hda_map_128k : 1; - uint32_t reserved14 : 2; - uint32_t tx_push_idle_num : 16; - }; - uint32_t val; - } slcbridge_conf; - uint32_t slc0_to_eof_des_addr; - uint32_t slc0_tx_eof_des_addr; - uint32_t slc0_to_eof_bfr_des_addr; - uint32_t reserved_84; - uint32_t reserved_88; - uint32_t reserved_8c; - union { - struct { - uint32_t mode : 3; - uint32_t reserved3 : 1; - uint32_t addr : 2; - uint32_t reserved6 : 26; - }; - uint32_t val; - } ahb_test; - union { - struct { - uint32_t cmd_st : 3; - uint32_t reserved3 : 1; - uint32_t func_st : 4; - uint32_t sdio_wakeup : 1; - uint32_t reserved9 : 3; - uint32_t bus_st : 3; - uint32_t reserved15 : 1; - uint32_t func1_acc_state : 5; - uint32_t reserved21 : 11; - }; - uint32_t val; - } sdio_st; - union { - struct { - uint32_t token_no_replace : 1; - uint32_t infor_no_replace : 1; - uint32_t rx_fill_mode : 1; - uint32_t rx_eof_mode : 1; - uint32_t rx_fill_en : 1; - uint32_t rd_retry_threshold : 11; - uint32_t reserved16 : 16; - }; - uint32_t val; - } rx_dscr_conf; - uint32_t slc0_txlink_dscr; - uint32_t slc0_txlink_dscr_bf0; - uint32_t slc0_txlink_dscr_bf1; - uint32_t slc0_rxlink_dscr; - uint32_t slc0_rxlink_dscr_bf0; - uint32_t slc0_rxlink_dscr_bf1; - uint32_t reserved_b4; - uint32_t reserved_b8; - uint32_t reserved_bc; - uint32_t reserved_c0; - uint32_t reserved_c4; - uint32_t reserved_c8; - uint32_t slc0_tx_erreof_des_addr; - uint32_t reserved_d0; - union { - struct { - uint32_t token : 12; - uint32_t reserved12 : 20; - }; - uint32_t val; - } token_lat; - union { - struct { - uint32_t wr_retry_threshold : 11; - uint32_t reserved11 : 21; - }; - uint32_t val; - } tx_dscr_conf; - uint32_t cmd_infor0; - uint32_t cmd_infor1; - union { - struct { - uint32_t len_wdata : 20; - uint32_t len_wr : 1; - uint32_t len_inc : 1; - uint32_t len_inc_more : 1; - uint32_t rx_packet_load_en : 1; - uint32_t tx_packet_load_en : 1; - uint32_t rx_get_used_dscr : 1; - uint32_t tx_get_used_dscr : 1; - uint32_t rx_new_pkt_ind : 1; - uint32_t tx_new_pkt_ind : 1; - uint32_t reserved29 : 3; - }; - uint32_t val; - } slc0_len_conf; - union { - struct { - uint32_t len : 20; - uint32_t reserved20 : 12; - }; - uint32_t val; - } slc0_length; - uint32_t slc0_txpkt_h_dscr; - uint32_t slc0_txpkt_e_dscr; - uint32_t slc0_rxpkt_h_dscr; - uint32_t slc0_rxpkt_e_dscr; - uint32_t slc0_txpktu_h_dscr; - uint32_t slc0_txpktu_e_dscr; - uint32_t slc0_rxpktu_h_dscr; - uint32_t slc0_rxpktu_e_dscr; - uint32_t reserved_10c; - uint32_t reserved_110; - union { - struct { - uint32_t seq_position : 8; - uint32_t reserved8 : 24; - }; - uint32_t val; - } seq_position; - union { - struct { - uint32_t rx_dscr_rec_lim : 10; - uint32_t reserved10 : 22; - }; - uint32_t val; - } slc0_dscr_rec_conf; - union { - struct { - uint32_t dat0_crc_err_cnt : 8; - uint32_t dat1_crc_err_cnt : 8; - uint32_t dat2_crc_err_cnt : 8; - uint32_t dat3_crc_err_cnt : 8; - }; - uint32_t val; - } sdio_crc_st0; - union { - struct { - uint32_t cmd_crc_err_cnt : 8; - uint32_t reserved8 : 23; - uint32_t err_cnt_clr : 1; - }; - uint32_t val; - } sdio_crc_st1; - uint32_t slc0_eof_start_des; - uint32_t slc0_push_dscr_addr; - uint32_t slc0_done_dscr_addr; - uint32_t slc0_sub_start_des; - union { - struct { - uint32_t rx_dscr_cnt_lat : 10; - uint32_t reserved10 : 6; - uint32_t rx_get_eof_occ : 1; - uint32_t reserved17 : 15; - }; - uint32_t val; - } slc0_dscr_cnt; - union { - struct { - uint32_t len_lim : 20; - uint32_t reserved20 : 12; - }; - uint32_t val; - } slc0_len_lim_conf; - union { - struct { - uint32_t frhost_bit01 : 1; - uint32_t frhost_bit11 : 1; - uint32_t frhost_bit21 : 1; - uint32_t frhost_bit31 : 1; - uint32_t frhost_bit41 : 1; - uint32_t frhost_bit51 : 1; - uint32_t frhost_bit61 : 1; - uint32_t frhost_bit71 : 1; - uint32_t rx_start1 : 1; - uint32_t tx_start1 : 1; - uint32_t rx_udf1 : 1; - uint32_t tx_ovf1 : 1; - uint32_t token0_1to01 : 1; - uint32_t token1_1to01 : 1; - uint32_t tx_done1 : 1; - uint32_t tx_suc_eof1 : 1; - uint32_t rx_done1 : 1; - uint32_t rx_eof1 : 1; - uint32_t tohost1 : 1; - uint32_t tx_dscr_err1 : 1; - uint32_t rx_dscr_err1 : 1; - uint32_t tx_dscr_empty1 : 1; - uint32_t host_rd_ack1 : 1; - uint32_t wr_retry_done1 : 1; - uint32_t tx_err_eof1 : 1; - uint32_t cmd_dtc1 : 1; - uint32_t rx_quick_eof1 : 1; - uint32_t host_pop_eof_err1 : 1; - uint32_t reserved28 : 4; - }; - uint32_t val; - } slc0_int_st1; - union { - struct { - uint32_t frhost_bit01 : 1; - uint32_t frhost_bit11 : 1; - uint32_t frhost_bit21 : 1; - uint32_t frhost_bit31 : 1; - uint32_t frhost_bit41 : 1; - uint32_t frhost_bit51 : 1; - uint32_t frhost_bit61 : 1; - uint32_t frhost_bit71 : 1; - uint32_t rx_start1 : 1; - uint32_t tx_start1 : 1; - uint32_t rx_udf1 : 1; - uint32_t tx_ovf1 : 1; - uint32_t token0_1to01 : 1; - uint32_t token1_1to01 : 1; - uint32_t tx_done1 : 1; - uint32_t tx_suc_eof1 : 1; - uint32_t rx_done1 : 1; - uint32_t rx_eof1 : 1; - uint32_t tohost1 : 1; - uint32_t tx_dscr_err1 : 1; - uint32_t rx_dscr_err1 : 1; - uint32_t tx_dscr_empty1 : 1; - uint32_t host_rd_ack1 : 1; - uint32_t wr_retry_done1 : 1; - uint32_t tx_err_eof1 : 1; - uint32_t cmd_dtc1 : 1; - uint32_t rx_quick_eof1 : 1; - uint32_t host_pop_eof_err1 : 1; - uint32_t reserved28 : 4; - }; - uint32_t val; - } slc0_int_ena1; - uint32_t reserved_144; - uint32_t reserved_148; - uint32_t reserved_14c; - 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 date; - uint32_t id; -} slc_dev_t; -extern slc_dev_t SLC; -#ifdef __cplusplus -} -#endif - - - -#endif /*_SOC_SLC_STRUCT_H_ */ diff --git a/components/soc/esp32s3/include/soc/soc.h b/components/soc/esp32s3/include/soc/soc.h index c5db076731..001f5fe853 100644 --- a/components/soc/esp32s3/include/soc/soc.h +++ b/components/soc/esp32s3/include/soc/soc.h @@ -331,7 +331,7 @@ * 25 4 extern level CACHEERR * 26 5 extern level * 27 3 extern level Reserved Reserved - * 28 4 extern edge DPORT ACCESS DPORT ACCESS + * 28 4 extern edge IPC_ISR IPC_ISR * 29 3 software Reserved Reserved * 30 4 extern edge Reserved Reserved * 31 5 extern level @@ -346,7 +346,7 @@ #define ETS_FRC1_INUM 22 #define ETS_T1_WDT_INUM 24 #define ETS_CACHEERR_INUM 25 -#define ETS_DPORT_INUM 28 +#define ETS_IPC_ISR_INUM 28 //CPU0 Interrupt number used in ROM, should be cancelled in SDK #define ETS_SLC_INUM 1 diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index 40942446cc..c52f828d90 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -16,29 +16,52 @@ #define SOC_CACHE_SUPPORT_WRAP 1 #define SOC_ULP_SUPPORTED 1 #define SOC_USB_OTG_SUPPORTED 1 +#define SOC_USB_SERIAL_JTAG_SUPPORTED 1 #define SOC_RTC_SLOW_MEM_SUPPORTED 1 #define SOC_CCOMP_TIMER_SUPPORTED 1 -#define SOC_DIG_SIGN_SUPPORTED 0 -#define SOC_HMAC_SUPPORTED 0 +#define SOC_DIG_SIGN_SUPPORTED 1 +#define SOC_HMAC_SUPPORTED 1 #define SOC_ASYNC_MEMCPY_SUPPORTED 1 +#define SOC_SUPPORTS_SECURE_DL_MODE 1 #define SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS 3 #define SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS 1 #define SOC_SDMMC_HOST_SUPPORTED 1 #define SOC_FLASH_ENCRYPTION_XTS_AES 1 #define SOC_FLASH_ENCRYPTION_XTS_AES_256 1 #define SOC_PSRAM_DMA_CAPABLE 1 +#define SOC_XT_WDT_SUPPORTED 1 + /*-------------------------- SOC CAPS ----------------------------------------*/ #define SOC_APPCPU_HAS_CLOCK_GATING_BUG (1) /*-------------------------- ADC CAPS ----------------------------------------*/ -#define SOC_ADC_PERIPH_NUM (2) -#define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) (10) -#define SOC_ADC_MAX_CHANNEL_NUM (10) -#define SOC_ADC_MAX_BITWIDTH (12) -#define SOC_ADC_SUPPORT_RTC_CTRL (1) -#define SOC_ADC_ARBITER_SUPPORTED (1) +/*!< SAR ADC Module*/ +#define SOC_ADC_RTC_CTRL_SUPPORTED 1 +#define SOC_ADC_ARBITER_SUPPORTED 1 +#define SOC_ADC_FILTER_SUPPORTED 1 +#define SOC_ADC_MONITOR_SUPPORTED 1 +#define SOC_ADC_PERIPH_NUM (2) +#define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) (10) +#define SOC_ADC_MAX_CHANNEL_NUM (10) +/*!< Digital */ +#define SOC_ADC_DIGI_CONTROLLER_NUM (2) +#define SOC_ADC_PATT_LEN_MAX (24) //Two pattern table, each contains 12 items. Each item takes 1 byte +#define SOC_ADC_DIGI_MAX_BITWIDTH (13) +/*!< F_sample = F_digi_con / 2 / interval. F_digi_con = 5M for now. 30 <= interva <= 4095 */ +#define SOC_ADC_SAMPLE_FREQ_THRES_HIGH 83333 +#define SOC_ADC_SAMPLE_FREQ_THRES_LOW 611 + +/*!< RTC */ +#define SOC_ADC_MAX_BITWIDTH (12) + +/*!< Calibration */ +#define SOC_ADC_CALIBRATION_V1_SUPPORTED (1) /*!< support HW offset calibration version 1*/ + + +/*-------------------------- APB BACKUP DMA CAPS -------------------------------*/ +#define SOC_APB_BACKUP_DMA (1) /*-------------------------- BROWNOUT CAPS -----------------------------------*/ #include "brownout_caps.h" @@ -46,6 +69,17 @@ /*-------------------------- CPU CAPS ----------------------------------------*/ #include "cpu_caps.h" +/*-------------------------- DIGITAL SIGNATURE CAPS ----------------------------------------*/ +/** The maximum length of a Digital Signature in bits. */ +#define SOC_DS_SIGNATURE_MAX_BIT_LEN (4096) + +/** Initialization vector (IV) length for the RSA key parameter message digest (MD) in bytes. */ +#define SOC_DS_KEY_PARAM_MD_IV_LENGTH (16) + +/** Maximum wait time for DS parameter decryption key. If overdue, then key error. + See TRM DS chapter for more details */ +#define SOC_DS_KEY_CHECK_MAX_WAIT_US (1100) + /*-------------------------- GDMA CAPS ---------------------------------------*/ #define SOC_GDMA_GROUPS (1) // Number of GDMA groups #define SOC_GDMA_PAIRS_PER_GROUP (5) // Number of GDMA pairs in each group @@ -58,12 +92,18 @@ /*-------------------------- Dedicated GPIO CAPS -----------------------------*/ #define SOC_DEDIC_GPIO_OUT_CHANNELS_NUM (8) /*!< 8 outward channels on each CPU core */ #define SOC_DEDIC_GPIO_IN_CHANNELS_NUM (8) /*!< 8 inward channels on each CPU core */ +#define SOC_DEDIC_GPIO_OUT_AUTO_ENABLE (1) /*!< Dedicated GPIO output attribution is enabled automatically */ /*-------------------------- I2C CAPS ----------------------------------------*/ #include "i2c_caps.h" /*-------------------------- I2S CAPS ----------------------------------------*/ -#include "i2s_caps.h" +#define SOC_I2S_NUM (2) +#define SOC_I2S_SUPPORTS_PCM (1) +#define SOC_I2S_SUPPORTS_PDM_TX (1) +#define SOC_I2S_SUPPORTS_PDM_RX (1) +#define SOC_I2S_SUPPORTS_PDM_CODEC (1) +#define SOC_I2S_SUPPORTS_TDM (1) /*-------------------------- LEDC CAPS ---------------------------------------*/ #include "ledc_caps.h" @@ -79,27 +119,30 @@ #define SOC_MCPWM_CAPTURE_TIMERS_PER_GROUP (1) ///< The number of capture timers that each group has #define SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER (3) ///< The number of capture channels that each capture timer has #define SOC_MCPWM_GPIO_SYNCHROS_PER_GROUP (3) ///< The number of GPIO synchros that each group has +#define SOC_MCPWM_SWSYNC_CAN_PROPAGATE (1) ///< Software sync event can be routed to its output #define SOC_MCPWM_BASE_CLK_HZ (160000000ULL) ///< Base Clock frequency of 160MHz /*-------------------------- MPU CAPS ----------------------------------------*/ #include "mpu_caps.h" /*-------------------------- PCNT CAPS ---------------------------------------*/ -#define SOC_PCNT_PORT_NUM (1) -#define SOC_PCNT_UNIT_NUM (4) -#define SOC_PCNT_UNIT_CHANNEL_NUM (2) +#define SOC_PCNT_GROUPS (1) +#define SOC_PCNT_UNITS_PER_GROUP (4) +#define SOC_PCNT_CHANNELS_PER_UNIT (2) +#define SOC_PCNT_THRES_POINT_PER_UNIT (2) /*-------------------------- RMT CAPS ----------------------------------------*/ -#define SOC_RMT_GROUPS (1) /*!< One RMT group */ -#define SOC_RMT_TX_CANDIDATES_PER_GROUP (4) /*!< Number of channels that capable of Transmit in each group */ -#define SOC_RMT_RX_CANDIDATES_PER_GROUP (4) /*!< Number of channels that capable of Receive in each group */ -#define SOC_RMT_CHANNELS_PER_GROUP (8) /*!< Total 8 channels */ -#define SOC_RMT_MEM_WORDS_PER_CHANNEL (48) /*!< Each channel owns 48 words memory (1 word = 4 Bytes) */ -#define SOC_RMT_SUPPORT_RX_PINGPONG (1) /*!< Support Ping-Pong mode on RX path */ -#define SOC_RMT_SUPPORT_RX_DEMODULATION (1) /*!< Support signal demodulation on RX path (i.e. remove carrier) */ -#define SOC_RMT_SUPPORT_TX_LOOP_COUNT (1) /*!< Support transmit specified number of cycles in loop mode */ -#define SOC_RMT_SUPPORT_TX_SYNCHRO (1) /*!< Support coordinate a group of TX channels to start simultaneously */ -#define SOC_RMT_SUPPORT_XTAL (1) /*!< Support set XTAL clock as the RMT clock source */ +#define SOC_RMT_GROUPS (1) /*!< One RMT group */ +#define SOC_RMT_TX_CANDIDATES_PER_GROUP (4) /*!< Number of channels that capable of Transmit in each group */ +#define SOC_RMT_RX_CANDIDATES_PER_GROUP (4) /*!< Number of channels that capable of Receive in each group */ +#define SOC_RMT_CHANNELS_PER_GROUP (8) /*!< Total 8 channels */ +#define SOC_RMT_MEM_WORDS_PER_CHANNEL (48) /*!< Each channel owns 48 words memory (1 word = 4 Bytes) */ +#define SOC_RMT_SUPPORT_RX_PINGPONG (1) /*!< Support Ping-Pong mode on RX path */ +#define SOC_RMT_SUPPORT_RX_DEMODULATION (1) /*!< Support signal demodulation on RX path (i.e. remove carrier) */ +#define SOC_RMT_SUPPORT_TX_LOOP_COUNT (1) /*!< Support transmit specified number of cycles in loop mode */ +#define SOC_RMT_SUPPORT_TX_LOOP_AUTOSTOP (1) /*!< Hardware support of auto-stop in loop mode */ +#define SOC_RMT_SUPPORT_TX_SYNCHRO (1) /*!< Support coordinate a group of TX channels to start simultaneously */ +#define SOC_RMT_SUPPORT_XTAL (1) /*!< Support set XTAL clock as the RMT clock source */ /*-------------------------- LCD CAPS ----------------------------------------*/ @@ -111,6 +154,18 @@ #define SOC_LCD_I80_BUS_WIDTH (16) /*!< Intel 8080 bus width */ #define SOC_LCD_RGB_DATA_WIDTH (16) /*!< Number of LCD data lines */ +/*-------------------------- RTC CAPS --------------------------------------*/ +#define SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH (128) +#define SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM (549) +#define SOC_RTC_CNTL_CPU_PD_DMA_ADDR_ALIGN (SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH >> 3) +#define SOC_RTC_CNTL_CPU_PD_DMA_BLOCK_SIZE (SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH >> 3) + +#define SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE (SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM * (SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH >> 3)) + +/* I/D Cache tag memory retention hardware parameters */ +#define SOC_RTC_CNTL_TAGMEM_PD_DMA_BUS_WIDTH (128) +#define SOC_RTC_CNTL_TAGMEM_PD_DMA_ADDR_ALIGN (SOC_RTC_CNTL_TAGMEM_PD_DMA_BUS_WIDTH >> 3) + /*-------------------------- RTCIO CAPS --------------------------------------*/ #include "rtc_io_caps.h" @@ -119,7 +174,24 @@ #define SOC_SIGMADELTA_CHANNEL_NUM (8) // 8 channels /*-------------------------- SPI CAPS ----------------------------------------*/ -#include "spi_caps.h" +#define SOC_SPI_PERIPH_NUM 3 +#define SOC_SPI_DMA_CHAN_NUM 3 +#define SOC_SPI_PERIPH_CS_NUM(i) 3 +#define SOC_SPI_MAXIMUM_BUFFER_SIZE 64 +#define SOC_SPI_SUPPORT_DDRCLK 1 +#define SOC_SPI_SLAVE_SUPPORT_SEG_TRANS 1 +#define SOC_SPI_SUPPORT_CD_SIG 1 +#define SOC_SPI_SUPPORT_CONTINUOUS_TRANS 1 +#define SOC_SPI_SUPPORT_SLAVE_HD_VER2 1 + +// Peripheral supports DIO, DOUT, QIO, or QOUT +#define SOC_SPI_PERIPH_SUPPORT_MULTILINE_MODE(host_id) ({(void)host_id; 1;}) + +// Peripheral supports output given level during its "dummy phase" +#define SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUTPUT 1 +#define SOC_MEMSPI_IS_INDEPENDENT 1 +#define SOC_SPI_MAX_PRE_DIVIDER 16 +#define SOC_SPI_SUPPORT_OCT 1 /*-------------------------- SPIRAM CAPS ----------------------------------------*/ #define SOC_SPIRAM_SUPPORTED 1 @@ -203,6 +275,10 @@ #define SOC_PM_SUPPORT_BT_WAKEUP (1) +#define SOC_PM_SUPPORT_CPU_PD (1) + +#define SOC_PM_SUPPORT_TAGMEM_PD (1) + /*-------------------------- Flash Encryption CAPS----------------------------*/ #define SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX (64) @@ -223,6 +299,9 @@ #define SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND (1) #define SOC_SPI_MEM_SUPPORT_AUTO_RESUME (1) #define SOC_SPI_MEM_SUPPORT_SW_SUSPEND (1) +#define SOC_SPI_MEM_SUPPORT_OPI_MODE (1) +#define SOC_SPI_MEM_SUPPORT_TIME_TUNING (1) + /*-------------------------- COEXISTENCE HARDWARE PTI CAPS -------------------------------*/ #define SOC_COEX_HW_PTI (1) diff --git a/components/soc/esp32s3/include/soc/spi_caps.h b/components/soc/esp32s3/include/soc/spi_caps.h deleted file mode 100644 index 0bb45db135..0000000000 --- a/components/soc/esp32s3/include/soc/spi_caps.h +++ /dev/null @@ -1,38 +0,0 @@ -// 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. - -#pragma once - -#define SOC_SPI_PERIPH_NUM 3 -#define SOC_SPI_DMA_CHAN_NUM 3 -#define SOC_SPI_PERIPH_CS_NUM(i) 3 - -#define SOC_SPI_MAXIMUM_BUFFER_SIZE 64 - -#define SOC_SPI_SUPPORT_DDRCLK 1 -#define SOC_SPI_SLAVE_SUPPORT_SEG_TRANS 1 -#define SOC_SPI_SUPPORT_CD_SIG 1 -#define SOC_SPI_SUPPORT_CONTINUOUS_TRANS 1 -#define SOC_SPI_SUPPORT_SLAVE_HD_VER2 1 - -// Peripheral supports DIO, DOUT, QIO, or QOUT -// VSPI (SPI3) only support 1-bit mode -#define SOC_SPI_PERIPH_SUPPORT_MULTILINE_MODE(host_id) ({(void)host_id; 1;}) - -// Peripheral supports output given level during its "dummy phase" -#define SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUTPUT 1 - -#define SOC_MEMSPI_IS_INDEPENDENT 1 - -#define SOC_SPI_MAX_PRE_DIVIDER 16 diff --git a/components/soc/esp32s3/include/soc/spi_mem_struct.h b/components/soc/esp32s3/include/soc/spi_mem_struct.h index 32ce1bf933..aa6f388653 100644 --- a/components/soc/esp32s3/include/soc/spi_mem_struct.h +++ b/components/soc/esp32s3/include/soc/spi_mem_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct spi_mem_dev_s { union { struct { uint32_t reserved0 : 17; /*reserved*/ diff --git a/components/soc/esp32s3/include/soc/spi_pins.h b/components/soc/esp32s3/include/soc/spi_pins.h index da0a54adc8..05d338085c 100644 --- a/components/soc/esp32s3/include/soc/spi_pins.h +++ b/components/soc/esp32s3/include/soc/spi_pins.h @@ -22,6 +22,9 @@ #define SPI_IOMUX_PIN_NUM_MISO 31 #define SPI_IOMUX_PIN_NUM_WP 28 +// There are 2 sets of GPIO pins which could be routed to FSPICS0, FSPICLK, FSPID, FSPIQ, FSPIHD, FSPIWP. +// However, there is only one set of GPIO pins which could be routed to FSPIIO4, FSPIIO5, FSPIIO6, FSPIIO7. +// As default (when we are not going to use Octal SPI), we make use of SPI2_FUNC_NUM to route one of the 2 sets of GPIO pins to FSPICS0 ~ FSPIWP as follows. #define SPI2_FUNC_NUM 4 #define SPI2_IOMUX_PIN_NUM_HD 9 #define SPI2_IOMUX_PIN_NUM_CS 10 @@ -30,4 +33,17 @@ #define SPI2_IOMUX_PIN_NUM_MISO 13 #define SPI2_IOMUX_PIN_NUM_WP 14 +// When using Octal SPI, we make use of SPI2_FUNC_NUM_OCT to route them as follows. +#define SPI2_FUNC_NUM_OCT 2 +#define SPI2_IOMUX_PIN_NUM_HD_OCT 33 +#define SPI2_IOMUX_PIN_NUM_CS_OCT 34 +#define SPI2_IOMUX_PIN_NUM_MOSI_OCT 35 +#define SPI2_IOMUX_PIN_NUM_CLK_OCT 36 +#define SPI2_IOMUX_PIN_NUM_MISO_OCT 37 +#define SPI2_IOMUX_PIN_NUM_WP_OCT 38 +#define SPI2_IOMUX_PIN_NUM_IO4_OCT 10 +#define SPI2_IOMUX_PIN_NUM_IO5_OCT 11 +#define SPI2_IOMUX_PIN_NUM_IO6_OCT 12 +#define SPI2_IOMUX_PIN_NUM_IO7_OCT 13 + //SPI3 have no iomux pins diff --git a/components/soc/esp32s3/include/soc/spi_struct.h b/components/soc/esp32s3/include/soc/spi_struct.h index c57ad937ce..2a3abd257c 100644 --- a/components/soc/esp32s3/include/soc/spi_struct.h +++ b/components/soc/esp32s3/include/soc/spi_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct spi_dev_s { union { struct { uint32_t conf_bitlen : 18; /*Define the APB cycles of SPI_CONF state. Can be configured in CONF state.*/ diff --git a/components/soc/esp32s3/include/soc/syscon_reg.h b/components/soc/esp32s3/include/soc/syscon_reg.h index 6706ccc53d..d5dae5f1b3 100644 --- a/components/soc/esp32s3/include/soc/syscon_reg.h +++ b/components/soc/esp32s3/include/soc/syscon_reg.h @@ -20,148 +20,148 @@ extern "C" { #endif -#define SYSCON_SYSCLK_CONF_REG (DR_REG_SYSCON_BASE + 0x000) +#define SYSCON_SYSCLK_CONF_REG (DR_REG_SYSCON_BASE + 0x0) /* SYSCON_RST_TICK_CNT : R/W ;bitpos:[12] ;default: 1'b0 ; */ -/*description: */ -#define SYSCON_RST_TICK_CNT (BIT(12)) +/*description: .*/ +#define SYSCON_RST_TICK_CNT (BIT(12)) #define SYSCON_RST_TICK_CNT_M (BIT(12)) #define SYSCON_RST_TICK_CNT_V 0x1 #define SYSCON_RST_TICK_CNT_S 12 /* SYSCON_CLK_EN : R/W ;bitpos:[11] ;default: 1'b0 ; */ -/*description: */ -#define SYSCON_CLK_EN (BIT(11)) +/*description: .*/ +#define SYSCON_CLK_EN (BIT(11)) #define SYSCON_CLK_EN_M (BIT(11)) #define SYSCON_CLK_EN_V 0x1 #define SYSCON_CLK_EN_S 11 /* SYSCON_CLK_320M_EN : R/W ;bitpos:[10] ;default: 1'b0 ; */ -/*description: */ -#define SYSCON_CLK_320M_EN (BIT(10)) +/*description: .*/ +#define SYSCON_CLK_320M_EN (BIT(10)) #define SYSCON_CLK_320M_EN_M (BIT(10)) #define SYSCON_CLK_320M_EN_V 0x1 #define SYSCON_CLK_320M_EN_S 10 /* SYSCON_PRE_DIV_CNT : R/W ;bitpos:[9:0] ;default: 10'h1 ; */ -/*description: */ -#define SYSCON_PRE_DIV_CNT 0x000003FF +/*description: .*/ +#define SYSCON_PRE_DIV_CNT 0x000003FF #define SYSCON_PRE_DIV_CNT_M ((SYSCON_PRE_DIV_CNT_V)<<(SYSCON_PRE_DIV_CNT_S)) #define SYSCON_PRE_DIV_CNT_V 0x3FF #define SYSCON_PRE_DIV_CNT_S 0 -#define SYSCON_TICK_CONF_REG (DR_REG_SYSCON_BASE + 0x004) +#define SYSCON_TICK_CONF_REG (DR_REG_SYSCON_BASE + 0x4) /* SYSCON_TICK_ENABLE : R/W ;bitpos:[16] ;default: 1'd1 ; */ -/*description: */ -#define SYSCON_TICK_ENABLE (BIT(16)) +/*description: .*/ +#define SYSCON_TICK_ENABLE (BIT(16)) #define SYSCON_TICK_ENABLE_M (BIT(16)) #define SYSCON_TICK_ENABLE_V 0x1 #define SYSCON_TICK_ENABLE_S 16 /* SYSCON_CK8M_TICK_NUM : R/W ;bitpos:[15:8] ;default: 8'd7 ; */ -/*description: */ -#define SYSCON_CK8M_TICK_NUM 0x000000FF +/*description: .*/ +#define SYSCON_CK8M_TICK_NUM 0x000000FF #define SYSCON_CK8M_TICK_NUM_M ((SYSCON_CK8M_TICK_NUM_V)<<(SYSCON_CK8M_TICK_NUM_S)) #define SYSCON_CK8M_TICK_NUM_V 0xFF #define SYSCON_CK8M_TICK_NUM_S 8 /* SYSCON_XTAL_TICK_NUM : R/W ;bitpos:[7:0] ;default: 8'd39 ; */ -/*description: */ -#define SYSCON_XTAL_TICK_NUM 0x000000FF +/*description: .*/ +#define SYSCON_XTAL_TICK_NUM 0x000000FF #define SYSCON_XTAL_TICK_NUM_M ((SYSCON_XTAL_TICK_NUM_V)<<(SYSCON_XTAL_TICK_NUM_S)) #define SYSCON_XTAL_TICK_NUM_V 0xFF #define SYSCON_XTAL_TICK_NUM_S 0 -#define SYSCON_CLK_OUT_EN_REG (DR_REG_SYSCON_BASE + 0x008) +#define SYSCON_CLK_OUT_EN_REG (DR_REG_SYSCON_BASE + 0x8) /* SYSCON_CLK_XTAL_OEN : R/W ;bitpos:[10] ;default: 1'b1 ; */ -/*description: */ -#define SYSCON_CLK_XTAL_OEN (BIT(10)) +/*description: .*/ +#define SYSCON_CLK_XTAL_OEN (BIT(10)) #define SYSCON_CLK_XTAL_OEN_M (BIT(10)) #define SYSCON_CLK_XTAL_OEN_V 0x1 #define SYSCON_CLK_XTAL_OEN_S 10 /* SYSCON_CLK40X_BB_OEN : R/W ;bitpos:[9] ;default: 1'b1 ; */ -/*description: */ -#define SYSCON_CLK40X_BB_OEN (BIT(9)) +/*description: .*/ +#define SYSCON_CLK40X_BB_OEN (BIT(9)) #define SYSCON_CLK40X_BB_OEN_M (BIT(9)) #define SYSCON_CLK40X_BB_OEN_V 0x1 #define SYSCON_CLK40X_BB_OEN_S 9 /* SYSCON_CLK_DAC_CPU_OEN : R/W ;bitpos:[8] ;default: 1'b1 ; */ -/*description: */ -#define SYSCON_CLK_DAC_CPU_OEN (BIT(8)) +/*description: .*/ +#define SYSCON_CLK_DAC_CPU_OEN (BIT(8)) #define SYSCON_CLK_DAC_CPU_OEN_M (BIT(8)) #define SYSCON_CLK_DAC_CPU_OEN_V 0x1 #define SYSCON_CLK_DAC_CPU_OEN_S 8 /* SYSCON_CLK_ADC_INF_OEN : R/W ;bitpos:[7] ;default: 1'b1 ; */ -/*description: */ -#define SYSCON_CLK_ADC_INF_OEN (BIT(7)) +/*description: .*/ +#define SYSCON_CLK_ADC_INF_OEN (BIT(7)) #define SYSCON_CLK_ADC_INF_OEN_M (BIT(7)) #define SYSCON_CLK_ADC_INF_OEN_V 0x1 #define SYSCON_CLK_ADC_INF_OEN_S 7 /* SYSCON_CLK_320M_OEN : R/W ;bitpos:[6] ;default: 1'b1 ; */ -/*description: */ -#define SYSCON_CLK_320M_OEN (BIT(6)) +/*description: .*/ +#define SYSCON_CLK_320M_OEN (BIT(6)) #define SYSCON_CLK_320M_OEN_M (BIT(6)) #define SYSCON_CLK_320M_OEN_V 0x1 #define SYSCON_CLK_320M_OEN_S 6 /* SYSCON_CLK160_OEN : R/W ;bitpos:[5] ;default: 1'b1 ; */ -/*description: */ -#define SYSCON_CLK160_OEN (BIT(5)) +/*description: .*/ +#define SYSCON_CLK160_OEN (BIT(5)) #define SYSCON_CLK160_OEN_M (BIT(5)) #define SYSCON_CLK160_OEN_V 0x1 #define SYSCON_CLK160_OEN_S 5 /* SYSCON_CLK80_OEN : R/W ;bitpos:[4] ;default: 1'b1 ; */ -/*description: */ -#define SYSCON_CLK80_OEN (BIT(4)) +/*description: .*/ +#define SYSCON_CLK80_OEN (BIT(4)) #define SYSCON_CLK80_OEN_M (BIT(4)) #define SYSCON_CLK80_OEN_V 0x1 #define SYSCON_CLK80_OEN_S 4 /* SYSCON_CLK_BB_OEN : R/W ;bitpos:[3] ;default: 1'b1 ; */ -/*description: */ -#define SYSCON_CLK_BB_OEN (BIT(3)) +/*description: .*/ +#define SYSCON_CLK_BB_OEN (BIT(3)) #define SYSCON_CLK_BB_OEN_M (BIT(3)) #define SYSCON_CLK_BB_OEN_V 0x1 #define SYSCON_CLK_BB_OEN_S 3 /* SYSCON_CLK44_OEN : R/W ;bitpos:[2] ;default: 1'b1 ; */ -/*description: */ -#define SYSCON_CLK44_OEN (BIT(2)) +/*description: .*/ +#define SYSCON_CLK44_OEN (BIT(2)) #define SYSCON_CLK44_OEN_M (BIT(2)) #define SYSCON_CLK44_OEN_V 0x1 #define SYSCON_CLK44_OEN_S 2 /* SYSCON_CLK22_OEN : R/W ;bitpos:[1] ;default: 1'b1 ; */ -/*description: */ -#define SYSCON_CLK22_OEN (BIT(1)) +/*description: .*/ +#define SYSCON_CLK22_OEN (BIT(1)) #define SYSCON_CLK22_OEN_M (BIT(1)) #define SYSCON_CLK22_OEN_V 0x1 #define SYSCON_CLK22_OEN_S 1 /* SYSCON_CLK20_OEN : R/W ;bitpos:[0] ;default: 1'b1 ; */ -/*description: */ -#define SYSCON_CLK20_OEN (BIT(0)) +/*description: .*/ +#define SYSCON_CLK20_OEN (BIT(0)) #define SYSCON_CLK20_OEN_M (BIT(0)) #define SYSCON_CLK20_OEN_V 0x1 #define SYSCON_CLK20_OEN_S 0 -#define SYSCON_WIFI_BB_CFG_REG (DR_REG_SYSCON_BASE + 0x00C) +#define SYSCON_WIFI_BB_CFG_REG (DR_REG_SYSCON_BASE + 0xC) /* SYSCON_WIFI_BB_CFG : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define SYSCON_WIFI_BB_CFG 0xFFFFFFFF +/*description: .*/ +#define SYSCON_WIFI_BB_CFG 0xFFFFFFFF #define SYSCON_WIFI_BB_CFG_M ((SYSCON_WIFI_BB_CFG_V)<<(SYSCON_WIFI_BB_CFG_S)) #define SYSCON_WIFI_BB_CFG_V 0xFFFFFFFF #define SYSCON_WIFI_BB_CFG_S 0 -#define SYSCON_WIFI_BB_CFG_2_REG (DR_REG_SYSCON_BASE + 0x010) +#define SYSCON_WIFI_BB_CFG_2_REG (DR_REG_SYSCON_BASE + 0x10) /* SYSCON_WIFI_BB_CFG_2 : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define SYSCON_WIFI_BB_CFG_2 0xFFFFFFFF +/*description: .*/ +#define SYSCON_WIFI_BB_CFG_2 0xFFFFFFFF #define SYSCON_WIFI_BB_CFG_2_M ((SYSCON_WIFI_BB_CFG_2_V)<<(SYSCON_WIFI_BB_CFG_2_S)) #define SYSCON_WIFI_BB_CFG_2_V 0xFFFFFFFF #define SYSCON_WIFI_BB_CFG_2_S 0 -#define SYSCON_WIFI_CLK_EN_REG (DR_REG_SYSCON_BASE + 0x014) +#define SYSCON_WIFI_CLK_EN_REG (DR_REG_SYSCON_BASE + 0x14) /* SYSCON_WIFI_CLK_EN : R/W ;bitpos:[31:0] ;default: 32'hfffce030 ; */ -/*description: */ -#define SYSCON_WIFI_CLK_EN 0xFFFFFFFF +/*description: .*/ +#define SYSCON_WIFI_CLK_EN 0xFFFFFFFF #define SYSCON_WIFI_CLK_EN_M ((SYSCON_WIFI_CLK_EN_V)<<(SYSCON_WIFI_CLK_EN_S)) #define SYSCON_WIFI_CLK_EN_V 0xFFFFFFFF #define SYSCON_WIFI_CLK_EN_S 0 -#define SYSCON_WIFI_RST_EN_REG (DR_REG_SYSCON_BASE + 0x018) +#define SYSCON_WIFI_RST_EN_REG (DR_REG_SYSCON_BASE + 0x18) /* SYSCON_WIFI_RST : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define SYSCON_WIFI_RST 0xFFFFFFFF +/*description: .*/ +#define SYSCON_WIFI_RST 0xFFFFFFFF #define SYSCON_WIFI_RST_M ((SYSCON_WIFI_RST_V)<<(SYSCON_WIFI_RST_S)) #define SYSCON_WIFI_RST_V 0xFFFFFFFF #define SYSCON_WIFI_RST_S 0 @@ -169,9 +169,9 @@ extern "C" { #define SYSTEM_WIFI_CLK_EN_REG SYSCON_WIFI_CLK_EN_REG /* SYSTEM_WIFI_CLK_EN : R/W ;bitpos:[31:0] ;default: 32'hfffce030 ; */ /*description: */ -#define SYSTEM_WIFI_CLK_EN 0xFFFFFFFF +#define SYSTEM_WIFI_CLK_EN 0x00FB9FCF #define SYSTEM_WIFI_CLK_EN_M ((SYSTEM_WIFI_CLK_EN_V) << (SYSTEM_WIFI_CLK_EN_S)) -#define SYSTEM_WIFI_CLK_EN_V 0xFFFFFFFF +#define SYSTEM_WIFI_CLK_EN_V 0x00FB9FCF #define SYSTEM_WIFI_CLK_EN_S 0 /* Mask for all Wifi clock bits, 6 */ @@ -222,477 +222,494 @@ extern "C" { #define SYSTEM_FE_RST (BIT(1)) #define SYSTEM_BB_RST (BIT(0)) -#define SYSCON_HOST_INF_SEL_REG (DR_REG_SYSCON_BASE + 0x01C) +#define SYSCON_HOST_INF_SEL_REG (DR_REG_SYSCON_BASE + 0x1C) /* SYSCON_PERI_IO_SWAP : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ -/*description: */ -#define SYSCON_PERI_IO_SWAP 0x000000FF +/*description: .*/ +#define SYSCON_PERI_IO_SWAP 0x000000FF #define SYSCON_PERI_IO_SWAP_M ((SYSCON_PERI_IO_SWAP_V)<<(SYSCON_PERI_IO_SWAP_S)) #define SYSCON_PERI_IO_SWAP_V 0xFF #define SYSCON_PERI_IO_SWAP_S 0 -#define SYSCON_EXT_MEM_PMS_LOCK_REG (DR_REG_SYSCON_BASE + 0x020) +#define SYSCON_EXT_MEM_PMS_LOCK_REG (DR_REG_SYSCON_BASE + 0x20) /* SYSCON_EXT_MEM_PMS_LOCK : R/W ;bitpos:[0] ;default: 1'b0 ; */ -/*description: */ -#define SYSCON_EXT_MEM_PMS_LOCK (BIT(0)) +/*description: .*/ +#define SYSCON_EXT_MEM_PMS_LOCK (BIT(0)) #define SYSCON_EXT_MEM_PMS_LOCK_M (BIT(0)) #define SYSCON_EXT_MEM_PMS_LOCK_V 0x1 #define SYSCON_EXT_MEM_PMS_LOCK_S 0 -#define SYSCON_EXT_MEM_WRITEBACK_BYPASS_REG (DR_REG_SYSCON_BASE + 0x024) +#define SYSCON_EXT_MEM_WRITEBACK_BYPASS_REG (DR_REG_SYSCON_BASE + 0x24) /* SYSCON_WRITEBACK_BYPASS : R/W ;bitpos:[0] ;default: 1'b0 ; */ -/*description: Set 1 to bypass cache writeback request to external memory so - that spi will not check its attribute.*/ -#define SYSCON_WRITEBACK_BYPASS (BIT(0)) +/*description: Set 1 to bypass cache writeback request to external memory so that spi will not +check its attribute..*/ +#define SYSCON_WRITEBACK_BYPASS (BIT(0)) #define SYSCON_WRITEBACK_BYPASS_M (BIT(0)) #define SYSCON_WRITEBACK_BYPASS_V 0x1 #define SYSCON_WRITEBACK_BYPASS_S 0 -#define SYSCON_FLASH_ACE0_ATTR_REG (DR_REG_SYSCON_BASE + 0x028) +#define SYSCON_FLASH_ACE0_ATTR_REG (DR_REG_SYSCON_BASE + 0x28) /* SYSCON_FLASH_ACE0_ATTR : R/W ;bitpos:[8:0] ;default: 9'hff ; */ -/*description: */ -#define SYSCON_FLASH_ACE0_ATTR 0x000001FF +/*description: .*/ +#define SYSCON_FLASH_ACE0_ATTR 0x000001FF #define SYSCON_FLASH_ACE0_ATTR_M ((SYSCON_FLASH_ACE0_ATTR_V)<<(SYSCON_FLASH_ACE0_ATTR_S)) #define SYSCON_FLASH_ACE0_ATTR_V 0x1FF #define SYSCON_FLASH_ACE0_ATTR_S 0 -#define SYSCON_FLASH_ACE1_ATTR_REG (DR_REG_SYSCON_BASE + 0x02C) +#define SYSCON_FLASH_ACE1_ATTR_REG (DR_REG_SYSCON_BASE + 0x2C) /* SYSCON_FLASH_ACE1_ATTR : R/W ;bitpos:[8:0] ;default: 9'hff ; */ -/*description: */ -#define SYSCON_FLASH_ACE1_ATTR 0x000001FF +/*description: .*/ +#define SYSCON_FLASH_ACE1_ATTR 0x000001FF #define SYSCON_FLASH_ACE1_ATTR_M ((SYSCON_FLASH_ACE1_ATTR_V)<<(SYSCON_FLASH_ACE1_ATTR_S)) #define SYSCON_FLASH_ACE1_ATTR_V 0x1FF #define SYSCON_FLASH_ACE1_ATTR_S 0 -#define SYSCON_FLASH_ACE2_ATTR_REG (DR_REG_SYSCON_BASE + 0x030) +#define SYSCON_FLASH_ACE2_ATTR_REG (DR_REG_SYSCON_BASE + 0x30) /* SYSCON_FLASH_ACE2_ATTR : R/W ;bitpos:[8:0] ;default: 9'hff ; */ -/*description: */ -#define SYSCON_FLASH_ACE2_ATTR 0x000001FF +/*description: .*/ +#define SYSCON_FLASH_ACE2_ATTR 0x000001FF #define SYSCON_FLASH_ACE2_ATTR_M ((SYSCON_FLASH_ACE2_ATTR_V)<<(SYSCON_FLASH_ACE2_ATTR_S)) #define SYSCON_FLASH_ACE2_ATTR_V 0x1FF #define SYSCON_FLASH_ACE2_ATTR_S 0 -#define SYSCON_FLASH_ACE3_ATTR_REG (DR_REG_SYSCON_BASE + 0x034) +#define SYSCON_FLASH_ACE3_ATTR_REG (DR_REG_SYSCON_BASE + 0x34) /* SYSCON_FLASH_ACE3_ATTR : R/W ;bitpos:[8:0] ;default: 9'hff ; */ -/*description: */ -#define SYSCON_FLASH_ACE3_ATTR 0x000001FF +/*description: .*/ +#define SYSCON_FLASH_ACE3_ATTR 0x000001FF #define SYSCON_FLASH_ACE3_ATTR_M ((SYSCON_FLASH_ACE3_ATTR_V)<<(SYSCON_FLASH_ACE3_ATTR_S)) #define SYSCON_FLASH_ACE3_ATTR_V 0x1FF #define SYSCON_FLASH_ACE3_ATTR_S 0 -#define SYSCON_FLASH_ACE0_ADDR_REG (DR_REG_SYSCON_BASE + 0x038) +#define SYSCON_FLASH_ACE0_ADDR_REG (DR_REG_SYSCON_BASE + 0x38) /* SYSCON_FLASH_ACE0_ADDR_S : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define SYSCON_FLASH_ACE0_ADDR_S 0xFFFFFFFF +/*description: .*/ +#define SYSCON_FLASH_ACE0_ADDR_S 0xFFFFFFFF #define SYSCON_FLASH_ACE0_ADDR_S_M ((SYSCON_FLASH_ACE0_ADDR_S_V)<<(SYSCON_FLASH_ACE0_ADDR_S_S)) #define SYSCON_FLASH_ACE0_ADDR_S_V 0xFFFFFFFF #define SYSCON_FLASH_ACE0_ADDR_S_S 0 -#define SYSCON_FLASH_ACE1_ADDR_REG (DR_REG_SYSCON_BASE + 0x03C) +#define SYSCON_FLASH_ACE1_ADDR_REG (DR_REG_SYSCON_BASE + 0x3C) /* SYSCON_FLASH_ACE1_ADDR_S : R/W ;bitpos:[31:0] ;default: 32'h10000000 ; */ -/*description: */ -#define SYSCON_FLASH_ACE1_ADDR_S 0xFFFFFFFF +/*description: .*/ +#define SYSCON_FLASH_ACE1_ADDR_S 0xFFFFFFFF #define SYSCON_FLASH_ACE1_ADDR_S_M ((SYSCON_FLASH_ACE1_ADDR_S_V)<<(SYSCON_FLASH_ACE1_ADDR_S_S)) #define SYSCON_FLASH_ACE1_ADDR_S_V 0xFFFFFFFF #define SYSCON_FLASH_ACE1_ADDR_S_S 0 -#define SYSCON_FLASH_ACE2_ADDR_REG (DR_REG_SYSCON_BASE + 0x040) +#define SYSCON_FLASH_ACE2_ADDR_REG (DR_REG_SYSCON_BASE + 0x40) /* SYSCON_FLASH_ACE2_ADDR_S : R/W ;bitpos:[31:0] ;default: 32'h20000000 ; */ -/*description: */ -#define SYSCON_FLASH_ACE2_ADDR_S 0xFFFFFFFF +/*description: .*/ +#define SYSCON_FLASH_ACE2_ADDR_S 0xFFFFFFFF #define SYSCON_FLASH_ACE2_ADDR_S_M ((SYSCON_FLASH_ACE2_ADDR_S_V)<<(SYSCON_FLASH_ACE2_ADDR_S_S)) #define SYSCON_FLASH_ACE2_ADDR_S_V 0xFFFFFFFF #define SYSCON_FLASH_ACE2_ADDR_S_S 0 -#define SYSCON_FLASH_ACE3_ADDR_REG (DR_REG_SYSCON_BASE + 0x044) +#define SYSCON_FLASH_ACE3_ADDR_REG (DR_REG_SYSCON_BASE + 0x44) /* SYSCON_FLASH_ACE3_ADDR_S : R/W ;bitpos:[31:0] ;default: 32'h30000000 ; */ -/*description: */ -#define SYSCON_FLASH_ACE3_ADDR_S 0xFFFFFFFF +/*description: .*/ +#define SYSCON_FLASH_ACE3_ADDR_S 0xFFFFFFFF #define SYSCON_FLASH_ACE3_ADDR_S_M ((SYSCON_FLASH_ACE3_ADDR_S_V)<<(SYSCON_FLASH_ACE3_ADDR_S_S)) #define SYSCON_FLASH_ACE3_ADDR_S_V 0xFFFFFFFF #define SYSCON_FLASH_ACE3_ADDR_S_S 0 -#define SYSCON_FLASH_ACE0_SIZE_REG (DR_REG_SYSCON_BASE + 0x048) +#define SYSCON_FLASH_ACE0_SIZE_REG (DR_REG_SYSCON_BASE + 0x48) /* SYSCON_FLASH_ACE0_SIZE : R/W ;bitpos:[15:0] ;default: 16'h1000 ; */ -/*description: */ -#define SYSCON_FLASH_ACE0_SIZE 0x0000FFFF +/*description: .*/ +#define SYSCON_FLASH_ACE0_SIZE 0x0000FFFF #define SYSCON_FLASH_ACE0_SIZE_M ((SYSCON_FLASH_ACE0_SIZE_V)<<(SYSCON_FLASH_ACE0_SIZE_S)) #define SYSCON_FLASH_ACE0_SIZE_V 0xFFFF #define SYSCON_FLASH_ACE0_SIZE_S 0 -#define SYSCON_FLASH_ACE1_SIZE_REG (DR_REG_SYSCON_BASE + 0x04C) +#define SYSCON_FLASH_ACE1_SIZE_REG (DR_REG_SYSCON_BASE + 0x4C) /* SYSCON_FLASH_ACE1_SIZE : R/W ;bitpos:[15:0] ;default: 16'h1000 ; */ -/*description: */ -#define SYSCON_FLASH_ACE1_SIZE 0x0000FFFF +/*description: .*/ +#define SYSCON_FLASH_ACE1_SIZE 0x0000FFFF #define SYSCON_FLASH_ACE1_SIZE_M ((SYSCON_FLASH_ACE1_SIZE_V)<<(SYSCON_FLASH_ACE1_SIZE_S)) #define SYSCON_FLASH_ACE1_SIZE_V 0xFFFF #define SYSCON_FLASH_ACE1_SIZE_S 0 -#define SYSCON_FLASH_ACE2_SIZE_REG (DR_REG_SYSCON_BASE + 0x050) +#define SYSCON_FLASH_ACE2_SIZE_REG (DR_REG_SYSCON_BASE + 0x50) /* SYSCON_FLASH_ACE2_SIZE : R/W ;bitpos:[15:0] ;default: 16'h1000 ; */ -/*description: */ -#define SYSCON_FLASH_ACE2_SIZE 0x0000FFFF +/*description: .*/ +#define SYSCON_FLASH_ACE2_SIZE 0x0000FFFF #define SYSCON_FLASH_ACE2_SIZE_M ((SYSCON_FLASH_ACE2_SIZE_V)<<(SYSCON_FLASH_ACE2_SIZE_S)) #define SYSCON_FLASH_ACE2_SIZE_V 0xFFFF #define SYSCON_FLASH_ACE2_SIZE_S 0 -#define SYSCON_FLASH_ACE3_SIZE_REG (DR_REG_SYSCON_BASE + 0x054) +#define SYSCON_FLASH_ACE3_SIZE_REG (DR_REG_SYSCON_BASE + 0x54) /* SYSCON_FLASH_ACE3_SIZE : R/W ;bitpos:[15:0] ;default: 16'h1000 ; */ -/*description: */ -#define SYSCON_FLASH_ACE3_SIZE 0x0000FFFF +/*description: .*/ +#define SYSCON_FLASH_ACE3_SIZE 0x0000FFFF #define SYSCON_FLASH_ACE3_SIZE_M ((SYSCON_FLASH_ACE3_SIZE_V)<<(SYSCON_FLASH_ACE3_SIZE_S)) #define SYSCON_FLASH_ACE3_SIZE_V 0xFFFF #define SYSCON_FLASH_ACE3_SIZE_S 0 -#define SYSCON_SRAM_ACE0_ATTR_REG (DR_REG_SYSCON_BASE + 0x058) +#define SYSCON_SRAM_ACE0_ATTR_REG (DR_REG_SYSCON_BASE + 0x58) /* SYSCON_SRAM_ACE0_ATTR : R/W ;bitpos:[8:0] ;default: 9'hff ; */ -/*description: */ -#define SYSCON_SRAM_ACE0_ATTR 0x000001FF +/*description: .*/ +#define SYSCON_SRAM_ACE0_ATTR 0x000001FF #define SYSCON_SRAM_ACE0_ATTR_M ((SYSCON_SRAM_ACE0_ATTR_V)<<(SYSCON_SRAM_ACE0_ATTR_S)) #define SYSCON_SRAM_ACE0_ATTR_V 0x1FF #define SYSCON_SRAM_ACE0_ATTR_S 0 -#define SYSCON_SRAM_ACE1_ATTR_REG (DR_REG_SYSCON_BASE + 0x05C) +#define SYSCON_SRAM_ACE1_ATTR_REG (DR_REG_SYSCON_BASE + 0x5C) /* SYSCON_SRAM_ACE1_ATTR : R/W ;bitpos:[8:0] ;default: 9'hff ; */ -/*description: */ -#define SYSCON_SRAM_ACE1_ATTR 0x000001FF +/*description: .*/ +#define SYSCON_SRAM_ACE1_ATTR 0x000001FF #define SYSCON_SRAM_ACE1_ATTR_M ((SYSCON_SRAM_ACE1_ATTR_V)<<(SYSCON_SRAM_ACE1_ATTR_S)) #define SYSCON_SRAM_ACE1_ATTR_V 0x1FF #define SYSCON_SRAM_ACE1_ATTR_S 0 -#define SYSCON_SRAM_ACE2_ATTR_REG (DR_REG_SYSCON_BASE + 0x060) +#define SYSCON_SRAM_ACE2_ATTR_REG (DR_REG_SYSCON_BASE + 0x60) /* SYSCON_SRAM_ACE2_ATTR : R/W ;bitpos:[8:0] ;default: 9'hff ; */ -/*description: */ -#define SYSCON_SRAM_ACE2_ATTR 0x000001FF +/*description: .*/ +#define SYSCON_SRAM_ACE2_ATTR 0x000001FF #define SYSCON_SRAM_ACE2_ATTR_M ((SYSCON_SRAM_ACE2_ATTR_V)<<(SYSCON_SRAM_ACE2_ATTR_S)) #define SYSCON_SRAM_ACE2_ATTR_V 0x1FF #define SYSCON_SRAM_ACE2_ATTR_S 0 -#define SYSCON_SRAM_ACE3_ATTR_REG (DR_REG_SYSCON_BASE + 0x064) +#define SYSCON_SRAM_ACE3_ATTR_REG (DR_REG_SYSCON_BASE + 0x64) /* SYSCON_SRAM_ACE3_ATTR : R/W ;bitpos:[8:0] ;default: 9'hff ; */ -/*description: */ -#define SYSCON_SRAM_ACE3_ATTR 0x000001FF +/*description: .*/ +#define SYSCON_SRAM_ACE3_ATTR 0x000001FF #define SYSCON_SRAM_ACE3_ATTR_M ((SYSCON_SRAM_ACE3_ATTR_V)<<(SYSCON_SRAM_ACE3_ATTR_S)) #define SYSCON_SRAM_ACE3_ATTR_V 0x1FF #define SYSCON_SRAM_ACE3_ATTR_S 0 -#define SYSCON_SRAM_ACE0_ADDR_REG (DR_REG_SYSCON_BASE + 0x068) +#define SYSCON_SRAM_ACE0_ADDR_REG (DR_REG_SYSCON_BASE + 0x68) /* SYSCON_SRAM_ACE0_ADDR_S : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define SYSCON_SRAM_ACE0_ADDR_S 0xFFFFFFFF +/*description: .*/ +#define SYSCON_SRAM_ACE0_ADDR_S 0xFFFFFFFF #define SYSCON_SRAM_ACE0_ADDR_S_M ((SYSCON_SRAM_ACE0_ADDR_S_V)<<(SYSCON_SRAM_ACE0_ADDR_S_S)) #define SYSCON_SRAM_ACE0_ADDR_S_V 0xFFFFFFFF #define SYSCON_SRAM_ACE0_ADDR_S_S 0 -#define SYSCON_SRAM_ACE1_ADDR_REG (DR_REG_SYSCON_BASE + 0x06C) +#define SYSCON_SRAM_ACE1_ADDR_REG (DR_REG_SYSCON_BASE + 0x6C) /* SYSCON_SRAM_ACE1_ADDR_S : R/W ;bitpos:[31:0] ;default: 32'h10000000 ; */ -/*description: */ -#define SYSCON_SRAM_ACE1_ADDR_S 0xFFFFFFFF +/*description: .*/ +#define SYSCON_SRAM_ACE1_ADDR_S 0xFFFFFFFF #define SYSCON_SRAM_ACE1_ADDR_S_M ((SYSCON_SRAM_ACE1_ADDR_S_V)<<(SYSCON_SRAM_ACE1_ADDR_S_S)) #define SYSCON_SRAM_ACE1_ADDR_S_V 0xFFFFFFFF #define SYSCON_SRAM_ACE1_ADDR_S_S 0 -#define SYSCON_SRAM_ACE2_ADDR_REG (DR_REG_SYSCON_BASE + 0x070) +#define SYSCON_SRAM_ACE2_ADDR_REG (DR_REG_SYSCON_BASE + 0x70) /* SYSCON_SRAM_ACE2_ADDR_S : R/W ;bitpos:[31:0] ;default: 32'h20000000 ; */ -/*description: */ -#define SYSCON_SRAM_ACE2_ADDR_S 0xFFFFFFFF +/*description: .*/ +#define SYSCON_SRAM_ACE2_ADDR_S 0xFFFFFFFF #define SYSCON_SRAM_ACE2_ADDR_S_M ((SYSCON_SRAM_ACE2_ADDR_S_V)<<(SYSCON_SRAM_ACE2_ADDR_S_S)) #define SYSCON_SRAM_ACE2_ADDR_S_V 0xFFFFFFFF #define SYSCON_SRAM_ACE2_ADDR_S_S 0 -#define SYSCON_SRAM_ACE3_ADDR_REG (DR_REG_SYSCON_BASE + 0x074) +#define SYSCON_SRAM_ACE3_ADDR_REG (DR_REG_SYSCON_BASE + 0x74) /* SYSCON_SRAM_ACE3_ADDR_S : R/W ;bitpos:[31:0] ;default: 32'h30000000 ; */ -/*description: */ -#define SYSCON_SRAM_ACE3_ADDR_S 0xFFFFFFFF +/*description: .*/ +#define SYSCON_SRAM_ACE3_ADDR_S 0xFFFFFFFF #define SYSCON_SRAM_ACE3_ADDR_S_M ((SYSCON_SRAM_ACE3_ADDR_S_V)<<(SYSCON_SRAM_ACE3_ADDR_S_S)) #define SYSCON_SRAM_ACE3_ADDR_S_V 0xFFFFFFFF #define SYSCON_SRAM_ACE3_ADDR_S_S 0 -#define SYSCON_SRAM_ACE0_SIZE_REG (DR_REG_SYSCON_BASE + 0x078) +#define SYSCON_SRAM_ACE0_SIZE_REG (DR_REG_SYSCON_BASE + 0x78) /* SYSCON_SRAM_ACE0_SIZE : R/W ;bitpos:[15:0] ;default: 16'h1000 ; */ -/*description: */ -#define SYSCON_SRAM_ACE0_SIZE 0x0000FFFF +/*description: .*/ +#define SYSCON_SRAM_ACE0_SIZE 0x0000FFFF #define SYSCON_SRAM_ACE0_SIZE_M ((SYSCON_SRAM_ACE0_SIZE_V)<<(SYSCON_SRAM_ACE0_SIZE_S)) #define SYSCON_SRAM_ACE0_SIZE_V 0xFFFF #define SYSCON_SRAM_ACE0_SIZE_S 0 -#define SYSCON_SRAM_ACE1_SIZE_REG (DR_REG_SYSCON_BASE + 0x07C) +#define SYSCON_SRAM_ACE1_SIZE_REG (DR_REG_SYSCON_BASE + 0x7C) /* SYSCON_SRAM_ACE1_SIZE : R/W ;bitpos:[15:0] ;default: 16'h1000 ; */ -/*description: */ -#define SYSCON_SRAM_ACE1_SIZE 0x0000FFFF +/*description: .*/ +#define SYSCON_SRAM_ACE1_SIZE 0x0000FFFF #define SYSCON_SRAM_ACE1_SIZE_M ((SYSCON_SRAM_ACE1_SIZE_V)<<(SYSCON_SRAM_ACE1_SIZE_S)) #define SYSCON_SRAM_ACE1_SIZE_V 0xFFFF #define SYSCON_SRAM_ACE1_SIZE_S 0 -#define SYSCON_SRAM_ACE2_SIZE_REG (DR_REG_SYSCON_BASE + 0x080) +#define SYSCON_SRAM_ACE2_SIZE_REG (DR_REG_SYSCON_BASE + 0x80) /* SYSCON_SRAM_ACE2_SIZE : R/W ;bitpos:[15:0] ;default: 16'h1000 ; */ -/*description: */ -#define SYSCON_SRAM_ACE2_SIZE 0x0000FFFF +/*description: .*/ +#define SYSCON_SRAM_ACE2_SIZE 0x0000FFFF #define SYSCON_SRAM_ACE2_SIZE_M ((SYSCON_SRAM_ACE2_SIZE_V)<<(SYSCON_SRAM_ACE2_SIZE_S)) #define SYSCON_SRAM_ACE2_SIZE_V 0xFFFF #define SYSCON_SRAM_ACE2_SIZE_S 0 -#define SYSCON_SRAM_ACE3_SIZE_REG (DR_REG_SYSCON_BASE + 0x084) +#define SYSCON_SRAM_ACE3_SIZE_REG (DR_REG_SYSCON_BASE + 0x84) /* SYSCON_SRAM_ACE3_SIZE : R/W ;bitpos:[15:0] ;default: 16'h1000 ; */ -/*description: */ -#define SYSCON_SRAM_ACE3_SIZE 0x0000FFFF +/*description: .*/ +#define SYSCON_SRAM_ACE3_SIZE 0x0000FFFF #define SYSCON_SRAM_ACE3_SIZE_M ((SYSCON_SRAM_ACE3_SIZE_V)<<(SYSCON_SRAM_ACE3_SIZE_S)) #define SYSCON_SRAM_ACE3_SIZE_V 0xFFFF #define SYSCON_SRAM_ACE3_SIZE_S 0 -#define SYSCON_SPI_MEM_PMS_CTRL_REG (DR_REG_SYSCON_BASE + 0x088) +#define SYSCON_SPI_MEM_PMS_CTRL_REG (DR_REG_SYSCON_BASE + 0x88) /* SYSCON_SPI_MEM_REJECT_CDE : RO ;bitpos:[6:2] ;default: 5'h0 ; */ -/*description: */ -#define SYSCON_SPI_MEM_REJECT_CDE 0x0000001F +/*description: .*/ +#define SYSCON_SPI_MEM_REJECT_CDE 0x0000001F #define SYSCON_SPI_MEM_REJECT_CDE_M ((SYSCON_SPI_MEM_REJECT_CDE_V)<<(SYSCON_SPI_MEM_REJECT_CDE_S)) #define SYSCON_SPI_MEM_REJECT_CDE_V 0x1F #define SYSCON_SPI_MEM_REJECT_CDE_S 2 /* SYSCON_SPI_MEM_REJECT_CLR : WOD ;bitpos:[1] ;default: 1'b0 ; */ -/*description: */ -#define SYSCON_SPI_MEM_REJECT_CLR (BIT(1)) +/*description: .*/ +#define SYSCON_SPI_MEM_REJECT_CLR (BIT(1)) #define SYSCON_SPI_MEM_REJECT_CLR_M (BIT(1)) #define SYSCON_SPI_MEM_REJECT_CLR_V 0x1 #define SYSCON_SPI_MEM_REJECT_CLR_S 1 /* SYSCON_SPI_MEM_REJECT_INT : RO ;bitpos:[0] ;default: 1'b0 ; */ -/*description: */ -#define SYSCON_SPI_MEM_REJECT_INT (BIT(0)) +/*description: .*/ +#define SYSCON_SPI_MEM_REJECT_INT (BIT(0)) #define SYSCON_SPI_MEM_REJECT_INT_M (BIT(0)) #define SYSCON_SPI_MEM_REJECT_INT_V 0x1 #define SYSCON_SPI_MEM_REJECT_INT_S 0 -#define SYSCON_SPI_MEM_REJECT_ADDR_REG (DR_REG_SYSCON_BASE + 0x08C) +#define SYSCON_SPI_MEM_REJECT_ADDR_REG (DR_REG_SYSCON_BASE + 0x8C) /* SYSCON_SPI_MEM_REJECT_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ -/*description: */ -#define SYSCON_SPI_MEM_REJECT_ADDR 0xFFFFFFFF +/*description: .*/ +#define SYSCON_SPI_MEM_REJECT_ADDR 0xFFFFFFFF #define SYSCON_SPI_MEM_REJECT_ADDR_M ((SYSCON_SPI_MEM_REJECT_ADDR_V)<<(SYSCON_SPI_MEM_REJECT_ADDR_S)) #define SYSCON_SPI_MEM_REJECT_ADDR_V 0xFFFFFFFF #define SYSCON_SPI_MEM_REJECT_ADDR_S 0 -#define SYSCON_SDIO_CTRL_REG (DR_REG_SYSCON_BASE + 0x090) +#define SYSCON_SDIO_CTRL_REG (DR_REG_SYSCON_BASE + 0x90) /* SYSCON_SDIO_WIN_ACCESS_EN : R/W ;bitpos:[0] ;default: 1'h0 ; */ -/*description: */ -#define SYSCON_SDIO_WIN_ACCESS_EN (BIT(0)) +/*description: .*/ +#define SYSCON_SDIO_WIN_ACCESS_EN (BIT(0)) #define SYSCON_SDIO_WIN_ACCESS_EN_M (BIT(0)) #define SYSCON_SDIO_WIN_ACCESS_EN_V 0x1 #define SYSCON_SDIO_WIN_ACCESS_EN_S 0 -#define SYSCON_REDCY_SIG0_REG (DR_REG_SYSCON_BASE + 0x094) +#define SYSCON_REDCY_SIG0_REG (DR_REG_SYSCON_BASE + 0x94) /* SYSCON_REDCY_ANDOR : RO ;bitpos:[31] ;default: 1'h0 ; */ -/*description: */ -#define SYSCON_REDCY_ANDOR (BIT(31)) +/*description: .*/ +#define SYSCON_REDCY_ANDOR (BIT(31)) #define SYSCON_REDCY_ANDOR_M (BIT(31)) #define SYSCON_REDCY_ANDOR_V 0x1 #define SYSCON_REDCY_ANDOR_S 31 /* SYSCON_REDCY_SIG0 : R/W ;bitpos:[30:0] ;default: 31'h0 ; */ -/*description: */ -#define SYSCON_REDCY_SIG0 0x7FFFFFFF +/*description: .*/ +#define SYSCON_REDCY_SIG0 0x7FFFFFFF #define SYSCON_REDCY_SIG0_M ((SYSCON_REDCY_SIG0_V)<<(SYSCON_REDCY_SIG0_S)) #define SYSCON_REDCY_SIG0_V 0x7FFFFFFF #define SYSCON_REDCY_SIG0_S 0 -#define SYSCON_REDCY_SIG1_REG (DR_REG_SYSCON_BASE + 0x098) +#define SYSCON_REDCY_SIG1_REG (DR_REG_SYSCON_BASE + 0x98) /* SYSCON_REDCY_NANDOR : RO ;bitpos:[31] ;default: 1'h0 ; */ -/*description: */ -#define SYSCON_REDCY_NANDOR (BIT(31)) +/*description: .*/ +#define SYSCON_REDCY_NANDOR (BIT(31)) #define SYSCON_REDCY_NANDOR_M (BIT(31)) #define SYSCON_REDCY_NANDOR_V 0x1 #define SYSCON_REDCY_NANDOR_S 31 /* SYSCON_REDCY_SIG1 : R/W ;bitpos:[30:0] ;default: 31'h0 ; */ -/*description: */ -#define SYSCON_REDCY_SIG1 0x7FFFFFFF +/*description: .*/ +#define SYSCON_REDCY_SIG1 0x7FFFFFFF #define SYSCON_REDCY_SIG1_M ((SYSCON_REDCY_SIG1_V)<<(SYSCON_REDCY_SIG1_S)) #define SYSCON_REDCY_SIG1_V 0x7FFFFFFF #define SYSCON_REDCY_SIG1_S 0 -#define SYSCON_FRONT_END_MEM_PD_REG (DR_REG_SYSCON_BASE + 0x09C) +#define SYSCON_FRONT_END_MEM_PD_REG (DR_REG_SYSCON_BASE + 0x9C) /* SYSCON_FREQ_MEM_FORCE_PD : R/W ;bitpos:[7] ;default: 1'b0 ; */ -/*description: */ -#define SYSCON_FREQ_MEM_FORCE_PD (BIT(7)) +/*description: .*/ +#define SYSCON_FREQ_MEM_FORCE_PD (BIT(7)) #define SYSCON_FREQ_MEM_FORCE_PD_M (BIT(7)) #define SYSCON_FREQ_MEM_FORCE_PD_V 0x1 #define SYSCON_FREQ_MEM_FORCE_PD_S 7 /* SYSCON_FREQ_MEM_FORCE_PU : R/W ;bitpos:[6] ;default: 1'b1 ; */ -/*description: */ -#define SYSCON_FREQ_MEM_FORCE_PU (BIT(6)) +/*description: .*/ +#define SYSCON_FREQ_MEM_FORCE_PU (BIT(6)) #define SYSCON_FREQ_MEM_FORCE_PU_M (BIT(6)) #define SYSCON_FREQ_MEM_FORCE_PU_V 0x1 #define SYSCON_FREQ_MEM_FORCE_PU_S 6 /* SYSCON_DC_MEM_FORCE_PD : R/W ;bitpos:[5] ;default: 1'b0 ; */ -/*description: */ -#define SYSCON_DC_MEM_FORCE_PD (BIT(5)) +/*description: .*/ +#define SYSCON_DC_MEM_FORCE_PD (BIT(5)) #define SYSCON_DC_MEM_FORCE_PD_M (BIT(5)) #define SYSCON_DC_MEM_FORCE_PD_V 0x1 #define SYSCON_DC_MEM_FORCE_PD_S 5 /* SYSCON_DC_MEM_FORCE_PU : R/W ;bitpos:[4] ;default: 1'b1 ; */ -/*description: */ -#define SYSCON_DC_MEM_FORCE_PU (BIT(4)) +/*description: .*/ +#define SYSCON_DC_MEM_FORCE_PU (BIT(4)) #define SYSCON_DC_MEM_FORCE_PU_M (BIT(4)) #define SYSCON_DC_MEM_FORCE_PU_V 0x1 #define SYSCON_DC_MEM_FORCE_PU_S 4 /* SYSCON_PBUS_MEM_FORCE_PD : R/W ;bitpos:[3] ;default: 1'b0 ; */ -/*description: */ -#define SYSCON_PBUS_MEM_FORCE_PD (BIT(3)) +/*description: .*/ +#define SYSCON_PBUS_MEM_FORCE_PD (BIT(3)) #define SYSCON_PBUS_MEM_FORCE_PD_M (BIT(3)) #define SYSCON_PBUS_MEM_FORCE_PD_V 0x1 #define SYSCON_PBUS_MEM_FORCE_PD_S 3 /* SYSCON_PBUS_MEM_FORCE_PU : R/W ;bitpos:[2] ;default: 1'b1 ; */ -/*description: */ -#define SYSCON_PBUS_MEM_FORCE_PU (BIT(2)) +/*description: .*/ +#define SYSCON_PBUS_MEM_FORCE_PU (BIT(2)) #define SYSCON_PBUS_MEM_FORCE_PU_M (BIT(2)) #define SYSCON_PBUS_MEM_FORCE_PU_V 0x1 #define SYSCON_PBUS_MEM_FORCE_PU_S 2 /* SYSCON_AGC_MEM_FORCE_PD : R/W ;bitpos:[1] ;default: 1'b0 ; */ -/*description: */ -#define SYSCON_AGC_MEM_FORCE_PD (BIT(1)) +/*description: .*/ +#define SYSCON_AGC_MEM_FORCE_PD (BIT(1)) #define SYSCON_AGC_MEM_FORCE_PD_M (BIT(1)) #define SYSCON_AGC_MEM_FORCE_PD_V 0x1 #define SYSCON_AGC_MEM_FORCE_PD_S 1 /* SYSCON_AGC_MEM_FORCE_PU : R/W ;bitpos:[0] ;default: 1'b1 ; */ -/*description: */ -#define SYSCON_AGC_MEM_FORCE_PU (BIT(0)) +/*description: .*/ +#define SYSCON_AGC_MEM_FORCE_PU (BIT(0)) #define SYSCON_AGC_MEM_FORCE_PU_M (BIT(0)) #define SYSCON_AGC_MEM_FORCE_PU_V 0x1 #define SYSCON_AGC_MEM_FORCE_PU_S 0 -#define SYSCON_SPI_MEM_ECC_CTRL_REG (DR_REG_SYSCON_BASE + 0x0A0) +#define SYSCON_SPI_MEM_ECC_CTRL_REG (DR_REG_SYSCON_BASE + 0xA0) /* SYSCON_SRAM_PAGE_SIZE : R/W ;bitpos:[21:20] ;default: 2'd2 ; */ -/*description: Set the page size of the used MSPI external RAM. 0: 256 bytes. - 1: 512 bytes. 2: 1024 bytes. 3: 2048 bytes.*/ -#define SYSCON_SRAM_PAGE_SIZE 0x00000003 +/*description: Set the page size of the used MSPI external RAM. 0: 256 bytes. 1: 512 bytes. 2: +1024 bytes. 3: 2048 bytes..*/ +#define SYSCON_SRAM_PAGE_SIZE 0x00000003 #define SYSCON_SRAM_PAGE_SIZE_M ((SYSCON_SRAM_PAGE_SIZE_V)<<(SYSCON_SRAM_PAGE_SIZE_S)) #define SYSCON_SRAM_PAGE_SIZE_V 0x3 #define SYSCON_SRAM_PAGE_SIZE_S 20 /* SYSCON_FLASH_PAGE_SIZE : R/W ;bitpos:[19:18] ;default: 2'd0 ; */ -/*description: Set the page size of the used MSPI flash. 0: 256 bytes. 1: 512 - bytes. 2: 1024 bytes. 3: 2048 bytes.*/ -#define SYSCON_FLASH_PAGE_SIZE 0x00000003 +/*description: Set the page size of the used MSPI flash. 0: 256 bytes. 1: 512 bytes. 2: 1024 by +tes. 3: 2048 bytes..*/ +#define SYSCON_FLASH_PAGE_SIZE 0x00000003 #define SYSCON_FLASH_PAGE_SIZE_M ((SYSCON_FLASH_PAGE_SIZE_V)<<(SYSCON_FLASH_PAGE_SIZE_S)) #define SYSCON_FLASH_PAGE_SIZE_V 0x3 #define SYSCON_FLASH_PAGE_SIZE_S 18 -#define SYSCON_CLKGATE_FORCE_ON_REG (DR_REG_SYSCON_BASE + 0x0A8) +#define SYSCON_CLKGATE_FORCE_ON_REG (DR_REG_SYSCON_BASE + 0xA8) /* SYSCON_SRAM_CLKGATE_FORCE_ON : R/W ;bitpos:[13:3] ;default: ~11'b0 ; */ -/*description: */ -#define SYSCON_SRAM_CLKGATE_FORCE_ON 0x000007FF +/*description: .*/ +#define SYSCON_SRAM_CLKGATE_FORCE_ON 0x000007FF #define SYSCON_SRAM_CLKGATE_FORCE_ON_M ((SYSCON_SRAM_CLKGATE_FORCE_ON_V)<<(SYSCON_SRAM_CLKGATE_FORCE_ON_S)) #define SYSCON_SRAM_CLKGATE_FORCE_ON_V 0x7FF #define SYSCON_SRAM_CLKGATE_FORCE_ON_S 3 /* SYSCON_ROM_CLKGATE_FORCE_ON : R/W ;bitpos:[2:0] ;default: ~3'b0 ; */ -/*description: */ -#define SYSCON_ROM_CLKGATE_FORCE_ON 0x00000007 +/*description: .*/ +#define SYSCON_ROM_CLKGATE_FORCE_ON 0x00000007 #define SYSCON_ROM_CLKGATE_FORCE_ON_M ((SYSCON_ROM_CLKGATE_FORCE_ON_V)<<(SYSCON_ROM_CLKGATE_FORCE_ON_S)) #define SYSCON_ROM_CLKGATE_FORCE_ON_V 0x7 #define SYSCON_ROM_CLKGATE_FORCE_ON_S 0 -#define SYSCON_MEM_POWER_DOWN_REG (DR_REG_SYSCON_BASE + 0x0AC) +#define SYSCON_MEM_POWER_DOWN_REG (DR_REG_SYSCON_BASE + 0xAC) /* SYSCON_SRAM_POWER_DOWN : R/W ;bitpos:[13:3] ;default: 11'b0 ; */ -/*description: */ -#define SYSCON_SRAM_POWER_DOWN 0x000007FF +/*description: .*/ +#define SYSCON_SRAM_POWER_DOWN 0x000007FF #define SYSCON_SRAM_POWER_DOWN_M ((SYSCON_SRAM_POWER_DOWN_V)<<(SYSCON_SRAM_POWER_DOWN_S)) #define SYSCON_SRAM_POWER_DOWN_V 0x7FF #define SYSCON_SRAM_POWER_DOWN_S 3 /* SYSCON_ROM_POWER_DOWN : R/W ;bitpos:[2:0] ;default: 3'b0 ; */ -/*description: */ -#define SYSCON_ROM_POWER_DOWN 0x00000007 +/*description: .*/ +#define SYSCON_ROM_POWER_DOWN 0x00000007 #define SYSCON_ROM_POWER_DOWN_M ((SYSCON_ROM_POWER_DOWN_V)<<(SYSCON_ROM_POWER_DOWN_S)) #define SYSCON_ROM_POWER_DOWN_V 0x7 #define SYSCON_ROM_POWER_DOWN_S 0 -#define SYSCON_MEM_POWER_UP_REG (DR_REG_SYSCON_BASE + 0x0B0) +#define SYSCON_MEM_POWER_UP_REG (DR_REG_SYSCON_BASE + 0xB0) /* SYSCON_SRAM_POWER_UP : R/W ;bitpos:[13:3] ;default: ~11'b0 ; */ -/*description: */ -#define SYSCON_SRAM_POWER_UP 0x000007FF +/*description: .*/ +#define SYSCON_SRAM_POWER_UP 0x000007FF #define SYSCON_SRAM_POWER_UP_M ((SYSCON_SRAM_POWER_UP_V)<<(SYSCON_SRAM_POWER_UP_S)) #define SYSCON_SRAM_POWER_UP_V 0x7FF #define SYSCON_SRAM_POWER_UP_S 3 /* SYSCON_ROM_POWER_UP : R/W ;bitpos:[2:0] ;default: ~3'b0 ; */ -/*description: */ -#define SYSCON_ROM_POWER_UP 0x00000007 +/*description: .*/ +#define SYSCON_ROM_POWER_UP 0x00000007 #define SYSCON_ROM_POWER_UP_M ((SYSCON_ROM_POWER_UP_V)<<(SYSCON_ROM_POWER_UP_S)) #define SYSCON_ROM_POWER_UP_V 0x7 #define SYSCON_ROM_POWER_UP_S 0 -#define SYSCON_RETENTION_CTRL_REG (DR_REG_SYSCON_BASE + 0x0B4) +#define SYSCON_RETENTION_CTRL_REG (DR_REG_SYSCON_BASE + 0xB4) /* SYSCON_NOBYPASS_CPU_ISO_RST : R/W ;bitpos:[27] ;default: 1'b0 ; */ -/*description: */ -#define SYSCON_NOBYPASS_CPU_ISO_RST (BIT(27)) +/*description: .*/ +#define SYSCON_NOBYPASS_CPU_ISO_RST (BIT(27)) #define SYSCON_NOBYPASS_CPU_ISO_RST_M (BIT(27)) #define SYSCON_NOBYPASS_CPU_ISO_RST_V 0x1 #define SYSCON_NOBYPASS_CPU_ISO_RST_S 27 /* SYSCON_RETENTION_CPU_LINK_ADDR : R/W ;bitpos:[26:0] ;default: 27'd0 ; */ -/*description: */ -#define SYSCON_RETENTION_CPU_LINK_ADDR 0x07FFFFFF +/*description: .*/ +#define SYSCON_RETENTION_CPU_LINK_ADDR 0x07FFFFFF #define SYSCON_RETENTION_CPU_LINK_ADDR_M ((SYSCON_RETENTION_CPU_LINK_ADDR_V)<<(SYSCON_RETENTION_CPU_LINK_ADDR_S)) #define SYSCON_RETENTION_CPU_LINK_ADDR_V 0x7FFFFFF #define SYSCON_RETENTION_CPU_LINK_ADDR_S 0 -#define SYSCON_RETENTION_CTRL1_REG (DR_REG_SYSCON_BASE + 0x0B8) +#define SYSCON_RETENTION_CTRL1_REG (DR_REG_SYSCON_BASE + 0xB8) /* SYSCON_RETENTION_TAG_LINK_ADDR : R/W ;bitpos:[26:0] ;default: 27'd0 ; */ -/*description: */ -#define SYSCON_RETENTION_TAG_LINK_ADDR 0x07FFFFFF +/*description: .*/ +#define SYSCON_RETENTION_TAG_LINK_ADDR 0x07FFFFFF #define SYSCON_RETENTION_TAG_LINK_ADDR_M ((SYSCON_RETENTION_TAG_LINK_ADDR_V)<<(SYSCON_RETENTION_TAG_LINK_ADDR_S)) #define SYSCON_RETENTION_TAG_LINK_ADDR_V 0x7FFFFFF #define SYSCON_RETENTION_TAG_LINK_ADDR_S 0 -#define SYSCON_RETENTION_CTRL2_REG (DR_REG_SYSCON_BASE + 0x0BC) +#define SYSCON_RETENTION_CTRL2_REG (DR_REG_SYSCON_BASE + 0xBC) /* SYSCON_RET_ICACHE_ENABLE : R/W ;bitpos:[31] ;default: 1'b0 ; */ -/*description: */ -#define SYSCON_RET_ICACHE_ENABLE (BIT(31)) +/*description: .*/ +#define SYSCON_RET_ICACHE_ENABLE (BIT(31)) #define SYSCON_RET_ICACHE_ENABLE_M (BIT(31)) #define SYSCON_RET_ICACHE_ENABLE_V 0x1 #define SYSCON_RET_ICACHE_ENABLE_S 31 /* SYSCON_RET_ICACHE_START_POINT : R/W ;bitpos:[29:22] ;default: 8'd0 ; */ -/*description: */ -#define SYSCON_RET_ICACHE_START_POINT 0x000000FF +/*description: .*/ +#define SYSCON_RET_ICACHE_START_POINT 0x000000FF #define SYSCON_RET_ICACHE_START_POINT_M ((SYSCON_RET_ICACHE_START_POINT_V)<<(SYSCON_RET_ICACHE_START_POINT_S)) #define SYSCON_RET_ICACHE_START_POINT_V 0xFF #define SYSCON_RET_ICACHE_START_POINT_S 22 /* SYSCON_RET_ICACHE_VLD_SIZE : R/W ;bitpos:[20:13] ;default: 8'hff ; */ -/*description: */ -#define SYSCON_RET_ICACHE_VLD_SIZE 0x000000FF +/*description: .*/ +#define SYSCON_RET_ICACHE_VLD_SIZE 0x000000FF #define SYSCON_RET_ICACHE_VLD_SIZE_M ((SYSCON_RET_ICACHE_VLD_SIZE_V)<<(SYSCON_RET_ICACHE_VLD_SIZE_S)) #define SYSCON_RET_ICACHE_VLD_SIZE_V 0xFF #define SYSCON_RET_ICACHE_VLD_SIZE_S 13 /* SYSCON_RET_ICACHE_SIZE : R/W ;bitpos:[11:4] ;default: 8'hff ; */ -/*description: */ -#define SYSCON_RET_ICACHE_SIZE 0x000000FF +/*description: .*/ +#define SYSCON_RET_ICACHE_SIZE 0x000000FF #define SYSCON_RET_ICACHE_SIZE_M ((SYSCON_RET_ICACHE_SIZE_V)<<(SYSCON_RET_ICACHE_SIZE_S)) #define SYSCON_RET_ICACHE_SIZE_V 0xFF #define SYSCON_RET_ICACHE_SIZE_S 4 -#define SYSCON_RETENTION_CTRL3_REG (DR_REG_SYSCON_BASE + 0x0C0) +#define SYSCON_RETENTION_CTRL3_REG (DR_REG_SYSCON_BASE + 0xC0) /* SYSCON_RET_DCACHE_ENABLE : R/W ;bitpos:[31] ;default: 1'b0 ; */ -/*description: */ -#define SYSCON_RET_DCACHE_ENABLE (BIT(31)) +/*description: .*/ +#define SYSCON_RET_DCACHE_ENABLE (BIT(31)) #define SYSCON_RET_DCACHE_ENABLE_M (BIT(31)) #define SYSCON_RET_DCACHE_ENABLE_V 0x1 #define SYSCON_RET_DCACHE_ENABLE_S 31 /* SYSCON_RET_DCACHE_START_POINT : R/W ;bitpos:[30:22] ;default: 9'd0 ; */ -/*description: */ -#define SYSCON_RET_DCACHE_START_POINT 0x000001FF +/*description: .*/ +#define SYSCON_RET_DCACHE_START_POINT 0x000001FF #define SYSCON_RET_DCACHE_START_POINT_M ((SYSCON_RET_DCACHE_START_POINT_V)<<(SYSCON_RET_DCACHE_START_POINT_S)) #define SYSCON_RET_DCACHE_START_POINT_V 0x1FF #define SYSCON_RET_DCACHE_START_POINT_S 22 /* SYSCON_RET_DCACHE_VLD_SIZE : R/W ;bitpos:[21:13] ;default: 9'h1ff ; */ -/*description: */ -#define SYSCON_RET_DCACHE_VLD_SIZE 0x000001FF +/*description: .*/ +#define SYSCON_RET_DCACHE_VLD_SIZE 0x000001FF #define SYSCON_RET_DCACHE_VLD_SIZE_M ((SYSCON_RET_DCACHE_VLD_SIZE_V)<<(SYSCON_RET_DCACHE_VLD_SIZE_S)) #define SYSCON_RET_DCACHE_VLD_SIZE_V 0x1FF #define SYSCON_RET_DCACHE_VLD_SIZE_S 13 /* SYSCON_RET_DCACHE_SIZE : R/W ;bitpos:[12:4] ;default: 9'h1ff ; */ -/*description: */ -#define SYSCON_RET_DCACHE_SIZE 0x000001FF +/*description: .*/ +#define SYSCON_RET_DCACHE_SIZE 0x000001FF #define SYSCON_RET_DCACHE_SIZE_M ((SYSCON_RET_DCACHE_SIZE_V)<<(SYSCON_RET_DCACHE_SIZE_S)) #define SYSCON_RET_DCACHE_SIZE_V 0x1FF #define SYSCON_RET_DCACHE_SIZE_S 4 +#define SYSCON_RETENTION_CTRL4_REG (DR_REG_SYSCON_BASE + 0xC4) +/* SYSCON_RETENTION_INV_CFG : R/W ;bitpos:[31:0] ;default: ~32'h0 ; */ +/*description: .*/ +#define SYSCON_RETENTION_INV_CFG 0xFFFFFFFF +#define SYSCON_RETENTION_INV_CFG_M ((SYSCON_RETENTION_INV_CFG_V)<<(SYSCON_RETENTION_INV_CFG_S)) +#define SYSCON_RETENTION_INV_CFG_V 0xFFFFFFFF +#define SYSCON_RETENTION_INV_CFG_S 0 + +#define SYSCON_RETENTION_CTRL5_REG (DR_REG_SYSCON_BASE + 0xC8) +/* SYSCON_RETENTION_DISABLE : R/W ;bitpos:[0] ;default: 1'b0 ; */ +/*description: .*/ +#define SYSCON_RETENTION_DISABLE (BIT(0)) +#define SYSCON_RETENTION_DISABLE_M (BIT(0)) +#define SYSCON_RETENTION_DISABLE_V 0x1 +#define SYSCON_RETENTION_DISABLE_S 0 + #define SYSCON_DATE_REG (DR_REG_SYSCON_BASE + 0x3FC) -/* SYSCON_DATE : R/W ;bitpos:[31:0] ;default: 32'h21010400 ; */ -/*description: Version control*/ -#define SYSCON_DATE 0xFFFFFFFF +/* SYSCON_DATE : R/W ;bitpos:[31:0] ;default: 32'h2101150 ; */ +/*description: Version control.*/ +#define SYSCON_DATE 0xFFFFFFFF #define SYSCON_DATE_M ((SYSCON_DATE_V)<<(SYSCON_DATE_S)) #define SYSCON_DATE_V 0xFFFFFFFF #define SYSCON_DATE_S 0 + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32s3/include/soc/syscon_struct.h b/components/soc/esp32s3/include/soc/syscon_struct.h index 6c32efe3d6..a392939e42 100644 --- a/components/soc/esp32s3/include/soc/syscon_struct.h +++ b/components/soc/esp32s3/include/soc/syscon_struct.h @@ -13,312 +13,320 @@ // limitations under the License. #ifndef _SOC_SYSCON_STRUCT_H_ #define _SOC_SYSCON_STRUCT_H_ + + #include #ifdef __cplusplus extern "C" { #endif -typedef volatile struct { +typedef volatile struct syscon_dev_s { union { struct { - uint32_t apb_ctrl_pre_div_cnt: 10; - uint32_t apb_ctrl_clk_320m_en: 1; - uint32_t clk_en: 1; - uint32_t apb_ctrl_rst_tick_cnt: 1; - uint32_t reserved13: 19; + uint32_t pre_div : 10; + uint32_t clk_320m_en : 1; + uint32_t clk_en : 1; + uint32_t rst_tick : 1; + uint32_t reserved13 : 19; }; uint32_t val; - } apb_ctrl_sysclk_conf; + } clk_conf; union { struct { - uint32_t apb_ctrl_xtal_tick_num: 8; - uint32_t apb_ctrl_ck8m_tick_num: 8; - uint32_t apb_ctrl_tick_enable: 1; - uint32_t reserved17: 15; + uint32_t xtal_tick : 8; + uint32_t ck8m_tick : 8; + uint32_t tick_enable : 1; + uint32_t reserved17 : 15; }; uint32_t val; - } apb_ctrl_tick_conf; + } tick_conf; union { struct { - uint32_t clk20_oen: 1; - uint32_t clk22_oen: 1; - uint32_t clk44_oen: 1; - uint32_t clk_bb_oen: 1; - uint32_t clk80_oen: 1; - uint32_t clk160_oen: 1; - uint32_t clk_320m_oen: 1; - uint32_t clk_adc_inf_oen: 1; - uint32_t clk_dac_cpu_oen: 1; - uint32_t clk40x_bb_oen: 1; - uint32_t clk_xtal_oen: 1; - uint32_t reserved11: 21; + uint32_t clk20_oen : 1; + uint32_t clk22_oen : 1; + uint32_t clk44_oen : 1; + uint32_t clk_bb_oen : 1; + uint32_t clk80_oen : 1; + uint32_t clk160_oen : 1; + uint32_t clk_320m_oen : 1; + uint32_t clk_adc_inf_oen : 1; + uint32_t clk_dac_cpu_oen : 1; + uint32_t clk40x_bb_oen : 1; + uint32_t clk_xtal_oen : 1; + uint32_t reserved11 : 21; }; uint32_t val; - } apb_ctrl_clk_out_en; - uint32_t wifi_bb_cfg; /**/ - uint32_t wifi_bb_cfg_2; /**/ - uint32_t wifi_clk_en; /**/ - uint32_t wifi_rst_en; /**/ + } clk_out_en; + uint32_t wifi_bb_cfg; + uint32_t wifi_bb_cfg_2; + uint32_t wifi_clk_en; + uint32_t wifi_rst_en; union { struct { - uint32_t peri_io_swap: 8; - uint32_t reserved8: 24; + uint32_t peri_io_swap : 8; + uint32_t reserved8 : 24; }; uint32_t val; } host_inf_sel; union { struct { - uint32_t ext_mem_pms_lock: 1; - uint32_t reserved1: 31; + uint32_t ext_mem_pms_lock : 1; + uint32_t reserved1 : 31; }; uint32_t val; } ext_mem_pms_lock; union { struct { - uint32_t writeback_bypass: 1; /*Set 1 to bypass cache writeback request to external memory so that spi will not check its attribute.*/ - uint32_t reserved1: 31; + uint32_t writeback_bypass : 1; /*Set 1 to bypass cache writeback request to external memory so that spi will not check its attribute.*/ + uint32_t reserved1 : 31; }; uint32_t val; } ext_mem_writeback_bypass; union { struct { - uint32_t flash_ace0_attr: 9; - uint32_t reserved9: 23; + uint32_t flash_ace0_attr : 9; + uint32_t reserved9 : 23; }; uint32_t val; } flash_ace0_attr; union { struct { - uint32_t flash_ace1_attr: 9; - uint32_t reserved9: 23; + uint32_t flash_ace1_attr : 9; + uint32_t reserved9 : 23; }; uint32_t val; } flash_ace1_attr; union { struct { - uint32_t flash_ace2_attr: 9; - uint32_t reserved9: 23; + uint32_t flash_ace2_attr : 9; + uint32_t reserved9 : 23; }; uint32_t val; } flash_ace2_attr; union { struct { - uint32_t flash_ace3_attr: 9; - uint32_t reserved9: 23; + uint32_t flash_ace3_attr : 9; + uint32_t reserved9 : 23; }; uint32_t val; } flash_ace3_attr; - uint32_t flash_ace0_addr; /**/ - uint32_t flash_ace1_addr; /**/ - uint32_t flash_ace2_addr; /**/ - uint32_t flash_ace3_addr; /**/ + uint32_t flash_ace0_addr; + uint32_t flash_ace1_addr; + uint32_t flash_ace2_addr; + uint32_t flash_ace3_addr; union { struct { - uint32_t flash_ace0_size:16; - uint32_t reserved16: 16; + uint32_t flash_ace0_size : 16; + uint32_t reserved16 : 16; }; uint32_t val; } flash_ace0_size; union { struct { - uint32_t flash_ace1_size:16; - uint32_t reserved16: 16; + uint32_t flash_ace1_size : 16; + uint32_t reserved16 : 16; }; uint32_t val; } flash_ace1_size; union { struct { - uint32_t flash_ace2_size:16; - uint32_t reserved16: 16; + uint32_t flash_ace2_size : 16; + uint32_t reserved16 : 16; }; uint32_t val; } flash_ace2_size; union { struct { - uint32_t flash_ace3_size:16; - uint32_t reserved16: 16; + uint32_t flash_ace3_size : 16; + uint32_t reserved16 : 16; }; uint32_t val; } flash_ace3_size; union { struct { - uint32_t sram_ace0_attr: 9; - uint32_t reserved9: 23; + uint32_t sram_ace0_attr : 9; + uint32_t reserved9 : 23; }; uint32_t val; } sram_ace0_attr; union { struct { - uint32_t sram_ace1_attr: 9; - uint32_t reserved9: 23; + uint32_t sram_ace1_attr : 9; + uint32_t reserved9 : 23; }; uint32_t val; } sram_ace1_attr; union { struct { - uint32_t sram_ace2_attr: 9; - uint32_t reserved9: 23; + uint32_t sram_ace2_attr : 9; + uint32_t reserved9 : 23; }; uint32_t val; } sram_ace2_attr; union { struct { - uint32_t sram_ace3_attr: 9; - uint32_t reserved9: 23; + uint32_t sram_ace3_attr : 9; + uint32_t reserved9 : 23; }; uint32_t val; } sram_ace3_attr; - uint32_t sram_ace0_addr; /**/ - uint32_t sram_ace1_addr; /**/ - uint32_t sram_ace2_addr; /**/ - uint32_t sram_ace3_addr; /**/ + uint32_t sram_ace0_addr; + uint32_t sram_ace1_addr; + uint32_t sram_ace2_addr; + uint32_t sram_ace3_addr; union { struct { - uint32_t sram_ace0_size:16; - uint32_t reserved16: 16; + uint32_t sram_ace0_size : 16; + uint32_t reserved16 : 16; }; uint32_t val; } sram_ace0_size; union { struct { - uint32_t sram_ace1_size:16; - uint32_t reserved16: 16; + uint32_t sram_ace1_size : 16; + uint32_t reserved16 : 16; }; uint32_t val; } sram_ace1_size; union { struct { - uint32_t sram_ace2_size:16; - uint32_t reserved16: 16; + uint32_t sram_ace2_size : 16; + uint32_t reserved16 : 16; }; uint32_t val; } sram_ace2_size; union { struct { - uint32_t sram_ace3_size:16; - uint32_t reserved16: 16; + uint32_t sram_ace3_size : 16; + uint32_t reserved16 : 16; }; uint32_t val; } sram_ace3_size; union { struct { - uint32_t spi_mem_reject_int: 1; - uint32_t spi_mem_reject_clr: 1; - uint32_t spi_mem_reject_cde: 5; - uint32_t reserved7: 25; + uint32_t spi_mem_reject_int : 1; + uint32_t spi_mem_reject_clr : 1; + uint32_t spi_mem_reject_cde : 5; + uint32_t reserved7 : 25; }; uint32_t val; } spi_mem_pms_ctrl; - uint32_t spi_mem_reject_addr; /**/ + uint32_t spi_mem_reject_addr; union { struct { - uint32_t sdio_win_access_en: 1; - uint32_t reserved1: 31; + uint32_t sdio_win_access_en : 1; + uint32_t reserved1 : 31; }; uint32_t val; - } apb_ctrl_sdio_ctrl; + } sdio_ctrl; union { struct { - uint32_t redcy_sig0: 31; - uint32_t redcy_andor: 1; + uint32_t redcy_sig0 : 31; + uint32_t redcy_andor : 1; }; uint32_t val; } redcy_sig0; union { struct { - uint32_t redcy_sig1: 31; - uint32_t redcy_nandor: 1; + uint32_t redcy_sig1 : 31; + uint32_t redcy_nandor : 1; }; uint32_t val; } redcy_sig1; union { struct { - uint32_t agc_mem_force_pu: 1; - uint32_t agc_mem_force_pd: 1; - uint32_t pbus_mem_force_pu: 1; - uint32_t pbus_mem_force_pd: 1; - uint32_t dc_mem_force_pu: 1; - uint32_t dc_mem_force_pd: 1; - uint32_t freq_mem_force_pu: 1; - uint32_t freq_mem_force_pd: 1; - uint32_t reserved8: 24; + uint32_t agc_mem_force_pu : 1; + uint32_t agc_mem_force_pd : 1; + uint32_t pbus_mem_force_pu : 1; + uint32_t pbus_mem_force_pd : 1; + uint32_t dc_mem_force_pu : 1; + uint32_t dc_mem_force_pd : 1; + uint32_t freq_mem_force_pu : 1; + uint32_t freq_mem_force_pd : 1; + uint32_t reserved8 : 24; }; uint32_t val; } front_end_mem_pd; union { struct { - uint32_t reserved0: 18; /*reserved*/ - uint32_t flash_page_size: 2; /*Set the page size of the used MSPI flash. 0: 256 bytes. 1: 512 bytes. 2: 1024 bytes. 3: 2048 bytes.*/ - uint32_t sram_page_size: 2; /*Set the page size of the used MSPI external RAM. 0: 256 bytes. 1: 512 bytes. 2: 1024 bytes. 3: 2048 bytes.*/ - uint32_t reserved22: 10; /*reserved*/ + uint32_t reserved0 : 18; /*reserved*/ + uint32_t flash_page_size : 2; /*Set the page size of the used MSPI flash. 0: 256 bytes. 1: 512 bytes. 2: 1024 bytes. 3: 2048 bytes.*/ + uint32_t sram_page_size : 2; /*Set the page size of the used MSPI external RAM. 0: 256 bytes. 1: 512 bytes. 2: 1024 bytes. 3: 2048 bytes.*/ + uint32_t reserved22 : 10; /*reserved*/ }; uint32_t val; } spi_mem_ecc_ctrl; uint32_t reserved_a4; union { struct { - uint32_t rom_clkgate_force_on: 3; - uint32_t sram_clkgate_force_on:11; - uint32_t reserved14: 18; + uint32_t rom_clkgate_force_on : 3; + uint32_t sram_clkgate_force_on : 11; + uint32_t reserved14 : 18; }; uint32_t val; } clkgate_force_on; union { struct { - uint32_t rom_power_down: 3; - uint32_t sram_power_down:11; - uint32_t reserved14: 18; + uint32_t rom_power_down : 3; + uint32_t sram_power_down : 11; + uint32_t reserved14 : 18; }; uint32_t val; } mem_power_down; union { struct { - uint32_t rom_power_up: 3; - uint32_t sram_power_up:11; - uint32_t reserved14: 18; + uint32_t rom_power_up : 3; + uint32_t sram_power_up : 11; + uint32_t reserved14 : 18; }; uint32_t val; } mem_power_up; union { struct { - uint32_t retention_cpu_link_addr:27; - uint32_t nobypass_cpu_iso_rst: 1; - uint32_t reserved28: 4; + uint32_t retention_cpu_link_addr : 27; + uint32_t nobypass_cpu_iso_rst : 1; + uint32_t reserved28 : 4; }; uint32_t val; } retention_ctrl; union { struct { - uint32_t retention_tag_link_addr:27; - uint32_t reserved27: 5; + uint32_t retention_tag_link_addr : 27; + uint32_t reserved27 : 5; }; uint32_t val; } retention_ctrl1; union { struct { - uint32_t reserved0: 4; - uint32_t ret_icache_size: 8; - uint32_t reserved12: 1; - uint32_t ret_icache_vld_size: 8; - uint32_t reserved21: 1; - uint32_t ret_icache_start_point: 8; - uint32_t reserved30: 1; - uint32_t ret_icache_enable: 1; + uint32_t reserved0 : 4; + uint32_t ret_icache_size : 8; + uint32_t reserved12 : 1; + uint32_t ret_icache_vld_size : 8; + uint32_t reserved21 : 1; + uint32_t ret_icache_start_point : 8; + uint32_t reserved30 : 1; + uint32_t ret_icache_enable : 1; }; uint32_t val; } retention_ctrl2; union { struct { - uint32_t reserved0: 4; - uint32_t ret_dcache_size: 9; - uint32_t ret_dcache_vld_size: 9; - uint32_t ret_dcache_start_point: 9; - uint32_t ret_dcache_enable: 1; + uint32_t reserved0 : 4; + uint32_t ret_dcache_size : 9; + uint32_t ret_dcache_vld_size : 9; + uint32_t ret_dcache_start_point : 9; + uint32_t ret_dcache_enable : 1; }; uint32_t val; } retention_ctrl3; - uint32_t reserved_c4; - uint32_t reserved_c8; + uint32_t retention_ctrl4; + union { + struct { + uint32_t retention_disable : 1; + uint32_t reserved1 : 31; + }; + uint32_t val; + } retention_ctrl5; uint32_t reserved_cc; uint32_t reserved_d0; uint32_t reserved_d4; @@ -523,11 +531,13 @@ typedef volatile struct { uint32_t reserved_3f0; uint32_t reserved_3f4; uint32_t reserved_3f8; - uint32_t apb_ctrl_date; /*Version control*/ + uint32_t date; } syscon_dev_t; extern syscon_dev_t SYSCON; #ifdef __cplusplus } #endif -#endif /* _SOC_SYSCON_STRUCT_H_ */ + + +#endif /*_SOC_SYSCON_STRUCT_H_ */ diff --git a/components/soc/esp32s3/include/soc/system_struct.h b/components/soc/esp32s3/include/soc/system_struct.h index d81146c9b0..6c4ce1f118 100644 --- a/components/soc/esp32s3/include/soc/system_struct.h +++ b/components/soc/esp32s3/include/soc/system_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct system_dev_s { union { struct { uint32_t control_core_1_runstall : 1; diff --git a/components/soc/esp32s3/include/soc/systimer_struct.h b/components/soc/esp32s3/include/soc/systimer_struct.h index 1d5c4a8c5f..115058c522 100644 --- a/components/soc/esp32s3/include/soc/systimer_struct.h +++ b/components/soc/esp32s3/include/soc/systimer_struct.h @@ -90,6 +90,7 @@ typedef union { * update timer_unit0 */ uint32_t timer_unit_update: 1; + uint32_t reserved_32: 1; }; uint32_t val; } systimer_unit_op_reg_t; @@ -104,6 +105,7 @@ typedef struct { * timer unit load high 32 bit */ uint32_t timer_unit_load_hi: 20; + uint32_t reserved_20: 12; }; uint32_t val; } hi; @@ -129,6 +131,7 @@ typedef struct { * timer target high 32 bit */ uint32_t timer_target_hi: 20; + uint32_t reserved_20: 12; }; uint32_t val; } hi; @@ -177,6 +180,7 @@ typedef struct { * timer read value high 20bit */ uint32_t timer_unit_value_hi: 20; + uint32_t reserved_20: 12; }; uint32_t val; } hi; @@ -201,6 +205,7 @@ typedef union { * timer comp load value */ uint32_t timer_comp_load: 1; + uint32_t reserved_1: 31; }; uint32_t val; } systimer_comp_load_reg_t; @@ -215,6 +220,7 @@ typedef union { * timer unit load value */ uint32_t timer_unit_load: 1; + uint32_t reserved_1: 31; }; uint32_t val; } systimer_unit_load_reg_t; @@ -238,6 +244,7 @@ typedef union { * interupt2 enable */ uint32_t target2_int_ena: 1; + uint32_t reserved_3: 29; }; uint32_t val; } systimer_int_ena_reg_t; @@ -259,6 +266,7 @@ typedef union { * interupt2 raw */ uint32_t target2_int_raw: 1; + uint32_t reserved_3: 29; }; uint32_t val; } systimer_int_raw_reg_t; @@ -280,6 +288,7 @@ typedef union { * interupt2 clear */ uint32_t target2_int_clr: 1; + uint32_t reserved_3: 29; }; uint32_t val; } systimer_int_clr_reg_t; @@ -301,6 +310,7 @@ typedef union { * interupt2 status */ uint32_t target2_int_st: 1; + uint32_t reserved_3: 29; }; uint32_t val; } systimer_int_st_reg_t; @@ -325,6 +335,7 @@ typedef struct { * actual target value value high 20bits */ uint32_t target_hi_ro: 20; + uint32_t reserved_20: 12; }; uint32_t val; } hi; diff --git a/components/soc/esp32s3/include/soc/twai_struct.h b/components/soc/esp32s3/include/soc/twai_struct.h index 19810eda15..df022feb47 100644 --- a/components/soc/esp32s3/include/soc/twai_struct.h +++ b/components/soc/esp32s3/include/soc/twai_struct.h @@ -23,7 +23,7 @@ extern "C" { /* ---------------------------- Register Layout ------------------------------ */ -/* The TWAI peripheral's registers are 8bits, however the ESP32 can only access +/* The TWAI peripheral's registers are 8bits, however the ESP32-S3 can only access * peripheral registers every 32bits. Therefore each TWAI register is mapped to * the least significant byte of every 32bits. */ @@ -36,10 +36,10 @@ typedef volatile struct twai_dev_s { uint32_t lom: 1; /* MOD.1 Listen Only Mode */ uint32_t stm: 1; /* MOD.2 Self Test Mode */ uint32_t afm: 1; /* MOD.3 Acceptance Filter Mode */ - uint32_t reserved28: 28; /* Internal Reserved. MOD.4 Sleep Mode not supported */ + uint32_t reserved4: 28; /* Internal Reserved. MOD.4 Sleep Mode not supported */ }; uint32_t val; - } mode_reg; /* Address 0 */ + } mode_reg; /* Address 0x0000 */ union { struct { uint32_t tr: 1; /* CMR.0 Transmission Request */ @@ -47,10 +47,10 @@ typedef volatile struct twai_dev_s { uint32_t rrb: 1; /* CMR.2 Release Receive Buffer */ uint32_t cdo: 1; /* CMR.3 Clear Data Overrun */ uint32_t srr: 1; /* CMR.4 Self Reception Request */ - uint32_t reserved27: 27; /* Internal Reserved */ + uint32_t reserved5: 27; /* Internal Reserved */ }; uint32_t val; - } command_reg; /* Address 1 */ + } command_reg; /* Address 0x0004 */ union { struct { uint32_t rbs: 1; /* SR.0 Receive Buffer Status */ @@ -62,97 +62,99 @@ typedef volatile struct twai_dev_s { uint32_t es: 1; /* SR.6 Error Status */ uint32_t bs: 1; /* SR.7 Bus Status */ uint32_t ms: 1; /* SR.8 Miss Status */ - uint32_t reserved24: 23; /* Internal Reserved */ + uint32_t reserved9: 23; /* Internal Reserved */ }; uint32_t val; - } status_reg; /* Address 2 */ + } status_reg; /* Address 0x0008 */ union { struct { uint32_t ri: 1; /* IR.0 Receive Interrupt */ uint32_t ti: 1; /* IR.1 Transmit Interrupt */ uint32_t ei: 1; /* IR.2 Error Interrupt */ - uint32_t reserved2: 2; /* Internal Reserved (Data Overrun interrupt and Wake-up not supported) */ + uint32_t doi: 1; /* IR.3 Data Overrun Interrupt */ + uint32_t reserved4: 1; /* Internal Reserved (Wake-up not supported) */ uint32_t epi: 1; /* IR.5 Error Passive Interrupt */ uint32_t ali: 1; /* IR.6 Arbitration Lost Interrupt */ uint32_t bei: 1; /* IR.7 Bus Error Interrupt */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } interrupt_reg; /* Address 3 */ + } interrupt_reg; /* Address 0x000C */ union { struct { uint32_t rie: 1; /* IER.0 Receive Interrupt Enable */ uint32_t tie: 1; /* IER.1 Transmit Interrupt Enable */ uint32_t eie: 1; /* IER.2 Error Interrupt Enable */ - uint32_t reserved2: 2; /* Internal Reserved (Data Overrun interrupt and Wake-up not supported) */ + uint32_t doie: 1; /* IER.3 Data Overrun Interrupt Enable */ + uint32_t reserved4: 1; /* Internal Reserved (Wake-up not supported) */ uint32_t epie: 1; /* IER.5 Error Passive Interrupt Enable */ uint32_t alie: 1; /* IER.6 Arbitration Lost Interrupt Enable */ uint32_t beie: 1; /* IER.7 Bus Error Interrupt Enable */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } interrupt_enable_reg; /* Address 4 */ - uint32_t reserved_05; /* Address 5 */ + } interrupt_enable_reg; /* Address 0x0010 */ + uint32_t reserved_14; union { struct { uint32_t brp: 13; /* BTR0[12:0] Baud Rate Prescaler */ - uint32_t reserved1: 1; /* Internal Reserved */ + uint32_t reserved13: 1; /* Internal Reserved */ uint32_t sjw: 2; /* BTR0[15:14] Synchronization Jump Width*/ uint32_t reserved16: 16; /* Internal Reserved */ }; uint32_t val; - } bus_timing_0_reg; /* Address 6 */ + } bus_timing_0_reg; /* Address 0x0018 */ union { struct { uint32_t tseg1: 4; /* BTR1[3:0] Timing Segment 1 */ uint32_t tseg2: 3; /* BTR1[6:4] Timing Segment 2 */ uint32_t sam: 1; /* BTR1.7 Sampling*/ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } bus_timing_1_reg; /* Address 7 */ - uint32_t reserved_08; /* Address 8 (Output control not supported) */ - uint32_t reserved_09; /* Address 9 (Test Register not supported) */ - uint32_t reserved_10; /* Address 10 */ + } bus_timing_1_reg; /* Address 0x001C */ + uint32_t reserved_20; /* Address 0x0020 (Output control not supported) */ + uint32_t reserved_24; /* Address 0x0024 (Test Register not supported) */ + uint32_t reserved_28; /* Address 0x0028 */ //Capture and Counter Registers union { struct { uint32_t alc: 5; /* ALC[4:0] Arbitration lost capture */ - uint32_t reserved27: 27; /* Internal Reserved */ + uint32_t reserved5: 27; /* Internal Reserved */ }; uint32_t val; - } arbitration_lost_captue_reg; /* Address 11 */ + } arbitration_lost_captue_reg; /* Address 0x002C */ union { struct { uint32_t seg: 5; /* ECC[4:0] Error Code Segment 0 to 5 */ uint32_t dir: 1; /* ECC.5 Error Direction (TX/RX) */ uint32_t errc: 2; /* ECC[7:6] Error Code */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } error_code_capture_reg; /* Address 12 */ + } error_code_capture_reg; /* Address 0x0030 */ union { struct { uint32_t ewl: 8; /* EWL[7:0] Error Warning Limit */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } error_warning_limit_reg; /* EWLR[7:0] Error Warning Limit: Address 13 */ + } error_warning_limit_reg; /* Address 0x0034 */ union { struct { uint32_t rxerr: 8; /* RXERR[7:0] Receive Error Counter */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } rx_error_counter_reg; /* Address 12 */ + } rx_error_counter_reg; /* Address 0x0038 */ union { struct { uint32_t txerr: 8; /* TXERR[7:0] Receive Error Counter */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; - } tx_error_counter_reg; /* Address 15 */ + } tx_error_counter_reg; /* Address 0x003C */ //Shared Registers (TX Buff/RX Buff/Acc Filter) union { @@ -160,45 +162,49 @@ typedef volatile struct twai_dev_s { union { struct { uint32_t byte: 8; /* ACRx[7:0] Acceptance Code */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; } acr[4]; union { struct { uint32_t byte: 8; /* AMRx[7:0] Acceptance Mask */ - uint32_t reserved24: 24; /* Internal Reserved */ + uint32_t reserved8: 24; /* Internal Reserved */ }; uint32_t val; } amr[4]; - uint32_t reserved32[5]; + uint32_t reserved_60; + uint32_t reserved_64; + uint32_t reserved_68; + uint32_t reserved_6c; + uint32_t reserved_70; } acceptance_filter; union { struct { - uint32_t byte: 8; - uint32_t reserved24: 24; + uint32_t byte: 8; /* TX/RX Byte X [7:0] */ + uint32_t reserved24: 24; /* Internal Reserved */ }; uint32_t val; } tx_rx_buffer[13]; - }; /* Address 16-28 TX/RX Buffer and Acc Filter*/; + }; /* Address 0x0040 - 0x0070 */ //Misc Registers union { struct { uint32_t rmc: 7; /* RMC[6:0] RX Message Counter */ - uint32_t reserved25: 25; /* Internal Reserved */ + uint32_t reserved7: 25; /* Internal Reserved */ }; uint32_t val; - } rx_message_counter_reg; /* Address 29 */ - uint32_t reserved_30; /* Address 30 (RX Buffer Start Address not supported) */ + } rx_message_counter_reg; /* Address 0x0074 */ + uint32_t reserved_78; /* Address 0x0078 (RX Buffer Start Address not supported) */ union { struct { uint32_t cd: 8; /* CDR[7:0] CLKOUT frequency selector based of fOSC */ uint32_t co: 1; /* CDR.8 CLKOUT enable/disable */ - uint32_t reserved24: 23; /* Internal Reserved */ + uint32_t reserved9: 23; /* Internal Reserved */ }; uint32_t val; - } clock_divider_reg; /* Address 31 */ + } clock_divider_reg; /* Address 0x007C */ } twai_dev_t; _Static_assert(sizeof(twai_dev_t) == 128, "TWAI registers should be 32 * 4 bytes"); diff --git a/components/soc/esp32s3/include/soc/uart_pins.h b/components/soc/esp32s3/include/soc/uart_pins.h new file mode 100644 index 0000000000..c2e9e24527 --- /dev/null +++ b/components/soc/esp32s3/include/soc/uart_pins.h @@ -0,0 +1,55 @@ +// Copyright 2015-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. + +#pragma once + +#include "soc/io_mux_reg.h" + +/* Specify the number of pins for UART */ +#define SOC_UART_PINS_COUNT (4) + +/* Specify the GPIO pin number for each UART signal in the IOMUX */ +#define U0RXD_GPIO_NUM 44 +#define U0TXD_GPIO_NUM 43 +#define U0CTS_GPIO_NUM 16 +#define U0RTS_GPIO_NUM 15 + +#define U1RXD_GPIO_NUM 18 +#define U1TXD_GPIO_NUM 17 +#define U1CTS_GPIO_NUM 20 +#define U1RTS_GPIO_NUM 19 + +#define U2RXD_GPIO_NUM (-1) +#define U2TXD_GPIO_NUM (-1) +#define U2CTS_GPIO_NUM (-1) +#define U2RTS_GPIO_NUM (-1) + +/* The following defines are necessary for reconfiguring the UART + * to use IOMUX, at runtime. */ +#define U0TXD_MUX_FUNC (FUNC_U0TXD_U0TXD) +#define U0RXD_MUX_FUNC (FUNC_U0RXD_U0RXD) +#define U0RTS_MUX_FUNC (FUNC_XTAL_32K_P_U0RTS) +#define U0CTS_MUX_FUNC (FUNC_XTAL_32K_N_U0CTS) + +#define U1TXD_MUX_FUNC (FUNC_DAC_1_U1TXD) +#define U1RXD_MUX_FUNC (FUNC_DAC_2_U1RXD) +#define U1RTS_MUX_FUNC (FUNC_GPIO19_U1RTS) +#define U1CTS_MUX_FUNC (FUNC_GPIO20_U1CTS) + +/* UART2 cannot be used directly through the IOMUX, these value + * shall not be used. */ +#define U2TXD_MUX_FUNC (-1) +#define U2RXD_MUX_FUNC (-1) +#define U2RTS_MUX_FUNC (-1) +#define U2CTS_MUX_FUNC (-1) diff --git a/components/soc/esp32s3/include/soc/uhci_struct.h b/components/soc/esp32s3/include/soc/uhci_struct.h index 2f7f2cee28..6fdd2cad1f 100644 --- a/components/soc/esp32s3/include/soc/uhci_struct.h +++ b/components/soc/esp32s3/include/soc/uhci_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct uhci_dev_s { union { struct { uint32_t tx_rst : 1; diff --git a/components/soc/esp32s3/include/soc/usb_serial_jtag_struct.h b/components/soc/esp32s3/include/soc/usb_serial_jtag_struct.h index cac2ddedac..539717f267 100644 --- a/components/soc/esp32s3/include/soc/usb_serial_jtag_struct.h +++ b/components/soc/esp32s3/include/soc/usb_serial_jtag_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif #include "soc.h" -typedef volatile struct { +typedef volatile struct usb_serial_jtag_dev_s { union { struct { uint32_t rdwr_byte : 32; /*Although only low 8-bits is valid, but change it to 32bits to avoid there's no read/modify/write behaviour*/ /*Write and read byte data to/from UART Tx/Rx FIFO through this field. When USB_DEVICE_SERIAL_IN_EMPTY_INT is set, then user can write data (up to 64 bytes) into UART Tx FIFO. When USB_DEVICE_SERIAL_OUT_RECV_PKT_INT is set, user can check USB_DEVICE_OUT_EP1_WR_ADDR USB_DEVICE_OUT_EP0_RD_ADDR to know how many data is received, then read data from UART Rx FIFO.*/ diff --git a/components/soc/esp32s3/include/soc/usb_wrap_struct.h b/components/soc/esp32s3/include/soc/usb_wrap_struct.h index ba38facf52..3df4106cd5 100644 --- a/components/soc/esp32s3/include/soc/usb_wrap_struct.h +++ b/components/soc/esp32s3/include/soc/usb_wrap_struct.h @@ -154,6 +154,7 @@ typedef union { * USB D- rx value in test. */ uint32_t test_rx_dm:1; + uint32_t reserved7:25; }; uint32_t val; } usb_wrap_test_conf_reg_t; diff --git a/components/soc/esp32s3/include/soc/usbh_struct.h b/components/soc/esp32s3/include/soc/usbh_struct.h index 7401bbf9cf..3a52bf9952 100644 --- a/components/soc/esp32s3/include/soc/usbh_struct.h +++ b/components/soc/esp32s3/include/soc/usbh_struct.h @@ -831,7 +831,7 @@ typedef union { uint32_t bbleerr: 1; uint32_t nakintrpt: 1; uint32_t nyetintrpt: 1; - uint32_t reserved16: 16; + uint32_t reserved15: 17; }; uint32_t val; } usb_diepint_reg_t; diff --git a/components/soc/esp32s3/include/soc/world_controller_struct.h b/components/soc/esp32s3/include/soc/world_controller_struct.h index da042acda5..89a317d9a3 100644 --- a/components/soc/esp32s3/include/soc/world_controller_struct.h +++ b/components/soc/esp32s3/include/soc/world_controller_struct.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef volatile struct { +typedef volatile struct world_controller_dev_s { uint32_t wcl_core_0_entry_1_addr; uint32_t wcl_core_0_entry_2_addr; uint32_t wcl_core_0_entry_3_addr; diff --git a/components/soc/esp32s3/ld/esp32s3.peripherals.ld b/components/soc/esp32s3/ld/esp32s3.peripherals.ld index 5b15a44618..27343e9dd9 100644 --- a/components/soc/esp32s3/ld/esp32s3.peripherals.ld +++ b/components/soc/esp32s3/ld/esp32s3.peripherals.ld @@ -1,3 +1,8 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ PROVIDE ( UART0 = 0x60000000 ); PROVIDE ( SPIMEM1 = 0x60002000 ); PROVIDE ( SPIMEM0 = 0x60003000 ); @@ -8,6 +13,7 @@ PROVIDE ( RTCIO = 0x60008400 ); PROVIDE ( SENS = 0x60008800 ); PROVIDE ( HINF = 0x6000B000 ); PROVIDE ( I2S0 = 0x6000F000 ); +PROVIDE ( I2S1 = 0x6002D000 ); PROVIDE ( UART1 = 0x60010000 ); PROVIDE ( I2C0 = 0x60013000 ); PROVIDE ( UHCI0 = 0x60014000 ); diff --git a/components/soc/esp32s3/pcnt_periph.c b/components/soc/esp32s3/pcnt_periph.c index a411187dee..bb163ccd62 100644 --- a/components/soc/esp32s3/pcnt_periph.c +++ b/components/soc/esp32s3/pcnt_periph.c @@ -16,54 +16,58 @@ #include "soc/gpio_sig_map.h" const pcnt_signal_conn_t pcnt_periph_signals = { - .module = PERIPH_PCNT_MODULE, - .irq = ETS_PCNT_INTR_SOURCE, - .units = { + .groups = { [0] = { - .channels = { + .module = PERIPH_PCNT_MODULE, + .irq = ETS_PCNT_INTR_SOURCE, + .units = { [0] = { - .control_sig = PCNT_CTRL_CH0_IN0_IDX, - .pulse_sig = PCNT_SIG_CH0_IN0_IDX + .channels = { + [0] = { + .control_sig = PCNT_CTRL_CH0_IN0_IDX, + .pulse_sig = PCNT_SIG_CH0_IN0_IDX + }, + [1] = { + .control_sig = PCNT_CTRL_CH1_IN0_IDX, + .pulse_sig = PCNT_SIG_CH1_IN0_IDX + } + } }, [1] = { - .control_sig = PCNT_CTRL_CH1_IN0_IDX, - .pulse_sig = PCNT_SIG_CH1_IN0_IDX - } - } - }, - [1] = { - .channels = { - [0] = { - .control_sig = PCNT_CTRL_CH0_IN1_IDX, - .pulse_sig = PCNT_SIG_CH0_IN1_IDX + .channels = { + [0] = { + .control_sig = PCNT_CTRL_CH0_IN1_IDX, + .pulse_sig = PCNT_SIG_CH0_IN1_IDX + }, + [1] = { + .control_sig = PCNT_CTRL_CH1_IN1_IDX, + .pulse_sig = PCNT_SIG_CH1_IN1_IDX + } + } }, - [1] = { - .control_sig = PCNT_CTRL_CH1_IN1_IDX, - .pulse_sig = PCNT_SIG_CH1_IN1_IDX - } - } - }, - [2] = { - .channels = { - [0] = { - .control_sig = PCNT_CTRL_CH0_IN2_IDX, - .pulse_sig = PCNT_SIG_CH0_IN2_IDX + [2] = { + .channels = { + [0] = { + .control_sig = PCNT_CTRL_CH0_IN2_IDX, + .pulse_sig = PCNT_SIG_CH0_IN2_IDX + }, + [1] = { + .control_sig = PCNT_CTRL_CH1_IN2_IDX, + .pulse_sig = PCNT_SIG_CH1_IN2_IDX + } + } }, - [1] = { - .control_sig = PCNT_CTRL_CH1_IN2_IDX, - .pulse_sig = PCNT_SIG_CH1_IN2_IDX - } - } - }, - [3] = { - .channels = { - [0] = { - .control_sig = PCNT_CTRL_CH0_IN3_IDX, - .pulse_sig = PCNT_SIG_CH0_IN3_IDX - }, - [1] = { - .control_sig = PCNT_CTRL_CH1_IN3_IDX, - .pulse_sig = PCNT_SIG_CH1_IN3_IDX + [3] = { + .channels = { + [0] = { + .control_sig = PCNT_CTRL_CH0_IN3_IDX, + .pulse_sig = PCNT_SIG_CH0_IN3_IDX + }, + [1] = { + .control_sig = PCNT_CTRL_CH1_IN3_IDX, + .pulse_sig = PCNT_SIG_CH1_IN3_IDX + } + } } } } diff --git a/components/soc/esp32s3/spi_periph.c b/components/soc/esp32s3/spi_periph.c index b0d7aecf20..f0c4dcd38e 100644 --- a/components/soc/esp32s3/spi_periph.c +++ b/components/soc/esp32s3/spi_periph.c @@ -50,10 +50,18 @@ const spi_signal_conn_t spi_periph_signal[SOC_SPI_PERIPH_NUM] = { .spiq_out = FSPIQ_OUT_IDX, .spiwp_out = FSPIWP_OUT_IDX, .spihd_out = FSPIHD_OUT_IDX, + .spid4_out = FSPIIO4_OUT_IDX, + .spid5_out = FSPIIO5_OUT_IDX, + .spid6_out = FSPIIO6_OUT_IDX, + .spid7_out = FSPIIO7_OUT_IDX, .spid_in = FSPID_IN_IDX, .spiq_in = FSPIQ_IN_IDX, .spiwp_in = FSPIWP_IN_IDX, .spihd_in = FSPIHD_IN_IDX, + .spid4_in = FSPIIO4_IN_IDX, + .spid5_in = FSPIIO5_IN_IDX, + .spid6_in = FSPIIO6_IN_IDX, + .spid7_in = FSPIIO7_IN_IDX, .spics_out = {FSPICS0_OUT_IDX, FSPICS1_OUT_IDX, FSPICS2_OUT_IDX}, .spics_in = FSPICS0_IN_IDX, .spiclk_iomux_pin = SPI2_IOMUX_PIN_NUM_CLK, diff --git a/components/soc/esp32s3/uart_periph.c b/components/soc/esp32s3/uart_periph.c index 78b8090b15..450787854f 100644 --- a/components/soc/esp32s3/uart_periph.c +++ b/components/soc/esp32s3/uart_periph.c @@ -19,27 +19,104 @@ */ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { { - .tx_sig = U0TXD_OUT_IDX, - .rx_sig = U0RXD_IN_IDX, - .rts_sig = U0RTS_OUT_IDX, - .cts_sig = U0CTS_IN_IDX, + .pins = { + [SOC_UART_TX_PIN_IDX] = { + .default_gpio = U0TXD_GPIO_NUM, + .iomux_func = U0TXD_MUX_FUNC, + .input = 0, + .signal = U0TXD_OUT_IDX, + }, + + [SOC_UART_RX_PIN_IDX] = { + .default_gpio = U0RXD_GPIO_NUM, + .iomux_func = U0RXD_MUX_FUNC, + .input = 1, + .signal = U0RXD_IN_IDX, + }, + + [SOC_UART_RTS_PIN_IDX] = { + .default_gpio = U0RTS_GPIO_NUM, + .iomux_func = U0RTS_MUX_FUNC, + .input = 0, + .signal = U0RTS_OUT_IDX, + }, + + [SOC_UART_CTS_PIN_IDX] = { + .default_gpio = U0CTS_GPIO_NUM, + .iomux_func = U0CTS_MUX_FUNC, + .input = 1, + .signal = U0CTS_IN_IDX, + } + }, .irq = ETS_UART0_INTR_SOURCE, .module = PERIPH_UART0_MODULE, }, + { - .tx_sig = U1TXD_OUT_IDX, - .rx_sig = U1RXD_IN_IDX, - .rts_sig = U1RTS_OUT_IDX, - .cts_sig = U1CTS_IN_IDX, + .pins = { + [SOC_UART_TX_PIN_IDX] = { + .default_gpio = U1TXD_GPIO_NUM, + .iomux_func = U1TXD_MUX_FUNC, + .input = 0, + .signal = U1TXD_OUT_IDX, + }, + + [SOC_UART_RX_PIN_IDX] = { + .default_gpio = U1RXD_GPIO_NUM, + .iomux_func = U1RXD_MUX_FUNC, + .input = 1, + .signal = U1RXD_IN_IDX, + }, + + [SOC_UART_RTS_PIN_IDX] = { + .default_gpio = U1RTS_GPIO_NUM, + .iomux_func = U1RTS_MUX_FUNC, + .input = 0, + .signal = U1RTS_OUT_IDX, + }, + + [SOC_UART_CTS_PIN_IDX] = { + .default_gpio = U1CTS_GPIO_NUM, + .iomux_func = U1CTS_MUX_FUNC, + .input = 1, + .signal = U1CTS_IN_IDX, + }, + }, .irq = ETS_UART1_INTR_SOURCE, .module = PERIPH_UART1_MODULE, }, + { - .tx_sig = U2TXD_OUT_IDX, - .rx_sig = U2RXD_IN_IDX, - .rts_sig = U2RTS_OUT_IDX, - .cts_sig = U2CTS_IN_IDX, + .pins = { + [SOC_UART_TX_PIN_IDX] = { + .default_gpio = U2TXD_GPIO_NUM, + .iomux_func = U2TXD_MUX_FUNC, + .input = 0, + .signal = U2TXD_OUT_IDX, + }, + + [SOC_UART_RX_PIN_IDX] = { + .default_gpio = U2RXD_GPIO_NUM, + .iomux_func = U2RXD_MUX_FUNC, + .input = 1, + .signal = U2RXD_IN_IDX, + }, + + [SOC_UART_RTS_PIN_IDX] = { + .default_gpio = U2RTS_GPIO_NUM, + .iomux_func = U2RTS_MUX_FUNC, + .input = 0, + .signal = U2RTS_OUT_IDX, + }, + + [SOC_UART_CTS_PIN_IDX] = { + .default_gpio = U2CTS_GPIO_NUM, + .iomux_func = U2CTS_MUX_FUNC, + .input = 1, + .signal = U2CTS_IN_IDX, + } + }, .irq = ETS_UART2_INTR_SOURCE, .module = PERIPH_UART2_MODULE, - }, + } }; diff --git a/components/soc/esp32s3/usb_phy_periph.c b/components/soc/esp32s3/usb_phy_periph.c new file mode 100644 index 0000000000..596db0417c --- /dev/null +++ b/components/soc/esp32s3/usb_phy_periph.c @@ -0,0 +1,23 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/usb_phy_periph.h" +#include "soc/gpio_sig_map.h" + +/* + Bunch of constants for USB peripheral: GPIO signals +*/ +const usb_phy_signal_conn_t usb_phy_periph_signal = { + .extphy_vp_in = USB_EXTPHY_VP_IDX, + .extphy_vm_in = USB_EXTPHY_VM_IDX, + .extphy_rcv_in = USB_EXTPHY_RCV_IDX, + .extphy_oen_out = USB_EXTPHY_OEN_IDX, + .extphy_vpo_out = USB_EXTPHY_VPO_IDX, + .extphy_vmo_out = USB_EXTPHY_VMO_IDX, + .extphy_suspend_in = USB_EXTPHY_SUSPND_IDX, + .extphy_speed_in = USB_EXTPHY_SPEED_IDX, + .module = PERIPH_USB_MODULE +}; diff --git a/components/soc/include/soc/adc_periph.h b/components/soc/include/soc/adc_periph.h index 796ea18e90..437d8ad6e6 100644 --- a/components/soc/include/soc/adc_periph.h +++ b/components/soc/include/soc/adc_periph.h @@ -18,7 +18,7 @@ #include "soc/soc_caps.h" #include "soc/syscon_struct.h" -#if SOC_ADC_SUPPORT_RTC_CTRL +#if SOC_ADC_RTC_CTRL_SUPPORTED #include "soc/sens_reg.h" #include "soc/sens_struct.h" #endif diff --git a/components/soc/include/soc/i2s_periph.h b/components/soc/include/soc/i2s_periph.h index a2b9c54274..167c84700f 100644 --- a/components/soc/include/soc/i2s_periph.h +++ b/components/soc/include/soc/i2s_periph.h @@ -1,4 +1,4 @@ -// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// 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. @@ -27,16 +27,21 @@ extern "C" { Stores a bunch of per-I2S-peripheral data. */ typedef struct { - const uint8_t o_bck_in_sig; - const uint8_t o_ws_in_sig; - const uint8_t o_bck_out_sig; - const uint8_t o_ws_out_sig; - const uint8_t o_data_out_sig; - const uint8_t i_bck_in_sig; - const uint8_t i_ws_in_sig; - const uint8_t i_bck_out_sig; - const uint8_t i_ws_out_sig; - const uint8_t i_data_in_sig; + const uint8_t mck_out_sig; + + const uint8_t m_tx_bck_sig; + const uint8_t m_rx_bck_sig; + const uint8_t m_tx_ws_sig; + const uint8_t m_rx_ws_sig; + + const uint8_t s_tx_bck_sig; + const uint8_t s_rx_bck_sig; + const uint8_t s_tx_ws_sig; + const uint8_t s_rx_ws_sig; + + const uint8_t data_out_sig; + const uint8_t data_in_sig; + const uint8_t irq; const periph_module_t module; } i2s_signal_conn_t; diff --git a/components/soc/include/soc/lcd_periph.h b/components/soc/include/soc/lcd_periph.h index 6b1071b316..d7d3ebc68b 100644 --- a/components/soc/include/soc/lcd_periph.h +++ b/components/soc/include/soc/lcd_periph.h @@ -21,6 +21,7 @@ extern "C" { #endif +#if SOC_LCDCAM_SUPPORTED typedef struct { struct { const periph_module_t module; @@ -41,6 +42,19 @@ typedef struct { } panels[SOC_LCD_RGB_PANELS]; } lcd_signal_conn_t; +#endif // SOC_LCDCAM_SUPPORTED + +#if SOC_I2S_LCD_I80_VARIANT +typedef struct { + struct { + const periph_module_t module; + const int irq_id; + const int data_sigs[SOC_LCD_I80_BUS_WIDTH]; + const int wr_sig; + } buses[SOC_LCD_I80_BUSES]; +} lcd_signal_conn_t; +#endif // SOC_I2S_LCD_I80_VARIANT + extern const lcd_signal_conn_t lcd_periph_signals; #ifdef __cplusplus diff --git a/components/soc/include/soc/pcnt_periph.h b/components/soc/include/soc/pcnt_periph.h index fa0f58221d..966950c846 100644 --- a/components/soc/include/soc/pcnt_periph.h +++ b/components/soc/include/soc/pcnt_periph.h @@ -1,4 +1,4 @@ -// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// Copyright 2019-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. @@ -27,12 +27,14 @@ extern "C" { typedef struct { struct { struct { - const uint32_t pulse_sig; - const uint32_t control_sig; - } channels[SOC_PCNT_UNIT_CHANNEL_NUM]; - } units[SOC_PCNT_UNIT_NUM]; - const uint32_t irq; - const periph_module_t module; + struct { + const uint32_t pulse_sig; + const uint32_t control_sig; + } channels[SOC_PCNT_CHANNELS_PER_UNIT]; + } units[SOC_PCNT_UNITS_PER_GROUP]; + const uint32_t irq; + const periph_module_t module; + } groups[SOC_PCNT_GROUPS]; } pcnt_signal_conn_t; extern const pcnt_signal_conn_t pcnt_periph_signals; diff --git a/components/soc/include/soc/rtc_io_periph.h b/components/soc/include/soc/rtc_io_periph.h index e9309771c6..618b64cd8f 100644 --- a/components/soc/include/soc/rtc_io_periph.h +++ b/components/soc/include/soc/rtc_io_periph.h @@ -27,7 +27,7 @@ #include "soc/rtc_cntl_reg.h" #include "soc/rtc_cntl_struct.h" -#if SOC_ADC_SUPPORT_RTC_CTRL +#if SOC_ADC_RTC_CTRL_SUPPORTED #include "soc/sens_struct.h" #endif diff --git a/components/soc/include/soc/sdio_slave_periph.h b/components/soc/include/soc/sdio_slave_periph.h index d39f72f526..0f748ae12e 100644 --- a/components/soc/include/soc/sdio_slave_periph.h +++ b/components/soc/include/soc/sdio_slave_periph.h @@ -15,9 +15,12 @@ #pragma once #include //include soc related (generated) definitions +#include "soc/soc_caps.h" #include "soc/soc_pins.h" +#ifdef SOC_SDIO_SLAVE_SUPPORTED #include "soc/slc_reg.h" #include "soc/slc_struct.h" +#endif #include "soc/host_reg.h" #include "soc/host_struct.h" #include "soc/hinf_reg.h" diff --git a/components/soc/include/soc/spi_periph.h b/components/soc/include/soc/spi_periph.h index 4ddb8b3f1e..7aa3865035 100644 --- a/components/soc/include/soc/spi_periph.h +++ b/components/soc/include/soc/spi_periph.h @@ -30,8 +30,7 @@ #endif #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif #if CONFIG_IDF_TARGET_ESP32S2 @@ -41,8 +40,6 @@ extern "C" #define SPI_FWRITE_QIO 0 #endif - - /* Stores a bunch of per-spi-peripheral data. */ @@ -53,10 +50,22 @@ typedef struct { const uint8_t spiq_out; const uint8_t spiwp_out; const uint8_t spihd_out; +#if SOC_SPI_SUPPORT_OCT + const uint8_t spid4_out; + const uint8_t spid5_out; + const uint8_t spid6_out; + const uint8_t spid7_out; +#endif // SOC_SPI_SUPPORT_OCT const uint8_t spid_in; //GPIO mux input signals const uint8_t spiq_in; const uint8_t spiwp_in; const uint8_t spihd_in; +#if SOC_SPI_SUPPORT_OCT + const uint8_t spid4_in; + const uint8_t spid5_in; + const uint8_t spid6_in; + const uint8_t spid7_in; +#endif // SOC_SPI_SUPPORT_OCT const uint8_t spics_out[3]; // /CS GPIO output mux signals const uint8_t spics_in; const uint8_t spidqs_out; diff --git a/components/soc/include/soc/uart_periph.h b/components/soc/include/soc/uart_periph.h index f7e4709932..320b947c3b 100644 --- a/components/soc/include/soc/uart_periph.h +++ b/components/soc/include/soc/uart_periph.h @@ -18,16 +18,40 @@ #include "soc/uart_struct.h" #include "soc/periph_defs.h" #include "soc/gpio_sig_map.h" +#include "soc/io_mux_reg.h" +#include "soc/uart_pins.h" #ifdef __cplusplus extern "C" { #endif +#define SOC_UART_TX_PIN_IDX (0) +#define SOC_UART_RX_PIN_IDX (1) +#define SOC_UART_RTS_PIN_IDX (2) +#define SOC_UART_CTS_PIN_IDX (3) + +/** + * @brief Macro that can be used to retrieve the signal of a certain pin for a + * certain UART. + */ +#define UART_PERIPH_SIGNAL(IDX, PIN) (uart_periph_signal[(IDX)].pins[(PIN)].signal) + typedef struct { - const uint8_t tx_sig; - const uint8_t rx_sig; - const uint8_t rts_sig; - const uint8_t cts_sig; + /* Default GPIO number for this UART pin in the IOMUX. + * This value can be -1 if there is no default GPIO for a pin. + * For example, ESP32-C3 doesn't have any default GPIO for + * U0CTS and U0RTS. */ + int32_t default_gpio : 15; + /* Func which should be assigned to the GPIO to be used as UART */ + int32_t iomux_func : 4; + /* Marks if the current UART pin is input (or not) */ + uint32_t input : 1; + /* Signal in the GPIO signal map. */ + uint32_t signal : 12; +} uart_periph_sig_t; + +typedef struct { + const uart_periph_sig_t pins[SOC_UART_PINS_COUNT]; const uint8_t irq; const periph_module_t module; } uart_signal_conn_t; diff --git a/components/soc/include/soc/usb_phy_periph.h b/components/soc/include/soc/usb_phy_periph.h new file mode 100644 index 0000000000..802d1720ce --- /dev/null +++ b/components/soc/include/soc/usb_phy_periph.h @@ -0,0 +1,35 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once +#include +#include "soc/soc_caps.h" +#include "soc/periph_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + Stores a bunch of USB-peripheral data. +*/ +typedef struct { + const uint8_t extphy_vp_in; + const uint8_t extphy_vm_in; + const uint8_t extphy_rcv_in; + const uint8_t extphy_oen_out; + const uint8_t extphy_vpo_out; + const uint8_t extphy_vmo_out; + const uint8_t extphy_suspend_in; + const uint8_t extphy_speed_in; + const periph_module_t module; +} usb_phy_signal_conn_t; + +extern const usb_phy_signal_conn_t usb_phy_periph_signal; + +#ifdef __cplusplus +} +#endif diff --git a/components/spi_flash/CMakeLists.txt b/components/spi_flash/CMakeLists.txt index 573c6698eb..9cc02602f2 100644 --- a/components/spi_flash/CMakeLists.txt +++ b/components/spi_flash/CMakeLists.txt @@ -1,122 +1,63 @@ -idf_component_get_property(spi_flash_mock ${COMPONENT_NAME} USE_MOCK) idf_build_get_property(target IDF_TARGET) -if(${spi_flash_mock}) - message(STATUS "building SPI FLASH MOCKS") - - set(IDF_PATH $ENV{IDF_PATH}) - set(CMOCK_DIR "${IDF_PATH}/components/cmock/CMock") - set(MOCK_GEN_DIR "${CMAKE_CURRENT_BINARY_DIR}/mocks") - - file(MAKE_DIRECTORY ${MOCK_GEN_DIR}) - - set(MOCK_OUTPUT - "${MOCK_GEN_DIR}/Mockesp_partition.c" "${MOCK_GEN_DIR}/Mockesp_partition.h" - "${MOCK_GEN_DIR}/Mockesp_flash.c" "${MOCK_GEN_DIR}/Mockesp_flash.h" - "${MOCK_GEN_DIR}/Mockesp_spi_flash.c" "${MOCK_GEN_DIR}/Mockesp_spi_flash.h") - - set(MOCK_HEADERS - ${CMAKE_CURRENT_SOURCE_DIR}/include/esp_partition.h - ${CMAKE_CURRENT_SOURCE_DIR}/include/esp_flash.h - ${CMAKE_CURRENT_SOURCE_DIR}/include/esp_spi_flash.h - ) - - set(ENV{UNITY_DIR} "$ENV{IDF_PATH}/components/cmock/CMock") - - set(include_dirs - "${CMAKE_CURRENT_SOURCE_DIR}/include" - "${MOCK_GEN_DIR}") - - set(srcs "${MOCK_GEN_DIR}/Mockesp_partition.c" - "${MOCK_GEN_DIR}/Mockesp_spi_flash.c" - "${MOCK_GEN_DIR}/Mockesp_flash.c") - - if(${target} STREQUAL "linux") - list(APPEND include_dirs - "${CMAKE_CURRENT_SOURCE_DIR}/../spi_flash/sim/stubs/soc/include" - "${CMAKE_CURRENT_SOURCE_DIR}/../spi_flash/sim/stubs/xtensa") - endif() - - idf_component_register(SRCS "${srcs}" - INCLUDE_DIRS ${include_dirs} - REQUIRES cmock) - - add_custom_command( - OUTPUT ruby_found SYMBOLIC - COMMAND "ruby" "-v" - COMMENT "Try to find ruby. If this fails, you need to install ruby" +if(BOOTLOADER_BUILD) + set(srcs "${target}/spi_flash_rom_patch.c") + set(cache_srcs "") + set(priv_requires bootloader_support soc) +else() + set(cache_srcs + "cache_utils.c" + "flash_mmap.c" + "flash_ops.c" + "${target}/flash_ops_${target}.c" + ) + set(srcs + "partition.c" + "${target}/spi_flash_rom_patch.c" ) - # This command builds the mocks. - # First, environment variable UNITY_DIR is set. This is necessary to prevent unity from looking in its own submodule - # which doesn't work in our CI yet... - # The rest is a straight forward call to cmock.rb, consult cmock's documentation for more information. - add_custom_command( - OUTPUT ${MOCK_OUTPUT} - DEPENDS ruby_found - COMMAND ${CMAKE_COMMAND} -E env "UNITY_DIR=${IDF_PATH}/components/unity/unity" - ruby - ${CMOCK_DIR}/lib/cmock.rb - -o${CMAKE_CURRENT_SOURCE_DIR}/mock/mock_config.yaml - ${MOCK_HEADERS} - ) - -else() - if(BOOTLOADER_BUILD) - set(srcs "${target}/spi_flash_rom_patch.c") - set(cache_srcs "") - set(priv_requires bootloader_support soc) - else() - set(cache_srcs - "cache_utils.c" - "flash_mmap.c" - "flash_ops.c" - "${target}/flash_ops_${target}.c" - ) - set(srcs - "partition.c" - "${target}/spi_flash_rom_patch.c" - ) - - if(CONFIG_ESPTOOLPY_OCT_FLASH) - list(APPEND srcs "${target}/spi_flash_oct_flash_init.c") - endif() - - if(CONFIG_IDF_TARGET_ESP32S3) - list(APPEND srcs - "esp32s3/spi_timing_config.c" - "spi_flash_timing_tuning.c") - endif() - - # New implementation after IDF v4.0 - list(APPEND srcs - "spi_flash_chip_drivers.c" - "spi_flash_chip_generic.c" - "spi_flash_chip_issi.c" - "spi_flash_chip_mxic.c" - "spi_flash_chip_gd.c" - "spi_flash_chip_winbond.c" - "spi_flash_chip_boya.c" - "memspi_host_driver.c") - - list(APPEND cache_srcs - "esp_flash_api.c" - "esp_flash_spi_init.c" - "spi_flash_os_func_app.c" - "spi_flash_os_func_noos.c") - - list(APPEND srcs ${cache_srcs}) - set(priv_requires bootloader_support app_update soc esp_ipc driver) + if(CONFIG_ESPTOOLPY_OCT_FLASH) + list(APPEND srcs "${target}/spi_flash_oct_flash_init.c") endif() - idf_component_register(SRCS "${srcs}" - REQUIRES hal - PRIV_REQUIRES "${priv_requires}" - INCLUDE_DIRS include - PRIV_INCLUDE_DIRS include/spi_flash - LDFRAGMENTS linker.lf) + if(CONFIG_IDF_TARGET_ESP32S3) + list(APPEND srcs + "esp32s3/spi_timing_config.c" + "spi_flash_timing_tuning.c") + endif() - # Avoid cache miss by unexpected inlineing when built by -Os - set_source_files_properties(${cache_srcs} PROPERTIES COMPILE_FLAGS - "-fno-inline-functions -fno-inline-small-functions -fno-inline-functions-called-once") + # New implementation after IDF v4.0 + list(APPEND srcs + "spi_flash_chip_drivers.c" + "spi_flash_chip_generic.c" + "spi_flash_chip_issi.c" + "spi_flash_chip_mxic.c" + "spi_flash_chip_gd.c" + "spi_flash_chip_winbond.c" + "spi_flash_chip_boya.c" + "spi_flash_chip_mxic_opi.c" + "memspi_host_driver.c") + list(APPEND cache_srcs + "esp_flash_api.c" + "esp_flash_spi_init.c" + "spi_flash_os_func_app.c" + "spi_flash_os_func_noos.c") + + list(APPEND srcs ${cache_srcs}) + set(priv_requires bootloader_support app_update soc esp_ipc driver) +endif() + +idf_component_register(SRCS "${srcs}" + REQUIRES hal + PRIV_REQUIRES "${priv_requires}" + INCLUDE_DIRS include + PRIV_INCLUDE_DIRS include/spi_flash + LDFRAGMENTS linker.lf) + +# Avoid cache miss by unexpected inlineing when built by -Os +set_source_files_properties(${cache_srcs} PROPERTIES COMPILE_FLAGS "-fno-inline-functions") +if(CMAKE_C_COMPILER_ID MATCHES "GNU") + # These flags are GCC specific + set_property(SOURCE ${cache_srcs} APPEND_STRING PROPERTY COMPILE_FLAGS + " -fno-inline-small-functions -fno-inline-functions-called-once") endif() diff --git a/components/spi_flash/Kconfig b/components/spi_flash/Kconfig index ea1970a76d..32a2544f1a 100644 --- a/components/spi_flash/Kconfig +++ b/components/spi_flash/Kconfig @@ -248,6 +248,15 @@ menu "SPI Flash driver" given by ``chip_drv`` member of the chip struct. This adds support for variant chips, however will extend detecting time. + config SPI_FLASH_SUPPORT_MXIC_OPI_CHIP + bool "mxic (opi)" + depends on IDF_TARGET_ESP32S3 + default y + help + Enable this to support auto detection of Octal MXIC chips if chip vendor not directly + given by ``chip_drv`` member of the chip struct. This adds support for variant + chips, however will extend detecting time. + endmenu #auto detect flash chips config SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE diff --git a/components/spi_flash/esp32s3/mspi_timing_tuning_configs.h b/components/spi_flash/esp32s3/mspi_timing_tuning_configs.h index d438d58d48..5e98c777c3 100644 --- a/components/spi_flash/esp32s3/mspi_timing_tuning_configs.h +++ b/components/spi_flash/esp32s3/mspi_timing_tuning_configs.h @@ -5,37 +5,52 @@ */ #pragma once -//Octal FLASH: core clock 160M, module clock 40M, DTR mode +//FLASH: core clock 160M, module clock 40M, DTR mode #define MSPI_TIMING_FLASH_CONFIG_TABLE_CORE_CLK_160M_MODULE_CLK_40M_DTR_MODE {{1, 0, 0}, {0, 0, 0}, {2, 1, 1}, {2, 0, 1}, {2, 2, 2}, {2, 1, 2}, {1, 0, 1}, {0, 0, 1}} #define MSPI_TIMING_FLASH_CONFIG_NUM_CORE_CLK_160M_MODULE_CLK_40M_DTR_MODE 8 #define MSPI_TIMING_FLASH_DEFAULT_CONFIG_ID_CORE_CLK_160M_MODULE_CLK_40M_DTR_MODE 2 -//Octal FLASH: core clock 160M, module clock 80M, DTR mode +//FLASH: core clock 160M, module clock 80M, DTR mode #define MSPI_TIMING_FLASH_CONFIG_TABLE_CORE_CLK_160M_MODULE_CLK_80M_DTR_MODE {{0, 0, 0}, {4, 2, 2}, {2, 1, 2}, {4, 1, 2}, {1, 0, 1}, {4, 0, 2}, {0, 0, 1}, {4, 2, 3}, {2, 1, 3}, {4, 1, 3}, {1, 0, 2}, {4, 0, 3}, {0, 0, 2}, {4, 2, 4}} #define MSPI_TIMING_FLASH_CONFIG_NUM_CORE_CLK_160M_MODULE_CLK_80M_DTR_MODE 14 #define MSPI_TIMING_FLASH_DEFAULT_CONFIG_ID_CORE_CLK_160M_MODULE_CLK_80M_DTR_MODE 1 -//Octal FLASH: core clock 240M, module clock 120M, DTR mode +//FLASH: core clock 240M, module clock 120M, DTR mode #define MSPI_TIMING_FLASH_CONFIG_TABLE_CORE_CLK_240M_MODULE_CLK_120M_DTR_MODE {{0, 0, 0}, {4, 1, 2}, {1, 0, 1}, {4, 0, 2}, {0, 0, 1}, {4, 1, 3}, {1, 0, 2}, {4, 0, 3}, {0, 0, 2}, {4, 1, 4}, {1, 0, 3}, {4, 0, 4}, {0, 0, 3}, {4, 1, 5}} #define MSPI_TIMING_FLASH_CONFIG_NUM_CORE_CLK_240M_MODULE_CLK_120M_DTR_MODE 14 #define MSPI_TIMING_FLASH_DEFAULT_CONFIG_ID_CORE_CLK_240M_MODULE_CLK_120M_DTR_MODE 1 -//Octal FLASH: core clock 160M, module clock 80M, STR mode +//FLASH: core clock 160M, module clock 80M, STR mode #define MSPI_TIMING_FLASH_CONFIG_TABLE_CORE_CLK_160M_MODULE_CLK_80M_STR_MODE {{1, 0, 0}, {0, 0, 0}, {2, 1, 1}, {2, 0, 1}, {2, 2, 2}, {2, 1, 2}, {1, 0, 1}, {0, 0, 1}} #define MSPI_TIMING_FLASH_CONFIG_NUM_CORE_CLK_160M_MODULE_CLK_80M_STR_MODE 8 #define MSPI_TIMING_FLASH_DEFAULT_CONFIG_ID_CORE_CLK_160M_MODULE_CLK_80M_STR_MODE 2 -//Octal FLASH: core clock 120M, module clock 120M, STR mode +//FLASH: core clock 120M, module clock 120M, STR mode #define MSPI_TIMING_FLASH_CONFIG_TABLE_CORE_CLK_120M_MODULE_CLK_120M_STR_MODE {{2, 0, 1}, {0, 0, 0}, {2, 2, 2}, {1, 0, 1}, {2, 0, 2}, {0, 0, 1}, {2, 2, 3}, {1, 0, 2}, {2, 0, 3}, {0, 0, 2}, {2, 2, 4}, {1, 0, 3}} #define MSPI_TIMING_FLASH_CONFIG_NUM_CORE_CLK_120M_MODULE_CLK_120M_STR_MODE 12 #define MSPI_TIMING_FLASH_DEFAULT_CONFIG_ID_CORE_CLK_120M_MODULE_CLK_120M_STR_MODE 2 -//Octal PSRAM: core clock 80M, module clock 40M, DTR mode +//FLASH: core clock 240M, module clock 120M, STR mode +#define MSPI_TIMING_FLASH_CONFIG_TABLE_CORE_CLK_240M_MODULE_CLK_120M_STR_MODE {{1, 0, 0}, {0, 0, 0}, {1, 1, 1}, {2, 3, 2}, {1, 0, 1}, {0, 0, 1}, {1, 1, 2}, {2, 3, 3}, {1, 0, 2}, {0, 0, 2}, {1, 1, 3}, {2, 3, 4}} +#define MSPI_TIMING_FLASH_CONFIG_NUM_CORE_CLK_240M_MODULE_CLK_120M_STR_MODE 12 +#define MSPI_TIMING_FLASH_DEFAULT_CONFIG_ID_CORE_CLK_240M_MODULE_CLK_120M_STR_MODE 2 + +//PSRAM: core clock 80M, module clock 40M, DTR mode #define MSPI_TIMING_PSRAM_CONFIG_TABLE_CORE_CLK_80M_MODULE_CLK_40M_DTR_MODE {{1, 0, 0}, {2, 1, 1}, {2, 0, 1}, {0, 0, 0}, {3, 1, 1}, {3, 0, 1}, {1, 0, 1}, {2, 1, 2}, {2, 0, 2}, {0, 0, 1}, {3, 1, 2}, {3, 0, 2}} #define MSPI_TIMING_PSRAM_CONFIG_NUM_CORE_CLK_80M_MODULE_CLK_40M_DTR_MODE 12 #define MSPI_TIMING_PSRAM_DEFAULT_CONFIG_ID_CORE_CLK_80M_MODULE_CLK_40M_DTR_MODE 4 -//Octal PSRAM: core clock 160M, module clock 80M, DTR mode -#define MSPI_TIMING_PSRAM_CONFIG_TABLE_CORE_CLK_160M_MODULE_CLK_80M_DTR_MODE {{1, 0, 0}, {0, 0, 0}, {3, 0, 1}, {1, 0, 1}, {0, 0, 1}, {3, 0, 2}, {1, 0, 2}, {0, 0, 2}, {3, 0, 3}, {1, 0, 3}, {0, 0, 3}, {3, 0, 4}, {1, 0, 4}, {0, 0, 4}} +//PSRAM: core clock 160M, module clock 80M, DTR mode +#define MSPI_TIMING_PSRAM_CONFIG_TABLE_CORE_CLK_160M_MODULE_CLK_80M_DTR_MODE {{0, 0, 0}, {4, 2, 2}, {2, 1, 2}, {4, 1, 2}, {1, 0, 1}, {4, 0, 2}, {0, 0, 1}, {4, 2, 3}, {2, 1, 3}, {4, 1, 3}, {1, 0, 2}, {4, 0, 3}, {0, 0, 2}, {4, 2, 4}} #define MSPI_TIMING_PSRAM_CONFIG_NUM_CORE_CLK_160M_MODULE_CLK_80M_DTR_MODE 14 #define MSPI_TIMING_PSRAM_DEFAULT_CONFIG_ID_CORE_CLK_160M_MODULE_CLK_80M_DTR_MODE 1 + +//PSRAM: core clock 240M, module clock 120M, STR mode +#define MSPI_TIMING_PSRAM_CONFIG_TABLE_CORE_CLK_240M_MODULE_CLK_120M_STR_MODE {{1, 0, 0}, {0, 0, 0}, {1, 1, 1}, {2, 3, 2}, {1, 0, 1}, {0, 0, 1}, {1, 1, 2}, {2, 3, 3}, {1, 0, 2}, {0, 0, 2}, {1, 1, 3}, {2, 3, 4}} +#define MSPI_TIMING_PSRAM_CONFIG_NUM_CORE_CLK_240M_MODULE_CLK_120M_STR_MODE 12 +#define MSPI_TIMING_PSRAM_DEFAULT_CONFIG_ID_CORE_CLK_240M_MODULE_CLK_120M_STR_MODE 2 + +//PSRAM: core clock 120M, module clock 120M, STR mode +#define MSPI_TIMING_PSRAM_CONFIG_TABLE_CORE_CLK_120M_MODULE_CLK_120M_STR_MODE {{2, 0, 1}, {0, 0, 0}, {2, 2, 2}, {1, 0, 1}, {2, 0, 2}, {0, 0, 1}, {2, 2, 3}, {1, 0, 2}, {2, 0, 3}, {0, 0, 2}, {2, 2, 4}, {1, 0, 3}} +#define MSPI_TIMING_PSRAM_CONFIG_NUM_CORE_CLK_120M_MODULE_CLK_120M_STR_MODE 12 +#define MSPI_TIMING_PSRAM_DEFAULT_CONFIG_ID_CORE_CLK_120M_MODULE_CLK_120M_STR_MODE 2 diff --git a/components/spi_flash/esp32s3/spi_flash_oct_flash_init.c b/components/spi_flash/esp32s3/spi_flash_oct_flash_init.c index 42de479acc..f689b8bbe0 100644 --- a/components/spi_flash/esp32s3/spi_flash_oct_flash_init.c +++ b/components/spi_flash/esp32s3/spi_flash_oct_flash_init.c @@ -12,6 +12,7 @@ #include "esp32s3/rom/opi_flash.h" #include "spi_flash_private.h" #include "soc/spi_mem_reg.h" +#include "soc/io_mux_reg.h" #if CONFIG_ESPTOOLPY_FLASH_VENDOR_MXIC #include "opi_flash_cmd_format_mxic.h" #endif @@ -21,40 +22,11 @@ #define SPI_FLASH_SPI_CMD_RDCR 0x15 #define SPI_FLASH_SPI_CMD_WRSRCR 0x01 -#define SPI_FLASH_OCTCLK_IO 30 -#define SPI_FLASH_OCTDQS_IO 37 -#define SPI_FLASH_OCTD0_IO 32 -#define SPI_FLASH_OCTD1_IO 31 -#define SPI_FLASH_OCTD2_IO 28 -#define SPI_FLASH_OCTD3_IO 27 -#define SPI_FLASH_OCTD4_IO 33 -#define SPI_FLASH_OCTD5_IO 34 -#define SPI_FLASH_OCTD6_IO 35 -#define SPI_FLASH_OCTD7_IO 36 -#define SPI_FLASH_OCTCS_IO 29 -#define SPI_FLASH_OCTCS1_IO 26 - - // default value is rom_default_spiflash_legacy_flash_func extern const spiflash_legacy_funcs_t *rom_spiflash_legacy_funcs; extern int SPI_write_enable(void *spi); DRAM_ATTR const esp_rom_opiflash_def_t opiflash_cmd_def = OPI_CMD_FORMAT(); -void s_set_flash_pin_drive_capability(uint8_t drv) -{ - esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTCLK_IO, drv); - esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTDQS_IO, drv); - esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTD0_IO, drv); - esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTD1_IO, drv); - esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTD2_IO, drv); - esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTD3_IO, drv); - esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTD4_IO, drv); - esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTD5_IO, drv); - esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTD6_IO, drv); - esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTD7_IO, drv); - esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTCS_IO, drv); - esp_rom_gpio_pad_set_drv(SPI_FLASH_OCTCS1_IO, drv); -} static void s_register_rom_function(void) { @@ -145,6 +117,14 @@ static void s_set_flash_ouput_driver_strength(int spi_num, uint8_t strength) false); } +static void s_set_pin_drive_capability(uint8_t drv) +{ + //flash clock + REG_SET_FIELD(SPI_MEM_DATE_REG(0), SPI_MEM_SPI_FMEM_SPICLK_FUN_DRV, 3); + //cs0 + PIN_SET_DRV(IO_MUX_GPIO29_REG, 3); +} + static void s_flash_init_mxic(esp_rom_spiflash_read_mode_t mode) { esp_rom_opiflash_legacy_driver_init(&opiflash_cmd_def); @@ -156,13 +136,13 @@ static void s_flash_init_mxic(esp_rom_spiflash_read_mode_t mode) // STR/DTR specific setting esp_rom_spiflash_wait_idle(&g_rom_flashchip); #if CONFIG_ESPTOOLPY_FLASHMODE_OPI_STR - s_set_flash_pin_drive_capability(1); + s_set_pin_drive_capability(3); s_set_flash_dtr_str_opi_mode(1, 0x1); esp_rom_opiflash_cache_mode_config(mode, &rom_opiflash_cmd_def->cache_rd_cmd); esp_rom_spi_set_dtr_swap_mode(0, false, false); esp_rom_spi_set_dtr_swap_mode(1, false, false); #else //CONFIG_ESPTOOLPY_FLASHMODE_OPI_DTR - s_set_flash_pin_drive_capability(3); + s_set_pin_drive_capability(3); s_set_flash_dtr_str_opi_mode(1, 0x2); esp_rom_opiflash_cache_mode_config(mode, &rom_opiflash_cmd_def->cache_rd_cmd); esp_rom_spi_set_dtr_swap_mode(0, true, true); diff --git a/components/spi_flash/esp32s3/spi_timing_config.c b/components/spi_flash/esp32s3/spi_timing_config.c index ef496e68cb..75745cdfd7 100644 --- a/components/spi_flash/esp32s3/spi_timing_config.c +++ b/components/spi_flash/esp32s3/spi_timing_config.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include "sdkconfig.h" #include "string.h" #include "esp_attr.h" @@ -13,17 +14,28 @@ #include "soc/spi_mem_reg.h" #include "spi_timing_config.h" -#define OPI_PSRAM_SYNC_READ 0x0000 -#define OPI_PSRAM_SYNC_WRITE 0x8080 -#define OCT_PSRAM_RD_DUMMY_NUM (2*(10-1)) -#define OCT_PSRAM_WR_DUMMY_NUM (2*(5-1)) +#define OPI_PSRAM_SYNC_READ 0x0000 +#define OPI_PSRAM_SYNC_WRITE 0x8080 +#define OCT_PSRAM_RD_DUMMY_NUM (2*(10-1)) +#define OCT_PSRAM_WR_DUMMY_NUM (2*(5-1)) +#define QPI_PSRAM_FAST_READ 0XEB +#define QPI_PSRAM_WRITE 0X38 +#define QPI_PSRAM_FAST_READ_DUMMY 6 -/////////////////////////////////////////TIMING TUNING IS NEEDED////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING //If one of the FLASH / PSRAM or both of them need timing tuning, we should build following code +#define MULTI_LINE_MASK_OCT_FLASH (SPI_MEM_FCMD_OCT | SPI_MEM_FADDR_OCT | SPI_MEM_FDIN_OCT | SPI_MEM_FDOUT_OCT) +#define MULTI_LINE_MASK_QUAD_FLASH (SPI_MEM_FASTRD_MODE | SPI_MEM_FREAD_DUAL | SPI_MEM_FREAD_DIO | SPI_MEM_FREAD_QUAD | SPI_MEM_FREAD_QIO) +#define SPI_FLASH_QIO_MODE (SPI_MEM_FREAD_QIO | SPI_MEM_FASTRD_MODE) +#define SPI_FLASH_QUAD_MODE (SPI_MEM_FREAD_QUAD | SPI_MEM_FASTRD_MODE) +#define SPI_FLASH_DIO_MODE (SPI_MEM_FREAD_DIO | SPI_MEM_FASTRD_MODE) +#define SPI_FLASH_DUAL_MODE (SPI_MEM_FREAD_DUAL | SPI_MEM_FASTRD_MODE) +#define SPI_FLASH_FAST_MODE (SPI_MEM_FASTRD_MODE) +#define SPI_FLASH_SLOW_MODE 0 -spi_timing_config_core_clock_t IRAM_ATTR spi_timing_config_get_core_clock(void) +#define NOT_INIT_INT 127 + +//-------------------------------------MSPI Clock Setting-------------------------------------// +spi_timing_config_core_clock_t spi_timing_config_get_core_clock(void) { switch (SPI_TIMING_CORE_CLOCK_MHZ) { case 80: @@ -39,7 +51,7 @@ spi_timing_config_core_clock_t IRAM_ATTR spi_timing_config_get_core_clock(void) } } -void IRAM_ATTR spi_timing_config_set_core_clock(uint8_t spi_num, spi_timing_config_core_clock_t core_clock) +void spi_timing_config_set_core_clock(uint8_t spi_num, spi_timing_config_core_clock_t core_clock) { uint32_t reg_val = 0; @@ -63,8 +75,7 @@ void IRAM_ATTR spi_timing_config_set_core_clock(uint8_t spi_num, spi_timing_conf REG_SET_FIELD(SPI_MEM_CORE_CLK_SEL_REG(spi_num), SPI_MEM_CORE_CLK_SEL, reg_val); } -//-------------------------------------FLASH timing tuning-------------------------------------// -void IRAM_ATTR spi_timing_config_set_flash_clock(uint8_t spi_num, uint32_t freqdiv) +void spi_timing_config_set_flash_clock(uint8_t spi_num, uint32_t freqdiv) { assert(freqdiv > 0); if (freqdiv == 1) { @@ -75,7 +86,43 @@ void IRAM_ATTR spi_timing_config_set_flash_clock(uint8_t spi_num, uint32_t freqd } } -void IRAM_ATTR spi_timing_config_flash_set_din_mode_num(uint8_t spi_num, uint8_t din_mode, uint8_t din_num) +void spi_timing_config_set_psram_clock(uint8_t spi_num, uint32_t freqdiv) +{ + if (freqdiv == 1) { + WRITE_PERI_REG(SPI_MEM_SRAM_CLK_REG(spi_num), SPI_MEM_SCLK_EQU_SYSCLK); + } else { + uint32_t freqbits = (((freqdiv-1)< 0) { SET_PERI_REG_MASK(SPI_MEM_TIMING_CALI_REG(spi_num), SPI_MEM_TIMING_CALI_M); SET_PERI_REG_BITS(SPI_MEM_TIMING_CALI_REG(spi_num), SPI_MEM_EXTRA_DUMMY_CYCLELEN_V, extra_dummy, @@ -100,20 +148,50 @@ void IRAM_ATTR spi_timing_config_flash_set_extra_dummy(uint8_t spi_num, uint8_t SET_PERI_REG_BITS(SPI_MEM_TIMING_CALI_REG(spi_num), SPI_MEM_EXTRA_DUMMY_CYCLELEN_V, 0, SPI_MEM_EXTRA_DUMMY_CYCLELEN_S); } -} - -//-------------------------------------PSRAM timing tuning-------------------------------------// -void IRAM_ATTR spi_timing_config_set_psram_clock(uint8_t spi_num, uint32_t freqdiv) -{ - if (freqdiv == 1) { - WRITE_PERI_REG(SPI_MEM_SRAM_CLK_REG(spi_num), SPI_MEM_SCLK_EQU_SYSCLK); - } else { - uint32_t freqbits = (((freqdiv-1)< 0) { SET_PERI_REG_MASK(SPI_MEM_SPI_SMEM_TIMING_CALI_REG(spi_num), SPI_MEM_SPI_SMEM_TIMING_CALI_M); SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_TIMING_CALI_REG(spi_num), SPI_MEM_SPI_SMEM_EXTRA_DUMMY_CYCLELEN_V, extra_dummy, @@ -138,10 +217,14 @@ void IRAM_ATTR spi_timing_config_psram_set_extra_dummy(uint8_t spi_num, uint8_t SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_TIMING_CALI_REG(spi_num), SPI_MEM_SPI_SMEM_EXTRA_DUMMY_CYCLELEN_V, 0, SPI_MEM_SPI_SMEM_EXTRA_DUMMY_CYCLELEN_S); } +#elif CONFIG_SPIRAM_MODE_QUAD + SET_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(spi_num), SPI_MEM_USR_RD_SRAM_DUMMY_M); + SET_PERI_REG_BITS(SPI_MEM_CACHE_SCTRL_REG(spi_num), SPI_MEM_SRAM_RDUMMY_CYCLELEN_V, (QPI_PSRAM_FAST_READ_DUMMY + extra_dummy - 1), SPI_MEM_SRAM_RDUMMY_CYCLELEN_S); +#endif } //-------------------------------------------FLASH/PSRAM Read/Write------------------------------------------// -void IRAM_ATTR spi_timing_config_flash_read_data(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len) +void spi_timing_config_flash_read_data(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len) { #if CONFIG_ESPTOOLPY_OCT_FLASH // note that in spi_flash_read API, there is a wait-idle stage, since flash can only be read in idle state. @@ -152,46 +235,181 @@ void IRAM_ATTR spi_timing_config_flash_read_data(uint8_t spi_num, uint8_t *buf, } esp_rom_opiflash_read_raw(addr, buf, len); #else - abort(); + esp_rom_spiflash_read(addr, (uint32_t *)buf, len); #endif } -void IRAM_ATTR spi_timing_config_psram_write_data(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len) +static void s_psram_write_data(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len) { -#if CONFIG_ESPTOOLPY_OCT_FLASH - uint32_t cmd = OPI_PSRAM_SYNC_WRITE; - int dummy = OCT_PSRAM_WR_DUMMY_NUM; - +#if CONFIG_SPIRAM_MODE_OCT esp_rom_opiflash_exec_cmd(spi_num, ESP_ROM_SPIFLASH_OPI_DTR_MODE, - cmd, 16, + OPI_PSRAM_SYNC_WRITE, 16, addr, 32, - dummy, - buf, 8 * len, + OCT_PSRAM_WR_DUMMY_NUM, + buf, len * 8, NULL, 0, BIT(1), false); -#else - abort(); +#elif CONFIG_SPIRAM_MODE_QUAD + psram_exec_cmd(spi_num, 0, + QPI_PSRAM_WRITE, 8, + addr, 24, + 0, + buf, len * 8, + NULL, 0, + SPI_MEM_CS1_DIS_M, + false); #endif } -void IRAM_ATTR spi_timing_config_psram_read_data(uint8_t spi_num,uint8_t *buf, uint32_t addr, uint32_t len) +static void s_psram_read_data(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len) { -#if CONFIG_ESPTOOLPY_OCT_FLASH - uint32_t cmd = OPI_PSRAM_SYNC_READ; - int dummy = OCT_PSRAM_RD_DUMMY_NUM; - +#if CONFIG_SPIRAM_MODE_OCT + for (int i = 0; i < 16; i++) { + REG_WRITE(SPI_MEM_W0_REG(1) + i*4, 0); + } esp_rom_opiflash_exec_cmd(spi_num, ESP_ROM_SPIFLASH_OPI_DTR_MODE, - cmd, 16, + OPI_PSRAM_SYNC_READ, 16, addr, 32, - dummy, + OCT_PSRAM_RD_DUMMY_NUM, NULL, 0, - buf, 8 * len, + buf, len * 8, BIT(1), false); -#else - abort(); +#elif CONFIG_SPIRAM_MODE_QUAD + psram_exec_cmd(spi_num, 0, + QPI_PSRAM_FAST_READ, 8, + addr, 24, + QPI_PSRAM_FAST_READ_DUMMY + s_psram_extra_dummy, + NULL, 0, + buf, len * 8, + SPI_MEM_CS1_DIS_M, + false); +#endif +} + +static void s_psram_execution(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len, bool is_read) +{ + while (len) { + uint32_t length = MIN(len, 32); + if (is_read) { + s_psram_read_data(1, buf, addr, length); + } else { + s_psram_write_data(1, buf, addr, length); + } + addr += length; + buf += length; + len -= length; + } +} + +void spi_timing_config_psram_write_data(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len) +{ + s_psram_execution(spi_num, buf, addr, len, false); +} + +void spi_timing_config_psram_read_data(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len) +{ + s_psram_execution(spi_num, buf, addr, len, true); +} + + +/*------------------------------------------------------------------------------------------------- + * SPI1 Timing Tuning APIs + * These APIs are only used in `spi_flash_timing_tuning.c/sweep_for_success_sample_points()` for + * configuring SPI1 timing tuning related registers to find best tuning parameter + *-------------------------------------------------------------------------------------------------*/ +void spi_timing_config_flash_tune_din_num_mode(uint8_t din_mode, uint8_t din_num) +{ + /** + * 1. SPI_MEM_DINx_MODE(1), SPI_MEM_DINx_NUM(1) are meaningless + * SPI0 and SPI1 share the SPI_MEM_DINx_MODE(0), SPI_MEM_DINx_NUM(0) for FLASH timing tuning + * 2. We use SPI1 to get the best Flash timing tuning (mode and num) config + */ + spi_timing_config_flash_set_din_mode_num(0, din_mode, din_num); +} + +void spi_timing_config_flash_tune_dummy(uint8_t extra_dummy) +{ + spi_timing_config_flash_set_extra_dummy(1, extra_dummy); +} + +void spi_timing_config_psram_tune_din_num_mode(uint8_t din_mode, uint8_t din_num) +{ + /** + * 1. SPI_MEM_SPI_SMEM_DINx_MODE(1), SPI_MEM_SPI_SMEM_DINx_NUM(1) are meaningless + * SPI0 and SPI1 share the SPI_MEM_SPI_SMEM_DINx_MODE(0), SPI_MEM_SPI_SMEM_DINx_NUM(0) for PSRAM timing tuning + * 2. We use SPI1 to get the best PSRAM timing tuning (mode and num) config + */ + spi_timing_config_psram_set_din_mode_num(0, din_mode, din_num); +} + +void spi_timing_config_psram_tune_dummy(uint8_t extra_dummy) +{ +#if CONFIG_SPIRAM_MODE_OCT + //On 728, for SPI1, flash and psram share the extra dummy register + spi_timing_config_flash_set_extra_dummy(1, extra_dummy); +#elif CONFIG_SPIRAM_MODE_QUAD + //Update this `s_psram_extra_dummy`, the `s_psram_read_data` will set dummy according to this `s_psram_extra_dummy` + s_psram_extra_dummy = extra_dummy; + SET_PERI_REG_MASK(SPI_MEM_USER_REG(1), SPI_MEM_USR_DUMMY); // dummy en + SET_PERI_REG_BITS(SPI_MEM_USER1_REG(1), SPI_MEM_USR_DUMMY_CYCLELEN_V, extra_dummy - 1, SPI_MEM_USR_DUMMY_CYCLELEN_S); #endif } #endif //#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING + +static bool spi_timing_config_cs_setup_enable(void) +{ + return REG_GET_BIT(SPI_MEM_USER_REG(0), SPI_MEM_CS_SETUP); +} + +static bool spi_timing_config_cs_hold_enable(void) +{ + return REG_GET_BIT(SPI_MEM_USER_REG(0), SPI_MEM_CS_HOLD); +} + +bool spi_timine_config_flash_is_tuned(void) +{ +#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING + return true; +#else + return false; +#endif +} + +/** + * Get the SPI1 Flash CS timing setting. The setup time and hold time are both realistic cycles. + * @note On ESP32-S3, SPI0/1 share the Flash CS timing registers. Therefore, we should not change these values. + * @note This function inform `spi_flash_timing_tuning.c` (driver layer) of the cycle, + * and other component (esp_flash driver) should get these cycle and configure the registers accordingly. + */ +void spi_timing_config_get_cs_timing(uint8_t *setup_time, uint32_t *hold_time) +{ + *setup_time = REG_GET_FIELD(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_SETUP_TIME); + *hold_time = REG_GET_FIELD(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_HOLD_TIME); + /** + * The logic here is, if setup_en / hold_en is false, then we return the realistic cycle number, + * which is 0. If true, then the realistic cycle number is (reg_value + 1) + */ + if (spi_timing_config_cs_setup_enable()) { + *setup_time += 1; + } else { + *setup_time = 0; + } + if (spi_timing_config_cs_hold_enable()) { + *hold_time += 1; + } else { + *hold_time = 0; + } +} + +/** + * Get the SPI1 Flash clock setting. + * @note Similarly, this function inform `spi_flash_timing_tuning.c` (driver layer) of the clock setting, + * and other component (esp_flash driver) should get these and configure the registers accordingly. + */ +uint32_t spi_timing_config_get_flash_clock_reg(void) +{ + return READ_PERI_REG(SPI_MEM_CLOCK_REG(1)); +} diff --git a/components/spi_flash/esp32s3/spi_timing_config.h b/components/spi_flash/esp32s3/spi_timing_config.h index 0c94b2e718..cd7d06c683 100644 --- a/components/spi_flash/esp32s3/spi_timing_config.h +++ b/components/spi_flash/esp32s3/spi_timing_config.h @@ -18,97 +18,163 @@ extern "C" { #define SPI_TIMING_CONFIG_NUM_DEFAULT 20 //This should be larger than the max available timing config num #define SPI_TIMING_TEST_DATA_LEN 64 - #define SPI_TIMING_PSRAM_TEST_DATA_ADDR 0 #define SPI_TIMING_FLASH_TEST_DATA_ADDR ESP_BOOTLOADER_OFFSET - -//-------------------------------------------FLASH Operation Mode and Corresponding Timing Tuning Parameter Table --------------------------------------// -#define SPI_TIMING_FLASH_DTR_MODE (CONFIG_ESPTOOLPY_FLASHMODE_OPI_DTR || CONFIG_ESPTOOLPY_FLASHMODE_OIO_DTR) -#define SPI_TIMING_FLASH_STR_MODE (CONFIG_ESPTOOLPY_FLASHMODE_OPI_STR || CONFIG_ESPTOOLPY_FLASHMODE_OIO_STR || CONFIG_ESPTOOLPY_FLASHMODE_OOUT_STR) - -/* Determine A feasible core clock below: SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ and SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ*/ -//OCTAL FLASH -#if CONFIG_ESPTOOLPY_OCT_FLASH - -// OCT FLASH 40M DTR -#if SPI_TIMING_FLASH_DTR_MODE && CONFIG_ESPTOOLPY_FLASHFREQ_40M -_Static_assert(!CONFIG_ESPTOOLPY_FLASHFREQ_40M, "Octal FLASH 40MHz DDR is not supported. TODO: IDF-1630"); -#define SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 160 +/** + * @note BACKGOURND: + * + * The SPI FLASH module clock and SPI PSRAM module clock is divided from the SPI core clock, core clock is from system clock: + * + * PLL ----| |---- FLASH Module Clock + * XTAL ----|----> Core Clock ---->| + * RTC8M ----| |---- PSRAM Module Clock + * + * + * DDR stands for double data rate, MSPI samples at both posedge and negedge. So the real spped will be doubled. + * Speed from high to low: 120M DDR > 80M DDR > 120 SDR > 80M SDR > ... + * + * Module with speed lower than 120M SDR doesn't need to be tuned + * + * @note LIMITATION: + * How to determine the core clock on 728. There are 2 limitations. + * + * 1. MSPI FLASH and PSRAM share the core clock register. Therefore: + * SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ == SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ + * + * 2. DDR mode requires the core clock divider (core_clk / div = module_clk) to be power of 2. + */ +//--------------------------------------FLASH Sampling Mode --------------------------------------// +#define SPI_TIMING_FLASH_DTR_MODE (CONFIG_ESPTOOLPY_FLASHMODE_OPI_DTR || CONFIG_ESPTOOLPY_FLASHMODE_OIO_DTR) +#define SPI_TIMING_FLASH_STR_MODE (CONFIG_ESPTOOLPY_FLASHMODE_OPI_STR || !CONFIG_ESPTOOLPY_OCT_FLASH) +//--------------------------------------FLASH Module Clock --------------------------------------// +#if CONFIG_ESPTOOLPY_FLASHFREQ_20M +#define SPI_TIMING_FLASH_MODULE_CLOCK 20 +#elif CONFIG_ESPTOOLPY_FLASHFREQ_40M +#define SPI_TIMING_FLASH_MODULE_CLOCK 40 +#elif CONFIG_ESPTOOLPY_FLASHFREQ_80M +#define SPI_TIMING_FLASH_MODULE_CLOCK 80 +#else //CONFIG_ESPTOOLPY_FLASHFREQ_120M +#define SPI_TIMING_FLASH_MODULE_CLOCK 120 +#endif +//------------------------------------FLASH Needs Tuning or not-------------------------------------// +#if SPI_TIMING_FLASH_DTR_MODE +#define SPI_TIMING_FLASH_NEEDS_TUNING (SPI_TIMING_FLASH_MODULE_CLOCK > 40) +#elif SPI_TIMING_FLASH_STR_MODE +#define SPI_TIMING_FLASH_NEEDS_TUNING (SPI_TIMING_FLASH_MODULE_CLOCK > 80) #endif -//OCT FLASH 80M DTR +//--------------------------------------PSRAM Sampling Mode --------------------------------------// +#define SPI_TIMING_PSRAM_DTR_MODE CONFIG_SPIRAM_MODE_OCT +#define SPI_TIMING_PSRAM_STR_MODE !CONFIG_SPIRAM_MODE_OCT +//--------------------------------------PSRAM Module Clock --------------------------------------// +#if CONFIG_ESP32S3_SPIRAM_SUPPORT +#if CONFIG_SPIRAM_SPEED_40M +#define SPI_TIMING_PSRAM_MODULE_CLOCK 40 +#elif CONFIG_SPIRAM_SPEED_80M +#define SPI_TIMING_PSRAM_MODULE_CLOCK 80 +#else //CONFIG_SPIRAM_SPEED_120M +#define SPI_TIMING_PSRAM_MODULE_CLOCK 120 +#endif +#else //Disable PSRAM +#define SPI_TIMING_PSRAM_MODULE_CLOCK 10 //Define this to 10MHz, because we rely on `SPI_TIMING_PSRAM_MODULE_CLOCK` macro for calculation and check below, see `Determine the Core Clock` chapter +#endif +//------------------------------------PSRAM Needs Tuning or not-------------------------------------// +#if SPI_TIMING_PSRAM_DTR_MODE +#define SPI_TIMING_PSRAM_NEEDS_TUNING (SPI_TIMING_PSRAM_MODULE_CLOCK > 40) +#elif SPI_TIMING_PSRAM_STR_MODE +#define SPI_TIMING_PSRAM_NEEDS_TUNING (SPI_TIMING_PSRAM_MODULE_CLOCK > 80) +#endif + + +/** + * @note Define A feasible core clock below: SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ and SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ + */ +/** + * Due to MSPI core clock is used by both MSPI Flash and PSRAM clock, + * define the STR/DTR mode here for selecting the core clock: + * @note If either Flash or PSRAM, or both of them are set to DTR mode, then we use DIV 2 + */ +#if (SPI_TIMING_FLASH_DTR_MODE || SPI_TIMING_PSRAM_DTR_MODE) +#define SPI_TIMING_CORE_CLOCK_DIV 2 +#else //#if (SPI_TIMING_FLASH_STR_MODE && (SPI_TIMING_PSRAM_STR_MODE || !CONFIG_ESP32S3_SPIRAM_SUPPORT)) +#define SPI_TIMING_CORE_CLOCK_DIV 1 +#endif + +///////////////////////////////////// FLASH CORE CLOCK ///////////////////////////////////// +//FLASH 80M DTR #if SPI_TIMING_FLASH_DTR_MODE && CONFIG_ESPTOOLPY_FLASHFREQ_80M -#define SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 160 +#define SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 160 #endif -//OCT FLASH 120M DTR +//FLASH 120M DTR #if SPI_TIMING_FLASH_DTR_MODE && CONFIG_ESPTOOLPY_FLASHFREQ_120M -#define SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 240 +#define SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 240 #endif -//OCT FLASH 80M STR -#if SPI_TIMING_FLASH_STR_MODE && CONFIG_ESPTOOLPY_FLASHFREQ_80M -#define SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 160 -#endif - -//OCT FLASH 120M STR +//FLASH 120M STR #if SPI_TIMING_FLASH_STR_MODE && CONFIG_ESPTOOLPY_FLASHFREQ_120M -#define SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 120 +#if (SPI_TIMING_CORE_CLOCK_DIV == 2) +#define SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 240 +#elif (SPI_TIMING_CORE_CLOCK_DIV == 1) +#define SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ 120 #endif +#endif //FLASH 120M STR -#endif //#if CONFIG_ESPTOOLPY_OCT_FLASH -/* QUAD FLASH Operation Mode should be added here if needed */ - - -//---------------------------------------PSRAM Operation Mode and Corresponding Timing Tuning Parameter Table--------------------------------------// -#define SPI_TIMING_PSRAM_DTR_MODE 1 //Currently we only support DTR Octal PSRAM -#define SPI_TIMING_PSRAM_STR_MODE 0 - -//OCTAL PSRAM -#if CONFIG_SPIRAM_MODE_OCT - -//OCT 40M PSRAM -#if SPI_TIMING_PSRAM_DTR_MODE && CONFIG_SPIRAM_SPEED_40M -#define SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ 80 -#endif - -//OCT 80M PSRAM +///////////////////////////////////// PSRAM CORE CLOCK ///////////////////////////////////// +//PSRAM 80M DTR #if SPI_TIMING_PSRAM_DTR_MODE && CONFIG_SPIRAM_SPEED_80M -#define SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ 160 +#define SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ 160 #endif -#endif //#if CONFIG_SPIRAM_MODE_OCT -/* QUAD PSRAM Operation Mode should be added here if needed */ - - -//------------------------------------------Get the timing tuning config-----------------------------------------------// -#ifdef SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ -//FLASH needs tuning, and it expects this core clock: SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ -#define SPI_TIMING_FLASH_NEEDS_TUNING 1 +//PSRAM 120M STR +#if SPI_TIMING_PSRAM_STR_MODE && CONFIG_SPIRAM_SPEED_120M +#if (SPI_TIMING_CORE_CLOCK_DIV == 2) +#define SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ 240 +#elif (SPI_TIMING_CORE_CLOCK_DIV == 1) +#define SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ 120 #endif +#endif //PSRAM 120M STR -#ifdef SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ -//PSRAM needs tuning, and it expects this core clock: SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ -#define SPI_TIMING_PSRAM_NEEDS_TUNING 1 -#endif -//If both FLASH and PSRAM need tuning, the core clock should be same +//------------------------------------------Determine the Core Clock-----------------------------------------------// +/** + * @note + * Limitation 1: + * On 728, MSPI FLASH and PSRAM share the core clock register. Therefore, + * the expected CORE CLOCK frequencies should be the same. + */ #if SPI_TIMING_FLASH_NEEDS_TUNING && SPI_TIMING_PSRAM_NEEDS_TUNING _Static_assert(SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ == SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ, "FLASH and PSRAM Mode configuration are not supported"); -#define SPI_TIMING_CORE_CLOCK_MHZ SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ +#define SPI_TIMING_CORE_CLOCK_MHZ SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ -//If only FLASH needs tuning, the core clock could be as FLASH expected +//If only FLASH needs tuning, the core clock COULD be as FLASH expected #elif SPI_TIMING_FLASH_NEEDS_TUNING && !SPI_TIMING_PSRAM_NEEDS_TUNING -#define SPI_TIMING_CORE_CLOCK_MHZ SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ +_Static_assert(SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ % SPI_TIMING_PSRAM_MODULE_CLOCK == 0, "FLASH and PSRAM Mode configuration are not supported"); +#define SPI_TIMING_CORE_CLOCK_MHZ SPI_TIMING_FLASH_EXPECTED_CORE_CLK_MHZ -//If only PSRAM needs tuning, the core clock could be as PSRAM expected +//If only PSRAM needs tuning, the core clock COULD be as PSRAM expected #elif !SPI_TIMING_FLASH_NEEDS_TUNING && SPI_TIMING_PSRAM_NEEDS_TUNING -#define SPI_TIMING_CORE_CLOCK_MHZ SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ +_Static_assert(SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ % SPI_TIMING_FLASH_MODULE_CLOCK == 0, "FLASH and PSRAM Mode configuration are not supported"); +#define SPI_TIMING_CORE_CLOCK_MHZ SPI_TIMING_PSRAM_EXPECTED_CORE_CLK_MHZ #else #define SPI_TIMING_CORE_CLOCK_MHZ 80 #endif +/** + * @note + * Limitation 2: DDR mode requires the core clock divider (core_clk / div = module_clk) to be power of 2. + */ +#define CHECK_POWER_OF_2(n) ((((n) & ((~(n)) + 1))) == (n)) + +#if SPI_TIMING_FLASH_DTR_MODE +_Static_assert(CHECK_POWER_OF_2(SPI_TIMING_CORE_CLOCK_MHZ / SPI_TIMING_FLASH_MODULE_CLOCK), "FLASH and PSRAM Mode configuration are not supported"); +#endif +#if SPI_TIMING_PSRAM_DTR_MODE +_Static_assert(CHECK_POWER_OF_2(SPI_TIMING_CORE_CLOCK_MHZ / SPI_TIMING_PSRAM_MODULE_CLOCK), "FLASH and PSRAM Mode configuration are not supported"); +#endif + + //------------------------------------------Helper Macros to get FLASH/PSRAM tuning configs-----------------------------------------------// #define __GET_TUNING_CONFIG(type, core_clock, module_clock, mode) \ (spi_timing_config_t) { .tuning_config_table = MSPI_TIMING_##type##_CONFIG_TABLE_CORE_CLK_##core_clock##M_MODULE_CLK_##module_clock##M_##mode, \ @@ -167,6 +233,23 @@ void spi_timing_config_psram_set_extra_dummy(uint8_t spi_num, uint8_t extra_dumm void spi_timing_config_psram_write_data(uint8_t spi_num, uint8_t *buf, uint32_t addr, uint32_t len); void spi_timing_config_psram_read_data(uint8_t spi_num,uint8_t *buf, uint32_t addr, uint32_t len); +/*------------------------------------------------------------------------------------------------- + * SPI1 Timing Tuning APIs + * These APIs are only used in `spi_flash_timing_tuning.c/sweep_for_success_sample_points()` for + * configuring SPI1 timing tuning related registers to find best tuning parameter + *-------------------------------------------------------------------------------------------------*/ +void spi_timing_config_flash_tune_din_num_mode(uint8_t din_mode, uint8_t din_num); +void spi_timing_config_flash_tune_dummy(uint8_t extra_dummy); +void spi_timing_config_psram_tune_din_num_mode(uint8_t din_mode, uint8_t din_num); +void spi_timing_config_psram_tune_dummy(uint8_t extra_dummy); + +/** + * SPI1 register info get APIs. These APIs inform `spi_flash_timing_tuning.c` (driver layer) of the SPI1 flash settings. + * In this way, other components (e.g.: esp_flash driver) can get the info from it. + */ +void spi_timing_config_get_cs_timing(uint8_t *setup_time, uint32_t *hold_time); +uint32_t spi_timing_config_get_flash_clock_reg(void); + #ifdef __cplusplus } #endif diff --git a/components/spi_flash/esp_flash_api.c b/components/spi_flash/esp_flash_api.c index f077d7eb33..dacfda2580 100644 --- a/components/spi_flash/esp_flash_api.c +++ b/components/spi_flash/esp_flash_api.c @@ -27,6 +27,17 @@ #if CONFIG_IDF_TARGET_ESP32S2 #include "esp_crypto_lock.h" // for locking flash encryption peripheral #endif //CONFIG_IDF_TARGET_ESP32S2 +#if CONFIG_IDF_TARGET_ESP32 +#include "esp32/rom/spi_flash.h" +#elif CONFIG_IDF_TARGET_ESP32S2 +#include "esp32s2/rom/spi_flash.h" +#elif CONFIG_IDF_TARGET_ESP32S3 +#include "esp32s3/rom/spi_flash.h" +#elif CONFIG_IDF_TARGET_ESP32C3 +#include "esp32c3/rom/spi_flash.h" +#elif CONFIG_IDF_TARGET_ESP32H2 +#include "esp32h2/rom/spi_flash.h" +#endif static const char TAG[] = "spi_flash"; @@ -58,7 +69,7 @@ static const char TAG[] = "spi_flash"; } while(0) #endif // CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED -#define IO_STR_LEN 7 +#define IO_STR_LEN 10 static const char io_mode_str[][IO_STR_LEN] = { "slowrd", @@ -67,9 +78,12 @@ static const char io_mode_str[][IO_STR_LEN] = { "dio", "qout", "qio", + [6 ... 15] = "not used", // reserved io mode for future, not used currently. + "opi_str", + "opi_dtr", }; -_Static_assert(sizeof(io_mode_str)/IO_STR_LEN == SPI_FLASH_READ_MODE_MAX, "the io_mode_str should be consistent with the esp_flash_io_mode_t defined in spi_flash_ll.h"); +_Static_assert(sizeof(io_mode_str)/IO_STR_LEN == SPI_FLASH_READ_MODE_MAX, "the io_mode_str should be consistent with the esp_flash_io_mode_t defined in spi_flash_types.h"); esp_err_t esp_flash_read_chip_id(esp_flash_t* chip, uint32_t* flash_id); @@ -247,6 +261,84 @@ esp_err_t IRAM_ATTR esp_flash_init(esp_flash_t *chip) return rom_spiflash_api_funcs->end(chip, err); } +// Note: This function is only used for internal. Only call this function to initialize the main flash. +// (flash chip on SPI1 CS0) +esp_err_t IRAM_ATTR esp_flash_init_main(esp_flash_t *chip) +{ + // Chip init flow + // 1. Read chip id + // 2. (optional) Detect chip vendor + // 3. Get basic parameters of the chip (size, dummy count, etc.) + // 4. Init chip into desired mode (without breaking the cache!) + esp_err_t err = ESP_OK; + bool octal_mode = (chip->read_mode >= SPI_FLASH_OPI_FLAG); + if (chip == NULL || chip->host == NULL || chip->host->driver == NULL || + ((memspi_host_inst_t*)chip->host)->spi == NULL) { + return ESP_ERR_INVALID_ARG; + } + + //read chip id + // This can indicate the MSPI support OPI, if the flash works on MSPI in OPI mode, we directly bypass read id. + uint32_t flash_id = 0; + if (octal_mode) { + // bypass the reading but get the flash_id from the ROM variable, to avoid resetting the chip to QSPI mode and read the ID again + flash_id = g_rom_flashchip.device_id; + } else { + int retries = 10; + do { + err = esp_flash_read_chip_id(chip, &flash_id); + } while (err == ESP_ERR_FLASH_NOT_INITIALISED && retries-- > 0); + } + + if (err != ESP_OK) { + return err; + } + chip->chip_id = flash_id; + + if (!esp_flash_chip_driver_initialized(chip)) { + // Detect chip_drv + err = detect_spi_flash_chip(chip); + if (err != ESP_OK) { + return err; + } + } + + // Detect flash size + uint32_t size; + err = esp_flash_get_size(chip, &size); + if (err != ESP_OK) { + ESP_LOGE(TAG, "failed to get chip size"); + return err; + } + + if (chip->chip_drv->get_chip_caps == NULL) { + // chip caps get failed, pass the flash capability check. + ESP_LOGW(TAG, "get_chip_caps function pointer hasn't been initialized"); + } else { + if (((chip->chip_drv->get_chip_caps(chip) & SPI_FLASH_CHIP_CAP_32MB_SUPPORT) == 0) && (size > (16 *1024 * 1024))) { + ESP_LOGW(TAG, "Detected flash size > 16 MB, but access beyond 16 MB is not supported for this flash model yet."); + size = (16 * 1024 * 1024); + } + } + + ESP_LOGI(TAG, "flash io: %s", io_mode_str[chip->read_mode]); + err = rom_spiflash_api_funcs->start(chip); + if (err != ESP_OK) { + return err; + } + + if (err == ESP_OK && !octal_mode) { + // Try to set the flash mode to whatever default mode was chosen + err = chip->chip_drv->set_io_mode(chip); + if (err == ESP_ERR_FLASH_NO_RESPONSE && !esp_flash_is_quad_mode(chip)) { + //some chips (e.g. Winbond) don't support to clear QE, treat as success + err = ESP_OK; + } + } + // Done: all fields on 'chip' are initialised + return rom_spiflash_api_funcs->end(chip, err); +} + static esp_err_t IRAM_ATTR read_id_core(esp_flash_t* chip, uint32_t* out_id, bool sanity_check) { bool installed = esp_flash_chip_driver_initialized(chip); diff --git a/components/spi_flash/esp_flash_spi_init.c b/components/spi_flash/esp_flash_spi_init.c index 934ec7b2a2..79605e56c8 100644 --- a/components/spi_flash/esp_flash_spi_init.c +++ b/components/spi_flash/esp_flash_spi_init.c @@ -27,6 +27,7 @@ #include "hal/gpio_hal.h" #include "esp_flash_internal.h" #include "esp_rom_gpio.h" +#include "spi_flash_private.h" #if CONFIG_IDF_TARGET_ESP32 #include "esp32/rom/spi_flash.h" #elif CONFIG_IDF_TARGET_ESP32S2 @@ -41,6 +42,13 @@ __attribute__((unused)) static const char TAG[] = "spi_flash"; +/* This pointer is defined in ROM and extern-ed on targets where CONFIG_SPI_FLASH_ROM_IMPL = y*/ +#if !CONFIG_SPI_FLASH_ROM_IMPL +esp_flash_t *esp_flash_default_chip = NULL; +#endif + +#ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL + #ifdef CONFIG_ESPTOOLPY_FLASHFREQ_80M #define DEFAULT_FLASH_SPEED ESP_FLASH_80MHZ #elif defined CONFIG_ESPTOOLPY_FLASHFREQ_40M @@ -49,6 +57,8 @@ __attribute__((unused)) static const char TAG[] = "spi_flash"; #define DEFAULT_FLASH_SPEED ESP_FLASH_26MHZ #elif defined CONFIG_ESPTOOLPY_FLASHFREQ_20M #define DEFAULT_FLASH_SPEED ESP_FLASH_20MHZ +#elif defined CONFIG_ESPTOOLPY_FLASHFREQ_120M +#define DEFAULT_FLASH_SPEED ESP_FLASH_120MHZ #else #error Flash frequency not defined! Check the ``CONFIG_ESPTOOLPY_FLASHFREQ_*`` options. #endif @@ -61,6 +71,10 @@ __attribute__((unused)) static const char TAG[] = "spi_flash"; #define DEFAULT_FLASH_MODE SPI_FLASH_DIO #elif defined(CONFIG_ESPTOOLPY_FLASHMODE_DOUT) #define DEFAULT_FLASH_MODE SPI_FLASH_DOUT +#elif defined(CONFIG_ESPTOOLPY_FLASHMODE_OPI_STR) +#define DEFAULT_FLASH_MODE SPI_FLASH_OPI_STR +#elif defined(CONFIG_ESPTOOLPY_FLASHMODE_OPI_DTR) +#define DEFAULT_FLASH_MODE SPI_FLASH_OPI_DTR #else #define DEFAULT_FLASH_MODE SPI_FLASH_FASTRD #endif @@ -264,13 +278,6 @@ esp_err_t spi_bus_remove_flash_device(esp_flash_t *chip) /* The default (ie initial boot) no-OS ROM esp_flash_os_functions_t */ extern const esp_flash_os_functions_t esp_flash_noos_functions; -/* This pointer is defined in ROM and extern-ed on targets where CONFIG_SPI_FLASH_ROM_IMPL = y*/ -#if !CONFIG_SPI_FLASH_ROM_IMPL -esp_flash_t *esp_flash_default_chip = NULL; -#endif - -#ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL - static DRAM_ATTR memspi_host_inst_t esp_flash_default_host; static DRAM_ATTR esp_flash_t default_chip = { @@ -290,6 +297,19 @@ esp_err_t esp_flash_init_default_chip(void) cfg.iomux = esp_rom_efuse_get_flash_gpio_info() == 0 ? true : false; #endif + #if CONFIG_ESPTOOLPY_OCT_FLASH + cfg.octal_mode_en = 1; + cfg.default_io_mode = DEFAULT_FLASH_MODE; + #endif + + // For chips need time tuning, get value directely from system here. + #if SOC_SPI_MEM_SUPPORT_TIME_TUNING + if (spi_timine_config_flash_is_tuned()) { + cfg.using_timing_tuning = 1; + spi_timing_get_flash_timing_param(&cfg.timing_reg); + } + #endif // SOC_SPI_MEM_SUPPORT_TIME_TUNING + //the host is already initialized, only do init for the data and load it to the host esp_err_t err = memspi_host_init_pointers(&esp_flash_default_host, &cfg); if (err != ESP_OK) { @@ -298,7 +318,7 @@ esp_err_t esp_flash_init_default_chip(void) // ROM TODO: account for non-standard default pins in efuse // ROM TODO: to account for chips which are slow to power on, maybe keep probing in a loop here - err = esp_flash_init(&default_chip); + err = esp_flash_init_main(&default_chip); if (err != ESP_OK) { return err; } diff --git a/components/spi_flash/flash_ops.c b/components/spi_flash/flash_ops.c index c928634706..116f07ec31 100644 --- a/components/spi_flash/flash_ops.c +++ b/components/spi_flash/flash_ops.c @@ -39,6 +39,7 @@ #elif CONFIG_IDF_TARGET_ESP32S3 #include "soc/spi_mem_reg.h" #include "esp32s3/rom/spi_flash.h" +#include "esp32s3/rom/opi_flash.h" #include "esp32s3/rom/cache.h" #include "esp32s3/clk.h" #include "esp32s3/clk.h" @@ -55,7 +56,6 @@ #include "cache_utils.h" #include "esp_flash.h" #include "esp_attr.h" -#include "spi_flash_private.h" #include "bootloader_flash.h" esp_rom_spiflash_result_t IRAM_ATTR spi_flash_write_encrypted_chip(size_t dest_addr, const void *src, size_t size); @@ -164,6 +164,17 @@ void IRAM_ATTR *spi_flash_malloc_internal(size_t size) } #endif +void IRAM_ATTR esp_mspi_pin_init(void) +{ +#if CONFIG_ESPTOOLPY_OCT_FLASH || CONFIG_SPIRAM_MODE_OCT + esp_rom_opiflash_pin_config(); + extern void spi_timing_set_pin_drive_strength(void); + spi_timing_set_pin_drive_strength(); +#else + //Set F4R4 board pin drive strength. TODO: IDF-3663 +#endif +} + void spi_flash_init(void) { spi_flash_init_lock(); @@ -506,6 +517,7 @@ out: #endif // CONFIG_SPI_FLASH_USE_LEGACY_IMPL #if !CONFIG_SPI_FLASH_USE_LEGACY_IMPL +#if !CONFIG_ESPTOOLPY_OCT_FLASH // Test for encryption on opi flash, IDF-3852. extern void spi_common_set_dummy_output(esp_rom_spiflash_read_mode_t mode); extern void spi_dummy_len_fix(uint8_t spi, uint8_t freqdiv); void IRAM_ATTR flash_rom_init(void) @@ -559,6 +571,7 @@ void IRAM_ATTR flash_rom_init(void) #endif //!CONFIG_IDF_TARGET_ESP32S2 esp_rom_spiflash_config_clk(freqdiv, 1); } +#endif //CONFIG_ESPTOOLPY_OCT_FLASH #else void IRAM_ATTR flash_rom_init(void) { diff --git a/components/spi_flash/include/esp_partition.h b/components/spi_flash/include/esp_partition.h index e59babb451..36baea2986 100644 --- a/components/spi_flash/include/esp_partition.h +++ b/components/spi_flash/include/esp_partition.h @@ -87,6 +87,7 @@ typedef enum { ESP_PARTITION_SUBTYPE_DATA_COREDUMP = 0x03, //!< COREDUMP partition ESP_PARTITION_SUBTYPE_DATA_NVS_KEYS = 0x04, //!< Partition for NVS keys ESP_PARTITION_SUBTYPE_DATA_EFUSE_EM = 0x05, //!< Partition for emulate eFuse bits + ESP_PARTITION_SUBTYPE_DATA_UNDEFINED = 0x06, //!< Undefined (or unspecified) data partition ESP_PARTITION_SUBTYPE_DATA_ESPHTTPD = 0x80, //!< ESPHTTPD partition ESP_PARTITION_SUBTYPE_DATA_FAT = 0x81, //!< FAT partition 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 cf26fda148..1ff0bfdea5 100644 --- a/components/spi_flash/include/spi_flash/spi_flash_defs.h +++ b/components/spi_flash/include/spi_flash/spi_flash_defs.h @@ -68,3 +68,7 @@ #define SPI_FLASH_FASTRD_DUMMY_BITLEN 8 #define SPI_FLASH_SLOWRD_ADDR_BITLEN 24 #define SPI_FLASH_SLOWRD_DUMMY_BITLEN 0 +#define SPI_FLASH_OPISTR_ADDR_BITLEN 32 +#define SPI_FLASH_OPISTR_DUMMY_BITLEN 20 +#define SPI_FLASH_OPIDTR_ADDR_BITLEN 32 +#define SPI_FLASH_OPIDTR_DUMMY_BITLEN 40 diff --git a/components/spi_flash/include/spi_flash_chip_driver.h b/components/spi_flash/include/spi_flash_chip_driver.h index 9a143d84d2..d2ef25bf6d 100644 --- a/components/spi_flash/include/spi_flash_chip_driver.h +++ b/components/spi_flash/include/spi_flash_chip_driver.h @@ -206,6 +206,11 @@ struct spi_flash_chip_t { * Get the capabilities of the flash chip. See SPI_FLASH_CHIP_CAP_* macros as reference. */ spi_flash_caps_t (*get_chip_caps)(esp_flash_t *chip); + + /** + * Configure the host registers to use the specified read mode set in the ``chip->read_mode``. + */ + esp_err_t (*config_host_io_mode)(esp_flash_t *chip, uint32_t flags); }; /* Pointer to an array of pointers to all known drivers for flash chips. This array is used diff --git a/components/spi_flash/include/spi_flash_chip_generic.h b/components/spi_flash/include/spi_flash_chip_generic.h index 9e99f73e44..019a6966a4 100644 --- a/components/spi_flash/include/spi_flash_chip_generic.h +++ b/components/spi_flash/include/spi_flash_chip_generic.h @@ -370,14 +370,15 @@ esp_err_t spi_flash_common_set_io_mode(esp_flash_t *chip, esp_flash_wrsr_func_t * transactions. Also prepare the command to be sent in read functions. * * @param chip Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted. - * @param addr_32bit Whether 32 bit commands will be used (Currently only W25Q256 and GD25Q256 are supported) + * @param flags Special rules to configure io mode, (i.e. Whether 32 bit commands will be used (Currently only W25Q256 and GD25Q256 are supported)) * * @return * - ESP_OK if success * - ESP_ERR_FLASH_NOT_INITIALISED if chip not initialized properly * - or other error passed from the ``configure_host_mode`` function of host driver */ -esp_err_t spi_flash_chip_generic_config_host_io_mode(esp_flash_t *chip, bool addr_32bit); +esp_err_t spi_flash_chip_generic_config_host_io_mode(esp_flash_t *chip, uint32_t flags); +#define SPI_FLASH_CONFIG_IO_MODE_32B_ADDR BIT(0) /** * @brief Handle explicit yield requests @@ -396,5 +397,15 @@ esp_err_t spi_flash_chip_generic_yield(esp_flash_t* chip, uint32_t wip); */ esp_err_t spi_flash_chip_generic_suspend_cmd_conf(esp_flash_t *chip); +/** + * + * @brief Read the chip unique ID unsupported function. + * + * @param chip Pointer to SPI flash chip to use. + * @param flash_unique_id Pointer to store output unique id (Although this function is an unsupported function, but the parameter should be kept for the consistence of the function pointer). + * @return Always ESP_ERR_NOT_SUPPORTED. + */ +esp_err_t spi_flash_chip_generic_read_unique_id_none(esp_flash_t *chip, uint64_t* flash_unique_id); + /// Default timeout configuration used by most chips -const flash_chip_op_timeout_t spi_flash_chip_generic_timeout; +extern const flash_chip_op_timeout_t spi_flash_chip_generic_timeout; diff --git a/components/spi_flash/include/spi_flash_chip_mxic.h b/components/spi_flash/include/spi_flash_chip_mxic.h index f998c1564e..201ad496e2 100644 --- a/components/spi_flash/include/spi_flash_chip_mxic.h +++ b/components/spi_flash/include/spi_flash_chip_mxic.h @@ -25,3 +25,10 @@ * is not found. */ extern const spi_flash_chip_t esp_flash_chip_mxic; + +/** + * MXIC OPI flash chip_drv, uses all the above functions for its operations. In + * default autodetection, this is used as a catchall if a more specific chip_drv + * is not found. + */ +extern const spi_flash_chip_t esp_flash_chip_mxic_opi; diff --git a/components/spi_flash/include/spi_flash_private.h b/components/spi_flash/include/spi_flash_private.h index f792faef65..9d822fb947 100644 --- a/components/spi_flash/include/spi_flash_private.h +++ b/components/spi_flash/include/spi_flash_private.h @@ -26,6 +26,8 @@ #elif CONFIG_IDF_TARGET_ESP32S3 #include "esp32s3/rom/spi_flash.h" #endif +#include "esp_flash.h" +#include "hal/spi_flash_hal.h" #ifdef __cplusplus extern "C" { @@ -38,13 +40,15 @@ esp_err_t esp_opiflash_init(void); /** * @brief Make MSPI work under 20Mhz + * @param control_spi1 Select whether to control SPI1. For tuning, we need to use SPI1. After tuning (during startup stage), let the flash driver to control SPI1 */ -void spi_timing_enter_mspi_low_speed_mode(void); +void spi_timing_enter_mspi_low_speed_mode(bool control_spi1); /** * @brief Make MSPI work under the frequency as users set + * @param control_spi1 Select whether to control SPI1. For tuning, we need to use SPI1. After tuning (during startup stage), let the flash driver to control SPI1 */ -void spi_timing_enter_mspi_high_speed_mode(void); +void spi_timing_enter_mspi_high_speed_mode(bool control_spi1); /** * @brief Tune MSPI flash timing to make it work under high frequency @@ -56,12 +60,34 @@ void spi_timing_flash_tuning(void); */ void spi_timing_psram_tuning(void); +/** + * @brief To initislize the MSPI pins + */ +void esp_mspi_pin_init(void); + /** * @brief Set SPI1 registers to make ROM functions work * @note This function is used for setting SPI1 registers to the state that ROM SPI functions work */ void spi_flash_set_rom_required_regs(void); +/** + * @brief Initialize main flash + * @param chip Pointer to main SPI flash(SPI1 CS0) chip to use.. + */ +esp_err_t esp_flash_init_main(esp_flash_t *chip); + +/** + * @brief Should be only used by SPI1 Flash driver to know the necessary timing registers + * @param out_timing_config Pointer to timing_tuning parameters. + */ +void spi_timing_get_flash_timing_param(spi_flash_hal_timing_config_t *out_timing_config); + +/** + * @brief Judge if the flash in tuned + */ +bool spi_timine_config_flash_is_tuned(void); + #ifdef __cplusplus } #endif diff --git a/components/spi_flash/linker.lf b/components/spi_flash/linker.lf index ae285a1c2c..92beb351a8 100644 --- a/components/spi_flash/linker.lf +++ b/components/spi_flash/linker.lf @@ -14,6 +14,10 @@ entries: if IDF_TARGET_ESP32S3 = y: spi_flash_timing_tuning (noflash) + spi_timing_config (noflash) if IDF_TARGET_ESP32S3 = y && ESPTOOLPY_OCT_FLASH = y: spi_flash_oct_flash_init (noflash) + + if IDF_TARGET_ESP32S3 = y : + spi_flash_chip_mxic_opi (noflash) diff --git a/components/spi_flash/memspi_host_driver.c b/components/spi_flash/memspi_host_driver.c index 9194201073..b242c9512b 100644 --- a/components/spi_flash/memspi_host_driver.c +++ b/components/spi_flash/memspi_host_driver.c @@ -207,19 +207,47 @@ esp_err_t memspi_host_set_write_protect(spi_flash_host_inst_t *host, bool wp) // This is the simple case where the hardware has no other requirements than the size and page boundary int memspi_host_write_data_slicer(spi_flash_host_inst_t *host, uint32_t address, uint32_t len, uint32_t *align_address, uint32_t page_size) { + uint32_t slicer_flag = ((spi_flash_hal_context_t*)host)->slicer_flags; uint32_t align_addr = address; + + if (slicer_flag & SPI_FLASH_HOST_CONTEXT_SLICER_FLAG_DTR) { + if (((align_addr % 2) != 0) && ((len % 2) != 0)) { + align_addr -= 1; + len += 1; + } else if (((align_addr % 2) != 0) && ((len % 2) == 0)) { + align_addr -= 1; + len += 2; + } else if (((align_addr % 2) == 0) && ((len % 2) != 0)) { + len += 1; + } + } + uint32_t end_bound = (align_addr/page_size + 1) * page_size; // Shouldn't program cross the page, or longer than SPI_FLASH_HAL_MAX_WRITE_BYTES uint32_t max_len = MIN(end_bound - align_addr, SPI_FLASH_HAL_MAX_WRITE_BYTES); - *align_address = address; + *align_address = align_addr; return MIN(max_len, len); } int memspi_host_read_data_slicer(spi_flash_host_inst_t *host, uint32_t address, uint32_t len, uint32_t *align_address, uint32_t page_size) { // Shouldn't read longer than SPI_FLASH_HAL_MAX_READ_BYTES + uint32_t slicer_flag = ((spi_flash_hal_context_t*)host)->slicer_flags; + uint32_t align_addr = address; + + if (slicer_flag & SPI_FLASH_HOST_CONTEXT_SLICER_FLAG_DTR) { + if (((align_addr % 2) != 0) && ((len % 2) != 0)) { + align_addr -= 1; + len += 1; + } else if (((align_addr % 2) != 0) && ((len % 2) == 0)) { + align_addr -= 1; + len += 2; + } else if (((align_addr % 2) == 0) && ((len % 2) != 0)) { + len += 1; + } + } uint32_t max_len = SPI_FLASH_HAL_MAX_READ_BYTES; - *align_address = address; + *align_address = align_addr; return MIN(max_len, len); } diff --git a/components/spi_flash/mock/mock_config.yaml b/components/spi_flash/mock/mock_config.yaml index 60dd3b5267..392ecceea7 100644 --- a/components/spi_flash/mock/mock_config.yaml +++ b/components/spi_flash/mock/mock_config.yaml @@ -5,3 +5,4 @@ - return_thru_ptr - array - callback + - ignore_arg diff --git a/components/spi_flash/sim/stubs/esp_common/esp_err.h b/components/spi_flash/sim/stubs/esp_common/esp_err.h deleted file mode 100644 index d52b19f657..0000000000 --- a/components/spi_flash/sim/stubs/esp_common/esp_err.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - * - * This is a STUB FILE HEADER used when compiling ESP-IDF to run tests on the host system. - * The header file used normally for ESP-IDF has the same name but is located elsewhere. - */ -#pragma once - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef int32_t esp_err_t; - -/* Definitions for error constants. */ -#define ESP_OK 0 /*!< esp_err_t value indicating success (no error) */ -#define ESP_FAIL -1 /*!< Generic esp_err_t code indicating failure */ - -#define ESP_ERR_NO_MEM 0x101 /*!< Out of memory */ -#define ESP_ERR_INVALID_ARG 0x102 /*!< Invalid argument */ -#define ESP_ERR_INVALID_STATE 0x103 /*!< Invalid state */ -#define ESP_ERR_INVALID_SIZE 0x104 /*!< Invalid size */ -#define ESP_ERR_NOT_FOUND 0x105 /*!< Requested resource not found */ -#define ESP_ERR_NOT_SUPPORTED 0x106 /*!< Operation or feature not supported */ -#define ESP_ERR_TIMEOUT 0x107 /*!< Operation timed out */ -#define ESP_ERR_INVALID_RESPONSE 0x108 /*!< Received response was invalid */ -#define ESP_ERR_INVALID_CRC 0x109 /*!< CRC or checksum was invalid */ -#define ESP_ERR_INVALID_VERSION 0x10A /*!< Version was invalid */ -#define ESP_ERR_INVALID_MAC 0x10B /*!< MAC address was invalid */ - -#define ESP_ERR_WIFI_BASE 0x3000 /*!< Starting number of WiFi error codes */ -#define ESP_ERR_MESH_BASE 0x4000 /*!< Starting number of MESH error codes */ -#define ESP_ERR_FLASH_BASE 0x6000 /*!< Starting number of flash error codes */ - -/** - * @brief Returns string for esp_err_t error codes - * - * This function finds the error code in a pre-generated lookup-table and - * returns its string representation. - * - * The function is generated by the Python script - * tools/gen_esp_err_to_name.py which should be run each time an esp_err_t - * error is modified, created or removed from the IDF project. - * - * @param code esp_err_t error code - * @return string error message - */ -const char *esp_err_to_name(esp_err_t code); - -/** - * @brief Returns string for esp_err_t and system error codes - * - * This function finds the error code in a pre-generated lookup-table of - * esp_err_t errors and returns its string representation. If the error code - * is not found then it is attempted to be found among system errors. - * - * The function is generated by the Python script - * tools/gen_esp_err_to_name.py which should be run each time an esp_err_t - * error is modified, created or removed from the IDF project. - * - * @param code esp_err_t error code - * @param[out] buf buffer where the error message should be written - * @param buflen Size of buffer buf. At most buflen bytes are written into the buf buffer (including the terminating null byte). - * @return buf containing the string error message - */ -const char *esp_err_to_name_r(esp_err_t code, char *buf, size_t buflen); - -/** @cond */ -void _esp_error_check_failed(esp_err_t rc, const char *file, int line, const char *function, const char *expression) __attribute__((noreturn)); - -/** @cond */ -void _esp_error_check_failed_without_abort(esp_err_t rc, const char *file, int line, const char *function, const char *expression); - -#ifndef __ASSERT_FUNC -/* This won't happen on IDF, which defines __ASSERT_FUNC in assert.h, but it does happen when building on the host which - uses /usr/include/assert.h or equivalent. -*/ -#ifdef __ASSERT_FUNCTION -#define __ASSERT_FUNC __ASSERT_FUNCTION /* used in glibc assert.h */ -#else -#define __ASSERT_FUNC "??" -#endif -#endif -/** @endcond */ - -/** - * Macro which can be used to check the error code, - * and terminate the program in case the code is not ESP_OK. - * Prints the error code, error location, and the failed statement to serial output. - * - * Disabled if assertions are disabled. - */ -#ifdef NDEBUG -#define ESP_ERROR_CHECK(x) do { \ - esp_err_t __err_rc = (x); \ - (void) sizeof(__err_rc); \ - } while(0) -#elif defined(CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT) -#define ESP_ERROR_CHECK(x) do { \ - esp_err_t __err_rc = (x); \ - if (__err_rc != ESP_OK) { \ - abort(); \ - } \ - } while(0) -#else -#define ESP_ERROR_CHECK(x) do { \ - esp_err_t __err_rc = (x); \ - if (__err_rc != ESP_OK) { \ - _esp_error_check_failed(__err_rc, __FILE__, __LINE__, \ - __ASSERT_FUNC, #x); \ - } \ - } while(0) -#endif - -/** - * Macro which can be used to check the error code. Prints the error code, error location, and the failed statement to - * serial output. - * In comparison with ESP_ERROR_CHECK(), this prints the same error message but isn't terminating the program. - */ -#ifdef NDEBUG -#define ESP_ERROR_CHECK_WITHOUT_ABORT(x) ({ \ - esp_err_t __err_rc = (x); \ - __err_rc; \ - }) -#else -#define ESP_ERROR_CHECK_WITHOUT_ABORT(x) ({ \ - esp_err_t __err_rc = (x); \ - if (__err_rc != ESP_OK) { \ - _esp_error_check_failed_without_abort(__err_rc, __FILE__, __LINE__, \ - __ASSERT_FUNC, #x); \ - } \ - __err_rc; \ - }) -#endif //NDEBUG - -#ifdef __cplusplus -} -#endif diff --git a/components/spi_flash/sim/stubs/spi_flash/esp_partition.h b/components/spi_flash/sim/stubs/spi_flash/esp_partition.h index 632321e381..c2d78a46b2 100644 --- a/components/spi_flash/sim/stubs/spi_flash/esp_partition.h +++ b/components/spi_flash/sim/stubs/spi_flash/esp_partition.h @@ -51,6 +51,7 @@ typedef enum { ESP_PARTITION_SUBTYPE_DATA_COREDUMP = 0x03, //!< COREDUMP partition ESP_PARTITION_SUBTYPE_DATA_NVS_KEYS = 0x04, //!< Partition for NVS keys ESP_PARTITION_SUBTYPE_DATA_EFUSE_EM = 0x05, //!< Partition for emulate eFuse bits + ESP_PARTITION_SUBTYPE_DATA_UNDEFINED = 0x06, //!< Undefined (or unspecified) data partition ESP_PARTITION_SUBTYPE_DATA_ESPHTTPD = 0x80, //!< ESPHTTPD partition ESP_PARTITION_SUBTYPE_DATA_FAT = 0x81, //!< FAT partition diff --git a/components/spi_flash/sim/stubs/xtensa/esp_attr.h b/components/spi_flash/sim/stubs/xtensa/esp_attr.h deleted file mode 100644 index ea1f030634..0000000000 --- a/components/spi_flash/sim/stubs/xtensa/esp_attr.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - * - * This is a STUB FILE HEADER used when compiling ESP-IDF to run tests on the host system. - * The header file used normally for ESP-IDF has the same name but is located elsewhere. - */ -#ifndef __ESP_ATTR_H__ -#define __ESP_ATTR_H__ - -#include "sdkconfig.h" - -#define ROMFN_ATTR - -//Normally, the linker script will put all code and rodata in flash, -//and all variables in shared RAM. These macros can be used to redirect -//particular functions/variables to other memory regions. - -// Forces code into IRAM instead of flash -#define IRAM_ATTR _SECTION_ATTR_IMPL(".iram1", __COUNTER__) - -// Forces data into DRAM instead of flash -#define DRAM_ATTR _SECTION_ATTR_IMPL(".dram1", __COUNTER__) - -#ifdef CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY -// Forces data into IRAM instead of DRAM -#define IRAM_DATA_ATTR __attribute__((section(".iram.data"))) - -// Forces data into IRAM instead of DRAM and map it to coredump -#define COREDUMP_IRAM_DATA_ATTR _SECTION_ATTR_IMPL(".iram.data.coredump", __COUNTER__) - -// Forces bss into IRAM instead of DRAM -#define IRAM_BSS_ATTR __attribute__((section(".iram.bss"))) -#else -#define COREDUMP_IRAM_DATA_ATTR -#define IRAM_DATA_ATTR - -#define IRAM_BSS_ATTR -#endif - -// Forces data to be 4 bytes aligned -#define WORD_ALIGNED_ATTR __attribute__((aligned(4))) - -// Forces data to be placed to DMA-capable places -#define DMA_ATTR WORD_ALIGNED_ATTR DRAM_ATTR - -// Forces a function to be inlined -#define FORCE_INLINE_ATTR static inline __attribute__((always_inline)) - -// Forces a string into DRAM instead of flash -// Use as esp_rom_printf(DRAM_STR("Hello world!\n")); -#define DRAM_STR(str) (__extension__({static const DRAM_ATTR char __c[] = (str); (const char *)&__c;})) - -// Forces code into RTC fast memory. See "docs/deep-sleep-stub.rst" -#define RTC_IRAM_ATTR _SECTION_ATTR_IMPL(".rtc.text", __COUNTER__) - -#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY -// Forces bss variable into external memory. " -#define EXT_RAM_ATTR _SECTION_ATTR_IMPL(".ext_ram.bss", __COUNTER__) -#else -#define EXT_RAM_ATTR -#endif - -// Forces data into RTC slow memory. See "docs/deep-sleep-stub.rst" -// Any variable marked with this attribute will keep its value -// during a deep sleep / wake cycle. -#define RTC_DATA_ATTR _SECTION_ATTR_IMPL(".rtc.data", __COUNTER__) - -// Forces read-only data into RTC memory. See "docs/deep-sleep-stub.rst" -#define RTC_RODATA_ATTR _SECTION_ATTR_IMPL(".rtc.rodata", __COUNTER__) - -// Allows to place data into RTC_SLOW memory. -#define RTC_SLOW_ATTR _SECTION_ATTR_IMPL(".rtc.force_slow", __COUNTER__) - -// Allows to place data into RTC_FAST memory. -#define RTC_FAST_ATTR _SECTION_ATTR_IMPL(".rtc.force_fast", __COUNTER__) - -// Forces data into noinit section to avoid initialization after restart. -#define __NOINIT_ATTR _SECTION_ATTR_IMPL(".noinit", __COUNTER__) - -// Forces data into RTC slow memory of .noinit section. -// Any variable marked with this attribute will keep its value -// after restart or during a deep sleep / wake cycle. -#define RTC_NOINIT_ATTR _SECTION_ATTR_IMPL(".rtc_noinit", __COUNTER__) - -// Forces code into DRAM instead of flash and map it to coredump -#define COREDUMP_DRAM_ATTR _SECTION_ATTR_IMPL(".dram1.coredump", __COUNTER__) - -// Forces data into RTC memory and map it to coredump -#define COREDUMP_RTC_DATA_ATTR _SECTION_ATTR_IMPL(".rtc.coredump", __COUNTER__) - -// Allows to place data into RTC_FAST memory and map it to coredump -#define COREDUMP_RTC_FAST_ATTR _SECTION_ATTR_IMPL(".rtc.fast.coredump", __COUNTER__) - -// Forces to not inline function -#define NOINLINE_ATTR __attribute__((noinline)) - -// This allows using enum as flags in C++ -// Format: FLAG_ATTR(flag_enum_t) -#ifdef __cplusplus - -// Inline is required here to avoid multiple definition error in linker -#define FLAG_ATTR_IMPL(TYPE, INT_TYPE) \ -FORCE_INLINE_ATTR constexpr TYPE operator~ (TYPE a) { return (TYPE)~(INT_TYPE)a; } \ -FORCE_INLINE_ATTR constexpr TYPE operator| (TYPE a, TYPE b) { return (TYPE)((INT_TYPE)a | (INT_TYPE)b); } \ -FORCE_INLINE_ATTR constexpr TYPE operator& (TYPE a, TYPE b) { return (TYPE)((INT_TYPE)a & (INT_TYPE)b); } \ -FORCE_INLINE_ATTR constexpr TYPE operator^ (TYPE a, TYPE b) { return (TYPE)((INT_TYPE)a ^ (INT_TYPE)b); } \ -FORCE_INLINE_ATTR constexpr TYPE operator>> (TYPE a, int b) { return (TYPE)((INT_TYPE)a >> b); } \ -FORCE_INLINE_ATTR constexpr TYPE operator<< (TYPE a, int b) { return (TYPE)((INT_TYPE)a << b); } \ -FORCE_INLINE_ATTR TYPE& operator|=(TYPE& a, TYPE b) { a = a | b; return a; } \ -FORCE_INLINE_ATTR TYPE& operator&=(TYPE& a, TYPE b) { a = a & b; return a; } \ -FORCE_INLINE_ATTR TYPE& operator^=(TYPE& a, TYPE b) { a = a ^ b; return a; } \ -FORCE_INLINE_ATTR TYPE& operator>>=(TYPE& a, int b) { a >>= b; return a; } \ -FORCE_INLINE_ATTR TYPE& operator<<=(TYPE& a, int b) { a <<= b; return a; } - -#define FLAG_ATTR_U32(TYPE) FLAG_ATTR_IMPL(TYPE, uint32_t) -#define FLAG_ATTR FLAG_ATTR_U32 - -#else -#define FLAG_ATTR(TYPE) -#endif - -// Implementation for a unique custom section -// -// This prevents gcc producing "x causes a section type conflict with y" -// errors if two variables in the same source file have different linkage (maybe const & non-const) but are placed in the same custom section -// -// Using unique sections also means --gc-sections can remove unused -// data with a custom section type set -#define _SECTION_ATTR_IMPL(SECTION, COUNTER) __attribute__((section(SECTION "." _COUNTER_STRINGIFY(COUNTER)))) - -#define _COUNTER_STRINGIFY(COUNTER) #COUNTER - -/* Use IDF_DEPRECATED attribute to mark anything deprecated from use in - ESP-IDF's own source code, but not deprecated for external users. -*/ -#ifdef IDF_CI_BUILD -#define IDF_DEPRECATED(REASON) __attribute__((deprecated(REASON))) -#else -#define IDF_DEPRECATED(REASON) -#endif - -#endif /* __ESP_ATTR_H__ */ diff --git a/components/spi_flash/spi_flash_chip_boya.c b/components/spi_flash/spi_flash_chip_boya.c index f87c337585..c2d3bd2ac5 100644 --- a/components/spi_flash/spi_flash_chip_boya.c +++ b/components/spi_flash/spi_flash_chip_boya.c @@ -83,4 +83,5 @@ const spi_flash_chip_t esp_flash_chip_boya = { .sus_setup = spi_flash_chip_generic_suspend_cmd_conf, .read_unique_id = spi_flash_chip_generic_read_unique_id, .get_chip_caps = spi_flash_chip_boya_get_caps, + .config_host_io_mode = spi_flash_chip_generic_config_host_io_mode, }; diff --git a/components/spi_flash/spi_flash_chip_drivers.c b/components/spi_flash/spi_flash_chip_drivers.c index 1c0940760a..d54963b84b 100644 --- a/components/spi_flash/spi_flash_chip_drivers.c +++ b/components/spi_flash/spi_flash_chip_drivers.c @@ -47,6 +47,9 @@ static const spi_flash_chip_t *default_registered_chips[] = { #endif #ifdef CONFIG_SPI_FLASH_SUPPORT_BOYA_CHIP &esp_flash_chip_boya, +#endif +#ifdef CONFIG_SPI_FLASH_SUPPORT_MXIC_OPI_CHIP + &esp_flash_chip_mxic_opi, #endif // Default chip drivers that will accept all chip ID. // FM, Winbond and XMC chips are supposed to be supported by this chip driver. diff --git a/components/spi_flash/spi_flash_chip_gd.c b/components/spi_flash/spi_flash_chip_gd.c index 509e008f55..b36c25e549 100644 --- a/components/spi_flash/spi_flash_chip_gd.c +++ b/components/spi_flash/spi_flash_chip_gd.c @@ -144,4 +144,5 @@ const spi_flash_chip_t esp_flash_chip_gd = { .sus_setup = spi_flash_chip_generic_suspend_cmd_conf, .read_unique_id = spi_flash_chip_generic_read_unique_id, .get_chip_caps = spi_flash_chip_gd_get_caps, + .config_host_io_mode = spi_flash_chip_generic_config_host_io_mode, }; diff --git a/components/spi_flash/spi_flash_chip_generic.c b/components/spi_flash/spi_flash_chip_generic.c index 0dc3062fd5..c1173c9b83 100644 --- a/components/spi_flash/spi_flash_chip_generic.c +++ b/components/spi_flash/spi_flash_chip_generic.c @@ -200,9 +200,10 @@ esp_err_t spi_flash_chip_generic_read(esp_flash_t *chip, void *buffer, uint32_t const uint32_t page_size = chip->chip_drv->page_size; uint32_t align_address; uint8_t temp_buffer[64]; //spiflash hal max length of read no longer than 64byte + uint32_t config_io_flags = 0; // Configure the host, and return - err = spi_flash_chip_generic_config_host_io_mode(chip, false); + err = chip->chip_drv->config_host_io_mode(chip, config_io_flags); if (err == ESP_ERR_NOT_SUPPORTED) { ESP_LOGE(TAG, "configure host io mode failed - unsupported"); @@ -448,13 +449,14 @@ esp_err_t spi_flash_chip_generic_wait_idle(esp_flash_t *chip, uint32_t timeout_u return (timeout_us > 0) ? ESP_OK : ESP_ERR_TIMEOUT; } -esp_err_t spi_flash_chip_generic_config_host_io_mode(esp_flash_t *chip, bool addr_32bit) +esp_err_t spi_flash_chip_generic_config_host_io_mode(esp_flash_t *chip, uint32_t flags) { uint32_t dummy_cyclelen_base; uint32_t addr_bitlen; uint32_t read_command; bool conf_required = false; esp_flash_io_mode_t read_mode = chip->read_mode; + bool addr_32bit = (flags & SPI_FLASH_CONFIG_IO_MODE_32B_ADDR); switch (read_mode & 0xFFFF) { case SPI_FLASH_QIO: @@ -553,6 +555,12 @@ esp_err_t spi_flash_chip_generic_read_unique_id(esp_flash_t *chip, uint64_t* fla return err; } +esp_err_t spi_flash_chip_generic_read_unique_id_none(esp_flash_t *chip, uint64_t* flash_unique_id) +{ + // For flash doesn't support read unique id. + return ESP_ERR_NOT_SUPPORTED; +} + spi_flash_caps_t spi_flash_chip_generic_get_caps(esp_flash_t *chip) { // For generic part flash capability, take the XMC chip as reference. @@ -609,6 +617,7 @@ const spi_flash_chip_t esp_flash_chip_generic = { .sus_setup = spi_flash_chip_generic_suspend_cmd_conf, .read_unique_id = spi_flash_chip_generic_read_unique_id, .get_chip_caps = spi_flash_chip_generic_get_caps, + .config_host_io_mode = spi_flash_chip_generic_config_host_io_mode, }; #ifndef CONFIG_SPI_FLASH_ROM_IMPL diff --git a/components/spi_flash/spi_flash_chip_issi.c b/components/spi_flash/spi_flash_chip_issi.c index e8ae39fcff..56f29743b6 100644 --- a/components/spi_flash/spi_flash_chip_issi.c +++ b/components/spi_flash/spi_flash_chip_issi.c @@ -107,4 +107,5 @@ const spi_flash_chip_t esp_flash_chip_issi = { .sus_setup = spi_flash_chip_generic_suspend_cmd_conf, .read_unique_id = spi_flash_chip_generic_read_unique_id, .get_chip_caps = spi_flash_chip_issi_get_caps, + .config_host_io_mode = spi_flash_chip_generic_config_host_io_mode, }; diff --git a/components/spi_flash/spi_flash_chip_mxic.c b/components/spi_flash/spi_flash_chip_mxic.c index f88486dfd4..fef8f99f19 100644 --- a/components/spi_flash/spi_flash_chip_mxic.c +++ b/components/spi_flash/spi_flash_chip_mxic.c @@ -16,6 +16,7 @@ #include "spi_flash_chip_generic.h" #include "spi_flash_defs.h" #include "esp_log.h" +#include "hal/spi_flash_hal.h" /* Driver for MXIC flash chip */ @@ -26,6 +27,10 @@ esp_err_t spi_flash_chip_mxic_probe(esp_flash_t *chip, uint32_t flash_id) if (flash_id >> 16 != MFG_ID) { return ESP_ERR_NOT_FOUND; } + if (chip->read_mode >= SPI_FLASH_OPI_FLAG) { + // The code here serve for ordinary mxic chip. If opi mode has been selected, go `spi_flash_chip_mxic_opi.c` + return ESP_ERR_NOT_FOUND; + } return ESP_OK; } @@ -40,13 +45,6 @@ esp_err_t spi_flash_chip_issi_get_io_mode(esp_flash_t *chip, esp_flash_io_mode_t static const char chip_name[] = "mxic"; -esp_err_t spi_flash_chip_mxic_read_unique_id(esp_flash_t *chip, uint64_t* flash_unique_id) -{ - //MXIC not support read unique id. - ESP_LOGE(chip_name, "chip %s doesn't support reading unique id", chip->chip_drv->name); - return ESP_ERR_NOT_SUPPORTED; -} - spi_flash_caps_t spi_flash_chip_mxic_get_caps(esp_flash_t *chip) { spi_flash_caps_t caps_flags = 0; @@ -91,6 +89,7 @@ const spi_flash_chip_t esp_flash_chip_mxic = { .read_reg = spi_flash_chip_mxic_read_reg, .yield = spi_flash_chip_generic_yield, .sus_setup = spi_flash_chip_generic_suspend_cmd_conf, - .read_unique_id = spi_flash_chip_mxic_read_unique_id, + .read_unique_id = spi_flash_chip_generic_read_unique_id_none, .get_chip_caps = spi_flash_chip_mxic_get_caps, + .config_host_io_mode = spi_flash_chip_generic_config_host_io_mode, }; diff --git a/components/spi_flash/spi_flash_chip_mxic_opi.c b/components/spi_flash/spi_flash_chip_mxic_opi.c new file mode 100644 index 0000000000..0ddd233aa1 --- /dev/null +++ b/components/spi_flash/spi_flash_chip_mxic_opi.c @@ -0,0 +1,420 @@ +// 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. + +#include +#include "spi_flash_chip_generic.h" +#include "spi_flash_defs.h" +#include "esp_log.h" +#include "string.h" +#include // For MIN/MAX +#include "hal/spi_flash_hal.h" + +#define CMD_OPI_FLASH_MXIC(cmd) ((((~(cmd) & 0xff) << 8)) | ((cmd) & 0xff)) +#define CMD_OPI_FLASH_MXIC_CHIP_ERASE 0x9F60 +#define CMD_OPI_FLASH_MXIC_READ_STR 0x13EC +#define CMD_OPI_FLASH_MXIC_READ_DTR 0x11EE +#define CMD_OPI_FLASH_MXIC_RDCR2 0x8E71 +#define CMD_OPI_FLASH_MXIC_WRCR2 0x8D72 + +/* Driver for MXIC OPI flash chip */ +static const char chip_name[] = "mxic (opi)"; + +esp_err_t spi_flash_chip_mxic_opi_probe(esp_flash_t *chip, uint32_t flash_id) +{ + /* Check manufacturer and product IDs match our desired masks */ + const uint8_t MFG_ID = 0xC2; + if (flash_id >> 16 != MFG_ID) { + return ESP_ERR_NOT_FOUND; + } + + if (chip->read_mode < SPI_FLASH_OPI_FLAG) { + // The code here serve for opi flash under opi mode only, for ordinary mxic chip, go `spi_flash_chip_mxic.c` + return ESP_ERR_NOT_FOUND; + } + + return ESP_OK; +} + +spi_flash_caps_t spi_flash_chip_mxic_opi_get_caps(esp_flash_t *chip) +{ + spi_flash_caps_t caps_flags = 0; + caps_flags |= SPI_FLASH_CHIP_CAP_32MB_SUPPORT; + // flash-suspend is not supported yet. // IDF-3852 + // reading unique id is not supported. + return caps_flags; +} + +esp_err_t spi_flash_chip_mxic_opi_set_write_protect(esp_flash_t *chip, bool write_protect) +{ + esp_err_t err = ESP_OK; + + err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->idle_timeout); + spi_flash_trans_t t = {}; + if (err == ESP_OK || err == ESP_ERR_NOT_SUPPORTED) { + if(write_protect) { + t.command = CMD_OPI_FLASH_MXIC(CMD_WRDI); + } else { + t.command = CMD_OPI_FLASH_MXIC(CMD_WREN); + } + err = chip->host->driver->common_command(chip->host, &t); + } + + bool wp_read; + err = chip->chip_drv->get_chip_write_protect(chip, &wp_read); + if (err == ESP_OK && wp_read != write_protect) { + err = ESP_ERR_NOT_FOUND; + } + return err; +} + +static void spi_flash_chip_mxic_opi_get_data_length_zoom(esp_flash_io_mode_t io_mode, uint32_t *length_zoom) +{ + /* Under STR mode, one byte occupies one single clock. While under DTR mode, one byte occupies half clock. + For exmaple, if an operation needs 3 clock dummy, host send 3 dummy bytes under STR mode, while 6 dummy bytes under DTR mode. + Therefore, we need to adjust data zoom to fit the clock here. */ + assert((io_mode == SPI_FLASH_OPI_STR) || (io_mode == SPI_FLASH_OPI_DTR)); + *length_zoom = (io_mode == SPI_FLASH_OPI_STR) ? 1 : 2; +} + +esp_err_t spi_flash_chip_mxic_opi_read_id(esp_flash_t *chip, uint32_t* out_chip_id) +{ + uint64_t id_buf = 0; + uint32_t length_zoom; + spi_flash_chip_mxic_opi_get_data_length_zoom(chip->read_mode, &length_zoom); + spi_flash_trans_t t = { + .command = CMD_OPI_FLASH_MXIC(CMD_RDID), + .miso_len = 3 * length_zoom, + .dummy_bitlen = 4 * length_zoom, + .address_bitlen = 32, + .miso_data = ((uint8_t*) &id_buf), + }; + + chip->host->driver->common_command(chip->host, &t); + + if(chip->read_mode == SPI_FLASH_OPI_DTR) { + // Adjust the id_buf in DTR mode, because in DTR mode, the data back in STR rule. + // So it looks like [MD, MD, MT, MT, MID, MID], adjust it to [MD, MT, MID] here. + ESP_EARLY_LOGV(chip_name, "raw_chip_id: %llx\n", id_buf); + id_buf = (id_buf & 0xff) | ((id_buf & 0xff0000) >> 8) | ((id_buf & 0xff00000000) >> 16); + } else { + ESP_EARLY_LOGV(chip_name, "raw_chip_id: %X\n", id_buf); + } + + uint32_t raw_flash_id = __builtin_bswap32(id_buf); + if (raw_flash_id == 0xFFFFFF || raw_flash_id == 0) { + ESP_EARLY_LOGE(chip_name, "no response\n"); + return ESP_ERR_FLASH_NO_RESPONSE; + } + + *out_chip_id = (raw_flash_id >> 8); + ESP_EARLY_LOGV(chip_name, "chip_id: %X\n", *out_chip_id); + return ESP_OK; +} + +esp_err_t spi_flash_chip_mxic_opi_read_reg(esp_flash_t *chip, spi_flash_register_t reg_id, uint32_t* out_reg) +{ + uint32_t stat_buf = 0; + uint32_t length_zoom; + spi_flash_chip_mxic_opi_get_data_length_zoom(chip->read_mode, &length_zoom); + spi_flash_trans_t t = { + .command = CMD_OPI_FLASH_MXIC(CMD_RDSR), + .miso_data = ((uint8_t*) &stat_buf), + .miso_len = 1 * length_zoom, + .address_bitlen = 32, + .dummy_bitlen = 4 * length_zoom, + }; + esp_err_t err = chip->host->driver->common_command(chip->host, &t); + if (err != ESP_OK) { + return err; + } + + // For DTR mode, RDSR result like [SR1, SR1], just keeping one SR1. + *out_reg = (stat_buf & 0xff); + return ESP_OK; +} + +esp_err_t spi_flash_chip_mxic_opi_get_write_protect(esp_flash_t *chip, bool *out_write_protected) +{ + esp_err_t err = ESP_OK; + uint32_t status; + assert(out_write_protected!=NULL); + err = chip->chip_drv->read_reg(chip, SPI_FLASH_REG_STATUS, &status); + if (err != ESP_OK) { + return err; + } + + *out_write_protected = ((status & SR_WREN) == 0); + return err; +} + +esp_err_t spi_flash_chip_mxic_opi_erase_chip(esp_flash_t *chip) +{ + esp_err_t err; + + err = chip->chip_drv->set_chip_write_protect(chip, false); + if (err == ESP_OK) { + err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->idle_timeout); + } + + if (err == ESP_OK || err == ESP_ERR_NOT_SUPPORTED) { + // Do erase chip here. + spi_flash_trans_t t = { + .command = CMD_OPI_FLASH_MXIC_CHIP_ERASE, + }; + err = chip->host->driver->common_command(chip->host, &t); + chip->busy = 1; +#ifdef CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED + err = chip->chip_drv->wait_idle(chip, ESP_FLASH_CHIP_GENERIC_NO_TIMEOUT); +#else + err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->chip_erase_timeout); +#endif + } + // Ensure WEL is 0, even if the erase failed. + if (err == ESP_ERR_NOT_SUPPORTED) { + chip->chip_drv->set_chip_write_protect(chip, true); + } + + return err; + +} + +esp_err_t spi_flash_chip_mxic_opi_erase_sector(esp_flash_t *chip, uint32_t start_address) +{ + esp_err_t err = chip->chip_drv->set_chip_write_protect(chip, false); + if (err == ESP_OK) { + err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->idle_timeout); + } + //The chip didn't accept the previous write command. Ignore this in preparationstage. + if (err == ESP_OK || err == ESP_ERR_NOT_SUPPORTED) { + spi_flash_trans_t t = { + .command = CMD_OPI_FLASH_MXIC(CMD_SECTOR_ERASE_4B), + .address_bitlen = 32, + .address = start_address, + }; + err = chip->host->driver->common_command(chip->host, &t); + chip->busy = 1; +#ifdef CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED + err = chip->chip_drv->wait_idle(chip, ESP_FLASH_CHIP_GENERIC_NO_TIMEOUT); +#else + err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->sector_erase_timeout); +#endif + } + // Ensure WEL is 0, even if the erase failed. + if (err == ESP_ERR_NOT_SUPPORTED) { + err = chip->chip_drv->set_chip_write_protect(chip, true); + } + + return err; +} + +esp_err_t spi_flash_chip_mxic_opi_erase_block(esp_flash_t *chip, uint32_t start_address) +{ + esp_err_t err = chip->chip_drv->set_chip_write_protect(chip, false); + if (err == ESP_OK) { + err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->idle_timeout); + } + //The chip didn't accept the previous write command. Ignore this in preparationstage. + if (err == ESP_OK || err == ESP_ERR_NOT_SUPPORTED) { + spi_flash_trans_t t = { + .command = CMD_OPI_FLASH_MXIC(CMD_LARGE_BLOCK_ERASE_4B), + .address_bitlen = 32, + .address = start_address, + }; + err = chip->host->driver->common_command(chip->host, &t); + chip->busy = 1; +#ifdef CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED + err = chip->chip_drv->wait_idle(chip, ESP_FLASH_CHIP_GENERIC_NO_TIMEOUT); +#else + err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->block_erase_timeout); +#endif + } + // Ensure WEL is 0, even if the erase failed. + if (err == ESP_ERR_NOT_SUPPORTED) { + err = chip->chip_drv->set_chip_write_protect(chip, true); + } + + return err; +} + +esp_err_t spi_flash_chip_mxic_opi_page_program(esp_flash_t *chip, const void *buffer, uint32_t address, uint32_t length) +{ + esp_err_t err; + + err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->idle_timeout); + //The chip didn't accept the previous write command. Ignore this in preparationstage. + if (err == ESP_OK || err == ESP_ERR_NOT_SUPPORTED) { + // Perform the actual Page Program command + spi_flash_trans_t t = { + .command = CMD_OPI_FLASH_MXIC(CMD_PROGRAM_PAGE_4B), + .address_bitlen = 32, + .address = address, + .mosi_len = length, + .mosi_data = buffer, + }; + chip->host->driver->common_command(chip->host, &t); + chip->busy = 1; + + err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->page_program_timeout); + } + // Ensure WEL is 0, even if the page program failed. + if (err == ESP_ERR_NOT_SUPPORTED) { + err = chip->chip_drv->set_chip_write_protect(chip, true); + } + return err; +} + +esp_err_t spi_flash_chip_mxic_opi_write(esp_flash_t *chip, const void *buffer, uint32_t address, uint32_t length) +{ + esp_err_t err = ESP_OK; + const uint32_t page_size = chip->chip_drv->page_size; + uint32_t align_address; + uint8_t temp_buffer[64]; //spiflash hal max length of write no longer than 64byte + + while (err == ESP_OK && length > 0) { + memset(temp_buffer, 0xFF, sizeof(temp_buffer)); + uint32_t page_len = chip->host->driver->write_data_slicer(chip->host, address, length, &align_address, page_size); + uint32_t left_off = address - align_address; + uint32_t write_len = MIN(align_address + page_len, address + length) - address; + memcpy(temp_buffer + left_off, buffer, write_len); + + err = chip->chip_drv->set_chip_write_protect(chip, false); + if (err == ESP_OK && length > 0) { + err = chip->chip_drv->program_page(chip, temp_buffer, align_address, page_len); + + address += write_len; + buffer = (void *)((intptr_t)buffer + write_len); + length -= write_len; + } + } + // The caller is responsible to do host->driver->flush_cache, because this function may be + // called in small pieces. Frequency call of flush cache will do harm to the performance. + return err; +} + +esp_err_t spi_flash_chip_mxic_opi_get_io_mode(esp_flash_t *chip, esp_flash_io_mode_t* out_io_mode) +{ + uint32_t stat_buf = 0; + uint32_t length_zoom; + spi_flash_chip_mxic_opi_get_data_length_zoom(chip->read_mode, &length_zoom); + + spi_flash_trans_t t = { + .command = CMD_OPI_FLASH_MXIC_RDCR2, + .dummy_bitlen = 4 * length_zoom, + .miso_data = ((uint8_t*) &stat_buf), + .miso_len = 1 * length_zoom, + .address_bitlen = 32, + }; + esp_err_t err = chip->host->driver->common_command(chip->host, &t); + if (err != ESP_OK) { + return err; + } + + // For DTR mode, RDSR result like [CR1, CR1], just keeping one CR1. + switch (stat_buf & 0xff) + { + case 0x1: + *out_io_mode = SPI_FLASH_OPI_STR; + break; + case 0x2: + *out_io_mode = SPI_FLASH_OPI_DTR; + break; + default: + // wrong mode. + *out_io_mode = 0; + break; + } + if (*out_io_mode != chip->read_mode) { + // Current chip mode is not the mode we configured. + *out_io_mode = 0; + } + + return ESP_OK; +} + +esp_err_t spi_flash_chip_xmic_opi_set_io_mode(esp_flash_t *chip) +{ + // TODO: configure opi flash chip set io mode, only useful for external flash currently. + // For main flash, we already set io mode when chip starts up. But for external flash, + // We need to set mode when flash initialized, so keeping this for future usage. + return ESP_OK; +} + +// This function should only be called after opi mode initialization. So, only configure for OPI-STR/OPI-DTR mode +// not support other mode in this file, return `ESP_ERR_FLASH_NOT_INITIALISED` directely. +esp_err_t spi_flash_chip_xmic_opi_config_host_io_mode(esp_flash_t *chip, uint32_t flags) +{ + uint32_t dummy_cyclelen_base; + uint32_t addr_bitlen; + uint32_t read_command; + esp_flash_io_mode_t read_mode = chip->read_mode; + + switch (read_mode & 0xFFFF) { + case SPI_FLASH_OPI_STR: + addr_bitlen = SPI_FLASH_OPISTR_ADDR_BITLEN; + dummy_cyclelen_base = SPI_FLASH_OPISTR_DUMMY_BITLEN; + read_command = CMD_OPI_FLASH_MXIC_READ_STR; + break; + case SPI_FLASH_OPI_DTR: + addr_bitlen = SPI_FLASH_OPIDTR_ADDR_BITLEN; + dummy_cyclelen_base = SPI_FLASH_OPIDTR_DUMMY_BITLEN; + read_command = CMD_OPI_FLASH_MXIC_READ_DTR; + break; + default: + return ESP_ERR_FLASH_NOT_INITIALISED; + } + + return chip->host->driver->configure_host_io_mode(chip->host, read_command, addr_bitlen, dummy_cyclelen_base, read_mode); +} + +// Most of mxic opi implementations are totally different from that is generic. +// Replace them to opi implementation. +const spi_flash_chip_t esp_flash_chip_mxic_opi = { + .name = chip_name, + .timeout = &spi_flash_chip_generic_timeout, + .probe = spi_flash_chip_mxic_opi_probe, + .reset = spi_flash_chip_generic_reset, + .detect_size = spi_flash_chip_generic_detect_size, + .erase_chip = spi_flash_chip_mxic_opi_erase_chip, + .erase_sector = spi_flash_chip_mxic_opi_erase_sector, + .erase_block = spi_flash_chip_mxic_opi_erase_block, + .sector_size = 4 * 1024, + .block_erase_size = 64 * 1024, + + .get_chip_write_protect = spi_flash_chip_mxic_opi_get_write_protect, + .set_chip_write_protect = spi_flash_chip_mxic_opi_set_write_protect, + + .num_protectable_regions = 0, + .protectable_regions = NULL, + .get_protected_regions = NULL, + .set_protected_regions = NULL, + + .read = spi_flash_chip_generic_read, + .write = spi_flash_chip_mxic_opi_write, + .program_page = spi_flash_chip_mxic_opi_page_program, + .page_size = 256, + .write_encrypted = spi_flash_chip_generic_write_encrypted, + + .wait_idle = spi_flash_chip_generic_wait_idle, + + .set_io_mode = spi_flash_chip_xmic_opi_set_io_mode, + .get_io_mode = spi_flash_chip_mxic_opi_get_io_mode, + + .read_id = spi_flash_chip_mxic_opi_read_id, + .read_reg = spi_flash_chip_mxic_opi_read_reg, + .yield = spi_flash_chip_generic_yield, + .sus_setup = spi_flash_chip_generic_suspend_cmd_conf, + .read_unique_id = spi_flash_chip_generic_read_unique_id_none, + .get_chip_caps = spi_flash_chip_mxic_opi_get_caps, + .config_host_io_mode = spi_flash_chip_xmic_opi_config_host_io_mode, +}; diff --git a/components/spi_flash/spi_flash_chip_winbond.c b/components/spi_flash/spi_flash_chip_winbond.c index 98e94ae01a..6bec557716 100644 --- a/components/spi_flash/spi_flash_chip_winbond.c +++ b/components/spi_flash/spi_flash_chip_winbond.c @@ -48,9 +48,13 @@ esp_err_t spi_flash_chip_winbond_read(esp_flash_t *chip, void *buffer, uint32_t const uint32_t page_size = chip->chip_drv->page_size; uint32_t align_address; uint8_t temp_buffer[64]; //spiflash hal max length of read no longer than 64byte + uint32_t config_io_flags = 0; // Configure the host, and return - err = spi_flash_chip_generic_config_host_io_mode(chip, REGION_32BIT(address, length)); + if (REGION_32BIT(address, length)) { + config_io_flags |= SPI_FLASH_CONFIG_IO_MODE_32B_ADDR; + } + err = chip->chip_drv->config_host_io_mode(chip, config_io_flags); if (err == ESP_ERR_NOT_SUPPORTED) { ESP_LOGE(TAG, "configure host io mode failed - unsupported"); @@ -192,6 +196,7 @@ const spi_flash_chip_t esp_flash_chip_winbond = { .sus_setup = spi_flash_chip_generic_suspend_cmd_conf, .read_unique_id = spi_flash_chip_generic_read_unique_id, .get_chip_caps = spi_flash_chip_winbond_get_caps, + .config_host_io_mode = spi_flash_chip_generic_config_host_io_mode, }; diff --git a/components/spi_flash/spi_flash_timing_tuning.c b/components/spi_flash/spi_flash_timing_tuning.c index 705da2c45c..5fd5fa5c54 100644 --- a/components/spi_flash/spi_flash_timing_tuning.c +++ b/components/spi_flash/spi_flash_timing_tuning.c @@ -12,14 +12,45 @@ #include "esp_types.h" #include "esp_log.h" #include "soc/spi_mem_reg.h" +#include "soc/io_mux_reg.h" #include "spi_flash_private.h" +#include "soc/soc.h" #if CONFIG_IDF_TARGET_ESP32S3 #include "esp32s3/spi_timing_config.h" #endif +#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(*(arr))) + +#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING +const static char *TAG = "MSPI Timing"; static spi_timing_tuning_param_t s_flash_best_timing_tuning_config; static spi_timing_tuning_param_t s_psram_best_timing_tuning_config; +#endif +/*------------------------------------------------------------------------------ + * Common settings + *----------------------------------------------------------------------------*/ +void spi_timing_set_pin_drive_strength(void) +{ + //For now, set them all to 3. Need to check after QVL test results are out. TODO: IDF-3663 + //Set default clk + SET_PERI_REG_MASK(SPI_MEM_DATE_REG(0), SPI_MEM_SPICLK_PAD_DRV_CTL_EN); + REG_SET_FIELD(SPI_MEM_DATE_REG(0), SPI_MEM_SPI_SMEM_SPICLK_FUN_DRV, 3); + REG_SET_FIELD(SPI_MEM_DATE_REG(0), SPI_MEM_SPI_FMEM_SPICLK_FUN_DRV, 3); + //Set default mspi d0 ~ d7, dqs pin drive strength + uint32_t regs[] = {IO_MUX_GPIO27_REG, IO_MUX_GPIO28_REG, + IO_MUX_GPIO31_REG, IO_MUX_GPIO32_REG, + IO_MUX_GPIO33_REG, IO_MUX_GPIO34_REG, + IO_MUX_GPIO35_REG, IO_MUX_GPIO36_REG, + IO_MUX_GPIO37_REG}; + for (int i = 0; i < ARRAY_SIZE(regs); i++) { + PIN_SET_DRV(regs[i], 3); + } +} + +/*------------------------------------------------------------------------------ + * Static functions to get clock configs + *----------------------------------------------------------------------------*/ static spi_timing_config_core_clock_t get_mspi_core_clock(void) { return spi_timing_config_get_core_clock(); @@ -46,6 +77,8 @@ static uint32_t get_psram_clock_divider(void) return SPI_TIMING_CORE_CLOCK_MHZ / 40; #elif CONFIG_SPIRAM_SPEED_80M return SPI_TIMING_CORE_CLOCK_MHZ / 80; +#elif CONFIG_SPIRAM_SPEED_120M + return SPI_TIMING_CORE_CLOCK_MHZ / 120; #else //Will enter this branch only if PSRAM is not enable return 0; @@ -53,6 +86,9 @@ static uint32_t get_psram_clock_divider(void) } #if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING +/*------------------------------------------------------------------------------ + * Static functions to do timing tuning + *----------------------------------------------------------------------------*/ /** * Set timing tuning regs, in order to get successful sample points */ @@ -90,25 +126,15 @@ static void sweep_for_success_sample_points(uint8_t *reference_data, const spi_t memset(read_data, 0, SPI_TIMING_TEST_DATA_LEN); #if SPI_TIMING_FLASH_NEEDS_TUNING if (is_flash) { - /** - * 1. SPI_MEM_DINx_MODE(1), SPI_MEM_DINx_NUM(1) are meaningless - * SPI0 and SPI1 share the SPI_MEM_DINx_MODE(0), SPI_MEM_DINx_NUM(0) for FLASH timing tuning - * 2. We use SPI1 to get the best Flash timing tuning (mode and num) config - */ - spi_timing_config_flash_set_din_mode_num(0, config->tuning_config_table[config_idx].spi_din_mode, config->tuning_config_table[config_idx].spi_din_num); - spi_timing_config_flash_set_extra_dummy(1, config->tuning_config_table[config_idx].extra_dummy_len); + spi_timing_config_flash_tune_din_num_mode(config->tuning_config_table[config_idx].spi_din_mode, config->tuning_config_table[config_idx].spi_din_num); + spi_timing_config_flash_tune_dummy(config->tuning_config_table[config_idx].extra_dummy_len); spi_timing_config_flash_read_data(1, read_data, SPI_TIMING_FLASH_TEST_DATA_ADDR, sizeof(read_data)); } #endif #if SPI_TIMING_PSRAM_NEEDS_TUNING if (!is_flash) { - /** - * 1. SPI_MEM_SPI_SMEM_DINx_MODE(1), SPI_MEM_SPI_SMEM_DINx_NUM(1) are meaningless - * SPI0 and SPI1 share the SPI_MEM_SPI_SMEM_DINx_MODE(0), SPI_MEM_SPI_SMEM_DINx_NUM(0) for PSRAM timing tuning - * 2. We use SPI1 to get the best PSRAM timing tuning (mode and num) config - */ - spi_timing_config_psram_set_din_mode_num(0, config->tuning_config_table[config_idx].spi_din_mode, config->tuning_config_table[config_idx].spi_din_num); - spi_timing_config_flash_set_extra_dummy(1, config->tuning_config_table[config_idx].extra_dummy_len); + spi_timing_config_psram_tune_din_num_mode(config->tuning_config_table[config_idx].spi_din_mode, config->tuning_config_table[config_idx].spi_din_num); + spi_timing_config_psram_tune_dummy(config->tuning_config_table[config_idx].extra_dummy_len); spi_timing_config_psram_read_data(1, read_data, SPI_TIMING_PSRAM_TEST_DATA_ADDR, SPI_TIMING_TEST_DATA_LEN); } #endif @@ -134,7 +160,6 @@ static void find_max_consecutive_success_points(uint8_t *array, uint32_t size, u while (i < size) { if (array[i]) { match_num++; - } else { if (match_num > max) { max = match_num; @@ -149,18 +174,77 @@ static void find_max_consecutive_success_points(uint8_t *array, uint32_t size, u *out_end_index = match_num == size ? size : end; } -static void select_best_tuning_config(spi_timing_config_t *config, uint32_t length, uint32_t end, bool is_flash) +#if SPI_TIMING_FLASH_DTR_MODE || SPI_TIMING_PSRAM_DTR_MODE +static uint32_t select_best_tuning_config_dtr(spi_timing_config_t *config, uint32_t consecutive_length, uint32_t end) { +#if (SPI_TIMING_CORE_CLOCK_MHZ == 160) + //Core clock 160M DTR best point scheme uint32_t best_point; - if (length >= 3) { - best_point = end - length / 2; - } else { + + //Define these magic number in macros in `spi_timing_config.h`. TODO: IDF-3663 + if (consecutive_length <= 2 || consecutive_length >= 6) { + //tuning is FAIL, select default point, and generate a warning best_point = config->default_config_id; + ESP_EARLY_LOGW(TAG, "tuning fail, best point is fallen back to index %d", best_point); + } else if (consecutive_length <= 4) { + //consecutive length : 3 or 4 + best_point = end - 1; + ESP_EARLY_LOGD(TAG,"tuning success, best point is index %d", best_point); + } else { + //consecutive point list length equals 5 + best_point = end - 2; + ESP_EARLY_LOGD(TAG,"tuning success, best point is index %d", best_point); } + return best_point; +#else + //won't reach here + abort(); +#endif +} +#endif + +#if SPI_TIMING_FLASH_STR_MODE || SPI_TIMING_PSRAM_STR_MODE +static uint32_t select_best_tuning_config_str(spi_timing_config_t *config, uint32_t consecutive_length, uint32_t end) +{ +#if (SPI_TIMING_CORE_CLOCK_MHZ == 120 || SPI_TIMING_CORE_CLOCK_MHZ == 240) + //STR best point scheme + uint32_t best_point; + + if (consecutive_length <= 2|| consecutive_length >= 5) { + //tuning is FAIL, select default point, and generate a warning + best_point = config->default_config_id; + ESP_EARLY_LOGW(TAG, "tuning fail, best point is fallen back to index %d", best_point); + } else { + //consecutive length : 3 or 4 + best_point = end - consecutive_length / 2; + ESP_EARLY_LOGD(TAG,"tuning success, best point is index %d", best_point); + } + + return best_point; +#else + //won't reach here + abort(); +#endif +} +#endif + +static void select_best_tuning_config(spi_timing_config_t *config, uint32_t consecutive_length, uint32_t end, bool is_flash) +{ + uint32_t best_point = 0; if (is_flash) { +#if SPI_TIMING_FLASH_DTR_MODE + best_point = select_best_tuning_config_dtr(config, consecutive_length, end); +#else //#if SPI_TIMING_FLASH_STR_MODE + best_point = select_best_tuning_config_str(config, consecutive_length, end); +#endif s_flash_best_timing_tuning_config = config->tuning_config_table[best_point]; } else { +#if SPI_TIMING_PSRAM_DTR_MODE + best_point = select_best_tuning_config_dtr(config, consecutive_length, end); +#else //#if SPI_TIMING_PSRAM_STR_MODE + best_point = select_best_tuning_config_str(config, consecutive_length, end); +#endif s_psram_best_timing_tuning_config = config->tuning_config_table[best_point]; } } @@ -168,7 +252,7 @@ static void select_best_tuning_config(spi_timing_config_t *config, uint32_t leng static void do_tuning(uint8_t *reference_data, spi_timing_config_t *timing_config, bool is_flash) { /** - * We use SPI1 to tune the FLASH timing: + * We use SPI1 to tune the timing: * 1. Get all SPI1 sampling results. * 2. Find the longest consecutive successful sampling points from the result above. * 3. The middle one will be the best sampling point. @@ -185,7 +269,9 @@ static void do_tuning(uint8_t *reference_data, spi_timing_config_t *timing_confi #endif //#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING -//------------------------------------------FLASH Timing Tuning----------------------------------------// +/*------------------------------------------------------------------------------ + * FLASH Timing Tuning + *----------------------------------------------------------------------------*/ #if SPI_TIMING_FLASH_NEEDS_TUNING static void get_flash_tuning_configs(spi_timing_config_t *config) { @@ -210,11 +296,12 @@ static void get_flash_tuning_configs(spi_timing_config_t *config) void spi_timing_flash_tuning(void) { + ESP_EARLY_LOGW("FLASH", "DO NOT USE FOR MASS PRODUCTION! Timing parameters will be updated in future IDF version."); /** * set SPI01 related regs to 20mhz configuration, to get reference data from FLASH - * see detailed comments in this function (`spi_timing_enter_mspi_low_speed_mode) + * see detailed comments in this function (`spi_timing_enter_mspi_low_speed_mode`) */ - spi_timing_enter_mspi_low_speed_mode(); + spi_timing_enter_mspi_low_speed_mode(true); //Disable the variable dummy mode when doing timing tuning CLEAR_PERI_REG_MASK(SPI_MEM_DDR_REG(1), SPI_MEM_SPI_FMEM_VAR_DUMMY); //GD flash will read error in variable mode with 20MHz @@ -225,7 +312,7 @@ void spi_timing_flash_tuning(void) get_flash_tuning_configs(&timing_configs); do_tuning(reference_data, &timing_configs, true); - spi_timing_enter_mspi_high_speed_mode(); + spi_timing_enter_mspi_high_speed_mode(true); } #else void spi_timing_flash_tuning(void) @@ -235,7 +322,9 @@ void spi_timing_flash_tuning(void) #endif //SPI_TIMING_FLASH_NEEDS_TUNING -//------------------------------------------PSRAM Timing Tuning----------------------------------------// +/*------------------------------------------------------------------------------ + * PSRAM Timing Tuning + *----------------------------------------------------------------------------*/ #if SPI_TIMING_PSRAM_NEEDS_TUNING static void get_psram_tuning_configs(spi_timing_config_t *config) { @@ -249,6 +338,8 @@ static void get_psram_tuning_configs(spi_timing_config_t *config) *config = SPI_TIMING_PSRAM_GET_TUNING_CONFIG(SPI_TIMING_CORE_CLOCK_MHZ, 40, PSRAM_MODE); #elif CONFIG_SPIRAM_SPEED_80M *config = SPI_TIMING_PSRAM_GET_TUNING_CONFIG(SPI_TIMING_CORE_CLOCK_MHZ, 80, PSRAM_MODE); +#elif CONFIG_SPIRAM_SPEED_120M + *config = SPI_TIMING_PSRAM_GET_TUNING_CONFIG(SPI_TIMING_CORE_CLOCK_MHZ, 120, PSRAM_MODE); #endif #undef PSRAM_MODE @@ -256,11 +347,12 @@ static void get_psram_tuning_configs(spi_timing_config_t *config) void spi_timing_psram_tuning(void) { + ESP_EARLY_LOGW("PSRAM", "DO NOT USE FOR MASS PRODUCTION! Timing parameters will be updated in future IDF version."); /** * set SPI01 related regs to 20mhz configuration, to write reference data to PSRAM - * see detailed comments in this function (`spi_timing_enter_mspi_low_speed_mode) + * see detailed comments in this function (`spi_timing_enter_mspi_low_speed_mode`) */ - spi_timing_enter_mspi_low_speed_mode(); + spi_timing_enter_mspi_low_speed_mode(true); // write data into psram, used to do timing tuning test. uint8_t reference_data[SPI_TIMING_TEST_DATA_LEN]; @@ -275,7 +367,7 @@ void spi_timing_psram_tuning(void) CLEAR_PERI_REG_MASK(SPI_MEM_DDR_REG(1), SPI_MEM_SPI_FMEM_VAR_DUMMY); //Get required config, and set them to PSRAM related registers do_tuning(reference_data, &timing_configs, false); - spi_timing_enter_mspi_high_speed_mode(); + spi_timing_enter_mspi_high_speed_mode(true); } #else @@ -285,16 +377,23 @@ void spi_timing_psram_tuning(void) } #endif //SPI_TIMING_PSRAM_NEEDS_TUNING - -//---------------------------------------------APIs to make SPI0 and SPI1 FLASH work for high/low freq-------------------------------// -static void clear_timing_tuning_regs(void) +/*------------------------------------------------------------------------------ + * APIs to make SPI0 (and SPI1) FLASH work for high/low freq + *----------------------------------------------------------------------------*/ +#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING +static void clear_timing_tuning_regs(bool control_spi1) { spi_timing_config_flash_set_din_mode_num(0, 0, 0); //SPI0 and SPI1 share the registers for flash din mode and num setting, so we only set SPI0's reg spi_timing_config_flash_set_extra_dummy(0, 0); - spi_timing_config_flash_set_extra_dummy(1, 0); + if (control_spi1) { + spi_timing_config_flash_set_extra_dummy(1, 0); + } else { + //Won't touch SPI1 registers + } } +#endif //#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING -void spi_timing_enter_mspi_low_speed_mode(void) +void spi_timing_enter_mspi_low_speed_mode(bool control_spi1) { /** * Here we are going to slow the SPI1 frequency to 20Mhz, so we need to set SPI1 din_num and din_mode regs. @@ -307,30 +406,40 @@ void spi_timing_enter_mspi_low_speed_mode(void) //Switch SPI1 and SPI0 clock as 20MHz, set its SPIMEM core clock as 80M and set clock division as 4 spi_timing_config_set_core_clock(0, SPI_TIMING_CONFIG_CORE_CLOCK_80M); //SPI0 and SPI1 share the register for core clock. So we only set SPI0 here. - spi_timing_config_set_flash_clock(1, 4); spi_timing_config_set_flash_clock(0, 4); + if (control_spi1) { + //After tuning, won't touch SPI1 again + spi_timing_config_set_flash_clock(1, 4); + } - clear_timing_tuning_regs(); +#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING + clear_timing_tuning_regs(control_spi1); +#endif } -static void set_timing_tuning_regs_as_required(void) +#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING +static void set_timing_tuning_regs_as_required(bool control_spi1) { //SPI0 and SPI1 share the registers for flash din mode and num setting, so we only set SPI0's reg spi_timing_config_flash_set_din_mode_num(0, s_flash_best_timing_tuning_config.spi_din_mode, s_flash_best_timing_tuning_config.spi_din_num); spi_timing_config_flash_set_extra_dummy(0, s_flash_best_timing_tuning_config.extra_dummy_len); - spi_timing_config_flash_set_extra_dummy(1, s_flash_best_timing_tuning_config.extra_dummy_len); + if (control_spi1) { + spi_timing_config_flash_set_extra_dummy(1, s_flash_best_timing_tuning_config.extra_dummy_len); + } spi_timing_config_psram_set_din_mode_num(0, s_psram_best_timing_tuning_config.spi_din_mode, s_psram_best_timing_tuning_config.spi_din_num); spi_timing_config_psram_set_extra_dummy(0, s_psram_best_timing_tuning_config.extra_dummy_len); } +#endif //#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING /** - * Set SPI0 and SPI1 flash module clock, din_num, din_mode and extra dummy, + * Set SPI0 FLASH and PSRAM module clock, din_num, din_mode and extra dummy, * according to the configuration got from timing tuning function (`calculate_best_flash_tuning_config`). + * iF control_spi1 == 1, will also update SPI1 timing registers. Should only be set to 1 when do tuning. * * This function should always be called after `spi_timing_flash_tuning` or `calculate_best_flash_tuning_config` */ -void spi_timing_enter_mspi_high_speed_mode(void) +void spi_timing_enter_mspi_high_speed_mode(bool control_spi1) { spi_timing_config_core_clock_t core_clock = get_mspi_core_clock(); uint32_t flash_div = get_flash_clock_divider(); @@ -340,9 +449,38 @@ void spi_timing_enter_mspi_high_speed_mode(void) spi_timing_config_set_core_clock(0, core_clock); //SPI0 and SPI1 share the register for core clock. So we only set SPI0 here. //Set FLASH module clock spi_timing_config_set_flash_clock(0, flash_div); - spi_timing_config_set_flash_clock(1, flash_div); + if (control_spi1) { + spi_timing_config_set_flash_clock(1, flash_div); + } //Set PSRAM module clock spi_timing_config_set_psram_clock(0, psram_div); - set_timing_tuning_regs_as_required(); +#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING + set_timing_tuning_regs_as_required(true); +#endif } + +/** + * Should be only used by SPI1 Flash driver to know the necessary timing registers + */ +#if SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING +void spi_timing_get_flash_timing_param(spi_flash_hal_timing_config_t *out_timing_config) +{ + // Get clock configuration directly from system. + out_timing_config->clock_config.spimem.val = spi_timing_config_get_flash_clock_reg(); + + // Get extra dummy length here. Therefore, no matter what freq, or mode. + // If it needs tuning, it will return correct extra dummy len. If no tuning, it will return 0. + + out_timing_config->extra_dummy = s_flash_best_timing_tuning_config.extra_dummy_len; + + // Get CS setup/hold value here. + spi_timing_config_get_cs_timing(&out_timing_config->cs_setup, &out_timing_config->cs_hold); +} +#else +void spi_timing_get_flash_timing_param(spi_flash_hal_timing_config_t *out_timing_config) +{ + // This function shouldn't be called if timing tuning is not used. + abort(); +} +#endif // SPI_TIMING_FLASH_NEEDS_TUNING || SPI_TIMING_PSRAM_NEEDS_TUNING diff --git a/components/spi_flash/test/test_esp_flash.c b/components/spi_flash/test/test_esp_flash.c index 1c40917cad..27d7c228e6 100644 --- a/components/spi_flash/test/test_esp_flash.c +++ b/components/spi_flash/test/test_esp_flash.c @@ -727,6 +727,7 @@ static void write_large_buffer(const esp_partition_t *part, const uint8_t *sourc static void read_and_check(const esp_partition_t *part, const uint8_t *source, size_t length); // Internal functions for testing, from esp_flash_api.c +#if !CONFIG_ESPTOOLPY_OCT_FLASH esp_err_t esp_flash_set_io_mode(esp_flash_t* chip, bool qe); esp_err_t esp_flash_get_io_mode(esp_flash_t* chip, bool* qe); esp_err_t esp_flash_read_chip_id(esp_flash_t* chip, uint32_t* flash_id); @@ -801,16 +802,17 @@ IRAM_ATTR NOINLINE_ATTR static void test_toggle_qe(const esp_partition_t* part) // `spi_flash_common_set_io_mode` and then run this test. FLASH_TEST_CASE_IGNORE("Test esp_flash_write can toggle QE bit", test_toggle_qe); FLASH_TEST_CASE_3_IGNORE("Test esp_flash_write can toggle QE bit", test_toggle_qe); +#endif //CONFIG_ESPTOOLPY_OCT_FLASH void test_permutations_part(const flashtest_config_t* config, esp_partition_t* part, void* source_buf, size_t length) { if (config->host_id != -1) { esp_flash_speed_t speed = ESP_FLASH_SPEED_MIN; - while (speed != ESP_FLASH_SPEED_MAX) { + while (speed != ESP_FLASH_120MHZ) { //test io_mode in the inner loop to test QE set/clear function, since //the io mode will switch frequently. esp_flash_io_mode_t io_mode = SPI_FLASH_READ_MODE_MIN; - while (io_mode != SPI_FLASH_READ_MODE_MAX) { + while (io_mode != SPI_FLASH_QIO + 1) { if (io_mode > SPI_FLASH_FASTRD && !SOC_SPI_PERIPH_SUPPORT_MULTILINE_MODE(config->host_id)) { io_mode++; diff --git a/components/spi_flash/test/test_read_write.c b/components/spi_flash/test/test_read_write.c index 57db40dae7..9510fb7e8d 100644 --- a/components/spi_flash/test/test_read_write.c +++ b/components/spi_flash/test/test_read_write.c @@ -23,11 +23,22 @@ #include #include #include -#include #include "../cache_utils.h" #include "soc/timer_periph.h" #include "esp_heap_caps.h" +#if CONFIG_IDF_TARGET_ESP32 +#include "esp32/rom/spi_flash.h" +#elif CONFIG_IDF_TARGET_ESP32S2 +#include "esp32s2/rom/spi_flash.h" +#elif CONFIG_IDF_TARGET_ESP32S3 +#include "esp32s3/rom/spi_flash.h" +#elif CONFIG_IDF_TARGET_ESP32C3 +#include "esp32c3/rom/spi_flash.h" +#elif CONFIG_IDF_TARGET_ESP32H2 +#include "esp32h2/rom/spi_flash.h" +#endif + #define MIN_BLOCK_SIZE 12 /* Base offset in flash for tests. */ @@ -147,14 +158,18 @@ static void IRAM_ATTR fix_rom_func(void) { uint32_t freqdiv = 0; -#if CONFIG_ESPTOOLPY_FLASHFREQ_80M +#if CONFIG_ESPTOOLPY_FLASHFREQ_80M && !CONFIG_ESPTOOLPY_OCT_FLASH freqdiv = 1; +#elif CONFIG_ESPTOOLPY_FLASHFREQ_80M && CONFIG_ESPTOOLPY_OCT_FLASH + freqdiv = 2; #elif CONFIG_ESPTOOLPY_FLASHFREQ_40M freqdiv = 2; #elif CONFIG_ESPTOOLPY_FLASHFREQ_26M freqdiv = 3; #elif CONFIG_ESPTOOLPY_FLASHFREQ_20M freqdiv = 4; +#elif CONFIG_ESPTOOLPY_FLASHFREQ_120M + freqdiv = 2; #endif #if CONFIG_IDF_TARGET_ESP32 @@ -182,13 +197,19 @@ static void IRAM_ATTR fix_rom_func(void) read_mode = ESP_ROM_SPIFLASH_DIO_MODE; #elif CONFIG_ESPTOOLPY_FLASHMODE_DOUT read_mode = ESP_ROM_SPIFLASH_DOUT_MODE; +#elif CONFIG_ESPTOOLPY_FLASHMODE_OPI_STR + read_mode = ESP_ROM_SPIFLASH_OPI_STR_MODE; +#elif CONFIG_ESPTOOLPY_FLASHMODE_OPI_DTR + read_mode = ESP_ROM_SPIFLASH_OPI_DTR_MODE; #endif #if !CONFIG_IDF_TARGET_ESP32S2 && !CONFIG_IDF_TARGET_ESP32 spi_common_set_dummy_output(read_mode); #endif //!CONFIG_IDF_TARGET_ESP32S2 esp_rom_spiflash_config_clk(freqdiv, 1); +#if !CONFIG_ESPTOOLPY_OCT_FLASH esp_rom_spiflash_config_readmode(read_mode); +#endif } static void IRAM_ATTR test_write(int dst_off, int src_off, int len) diff --git a/components/spi_flash/test/test_spi_flash.c b/components/spi_flash/test/test_spi_flash.c index 3cbca1f790..a3672eee3b 100644 --- a/components/spi_flash/test/test_spi_flash.c +++ b/components/spi_flash/test/test_spi_flash.c @@ -15,6 +15,8 @@ #include "esp_rom_sys.h" #include "esp_timer.h" +#include "bootloader_flash.h" //for bootloader_flash_xmc_startup + #include "sdkconfig.h" #if CONFIG_IDF_TARGET_ESP32 #include "esp32/rom/spi_flash.h" @@ -427,3 +429,21 @@ TEST_CASE("rom unlock will not erase QE bit", "[spi_flash]") TEST_ASSERT(status & 0x40); } #endif + +static IRAM_ATTR NOINLINE_ATTR void test_xmc_startup(void) +{ + extern void spi_flash_disable_interrupts_caches_and_other_cpu(void); + extern void spi_flash_enable_interrupts_caches_and_other_cpu(void); + esp_err_t ret = ESP_OK; + + spi_flash_disable_interrupts_caches_and_other_cpu(); + ret = bootloader_flash_xmc_startup(); + spi_flash_enable_interrupts_caches_and_other_cpu(); + + TEST_ASSERT_EQUAL(ESP_OK, ret); +} + +TEST_CASE("bootloader_flash_xmc_startup can be called when cache disabled", "[spi_flash]") +{ + test_xmc_startup(); +} diff --git a/components/spiffs/CMakeLists.txt b/components/spiffs/CMakeLists.txt index 9a9d35f5b0..5954094c43 100644 --- a/components/spiffs/CMakeLists.txt +++ b/components/spiffs/CMakeLists.txt @@ -10,4 +10,6 @@ idf_component_register(SRCS "esp_spiffs.c" REQUIRES spi_flash PRIV_REQUIRES bootloader_support esptool_py) -set_source_files_properties(spiffs/src/spiffs_nucleus.c PROPERTIES COMPILE_FLAGS -Wno-stringop-truncation) +if(CMAKE_C_COMPILER_ID MATCHES "GNU") + set_source_files_properties(spiffs/src/spiffs_nucleus.c PROPERTIES COMPILE_FLAGS -Wno-stringop-truncation) +endif() diff --git a/components/tcp_transport/transport_ssl.c b/components/tcp_transport/transport_ssl.c index d08061b179..988995ce56 100644 --- a/components/tcp_transport/transport_ssl.c +++ b/components/tcp_transport/transport_ssl.c @@ -446,6 +446,9 @@ esp_transport_handle_t esp_transport_ssl_init(void) struct transport_esp_tls* esp_transport_esp_tls_create(void) { transport_esp_tls_t *transport_esp_tls = calloc(1, sizeof(transport_esp_tls_t)); + if (transport_esp_tls == NULL) { + return NULL; + } transport_esp_tls->sockfd = INVALID_SOCKET; return transport_esp_tls; } diff --git a/components/tcpip_adapter/tcpip_adapter_compat.c b/components/tcpip_adapter/tcpip_adapter_compat.c index b3955020ac..bcd798fe7a 100644 --- a/components/tcpip_adapter/tcpip_adapter_compat.c +++ b/components/tcpip_adapter/tcpip_adapter_compat.c @@ -109,7 +109,7 @@ void tcpip_adapter_init(void) esp_err_t tcpip_adapter_clear_default_eth_handlers(void) { - return esp_eth_clear_default_handlers(netif_from_if(TCPIP_ADAPTER_IF_ETH)); + return ESP_OK; } esp_err_t tcpip_adapter_set_default_eth_handlers(void) @@ -119,8 +119,6 @@ esp_err_t tcpip_adapter_set_default_eth_handlers(void) esp_netif_t *eth_netif = esp_netif_new(&cfg); s_esp_netifs[TCPIP_ADAPTER_IF_ETH] = eth_netif; - - return esp_eth_set_default_handlers(eth_netif); } return ESP_OK; diff --git a/components/tinyusb/CMakeLists.txt b/components/tinyusb/CMakeLists.txt index b180c75e23..e7c1b7edbc 100644 --- a/components/tinyusb/CMakeLists.txt +++ b/components/tinyusb/CMakeLists.txt @@ -73,7 +73,7 @@ endif() # CONFIG_TINYUSB idf_component_register(SRCS ${srcs} INCLUDE_DIRS ${includes_public} PRIV_INCLUDE_DIRS ${includes_private} - PRIV_REQUIRES "vfs" + PRIV_REQUIRES "vfs" "usb" ) if(CONFIG_TINYUSB) diff --git a/components/tinyusb/additions/include/tusb_cdc_acm.h b/components/tinyusb/additions/include/tusb_cdc_acm.h index af7985e6c4..fb837a5f31 100644 --- a/components/tinyusb/additions/include/tusb_cdc_acm.h +++ b/components/tinyusb/additions/include/tusb_cdc_acm.h @@ -157,7 +157,7 @@ size_t tinyusb_cdcacm_write_queue_char(tinyusb_cdcacm_itf_t itf, char ch); * @param in_size - size to write from arr_src * @return size_t - amount of queued bytes */ -size_t tinyusb_cdcacm_write_queue(tinyusb_cdcacm_itf_t itf, uint8_t *in_buf, size_t in_size); +size_t tinyusb_cdcacm_write_queue(tinyusb_cdcacm_itf_t itf, const uint8_t *in_buf, size_t in_size); /** * @brief Send all data from a write buffer. Use `tinyusb_cdcacm_write_queue` to add data to the buffer. diff --git a/components/tinyusb/additions/src/tusb_cdc_acm.c b/components/tinyusb/additions/src/tusb_cdc_acm.c index f2e536c64b..4dad2bc062 100644 --- a/components/tinyusb/additions/src/tusb_cdc_acm.c +++ b/components/tinyusb/additions/src/tusb_cdc_acm.c @@ -290,7 +290,7 @@ size_t tinyusb_cdcacm_write_queue_char(tinyusb_cdcacm_itf_t itf, char ch) } -size_t tinyusb_cdcacm_write_queue(tinyusb_cdcacm_itf_t itf, uint8_t *in_buf, size_t in_size) +size_t tinyusb_cdcacm_write_queue(tinyusb_cdcacm_itf_t itf, const uint8_t *in_buf, size_t in_size) { if (!get_acm(itf)) { // non-initialized return 0; diff --git a/components/unity/CMakeLists.txt b/components/unity/CMakeLists.txt index 10865c3afd..14184db294 100644 --- a/components/unity/CMakeLists.txt +++ b/components/unity/CMakeLists.txt @@ -1,3 +1,5 @@ +idf_build_get_property(target IDF_TARGET) + set(srcs "unity/src/unity.c") @@ -5,6 +7,8 @@ set(includes "include" "unity/src") +set(requires "") + if(CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL) list(APPEND COMPONENT_PRIV_INCLUDEDIRS "include/priv") endif() @@ -18,17 +22,15 @@ if(CONFIG_UNITY_ENABLE_FIXTURE) list(APPEND includes "unity/extras/fixture/src") endif() -if(${IDF_TARGET} STREQUAL "linux") - idf_component_get_property(spi_flash_dir spi_flash COMPONENT_DIR) - list(APPEND includes "${spi_flash_dir}/sim/stubs/esp_common") -else() +if(NOT "${target}" STREQUAL "linux") list(APPEND srcs "unity_port_esp32.c") endif() idf_component_register(SRCS "${srcs}" - INCLUDE_DIRS ${includes}) + INCLUDE_DIRS ${includes} + REQUIRES ${requires}) -if(NOT ${IDF_TARGET} STREQUAL "linux") +if(NOT "${target}" STREQUAL "linux") target_compile_definitions(${COMPONENT_LIB} PUBLIC -DUNITY_INCLUDE_CONFIG_H ) diff --git a/components/usb/CMakeLists.txt b/components/usb/CMakeLists.txt index 20d143ea6e..5bf8229d5c 100644 --- a/components/usb/CMakeLists.txt +++ b/components/usb/CMakeLists.txt @@ -4,7 +4,14 @@ set(priv_include) set(priv_require) if(CONFIG_USB_OTG_SUPPORTED) - list(APPEND srcs "hcd.c") + list(APPEND srcs "hcd.c" + "hub.c" + "usb_helpers.c" + "usb_host.c" + "usb_private.c" + "usbh.c" + "usb_phy.c") + list(APPEND include "include") list(APPEND priv_include "private_include") list(APPEND priv_require "hal" "driver") endif() diff --git a/components/usb/Kconfig b/components/usb/Kconfig index 2be5c9da6b..939a2b1d14 100644 --- a/components/usb/Kconfig +++ b/components/usb/Kconfig @@ -6,4 +6,51 @@ menu "USB-OTG" bool default y if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 -endmenu + config USB_HOST_CONTROL_TRANSFER_MAX_SIZE + depends on USB_OTG_SUPPORTED + int "Largest size (in bytes) of transfers to/from default endpoints" + default 256 + help + Each USB device attached is allocated a dedicated buffer for its OUT/IN transfers to/from the device's + control endpoint. The maximum size of that buffer is determined by this option. The limited size of the + transfer buffer have the following implications: + - The maximum length of control transfers is limited + - Device's with configuration descriptors larger than this limit cannot be supported + + choice USB_HOST_HW_BUFFER_BIAS + depends on USB_OTG_SUPPORTED + prompt "Hardware FIFO size biasing" + default USB_HOST_HW_BUFFER_BIAS_BALANCED + help + The underlying hardware has size adjustable FIFOs to cache USB packets on reception (IN) or for + transmission (OUT). The size of these FIFOs will affect the largest MPS (maximum packet size) and the + maximum number of packets that can be cached at any one time. The hardware contains the following + FIFOS: RX (for all IN packets), Non-periodic TX (for Bulk and Control OUT packets), and Periodic TX + (for Interrupt and Isochronous OUT packets). This configuration option allows biasing the FIFO sizes + towards a particular use case, which may be necessary for devices that have endpoints with large MPS. + The MPS limits for each biasing are listed below: + + Balanced: + - IN (all transfer types), 408 bytes + - OUT non-periodic (Bulk/Control), 192 bytes (i.e., 3 x 64 byte packets) + - OUT periodic (Interrupt/Isochronous), 192 bytes + + Bias IN: + - IN (all transfer types), 600 bytes + - OUT non-periodic (Bulk/Control), 64 bytes (i.e., 1 x 64 byte packets) + - OUT periodic (Interrupt/Isochronous), 128 bytes + + Bias Periodic OUT: + - IN (all transfer types), 128 bytes + - OUT non-periodic (Bulk/Control), 64 bytes (i.e., 1 x 64 byte packets) + - OUT periodic (Interrupt/Isochronous), 600 bytes + + config USB_HOST_HW_BUFFER_BIAS_BALANCED + bool "Balanced" + config USB_HOST_HW_BUFFER_BIAS_IN + bool "Bias IN" + config USB_HOST_HW_BUFFER_BIAS_PERIODIC_OUT + bool "Periodic OUT" + endchoice + +endmenu #USB-OTG diff --git a/components/usb/hcd.c b/components/usb/hcd.c index 5e94b5921b..87be3a350a 100644 --- a/components/usb/hcd.c +++ b/components/usb/hcd.c @@ -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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -30,7 +22,9 @@ #include "driver/periph_ctrl.h" #include "hcd.h" #include "usb_private.h" -#include "usb.h" +#include "usb/usb_types_ch9.h" + +#include "esp_rom_sys.h" // ----------------------------------------------------- Macros -------------------------------------------------------- @@ -219,13 +213,11 @@ typedef struct { } flags; union { struct { - uint32_t stop_idx: 8; //The descriptor index when the channel was halted uint32_t executing: 1; //The buffer is currently executing - uint32_t error_occurred: 1; //An error occurred - uint32_t cancelled: 1; //The buffer was actively cancelled - uint32_t reserved5: 5; - hcd_pipe_state_t pipe_state: 8; //The pipe's state when the error occurred - hcd_pipe_event_t pipe_event: 8; //The pipe event when the error occurred + uint32_t reserved7: 7; + uint32_t stop_idx: 8; //The descriptor index when the channel was halted + hcd_pipe_event_t pipe_event: 8; //The pipe event when the buffer was done + uint32_t reserved8: 8; }; uint32_t val; } status_flags; //Status flags for the buffer @@ -236,8 +228,8 @@ typedef struct { */ struct pipe_obj { //URB queueing related - TAILQ_HEAD(tailhead_urb_pending, urb_obj) pending_urb_tailq; - TAILQ_HEAD(tailhead_urb_done, urb_obj) done_urb_tailq; + TAILQ_HEAD(tailhead_urb_pending, urb_s) pending_urb_tailq; + TAILQ_HEAD(tailhead_urb_done, urb_s) done_urb_tailq; int num_urb_pending; int num_urb_done; //Multi-buffer control @@ -268,13 +260,12 @@ struct pipe_obj { TaskHandle_t task_waiting_pipe_notif; //Task handle used for internal pipe events union { struct { - uint32_t waiting_xfer_done: 1; - uint32_t paused: 1; + uint32_t waiting_halt: 1; uint32_t pipe_cmd_processing: 1; - uint32_t is_active: 1; + uint32_t has_urb: 1; //Indicates there is at least one URB either pending, inflight, or done uint32_t persist: 1; //indicates that this pipe should persist through a run-time port reset uint32_t reset_lock: 1; //Indicates that this pipe is undergoing a run-time reset - uint32_t reserved26: 26; + uint32_t reserved27: 27; }; uint32_t val; } cs_flags; @@ -305,17 +296,17 @@ struct port_obj { uint32_t event_pending: 1; //The port has an event that needs to be handled uint32_t event_processing: 1; //The port is current processing (handling) an event uint32_t cmd_processing: 1; //Used to indicate command handling is ongoing - uint32_t waiting_all_pipes_pause: 1; //Waiting for all pipes routed through this port to be paused uint32_t disable_requested: 1; uint32_t conn_dev_ena: 1; //Used to indicate the port is connected to a device that has been reset uint32_t periodic_scheduling_enabled: 1; - uint32_t reserved9:9; - uint32_t num_pipes_waiting_pause: 16; + uint32_t reserved26: 26; }; uint32_t val; } flags; bool initialized; - hcd_port_fifo_bias_t fifo_bias; + //FIFO biasing related + const usbh_hal_fifo_config_t *fifo_config; + const fifo_mps_limits_t *fifo_mps_limits; //Port callback and context hcd_port_callback_t callback; void *callback_arg; @@ -400,13 +391,30 @@ static void _buffer_exec(pipe_t *pipe); * @brief Check if a buffer as completed execution * * This should only be called after receiving a USBH_HAL_CHAN_EVENT_CPLT event to check if a buffer is actually - * done. Buffers that aren't complete (such as Control transfers) will be continued automatically. + * done. * * @param pipe Pipe object * @return true Buffer complete * @return false Buffer not complete */ -static bool _buffer_check_done(pipe_t *pipe); +static inline bool _buffer_check_done(pipe_t *pipe) +{ + if (pipe->ep_char.type != USB_PRIV_XFER_TYPE_CTRL) { + return true; + } + //Only control transfers need to be continued + dma_buffer_block_t *buffer_inflight = pipe->buffers[pipe->multi_buffer_control.rd_idx]; + return (buffer_inflight->flags.ctrl.cur_stg == 2); +} + +/** + * @brief Continue execution of a buffer + * + * This should only be called after checking if a buffer has completed execution using _buffer_check_done() + * + * @param pipe Pipe object + */ +static void _buffer_exec_cont(pipe_t *pipe); /** * @brief Marks the last executed buffer as complete @@ -415,40 +423,14 @@ static bool _buffer_check_done(pipe_t *pipe); * * @param pipe Pipe object * @param stop_idx Descriptor index when the buffer stopped execution + * @param pipe_event Pipe event that caused the buffer to be complete */ -static inline void _buffer_done(pipe_t *pipe, int stop_idx) +static inline void _buffer_done(pipe_t *pipe, int stop_idx, hcd_pipe_event_t pipe_event) { - //Store the stop_idx for later parsing + //Store the stop_idx and pipe_event for later parsing dma_buffer_block_t *buffer_done = pipe->buffers[pipe->multi_buffer_control.rd_idx]; buffer_done->status_flags.executing = 0; - buffer_done->status_flags.error_occurred = 0; buffer_done->status_flags.stop_idx = stop_idx; - pipe->multi_buffer_control.rd_idx++; - pipe->multi_buffer_control.buffer_num_to_exec--; - pipe->multi_buffer_control.buffer_num_to_parse++; - pipe->multi_buffer_control.buffer_is_executing = 0; -} - -/** - * @brief Marks the last executed buffer as complete due to an error - * - * This should be called on a pipe that has received a USBH_HAL_CHAN_EVENT_ERROR event - * - * @param pipe Pipe object - * @param stop_idx Descriptor index when the buffer stopped execution - * @param pipe_state State of the pipe after the error - * @param pipe_event Error event - * @param cancelled Whether the pipe stopped due to cancellation - */ -static inline void _buffer_done_error(pipe_t *pipe, int stop_idx, hcd_pipe_state_t pipe_state, hcd_pipe_event_t pipe_event, bool cancelled) -{ - //Mark the buffer as erroneous for later parsing - dma_buffer_block_t *buffer_done = pipe->buffers[pipe->multi_buffer_control.rd_idx]; - buffer_done->status_flags.executing = 0; - buffer_done->status_flags.error_occurred = 1; - buffer_done->status_flags.cancelled = cancelled; - buffer_done->status_flags.stop_idx = stop_idx; - buffer_done->status_flags.pipe_state = pipe_state; buffer_done->status_flags.pipe_event = pipe_event; pipe->multi_buffer_control.rd_idx++; pipe->multi_buffer_control.buffer_num_to_exec--; @@ -493,50 +475,13 @@ static void _buffer_parse(pipe_t *pipe); * * @param pipe Pipe object * @param cancelled Whether this flush is due to cancellation + * @return true One or more buffers were flushed + * @return false There were no buffers that needed to be flushed */ -static void _buffer_flush_all(pipe_t *pipe, bool cancelled); +static bool _buffer_flush_all(pipe_t *pipe, bool cancelled); // ------------------------ Pipe --------------------------- -/** - * @brief Wait until a pipe's in-flight URB is done - * - * If the pipe has an in-flight URB, this function will block until it is done (via a internal pipe event). - * If the pipe has no in-flight URB, this function do nothing and return immediately. - * If the pipe's state changes unexpectedly, this function will return false. - * - * Also parses all buffers on exit - * - * @note This function is blocking (will exit and re-enter the critical section to do so) - * - * @param pipe Pipe object - * @return true Pipes in-flight URB is done - * @return false Pipes state unexpectedly changed - */ -static bool _pipe_wait_done(pipe_t *pipe); - -/** - * @brief Retires all URBs (those that were previously in-flight or pending) - * - * Retiring all URBs will result in any pending URB being moved to the done tailq. This function will update the IPR - * status of each URB. - * - If the retiring is self-initiated (i.e., due to a pipe command), the URB status will be set to USB_TRANSFER_STATUS_CANCELED. - * - If the retiring is NOT self-initiated (i.e., the pipe is no longer valid), the URB status will be set to USB_TRANSFER_STATUS_NO_DEVICE - * - * Entry: - * - There can be no in-flight URB (must already be parsed and returned to done queue) - * - All buffers must be parsed - * Exit: - * - If there was an in-flight URB, it is parsed and returned to the done queue - * - If there are any pending URBs: - * - They are moved to the done tailq - * - * @param pipe Pipe object - * @param cancelled Are we actively Pipe retire is initialized by the user due to a command, thus URB are - * actively cancelled. - */ -static void _pipe_retire(pipe_t *pipe, bool self_initiated); - /** * @brief Decode a HAL channel error to the corresponding pipe event * @@ -545,59 +490,47 @@ static void _pipe_retire(pipe_t *pipe, bool self_initiated); */ static inline hcd_pipe_event_t pipe_decode_error_event(usbh_hal_chan_error_t chan_error); +/** + * @brief Halt a pipe + * + * - Attempts to halt a pipe. Pipe must be active in order to be halted + * - If the underlying channel has an ongoing transfer, a halt will be requested, then the function will block until the + * channel indicates it is halted + * - If the channel is no on-going transfer, the pipe will simply be marked has halted (thus preventing any further URBs + * from being enqueued) + * + * @note This function can block + * @param pipe Pipe object + * @return esp_err_t + */ +static esp_err_t _pipe_cmd_halt(pipe_t *pipe); + +/** + * @brief Flush a pipe + * + * - Flushing a pipe causes all of its pending URBs to be become done, thus allowing them to be dequeued + * - The pipe must be halted in order to be flushed + * - The pipe callback will be run if one or more URBs become done + * + * @param pipe Pipe object + * @return esp_err_t + */ +static esp_err_t _pipe_cmd_flush(pipe_t *pipe); + +/** + * @brief Clear a pipe from its halt + * + * - Pipe must be halted in order to be cleared + * - Clearing a pipe makes it active again + * - If there are any enqueued URBs, they will executed + * + * @param pipe Pipe object + * @return esp_err_t + */ +static esp_err_t _pipe_cmd_clear(pipe_t *pipe); + // ------------------------ Port --------------------------- -/** - * @brief Invalidates all the pipes routed through a port - * - * This should be called when port or its connected device is no longer valid (e.g., the port is suddenly reset/disabled - * or the device suddenly disconnects) - * - * @note This function may run one or more callbacks, and will exit and enter the critical section to do so - * - * Entry: - * - The port or its connected device is no longer valid. This guarantees that none of the pipes will be transferring - * Exit: - * - Each pipe will have any pending URBs moved to their respective done tailq - * - Each pipe will be put into the invalid state - * - Generate a HCD_PIPE_EVENT_INVALID event on each pipe and run their respective callbacks - * - * @param port Port object - */ -static void _port_invalidate_all_pipes(port_t *port); - -/** - * @brief Pause all pipes routed through a port - * - * Call this before attempting to reset or suspend a port - * - * Entry: - * - The port is in the HCD_PORT_STATE_ENABLED state (i.e., there is a connected device which has been reset) - * Exit: - * - All pipes routed through the port have either paused, or are waiting to complete their in-flight URBs before pausing - * - If waiting for one or more pipes to pause, _internal_port_event_wait() must be called after this function returns - * - * @param port Port object - * @return true All pipes have been paused - * @return false Need to wait for one or more pipes to pause. Call _internal_port_event_wait() afterwards - */ -static bool _port_pause_all_pipes(port_t *port); - -/** - * @brief Un-pause all pipes routed through a port - * - * Call this before after coming out of a port reset or resume. - * - * Entry: - * - The port is in the HCD_PORT_STATE_ENABLED state - * - All pipes are paused - * Exit: - * - All pipes un-paused. If those pipes have pending URBs, they will be started. - * - * @param port Port object - */ -static void _port_unpause_all_pipes(port_t *port); - /** * @brief Prepare persistent pipes for reset * @@ -621,72 +554,13 @@ static bool _port_persist_all_pipes(port_t *port); static void _port_recover_all_pipes(port_t *port); /** - * @brief Send a reset condition on a port's bus - * - * Entry: - * - The port must be in the HCD_PORT_STATE_ENABLED or HCD_PORT_STATE_DISABLED state - * Exit: - * - Reset condition sent on the port's bus - * - * @note This function is blocking (will exit and re-enter the critical section to do so) + * @brief Checks if all pipes are in the halted state * * @param port Port object - * @return true Reset condition successfully sent - * @return false Failed to send reset condition due to unexpected port state + * @return true All pipes are halted + * @return false Not all pipes are halted */ -static bool _port_bus_reset(port_t *port); - -/** - * @brief Send a suspend condition on a port's bus - * - * This function will first pause pipes routed through a port, and then send a suspend condition. - * - * Entry: - * - The port must be in the HCD_PORT_STATE_ENABLED state - * Exit: - * - All pipes paused and the port is put into the suspended state - * - * @note This function is blocking (will exit and re-enter the critical section to do so) - * - * @param port Port object - * @return true Suspend condition successfully sent. Port is now in the HCD_PORT_STATE_SUSPENDED state - * @return false Failed to send a suspend condition due to unexpected port state - */ -static bool _port_bus_suspend(port_t *port); - -/** - * @brief Send a resume condition on a port's bus - * - * This function will send a resume condition, and then un-pause all the pipes routed through a port - * - * Entry: - * - The port must be in the HCD_PORT_STATE_SUSPENDED state - * Exit: - * - The port is put into the enabled state and all pipes un-paused - * - * @note This function is blocking (will exit and re-enter the critical section to do so) - * - * @param port Port object - * @return true Resume condition successfully sent. Port is now in the HCD_PORT_STATE_ENABLED state - * @return false Failed to send a resume condition due to unexpected port state. - */ -static bool _port_bus_resume(port_t *port); - -/** - * @brief Disable a port - * - * Entry: - * - The port must be in the HCD_PORT_STATE_ENABLED or HCD_PORT_STATE_SUSPENDED state - * Exit: - * - All pipes paused (should already be paused if port was suspended), and the port is put into the disabled state. - * - * @note This function is blocking (will exit and re-enter the critical section to do so) - * - * @param port Port object - * @return true Port successfully disabled - * @return false Port to disable port due to unexpected port state - */ -static bool _port_disable(port_t *port); +static bool _port_check_all_pipes_halted(port_t *port); /** * @brief Debounce port after a connection or disconnection event @@ -694,12 +568,77 @@ static bool _port_disable(port_t *port); * This function should be called after a port connection or disconnect event. This function will execute a debounce * delay then check the actual connection/disconnections state. * + * @note This function can block * @param port Port object * @return true A device is connected * @return false No device connected */ static bool _port_debounce(port_t *port); +/** + * @brief Power ON the port + * + * @param port Port object + * @return esp_err_t + */ +static esp_err_t _port_cmd_power_on(port_t *port); + +/** + * @brief Power OFF the port + * + * - If a device is currently connected, this function will cause a disconnect event + * + * @param port Port object + * @return esp_err_t + */ +static esp_err_t _port_cmd_power_off(port_t *port); + +/** + * @brief Reset the port + * + * - This function issues a reset signal using the timings specified by the USB2.0 spec + * + * @note This function can block + * @param port Port object + * @return esp_err_t + */ +static esp_err_t _port_cmd_reset(port_t *port); + +/** + * @brief Suspend the port + * + * - Port must be enabled in order to to be suspended + * - All pipes must be halted for the port to be suspended + * - Suspending the port stops Keep Alive/SOF from being sent to the connected device + * + * @param port Port object + * @return esp_err_t + */ +static esp_err_t _port_cmd_bus_suspend(port_t *port); + +/** + * @brief Resume the port + * + * - Port must be suspended in order to be resumed + * + * @note This function can block + * @param port Port object + * @return esp_err_t + */ +static esp_err_t _port_cmd_bus_resume(port_t *port); + +/** + * @brief Disable the port + * + * - All pipes must be halted for the port to be disabled + * - The port must be enabled or suspended in order to be disabled + * + * @note This function can block + * @param port Port object + * @return esp_err_t + */ +static esp_err_t _port_cmd_disable(port_t *port); + // ----------------------- Events -------------------------- /** @@ -822,14 +761,8 @@ static hcd_port_event_t _intr_hdlr_hprt(port_t *port, usbh_hal_port_event_t hal_ break; } case USBH_HAL_PORT_EVENT_DISCONN: { - if (port->flags.conn_dev_ena) { - //The port was previously enabled, so this is a sudden disconnection - port->state = HCD_PORT_STATE_RECOVERY; - port_event = HCD_PORT_EVENT_SUDDEN_DISCONN; - } else { - //For normal disconnections, don't update state immediately as we still need to debounce. - port_event = HCD_PORT_EVENT_DISCONNECTION; - } + port->state = HCD_PORT_STATE_RECOVERY; + port_event = HCD_PORT_EVENT_DISCONNECTION; port->flags.conn_dev_ena = 0; break; } @@ -892,31 +825,27 @@ static hcd_pipe_event_t _intr_hdlr_chan(pipe_t *pipe, usbh_hal_chan_t *chan_obj, { usbh_hal_chan_event_t chan_event = usbh_hal_chan_decode_intr(chan_obj); hcd_pipe_event_t event = HCD_PIPE_EVENT_NONE; - //Check the the pipe's port still has a connected and enabled device before processing the interrupt - if (!pipe->port->flags.conn_dev_ena) { - return event; //Treat as a no event. - } - bool handle_waiting_xfer_done = false; + switch (chan_event) { case USBH_HAL_CHAN_EVENT_CPLT: { if (!_buffer_check_done(pipe)) { + _buffer_exec_cont(pipe); break; } pipe->last_event = HCD_PIPE_EVENT_URB_DONE; event = pipe->last_event; //Mark the buffer as done int stop_idx = usbh_hal_chan_get_qtd_idx(chan_obj); - _buffer_done(pipe, stop_idx); - //First check if there is another buffer we can execute - if (_buffer_can_exec(pipe) && !pipe->cs_flags.waiting_xfer_done) { + _buffer_done(pipe, stop_idx, pipe->last_event); + //First check if there is another buffer we can execute. But we only want to execute if there's still a valid device + if (_buffer_can_exec(pipe) && pipe->port->flags.conn_dev_ena) { //If the next buffer is filled and ready to execute, execute it _buffer_exec(pipe); } //Handle the previously done buffer _buffer_parse(pipe); - if (pipe->cs_flags.waiting_xfer_done) { - handle_waiting_xfer_done = true; - } else if (_buffer_can_fill(pipe)) { + //Check to see if we can fill another buffer. But we only want to fill if there is still a valid device + if (_buffer_can_fill(pipe) && pipe->port->flags.conn_dev_ena) { //Now that we've parsed a buffer, see if another URB can be filled in its place _buffer_fill(pipe); } @@ -931,39 +860,33 @@ static hcd_pipe_event_t _intr_hdlr_chan(pipe_t *pipe, usbh_hal_chan_t *chan_obj, pipe->state = HCD_PIPE_STATE_HALTED; //Mark the buffer as done with an error int stop_idx = usbh_hal_chan_get_qtd_idx(chan_obj); - _buffer_done_error(pipe, stop_idx, pipe->state, pipe->last_event, false); + _buffer_done(pipe, stop_idx, pipe->last_event); //Parse the buffer _buffer_parse(pipe); - if (pipe->cs_flags.waiting_xfer_done) { - handle_waiting_xfer_done = true; - } + break; + } + case USBH_HAL_CHAN_EVENT_HALT_REQ: { + assert(pipe->cs_flags.waiting_halt); + //We've halted a transfer, so we need to trigger the pipe callback + pipe->last_event = HCD_PIPE_EVENT_URB_DONE; + event = pipe->last_event; + //Halt request event is triggered when packet is successful completed. But just treat all halted transfers as errors + pipe->state = HCD_PIPE_STATE_HALTED; + int stop_idx = usbh_hal_chan_get_qtd_idx(chan_obj); + _buffer_done(pipe, stop_idx, HCD_PIPE_EVENT_NONE); + //Parse the buffer + _buffer_parse(pipe); + //Notify the task waiting for the pipe halt + *yield |= _internal_pipe_event_notify(pipe, true); break; } case USBH_HAL_CHAN_EVENT_NONE: { break; //Nothing to do } - case USBH_HAL_CHAN_EVENT_HALT_REQ: //We currently don't halt request so this event should never occur default: abort(); break; } - if (handle_waiting_xfer_done) { - //A port/pipe command is waiting for this pipe to complete its transfer. So don't load the next transfer - pipe->cs_flags.waiting_xfer_done = 0; - if (pipe->port->flags.waiting_all_pipes_pause) { - //Port command is waiting for all pipes to be paused - pipe->cs_flags.paused = 1; - pipe->port->flags.num_pipes_waiting_pause--; - if (pipe->port->flags.num_pipes_waiting_pause == 0) { - //All pipes have finished pausing, Notify the blocked port command - pipe->port->flags.waiting_all_pipes_pause = 0; - *yield |= _internal_port_event_notify_from_isr(pipe->port); - } - } else { - //Pipe command is waiting for transfer to complete - *yield |= _internal_pipe_event_notify(pipe, true); - } - } return event; } @@ -1138,94 +1061,7 @@ esp_err_t hcd_uninstall(void) // ------------------------------------------------------ Port --------------------------------------------------------- -// ----------------------- Private ------------------------- - -static void _port_invalidate_all_pipes(port_t *port) -{ - //This function should only be called when the port is invalid - assert(!port->flags.conn_dev_ena); - pipe_t *pipe; - //Process all pipes that have queued URBs - TAILQ_FOREACH(pipe, &port->pipes_active_tailq, tailq_entry) { - //Mark the pipe as invalid and set an invalid event - pipe->state = HCD_PIPE_STATE_INVALID; - pipe->last_event = HCD_PIPE_EVENT_INVALID; - //Flush all buffers that are still awaiting exec - _buffer_flush_all(pipe, false); - //Retire any remaining URBs in the pending tailq - _pipe_retire(pipe, false); - if (pipe->task_waiting_pipe_notif != NULL) { - //Unblock the thread/task waiting for a notification from the pipe as the pipe is no longer valid. - _internal_pipe_event_notify(pipe, false); - } - if (pipe->callback != NULL) { - HCD_EXIT_CRITICAL(); - (void) pipe->callback((hcd_pipe_handle_t)pipe, HCD_PIPE_EVENT_INVALID, pipe->callback_arg, false); - HCD_ENTER_CRITICAL(); - } - } - //Process all idle pipes - TAILQ_FOREACH(pipe, &port->pipes_idle_tailq, tailq_entry) { - //Mark pipe as invalid and call its callback - pipe->state = HCD_PIPE_STATE_INVALID; - pipe->last_event = HCD_PIPE_EVENT_INVALID; - if (pipe->callback != NULL) { - HCD_EXIT_CRITICAL(); - (void) pipe->callback((hcd_pipe_handle_t)pipe, HCD_PIPE_EVENT_INVALID, pipe->callback_arg, false); - HCD_ENTER_CRITICAL(); - } - } -} - -static bool _port_pause_all_pipes(port_t *port) -{ - assert(port->state == HCD_PORT_STATE_ENABLED); - pipe_t *pipe; - int num_pipes_waiting_done = 0; - //Process all pipes that have queued URBs - TAILQ_FOREACH(pipe, &port->pipes_active_tailq, tailq_entry) { - //Check if pipe is currently executing - if (pipe->multi_buffer_control.buffer_is_executing) { - //Pipe is executing a buffer. Indicate to the pipe we are waiting the buffer's transfer to complete - pipe->cs_flags.waiting_xfer_done = 1; - num_pipes_waiting_done++; - } else { - //No buffer is being executed so need to wait - pipe->cs_flags.paused = 1; - } - } - //Process all idle pipes. They don't have queue transfer so just mark them as paused - TAILQ_FOREACH(pipe, &port->pipes_idle_tailq, tailq_entry) { - pipe->cs_flags.paused = 1; - } - if (num_pipes_waiting_done > 0) { - //Indicate we need to wait for one or more pipes to complete their transfers - port->flags.num_pipes_waiting_pause = num_pipes_waiting_done; - port->flags.waiting_all_pipes_pause = 1; - return false; - } - return true; -} - -static void _port_unpause_all_pipes(port_t *port) -{ - assert(port->state == HCD_PORT_STATE_ENABLED); - pipe_t *pipe; - //Process all idle pipes. They don't have queue transfer so just mark them as un-paused - TAILQ_FOREACH(pipe, &port->pipes_idle_tailq, tailq_entry) { - pipe->cs_flags.paused = 0; - } - //Process all pipes that have queued URBs - TAILQ_FOREACH(pipe, &port->pipes_active_tailq, tailq_entry) { - pipe->cs_flags.paused = 0; - if (_buffer_can_fill(pipe)) { - _buffer_fill(pipe); - } - if (_buffer_can_exec(pipe)) { - _buffer_exec(pipe); - } - } -} +// ----------------------- Helpers ------------------------- static bool _port_persist_all_pipes(port_t *port) { @@ -1264,108 +1100,23 @@ static void _port_recover_all_pipes(port_t *port) } } -static bool _port_bus_reset(port_t *port) +static bool _port_check_all_pipes_halted(port_t *port) { - assert(port->state == HCD_PORT_STATE_ENABLED || port->state == HCD_PORT_STATE_DISABLED); - //Put and hold the bus in the reset state. If the port was previously enabled, a disabled event will occur after this - port->state = HCD_PORT_STATE_RESETTING; - usbh_hal_port_toggle_reset(port->hal, true); - HCD_EXIT_CRITICAL(); - vTaskDelay(pdMS_TO_TICKS(RESET_HOLD_MS)); - HCD_ENTER_CRITICAL(); - if (port->state != HCD_PORT_STATE_RESETTING) { - //The port state has unexpectedly changed - goto bailout; - } - //Return the bus to the idle state and hold it for the required reset recovery time. Port enabled event should occur - usbh_hal_port_toggle_reset(port->hal, false); - HCD_EXIT_CRITICAL(); - vTaskDelay(pdMS_TO_TICKS(RESET_RECOVERY_MS)); - HCD_ENTER_CRITICAL(); - if (port->state != HCD_PORT_STATE_ENABLED || !port->flags.conn_dev_ena) { - //The port state has unexpectedly changed - goto bailout; - } - return true; -bailout: - return false; -} - -static bool _port_bus_suspend(port_t *port) -{ - assert(port->state == HCD_PORT_STATE_ENABLED); - //Pause all pipes before suspending the bus - if (!_port_pause_all_pipes(port)) { - //Need to wait for some pipes to pause. Wait for notification from ISR - _internal_port_event_wait(port); - if (port->state != HCD_PORT_STATE_ENABLED || !port->flags.conn_dev_ena) { - //Port state unexpectedly changed - goto bailout; + bool all_halted = true; + pipe_t *pipe; + TAILQ_FOREACH(pipe, &port->pipes_active_tailq, tailq_entry) { + if (pipe->state != HCD_PIPE_STATE_HALTED) { + all_halted = false; + break; } } - //All pipes are guaranteed paused at this point. Proceed to suspend the port - usbh_hal_port_suspend(port->hal); - port->state = HCD_PORT_STATE_SUSPENDED; - return true; -bailout: - return false; -} - -static bool _port_bus_resume(port_t *port) -{ - assert(port->state == HCD_PORT_STATE_SUSPENDED); - //Put and hold the bus in the K state. - usbh_hal_port_toggle_resume(port->hal, true); - port->state = HCD_PORT_STATE_RESUMING; - HCD_EXIT_CRITICAL(); - vTaskDelay(pdMS_TO_TICKS(RESUME_HOLD_MS)); - HCD_ENTER_CRITICAL(); - //Return and hold the bus to the J state (as port of the LS EOP) - usbh_hal_port_toggle_resume(port->hal, false); - if (port->state != HCD_PORT_STATE_RESUMING || !port->flags.conn_dev_ena) { - //Port state unexpectedly changed - goto bailout; - } - HCD_EXIT_CRITICAL(); - vTaskDelay(pdMS_TO_TICKS(RESUME_RECOVERY_MS)); - HCD_ENTER_CRITICAL(); - if (port->state != HCD_PORT_STATE_RESUMING || !port->flags.conn_dev_ena) { - //Port state unexpectedly changed - goto bailout; - } - port->state = HCD_PORT_STATE_ENABLED; - _port_unpause_all_pipes(port); - return true; -bailout: - return false; -} - -static bool _port_disable(port_t *port) -{ - assert(port->state == HCD_PORT_STATE_ENABLED || port->state == HCD_PORT_STATE_SUSPENDED); - if (port->state == HCD_PORT_STATE_ENABLED) { - //There may be pipes that are still transferring, so pause them. - if (!_port_pause_all_pipes(port)) { - //Need to wait for some pipes to pause. Wait for notification from ISR - _internal_port_event_wait(port); - if (port->state != HCD_PORT_STATE_ENABLED || !port->flags.conn_dev_ena) { - //Port state unexpectedly changed - goto bailout; - } + TAILQ_FOREACH(pipe, &port->pipes_idle_tailq, tailq_entry) { + if (pipe->state != HCD_PIPE_STATE_HALTED) { + all_halted = false; + break; } } - //All pipes are guaranteed paused at this point. Proceed to suspend the port. This should trigger an internal event - port->flags.disable_requested = 1; - usbh_hal_port_disable(port->hal); - _internal_port_event_wait(port); - if (port->state != HCD_PORT_STATE_DISABLED) { - //Port state unexpectedly changed - goto bailout; - } - _port_invalidate_all_pipes(port); - return true; -bailout: - return false; + return all_halted; } static bool _port_debounce(port_t *port) @@ -1389,6 +1140,166 @@ static bool _port_debounce(port_t *port) return is_connected; } +// ---------------------- Commands ------------------------- + +static esp_err_t _port_cmd_power_on(port_t *port) +{ + esp_err_t ret; + //Port can only be powered on if it's currently unpowered + if (port->state == HCD_PORT_STATE_NOT_POWERED) { + port->state = HCD_PORT_STATE_DISCONNECTED; + usbh_hal_port_init(port->hal); + usbh_hal_port_toggle_power(port->hal, true); + ret = ESP_OK; + } else { + ret = ESP_ERR_INVALID_STATE; + } + return ret; +} + +static esp_err_t _port_cmd_power_off(port_t *port) +{ + esp_err_t ret; + //Port can only be unpowered if already powered + if (port->state != HCD_PORT_STATE_NOT_POWERED) { + port->state = HCD_PORT_STATE_NOT_POWERED; + usbh_hal_port_deinit(port->hal); + usbh_hal_port_toggle_power(port->hal, false); + //If a device is currently connected, this should trigger a disconnect event + ret = ESP_OK; + } else { + ret = ESP_ERR_INVALID_STATE; + } + return ret; +} + +static esp_err_t _port_cmd_reset(port_t *port) +{ + esp_err_t ret; + //Port can only a reset when it is in the enabled or disabled states (in case of new connection) + if (port->state != HCD_PORT_STATE_ENABLED && port->state != HCD_PORT_STATE_DISABLED) { + ret = ESP_ERR_INVALID_STATE; + goto exit; + } + bool is_runtime_reset = (port->state == HCD_PORT_STATE_ENABLED) ? true : false; + if (is_runtime_reset && !_port_persist_all_pipes(port)) { + //If this is a run time reset, check all pipes that are still allocated can persist the reset + ret = ESP_ERR_INVALID_STATE; + goto exit; + } + //All pipes (if any_) are guaranteed to be persistent at this point. Proceed to resetting the bus + port->state = HCD_PORT_STATE_RESETTING; + //Put and hold the bus in the reset state. If the port was previously enabled, a disabled event will occur after this + usbh_hal_port_toggle_reset(port->hal, true); + HCD_EXIT_CRITICAL(); + vTaskDelay(pdMS_TO_TICKS(RESET_HOLD_MS)); + HCD_ENTER_CRITICAL(); + if (port->state != HCD_PORT_STATE_RESETTING) { + //The port state has unexpectedly changed + ret = ESP_ERR_INVALID_RESPONSE; + goto bailout; + } + //Return the bus to the idle state and hold it for the required reset recovery time. Port enabled event should occur + usbh_hal_port_toggle_reset(port->hal, false); + HCD_EXIT_CRITICAL(); + vTaskDelay(pdMS_TO_TICKS(RESET_RECOVERY_MS)); + HCD_ENTER_CRITICAL(); + if (port->state != HCD_PORT_STATE_ENABLED || !port->flags.conn_dev_ena) { + //The port state has unexpectedly changed + ret = ESP_ERR_INVALID_RESPONSE; + goto bailout; + } + //Set FIFO sizes based on the selected biasing + usbh_hal_set_fifo_size(port->hal, port->fifo_config); + //We start periodic scheduling only after a RESET command since SOFs only start after a reset + usbh_hal_port_set_frame_list(port->hal, port->frame_list, FRAME_LIST_LEN); + usbh_hal_port_periodic_enable(port->hal); + ret = ESP_OK; +bailout: + if (is_runtime_reset) { + _port_recover_all_pipes(port); + } +exit: + return ret; +} + +static esp_err_t _port_cmd_bus_suspend(port_t *port) +{ + esp_err_t ret; + //Port must have been previously enabled, and all pipes must already be halted + if (port->state == HCD_PORT_STATE_ENABLED && !_port_check_all_pipes_halted(port)) { + ret = ESP_ERR_INVALID_STATE; + goto exit; + } + //All pipes are guaranteed halted at this point. Proceed to suspend the port + usbh_hal_port_suspend(port->hal); + port->state = HCD_PORT_STATE_SUSPENDED; + ret = ESP_OK; +exit: + return ret; +} + +static esp_err_t _port_cmd_bus_resume(port_t *port) +{ + esp_err_t ret; + //Port can only be resumed if it was previously suspended + if (port->state != HCD_PORT_STATE_SUSPENDED) { + ret = ESP_ERR_INVALID_STATE; + goto exit; + } + //Put and hold the bus in the K state. + usbh_hal_port_toggle_resume(port->hal, true); + port->state = HCD_PORT_STATE_RESUMING; + HCD_EXIT_CRITICAL(); + vTaskDelay(pdMS_TO_TICKS(RESUME_HOLD_MS)); + HCD_ENTER_CRITICAL(); + //Return and hold the bus to the J state (as port of the LS EOP) + usbh_hal_port_toggle_resume(port->hal, false); + if (port->state != HCD_PORT_STATE_RESUMING || !port->flags.conn_dev_ena) { + //Port state unexpectedly changed + ret = ESP_ERR_INVALID_RESPONSE; + goto exit; + } + HCD_EXIT_CRITICAL(); + vTaskDelay(pdMS_TO_TICKS(RESUME_RECOVERY_MS)); + HCD_ENTER_CRITICAL(); + if (port->state != HCD_PORT_STATE_RESUMING || !port->flags.conn_dev_ena) { + //Port state unexpectedly changed + ret = ESP_ERR_INVALID_RESPONSE; + goto exit; + } + port->state = HCD_PORT_STATE_ENABLED; + ret = ESP_OK; +exit: + return ret; +} + +static esp_err_t _port_cmd_disable(port_t *port) +{ + esp_err_t ret; + if (port->state != HCD_PORT_STATE_ENABLED && port->state != HCD_PORT_STATE_SUSPENDED) { + ret = ESP_ERR_INVALID_STATE; + goto exit; + } + //All pipes must be halted before disabling the port + if (!_port_check_all_pipes_halted(port)){ + ret = ESP_ERR_INVALID_STATE; + goto exit; + } + //All pipes are guaranteed to be halted or freed at this point. Proceed to disable the port + port->flags.disable_requested = 1; + usbh_hal_port_disable(port->hal); + _internal_port_event_wait(port); + if (port->state != HCD_PORT_STATE_DISABLED) { + //Port state unexpectedly changed + ret = ESP_ERR_INVALID_RESPONSE; + goto exit; + } + ret = ESP_OK; +exit: + return ret; +} + // ----------------------- Public -------------------------- esp_err_t hcd_port_init(int port_number, const hcd_port_config_t *port_config, hcd_port_handle_t *port_hdl) @@ -1396,6 +1307,29 @@ esp_err_t hcd_port_init(int port_number, const hcd_port_config_t *port_config, h HCD_CHECK(port_number > 0 && port_config != NULL && port_hdl != NULL, ESP_ERR_INVALID_ARG); HCD_CHECK(port_number <= NUM_PORTS, ESP_ERR_NOT_FOUND); + //Get a pointer to the correct FIFO bias constant values + const usbh_hal_fifo_config_t *fifo_config; + const fifo_mps_limits_t *mps_limits; + switch (port_config->fifo_bias) { + case HCD_PORT_FIFO_BIAS_BALANCED: + fifo_config = &fifo_config_default; + mps_limits = &mps_limits_default; + break; + case HCD_PORT_FIFO_BIAS_RX: + fifo_config = &fifo_config_bias_rx; + mps_limits = &mps_limits_bias_rx; + break; + case HCD_PORT_FIFO_BIAS_PTX: + fifo_config = &fifo_config_bias_ptx; + mps_limits = &mps_limits_bias_ptx; + break; + default: + fifo_config = NULL; + mps_limits = NULL; + abort(); + break; + } + HCD_ENTER_CRITICAL(); HCD_CHECK_FROM_CRIT(s_hcd_obj != NULL && !s_hcd_obj->port_obj->initialized, ESP_ERR_INVALID_STATE); //Port object memory and resources (such as the mutex) already be allocated. Just need to initialize necessary fields only @@ -1404,6 +1338,8 @@ esp_err_t hcd_port_init(int port_number, const hcd_port_config_t *port_config, h TAILQ_INIT(&port_obj->pipes_active_tailq); port_obj->state = HCD_PORT_STATE_NOT_POWERED; port_obj->last_event = HCD_PORT_EVENT_NONE; + port_obj->fifo_config = fifo_config; + port_obj->fifo_mps_limits = mps_limits; port_obj->callback = port_config->callback; port_obj->callback_arg = port_config->callback_arg; port_obj->context = port_config->context; @@ -1427,7 +1363,7 @@ esp_err_t hcd_port_deinit(hcd_port_handle_t port_hdl) HCD_CHECK_FROM_CRIT(s_hcd_obj != NULL && port->initialized && port->num_pipes_idle == 0 && port->num_pipes_queued == 0 && (port->state == HCD_PORT_STATE_NOT_POWERED || port->state == HCD_PORT_STATE_RECOVERY) - && port->flags.val == 0 && port->task_waiting_port_notif == NULL, + && port->task_waiting_port_notif == NULL, ESP_ERR_INVALID_STATE); port->initialized = false; esp_intr_disable(s_hcd_obj->isr_hdl); @@ -1447,74 +1383,27 @@ esp_err_t hcd_port_command(hcd_port_handle_t port_hdl, hcd_port_cmd_t command) port->flags.cmd_processing = 1; switch (command) { case HCD_PORT_CMD_POWER_ON: { - //Port can only be powered on if currently unpowered - if (port->state == HCD_PORT_STATE_NOT_POWERED) { - port->state = HCD_PORT_STATE_DISCONNECTED; - usbh_hal_port_init(port->hal); - usbh_hal_port_toggle_power(port->hal, true); - ret = ESP_OK; - } + ret = _port_cmd_power_on(port); break; } case HCD_PORT_CMD_POWER_OFF: { - //Port can only be unpowered if already powered - if (port->state != HCD_PORT_STATE_NOT_POWERED) { - port->state = HCD_PORT_STATE_NOT_POWERED; - usbh_hal_port_deinit(port->hal); - usbh_hal_port_toggle_power(port->hal, false); - //If a device is currently connected, this should trigger a disconnect event - ret = ESP_OK; - } + ret = _port_cmd_power_off(port); break; } case HCD_PORT_CMD_RESET: { - //Port can only a reset when it is in the enabled or disabled states (in case of new connection) - if (port->state == HCD_PORT_STATE_ENABLED || port->state == HCD_PORT_STATE_DISABLED) { - bool is_runtime_reset = (port->state == HCD_PORT_STATE_ENABLED) ? true : false; - if (is_runtime_reset) { - //Check all pipes that are still allocated are persistent before we execute the reset - if (!_port_persist_all_pipes(port)) { - ret = ESP_ERR_INVALID_STATE; - break; - } - } - if (_port_bus_reset(port)) { - //Set FIFO sizes to default - usbh_hal_set_fifo_size(port->hal, &fifo_config_default); - port->fifo_bias = HCD_PORT_FIFO_BIAS_BALANCED; - //We start periodic scheduling only after a RESET command since SOFs only start after a reset - usbh_hal_port_set_frame_list(port->hal, port->frame_list, FRAME_LIST_LEN); - usbh_hal_port_periodic_enable(port->hal); - ret = ESP_OK; - } else { - ret = ESP_ERR_INVALID_RESPONSE; - } - if (is_runtime_reset) { - _port_recover_all_pipes(port); - } - - } + ret = _port_cmd_reset(port); break; } case HCD_PORT_CMD_SUSPEND: { - //Port can only be suspended if already in the enabled state - if (port->state == HCD_PORT_STATE_ENABLED) { - ret = (_port_bus_suspend(port)) ? ESP_OK : ESP_ERR_INVALID_RESPONSE; - } + ret = _port_cmd_bus_suspend(port); break; } case HCD_PORT_CMD_RESUME: { - //Port can only be resumed if already suspended - if (port->state == HCD_PORT_STATE_SUSPENDED) { - ret = (_port_bus_resume(port)) ? ESP_OK : ESP_ERR_INVALID_RESPONSE; - } + ret = _port_cmd_bus_resume(port); break; } case HCD_PORT_CMD_DISABLE: { - //Can only disable the port when already enabled or suspended - if (port->state == HCD_PORT_STATE_ENABLED || port->state == HCD_PORT_STATE_SUSPENDED) { - ret = (_port_disable(port)) ? ESP_OK : ESP_ERR_INVALID_RESPONSE; - } + ret = _port_cmd_disable(port); break; } } @@ -1570,22 +1459,8 @@ hcd_port_event_t hcd_port_handle_event(hcd_port_handle_t port_hdl) break; } case HCD_PORT_EVENT_DISCONNECTION: - if (_port_debounce(port)) { - //A device is still connected, so it was just a debounce - port->state = HCD_PORT_STATE_DISABLED; - ret = HCD_PORT_EVENT_NONE; - } else { - //No device connected after debounce delay. This is an actual disconnection - if (port->state != HCD_PORT_STATE_NOT_POWERED) { //Don't update state if disconnect was due to power-off - port->state = HCD_PORT_STATE_DISCONNECTED; - } - ret = HCD_PORT_EVENT_DISCONNECTION; - } - break; case HCD_PORT_EVENT_ERROR: - case HCD_PORT_EVENT_OVERCURRENT: - case HCD_PORT_EVENT_SUDDEN_DISCONN: { - _port_invalidate_all_pipes(port); + case HCD_PORT_EVENT_OVERCURRENT: { break; } default: { @@ -1637,28 +1512,37 @@ void *hcd_port_get_context(hcd_port_handle_t port_hdl) esp_err_t hcd_port_set_fifo_bias(hcd_port_handle_t port_hdl, hcd_port_fifo_bias_t bias) { esp_err_t ret; + //Get a pointer to the correct FIFO bias constant values + const usbh_hal_fifo_config_t *fifo_config; + const fifo_mps_limits_t *mps_limits; + switch (bias) { + case HCD_PORT_FIFO_BIAS_BALANCED: + fifo_config = &fifo_config_default; + mps_limits = &mps_limits_default; + break; + case HCD_PORT_FIFO_BIAS_RX: + fifo_config = &fifo_config_bias_rx; + mps_limits = &mps_limits_bias_rx; + break; + case HCD_PORT_FIFO_BIAS_PTX: + fifo_config = &fifo_config_bias_ptx; + mps_limits = &mps_limits_bias_ptx; + break; + default: + fifo_config = NULL; + mps_limits = NULL; + abort(); + break; + } + //Configure the new FIFO sizes and store the pointers port_t *port = (port_t *)port_hdl; xSemaphoreTake(port->port_mux, portMAX_DELAY); HCD_ENTER_CRITICAL(); //Check that port is in the correct state to update FIFO sizes if (port->initialized && !port->flags.event_pending && port->num_pipes_idle == 0 && port->num_pipes_queued == 0) { - const usbh_hal_fifo_config_t *fifo_config; - switch (bias) { - case HCD_PORT_FIFO_BIAS_BALANCED: - fifo_config = &fifo_config_default; - break; - case HCD_PORT_FIFO_BIAS_RX: - fifo_config = &fifo_config_bias_rx; - break; - case HCD_PORT_FIFO_BIAS_PTX: - fifo_config = &fifo_config_bias_ptx; - break; - default: - fifo_config = NULL; - abort(); - } usbh_hal_set_fifo_size(port->hal, fifo_config); - port->fifo_bias = bias; + port->fifo_config = fifo_config; + port->fifo_mps_limits = mps_limits; ret = ESP_OK; } else { ret = ESP_ERR_INVALID_STATE; @@ -1672,45 +1556,6 @@ esp_err_t hcd_port_set_fifo_bias(hcd_port_handle_t port_hdl, hcd_port_fifo_bias_ // ----------------------- Private ------------------------- -static bool _pipe_wait_done(pipe_t *pipe) -{ - //Check if the pipe has a currently executing buffer - if (pipe->multi_buffer_control.buffer_is_executing) { - //Wait for pipe to complete its transfer - pipe->cs_flags.waiting_xfer_done = 1; - _internal_pipe_event_wait(pipe); - if (pipe->state == HCD_PIPE_STATE_INVALID) { - //The pipe become invalid whilst waiting for its internal event - pipe->cs_flags.waiting_xfer_done = 0; //Need to manually reset this bit in this case - return false; - } - bool chan_halted = usbh_hal_chan_request_halt(pipe->chan_obj); - assert(chan_halted); - (void) chan_halted; - } - return true; -} - -static void _pipe_retire(pipe_t *pipe, bool self_initiated) -{ - //Cannot have a currently executing buffer - assert(!pipe->multi_buffer_control.buffer_is_executing); - if (pipe->num_urb_pending > 0) { - //Process all remaining pending URBs - urb_t *urb; - TAILQ_FOREACH(urb, &pipe->pending_urb_tailq, tailq_entry) { - //Update the URB's current state - urb->hcd_var = URB_HCD_STATE_DONE; - //If we are initiating the retire, mark the URB as canceled - urb->transfer.status = (self_initiated) ? USB_TRANSFER_STATUS_CANCELED : USB_TRANSFER_STATUS_NO_DEVICE; - } - //Concatenated pending tailq to the done tailq - TAILQ_CONCAT(&pipe->done_urb_tailq, &pipe->pending_urb_tailq, tailq_entry); - pipe->num_urb_done += pipe->num_urb_pending; - pipe->num_urb_pending = 0; - } -} - static inline hcd_pipe_event_t pipe_decode_error_event(usbh_hal_chan_error_t chan_error) { hcd_pipe_event_t event = HCD_PIPE_EVENT_NONE; @@ -1768,7 +1613,7 @@ static void buffer_block_free(dma_buffer_block_t *buffer) free(buffer); } -static bool pipe_alloc_check_args(const hcd_pipe_config_t *pipe_config, usb_speed_t port_speed, hcd_port_fifo_bias_t fifo_bias, usb_transfer_type_t type, bool is_default_pipe) +static bool pipe_alloc_check_args(const hcd_pipe_config_t *pipe_config, usb_speed_t port_speed, const fifo_mps_limits_t *mps_limits, usb_transfer_type_t type, bool is_default_pipe) { //Check if pipe can be supported if (port_speed == USB_SPEED_LOW && pipe_config->dev_speed == USB_SPEED_FULL) { @@ -1790,25 +1635,12 @@ static bool pipe_alloc_check_args(const hcd_pipe_config_t *pipe_config, usb_spee //Interval not supported for isochronous pipe (where 0 < 2^(bInterval - 1) <= 32) return false; } - if (is_default_pipe) { return true; } - //Check if MPS is within FIFO limits - const fifo_mps_limits_t *mps_limits; - switch (fifo_bias) { - case HCD_PORT_FIFO_BIAS_BALANCED: - mps_limits = &mps_limits_default; - break; - case HCD_PORT_FIFO_BIAS_RX: - mps_limits = &mps_limits_bias_rx; - break; - default: //HCD_PORT_FIFO_BIAS_PTX - mps_limits = &mps_limits_bias_ptx; - break; - } + int limit; - if (USB_DESC_EP_GET_EP_DIR(pipe_config->ep_desc)) { //IN + if (USB_EP_DESC_GET_EP_DIR(pipe_config->ep_desc)) { //IN limit = mps_limits->in_mps; } else { //OUT if (type == USB_TRANSFER_TYPE_CTRL || type == USB_TRANSFER_TYPE_BULK) { @@ -1880,6 +1712,102 @@ static void pipe_set_ep_char(const hcd_pipe_config_t *pipe_config, usb_transfer_ } } +// ---------------------- Commands ------------------------- + +static esp_err_t _pipe_cmd_halt(pipe_t *pipe) +{ + esp_err_t ret; + //Pipe must be in the active state in order to be halted + if (pipe->state != HCD_PIPE_STATE_ACTIVE) { + ret = ESP_ERR_INVALID_STATE; + goto exit; + } + //Request that the channel halts + if (!usbh_hal_chan_request_halt(pipe->chan_obj)) { + //We need to wait for channel to be halted. State will be updated in the ISR + pipe->cs_flags.waiting_halt = 1; + _internal_pipe_event_wait(pipe); + } else { + pipe->state = HCD_PIPE_STATE_HALTED; + } + ret = ESP_OK; +exit: + return ret; +} + +static esp_err_t _pipe_cmd_flush(pipe_t *pipe) +{ + esp_err_t ret; + //The pipe must be halted in order to be flushed + if (pipe->state != HCD_PIPE_STATE_HALTED) { + ret = ESP_ERR_INVALID_STATE; + goto exit; + } + //Cannot have a currently executing buffer + assert(!pipe->multi_buffer_control.buffer_is_executing); + bool call_pipe_cb; + //Flush any filled buffers + call_pipe_cb = _buffer_flush_all(pipe, true); + //Move all URBs from the pending tailq to the done tailq + if (pipe->num_urb_pending > 0) { + //Process all remaining pending URBs + urb_t *urb; + TAILQ_FOREACH(urb, &pipe->pending_urb_tailq, tailq_entry) { + //Update the URB's current state + urb->hcd_var = URB_HCD_STATE_DONE; + //We are canceling the URB. Update its actual_num_bytes and status + urb->transfer.actual_num_bytes = 0; + urb->transfer.status = USB_TRANSFER_STATUS_CANCELED; + if (pipe->ep_char.type == USB_PRIV_XFER_TYPE_ISOCHRONOUS) { + //Update the URB's isoc packet descriptors as well + for (int pkt_idx = 0; pkt_idx < urb->transfer.num_isoc_packets; pkt_idx++) { + urb->transfer.isoc_packet_desc[pkt_idx].actual_num_bytes = 0; + urb->transfer.isoc_packet_desc[pkt_idx].status = USB_TRANSFER_STATUS_CANCELED; + } + } + } + //Concatenated pending tailq to the done tailq + TAILQ_CONCAT(&pipe->done_urb_tailq, &pipe->pending_urb_tailq, tailq_entry); + pipe->num_urb_done += pipe->num_urb_pending; + pipe->num_urb_pending = 0; + call_pipe_cb = true; + } + if (call_pipe_cb) { + //One or more URBs can be dequeued as a result of the flush. We need to call the callback + HCD_EXIT_CRITICAL(); + pipe->callback((hcd_pipe_handle_t)pipe, HCD_PIPE_EVENT_URB_DONE, pipe->callback_arg, false); + HCD_ENTER_CRITICAL(); + } + ret = ESP_OK; +exit: + return ret; +} + +static esp_err_t _pipe_cmd_clear(pipe_t *pipe) +{ + esp_err_t ret; + //Pipe must be in the halted state in order to be made active, and there must be an enabled device on the port + if (pipe->state != HCD_PIPE_STATE_HALTED || !pipe->port->flags.conn_dev_ena) { + ret = ESP_ERR_INVALID_STATE; + goto exit; + } + //Update the pipe's state + pipe->state = HCD_PIPE_STATE_ACTIVE; + if (pipe->num_urb_pending > 0) { + //Fill as many buffers as possible + while (_buffer_can_fill(pipe)) { + _buffer_fill(pipe); + } + } + //Execute any filled buffers + if (_buffer_can_exec(pipe)) { + _buffer_exec(pipe); + } + ret = ESP_OK; +exit: + return ret; +} + // ----------------------- Public -------------------------- esp_err_t hcd_pipe_alloc(hcd_port_handle_t port_hdl, const hcd_pipe_config_t *pipe_config, hcd_pipe_handle_t *pipe_hdl) @@ -1890,7 +1818,7 @@ esp_err_t hcd_pipe_alloc(hcd_port_handle_t port_hdl, const hcd_pipe_config_t *pi //Can only allocate a pipe if the target port is initialized and connected to an enabled device HCD_CHECK_FROM_CRIT(port->initialized && port->flags.conn_dev_ena, ESP_ERR_INVALID_STATE); usb_speed_t port_speed = port->speed; - hcd_port_fifo_bias_t port_fifo_bias = port->fifo_bias; + const fifo_mps_limits_t *mps_limits = port->fifo_mps_limits; int pipe_idx = port->num_pipes_idle + port->num_pipes_queued; HCD_EXIT_CRITICAL(); @@ -1900,11 +1828,11 @@ esp_err_t hcd_pipe_alloc(hcd_port_handle_t port_hdl, const hcd_pipe_config_t *pi type = USB_TRANSFER_TYPE_CTRL; is_default = true; } else { - type = USB_DESC_EP_GET_XFERTYPE(pipe_config->ep_desc); + type = USB_EP_DESC_GET_XFERTYPE(pipe_config->ep_desc); is_default = false; } //Check if pipe configuration can be supported - if (!pipe_alloc_check_args(pipe_config, port_speed, port_fifo_bias, type, is_default)) { + if (!pipe_alloc_check_args(pipe_config, port_speed, mps_limits, type, is_default)) { return ESP_ERR_NOT_SUPPORTED; } @@ -1979,10 +1907,7 @@ esp_err_t hcd_pipe_free(hcd_pipe_handle_t pipe_hdl) HCD_ENTER_CRITICAL(); //Check that all URBs have been removed and pipe has no pending events HCD_CHECK_FROM_CRIT(!pipe->multi_buffer_control.buffer_is_executing - && pipe->multi_buffer_control.buffer_num_to_parse == 0 - && pipe->multi_buffer_control.buffer_num_to_exec == 0 - && pipe->num_urb_pending == 0 - && pipe->num_urb_done == 0 + && !pipe->cs_flags.has_urb && !pipe->cs_flags.reset_lock, ESP_ERR_INVALID_STATE); //Remove pipe from the list of idle pipes (it must be in the idle list because it should have no queued URBs) @@ -2005,11 +1930,9 @@ esp_err_t hcd_pipe_update_mps(hcd_pipe_handle_t pipe_hdl, int mps) pipe_t *pipe = (pipe_t *)pipe_hdl; HCD_ENTER_CRITICAL(); //Check if pipe is in the correct state to be updated - HCD_CHECK_FROM_CRIT(pipe->state != HCD_PIPE_STATE_INVALID - && !pipe->cs_flags.pipe_cmd_processing - && pipe->num_urb_pending == 0 - && pipe->num_urb_done == 0 - && !pipe->cs_flags.reset_lock, + HCD_CHECK_FROM_CRIT(!pipe->cs_flags.pipe_cmd_processing && + !pipe->cs_flags.has_urb && + !pipe->cs_flags.reset_lock, ESP_ERR_INVALID_STATE); pipe->ep_char.mps = mps; //Update the underlying channel's registers @@ -2023,11 +1946,9 @@ esp_err_t hcd_pipe_update_dev_addr(hcd_pipe_handle_t pipe_hdl, uint8_t dev_addr) pipe_t *pipe = (pipe_t *)pipe_hdl; HCD_ENTER_CRITICAL(); //Check if pipe is in the correct state to be updated - HCD_CHECK_FROM_CRIT(pipe->state != HCD_PIPE_STATE_INVALID - && !pipe->cs_flags.pipe_cmd_processing - && pipe->num_urb_pending == 0 - && pipe->num_urb_done == 0 - && !pipe->cs_flags.reset_lock, + HCD_CHECK_FROM_CRIT(!pipe->cs_flags.pipe_cmd_processing && + !pipe->cs_flags.has_urb && + !pipe->cs_flags.reset_lock, ESP_ERR_INVALID_STATE); pipe->ep_char.dev_addr = dev_addr; //Update the underlying channel's registers @@ -2036,16 +1957,29 @@ esp_err_t hcd_pipe_update_dev_addr(hcd_pipe_handle_t pipe_hdl, uint8_t dev_addr) return ESP_OK; } -esp_err_t hcd_pipe_persist_reset(hcd_pipe_handle_t pipe_hdl) +esp_err_t hcd_pipe_update_callback(hcd_pipe_handle_t pipe_hdl, hcd_pipe_callback_t callback, void *user_arg) { pipe_t *pipe = (pipe_t *)pipe_hdl; HCD_ENTER_CRITICAL(); //Check if pipe is in the correct state to be updated - HCD_CHECK_FROM_CRIT(pipe->state != HCD_PIPE_STATE_INVALID - && !pipe->cs_flags.pipe_cmd_processing - && pipe->num_urb_pending == 0 - && pipe->num_urb_done == 0 - && !pipe->cs_flags.reset_lock, + HCD_CHECK_FROM_CRIT(!pipe->cs_flags.pipe_cmd_processing && + !pipe->cs_flags.has_urb && + !pipe->cs_flags.reset_lock, + ESP_ERR_INVALID_STATE); + pipe->callback = callback; + pipe->callback_arg = user_arg; + HCD_EXIT_CRITICAL(); + return ESP_OK; +} + +esp_err_t hcd_pipe_set_persist_reset(hcd_pipe_handle_t pipe_hdl) +{ + pipe_t *pipe = (pipe_t *)pipe_hdl; + HCD_ENTER_CRITICAL(); + //Check if pipe is in the correct state to be updated + HCD_CHECK_FROM_CRIT(!pipe->cs_flags.pipe_cmd_processing && + !pipe->cs_flags.has_urb && + !pipe->cs_flags.reset_lock, ESP_ERR_INVALID_STATE); pipe->cs_flags.persist = 1; HCD_EXIT_CRITICAL(); @@ -2067,14 +2001,7 @@ hcd_pipe_state_t hcd_pipe_get_state(hcd_pipe_handle_t pipe_hdl) hcd_pipe_state_t ret; pipe_t *pipe = (pipe_t *)pipe_hdl; HCD_ENTER_CRITICAL(); - //If there is no enabled device, all existing pipes are invalid. - if (pipe->port->state != HCD_PORT_STATE_ENABLED - && pipe->port->state != HCD_PORT_STATE_SUSPENDED - && pipe->port->state != HCD_PORT_STATE_RESUMING) { - ret = HCD_PIPE_STATE_INVALID; - } else { - ret = pipe->state; - } + ret = pipe->state; HCD_EXIT_CRITICAL(); return ret; } @@ -2084,60 +2011,31 @@ esp_err_t hcd_pipe_command(hcd_pipe_handle_t pipe_hdl, hcd_pipe_cmd_t command) pipe_t *pipe = (pipe_t *)pipe_hdl; esp_err_t ret = ESP_OK; + xSemaphoreTake(pipe->port->port_mux, portMAX_DELAY); HCD_ENTER_CRITICAL(); //Cannot execute pipe commands the pipe is already executing a command, or if the pipe or its port are no longer valid - if (pipe->cs_flags.pipe_cmd_processing || pipe->cs_flags.reset_lock || !pipe->port->flags.conn_dev_ena || pipe->state == HCD_PIPE_STATE_INVALID) { + if (pipe->cs_flags.reset_lock) { ret = ESP_ERR_INVALID_STATE; } else { pipe->cs_flags.pipe_cmd_processing = 1; switch (command) { - case HCD_PIPE_CMD_ABORT: { - //Retire all scheduled URBs. Pipe's state remains unchanged - if (!_pipe_wait_done(pipe)) { //Stop any on going transfers - ret = ESP_ERR_INVALID_RESPONSE; - } - _buffer_flush_all(pipe, true); //Some buffers might still be filled. Flush them - _pipe_retire(pipe, true); //Retire any pending transfers - break; - } - case HCD_PIPE_CMD_RESET: { - //Retire all scheduled URBs. Pipe's state moves to active - if (!_pipe_wait_done(pipe)) { //Stop any on going transfers - ret = ESP_ERR_INVALID_RESPONSE; - break; - } - _buffer_flush_all(pipe, true); //Some buffers might still be filled. Flush them - _pipe_retire(pipe, true); //Retire any pending transfers - pipe->state = HCD_PIPE_STATE_ACTIVE; - break; - } - case HCD_PIPE_CMD_CLEAR: { //Can only do this if port is still active - //Pipe's state moves from halted to active - if (pipe->state == HCD_PIPE_STATE_HALTED) { - pipe->state = HCD_PIPE_STATE_ACTIVE; - //Start the next pending transfer if it exists - if (_buffer_can_fill(pipe)) { - _buffer_fill(pipe); - } - if (_buffer_can_exec(pipe)) { - _buffer_exec(pipe); - } - } - break; - } case HCD_PIPE_CMD_HALT: { - //Pipe's state moves to halted - if (!_pipe_wait_done(pipe)) { //Stop any on going transfers - ret = ESP_ERR_INVALID_RESPONSE; - break; - } - pipe->state = HCD_PIPE_STATE_HALTED; + ret = _pipe_cmd_halt(pipe); + break; + } + case HCD_PIPE_CMD_FLUSH: { + ret = _pipe_cmd_flush(pipe); + break; + } + case HCD_PIPE_CMD_CLEAR: { + ret = _pipe_cmd_clear(pipe); break; } } pipe->cs_flags.pipe_cmd_processing = 0; } HCD_EXIT_CRITICAL(); + xSemaphoreGive(pipe->port->port_mux); return ret; } @@ -2157,11 +2055,11 @@ hcd_pipe_event_t hcd_pipe_get_event(hcd_pipe_handle_t pipe_hdl) static inline void _buffer_fill_ctrl(dma_buffer_block_t *buffer, usb_transfer_t *transfer) { //Get information about the control transfer by analyzing the setup packet (the first 8 bytes of the URB's data) - usb_ctrl_req_t *ctrl_req = (usb_ctrl_req_t *)transfer->data_buffer; - bool data_stg_in = (ctrl_req->bRequestType & USB_B_REQUEST_TYPE_DIR_IN); - bool data_stg_skip = (transfer->num_bytes == 0); + usb_setup_packet_t *setup_pkt = (usb_setup_packet_t *)transfer->data_buffer; + bool data_stg_in = (setup_pkt->bmRequestType & USB_BM_REQUEST_TYPE_DIR_IN); + bool data_stg_skip = (setup_pkt->wLength == 0); //Fill setup stage - usbh_hal_xfer_desc_fill(buffer->xfer_desc_list, 0, transfer->data_buffer, sizeof(usb_ctrl_req_t), + usbh_hal_xfer_desc_fill(buffer->xfer_desc_list, 0, transfer->data_buffer, sizeof(usb_setup_packet_t), USBH_HAL_XFER_DESC_FLAG_SETUP | USBH_HAL_XFER_DESC_FLAG_HOC); //Fill data stage if (data_stg_skip) { @@ -2169,7 +2067,7 @@ static inline void _buffer_fill_ctrl(dma_buffer_block_t *buffer, usb_transfer_t usbh_hal_xfer_desc_clear(buffer->xfer_desc_list, 1); } else { //Fill data stage - usbh_hal_xfer_desc_fill(buffer->xfer_desc_list, 1, transfer->data_buffer + sizeof(usb_ctrl_req_t), transfer->num_bytes, + usbh_hal_xfer_desc_fill(buffer->xfer_desc_list, 1, transfer->data_buffer + sizeof(usb_setup_packet_t), setup_pkt->wLength, ((data_stg_in) ? USBH_HAL_XFER_DESC_FLAG_IN : 0) | USBH_HAL_XFER_DESC_FLAG_HOC); } //Fill status stage (i.e., a zero length packet). If data stage is skipped, the status stage is always IN. @@ -2370,15 +2268,14 @@ static void _buffer_exec(pipe_t *pipe) usbh_hal_chan_activate(pipe->chan_obj, buffer_to_exec->xfer_desc_list, desc_list_len, start_idx); } -static bool _buffer_check_done(pipe_t *pipe) +static void _buffer_exec_cont(pipe_t *pipe) { - if (pipe->ep_char.type != USB_PRIV_XFER_TYPE_CTRL) { - return true; - } - //Only control transfers need to be continued + //This should only ever be called on control transfers + assert(pipe->ep_char.type == USB_PRIV_XFER_TYPE_CTRL); dma_buffer_block_t *buffer_inflight = pipe->buffers[pipe->multi_buffer_control.rd_idx]; bool next_dir_is_in; int next_pid; + assert(buffer_inflight->flags.ctrl.cur_stg != 2); if (buffer_inflight->flags.ctrl.cur_stg == 0) { //Just finished control stage if (buffer_inflight->flags.ctrl.data_stg_skip) { //Skipping data stage. Go straight to status stage @@ -2391,18 +2288,15 @@ static bool _buffer_check_done(pipe_t *pipe) next_pid = 1; //Data stage always starts with a PID of DATA1 buffer_inflight->flags.ctrl.cur_stg = 1; } - } else if (buffer_inflight->flags.ctrl.cur_stg == 1) { //Just finished data stage. Go to status stage + } else { //cur_stg == 1. //Just finished data stage. Go to status stage next_dir_is_in = !buffer_inflight->flags.ctrl.data_stg_in; //Status stage is always the opposite direction of data stage next_pid = 1; //Status stage always has a PID of DATA1 buffer_inflight->flags.ctrl.cur_stg = 2; - } else { //Just finished status stage. Transfer is complete - return true; } //Continue the control transfer usbh_hal_chan_set_dir(pipe->chan_obj, next_dir_is_in); usbh_hal_chan_set_pid(pipe->chan_obj, next_pid); usbh_hal_chan_activate(pipe->chan_obj, buffer_inflight->xfer_desc_list, XFER_LIST_LEN_CTRL, buffer_inflight->flags.ctrl.cur_stg); - return false; } static inline void _buffer_parse_ctrl(dma_buffer_block_t *buffer) @@ -2410,15 +2304,15 @@ static inline void _buffer_parse_ctrl(dma_buffer_block_t *buffer) usb_transfer_t *transfer = &buffer->urb->transfer; //Update URB's actual number of bytes if (buffer->flags.ctrl.data_stg_skip) { - //There was no data stage. Just set the actual length to zero - transfer->actual_num_bytes = 0; + //There was no data stage. Just set the actual length to the size of the setup packet + transfer->actual_num_bytes = sizeof(usb_setup_packet_t); } else { //Parse the data stage for the remaining length int rem_len; int desc_status; usbh_hal_xfer_desc_parse(buffer->xfer_desc_list, 1, &rem_len, &desc_status); assert(desc_status == USBH_HAL_XFER_DESC_STS_SUCCESS); - assert(rem_len <= transfer->num_bytes); + assert(rem_len <= (transfer->num_bytes - sizeof(usb_setup_packet_t))); transfer->actual_num_bytes = transfer->num_bytes - rem_len; } //Update URB status @@ -2497,6 +2391,7 @@ static inline void _buffer_parse_isoc(dma_buffer_block_t *buffer, bool is_in) { usb_transfer_t *transfer = &buffer->urb->transfer; int desc_idx = buffer->flags.isoc.start_idx; //Descriptor index tracks which descriptor in the QTD list + int total_actual_num_bytes = 0; for (int pkt_idx = 0; pkt_idx < transfer->num_isoc_packets; pkt_idx++) { //Clear the filled descriptor int rem_len; @@ -2508,6 +2403,7 @@ static inline void _buffer_parse_isoc(dma_buffer_block_t *buffer, bool is_in) assert(rem_len <= transfer->isoc_packet_desc[pkt_idx].num_bytes); //Check for DMA errata //Update ISO packet actual length and status transfer->isoc_packet_desc[pkt_idx].actual_num_bytes = transfer->isoc_packet_desc[pkt_idx].num_bytes - rem_len; + total_actual_num_bytes += transfer->isoc_packet_desc[pkt_idx].actual_num_bytes; transfer->isoc_packet_desc[pkt_idx].status = (desc_status == USBH_HAL_XFER_DESC_STS_NOT_EXECUTED) ? USB_TRANSFER_STATUS_SKIPPED : USB_TRANSFER_STATUS_COMPLETED; //A descriptor is also allocated for unscheduled frames. We need to skip over them desc_idx += buffer->flags.isoc.interval; @@ -2515,43 +2411,39 @@ static inline void _buffer_parse_isoc(dma_buffer_block_t *buffer, bool is_in) desc_idx -= XFER_LIST_LEN_INTR; } } + //Write back the actual_num_bytes and statue of entire transfer + assert(total_actual_num_bytes <= transfer->num_bytes); + transfer->actual_num_bytes = total_actual_num_bytes; + transfer->status = USB_TRANSFER_STATUS_COMPLETED; } static inline void _buffer_parse_error(dma_buffer_block_t *buffer) { - //The URB had an error, so we consider that NO bytes were transferred + //The URB had an error, so we consider that NO bytes were transferred. Set actual_num_bytes to zero usb_transfer_t *transfer = &buffer->urb->transfer; transfer->actual_num_bytes = 0; for (int i = 0; i < transfer->num_isoc_packets; i++) { transfer->isoc_packet_desc[i].actual_num_bytes = 0; } - //Update status of URB - if (buffer->status_flags.cancelled) { - transfer->status = USB_TRANSFER_STATUS_CANCELED; - } else if (buffer->status_flags.pipe_state == HCD_PIPE_STATE_INVALID) { - transfer->status = USB_TRANSFER_STATUS_NO_DEVICE; - } else { - switch (buffer->status_flags.pipe_event) { - case HCD_PIPE_EVENT_ERROR_XFER: //Excessive transaction error - transfer->status = USB_TRANSFER_STATUS_ERROR; - break; - case HCD_PIPE_EVENT_ERROR_OVERFLOW: - transfer->status = USB_TRANSFER_STATUS_OVERFLOW; - break; - case HCD_PIPE_EVENT_ERROR_STALL: - transfer->status = USB_TRANSFER_STATUS_STALL; - break; - case HCD_PIPE_EVENT_URB_DONE: //Special case where we are cancelling an URB due to pipe_retire - transfer->status = USB_TRANSFER_STATUS_CANCELED; - break; - default: - //HCD_PIPE_EVENT_ERROR_URB_NOT_AVAIL should never occur - abort(); - break; - } + //Update status of URB. Status will depend on the pipe_event + switch (buffer->status_flags.pipe_event) { + case HCD_PIPE_EVENT_NONE: + transfer->status = USB_TRANSFER_STATUS_CANCELED; + break; + case HCD_PIPE_EVENT_ERROR_XFER: + transfer->status = USB_TRANSFER_STATUS_ERROR; + break; + case HCD_PIPE_EVENT_ERROR_OVERFLOW: + transfer->status = USB_TRANSFER_STATUS_OVERFLOW; + break; + case HCD_PIPE_EVENT_ERROR_STALL: + transfer->status = USB_TRANSFER_STATUS_STALL; + break; + default: + //HCD_PIPE_EVENT_URB_DONE and HCD_PIPE_EVENT_ERROR_URB_NOT_AVAIL should not occur here + abort(); + break; } - //Clear error flags - buffer->status_flags.val = 0; } static void _buffer_parse(pipe_t *pipe) @@ -2563,9 +2455,8 @@ static void _buffer_parse(pipe_t *pipe) int mps = pipe->ep_char.mps; //Parsing the buffer will update the buffer's corresponding URB - if (buffer_to_parse->status_flags.error_occurred) { - _buffer_parse_error(buffer_to_parse); - } else { + if (buffer_to_parse->status_flags.pipe_event == HCD_PIPE_EVENT_URB_DONE) { + //URB was successful switch (pipe->ep_char.type) { case USB_PRIV_XFER_TYPE_CTRL: { _buffer_parse_ctrl(buffer_to_parse); @@ -2588,6 +2479,9 @@ static void _buffer_parse(pipe_t *pipe) break; } } + } else { + //URB failed + _buffer_parse_error(buffer_to_parse); } urb_t *urb = buffer_to_parse->urb; urb->hcd_var = URB_HCD_STATE_DONE; @@ -2602,18 +2496,19 @@ static void _buffer_parse(pipe_t *pipe) pipe->multi_buffer_control.buffer_num_to_fill++; } -static void _buffer_flush_all(pipe_t *pipe, bool cancelled) +static bool _buffer_flush_all(pipe_t *pipe, bool cancelled) { - int cur_num_to_mark_done = pipe->multi_buffer_control.buffer_num_to_exec; + int cur_num_to_mark_done = pipe->multi_buffer_control.buffer_num_to_exec; for (int i = 0; i < cur_num_to_mark_done; i++) { //Mark any filled buffers as done - _buffer_done_error(pipe, 0, pipe->state, pipe->last_event, cancelled); + _buffer_done(pipe, 0, HCD_PIPE_EVENT_NONE); } int cur_num_to_parse = pipe->multi_buffer_control.buffer_num_to_parse; for (int i = 0; i < cur_num_to_parse; i++) { _buffer_parse(pipe); } //At this point, there should be no more filled buffers. Only URBs in the pending or done tailq + return (cur_num_to_parse > 0); } // ---------------------------------------------- HCD Transfer Descriptors --------------------------------------------- @@ -2646,13 +2541,13 @@ esp_err_t hcd_urb_enqueue(hcd_pipe_handle_t pipe_hdl, urb_t *urb) if (_buffer_can_exec(pipe)) { _buffer_exec(pipe); } - if (!pipe->cs_flags.is_active) { + if (!pipe->cs_flags.has_urb) { //This is the first URB to be enqueued into the pipe. Move the pipe to the list of active pipes TAILQ_REMOVE(&pipe->port->pipes_idle_tailq, pipe, tailq_entry); TAILQ_INSERT_TAIL(&pipe->port->pipes_active_tailq, pipe, tailq_entry); pipe->port->num_pipes_idle--; pipe->port->num_pipes_queued++; - pipe->cs_flags.is_active = 1; + pipe->cs_flags.has_urb = 1; } HCD_EXIT_CRITICAL(); return ESP_OK; @@ -2672,7 +2567,7 @@ urb_t *hcd_urb_dequeue(hcd_pipe_handle_t pipe_hdl) assert(urb->hcd_ptr == (void *)pipe && urb->hcd_var == URB_HCD_STATE_DONE); //The URB's reserved field should have been set to this pipe urb->hcd_ptr = NULL; urb->hcd_var = URB_HCD_STATE_IDLE; - if (pipe->cs_flags.is_active + if (pipe->cs_flags.has_urb && pipe->num_urb_pending == 0 && pipe->num_urb_done == 0 && pipe->multi_buffer_control.buffer_num_to_exec == 0 && pipe->multi_buffer_control.buffer_num_to_parse == 0) { //This pipe has no more enqueued URBs. Move the pipe to the list of idle pipes @@ -2680,7 +2575,7 @@ urb_t *hcd_urb_dequeue(hcd_pipe_handle_t pipe_hdl) TAILQ_INSERT_TAIL(&pipe->port->pipes_idle_tailq, pipe, tailq_entry); pipe->port->num_pipes_idle++; pipe->port->num_pipes_queued--; - pipe->cs_flags.is_active = 0; + pipe->cs_flags.has_urb = 0; } } else { //No more URBs to dequeue from this pipe diff --git a/components/usb/hub.c b/components/usb/hub.c new file mode 100644 index 0000000000..f970c41b3f --- /dev/null +++ b/components/usb/hub.c @@ -0,0 +1,668 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "sdkconfig.h" +#include +#include "freertos/FreeRTOS.h" +#include "freertos/portmacro.h" +#include "esp_err.h" +#include "esp_heap_caps.h" +#include "esp_log.h" +#include "usb_private.h" +#include "hcd.h" +#include "hub.h" + +/* +Implementation of the HUB driver that only supports the root hub with a single port. Therefore, we currently don't +implement the bare minimum to control the root HCD port. +*/ + +#define HUB_ROOT_PORT_NUM 1 //HCD only supports one port +#ifdef CONFIG_USB_HOST_HW_BUFFER_BIAS_IN +#define HUB_ROOT_HCD_PORT_FIFO_BIAS HCD_PORT_FIFO_BIAS_RX +#elif CONFIG_USB_HOST_HW_BUFFER_BIAS_PERIODIC_OUT +#define HUB_ROOT_HCD_PORT_FIFO_BIAS HCD_PORT_FIFO_BIAS_PTX +#else //CONFIG_USB_HOST_HW_BUFFER_BIAS_BALANCED +#define HUB_ROOT_HCD_PORT_FIFO_BIAS HCD_PORT_FIFO_BIAS_BALANCED +#endif + +#define ENUM_CTRL_TRANSFER_MAX_LEN CONFIG_USB_HOST_CONTROL_TRANSFER_MAX_SIZE +#define ENUM_DEV_ADDR 1 //Device address used in enumeration +#define ENUM_CONFIG_INDEX 0 //Index of the first configuration of the device +#define ENUM_DEV_DESC_REQ_SIZE 64 //Worst case size for device descriptor request +#define ENUM_LOW_SPEED_MPS 8 //Worst case MPS for the default endpoint of a low-speed device +#define ENUM_FULL_SPEED_MPS 64 //Worst case MPS for the default endpoint of a full-speed device + +#define HUB_DRIVER_FLAG_ACTION_ROOT_EVENT 0x01 +#define HUB_DRIVER_FLAG_ACTION_ENUM_EVENT 0x02 +#define HUB_DRIVER_FLAG_ACTION_PORT_RECOVER 0x04 + +typedef enum { + HUB_DRIVER_STATE_INSTALLED, + HUB_DRIVER_STATE_ROOT_POWERD, + HUB_DRIVER_STATE_ROOT_ENUMERATING, + HUB_DRIVER_STATE_ROOT_ACTIVE, + HUB_DRIVER_STATE_ROOT_RECOVERY, +} hub_driver_state_t; + +typedef enum { + ENUM_STAGE_NONE, /**< There is no device awaiting enumeration */ + ENUM_STAGE_START, /**< Start of enumeration. Allocates device object */ + ENUM_STAGE_GET_SHORT_DEV_DESC, /**< Getting short device descriptor */ + ENUM_STAGE_GET_SHORT_DEV_DESC_CHECK, /**< Check that short device descriptor was obtained */ + ENUM_STAGE_SECOND_RESET, /**< Doing second reset */ + ENUM_STAGE_SET_ADDR, /**< Setting address */ + ENUM_STAGE_SET_ADDR_CHECK, /**< Check that address was set successful */ + ENUM_STAGE_GET_FULL_DEV_DESC, /**< Getting full device descriptor */ + ENUM_STAGE_GET_FULL_DEV_DESC_CHECK, /**< Check that full device descriptor was obtained */ + ENUM_STAGE_GET_CONFIG_DESC, /**< Getting full configuration descriptor */ + ENUM_STAGE_GET_CONFIG_DESC_CHECK, /**< Check that full configuration descriptor was obtained */ + ENUM_STAGE_SET_CONFIG, /**< Set configuration number */ + ENUM_STAGE_SET_CONFIG_CHECK, /**< Check that configuration number was set */ + ENUM_STAGE_CLEANUP, /**< Clean up successful enumeration. Adds enumerated device to USBH */ + ENUM_STAGE_CLEANUP_FAILED, /**< Cleanup failed enumeration. Free device resources */ +} enum_stage_t; + +typedef struct { + //Dynamic members require a critical section + struct { + union { + struct { + uint32_t actions: 8; + uint32_t reserved24: 24; + }; + uint32_t val; + } flags; + hub_driver_state_t driver_state; + usb_device_handle_t root_dev_hdl; //Indicates if an enumerated device is connected to the root port + } dynamic; + //Single thread members don't require a critical section so long as they are never accessed from multiple threads + struct { + enum_stage_t enum_stage; + urb_t *enum_urb; + usb_device_handle_t enum_dev_hdl; //Handle of the device being enumerated. Moves to root_dev_hdl on enumeration completion + hcd_pipe_handle_t enum_dflt_pipe_hdl; + } single_thread; + //Constant members do no change after installation thus do not require a critical section + struct { + hcd_port_handle_t root_port_hdl; + usb_notif_cb_t notif_cb; + void *notif_cb_arg; + } constant; +} 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 HUB_DRIVER_CHECK(cond, ret_val) ({ \ + if (!(cond)) { \ + return (ret_val); \ + } \ +}) +#define HUB_DRIVER_CHECK_FROM_CRIT(cond, ret_val) ({ \ + if (!(cond)) { \ + HUB_DRIVER_EXIT_CRITICAL(); \ + return ret_val; \ + } \ +}) + +// ------------------------------------------------- Event Handling ---------------------------------------------------- + +// ---------------------- Callbacks ------------------------ + +static bool root_port_callback(hcd_port_handle_t port_hdl, hcd_port_event_t port_event, void *user_arg, bool in_isr) +{ + HUB_DRIVER_ENTER_CRITICAL_SAFE(); + p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_ROOT_EVENT; + HUB_DRIVER_EXIT_CRITICAL_SAFE(); + bool yield; + if (in_isr) { + p_hub_driver_obj->constant.notif_cb(USB_NOTIF_SOURCE_HUB, in_isr, p_hub_driver_obj->constant.notif_cb_arg); + } else { + yield = false; + } + return yield; +} + +static bool enum_dflt_pipe_callback(hcd_pipe_handle_t pipe_hdl, hcd_pipe_event_t pipe_event, void *user_arg, bool in_isr) +{ + //Note: This callback may have triggered when a failed enumeration is already cleaned up (e.g., due to a failed port reset) + HUB_DRIVER_ENTER_CRITICAL_SAFE(); + p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_ENUM_EVENT; + HUB_DRIVER_EXIT_CRITICAL_SAFE(); + return p_hub_driver_obj->constant.notif_cb(USB_NOTIF_SOURCE_HUB, in_isr, p_hub_driver_obj->constant.notif_cb_arg); +} + +static void usbh_hub_callback(hcd_port_handle_t port_hdl, usbh_hub_event_t hub_event, void *arg) +{ + //We currently only support the root port + assert(port_hdl == p_hub_driver_obj->constant.root_port_hdl); + HUB_DRIVER_ENTER_CRITICAL(); + //Any hub_event results in whatever device connected to the root port to no longer be valid. We clear root_dev_hdl here. + usb_device_handle_t dev_hdl = p_hub_driver_obj->dynamic.root_dev_hdl; + p_hub_driver_obj->dynamic.root_dev_hdl = NULL; + assert(dev_hdl); + bool call_port_disable = false; + switch (hub_event) { + case USBH_HUB_EVENT_CLEANUP_PORT: + //After USBH has cleaned up gone device. The port can be recovered. + p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_PORT_RECOVER; + break; + case USBH_HUB_EVENT_DISABLE_PORT: + p_hub_driver_obj->dynamic.driver_state = HUB_DRIVER_STATE_ROOT_POWERD; + call_port_disable = true; + break; + default: + abort(); //Should never occur + break; + } + HUB_DRIVER_EXIT_CRITICAL(); + if (call_port_disable) { + ESP_LOGD(HUB_DRIVER_TAG, "Disabling root port"); + hcd_port_command(port_hdl, HCD_PORT_CMD_DISABLE); + ESP_ERROR_CHECK(usbh_hub_dev_port_disabled(dev_hdl)); + } +} + +// ---------------------- Handlers ------------------------- + +static void root_port_handle_events(hcd_port_handle_t root_port_hdl) +{ + hcd_port_event_t port_event = hcd_port_handle_event(root_port_hdl); + switch (port_event) { + case HCD_PORT_EVENT_NONE: + //Nothing to do + break; + case HCD_PORT_EVENT_CONNECTION: { + if (hcd_port_command(root_port_hdl, HCD_PORT_CMD_RESET) == ESP_OK) { + ESP_LOGD(HUB_DRIVER_TAG, "Root port reset"); + //Start enumeration + HUB_DRIVER_ENTER_CRITICAL(); + p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_ENUM_EVENT; + p_hub_driver_obj->dynamic.driver_state = HUB_DRIVER_STATE_ROOT_ENUMERATING; + HUB_DRIVER_EXIT_CRITICAL(); + p_hub_driver_obj->single_thread.enum_stage = ENUM_STAGE_START; + } else { + ESP_LOGE(HUB_DRIVER_TAG, "Root port reset failed"); + } + break; + } + case HCD_PORT_EVENT_DISCONNECTION: + case HCD_PORT_EVENT_ERROR: + case HCD_PORT_EVENT_OVERCURRENT: { + usb_device_handle_t dev_hdl = NULL; + HUB_DRIVER_ENTER_CRITICAL(); + switch (p_hub_driver_obj->dynamic.driver_state) { + case HUB_DRIVER_STATE_ROOT_POWERD: + //This occurred before enumeration. Therefore, there's no device and we can go straight to port recovery + p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_ENUM_EVENT; + break; + case HUB_DRIVER_STATE_ROOT_ENUMERATING: + //This occurred during enumeration. Therefore, we need to recover the failed enumeration + p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_ENUM_EVENT; + p_hub_driver_obj->single_thread.enum_stage = ENUM_STAGE_CLEANUP_FAILED; + break; + case HUB_DRIVER_STATE_ROOT_ACTIVE: + //There was an enumerated device. We need to indicate to USBH that the device is gone + dev_hdl = p_hub_driver_obj->dynamic.root_dev_hdl; + break; + default: + abort(); //Should never occur + break; + } + p_hub_driver_obj->dynamic.driver_state = HUB_DRIVER_STATE_ROOT_RECOVERY; + HUB_DRIVER_EXIT_CRITICAL(); + if (dev_hdl) { + ESP_ERROR_CHECK(usbh_hub_mark_dev_gone(dev_hdl)); + } + break; + } + default: + abort(); //Should never occur + break; + } +} + +// ------------------------------------------------- Enum Functions ---------------------------------------------------- + +static enum_stage_t enum_stage_start(void) +{ + usb_speed_t speed; + if (hcd_port_get_speed(p_hub_driver_obj->constant.root_port_hdl, &speed) != ESP_OK) { + return ENUM_STAGE_NONE; + } + usb_device_handle_t enum_dev_hdl; + hcd_pipe_handle_t enum_dflt_pipe_hdl; + //We use NULL as the parent device to indicate the root hub port 1. We currently only support a single device + if (usbh_hub_add_dev(p_hub_driver_obj->constant.root_port_hdl, speed, &enum_dev_hdl, &enum_dflt_pipe_hdl) != ESP_OK) { + return ENUM_STAGE_NONE; + } + //Set our own default pipe callback + ESP_ERROR_CHECK(hcd_pipe_update_callback(enum_dflt_pipe_hdl, enum_dflt_pipe_callback, NULL)); + HUB_DRIVER_ENTER_CRITICAL(); + p_hub_driver_obj->single_thread.enum_dev_hdl = enum_dev_hdl; + p_hub_driver_obj->single_thread.enum_dflt_pipe_hdl = enum_dflt_pipe_hdl; + HUB_DRIVER_EXIT_CRITICAL(); + ESP_LOGD(HUB_DRIVER_TAG, "Enumeration starting"); + return ENUM_STAGE_GET_SHORT_DEV_DESC; +} + +static enum_stage_t enum_stage_get_short_dev_desc(hcd_pipe_handle_t pipe_hdl, urb_t *enum_urb) +{ + USB_SETUP_PACKET_INIT_GET_DEVICE_DESC((usb_setup_packet_t *)enum_urb->transfer.data_buffer); + enum_urb->transfer.num_bytes = sizeof(usb_setup_packet_t) + ENUM_DEV_DESC_REQ_SIZE; + if (hcd_urb_enqueue(pipe_hdl, enum_urb) != ESP_OK) { + ESP_LOGE(HUB_DRIVER_TAG, "Failed to get short device descriptor"); + return ENUM_STAGE_CLEANUP_FAILED; + } + ESP_LOGD(HUB_DRIVER_TAG, "Getting short device descriptor"); + return ENUM_STAGE_GET_SHORT_DEV_DESC_CHECK; +} + +static enum_stage_t enum_stage_check_short_dev_desc(hcd_pipe_handle_t pipe_hdl, urb_t *enum_urb) +{ + //Dequeue the URB + urb_t *dequeued_enum_urb = hcd_urb_dequeue(pipe_hdl); + assert(dequeued_enum_urb == enum_urb); + if (enum_urb->transfer.status != USB_TRANSFER_STATUS_COMPLETED) { + ESP_LOGE(HUB_DRIVER_TAG, "Short device descriptor transfer failed"); + return ENUM_STAGE_CLEANUP_FAILED; + } + usb_device_desc_t *device_desc = (usb_device_desc_t *)(enum_urb->transfer.data_buffer + sizeof(usb_setup_packet_t)); + if (enum_urb->transfer.actual_num_bytes < sizeof(usb_setup_packet_t) + 8) { //Device must return at least 8 bytes in its data stage + ESP_LOGE(HUB_DRIVER_TAG, "Short device descriptor too short"); + return ENUM_STAGE_CLEANUP_FAILED; + } + //Update the MPS of the default pipe + if (hcd_pipe_update_mps(pipe_hdl, device_desc->bMaxPacketSize0) != ESP_OK) { + ESP_LOGE(HUB_DRIVER_TAG, "Failed to update default pipe MPS"); + return ENUM_STAGE_CLEANUP_FAILED; + } + ESP_LOGD(HUB_DRIVER_TAG, "Short device descriptor obtained"); + return ENUM_STAGE_SECOND_RESET; +} + +static enum_stage_t enum_stage_second_reset(hcd_pipe_handle_t pipe_hdl, urb_t *enum_urb) +{ + ESP_ERROR_CHECK(hcd_pipe_set_persist_reset(pipe_hdl)); //Persist the default pipe through the reset + if (hcd_port_command(p_hub_driver_obj->constant.root_port_hdl, HCD_PORT_CMD_RESET) != ESP_OK) { + ESP_LOGE(HUB_DRIVER_TAG, "Failed to issue second reset"); + return ENUM_STAGE_CLEANUP_FAILED; + } + ESP_LOGD(HUB_DRIVER_TAG, "Second reset done"); + return ENUM_STAGE_SET_ADDR; +} + +static enum_stage_t enum_stage_set_addr(hcd_pipe_handle_t pipe_hdl, urb_t *enum_urb) +{ + USB_SETUP_PACKET_INIT_SET_ADDR((usb_setup_packet_t *)enum_urb->transfer.data_buffer, ENUM_DEV_ADDR); + enum_urb->transfer.num_bytes = sizeof(usb_setup_packet_t); //No data stage + if (hcd_urb_enqueue(pipe_hdl, enum_urb) != ESP_OK) { + ESP_LOGE(HUB_DRIVER_TAG, "Failed to set address"); + return ENUM_STAGE_CLEANUP_FAILED; + } + ESP_LOGD(HUB_DRIVER_TAG, "Setting address %d", ENUM_DEV_ADDR); + return ENUM_STAGE_SET_ADDR_CHECK; +} + +static enum_stage_t enum_stage_check_set_addr(hcd_pipe_handle_t pipe_hdl, urb_t *enum_urb, usb_device_handle_t dev_hdl) +{ + //Dequeue the URB + urb_t *dequeued_enum_urb = hcd_urb_dequeue(pipe_hdl); + assert(dequeued_enum_urb == enum_urb); + if (enum_urb->transfer.status != USB_TRANSFER_STATUS_COMPLETED) { + ESP_LOGE(HUB_DRIVER_TAG, "Set address transfer failed"); + return ENUM_STAGE_CLEANUP_FAILED; + } + //Update the pipe and device's address, and fill the address into the device object + ESP_ERROR_CHECK(hcd_pipe_update_dev_addr(pipe_hdl, ENUM_DEV_ADDR)); + ESP_ERROR_CHECK(usbh_hub_enum_fill_dev_addr(dev_hdl, ENUM_DEV_ADDR)); + ESP_LOGD(HUB_DRIVER_TAG, "Address set successfully"); + return ENUM_STAGE_GET_FULL_DEV_DESC; +} + +static enum_stage_t enum_stage_get_full_dev_desc(hcd_pipe_handle_t pipe_hdl, urb_t *enum_urb) +{ + USB_SETUP_PACKET_INIT_GET_DEVICE_DESC((usb_setup_packet_t *)enum_urb->transfer.data_buffer); + enum_urb->transfer.num_bytes = sizeof(usb_setup_packet_t) + ENUM_DEV_DESC_REQ_SIZE; + if (hcd_urb_enqueue(pipe_hdl, enum_urb) != ESP_OK) { + ESP_LOGE(HUB_DRIVER_TAG, "Failed to get full device descriptor"); + return ENUM_STAGE_CLEANUP_FAILED; + } + ESP_LOGD(HUB_DRIVER_TAG, "Getting full device descriptor"); + return ENUM_STAGE_GET_FULL_DEV_DESC_CHECK; +} + +static enum_stage_t enum_stage_check_full_dev_desc(hcd_pipe_handle_t pipe_hdl, urb_t *enum_urb, usb_device_handle_t dev_hdl) +{ + //Dequeue the URB + urb_t *dequeued_enum_urb = hcd_urb_dequeue(pipe_hdl); + assert(dequeued_enum_urb == enum_urb); + if (enum_urb->transfer.status != USB_TRANSFER_STATUS_COMPLETED) { + ESP_LOGE(HUB_DRIVER_TAG, "Full device descriptor transfer failed"); + return ENUM_STAGE_CLEANUP_FAILED; + } + if (enum_urb->transfer.actual_num_bytes < sizeof(usb_setup_packet_t) + sizeof(usb_device_desc_t)) { + ESP_LOGE(HUB_DRIVER_TAG, "Full device descriptor too short"); + return ENUM_STAGE_CLEANUP_FAILED; + } + //Fill device descriptor into device + const usb_device_desc_t *device_desc = (const usb_device_desc_t *)(enum_urb->transfer.data_buffer + sizeof(usb_setup_packet_t)); + ESP_ERROR_CHECK(usbh_hub_enum_fill_dev_desc(dev_hdl, device_desc)); + ESP_LOGD(HUB_DRIVER_TAG, "Full device descriptor obtained"); + return ENUM_STAGE_GET_CONFIG_DESC; +} + +static enum_stage_t enum_stage_get_config_desc(hcd_pipe_handle_t pipe_hdl, urb_t *enum_urb) +{ + //Get the configuration descriptor at index 0 + USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)enum_urb->transfer.data_buffer, ENUM_CONFIG_INDEX, ENUM_CTRL_TRANSFER_MAX_LEN); + enum_urb->transfer.num_bytes = sizeof(usb_setup_packet_t) + ENUM_CTRL_TRANSFER_MAX_LEN; + if (hcd_urb_enqueue(pipe_hdl, enum_urb) != ESP_OK) { + ESP_LOGE(HUB_DRIVER_TAG, "Failed to get configuration descriptor"); + return ENUM_STAGE_CLEANUP_FAILED; + } + ESP_LOGD(HUB_DRIVER_TAG, "Getting configuration descriptor"); + return ENUM_STAGE_GET_CONFIG_DESC_CHECK; +} + +static enum_stage_t enum_stage_check_config_desc(hcd_pipe_handle_t pipe_hdl, urb_t *enum_urb, usb_device_handle_t dev_hdl) +{ + //Dequeue the URB + urb_t *dequeued_enum_urb = hcd_urb_dequeue(pipe_hdl); + assert(dequeued_enum_urb == enum_urb); + if (enum_urb->transfer.status != USB_TRANSFER_STATUS_COMPLETED) { + ESP_LOGE(HUB_DRIVER_TAG, "Configuration descriptor transfer failed"); + return ENUM_STAGE_CLEANUP_FAILED; + } + usb_config_desc_t *config_desc = (usb_config_desc_t *)(enum_urb->transfer.data_buffer + sizeof(usb_setup_packet_t)); + if (enum_urb->transfer.actual_num_bytes < sizeof(usb_setup_packet_t) + sizeof(usb_config_desc_t)) { + ESP_LOGE(HUB_DRIVER_TAG, "Configuration descriptor too small"); + return ENUM_STAGE_CLEANUP_FAILED; + } + if (config_desc->wTotalLength > ENUM_CTRL_TRANSFER_MAX_LEN) { + ESP_LOGE(HUB_DRIVER_TAG, "Configuration descriptor larger than control transfer max length"); + return ENUM_STAGE_CLEANUP_FAILED; + } + //Fill configuration descriptor into device + ESP_ERROR_CHECK(usbh_hub_enum_fill_config_desc(dev_hdl, config_desc)); + return ENUM_STAGE_SET_CONFIG; +} + +static enum_stage_t enum_stage_set_config(hcd_pipe_handle_t pipe_hdl, urb_t *enum_urb) +{ + USB_SETUP_PACKET_INIT_SET_CONFIG((usb_setup_packet_t *)enum_urb->transfer.data_buffer, ENUM_CONFIG_INDEX + 1); + enum_urb->transfer.num_bytes = sizeof(usb_setup_packet_t); //No data stage + if (hcd_urb_enqueue(pipe_hdl, enum_urb) != ESP_OK) { + ESP_LOGE(HUB_DRIVER_TAG, "Failed to set configuration"); + return ENUM_STAGE_CLEANUP_FAILED; + } + ESP_LOGD(HUB_DRIVER_TAG, "Setting configuration"); + return ENUM_STAGE_SET_CONFIG_CHECK; +} + +static enum_stage_t enum_stage_check_config(hcd_pipe_handle_t pipe_hdl, urb_t *enum_urb) +{ + //Dequeue the URB + urb_t *dequeued_enum_urb = hcd_urb_dequeue(pipe_hdl); + assert(dequeued_enum_urb == enum_urb); + if (enum_urb->transfer.status != USB_TRANSFER_STATUS_COMPLETED) { + ESP_LOGE(HUB_DRIVER_TAG, "Set configuration transfer failed"); + return ENUM_STAGE_CLEANUP_FAILED; + } + ESP_LOGD(HUB_DRIVER_TAG, "Configuration set successfully"); + return ENUM_STAGE_CLEANUP; +} + +static enum_stage_t enum_stage_cleanup(void) +{ + //We currently only support a single device connected to the root port. Move the device handle from enum to root + HUB_DRIVER_ENTER_CRITICAL(); + p_hub_driver_obj->dynamic.root_dev_hdl = p_hub_driver_obj->single_thread.enum_dev_hdl; + p_hub_driver_obj->dynamic.driver_state = HUB_DRIVER_STATE_ROOT_ACTIVE; + HUB_DRIVER_EXIT_CRITICAL(); + usb_device_handle_t dev_hdl = p_hub_driver_obj->single_thread.enum_dev_hdl; + p_hub_driver_obj->single_thread.enum_dev_hdl = NULL; + p_hub_driver_obj->single_thread.enum_dflt_pipe_hdl = NULL; + //Update device object after enumeration is done + ESP_ERROR_CHECK(usbh_hub_enum_done(dev_hdl)); + return ENUM_STAGE_NONE; +} + +static enum_stage_t enum_stage_cleanup_failed(void) +{ + //Enumeration failed. Clear the enum device handle and pipe + usb_device_handle_t dev_hdl = p_hub_driver_obj->single_thread.enum_dev_hdl; + if (p_hub_driver_obj->single_thread.enum_dev_hdl) { + //Halt, flush, and dequeue enum default pipe + ESP_ERROR_CHECK(hcd_pipe_command(p_hub_driver_obj->single_thread.enum_dflt_pipe_hdl, HCD_PIPE_CMD_HALT)); + ESP_ERROR_CHECK(hcd_pipe_command(p_hub_driver_obj->single_thread.enum_dflt_pipe_hdl, HCD_PIPE_CMD_FLUSH)); + urb_t *dequeued_enum_urb = hcd_urb_dequeue(p_hub_driver_obj->single_thread.enum_dflt_pipe_hdl); + assert(dequeued_enum_urb == p_hub_driver_obj->single_thread.enum_urb); + ESP_ERROR_CHECK(usbh_hub_enum_failed(dev_hdl)); //Free the underlying device object first before recovering the port + } + p_hub_driver_obj->single_thread.enum_dev_hdl = NULL; + p_hub_driver_obj->single_thread.enum_dflt_pipe_hdl = NULL; + HUB_DRIVER_ENTER_CRITICAL(); + //Enum could have failed due to a port error. If so, we need to trigger a port recovery + if (p_hub_driver_obj->dynamic.driver_state == HUB_DRIVER_STATE_ROOT_RECOVERY) { + p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_PORT_RECOVER; + } + HUB_DRIVER_EXIT_CRITICAL(); + return ENUM_STAGE_NONE; +} + +static void enum_handle_events(void) +{ + enum_stage_t cur_stage = p_hub_driver_obj->single_thread.enum_stage; + hcd_pipe_handle_t enum_dflt_pipe_hdl = p_hub_driver_obj->single_thread.enum_dflt_pipe_hdl; + urb_t *enum_urb = p_hub_driver_obj->single_thread.enum_urb; + usb_device_handle_t dev_hdl = p_hub_driver_obj->single_thread.enum_dev_hdl; + enum_stage_t next_stage; + switch (cur_stage) { + case ENUM_STAGE_START: + next_stage = enum_stage_start(); + break; + case ENUM_STAGE_GET_SHORT_DEV_DESC: + next_stage = enum_stage_get_short_dev_desc(enum_dflt_pipe_hdl, enum_urb); + break; + case ENUM_STAGE_GET_SHORT_DEV_DESC_CHECK: + next_stage = enum_stage_check_short_dev_desc(enum_dflt_pipe_hdl, enum_urb); + break; + case ENUM_STAGE_SECOND_RESET: + next_stage = enum_stage_second_reset(enum_dflt_pipe_hdl, enum_urb); + break; + case ENUM_STAGE_SET_ADDR: + next_stage = enum_stage_set_addr(enum_dflt_pipe_hdl, enum_urb); + break; + case ENUM_STAGE_SET_ADDR_CHECK: + next_stage = enum_stage_check_set_addr(enum_dflt_pipe_hdl, enum_urb, dev_hdl); + break; + case ENUM_STAGE_GET_FULL_DEV_DESC: + next_stage = enum_stage_get_full_dev_desc(enum_dflt_pipe_hdl, enum_urb); + break; + case ENUM_STAGE_GET_FULL_DEV_DESC_CHECK: + next_stage = enum_stage_check_full_dev_desc(enum_dflt_pipe_hdl, enum_urb, dev_hdl); + break; + case ENUM_STAGE_GET_CONFIG_DESC: + next_stage = enum_stage_get_config_desc(enum_dflt_pipe_hdl, enum_urb); + break; + case ENUM_STAGE_GET_CONFIG_DESC_CHECK: + next_stage = enum_stage_check_config_desc(enum_dflt_pipe_hdl, enum_urb, dev_hdl); + break; + case ENUM_STAGE_SET_CONFIG: + next_stage = enum_stage_set_config(enum_dflt_pipe_hdl, enum_urb); + break; + case ENUM_STAGE_SET_CONFIG_CHECK: + next_stage = enum_stage_check_config(enum_dflt_pipe_hdl, enum_urb); + break; + case ENUM_STAGE_CLEANUP: + next_stage = enum_stage_cleanup(); + break; + case ENUM_STAGE_CLEANUP_FAILED: + next_stage = enum_stage_cleanup_failed(); + break; + default: + //Note: Don't abort here. The enum_dflt_pipe_callback() can trigger a HUB_DRIVER_FLAG_ACTION_ENUM_EVENT after a cleanup + next_stage = ENUM_STAGE_NONE; + break; + } + p_hub_driver_obj->single_thread.enum_stage = next_stage; + HUB_DRIVER_ENTER_CRITICAL(); + if (next_stage == ENUM_STAGE_GET_SHORT_DEV_DESC || + next_stage == ENUM_STAGE_SECOND_RESET || + next_stage == ENUM_STAGE_SET_ADDR || + next_stage == ENUM_STAGE_GET_FULL_DEV_DESC || + next_stage == ENUM_STAGE_GET_CONFIG_DESC || + next_stage == ENUM_STAGE_SET_CONFIG || + next_stage == ENUM_STAGE_CLEANUP || + next_stage == ENUM_STAGE_CLEANUP_FAILED) { + p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_ENUM_EVENT; + } + HUB_DRIVER_EXIT_CRITICAL(); +} + +// ---------------------------------------------- Hub Driver Functions ------------------------------------------------- + +esp_err_t hub_install(hub_config_t *hub_config) +{ + HUB_DRIVER_ENTER_CRITICAL(); + HUB_DRIVER_CHECK_FROM_CRIT(p_hub_driver_obj == NULL, ESP_ERR_INVALID_STATE); + HUB_DRIVER_EXIT_CRITICAL(); + //Allocate Hub driver object + hub_driver_t *hub_driver_obj = heap_caps_calloc(1, sizeof(hub_driver_t), MALLOC_CAP_DEFAULT); + urb_t *enum_urb = urb_alloc(sizeof(usb_setup_packet_t) + ENUM_CTRL_TRANSFER_MAX_LEN, 0, 0); + if (hub_driver_obj == NULL || enum_urb == NULL) { + return ESP_ERR_NO_MEM; + } + esp_err_t ret; + //Install HCD port + hcd_port_config_t port_config = { + .fifo_bias = HUB_ROOT_HCD_PORT_FIFO_BIAS, + .callback = root_port_callback, + .callback_arg = NULL, + .context = NULL, + }; + hcd_port_handle_t port_hdl; + ret = hcd_port_init(HUB_ROOT_PORT_NUM, &port_config, &port_hdl); + if (ret != ESP_OK) { + goto err; + } + //Initialize hub driver object + hub_driver_obj->dynamic.driver_state = HUB_DRIVER_STATE_INSTALLED; + hub_driver_obj->single_thread.enum_stage = ENUM_STAGE_NONE; + hub_driver_obj->single_thread.enum_urb = enum_urb; + hub_driver_obj->constant.root_port_hdl = port_hdl; + hub_driver_obj->constant.notif_cb = hub_config->notif_cb; + hub_driver_obj->constant.notif_cb_arg = hub_config->notif_cb_arg; + HUB_DRIVER_ENTER_CRITICAL(); + if (p_hub_driver_obj != NULL) { + HUB_DRIVER_EXIT_CRITICAL(); + ret = ESP_ERR_INVALID_STATE; + goto assign_err; + } + p_hub_driver_obj = hub_driver_obj; + HUB_DRIVER_EXIT_CRITICAL(); + //Indicate to USBH that the hub is installed + ESP_ERROR_CHECK(usbh_hub_is_installed(usbh_hub_callback, NULL)); + ret = ESP_OK; + return ret; + +assign_err: + ESP_ERROR_CHECK(hcd_port_deinit(port_hdl)); +err: + urb_free(enum_urb); + heap_caps_free(hub_driver_obj); + return ret; +} + +esp_err_t hub_uninstall(void) +{ + HUB_DRIVER_ENTER_CRITICAL(); + HUB_DRIVER_CHECK_FROM_CRIT(p_hub_driver_obj != NULL, ESP_ERR_INVALID_STATE); + HUB_DRIVER_CHECK_FROM_CRIT(p_hub_driver_obj->dynamic.driver_state == HUB_DRIVER_STATE_INSTALLED, ESP_ERR_INVALID_STATE); + hub_driver_t *hub_driver_obj = p_hub_driver_obj; + p_hub_driver_obj = NULL; + HUB_DRIVER_EXIT_CRITICAL(); + + ESP_ERROR_CHECK(hcd_port_deinit(hub_driver_obj->constant.root_port_hdl)); + //Free Hub driver resources + urb_free(hub_driver_obj->single_thread.enum_urb); + heap_caps_free(hub_driver_obj); + return ESP_OK; +} + +esp_err_t hub_root_start(void) +{ + HUB_DRIVER_ENTER_CRITICAL(); + HUB_DRIVER_CHECK_FROM_CRIT(p_hub_driver_obj != NULL, ESP_ERR_INVALID_STATE); + HUB_DRIVER_CHECK_FROM_CRIT(p_hub_driver_obj->dynamic.driver_state == HUB_DRIVER_STATE_INSTALLED, ESP_ERR_INVALID_STATE); + HUB_DRIVER_EXIT_CRITICAL(); + //Power ON the root port + esp_err_t ret; + ret = hcd_port_command(p_hub_driver_obj->constant.root_port_hdl, HCD_PORT_CMD_POWER_ON); + if (ret == ESP_OK) { + HUB_DRIVER_ENTER_CRITICAL(); + p_hub_driver_obj->dynamic.driver_state = HUB_DRIVER_STATE_ROOT_POWERD; + HUB_DRIVER_EXIT_CRITICAL(); + } + return ret; +} + +esp_err_t hub_root_stop(void) +{ + HUB_DRIVER_ENTER_CRITICAL(); + HUB_DRIVER_CHECK_FROM_CRIT(p_hub_driver_obj != NULL, ESP_ERR_INVALID_STATE); + HUB_DRIVER_CHECK_FROM_CRIT(p_hub_driver_obj->dynamic.driver_state != HUB_DRIVER_STATE_INSTALLED, ESP_ERR_INVALID_STATE); + HUB_DRIVER_EXIT_CRITICAL(); + esp_err_t ret; + ret = hcd_port_command(p_hub_driver_obj->constant.root_port_hdl, HCD_PORT_CMD_POWER_OFF); + if (ret == ESP_OK) { + HUB_DRIVER_ENTER_CRITICAL(); + p_hub_driver_obj->dynamic.driver_state = HUB_DRIVER_STATE_INSTALLED; + HUB_DRIVER_EXIT_CRITICAL(); + } + return ret; +} + +esp_err_t hub_process(void) +{ + HUB_DRIVER_ENTER_CRITICAL(); + uint32_t action_flags = p_hub_driver_obj->dynamic.flags.actions; + p_hub_driver_obj->dynamic.flags.actions = 0; + HUB_DRIVER_EXIT_CRITICAL(); + + while (action_flags) { + if (action_flags & HUB_DRIVER_FLAG_ACTION_ROOT_EVENT) { + root_port_handle_events(p_hub_driver_obj->constant.root_port_hdl); + } + if (action_flags & HUB_DRIVER_FLAG_ACTION_ENUM_EVENT) { + enum_handle_events(); + } + if (action_flags & HUB_DRIVER_FLAG_ACTION_PORT_RECOVER) { + ESP_LOGD(HUB_DRIVER_TAG, "Recovering root port"); + ESP_ERROR_CHECK(hcd_port_recover(p_hub_driver_obj->constant.root_port_hdl)); + ESP_ERROR_CHECK(hcd_port_command(p_hub_driver_obj->constant.root_port_hdl, HCD_PORT_CMD_POWER_ON)); + HUB_DRIVER_ENTER_CRITICAL(); + p_hub_driver_obj->dynamic.driver_state = HUB_DRIVER_STATE_ROOT_POWERD; + HUB_DRIVER_EXIT_CRITICAL(); + } + HUB_DRIVER_ENTER_CRITICAL(); + action_flags = p_hub_driver_obj->dynamic.flags.actions; + p_hub_driver_obj->dynamic.flags.actions = 0; + HUB_DRIVER_EXIT_CRITICAL(); + } + return ESP_OK; +} diff --git a/components/usb/include/esp_private/usb_phy.h b/components/usb/include/esp_private/usb_phy.h new file mode 100644 index 0000000000..5e8f9c8df1 --- /dev/null +++ b/components/usb/include/esp_private/usb_phy.h @@ -0,0 +1,142 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include "soc/soc_caps.h" +#include "hal/usb_phy_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief USB PHY status + */ +typedef enum { + USB_PHY_STATUS_FREE, /**< PHY is not being used */ + USB_PHY_STATUS_IN_USE, /**< PHY is in use */ +} usb_phy_status_t; + +/** + * @brief USB PHY available actions + */ +typedef enum { + USB_PHY_ACTION_HOST_ALLOW_CONN, /**< Enable physical connection when operating as an OTG Host */ + USB_PHY_ACTION_HOST_FORCE_DISCONN, /**< Disable physical connection when operating as an OTG Host */ + USB_PHY_ACTION_MAX, +} usb_phy_action_t; + +/** + * @brief USB external PHY iopins configure struct + */ +typedef struct { + int vp_io_num; /**< GPIO pin to USB_EXTPHY_VP_IDX */ + int vm_io_num; /**< GPIO pin to USB_EXTPHY_VM_IDX */ + int rcv_io_num; /**< GPIO pin to USB_EXTPHY_RCV_IDX */ + int oen_io_num; /**< GPIO pin to USB_EXTPHY_OEN_IDX */ + int vpo_io_num; /**< GPIO pin to USB_EXTPHY_VPO_IDX */ + int vmo_io_num; /**< GPIO pin to USB_EXTPHY_VMO_IDX */ +} usb_phy_gpio_conf_t; + +/** + * @brief USB PHY configure struct + * + * At minimum the PHY controller and PHY target must be initialized. + */ +typedef struct { + usb_phy_controller_t controller; /**< USB PHY controller */ + usb_phy_target_t target; /**< USB PHY target INT/EXT */ + usb_otg_mode_t otg_mode; /**< USB OTG mode */ + usb_phy_speed_t otg_speed; /**< USB OTG speed */ + usb_phy_gpio_conf_t *gpio_conf; /**< USB external PHY iopins configure */ +} usb_phy_config_t; + +typedef struct phy_context_t *usb_phy_handle_t; /**< USB PHY context handle */ + +/** + * @brief Initialize a new USB PHY + * Configure at least PHY source. + * + * @param[in] config USB PHY configurtion struct + * @param[out] handle_ret USB PHY context handle + * + * @return + * - ESP_OK Success + * - ESP_FAIL USB PHY init error. + * - ESP_ERR_INVALID_STATE USB PHY not installed. + * - ESP_ERR_NO_MEM USB_OTG installation failed due to no mem. + */ +esp_err_t usb_new_phy(const usb_phy_config_t *config, usb_phy_handle_t *handle_ret); + +/** + * @brief Configure OTG mode for a USB PHY + * + * @param handle Pointer of USB PHY context handle + * @param mode USB OTG mode + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error. + * - ESP_FAIL OTG set mode fail. + */ +esp_err_t usb_phy_otg_set_mode(usb_phy_handle_t handle, usb_otg_mode_t mode); + +/** + * @brief Configure USB speed for a USB PHY that is operating as an OTG Device + * + * @param handle Pointer of USB PHY context handle + * @param mode USB speed + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error. + * - ESP_FAIL OTG set speed fail. + */ +esp_err_t usb_phy_otg_dev_set_speed(usb_phy_handle_t handle, usb_phy_speed_t speed); + +/** + * @brief Take a action for a USB PHY + * + * @param handle Pointer of USB PHY context handle + * @param action USB PHY action + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error. + * - ESP_FAIL Action cannot be performed. + */ +esp_err_t usb_phy_action(usb_phy_handle_t handle, usb_phy_action_t action); + +/** + * @brief Delete a USB PHY + * + * @param handle Pointer of USB PHY context handle + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error. + */ +esp_err_t usb_del_phy(usb_phy_handle_t handle); + +/** + * @brief Get status of a USB PHY + * + * @param[in] target The specific PHY target to check + * @param[out] status Status of the PHY + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error. + * - ESP_ERR_INVALID_STATE USB PHY not installed. + */ +esp_err_t usb_phy_get_phy_status(usb_phy_target_t target, usb_phy_status_t *status); + +#ifdef __cplusplus +} +#endif diff --git a/components/usb/include/usb/usb_helpers.h b/components/usb/include/usb/usb_helpers.h new file mode 100644 index 0000000000..d8405dd5fc --- /dev/null +++ b/components/usb/include/usb/usb_helpers.h @@ -0,0 +1,134 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* +Warning: The USB Host Library API is still a beta version and may be subject to change +*/ + +#pragma once + +#include +#include "usb/usb_types_ch9.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// ---------------------------------------- Configuration Descriptor Parsing ------------------------------------------- + +/** + * @brief Get the next descriptor + * + * Given a particular descriptor within a full configuration descriptor, get the next descriptor within the + * configuration descriptor. This is a convenience function that can be used to walk each individual descriptor within + * a full configuration descriptor. + * + * @param[in] cur_desc Current descriptor + * @param[in] wTotalLength Total length of the configuration descriptor + * @param[inout] offset Byte offset relative to the start of the configuration descriptor. On input, it is the offset of + * the current descriptor. On output, it is the offset of the returned descriptor. + * @return usb_standard_desc_t* Next descriptor, NULL if end of configuration descriptor reached + */ +const usb_standard_desc_t *usb_parse_next_descriptor(const usb_standard_desc_t *cur_desc, uint16_t wTotalLength, int *offset); + +/** + * @brief Get the next descriptor of a particular type + * + * Given a particular descriptor within a full configuration descriptor, get the next descriptor of a particular type + * (i.e., using the bDescriptorType value) within the configuration descriptor. + * + * @param[in] cur_desc Current descriptor + * @param[in] wTotalLength Total length of the configuration descriptor + * @param[in] bDescriptorType Type of the next descriptor to get + * @param[inout] offset Byte offset relative to the start of the configuration descriptor. On input, it is the offset of + * the current descriptor. On output, it is the offset of the returned descriptor. + * @return usb_standard_desc_t* Next descriptor, NULL if end descriptor is not found or configuration descriptor reached + */ +const usb_standard_desc_t *usb_parse_next_descriptor_of_type(const usb_standard_desc_t *cur_desc, uint16_t wTotalLength, uint8_t bDescriptorType, int *offset); + +/** + * @brief Get the number of alternate settings for a bInterfaceNumber + * + * Given a particular configuration descriptor, for a particular bInterfaceNumber, get the number of alternate settings + * available for that interface (i.e., the max possible value of bAlternateSetting for that bInterfaceNumber). + * + * @param[in] config_desc Pointer to the start of a full configuration descriptor + * @param[in] bInterfaceNumber Interface number + * @return int The number of alternate settings that the interface has, -1 if bInterfaceNumber not found + */ +int usb_parse_interface_number_of_alternate(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber); + +/** + * @brief Get a particular interface descriptor (using bInterfaceNumber and bAlternateSetting) + * + * Given a full configuration descriptor, get a particular interface descriptor. + * + * @note To get the number of alternate settings for a particular bInterfaceNumber, call + * usb_parse_interface_number_of_alternate() + * + * @param[in] config_desc Pointer to the start of a full configuration descriptor + * @param[in] bInterfaceNumber Interface number + * @param[in] bAlternateSetting Alternate setting number + * @param[out] offset Byte offset of the interface descriptor relative to the start of the configuration descriptor. Can be NULL. + * @return const usb_intf_desc_t* Pointer to interface descriptor, NULL if not found. + */ +const usb_intf_desc_t *usb_parse_interface_descriptor(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber, uint8_t bAlternateSetting, int *offset); + +/** + * @brief Get an endpoint descriptor within an interface descriptor + * + * Given an interface descriptor, get the Nth endpoint descriptor of the interface. The number of endpoints in an + * interface is indicated by the bNumEndpoints field of the interface descriptor. + * + * @note If bNumEndpoints is 0, it means the interface uses the default endpoint only + * + * @param[in] intf_desc Pointer to thee start of an interface descriptor + * @param[in] index Endpoint index + * @param[in] wTotalLength Total length of the containing configuration descriptor + * @param[inout] offset Byte offset relative to the start of the configuration descriptor. On input, it is the offset + * of the interface descriptor. On output, it is the offset of the endpoint descriptor. + * @return const usb_ep_desc_t* Pointer to endpoint descriptor, NULL if not found. + */ +const usb_ep_desc_t *usb_parse_endpoint_descriptor_by_index(const usb_intf_desc_t *intf_desc, int index, uint16_t wTotalLength, int *offset); + +/** + * @brief Get an endpoint descriptor based on an endpoint's address + * + * Given a configuration descriptor, get an endpoint descriptor based on it's bEndpointAddress, bAlternateSetting, and + * bInterfaceNumber. + * + * @param[in] config_desc Pointer to the start of a full configuration descriptor + * @param[in] bInterfaceNumber Interface number + * @param[in] bAlternateSetting Alternate setting number + * @param[in] bEndpointAddress Endpoint address + * @param[out] offset Byte offset of the endpoint descriptor relative to the start of the configuration descriptor. Can be NULL + * @return const usb_ep_desc_t* Pointer to endpoint descriptor, NULL if not found. + */ +const usb_ep_desc_t *usb_parse_endpoint_descriptor_by_address(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber, uint8_t bAlternateSetting, uint8_t bEndpointAddress, int *offset); + +// ------------------------------------------------------ Misc --------------------------------------------------------- + +/** + * @brief Round up to an integer multiple of endpoint's MPS + * + * This is a convenience function to round up a size/length to an endpoint's MPS (Maximum packet size). This is useful + * when calculating transfer or buffer lengths of IN endpoints. + * + * @param[in] num_bytes Number of bytes + * @param[in] mps MPS + * @return int Round up integer multiple of MPS + */ +static inline int usb_round_up_to_mps(int num_bytes, int mps) +{ + if (num_bytes < 0 || mps < 0) { + return 0; + } + return ((num_bytes + mps - 1) / mps) * mps; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/usb/include/usb/usb_host.h b/components/usb/include/usb/usb_host.h new file mode 100644 index 0000000000..6c104af6cf --- /dev/null +++ b/components/usb/include/usb/usb_host.h @@ -0,0 +1,412 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* +Warning: The USB Host Library API is still a beta version and may be subject to change +*/ + +#pragma once + +#include +#include "freertos/FreeRTOS.h" +#include "esp_err.h" +#include "esp_intr_alloc.h" +//Include the other USB Host Library headers as well +#include "usb/usb_helpers.h" +#include "usb/usb_types_ch9.h" +#include "usb/usb_types_stack.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// ------------------------------------------------- Macros and Types -------------------------------------------------- + +// ----------------------- Handles ------------------------- + +typedef void * usb_host_client_handle_t; /**< Handle to a client using the USB Host Library */ + +// ----------------------- Events -------------------------- + +#define USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS 0x01 /**< All clients have been deregistered from the USB Host Library */ +#define USB_HOST_LIB_EVENT_FLAGS_ALL_FREE 0x02 /**< The USB Host Library has freed all devices */ + +/** + * @brief The type event in a client event message + */ +typedef enum { + USB_HOST_CLIENT_EVENT_NEW_DEV, /**< A new device has been enumerated and added to the USB Host Library */ + USB_HOST_CLIENT_EVENT_DEV_GONE, /**< A device opened by the client is now gone */ +} usb_host_client_event_t; + +/** + * @brief Client event message + * + * Client event messages are sent to each client of the USB Host Library in order to notify them of various + * USB Host Library events such as: + * - Addition of new devices + * - Removal of existing devices + * + * @note The event message structure has a union with members corresponding to each particular event. Based on the event + * type, only the relevant member field should be accessed. + */ +typedef struct { + usb_host_client_event_t event; /**< Type of event */ + union { + struct { + uint8_t address; /**< New device's address */ + } new_dev; + struct { + usb_device_handle_t dev_hdl; /**< The handle of the device that was gone */ + } dev_gone; + }; +} usb_host_client_event_msg_t; + +// ---------------------- Callbacks ------------------------ + +/** + * @brief Client event callback + * + * - Each client of the USB Host Library must register an event callback to receive event messages from the USB Host + * Library. + * - The client event callback is run from the context of the clients usb_host_client_handle_events() function + */ +typedef void (*usb_host_client_event_cb_t)(const usb_host_client_event_msg_t *event_msg, void *arg); + +// -------------------- Configurations --------------------- + +/** + * @brief USB Host Library configuration + * + * Configuration structure of the USB Host Library. Provided in the usb_host_install() function + */ +typedef struct { + int intr_flags; /**< Interrupt flags for the underlying ISR used by the USB Host stack */ +} usb_host_config_t; + +/** + * @brief USB Host Library Client configuration + * + * Configuration structure for a USB Host Library client. Provided in usb_host_client_register() + */ +typedef struct { + usb_host_client_event_cb_t client_event_callback; /**< Client's event callback function */ + void *callback_arg; /**< Event callback function argument */ + int max_num_event_msg; /**< Maximum number of event messages that can be stored (e.g., 3) */ +} usb_host_client_config_t; + +// ------------------------------------------------ Library Functions -------------------------------------------------- + +/** + * @brief Install the USB Host Library + * + * - This function should only once to install the USB Host Library + * - This function should be called before any other USB Host Library functions are called + * + * @param[in] config USB Host Library configuration + * @return esp_err_t + */ +esp_err_t usb_host_install(const usb_host_config_t *config); + +/** + * @brief Uninstall the USB Host Library + * + * - This function should be called to uninstall the USB Host Library, thereby freeing its resources + * - All clients must have been deregistered before calling this function + * - All devices must have been freed by calling usb_host_device_free_all() and receiving the + * USB_HOST_LIB_EVENT_FLAGS_ALL_FREE event flag + * + * @return esp_err_t + */ +esp_err_t usb_host_uninstall(void); + +/** + * @brief Handle USB Host Library events + * + * - This function handles all of the USB Host Library's processing and should be called repeatedly in a loop + * - Check event_flags_ret to see if an flags are set indicating particular USB Host Library events + * + * @param[in] timeout_ticks Timeout in ticks to wait for an event to occur + * @param[out] event_flags_ret Event flags that indicate what USB Host Library event occurred + * @return esp_err_t + */ +esp_err_t usb_host_lib_handle_events(TickType_t timeout_ticks, uint32_t *event_flags_ret); + +// ------------------------------------------------ Client Functions --------------------------------------------------- + +/** + * @brief Register a client of the USB Host Library + * + * - This function registers a client of the USB Host Library + * - Once a client is registered, its processing function usb_host_client_handle_events() should be called repeatedly + * + * @param[in] client_config Client configuration + * @param[out] client_hdl_ret Client handle + * @return esp_err_t + */ +esp_err_t usb_host_client_register(const usb_host_client_config_t *client_config, usb_host_client_handle_t *client_hdl_ret); + +/** + * @brief Deregister a USB Host Library client + * + * - This function deregisters a client of the USB Host Library + * - The client must have closed all previously opened devices before attempting to deregister + * + * @param[in] client_hdl Client handle + * @return esp_err_t + */ +esp_err_t usb_host_client_deregister(usb_host_client_handle_t client_hdl); + +/** + * @brief USB Host Library client processing function + * + * - This function handles all of a client's processing and should be called repeatedly in a loop + * + * @param[in] client_hdl Client handle + * @param[in] timeout_ticks Timeout in ticks to wait for an event to occur + * @return esp_err_t + */ +esp_err_t usb_host_client_handle_events(usb_host_client_handle_t client_hdl, TickType_t timeout_ticks); + +/** + * @brief Unblock a client + * + * - This function simply unblocks a client if it is blocked on the usb_host_client_handle_events() function. + * - This function is useful when need to unblock a client in order to deregister it. + * + * @param[in] client_hdl Client handle + * @return esp_err_t + */ +esp_err_t usb_host_client_unblock(usb_host_client_handle_t client_hdl); + +// ------------------------------------------------- Device Handling --------------------------------------------------- + +/** + * @brief Open a device + * + * - This function allows a client to open a device + * - A client must open a device first before attempting to use it (e.g., sending transfers, device requests etc.) + * + * @param[in] client_hdl Client handle + * @param[in] dev_addr Device's address + * @param[out] dev_hdl_ret Device's handle + * @return esp_err_t + */ +esp_err_t usb_host_device_open(usb_host_client_handle_t client_hdl, uint8_t dev_addr, usb_device_handle_t *dev_hdl_ret); + +/** + * @brief Close a device + * + * - This function allows a client to close a device + * - A client must close a device after it has finished using the device (claimed interfaces must also be released) + * - A client must close all devices it has opened before deregistering + * + * @param[in] client_hdl Client handle + * @param[in] dev_hdl Device handle + * @return esp_err_t + */ +esp_err_t usb_host_device_close(usb_host_client_handle_t client_hdl, usb_device_handle_t dev_hdl); + +/** + * @brief Indicate that all devices can be freed when possible + * + * - This function marks all devices as waiting to be freed + * - If a device is not opened by any clients, it will be freed immediately + * - If a device is opened by at least one client, the device will be free when the last client closes that device. + * - Wait for the USB_HOST_LIB_EVENT_FLAGS_ALL_FREE flag to be set by usb_host_lib_handle_events() in order to know + * when all devices have been freed + * - This function is useful when cleaning up devices before uninstalling the USB Host Library + * + * @return esp_err_t + */ +esp_err_t usb_host_device_free_all(void); + +// ------------------------------------------------- Device Requests --------------------------------------------------- + +// ------------------- Cached Requests --------------------- + +/** + * @brief Get device's information + * + * - This function gets some basic information of a device + * - The device must be opened first before attempting to get its information + * + * @param[in] dev_hdl Device handle + * @param[out] dev_info Device information + * @return esp_err_t + */ +esp_err_t usb_host_device_info(usb_device_handle_t dev_hdl, usb_device_info_t *dev_info); + +// ----------------------------------------------- Descriptor Requests ------------------------------------------------- + +// ----------------- Cached Descriptors -------------------- + +/** + * @brief Get device's device descriptor + * + * - A client must call usb_host_device_open() first + * - No control transfer is sent. The device's descriptor is cached on enumeration + * - This function simple returns a pointer to the cached descriptor + * + * @note No control transfer is sent. The device's descriptor is cached on enumeration + * @param[in] dev_hdl Device handle + * @param[out] device_desc Device descriptor + * @return esp_err_t + */ +esp_err_t usb_host_get_device_descriptor(usb_device_handle_t dev_hdl, const usb_device_desc_t **device_desc); + +/** + * @brief Get device's active configuration descriptor + * + * - A client must call usb_host_device_open() first + * - No control transfer is sent. The device's active configuration descriptor is cached on enumeration + * - This function simple returns a pointer to the cached descriptor + * + * @note No control transfer is sent. A device's active configuration descriptor is cached on enumeration + * @param[in] dev_hdl Device handle + * @param[out] config_desc Configuration descriptor + * @return esp_err_t + */ +esp_err_t usb_host_get_active_config_descriptor(usb_device_handle_t dev_hdl, const usb_config_desc_t **config_desc); + +// ----------------------------------------------- Interface Functions ------------------------------------------------- + +/** + * @brief Function for a client to claim a device's interface + * + * - A client must claim a device's interface before attempting to communicate with any of its endpoints + * - Once an interface is claimed by a client, it cannot be claimed by any other client. + * + * @param[in] client_hdl Client handle + * @param[in] dev_hdl Device handle + * @param[in] bInterfaceNumber Interface number + * @param[in] bAlternateSetting Interface alternate setting number + * @return esp_err_t + */ +esp_err_t usb_host_interface_claim(usb_host_client_handle_t client_hdl, usb_device_handle_t dev_hdl, uint8_t bInterfaceNumber, uint8_t bAlternateSetting); + +/** + * @brief Function for a client to release a previously claimed interface + * + * - A client should release a device's interface after it no longer needs to communicate with the interface + * - A client must release all of its interfaces of a device it has claimed before being able to close the device + * + * @param[in] client_hdl Client handle + * @param[in] dev_hdl Device handle + * @param[in] bInterfaceNumber Interface number + * @return esp_err_t + */ +esp_err_t usb_host_interface_release(usb_host_client_handle_t client_hdl, usb_device_handle_t dev_hdl, uint8_t bInterfaceNumber); + +/** + * @brief Halt a particular endpoint + * + * - The device must have been opened by a client + * - The endpoint must be part of an interface claimed by a client + * - Once halted, the endpoint must be cleared using usb_host_endpoint_clear() before it can communicate again + * + * @param dev_hdl Device handle + * @param bEndpointAddress Endpoint address + * @return esp_err_t + */ +esp_err_t usb_host_endpoint_halt(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress); + +/** + * @brief Flush a particular endpoint + * + * - The device must have been opened by a client + * - The endpoint must be part of an interface claimed by a client + * - The endpoint must have been halted (either through a transfer error, or usb_host_endpoint_halt()) + * - Flushing an endpoint will caused an queued up transfers to be canceled + * + * @param dev_hdl Device handle + * @param bEndpointAddress Endpoint address + * @return esp_err_t + */ +esp_err_t usb_host_endpoint_flush(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress); + +/** + * @brief Clear a halt on a particular endpoint + * + * - The device must have been opened by a client + * - The endpoint must be part of an interface claimed by a client + * - The endpoint must have been halted (either through a transfer error, or usb_host_endpoint_halt()) + * - If the endpoint has any queued up transfers, clearing a halt will resume their execution + * + * @param dev_hdl Device handle + * @param bEndpointAddress Endpoint address + * @return esp_err_t + */ +esp_err_t usb_host_endpoint_clear(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress); + +// ------------------------------------------------ Asynchronous I/O --------------------------------------------------- + +/** + * @brief Allocate a transfer object + * + * - This function allocates a transfer object + * - Each transfer object has a fixed sized buffer specified on allocation + * - A transfer object can be re-used indefinitely + * - A transfer can be submitted using usb_host_transfer_submit() or usb_host_transfer_submit_control() + * + * @param[in] data_buffer_size Size of the transfer's data buffer + * @param[in] num_isoc_packets Number of isochronous packets in transfer (set to 0 for non-isochronous transfers) + * @param[out] transfer Transfer object + * @return esp_err_t + */ +esp_err_t usb_host_transfer_alloc(size_t data_buffer_size, int num_isoc_packets, usb_transfer_t **transfer); + +/** + * @brief Free a transfer object + * + * - Free a transfer object previously allocated using usb_host_transfer_alloc() + * - The transfer must not be in-flight when attempting to free it + * + * @param[in] transfer Transfer object + * @return esp_err_t + */ +esp_err_t usb_host_transfer_free(usb_transfer_t *transfer); + +/** + * @brief Submit a non-control transfer + * + * - Submit a transfer to a particular endpoint. The device and endpoint number is specified inside the transfer + * - The transfer must be properly initialized before submitting + * - On completion, the transfer's callback will be called from the client's usb_host_client_handle_events() function. + * + * @param[in] transfer Initialized transfer object + * @return esp_err_t + */ +esp_err_t usb_host_transfer_submit(usb_transfer_t *transfer); + +/** + * @brief Submit a control transfer + * + * - Submit a control transfer to a particular device. The client must have opened the device first + * - The transfer must be properly initialized before submitting. The first 8 bytes of the transfer's data buffer should + * contain the control transfer setup packet + * - On completion, the transfer's callback will be called from the client's usb_host_client_handle_events() function. + * + * @param[in] client_hdl Client handle + * @param[in] transfer Initialized transfer object + * @return esp_err_t + */ +esp_err_t usb_host_transfer_submit_control(usb_host_client_handle_t client_hdl, usb_transfer_t *transfer); + +/** + * @brief Cancel a submitted transfer + * + * - Cancel a previously submitted transfer + * - In its current implementation, any transfer that is already in-flight will not be canceled + * + * @param transfer Transfer object + * @return esp_err_t + */ +esp_err_t usb_host_transfer_cancel(usb_transfer_t *transfer); + +#ifdef __cplusplus +} +#endif diff --git a/components/usb/include/usb/usb_types_ch9.h b/components/usb/include/usb/usb_types_ch9.h new file mode 100644 index 0000000000..7d40bc46e0 --- /dev/null +++ b/components/usb/include/usb/usb_types_ch9.h @@ -0,0 +1,474 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* +Warning: The USB Host Library API is still a beta version and may be subject to change +*/ + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define USB_DESC_ATTR __attribute__((packed)) + +// ---------------------------------------------------- Chapter 9 ------------------------------------------------------ + +/** + * @brief USB2.0 device states + * + * See Table 9-1 of USB2.0 specification for more details + * + * @note The USB_DEVICE_STATE_NOT_ATTACHED is not part of the USB2.0 specification, but is a catch all state for devices + * that need to be cleaned up after a sudden disconnection or port error. + */ +typedef enum { + USB_DEVICE_STATE_NOT_ATTACHED, /**< The device was previously configured or suspended, but is no longer attached (either suddenly disconnected or a port error) */ + USB_DEVICE_STATE_ATTACHED, /**< Device is attached to the USB, but is not powered. */ + USB_DEVICE_STATE_POWERED, /**< Device is attached to the USB and powered, but has not been reset. */ + USB_DEVICE_STATE_DEFAULT, /**< Device is attached to the USB and powered and has been reset, but has not been assigned a unique address. Device responds at the default address. */ + USB_DEVICE_STATE_ADDRESS, /**< Device is attached to the USB, powered, has been reset, and a unique device address has been assigned. Device is not configured. */ + USB_DEVICE_STATE_CONFIGURED, /**< Device is attached to the USB, powered, has been reset, has a unique address, is configured, and is not suspended. The host may now use the function provided by the device. */ + USB_DEVICE_STATE_SUSPENDED, /**< Device is, at minimum, attached to the USB and is powered and has not seen bus activity for 3 ms. It may also have a unique address and be configured for use. However, because the device is suspended, the host may not use the device’s function. */ +} usb_device_state_t; + +/** + * @brief Descriptor types from USB2.0 specification table 9.5 + */ +#define USB_B_DESCRIPTOR_TYPE_DEVICE 0x01 +#define USB_B_DESCRIPTOR_TYPE_CONFIGURATION 0x02 +#define USB_B_DESCRIPTOR_TYPE_STRING 0x03 +#define USB_B_DESCRIPTOR_TYPE_INTERFACE 0x04 +#define USB_B_DESCRIPTOR_TYPE_ENDPOINT 0x05 +#define USB_B_DESCRIPTOR_TYPE_DEVICE_QUALIFIER 0x06 +#define USB_B_DESCRIPTOR_TYPE_OTHER_SPEED_CONFIGURATION 0x07 +#define USB_B_DESCRIPTOR_TYPE_INTERFACE_POWER 0x08 + +/** + * @brief Descriptor types from USB 2.0 ECN + */ +#define USB_B_DESCRIPTOR_TYPE_OTG 0x09 +#define USB_B_DESCRIPTOR_TYPE_DEBUG 0x0a +#define USB_B_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION 0x0b + +/** + * @brief Descriptor types from Wireless USB spec + */ +#define USB_B_DESCRIPTOR_TYPE_SECURITY 0x0c +#define USB_B_DESCRIPTOR_TYPE_KEY 0x0d +#define USB_B_DESCRIPTOR_TYPE_ENCRYPTION_TYPE 0x0e +#define USB_B_DESCRIPTOR_TYPE_BOS 0x0f +#define USB_B_DESCRIPTOR_TYPE_DEVICE_CAPABILITY 0x10 +#define USB_B_DESCRIPTOR_TYPE_WIRELESS_ENDPOINT_COMP 0x11 +#define USB_B_DESCRIPTOR_TYPE_WIRE_ADAPTER 0x21 +#define USB_B_DESCRIPTOR_TYPE_RPIPE 0x22 +#define USB_B_DESCRIPTOR_TYPE_CS_RADIO_CONTROL 0x23 + +/** + * @brief Descriptor types from UAS specification + */ +#define USB_B_DESCRIPTOR_TYPE_PIPE_USAGE 0x24 + +// -------------------- Setup Packet ----------------------- + +/** + * @brief Size of a USB control transfer setup packet in bytes + */ +#define USB_SETUP_PACKET_SIZE 8 + +/** + * @brief Structure representing a USB control transfer setup packet + * + * See Table 9-2 of USB2.0 specification for more details + */ +typedef union { + struct { + uint8_t bmRequestType; /**< Characteristics of request */ + uint8_t bRequest; /**< Specific request */ + uint16_t wValue; /**< Word-sized field that varies according to request */ + uint16_t wIndex; /**< Word-sized field that varies according to request; typically used to pass an index or offset */ + uint16_t wLength; /**< Number of bytes to transfer if there is a data stage */ + } __attribute__((packed)); + uint8_t val[USB_SETUP_PACKET_SIZE]; +} usb_setup_packet_t; +_Static_assert(sizeof(usb_setup_packet_t) == USB_SETUP_PACKET_SIZE, "Size of usb_setup_packet_t incorrect"); + +/** + * @brief Bit masks belonging to the bmRequestType field of a setup packet + */ +#define USB_BM_REQUEST_TYPE_DIR_OUT (0X00 << 7) +#define USB_BM_REQUEST_TYPE_DIR_IN (0x01 << 7) +#define USB_BM_REQUEST_TYPE_TYPE_STANDARD (0x00 << 5) +#define USB_BM_REQUEST_TYPE_TYPE_CLASS (0x01 << 5) +#define USB_BM_REQUEST_TYPE_TYPE_VENDOR (0x02 << 5) +#define USB_BM_REQUEST_TYPE_TYPE_RESERVED (0x03 << 5) +#define USB_BM_REQUEST_TYPE_TYPE_MASK (0x03 << 5) +#define USB_BM_REQUEST_TYPE_RECIP_DEVICE (0x00 << 0) +#define USB_BM_REQUEST_TYPE_RECIP_INTERFACE (0x01 << 0) +#define USB_BM_REQUEST_TYPE_RECIP_ENDPOINT (0x02 << 0) +#define USB_BM_REQUEST_TYPE_RECIP_OTHER (0x03 << 0) +#define USB_BM_REQUEST_TYPE_RECIP_MASK (0x1f << 0) + +/** + * @brief Bit masks belonging to the bRequest field of a setup packet + */ +#define USB_B_REQUEST_GET_STATUS 0x00 +#define USB_B_REQUEST_CLEAR_FEATURE 0x01 +#define USB_B_REQUEST_SET_FEATURE 0x03 +#define USB_B_REQUEST_SET_ADDRESS 0x05 +#define USB_B_REQUEST_GET_DESCRIPTOR 0x06 +#define USB_B_REQUEST_SET_DESCRIPTOR 0x07 +#define USB_B_REQUEST_GET_CONFIGURATION 0x08 +#define USB_B_REQUEST_SET_CONFIGURATION 0x09 +#define USB_B_REQUEST_GET_INTERFACE 0x0A +#define USB_B_REQUEST_SET_INTERFACE 0x0B +#define USB_B_REQUEST_SYNCH_FRAME 0x0C + +/** + * @brief Bit masks belonging to the wValue field of a setup packet + */ +#define USB_W_VALUE_DT_DEVICE 0x01 +#define USB_W_VALUE_DT_CONFIG 0x02 +#define USB_W_VALUE_DT_STRING 0x03 +#define USB_W_VALUE_DT_INTERFACE 0x04 +#define USB_W_VALUE_DT_ENDPOINT 0x05 +#define USB_W_VALUE_DT_DEVICE_QUALIFIER 0x06 +#define USB_W_VALUE_DT_OTHER_SPEED_CONFIG 0x07 +#define USB_W_VALUE_DT_INTERFACE_POWER 0x08 + +/** + * @brief Initializer for a SET_ADDRESS request + * + * Sets the address of a connected device + */ +#define USB_SETUP_PACKET_INIT_SET_ADDR(setup_pkt_ptr, addr) ({ \ + (setup_pkt_ptr)->bmRequestType = USB_BM_REQUEST_TYPE_DIR_OUT | USB_BM_REQUEST_TYPE_TYPE_STANDARD |USB_BM_REQUEST_TYPE_RECIP_DEVICE; \ + (setup_pkt_ptr)->bRequest = USB_B_REQUEST_SET_ADDRESS; \ + (setup_pkt_ptr)->wValue = (addr); \ + (setup_pkt_ptr)->wIndex = 0; \ + (setup_pkt_ptr)->wLength = 0; \ +}) + +/** + * @brief Initializer for a request to get a device's device descriptor + */ +#define USB_SETUP_PACKET_INIT_GET_DEVICE_DESC(setup_pkt_ptr) ({ \ + (setup_pkt_ptr)->bmRequestType = USB_BM_REQUEST_TYPE_DIR_IN | USB_BM_REQUEST_TYPE_TYPE_STANDARD | USB_BM_REQUEST_TYPE_RECIP_DEVICE; \ + (setup_pkt_ptr)->bRequest = USB_B_REQUEST_GET_DESCRIPTOR; \ + (setup_pkt_ptr)->wValue = (USB_W_VALUE_DT_DEVICE << 8); \ + (setup_pkt_ptr)->wIndex = 0; \ + (setup_pkt_ptr)->wLength = 18; \ +}) + +/** + * @brief Initializer for a request to get a device's current configuration number + */ +#define USB_SETUP_PACKET_INIT_GET_CONFIG(setup_pkt_ptr) ({ \ + (setup_pkt_ptr)->bmRequestType = USB_BM_REQUEST_TYPE_DIR_IN | USB_BM_REQUEST_TYPE_TYPE_STANDARD | USB_BM_REQUEST_TYPE_RECIP_DEVICE; \ + (setup_pkt_ptr)->bRequest = USB_B_REQUEST_GET_CONFIGURATION; \ + (setup_pkt_ptr)->wValue = 0; \ + (setup_pkt_ptr)->wIndex = 0; \ + (setup_pkt_ptr)->wLength = 1; \ +}) + +/** + * @brief Initializer for a request to get one of the device's current configuration descriptor + * + * - desc_index indicates the configuration's index number + * - Number of bytes of the configuration descriptor to get + */ +#define USB_SETUP_PACKET_INIT_GET_CONFIG_DESC(setup_pkt_ptr, desc_index, desc_len) ({ \ + (setup_pkt_ptr)->bmRequestType = USB_BM_REQUEST_TYPE_DIR_IN | USB_BM_REQUEST_TYPE_TYPE_STANDARD | USB_BM_REQUEST_TYPE_RECIP_DEVICE; \ + (setup_pkt_ptr)->bRequest = USB_B_REQUEST_GET_DESCRIPTOR; \ + (setup_pkt_ptr)->wValue = (USB_W_VALUE_DT_CONFIG << 8) | ((desc_index) & 0xFF); \ + (setup_pkt_ptr)->wIndex = 0; \ + (setup_pkt_ptr)->wLength = (desc_len); \ +}) + +/** + * @brief Initializer for a request to set a device's current configuration number + */ +#define USB_SETUP_PACKET_INIT_SET_CONFIG(setup_pkt_ptr, config_num) ({ \ + (setup_pkt_ptr)->bmRequestType = USB_BM_REQUEST_TYPE_DIR_OUT | USB_BM_REQUEST_TYPE_TYPE_STANDARD | USB_BM_REQUEST_TYPE_RECIP_DEVICE; \ + (setup_pkt_ptr)->bRequest = USB_B_REQUEST_SET_CONFIGURATION; \ + (setup_pkt_ptr)->wValue = (config_num); \ + (setup_pkt_ptr)->wIndex = 0; \ + (setup_pkt_ptr)->wLength = 0; \ +}) + +/** + * @brief Initializer for a request to set an interface's alternate setting + */ +#define USB_SETUP_PACKET_INIT_SET_INTERFACE(setup_pkt_ptr, intf_num, alt_setting_num) ({ \ + (setup_pkt_ptr)->bmRequestType = USB_BM_REQUEST_TYPE_DIR_OUT | USB_BM_REQUEST_TYPE_TYPE_STANDARD | USB_BM_REQUEST_TYPE_RECIP_INTERFACE; \ + (setup_pkt_ptr)->bRequest = USB_B_REQUEST_SET_INTERFACE; \ + (setup_pkt_ptr)->wValue = (alt_setting_num); \ + (setup_pkt_ptr)->wIndex = (intf_num); \ + (setup_pkt_ptr)->wLength = 0; \ +}) + +// ---------------- Standard Descriptor -------------------- + +/** + * @brief Size of dummy USB standard descriptor + */ +#define USB_STANDARD_DESC_SIZE 2 + +/** + * @brief USB standard descriptor + * + * All USB standard descriptors start with these two bytes. Use this type when traversing over configuration descriptors + */ +typedef union { + struct { + uint8_t bLength; /**< Size of the descriptor in bytes */ + uint8_t bDescriptorType; /**< Descriptor Type */ + } USB_DESC_ATTR; + uint8_t val[USB_STANDARD_DESC_SIZE]; +} usb_standard_desc_t; +_Static_assert(sizeof(usb_standard_desc_t) == USB_STANDARD_DESC_SIZE, "Size of usb_standard_desc_t incorrect"); + +// ------------------ Device Descriptor -------------------- + +/** + * @brief Size of a USB device descriptor in bytes + */ +#define USB_DEVICE_DESC_SIZE 18 + +/** + * @brief Structure representing a USB device descriptor + * + * See Table 9-8 of USB2.0 specification for more details + */ +typedef union { + struct { + uint8_t bLength; /**< Size of the descriptor in bytes */ + uint8_t bDescriptorType; /**< DEVICE Descriptor Type */ + uint16_t bcdUSB; /**< USB Specification Release Number in Binary-Coded Decimal (i.e., 2.10 is 210H) */ + uint8_t bDeviceClass; /**< Class code (assigned by the USB-IF) */ + uint8_t bDeviceSubClass; /**< Subclass code (assigned by the USB-IF) */ + uint8_t bDeviceProtocol; /**< Protocol code (assigned by the USB-IF) */ + uint8_t bMaxPacketSize0; /**< Maximum packet size for endpoint zero (only 8, 16, 32, or 64 are valid) */ + uint16_t idVendor; /**< Vendor ID (assigned by the USB-IF) */ + uint16_t idProduct; /**< Product ID (assigned by the manufacturer) */ + uint16_t bcdDevice; /**< Device release number in binary-coded decimal */ + uint8_t iManufacturer; /**< Index of string descriptor describing manufacturer */ + uint8_t iProduct; /**< Index of string descriptor describing product */ + uint8_t iSerialNumber; /**< Index of string descriptor describing the device’s serial number */ + uint8_t bNumConfigurations; /**< Number of possible configurations */ + } USB_DESC_ATTR; + uint8_t val[USB_DEVICE_DESC_SIZE]; +} usb_device_desc_t; +_Static_assert(sizeof(usb_device_desc_t) == USB_DEVICE_DESC_SIZE, "Size of usb_device_desc_t incorrect"); + +/** + * @brief Possible base class values of the bDeviceClass field of a USB device descriptor + */ +#define USB_CLASS_PER_INTERFACE 0x00 +#define USB_CLASS_AUDIO 0x01 +#define USB_CLASS_COMM 0x02 +#define USB_CLASS_HID 0x03 +#define USB_CLASS_PHYSICAL 0x05 +#define USB_CLASS_STILL_IMAGE 0x06 +#define USB_CLASS_PRINTER 0x07 +#define USB_CLASS_MASS_STORAGE 0x08 +#define USB_CLASS_HUB 0x09 +#define USB_CLASS_CDC_DATA 0x0a +#define USB_CLASS_CSCID 0x0b +#define USB_CLASS_CONTENT_SEC 0x0d +#define USB_CLASS_VIDEO 0x0e +#define USB_CLASS_WIRELESS_CONTROLLER 0xe0 +#define USB_CLASS_PERSONAL_HEALTHCARE 0x0f +#define USB_CLASS_AUDIO_VIDEO 0x10 +#define USB_CLASS_BILLBOARD 0x11 +#define USB_CLASS_USB_TYPE_C_BRIDGE 0x12 +#define USB_CLASS_MISC 0xef +#define USB_CLASS_APP_SPEC 0xfe +#define USB_CLASS_VENDOR_SPEC 0xff + +/** + * @brief Vendor specific subclass code + */ +#define USB_SUBCLASS_VENDOR_SPEC 0xff + +// -------------- Configuration Descriptor ----------------- + +/** + * @brief Size of a short USB configuration descriptor in bytes + * + * @note The size of a full USB configuration includes all the interface and endpoint + * descriptors of that configuration. + */ +#define USB_CONFIG_DESC_SIZE 9 + +/** + * @brief Structure representing a short USB configuration descriptor + * + * See Table 9-10 of USB2.0 specification for more details + * + * @note The full USB configuration includes all the interface and endpoint + * descriptors of that configuration. + */ +typedef union { + struct { + uint8_t bLength; /**< Size of the descriptor in bytes */ + uint8_t bDescriptorType; /**< CONFIGURATION Descriptor Type */ + uint16_t wTotalLength; /**< Total length of data returned for this configuration */ + uint8_t bNumInterfaces; /**< Number of interfaces supported by this configuration */ + uint8_t bConfigurationValue; /**< Value to use as an argument to the SetConfiguration() request to select this configuration */ + uint8_t iConfiguration; /**< Index of string descriptor describing this configuration */ + uint8_t bmAttributes; /**< Configuration characteristics */ + uint8_t bMaxPower; /**< Maximum power consumption of the USB device from the bus in this specific configuration when the device is fully operational. */ + } USB_DESC_ATTR; + uint8_t val[USB_CONFIG_DESC_SIZE]; +} usb_config_desc_t; +_Static_assert(sizeof(usb_config_desc_t) == USB_CONFIG_DESC_SIZE, "Size of usb_config_desc_t incorrect"); + +/** + * @brief Bit masks belonging to the bmAttributes field of a configuration descriptor + */ +#define USB_BM_ATTRIBUTES_ONE (1 << 7) //Must be set +#define USB_BM_ATTRIBUTES_SELFPOWER (1 << 6) //Self powered +#define USB_BM_ATTRIBUTES_WAKEUP (1 << 5) //Can wake-up +#define USB_BM_ATTRIBUTES_BATTERY (1 << 4) //Battery powered + +// ---------- Interface Association Descriptor ------------- + +/** + * @brief Size of a USB interface association descriptor in bytes + */ +#define USB_IAD_DESC_SIZE 9 + +/** + * @brief Structure representing a USB interface association descriptor + */ +typedef union { + struct { + uint8_t bLength; /**< Size of the descriptor in bytes */ + uint8_t bDescriptorType; /**< INTERFACE ASSOCIATION Descriptor Type */ + uint8_t bFirstInterface; /**< Interface number of the first interface that is associated with this function */ + uint8_t bInterfaceCount; /**< Number of contiguous interfaces that are associated with this function */ + uint8_t bFunctionClass; /**< Class code (assigned by USB-IF) */ + uint8_t bFunctionSubClass; /**< Subclass code (assigned by USB-IF) */ + uint8_t bFunctionProtocol; /**< Protocol code (assigned by USB-IF) */ + uint8_t iFunction; /**< Index of string descriptor describing this function */ + } USB_DESC_ATTR; + uint8_t val[USB_IAD_DESC_SIZE]; +} usb_iad_desc_t; +_Static_assert(sizeof(usb_iad_desc_t) == USB_IAD_DESC_SIZE, "Size of usb_iad_desc_t incorrect"); + +// ---------------- Interface Descriptor ------------------- + +/** + * @brief Size of a USB interface descriptor in bytes + */ +#define USB_INTF_DESC_SIZE 9 + +/** + * @brief Structure representing a USB interface descriptor + * + * See Table 9-12 of USB2.0 specification for more details + */ +typedef union { + struct { + uint8_t bLength; /**< Size of the descriptor in bytes */ + uint8_t bDescriptorType; /**< INTERFACE Descriptor Type */ + uint8_t bInterfaceNumber; /**< Number of this interface. */ + uint8_t bAlternateSetting; /**< Value used to select this alternate setting for the interface identified in the prior field */ + uint8_t bNumEndpoints; /**< Number of endpoints used by this interface (excluding endpoint zero). */ + uint8_t bInterfaceClass; /**< Class code (assigned by the USB-IF) */ + uint8_t bInterfaceSubClass; /**< Subclass code (assigned by the USB-IF) */ + uint8_t bInterfaceProtocol; /**< Protocol code (assigned by the USB) */ + uint8_t iInterface; /**< Index of string descriptor describing this interface */ + } USB_DESC_ATTR; + uint8_t val[USB_INTF_DESC_SIZE]; +} usb_intf_desc_t; +_Static_assert(sizeof(usb_intf_desc_t) == USB_INTF_DESC_SIZE, "Size of usb_intf_desc_t incorrect"); + +// ----------------- Endpoint Descriptor ------------------- + +/** + * @brief Size of a USB endpoint descriptor in bytes + */ +#define USB_EP_DESC_SIZE 7 + +/** + * @brief Structure representing a USB endpoint descriptor + * + * See Table 9-13 of USB2.0 specification for more details + */ +typedef union { + struct { + uint8_t bLength; /**< Size of the descriptor in bytes */ + uint8_t bDescriptorType; /**< ENDPOINT Descriptor Type */ + uint8_t bEndpointAddress; /**< The address of the endpoint on the USB device described by this descriptor */ + uint8_t bmAttributes; /**< This field describes the endpoint’s attributes when it is configured using the bConfigurationValue. */ + uint16_t wMaxPacketSize; /**< Maximum packet size this endpoint is capable of sending or receiving when this configuration is selected. */ + uint8_t bInterval; /**< Interval for polling Isochronous and Interrupt endpoints. Expressed in frames or microframes depending on the device operating speed (1 ms for Low-Speed and Full-Speed or 125 us for USB High-Speed and above). */ + } USB_DESC_ATTR; + uint8_t val[USB_EP_DESC_SIZE]; +} usb_ep_desc_t; +_Static_assert(sizeof(usb_ep_desc_t) == USB_EP_DESC_SIZE, "Size of usb_ep_desc_t incorrect"); + +/** + * @brief Bit masks belonging to the bEndpointAddress field of an endpoint descriptor + */ +#define USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK 0x0f +#define USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK 0x80 + +/** + * @brief Bit masks belonging to the bmAttributes field of an endpoint descriptor + */ +#define USB_BM_ATTRIBUTES_XFERTYPE_MASK 0x03 +#define USB_BM_ATTRIBUTES_XFER_CONTROL (0 << 0) +#define USB_BM_ATTRIBUTES_XFER_ISOC (1 << 0) +#define USB_BM_ATTRIBUTES_XFER_BULK (2 << 0) +#define USB_BM_ATTRIBUTES_XFER_INT (3 << 0) +#define USB_BM_ATTRIBUTES_SYNCTYPE_MASK 0x0C /* in bmAttributes */ +#define USB_BM_ATTRIBUTES_SYNC_NONE (0 << 2) +#define USB_BM_ATTRIBUTES_SYNC_ASYNC (1 << 2) +#define USB_BM_ATTRIBUTES_SYNC_ADAPTIVE (2 << 2) +#define USB_BM_ATTRIBUTES_SYNC_SYNC (3 << 2) +#define USB_BM_ATTRIBUTES_USAGETYPE_MASK 0x30 +#define USB_BM_ATTRIBUTES_USAGE_DATA (0 << 4) +#define USB_BM_ATTRIBUTES_USAGE_FEEDBACK (1 << 4) +#define USB_BM_ATTRIBUTES_USAGE_IMPLICIT_FB (2 << 4) + +/** + * @brief Macro helpers to get information about an endpoint from its descriptor + */ +#define USB_EP_DESC_GET_XFERTYPE(desc_ptr) ((usb_transfer_type_t) ((desc_ptr)->bmAttributes & USB_BM_ATTRIBUTES_XFERTYPE_MASK)) +#define USB_EP_DESC_GET_EP_NUM(desc_ptr) ((desc_ptr)->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK) +#define USB_EP_DESC_GET_EP_DIR(desc_ptr) (((desc_ptr)->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK) ? 1 : 0) +#define USB_EP_DESC_GET_MPS(desc_ptr) ((desc_ptr)->wMaxPacketSize & 0x7FF) + +// ------------------ String Descriptor -------------------- + +/** + * @brief Size of a short USB string descriptor in bytes + */ +#define USB_STR_DESC_SIZE 4 + +/** + * @brief Structure representing a USB string descriptor + */ +typedef union { + struct { + uint8_t bLength; /**< Size of the descriptor in bytes */ + uint8_t bDescriptorType; /**< STRING Descriptor Type */ + uint16_t wData[1]; /**< UTF-16LE encoded */ + } USB_DESC_ATTR; + uint8_t val[USB_STR_DESC_SIZE]; +} usb_str_desc_t; +_Static_assert(sizeof(usb_str_desc_t) == USB_STR_DESC_SIZE, "Size of usb_str_desc_t incorrect"); + +#ifdef __cplusplus +} +#endif diff --git a/components/usb/include/usb/usb_types_stack.h b/components/usb/include/usb/usb_types_stack.h new file mode 100644 index 0000000000..438c22d9ef --- /dev/null +++ b/components/usb/include/usb/usb_types_stack.h @@ -0,0 +1,141 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* +Warning: The USB Host Library API is still a beta version and may be subject to change +*/ + +#pragma once + +#include "usb/usb_types_ch9.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// ------------------------------------------------ Protocol Standard -------------------------------------------------- + +/** + * @brief USB Standard Speeds + */ +typedef enum { + USB_SPEED_LOW = 0, /**< USB Low Speed (1.5 Mbit/s) */ + USB_SPEED_FULL, /**< USB Full Speed (12 Mbit/s) */ +} usb_speed_t; + +/** + * @brief The type of USB transfer + * + * @note The enum values need to match the bmAttributes field of an EP descriptor + */ +typedef enum { + USB_TRANSFER_TYPE_CTRL = 0, + USB_TRANSFER_TYPE_ISOCHRONOUS, + USB_TRANSFER_TYPE_BULK, + USB_TRANSFER_TYPE_INTR, +} usb_transfer_type_t; + +// ------------------------------------------------- Device Related ---------------------------------------------------- + +/** + * @brief Handle of a USB Device connected to a USB Host + */ +typedef void * usb_device_handle_t; + +/** + * @brief Basic information of an enumerated device + */ +typedef struct { + usb_speed_t speed; /**< Device's speed */ + uint8_t dev_addr; /**< Device's address */ + uint8_t bMaxPacketSize0; /**< The maximum packet size of the device's default endpoint */ + uint8_t bConfigurationValue; /**< Device's current configuration number */ +} usb_device_info_t; + +// ------------------------------------------------ Transfer Related --------------------------------------------------- + +/** + * @brief The status of a particular transfer + */ +typedef enum { + USB_TRANSFER_STATUS_COMPLETED, /**< The transfer was successful (but may be short) */ + USB_TRANSFER_STATUS_ERROR, /**< The transfer failed because due to excessive errors (e.g. no response or CRC error) */ + USB_TRANSFER_STATUS_TIMED_OUT, /**< The transfer failed due to a time out */ + USB_TRANSFER_STATUS_CANCELED, /**< The transfer was canceled */ + USB_TRANSFER_STATUS_STALL, /**< The transfer was stalled */ + USB_TRANSFER_STATUS_OVERFLOW, /**< The transfer as more data was sent than was requested */ + USB_TRANSFER_STATUS_SKIPPED, /**< ISOC packets only. The packet was skipped due to system latency or bus overload */ +} usb_transfer_status_t; + +/** + * @brief Isochronous packet descriptor + * + * If the number of bytes in an Isochronous transfer is larger than the MPS of the endpoint, the transfer is split + * into multiple packets transmitted at the endpoint's specified interval. An array of Isochronous packet descriptors + * describes how an Isochronous transfer should be split into multiple packets. + */ +typedef struct { + int num_bytes; /**< Number of bytes to transmit/receive in the packet. IN packets should be integer multiple of MPS */ + int actual_num_bytes; /**< Actual number of bytes transmitted/received in the packet */ + usb_transfer_status_t status; /**< Status of the packet */ +} usb_isoc_packet_desc_t; + +/** + * @brief USB transfer structure + * + * This structure is used to represent a transfer from a software client to an endpoint over the USB bus. Some of the + * fields are made const on purpose as they are fixed on allocation. Users should call the appropriate USB Host Library + * function to allocate a USB transfer structure instead of allocating this structure themselves. + * + * The transfer type is inferred from the endpoint this transfer is sent to. Depending on the transfer type, users + * should note the following: + * + * - Bulk: This structure represents a single bulk transfer. If the number of bytes exceeds the endpoint's MPS, the + * transfer will be split into multiple MPS sized packets followed by a short packet. + * - Control: This structure represents a single control transfer. This first 8 bytes of the data_buffer must be filled + * with the setup packet (see usb_setup_packet_t). The num_bytes field should be the total size of the + * transfer (i.e., size of setup packet + wLength). + * - Interrupt: Represents an interrupt transfer. If num_bytes exceeds the MPS of the endpoint, the transfer will be + * split into multiple packets, and each packet is transferred at the endpoint's specified interval. + * - Isochronous: Represents a stream of bytes that should be transferred to an endpoint at a fixed rate. The transfer + * is split into packets according to the each isoc_packet_desc. A packet is transferred at each interval + * of the endpoint. + * + * @note For Bulk/Control/Interrupt IN transfers, the num_bytes must be a integer multiple of the endpoint's MPS + * @note This structure should be allocated via usb_host_transfer_alloc() + * @note Once the transfer has be submitted, users should not modify the structure until the transfer has completed + */ +typedef struct usb_transfer_s usb_transfer_t; + +/** + * @brief USB transfer completion callback + */ +typedef void (*usb_transfer_cb_t)(usb_transfer_t *transfer); + +struct usb_transfer_s{ + uint8_t *const data_buffer; /**< Pointer to data buffer */ + const size_t data_buffer_size; /**< Size of the data buffer in bytes */ + int num_bytes; /**< Number of bytes to transfer. + Control transfers should include the size of the setup packet. + Isochronous transfer should be the total transfer size of all packets. + For non-control IN transfers, num_bytes should be an integer multiple of MPS. */ + int actual_num_bytes; /**< Actual number of bytes transferred */ + uint32_t flags; /**< Transfer flags */ + usb_device_handle_t device_handle; /**< Device handle */ + uint8_t bEndpointAddress; /**< Endpoint Address */ + usb_transfer_status_t status; /**< Status of the transfer */ + uint32_t timeout_ms; /**< Timeout (in milliseconds) of the packet (currently not supported yet) */ + usb_transfer_cb_t callback; /**< Transfer callback */ + void *context; /**< Context variable for transfer to associate transfer with something */ + const int num_isoc_packets; /**< Only relevant to Isochronous. Number of service periods (i.e., intervals) to transfer data buffer over. */ + usb_isoc_packet_desc_t isoc_packet_desc[0]; /**< Descriptors for each Isochronous packet */ +}; + +#define USB_TRANSFER_FLAG_ZERO_PACK 0x01 /**< (For bulk OUT only). Indicates that a bulk OUT transfers should always terminate with a short packet, even if it means adding an extra zero length packet */ + +#ifdef __cplusplus +} +#endif diff --git a/components/usb/maintainers.md b/components/usb/maintainers.md index d31fb84d25..81e2d00dec 100644 --- a/components/usb/maintainers.md +++ b/components/usb/maintainers.md @@ -1,18 +1,41 @@ # USB Host Stack Maintainers Notes -This document is intended future maintainers of the ESP-IDF USB Host stack. +This document is intended for future maintainers of the ESP-IDF USB Host stack. Note: The underlying DWC_OTG controller will sometimes be referred to as the Host Controller in this document. +Note: Some static functions within the stack need to be called within critical sections. Therefore, the USB Host stack will prefix all such function names with an underscore (e.g., `_some_static_func()`) will need to be called in critical sections) + The host driver is currently split into the following layers, ordered from the lowest (furthest away from the user) to the highest layer (closest to the user). * USB Host lower layer in `usbh_ll.h` * USB HAL in `usbh_hal.h` and `usbh_hal.c` * Host Controller Driver in `hcd.c` and `hcd.h` +* USB Host Driver in `usb_host.h` and `usb_host.c` + +# DWC_OTG + +Details regarding the DWC_OTG peripheral are covered in the data book and programming guide. However, this section adds some extra notes regarding the hardware's behavior that are not specified / cannot be easily found in the data book or programming guide. + +## Implicit interrupt on short packet on INTERRUPT transfer. + +- An interrupt channel will trigger an interrupt one of its QTDs is a short packet (event if the QTD did not set the interrupt on complete bit). This implicit interrupt is used to notify the software that it should halt the channel to +stop the remainder of the interrupt transfer. + +## Channel interrupt on port errors + +- If there are one or more channels active, and a port error interrupt occurs (such as disconnection, over-current), the active channels will not have an interrupt. Each need to be manually disabled to obtain an interrupt. + +## Reset + +- When resetting, if a disconnect occurs while a reset condition is being held. The disconnect is not detected until the reset condition is released. Once released, a `USBH_HAL_PORT_EVENT_DISCONN` is generated. +- During a second reset (i.e., there is already an enabled device). + - Once the reset condition is asserted, a `USBH_HAL_PORT_EVENT_DISABLED` is generated + - Once released, a `USBH_HAL_PORT_EVENT_ENABLED` is generated again. # USB Host Lower Layer -* `usbh_ll.h` abstracts away the basic register operation of the **DWC** OTG controller +* `usbh_ll.h` abstracts away the basic register operation of the DWC_OTG controller * The LL provides register operations of the DWC OTG controller operating under Host Mode using scatter/gather internal DMA. * For non-host mode specific register operations (i.e. global registers), the functions are prefixed with `usb_ll_...()` * For host mode specific register operations, the functions are prefixed with `usbh_ll_...()` @@ -47,49 +70,52 @@ The HAL layer abstracts the DWC_OTG operating in Host Mode using Internal Scatte # Host Controller Driver (HCD) -The HCD (Host Controller Driver) abstracts the DWC_OTG as N number of ports and an arbitrary number of pipes that can be routed through one of the ports to a device. However note that **the underlying hardware controller only has a single port, so technically only one port can ever be enabled**. +The HCD (Host Controller Driver) abstracts the DWC_OTG as N number of ports and an arbitrary number of pipes that can be routed through one of the ports to a device. However, note that **the underlying hardware controller only has a single port, so technically only one port can ever be enabled**. - In other words, the HCD essentially implements a root hub (not fully behavioral compliant) that contains a single port. - Pipes are "an association between an endpoint on a device and software on the host". URBs (USB Request Block) represent a USB transfer that can be enqueued into a pipe for transmission, and dequeued from a pipe when completed. The HCD currently has the following limitations: -- HCD **does not** "present the root hub and its behavior according to the hub class definition". We currently don't have a hub driver yet, so the port commands in the driver do not fully represent an interface of a USB hub as described in 10.4 of the USB2.0 spec. +- HCD **does not "present the root hub and its behavior according to the hub class definition"**. We currently don't have a hub driver yet, so the port commands in the driver do not fully represent an interface of a USB hub as described in 10.4 of the USB2.0 spec. - No more than 8 pipes can be allocated at any one time due to underlying Host Controllers 8 channel limit. In the future, we could make particular pipes share a single Host Controller channel. -- The HCD currently only supports Control and Bulk transfer types. -- If you are connecting to a device with a large MPS requirements (e.g., Isochronous transfers), you may need to call `hcd_port_set_fifo_bias()` to adjust the size of the internal FIFO ## HCD Port -- An HCD port can be as a simplified version of a port on the Root Hub of the host controller. However, the complexity of parsing Hub Requests is discarded in favor of port commands (`hcd_port_cmd_t`) as the current USB Host Stack does not support hubs yet. +- An HCD port can be thought of as a simplified version of a port on the Root Hub of the host controller. However, the complexity of parsing Hub Requests is discarded in favor of port commands (`hcd_port_cmd_t`) as the current USB Host Stack does not support hubs yet. - A port must first initialized before it can be used. A port is identified by its handled of type `hcd_port_handle_t` - The port can be manipulated using commands such as: - Powering the port ON/OFF - Issuing reset/resume signals - The various host port events are represented in the `hcd_port_event_t` enumeration -- When a fatal error (such as a sudden disconnection or a port over current), the port will be put into the HCD_PORT_STATE_RECOVERY state. The port can be deinitialized from there, or recovered using `hcd_port_recover()`. All the pipes routed through the port will be made invalid. -- The FIFO bias of a port can be set using `hcd_port_set_fifo_bias()`. Biasing the FIFO will affect the permissible MPS sizes of pipes. For example, if the connected device has an IN endpoint with large MPS (e.g., 512 bytes), the FIFO should be biased as `HCD_PORT_FIFO_BIAS_RX`. +- When the following port events occur, the port will be put into the HCD_PORT_STATE_RECOVERY state. The port can be deinitialized from there, or recovered using `hcd_port_recover()`. All the pipes routed through the port must be freed before the port can be recovered. + - `HCD_PORT_EVENT_DISCONNECTION` + - `HCD_PORT_EVENT_ERROR` + - `HCD_PORT_EVENT_OVERCURRENT` +- The port's internal FIFOs (RX, Periodic TX, Non-periodic TX) must be after each port reset (a port reset seems to clear the FIFO sizing registers). The sizing of these FIFOs will affect the largest supported MPS of endpoints using that FIFO. For convenience, the HCD provides the `hcd_port_fifo_bias_t` enum that will set the FIFO sizes for you but biased towards a particular use case. For example, if the connected device has an IN endpoint with large MPS (e.g., 512 bytes), the FIFO should be biased as `HCD_PORT_FIFO_BIAS_RX`. + - The FIFO sizes will be set on port initialization (supplied in `hcd_port_config_t`) + - FIFOs can be resized after port reset using `hcd_port_set_fifo_bias()` but some restrictions apply (see API description). ## HCD Pipes -- URBs can be enqueued into a pipe. Pipes use a linked list internally, so there is in-theory no limit to the number of URBs that can be enqueued. +- Pipes can be opened to a particular endpoint based on a descriptor provided on allocation. If opening a default pipe, a `NULL` descriptor can be provided. +- URBs can be enqueued into a pipe. Pipes use a linked list internally, so there is (in theory) no limit to the number of URBs that can be enqueued. - URBs need to be dequeued once they are completed. - URBs need to have the transfer information (such as data buffer, transfer length in bytes) filled before they should be enqueued. -- URBs will be owned by the HCD until they are dequeued. Thus, users should not attempt to modify an URB object (and the URB's data buffer) until the URB is dequeued. +- URBs will be owned by the HCD until they are dequeued. Thus, users should not attempt to modify a URB object (and the URB's data buffer) until the URB is dequeued. - The URB is defined in `usb_private.h` instead of `hcd.h` so that the same structure can shared throughout the entire Host stack. Each layer simply needs to pass the pointer of the URB to the next layer thus minimizing the amount of copying required. ## HCD SW Arch The software arch for the HCD has the following properties and intentions: -- Some static functions need to be called in critical sections whilst others need not. Therefore, static functions prefixed by an underscore ((e.g., `_some_static_func()`) will need to be called in critical sections. - Some static functions may be blocking. Those functions will have a note in their descriptions. - The HCD communicates events entirely through callbacks and polling/handling functions. The client can choose what type of data structure they want to use in the callbacks to keep track of port and pipe events. Callbacks don't even need to be used, and the HCD should be able to operate entirely on a polling basis. -- The port and each pipe have to be treated as completely separate entities (wither their own handles and events). This allows client to group these entities however it sees fit. For example, the client can: +- The port and each pipe have to be treated as completely separate entities (with their own handles and events). This allows clients to group these entities however it sees fit. For example, the client can: - Let a hub driver manage the port, and manipulate the port via its port handle - Group pipes into interfaces and expose the interface as a single entity -- The HCD will not internally allocate any tasks. It is up to the client to decide how distribute workload (e.g., a single while loop polling a port and all its pipes vs or each pipe having its own task). -- The HCD uses an interrupt process things that require low latency such as processing pipe transfer requests. Where possible, processing is deferred to the `hcd_port_handle_event()` to reduce ISR workload. +- The HCD will not internally allocate any tasks. It is up to the client to decide how to distribute workload (e.g., a single while loop polling a port and all its pipes vs or each pipe having its own task). +- The HCD uses an interrupt to process things that require low latency such as processing pipe transfer requests. Where possible, processing is deferred to the `hcd_port_handle_event()` to reduce ISR workload. ### Events @@ -112,4 +138,4 @@ The HCD API is thread safe however the following limitations should be noted: - Likewise, it is the client's responsibility to ensure that events and pipes are cleared before calling `hcd_port_deinit()`. - `hcd_port_command()` is thread safe, but only one port command can be executed at any one time. Therefore HCD internally used a mutex to protect against concurrent commands. - If multiple threads attempt to execute a command on the sample one, all but one of those threads will return with an invalid state error. -- HCD functions should not be called from critical sections and interrupts, as some functions (e.g., `hcd_port_command()` and `hcd_pipe_command()`) may be blocking. \ No newline at end of file +- Blocking HCD functions should not be called from critical sections and interrupts (e.g., `hcd_port_command()` and `hcd_pipe_command()`). \ No newline at end of file diff --git a/components/usb/private_include/hcd.h b/components/usb/private_include/hcd.h index d5f25c0e92..b1e24ae530 100644 --- a/components/usb/private_include/hcd.h +++ b/components/usb/private_include/hcd.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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -23,7 +15,7 @@ extern "C" { #include #include "esp_err.h" #include "usb_private.h" -#include "usb.h" +#include "usb/usb_types_ch9.h" // ------------------------------------------------- Macros & Types ---------------------------------------------------- @@ -53,18 +45,14 @@ typedef enum { * * Active: * - Pipe is able to transmit data. URBs can be enqueued. - * - Event if pipe has no URBs enqueued, it can still be in the active state. + * - Even if pipe has no URBs enqueued, it can still be in the active state. * Halted: * - An error has occurred on the pipe. URBs will no longer be executed. - * - Halt should be cleared using the clear command - * Invalid: - * - The underlying device that the pipe connects is not longer valid, thus making the pipe invalid. - * - Pending URBs should be dequeued and the pipe should be freed. + * - Halt should be cleared using the HCD_PIPE_CMD_CLEAR command */ typedef enum { HCD_PIPE_STATE_ACTIVE, /**< The pipe is active */ HCD_PIPE_STATE_HALTED, /**< The pipe is halted */ - HCD_PIPE_STATE_INVALID, /**< The pipe no longer exists and should be freed */ } hcd_pipe_state_t; // ----------------------- Events -------------------------- @@ -80,20 +68,16 @@ typedef enum { HCD_PORT_EVENT_DISCONNECTION, /**< A device disconnection has been detected */ HCD_PORT_EVENT_ERROR, /**< A port error has been detected. Port is now HCD_PORT_STATE_RECOVERY */ HCD_PORT_EVENT_OVERCURRENT, /**< Overcurrent detected on the port. Port is now HCD_PORT_STATE_RECOVERY */ - HCD_PORT_EVENT_SUDDEN_DISCONN, /**< The port has suddenly disconnected (i.e., there was an enabled device connected - to the port when the disconnection occurred. Port is now HCD_PORT_STATE_RECOVERY. */ } hcd_port_event_t; /** * @brief HCD pipe events * * @note Pipe error events will put the pipe into the HCD_PIPE_STATE_HALTED state - * @note The HCD_PIPE_EVENT_INVALID will put the pipe in the HCD_PIPE_STATE_INVALID state */ typedef enum { HCD_PIPE_EVENT_NONE, /**< The pipe has no events (used to indicate no events when polling) */ HCD_PIPE_EVENT_URB_DONE, /**< The pipe has completed an URB. The URB can be dequeued */ - HCD_PIPE_EVENT_INVALID, /**< The pipe is invalid because the underlying device is no longer valid */ HCD_PIPE_EVENT_ERROR_XFER, /**< Excessive (three consecutive) transaction errors (e.g., no ACK, bad CRC etc) */ HCD_PIPE_EVENT_ERROR_URB_NOT_AVAIL, /**< URB was not available */ HCD_PIPE_EVENT_ERROR_OVERFLOW, /**< Received more data than requested. Usually a Packet babble error @@ -111,9 +95,9 @@ typedef enum { HCD_PORT_CMD_POWER_OFF, /**< Power OFF the port. If the port is enabled, this will cause a HCD_PORT_EVENT_SUDDEN_DISCONN event. If the port is disabled, this will cause a HCD_PORT_EVENT_DISCONNECTION event. */ HCD_PORT_CMD_RESET, /**< Issue a reset on the port */ - HCD_PORT_CMD_SUSPEND, /**< Suspend the port */ + HCD_PORT_CMD_SUSPEND, /**< Suspend the port. All pipes must be halted */ HCD_PORT_CMD_RESUME, /**< Resume the port */ - HCD_PORT_CMD_DISABLE, /**< Disable the port (stops the SOFs or keep alive). Any created pipes will receive a HCD_PIPE_EVENT_INVALID event */ + HCD_PORT_CMD_DISABLE, /**< Disable the port (stops the SOFs or keep alive). All pipes must be halted. */ } hcd_port_cmd_t; /** @@ -122,10 +106,9 @@ typedef enum { * The pipe commands represent the list of pipe manipulations outlined in 10.5.2.2. of USB2.0 specification. */ typedef enum { - HCD_PIPE_CMD_ABORT, /**< Retire all scheduled URBs. Pipe's state remains unchanged */ - HCD_PIPE_CMD_RESET, /**< Retire all scheduled URBs. Pipe's state moves to active */ - HCD_PIPE_CMD_CLEAR, /**< Pipe's state moves from halted to active */ - HCD_PIPE_CMD_HALT /**< Pipe's state moves to halted */ + HCD_PIPE_CMD_HALT, /**< Halt an active pipe. The currently executing URB will be canceled. Enqueued URBs are left untouched */ + HCD_PIPE_CMD_FLUSH, /**< Can only be called when halted. Will cause all enqueued URBs to be canceled */ + HCD_PIPE_CMD_CLEAR, /**< Causes a halted pipe to become active again. Any enqueued URBs will being executing.*/ } hcd_pipe_cmd_t; // -------------------- Object Types ----------------------- @@ -171,6 +154,7 @@ typedef struct { * @brief Port configuration structure */ typedef struct { + hcd_port_fifo_bias_t fifo_bias; /**< HCD port internal FIFO biasing */ hcd_port_callback_t callback; /**< HCD port event callback */ void *callback_arg; /**< User argument for HCD port callback */ void *context; /**< Context variable used to associate the port with upper layer object */ @@ -185,7 +169,7 @@ typedef struct { hcd_pipe_callback_t callback; /**< HCD pipe event ISR callback */ void *callback_arg; /**< User argument for HCD pipe callback */ void *context; /**< Context variable used to associate the pipe with upper layer object */ - const usb_desc_ep_t *ep_desc; /**< Pointer to endpoint descriptor of the pipe */ + const usb_ep_desc_t *ep_desc; /**< Pointer to endpoint descriptor of the pipe */ usb_speed_t dev_speed; /**< Speed of the device */ uint8_t dev_addr; /**< Device address of the pipe */ } hcd_pipe_config_t; @@ -257,11 +241,12 @@ esp_err_t hcd_port_deinit(hcd_port_handle_t port_hdl); * * Call this function to manipulate a port (e.g., powering it ON, sending a reset etc). The following conditions * must be met when calling this function: - * - The port is in the correct state for the command (e.g., port must be suspend in order to use the resume command) + * - The port is in the correct state for the command (e.g., port must be suspended in order to use the resume command) * - The port does not have any pending events * * @note This function is internally protected by a mutex. If multiple threads call this function, this function will * can block. + * @note The function can block * @note For some of the commands that involve a blocking delay (e.g., reset and resume), if the port's state changes * unexpectedly (e.g., a disconnect during a resume), this function will return ESP_ERR_INVALID_RESPONSE. * @@ -358,8 +343,7 @@ esp_err_t hcd_port_set_fifo_bias(hcd_port_handle_t port_hdl, hcd_port_fifo_bias_ * When allocating a pipe, the HCD will assess whether there are sufficient resources (i.e., bus time, and controller * channels). If sufficient, the pipe will be allocated. * - * @note Currently, Interrupt and Isochronous pipes are not supported yet - * @note The host port must be in the enabled state before a pipe can be allcoated + * @note The host port must be in the enabled state before a pipe can be allocated * * @param[in] port_hdl Handle of the port this pipe will be routed through * @param[in] pipe_config Pipe configuration @@ -392,9 +376,9 @@ esp_err_t hcd_pipe_free(hcd_pipe_handle_t pipe_hdl); * * This function is intended to be called on default pipes during enumeration in order to update the pipe's maximum * packet size. This function can only be called on a pipe that has met the following conditions: - * - Pipe is still valid (i.e., not in the HCD_PIPE_STATE_INVALID state) - * - Pipe is not currently processing a command - * - All URBs have been dequeued from the pipe + * - Pipe is not current processing a command + * - Pipe does not have any enqueued URBs + * - Port cannot be resetting * * @param pipe_hdl Pipe handle * @param mps New Maximum Packet Size @@ -409,9 +393,9 @@ esp_err_t hcd_pipe_update_mps(hcd_pipe_handle_t pipe_hdl, int mps); * * This function is intended to be called on default pipes during enumeration in order to update the pipe's device * address. This function can only be called on a pipe that has met the following conditions: - * - Pipe is still valid (i.e., not in the HCD_PIPE_STATE_INVALID state) - * - Pipe is not currently processing a command - * - All URBs have been dequeued from the pipe + * - Pipe is not current processing a command + * - Pipe does not have any enqueued URBs + * - Port cannot be resetting * * @param pipe_hdl Pipe handle * @param dev_addr New device address @@ -421,6 +405,22 @@ esp_err_t hcd_pipe_update_mps(hcd_pipe_handle_t pipe_hdl, int mps); */ esp_err_t hcd_pipe_update_dev_addr(hcd_pipe_handle_t pipe_hdl, uint8_t dev_addr); +/** + * @brief Update a pipe's callback + * + * This function is intended to be called on default pipes at the end of enumeration to switch to a callback that + * handles the completion of regular control transfer. + * - Pipe is not current processing a command + * - Pipe does not have any enqueued URBs + * - Port cannot be resetting + * + * @param pipe_hdl Pipe handle + * @param callback Callback + * @param user_arg Callback argument + * @return esp_err_t + */ +esp_err_t hcd_pipe_update_callback(hcd_pipe_handle_t pipe_hdl, hcd_pipe_callback_t callback, void *user_arg); + /** * @brief Make a pipe persist through a run time reset * @@ -454,19 +454,14 @@ hcd_pipe_state_t hcd_pipe_get_state(hcd_pipe_handle_t pipe_hdl); /** * @brief Execute a command on a particular pipe * - * Pipe commands allow a pipe to be manipulated (such as clearing a halt, retiring all URBs etc). The following - * conditions must for a pipe command to be issued: - * - Pipe is still valid (i.e., not in the HCD_PIPE_STATE_INVALID) - * - No other thread/task processing a command on the pipe concurrently (will return) + * Pipe commands allow a pipe to be manipulated (such as clearing a halt, retiring all URBs etc) * - * @note Some pipe commands will block until the pipe's current in-flight URB is complete. If the pipe's state - * changes unexpectedly, this function will return ESP_ERR_INVALID_RESPONSE + * @note This function can block * * @param pipe_hdl Pipe handle * @param command Pipe command * @retval ESP_OK: Command executed successfully * @retval ESP_ERR_INVALID_STATE: The pipe is not in the correct state/condition too execute the command - * @retval ESP_ERR_INVALID_RESPONSE: The pipe's state changed unexpectedly */ esp_err_t hcd_pipe_command(hcd_pipe_handle_t pipe_hdl, hcd_pipe_cmd_t command); @@ -490,6 +485,7 @@ hcd_pipe_event_t hcd_pipe_get_event(hcd_pipe_handle_t pipe_hdl); * - The URB is properly initialized (data buffer and transfer length are set) * - The URB must not already be enqueued * - The pipe must be in the HCD_PIPE_STATE_ACTIVE state + * - The pipe cannot be executing a command * * @param pipe_hdl Pipe handle * @param urb URB to enqueue @@ -514,7 +510,7 @@ urb_t *hcd_urb_dequeue(hcd_pipe_handle_t pipe_hdl); * @brief Abort an enqueued URB * * This function will attempt to abort an URB that is already enqueued. If the URB has yet to be executed, it will be - * "cancelled" and can then be dequeued. If the URB is currenty in-flight or has already completed, the URB will not be + * "canceled" and can then be dequeued. If the URB is currently in-flight or has already completed, the URB will not be * affected by this function. * * @param urb URB to abort diff --git a/components/usb/private_include/hub.h b/components/usb/private_include/hub.h new file mode 100644 index 0000000000..fad62817b8 --- /dev/null +++ b/components/usb/private_include/hub.h @@ -0,0 +1,88 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include "esp_err.h" +#include "usb_private.h" +#include "usbh.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// ------------------------------------------------------ Types -------------------------------------------------------- + +/** + * @brief Hub driver configuration + */ +typedef struct { + usb_notif_cb_t notif_cb; /**< Notification callback */ + void *notif_cb_arg; /**< Notification callback argument */ +} hub_config_t; + +// ---------------------------------------------- Hub Driver Functions ------------------------------------------------- + +/** + * @brief Install Hub driver + * + * Entry: + * - USBH must already be installed + * Exit: + * - Install Hub driver memory resources + * - Initializes the HCD root port + * + * @param[in] hub_config Hub driver configuration + * @return esp_err_t + */ +esp_err_t hub_install(hub_config_t *hub_config); + +/** + * @brief Uninstall Hub driver + * + * This must be called before uninstalling the USBH + * Entry: + * - Must have stopped the root port + * Exit: + * - HCD root port deinitialized + * + * @return esp_err_t + */ +esp_err_t hub_uninstall(void); + +/** + * @brief Start the Hub driver's root port + * + * This will power the root port ON + * + * @return esp_err_t + */ +esp_err_t hub_root_start(void); + +/** + * @brief Stops the Hub driver's root port + * + * This will power OFF the root port + * + * @return esp_err_t + */ +esp_err_t hub_root_stop(void); + +/** + * @brief Hub driver's processing function + * + * Hub driver handling function that must be called repeatdly to process the Hub driver's events. If blocking, the + * caller can block on the notification callback of source USB_NOTIF_SOURCE_HUB to run this function. + * + * @return esp_err_t + */ +esp_err_t hub_process(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/usb/private_include/usb.h b/components/usb/private_include/usb.h deleted file mode 100644 index 7c4287ec6e..0000000000 --- a/components/usb/private_include/usb.h +++ /dev/null @@ -1,561 +0,0 @@ -// 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. - -/* -Note: This header file contains the types and macros belong/relate to the USB2.0 protocol and are HW implementation -agnostic. In other words, this header is only meant to be used in the HCD layer and above of the USB Host stack. For -types and macros that are HW implementation specific (i.e., HAL layer and below), add them to the -"hal/usb_types_private.h" header instead. -*/ - -#pragma once - -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -#define USB_CTRL_REQ_ATTR __attribute__((packed)) -#define USB_DESC_ATTR __attribute__((packed)) - -// ------------------------------------------------ Common USB Types --------------------------------------------------- - -// --------------------- Bus Related ----------------------- - -/** - * @brief USB Standard Speeds - */ -typedef enum { - USB_SPEED_LOW = 0, /**< USB Low Speed (1.5 Mbit/s) */ - USB_SPEED_FULL, /**< USB Full Speed (12 Mbit/s) */ -} usb_speed_t; - -// ------------------ Transfer Related --------------------- - -/** - * @brief The type of USB transfer - * - * @note The enum values need to match the bmAttributes field of an EP descriptor - */ -typedef enum { - USB_TRANSFER_TYPE_CTRL = 0, - USB_TRANSFER_TYPE_ISOCHRONOUS, - USB_TRANSFER_TYPE_BULK, - USB_TRANSFER_TYPE_INTR, -} usb_transfer_type_t; - -/** - * @brief The status of a particular transfer - */ -typedef enum { - USB_TRANSFER_STATUS_COMPLETED, /**< The transfer was successful (but may be short) */ - USB_TRANSFER_STATUS_ERROR, /**< The transfer failed because due to excessive errors (e.g. no response or CRC error) */ - USB_TRANSFER_STATUS_TIMED_OUT, /**< The transfer failed due to a time out */ - USB_TRANSFER_STATUS_CANCELED, /**< The transfer was canceled */ - USB_TRANSFER_STATUS_STALL, /**< The transfer was stalled */ - USB_TRANSFER_STATUS_NO_DEVICE, /**< The transfer failed because the device is no longer valid (e.g., disconnected */ - USB_TRANSFER_STATUS_OVERFLOW, /**< The transfer as more data was sent than was requested */ - USB_TRANSFER_STATUS_SKIPPED, /**< ISOC packets only. The packet was skipped due to system latency or bus overload */ -} usb_transfer_status_t; - - -#define USB_TRANSFER_FLAG_ZERO_PACK 0x01 /**< (For bulk OUT only). Indicates that a bulk OUT transfers should always terminate with a short packet, even if it means adding an extra zero length packet */ - -/** - * @brief Isochronous packet descriptor - * - * If the number of bytes in an Isochronous transfer is larger than the MPS of the endpoint, the transfer is split - * into multiple packets transmitted at the endpoint's specified interval. An array of Isochronous packet descriptors - * describes how an Isochronous transfer should be split into multiple packets. - */ -typedef struct { - int num_bytes; /**< Number of bytes to transmit/receive in the packet */ - int actual_num_bytes; /**< Actual number of bytes transmitted/received in the packet */ - usb_transfer_status_t status; /**< Status of the packet */ -} usb_isoc_packet_desc_t; - -/** - * @brief USB transfer structure - * - * This structure is used to represent a transfer from a software client to an endopint over the USB bus. Some of the - * fields are made const on purpose as they are fixed on allocation. Users should call the appropriate USB Host Driver - * function to allocate a USB transfer structure instead of allocating this structure themselves. - * - * The transfer type is inferred from the endpoint this transfer is sent to. Depending on the transfer type, users - * should note the following: - * - * - Bulk: This structure represents a single bulk transfer. If the number of bytes exceeds the endpoint's MPS, the - * transfer will be split into multiple MPS sized packets followed by a short packet. - * - Control: This structure represents a single control transfer. This first 8 bytes of the data_buffer must be filled - * with the setup packet. The num_bytes field should exclude the size of the setup packet (i.e., set to 0 if - * the control transfer has no data stage). - * - Interrupt: Represents an interrupt transfer. If num_bytes exceeds the MPS of the endpoint, the transfer will be - * split into multiple packets, and each packet is transferred at the endpoint's specified interval. - * - Isochronous: Represents a stream of bytes that should be transferred to an endpoint at a fixed rate. The transfer - * is split into packets according to the each isoc_packet_desc. A packet is transferred at each interval - * of the endpoint. - * - * @note For Bulk/Control/Interrupt IN transfers, the num_bytes must be a integer multiple of the endpoint's MPS - * @note This structure should be allocated via __insert_func_name__() - * @note Once the transfer has be submitted, users should not modify the structure until the transfer has completed - */ -typedef struct usb_transfer_obj usb_transfer_t; - -/** - * @brief USB transfer completion callback - */ -typedef void (*usb_transfer_cb_t)(usb_transfer_t *transfer); - -struct usb_transfer_obj{ - uint8_t *const data_buffer; /**< Pointer to data buffer */ - const size_t data_buffer_size; /**< Size of the data buffer in bytes */ - int num_bytes; /**< Number of bytes to transfer. Control transfers should exclude size of setup packet. IN transfers should be integer multiple of MPS */ - int actual_num_bytes; /**< Actual number of bytes transferred */ - uint32_t flags; /**< Transfer flags */ - usb_transfer_status_t status; /**< Status of the transfer */ - uint32_t timeout; /**< Timeout (in milliseconds) of the packet (currently not supported yet) */ - usb_transfer_cb_t callback; /**< Transfer callback */ - void *context; /**< Context variable for transfer to associate transfer with something */ - const int num_isoc_packets; /**< Only relevant to Isochronous. Number of service periods (i.e., intervals) to transfer data buffer over. */ - usb_isoc_packet_desc_t isoc_packet_desc[0]; /**< Descriptors for each Isochronous packet */ -}; - - -// ---------------------------------------------------- Chapter 9 ------------------------------------------------------ - -/** - * @brief Descriptor types from USB2.0 specification table 9.5 - */ -#define USB_B_DESCRIPTOR_TYPE_DEVICE 0x01 -#define USB_B_DESCRIPTOR_TYPE_CONFIGURATION 0x02 -#define USB_B_DESCRIPTOR_TYPE_STRING 0x03 -#define USB_B_DESCRIPTOR_TYPE_INTERFACE 0x04 -#define USB_B_DESCRIPTOR_TYPE_ENDPOINT 0x05 -#define USB_B_DESCRIPTOR_TYPE_DEVICE_QUALIFIER 0x06 -#define USB_B_DESCRIPTOR_TYPE_OTHER_SPEED_CONFIGURATION 0x07 -#define USB_B_DESCRIPTOR_TYPE_INTERFACE_POWER 0x08 - -/** - * @brief Descriptor types from USB 2.0 ECN - */ -#define USB_B_DESCRIPTOR_TYPE_OTG 0x09 -#define USB_B_DESCRIPTOR_TYPE_DEBUG 0x0a -#define USB_B_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION 0x0b - -/** - * @brief Descriptor types from Wireless USB spec - */ -#define USB_B_DESCRIPTOR_TYPE_SECURITY 0x0c -#define USB_B_DESCRIPTOR_TYPE_KEY 0x0d -#define USB_B_DESCRIPTOR_TYPE_ENCRYPTION_TYPE 0x0e -#define USB_B_DESCRIPTOR_TYPE_BOS 0x0f -#define USB_B_DESCRIPTOR_TYPE_DEVICE_CAPABILITY 0x10 -#define USB_B_DESCRIPTOR_TYPE_WIRELESS_ENDPOINT_COMP 0x11 -#define USB_B_DESCRIPTOR_TYPE_WIRE_ADAPTER 0x21 -#define USB_B_DESCRIPTOR_TYPE_RPIPE 0x22 -#define USB_B_DESCRIPTOR_TYPE_CS_RADIO_CONTROL 0x23 - -/** - * @brief Descriptor types from UAS specification - */ -#define USB_B_DESCRIPTOR_TYPE_PIPE_USAGE 0x24 - -// ------------------- Control Request --------------------- - -/** - * @brief Size of a USB control transfer setup packet in bytes - */ -#define USB_CTRL_REQ_SIZE 8 - -/** - * @brief Structure representing a USB control transfer setup packet - */ -typedef union { - struct { - uint8_t bRequestType; - uint8_t bRequest; - uint16_t wValue; - uint16_t wIndex; - uint16_t wLength; - } USB_CTRL_REQ_ATTR; - uint8_t val[USB_CTRL_REQ_SIZE]; -} usb_ctrl_req_t; -_Static_assert(sizeof(usb_ctrl_req_t) == USB_CTRL_REQ_SIZE, "Size of usb_ctrl_req_t incorrect"); - -/** - * @brief Bit masks belonging to the bRequestType field of a setup packet - */ -#define USB_B_REQUEST_TYPE_DIR_OUT (0X00 << 7) -#define USB_B_REQUEST_TYPE_DIR_IN (0x01 << 7) -#define USB_B_REQUEST_TYPE_TYPE_STANDARD (0x00 << 5) -#define USB_B_REQUEST_TYPE_TYPE_CLASS (0x01 << 5) -#define USB_B_REQUEST_TYPE_TYPE_VENDOR (0x02 << 5) -#define USB_B_REQUEST_TYPE_TYPE_RESERVED (0x03 << 5) -#define USB_B_REQUEST_TYPE_TYPE_MASK (0x03 << 5) -#define USB_B_REQUEST_TYPE_RECIP_DEVICE (0x00 << 0) -#define USB_B_REQUEST_TYPE_RECIP_INTERFACE (0x01 << 0) -#define USB_B_REQUEST_TYPE_RECIP_ENDPOINT (0x02 << 0) -#define USB_B_REQUEST_TYPE_RECIP_OTHER (0x03 << 0) -#define USB_B_REQUEST_TYPE_RECIP_MASK (0x1f << 0) - -/** - * @brief Bit masks belonging to the bRequest field of a setup packet - */ -#define USB_B_REQUEST_GET_STATUS 0x00 -#define USB_B_REQUEST_CLEAR_FEATURE 0x01 -#define USB_B_REQUEST_SET_FEATURE 0x03 -#define USB_B_REQUEST_SET_ADDRESS 0x05 -#define USB_B_REQUEST_GET_DESCRIPTOR 0x06 -#define USB_B_REQUEST_SET_DESCRIPTOR 0x07 -#define USB_B_REQUEST_GET_CONFIGURATION 0x08 -#define USB_B_REQUEST_SET_CONFIGURATION 0x09 -#define USB_B_REQUEST_GET_INTERFACE 0x0A -#define USB_B_REQUEST_SET_INTERFACE 0x0B -#define USB_B_REQUEST_SYNCH_FRAME 0x0C - -/** - * @brief Bit masks belonging to the wValue field of a setup packet - */ -#define USB_W_VALUE_DT_DEVICE 0x01 -#define USB_W_VALUE_DT_CONFIG 0x02 -#define USB_W_VALUE_DT_STRING 0x03 -#define USB_W_VALUE_DT_INTERFACE 0x04 -#define USB_W_VALUE_DT_ENDPOINT 0x05 -#define USB_W_VALUE_DT_DEVICE_QUALIFIER 0x06 -#define USB_W_VALUE_DT_OTHER_SPEED_CONFIG 0x07 -#define USB_W_VALUE_DT_INTERFACE_POWER 0x08 - -/** - * @brief Initializer for a SET_ADDRESS request - * - * Sets the address of a connected device - */ -#define USB_CTRL_REQ_INIT_SET_ADDR(ctrl_req_ptr, addr) ({ \ - (ctrl_req_ptr)->bRequestType = USB_B_REQUEST_TYPE_DIR_OUT | USB_B_REQUEST_TYPE_TYPE_STANDARD |USB_B_REQUEST_TYPE_RECIP_DEVICE; \ - (ctrl_req_ptr)->bRequest = USB_B_REQUEST_SET_ADDRESS; \ - (ctrl_req_ptr)->wValue = (addr); \ - (ctrl_req_ptr)->wIndex = 0; \ - (ctrl_req_ptr)->wLength = 0; \ -}) - -/** - * @brief Initializer for a request to get a device's device descriptor - */ -#define USB_CTRL_REQ_INIT_GET_DEVICE_DESC(ctrl_req_ptr) ({ \ - (ctrl_req_ptr)->bRequestType = USB_B_REQUEST_TYPE_DIR_IN | USB_B_REQUEST_TYPE_TYPE_STANDARD | USB_B_REQUEST_TYPE_RECIP_DEVICE; \ - (ctrl_req_ptr)->bRequest = USB_B_REQUEST_GET_DESCRIPTOR; \ - (ctrl_req_ptr)->wValue = (USB_W_VALUE_DT_DEVICE << 8); \ - (ctrl_req_ptr)->wIndex = 0; \ - (ctrl_req_ptr)->wLength = 18; \ -}) - -/** - * @brief Initializer for a request to get a device's current configuration number - */ -#define USB_CTRL_REQ_INIT_GET_CONFIG(ctrl_req_ptr) ({ \ - (ctrl_req_ptr)->bRequestType = USB_B_REQUEST_TYPE_DIR_IN | USB_B_REQUEST_TYPE_TYPE_STANDARD | USB_B_REQUEST_TYPE_RECIP_DEVICE; \ - (ctrl_req_ptr)->bRequest = USB_B_REQUEST_GET_CONFIGURATION; \ - (ctrl_req_ptr)->wValue = 0; \ - (ctrl_req_ptr)->wIndex = 0; \ - (ctrl_req_ptr)->wLength = 1; \ -}) - -/** - * @brief Initializer for a request to get one of the device's current configuration descriptor - * - * - desc_index indicates the configuration's index number - * - Number of bytes of the configuration descriptor to get - */ -#define USB_CTRL_REQ_INIT_GET_CONFIG_DESC(ctrl_req_ptr, desc_index, desc_len) ({ \ - (ctrl_req_ptr)->bRequestType = USB_B_REQUEST_TYPE_DIR_IN | USB_B_REQUEST_TYPE_TYPE_STANDARD | USB_B_REQUEST_TYPE_RECIP_DEVICE; \ - (ctrl_req_ptr)->bRequest = USB_B_REQUEST_GET_DESCRIPTOR; \ - (ctrl_req_ptr)->wValue = (USB_W_VALUE_DT_CONFIG << 8) | ((desc_index) & 0xFF); \ - (ctrl_req_ptr)->wIndex = 0; \ - (ctrl_req_ptr)->wLength = (desc_len); \ -}) - -/** - * @brief Initializer for a request to set a device's current configuration number - */ -#define USB_CTRL_REQ_INIT_SET_CONFIG(ctrl_req_ptr, config_num) ({ \ - (ctrl_req_ptr)->bRequestType = USB_B_REQUEST_TYPE_DIR_OUT | USB_B_REQUEST_TYPE_TYPE_STANDARD | USB_B_REQUEST_TYPE_RECIP_DEVICE; \ - (ctrl_req_ptr)->bRequest = USB_B_REQUEST_SET_CONFIGURATION; \ - (ctrl_req_ptr)->wValue = (config_num); \ - (ctrl_req_ptr)->wIndex = 0; \ - (ctrl_req_ptr)->wLength = 0; \ -}) - -/** - * @brief Initializer for a request to set an interface's alternate setting - */ -#define USB_CTRL_REQ_INIT_SET_INTERFACE(ctrl_req_ptr, intf_num, alt_setting_num) ({ \ - (ctrl_req_ptr)->bRequestType = USB_B_REQUEST_TYPE_DIR_OUT | USB_B_REQUEST_TYPE_TYPE_STANDARD | USB_B_REQUEST_TYPE_RECIP_INTERFACE; \ - (ctrl_req_ptr)->bRequest = USB_B_REQUEST_SET_INTERFACE; \ - (ctrl_req_ptr)->wValue = (alt_setting_num); \ - (ctrl_req_ptr)->wIndex = (intf_num); \ - (ctrl_req_ptr)->wLength = 0; \ -}) - -// ---------------- Standard Descriptor -------------------- - -/** - * @brief Size of dummy USB standard descriptor - */ -#define USB_DESC_STANDARD_SIZE 2 - -/** - * @brief Dummy USB standard descriptor - * - * All USB standard descriptors start with these two bytes. Use this type traversing over descriptors - */ -typedef union { - struct { - uint8_t bLength; - uint8_t bDescriptorType; - } USB_DESC_ATTR; - uint8_t val[USB_DESC_STANDARD_SIZE]; -} usb_desc_standard_t; -_Static_assert(sizeof(usb_desc_standard_t) == USB_DESC_STANDARD_SIZE, "Size of usb_desc_standard_t incorrect"); - -// ------------------ Device Descriptor -------------------- - -/** - * @brief Size of a USB device descriptor in bytes - */ -#define USB_DESC_DEVICE_SIZE 18 - -/** - * @brief Structure representing a USB device descriptor - */ -typedef union { - struct { - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t bcdUSB; - uint8_t bDeviceClass; - uint8_t bDeviceSubClass; - uint8_t bDeviceProtocol; - uint8_t bMaxPacketSize0; - uint16_t idVendor; - uint16_t idProduct; - uint16_t bcdDevice; - uint8_t iManufacturer; - uint8_t iProduct; - uint8_t iSerialNumber; - uint8_t bNumConfigurations; - } USB_DESC_ATTR; - uint8_t val[USB_DESC_DEVICE_SIZE]; -} usb_desc_device_t; -_Static_assert(sizeof(usb_desc_device_t) == USB_DESC_DEVICE_SIZE, "Size of usb_desc_device_t incorrect"); - -/** - * @brief Possible base class values of the bDeviceClass field of a USB device descriptor - */ -#define USB_CLASS_PER_INTERFACE 0x00 -#define USB_CLASS_AUDIO 0x01 -#define USB_CLASS_COMM 0x02 -#define USB_CLASS_HID 0x03 -#define USB_CLASS_PHYSICAL 0x05 -#define USB_CLASS_STILL_IMAGE 0x06 -#define USB_CLASS_PRINTER 0x07 -#define USB_CLASS_MASS_STORAGE 0x08 -#define USB_CLASS_HUB 0x09 -#define USB_CLASS_CDC_DATA 0x0a -#define USB_CLASS_CSCID 0x0b -#define USB_CLASS_CONTENT_SEC 0x0d -#define USB_CLASS_VIDEO 0x0e -#define USB_CLASS_WIRELESS_CONTROLLER 0xe0 -#define USB_CLASS_PERSONAL_HEALTHCARE 0x0f -#define USB_CLASS_AUDIO_VIDEO 0x10 -#define USB_CLASS_BILLBOARD 0x11 -#define USB_CLASS_USB_TYPE_C_BRIDGE 0x12 -#define USB_CLASS_MISC 0xef -#define USB_CLASS_APP_SPEC 0xfe -#define USB_CLASS_VENDOR_SPEC 0xff - -/** - * @brief Vendor specific subclass code - */ -#define USB_SUBCLASS_VENDOR_SPEC 0xff - -// -------------- Configuration Descriptor ----------------- - -/** - * @brief Size of a short USB configuration descriptor in bytes - * - * @note The size of a full USB configuration includes all the interface and endpoint - * descriptors of that configuration. - */ -#define USB_DESC_CONFIG_SIZE 9 - -/** - * @brief Structure representing a short USB configuration descriptor - * - * @note The full USB configuration includes all the interface and endpoint - * descriptors of that configuration. - */ -typedef union { - struct { - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t wTotalLength; - uint8_t bNumInterfaces; - uint8_t bConfigurationValue; - uint8_t iConfiguration; - uint8_t bmAttributes; - uint8_t bMaxPower; - } USB_DESC_ATTR; - uint8_t val[USB_DESC_CONFIG_SIZE]; -} usb_desc_config_t; -_Static_assert(sizeof(usb_desc_config_t) == USB_DESC_CONFIG_SIZE, "Size of usb_desc_config_t incorrect"); - -/** - * @brief Bit masks belonging to the bmAttributes field of a configuration descriptor - */ -#define USB_BM_ATTRIBUTES_ONE (1 << 7) //Must be set -#define USB_BM_ATTRIBUTES_SELFPOWER (1 << 6) //Self powered -#define USB_BM_ATTRIBUTES_WAKEUP (1 << 5) //Can wake-up -#define USB_BM_ATTRIBUTES_BATTERY (1 << 4) //Battery powered - -// ---------- Interface Association Descriptor ------------- - -/** - * @brief Size of a USB interface association descriptor in bytes - */ -#define USB_DESC_INTF_ASSOC_SIZE 9 - -/** - * @brief Structure representing a USB interface association descriptor - */ -typedef union { - struct { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bFirstInterface; - uint8_t bInterfaceCount; - uint8_t bFunctionClass; - uint8_t bFunctionSubClass; - uint8_t bFunctionProtocol; - uint8_t iFunction; - } USB_DESC_ATTR; - uint8_t val[USB_DESC_INTF_ASSOC_SIZE]; -} usb_desc_iad_t; -_Static_assert(sizeof(usb_desc_iad_t) == USB_DESC_INTF_ASSOC_SIZE, "Size of usb_desc_iad_t incorrect"); - -// ---------------- Interface Descriptor ------------------- - -/** - * @brief Size of a USB interface descriptor in bytes - */ -#define USB_DESC_INTF_SIZE 9 - -/** - * @brief Structure representing a USB interface descriptor - */ -typedef union { - struct { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bInterfaceNumber; - uint8_t bAlternateSetting; - uint8_t bNumEndpoints; - uint8_t bInterfaceClass; - uint8_t bInterfaceSubClass; - uint8_t bInterfaceProtocol; - uint8_t iInterface; - } USB_DESC_ATTR; - uint8_t val[USB_DESC_INTF_SIZE]; -} usb_desc_intf_t; -_Static_assert(sizeof(usb_desc_intf_t) == USB_DESC_INTF_SIZE, "Size of usb_desc_intf_t incorrect"); - -// ----------------- Endpoint Descriptor ------------------- - -/** - * @brief Size of a USB endpoint descriptor in bytes - */ -#define USB_DESC_EP_SIZE 7 - -/** - * @brief Structure representing a USB endpoint descriptor - */ -typedef union { - struct { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bEndpointAddress; - uint8_t bmAttributes; - uint16_t wMaxPacketSize; - uint8_t bInterval; - } USB_DESC_ATTR; - uint8_t val[USB_DESC_EP_SIZE]; -} usb_desc_ep_t; -_Static_assert(sizeof(usb_desc_ep_t) == USB_DESC_EP_SIZE, "Size of usb_desc_ep_t incorrect"); - -/** - * @brief Bit masks belonging to the bEndpointAddress field of an endpoint descriptor - */ -#define USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK 0x0f -#define USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK 0x80 - -/** - * @brief Bit masks belonging to the bmAttributes field of an endpoint descriptor - */ -#define USB_BM_ATTRIBUTES_XFERTYPE_MASK 0x03 -#define USB_BM_ATTRIBUTES_XFER_CONTROL (0 << 0) -#define USB_BM_ATTRIBUTES_XFER_ISOC (1 << 0) -#define USB_BM_ATTRIBUTES_XFER_BULK (2 << 0) -#define USB_BM_ATTRIBUTES_XFER_INT (3 << 0) -#define USB_BM_ATTRIBUTES_SYNCTYPE_MASK 0x0C /* in bmAttributes */ -#define USB_BM_ATTRIBUTES_SYNC_NONE (0 << 2) -#define USB_BM_ATTRIBUTES_SYNC_ASYNC (1 << 2) -#define USB_BM_ATTRIBUTES_SYNC_ADAPTIVE (2 << 2) -#define USB_BM_ATTRIBUTES_SYNC_SYNC (3 << 2) -#define USB_BM_ATTRIBUTES_USAGETYPE_MASK 0x30 -#define USB_BM_ATTRIBUTES_USAGE_DATA (0 << 4) -#define USB_BM_ATTRIBUTES_USAGE_FEEDBACK (1 << 4) -#define USB_BM_ATTRIBUTES_USAGE_IMPLICIT_FB (2 << 4) - -/** - * @brief Macro helpers to get information about an endpoint from its descriptor - */ -#define USB_DESC_EP_GET_XFERTYPE(desc_ptr) ((usb_transfer_type_t) ((desc_ptr)->bmAttributes & USB_BM_ATTRIBUTES_XFERTYPE_MASK)) -#define USB_DESC_EP_GET_EP_NUM(desc_ptr) ((desc_ptr)->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK) -#define USB_DESC_EP_GET_EP_DIR(desc_ptr) (((desc_ptr)->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK) ? 1 : 0) -#define USB_DESC_EP_GET_MPS(desc_ptr) ((desc_ptr)->wMaxPacketSize & 0x7FF) - -// ------------------ String Descriptor -------------------- - -/** - * @brief Size of a short USB string descriptor in bytes - */ -#define USB_DESC_STR_SIZE 4 - -/** - * @brief Structure representing a USB string descriptor - */ -typedef union { - struct { - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t wData[1]; /* UTF-16LE encoded */ - } USB_DESC_ATTR; - uint8_t val[USB_DESC_STR_SIZE]; -} usb_desc_str_t; -_Static_assert(sizeof(usb_desc_str_t) == USB_DESC_STR_SIZE, "Size of usb_desc_str_t incorrect"); - -#ifdef __cplusplus -} -#endif diff --git a/components/usb/private_include/usb_private.h b/components/usb/private_include/usb_private.h index f3b0eaac38..b245970b54 100644 --- a/components/usb/private_include/usb_private.h +++ b/components/usb/private_include/usb_private.h @@ -1,34 +1,32 @@ -// Copyright 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: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once #include +#include #include #include -#include "usb.h" +#include "usb/usb_types_ch9.h" +#include "usb/usb_types_stack.h" #ifdef __cplusplus extern "C" { #endif +// ------------------------------------------------------ Types -------------------------------------------------------- + typedef struct { uint8_t *data_buffer; size_t data_buffer_size; int num_bytes; int actual_num_bytes; uint32_t flags; + usb_device_handle_t device_handle; + uint8_t bEndpointAddress; usb_transfer_status_t status; uint32_t timeout; usb_transfer_cb_t callback; @@ -38,17 +36,49 @@ typedef struct { } usb_transfer_dummy_t; _Static_assert(sizeof(usb_transfer_dummy_t) == sizeof(usb_transfer_t), "usb_transfer_dummy_t does not match usb_transfer_t"); -struct urb_obj{ - TAILQ_ENTRY(urb_obj) tailq_entry; - //HCD context pointer and variables. Must be initialized to NULL and 0 respectively +struct urb_s{ + TAILQ_ENTRY(urb_s) tailq_entry; + //HCD handler pointer and variables. Must be initialized to NULL and 0 respectively void *hcd_ptr; uint32_t hcd_var; - //Host Driver layer will add its fields here. + //Host Driver layer handler + void *usb_host_client; //Currently only used when submitted to shared pipes (i.e., Device default pipes) + size_t usb_host_header_size; //USB Host may need the data buffer to have a transparent header //Public transfer structure. Must be last due to variable length array usb_transfer_t transfer; }; +typedef struct urb_s urb_t; -typedef struct urb_obj urb_t; +typedef enum { + USB_NOTIF_SOURCE_USBH = 0x01, + USB_NOTIF_SOURCE_HUB = 0x02, +} usb_notif_source_t; + +typedef bool (*usb_notif_cb_t)(usb_notif_source_t source, bool in_isr, void *context); + +// --------------------------------------------------- Allocation ------------------------------------------------------ + +/** + * @brief Allocate a URB + * + * - Data buffer is allocated in DMA capable memory + * - The constant fields of the URB are also set + * - The data_buffer field of the URB is set to point to start of the allocated data buffer AFTER the header. To access + * the header, users need a negative offset from data_buffer. + * + * @param data_buffer_size Size of the URB's data buffer + * @param header_size Size of header to put in front of URB's data buffer + * @param num_isoc_packets Number of isochronous packet descriptors + * @return urb_t* URB object + */ +urb_t *urb_alloc(size_t data_buffer_size, size_t header_size, int num_isoc_packets); + +/** + * @brief Free a URB + * + * @param urb URB object + */ +void urb_free(urb_t *urb); #ifdef __cplusplus } diff --git a/components/usb/private_include/usbh.h b/components/usb/private_include/usbh.h new file mode 100644 index 0000000000..924646fc48 --- /dev/null +++ b/components/usb/private_include/usbh.h @@ -0,0 +1,383 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "hcd.h" +#include "usb/usb_types_ch9.h" +#include "usb/usb_types_stack.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// ------------------------------------------------------ Types -------------------------------------------------------- + +// ----------------------- Events -------------------------- + +typedef enum { + USBH_EVENT_DEV_NEW, /**< A new device has been enumerated and added to the device pool */ + USBH_EVENT_DEV_GONE, /**< A device is gone. Clients should close the device */ + USBH_EVENT_DEV_ALL_FREE, /**< All devices have been freed */ +} usbh_event_t; + +typedef enum { + USBH_HUB_EVENT_CLEANUP_PORT, /**< Indicate to the Hub driver that it should clean up the port of a device (occurs after a gone device has been freed) */ + USBH_HUB_EVENT_DISABLE_PORT, /**< Indicate to the Hub driver that it should disable the port of a device (occurs after a device has been freed) */ +} usbh_hub_event_t; + +// ---------------------- Callbacks ------------------------ + +/** + * @brief Callback used to indicate completion of control transfers submitted usbh_dev_submit_ctrl_urb() + * @note This callback is called from within usbh_process() + */ +typedef void (*usbh_ctrl_xfer_cb_t)(usb_device_handle_t dev_hdl, urb_t *urb, void *arg); + +/** + * @brief Callback used to indicate that the USBH has an event + * + * @note This callback is called from within usbh_process() + * @note On a USBH_EVENT_DEV_ALL_FREE event, the dev_hdl argument is set to NULL + */ +typedef void (*usbh_event_cb_t)(usb_device_handle_t dev_hdl, usbh_event_t usbh_event, void *arg); + +/** + * @brief Callback used by the USBH to request actions from the Hub driver + * @note This callback is called from within usbh_process() + */ +typedef void (*usbh_hub_cb_t)(hcd_port_handle_t port_hdl, usbh_hub_event_t hub_event, void *arg); + +// ----------------------- Objects ------------------------- + +/** + * @brief Configuration for an endpoint being allocated using usbh_ep_alloc() + */ +typedef struct { + const usb_ep_desc_t *ep_desc; /**< Endpoint descriptor */ + hcd_pipe_callback_t pipe_cb; /**< Endpoint's pipe callback */ + void *pipe_cb_arg; /**< Pipe callback argument */ + void *context; /**< Pipe context */ +} usbh_ep_config_t; + +/** + * @brief USBH configuration used in usbh_install() + */ +typedef struct { + usb_notif_cb_t notif_cb; /**< Notification callback */ + void *notif_cb_arg; /**< Notification callback argument */ + usbh_ctrl_xfer_cb_t ctrl_xfer_cb; /**< Control transfer callback */ + void *ctrl_xfer_cb_arg; /**< Control transfer callback argument */ + usbh_event_cb_t event_cb; /**< USBH event callback */ + void *event_cb_arg; /**< USBH event callback argument */ + hcd_config_t hcd_config; /**< HCD configuration */ +} usbh_config_t; + +// ------------------------------------------------- USBH Functions ---------------------------------------------------- + +/** + * @brief Installs the USBH driver + * + * - This function will internally install the HCD + * - This must be called before calling any Hub driver functions + * + * @param usbh_config USBH driver configuration + * @return esp_err_t + */ +esp_err_t usbh_install(const usbh_config_t *usbh_config); + +/** + * @brief Uninstall the USBH driver + * + * - This function will uninstall the HCD + * - The Hub driver must be uninstalled before calling this function + * + * @return esp_err_t + */ +esp_err_t usbh_uninstall(void); + +/** + * @brief USBH processing function + * + * - USBH processing function that must be called repeatedly to process USBH events + * - If blocking, the caller can block until a USB_NOTIF_SOURCE_USBH notification is received before running this + * function + * + * @return esp_err_t + */ +esp_err_t usbh_process(void); + +// ------------------------------------------------ Device Functions --------------------------------------------------- + +// --------------------- Device Pool ----------------------- + +/** + * @brief Open a device by address + * + * A device must be opened before it can be used + * + * @param[in] dev_addr Device address + * @param[out] dev_hdl Device handle + * @return esp_err_t + */ +esp_err_t usbh_dev_open(uint8_t dev_addr, usb_device_handle_t *dev_hdl); + +/** + * @brief CLose a device + * + * Device can be opened by calling usbh_dev_open() + * + * @param[in] dev_hdl Device handle + * @return esp_err_t + */ +esp_err_t usbh_dev_close(usb_device_handle_t dev_hdl); + +/** + * @brief Mark that all devices should be freed at the next possible opportunity + * + * A device marked as free will not be freed until the last client using the device has called usbh_dev_close() + * + * @return esp_err_t + */ +esp_err_t usbh_dev_mark_all_free(void); + +// ------------------- Single Device ---------------------- + +/** + * @brief Get a device's address + * + * @note Can be called without opening the device + * + * @param[in] dev_hdl Device handle + * @param[out] dev_addr Device's address + * @return esp_err_t + */ +esp_err_t usbh_dev_get_addr(usb_device_handle_t dev_hdl, uint8_t *dev_addr); + +/** + * @brief Get a device's information + * + * @param[in] dev_hdl Device handle + * @param[out] dev_info Device information + * @return esp_err_t + */ +esp_err_t usbh_dev_get_info(usb_device_handle_t dev_hdl, usb_device_info_t *dev_info); + +/** + * @brief Get a device's device descriptor + * + * - The device descriptor is cached when the device is created by the Hub driver + * + * @param[in] dev_hdl Device handle + * @param[out] dev_desc_ret Device descriptor + * @return esp_err_t + */ +esp_err_t usbh_dev_get_desc(usb_device_handle_t dev_hdl, const usb_device_desc_t **dev_desc_ret); + +/** + * @brief Get a device's active configuration descriptor + * + * Simply returns a reference to the internally cached configuration descriptor + * + * @param[in] dev_hdl Device handle + * @param config_desc_ret + * @return esp_err_t + */ +esp_err_t usbh_dev_get_config_desc(usb_device_handle_t dev_hdl, const usb_config_desc_t **config_desc_ret); + +/** + * @brief Submit a control transfer (URB) to a device + * + * @param[in] dev_hdl Device handle + * @param[in] urb URB + * @return esp_err_t + */ +esp_err_t usbh_dev_submit_ctrl_urb(usb_device_handle_t dev_hdl, urb_t *urb); + +// ----------------------------------------------- Endpoint Functions ------------------------------------------------- + +/** + * @brief Allocate an endpoint on a device + * + * Clients that have opened a device must call this function to allocate all endpoints in an interface that is claimed. + * The pipe handle of the endpoint is returned so that clients can use and control the pipe directly. + * + * @note Default pipes are owned by the USBH. For control transfers, use usbh_dev_submit_ctrl_urb() instead + * @note Device must be opened by the client first + * + * @param[in] dev_hdl Device handle + * @param[in] ep_config + * @param[out] pipe_hdl_ret Pipe handle + * @return esp_err_t + */ +esp_err_t usbh_ep_alloc(usb_device_handle_t dev_hdl, usbh_ep_config_t *ep_config, hcd_pipe_handle_t *pipe_hdl_ret); + +/** + * @brief Free and endpoint on a device + * + * Free an endpoint previously opened by usbh_ep_alloc() + * + * @param[in] dev_hdl Device handle + * @param[in] bEndpointAddress Endpoint's address + * @return esp_err_t + */ +esp_err_t usbh_ep_free(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress); + +/** + * @brief Get the context of an endpoint + * + * Get the context variable assigned to and endpoint on allocation. + * + * @param[in] dev_hdl Device handle + * @param[in] bEndpointAddress Endpoint's address + * @param[out] context_ret Context variable + * @return esp_err_t + */ +esp_err_t usbh_ep_get_context(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress, void **context_ret); + +// -------------------------------------------------- Hub Functions ---------------------------------------------------- + +// ------------------- Device Related ---------------------- + +/** + * @brief Indicates to USBH that the Hub driver is installed + * + * - The Hub driver must call this function in its installation to indicate the the USBH that it has been installed. + * - This should only be called after the USBH has already be installed + * + * @note Hub Driver only + * @param[in] hub_callback Hub callback + * @param[in] callback_arg Callback argument + * @return esp_err_t + */ +esp_err_t usbh_hub_is_installed(usbh_hub_cb_t hub_callback, void *callback_arg); + +/** + * @brief Indicates to USBH the start of enumeration for a device + * + * - The Hub driver calls this function before it starts enumerating a new device. + * - The USBH will allocate a new device that will be initialized by the Hub driver using the remaining hub enumeration + * functions. + * - The new device's default pipe handle is returned to all the Hub driver to be used during enumeration. + * + * @note Hub Driver only + * @param[in] port_hdl Handle of the port that the device is connected to + * @param[in] dev_speed Device's speed + * @param[out] new_dev_hdl Device's handle + * @param[out] default_pipe_hdl Device's default pipe handle + * @return esp_err_t + */ +esp_err_t usbh_hub_add_dev(hcd_port_handle_t port_hdl, usb_speed_t dev_speed, usb_device_handle_t *new_dev_hdl, hcd_pipe_handle_t *default_pipe_hdl); + +/** + * @brief Indicate that a device is gone + * + * This Hub driver must call this function to indicate that a device is gone. A device is gone when: + * - It suddenly disconnects + * - Its upstream port or device has an error or is also gone. + * Marking a device as gone will: + * - Trigger a USBH_EVENT_DEV_GONE + * - Prevent further transfers to the device + * - Trigger the device's cleanup if it is already closed + * - When the last client closes the device via usbh_dev_close(), the device's resources will be cleaned up + * + * @note Hub Driver only + * @param[in] dev_hdl Device handle + * @return esp_err_t + */ +esp_err_t usbh_hub_mark_dev_gone(usb_device_handle_t dev_hdl); + +/** + * @brief Indicate that a device's port has been disabled + * + * - The Hub driver must call this function once it has disabled the port of a particular device + * - The Hub driver disables a device's port when requested by the USBH via the USBH_HUB_EVENT_DISABLE_PORT + * - This function will trigger the device's cleanup. + * + * @note Hub Driver only + * @param[in] dev_hdl Device handle + * @return esp_err_t + */ +esp_err_t usbh_hub_dev_port_disabled(usb_device_handle_t dev_hdl); + +// ----------------- Enumeration Related ------------------- + +/** + * @brief Fill the enumerating device's descriptor + * + * @note Hub Driver only + * @note Must call in sequence + * @param[in] dev_hdl Device handle + * @param device_desc + * @return esp_err_t + */ +esp_err_t usbh_hub_enum_fill_dev_desc(usb_device_handle_t dev_hdl, const usb_device_desc_t *device_desc); + +/** + * @brief Assign the enumerating device's address + * + * @note Hub Driver only + * @note Must call in sequence + * @param[in] dev_hdl Device handle + * @param dev_addr + * @return esp_err_t + */ +esp_err_t usbh_hub_enum_fill_dev_addr(usb_device_handle_t dev_hdl, uint8_t dev_addr); + +/** + * @brief Fill the enumerating device's active configuration descriptor + * + * @note Hub Driver only + * @note Must call in sequence + * @param[in] dev_hdl Device handle + * @param config_desc_full + * @return esp_err_t + */ +esp_err_t usbh_hub_enum_fill_config_desc(usb_device_handle_t dev_hdl, const usb_config_desc_t *config_desc_full); + +/** + * @brief Assign the enumerating device's active configuration number + * + * @note Hub Driver only + * @note Must call in sequence + * @param[in] dev_hdl Device handle + * @param bConfigurationValue + * @return esp_err_t + */ +esp_err_t usbh_hub_enum_fill_config_num(usb_device_handle_t dev_hdl, uint8_t bConfigurationValue); + +/** + * @brief Indicate the device enumeration is completed + * + * This will all the device to be opened by clients, and also trigger a USBH_EVENT_DEV_NEW event. + * + * @note Hub Driver only + * @note Must call in sequence + * @param[in] dev_hdl Device handle + * @return esp_err_t + */ +esp_err_t usbh_hub_enum_done(usb_device_handle_t dev_hdl); + +/** + * @brief Indicate that device enumeration has failed + * + * This will cause the enumerating device's resources to be cleaned up + * The Hub Driver must guarantee that the enumerating device's default pipe is already halted, flushed, and dequeued. + * + * @note Hub Driver only + * @note Must call in sequence + * @param[in] dev_hdl Device handle + * @return esp_err_t + */ +esp_err_t usbh_hub_enum_failed(usb_device_handle_t dev_hdl); + +#ifdef __cplusplus +} +#endif diff --git a/components/usb/test/CMakeLists.txt b/components/usb/test/CMakeLists.txt index b2b31a2bec..7857c7ee66 100644 --- a/components/usb/test/CMakeLists.txt +++ b/components/usb/test/CMakeLists.txt @@ -5,7 +5,8 @@ if(NOT "${target}" MATCHES "^esp32s[2-3]") return() endif() -idf_component_register(SRC_DIRS "common" "hcd" - PRIV_INCLUDE_DIRS "../private_include" "common" "hcd" +idf_component_register( + SRC_DIRS "common" "hcd" "usb_host" + PRIV_INCLUDE_DIRS "../private_include" "common" "hcd" "usb_host" PRIV_REQUIRES cmock usb test_utils ) diff --git a/components/usb/test/common/test_usb_mock_classes.c b/components/usb/test/common/test_usb_mock_classes.c index cadf33d9a8..f3d7d42d8e 100644 --- a/components/usb/test/common/test_usb_mock_classes.c +++ b/components/usb/test/common/test_usb_mock_classes.c @@ -15,7 +15,7 @@ #include #include #include -#include "usb.h" +#include "usb/usb_types_ch9.h" #include "test_usb_mock_classes.h" // ---------------------------------------------------- MSC SCSI ------------------------------------------------------- diff --git a/components/usb/test/common/test_usb_mock_classes.h b/components/usb/test/common/test_usb_mock_classes.h index 77352b3bcf..6c80b076c1 100644 --- a/components/usb/test/common/test_usb_mock_classes.h +++ b/components/usb/test/common/test_usb_mock_classes.h @@ -21,7 +21,7 @@ Host stack. #include #include -#include "usb.h" +#include "usb/usb_types_ch9.h" #ifdef __cplusplus extern "C" { @@ -94,8 +94,8 @@ Configuration Descriptor: If you're using a flash driver with different endpoints, modify the endpoint descriptors below. */ -static const usb_desc_ep_t mock_msc_scsi_bulk_out_ep_desc = { - .bLength = sizeof(usb_desc_ep_t), +static const usb_ep_desc_t mock_msc_scsi_bulk_out_ep_desc = { + .bLength = sizeof(usb_ep_desc_t), .bDescriptorType = USB_B_DESCRIPTOR_TYPE_ENDPOINT, .bEndpointAddress = 0x01, //EP 1 OUT .bmAttributes = USB_BM_ATTRIBUTES_XFER_BULK, @@ -103,8 +103,8 @@ static const usb_desc_ep_t mock_msc_scsi_bulk_out_ep_desc = { .bInterval = 1, }; -static const usb_desc_ep_t mock_msc_scsi_bulk_in_ep_desc = { - .bLength = sizeof(usb_desc_ep_t), +static const usb_ep_desc_t mock_msc_scsi_bulk_in_ep_desc = { + .bLength = sizeof(usb_ep_desc_t), .bDescriptorType = USB_B_DESCRIPTOR_TYPE_ENDPOINT, .bEndpointAddress = 0x82, //EP 2 IN .bmAttributes = USB_BM_ATTRIBUTES_XFER_BULK, @@ -123,12 +123,12 @@ static const usb_desc_ep_t mock_msc_scsi_bulk_in_ep_desc = { #define MOCK_MSC_SCSI_BULK_IN_EP_ADDR 0x82 #define MOCK_MSC_SCSI_BULK_EP_MPS 64 -#define MOCK_MSC_SCSI_REQ_INIT_RESET(ctrl_req_ptr, intf_num) ({ \ - (ctrl_req_ptr)->bRequestType = USB_B_REQUEST_TYPE_DIR_OUT | USB_B_REQUEST_TYPE_TYPE_CLASS | USB_B_REQUEST_TYPE_RECIP_INTERFACE; \ - (ctrl_req_ptr)->bRequest = 0xFF; \ - (ctrl_req_ptr)->wValue = 0; \ - (ctrl_req_ptr)->wIndex = (intf_num); \ - (ctrl_req_ptr)->wLength = 0; \ +#define MOCK_MSC_SCSI_REQ_INIT_RESET(setup_pkt_ptr, intf_num) ({ \ + (setup_pkt_ptr)->bmRequestType = USB_BM_REQUEST_TYPE_DIR_OUT | USB_BM_REQUEST_TYPE_TYPE_CLASS | USB_BM_REQUEST_TYPE_RECIP_INTERFACE; \ + (setup_pkt_ptr)->bRequest = 0xFF; \ + (setup_pkt_ptr)->wValue = 0; \ + (setup_pkt_ptr)->wIndex = (intf_num); \ + (setup_pkt_ptr)->wLength = 0; \ }) typedef struct __attribute__((packed)) { @@ -193,21 +193,67 @@ Note: The mock HID mouse tests require that USB low speed mouse be connected. Th - Be implement the HID with standard report format used by mice - It's configuration 1 should have the following endpoint -Endpoint Descriptor: - bLength 7 - bDescriptorType 5 - bEndpointAddress 0x81 EP 1 IN - bmAttributes 3 - Transfer Type Interrupt - Synch Type None - Usage Type Data - wMaxPacketSize 0x0004 1x 4 bytes - bInterval 10 +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 2.00 + bDeviceClass 0 + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 8 + idVendor 0x413c Dell Computer Corp. + idProduct 0x301a + bcdDevice 1.00 + iManufacturer 1 + iProduct 2 + iSerial 0 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 0x0022 + bNumInterfaces 1 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0xa0 + (Bus Powered) + Remote Wakeup + MaxPower 100mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 3 Human Interface Device + bInterfaceSubClass 1 Boot Interface Subclass + bInterfaceProtocol 2 Mouse + iInterface 0 + HID Device Descriptor: + bLength 9 + bDescriptorType 33 + bcdHID 1.11 + bCountryCode 0 Not supported + bNumDescriptors 1 + bDescriptorType 34 Report + wDescriptorLength 46 + Report Descriptors: + ** UNAVAILABLE ** + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0004 1x 4 bytes + bInterval 10 If you're using another mice with different endpoints, modify the endpoint descriptor below */ -static const usb_desc_ep_t mock_hid_mouse_in_ep_desc = { - .bLength = sizeof(usb_desc_ep_t), +static const usb_ep_desc_t mock_hid_mouse_in_ep_desc = { + .bLength = sizeof(usb_ep_desc_t), .bDescriptorType = USB_B_DESCRIPTOR_TYPE_ENDPOINT, .bEndpointAddress = 0x81, //EP 1 IN .bmAttributes = USB_BM_ATTRIBUTES_XFER_INT, @@ -215,6 +261,14 @@ static const usb_desc_ep_t mock_hid_mouse_in_ep_desc = { .bInterval = 10, //Interval of 10ms }; +#define MOCK_HID_MOUSE_DEV_ID_VENDOR 0x413C +#define MOCK_HID_MOUSE_DEV_ID_PRODUCT 0x301A +#define MOCK_HID_MOUSE_DEV_DFLT_EP_MPS 8 +#define MOCK_HID_MOUSE_INTF_NUMBER 0 +#define MOCK_HID_MOUSE_INTF_ALT_SETTING 0 +#define MOCK_HID_MOUSE_INTR_IN_EP_ADDR 0x81 +#define MOCK_HID_MOUSE_INTR_IN_MPS 0x04 + typedef union { struct { uint32_t left_button: 1; @@ -241,8 +295,8 @@ ISOC, transferring to a non-existent endpoint should work. The non-existent endp #define MOCK_ISOC_EP_MPS 512 -static const usb_desc_ep_t mock_isoc_out_ep_desc = { - .bLength = sizeof(usb_desc_ep_t), +static const usb_ep_desc_t mock_isoc_out_ep_desc = { + .bLength = sizeof(usb_ep_desc_t), .bDescriptorType = USB_B_DESCRIPTOR_TYPE_ENDPOINT, .bEndpointAddress = MOCK_ISOC_EP_NUM, .bmAttributes = USB_BM_ATTRIBUTES_XFER_ISOC, diff --git a/components/usb/test/hcd/test_hcd_bulk.c b/components/usb/test/hcd/test_hcd_bulk.c index aef531a046..e1bd189c27 100644 --- a/components/usb/test/hcd/test_hcd_bulk.c +++ b/components/usb/test/hcd/test_hcd_bulk.c @@ -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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -26,10 +18,10 @@ static void mock_msc_reset_req(hcd_pipe_handle_t default_pipe) { //Create URB - urb_t *urb = test_hcd_alloc_urb(0, sizeof(usb_ctrl_req_t)); - usb_ctrl_req_t *ctrl_req = (usb_ctrl_req_t *)urb->transfer.data_buffer; - MOCK_MSC_SCSI_REQ_INIT_RESET(ctrl_req, MOCK_MSC_SCSI_INTF_NUMBER); - urb->transfer.num_bytes = 0; + urb_t *urb = test_hcd_alloc_urb(0, sizeof(usb_setup_packet_t)); + usb_setup_packet_t *setup_pkt = (usb_setup_packet_t *)urb->transfer.data_buffer; + MOCK_MSC_SCSI_REQ_INIT_RESET(setup_pkt, MOCK_MSC_SCSI_INTF_NUMBER); + urb->transfer.num_bytes = sizeof(usb_setup_packet_t); //Enqueue, wait, dequeue, and check URB TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb)); test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE); diff --git a/components/usb/test/hcd/test_hcd_common.c b/components/usb/test/hcd/test_hcd_common.c index 2bf815b47b..93a22d8fd9 100644 --- a/components/usb/test/hcd/test_hcd_common.c +++ b/components/usb/test/hcd/test_hcd_common.c @@ -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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -26,7 +18,7 @@ #include "soc/usb_wrap_struct.h" #include "hcd.h" #include "usb_private.h" -#include "usb.h" +#include "usb/usb_types_ch9.h" #include "test_hcd_common.h" #define PORT_NUM 1 @@ -174,6 +166,7 @@ hcd_port_handle_t test_hcd_setup(void) TEST_ASSERT_EQUAL(ESP_OK, hcd_install(&hcd_config)); //Initialize a port hcd_port_config_t port_config = { + .fifo_bias = HCD_PORT_FIFO_BIAS_BALANCED, .callback = port_callback, .callback_arg = (void *)port_evt_queue, .context = (void *)port_evt_queue, @@ -237,7 +230,7 @@ void test_hcd_wait_for_disconn(hcd_port_handle_t port_hdl, bool already_disabled test_hcd_force_conn_state(false, pdMS_TO_TICKS(100)); //Force disconnected state on PHY test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_DISCONNECTION); TEST_ASSERT_EQUAL(HCD_PORT_EVENT_DISCONNECTION, hcd_port_handle_event(port_hdl)); - TEST_ASSERT_EQUAL(HCD_PORT_STATE_DISCONNECTED, hcd_port_get_state(port_hdl)); + TEST_ASSERT_EQUAL(HCD_PORT_STATE_RECOVERY, hcd_port_get_state(port_hdl)); //Power down the port TEST_ASSERT_EQUAL(ESP_OK, hcd_port_command(port_hdl, HCD_PORT_CMD_POWER_OFF)); TEST_ASSERT_EQUAL(HCD_PORT_STATE_NOT_POWERED, hcd_port_get_state(port_hdl)); @@ -245,7 +238,7 @@ void test_hcd_wait_for_disconn(hcd_port_handle_t port_hdl, bool already_disabled // ---------------------------------------------- Pipe Setup/Tear-down ------------------------------------------------- -hcd_pipe_handle_t test_hcd_pipe_alloc(hcd_port_handle_t port_hdl, const usb_desc_ep_t *ep_desc, uint8_t dev_addr, usb_speed_t dev_speed) +hcd_pipe_handle_t test_hcd_pipe_alloc(hcd_port_handle_t port_hdl, const usb_ep_desc_t *ep_desc, uint8_t dev_addr, usb_speed_t dev_speed) { //Create a queue for pipe callback to queue up pipe events QueueHandle_t pipe_evt_queue = xQueueCreate(EVENT_QUEUE_LEN, sizeof(pipe_event_msg_t)); @@ -300,24 +293,24 @@ void test_hcd_free_urb(urb_t *urb) uint8_t test_hcd_enum_device(hcd_pipe_handle_t default_pipe) { //We need to create a URB for the enumeration control transfers - urb_t *urb = test_hcd_alloc_urb(0, sizeof(usb_ctrl_req_t) + 256); - usb_ctrl_req_t *ctrl_req = (usb_ctrl_req_t *)urb->transfer.data_buffer; + urb_t *urb = test_hcd_alloc_urb(0, sizeof(usb_setup_packet_t) + 256); + usb_setup_packet_t *setup_pkt = (usb_setup_packet_t *)urb->transfer.data_buffer; //Get the device descriptor (note that device might only return 8 bytes) - USB_CTRL_REQ_INIT_GET_DEVICE_DESC(ctrl_req); - urb->transfer.num_bytes = sizeof(usb_desc_device_t); + USB_SETUP_PACKET_INIT_GET_DEVICE_DESC(setup_pkt); + urb->transfer.num_bytes = sizeof(usb_setup_packet_t) + sizeof(usb_device_desc_t); TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb)); test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE); TEST_ASSERT_EQUAL(urb, hcd_urb_dequeue(default_pipe)); TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status); //Update the MPS of the default pipe - usb_desc_device_t *device_desc = (usb_desc_device_t *)(urb->transfer.data_buffer + sizeof(usb_ctrl_req_t)); + usb_device_desc_t *device_desc = (usb_device_desc_t *)(urb->transfer.data_buffer + sizeof(usb_setup_packet_t)); TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_update_mps(default_pipe, device_desc->bMaxPacketSize0)); //Send a set address request - USB_CTRL_REQ_INIT_SET_ADDR(ctrl_req, ENUM_ADDR); //We only support one device for now so use address 1 - urb->transfer.num_bytes = 0; + USB_SETUP_PACKET_INIT_SET_ADDR(setup_pkt, ENUM_ADDR); //We only support one device for now so use address 1 + urb->transfer.num_bytes = sizeof(usb_setup_packet_t); TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb)); test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE); TEST_ASSERT_EQUAL(urb, hcd_urb_dequeue(default_pipe)); @@ -327,8 +320,8 @@ uint8_t test_hcd_enum_device(hcd_pipe_handle_t default_pipe) TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_update_dev_addr(default_pipe, ENUM_ADDR)); //Send a set configuration request - USB_CTRL_REQ_INIT_SET_CONFIG(ctrl_req, ENUM_CONFIG); - urb->transfer.num_bytes = 0; + USB_SETUP_PACKET_INIT_SET_CONFIG(setup_pkt, ENUM_CONFIG); + urb->transfer.num_bytes = sizeof(usb_setup_packet_t); TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb)); test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE); TEST_ASSERT_EQUAL(urb, hcd_urb_dequeue(default_pipe)); diff --git a/components/usb/test/hcd/test_hcd_common.h b/components/usb/test/hcd/test_hcd_common.h index 1d9dac14a2..493b95dc24 100644 --- a/components/usb/test/hcd/test_hcd_common.h +++ b/components/usb/test/hcd/test_hcd_common.h @@ -1,22 +1,14 @@ -// 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" #include "hcd.h" #include "usb_private.h" -#include "usb.h" +#include "usb/usb_types_ch9.h" #define URB_CONTEXT_VAL ((void *)0xDEADBEEF) @@ -109,7 +101,7 @@ void test_hcd_wait_for_disconn(hcd_port_handle_t port_hdl, bool already_disabled * @param dev_speed Device speed of the pipe * @return hcd_pipe_handle_t Pipe handle */ -hcd_pipe_handle_t test_hcd_pipe_alloc(hcd_port_handle_t port_hdl, const usb_desc_ep_t *ep_desc, uint8_t dev_addr, usb_speed_t dev_speed); +hcd_pipe_handle_t test_hcd_pipe_alloc(hcd_port_handle_t port_hdl, const usb_ep_desc_t *ep_desc, uint8_t dev_addr, usb_speed_t dev_speed); /** * @brief Test the freeing of a pipe diff --git a/components/usb/test/hcd/test_hcd_ctrl.c b/components/usb/test/hcd/test_hcd_ctrl.c index fe29db4374..678de453ca 100644 --- a/components/usb/test/hcd/test_hcd_ctrl.c +++ b/components/usb/test/hcd/test_hcd_ctrl.c @@ -22,7 +22,7 @@ #define TEST_DEV_ADDR 0 #define NUM_URBS 3 #define TRANSFER_MAX_BYTES 256 -#define URB_DATA_BUFF_SIZE (sizeof(usb_ctrl_req_t) + TRANSFER_MAX_BYTES) //256 is worst case size for configuration descriptors +#define URB_DATA_BUFF_SIZE (sizeof(usb_setup_packet_t) + TRANSFER_MAX_BYTES) //256 is worst case size for configuration descriptors /* Test HCD control pipe URBs (normal completion and early abort) @@ -54,8 +54,8 @@ TEST_CASE("Test HCD control pipe URBs", "[hcd][ignore]") for (int i = 0; i < NUM_URBS; i++) { urb_list[i] = test_hcd_alloc_urb(0, URB_DATA_BUFF_SIZE); //Initialize with a "Get Config Descriptor request" - urb_list[i]->transfer.num_bytes = TRANSFER_MAX_BYTES; - USB_CTRL_REQ_INIT_GET_CONFIG_DESC((usb_ctrl_req_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); + urb_list[i]->transfer.num_bytes = sizeof(usb_setup_packet_t) + TRANSFER_MAX_BYTES; + USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); urb_list[i]->transfer.context = URB_CONTEXT_VAL; } @@ -68,20 +68,20 @@ TEST_CASE("Test HCD control pipe URBs", "[hcd][ignore]") for (int i = 0; i < NUM_URBS; i++) { test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE); } - //Dequeue URBs + //Dequeue URBs, check, and print for (int i = 0; i < NUM_URBS; i++) { urb_t *urb = hcd_urb_dequeue(default_pipe); TEST_ASSERT_EQUAL(urb_list[i], urb); TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status); TEST_ASSERT_EQUAL(URB_CONTEXT_VAL, urb->transfer.context); + //We must have transmitted at least the setup packet, but device may return less than bytes requested + TEST_ASSERT_GREATER_OR_EQUAL(sizeof(usb_setup_packet_t), urb->transfer.actual_num_bytes); + TEST_ASSERT_LESS_OR_EQUAL(urb->transfer.num_bytes, urb->transfer.actual_num_bytes); + usb_config_desc_t *config_desc = (usb_config_desc_t *)(urb->transfer.data_buffer + sizeof(usb_setup_packet_t)); + TEST_ASSERT_EQUAL(USB_B_DESCRIPTOR_TYPE_CONFIGURATION , config_desc->bDescriptorType); + printf("Config Desc wTotalLength %d\n", config_desc->wTotalLength); } - //Print config desc - for (int i = 0; i < urb_list[0]->transfer.actual_num_bytes; i++) { - printf("%d\t0x%x\n", i, urb_list[0]->transfer.data_buffer[sizeof(usb_ctrl_req_t) + i]); - } - - //Enqueue URBs again but abort them short after for (int i = 0; i < NUM_URBS; i++) { TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb_list[i])); @@ -98,8 +98,11 @@ TEST_CASE("Test HCD control pipe URBs", "[hcd][ignore]") //No need to check for URB pointer address as they may be out of order TEST_ASSERT(urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED || urb->transfer.status == USB_TRANSFER_STATUS_CANCELED); if (urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED) { - TEST_ASSERT_GREATER_THAN(0, urb->transfer.actual_num_bytes); + //We must have transmitted at least the setup packet, but device may return less than bytes requested + TEST_ASSERT_GREATER_OR_EQUAL(sizeof(usb_setup_packet_t), urb->transfer.actual_num_bytes); + TEST_ASSERT_LESS_OR_EQUAL(urb->transfer.num_bytes, urb->transfer.actual_num_bytes); } else { + //A failed transfer should 0 actual number of bytes transmitted TEST_ASSERT_EQUAL(0, urb->transfer.actual_num_bytes); } TEST_ASSERT_EQUAL(urb->transfer.context, URB_CONTEXT_VAL); @@ -119,8 +122,8 @@ TEST_CASE("Test HCD control pipe URBs", "[hcd][ignore]") Test HCD control pipe STALL condition, abort, and clear Purpose: - - Test that a control pipe can react to a STALL (i.e., a HCD_PIPE_EVENT_HALTED event) - - The HCD_PIPE_CMD_ABORT can retire all URBs + - Test that a control pipe can react to a STALL (i.e., a HCD_PIPE_EVENT_ERROR_STALL event) + - The HCD_PIPE_CMD_FLUSH can retire all URBs - Pipe clear command can return the pipe to being active Procedure: @@ -128,7 +131,7 @@ Procedure: - Setup default pipe and allocate URBs - Corrupt the first URB so that it will trigger a STALL, then enqueue all the URBs - Check that a HCD_PIPE_EVENT_ERROR_STALL event is triggered - - Check that all URBs can be retired using HCD_PIPE_CMD_ABORT + - Check that all URBs can be retired using HCD_PIPE_CMD_FLUSH, a HCD_PIPE_EVENT_URB_DONE event should be generated - Check that the STALL can be cleared by using HCD_PIPE_CMD_CLEAR - Fix the corrupt first URB and retry the URBs - Dequeue URBs @@ -146,12 +149,12 @@ TEST_CASE("Test HCD control pipe STALL", "[hcd][ignore]") for (int i = 0; i < NUM_URBS; i++) { urb_list[i] = test_hcd_alloc_urb(0, URB_DATA_BUFF_SIZE); //Initialize with a "Get Config Descriptor request" - urb_list[i]->transfer.num_bytes = TRANSFER_MAX_BYTES; - USB_CTRL_REQ_INIT_GET_CONFIG_DESC((usb_ctrl_req_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); + urb_list[i]->transfer.num_bytes = sizeof(usb_setup_packet_t) + TRANSFER_MAX_BYTES; + USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); urb_list[i]->transfer.context = URB_CONTEXT_VAL; } //Corrupt the first URB so that it triggers a STALL - ((usb_ctrl_req_t *)urb_list[0]->transfer.data_buffer)->bRequest = 0xAA; + ((usb_setup_packet_t *)urb_list[0]->transfer.data_buffer)->bRequest = 0xAA; //Enqueue URBs. A STALL should occur int num_enqueued = 0; @@ -168,14 +171,18 @@ TEST_CASE("Test HCD control pipe STALL", "[hcd][ignore]") TEST_ASSERT_EQUAL(HCD_PIPE_STATE_HALTED, hcd_pipe_get_state(default_pipe)); //Call the pipe abort command to retire all URBs then dequeue them all - TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_ABORT)); + TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_FLUSH)); + test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE); for (int i = 0; i < num_enqueued; i++) { urb_t *urb = hcd_urb_dequeue(default_pipe); TEST_ASSERT_EQUAL(urb_list[i], urb); TEST_ASSERT(urb->transfer.status == USB_TRANSFER_STATUS_STALL || urb->transfer.status == USB_TRANSFER_STATUS_CANCELED); if (urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED) { - TEST_ASSERT_GREATER_THAN(0, urb->transfer.actual_num_bytes); + //We must have transmitted at least the setup packet, but device may return less than bytes requested + TEST_ASSERT_GREATER_OR_EQUAL(sizeof(usb_setup_packet_t), urb->transfer.actual_num_bytes); + TEST_ASSERT_LESS_OR_EQUAL(urb->transfer.num_bytes, urb->transfer.actual_num_bytes); } else { + //A failed transfer should 0 actual number of bytes transmitted TEST_ASSERT_EQUAL(0, urb->transfer.actual_num_bytes); } TEST_ASSERT_EQUAL(URB_CONTEXT_VAL, urb->transfer.context); @@ -187,7 +194,7 @@ TEST_CASE("Test HCD control pipe STALL", "[hcd][ignore]") printf("Retrying\n"); //Correct first URB then requeue - USB_CTRL_REQ_INIT_GET_CONFIG_DESC((usb_ctrl_req_t *)urb_list[0]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); + USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)urb_list[0]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); for (int i = 0; i < NUM_URBS; i++) { TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb_list[i])); } @@ -199,8 +206,13 @@ TEST_CASE("Test HCD control pipe STALL", "[hcd][ignore]") urb_t *urb = hcd_urb_dequeue(default_pipe); TEST_ASSERT_EQUAL(urb_list[i], urb); TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status); - TEST_ASSERT_GREATER_THAN(0, urb->transfer.actual_num_bytes); TEST_ASSERT_EQUAL(URB_CONTEXT_VAL, urb->transfer.context); + //We must have transmitted at least the setup packet, but device may return less than bytes requested + TEST_ASSERT_GREATER_OR_EQUAL(sizeof(usb_setup_packet_t), urb->transfer.actual_num_bytes); + TEST_ASSERT_LESS_OR_EQUAL(urb->transfer.num_bytes, urb->transfer.actual_num_bytes); + usb_config_desc_t *config_desc = (usb_config_desc_t *)(urb->transfer.data_buffer + sizeof(usb_setup_packet_t)); + TEST_ASSERT_EQUAL(USB_B_DESCRIPTOR_TYPE_CONFIGURATION , config_desc->bDescriptorType); + printf("Config Desc wTotalLength %d\n", config_desc->wTotalLength); } //Free URB list and pipe @@ -224,9 +236,10 @@ Purpose: Procedure: - Setup HCD and wait for connection - Setup default pipe and allocate URBs - - Enqqueue URBs but execute a HCD_PIPE_CMD_HALT command immediately after. Halt command should let on - the current going URB finish before actually halting the pipe. - - Un-halt the pipe a HCD_PIPE_CMD_HALT command. Enqueued URBs will be resumed + - Enqqueue URBs but execute a HCD_PIPE_CMD_HALT command immediately after. + - Halt command should immediately halt the current URB and generate a HCD_PIPE_EVENT_URB_DONE + - Other pending URBs should be untouched. + - Un-halt the pipe using a HCD_PIPE_CMD_CLEAR command. Enqueued URBs will be resumed - Check that all URBs have completed successfully - Dequeue URBs and teardown */ @@ -242,8 +255,8 @@ TEST_CASE("Test HCD control pipe runtime halt and clear", "[hcd][ignore]") for (int i = 0; i < NUM_URBS; i++) { urb_list[i] = test_hcd_alloc_urb(0, URB_DATA_BUFF_SIZE); //Initialize with a "Get Config Descriptor request" - urb_list[i]->transfer.num_bytes = TRANSFER_MAX_BYTES; - USB_CTRL_REQ_INIT_GET_CONFIG_DESC((usb_ctrl_req_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); + urb_list[i]->transfer.num_bytes = sizeof(usb_setup_packet_t) + TRANSFER_MAX_BYTES; + USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); urb_list[i]->transfer.context = URB_CONTEXT_VAL; } @@ -253,6 +266,7 @@ TEST_CASE("Test HCD control pipe runtime halt and clear", "[hcd][ignore]") TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb_list[i])); } TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_HALT)); + test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE); TEST_ASSERT_EQUAL(HCD_PIPE_STATE_HALTED, hcd_pipe_get_state(default_pipe)); printf("Pipe halted\n"); @@ -264,11 +278,20 @@ TEST_CASE("Test HCD control pipe runtime halt and clear", "[hcd][ignore]") //Wait for each URB to be done, dequeue, and check results for (int i = 0; i < NUM_URBS; i++) { - test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE); urb_t *urb = hcd_urb_dequeue(default_pipe); TEST_ASSERT_EQUAL(urb_list[i], urb); - TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status); - TEST_ASSERT_GREATER_THAN(0, urb->transfer.actual_num_bytes); + TEST_ASSERT(urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED || urb->transfer.status == USB_TRANSFER_STATUS_CANCELED); + if (urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED) { + //We must have transmitted at least the setup packet, but device may return less than bytes requested + TEST_ASSERT_GREATER_OR_EQUAL(sizeof(usb_setup_packet_t), urb->transfer.actual_num_bytes); + TEST_ASSERT_LESS_OR_EQUAL(urb->transfer.num_bytes, urb->transfer.actual_num_bytes); + usb_config_desc_t *config_desc = (usb_config_desc_t *)(urb->transfer.data_buffer + sizeof(usb_setup_packet_t)); + TEST_ASSERT_EQUAL(USB_B_DESCRIPTOR_TYPE_CONFIGURATION , config_desc->bDescriptorType); + printf("Config Desc wTotalLength %d\n", config_desc->wTotalLength); + } else { + //A failed transfer should 0 actual number of bytes transmitted + TEST_ASSERT_EQUAL(0, urb->transfer.actual_num_bytes); + } TEST_ASSERT_EQUAL(URB_CONTEXT_VAL, urb->transfer.context); } diff --git a/components/usb/test/hcd/test_hcd_intr.c b/components/usb/test/hcd/test_hcd_intr.c index b4de2042c5..1e6f01cbd4 100644 --- a/components/usb/test/hcd/test_hcd_intr.c +++ b/components/usb/test/hcd/test_hcd_intr.c @@ -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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "freertos/FreeRTOS.h" diff --git a/components/usb/test/hcd/test_hcd_isoc.c b/components/usb/test/hcd/test_hcd_isoc.c index d421d926ee..cb9dbec971 100644 --- a/components/usb/test/hcd/test_hcd_isoc.c +++ b/components/usb/test/hcd/test_hcd_isoc.c @@ -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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -65,7 +57,7 @@ TEST_CASE("Test HCD isochronous pipe URBs", "[hcd][ignore]") //Initialize URBs for (int urb_idx = 0; urb_idx < NUM_URBS; urb_idx++) { urb_list[urb_idx] = test_hcd_alloc_urb(NUM_PACKETS_PER_URB, URB_DATA_BUFF_SIZE); - urb_list[urb_idx]->transfer.num_bytes = 0; //num_bytes is not used for ISOC + urb_list[urb_idx]->transfer.num_bytes = URB_DATA_BUFF_SIZE; urb_list[urb_idx]->transfer.context = URB_CONTEXT_VAL; for (int pkt_idx = 0; pkt_idx < NUM_PACKETS_PER_URB; pkt_idx++) { urb_list[urb_idx]->transfer.isoc_packet_desc[pkt_idx].num_bytes = ISOC_PACKET_SIZE; diff --git a/components/usb/test/hcd/test_hcd_port.c b/components/usb/test/hcd/test_hcd_port.c index 5d2c56f8ab..e7267de5f1 100644 --- a/components/usb/test/hcd/test_hcd_port.c +++ b/components/usb/test/hcd/test_hcd_port.c @@ -1,43 +1,40 @@ -// 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-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" #include "unity.h" +#include "esp_rom_sys.h" #include "test_utils.h" #include "test_hcd_common.h" #define TEST_DEV_ADDR 0 #define NUM_URBS 3 #define TRANSFER_MAX_BYTES 256 -#define URB_DATA_BUFF_SIZE (sizeof(usb_ctrl_req_t) + TRANSFER_MAX_BYTES) //256 is worst case size for configuration descriptors +#define URB_DATA_BUFF_SIZE (sizeof(usb_setup_packet_t) + TRANSFER_MAX_BYTES) //256 is worst case size for configuration descriptors +#define POST_ENQUEUE_DELAY_US 10 /* Test a port sudden disconnect and port recovery Purpose: Test that when sudden disconnection happens on an HCD port, the port will - Generate the HCD_PORT_EVENT_SUDDEN_DISCONN and be put into the HCD_PORT_STATE_RECOVERY state - - Ongoing URBs and pipes are handled correctly + - Pipes can be halted and flushed after a port error Procedure: - Setup the HCD and a port - Trigger a port connection - Create a default pipe - - Start transfers but immediately trigger a disconnect - - Check that HCD_PORT_EVENT_SUDDEN_DISCONN event is generated. Handle the event. - - Check that default pipe received a HCD_PIPE_EVENT_INVALID event. Pipe state should be invalid. Dequeue URBs + - Start transfers but trigger a disconnect after a short delay + - Check that HCD_PORT_EVENT_SUDDEN_DISCONN event is generated. Handle that port event. + - Check that the default pipe remains in the HCD_PIPE_STATE_ACTIVE after the port error. + - Check that the default pipe can be halted, a HCD_PIPE_EVENT_URB_DONE event should be generated + - Check that the default pipe can be flushed, a HCD_PIPE_EVENT_URB_DONE event should be generated + - Check that all URBs can be dequeued. - Free default pipe - Recover the port - Trigger connection and disconnection again (to make sure the port works post recovery) @@ -56,8 +53,8 @@ TEST_CASE("Test HCD port sudden disconnect", "[hcd][ignore]") for (int i = 0; i < NUM_URBS; i++) { urb_list[i] = test_hcd_alloc_urb(0, URB_DATA_BUFF_SIZE); //Initialize with a "Get Config Descriptor request" - urb_list[i]->transfer.num_bytes = TRANSFER_MAX_BYTES; - USB_CTRL_REQ_INIT_GET_CONFIG_DESC((usb_ctrl_req_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); + urb_list[i]->transfer.num_bytes = sizeof(usb_setup_packet_t) + TRANSFER_MAX_BYTES; + USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); urb_list[i]->transfer.context = (void *)0xDEADBEEF; } @@ -66,29 +63,35 @@ TEST_CASE("Test HCD port sudden disconnect", "[hcd][ignore]") for (int i = 0; i < NUM_URBS; i++) { TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb_list[i])); } + //Add a short delay to let the transfers run for a bit + esp_rom_delay_us(POST_ENQUEUE_DELAY_US); test_hcd_force_conn_state(false, 0); //Disconnect event should have occurred. Handle the event - test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_SUDDEN_DISCONN); - TEST_ASSERT_EQUAL(HCD_PORT_EVENT_SUDDEN_DISCONN, hcd_port_handle_event(port_hdl)); + test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_DISCONNECTION); + TEST_ASSERT_EQUAL(HCD_PORT_EVENT_DISCONNECTION, hcd_port_handle_event(port_hdl)); TEST_ASSERT_EQUAL(HCD_PORT_STATE_RECOVERY, hcd_port_get_state(port_hdl)); printf("Sudden disconnect\n"); - //Pipe should have received (zero or more HCD_PIPE_EVENT_URB_DONE) followed by a HCD_PIPE_EVENT_INVALID (MUST OCCUR) - int num_pipe_events = test_hcd_get_num_pipe_events(default_pipe); - for (int i = 0; i < num_pipe_events - 1; i++) { - test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE); - } - test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_INVALID); - TEST_ASSERT_EQUAL(hcd_pipe_get_state(default_pipe), HCD_PIPE_STATE_INVALID); + //We should be able to halt then flush the pipe + TEST_ASSERT_EQUAL(HCD_PIPE_STATE_ACTIVE, hcd_pipe_get_state(default_pipe)); + TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_HALT)); + test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE); + TEST_ASSERT_EQUAL(HCD_PIPE_STATE_HALTED, hcd_pipe_get_state(default_pipe)); + TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_FLUSH)); + test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE); + printf("Pipe halted and flushed\n"); //Dequeue URBs for (int i = 0; i < NUM_URBS; i++) { urb_t *urb = hcd_urb_dequeue(default_pipe); TEST_ASSERT_EQUAL(urb_list[i], urb); - TEST_ASSERT(urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED || urb->transfer.status == USB_TRANSFER_STATUS_NO_DEVICE); + TEST_ASSERT(urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED || urb->transfer.status == USB_TRANSFER_STATUS_CANCELED); if (urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED) { - TEST_ASSERT_GREATER_THAN(0, urb->transfer.actual_num_bytes); + //We must have transmitted at least the setup packet, but device may return less than bytes requested + TEST_ASSERT_GREATER_OR_EQUAL(sizeof(usb_setup_packet_t), urb->transfer.actual_num_bytes); + TEST_ASSERT_LESS_OR_EQUAL(urb->transfer.num_bytes, urb->transfer.actual_num_bytes); } else { + //A failed transfer should 0 actual number of bytes transmitted TEST_ASSERT_EQUAL(0, urb->transfer.actual_num_bytes); } TEST_ASSERT_EQUAL(0xDEADBEEF, urb->transfer.context); @@ -113,17 +116,20 @@ TEST_CASE("Test HCD port sudden disconnect", "[hcd][ignore]") Test port suspend and resume with active pipes Purpose: - - Test port suspend and resume commands work correctly whilst there are active pipes with ongoing transfers - - When suspending, the pipes should be allowed to finish their current ongoing transfer before the bus is suspended. - - When resuming, pipes with pending transfer should be started after the bus is resumed. + - Test port suspend and resume procedure + - When suspending, the pipes should be halted before suspending the port. Any pending transfers should remain pending + - When resuming, the pipes should remain in the halted state + - Pipes on being cleared of the halt should resume transferring the pending transfers Procedure: - Setup the HCD and a port - Trigger a port connection - Create a default pipe - - Start transfers but suspend the port immediately + - Start transfers + - Halt the default pipe after a short delay + - Suspend the port - Resume the port - - Check that all the URBs have completed successfully + - Check that all the URBs have either completed successfully or been canceled by the pipe halt - Cleanup URBs and default pipe - Trigger disconnection and teardown */ @@ -139,8 +145,8 @@ TEST_CASE("Test HCD port suspend and resume", "[hcd][ignore]") for (int i = 0; i < NUM_URBS; i++) { urb_list[i] = test_hcd_alloc_urb(0, URB_DATA_BUFF_SIZE); //Initialize with a "Get Config Descriptor request" - urb_list[i]->transfer.num_bytes = TRANSFER_MAX_BYTES; - USB_CTRL_REQ_INIT_GET_CONFIG_DESC((usb_ctrl_req_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); + urb_list[i]->transfer.num_bytes = sizeof(usb_setup_packet_t) + TRANSFER_MAX_BYTES; + USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); urb_list[i]->transfer.context = (void *)0xDEADBEEF; } @@ -149,6 +155,13 @@ TEST_CASE("Test HCD port suspend and resume", "[hcd][ignore]") for (int i = 0; i < NUM_URBS; i++) { TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb_list[i])); } + //Add a short delay to let the transfers run for a bit + esp_rom_delay_us(POST_ENQUEUE_DELAY_US); + //Halt the default pipe before suspending + TEST_ASSERT_EQUAL(HCD_PIPE_STATE_ACTIVE, hcd_pipe_get_state(default_pipe)); + TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_HALT)); + TEST_ASSERT_EQUAL(HCD_PIPE_STATE_HALTED, hcd_pipe_get_state(default_pipe)); + //Suspend the port TEST_ASSERT_EQUAL(ESP_OK, hcd_port_command(port_hdl, HCD_PORT_CMD_SUSPEND)); TEST_ASSERT_EQUAL(HCD_PORT_STATE_SUSPENDED, hcd_port_get_state(port_hdl)); printf("Suspended\n"); @@ -158,13 +171,23 @@ TEST_CASE("Test HCD port suspend and resume", "[hcd][ignore]") TEST_ASSERT_EQUAL(ESP_OK, hcd_port_command(port_hdl, HCD_PORT_CMD_RESUME)); TEST_ASSERT_EQUAL(HCD_PORT_STATE_ENABLED, hcd_port_get_state(port_hdl)); printf("Resumed\n"); + //Clear the default pipe's halt + TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_CLEAR)); + TEST_ASSERT_EQUAL(HCD_PIPE_STATE_ACTIVE, hcd_pipe_get_state(default_pipe)); vTaskDelay(pdMS_TO_TICKS(100)); //Give some time for resumed URBs to complete //Dequeue URBs for (int i = 0; i < NUM_URBS; i++) { urb_t *urb = hcd_urb_dequeue(default_pipe); TEST_ASSERT_EQUAL(urb_list[i], urb); - TEST_ASSERT_EQUAL(urb->transfer.status, USB_TRANSFER_STATUS_COMPLETED); - TEST_ASSERT_GREATER_THAN(0, urb->transfer.actual_num_bytes); + TEST_ASSERT(urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED || urb->transfer.status == USB_TRANSFER_STATUS_CANCELED); + if (urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED) { + //We must have transmitted at least the setup packet, but device may return less than bytes requested + TEST_ASSERT_GREATER_OR_EQUAL(sizeof(usb_setup_packet_t), urb->transfer.actual_num_bytes); + TEST_ASSERT_LESS_OR_EQUAL(urb->transfer.num_bytes, urb->transfer.actual_num_bytes); + } else { + //A failed transfer should 0 actual number of bytes transmitted + TEST_ASSERT_EQUAL(0, urb->transfer.actual_num_bytes); + } TEST_ASSERT_EQUAL(0xDEADBEEF, urb->transfer.context); } @@ -179,18 +202,20 @@ TEST_CASE("Test HCD port suspend and resume", "[hcd][ignore]") } /* -Test HCD port disable with active pipes +Test HCD port disable and disconnection Purpose: - - Test that the port disable command works correctly with active pipes - - Pipes should be to finish their current ongoing transfer before port is disabled - - After disabling the port, all pipes should become invalid. + - Test that the port disable command works correctly + - Check that port can only be disabled when pipes have been halted + - Check that a disconnection after port disable still triggers a HCD_PORT_EVENT_DISCONNECTION event Procedure: - Setup HCD, a default pipe, and multiple URBs - - Start transfers but immediately disable the port - - Check pipe received invalid event - - Check that transfer are either done or not executed + - Start transfers + - Halt the default pipe after a short delay + - Check that port can be disabled + - Flush the default pipe and cleanup the default pipe + - Check that a disconnection still works after disable - Teardown */ TEST_CASE("Test HCD port disable", "[hcd][ignore]") @@ -205,8 +230,8 @@ TEST_CASE("Test HCD port disable", "[hcd][ignore]") for (int i = 0; i < NUM_URBS; i++) { urb_list[i] = test_hcd_alloc_urb(0, URB_DATA_BUFF_SIZE); //Initialize with a "Get Config Descriptor request" - urb_list[i]->transfer.num_bytes = TRANSFER_MAX_BYTES; - USB_CTRL_REQ_INIT_GET_CONFIG_DESC((usb_ctrl_req_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); + urb_list[i]->transfer.num_bytes = sizeof(usb_setup_packet_t) + TRANSFER_MAX_BYTES; + USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES); urb_list[i]->transfer.context = (void *)0xDEADBEEF; } @@ -215,25 +240,32 @@ TEST_CASE("Test HCD port disable", "[hcd][ignore]") for (int i = 0; i < NUM_URBS; i++) { TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb_list[i])); } + //Add a short delay to let the transfers run for a bit + esp_rom_delay_us(POST_ENQUEUE_DELAY_US); + //Halt the default pipe before suspending + TEST_ASSERT_EQUAL(HCD_PIPE_STATE_ACTIVE, hcd_pipe_get_state(default_pipe)); + TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_HALT)); + TEST_ASSERT_EQUAL(HCD_PIPE_STATE_HALTED, hcd_pipe_get_state(default_pipe)); + + + //Check that port can be disabled TEST_ASSERT_EQUAL(ESP_OK, hcd_port_command(port_hdl, HCD_PORT_CMD_DISABLE)); TEST_ASSERT_EQUAL(HCD_PORT_STATE_DISABLED, hcd_port_get_state(port_hdl)); printf("Disabled\n"); - //Pipe should have received (zero or more HCD_PIPE_EVENT_URB_DONE) followed by a HCD_PIPE_EVENT_INVALID (MUST OCCUR) - int num_pipe_events = test_hcd_get_num_pipe_events(default_pipe); - for (int i = 0; i < num_pipe_events - 1; i++) { - test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE); - } - test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_INVALID); - + //Flush pipe + TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_FLUSH)); //Dequeue URBs for (int i = 0; i < NUM_URBS; i++) { urb_t *urb = hcd_urb_dequeue(default_pipe); TEST_ASSERT_EQUAL(urb_list[i], urb); - TEST_ASSERT(urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED || urb->transfer.status == USB_TRANSFER_STATUS_NO_DEVICE); + TEST_ASSERT(urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED || urb->transfer.status == USB_TRANSFER_STATUS_CANCELED); if (urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED) { - TEST_ASSERT_GREATER_THAN(0, urb->transfer.actual_num_bytes); + //We must have transmitted at least the setup packet, but device may return less than bytes requested + TEST_ASSERT_GREATER_OR_EQUAL(sizeof(usb_setup_packet_t), urb->transfer.actual_num_bytes); + TEST_ASSERT_LESS_OR_EQUAL(urb->transfer.num_bytes, urb->transfer.actual_num_bytes); } else { + //A failed transfer should 0 actual number of bytes transmitted TEST_ASSERT_EQUAL(0, urb->transfer.actual_num_bytes); } TEST_ASSERT_EQUAL(0xDEADBEEF, urb->transfer.context); @@ -244,7 +276,8 @@ TEST_CASE("Test HCD port disable", "[hcd][ignore]") test_hcd_free_urb(urb_list[i]); } test_hcd_pipe_free(default_pipe); - //Cleanup + + //Trigger a disconnection and cleanup test_hcd_wait_for_disconn(port_hdl, true); test_hcd_teardown(port_hdl); } @@ -296,8 +329,8 @@ TEST_CASE("Test HCD port command bailout", "[hcd][ignore]") TEST_ASSERT_EQUAL(ESP_ERR_INVALID_RESPONSE, hcd_port_command(port_hdl, HCD_PORT_CMD_RESUME)); //Check that concurrent task triggered a sudden disconnection - test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_SUDDEN_DISCONN); - TEST_ASSERT_EQUAL(HCD_PORT_EVENT_SUDDEN_DISCONN, hcd_port_handle_event(port_hdl)); + test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_DISCONNECTION); + TEST_ASSERT_EQUAL(HCD_PORT_EVENT_DISCONNECTION, hcd_port_handle_event(port_hdl)); TEST_ASSERT_EQUAL(HCD_PORT_STATE_RECOVERY, hcd_port_get_state(port_hdl)); //Cleanup task and semaphore diff --git a/components/usb/test/usb_host/ctrl_client.h b/components/usb/test/usb_host/ctrl_client.h new file mode 100644 index 0000000000..4cfeccc53d --- /dev/null +++ b/components/usb/test/usb_host/ctrl_client.h @@ -0,0 +1,15 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +typedef struct { + int num_ctrl_xfer_to_send; + uint16_t idVendor; + uint16_t idProduct; +} ctrl_client_test_param_t; + +void ctrl_client_async_seq_task(void *arg); diff --git a/components/usb/test/usb_host/ctrl_client_async_seq.c b/components/usb/test/usb_host/ctrl_client_async_seq.c new file mode 100644 index 0000000000..85751adeb6 --- /dev/null +++ b/components/usb/test/usb_host/ctrl_client_async_seq.c @@ -0,0 +1,185 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_err.h" +#include "esp_log.h" +#include "ctrl_client.h" +#include "usb/usb_host.h" +#include "unity.h" +#include "test_utils.h" + +/* +Implementation of a control transfer client used for USB Host Tests. + +- Implemented using sequential call patterns, meaning: + - The entire client is contained within a single task + - All API calls and callbacks are run sequentially + - No critical sections required since everything is sequential +- The control transfer client will: + - Register itself as a client + - Receive USB_HOST_CLIENT_EVENT_NEW_DEV event message, and open the device + - Allocate multiple transfer objects + - Submit a number of control transfers (get configuration descriptor requests) + - Free transfer objects + - Close the device + - Deregister control client +*/ + +#define MAX(x,y) (((x) >= (y)) ? (x) : (y)) +#define CTRL_CLIENT_MAX_EVENT_MSGS 5 +#define NUM_TRANSFER_OBJ 3 +#define MAX_TRANSFER_BYTES 256 + +const char *CTRL_CLIENT_TAG = "Ctrl Client"; + +typedef enum { + TEST_STAGE_WAIT_CONN, + TEST_STAGE_DEV_OPEN, + TEST_STAGE_CTRL_XFER, + TEST_STAGE_CTRL_XFER_WAIT, + TEST_STAGE_DEV_CLOSE, +} test_stage_t; + +typedef struct { + ctrl_client_test_param_t test_param; + test_stage_t cur_stage; + test_stage_t next_stage; + uint8_t num_xfer_done; + uint8_t num_xfer_sent; + uint8_t dev_addr_to_open; + usb_host_client_handle_t client_hdl; + usb_device_handle_t dev_hdl; + const usb_config_desc_t *config_desc_cached; +} ctrl_client_obj_t; + +static void ctrl_transfer_cb(usb_transfer_t *transfer) +{ + ctrl_client_obj_t *ctrl_obj = (ctrl_client_obj_t *)transfer->context; + //Check the completed control transfer + TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, transfer->status); + TEST_ASSERT_EQUAL(ctrl_obj->config_desc_cached->wTotalLength, transfer->actual_num_bytes - sizeof(usb_setup_packet_t)); + ctrl_obj->num_xfer_done++; + if (ctrl_obj->num_xfer_sent < ctrl_obj->test_param.num_ctrl_xfer_to_send) { + ctrl_obj->next_stage = TEST_STAGE_CTRL_XFER; + } else if (ctrl_obj->num_xfer_done == ctrl_obj->test_param.num_ctrl_xfer_to_send) { + ctrl_obj->next_stage = TEST_STAGE_DEV_CLOSE; + } +} + +static void ctrl_client_event_cb(const usb_host_client_event_msg_t *event_msg, void *arg) +{ + ctrl_client_obj_t *ctrl_obj = (ctrl_client_obj_t *)arg; + switch (event_msg->event) { + case USB_HOST_CLIENT_EVENT_NEW_DEV: + TEST_ASSERT_EQUAL(TEST_STAGE_WAIT_CONN, ctrl_obj->cur_stage); + ctrl_obj->next_stage = TEST_STAGE_DEV_OPEN; + ctrl_obj->dev_addr_to_open = event_msg->new_dev.address; + break; + default: + abort(); //Should never occur in this test + break; + } +} + +void ctrl_client_async_seq_task(void *arg) +{ + ctrl_client_obj_t ctrl_obj = {0}; + memcpy(&ctrl_obj.test_param, arg, sizeof(ctrl_client_test_param_t)); + ctrl_obj.cur_stage = TEST_STAGE_WAIT_CONN; + ctrl_obj.next_stage = TEST_STAGE_WAIT_CONN; + + //Register client + usb_host_client_config_t client_config = { + .client_event_callback = ctrl_client_event_cb, + .callback_arg = (void *)&ctrl_obj, + .max_num_event_msg = CTRL_CLIENT_MAX_EVENT_MSGS, + }; + TEST_ASSERT_EQUAL(ESP_OK, usb_host_client_register(&client_config, &ctrl_obj.client_hdl)); + + //Allocate transfers + usb_transfer_t *ctrl_xfer[NUM_TRANSFER_OBJ] = {NULL}; + for (int i = 0; i < NUM_TRANSFER_OBJ; i++) { + TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_alloc(sizeof(usb_setup_packet_t) + MAX_TRANSFER_BYTES, 0, &ctrl_xfer[i])); + ctrl_xfer[i]->callback = ctrl_transfer_cb; + ctrl_xfer[i]->context = (void *)&ctrl_obj; + } + + //Wait to be started by main thread + ulTaskNotifyTake(pdTRUE, portMAX_DELAY); + ESP_LOGD(CTRL_CLIENT_TAG, "Starting"); + + bool exit_loop = false; + bool skip_event_handling = false; + while (!exit_loop) { + if (!skip_event_handling) { + TEST_ASSERT_EQUAL(ESP_OK, usb_host_client_handle_events(ctrl_obj.client_hdl, portMAX_DELAY)); + } + skip_event_handling = false; + if (ctrl_obj.cur_stage == ctrl_obj.next_stage) { + continue; + } + ctrl_obj.cur_stage = ctrl_obj.next_stage; + + switch (ctrl_obj.next_stage) { + case TEST_STAGE_DEV_OPEN: { + ESP_LOGD(CTRL_CLIENT_TAG, "Open"); + //Open the device + TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_open(ctrl_obj.client_hdl, ctrl_obj.dev_addr_to_open, &ctrl_obj.dev_hdl)); + //Target our transfers to the device + for (int i = 0; i < NUM_TRANSFER_OBJ; i++) { + ctrl_xfer[i]->device_handle = ctrl_obj.dev_hdl; + } + //Check the VID/PID of the opened device + const usb_device_desc_t *device_desc; + TEST_ASSERT_EQUAL(ESP_OK, usb_host_get_device_descriptor(ctrl_obj.dev_hdl, &device_desc)); + TEST_ASSERT_EQUAL(ctrl_obj.test_param.idVendor, device_desc->idVendor); + TEST_ASSERT_EQUAL(ctrl_obj.test_param.idProduct, device_desc->idProduct); + //Cache the active configuration descriptor for later comparison + TEST_ASSERT_EQUAL(ESP_OK, usb_host_get_active_config_descriptor(ctrl_obj.dev_hdl, &ctrl_obj.config_desc_cached)); + ctrl_obj.next_stage = TEST_STAGE_CTRL_XFER; + skip_event_handling = true; + break; + } + case TEST_STAGE_CTRL_XFER: { + ESP_LOGD(CTRL_CLIENT_TAG, "Transfer"); + //Send a control transfer to get the device's configuration descriptor + usb_transfer_t *transfer = ctrl_xfer[ctrl_obj.num_xfer_sent % NUM_TRANSFER_OBJ]; + USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)transfer->data_buffer, 0, MAX_TRANSFER_BYTES); + transfer->num_bytes = sizeof(usb_setup_packet_t) + MAX_TRANSFER_BYTES; + transfer->bEndpointAddress = 0; + TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_submit_control(ctrl_obj.client_hdl, transfer)); + ctrl_obj.num_xfer_sent++; + ctrl_obj.next_stage = TEST_STAGE_CTRL_XFER_WAIT; + skip_event_handling = true; + break; + } + case TEST_STAGE_CTRL_XFER_WAIT: { + //Nothing to do but wait + break; + } + case TEST_STAGE_DEV_CLOSE: { + ESP_LOGD(CTRL_CLIENT_TAG, "Close"); + TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_close(ctrl_obj.client_hdl, ctrl_obj.dev_hdl)); + exit_loop = true; + break; + } + default: + abort(); + break; + } + } + //Free transfers and deregister client + for (int i = 0; i < NUM_TRANSFER_OBJ; i++) { + TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_free(ctrl_xfer[i])); + } + TEST_ASSERT_EQUAL(ESP_OK, usb_host_client_deregister(ctrl_obj.client_hdl)); + ESP_LOGD(CTRL_CLIENT_TAG, "Done"); + vTaskDelete(NULL); +} diff --git a/components/usb/test/usb_host/msc_client.h b/components/usb/test/usb_host/msc_client.h new file mode 100644 index 0000000000..b1809b949c --- /dev/null +++ b/components/usb/test/usb_host/msc_client.h @@ -0,0 +1,17 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +typedef struct { + int num_sectors_to_read; + int num_sectors_per_xfer; + uint32_t msc_scsi_xfer_tag; + uint16_t idVendor; + uint16_t idProduct; +} msc_client_test_param_t; + +void msc_client_async_seq_task(void *arg); diff --git a/components/usb/test/usb_host/msc_client_async_seq.c b/components/usb/test/usb_host/msc_client_async_seq.c new file mode 100644 index 0000000000..7189f4cd61 --- /dev/null +++ b/components/usb/test/usb_host/msc_client_async_seq.c @@ -0,0 +1,242 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "esp_err.h" +#include "esp_log.h" +#include "test_usb_mock_classes.h" +#include "msc_client.h" +#include "usb/usb_host.h" +#include "unity.h" +#include "test_utils.h" + +/* +Implementation of an MSC client used for USB Host Tests + +- Implemented using sequential call patterns, meaning: + - The entire client is contained within a single task + - All API calls and callbacks are run sequentially + - No critical sections required since everything is sequential +- The MSC client will: + - Register itself as a client + - Receive USB_HOST_CLIENT_EVENT_NEW_DEV event message, and open the device + - Allocate IN and OUT transfer objects for MSC SCSI transfers + - Iterate through multiple MSC SCSI block reads + - Free transfer objects + - Close device + - Deregister MSC client +*/ + +#define MAX(x,y) (((x) >= (y)) ? (x) : (y)) +#define MSC_CLIENT_MAX_EVENT_MSGS 5 + +const char *MSC_CLIENT_TAG = "MSC Client"; + +typedef enum { + TEST_STAGE_WAIT_CONN, + TEST_STAGE_DEV_OPEN, + TEST_STAGE_MSC_RESET, + TEST_STAGE_MSC_CBW, + TEST_STAGE_MSC_DATA, + TEST_STAGE_MSC_CSW, + TEST_STAGE_DEV_CLOSE, +} test_stage_t; + +typedef struct { + msc_client_test_param_t test_param; + test_stage_t cur_stage; + test_stage_t next_stage; + uint8_t dev_addr_to_open; + usb_host_client_handle_t client_hdl; + usb_device_handle_t dev_hdl; + int num_sectors_read; +} msc_client_obj_t; + +static void msc_transfer_cb(usb_transfer_t *transfer) +{ + msc_client_obj_t *msc_obj = (msc_client_obj_t *)transfer->context; + switch (msc_obj->cur_stage) { + case TEST_STAGE_MSC_RESET: { + //Check MSC SCSI interface reset + TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, transfer->status); + TEST_ASSERT_EQUAL(transfer->num_bytes, transfer->actual_num_bytes); + msc_obj->next_stage = TEST_STAGE_MSC_CBW; + break; + } + case TEST_STAGE_MSC_CBW: { + //Check MSC SCSI CBW transfer + TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, transfer->status); + TEST_ASSERT_EQUAL(sizeof(mock_msc_bulk_cbw_t), transfer->actual_num_bytes); + msc_obj->next_stage = TEST_STAGE_MSC_DATA; + break; + } + case TEST_STAGE_MSC_DATA: { + //Check MSC SCSI data IN transfer + TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, transfer->status); + TEST_ASSERT_EQUAL(MOCK_MSC_SCSI_SECTOR_SIZE * msc_obj->test_param.num_sectors_per_xfer, transfer->actual_num_bytes); + msc_obj->next_stage = TEST_STAGE_MSC_CSW; + break; + } + case TEST_STAGE_MSC_CSW: { + //Check MSC SCSI CSW transfer + TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, transfer->status); + TEST_ASSERT_EQUAL(true, mock_msc_scsi_check_csw((mock_msc_bulk_csw_t *)transfer->data_buffer, msc_obj->test_param.msc_scsi_xfer_tag)); + msc_obj->num_sectors_read += msc_obj->test_param.num_sectors_per_xfer; + if (msc_obj->num_sectors_read < msc_obj->test_param.num_sectors_to_read) { + msc_obj->next_stage = TEST_STAGE_MSC_CBW; + } else { + msc_obj->next_stage = TEST_STAGE_DEV_CLOSE; + } + break; + } + default: { + abort(); + break; + } + } +} + +static void msc_client_event_cb(const usb_host_client_event_msg_t *event_msg, void *arg) +{ + msc_client_obj_t *msc_obj = (msc_client_obj_t *)arg; + switch (event_msg->event) { + case USB_HOST_CLIENT_EVENT_NEW_DEV: + TEST_ASSERT_EQUAL(TEST_STAGE_WAIT_CONN, msc_obj->cur_stage); + msc_obj->next_stage = TEST_STAGE_DEV_OPEN; + msc_obj->dev_addr_to_open = event_msg->new_dev.address; + break; + default: + abort(); //Should never occur in this test + break; + + } +} + +void msc_client_async_seq_task(void *arg) +{ + msc_client_obj_t msc_obj; + memcpy(&msc_obj.test_param, arg, sizeof(msc_client_test_param_t)); + msc_obj.cur_stage = TEST_STAGE_WAIT_CONN; + msc_obj.next_stage = TEST_STAGE_WAIT_CONN; + msc_obj.client_hdl = NULL; + msc_obj.dev_addr_to_open = 0; + msc_obj.dev_hdl = NULL; + msc_obj.num_sectors_read = 0; + + //Register client + usb_host_client_config_t client_config = { + .client_event_callback = msc_client_event_cb, + .callback_arg = (void *)&msc_obj, + .max_num_event_msg = MSC_CLIENT_MAX_EVENT_MSGS, + }; + TEST_ASSERT_EQUAL(ESP_OK, usb_host_client_register(&client_config, &msc_obj.client_hdl)); + + //Allocate transfers + usb_transfer_t *xfer_out = NULL; //Must be large enough to contain CBW and MSC reset control transfer + usb_transfer_t *xfer_in = NULL; //Must be large enough to contain CSW and Data + size_t out_worst_case_size = MAX(sizeof(mock_msc_bulk_cbw_t), sizeof(usb_setup_packet_t)); + size_t in_worst_case_size = usb_round_up_to_mps(MAX(MOCK_MSC_SCSI_SECTOR_SIZE * msc_obj.test_param.num_sectors_per_xfer, sizeof(mock_msc_bulk_csw_t)), MOCK_MSC_SCSI_BULK_EP_MPS); + TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_alloc(out_worst_case_size, 0, &xfer_out)); + TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_alloc(in_worst_case_size, 0, &xfer_in)); + xfer_out->callback = msc_transfer_cb; + xfer_in->callback = msc_transfer_cb; + xfer_out->context = (void *)&msc_obj; + xfer_in->context = (void *)&msc_obj; + + //Wait to be started by main thread + ulTaskNotifyTake(pdTRUE, portMAX_DELAY); + ESP_LOGD(MSC_CLIENT_TAG, "Starting"); + + bool exit_loop = false; + bool skip_event_handling = false; + while (!exit_loop) { + if (!skip_event_handling) { + TEST_ASSERT_EQUAL(ESP_OK, usb_host_client_handle_events(msc_obj.client_hdl, portMAX_DELAY)); + } + skip_event_handling = false; + if (msc_obj.cur_stage == msc_obj.next_stage) { + continue; + } + msc_obj.cur_stage = msc_obj.next_stage; + + switch (msc_obj.cur_stage) { + case TEST_STAGE_DEV_OPEN: { + ESP_LOGD(MSC_CLIENT_TAG, "Open"); + //Open the device + TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_open(msc_obj.client_hdl, msc_obj.dev_addr_to_open, &msc_obj.dev_hdl)); + //Target our transfers to the device + xfer_out->device_handle = msc_obj.dev_hdl; + xfer_in->device_handle = msc_obj.dev_hdl; + //Check the VID/PID of the opened device + const usb_device_desc_t *device_desc; + TEST_ASSERT_EQUAL(ESP_OK, usb_host_get_device_descriptor(msc_obj.dev_hdl, &device_desc)); + TEST_ASSERT_EQUAL(msc_obj.test_param.idVendor, device_desc->idVendor); + TEST_ASSERT_EQUAL(msc_obj.test_param.idProduct, device_desc->idProduct); + //Claim the MSC interface + TEST_ASSERT_EQUAL(ESP_OK, usb_host_interface_claim(msc_obj.client_hdl, msc_obj.dev_hdl, MOCK_MSC_SCSI_INTF_NUMBER, MOCK_MSC_SCSI_INTF_ALT_SETTING)); + msc_obj.next_stage = TEST_STAGE_MSC_RESET; + skip_event_handling = true; //Need to execute TEST_STAGE_MSC_RESET + break; + } + case TEST_STAGE_MSC_RESET: { + ESP_LOGD(MSC_CLIENT_TAG, "MSC Reset"); + //Send an MSC SCSI interface reset + MOCK_MSC_SCSI_REQ_INIT_RESET((usb_setup_packet_t *)xfer_out->data_buffer, MOCK_MSC_SCSI_INTF_NUMBER); + xfer_out->num_bytes = sizeof(usb_setup_packet_t); + xfer_out->bEndpointAddress = 0; + TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_submit_control(msc_obj.client_hdl, xfer_out)); + //Next stage set from transfer callback + break; + } + case TEST_STAGE_MSC_CBW: { + ESP_LOGD(MSC_CLIENT_TAG, "CBW"); + mock_msc_scsi_init_cbw((mock_msc_bulk_cbw_t *)xfer_out->data_buffer, true, msc_obj.next_stage, msc_obj.test_param.num_sectors_per_xfer, msc_obj.test_param.msc_scsi_xfer_tag); + xfer_out->num_bytes = sizeof(mock_msc_bulk_cbw_t); + xfer_out->bEndpointAddress = MOCK_MSC_SCSI_BULK_OUT_EP_ADDR; + TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_submit(xfer_out)); + //Next stage set from transfer callback + break; + } + case TEST_STAGE_MSC_DATA: { + ESP_LOGD(MSC_CLIENT_TAG, "Data"); + xfer_in->num_bytes = usb_round_up_to_mps(MOCK_MSC_SCSI_SECTOR_SIZE * msc_obj.test_param.num_sectors_per_xfer, MOCK_MSC_SCSI_BULK_EP_MPS); + xfer_in->bEndpointAddress = MOCK_MSC_SCSI_BULK_IN_EP_ADDR; + TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_submit(xfer_in)); + //Next stage set from transfer callback + break; + } + case TEST_STAGE_MSC_CSW: { + ESP_LOGD(MSC_CLIENT_TAG, "CSW"); + xfer_in->num_bytes = usb_round_up_to_mps(sizeof(mock_msc_bulk_csw_t), MOCK_MSC_SCSI_BULK_EP_MPS); + xfer_in->bEndpointAddress = MOCK_MSC_SCSI_BULK_IN_EP_ADDR; + TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_submit(xfer_in)); + //Next stage set from transfer callback + break; + } + case TEST_STAGE_DEV_CLOSE: { + ESP_LOGD(MSC_CLIENT_TAG, "Close"); + TEST_ASSERT_EQUAL(ESP_OK, usb_host_interface_release(msc_obj.client_hdl, msc_obj.dev_hdl, MOCK_MSC_SCSI_INTF_NUMBER)); + TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_close(msc_obj.client_hdl, msc_obj.dev_hdl)); + exit_loop = true; + break; + } + default: + abort(); + break; + } + } + //Free transfers and deregister the client + TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_free(xfer_out)); + TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_free(xfer_in)); + TEST_ASSERT_EQUAL(ESP_OK, usb_host_client_deregister(msc_obj.client_hdl)); + ESP_LOGD(MSC_CLIENT_TAG, "Done"); + vTaskDelete(NULL); +} diff --git a/components/usb/test/usb_host/test_usb_helpers.c b/components/usb/test/usb_host/test_usb_helpers.c new file mode 100644 index 0000000000..07f905a26c --- /dev/null +++ b/components/usb/test/usb_host/test_usb_helpers.c @@ -0,0 +1,439 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "unity.h" +#include "test_utils.h" +#include "usb/usb_host.h" + +/* +Tests that check the configuration descriptor parsing functions provided in usb_host.h work by parsing a fixed +configuration descriptor. The fixed configuration descriptor used in this test is provided below (both in textual and +byte format), and is of a UVC device. Thus the configuration descriptor has a good set of scenarios that can be tested +(such as multiple interfaces, alternate settings, class specific descriptors, default endpoint only interfaces etc). +*/ + +/* +Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 0x0185 + bNumInterfaces 2 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 500mA + Interface Association: + bLength 8 + bDescriptorType 11 + bFirstInterface 0 + bInterfaceCount 2 + bFunctionClass 14 Video + bFunctionSubClass 3 Video Interface Collection + bFunctionProtocol 0 + iFunction 5 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 1 Video Control + bInterfaceProtocol 0 + iInterface 5 + VideoControl Interface Descriptor: + bLength 13 + bDescriptorType 36 + bDescriptorSubtype 1 (HEADER) + bcdUVC 1.00 + wTotalLength 0x004f + dwClockFrequency 15.000000MHz + bInCollection 1 + baInterfaceNr( 0) 1 + VideoControl Interface Descriptor: + bLength 9 + bDescriptorType 36 + bDescriptorSubtype 3 (OUTPUT_TERMINAL) + bTerminalID 4 + wTerminalType 0x0101 USB Streaming + bAssocTerminal 0 + bSourceID 3 + iTerminal 0 + VideoControl Interface Descriptor: + bLength 28 + bDescriptorType 36 + bDescriptorSubtype 6 (EXTENSION_UNIT) + bUnitID 3 + guidExtensionCode {4cf18db6-abd0-495c-9876-1fa3942ff9fa} + bNumControl 24 + bNrPins 1 + baSourceID( 0) 2 + bControlSize 3 + bmControls( 0) 0xff + bmControls( 1) 0xff + bmControls( 2) 0xff + iExtension 0 + VideoControl Interface Descriptor: + bLength 18 + bDescriptorType 36 + bDescriptorSubtype 2 (INPUT_TERMINAL) + bTerminalID 1 + wTerminalType 0x0201 Camera Sensor + bAssocTerminal 0 + iTerminal 0 + wObjectiveFocalLengthMin 0 + wObjectiveFocalLengthMax 0 + wOcularFocalLength 0 + bControlSize 3 + bmControls 0x0000000e + Auto-Exposure Mode + Auto-Exposure Priority + Exposure Time (Absolute) + VideoControl Interface Descriptor: + bLength 11 + bDescriptorType 36 + bDescriptorSubtype 5 (PROCESSING_UNIT) + Warning: Descriptor too short + bUnitID 2 + bSourceID 1 + wMaxMultiplier 0 + bControlSize 2 + bmControls 0x0000177f + Brightness + Contrast + Hue + Saturation + Sharpness + Gamma + White Balance Temperature + Backlight Compensation + Gain + Power Line Frequency + White Balance Temperature, Auto + iProcessing 0 + bmVideoStandards 0x62 + NTSC - 525/60 + PAL - 525/60 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 6 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + VideoStreaming Interface Descriptor: + bLength 15 + bDescriptorType 36 + bDescriptorSubtype 1 (INPUT_HEADER) + bNumFormats 2 + wTotalLength 0x00f7 + bEndPointAddress 129 + bmInfo 0 + bTerminalLink 4 + bStillCaptureMethod 0 + bTriggerSupport 0 + bTriggerUsage 0 + bControlSize 1 + bmaControls( 0) 0 + bmaControls( 1) 0 + VideoStreaming Interface Descriptor: + bLength 27 + bDescriptorType 36 + bDescriptorSubtype 4 (FORMAT_UNCOMPRESSED) + bFormatIndex 1 + bNumFrameDescriptors 2 + guidFormat {85f6cc1d-0c9f-44f5-9ce0-97c7dd8c98ab} + bBitsPerPixel 16 + bDefaultFrameIndex 1 + bAspectRatioX 0 + bAspectRatioY 0 + bmInterlaceFlags 0x00 + Interlaced stream or variable: No + Fields per frame: 2 fields + Field 1 first: No + Field pattern: Field 1 only + bCopyProtect 0 + VideoStreaming Interface Descriptor: + bLength 30 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 1 + bmCapabilities 0x00 + Still image unsupported + wWidth 480 + wHeight 320 + dwMinBitRate 12288000 + dwMaxBitRate 12288000 + dwMaxVideoFrameBufferSize 307200 + dwDefaultFrameInterval 2000000 + bFrameIntervalType 1 + dwFrameInterval( 0) 2000000 + VideoStreaming Interface Descriptor: + bLength 30 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 2 + bmCapabilities 0x00 + Still image unsupported + wWidth 640 + wHeight 480 + dwMinBitRate 73728000 + dwMaxBitRate 73728000 + dwMaxVideoFrameBufferSize 614400 + dwDefaultFrameInterval 666666 + bFrameIntervalType 1 + dwFrameInterval( 0) 666666 + VideoStreaming Interface Descriptor: + bLength 11 + bDescriptorType 36 + bDescriptorSubtype 6 (FORMAT_MJPEG) + bFormatIndex 2 + bNumFrameDescriptors 4 + bFlags 0 + Fixed-size samples: No + bDefaultFrameIndex 1 + bAspectRatioX 0 + bAspectRatioY 0 + bmInterlaceFlags 0x00 + Interlaced stream or variable: No + Fields per frame: 1 fields + Field 1 first: No + Field pattern: Field 1 only + bCopyProtect 0 + VideoStreaming Interface Descriptor: + bLength 30 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 1 + bmCapabilities 0x00 + Still image unsupported + wWidth 640 + wHeight 480 + dwMinBitRate 36864000 + dwMaxBitRate 36864000 + dwMaxVideoFrameBufferSize 307789 + dwDefaultFrameInterval 666666 + bFrameIntervalType 1 + dwFrameInterval( 0) 666666 + VideoStreaming Interface Descriptor: + bLength 38 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 2 + bmCapabilities 0x00 + Still image unsupported + wWidth 480 + wHeight 320 + dwMinBitRate 6144000 + dwMaxBitRate 18432000 + dwMaxVideoFrameBufferSize 154189 + dwDefaultFrameInterval 666666 + bFrameIntervalType 3 + dwFrameInterval( 0) 666666 + dwFrameInterval( 1) 1000000 + dwFrameInterval( 2) 2000000 + VideoStreaming Interface Descriptor: + bLength 30 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 3 + bmCapabilities 0x00 + Still image unsupported + wWidth 352 + wHeight 288 + dwMinBitRate 12165120 + dwMaxBitRate 12165120 + dwMaxVideoFrameBufferSize 101965 + dwDefaultFrameInterval 666666 + bFrameIntervalType 1 + dwFrameInterval( 0) 666666 + VideoStreaming Interface Descriptor: + bLength 30 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 4 + bmCapabilities 0x00 + Still image unsupported + wWidth 320 + wHeight 240 + dwMinBitRate 9216000 + dwMaxBitRate 9216000 + dwMaxVideoFrameBufferSize 77389 + dwDefaultFrameInterval 666666 + bFrameIntervalType 1 + dwFrameInterval( 0) 666666 + VideoStreaming Interface Descriptor: + bLength 6 + bDescriptorType 36 + bDescriptorSubtype 13 (COLORFORMAT) + bColorPrimaries 1 (BT.709,sRGB) + bTransferCharacteristics 1 (BT.709) + bMatrixCoefficients 4 (SMPTE 170M (BT.601)) + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 1 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x03bc 1x 956 bytes + bInterval 1 +*/ + +static uint8_t config_desc_bytes [] = { + 0x09, 0x02, 0x85, 0x01, 0x02, 0x01, 0x00, 0x80, 0xFA, 0x08, 0x0B, 0x00, 0x02, 0x0E, 0x03, 0x00, 0x05, 0x09, 0x04, + 0x00, 0x00, 0x01, 0x0E, 0x01, 0x00, 0x05, 0x0D, 0x24, 0x01, 0x00, 0x01, 0x4F, 0x00, 0xC0, 0xE1, 0xE4, 0x00, 0x01, + 0x01, 0x09, 0x24, 0x03, 0x04, 0x01, 0x01, 0x00, 0x03, 0x00, 0x1C, 0x24, 0x06, 0x03, 0xB6, 0x8D, 0xF1, 0x4C, 0xD0, + 0xAB, 0x5C, 0x49, 0x76, 0x98, 0xFA, 0xF9, 0x2F, 0x94, 0xA3, 0x1F, 0x18, 0x01, 0x02, 0x03, 0xFF, 0xFF, 0xFF, 0x00, + 0x12, 0x24, 0x02, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0E, 0x00, 0x00, 0x0B, + 0x24, 0x05, 0x02, 0x01, 0x00, 0x00, 0x02, 0x7F, 0x17, 0x00, 0x07, 0x05, 0x83, 0x03, 0x10, 0x00, 0x06, 0x05, 0x25, + 0x03, 0x80, 0x00, 0x09, 0x04, 0x01, 0x00, 0x00, 0x0E, 0x02, 0x00, 0x00, 0x0F, 0x24, 0x01, 0x02, 0xF7, 0x00, 0x81, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1B, 0x24, 0x04, 0x01, 0x02, 0x1D, 0xCC, 0xF6, 0x85, 0x9F, 0x0C, + 0xF5, 0x44, 0xE0, 0x9C, 0xAB, 0x98, 0x8C, 0xDD, 0xC7, 0x97, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x24, 0x05, + 0x01, 0x00, 0xE0, 0x01, 0x40, 0x01, 0x00, 0x80, 0xBB, 0x00, 0x00, 0x80, 0xBB, 0x00, 0x00, 0xB0, 0x04, 0x00, 0x80, + 0x84, 0x1E, 0x00, 0x01, 0x80, 0x84, 0x1E, 0x00, 0x1E, 0x24, 0x05, 0x02, 0x00, 0x80, 0x02, 0xE0, 0x01, 0x00, 0x00, + 0x65, 0x04, 0x00, 0x00, 0x65, 0x04, 0x00, 0x60, 0x09, 0x00, 0x2A, 0x2C, 0x0A, 0x00, 0x01, 0x2A, 0x2C, 0x0A, 0x00, + 0x0B, 0x24, 0x06, 0x02, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x24, 0x07, 0x01, 0x00, 0x80, 0x02, 0xE0, + 0x01, 0x00, 0x80, 0x32, 0x02, 0x00, 0x80, 0x32, 0x02, 0x4D, 0xB2, 0x04, 0x00, 0x2A, 0x2C, 0x0A, 0x00, 0x01, 0x2A, + 0x2C, 0x0A, 0x00, 0x26, 0x24, 0x07, 0x02, 0x00, 0xE0, 0x01, 0x40, 0x01, 0x00, 0xC0, 0x5D, 0x00, 0x00, 0x40, 0x19, + 0x01, 0x4D, 0x5A, 0x02, 0x00, 0x2A, 0x2C, 0x0A, 0x00, 0x03, 0x2A, 0x2C, 0x0A, 0x00, 0x40, 0x42, 0x0F, 0x00, 0x80, + 0x84, 0x1E, 0x00, 0x1E, 0x24, 0x07, 0x03, 0x00, 0x60, 0x01, 0x20, 0x01, 0x00, 0xA0, 0xB9, 0x00, 0x00, 0xA0, 0xB9, + 0x00, 0x4D, 0x8E, 0x01, 0x00, 0x2A, 0x2C, 0x0A, 0x00, 0x01, 0x2A, 0x2C, 0x0A, 0x00, 0x1E, 0x24, 0x07, 0x04, 0x00, + 0x40, 0x01, 0xF0, 0x00, 0x00, 0xA0, 0x8C, 0x00, 0x00, 0xA0, 0x8C, 0x00, 0x4D, 0x2E, 0x01, 0x00, 0x2A, 0x2C, 0x0A, + 0x00, 0x01, 0x2A, 0x2C, 0x0A, 0x00, 0x06, 0x24, 0x0D, 0x01, 0x01, 0x04, 0x09, 0x04, 0x01, 0x01, 0x01, 0x0E, 0x02, + 0x00, 0x00, 0x07, 0x05, 0x81, 0x05, 0xBC, 0x03, 0x01, +}; +_Static_assert(sizeof(config_desc_bytes) == 0x0185, "Configuration Descriptor size does not match"); + +#define TEST_NUM_INTF_DESC 3 //Total number of interface descriptors (including alternate) + +// --------------------- Sub-Test 1 ------------------------ + +/* +Test if we can walk the configuration descriptor to find each interface descriptor +*/ +static void test_walk_desc(const usb_config_desc_t *config_desc) +{ + int offset = 0; + const usb_standard_desc_t *cur_desc = (usb_standard_desc_t *)config_desc; + for (int i = 0; i < TEST_NUM_INTF_DESC; i++) { + cur_desc = usb_parse_next_descriptor_of_type(cur_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset); + TEST_ASSERT_NOT_EQUAL(NULL, cur_desc); + } + //Attempting to look for another interface descriptor should result in NULL + cur_desc = usb_parse_next_descriptor_of_type(cur_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset); + TEST_ASSERT_EQUAL(NULL, cur_desc); +} + +/* +Test if the count of number of alternate descriptors is correct +*/ +static void test_alt_intf_desc_count(const usb_config_desc_t *config_desc) +{ + //bInterface 0 has no alternate interfaces + TEST_ASSERT_EQUAL(0, usb_parse_interface_number_of_alternate(config_desc, 0)); + //bInterface 1 has 1 alternate interface + TEST_ASSERT_EQUAL(1, usb_parse_interface_number_of_alternate(config_desc, 1)); + //Non existent bInterface 2 should return -1 + TEST_ASSERT_EQUAL(-1, usb_parse_interface_number_of_alternate(config_desc, 2)); +} + +static void test_parse_intf_and_ep(const usb_config_desc_t *config_desc) +{ + int offset_intf = 0; + + //Get bInterfaceNumber 0 (index 0) + const usb_intf_desc_t *intf_desc = usb_parse_interface_descriptor(config_desc, 0, 0, &offset_intf); + TEST_ASSERT_NOT_EQUAL(NULL, intf_desc); + //Should only have one endpoint + int offset_ep = offset_intf; + const usb_ep_desc_t *ep_desc = usb_parse_endpoint_descriptor_by_index(intf_desc, 0, config_desc->wTotalLength, &offset_ep); + TEST_ASSERT_NOT_EQUAL(NULL, ep_desc); + TEST_ASSERT_EQUAL(0x83, ep_desc->bEndpointAddress); + offset_ep = offset_intf; + ep_desc = usb_parse_endpoint_descriptor_by_index(intf_desc, 1, config_desc->wTotalLength, &offset_ep); + TEST_ASSERT_EQUAL(NULL, ep_desc); + + //Get bInterfaceNumber 1 alternate setting 0 + offset_intf = 0; + intf_desc = usb_parse_interface_descriptor(config_desc, 1, 0, &offset_intf); + TEST_ASSERT_NOT_EQUAL(NULL, intf_desc); + //Should have no endpoints + offset_ep = offset_intf; + ep_desc = usb_parse_endpoint_descriptor_by_index(intf_desc, 0, config_desc->wTotalLength, &offset_ep); + TEST_ASSERT_EQUAL(NULL, ep_desc); + + //Get bInterfaceNumber 1 alternate setting 1 + offset_intf = 0; + intf_desc = usb_parse_interface_descriptor(config_desc, 1, 1, &offset_intf); + TEST_ASSERT_NOT_EQUAL(NULL, intf_desc); + //Should only have one endpoint + offset_ep = offset_intf; + ep_desc = usb_parse_endpoint_descriptor_by_index(intf_desc, 0, config_desc->wTotalLength, &offset_ep); + TEST_ASSERT_NOT_EQUAL(NULL, ep_desc); + TEST_ASSERT_EQUAL(0x81, ep_desc->bEndpointAddress); + offset_ep = offset_intf; + ep_desc = usb_parse_endpoint_descriptor_by_index(intf_desc, 1, config_desc->wTotalLength, &offset_ep); + TEST_ASSERT_EQUAL(NULL, ep_desc); +} + +static void test_parse_ep_by_address(const usb_config_desc_t *config_desc) +{ + int offset_ep = 0; + //Get bInterface 0 bAlternateSetting 0 EP 0x83 + const usb_ep_desc_t *ep_desc = usb_parse_endpoint_descriptor_by_address(config_desc, 0, 0, 0x83, &offset_ep); + TEST_ASSERT_NOT_EQUAL(NULL, ep_desc); + TEST_ASSERT_EQUAL(0x83, ep_desc->bEndpointAddress); + //Getting same EP address under different interface should return NULL + offset_ep = 0; + ep_desc = usb_parse_endpoint_descriptor_by_address(config_desc, 1, 0, 0x83, &offset_ep); + TEST_ASSERT_EQUAL(NULL, ep_desc); + + //Get bInterface 1 bAlternateSetting 1 EP 0x81 + offset_ep = 0; + ep_desc = usb_parse_endpoint_descriptor_by_address(config_desc, 1, 1, 0x81, &offset_ep); + TEST_ASSERT_NOT_EQUAL(NULL, ep_desc); + TEST_ASSERT_EQUAL(0x81, ep_desc->bEndpointAddress); + //Getting same EP address under different interface should return NULL + offset_ep = 0; + ep_desc = usb_parse_endpoint_descriptor_by_address(config_desc, 1, 0, 0x81, &offset_ep); + TEST_ASSERT_EQUAL(NULL, ep_desc); +} + +TEST_CASE("Test USB Helpers descriptor parsing", "[usb_host][ignore]") +{ + const usb_config_desc_t *config_desc = (const usb_config_desc_t *)config_desc_bytes; + test_walk_desc(config_desc); + test_alt_intf_desc_count(config_desc); + test_parse_intf_and_ep(config_desc); + test_parse_ep_by_address(config_desc); +} diff --git a/components/usb/test/usb_host/test_usb_host_async.c b/components/usb/test/usb_host/test_usb_host_async.c new file mode 100644 index 0000000000..4c7f792e7c --- /dev/null +++ b/components/usb/test/usb_host/test_usb_host_async.c @@ -0,0 +1,157 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "esp_intr_alloc.h" +#include "test_usb_mock_classes.h" +#include "msc_client.h" +#include "ctrl_client.h" +#include "usb/usb_host.h" +#include "unity.h" +#include "test_utils.h" + +#define TEST_MSC_NUM_SECTORS_TOTAL 10 +#define TEST_MSC_NUM_SECTORS_PER_XFER 2 +#define TEST_MSC_SCSI_TAG 0xDEADBEEF +#define TEST_CTRL_NUM_TRANSFERS 30 + +// --------------------------------------------------- Test Cases ------------------------------------------------------ + +/* +Test USB Host Asynchronous API single client + +Requires: This test requires an MSC SCSI device to be attached (see the MSC mock class) + +Purpose: + - Test that USB Host Asynchronous API works correctly with a single client + - Test that a client can be created + - Test that client can operate concurrently in a separate thread + - Test that the main thread is able to detect library events (such as USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) + +Procedure: + - Install USB Host Library + - Create a task to run an MSC client + - Start the MSC client task. It will execute a bunch of MSC SCSI sector reads + - Wait for the host library event handler to report a USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS event + - Free all devices + - Uninstall USB Host Library +*/ + +TEST_CASE("Test USB Host async (single client)", "[usb_host][ignore]") +{ + //Install USB Host + usb_host_config_t host_config = { + .intr_flags = ESP_INTR_FLAG_LEVEL1, + }; + ESP_ERROR_CHECK(usb_host_install(&host_config)); + printf("Installed\n"); + + //Create task to run client that communicates with MSC SCSI interface + msc_client_test_param_t params = { + .num_sectors_to_read = TEST_MSC_NUM_SECTORS_TOTAL, + .num_sectors_per_xfer = TEST_MSC_NUM_SECTORS_PER_XFER, + .msc_scsi_xfer_tag = TEST_MSC_SCSI_TAG, + .idVendor = MOCK_MSC_SCSI_DEV_ID_VENDOR, + .idProduct = MOCK_MSC_SCSI_DEV_ID_PRODUCT, + }; + TaskHandle_t task_hdl; + xTaskCreatePinnedToCore(msc_client_async_seq_task, "async", 4096, (void *)¶ms, 2, &task_hdl, 0); + //Start the task + xTaskNotifyGive(task_hdl); + + while (1) { + //Start handling system events + uint32_t event_flags; + usb_host_lib_handle_events(portMAX_DELAY, &event_flags); + if (event_flags & USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) { + printf("No more clients\n"); + TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_free_all()); + } + if (event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE) { + break; + } + } + + //Short delay to allow task to be cleaned up + vTaskDelay(10); + //Clean up USB Host + ESP_ERROR_CHECK(usb_host_uninstall()); +} + +/* +Test USB Host Asynchronous API with multiple clients + +Requires: This test requires an MSC SCSI device to be attached (see the MSC mock class) + +Purpose: + - Test the USB Host Asynchronous API works correctly with multiple clients + - Test that multiple clients can be created + - Test that multiple clients can operate concurrently in separate threads + - Test that the main thread is able to detect library events (such as USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) + +Procedure: + - Install USB Host Library + - Create separate tasks to run an MSC client and Ctrl Client + - MSC Client will execute a bunch of MSC SCSI sector reads + - Ctrl Client will execute a bunch of control transfers + - Wait for the host library event handler to report a USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS event + - Free all devices + - Uninstall USB Host Library +*/ +TEST_CASE("Test USB Host async (multi client)", "[usb_host][ignore]") +{ + //Install USB Host + usb_host_config_t host_config = { + .intr_flags = ESP_INTR_FLAG_LEVEL1, + }; + ESP_ERROR_CHECK(usb_host_install(&host_config)); + printf("Installed\n"); + + //Create task to run the MSC client + msc_client_test_param_t msc_params = { + .num_sectors_to_read = TEST_MSC_NUM_SECTORS_TOTAL, + .num_sectors_per_xfer = TEST_MSC_NUM_SECTORS_PER_XFER, + .msc_scsi_xfer_tag = TEST_MSC_SCSI_TAG, + .idVendor = MOCK_MSC_SCSI_DEV_ID_VENDOR, + .idProduct = MOCK_MSC_SCSI_DEV_ID_PRODUCT, + }; + TaskHandle_t msc_task_hdl; + xTaskCreatePinnedToCore(msc_client_async_seq_task, "msc", 4096, (void *)&msc_params, 2, &msc_task_hdl, 0); + + //Create task a control transfer client + ctrl_client_test_param_t ctrl_params = { + .num_ctrl_xfer_to_send = TEST_CTRL_NUM_TRANSFERS, + .idVendor = MOCK_MSC_SCSI_DEV_ID_VENDOR, + .idProduct = MOCK_MSC_SCSI_DEV_ID_PRODUCT, + }; + TaskHandle_t ctrl_task_hdl; + xTaskCreatePinnedToCore(ctrl_client_async_seq_task, "ctrl", 4096, (void *)&ctrl_params, 2, &ctrl_task_hdl, 0); + + //Start both tasks + xTaskNotifyGive(msc_task_hdl); + xTaskNotifyGive(ctrl_task_hdl); + + while (1) { + //Start handling system events + uint32_t event_flags; + usb_host_lib_handle_events(portMAX_DELAY, &event_flags); + if (event_flags & USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) { + printf("No more clients\n"); + TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_free_all()); + } + if (event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE) { + break; + } + } + + //Short delay to allow task to be cleaned up + vTaskDelay(10); + //Clean up USB Host + ESP_ERROR_CHECK(usb_host_uninstall()); +} diff --git a/components/usb/usb_helpers.c b/components/usb/usb_helpers.c new file mode 100644 index 0000000000..e657c789b4 --- /dev/null +++ b/components/usb/usb_helpers.c @@ -0,0 +1,168 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include "usb/usb_helpers.h" +#include "usb/usb_types_ch9.h" + +// ---------------------------------------- Configuration Descriptor Parsing ------------------------------------------- + +const usb_standard_desc_t *usb_parse_next_descriptor(const usb_standard_desc_t *cur_desc, uint16_t wTotalLength, int *offset) +{ + assert(cur_desc != NULL && offset != NULL); + if (*offset >= wTotalLength) { + return NULL; //We have traversed the entire configuration descriptor + } + if (*offset + cur_desc->bLength >= wTotalLength) { + return NULL; //Next descriptor is out of bounds + } + //Return the next descriptor, update offset + const usb_standard_desc_t *ret_desc = (const usb_standard_desc_t *)(((uint32_t)cur_desc) + cur_desc->bLength); + *offset += cur_desc->bLength; + return ret_desc; +} + +const usb_standard_desc_t *usb_parse_next_descriptor_of_type(const usb_standard_desc_t *cur_desc, uint16_t wTotalLength, uint8_t bDescriptorType, int *offset) +{ + assert(cur_desc != NULL && offset != NULL); + int offset_temp = *offset; //We only want to update offset if we've actually found a descriptor + //Keep stepping over descriptors until we find one of bDescriptorType or until we go out of bounds + const usb_standard_desc_t *ret_desc = usb_parse_next_descriptor(cur_desc, wTotalLength, &offset_temp); + while (ret_desc != NULL) { + if (ret_desc->bDescriptorType == bDescriptorType) { + break; + } + ret_desc = usb_parse_next_descriptor(ret_desc, wTotalLength, &offset_temp); + } + if (ret_desc != NULL) { + //We've found a descriptor. Update the offset + *offset = offset_temp; + } + return ret_desc; +} + +int usb_parse_interface_number_of_alternate(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber) +{ + assert(config_desc != NULL); + int offset = 0; + //Find the first interface descriptor of bInterfaceNumber + const usb_intf_desc_t *first_intf_desc = usb_parse_interface_descriptor(config_desc, bInterfaceNumber, 0, &offset); + if (first_intf_desc == NULL) { + return -1; //bInterfaceNumber not found + } + + int num_alt_setting = 0; + const usb_intf_desc_t *next_intf_desc = (const usb_intf_desc_t *)usb_parse_next_descriptor_of_type((const usb_standard_desc_t *)first_intf_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset); + while (next_intf_desc != NULL) { + if (next_intf_desc->bInterfaceNumber != bInterfaceNumber) { + break; + } + num_alt_setting++; + next_intf_desc = (const usb_intf_desc_t *)usb_parse_next_descriptor_of_type((const usb_standard_desc_t *)next_intf_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset); + } + return num_alt_setting; +} + +const usb_intf_desc_t *usb_parse_interface_descriptor(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber, uint8_t bAlternateSetting, int *offset) +{ + assert(config_desc != NULL); + if (bInterfaceNumber >= config_desc->bNumInterfaces) { + return NULL; //bInterfaceNumber is out of range + } + + //Walk to first interface descriptor of bInterfaceNumber + int offset_temp = 0; + const usb_intf_desc_t *next_intf_desc = (const usb_intf_desc_t *)usb_parse_next_descriptor_of_type((const usb_standard_desc_t *)config_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset_temp); + while (next_intf_desc != NULL) { + if (next_intf_desc->bInterfaceNumber == bInterfaceNumber) { + break; //We found the first interface descriptor with matching bInterfaceNumber + } + next_intf_desc = (const usb_intf_desc_t *)usb_parse_next_descriptor_of_type((const usb_standard_desc_t *)next_intf_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset_temp); + } + if (next_intf_desc == NULL) { + return NULL; //Couldn't find a interface with bInterfaceNumber + } + + //Keep walking until an interface descriptor matching bInterfaceNumber and bAlternateSetting is found + while (next_intf_desc != NULL) { + if (next_intf_desc->bInterfaceNumber == bInterfaceNumber + 1) { + //We've walked past our target bInterfaceNumber + next_intf_desc = NULL; + break; + } + if (next_intf_desc->bAlternateSetting == bAlternateSetting) { + //We've found our target interface descriptor + break; + } + //Get the next interface descriptor + next_intf_desc = (const usb_intf_desc_t *)usb_parse_next_descriptor_of_type((const usb_standard_desc_t *)next_intf_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset_temp); + } + if (next_intf_desc != NULL && offset != NULL) { + *offset = offset_temp; + } + return next_intf_desc; +} + +const usb_ep_desc_t *usb_parse_endpoint_descriptor_by_index(const usb_intf_desc_t *intf_desc, int index, uint16_t wTotalLength, int *offset) +{ + assert(intf_desc != NULL && offset != NULL); + if (index >= intf_desc->bNumEndpoints) { + return NULL; //Index is out of range + } + //Walk to the Nth endpoint descriptor we find + int offset_temp = *offset; + bool ep_found = true; + const usb_standard_desc_t *next_desc = (const usb_standard_desc_t *)intf_desc; + for (int i = 0; i <= index; i++) { + next_desc = usb_parse_next_descriptor_of_type((const usb_standard_desc_t *)next_desc, wTotalLength, USB_B_DESCRIPTOR_TYPE_ENDPOINT, &offset_temp); + if (next_desc == NULL) { + ep_found = false; + break; + } + } + if (ep_found) { + *offset = offset_temp; + return (const usb_ep_desc_t *)next_desc; + } + return NULL; +} + +const usb_ep_desc_t *usb_parse_endpoint_descriptor_by_address(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber, uint8_t bAlternateSetting, uint8_t bEndpointAddress, int *offset) +{ + assert(config_desc != NULL); + + //Find the interface descriptor + int offset_intf; + const usb_intf_desc_t *intf_desc = usb_parse_interface_descriptor(config_desc, bInterfaceNumber, bAlternateSetting, &offset_intf); + if (intf_desc == NULL) { + return NULL; + } + + //Walk endpoint descriptors until one matching bEndpointAddress is found + int offset_ep; + bool ep_found = false; + const usb_ep_desc_t *ep_desc = NULL; + for (int index = 0; index < intf_desc->bNumEndpoints; index++) { + offset_ep = offset_intf; + ep_desc = usb_parse_endpoint_descriptor_by_index(intf_desc, index, config_desc->wTotalLength, &offset_ep); + if (ep_desc == NULL) { + break; + } + if (ep_desc->bEndpointAddress == bEndpointAddress) { + ep_found = true; + break; + } + } + if (ep_found && offset != NULL) { + *offset = offset_ep; + } + return ep_desc; +} + +// ------------------------------------------------------ Misc --------------------------------------------------------- diff --git a/components/usb/usb_host.c b/components/usb/usb_host.c new file mode 100644 index 0000000000..5759fd6a41 --- /dev/null +++ b/components/usb/usb_host.c @@ -0,0 +1,1274 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* +Warning: The USB Host Library API is still a beta version and may be subject to change +*/ + +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" +#include "esp_err.h" +#include "esp_log.h" +#include "esp_heap_caps.h" +#include "hub.h" +#include "usbh.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 HOST_CHECK(cond, ret_val) ({ \ + if (!(cond)) { \ + return (ret_val); \ + } \ +}) +#define HOST_CHECK_FROM_CRIT(cond, ret_val) ({ \ + if (!(cond)) { \ + HOST_EXIT_CRITICAL(); \ + return ret_val; \ + } \ +}) + +#define PROCESS_PENDING_FLAG_USBH 0x01 +#define PROCESS_PENDING_FLAG_HUB 0x02 +#define PROCESS_PENDING_FLAG_EVENT 0x04 + +typedef struct endpoint_s endpoint_t; +typedef struct interface_s interface_t; +typedef struct client_s client_t; + +struct endpoint_s { + //Dynamic members require a critical section + struct { + TAILQ_ENTRY(endpoint_s) tailq_entry; + union { + struct { + uint32_t pending: 1; + uint32_t reserved31:31; + }; + } flags; + uint32_t num_urb_inflight; + hcd_pipe_event_t last_event; + } dynamic; + //Constant members do no change after claiming the interface thus do not require a critical section + struct { + hcd_pipe_handle_t pipe_hdl; + const usb_ep_desc_t *ep_desc; + interface_t *intf_obj; + } constant; +}; + +struct interface_s { + //Dynamic members require a critical section + struct { + TAILQ_ENTRY(interface_s) tailq_entry; + } mux_protected; + //Constant members do no change after claiming the interface thus do not require a critical section + struct { + const usb_intf_desc_t *intf_desc; + usb_device_handle_t dev_hdl; + client_t *client_obj; + endpoint_t *endpoints[0]; + } constant; +}; + +struct client_s { + //Dynamic members require a critical section + struct { + TAILQ_ENTRY(client_s) tailq_entry; + TAILQ_HEAD(tailhead_pending_ep, endpoint_s) pending_ep_tailq; + TAILQ_HEAD(tailhead_idle_ep, endpoint_s) idle_ep_tailq; + TAILQ_HEAD(tailhead_done_ctrl_xfers, urb_s) done_ctrl_xfer_tailq; + union { + struct { + uint32_t events_pending: 1; + uint32_t handling_events: 1; + uint32_t blocked: 1; + uint32_t taking_mux: 1; + uint32_t reserved4: 4; + uint32_t num_intf_claimed: 8; + uint32_t reserved16: 16; + }; + uint32_t val; + } flags; + uint32_t num_done_ctrl_xfer; + uint32_t opened_dev_addr_map; + } dynamic; + //Mux protected members must be protected by host library the mux_lock when accessed + struct { + TAILQ_HEAD(tailhead_interfaces, interface_s) interface_tailq; + } mux_protected; + //Constant members do no change after registration thus do not require a critical section + struct { + SemaphoreHandle_t event_sem; + usb_host_client_event_cb_t event_callback; + void *callback_arg; + QueueHandle_t event_msg_queue; + } constant; +}; + +typedef struct { + //Dynamic members require a critical section + struct { + //Access to these should be done in a critical section + uint32_t process_pending_flags; + uint32_t lib_event_flags; + union { + struct { + uint32_t process_pending: 1; + uint32_t handling_events: 1; + uint32_t blocked: 1; + uint32_t reserved5: 5; + uint32_t num_clients: 8; + uint32_t reserved16: 16; + }; + uint32_t val; + } flags; + } dynamic; + //Mux protected members must be protected by host library the mux_lock when accessed + struct { + TAILQ_HEAD(tailhead_clients, client_s) client_tailq; //List of all clients registered + } mux_protected; + //Constant members do no change after installation thus do not require a critical section + struct { + SemaphoreHandle_t event_sem; + SemaphoreHandle_t mux_lock; + } constant; +} host_lib_t; + +static host_lib_t *p_host_lib_obj = NULL; + +const char *USB_HOST_TAG = "USB HOST"; + +// ----------------------------------------------------- Helpers ------------------------------------------------------- + +static inline void _record_client_opened_device(client_t *client_obj, uint8_t dev_addr) +{ + assert(dev_addr != 0); + client_obj->dynamic.opened_dev_addr_map |= (1 << (dev_addr - 1)); +} + +static inline void _clear_client_opened_device(client_t *client_obj, uint8_t dev_addr) +{ + assert(dev_addr != 0); + client_obj->dynamic.opened_dev_addr_map &= ~(1 << (dev_addr - 1)); +} + +static inline bool _check_client_opened_device(client_t *client_obj, uint8_t dev_addr) +{ + assert(dev_addr != 0); + return (client_obj->dynamic.opened_dev_addr_map & (1 << (dev_addr - 1))); +} + +static bool _unblock_client(client_t *client_obj, bool in_isr) +{ + bool send_sem; + if (!client_obj->dynamic.flags.events_pending && !client_obj->dynamic.flags.handling_events) { + client_obj->dynamic.flags.events_pending = 1; + send_sem = true; + } else { + send_sem = false; + } + + HOST_EXIT_CRITICAL_SAFE(); + bool yield = false; + if (send_sem) { + if (in_isr) { + BaseType_t xTaskWoken = pdFALSE; + xSemaphoreGiveFromISR(client_obj->constant.event_sem, &xTaskWoken); + yield = (xTaskWoken == pdTRUE); + } else { + xSemaphoreGive(client_obj->constant.event_sem); + } + } + HOST_ENTER_CRITICAL_SAFE(); + + return yield; +} + +static bool _unblock_lib(bool in_isr) +{ + bool send_sem; + if (!p_host_lib_obj->dynamic.flags.process_pending && !p_host_lib_obj->dynamic.flags.handling_events) { + p_host_lib_obj->dynamic.flags.process_pending = 1; + send_sem = true; + } else { + send_sem = false; + } + + HOST_EXIT_CRITICAL_SAFE(); + bool yield = false; + if (send_sem) { + if (in_isr) { + BaseType_t xTaskWoken = pdFALSE; + xSemaphoreGiveFromISR(p_host_lib_obj->constant.event_sem, &xTaskWoken); + yield = (xTaskWoken == pdTRUE); + } else { + xSemaphoreGive(p_host_lib_obj->constant.event_sem); + } + } + HOST_ENTER_CRITICAL_SAFE(); + + return yield; +} + +static void send_event_msg_to_clients(const usb_host_client_event_msg_t *event_msg, bool send_to_all, uint8_t opened_dev_addr) +{ + //Lock client list + xSemaphoreTake(p_host_lib_obj->constant.mux_lock, portMAX_DELAY); + //Send event message to relevant or all clients + client_t *client_obj; + TAILQ_FOREACH(client_obj, &p_host_lib_obj->mux_protected.client_tailq, dynamic.tailq_entry) { + if (!send_to_all) { + //Check if client opened the device + HOST_ENTER_CRITICAL(); + bool send = _check_client_opened_device(client_obj, opened_dev_addr); + HOST_EXIT_CRITICAL(); + if (!send) { + continue; + } + } + //Send the event message + if (xQueueSend(client_obj->constant.event_msg_queue, event_msg, 0) == pdTRUE) { + HOST_ENTER_CRITICAL(); + _unblock_client(client_obj, false); + HOST_EXIT_CRITICAL(); + } else { + ESP_LOGE(USB_HOST_TAG, "Client event message queue full"); + } + } + //Unlock client list + xSemaphoreGive(p_host_lib_obj->constant.mux_lock); +} + +// ---------------------------------------------------- Callbacks ------------------------------------------------------ + +// ------------------- Library Related --------------------- + +static bool notif_callback(usb_notif_source_t source, bool in_isr, void *arg) +{ + HOST_ENTER_CRITICAL_SAFE(); + //Store notification source + switch (source) { + case USB_NOTIF_SOURCE_USBH: + p_host_lib_obj->dynamic.process_pending_flags |= PROCESS_PENDING_FLAG_USBH; + break; + case USB_NOTIF_SOURCE_HUB: + p_host_lib_obj->dynamic.process_pending_flags |= PROCESS_PENDING_FLAG_HUB; + break; + } + bool yield = _unblock_lib(in_isr); + HOST_EXIT_CRITICAL_SAFE(); + + return yield; +} + +static void ctrl_xfer_callback(usb_device_handle_t dev_hdl, urb_t *urb, void *arg) +{ + assert(urb->usb_host_client != NULL); + //Redistribute done control transfer to the clients that submitted them + client_t *client_obj = (client_t *)urb->usb_host_client; + + HOST_ENTER_CRITICAL(); + TAILQ_INSERT_TAIL(&client_obj->dynamic.done_ctrl_xfer_tailq, urb, tailq_entry); + client_obj->dynamic.num_done_ctrl_xfer++; + _unblock_client(client_obj, false); + HOST_EXIT_CRITICAL(); +} + +static void dev_event_callback(usb_device_handle_t dev_hdl, usbh_event_t usbh_event, void *arg) +{ + //Check usbh_event. The data type of event_arg depends on the type of event + switch (usbh_event) { + case USBH_EVENT_DEV_NEW: { + //Prepare a NEW_DEV client event message, the send it to all clients + uint8_t dev_addr; + ESP_ERROR_CHECK(usbh_dev_get_addr(dev_hdl, &dev_addr)); + usb_host_client_event_msg_t event_msg = { + .event = USB_HOST_CLIENT_EVENT_NEW_DEV, + .new_dev.address = dev_addr, + }; + send_event_msg_to_clients(&event_msg, true, 0); + break; + } + case USBH_EVENT_DEV_GONE: { + //Prepare event msg, send only to clients that have opened the device + uint8_t dev_addr; + ESP_ERROR_CHECK(usbh_dev_get_addr(dev_hdl, &dev_addr)); + usb_host_client_event_msg_t event_msg = { + .event = USB_HOST_CLIENT_EVENT_DEV_GONE, + .dev_gone.dev_hdl = dev_hdl, + }; + send_event_msg_to_clients(&event_msg, false, dev_addr); + break; + } + case USBH_EVENT_DEV_ALL_FREE: { + //Notify the lib handler that all devices are free + HOST_ENTER_CRITICAL(); + p_host_lib_obj->dynamic.lib_event_flags |= USB_HOST_LIB_EVENT_FLAGS_ALL_FREE; + _unblock_lib(false); + HOST_EXIT_CRITICAL(); + break; + } + default: + abort(); //Should never occur + break; + } +} + +// ------------------- Client Related ---------------------- + +static bool pipe_callback(hcd_pipe_handle_t pipe_hdl, hcd_pipe_event_t pipe_event, void *user_arg, bool in_isr) +{ + endpoint_t *ep_obj = (endpoint_t *)user_arg; + client_t *client_obj = (client_t *)ep_obj->constant.intf_obj->constant.client_obj; + + HOST_ENTER_CRITICAL_SAFE(); + //Store the event to be handled later. Note that we allow overwriting of events because more severe will halt the pipe prevent any further events. + ep_obj->dynamic.last_event = pipe_event; + //Add the EP to the client's pending list if it's not in the list already + if (!ep_obj->dynamic.flags.pending) { + ep_obj->dynamic.flags.pending = 1; + TAILQ_REMOVE(&client_obj->dynamic.idle_ep_tailq, ep_obj, dynamic.tailq_entry); + TAILQ_INSERT_TAIL(&client_obj->dynamic.pending_ep_tailq, ep_obj, dynamic.tailq_entry); + } + bool yield = _unblock_client(client_obj, in_isr); + HOST_EXIT_CRITICAL_SAFE(); + + return yield; +} + +// ------------------------------------------------ Library Functions -------------------------------------------------- + +// ----------------------- Public -------------------------- + +esp_err_t usb_host_install(const usb_host_config_t *config) +{ + HOST_CHECK(config != NULL, ESP_ERR_INVALID_ARG); + HOST_ENTER_CRITICAL(); + HOST_CHECK_FROM_CRIT(p_host_lib_obj == NULL, ESP_ERR_INVALID_STATE); + HOST_EXIT_CRITICAL(); + + esp_err_t ret; + host_lib_t *host_lib_obj = heap_caps_calloc(1, sizeof(host_lib_t), MALLOC_CAP_DEFAULT); + SemaphoreHandle_t event_sem = xSemaphoreCreateBinary(); + SemaphoreHandle_t mux_lock = xSemaphoreCreateMutex(); + if (host_lib_obj == NULL || event_sem == NULL || mux_lock == NULL) { + ret = ESP_ERR_NO_MEM; + goto alloc_err; + } + //Initialize host library object + TAILQ_INIT(&host_lib_obj->mux_protected.client_tailq); + host_lib_obj->constant.event_sem = event_sem; + host_lib_obj->constant.mux_lock = mux_lock; + //Install USBH + usbh_config_t usbh_config = { + .notif_cb = notif_callback, + .notif_cb_arg = NULL, + .ctrl_xfer_cb = ctrl_xfer_callback, + .ctrl_xfer_cb_arg = NULL, + .event_cb = dev_event_callback, + .event_cb_arg = NULL, + .hcd_config = { + .intr_flags = config->intr_flags, + }, + }; + ret = usbh_install(&usbh_config); + if (ret != ESP_OK) { + goto usbh_err; + } + //Install Hub + hub_config_t hub_config = { + .notif_cb = notif_callback, + .notif_cb_arg = NULL, + }; + ret = hub_install(&hub_config); + if (ret != ESP_OK) { + goto hub_err; + } + + //Assign host library object + HOST_ENTER_CRITICAL(); + if (p_host_lib_obj != NULL) { + HOST_EXIT_CRITICAL(); + ret = ESP_ERR_INVALID_STATE; + goto assign_err; + } + p_host_lib_obj = host_lib_obj; + HOST_EXIT_CRITICAL(); + + //Start the root hub + ESP_ERROR_CHECK(hub_root_start()); + ret = ESP_OK; + return ret; + +assign_err: + ESP_ERROR_CHECK(hub_uninstall()); +hub_err: + ESP_ERROR_CHECK(usbh_uninstall()); +usbh_err: +alloc_err: + if (mux_lock) { + vSemaphoreDelete(mux_lock); + } + if (event_sem) { + vSemaphoreDelete(event_sem); + } + heap_caps_free(host_lib_obj); + return ret; +} + +esp_err_t usb_host_uninstall(void) +{ + //All devices must have been freed at this point + HOST_ENTER_CRITICAL(); + HOST_CHECK_FROM_CRIT(p_host_lib_obj != NULL, ESP_ERR_INVALID_STATE); + HOST_CHECK_FROM_CRIT(p_host_lib_obj->dynamic.process_pending_flags == 0 && + p_host_lib_obj->dynamic.lib_event_flags == 0 && + p_host_lib_obj->dynamic.flags.val == 0, + ESP_ERR_INVALID_STATE); + HOST_EXIT_CRITICAL(); + + //Stop the root hub + ESP_ERROR_CHECK(hub_root_stop()); + + //Uninstall Hub and USBH + ESP_ERROR_CHECK(hub_uninstall()); + ESP_ERROR_CHECK(usbh_uninstall()); + + HOST_ENTER_CRITICAL(); + host_lib_t *host_lib_obj = p_host_lib_obj; + p_host_lib_obj = NULL; + HOST_EXIT_CRITICAL(); + + //Free memory objects + vSemaphoreDelete(host_lib_obj->constant.mux_lock); + vSemaphoreDelete(host_lib_obj->constant.event_sem); + heap_caps_free(host_lib_obj); + return ESP_OK; +} + +esp_err_t usb_host_lib_handle_events(TickType_t timeout_ticks, uint32_t *event_flags_ret) +{ + esp_err_t ret; + uint32_t event_flags = 0; + + HOST_ENTER_CRITICAL(); + if (!p_host_lib_obj->dynamic.flags.process_pending) { + //There is currently processing that needs to be done. Wait for some processing + HOST_EXIT_CRITICAL(); + BaseType_t sem_ret = xSemaphoreTake(p_host_lib_obj->constant.event_sem, timeout_ticks); + if (sem_ret == pdFALSE) { + ret = ESP_ERR_TIMEOUT; + goto exit; + } + HOST_ENTER_CRITICAL(); + } + //Read and clear process pending flags + uint32_t process_pending_flags = p_host_lib_obj->dynamic.process_pending_flags; + p_host_lib_obj->dynamic.process_pending_flags = 0; + p_host_lib_obj->dynamic.flags.handling_events = 1; + while (process_pending_flags) { + HOST_EXIT_CRITICAL(); + if (process_pending_flags & PROCESS_PENDING_FLAG_USBH) { + ESP_ERROR_CHECK(usbh_process()); + } + if (process_pending_flags & PROCESS_PENDING_FLAG_HUB) { + ESP_ERROR_CHECK(hub_process()); + } + HOST_ENTER_CRITICAL(); + //Read and clear process pending flags again, and loop back if there is more to process + process_pending_flags = p_host_lib_obj->dynamic.process_pending_flags; + p_host_lib_obj->dynamic.process_pending_flags = 0; + } + p_host_lib_obj->dynamic.flags.process_pending = 0; + p_host_lib_obj->dynamic.flags.handling_events = 0; + event_flags = p_host_lib_obj->dynamic.lib_event_flags; + p_host_lib_obj->dynamic.lib_event_flags = 0; + HOST_EXIT_CRITICAL(); + + ret = ESP_OK; +exit: + if (event_flags_ret != NULL) { + *event_flags_ret = event_flags; + } + return ret; +} + +// ------------------------------------------------ Client Functions --------------------------------------------------- + +// ----------------------- Private ------------------------- + +static void _handle_pending_ep(client_t *client_obj) +{ + //Handle each EP on the pending list + while (!TAILQ_EMPTY(&client_obj->dynamic.pending_ep_tailq)) { + //Get the next pending EP. + endpoint_t *ep_obj = TAILQ_FIRST(&client_obj->dynamic.pending_ep_tailq); + TAILQ_REMOVE(&client_obj->dynamic.pending_ep_tailq, ep_obj, dynamic.tailq_entry); + TAILQ_INSERT_TAIL(&client_obj->dynamic.idle_ep_tailq, ep_obj, dynamic.tailq_entry); + ep_obj->dynamic.flags.pending = 0; + hcd_pipe_event_t last_event = ep_obj->dynamic.last_event; + uint32_t num_urb_dequeued = 0; + + HOST_EXIT_CRITICAL(); + //Handle pipe event + switch (last_event) { + case HCD_PIPE_EVENT_ERROR_XFER: + case HCD_PIPE_EVENT_ERROR_URB_NOT_AVAIL: + case HCD_PIPE_EVENT_ERROR_OVERFLOW: + case HCD_PIPE_EVENT_ERROR_STALL: + //The pipe is now stalled. Flush all pending URBs + ESP_ERROR_CHECK(hcd_pipe_command(ep_obj->constant.pipe_hdl, HCD_PIPE_CMD_FLUSH)); + //All URBs in this pipe are now retired waiting to be dequeued. Fall through to dequeue them + __attribute__((fallthrough)); + case HCD_PIPE_EVENT_URB_DONE: { + //Dequeue all URBs and run their transfer callback + urb_t *urb = hcd_urb_dequeue(ep_obj->constant.pipe_hdl); + while (urb != NULL) { + urb->transfer.callback(&urb->transfer); + num_urb_dequeued++; + urb = hcd_urb_dequeue(ep_obj->constant.pipe_hdl); + } + break; + } + default: + abort(); //Should never occur + break; + } + HOST_ENTER_CRITICAL(); + + //Update the endpoint's number of URB's inflight + assert(num_urb_dequeued <= ep_obj->dynamic.num_urb_inflight); + ep_obj->dynamic.num_urb_inflight -= num_urb_dequeued; + } +} + +// ----------------------- Public -------------------------- + +esp_err_t usb_host_client_register(const usb_host_client_config_t *client_config, usb_host_client_handle_t *client_hdl_ret) +{ + HOST_CHECK(client_config != NULL && client_hdl_ret != NULL, ESP_ERR_INVALID_ARG); + HOST_CHECK(client_config->client_event_callback != NULL && client_config->max_num_event_msg > 0, ESP_ERR_INVALID_ARG); + + esp_err_t ret; + //Create client object + client_t *client_obj = heap_caps_calloc(1, sizeof(client_t), MALLOC_CAP_DEFAULT); + SemaphoreHandle_t event_sem = xSemaphoreCreateBinary(); + QueueHandle_t event_msg_queue = xQueueCreate(client_config->max_num_event_msg, sizeof(usb_host_client_event_msg_t)); + if (client_obj == NULL || event_sem == NULL || event_msg_queue == NULL) { + ret = ESP_ERR_NO_MEM; + goto alloc_err; + } + //Initialize client object + TAILQ_INIT(&client_obj->dynamic.pending_ep_tailq); + TAILQ_INIT(&client_obj->dynamic.idle_ep_tailq); + TAILQ_INIT(&client_obj->mux_protected.interface_tailq); + TAILQ_INIT(&client_obj->dynamic.done_ctrl_xfer_tailq); + client_obj->constant.event_sem = event_sem; + client_obj->constant.event_callback = client_config->client_event_callback; + client_obj->constant.callback_arg = client_config->callback_arg; + client_obj->constant.event_msg_queue = event_msg_queue; + + //Add client to the host library's list of clients + xSemaphoreTake(p_host_lib_obj->constant.mux_lock, portMAX_DELAY); + HOST_ENTER_CRITICAL(); + p_host_lib_obj->dynamic.flags.num_clients++; + HOST_EXIT_CRITICAL(); + TAILQ_INSERT_TAIL(&p_host_lib_obj->mux_protected.client_tailq, client_obj, dynamic.tailq_entry); + xSemaphoreGive(p_host_lib_obj->constant.mux_lock); + + //Write back client handle + *client_hdl_ret = (usb_host_client_handle_t)client_obj; + ret = ESP_OK; + return ret; + +alloc_err: + if (event_msg_queue) { + vQueueDelete(event_msg_queue); + } + if (event_sem) { + vSemaphoreDelete(event_sem); + } + heap_caps_free(client_obj); + return ESP_OK; +} + +esp_err_t usb_host_client_deregister(usb_host_client_handle_t client_hdl) +{ + HOST_CHECK(client_hdl != NULL, ESP_ERR_INVALID_ARG); + client_t *client_obj = (client_t *)client_hdl; + esp_err_t ret; + + //We take the mux_lock because we need to access the host library's client_tailq + xSemaphoreTake(p_host_lib_obj->constant.mux_lock, portMAX_DELAY); + HOST_ENTER_CRITICAL(); + //Check that client can currently deregistered + bool can_deregister; + if (!TAILQ_EMPTY(&client_obj->dynamic.pending_ep_tailq) || + !TAILQ_EMPTY(&client_obj->dynamic.idle_ep_tailq) || + !TAILQ_EMPTY(&client_obj->dynamic.done_ctrl_xfer_tailq) || + client_obj->dynamic.flags.handling_events || + client_obj->dynamic.flags.blocked || + client_obj->dynamic.flags.taking_mux || + client_obj->dynamic.flags.num_intf_claimed != 0 || + client_obj->dynamic.num_done_ctrl_xfer != 0 || + client_obj->dynamic.opened_dev_addr_map != 0) { + can_deregister = false; + } else { + can_deregister = true; + } + HOST_EXIT_CRITICAL(); + if (!can_deregister) { + ret = ESP_ERR_INVALID_STATE; + goto exit; + } + + //Remove client object from the library's list of clients + TAILQ_REMOVE(&p_host_lib_obj->mux_protected.client_tailq, client_obj, dynamic.tailq_entry); + HOST_ENTER_CRITICAL(); + p_host_lib_obj->dynamic.flags.num_clients--; + if (p_host_lib_obj->dynamic.flags.num_clients == 0) { + //This is the last client being deregistered. Notify the lib handler + p_host_lib_obj->dynamic.lib_event_flags |= USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS; + _unblock_lib(false); + } + HOST_EXIT_CRITICAL(); + //Free client object + vQueueDelete(client_obj->constant.event_msg_queue); + vSemaphoreDelete(client_obj->constant.event_sem); + heap_caps_free(client_obj); + ret = ESP_OK; +exit: + xSemaphoreGive(p_host_lib_obj->constant.mux_lock); + return ret; +} + +esp_err_t usb_host_client_handle_events(usb_host_client_handle_t client_hdl, TickType_t timeout_ticks) +{ + HOST_CHECK(client_hdl != NULL, ESP_ERR_INVALID_ARG); + esp_err_t ret; + client_t *client_obj = (client_t *)client_hdl; + + HOST_ENTER_CRITICAL(); + if (!client_obj->dynamic.flags.events_pending) { + //There are currently no events, wait for one to occur + client_obj->dynamic.flags.blocked = 1; + HOST_EXIT_CRITICAL(); + BaseType_t sem_ret = xSemaphoreTake(client_obj->constant.event_sem, timeout_ticks); + HOST_ENTER_CRITICAL(); + client_obj->dynamic.flags.blocked = 0; + if (sem_ret == pdFALSE) { + HOST_EXIT_CRITICAL(); + //Timed out waiting for semaphore + ret = ESP_ERR_TIMEOUT; + goto exit; + } + } + //Mark that we're processing events + client_obj->dynamic.flags.handling_events = 1; + while (client_obj->dynamic.flags.handling_events) { + //Handle pending endpoints + if (!TAILQ_EMPTY(&client_obj->dynamic.pending_ep_tailq)) { + _handle_pending_ep(client_obj); + } + //Handle any done control transfers + while (client_obj->dynamic.num_done_ctrl_xfer > 0) { + urb_t *urb = TAILQ_FIRST(&client_obj->dynamic.done_ctrl_xfer_tailq); + TAILQ_REMOVE(&client_obj->dynamic.done_ctrl_xfer_tailq, urb, tailq_entry); + client_obj->dynamic.num_done_ctrl_xfer--; + HOST_EXIT_CRITICAL(); + //Call the transfer's callback + urb->transfer.callback(&urb->transfer); + HOST_ENTER_CRITICAL(); + } + //Handle event messages + while (uxQueueMessagesWaiting(client_obj->constant.event_msg_queue) > 0) { + HOST_EXIT_CRITICAL(); + //Dequeue the event message and call the client event callback + usb_host_client_event_msg_t event_msg; + BaseType_t queue_ret = xQueueReceive(client_obj->constant.event_msg_queue, &event_msg, 0); + assert(queue_ret == pdTRUE); + client_obj->constant.event_callback(&event_msg, client_obj->constant.callback_arg); + HOST_ENTER_CRITICAL(); + } + //Check each event again to see any new events occurred + if (TAILQ_EMPTY(&client_obj->dynamic.pending_ep_tailq) && + client_obj->dynamic.num_done_ctrl_xfer == 0 && + uxQueueMessagesWaiting(client_obj->constant.event_msg_queue) == 0) { + //All pending endpoints and event messages handled + client_obj->dynamic.flags.events_pending = 0; + client_obj->dynamic.flags.handling_events = 0; + } + } + HOST_EXIT_CRITICAL(); + + ret = ESP_OK; +exit: + return ret; +} + +esp_err_t usb_host_client_unblock(usb_host_client_handle_t client_hdl) +{ + HOST_CHECK(client_hdl != NULL, ESP_ERR_INVALID_ARG); + client_t *client_obj = (client_t *)client_hdl; + + HOST_ENTER_CRITICAL(); + _unblock_client(client_obj, false); + HOST_EXIT_CRITICAL(); + + return ESP_OK; +} + +// ------------------------------------------------- Device Handling --------------------------------------------------- + +esp_err_t usb_host_device_open(usb_host_client_handle_t client_hdl, uint8_t dev_addr, usb_device_handle_t *dev_hdl_ret) +{ + HOST_CHECK(dev_addr > 0 && client_hdl != NULL && dev_hdl_ret != NULL, ESP_ERR_INVALID_ARG); + client_t *client_obj = (client_t *)client_hdl; + + esp_err_t ret; + usb_device_handle_t dev_hdl; + ret = usbh_dev_open(dev_addr, &dev_hdl); + if (ret != ESP_OK) { + goto exit; + } + + HOST_ENTER_CRITICAL(); + if (_check_client_opened_device(client_obj, dev_addr)) { + //Client has already opened the device. Close it and return an error + ret = ESP_ERR_INVALID_STATE; + HOST_EXIT_CRITICAL(); + goto already_opened; + } + //Record in client object that we have opened the device of this address + _record_client_opened_device(client_obj, dev_addr); + HOST_EXIT_CRITICAL(); + + *dev_hdl_ret = dev_hdl; + ret = ESP_OK; + return ret; + +already_opened: + ESP_ERROR_CHECK(usbh_dev_close(dev_hdl)); +exit: + return ret; +} + +esp_err_t usb_host_device_close(usb_host_client_handle_t client_hdl, usb_device_handle_t dev_hdl) +{ + HOST_CHECK(dev_hdl != NULL && client_hdl != NULL, ESP_ERR_INVALID_ARG); + client_t *client_obj = (client_t *)client_hdl; + + //We take the lock because we need to walk the interface list + xSemaphoreTake(p_host_lib_obj->constant.mux_lock, portMAX_DELAY); + esp_err_t ret; + //Check that all interfaces claimed by this client do not belong to this device + bool all_released = true; + interface_t *intf_obj; + TAILQ_FOREACH(intf_obj, &client_obj->mux_protected.interface_tailq, mux_protected.tailq_entry) { + if (intf_obj->constant.dev_hdl == dev_hdl) { + all_released = false; + break; + } + } + if (!all_released) { + ret = ESP_ERR_INVALID_STATE; + goto exit; + } + + //Check that client actually opened the device in the first place + HOST_ENTER_CRITICAL(); + uint8_t dev_addr; + ESP_ERROR_CHECK(usbh_dev_get_addr(dev_hdl, &dev_addr)); + HOST_CHECK_FROM_CRIT(_check_client_opened_device(client_obj, dev_addr), ESP_ERR_NOT_FOUND); + if (!_check_client_opened_device(client_obj, dev_addr)) { + //Client never opened this device + ret = ESP_ERR_INVALID_STATE; + HOST_EXIT_CRITICAL(); + goto exit; + } + //Proceed to clear the record of the device form the client + _clear_client_opened_device(client_obj, dev_addr); + HOST_EXIT_CRITICAL(); + + ESP_ERROR_CHECK(usbh_dev_close(dev_hdl)); + ret = ESP_OK; +exit: + xSemaphoreGive(p_host_lib_obj->constant.mux_lock); + return ret; +} + +esp_err_t usb_host_device_free_all(void) +{ + HOST_ENTER_CRITICAL(); + HOST_CHECK_FROM_CRIT(p_host_lib_obj->dynamic.flags.num_clients == 0, ESP_ERR_INVALID_STATE); //All clients must have been deregistered + HOST_EXIT_CRITICAL(); + esp_err_t ret; + ret = usbh_dev_mark_all_free(); + //Wait for USB_HOST_LIB_EVENT_FLAGS_ALL_FREE to confirm all devices free + return ret; +} + +// ------------------------------------------------- Device Requests --------------------------------------------------- + +// ------------------- Cached Requests --------------------- + +esp_err_t usb_host_device_info(usb_device_handle_t dev_hdl, usb_device_info_t *dev_info) +{ + HOST_CHECK(dev_hdl != NULL && dev_info != NULL, ESP_ERR_INVALID_ARG); + return usbh_dev_get_info(dev_hdl, dev_info); +} + +// ----------------------------------------------- Descriptor Requests ------------------------------------------------- + +// ----------------- Cached Descriptors -------------------- + +esp_err_t usb_host_get_device_descriptor(usb_device_handle_t dev_hdl, const usb_device_desc_t **device_desc) +{ + HOST_CHECK(dev_hdl != NULL && device_desc != NULL, ESP_ERR_INVALID_ARG); + return usbh_dev_get_desc(dev_hdl, device_desc); +} + +esp_err_t usb_host_get_active_config_descriptor(usb_device_handle_t dev_hdl, const usb_config_desc_t **config_desc) +{ + HOST_CHECK(dev_hdl != NULL && config_desc != NULL, ESP_ERR_INVALID_ARG); + return usbh_dev_get_config_desc(dev_hdl, config_desc); +} + +// ----------------------------------------------- Interface Functions ------------------------------------------------- + +// ----------------------- Private ------------------------- + +static esp_err_t endpoint_alloc(usb_device_handle_t dev_hdl, const usb_ep_desc_t *ep_desc, interface_t *intf_obj, endpoint_t **ep_obj_ret) +{ + endpoint_t *ep_obj = heap_caps_calloc(1, sizeof(endpoint_t), MALLOC_CAP_DEFAULT); + if (ep_obj == NULL) { + return ESP_ERR_NO_MEM; + } + esp_err_t ret; + usbh_ep_config_t ep_config = { + .ep_desc = ep_desc, + .pipe_cb = pipe_callback, + .pipe_cb_arg = (void *)ep_obj, + .context = (void *)ep_obj, + }; + hcd_pipe_handle_t pipe_hdl; + ret = usbh_ep_alloc(dev_hdl, &ep_config, &pipe_hdl); + if (ret != ESP_OK) { + goto ep_alloc_err; + } + //Initialize endpoint object + ep_obj->constant.pipe_hdl = pipe_hdl; + ep_obj->constant.ep_desc = ep_desc; + ep_obj->constant.intf_obj = intf_obj; + //Write back result + *ep_obj_ret = ep_obj; + ret = ESP_OK; + return ret; + +ep_alloc_err: + heap_caps_free(ep_obj); + return ret; +} + +static void endpoint_free(usb_device_handle_t dev_hdl, endpoint_t *ep_obj) +{ + if (ep_obj == NULL) { + return; + } + //Free the underlying endpoint + ESP_ERROR_CHECK(usbh_ep_free(dev_hdl, ep_obj->constant.ep_desc->bEndpointAddress)); + //Free the endpoint object + heap_caps_free(ep_obj); +} + +static interface_t *interface_alloc(client_t *client_obj, usb_device_handle_t dev_hdl, const usb_intf_desc_t *intf_desc) +{ + interface_t *intf_obj = heap_caps_calloc(1, sizeof(interface_t) + (sizeof(endpoint_t *) * intf_desc->bNumEndpoints), MALLOC_CAP_DEFAULT); + if (intf_obj == NULL) { + return NULL; + } + intf_obj->constant.intf_desc = intf_desc; + intf_obj->constant.client_obj = client_obj; + intf_obj->constant.dev_hdl = dev_hdl; + return intf_obj; +} + +static void interface_free(interface_t *intf_obj) +{ + if (intf_obj == NULL) { + return; + } + for (int i = 0; i < intf_obj->constant.intf_desc->bNumEndpoints; i++) { + assert(intf_obj->constant.endpoints[i] == NULL); + } + heap_caps_free(intf_obj); +} + +static esp_err_t interface_claim(client_t *client_obj, usb_device_handle_t dev_hdl, const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber, uint8_t bAlternateSetting, interface_t **intf_obj_ret) +{ + esp_err_t ret; + //We need to walk to configuration descriptor to find the correct interface descriptor, and each of its constituent endpoint descriptors + //Find the interface descriptor and allocate the interface object + int offset_intf; + const usb_intf_desc_t *intf_desc = usb_parse_interface_descriptor(config_desc, bInterfaceNumber, bAlternateSetting, &offset_intf); + if (intf_desc == NULL) { + ret = ESP_ERR_NOT_FOUND; + goto exit; + } + //Allocate interface object + interface_t *intf_obj = interface_alloc(client_obj, dev_hdl, intf_desc); + if (intf_obj == NULL) { + ret = ESP_ERR_NO_MEM; + goto exit; + } + //Find each endpoint descriptor in the interface by index, and allocate those endpoints + for (int i = 0; i < intf_desc->bNumEndpoints; i++) { + int offset_ep = offset_intf; + const usb_ep_desc_t *ep_desc = usb_parse_endpoint_descriptor_by_index(intf_desc, i, config_desc->wTotalLength, &offset_ep); + if (ep_desc == NULL) { + ret = ESP_ERR_NOT_FOUND; + goto ep_alloc_err; + } + //Allocate the endpoint + endpoint_t *ep_obj; + ret = endpoint_alloc(dev_hdl, ep_desc, intf_obj, &ep_obj); + if (ret != ESP_OK) { + goto ep_alloc_err; + } + //Store endpoint object into interface object + intf_obj->constant.endpoints[i] = ep_obj; + } + //Add interface object to client (safe because we have already taken the mutex) + TAILQ_INSERT_TAIL(&client_obj->mux_protected.interface_tailq, intf_obj, mux_protected.tailq_entry); + //Add each endpoint to the client's endpoint list + HOST_ENTER_CRITICAL(); + for (int i = 0; i < intf_obj->constant.intf_desc->bNumEndpoints; i++) { + TAILQ_INSERT_TAIL(&client_obj->dynamic.idle_ep_tailq, intf_obj->constant.endpoints[i], dynamic.tailq_entry); + } + HOST_EXIT_CRITICAL(); + //Write back result + *intf_obj_ret = intf_obj; + ret = ESP_OK; + return ret; + +ep_alloc_err: + for (int i = 0; i < intf_obj->constant.intf_desc->bNumEndpoints; i++) { + endpoint_free(dev_hdl, intf_obj->constant.endpoints[i]); + intf_obj->constant.endpoints[i] = NULL; + } + interface_free(intf_obj); +exit: + return ret; +} + +static esp_err_t interface_release(client_t *client_obj, usb_device_handle_t dev_hdl, uint8_t bInterfaceNumber) +{ + esp_err_t ret; + //Find the interface object + interface_t *intf_obj_iter; + interface_t *intf_obj = NULL; + TAILQ_FOREACH(intf_obj_iter, &client_obj->mux_protected.interface_tailq, mux_protected.tailq_entry) { + if (intf_obj_iter->constant.dev_hdl == dev_hdl && intf_obj_iter->constant.intf_desc->bInterfaceNumber == bInterfaceNumber) { + intf_obj = intf_obj_iter; + break; + } + } + if (intf_obj == NULL) { + ret = ESP_ERR_NOT_FOUND; + goto exit; + } + + //Check that all endpoints in the interface are in a state to be freed + HOST_ENTER_CRITICAL(); + bool can_free = true; + for (int i = 0; i < intf_obj->constant.intf_desc->bNumEndpoints; i++) { + endpoint_t *ep_obj = intf_obj->constant.endpoints[i]; + //Endpoint must not be on the pending list and must not have inflight URBs + if (ep_obj->dynamic.num_urb_inflight != 0 || ep_obj->dynamic.flags.pending) { + can_free = false; + break; + } + } + if (!can_free) { + HOST_EXIT_CRITICAL(); + ret = ESP_ERR_INVALID_STATE; + goto exit; + } + //Proceed to remove all endpoint objects from list + for (int i = 0; i < intf_obj->constant.intf_desc->bNumEndpoints; i++) { + TAILQ_REMOVE(&client_obj->dynamic.idle_ep_tailq, intf_obj->constant.endpoints[i], dynamic.tailq_entry); + } + HOST_EXIT_CRITICAL(); + + //Remove the interface object from the list (safe because we have already taken the mutex) + TAILQ_REMOVE(&client_obj->mux_protected.interface_tailq, intf_obj, mux_protected.tailq_entry); + + //Free each endpoint in the interface + for (int i = 0; i < intf_obj->constant.intf_desc->bNumEndpoints; i++) { + endpoint_free(dev_hdl, intf_obj->constant.endpoints[i]); + intf_obj->constant.endpoints[i] = NULL; + } + //Free the interface object itself + interface_free(intf_obj); + ret = ESP_OK; +exit: + return ret; +} + +// ----------------------- Public -------------------------- + +esp_err_t usb_host_interface_claim(usb_host_client_handle_t client_hdl, usb_device_handle_t dev_hdl, uint8_t bInterfaceNumber, uint8_t bAlternateSetting) +{ + HOST_CHECK(client_hdl != NULL && dev_hdl != NULL, ESP_ERR_INVALID_ARG); + client_t *client_obj = (client_t *)client_hdl; + + HOST_ENTER_CRITICAL(); + uint8_t dev_addr; + ESP_ERROR_CHECK(usbh_dev_get_addr(dev_hdl, &dev_addr)); + //Check if client actually opened device + HOST_CHECK_FROM_CRIT(_check_client_opened_device(client_obj, dev_addr), ESP_ERR_INVALID_STATE); + client_obj->dynamic.flags.taking_mux = 1; + HOST_EXIT_CRITICAL(); + + //Take mux lock. This protects the client being released or other clients from claiming interfaces + xSemaphoreTake(p_host_lib_obj->constant.mux_lock, portMAX_DELAY); + esp_err_t ret; + const usb_config_desc_t *config_desc; + ESP_ERROR_CHECK(usbh_dev_get_config_desc(dev_hdl, &config_desc)); + interface_t *intf_obj; + //Claim interface + ret = interface_claim(client_obj, dev_hdl, config_desc, bInterfaceNumber, bAlternateSetting, &intf_obj); + if (ret != ESP_OK) { + goto exit; + } + ret = ESP_OK; +exit: + xSemaphoreGive(p_host_lib_obj->constant.mux_lock); + + HOST_ENTER_CRITICAL(); + if (ret == ESP_OK) { + client_obj->dynamic.flags.num_intf_claimed++; + } + client_obj->dynamic.flags.taking_mux = 0; + HOST_EXIT_CRITICAL(); + return ret; +} + +esp_err_t usb_host_interface_release(usb_host_client_handle_t client_hdl, usb_device_handle_t dev_hdl, uint8_t bInterfaceNumber) +{ + HOST_CHECK(client_hdl != NULL && dev_hdl != NULL, ESP_ERR_INVALID_ARG); + client_t *client_obj = (client_t *)client_hdl; + + HOST_ENTER_CRITICAL(); + uint8_t dev_addr; + ESP_ERROR_CHECK(usbh_dev_get_addr(dev_hdl, &dev_addr)); + //Check if client actually opened device + HOST_CHECK_FROM_CRIT(_check_client_opened_device(client_obj, dev_addr), ESP_ERR_INVALID_STATE); + client_obj->dynamic.flags.taking_mux = 1; + HOST_EXIT_CRITICAL(); + + //Take mux lock. This protects the client being released or other clients from claiming interfaces + xSemaphoreTake(p_host_lib_obj->constant.mux_lock, portMAX_DELAY); + esp_err_t ret = interface_release(client_obj, dev_hdl, bInterfaceNumber); + xSemaphoreGive(p_host_lib_obj->constant.mux_lock); + + HOST_ENTER_CRITICAL(); + if (ret == ESP_OK) { + client_obj->dynamic.flags.num_intf_claimed--; + } + client_obj->dynamic.flags.taking_mux = 0; + HOST_EXIT_CRITICAL(); + + return ret; +} + +esp_err_t usb_host_endpoint_halt(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress) +{ + esp_err_t ret; + endpoint_t *ep_obj = NULL; + ret = usbh_ep_get_context(dev_hdl, bEndpointAddress, (void **)&ep_obj); + if (ret != ESP_OK) { + goto exit; + } + assert(ep_obj != NULL); + ret = hcd_pipe_command(ep_obj->constant.pipe_hdl, HCD_PIPE_CMD_HALT); +exit: + return ret; +} + +esp_err_t usb_host_endpoint_flush(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress) +{ + esp_err_t ret; + endpoint_t *ep_obj = NULL; + ret = usbh_ep_get_context(dev_hdl, bEndpointAddress, (void **)&ep_obj); + if (ret != ESP_OK) { + goto exit; + } + assert(ep_obj != NULL); + ret = hcd_pipe_command(ep_obj->constant.pipe_hdl, HCD_PIPE_CMD_FLUSH); +exit: + return ret; +} + +esp_err_t usb_host_endpoint_clear(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress) +{ + esp_err_t ret; + endpoint_t *ep_obj = NULL; + ret = usbh_ep_get_context(dev_hdl, bEndpointAddress, (void **)&ep_obj); + if (ret != ESP_OK) { + goto exit; + } + assert(ep_obj != NULL); + ret = hcd_pipe_command(ep_obj->constant.pipe_hdl, HCD_PIPE_CMD_CLEAR); +exit: + return ret; +} + +// ------------------------------------------------ Asynchronous I/O --------------------------------------------------- + +// ----------------------- Private ------------------------- + +static bool transfer_check(usb_transfer_t *transfer, usb_transfer_type_t type, int mps, bool is_in) +{ + if (transfer->callback == NULL) { + ESP_LOGE(USB_HOST_TAG, "Transfer callback is NULL"); + return false; + } + //Check that the total transfer length does not exceed data buffer size + if (transfer->num_bytes > transfer->data_buffer_size) { + ESP_LOGE(USB_HOST_TAG, "Transfer num_bytes > data_buffer_size"); + return false; + } + if (type == USB_TRANSFER_TYPE_CTRL) { + //Check that num_bytes and wLength are set correctly + usb_setup_packet_t *setup_pkt = (usb_setup_packet_t *)transfer->data_buffer; + if (transfer->num_bytes != sizeof(usb_setup_packet_t) + setup_pkt->wLength) { + ESP_LOGE(USB_HOST_TAG, "Control transfer num_bytes wLength mismatch"); + return false; + } + } else if (type == USB_TRANSFER_TYPE_ISOCHRONOUS) { + //Check that there is at least one isochronous packet descriptor + if (transfer->num_isoc_packets <= 0) { + ESP_LOGE(USB_HOST_TAG, "ISOC transfer has 0 packet descriptors"); + return false; + } + //Check that sum of all packet lengths add up to transfer length + //If IN, check that each packet length is integer multiple of MPS + int total_num_bytes = 0; + bool mod_mps_all_zero = true; + for (int i = 0; i < transfer->num_isoc_packets; i++) { + total_num_bytes += transfer->isoc_packet_desc[i].num_bytes; + if (transfer->isoc_packet_desc[i].num_bytes % mps != 0) { + mod_mps_all_zero = false; + } + } + if (transfer->num_bytes != total_num_bytes) { + ESP_LOGE(USB_HOST_TAG, "ISOC transfer num_bytes not equal to total num_bytes of all packets"); + return false; + } + if (is_in && !mod_mps_all_zero) { + ESP_LOGE(USB_HOST_TAG, "ISOC IN transfer all packets num_bytes must be integer multiple of MPS"); + return false; + } + } else { + //Check that IN transfers are integer multiple of MPS + if (is_in && (transfer->num_bytes % mps != 0)) { + ESP_LOGE(USB_HOST_TAG, "IN transfer num_bytes must be integer multiple of MPS"); + return false; + } + } + return true; +} + +// ----------------------- Public -------------------------- + +esp_err_t usb_host_transfer_alloc(size_t data_buffer_size, int num_isoc_packets, usb_transfer_t **transfer) +{ + urb_t *urb = urb_alloc(data_buffer_size, 0, num_isoc_packets); + if (urb == NULL) { + return ESP_ERR_NO_MEM; + } + *transfer = &urb->transfer; + return ESP_OK; +} + +esp_err_t usb_host_transfer_free(usb_transfer_t *transfer) +{ + HOST_CHECK(transfer != NULL, ESP_ERR_INVALID_ARG); + urb_t *urb = __containerof(transfer, urb_t, transfer); + urb_free(urb); + return ESP_OK; +} + +esp_err_t usb_host_transfer_submit(usb_transfer_t *transfer) +{ + HOST_CHECK(transfer != NULL, ESP_ERR_INVALID_ARG); + //Check that transfer and target endpoint are valid + HOST_CHECK(transfer->device_handle != NULL, ESP_ERR_INVALID_ARG); //Target device must be set + HOST_CHECK((transfer->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK) != 0, ESP_ERR_INVALID_ARG); + endpoint_t *ep_obj = NULL; + urb_t *urb_obj = __containerof(transfer, urb_t, transfer); + esp_err_t ret; + ret = usbh_ep_get_context(transfer->device_handle, transfer->bEndpointAddress, (void **)&ep_obj); + if (ret != ESP_OK) { + goto err; + } + assert(ep_obj != NULL); + HOST_CHECK(transfer_check(transfer, + USB_EP_DESC_GET_XFERTYPE(ep_obj->constant.ep_desc), + USB_EP_DESC_GET_MPS(ep_obj->constant.ep_desc), + transfer->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK), ESP_ERR_INVALID_ARG); + HOST_ENTER_CRITICAL(); + ep_obj->dynamic.num_urb_inflight++; + HOST_EXIT_CRITICAL(); + //Check if pipe is in a state to enqueue URBs + if (hcd_pipe_get_state(ep_obj->constant.pipe_hdl) != HCD_PIPE_STATE_ACTIVE) { + ret = ESP_ERR_INVALID_STATE; + goto hcd_err; + } + ret = hcd_urb_enqueue(ep_obj->constant.pipe_hdl, urb_obj); + if (ret != ESP_OK) { + goto hcd_err; + } + ret = ESP_OK; + return ret; + +hcd_err: + HOST_ENTER_CRITICAL(); + ep_obj->dynamic.num_urb_inflight--; + HOST_EXIT_CRITICAL(); +err: + return ret; +} + +esp_err_t usb_host_transfer_submit_control(usb_host_client_handle_t client_hdl, usb_transfer_t *transfer) +{ + HOST_CHECK(client_hdl != NULL && transfer != NULL, ESP_ERR_INVALID_ARG); + //Check that control transfer is valid + HOST_CHECK(transfer->device_handle != NULL, ESP_ERR_INVALID_ARG); //Target device must be set + usb_device_handle_t dev_hdl = transfer->device_handle; + bool xfer_is_in = ((usb_setup_packet_t *)transfer->data_buffer)->bmRequestType & USB_BM_REQUEST_TYPE_DIR_OUT; + usb_device_info_t dev_info; + ESP_ERROR_CHECK(usbh_dev_get_info(dev_hdl, &dev_info)); + HOST_CHECK(transfer_check(transfer, USB_TRANSFER_TYPE_CTRL, dev_info.bMaxPacketSize0, xfer_is_in), ESP_ERR_INVALID_ARG); + HOST_CHECK(transfer->bEndpointAddress == 0, ESP_ERR_INVALID_ARG); + //Save client handle into URB + urb_t *urb_obj = __containerof(transfer, urb_t, transfer); + urb_obj->usb_host_client = (void *)client_hdl; + return usbh_dev_submit_ctrl_urb(dev_hdl, urb_obj); +} diff --git a/components/usb/usb_phy.c b/components/usb/usb_phy.c new file mode 100644 index 0000000000..62fbb78f56 --- /dev/null +++ b/components/usb/usb_phy.c @@ -0,0 +1,328 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "freertos/FreeRTOS.h" +#include "esp_log.h" +#include "esp_check.h" +#include "driver/periph_ctrl.h" +#include "esp_private/usb_phy.h" +#include "soc/usb_phy_periph.h" +#include "hal/usb_phy_hal.h" +#include "hal/usb_phy_ll.h" +#include "esp_rom_gpio.h" +#include "driver/gpio.h" +#include "hal/gpio_ll.h" +#include "soc/usb_pins.h" + +static const char *USBPHY_TAG = "usb_phy"; + +#define USBPHY_NOT_INIT_ERR_STR "USB_PHY is not initialized" + +typedef struct phy_context_t phy_context_t; + +struct phy_context_t { + usb_phy_target_t target; /**< PHY target */ + usb_phy_controller_t controller; /**< PHY controller */ + usb_phy_status_t status; /**< PHY status */ + usb_otg_mode_t otg_mode; /**< USB OTG mode */ + usb_phy_speed_t otg_speed; /**< USB speed */ + usb_phy_gpio_conf_t *iopins; /**< external PHY I/O pins */ + usb_phy_hal_context_t hal_context; /**< USB_PHY hal context */ +}; + +typedef struct { + phy_context_t *internal_phy; /**< internal PHY context */ + phy_context_t *external_phy; /**< external PHY context */ + uint32_t ref_count; /**< reference count used to protect p_phy_ctrl_obj */ +} phy_ctrl_obj_t; + +/** + * @brief A pin descriptor for initialize external PHY I/O pins + */ +typedef struct { + int pin; /**< GPIO pin num */ + const int func; /**< GPIO matrix signal */ + const bool is_output; /**< input/output signal */ +} usb_iopin_dsc_t; + +static phy_ctrl_obj_t *p_phy_ctrl_obj = NULL; +static portMUX_TYPE phy_spinlock = portMUX_INITIALIZER_UNLOCKED; + +static esp_err_t phy_external_iopins_configure(usb_phy_gpio_conf_t *gpio_conf) +{ + const usb_iopin_dsc_t usb_periph_iopins[] = { + {gpio_conf->vp_io_num, usb_phy_periph_signal.extphy_vp_in, 0}, + {gpio_conf->vm_io_num, usb_phy_periph_signal.extphy_vm_in, 0}, + {gpio_conf->rcv_io_num, usb_phy_periph_signal.extphy_rcv_in, 0}, + {gpio_conf->oen_io_num, usb_phy_periph_signal.extphy_oen_out, 1}, + {gpio_conf->vpo_io_num, usb_phy_periph_signal.extphy_vpo_out, 1}, + {gpio_conf->vmo_io_num, usb_phy_periph_signal.extphy_vmo_out, 1}, + }; + + for (int i = 0; i < sizeof(usb_periph_iopins)/sizeof(usb_iopin_dsc_t); i++) { + const usb_iopin_dsc_t iopin = usb_periph_iopins[i]; + if (iopin.pin != -1) { + ESP_RETURN_ON_FALSE((iopin.is_output && GPIO_IS_VALID_OUTPUT_GPIO(iopin.pin)) || + (!iopin.is_output && GPIO_IS_VALID_GPIO(iopin.pin)), + ESP_ERR_INVALID_ARG, USBPHY_TAG, "io_num argument is invalid"); + esp_rom_gpio_pad_select_gpio(iopin.pin); + if (iopin.is_output) { + esp_rom_gpio_connect_out_signal(iopin.pin, iopin.func, false, false); + } else { + esp_rom_gpio_connect_in_signal(iopin.pin, iopin.func, false); + gpio_ll_input_enable(&GPIO, iopin.pin); + } + esp_rom_gpio_pad_unhold(iopin.pin); + } + } + return ESP_OK; +} + +esp_err_t usb_phy_otg_set_mode(usb_phy_handle_t handle, usb_otg_mode_t mode) +{ + ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, USBPHY_TAG, "handle argument is invalid"); + ESP_RETURN_ON_FALSE(mode < USB_OTG_MODE_MAX, ESP_ERR_INVALID_ARG, USBPHY_TAG, "mode argument is invalid"); + ESP_RETURN_ON_FALSE(handle->controller == USB_PHY_CTRL_OTG, ESP_FAIL, USBPHY_TAG, "phy source is not USB_OTG"); + + handle->otg_mode = mode; + if (mode == USB_OTG_MODE_HOST) { + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, USB_OTG_IDDIG_IN_IDX, false); //connected connector is A side + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, USB_SRP_BVALID_IN_IDX, false); + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_VBUSVALID_IN_IDX, false); //receiving a valid Vbus from host + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_AVALID_IN_IDX, false); //HIGH to force USB host mode + if (handle->target == USB_PHY_TARGET_INT) { + usb_phy_hal_int_load_conf_host(&(handle->hal_context)); + } + } else if (mode == USB_OTG_MODE_DEVICE) { + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_IDDIG_IN_IDX, false); //connected connector is mini-B side + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_SRP_BVALID_IN_IDX, false); //HIGH to force USB device mode + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_VBUSVALID_IN_IDX, false); //receiving a valid Vbus from device + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, USB_OTG_AVALID_IN_IDX, false); + } + + return ESP_OK; +} + +esp_err_t usb_phy_otg_dev_set_speed(usb_phy_handle_t handle, usb_phy_speed_t speed) +{ + ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, USBPHY_TAG, "handle argument is invalid"); + ESP_RETURN_ON_FALSE(speed < USB_PHY_SPEED_MAX, ESP_ERR_INVALID_ARG, USBPHY_TAG, "speed argument is invalid"); + ESP_RETURN_ON_FALSE(handle->controller == USB_PHY_CTRL_OTG, ESP_FAIL, USBPHY_TAG, "phy source is not USB_OTG"); + ESP_RETURN_ON_FALSE((handle->target == USB_PHY_TARGET_INT && handle->otg_mode == USB_OTG_MODE_DEVICE), ESP_FAIL, + USBPHY_TAG, "set speed not supported"); + + handle->otg_speed = speed; + usb_priv_speed_t hal_speed = 0; + if (speed == USB_PHY_SPEED_LOW) { + hal_speed = USB_PRIV_SPEED_LOW; + } else if (speed == USB_PHY_SPEED_FULL) { + hal_speed = USB_PRIV_SPEED_FULL; + } + usb_phy_hal_int_load_conf_dev(&(handle->hal_context), hal_speed); + return ESP_OK; +} + +esp_err_t usb_phy_action(usb_phy_handle_t handle, usb_phy_action_t action) +{ + ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, USBPHY_TAG, "handle argument is invalid"); + ESP_RETURN_ON_FALSE(action < USB_PHY_ACTION_MAX, ESP_ERR_INVALID_ARG, USBPHY_TAG, "action argument is invalid"); + ESP_RETURN_ON_FALSE((action == USB_PHY_ACTION_HOST_ALLOW_CONN && handle->controller == USB_PHY_CTRL_OTG) || + (action == USB_PHY_ACTION_HOST_FORCE_DISCONN && handle->controller == USB_PHY_CTRL_OTG), + ESP_ERR_INVALID_ARG, USBPHY_TAG, "wrong target for the action"); + + esp_err_t ret = ESP_OK; + switch (action) { + case USB_PHY_ACTION_HOST_ALLOW_CONN: + if (handle->target == USB_PHY_TARGET_INT) { + usb_phy_hal_int_mimick_disconn(&(handle->hal_context), false); + } else { + if (!handle->iopins) { + ret = ESP_FAIL; + ESP_LOGE(USBPHY_TAG, "no I/O pins provided for connection"); + break; + } + /* + Allow for connections on the external PHY by connecting the VP and VM signals to the external PHY. + */ + esp_rom_gpio_connect_in_signal(handle->iopins->vp_io_num, USB_EXTPHY_VP_IDX, false); + esp_rom_gpio_connect_in_signal(handle->iopins->vm_io_num, USB_EXTPHY_VM_IDX, false); + } + break; + + case USB_PHY_ACTION_HOST_FORCE_DISCONN: + if (handle->target == USB_PHY_TARGET_INT) { + usb_phy_hal_int_mimick_disconn(&(handle->hal_context), true); + } else { + /* + Disable connections on the external PHY by connecting the VP and VM signals to the constant LOW signal. + */ + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, USB_EXTPHY_VP_IDX, false); + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, USB_EXTPHY_VM_IDX, false); + } + break; + + default: + break; + } + + return ret; +} + +static esp_err_t usb_phy_install(void) +{ + portENTER_CRITICAL(&phy_spinlock); + if (p_phy_ctrl_obj) { + // p_phy_ctrl_obj already installed, return immediately + portEXIT_CRITICAL(&phy_spinlock); + return ESP_OK; + } + portEXIT_CRITICAL(&phy_spinlock); + + 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); + 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); + goto cleanup; + } + portEXIT_CRITICAL(&phy_spinlock); + periph_module_enable(usb_phy_periph_signal.module); + periph_module_reset(usb_phy_periph_signal.module); + return ESP_OK; + +cleanup: + free(phy_ctrl_obj); + return ret; +} + +esp_err_t usb_new_phy(const usb_phy_config_t *config, usb_phy_handle_t *handle_ret) +{ + ESP_RETURN_ON_FALSE(config, ESP_ERR_INVALID_ARG, USBPHY_TAG, "config argument is invalid"); + ESP_RETURN_ON_FALSE(config->target < USB_PHY_TARGET_MAX, ESP_ERR_INVALID_ARG, USBPHY_TAG, "specified PHY argument is invalid"); + ESP_RETURN_ON_FALSE(config->controller < USB_PHY_CTRL_MAX, ESP_ERR_INVALID_ARG, USBPHY_TAG, "specified source argument is invalid"); + + ESP_RETURN_ON_ERROR(usb_phy_install(), USBPHY_TAG, "usb_phy driver installation failed"); + esp_err_t ret = ESP_OK; + bool new_phy = false; + 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); + usb_phy_get_phy_status(config->target, &phy_context->status); + if (phy_context->status == USB_PHY_STATUS_FREE) { + new_phy = true; + p_phy_ctrl_obj->ref_count++; + if (config->target == USB_PHY_TARGET_EXT) { + p_phy_ctrl_obj->external_phy = phy_context; + } else { + p_phy_ctrl_obj->internal_phy = phy_context; + } + } + portEXIT_CRITICAL(&phy_spinlock); + ESP_GOTO_ON_FALSE(new_phy, ESP_ERR_INVALID_STATE, cleanup, USBPHY_TAG, "selected PHY is in use"); + + phy_context->target = config->target; + phy_context->controller = config->controller; + phy_context->status = USB_PHY_STATUS_IN_USE; + + usb_phy_hal_init(&(phy_context->hal_context)); + if (config->controller == USB_PHY_CTRL_OTG) { + usb_phy_hal_otg_conf(&(phy_context->hal_context), config->target == USB_PHY_TARGET_EXT); + } +#if SOC_USB_SERIAL_JTAG_SUPPORTED + else if (config->controller == USB_PHY_CTRL_SERIAL_JTAG) { + usb_phy_hal_jtag_conf(&(phy_context->hal_context), config->target == USB_PHY_TARGET_EXT); + phy_context->otg_mode = USB_OTG_MODE_DEVICE; + phy_context->otg_speed = USB_PHY_SPEED_FULL; + } +#endif + + if (config->target == USB_PHY_TARGET_INT) { + gpio_set_drive_capability(USBPHY_DM_NUM, GPIO_DRIVE_CAP_3); + gpio_set_drive_capability(USBPHY_DP_NUM, GPIO_DRIVE_CAP_3); + } + + *handle_ret = (usb_phy_handle_t) phy_context; + if (config->gpio_conf && config->target == USB_PHY_TARGET_EXT) { + phy_context->iopins = (usb_phy_gpio_conf_t *) calloc(1, sizeof(usb_phy_gpio_conf_t)); + ESP_GOTO_ON_FALSE(phy_context->iopins, ESP_ERR_NO_MEM, cleanup, USBPHY_TAG, "no mem for storing I/O pins"); + memcpy(phy_context->iopins, config->gpio_conf, sizeof(usb_phy_gpio_conf_t)); + ESP_ERROR_CHECK(phy_external_iopins_configure(phy_context->iopins)); + } + if (config->otg_mode != USB_PHY_MODE_DEFAULT) { + ESP_ERROR_CHECK(usb_phy_otg_set_mode(*handle_ret, config->otg_mode)); + } + if (config->otg_speed != USB_PHY_SPEED_UNDEFINED) { + ESP_ERROR_CHECK(usb_phy_otg_dev_set_speed(*handle_ret, config->otg_speed)); + } + return ESP_OK; + +cleanup: + free(phy_context->iopins); + free(phy_context); + if (p_phy_ctrl_obj->ref_count == 0) { + free(p_phy_ctrl_obj); + p_phy_ctrl_obj = NULL; + } + return ret; +} + +static void phy_uninstall(void) +{ + phy_ctrl_obj_t *p_phy_ctrl_obj_free = NULL; + portENTER_CRITICAL(&phy_spinlock); + if (p_phy_ctrl_obj->ref_count == 0) { + p_phy_ctrl_obj_free = p_phy_ctrl_obj; + p_phy_ctrl_obj = NULL; + // Disable USB peripheral + periph_module_disable(usb_phy_periph_signal.module); + } + portEXIT_CRITICAL(&phy_spinlock); + free(p_phy_ctrl_obj_free); +} + +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); + p_phy_ctrl_obj->ref_count--; + if (handle->target == USB_PHY_TARGET_EXT) { + p_phy_ctrl_obj->external_phy = NULL; + } else { + // Clear pullup and pulldown loads on D+ / D- + usb_phy_ll_int_load_conf(handle->hal_context.wrap_dev, false, false, false, false); + p_phy_ctrl_obj->internal_phy = NULL; + } + portEXIT_CRITICAL(&phy_spinlock); + free(handle->iopins); + free(handle); + phy_uninstall(); + return ESP_OK; +} + +esp_err_t usb_phy_get_phy_status(usb_phy_target_t target, usb_phy_status_t *status) +{ + ESP_RETURN_ON_FALSE(target < USB_PHY_TARGET_MAX, ESP_ERR_INVALID_ARG, USBPHY_TAG, "argument is invalid"); + ESP_RETURN_ON_FALSE(p_phy_ctrl_obj, ESP_ERR_INVALID_STATE, USBPHY_TAG, USBPHY_NOT_INIT_ERR_STR); + + if (target == USB_PHY_TARGET_EXT && p_phy_ctrl_obj->external_phy) { + *status = p_phy_ctrl_obj->external_phy->status; + } else if (target == USB_PHY_TARGET_INT && p_phy_ctrl_obj->internal_phy) { + *status = p_phy_ctrl_obj->internal_phy->status; + } else { + *status = USB_PHY_STATUS_FREE; + } + return ESP_OK; +} diff --git a/components/usb/usb_private.c b/components/usb/usb_private.c new file mode 100644 index 0000000000..1ab0448a6f --- /dev/null +++ b/components/usb/usb_private.c @@ -0,0 +1,38 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp_heap_caps.h" +#include "usb_private.h" +#include "usb/usb_types_ch9.h" + +urb_t *urb_alloc(size_t data_buffer_size, size_t header_size, int num_isoc_packets) +{ + urb_t *urb = heap_caps_calloc(1, sizeof(urb_t) + (sizeof(usb_isoc_packet_desc_t) * num_isoc_packets), MALLOC_CAP_DEFAULT); + uint8_t *data_buffer = heap_caps_malloc(data_buffer_size + header_size, MALLOC_CAP_DMA); + if (urb == NULL || data_buffer == NULL) { + goto err; + } + urb->usb_host_header_size = header_size; //Indicate that this URB's data_buffer has a header in front of it. + //Case as dummy transfer to write to initialize const fields + usb_transfer_dummy_t *dummy_transfer = (usb_transfer_dummy_t *)&urb->transfer; + dummy_transfer->data_buffer = (uint8_t *)(data_buffer + header_size); + dummy_transfer->data_buffer_size = data_buffer_size; + dummy_transfer->num_isoc_packets = num_isoc_packets; + return urb; +err: + heap_caps_free(urb); + heap_caps_free(data_buffer); + return NULL; +} + +void urb_free(urb_t *urb) +{ + if (urb == NULL) { + return; + } + heap_caps_free((uint8_t *)(urb->transfer.data_buffer - urb->usb_host_header_size)); + heap_caps_free(urb); +} diff --git a/components/usb/usbh.c b/components/usb/usbh.c new file mode 100644 index 0000000000..b8e8cfd784 --- /dev/null +++ b/components/usb/usbh.c @@ -0,0 +1,909 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "sdkconfig.h" +#include +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/portmacro.h" +#include "freertos/task.h" +#include "esp_err.h" +#include "esp_log.h" +#include "esp_heap_caps.h" +#include "hcd.h" +#include "usbh.h" +#include "usb/usb_helpers.h" +#include "usb/usb_types_ch9.h" + +//Device action flags. Listed in the order they should handled in. Some actions are mutually exclusive +#define DEV_FLAG_ACTION_SEND_GONE_EVENT 0x01 //Send a USB_HOST_CLIENT_EVENT_DEV_GONE event +#define DEV_FLAG_ACTION_DEFAULT_PIPE_FLUSH 0x02 //Retire all URBS in the default pipe +#define DEV_FLAG_ACTION_DEFAULT_PIPE_DEQUEUE 0x04 //Dequeue all URBs from default pipe +#define DEV_FLAG_ACTION_DEFAULT_PIPE_CLEAR 0x08 //Move the default pipe to the active state +#define DEV_FLAG_ACTION_FREE 0x10 //Free the device object +#define DEV_FLAG_ACTION_PORT_DISABLE 0x20 +#define DEV_FLAG_ACTION_SEND_NEW 0x40 //Send a new device event + +#define DEV_ENUM_TODO_FLAG_DEV_ADDR 0x01 +#define DEV_ENUM_TODO_FLAG_DEV_DESC 0x02 +#define DEV_ENUM_TODO_FLAG_CONFIG_DESC 0x04 + +#define EP_NUM_MIN 1 +#define EP_NUM_MAX 16 + +typedef struct device_s device_t; +struct device_s { + //Dynamic members require a critical section + struct { + TAILQ_ENTRY(device_s) tailq_entry; + union { + struct { + uint32_t actions: 8; + uint32_t in_pending_list: 1; + uint32_t is_gone: 1; + uint32_t waiting_close: 1; + uint32_t waiting_port_disable: 1; + uint32_t waiting_free: 1; + uint32_t reserved19: 19; + }; + uint32_t val; + } flags; + int num_ctrl_xfers_inflight; + usb_device_state_t state; + uint32_t ref_count; + usb_config_desc_t *config_desc; + hcd_pipe_handle_t ep_in[EP_NUM_MAX - 1]; //IN EP owner contexts. -1 to exclude the default endpoint + hcd_pipe_handle_t ep_out[EP_NUM_MAX - 1]; //OUT EP owner contexts. -1 to exclude the default endpoint + } dynamic; + //Constant members do no change after device allocation and enumeration thus do not require a critical section + struct { + hcd_pipe_handle_t default_pipe; + hcd_port_handle_t port_hdl; + uint8_t address; + usb_speed_t speed; + const usb_device_desc_t *desc; + uint32_t enum_todo_flags; + } constant; +}; + +typedef struct { + //Dynamic members require a critical section + struct { + TAILQ_HEAD(tailhead_devs, device_s) devs_idle_tailq; //Tailq of all enum and configured devices + TAILQ_HEAD(tailhead_devs_cb, device_s) devs_pending_tailq; //Tailq of devices that need to have their cb called + uint8_t num_device; //Number of enumerated devices + } dynamic; + //Constant members do no change after installation thus do not require a critical section + struct { + usb_notif_cb_t notif_cb; + void *notif_cb_arg; + usbh_hub_cb_t hub_cb; + void *hub_cb_arg; + usbh_event_cb_t event_cb; + void *event_cb_arg; + usbh_ctrl_xfer_cb_t ctrl_xfer_cb; + void *ctrl_xfer_cb_arg; + } constant; +} usbh_t; + +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 USBH_CHECK(cond, ret_val) ({ \ + if (!(cond)) { \ + return (ret_val); \ + } \ +}) +#define USBH_CHECK_FROM_CRIT(cond, ret_val) ({ \ + if (!(cond)) { \ + USBH_EXIT_CRITICAL(); \ + return ret_val; \ + } \ +}) + +// --------------------------------------------------- Allocation ------------------------------------------------------ + +static esp_err_t device_alloc(hcd_port_handle_t port_hdl, usb_speed_t speed, device_t **dev_obj_ret) +{ + esp_err_t ret; + device_t *dev_obj = heap_caps_calloc(1, sizeof(device_t), MALLOC_CAP_DEFAULT); + usb_device_desc_t *dev_desc = heap_caps_calloc(1, sizeof(usb_device_desc_t), MALLOC_CAP_DEFAULT); + if (dev_obj == NULL || dev_desc == NULL) { + ret = ESP_ERR_NO_MEM; + goto err; + } + //Allocate default pipe. We set the pipe callback to NULL for now + hcd_pipe_config_t pipe_config = { + .callback = NULL, + .callback_arg = NULL, + .context = (void *)dev_obj, + .ep_desc = NULL, //No endpoint descriptor means we're allocating a default pipe + .dev_speed = speed, + .dev_addr = 0, + }; + hcd_pipe_handle_t default_pipe_hdl; + ret = hcd_pipe_alloc(port_hdl, &pipe_config, &default_pipe_hdl); + if (ret != ESP_OK) { + goto err; + } + //Initialize device object + dev_obj->dynamic.state = USB_DEVICE_STATE_DEFAULT; + dev_obj->constant.default_pipe = default_pipe_hdl; + dev_obj->constant.port_hdl = port_hdl; + //Note: dev_obj->constant.address is assigned later during enumeration + dev_obj->constant.speed = speed; + dev_obj->constant.desc = dev_desc; + dev_obj->constant.enum_todo_flags = (DEV_ENUM_TODO_FLAG_DEV_ADDR | DEV_ENUM_TODO_FLAG_DEV_DESC | DEV_ENUM_TODO_FLAG_CONFIG_DESC); + *dev_obj_ret = dev_obj; + ret = ESP_OK; + return ret; + +err: + heap_caps_free(dev_desc); + heap_caps_free(dev_obj); + return ret; +} + +static void device_free(device_t *dev_obj) +{ + if (dev_obj == NULL) { + return; + } + //Configuration must be freed + assert(dev_obj->dynamic.config_desc == NULL); + ESP_ERROR_CHECK(hcd_pipe_free(dev_obj->constant.default_pipe)); + heap_caps_free((usb_device_desc_t *)dev_obj->constant.desc); + heap_caps_free(dev_obj); +} + +// -------------------------------------------------- Event Related ---------------------------------------------------- + +static bool _dev_set_actions(device_t *dev_obj, uint32_t action_flags) +{ + if (action_flags == 0) { + return false; + } + bool call_notif_cb; + //Check if device is already on the callback list + if (!dev_obj->dynamic.flags.in_pending_list) { + //Move device form idle device list to callback device list + TAILQ_REMOVE(&p_usbh_obj->dynamic.devs_idle_tailq, dev_obj, dynamic.tailq_entry); + TAILQ_INSERT_TAIL(&p_usbh_obj->dynamic.devs_pending_tailq, dev_obj, dynamic.tailq_entry); + dev_obj->dynamic.flags.actions |= action_flags; + dev_obj->dynamic.flags.in_pending_list = 1; + call_notif_cb = true; + } else { + call_notif_cb = false; + } + return call_notif_cb; +} + +static bool default_pipe_callback(hcd_pipe_handle_t pipe_hdl, hcd_pipe_event_t pipe_event, void *user_arg, bool in_isr) +{ + uint32_t action_flags; + device_t *dev_obj = (device_t *)user_arg; + switch (pipe_event) { + case HCD_PIPE_EVENT_URB_DONE: + //A control transfer completed on the default pipe. We need to dequeue it + action_flags = DEV_FLAG_ACTION_DEFAULT_PIPE_DEQUEUE; + break; + case HCD_PIPE_EVENT_ERROR_XFER: + case HCD_PIPE_EVENT_ERROR_URB_NOT_AVAIL: + case HCD_PIPE_EVENT_ERROR_OVERFLOW: + //The default pipe has encountered an error. We need to retire all URBs, dequeue them, then make the pipe active again + action_flags = DEV_FLAG_ACTION_DEFAULT_PIPE_FLUSH | + DEV_FLAG_ACTION_DEFAULT_PIPE_DEQUEUE | + DEV_FLAG_ACTION_DEFAULT_PIPE_CLEAR; + if (in_isr) { + ESP_EARLY_LOGE(USBH_TAG, "Dev %d EP 0 Error", dev_obj->constant.address); + } else { + ESP_LOGE(USBH_TAG, "Dev %d EP 0 Error", dev_obj->constant.address); + } + break; + case HCD_PIPE_EVENT_ERROR_STALL: + //The default pipe encountered a "protocol stall". We just need to dequeue URBs then make the pipe active again + action_flags = DEV_FLAG_ACTION_DEFAULT_PIPE_DEQUEUE | DEV_FLAG_ACTION_DEFAULT_PIPE_CLEAR; + if (in_isr) { + ESP_EARLY_LOGE(USBH_TAG, "Dev %d EP 0 STALL", dev_obj->constant.address); + } else { + ESP_LOGE(USBH_TAG, "Dev %d EP 0 STALL", dev_obj->constant.address); + } + break; + default: + action_flags = 0; + break; + } + + USBH_ENTER_CRITICAL_SAFE(); + bool call_notif_cb = _dev_set_actions(dev_obj, action_flags); + USBH_EXIT_CRITICAL_SAFE(); + + bool yield = false; + if (call_notif_cb) { + yield = p_usbh_obj->constant.notif_cb(USB_NOTIF_SOURCE_USBH, in_isr, p_usbh_obj->constant.notif_cb_arg); + } + return yield; +} + +static bool handle_dev_free(device_t *dev_obj) +{ + USBH_ENTER_CRITICAL(); + //Remove the device object for it's containing list + if (dev_obj->dynamic.flags.in_pending_list) { + dev_obj->dynamic.flags.in_pending_list = 0; + TAILQ_REMOVE(&p_usbh_obj->dynamic.devs_pending_tailq, dev_obj, dynamic.tailq_entry); + } else { + TAILQ_REMOVE(&p_usbh_obj->dynamic.devs_idle_tailq, dev_obj, dynamic.tailq_entry); + } + p_usbh_obj->dynamic.num_device--; + bool all_free = (p_usbh_obj->dynamic.num_device == 0); + USBH_EXIT_CRITICAL(); + + heap_caps_free(dev_obj->dynamic.config_desc); + dev_obj->dynamic.config_desc = NULL; + device_free(dev_obj); + return all_free; +} + +// ------------------------------------------------- USBH Functions ---------------------------------------------------- + +esp_err_t usbh_install(const usbh_config_t *usbh_config) +{ + USBH_CHECK(usbh_config != NULL, ESP_ERR_INVALID_ARG); + USBH_ENTER_CRITICAL(); + USBH_CHECK_FROM_CRIT(p_usbh_obj == NULL, ESP_ERR_INVALID_STATE); + USBH_EXIT_CRITICAL(); + + usbh_t *usbh_obj = heap_caps_calloc(1, sizeof(usbh_t), MALLOC_CAP_DEFAULT); + if (usbh_obj == NULL) { + return ESP_ERR_NO_MEM; + } + esp_err_t ret; + //Install HCD + ret = hcd_install(&usbh_config->hcd_config); + if (ret != ESP_OK) { + goto hcd_install_err; + } + //Initialize usbh object + TAILQ_INIT(&usbh_obj->dynamic.devs_idle_tailq); + TAILQ_INIT(&usbh_obj->dynamic.devs_pending_tailq); + usbh_obj->constant.notif_cb = usbh_config->notif_cb; + usbh_obj->constant.notif_cb_arg = usbh_config->notif_cb_arg; + usbh_obj->constant.event_cb = usbh_config->event_cb; + usbh_obj->constant.event_cb_arg = usbh_config->event_cb_arg; + usbh_obj->constant.ctrl_xfer_cb = usbh_config->ctrl_xfer_cb; + usbh_obj->constant.ctrl_xfer_cb_arg = usbh_config->ctrl_xfer_cb_arg; + + //Assign usbh object pointer + USBH_ENTER_CRITICAL(); + if (p_usbh_obj != NULL) { + USBH_EXIT_CRITICAL(); + ret = ESP_ERR_INVALID_STATE; + goto assign_err; + } + p_usbh_obj = usbh_obj; + USBH_EXIT_CRITICAL(); + + ret = ESP_OK; + return ret; + +assign_err: + ESP_ERROR_CHECK(hcd_uninstall()); +hcd_install_err: + heap_caps_free(usbh_obj); + return ret; +} + +esp_err_t usbh_uninstall(void) +{ + USBH_ENTER_CRITICAL(); + USBH_CHECK_FROM_CRIT(p_usbh_obj != NULL, ESP_ERR_INVALID_STATE); + //Check that USBH is in a state to be uninstalled + USBH_CHECK_FROM_CRIT(p_usbh_obj->dynamic.num_device == 0, ESP_ERR_INVALID_STATE); + usbh_t *usbh_obj = p_usbh_obj; + p_usbh_obj = NULL; + USBH_EXIT_CRITICAL(); + + //Uninstall HCD + ESP_ERROR_CHECK(hcd_uninstall()); + heap_caps_free(usbh_obj); + return ESP_OK; +} + +esp_err_t usbh_process(void) +{ + USBH_ENTER_CRITICAL(); + USBH_CHECK_FROM_CRIT(p_usbh_obj != NULL, ESP_ERR_INVALID_STATE); + //Keep clearing devices with events + while (!TAILQ_EMPTY(&p_usbh_obj->dynamic.devs_pending_tailq)){ + //Move the device back into the idle device list, + device_t *dev_obj = TAILQ_FIRST(&p_usbh_obj->dynamic.devs_pending_tailq); + TAILQ_REMOVE(&p_usbh_obj->dynamic.devs_pending_tailq, dev_obj, dynamic.tailq_entry); + TAILQ_INSERT_TAIL(&p_usbh_obj->dynamic.devs_idle_tailq, dev_obj, dynamic.tailq_entry); + //Clear the device's flags + uint32_t action_flags = dev_obj->dynamic.flags.actions; + dev_obj->dynamic.flags.actions = 0; + dev_obj->dynamic.flags.in_pending_list = 0; + + USBH_EXIT_CRITICAL(); + ESP_LOGD(USBH_TAG, "Processing actions 0x%x", action_flags); + //Sanity check. If the device is being freed, there must not be any other action flags set + assert(!(action_flags & DEV_FLAG_ACTION_FREE) || action_flags == DEV_FLAG_ACTION_FREE); + if (action_flags & DEV_FLAG_ACTION_SEND_GONE_EVENT) { + //Flush the default pipe. Then do an event gone + ESP_LOGE(USBH_TAG, "Device %d gone", dev_obj->constant.address); + p_usbh_obj->constant.event_cb((usb_device_handle_t)dev_obj, USBH_EVENT_DEV_GONE, p_usbh_obj->constant.event_cb_arg); + } + if (action_flags & DEV_FLAG_ACTION_DEFAULT_PIPE_FLUSH) { + ESP_ERROR_CHECK(hcd_pipe_command(dev_obj->constant.default_pipe, HCD_PIPE_CMD_HALT)); + ESP_ERROR_CHECK(hcd_pipe_command(dev_obj->constant.default_pipe, HCD_PIPE_CMD_FLUSH)); + } + if (action_flags & DEV_FLAG_ACTION_DEFAULT_PIPE_DEQUEUE) { + //Empty URBs from default pipe and trigger a control transfer callback + ESP_LOGD(USBH_TAG, "Default pipe device %d", dev_obj->constant.address); + int num_urbs = 0; + urb_t *urb = hcd_urb_dequeue(dev_obj->constant.default_pipe); + while (urb != NULL) { + num_urbs++; + p_usbh_obj->constant.ctrl_xfer_cb((usb_device_handle_t)dev_obj, urb, p_usbh_obj->constant.ctrl_xfer_cb_arg); + urb = hcd_urb_dequeue(dev_obj->constant.default_pipe); + } + USBH_ENTER_CRITICAL(); + dev_obj->dynamic.num_ctrl_xfers_inflight -= num_urbs; + USBH_EXIT_CRITICAL(); + } + if (action_flags & DEV_FLAG_ACTION_DEFAULT_PIPE_CLEAR) { + //We allow the pipe command to fail just in case the pipe becomes invalid mid command + hcd_pipe_command(dev_obj->constant.default_pipe, HCD_PIPE_CMD_CLEAR); + } + /* + Note: We make these action flags mutually exclusive in case they happen in rapid succession. They are handled + in the order of precedence + For example + - New device event is requested followed immediately by a disconnection + - Port disable requested followed immediately by a disconnection + */ + if (action_flags & DEV_FLAG_ACTION_FREE) { + ESP_LOGD(USBH_TAG, "Freeing device %d", dev_obj->constant.address); + if (handle_dev_free(dev_obj)) { + ESP_LOGD(USBH_TAG, "Device all free"); + p_usbh_obj->constant.event_cb((usb_device_handle_t)NULL, USBH_EVENT_DEV_ALL_FREE, p_usbh_obj->constant.event_cb_arg); + } + } else if (action_flags & DEV_FLAG_ACTION_PORT_DISABLE) { + //Request that the HUB disables this device's port + ESP_LOGD(USBH_TAG, "Disable device port %d", dev_obj->constant.address); + p_usbh_obj->constant.hub_cb(dev_obj->constant.port_hdl, USBH_HUB_EVENT_DISABLE_PORT, p_usbh_obj->constant.hub_cb_arg); + } else if (action_flags & DEV_FLAG_ACTION_SEND_NEW) { + ESP_LOGD(USBH_TAG, "New device %d", dev_obj->constant.address); + p_usbh_obj->constant.event_cb((usb_device_handle_t)dev_obj, USBH_EVENT_DEV_NEW, p_usbh_obj->constant.event_cb_arg); + } + USBH_ENTER_CRITICAL(); + + } + USBH_EXIT_CRITICAL(); + return ESP_OK; +} + +// ------------------------------------------------ Device Functions --------------------------------------------------- + +// --------------------- Device Pool ----------------------- + +esp_err_t usbh_dev_open(uint8_t dev_addr, usb_device_handle_t *dev_hdl) +{ + USBH_CHECK(dev_hdl != NULL, ESP_ERR_INVALID_ARG); + esp_err_t ret; + + USBH_ENTER_CRITICAL(); + //Go through the device lists to find the device with the specified address + device_t *found_dev_obj = NULL; + device_t *dev_obj; + TAILQ_FOREACH(dev_obj, &p_usbh_obj->dynamic.devs_idle_tailq, dynamic.tailq_entry) { + if (dev_obj->constant.address == dev_addr) { + found_dev_obj = dev_obj; + goto exit; + } + } + TAILQ_FOREACH(dev_obj, &p_usbh_obj->dynamic.devs_idle_tailq, dynamic.tailq_entry) { + if (dev_obj->constant.address == dev_addr) { + found_dev_obj = dev_obj; + goto exit; + } + } +exit: + if (found_dev_obj != NULL) { + //The device is not in a state to be referenced + if (dev_obj->dynamic.flags.is_gone || dev_obj->dynamic.flags.waiting_port_disable || dev_obj->dynamic.flags.waiting_free) { + ret = ESP_ERR_INVALID_STATE; + } else { + dev_obj->dynamic.ref_count++; + *dev_hdl = (usb_device_handle_t)found_dev_obj; + ret = ESP_OK; + } + } else { + ret = ESP_ERR_NOT_FOUND; + } + USBH_EXIT_CRITICAL(); + + return ret; +} + +esp_err_t usbh_dev_close(usb_device_handle_t dev_hdl) +{ + USBH_CHECK(dev_hdl != NULL, ESP_ERR_INVALID_ARG); + device_t *dev_obj = (device_t *)dev_hdl; + + USBH_ENTER_CRITICAL(); + USBH_CHECK_FROM_CRIT(dev_obj->dynamic.num_ctrl_xfers_inflight == 0, ESP_ERR_INVALID_STATE); + dev_obj->dynamic.ref_count--; + bool call_notif_cb = false; + if (dev_obj->dynamic.ref_count == 0) { + //Sanity check. This can only be set when ref count reaches 0 + assert(!dev_obj->dynamic.flags.waiting_free); + if (dev_obj->dynamic.flags.is_gone) { + //Device is already gone so it's port is already disabled. Trigger the USBH process to free the device + dev_obj->dynamic.flags.waiting_free = 1; + call_notif_cb = _dev_set_actions(dev_obj, DEV_FLAG_ACTION_FREE); + } else if (dev_obj->dynamic.flags.waiting_close) { + //Device is still connected but is no longer needed. Trigger the USBH process to request device's port be disabled + dev_obj->dynamic.flags.waiting_port_disable = 1; + call_notif_cb = _dev_set_actions(dev_obj, DEV_FLAG_ACTION_PORT_DISABLE); + } + //Else, there's nothing to do. Leave the device allocated + } + USBH_EXIT_CRITICAL(); + + if (call_notif_cb) { + p_usbh_obj->constant.notif_cb(USB_NOTIF_SOURCE_USBH, false, p_usbh_obj->constant.notif_cb_arg); + } + return ESP_OK; +} + +esp_err_t usbh_dev_mark_all_free(void) +{ + USBH_ENTER_CRITICAL(); + /* + Go through the device list and mark each device as waiting to be closed. If the device is not opened at all, we can + disable it immediately. + Note: We manually traverse the list because we need to add/remove items while traversing + */ + bool call_notif_cb = false; + for (int i = 0; i < 2; i++) { + device_t *dev_obj_cur; + device_t *dev_obj_next; + //Go through pending list first as it's more efficient + if (i == 0) { + dev_obj_cur = TAILQ_FIRST(&p_usbh_obj->dynamic.devs_pending_tailq); + } else { + dev_obj_cur = TAILQ_FIRST(&p_usbh_obj->dynamic.devs_idle_tailq); + } + while (dev_obj_cur != NULL) { + assert(!dev_obj_cur->dynamic.flags.waiting_close); //Sanity check + //Keep a copy of the next item first in case we remove the current item + dev_obj_next = TAILQ_NEXT(dev_obj_cur, dynamic.tailq_entry); + if (dev_obj_cur->dynamic.ref_count == 0 && !dev_obj_cur->dynamic.flags.is_gone) { + //Device is not opened as is not gone, so we can disable it now + dev_obj_cur->dynamic.flags.waiting_port_disable = 1; + call_notif_cb |= _dev_set_actions(dev_obj_cur, DEV_FLAG_ACTION_PORT_DISABLE); + } else { + //Device is still opened. Just mark it as waiting to be closed + dev_obj_cur->dynamic.flags.waiting_close = 1; + } + dev_obj_cur = dev_obj_next; + } + } + USBH_EXIT_CRITICAL(); + + if (call_notif_cb) { + p_usbh_obj->constant.notif_cb(USB_NOTIF_SOURCE_USBH, false, p_usbh_obj->constant.notif_cb_arg); + } + return ESP_OK; +} + +// ------------------- Single Device ---------------------- + +esp_err_t usbh_dev_get_addr(usb_device_handle_t dev_hdl, uint8_t *dev_addr) +{ + USBH_CHECK(dev_hdl != NULL && dev_addr != NULL, ESP_ERR_INVALID_ARG); + device_t *dev_obj = (device_t *)dev_hdl; + + USBH_ENTER_CRITICAL(); + USBH_CHECK_FROM_CRIT(dev_obj->constant.address > 0, ESP_ERR_INVALID_STATE); + *dev_addr = dev_obj->constant.address; + USBH_EXIT_CRITICAL(); + + return ESP_OK; +} + +esp_err_t usbh_dev_get_info(usb_device_handle_t dev_hdl, usb_device_info_t *dev_info) +{ + USBH_CHECK(dev_hdl != NULL && dev_info != NULL, ESP_ERR_INVALID_ARG); + device_t *dev_obj = (device_t *)dev_hdl; + + USBH_ENTER_CRITICAL(); + USBH_CHECK_FROM_CRIT(dev_obj->dynamic.state == USB_DEVICE_STATE_CONFIGURED || dev_obj->dynamic.state == USB_DEVICE_STATE_NOT_ATTACHED, ESP_ERR_INVALID_STATE); + dev_info->speed = dev_obj->constant.speed; + dev_info->dev_addr = dev_obj->constant.address; + dev_info->bMaxPacketSize0 = dev_obj->constant.desc->bMaxPacketSize0; + if (dev_obj->dynamic.config_desc == NULL) { + dev_info->bConfigurationValue = 0; + } else { + dev_info->bConfigurationValue = dev_obj->dynamic.config_desc->bConfigurationValue; + } + USBH_EXIT_CRITICAL(); + + return ESP_OK; +} + +esp_err_t usbh_dev_get_desc(usb_device_handle_t dev_hdl, const usb_device_desc_t **dev_desc_ret) +{ + USBH_CHECK(dev_hdl != NULL && dev_desc_ret != NULL, ESP_ERR_INVALID_ARG); + device_t *dev_obj = (device_t *)dev_hdl; + + USBH_ENTER_CRITICAL(); + USBH_CHECK_FROM_CRIT(dev_obj->dynamic.state == USB_DEVICE_STATE_CONFIGURED, ESP_ERR_INVALID_STATE); + USBH_EXIT_CRITICAL(); + + *dev_desc_ret = dev_obj->constant.desc; + return ESP_OK; +} + +esp_err_t usbh_dev_get_config_desc(usb_device_handle_t dev_hdl, const usb_config_desc_t **config_desc_ret) +{ + USBH_CHECK(dev_hdl != NULL && config_desc_ret != NULL, ESP_ERR_INVALID_ARG); + device_t *dev_obj = (device_t *)dev_hdl; + + USBH_ENTER_CRITICAL(); + USBH_CHECK_FROM_CRIT(dev_obj->dynamic.state == USB_DEVICE_STATE_CONFIGURED, ESP_ERR_INVALID_STATE); + *config_desc_ret = dev_obj->dynamic.config_desc; + USBH_EXIT_CRITICAL(); + + return ESP_OK; +} + +esp_err_t usbh_dev_submit_ctrl_urb(usb_device_handle_t dev_hdl, urb_t *urb) +{ + USBH_CHECK(dev_hdl != NULL && urb != NULL, ESP_ERR_INVALID_ARG); + device_t *dev_obj = (device_t *)dev_hdl; + + USBH_ENTER_CRITICAL(); + USBH_CHECK_FROM_CRIT(dev_obj->dynamic.state == USB_DEVICE_STATE_CONFIGURED, ESP_ERR_INVALID_STATE); + //Increment the control transfer count first + dev_obj->dynamic.num_ctrl_xfers_inflight++; + USBH_EXIT_CRITICAL(); + + esp_err_t ret; + if (hcd_pipe_get_state(dev_obj->constant.default_pipe) != HCD_PIPE_STATE_ACTIVE) { + ret = ESP_ERR_INVALID_STATE; + goto hcd_err; + } + ret = hcd_urb_enqueue(dev_obj->constant.default_pipe, urb); + if (ret != ESP_OK) { + goto hcd_err; + } + ret = ESP_OK; + return ret; + +hcd_err: + USBH_ENTER_CRITICAL(); + dev_obj->dynamic.num_ctrl_xfers_inflight--; + USBH_EXIT_CRITICAL(); + return ret; +} + +// ----------------------------------------------- Interface Functions ------------------------------------------------- + +esp_err_t usbh_ep_alloc(usb_device_handle_t dev_hdl, usbh_ep_config_t *ep_config, hcd_pipe_handle_t *pipe_hdl_ret) +{ + USBH_CHECK(dev_hdl != NULL && ep_config != NULL && pipe_hdl_ret != NULL, ESP_ERR_INVALID_ARG); + device_t *dev_obj = (device_t *)dev_hdl; + + USBH_ENTER_CRITICAL(); + USBH_CHECK_FROM_CRIT(dev_obj->dynamic.state == USB_DEVICE_STATE_CONFIGURED, ESP_ERR_INVALID_STATE); + dev_obj->dynamic.ref_count++; //Increase the ref_count to keep the device alive while allocating the endpoint + USBH_EXIT_CRITICAL(); + + esp_err_t ret; + //Allocate HCD pipe + hcd_pipe_config_t pipe_config = { + .callback = ep_config->pipe_cb, + .callback_arg = ep_config->pipe_cb_arg, + .context = ep_config->context, + .ep_desc = ep_config->ep_desc, + .dev_speed = dev_obj->constant.speed, + .dev_addr = dev_obj->constant.address, + }; + hcd_pipe_handle_t pipe_hdl; + ret = hcd_pipe_alloc(dev_obj->constant.port_hdl, &pipe_config, &pipe_hdl); + if (ret != ESP_OK) { + goto pipe_alloc_err; + } + + USBH_ENTER_CRITICAL(); + //Check that endpoint has not be allocated yet + bool is_in = ep_config->ep_desc->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK; + uint8_t addr = ep_config->ep_desc->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK; + //Assign the pipe handle + bool assigned = false; + if (is_in && dev_obj->dynamic.ep_in[addr - 1] == NULL) { //Is an IN EP + dev_obj->dynamic.ep_in[addr - 1] = pipe_hdl; + assigned = true; + } else { + dev_obj->dynamic.ep_out[addr - 1] = pipe_hdl; + assigned = true; + } + dev_obj->dynamic.ref_count--; //Restore ref_count + USBH_EXIT_CRITICAL(); + + if (!assigned) { + ret = ESP_ERR_INVALID_STATE; + goto assign_err; + } + //Write back output + *pipe_hdl_ret = pipe_hdl; + ret = ESP_OK; + return ret; + +assign_err: + ESP_ERROR_CHECK(hcd_pipe_free(pipe_hdl)); +pipe_alloc_err: + return ret; +} + +esp_err_t usbh_ep_free(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress) +{ + USBH_CHECK(dev_hdl != NULL, ESP_ERR_INVALID_ARG); + device_t *dev_obj = (device_t *)dev_hdl; + + USBH_ENTER_CRITICAL(); + //Un-assign the pipe handle from the endpoint + bool is_in = bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK; + uint8_t addr = bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK; + hcd_pipe_handle_t pipe_hdl; + if (is_in) { + USBH_CHECK_FROM_CRIT(dev_obj->dynamic.ep_in[addr - 1] != NULL, ESP_ERR_INVALID_STATE); + pipe_hdl = dev_obj->dynamic.ep_in[addr - 1]; + dev_obj->dynamic.ep_in[addr - 1] = NULL; + } else { + USBH_CHECK_FROM_CRIT(dev_obj->dynamic.ep_out[addr - 1] != NULL, ESP_ERR_INVALID_STATE); + pipe_hdl = dev_obj->dynamic.ep_out[addr - 1]; + dev_obj->dynamic.ep_out[addr - 1] = NULL; + } + USBH_EXIT_CRITICAL(); + + ESP_ERROR_CHECK(hcd_pipe_free(pipe_hdl)); + return ESP_OK; +} + +esp_err_t usbh_ep_get_context(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress, void **context_ret) +{ + bool is_in = bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK; + uint8_t addr = bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK; + USBH_CHECK(dev_hdl != NULL && + addr >= EP_NUM_MIN && //Control endpoints are owned by the USBH + addr <= EP_NUM_MAX && + context_ret != NULL, + ESP_ERR_INVALID_ARG); + device_t *dev_obj = (device_t *)dev_hdl; + + USBH_ENTER_CRITICAL(); + //Get the endpoint's corresponding pipe + hcd_pipe_handle_t pipe_hdl; + if (is_in) { + pipe_hdl = dev_obj->dynamic.ep_in[addr - 1]; + } else { + pipe_hdl = dev_obj->dynamic.ep_out[addr - 1]; + } + esp_err_t ret; + if (pipe_hdl == NULL) { + USBH_EXIT_CRITICAL(); + ret = ESP_ERR_NOT_FOUND; + goto exit; + } + //Return the context of the pipe + void *context = hcd_pipe_get_context(pipe_hdl); + *context_ret = context; + USBH_EXIT_CRITICAL(); + + ret = ESP_OK; +exit: + return ret; +} + +// -------------------------------------------------- Hub Functions ---------------------------------------------------- + +// ------------------- Device Related ---------------------- + +esp_err_t usbh_hub_is_installed(usbh_hub_cb_t hub_callback, void *callback_arg) +{ + USBH_CHECK(hub_callback != NULL, ESP_ERR_INVALID_ARG); + + USBH_ENTER_CRITICAL(); + //Check that USBH is already installed + USBH_CHECK_FROM_CRIT(p_usbh_obj != NULL, ESP_ERR_INVALID_STATE); + //Check that Hub has not be installed yet + USBH_CHECK_FROM_CRIT(p_usbh_obj->constant.hub_cb == NULL, ESP_ERR_INVALID_STATE); + p_usbh_obj->constant.hub_cb = hub_callback; + p_usbh_obj->constant.hub_cb_arg = callback_arg; + USBH_EXIT_CRITICAL(); + + return ESP_OK; +} + +esp_err_t usbh_hub_add_dev(hcd_port_handle_t port_hdl, usb_speed_t dev_speed, usb_device_handle_t *new_dev_hdl, hcd_pipe_handle_t *default_pipe_hdl) +{ + //Note: Parent device handle can be NULL if it's connected to the root hub + USBH_CHECK(new_dev_hdl != NULL, ESP_ERR_INVALID_ARG); + esp_err_t ret; + device_t *dev_obj; + ret = device_alloc(port_hdl, dev_speed, &dev_obj); + if (ret != ESP_OK) { + return ret; + } + //Write-back device handle + *new_dev_hdl = (usb_device_handle_t)dev_obj; + *default_pipe_hdl = dev_obj->constant.default_pipe; + ret = ESP_OK; + return ret; +} + +esp_err_t usbh_hub_mark_dev_gone(usb_device_handle_t dev_hdl) +{ + USBH_CHECK(dev_hdl != NULL, ESP_ERR_INVALID_ARG); + device_t *dev_obj = (device_t *)dev_hdl; + + USBH_ENTER_CRITICAL(); + dev_obj->dynamic.flags.is_gone = 1; + bool call_notif_cb; + //Check if the device can be freed now + if (dev_obj->dynamic.ref_count == 0) { + dev_obj->dynamic.flags.waiting_free = 1; + call_notif_cb = _dev_set_actions(dev_obj, DEV_FLAG_ACTION_FREE); + } else { + call_notif_cb = _dev_set_actions(dev_obj, DEV_FLAG_ACTION_SEND_GONE_EVENT | + DEV_FLAG_ACTION_DEFAULT_PIPE_FLUSH | + DEV_FLAG_ACTION_DEFAULT_PIPE_DEQUEUE); + } + USBH_EXIT_CRITICAL(); + + if (call_notif_cb) { + p_usbh_obj->constant.notif_cb(USB_NOTIF_SOURCE_USBH, false, p_usbh_obj->constant.notif_cb_arg); + } + return ESP_OK; +} + +esp_err_t usbh_hub_dev_port_disabled(usb_device_handle_t dev_hdl) +{ + USBH_CHECK(dev_hdl != NULL, ESP_ERR_INVALID_ARG); + device_t *dev_obj = (device_t *)dev_hdl; + + USBH_ENTER_CRITICAL(); + assert(dev_obj->dynamic.ref_count == 0); //At this stage, the device should have been closed by all users + dev_obj->dynamic.flags.waiting_free = 1; + bool call_notif_cb = _dev_set_actions(dev_obj, DEV_FLAG_ACTION_FREE); + USBH_EXIT_CRITICAL(); + + if (call_notif_cb) { + ESP_LOGD(USBH_TAG, "Notif free"); + p_usbh_obj->constant.notif_cb(USB_NOTIF_SOURCE_USBH, false, p_usbh_obj->constant.notif_cb_arg); + } + return ESP_OK; +} + +// ----------------- Enumeration Related ------------------- + +esp_err_t usbh_hub_enum_fill_dev_addr(usb_device_handle_t dev_hdl, uint8_t dev_addr) +{ + USBH_CHECK(dev_hdl != NULL, ESP_ERR_INVALID_ARG); + device_t *dev_obj = (device_t *)dev_hdl; + + USBH_ENTER_CRITICAL(); + USBH_CHECK_FROM_CRIT(dev_obj->constant.enum_todo_flags & DEV_ENUM_TODO_FLAG_DEV_ADDR, ESP_ERR_INVALID_STATE); + dev_obj->dynamic.state = USB_DEVICE_STATE_ADDRESS; + USBH_EXIT_CRITICAL(); + + //We can modify the info members outside the critical section + dev_obj->constant.enum_todo_flags &= ~DEV_ENUM_TODO_FLAG_DEV_ADDR; + dev_obj->constant.address = dev_addr; + return ESP_OK; +} + +esp_err_t usbh_hub_enum_fill_dev_desc(usb_device_handle_t dev_hdl, const usb_device_desc_t *device_desc) +{ + USBH_CHECK(dev_hdl != NULL && device_desc != NULL, ESP_ERR_INVALID_ARG); + device_t *dev_obj = (device_t *)dev_hdl; + //We can modify the info members outside the critical section + USBH_CHECK(dev_obj->constant.enum_todo_flags & DEV_ENUM_TODO_FLAG_DEV_DESC, ESP_ERR_INVALID_STATE); + dev_obj->constant.enum_todo_flags &= ~DEV_ENUM_TODO_FLAG_DEV_DESC; + memcpy((usb_device_desc_t *)dev_obj->constant.desc, device_desc, sizeof(usb_device_desc_t)); + return ESP_OK; +} + +esp_err_t usbh_hub_enum_fill_config_desc(usb_device_handle_t dev_hdl, const usb_config_desc_t *config_desc_full) +{ + USBH_CHECK(dev_hdl != NULL && config_desc_full != NULL, ESP_ERR_INVALID_ARG); + device_t *dev_obj = (device_t *)dev_hdl; + esp_err_t ret; + //Allocate memory to store the configuration descriptor + usb_config_desc_t *config_desc = heap_caps_malloc(config_desc_full->wTotalLength, MALLOC_CAP_DEFAULT); //Buffer to copy over full configuration descriptor (wTotalLength) + if (config_desc == NULL) { + ret = ESP_ERR_NO_MEM; + goto err; + } + //Copy the configuration descriptor + memcpy(config_desc, config_desc_full, config_desc_full->wTotalLength); + //Assign the config object to the device object + if (!(dev_obj->constant.enum_todo_flags & DEV_ENUM_TODO_FLAG_CONFIG_DESC)) { + ret = ESP_ERR_INVALID_STATE; + goto assign_err; + } + + USBH_ENTER_CRITICAL(); + assert(dev_obj->dynamic.config_desc == NULL); + dev_obj->dynamic.config_desc = config_desc; + USBH_EXIT_CRITICAL(); + + //We can modify the info members outside the critical section + dev_obj->constant.enum_todo_flags &= ~DEV_ENUM_TODO_FLAG_CONFIG_DESC; + ret = ESP_OK; + return ret; + +assign_err: + heap_caps_free(config_desc); +err: + return ret; +} + +esp_err_t usbh_hub_enum_done(usb_device_handle_t dev_hdl) +{ + USBH_CHECK(dev_hdl != NULL, ESP_ERR_INVALID_ARG); + device_t *dev_obj = (device_t *)dev_hdl; + USBH_CHECK(dev_obj->constant.enum_todo_flags == 0, ESP_ERR_INVALID_STATE); //All enumeration stages to be done + + USBH_ENTER_CRITICAL(); + dev_obj->dynamic.state = USB_DEVICE_STATE_CONFIGURED; + //Add the device to list of devices, then trigger a device event + TAILQ_INSERT_TAIL(&p_usbh_obj->dynamic.devs_idle_tailq, dev_obj, dynamic.tailq_entry); //Add it to the idle device list first + p_usbh_obj->dynamic.num_device++; + bool call_notif_cb = _dev_set_actions(dev_obj, DEV_FLAG_ACTION_SEND_NEW); + USBH_EXIT_CRITICAL(); + + //Update the default pipe callback + ESP_ERROR_CHECK(hcd_pipe_update_callback(dev_obj->constant.default_pipe, default_pipe_callback, (void *)dev_obj)); + //Call the notification callback + if (call_notif_cb) { + p_usbh_obj->constant.notif_cb(USB_NOTIF_SOURCE_USBH, false, p_usbh_obj->constant.notif_cb_arg); + } + return ESP_OK; +} + +esp_err_t usbh_hub_enum_failed(usb_device_handle_t dev_hdl) +{ + USBH_CHECK(dev_hdl != NULL, ESP_ERR_INVALID_ARG); + device_t *dev_obj = (device_t *)dev_hdl; + + USBH_ENTER_CRITICAL(); + usb_config_desc_t *config_desc = dev_obj->dynamic.config_desc; + dev_obj->dynamic.config_desc = NULL; + USBH_EXIT_CRITICAL(); + + if (config_desc) { + heap_caps_free(config_desc); + } + device_free(dev_obj); + return ESP_OK; +} diff --git a/components/vfs/Kconfig b/components/vfs/Kconfig index db0fede600..6b914d8ba3 100644 --- a/components/vfs/Kconfig +++ b/components/vfs/Kconfig @@ -14,6 +14,11 @@ menu "Virtual file system" Disabling this option can save memory when the support for these functions is not required. + Note that the following functions can still be used with socket file descriptors + when this option is disabled: + + close, read, write, ioctl, fcntl. + config VFS_SUPPORT_DIR bool "Provide directory related functions" default y diff --git a/components/vfs/README.rst b/components/vfs/README.rst deleted file mode 100644 index 4765f14433..0000000000 --- a/components/vfs/README.rst +++ /dev/null @@ -1,248 +0,0 @@ -Virtual filesystem component -============================ - -:link_to_translation:`zh_CN:[中文]` - -Overview --------- - -Virtual filesystem (VFS) component provides a unified interface for drivers which can perform operations on file-like objects. These can be real filesystems (FAT, SPIFFS, etc.) or device drivers which provide a file-like interface. - -This component allows C library functions, such as fopen and fprintf, to work with FS drivers. At a high level, each FS driver is associated with some path prefix. When one of C library functions needs to open a file, the VFS component searches for the FS driver associated with the file path and forwards the call to that driver. VFS also forwards read, write, and other calls for the given file to the same FS driver. - -For example, one can register a FAT filesystem driver with the ``/fat`` prefix and call ``fopen("/fat/file.txt", "w")``. The VFS component will then call the function ``open`` of the FAT driver and pass the argument ``/file.txt`` to it together with appropriate mode flags. All subsequent calls to C library functions for the returned ``FILE*`` stream will also be forwarded to the FAT driver. - - -FS registration ---------------- - -To register an FS driver, an application needs to define an instance of the :cpp:type:`esp_vfs_t` structure and populate it with function pointers to FS APIs: - -.. highlight:: c - -:: - - esp_vfs_t myfs = { - .flags = ESP_VFS_FLAG_DEFAULT, - .write = &myfs_write, - .open = &myfs_open, - .fstat = &myfs_fstat, - .close = &myfs_close, - .read = &myfs_read, - }; - - ESP_ERROR_CHECK(esp_vfs_register("/data", &myfs, NULL)); - -Depending on the way how the FS driver declares its API functions, either ``read``, ``write``, etc., or ``read_p``, ``write_p``, etc., should be used. - -Case 1: API functions are declared without an extra context pointer (the FS driver is a singleton):: - - ssize_t myfs_write(int fd, const void * data, size_t size); - - // In definition of esp_vfs_t: - .flags = ESP_VFS_FLAG_DEFAULT, - .write = &myfs_write, - // ... other members initialized - - // When registering FS, context pointer (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):: - - ssize_t myfs_write(myfs_t* fs, int fd, const void * data, size_t size); - - // In definition of 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_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)); - -Synchronous input/output multiplexing -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Synchronous input/output multiplexing by :cpp:func:`select` is supported in the VFS component. The implementation -works in the following way. - -1. :cpp:func:`select` is called with file descriptors which could belong to various VFS drivers. -2. The file descriptors are divided into groups each belonging to one VFS driver. -3. The file descriptors belonging to non-socket VFS drivers are handed over to the given VFS drivers by :cpp:func:`start_select` - described later on this page. This function represents the driver-specific implementation of :cpp:func:`select` for - the given driver. This should be a non-blocking call which means the function should immediately return after setting up - the environment for checking events related to the given file descriptors. -4. The file descriptors belonging to the socket VFS driver are handed over to the socket driver by - :cpp:func:`socket_select` described later on this page. This is a blocking call which means that it will return only - if there is an event related to socket file descriptors or a non-socket driver signals :cpp:func:`socket_select` - to exit. -5. Results are collected from each VFS driver and all drivers are stopped by deinitiazation - of the environment for checking events. -6. The :cpp:func:`select` call ends and returns the appropriate results. - -Non-socket VFS drivers -"""""""""""""""""""""" - -If you want to use :cpp:func:`select` with a file descriptor belonging to a non-socket VFS driver -then you need to register the driver with functions :cpp:func:`start_select` and -:cpp:func:`end_select` similarly to the following example: - -.. highlight:: c - -:: - - // In definition of esp_vfs_t: - .start_select = &uart_start_select, - .end_select = &uart_end_select, - // ... other members initialized - -:cpp:func:`start_select` is called for setting up the environment for -detection of read/write/error conditions on file descriptors belonging to the -given VFS driver. - -:cpp:func:`end_select` is called to stop/deinitialize/free the -environment which was setup by :cpp:func:`start_select`. - -.. note:: - :cpp:func:`end_select` might be called without a previous :cpp:func:`start_select` call in some rare - circumstances. :cpp:func:`end_select` should fail gracefully if this is the case. - -Please refer to the -reference implementation for the UART peripheral in -:component_file:`vfs/vfs_uart.c` and most particularly to the functions -:cpp:func:`esp_vfs_dev_uart_register`, :cpp:func:`uart_start_select`, and -:cpp:func:`uart_end_select` for more information. - -Please check the following examples that demonstrate the use of :cpp:func:`select` with VFS file descriptors: - - :example:`peripherals/uart/uart_select` - - :example:`system/select` - -Socket VFS drivers -"""""""""""""""""" - -A socket VFS driver is using its own internal implementation of :cpp:func:`select` and non-socket VFS drivers notify -it upon read/write/error conditions. - -A socket VFS driver needs to be registered with the following functions defined: - -.. highlight:: c - -:: - - // In definition of 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` is the internal implementation of :cpp:func:`select` for the socket driver. It works only -with file descriptors belonging to the socket VFS. - -:cpp:func:`get_socket_select_semaphore` returns the signalization object (semaphore) which will be used in non-socket -drivers to stop the waiting in :cpp:func:`socket_select`. - -:cpp:func:`stop_socket_select` call is used to stop the waiting in :cpp:func:`socket_select` by passing the object -returned by :cpp:func:`get_socket_select_semaphore`. - -:cpp:func:`stop_socket_select_isr` has the same functionality as :cpp:func:`stop_socket_select` but it can be used -from ISR. - -Please see :component_file:`lwip/port/esp32/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 enable the - :envvar:`CONFIG_LWIP_USE_ONLY_LWIP_SELECT` option to reduce the code size and improve performance. - -.. note:: - Don't change the socket driver during an active :cpp:func:`select` call or you might experience some undefined - behavior. - -Paths ------ - -Each registered FS has a path prefix associated with it. This prefix can be considered as a "mount point" of this partition. - -In case when mount points are nested, the mount point with the longest matching path prefix is used when opening the file. For instance, suppose that the following filesystems are registered in VFS: - -- FS 1 on /data -- FS 2 on /data/static - -Then: - -- FS 1 will be used when opening a file called ``/data/log.txt`` -- FS 2 will be used when opening a file called ``/data/static/index.html`` -- Even if ``/index.html"`` does not exist in FS 2, FS 1 will *not* be searched for ``/static/index.html``. - -As a general rule, mount point names must start with the path separator (``/``) and must contain at least one character after path separator. However, an empty mount point name is also supported and might be used in cases when an application needs to provide a "fallback" filesystem or to override VFS functionality altogether. Such filesystem will be used if no prefix matches the path given. - -VFS does not handle dots (``.``) in path names in any special way. VFS does not treat ``..`` as a reference to the parent directory. In the above example, using a path ``/data/static/../log.txt`` will not result in a call to FS 1 to open ``/log.txt``. Specific FS drivers (such as FATFS) might handle dots in file names differently. - -When opening files, the FS driver receives only relative paths to files. For example: - -1. The ``myfs`` driver is registered with ``/data`` as a path prefix. -2. The application calls ``fopen("/data/config.json", ...)``. -3. The VFS component calls ``myfs_open("/config.json", ...)``. -4. The ``myfs`` driver opens the ``/config.json`` file. - -VFS does not impose any limit on total file path length, but it does limit the FS path prefix to ``ESP_VFS_PATH_MAX`` characters. Individual FS drivers may have their own filename length limitations. - - -File descriptors ----------------- - -File descriptors are small positive integers from ``0`` to ``FD_SETSIZE - 1``, where ``FD_SETSIZE`` is defined in newlib's ``sys/types.h``. The largest file descriptors (configured by ``CONFIG_LWIP_MAX_SOCKETS``) are reserved for sockets. The VFS component contains a lookup-table called ``s_fd_table`` for mapping global file descriptors to VFS driver indexes registered in the ``s_vfs`` array. - - -Standard IO streams (stdin, stdout, stderr) -------------------------------------------- - -If the menuconfig option ``UART for console output`` is not set to ``None``, then ``stdin``, ``stdout``, and ``stderr`` are configured to read from, and write to, a UART. It is possible to use UART0 or UART1 for standard IO. By default, UART0 is used with 115200 baud rate; TX pin is GPIO1; RX pin is GPIO3. These parameters can be changed in menuconfig. - -Writing to ``stdout`` or ``stderr`` will send characters to the UART transmit FIFO. Reading from ``stdin`` will retrieve characters from the UART receive FIFO. - -By default, VFS uses simple functions for reading from and writing to UART. Writes busy-wait until all data is put into UART FIFO, and reads are non-blocking, returning only the data present in the FIFO. Due to this non-blocking read behavior, higher level C library calls, such as ``fscanf("%d\n", &var);``, might not have desired results. - -Applications which use the UART driver can instruct VFS to use the driver's interrupt driven, blocking read and write functions instead. This can be done using a call to the ``esp_vfs_dev_uart_use_driver`` function. It is also possible to revert to the basic non-blocking functions using a call to ``esp_vfs_dev_uart_use_nonblocking``. - -VFS also provides an optional newline conversion feature for input and output. Internally, most applications send and receive lines terminated by the LF (''\n'') character. Different terminal programs may require different line termination, such as CR or CRLF. Applications can configure this separately for input and output either via menuconfig, or by calls to the functions ``esp_vfs_dev_uart_port_set_rx_line_endings`` and ``esp_vfs_dev_uart_port_set_tx_line_endings``. - - - -Standard streams and FreeRTOS tasks -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -``FILE`` objects for ``stdin``, ``stdout``, and ``stderr`` are shared between all FreeRTOS tasks, but the pointers to these objects are stored in per-task ``struct _reent``. - -The following code is transferred to ``fprintf(__getreent()->_stderr, "42\n");`` by the preprocessor: - -.. highlight:: c - -:: - - fprintf(stderr, "42\n"); - - -The ``__getreent()`` function returns a per-task pointer to ``struct _reent`` in newlib libc. This structure is allocated on the TCB of each task. When a task is initialized, ``_stdin``, ``_stdout``, and ``_stderr`` members of ``struct _reent`` are set to the values of ``_stdin``, ``_stdout``, and ``_stderr`` of ``_GLOBAL_REENT`` (i.e., the structure which is used before FreeRTOS is started). - -Such a design has the following consequences: - -- It is possible to set ``stdin``, ``stdout``, and ``stderr`` for any given task without affecting other tasks, e.g., by doing ``stdin = fopen("/dev/uart/1", "r")``. -- Closing default ``stdin``, ``stdout``, or ``stderr`` using ``fclose`` will close the ``FILE`` stream object, which will affect all other tasks. -- To change the default ``stdin``, ``stdout``, ``stderr`` streams for new tasks, modify ``_GLOBAL_REENT->_stdin`` (``_stdout``, ``_stderr``) before creating the task. - -Event fds -------------------------------------------- - -``eventfd()`` call is a powerful tool to notify a ``select()`` based loop of custom events. The ``eventfd()`` implementation in ESP-IDF is generally the same as described in ``man(2) eventfd`` except for: - -- ``esp_vfs_eventfd_register()`` has to be called before calling ``eventfd()`` -- Options ``EFD_CLOEXEC``, ``EFD_NONBLOCK`` and ``EFD_SEMAPHORE`` are not supported in flags. -- Option ``EFD_SUPPORT_ISR`` has been added in flags. This flag is required to read and the write the eventfd in an interrupt handler. - -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. diff --git a/components/vfs/README_CN.rst b/components/vfs/README_CN.rst deleted file mode 100644 index 7ba1ee70c6..0000000000 --- a/components/vfs/README_CN.rst +++ /dev/null @@ -1,167 +0,0 @@ -虚拟文件系统组件 -============================ - -:link_to_translation:`en:[English]` - -概述 --------- - -虚拟文件系统 (VFS) 组件可为一些驱动提供一个统一接口。有了该接口,用户可像操作普通文件一样操作虚拟文件。这类驱动程序可以是 FAT、SPIFFS 等真实文件系统,也可以是有文件类接口的设备驱动程序。 - -VFS 组件支持 C 库函数(如 fopen 和 fprintf 等)与文件系统 (FS) 驱动程序协同工作。在高层级,每个 FS 驱动程序均与某些路径前缀相关联。当一个 C 库函数需要打开文件时,VFS 组件将搜索与该文件所在文件路径相关联的 FS 驱动程序,并将调用传递给该驱动程序。针对该文件的读取、写入等其他操作的调用也将传递给这个驱动程序。 - -例如,您可以使用 ``/fat`` 前缀注册 FAT 文件系统驱动,之后即可调用 ``fopen("/fat/file.txt", "w")``。之后,VFS 将调用 FAT 驱动的 ``open`` 函数,并将参数 ``/file.txt`` 和合适的打开模式传递给 ``open`` 函数;后续对返回的 ``FILE*`` 数据流调用 C 库函数也同样会传递给 FAT 驱动。 - -注册 FS 驱动程序 ---------------------- - -如需注册 FS 驱动程序,首先要定义一个 :cpp:type:`esp_vfs_t` 结构体实例,并用指向 FS API 的函数指针填充它。 - -.. highlight:: c - -:: - - esp_vfs_t myfs = { - .flags = ESP_VFS_FLAG_DEFAULT, - .write = &myfs_write, - .open = &myfs_open, - .fstat = &myfs_fstat, - .close = &myfs_close, - .read = &myfs_read, - }; - - ESP_ERROR_CHECK(esp_vfs_register("/data", &myfs, NULL)); - -在上述代码中需要用到 ``read``、 ``write`` 或 ``read_p``、 ``write_p``,具体使用哪组函数由 FS 驱动程序 API 的声明方式决定。 - -示例 1:声明 API 函数时不带额外的上下文指针参数,即 FS 驱动程序为单例模式,此时使用 ``write`` :: - - ssize_t myfs_write(int fd, const void * data, size_t size); - - // In definition of esp_vfs_t: - .flags = ESP_VFS_FLAG_DEFAULT, - .write = &myfs_write, - // ... other members initialized - - // When registering FS, context pointer (third argument) is 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: - .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_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)); - -同步输入/输出多路复用 -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -如需通过 :cpp:func:`select` 使用同步输入/输出多路复用,首先需要把 :cpp:func:`start_select` 和 :cpp:func:`end_select` 注册到 VFS,如下所示: - -.. highlight:: c - -:: - - // In definition of 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` 设置的资源。请在 :component_file:`vfs/vfs_uart.c` 中查看 UART 外设参考实现、:cpp:func:`esp_vfs_dev_uart_register`、:cpp:func:`uart_start_select` 和 :cpp:func:`uart_end_select` 函数。 - -请参考以下示例,查看如何使用 VFS 文件描述符调用 :cpp:func:`select`: - -- :example:`peripherals/uart/uart_select` -- :example:`system/select` - -如果 :cpp:func:`select` 用于套接字文件描述符,您可以启用 :envvar:`CONFIG_LWIP_USE_ONLY_LWIP_SELECT` 选项来减少代码量,提高性能。 - -路径 ------ - -已注册的 FS 驱动程序均有一个路径前缀与之关联,此路径前缀即为分区的挂载点。 - -如果挂载点中嵌套了其他挂载点,则在打开文件时使用具有最长匹配路径前缀的挂载点。例如,假设以下文件系统已在 VFS 中注册: - -- 在 /data 下注册 FS 驱动程序 1 -- 在 /data/static 下注册 FS 驱动程序 2 - -那么: - -- 打开 ``/data/log.txt`` 会调用驱动程序 FS 1; -- 打开 ``/data/static/index.html`` 需调用 FS 驱动程序 2; -- 即便 FS 驱动程序 2 中没有 ``/index.html``,也不会在 FS 驱动程序 1 中查找 ``/static/index.html``。 - -挂载点名称必须以路径分隔符 (``/``) 开头,且分隔符后至少包含一个字符。但在以下情况中,VFS 同样支持空的挂载点名称:1. 应用程序需要提供一个”最后方案“下使用的文件系统;2. 应用程序需要同时覆盖 VFS 功能。如果没有与路径匹配的前缀,就会使用到这种文件系统。 - -VFS 不会对路径中的点 (``.``) 进行特殊处理,也不会将 ``..`` 视为对父目录的引用。在上述示例中,使用 ``/data/static/../log.txt`` 路径不会调用 FS 驱动程序 1 打开 ``/log.txt``。特定的 FS 驱动程序(如 FATFS)可能以不同的方式处理文件名中的点。 - -执行打开文件操作时,FS 驱动程序仅得到文件的相对路径(挂载点前缀已经被去除): - -1. 以 ``/data`` 为路径前缀注册 ``myfs`` 驱动; -2. 应用程序调用 ``fopen("/data/config.json", ...)``; -3. VFS 调用 ``myfs_open("/config.json", ...)``; -4. ``myfs`` 驱动打开 ``/config.json`` 文件。 - -VFS 对文件路径长度没有限制,但文件系统路径前缀受 ``ESP_VFS_PATH_MAX`` 限制,即路径前缀上限为 ``ESP_VFS_PATH_MAX``。各个文件系统驱动则可能会对自己的文件名长度设置一些限制。 - - -文件描述符 ----------------- - -文件描述符是一组很小的正整数,从 ``0`` 到 ``FD_SETSIZE - 1``,``FD_SETSIZE`` 在 newlib ``sys/types.h`` 中定义。最大文件描述符由 ``CONFIG_LWIP_MAX_SOCKETS`` 定义,且为套接字保留。VFS 中包含一个名为 ``s_fd_table`` 的查找表,用于将全局文件描述符映射至 ``s_vfs`` 数组中注册的 VFS 驱动索引。 - - -标准 IO 流 (stdin, stdout, stderr) -------------------------------------------- - -如果 menuconfig 中 ``UART for console output`` 选项没有设置为 ``None``,则 ``stdin``、 ``stdout`` 和 ``stderr`` 将默认从 UART 读取或写入。UART0 或 UART1 可用作标准 IO。默认情况下,UART0 使用 115200 波特率,TX 管脚为 GPIO1,RX 管脚为 GPIO3。您可以在 menuconfig 中更改上述参数。 - -对 ``stdout`` 或 ``stderr`` 执行写入操作将会向 UART 发送 FIFO 发送字符,对 ``stdin`` 执行读取操作则会从 UART 接收 FIFO 中取出字符。 - -默认情况下,VFS 使用简单的函数对 UART 进行读写操作。在所有数据放进 UART FIFO 之前,写操作将处于 busy-wait 状态,读操处于非阻塞状态,仅返回 FIFO 中已有数据。由于读操作为非阻塞,高层级 C 库函数调用(如 ``fscanf("%d\n", &var);``)可能获取不到所需结果。 - -如果应用程序使用 UART 驱动,则可以调用 ``esp_vfs_dev_uart_use_driver`` 函数来指导 VFS 使用驱动中断、读写阻塞功能等。您也可以调用 ``esp_vfs_dev_uart_use_nonblocking`` 来恢复非阻塞函数。 - -VFS 还为输入和输出提供换行符转换功能(可选)。多数应用程序在程序内部发送或接收以 LF (''\n'') 结尾的行,但不同的终端程序可能需要不同的换行符,比如 CR 或 CRLF。应用程序可以通过 menuconfig 或者调用 ``esp_vfs_dev_uart_port_set_rx_line_endings`` 和 ``esp_vfs_dev_uart_port_set_tx_line_endings`` 为输入输出配置换行符。 - - -标准流和 FreeRTOS 任务 -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -``stdin``、``stdout`` 和 ``stderr`` 的 ``FILE`` 对象在所有 FreeRTOS 任务之间共享,指向这些对象的指针分别存储在每个任务的 ``struct _reent`` 中。 - -预处理器把如下代码: - -.. highlight:: c - -:: - - fprintf(stderr, "42\n"); - -解释为: - -.. highlight:: c - -:: - - fprintf(__getreent()->_stderr, "42\n"); - -其中 ``__getreent()`` 函数将为每个任务返回一个指向 ``struct _reent`` 的指针。每个任务的 TCB 均拥有一个 ``struct _reent`` 结构体,任务初始化后,``struct _reent`` 结构体中的 ``_stdin``、``_stdout`` 和 ``_stderr`` 将会被赋予 ``_GLOBAL_REENT`` 中 ``_stdin``、 ``_stdout`` 和 ``_stderr`` 的值,``_GLOBAL_REENT`` 即为 FreeRTOS 启动之前所用结构体。 - -这样设计带来的结果是: - -- 允许重定向给定任务的 ``stdin``、 ``stdout`` 和 ``stderr``,而不影响其他任务,例如通过 ``stdin = fopen("/dev/uart/1", "r")``; -- 但使用 ``fclose`` 关闭默认 ``stdin``、 ``stdout`` 或 ``stderr`` 将同时关闭相应的 ``FILE`` 流对象,因此会影响其他任务; -- 如需更改新任务的默认 ``stdin``、 ``stdout`` 和 ``stderr`` 流,请在创建新任务之前修改 ``_GLOBAL_REENT->_stdin`` (``_stdout``、``_stderr``)。 diff --git a/components/vfs/test/test_vfs_lwip.c b/components/vfs/test/test_vfs_lwip.c new file mode 100644 index 0000000000..064bb46d33 --- /dev/null +++ b/components/vfs/test/test_vfs_lwip.c @@ -0,0 +1,37 @@ +// 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. + +#include +#include +#include +#include +#include "unity.h" +#include "test_utils.h" + +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); + struct stat stat = { 0 }; + fstat(socket_fd, &stat); + + TEST_ASSERT_TRUE(S_ISSOCK(stat.st_mode)); + TEST_ASSERT_FALSE(S_ISBLK(stat.st_mode)); + TEST_ASSERT_FALSE(S_ISCHR(stat.st_mode)); + TEST_ASSERT_FALSE(S_ISDIR(stat.st_mode)); + TEST_ASSERT_FALSE(S_ISREG(stat.st_mode)); + TEST_ASSERT_FALSE(S_ISLNK(stat.st_mode)); + + close(socket_fd); +} diff --git a/components/vfs/test/test_vfs_uart.c b/components/vfs/test/test_vfs_uart.c index 4c3506179f..60903eade1 100644 --- a/components/vfs/test/test_vfs_uart.c +++ b/components/vfs/test/test_vfs_uart.c @@ -131,38 +131,38 @@ TEST_CASE("CRs are removed from the stdin correctly", "[vfs]") TEST_ASSERT_EQUAL_UINT8_ARRAY("4\n", dst, 2); } +struct read_task_arg_t { + char* out_buffer; + size_t out_buffer_len; + SemaphoreHandle_t ready; + SemaphoreHandle_t done; +}; + +struct write_task_arg_t { + const char* str; + SemaphoreHandle_t done; +}; + +static void read_task_fn(void* varg) +{ + struct read_task_arg_t* parg = (struct read_task_arg_t*) varg; + parg->out_buffer[0] = 0; + + fgets(parg->out_buffer, parg->out_buffer_len, stdin); + xSemaphoreGive(parg->done); + vTaskDelete(NULL); +} + +static void write_task_fn(void* varg) +{ + struct write_task_arg_t* parg = (struct write_task_arg_t*) varg; + fwrite_str_loopback(parg->str, strlen(parg->str)); + xSemaphoreGive(parg->done); + vTaskDelete(NULL); +} + TEST_CASE("can write to UART while another task is reading", "[vfs]") { - struct read_task_arg_t { - char* out_buffer; - size_t out_buffer_len; - SemaphoreHandle_t ready; - SemaphoreHandle_t done; - }; - - struct write_task_arg_t { - const char* str; - SemaphoreHandle_t done; - }; - - void read_task_fn(void* varg) - { - struct read_task_arg_t* parg = (struct read_task_arg_t*) varg; - parg->out_buffer[0] = 0; - - fgets(parg->out_buffer, parg->out_buffer_len, stdin); - xSemaphoreGive(parg->done); - vTaskDelete(NULL); - } - - void write_task_fn(void* varg) - { - struct write_task_arg_t* parg = (struct write_task_arg_t*) varg; - fwrite_str_loopback(parg->str, strlen(parg->str)); - xSemaphoreGive(parg->done); - vTaskDelete(NULL); - } - char out_buffer[32]; size_t out_buffer_len = sizeof(out_buffer); diff --git a/components/vfs/vfs.c b/components/vfs/vfs.c index 46890e3e64..dc1f3af099 100644 --- a/components/vfs/vfs.c +++ b/components/vfs/vfs.c @@ -37,7 +37,7 @@ static const char *TAG = "vfs"; #define VFS_MAX_COUNT 8 /* max number of VFS entries (registered filesystems) */ #define LEN_PATH_PREFIX_IGNORED SIZE_MAX /* special length value for VFS which is never recognised by open() */ -#define FD_TABLE_ENTRY_UNUSED (fd_table_t) { .permanent = false, .vfs_index = -1, .local_fd = -1 } +#define FD_TABLE_ENTRY_UNUSED (fd_table_t) { .permanent = false, .has_pending_close = false, .has_pending_select = false, .vfs_index = -1, .local_fd = -1 } typedef uint8_t local_fd_t; _Static_assert((1 << (sizeof(local_fd_t)*8)) >= MAX_FDS, "file descriptor type too small"); @@ -47,7 +47,10 @@ _Static_assert((1 << (sizeof(vfs_index_t)*8)) >= VFS_MAX_COUNT, "VFS index type _Static_assert(((vfs_index_t) -1) < 0, "vfs_index_t must be a signed type"); typedef struct { - bool permanent; + bool permanent :1; + bool has_pending_close :1; + bool has_pending_select :1; + uint8_t _reserved :5; vfs_index_t vfs_index; local_fd_t local_fd; } fd_table_t; @@ -511,7 +514,11 @@ int esp_vfs_close(struct _reent *r, int fd) _lock_acquire(&s_fd_table_lock); if (!s_fd_table[fd].permanent) { - s_fd_table[fd] = FD_TABLE_ENTRY_UNUSED; + if (s_fd_table[fd].has_pending_select) { + s_fd_table[fd].has_pending_close = true; + } else { + s_fd_table[fd] = FD_TABLE_ENTRY_UNUSED; + } } _lock_release(&s_fd_table_lock); return ret; @@ -906,6 +913,9 @@ int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds const bool is_socket_fd = s_fd_table[fd].permanent; const int vfs_index = s_fd_table[fd].vfs_index; const int local_fd = s_fd_table[fd].local_fd; + if (esp_vfs_safe_fd_isset(fd, errorfds)) { + s_fd_table[fd].has_pending_select = true; + } _lock_release(&s_fd_table_lock); if (vfs_index < 0) { @@ -1034,6 +1044,7 @@ int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds } call_end_selects(vfs_count, vfs_fds_triple, driver_args); // for VFSs for start_select was called before + if (ret >= 0) { ret += set_global_fd_sets(vfs_fds_triple, vfs_count, readfds, writefds, errorfds); } @@ -1041,6 +1052,13 @@ int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds vSemaphoreDelete(sel_sem.sem); sel_sem.sem = NULL; } + for (int fd = 0; fd < nfds; ++fd) { + _lock_acquire(&s_fd_table_lock); + if (s_fd_table[fd].has_pending_close) { + s_fd_table[fd] = FD_TABLE_ENTRY_UNUSED; + } + _lock_release(&s_fd_table_lock); + } free(vfs_fds_triple); free(driver_args); diff --git a/components/vfs/vfs_eventfd.c b/components/vfs/vfs_eventfd.c index f5f3c49ed5..726a0b13a9 100644 --- a/components/vfs/vfs_eventfd.c +++ b/components/vfs/vfs_eventfd.c @@ -260,7 +260,7 @@ static ssize_t event_write(int fd, const void *data, size_t size) return ret; } - if (xPortInIsrContext()) { + if (!xPortCanYield()) { ret = signal_event_fd_from_isr(fd, data, size); } else { const uint64_t *val = (const uint64_t *)data; diff --git a/components/wifi_provisioning/src/manager.c b/components/wifi_provisioning/src/manager.c index df08130dd2..de80f34659 100644 --- a/components/wifi_provisioning/src/manager.c +++ b/components/wifi_provisioning/src/manager.c @@ -927,11 +927,17 @@ esp_err_t wifi_prov_mgr_wifi_scan_start(bool blocking, bool passive, if (passive) { prov_ctx->scan_cfg.scan_type = WIFI_SCAN_TYPE_PASSIVE; +/* We do not recommend scan configuration modification in Wi-Fi and BT coexistence mode */ +#if !CONFIG_BT_ENABLED prov_ctx->scan_cfg.scan_time.passive = period_ms; +#endif } else { prov_ctx->scan_cfg.scan_type = WIFI_SCAN_TYPE_ACTIVE; +/* We do not recommend scan configuration modification in Wi-Fi and BT coexistence mode */ +#if !CONFIG_BT_ENABLED prov_ctx->scan_cfg.scan_time.active.min = period_ms; prov_ctx->scan_cfg.scan_time.active.max = period_ms; +#endif } prov_ctx->channels_per_group = group_channels; diff --git a/components/wpa_supplicant/CMakeLists.txt b/components/wpa_supplicant/CMakeLists.txt index fa7f4de2bb..282cd04169 100644 --- a/components/wpa_supplicant/CMakeLists.txt +++ b/components/wpa_supplicant/CMakeLists.txt @@ -136,6 +136,8 @@ else() "src/crypto/sha1-pbkdf2.c" "src/crypto/sha1.c" "src/crypto/sha256-internal.c" + "src/crypto/sha384-internal.c" + "src/crypto/sha512-internal.c" "src/crypto/sha256.c") endif() diff --git a/components/wpa_supplicant/component.mk b/components/wpa_supplicant/component.mk index d1509dfa1e..1d99db8da0 100644 --- a/components/wpa_supplicant/component.mk +++ b/components/wpa_supplicant/component.mk @@ -71,7 +71,7 @@ ifneq ($(CONFIG_WPA_11KV_SUPPORT), y) esp_supplicant/src/esp_scan.o endif -CFLAGS += -DCONFIG_DPP -DCONFIG_IEEE80211W -DESP_SUPPLICANT -DIEEE8021X_EAPOL -DEAP_PEER_METHOD -DEAP_TLS -DEAP_TTLS -DEAP_PEAP -DEAP_MSCHAPv2 -DUSE_WPA2_TASK -DCONFIG_WPS2 -DCONFIG_WPS_PIN -DUSE_WPS_TASK -DESPRESSIF_USE -DESP32_WORKAROUND -DCONFIG_ECC -DCONFIG_WNM -D__ets__ -Wno-strict-aliasing +CFLAGS += -DCONFIG_SHA256 -DCONFIG_DPP -DCONFIG_IEEE80211W -DESP_SUPPLICANT -DIEEE8021X_EAPOL -DEAP_PEER_METHOD -DEAP_TLS -DEAP_TTLS -DEAP_PEAP -DEAP_MSCHAPv2 -DUSE_WPA2_TASK -DCONFIG_WPS2 -DCONFIG_WPS_PIN -DUSE_WPS_TASK -DESPRESSIF_USE -DESP32_WORKAROUND -DCONFIG_ECC -DCONFIG_WNM -D__ets__ -Wno-strict-aliasing ifdef CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE CFLAGS += -DCONFIG_WPA3_SAE diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_common.c b/components/wpa_supplicant/esp_supplicant/src/esp_common.c index eaa248a2fc..a3ff7d73bc 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_common.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_common.c @@ -177,7 +177,7 @@ static void esp_clear_bssid_flag(struct wpa_supplicant *wpa_s) static void esp_register_action_frame(struct wpa_supplicant *wpa_s) { - wpa_s->type &= ~WLAN_FC_STYPE_ACTION; + wpa_s->type &= ~(1 << WLAN_FC_STYPE_ACTION); /* subtype is defined only for action frame */ wpa_s->subtype = 0; @@ -281,9 +281,7 @@ int esp_rrm_send_neighbor_rep_request(neighbor_rep_request_cb cb, struct wifi_ssid *ssid = esp_wifi_sta_get_prof_ssid_internal(); os_memcpy(wpa_ssid.ssid, ssid->ssid, ssid->len); wpa_ssid.ssid_len = ssid->len; - wpas_rrm_send_neighbor_rep_request(wpa_s, &wpa_ssid, 0, 0, cb, cb_ctx); - - return 0; + return wpas_rrm_send_neighbor_rep_request(wpa_s, &wpa_ssid, 0, 0, cb, cb_ctx); } int esp_wnm_send_bss_transition_mgmt_query(enum btm_query_reason query_reason, diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c index 00b08035c6..ec4a2d3fa8 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c @@ -90,7 +90,7 @@ void *hostap_init(void) spp_attrubute = esp_wifi_get_spp_attrubute_internal(WIFI_IF_AP); auth_conf->spp_sup.capable = ((spp_attrubute & WPA_CAPABILITY_SPP_CAPABLE) ? SPP_AMSDU_CAP_ENABLE : SPP_AMSDU_CAP_DISABLE); - auth_conf->spp_sup.require = ((spp_attrubute & WPA_CAPABILITY_SPP_REQUIRED) ? SPP_AMSDU_CAP_ENABLE : SPP_AMSDU_REQ_DISABLE); + auth_conf->spp_sup.require = ((spp_attrubute & WPA_CAPABILITY_SPP_REQUIRED) ? SPP_AMSDU_REQ_ENABLE : SPP_AMSDU_REQ_DISABLE); memcpy(hapd->conf->ssid.ssid, ssid->ssid, ssid->len); hapd->conf->ssid.ssid_len = ssid->len; diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_scan.c b/components/wpa_supplicant/esp_supplicant/src/esp_scan.c index e1e7ee18df..5c9fc41af2 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_scan.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_scan.c @@ -199,7 +199,8 @@ static int esp_issue_scan(struct wpa_supplicant *wpa_s, params->ssid = os_zalloc(scan_params->ssids[0].ssid_len + 1); if (!params->ssid) { wpa_printf(MSG_ERROR, "failed to allocate memory"); - return -1; + ret = -1; + goto cleanup; } os_memcpy(params->ssid, scan_params->ssids[0].ssid, scan_params->ssids[0].ssid_len); params->scan_type = WIFI_SCAN_TYPE_ACTIVE; @@ -210,7 +211,8 @@ static int esp_issue_scan(struct wpa_supplicant *wpa_s, params->bssid = os_zalloc(ETH_ALEN); if (!params->bssid) { wpa_printf(MSG_ERROR, "failed to allocate memory"); - return -1; + ret = -1; + goto cleanup; } os_memcpy(params->bssid, scan_params->bssid, ETH_ALEN); } diff --git a/components/wpa_supplicant/src/crypto/sha384-internal.c b/components/wpa_supplicant/src/crypto/sha384-internal.c new file mode 100644 index 0000000000..646f72979c --- /dev/null +++ b/components/wpa_supplicant/src/crypto/sha384-internal.c @@ -0,0 +1,92 @@ +/* + * SHA-384 hash implementation and interface functions + * Copyright (c) 2015, Pali Rohár + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "sha384_i.h" +#include "crypto.h" + + +/** + * sha384_vector - SHA384 hash for data vector + * @num_elem: Number of elements in the data vector + * @addr: Pointers to the data areas + * @len: Lengths of the data blocks + * @mac: Buffer for the hash + * Returns: 0 on success, -1 of failure + */ +int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len, + u8 *mac) +{ + struct sha384_state ctx; + size_t i; + + sha384_init(&ctx); + for (i = 0; i < num_elem; i++) + if (sha384_process(&ctx, addr[i], len[i])) + return -1; + if (sha384_done(&ctx, mac)) + return -1; + return 0; +} + + +/* ===== start - public domain SHA384 implementation ===== */ + +/* This is based on SHA384 implementation in LibTomCrypt that was released into + * public domain by Tom St Denis. */ + +#define CONST64(n) n ## ULL + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +void sha384_init(struct sha384_state *md) +{ + md->curlen = 0; + md->length = 0; + md->state[0] = CONST64(0xcbbb9d5dc1059ed8); + md->state[1] = CONST64(0x629a292a367cd507); + md->state[2] = CONST64(0x9159015a3070dd17); + md->state[3] = CONST64(0x152fecd8f70e5939); + md->state[4] = CONST64(0x67332667ffc00b31); + md->state[5] = CONST64(0x8eb44a8768581511); + md->state[6] = CONST64(0xdb0c2e0d64f98fa7); + md->state[7] = CONST64(0x47b5481dbefa4fa4); +} + +int sha384_process(struct sha384_state *md, const unsigned char *in, + unsigned long inlen) +{ + return sha512_process(md, in, inlen); +} + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (48 bytes) + @return CRYPT_OK if successful +*/ +int sha384_done(struct sha384_state *md, unsigned char *out) +{ + unsigned char buf[64]; + + if (md->curlen >= sizeof(md->buf)) + return -1; + + if (sha512_done(md, buf) != 0) + return -1; + + os_memcpy(out, buf, 48); + return 0; +} + +/* ===== end - public domain SHA384 implementation ===== */ diff --git a/components/wpa_supplicant/src/crypto/sha384_i.h b/components/wpa_supplicant/src/crypto/sha384_i.h new file mode 100644 index 0000000000..a00253ff2c --- /dev/null +++ b/components/wpa_supplicant/src/crypto/sha384_i.h @@ -0,0 +1,23 @@ +/* + * SHA-384 internal definitions + * Copyright (c) 2015, Pali Rohár + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef SHA384_I_H +#define SHA384_I_H + +#include "sha512_i.h" + +#define SHA384_BLOCK_SIZE SHA512_BLOCK_SIZE + +#define sha384_state sha512_state + +void sha384_init(struct sha384_state *md); +int sha384_process(struct sha384_state *md, const unsigned char *in, + unsigned long inlen); +int sha384_done(struct sha384_state *md, unsigned char *out); + +#endif /* SHA384_I_H */ diff --git a/components/wpa_supplicant/src/crypto/sha512-internal.c b/components/wpa_supplicant/src/crypto/sha512-internal.c new file mode 100644 index 0000000000..c0263941c1 --- /dev/null +++ b/components/wpa_supplicant/src/crypto/sha512-internal.c @@ -0,0 +1,270 @@ +/* + * SHA-512 hash implementation and interface functions + * Copyright (c) 2015, Pali Rohár + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "sha512_i.h" +#include "crypto.h" + + +/** + * sha512_vector - SHA512 hash for data vector + * @num_elem: Number of elements in the data vector + * @addr: Pointers to the data areas + * @len: Lengths of the data blocks + * @mac: Buffer for the hash + * Returns: 0 on success, -1 of failure + */ +int sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len, + u8 *mac) +{ + struct sha512_state ctx; + size_t i; + + sha512_init(&ctx); + for (i = 0; i < num_elem; i++) + if (sha512_process(&ctx, addr[i], len[i])) + return -1; + if (sha512_done(&ctx, mac)) + return -1; + return 0; +} + + +/* ===== start - public domain SHA512 implementation ===== */ + +/* This is based on SHA512 implementation in LibTomCrypt that was released into + * public domain by Tom St Denis. */ + +#define CONST64(n) n ## ULL + +/* the K array */ +static const u64 K[80] = { + CONST64(0x428a2f98d728ae22), CONST64(0x7137449123ef65cd), + CONST64(0xb5c0fbcfec4d3b2f), CONST64(0xe9b5dba58189dbbc), + CONST64(0x3956c25bf348b538), CONST64(0x59f111f1b605d019), + CONST64(0x923f82a4af194f9b), CONST64(0xab1c5ed5da6d8118), + CONST64(0xd807aa98a3030242), CONST64(0x12835b0145706fbe), + CONST64(0x243185be4ee4b28c), CONST64(0x550c7dc3d5ffb4e2), + CONST64(0x72be5d74f27b896f), CONST64(0x80deb1fe3b1696b1), + CONST64(0x9bdc06a725c71235), CONST64(0xc19bf174cf692694), + CONST64(0xe49b69c19ef14ad2), CONST64(0xefbe4786384f25e3), + CONST64(0x0fc19dc68b8cd5b5), CONST64(0x240ca1cc77ac9c65), + CONST64(0x2de92c6f592b0275), CONST64(0x4a7484aa6ea6e483), + CONST64(0x5cb0a9dcbd41fbd4), CONST64(0x76f988da831153b5), + CONST64(0x983e5152ee66dfab), CONST64(0xa831c66d2db43210), + CONST64(0xb00327c898fb213f), CONST64(0xbf597fc7beef0ee4), + CONST64(0xc6e00bf33da88fc2), CONST64(0xd5a79147930aa725), + CONST64(0x06ca6351e003826f), CONST64(0x142929670a0e6e70), + CONST64(0x27b70a8546d22ffc), CONST64(0x2e1b21385c26c926), + CONST64(0x4d2c6dfc5ac42aed), CONST64(0x53380d139d95b3df), + CONST64(0x650a73548baf63de), CONST64(0x766a0abb3c77b2a8), + CONST64(0x81c2c92e47edaee6), CONST64(0x92722c851482353b), + CONST64(0xa2bfe8a14cf10364), CONST64(0xa81a664bbc423001), + CONST64(0xc24b8b70d0f89791), CONST64(0xc76c51a30654be30), + CONST64(0xd192e819d6ef5218), CONST64(0xd69906245565a910), + CONST64(0xf40e35855771202a), CONST64(0x106aa07032bbd1b8), + CONST64(0x19a4c116b8d2d0c8), CONST64(0x1e376c085141ab53), + CONST64(0x2748774cdf8eeb99), CONST64(0x34b0bcb5e19b48a8), + CONST64(0x391c0cb3c5c95a63), CONST64(0x4ed8aa4ae3418acb), + CONST64(0x5b9cca4f7763e373), CONST64(0x682e6ff3d6b2b8a3), + CONST64(0x748f82ee5defb2fc), CONST64(0x78a5636f43172f60), + CONST64(0x84c87814a1f0ab72), CONST64(0x8cc702081a6439ec), + CONST64(0x90befffa23631e28), CONST64(0xa4506cebde82bde9), + CONST64(0xbef9a3f7b2c67915), CONST64(0xc67178f2e372532b), + CONST64(0xca273eceea26619c), CONST64(0xd186b8c721c0c207), + CONST64(0xeada7dd6cde0eb1e), CONST64(0xf57d4f7fee6ed178), + CONST64(0x06f067aa72176fba), CONST64(0x0a637dc5a2c898a6), + CONST64(0x113f9804bef90dae), CONST64(0x1b710b35131c471b), + CONST64(0x28db77f523047d84), CONST64(0x32caab7b40c72493), + CONST64(0x3c9ebe0a15c9bebc), CONST64(0x431d67c49c100d4c), + CONST64(0x4cc5d4becb3e42b6), CONST64(0x597f299cfc657e2a), + CONST64(0x5fcb6fab3ad6faec), CONST64(0x6c44198c4a475817) +}; + +/* Various logical functions */ +#define Ch(x,y,z) (z ^ (x & (y ^ z))) +#define Maj(x,y,z) (((x | y) & z) | (x & y)) +#define S(x, n) ROR64c(x, n) +#define R(x, n) (((x) & CONST64(0xFFFFFFFFFFFFFFFF)) >> ((u64) n)) +#define Sigma0(x) (S(x, 28) ^ S(x, 34) ^ S(x, 39)) +#define Sigma1(x) (S(x, 14) ^ S(x, 18) ^ S(x, 41)) +#define Gamma0(x) (S(x, 1) ^ S(x, 8) ^ R(x, 7)) +#define Gamma1(x) (S(x, 19) ^ S(x, 61) ^ R(x, 6)) +#ifndef MIN +#define MIN(x, y) (((x) < (y)) ? (x) : (y)) +#endif + +#define ROR64c(x, y) \ + ( ((((x) & CONST64(0xFFFFFFFFFFFFFFFF)) >> ((u64) (y) & CONST64(63))) | \ + ((x) << ((u64) (64 - ((y) & CONST64(63)))))) & \ + CONST64(0xFFFFFFFFFFFFFFFF)) + +/* compress 1024-bits */ +static int sha512_compress(struct sha512_state *md, unsigned char *buf) +{ + u64 S[8], t0, t1; + u64 *W; + int i; + + W = os_malloc(80 * sizeof(u64)); + if (!W) + return -1; + + /* copy state into S */ + for (i = 0; i < 8; i++) { + S[i] = md->state[i]; + } + + /* copy the state into 1024-bits into W[0..15] */ + for (i = 0; i < 16; i++) + W[i] = WPA_GET_BE64(buf + (8 * i)); + + /* fill W[16..79] */ + for (i = 16; i < 80; i++) { + W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + + W[i - 16]; + } + + /* Compress */ + for (i = 0; i < 80; i++) { + t0 = S[7] + Sigma1(S[4]) + Ch(S[4], S[5], S[6]) + K[i] + W[i]; + t1 = Sigma0(S[0]) + Maj(S[0], S[1], S[2]); + S[7] = S[6]; + S[6] = S[5]; + S[5] = S[4]; + S[4] = S[3] + t0; + S[3] = S[2]; + S[2] = S[1]; + S[1] = S[0]; + S[0] = t0 + t1; + } + + /* feedback */ + for (i = 0; i < 8; i++) { + md->state[i] = md->state[i] + S[i]; + } + + os_free(W); + return 0; +} + + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +void sha512_init(struct sha512_state *md) +{ + md->curlen = 0; + md->length = 0; + md->state[0] = CONST64(0x6a09e667f3bcc908); + md->state[1] = CONST64(0xbb67ae8584caa73b); + md->state[2] = CONST64(0x3c6ef372fe94f82b); + md->state[3] = CONST64(0xa54ff53a5f1d36f1); + md->state[4] = CONST64(0x510e527fade682d1); + md->state[5] = CONST64(0x9b05688c2b3e6c1f); + md->state[6] = CONST64(0x1f83d9abfb41bd6b); + md->state[7] = CONST64(0x5be0cd19137e2179); +} + + +/** + Process a block of memory though the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful +*/ +int sha512_process(struct sha512_state *md, const unsigned char *in, + unsigned long inlen) +{ + unsigned long n; + + if (md->curlen >= sizeof(md->buf)) + return -1; + + while (inlen > 0) { + if (md->curlen == 0 && inlen >= SHA512_BLOCK_SIZE) { + if (sha512_compress(md, (unsigned char *) in) < 0) + return -1; + md->length += SHA512_BLOCK_SIZE * 8; + in += SHA512_BLOCK_SIZE; + inlen -= SHA512_BLOCK_SIZE; + } else { + n = MIN(inlen, (SHA512_BLOCK_SIZE - md->curlen)); + os_memcpy(md->buf + md->curlen, in, n); + md->curlen += n; + in += n; + inlen -= n; + if (md->curlen == SHA512_BLOCK_SIZE) { + if (sha512_compress(md, md->buf) < 0) + return -1; + md->length += 8 * SHA512_BLOCK_SIZE; + md->curlen = 0; + } + } + } + + return 0; +} + + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (64 bytes) + @return CRYPT_OK if successful +*/ +int sha512_done(struct sha512_state *md, unsigned char *out) +{ + int i; + + if (md->curlen >= sizeof(md->buf)) + return -1; + + /* increase the length of the message */ + md->length += md->curlen * CONST64(8); + + /* append the '1' bit */ + md->buf[md->curlen++] = (unsigned char) 0x80; + + /* if the length is currently above 112 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->curlen > 112) { + while (md->curlen < 128) { + md->buf[md->curlen++] = (unsigned char) 0; + } + sha512_compress(md, md->buf); + md->curlen = 0; + } + + /* pad up to 120 bytes of zeroes + * note: that from 112 to 120 is the 64 MSB of the length. We assume + * that you won't hash > 2^64 bits of data... :-) + */ + while (md->curlen < 120) { + md->buf[md->curlen++] = (unsigned char) 0; + } + + /* store length */ + WPA_PUT_BE64(md->buf + 120, md->length); + sha512_compress(md, md->buf); + + /* copy output */ + for (i = 0; i < 8; i++) + WPA_PUT_BE64(out + (8 * i), md->state[i]); + + return 0; +} + +/* ===== end - public domain SHA512 implementation ===== */ diff --git a/components/wpa_supplicant/src/crypto/sha512_i.h b/components/wpa_supplicant/src/crypto/sha512_i.h new file mode 100644 index 0000000000..108958911e --- /dev/null +++ b/components/wpa_supplicant/src/crypto/sha512_i.h @@ -0,0 +1,25 @@ +/* + * SHA-512 internal definitions + * Copyright (c) 2015, Pali Rohár + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef SHA512_I_H +#define SHA512_I_H + +#define SHA512_BLOCK_SIZE 128 + +struct sha512_state { + u64 length, state[8]; + u32 curlen; + u8 buf[SHA512_BLOCK_SIZE]; +}; + +void sha512_init(struct sha512_state *md); +int sha512_process(struct sha512_state *md, const unsigned char *in, + unsigned long inlen); +int sha512_done(struct sha512_state *md, unsigned char *out); + +#endif /* SHA512_I_H */ diff --git a/components/wpa_supplicant/src/crypto/tls_mbedtls.c b/components/wpa_supplicant/src/crypto/tls_mbedtls.c index 9db60867ad..23d8d9d700 100644 --- a/components/wpa_supplicant/src/crypto/tls_mbedtls.c +++ b/components/wpa_supplicant/src/crypto/tls_mbedtls.c @@ -121,6 +121,10 @@ static int tls_mbedtls_read(void *ctx, unsigned char *buf, size_t len) struct wpabuf *local_buf; size_t data_len = len; + if (data->in_data == NULL) { + return MBEDTLS_ERR_SSL_WANT_READ; + } + if (len > wpabuf_len(data->in_data)) { wpa_printf(MSG_ERROR, "don't have suffient data\n"); data_len = wpabuf_len(data->in_data); @@ -466,6 +470,10 @@ static int tls_create_mbedtls_handle(const struct tls_connection_params *params, wpa_printf(MSG_ERROR, "mbedtls_ssl_setup returned -0x%x", -ret); goto exit; } +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + /* Disable BEAST attack countermeasures for Windows 2008 interoperability */ + mbedtls_ssl_conf_cbc_record_splitting(&tls->conf, MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED); +#endif /* Enable debug prints in case supplicant's prints are enabled */ #if defined(DEBUG_PRINT) && defined(CONFIG_MBEDTLS_DEBUG) && defined(ESPRESSIF_USE) @@ -556,56 +564,26 @@ struct wpabuf * tls_connection_handshake(void *tls_ctx, if (wpabuf_len(in_data)) { conn->tls_io_data.in_data = wpabuf_dup(in_data); } - ret = mbedtls_ssl_handshake_step(&tls->ssl); - if (ret < 0) { - wpa_printf(MSG_ERROR, "%s:%d", __func__, __LINE__); - goto end; - } /* Multiple reads */ - while (conn->tls_io_data.in_data) { + while (tls->ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER) { + if (tls->ssl.state == MBEDTLS_SSL_CLIENT_CERTIFICATE) { + /* Read random data before session completes, not present after handshake */ + if (tls->ssl.handshake) { + os_memcpy(conn->randbytes, tls->ssl.handshake->randbytes, + TLS_RANDOM_LEN * 2); + } + } ret = mbedtls_ssl_handshake_step(&tls->ssl); + if (ret < 0) break; } - - /* State machine just started, get client hello */ - if (tls->ssl.state == MBEDTLS_SSL_CLIENT_HELLO) { - ret = mbedtls_ssl_handshake_step(&tls->ssl); - } - - if (ret < 0) { - wpa_printf(MSG_ERROR, "%s:%d", __func__, __LINE__); + if (ret < 0 && ret != MBEDTLS_ERR_SSL_WANT_READ) { + wpa_printf(MSG_INFO, "%s: ret is %d line:%d", __func__, ret, __LINE__); goto end; } - /* Already read sever data till hello done */ - if (tls->ssl.state == MBEDTLS_SSL_CLIENT_CERTIFICATE) { - /* Read random data before session completes, not present after handshake */ - if (tls->ssl.handshake) { - os_memcpy(conn->randbytes, tls->ssl.handshake->randbytes, - TLS_RANDOM_LEN * 2); - } - - /* trigger state machine multiple times to reach till finish */ - while (tls->ssl.state <= MBEDTLS_SSL_CLIENT_FINISHED) { - ret = mbedtls_ssl_handshake_step(&tls->ssl); - if (ret < 0) { - break; - } - } - } - - /* Trigger state machine till handshake is complete or error occures */ - if (tls->ssl.state == MBEDTLS_SSL_FLUSH_BUFFERS) { - while (tls->ssl.state <= MBEDTLS_SSL_HANDSHAKE_OVER) { - ret = mbedtls_ssl_handshake_step(&tls->ssl); - if (ret < 0) { - break; - } - } - } - if (!conn->tls_io_data.out_data) { wpa_printf(MSG_INFO, "application data is null, adding one byte for ack"); u8 *dummy = os_zalloc(1); diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.c b/components/wpa_supplicant/src/rsn_supp/wpa.c index 2d45c11632..2de58804d9 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa.c @@ -2081,7 +2081,7 @@ bool wpa_sm_init(char * payload, WPA_SEND_FUNC snd_func, spp_attrubute = esp_wifi_get_spp_attrubute_internal(WIFI_IF_STA); sm->spp_sup.capable = ((spp_attrubute & WPA_CAPABILITY_SPP_CAPABLE) ? SPP_AMSDU_CAP_ENABLE : SPP_AMSDU_CAP_DISABLE); - sm->spp_sup.require = ((spp_attrubute & WPA_CAPABILITY_SPP_REQUIRED) ? SPP_AMSDU_CAP_ENABLE : SPP_AMSDU_REQ_DISABLE); + sm->spp_sup.require = ((spp_attrubute & WPA_CAPABILITY_SPP_REQUIRED) ? SPP_AMSDU_REQ_ENABLE : SPP_AMSDU_REQ_DISABLE); wpa_sm_set_state(WPA_INACTIVE); diff --git a/components/wpa_supplicant/src/tls/x509v3.c b/components/wpa_supplicant/src/tls/x509v3.c index 3491a5d724..4d99c72ccd 100644 --- a/components/wpa_supplicant/src/tls/x509v3.c +++ b/components/wpa_supplicant/src/tls/x509v3.c @@ -1376,7 +1376,7 @@ static int x509_sha1_oid(struct asn1_oid *oid) oid->oid[5] == 26 /* id-sha1 */; } -static int x509_sha256_oid(struct asn1_oid *oid) +static int x509_sha2_oid(struct asn1_oid *oid) { return oid->len == 9 && oid->oid[0] == 2 /* joint-iso-itu-t */ && @@ -1386,11 +1386,31 @@ static int x509_sha256_oid(struct asn1_oid *oid) oid->oid[4] == 101 /* gov */ && oid->oid[5] == 3 /* csor */ && oid->oid[6] == 4 /* nistAlgorithm */ && - oid->oid[7] == 2 /* hashAlgs */ && + oid->oid[7] == 2 /* hashAlgs */; +} + + +static int x509_sha256_oid(struct asn1_oid *oid) +{ + return x509_sha2_oid(oid) && oid->oid[8] == 1 /* sha256 */; } +static int x509_sha384_oid(struct asn1_oid *oid) +{ + return x509_sha2_oid(oid) && + oid->oid[8] == 2 /* sha384 */; +} + + +static int x509_sha512_oid(struct asn1_oid *oid) +{ + return x509_sha2_oid(oid) && + oid->oid[8] == 3 /* sha512 */; +} + + /** * x509_certificate_parse - Parse a X.509 certificate in DER format * @buf: Pointer to the X.509 certificate in DER format @@ -1515,7 +1535,7 @@ int x509_certificate_check_signature(struct x509_certificate *issuer, size_t data_len; struct asn1_hdr hdr; struct asn1_oid oid; - u8 hash[32]; + u8 hash[64]; size_t hash_len; if (!x509_pkcs_oid(&cert->signature.oid) || @@ -1627,6 +1647,32 @@ int x509_certificate_check_signature(struct x509_certificate *issuer, goto skip_digest_oid; } + if (x509_sha384_oid(&oid)) { + if (cert->signature.oid.oid[6] != + 12 /* sha384WithRSAEncryption */) { + wpa_printf(MSG_DEBUG, "X509: digestAlgorithm SHA384 " + "does not match with certificate " + "signatureAlgorithm (%lu)", + cert->signature.oid.oid[6]); + os_free(data); + return -1; + } + goto skip_digest_oid; + } + + if (x509_sha512_oid(&oid)) { + if (cert->signature.oid.oid[6] != + 13 /* sha512WithRSAEncryption */) { + wpa_printf(MSG_DEBUG, "X509: digestAlgorithm SHA512 " + "does not match with certificate " + "signatureAlgorithm (%lu)", + cert->signature.oid.oid[6]); + os_free(data); + return -1; + } + goto skip_digest_oid; + } + if (!x509_digest_oid(&oid)) { wpa_printf(MSG_DEBUG, "X509: Unrecognized digestAlgorithm"); os_free(data); @@ -1692,9 +1738,21 @@ skip_digest_oid: wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (SHA256)", hash, hash_len); break; - case 2: /* md2WithRSAEncryption */ case 12: /* sha384WithRSAEncryption */ + sha384_vector(1, &cert->tbs_cert_start, &cert->tbs_cert_len, + hash); + hash_len = 48; + wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (SHA384)", + hash, hash_len); + break; case 13: /* sha512WithRSAEncryption */ + sha512_vector(1, &cert->tbs_cert_start, &cert->tbs_cert_len, + hash); + hash_len = 64; + wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (SHA512)", + hash, hash_len); + break; + case 2: /* md2WithRSAEncryption */ default: wpa_printf(MSG_INFO, "X509: Unsupported certificate signature " "algorithm (%lu)", cert->signature.oid.oid[6]); diff --git a/docs/README.md b/docs/README.md index b30d7de2b3..600e308ad9 100644 --- a/docs/README.md +++ b/docs/README.md @@ -15,6 +15,4 @@ The above URLs are all for the master branch latest version. Click the drop-down # Building Documentation -The documentation build requirements Python 3 and running the wrapper `./build_docs.py` tool. Running `./build_docs.py --help` will give a summary of available options. - -See [Documenting Code](https://docs.espressif.com/projects/esp-idf/en/latest/contribute/documenting-code.html) in the ESP-IDF Programming Guide for full information about setting up to build the docs, and how to use the `./build_docs.py` tool. +The documentation is built using the python package `esp-docs`, which can be installed by running `pip install esp-docs`. Running `build-docs --help` will give a summary of available options. For more information see the `esp-docs` documentation at https://github.com/espressif/esp-docs/blob/master/README.md diff --git a/docs/_static/esp-idf-installer-download-server.png b/docs/_static/esp-idf-installer-download-server.png deleted file mode 100644 index 182fade5c3..0000000000 Binary files a/docs/_static/esp-idf-installer-download-server.png and /dev/null differ diff --git a/docs/_static/esp32-c3-devkitc-02-v1-annotated-photo.png b/docs/_static/esp32-c3-devkitc-02-v1-annotated-photo.png index 1da577f0ad..5b05cc38b4 100644 Binary files a/docs/_static/esp32-c3-devkitc-02-v1-annotated-photo.png and b/docs/_static/esp32-c3-devkitc-02-v1-annotated-photo.png differ diff --git a/docs/_static/esp32-c3-devkitm-1-v1-annotated-photo.png b/docs/_static/esp32-c3-devkitm-1-v1-annotated-photo.png index 9ad478b01d..1f8b081d5e 100644 Binary files a/docs/_static/esp32-c3-devkitm-1-v1-annotated-photo.png and b/docs/_static/esp32-c3-devkitm-1-v1-annotated-photo.png differ diff --git a/docs/_static/esp32-s2-devkitm-1-v1-annotated-photo.png b/docs/_static/esp32-s2-devkitm-1-v1-annotated-photo.png index e2e82962da..7da28ae225 100644 Binary files a/docs/_static/esp32-s2-devkitm-1-v1-annotated-photo.png and b/docs/_static/esp32-s2-devkitm-1-v1-annotated-photo.png differ diff --git a/docs/_static/esp32-s2-devkitm-1-v1-pin-layout.png b/docs/_static/esp32-s2-devkitm-1-v1-pin-layout.png new file mode 100644 index 0000000000..7b24a546d3 Binary files /dev/null and b/docs/_static/esp32-s2-devkitm-1-v1-pin-layout.png differ diff --git a/docs/_static/esp32-s2-devkitm-1u-v1-annotated-photo.png b/docs/_static/esp32-s2-devkitm-1u-v1-annotated-photo.png index db9b4349ac..3cb77d6ae0 100644 Binary files a/docs/_static/esp32-s2-devkitm-1u-v1-annotated-photo.png and b/docs/_static/esp32-s2-devkitm-1u-v1-annotated-photo.png 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 index 10fd2b1a78..0178b16129 100644 Binary files a/docs/_static/esp32-s2-saola-1-v1.2-annotated-photo.png and b/docs/_static/esp32-s2-saola-1-v1.2-annotated-photo.png differ diff --git a/docs/_static/modbus-data-mapping.png b/docs/_static/modbus-data-mapping.png new file mode 100644 index 0000000000..18fd2cf4fe Binary files /dev/null and b/docs/_static/modbus-data-mapping.png differ diff --git a/docs/_static/modbus-segment.png b/docs/_static/modbus-segment.png new file mode 100644 index 0000000000..80fb6bfe6a Binary files /dev/null and b/docs/_static/modbus-segment.png differ diff --git a/docs/build_docs.py b/docs/build_docs.py deleted file mode 100755 index 4ea2346522..0000000000 --- a/docs/build_docs.py +++ /dev/null @@ -1,472 +0,0 @@ -#!/usr/bin/env python3 -# coding=utf-8 -# -# Top-level docs builder -# -# This is just a front-end to sphinx-build that can call it multiple times for different language/target combinations -# -# Will build out to _build/LANG/TARGET by default -# -# Specific custom docs functionality should be added in conf_common.py or in a Sphinx extension, not here. -# -# 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. -# -from __future__ import print_function - -import argparse -import locale -import math -import multiprocessing -import os -import os.path -import re -import subprocess -import sys -from collections import namedtuple - -from packaging import version - -LANGUAGES = ['en', 'zh_CN'] -TARGETS = ['esp32', 'esp32s2', 'esp32s3', 'esp32c3'] - -SPHINX_WARN_LOG = 'sphinx-warning-log.txt' -SPHINX_SANITIZED_LOG = 'sphinx-warning-log-sanitized.txt' -SPHINX_KNOWN_WARNINGS = os.path.join(os.environ['IDF_PATH'], 'docs', 'sphinx-known-warnings.txt') - -DXG_WARN_LOG = 'doxygen-warning-log.txt' -DXG_SANITIZED_LOG = 'doxygen-warning-log-sanitized.txt' -DXG_KNOWN_WARNINGS = os.path.join(os.environ['IDF_PATH'], 'docs', 'doxygen-known-warnings.txt') -DXG_CI_VERSION = version.parse('1.8.11') - -LogMessage = namedtuple('LogMessage', 'original_text sanitized_text') - -languages = LANGUAGES -targets = TARGETS - - -def main(): - # check Python dependencies for docs - try: - subprocess.check_call([sys.executable, - os.path.join(os.environ['IDF_PATH'], - 'tools', - 'check_python_dependencies.py'), - '-r', - '{}/docs/requirements.txt'.format(os.environ['IDF_PATH']) - ]) - except subprocess.CalledProcessError: - raise SystemExit(2) # stdout will already have these errors - - # This is not the only way to make sure that all files opened by Python are treated as UTF-8, but the other way is passing encoding='utf-8' to all open() - # functions and this way makes Python 2 compatibility really tough if there is any code that assumes text files contain strings (kconfiglib assumes this). - # The reason for that is that you need to import io.open() to support the encoding argument on Python 2, and this function always uses Py2's unicode - # type not the str type. - if ('UTF-8' not in locale.getlocale()) and ('utf8' not in locale.getlocale()): - raise RuntimeError("build_docs.py requires the default locale's encoding to be UTF-8.\n" + - ' - Linux. Setting environment variable LC_ALL=C.UTF-8 when running build_docs.py may be ' + - 'enough to fix this.\n' - ' - Windows. Possible solution for the Windows 10 starting version 1803. Go to ' + - 'Control Panel->Clock and Region->Region->Administrative->Change system locale...; ' + - 'Check `Beta: Use Unicode UTF-8 for worldwide language support` and reboot') - - parser = argparse.ArgumentParser(description='build_docs.py: Build IDF docs', prog='build_docs.py') - - parser.add_argument('--language', '-l', choices=LANGUAGES, required=False) - parser.add_argument('--target', '-t', choices=TARGETS, required=False) - parser.add_argument('--build-dir', '-b', type=str, default='_build') - parser.add_argument('--source-dir', '-s', type=str, default='') - parser.add_argument('--builders', '-bs', nargs='+', type=str, default=['html'], - help='List of builders for Sphinx, e.g. html or latex, for latex a PDF is also generated') - parser.add_argument('--sphinx-parallel-builds', '-p', choices=['auto'] + [str(x) for x in range(8)], - help='Parallel Sphinx builds - number of independent Sphinx builds to run', default='auto') - parser.add_argument('--sphinx-parallel-jobs', '-j', choices=['auto'] + [str(x) for x in range(8)], - help='Sphinx parallel jobs argument - number of threads for each Sphinx build to use', default='1') - parser.add_argument('--input-docs', '-i', nargs='+', default=[''], - help='List of documents to build relative to the doc base folder, i.e. the language folder. Defaults to all documents') - - action_parsers = parser.add_subparsers(dest='action') - - build_parser = action_parsers.add_parser('build', help='Build documentation') - build_parser.add_argument('--check-warnings-only', '-w', action='store_true') - build_parser.add_argument('--fast-build', '-f', action='store_true', help='Skips including doxygen generated APIs into the Sphinx build') - - action_parsers.add_parser('linkcheck', help='Check links (a current IDF revision should be uploaded to GitHub)') - - action_parsers.add_parser('gh-linkcheck', help='Checking for hardcoded GitHub links') - - args = parser.parse_args() - - global languages - if args.language is None: - print('Building all languages') - languages = LANGUAGES - else: - languages = [args.language] - - global targets - if args.target is None: - print('Building all targets') - targets = TARGETS - else: - targets = [args.target] - - if args.action == 'build' or args.action is None: - if args.action is None: - args.check_warnings_only = False - args.fast_build = False - - if args.fast_build: - os.environ['DOCS_FAST_BUILD'] = 'y' - - sys.exit(action_build(args)) - - if args.action == 'linkcheck': - sys.exit(action_linkcheck(args)) - - if args.action == 'gh-linkcheck': - sys.exit(action_gh_linkcheck(args)) - - -def parallel_call(args, callback): - num_sphinx_builds = len(languages) * len(targets) - num_cpus = multiprocessing.cpu_count() - - if args.sphinx_parallel_builds == 'auto': - # at most one sphinx build per CPU, up to the number of CPUs - args.sphinx_parallel_builds = min(num_sphinx_builds, num_cpus) - else: - args.sphinx_parallel_builds = int(args.sphinx_parallel_builds) - - # Force -j1 because sphinx works incorrectly - args.sphinx_parallel_jobs = 1 - if args.sphinx_parallel_jobs == 'auto': - # N CPUs per build job, rounded up - (maybe smarter to round down to avoid contention, idk) - args.sphinx_parallel_jobs = int(math.ceil(num_cpus / args.sphinx_parallel_builds)) - else: - args.sphinx_parallel_jobs = int(args.sphinx_parallel_jobs) - - print('Will use %d parallel builds and %d jobs per build' % (args.sphinx_parallel_builds, args.sphinx_parallel_jobs)) - pool = multiprocessing.Pool(args.sphinx_parallel_builds) - - if args.sphinx_parallel_jobs > 1: - print('WARNING: Sphinx parallel jobs currently produce incorrect docs output with Sphinx 1.8.5') - - # make a list of all combinations of build_docs() args as tuples - # - # there's probably a fancy way to do this with itertools but this way is actually readable - entries = [] - for target in targets: - for language in languages: - build_dir = os.path.realpath(os.path.join(args.build_dir, language, target)) - source_dir = os.path.join(os.path.abspath(os.path.dirname(__file__)), args.source_dir, language) - - entries.append((language, target, build_dir, source_dir, args.sphinx_parallel_jobs, args.builders, args.input_docs)) - - print(entries) - errcodes = pool.map(callback, entries) - print(errcodes) - - is_error = False - for ret in errcodes: - if ret != 0: - print('\nThe following language/target combinations failed to build:') - is_error = True - break - if is_error: - for ret, entry in zip(errcodes, entries): - if ret != 0: - print('language: %s, target: %s, errcode: %d' % (entry[0], entry[1], ret)) - # Don't re-throw real error code from each parallel process - return 1 - else: - return 0 - - -def sphinx_call(language, target, build_dir, src_dir, sphinx_parallel_jobs, buildername, input_docs): - # Note: because this runs in a multiprocessing Process, everything which happens here should be isolated to a single process - # (ie it doesn't matter if Sphinx is using global variables, as they're it's own copy of the global variables) - - # wrap stdout & stderr in a way that lets us see which build_docs instance they come from - # - # this doesn't apply to subprocesses, they write to OS stdout & stderr so no prefix appears - prefix = '%s/%s: ' % (language, target) - - print('Building in build_dir: %s' % (build_dir)) - try: - os.makedirs(build_dir) - except OSError: - pass - - environ = {} - environ.update(os.environ) - environ['BUILDDIR'] = build_dir - - args = [sys.executable, '-u', '-m', 'sphinx.cmd.build', - '-j', str(sphinx_parallel_jobs), - '-b', buildername, - '-d', os.path.join(build_dir, 'doctrees'), - '-w', SPHINX_WARN_LOG, - '-t', target, - '-D', 'idf_target={}'.format(target), - '-D', 'docs_to_build={}'.format(','. join(input_docs)), - src_dir, - os.path.join(build_dir, buildername) # build directory - ] - - saved_cwd = os.getcwd() - os.chdir(build_dir) # also run sphinx in the build directory - print("Running '%s'" % (' '.join(args))) - - ret = 1 - try: - # Note: we can't call sphinx.cmd.build.main() here as multiprocessing doesn't est >1 layer deep - # and sphinx.cmd.build() also does a lot of work in the calling thread, especially for j ==1, - # so using a Pyhthon thread for this part is a poor option (GIL) - p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - for c in iter(lambda: p.stdout.readline(), b''): - sys.stdout.write(prefix) - sys.stdout.write(c.decode('utf-8')) - ret = p.wait() - assert (ret is not None) - sys.stdout.flush() - except KeyboardInterrupt: # this seems to be the only way to get Ctrl-C to kill everything? - p.kill() - os.chdir(saved_cwd) - return 130 # FIXME It doesn't return this errorcode, why? Just prints stacktrace - os.chdir(saved_cwd) - return ret - - -def action_build(args): - if not args.check_warnings_only: - ret = parallel_call(args, call_build_docs) - if ret != 0: - return ret - - -def check_doxygen_version(): - # Different version of doxygen may produce different warnings - # This could cause a build to fail locally, but pass CI and vice versa - process = subprocess.run(['doxygen', '--version'], encoding='utf-8', stdout=subprocess.PIPE) - doxygen_ver = process.stdout.strip() - - if version.parse(doxygen_ver) > DXG_CI_VERSION: - print('Local doxygen version {} is newer than CI doxygen version {}. Local build may contain ' - 'warnings that will not be raised when built by CI.'.format(doxygen_ver, DXG_CI_VERSION)) - - -def call_build_docs(entry): - (language, target, build_dir, src_dir, sphinx_parallel_jobs, builders, input_docs) = entry - for buildername in builders: - ret = sphinx_call(language, target, build_dir, src_dir, sphinx_parallel_jobs, buildername, input_docs) - - # Warnings are checked after each builder as logs are overwritten - # check Doxygen warnings: - ret += check_docs(language, target, - log_file=os.path.join(build_dir, DXG_WARN_LOG), - known_warnings_file=DXG_KNOWN_WARNINGS, - out_sanitized_log_file=os.path.join(build_dir, DXG_SANITIZED_LOG)) - # check Sphinx warnings: - ret += check_docs(language, target, - log_file=os.path.join(build_dir, SPHINX_WARN_LOG), - known_warnings_file=SPHINX_KNOWN_WARNINGS, - out_sanitized_log_file=os.path.join(build_dir, SPHINX_SANITIZED_LOG)) - - if ret != 0: - check_doxygen_version() - return ret - - # Build PDF from tex - if 'latex' in builders: - latex_dir = os.path.join(build_dir, 'latex') - ret = build_pdf(language, target, latex_dir) - - return ret - - -def build_pdf(language, target, latex_dir): - # Note: because this runs in a multiprocessing Process, everything which happens here should be isolated to a single process - - # wrap stdout & stderr in a way that lets us see which build_docs instance they come from - # - # this doesn't apply to subprocesses, they write to OS stdout & stderr so no prefix appears - prefix = '%s/%s: ' % (language, target) - - print('Building PDF in latex_dir: %s' % (latex_dir)) - - saved_cwd = os.getcwd() - os.chdir(latex_dir) - - # Based on read the docs PDFBuilder - rcfile = 'latexmkrc' - - cmd = [ - 'latexmk', - '-r', - rcfile, - '-pdf', - # When ``-f`` is used, latexmk will continue building if it - # encounters errors. We still receive a failure exit code in this - # case, but the correct steps should run. - '-f', - '-dvi-', # dont generate dvi - '-ps-', # dont generate ps - '-interaction=nonstopmode', - '-quiet', - '-outdir=build', - ] - - try: - p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - for c in iter(lambda: p.stdout.readline(), b''): - sys.stdout.write(prefix) - sys.stdout.write(c.decode('utf-8')) - ret = p.wait() - assert (ret is not None) - sys.stdout.flush() - except KeyboardInterrupt: # this seems to be the only way to get Ctrl-C to kill everything? - p.kill() - os.chdir(saved_cwd) - return 130 # FIXME It doesn't return this errorcode, why? Just prints stacktrace - os.chdir(saved_cwd) - - return ret - - -SANITIZE_FILENAME_REGEX = re.compile('[^:]*/([^/:]*)(:.*)') -SANITIZE_LINENUM_REGEX = re.compile('([^:]*)(:[0-9]+:)(.*)') - - -def sanitize_line(line): - """ - Clear a log message from insignificant parts - - filter: - - only filename, no path at the beginning - - no line numbers after the filename - """ - - line = re.sub(SANITIZE_FILENAME_REGEX, r'\1\2', line) - line = re.sub(SANITIZE_LINENUM_REGEX, r'\1:line:\3', line) - return line - - -def check_docs(language, target, log_file, known_warnings_file, out_sanitized_log_file): - """ - Check for Documentation warnings in `log_file`: should only contain (fuzzy) matches to `known_warnings_file` - - It prints all unknown messages with `target`/`language` prefix - It leaves `out_sanitized_log_file` file for observe and debug - """ - - # Sanitize all messages - all_messages = list() - with open(log_file) as f, open(out_sanitized_log_file, 'w') as o: - for line in f: - sanitized_line = sanitize_line(line) - all_messages.append(LogMessage(line, sanitized_line)) - o.write(sanitized_line) - - known_messages = list() - with open(known_warnings_file) as k: - for known_line in k: - known_messages.append(known_line) - - if 'doxygen' in known_warnings_file: - # Clean a known Doxygen limitation: it's expected to always document anonymous - # structs/unions but we don't do this in our docs, so filter these all out with a regex - # (this won't match any named field, only anonymous members - - # ie the last part of the field is is just ::@NUM not ::name) - RE_ANONYMOUS_FIELD = re.compile(r'.+:line: warning: parameters of member [^:\s]+(::[^:\s]+)*(::@\d+)+ are not \(all\) documented') - all_messages = [msg for msg in all_messages if not re.match(RE_ANONYMOUS_FIELD, msg.sanitized_text)] - - # Collect all new messages that are not match with the known messages. - # The order is an important. - new_messages = list() - known_idx = 0 - for msg in all_messages: - try: - known_idx = known_messages.index(msg.sanitized_text, known_idx) - except ValueError: - new_messages.append(msg) - - if new_messages: - print('\n%s/%s: Build failed due to new/different warnings (%s):\n' % (language, target, log_file)) - for msg in new_messages: - print('%s/%s: %s' % (language, target, msg.original_text), end='') - print('\n%s/%s: (Check files %s and %s for full details.)' % (language, target, known_warnings_file, log_file)) - return 1 - - return 0 - - -def action_linkcheck(args): - args.builders = 'linkcheck' - return parallel_call(args, call_linkcheck) - - -def call_linkcheck(entry): - return sphinx_call(*entry) - - -# https://github.com/espressif/esp-idf/tree/ -# https://github.com/espressif/esp-idf/blob/ -# https://github.com/espressif/esp-idf/raw/ -GH_LINK_RE = r'https://github.com/espressif/esp-idf/(?:tree|blob|raw)/[^\s]+' - -# we allow this one doc, because we always want users to see the latest support policy -GH_LINK_ALLOWED = ['https://github.com/espressif/esp-idf/blob/master/SUPPORT_POLICY.md', - 'https://github.com/espressif/esp-idf/blob/master/SUPPORT_POLICY_CN.md'] - - -def action_gh_linkcheck(args): - print('Checking for hardcoded GitHub links\n') - - github_links = [] - - docs_dir = os.path.relpath(os.path.dirname(__file__)) - for root, _, files in os.walk(docs_dir): - if '_build' in root: - continue - files = [os.path.join(root, f) for f in files if f.endswith('.rst')] - for path in files: - with open(path, 'r') as f: - for link in re.findall(GH_LINK_RE, f.read()): - if link not in GH_LINK_ALLOWED: - github_links.append((path, link)) - - if github_links: - for path, link in github_links: - print('%s: %s' % (path, link)) - print('WARNING: Some .rst files contain hardcoded Github links.') - print('Please check above output and replace links with one of the following:') - print('- :idf:`dir` - points to directory inside ESP-IDF') - print('- :idf_file:`file` - points to file inside ESP-IDF') - print('- :idf_raw:`file` - points to raw view of the file inside ESP-IDF') - print('- :component:`dir` - points to directory inside ESP-IDF components dir') - print('- :component_file:`file` - points to file inside ESP-IDF components dir') - print('- :component_raw:`file` - points to raw view of the file inside ESP-IDF components dir') - print('- :example:`dir` - points to directory inside ESP-IDF examples dir') - print('- :example_file:`file` - points to file inside ESP-IDF examples dir') - print('- :example_raw:`file` - points to raw view of the file inside ESP-IDF examples dir') - print('These link types will point to the correct GitHub version automatically') - return 1 - else: - print('No hardcoded links found') - return 0 - - -if __name__ == '__main__': - main() diff --git a/docs/conf_common.py b/docs/conf_common.py index 390b106f95..6210a9a23f 100644 --- a/docs/conf_common.py +++ b/docs/conf_common.py @@ -1,138 +1,22 @@ # -*- coding: utf-8 -*- # -# Common (non-language-specific) configuration for Read The Docs & Sphinx -# -# Based on a Read the Docs Template documentation build configuration file, -# created by sphinx-quickstart on Tue Aug 26 14:19:49 2014. +# Common (non-language-specific) configuration for Sphinx # # This file is imported from a language-specific conf.py (ie en/conf.py or # zh_CN/conf.py) -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. + +# type: ignore +# pylint: disable=wildcard-import +# pylint: disable=undefined-variable from __future__ import print_function, unicode_literals -import os import os.path -import re -import subprocess -import sys -from get_github_rev import get_github_rev -from idf_extensions.util import download_file_if_missing -from sanitize_version import sanitize_version +from esp_docs.conf_docs import * # noqa: F403,F401 -# build_docs on the CI server sometimes fails under Python3. This is a workaround: -sys.setrecursionlimit(3500) - -config_dir = os.path.abspath(os.path.dirname(__file__)) - -# http://stackoverflow.com/questions/12772927/specifying-an-online-image-in-sphinx-restructuredtext-format -# -suppress_warnings = ['image.nonlocal_uri'] - -# -- General configuration ------------------------------------------------ - -# If your documentation needs a minimal Sphinx version, state it here. -# needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = ['breathe', - - 'sphinx.ext.todo', - 'sphinx_copybutton', - 'sphinx_idf_theme', - 'sphinxcontrib.blockdiag', - 'sphinxcontrib.seqdiag', - 'sphinxcontrib.actdiag', - 'sphinxcontrib.nwdiag', - 'sphinxcontrib.rackdiag', - 'sphinxcontrib.packetdiag', - 'sphinxcontrib.cairosvgconverter', - - 'extensions.html_redirects', - 'extensions.toctree_filter', - 'extensions.list_filter', - 'extensions.google_analytics', - - # Note: order is important here, events must - # be registered by one extension before they can be - # connected to another extension - - 'idf_extensions.include_build_file', - 'idf_extensions.link_roles', - 'idf_extensions.build_system', - 'idf_extensions.esp_err_definitions', - 'idf_extensions.gen_toolchain_links', - 'idf_extensions.gen_version_specific_includes', - 'idf_extensions.kconfig_reference', - 'idf_extensions.gen_defines', - 'idf_extensions.run_doxygen', - 'idf_extensions.gen_idf_tools_links', - 'idf_extensions.format_idf_target', - 'idf_extensions.latex_builder', - 'idf_extensions.exclude_docs', - - # from https://github.com/pfalcon/sphinx_selective_exclude - 'sphinx_selective_exclude.eager_only', - # TODO: determine if we need search_auto_exclude - # 'sphinx_selective_exclude.search_auto_exclude', - ] - -# sphinx.ext.todo extension parameters -# If the below parameter is True, the extension -# produces output, else it produces nothing. -todo_include_todos = False - -# Enabling this fixes cropping of blockdiag edge labels -seqdiag_antialias = True - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = ['.rst', '.md'] - -source_parsers = {'.md': 'recommonmark.parser.CommonMarkParser', - } - -# The encoding of source files. -# source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = 'index' - - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# - -# This is the full exact version, canonical git version description -# visible when you open index.html. -version = subprocess.check_output(['git', 'describe']).strip().decode('utf-8') - -# The 'release' version is the same as version for non-CI builds, but for CI -# builds on a branch then it's replaced with the branch name -release = sanitize_version(version) - -print('Version: {0} Release: {1}'.format(version, release)) - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -# today = '' -# Else, today_fmt is used as the format for a strftime call. -# today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = ['**/inc/**', '_static/', '_build/**'] +if os.environ.get('IDF_PATH') is None: + raise RuntimeError('IDF_PATH should be set, run export.sh before building docs') BT_DOCS = ['api-guides/blufi.rst', 'api-guides/esp-ble-mesh/**', @@ -165,6 +49,7 @@ LEGACY_DOCS = ['api-guides/build-system-legacy.rst', 'get-started-legacy/**'] USB_DOCS = ['api-reference/peripherals/usb_device.rst', + 'api-reference/peripherals/usb_host.rst', 'api-guides/usb-otg-console.rst', 'api-guides/dfu.rst'] @@ -194,7 +79,6 @@ ESP32_DOCS = ['api-guides/ulp_instruction_set.rst', ESP32S2_DOCS = ['hw-reference/esp32s2/**', 'api-guides/ulps2_instruction_set.rst', 'api-guides/usb-console.rst', - 'api-reference/peripherals/hmac.rst', 'api-reference/peripherals/ds.rst', 'api-reference/peripherals/spi_slave_hd.rst', 'api-reference/peripherals/temp_sensor.rst', @@ -232,284 +116,34 @@ conditional_include_dict = {'SOC_BT_SUPPORTED':BT_DOCS, 'esp32s3':ESP32S3_DOCS, 'esp32c3':ESP32C3_DOCS} -# The reST default role (used for this markup: `text`) to use for all -# documents. -# default_role = None +extensions += ['sphinx_copybutton', + # Note: order is important here, events must + # be registered by one extension before they can be + # connected to another extension + 'esp_docs.idf_extensions.build_system', + 'esp_docs.idf_extensions.esp_err_definitions', + 'esp_docs.idf_extensions.gen_toolchain_links', + 'esp_docs.idf_extensions.gen_defines', + 'esp_docs.idf_extensions.gen_version_specific_includes', + 'esp_docs.idf_extensions.kconfig_reference', + 'esp_docs.idf_extensions.gen_idf_tools_links', + 'esp_docs.esp_extensions.run_doxygen', + ] -# If true, '()' will be appended to :func: etc. cross-reference text. -# add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -# add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -# show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -# modindex_common_prefix = [] - -# If true, keep warnings as "system message" paragraphs in the built documents. -# keep_warnings = False +# link roles config +github_repo = 'espressif/esp-idf' +# context used by sphinx_idf_theme +html_context['github_user'] = 'espressif' +html_context['github_repo'] = 'esp-idf' # Extra options required by sphinx_idf_theme project_slug = 'esp-idf' versions_url = 'https://dl.espressif.com/dl/esp-idf/idf_versions.js' -idf_targets = ['esp32', 'esp32s2', 'esp32c3'] +idf_targets = ['esp32', 'esp32s2', 'esp32s3', 'esp32c3'] languages = ['en', 'zh_CN'] -project_homepage = 'https://github.com/espressif/esp-idf' - -# -- Options for HTML output ---------------------------------------------- - -# Custom added feature to allow redirecting old URLs -# -# Redirects should be listed in page_redirects.xt -# -with open('../page_redirects.txt') as f: - lines = [re.sub(' +', ' ', line.strip()) for line in f.readlines() if line.strip() != '' and not line.startswith('#')] - for line in lines: # check for well-formed entries - if len(line.split(' ')) != 2: - raise RuntimeError('Invalid line in page_redirects.txt: %s' % line) -html_redirect_pages = [tuple(line.split(' ')) for line in lines] - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. - -html_theme = 'sphinx_idf_theme' - -# context used by sphinx_idf_theme -html_context = { - 'display_github': True, # Add 'Edit on Github' link instead of 'View page source' - 'github_user': 'espressif', - 'github_repo': 'esp-idf', - 'github_version': get_github_rev(), -} - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -# html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -# html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -# html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -# html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -html_logo = '../_static/espressif-logo.svg' - - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -# html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['../_static'] - -# Add any extra paths that contain custom files (such as robots.txt or -# .htaccess) here, relative to this directory. These files are copied -# directly to the root of the documentation. -# html_extra_path = [] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -# html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -# html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -# html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -# html_additional_pages = {} - -# If false, no module index is generated. -# html_domain_indices = True - -# If false, no index is generated. -# html_use_index = True - -# If true, the index is split into individual pages for each letter. -# html_split_index = False - -# If true, links to the reST sources are added to the pages. -# html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -# html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -# html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -# html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -# html_file_suffix = None - -# Output file base name for HTML help builder. -htmlhelp_basename = 'ReadtheDocsTemplatedoc' - google_analytics_id = os.environ.get('CI_GOOGLE_ANALYTICS_ID', None) -# -- Options for LaTeX output --------------------------------------------- - -latex_template_dir = os.path.join(config_dir, 'latex_templates') - -preamble = '' -with open(os.path.join(latex_template_dir, 'preamble.tex')) as f: - preamble = f.read() - -titlepage = '' -with open(os.path.join(latex_template_dir, 'titlepage.tex')) as f: - titlepage = f.read() - - -latex_elements = { - 'papersize': 'a4paper', - - # Latex figure (float) alignment - 'figure_align':'htbp', - - 'pointsize': '10pt', - - # Additional stuff for the LaTeX preamble. - 'fncychap': '\\usepackage[Sonny]{fncychap}', - - 'preamble': preamble, - - 'maketitle': titlepage, -} - -# The name of an image file (relative to this directory) to place at the bottom of -# the title page. -latex_logo = '../_static/espressif2.pdf' -latex_engine = 'xelatex' -latex_use_xindy = False - -# -- Options for manual page output --------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ('index', 'readthedocstemplate', u'Read the Docs Template Documentation', - [u'Read the Docs'], 1) -] - -# If true, show URL addresses after external links. -# man_show_urls = False - - -# -- Options for Texinfo output ------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ('index', 'ReadtheDocsTemplate', u'Read the Docs Template Documentation', - u'Read the Docs', 'ReadtheDocsTemplate', 'One line description of project.', - 'Miscellaneous'), -] - -# Documents to append as an appendix to all manuals. -# texinfo_appendices = [] - -# If false, no module index is generated. -# texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -# texinfo_show_urls = 'footnote' - -# If true, do not generate a @detailmenu in the "Top" node's menu. -# texinfo_no_detailmenu = False - - -# Override RTD CSS theme to introduce the theme corrections -# https://github.com/rtfd/sphinx_rtd_theme/pull/432 -def setup(app): - app.add_stylesheet('theme_overrides.css') - - # these two must be pushed in by build_docs.py - if 'idf_target' not in app.config: - app.add_config_value('idf_target', None, 'env') - app.add_config_value('idf_targets', None, 'env') - - app.add_config_value('conditional_include_dict', None, 'env') - app.add_config_value('docs_to_build', None, 'env') - - # Breathe extension variables (depend on build_dir) - # note: we generate into xml_in and then copy_if_modified to xml dir - app.config.breathe_projects = {'esp32-idf': os.path.join(app.config.build_dir, 'xml_in/')} - app.config.breathe_default_project = 'esp32-idf' - - setup_diag_font(app) - - # Config values pushed by -D using the cmdline is not available when setup is called - app.connect('config-inited', setup_config_values) - app.connect('config-inited', setup_html_context) - - -def setup_config_values(app, config): - # Sets up global config values needed by other extensions - idf_target_title_dict = { - 'esp32': 'ESP32', - 'esp32s2': 'ESP32-S2', - 'esp32c3': 'ESP32-C3' - } - - app.add_config_value('idf_target_title_dict', idf_target_title_dict, 'env') - - pdf_name = 'esp-idf-{}-{}-{}'.format(app.config.language, app.config.version, app.config.idf_target) - app.add_config_value('pdf_file', pdf_name, 'env') - - -def setup_html_context(app, config): - # Setup path for 'edit on github'-link - config.html_context['conf_py_path'] = '/docs/{}/'.format(app.config.language) - - -def setup_diag_font(app): - # blockdiag and other tools require a font which supports their character set - # the font file is stored on the download server to save repo size - - font_name = { - 'en': 'DejaVuSans.ttf', - 'zh_CN': 'NotoSansSC-Regular.otf', - }[app.config.language] - - font_dir = os.path.join(config_dir, '_static') - assert os.path.exists(font_dir) - - print('Downloading font file %s for %s' % (font_name, app.config.language)) - download_file_if_missing('https://dl.espressif.com/dl/esp-idf/docs/_static/{}'.format(font_name), font_dir) - - font_path = os.path.abspath(os.path.join(font_dir, font_name)) - assert os.path.exists(font_path) - - app.config.blockdiag_fontpath = font_path - app.config.seqdiag_fontpath = font_path - app.config.actdiag_fontpath = font_path - app.config.nwdiag_fontpath = font_path - app.config.rackdiag_fontpath = font_path - app.config.packetdiag_fontpath = font_path +project_homepage = 'https://github.com/espressif/esp-idf' diff --git a/docs/doxygen/Doxyfile b/docs/doxygen/Doxyfile new file mode 100644 index 0000000000..42781bcdf9 --- /dev/null +++ b/docs/doxygen/Doxyfile @@ -0,0 +1,269 @@ +# This is Doxygen configuration file +# +# Doxygen provides over 260 configuration statements +# To make this file easier to follow, +# it contains only statements that are non-default +# +# NOTE: +# It is recommended not to change defaults unless specifically required +# Test any changes how they affect generated documentation +# Make sure that correct warnings are generated to flag issues with documented code +# +# For the complete list of configuration statements see: +# http://doxygen.nl/manual/config.html + + +PROJECT_NAME = "IDF Programming Guide" + +## The 'INPUT' statement below is used as input by script 'gen-df-input.py' +## to automatically generate API reference list files heder_file.inc +## These files are placed in '_inc' directory +## and used to include in API reference documentation + +INPUT = \ + $(PROJECT_PATH)/components/tinyusb/additions/include/tinyusb.h \ + $(PROJECT_PATH)/components/tinyusb/additions/include/tinyusb_types.h \ + $(PROJECT_PATH)/components/tinyusb/additions/include/tusb_cdc_acm.h \ + $(PROJECT_PATH)/components/tinyusb/additions/include/tusb_config.h \ + $(PROJECT_PATH)/components/tinyusb/additions/include/tusb_console.h \ + $(PROJECT_PATH)/components/tinyusb/additions/include/tusb_tasks.h \ + $(PROJECT_PATH)/components/tinyusb/additions/include/vfs_tinyusb.h \ + $(PROJECT_PATH)/components/esp_wifi/include/esp_wifi.h \ + $(PROJECT_PATH)/components/esp_wifi/include/esp_wifi_types.h \ + $(PROJECT_PATH)/components/esp_wifi/include/esp_smartconfig.h \ + $(PROJECT_PATH)/components/esp_wifi/include/esp_now.h \ + $(PROJECT_PATH)/components/esp_wifi/include/esp_wifi_default.h \ + $(PROJECT_PATH)/components/esp_wifi/include/esp_mesh.h \ + $(PROJECT_PATH)/components/wpa_supplicant/esp_supplicant/include/esp_dpp.h \ + $(PROJECT_PATH)/components/esp_event/include/esp_event.h \ + $(PROJECT_PATH)/components/esp_event/include/esp_event_base.h \ + $(PROJECT_PATH)/components/esp_event/include/esp_event_legacy.h \ + $(PROJECT_PATH)/components/bt/include/esp32/include/esp_bt.h \ + $(PROJECT_PATH)/components/bt/common/api/include/api/esp_blufi_api.h \ + $(PROJECT_PATH)/components/bt/host/bluedroid/api/include/api/esp_bt_defs.h \ + $(PROJECT_PATH)/components/bt/host/bluedroid/api/include/api/esp_bt_main.h \ + $(PROJECT_PATH)/components/bt/host/bluedroid/api/include/api/esp_bt_device.h \ + $(PROJECT_PATH)/components/bt/host/bluedroid/api/include/api/esp_gap_ble_api.h \ + $(PROJECT_PATH)/components/bt/host/bluedroid/api/include/api/esp_gatt_defs.h \ + $(PROJECT_PATH)/components/bt/host/bluedroid/api/include/api/esp_gatts_api.h \ + $(PROJECT_PATH)/components/bt/host/bluedroid/api/include/api/esp_gattc_api.h \ + $(PROJECT_PATH)/components/bt/host/bluedroid/api/include/api/esp_gap_bt_api.h \ + $(PROJECT_PATH)/components/bt/host/bluedroid/api/include/api/esp_a2dp_api.h \ + $(PROJECT_PATH)/components/bt/host/bluedroid/api/include/api/esp_avrc_api.h \ + $(PROJECT_PATH)/components/bt/host/bluedroid/api/include/api/esp_spp_api.h \ + $(PROJECT_PATH)/components/bt/host/bluedroid/api/include/api/esp_hf_defs.h \ + $(PROJECT_PATH)/components/bt/host/bluedroid/api/include/api/esp_hf_client_api.h \ + $(PROJECT_PATH)/components/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h \ + $(PROJECT_PATH)/components/bt/host/nimble/esp-hci/include/esp_nimble_hci.h \ + $(PROJECT_PATH)/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_common_api.h \ + $(PROJECT_PATH)/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_local_data_operation_api.h \ + $(PROJECT_PATH)/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_low_power_api.h \ + $(PROJECT_PATH)/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_networking_api.h \ + $(PROJECT_PATH)/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_provisioning_api.h \ + $(PROJECT_PATH)/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_proxy_api.h \ + $(PROJECT_PATH)/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_config_model_api.h \ + $(PROJECT_PATH)/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_generic_model_api.h \ + $(PROJECT_PATH)/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_health_model_api.h \ + $(PROJECT_PATH)/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_lighting_model_api.h \ + $(PROJECT_PATH)/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_sensor_model_api.h \ + $(PROJECT_PATH)/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_time_scene_model_api.h \ + $(PROJECT_PATH)/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h \ + $(PROJECT_PATH)/components/esp_eth/include/esp_eth.h \ + $(PROJECT_PATH)/components/esp_eth/include/esp_eth_com.h \ + $(PROJECT_PATH)/components/esp_eth/include/esp_eth_mac.h \ + $(PROJECT_PATH)/components/esp_eth/include/esp_eth_phy.h \ + $(PROJECT_PATH)/components/esp_eth/include/esp_eth_netif_glue.h \ + $(PROJECT_PATH)/components/hal/include/hal/adc_types.h \ + $(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/adc_channel.h \ + $(PROJECT_PATH)/components/driver/include/driver/adc_common.h \ + $(PROJECT_PATH)/components/driver/$(IDF_TARGET)/include/driver/adc.h \ + $(PROJECT_PATH)/components/esp_adc_cal/include/esp_adc_cal.h \ + $(PROJECT_PATH)/components/hal/include/hal/dac_types.h \ + $(PROJECT_PATH)/components/driver/include/driver/dac_common.h \ + $(PROJECT_PATH)/components/hal/include/hal/gpio_types.h \ + $(PROJECT_PATH)/components/driver/include/driver/gpio.h \ + $(PROJECT_PATH)/components/driver/include/driver/dedic_gpio.h \ + $(PROJECT_PATH)/components/hal/include/hal/rtc_io_types.h \ + $(PROJECT_PATH)/components/driver/include/driver/rtc_io.h \ + $(PROJECT_PATH)/components/hal/include/hal/i2c_types.h \ + $(PROJECT_PATH)/components/driver/include/driver/i2c.h \ + $(PROJECT_PATH)/components/hal/include/hal/i2s_types.h \ + $(PROJECT_PATH)/components/driver/include/driver/i2s.h \ + $(PROJECT_PATH)/components/hal/include/hal/ledc_types.h \ + $(PROJECT_PATH)/components/driver/include/driver/ledc.h \ + $(PROJECT_PATH)/components/hal/include/hal/rmt_types.h \ + $(PROJECT_PATH)/components/driver/include/driver/rmt.h \ + $(PROJECT_PATH)/components/hal/include/hal/sigmadelta_types.h \ + $(PROJECT_PATH)/components/driver/include/driver/sigmadelta.h \ + $(PROJECT_PATH)/components/hal/include/hal/spi_types.h \ + $(PROJECT_PATH)/components/driver/include/driver/spi_common.h \ + $(PROJECT_PATH)/components/driver/include/driver/spi_master.h \ + $(PROJECT_PATH)/components/driver/include/driver/spi_slave.h \ + $(PROJECT_PATH)/components/driver/include/driver/spi_slave_hd.h \ + $(PROJECT_PATH)/components/hal/include/hal/timer_types.h \ + $(PROJECT_PATH)/components/driver/include/driver/timer.h \ + $(PROJECT_PATH)/components/hal/include/hal/touch_sensor_types.h \ + $(PROJECT_PATH)/components/driver/include/driver/touch_sensor_common.h \ + $(PROJECT_PATH)/components/hal/include/hal/twai_types.h \ + $(PROJECT_PATH)/components/driver/include/driver/twai.h \ + $(PROJECT_PATH)/components/hal/include/hal/uart_types.h \ + $(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/uart_channel.h \ + $(PROJECT_PATH)/components/driver/include/driver/uart.h \ + $(PROJECT_PATH)/components/esp_netif/include/esp_netif.h \ + $(PROJECT_PATH)/components/esp_netif/include/esp_netif_net_stack.h \ + $(PROJECT_PATH)/components/esp-tls/esp_tls.h \ + $(PROJECT_PATH)/components/mqtt/esp-mqtt/include/mqtt_client.h \ + $(PROJECT_PATH)/components/lwip/include/apps/ping/ping_sock.h \ + $(PROJECT_PATH)/components/lwip/include/apps/esp_sntp.h \ + $(PROJECT_PATH)/components/mdns/include/mdns.h \ + $(PROJECT_PATH)/components/esp_http_client/include/esp_http_client.h \ + $(PROJECT_PATH)/components/esp_websocket_client/include/esp_websocket_client.h \ + $(PROJECT_PATH)/components/esp_http_server/include/esp_http_server.h \ + $(PROJECT_PATH)/components/esp_https_server/include/esp_https_server.h \ + $(PROJECT_PATH)/components/esp_local_ctrl/include/esp_local_ctrl.h \ + $(PROJECT_PATH)/components/esp_serial_slave_link/include/esp_serial_slave_link/essl.h \ + $(PROJECT_PATH)/components/esp_serial_slave_link/include/esp_serial_slave_link/essl_sdio.h \ + $(PROJECT_PATH)/components/esp_serial_slave_link/include/esp_serial_slave_link/essl_spi.h \ + $(PROJECT_PATH)/components/mbedtls/esp_crt_bundle/include/esp_crt_bundle.h \ + $(PROJECT_PATH)/components/protocomm/include/common/protocomm.h \ + $(PROJECT_PATH)/components/protocomm/include/security/protocomm_security.h \ + $(PROJECT_PATH)/components/protocomm/include/security/protocomm_security0.h \ + $(PROJECT_PATH)/components/protocomm/include/security/protocomm_security1.h \ + $(PROJECT_PATH)/components/protocomm/include/transports/protocomm_ble.h \ + $(PROJECT_PATH)/components/protocomm/include/transports/protocomm_console.h \ + $(PROJECT_PATH)/components/protocomm/include/transports/protocomm_httpd.h \ + $(PROJECT_PATH)/components/wifi_provisioning/include/wifi_provisioning/manager.h \ + $(PROJECT_PATH)/components/wifi_provisioning/include/wifi_provisioning/scheme_ble.h \ + $(PROJECT_PATH)/components/wifi_provisioning/include/wifi_provisioning/scheme_softap.h \ + $(PROJECT_PATH)/components/wifi_provisioning/include/wifi_provisioning/scheme_console.h \ + $(PROJECT_PATH)/components/wifi_provisioning/include/wifi_provisioning/wifi_config.h \ + $(PROJECT_PATH)/components/wifi_provisioning/include/wifi_provisioning/wifi_scan.h \ + $(PROJECT_PATH)/components/hal/include/hal/spi_flash_types.h \ + $(PROJECT_PATH)/components/spi_flash/include/esp_flash_spi_init.h \ + $(PROJECT_PATH)/components/spi_flash/include/esp_flash.h \ + $(PROJECT_PATH)/components/spi_flash/include/esp_partition.h \ + $(PROJECT_PATH)/components/bootloader_support/include/esp_flash_encrypt.h \ + $(PROJECT_PATH)/components/bootloader_support/include/bootloader_random.h \ + $(PROJECT_PATH)/components/spiffs/include/esp_spiffs.h \ + $(PROJECT_PATH)/components/driver/include/driver/sdmmc_types.h \ + $(PROJECT_PATH)/components/sdmmc/include/sdmmc_cmd.h \ + $(PROJECT_PATH)/components/driver/include/driver/sdmmc_host.h \ + $(PROJECT_PATH)/components/driver/include/driver/sdspi_host.h \ + $(PROJECT_PATH)/components/hal/include/hal/sdio_slave_types.h \ + $(PROJECT_PATH)/components/driver/include/driver/sdio_slave.h \ + $(PROJECT_PATH)/components/nvs_flash/include/nvs.h \ + $(PROJECT_PATH)/components/nvs_flash/include/nvs_flash.h \ + $(PROJECT_PATH)/components/openthread/include/esp_openthread.h \ + $(PROJECT_PATH)/components/openthread/include/esp_openthread_border_router.h \ + $(PROJECT_PATH)/components/openthread/include/esp_openthread_lock.h \ + $(PROJECT_PATH)/components/openthread/include/esp_openthread_netif_glue.h \ + $(PROJECT_PATH)/components/openthread/include/esp_openthread_types.h \ + $(PROJECT_PATH)/components/vfs/include/esp_vfs.h \ + $(PROJECT_PATH)/components/vfs/include/esp_vfs_dev.h \ + $(PROJECT_PATH)/components/vfs/include/esp_vfs_eventfd.h \ + $(PROJECT_PATH)/components/vfs/include/esp_vfs_semihost.h \ + $(PROJECT_PATH)/components/fatfs/vfs/esp_vfs_fat.h \ + $(PROJECT_PATH)/components/fatfs/diskio/diskio_impl.h \ + $(PROJECT_PATH)/components/fatfs/diskio/diskio_sdmmc.h \ + $(PROJECT_PATH)/components/fatfs/diskio/diskio_wl.h \ + $(PROJECT_PATH)/components/fatfs/diskio/diskio_rawflash.h \ + $(PROJECT_PATH)/components/wear_levelling/include/wear_levelling.h \ + $(PROJECT_PATH)/components/console/esp_console.h \ + $(PROJECT_PATH)/components/heap/include/esp_heap_caps.h \ + $(PROJECT_PATH)/components/heap/include/esp_heap_trace.h \ + $(PROJECT_PATH)/components/heap/include/esp_heap_caps_init.h \ + $(PROJECT_PATH)/components/heap/include/multi_heap.h \ + $(PROJECT_PATH)/components/esp_hw_support/include/esp_intr_alloc.h \ + $(PROJECT_PATH)/components/esp_system/include/esp_int_wdt.h \ + $(PROJECT_PATH)/components/esp_system/include/esp_task_wdt.h \ + $(PROJECT_PATH)/components/esp_hw_support/include/esp_crc.h \ + $(PROJECT_PATH)/components/esp_system/include/esp_freertos_hooks.h \ + $(PROJECT_PATH)/components/esp_ipc/include/esp_ipc.h \ + $(PROJECT_PATH)/components/esp_system/include/esp_expression_with_stack.h \ + $(PROJECT_PATH)/components/app_update/include/esp_ota_ops.h \ + $(PROJECT_PATH)/components/esp_https_ota/include/esp_https_ota.h \ + $(PROJECT_PATH)/components/esp_hw_support/include/esp_async_memcpy.h \ + $(PROJECT_PATH)/components/esp_hw_support/include/esp_random.h \ + $(PROJECT_PATH)/components/esp_hw_support/include/esp_sleep.h \ + $(PROJECT_PATH)/components/log/include/esp_log.h \ + $(PROJECT_PATH)/components/esp_rom/include/esp_rom_sys.h \ + $(PROJECT_PATH)/components/esp_system/include/esp_system.h \ + $(PROJECT_PATH)/components/esp_common/include/esp_idf_version.h \ + $(PROJECT_PATH)/components/ulp/include/ulp_common.h \ + $(PROJECT_PATH)/components/app_trace/include/esp_app_trace.h \ + $(PROJECT_PATH)/components/app_trace/include/esp_sysview_trace.h \ + $(PROJECT_PATH)/components/esp_pm/include/esp_pm.h \ + $(PROJECT_PATH)/components/esp_pm/include/$(IDF_TARGET)/pm.h \ + $(PROJECT_PATH)/components/esp_timer/include/esp_timer.h \ + $(PROJECT_PATH)/components/esp_event/include/esp_event.h \ + $(PROJECT_PATH)/components/esp_event/include/esp_event_base.h \ + $(PROJECT_PATH)/components/efuse/include/esp_efuse.h \ + $(PROJECT_PATH)/components/bootloader_support/include/esp_app_format.h \ + $(PROJECT_PATH)/components/pthread/include/esp_pthread.h \ + $(PROJECT_PATH)/components/freertos/include/freertos/task.h \ + $(PROJECT_PATH)/components/freertos/include/freertos/queue.h \ + $(PROJECT_PATH)/components/freertos/include/freertos/semphr.h \ + $(PROJECT_PATH)/components/freertos/include/freertos/timers.h \ + $(PROJECT_PATH)/components/freertos/include/freertos/event_groups.h \ + $(PROJECT_PATH)/components/freertos/include/freertos/stream_buffer.h \ + $(PROJECT_PATH)/components/freertos/include/freertos/message_buffer.h \ + $(PROJECT_PATH)/components/esp_ringbuf/include/freertos/ringbuf.h \ + $(PROJECT_PATH)/components/esp_common/include/esp_err.h \ + $(PROJECT_PATH)/components/esp_common/include/esp_check.h \ + $(PROJECT_PATH)/components/esp_system/include/esp_system.h \ + $(PROJECT_PATH)/components/freemodbus/common/include/esp_modbus_common.h \ + $(PROJECT_PATH)/components/freemodbus/common/include/esp_modbus_slave.h \ + $(PROJECT_PATH)/components/freemodbus/common/include/esp_modbus_master.h \ + $(PROJECT_PATH)/components/perfmon/include/xtensa_perfmon_access.h \ + $(PROJECT_PATH)/components/perfmon/include/xtensa_perfmon_apis.h \ + $(PROJECT_PATH)/components/perfmon/include/xtensa_perfmon_masks.h \ + $(PROJECT_PATH)/components/ieee802154/include/esp_ieee802154.h \ + $(PROJECT_PATH)/components/ieee802154/include/esp_ieee802154_types.h + + +## Target specific headers are in seperate Doxyfile files +@INCLUDE = $(PROJECT_PATH)/docs/doxygen/Doxyfile_$(IDF_TARGET) + +## Get warnings for functions that have no documentation for their parameters or return value +## +WARN_NO_PARAMDOC = YES + +## Enable preprocessing and remove __attribute__(...) expressions from the INPUT files +## +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = YES +EXPAND_ONLY_PREDEF = YES +PREDEFINED = \ + $(ENV_DOXYGEN_DEFINES) \ + __attribute__(x)= \ + _Static_assert()= \ + IDF_DEPRECATED(X)= \ + IRAM_ATTR= \ + configSUPPORT_DYNAMIC_ALLOCATION=1 \ + configSUPPORT_STATIC_ALLOCATION=1 \ + configQUEUE_REGISTRY_SIZE=1 \ + configUSE_RECURSIVE_MUTEXES=1 \ + configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS=1 \ + configNUM_THREAD_LOCAL_STORAGE_POINTERS=1 \ + configUSE_APPLICATION_TASK_TAG=1 \ + configTASKLIST_INCLUDE_COREID=1 \ + "ESP_EVENT_DECLARE_BASE(x)=extern esp_event_base_t x" + +## Do not complain about not having dot +## +HAVE_DOT = NO + +## Generate XML that is required for Breathe +## +GENERATE_XML = YES +XML_OUTPUT = xml + +GENERATE_HTML = NO +HAVE_DOT = NO +GENERATE_LATEX = NO +GENERATE_MAN = YES +GENERATE_RTF = NO + +## Skip distracting progress messages +## +QUIET = YES diff --git a/docs/doxygen/Doxyfile_common b/docs/doxygen/Doxyfile_common deleted file mode 100644 index a04b7ee12f..0000000000 --- a/docs/doxygen/Doxyfile_common +++ /dev/null @@ -1,267 +0,0 @@ -# This is Doxygen configuration file -# -# Doxygen provides over 260 configuration statements -# To make this file easier to follow, -# it contains only statements that are non-default -# -# NOTE: -# It is recommended not to change defaults unless specifically required -# Test any changes how they affect generated documentation -# Make sure that correct warnings are generated to flag issues with documented code -# -# For the complete list of configuration statements see: -# http://doxygen.nl/manual/config.html - - -PROJECT_NAME = "IDF Programming Guide" - -## The 'INPUT' statement below is used as input by script 'gen-df-input.py' -## to automatically generate API reference list files heder_file.inc -## These files are placed in '_inc' directory -## and used to include in API reference documentation - -INPUT = \ - $(IDF_PATH)/components/tinyusb/additions/include/tinyusb.h \ - $(IDF_PATH)/components/tinyusb/additions/include/tinyusb_types.h \ - $(IDF_PATH)/components/tinyusb/additions/include/tusb_cdc_acm.h \ - $(IDF_PATH)/components/tinyusb/additions/include/tusb_config.h \ - $(IDF_PATH)/components/tinyusb/additions/include/tusb_console.h \ - $(IDF_PATH)/components/tinyusb/additions/include/tusb_tasks.h \ - $(IDF_PATH)/components/tinyusb/additions/include/vfs_tinyusb.h \ - $(IDF_PATH)/components/esp_wifi/include/esp_wifi.h \ - $(IDF_PATH)/components/esp_wifi/include/esp_wifi_types.h \ - $(IDF_PATH)/components/esp_wifi/include/esp_smartconfig.h \ - $(IDF_PATH)/components/esp_wifi/include/esp_now.h \ - $(IDF_PATH)/components/esp_wifi/include/esp_wifi_default.h \ - $(IDF_PATH)/components/esp_wifi/include/esp_mesh.h \ - $(IDF_PATH)/components/esp_event/include/esp_event.h \ - $(IDF_PATH)/components/esp_event/include/esp_event_base.h \ - $(IDF_PATH)/components/esp_event/include/esp_event_legacy.h \ - $(IDF_PATH)/components/bt/include/esp32/include/esp_bt.h \ - $(IDF_PATH)/components/bt/common/api/include/api/esp_blufi_api.h \ - $(IDF_PATH)/components/bt/host/bluedroid/api/include/api/esp_bt_defs.h \ - $(IDF_PATH)/components/bt/host/bluedroid/api/include/api/esp_bt_main.h \ - $(IDF_PATH)/components/bt/host/bluedroid/api/include/api/esp_bt_device.h \ - $(IDF_PATH)/components/bt/host/bluedroid/api/include/api/esp_gap_ble_api.h \ - $(IDF_PATH)/components/bt/host/bluedroid/api/include/api/esp_gatt_defs.h \ - $(IDF_PATH)/components/bt/host/bluedroid/api/include/api/esp_gatts_api.h \ - $(IDF_PATH)/components/bt/host/bluedroid/api/include/api/esp_gattc_api.h \ - $(IDF_PATH)/components/bt/host/bluedroid/api/include/api/esp_gap_bt_api.h \ - $(IDF_PATH)/components/bt/host/bluedroid/api/include/api/esp_a2dp_api.h \ - $(IDF_PATH)/components/bt/host/bluedroid/api/include/api/esp_avrc_api.h \ - $(IDF_PATH)/components/bt/host/bluedroid/api/include/api/esp_spp_api.h \ - $(IDF_PATH)/components/bt/host/bluedroid/api/include/api/esp_hf_defs.h \ - $(IDF_PATH)/components/bt/host/bluedroid/api/include/api/esp_hf_client_api.h \ - $(IDF_PATH)/components/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h \ - $(IDF_PATH)/components/bt/host/nimble/esp-hci/include/esp_nimble_hci.h \ - $(IDF_PATH)/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_common_api.h \ - $(IDF_PATH)/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_local_data_operation_api.h \ - $(IDF_PATH)/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_low_power_api.h \ - $(IDF_PATH)/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_networking_api.h \ - $(IDF_PATH)/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_provisioning_api.h \ - $(IDF_PATH)/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_proxy_api.h \ - $(IDF_PATH)/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_config_model_api.h \ - $(IDF_PATH)/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_generic_model_api.h \ - $(IDF_PATH)/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_health_model_api.h \ - $(IDF_PATH)/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_lighting_model_api.h \ - $(IDF_PATH)/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_sensor_model_api.h \ - $(IDF_PATH)/components/bt/esp_ble_mesh/api/models/include/esp_ble_mesh_time_scene_model_api.h \ - $(IDF_PATH)/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h \ - $(IDF_PATH)/components/hal/include/hal/eth_types.h \ - $(IDF_PATH)/components/esp_eth/include/esp_eth.h \ - $(IDF_PATH)/components/esp_eth/include/esp_eth_com.h \ - $(IDF_PATH)/components/esp_eth/include/esp_eth_mac.h \ - $(IDF_PATH)/components/esp_eth/include/esp_eth_phy.h \ - $(IDF_PATH)/components/esp_eth/include/esp_eth_netif_glue.h \ - $(IDF_PATH)/components/hal/include/hal/adc_types.h \ - $(IDF_PATH)/components/soc/$(IDF_TARGET)/include/soc/adc_channel.h \ - $(IDF_PATH)/components/driver/include/driver/adc_common.h \ - $(IDF_PATH)/components/driver/$(IDF_TARGET)/include/driver/adc.h \ - $(IDF_PATH)/components/esp_adc_cal/include/esp_adc_cal.h \ - $(IDF_PATH)/components/hal/include/hal/dac_types.h \ - $(IDF_PATH)/components/driver/include/driver/dac_common.h \ - $(IDF_PATH)/components/hal/include/hal/gpio_types.h \ - $(IDF_PATH)/components/driver/include/driver/gpio.h \ - $(IDF_PATH)/components/driver/include/driver/dedic_gpio.h \ - $(IDF_PATH)/components/hal/include/hal/rtc_io_types.h \ - $(IDF_PATH)/components/driver/include/driver/rtc_io.h \ - $(IDF_PATH)/components/hal/include/hal/i2c_types.h \ - $(IDF_PATH)/components/driver/include/driver/i2c.h \ - $(IDF_PATH)/components/hal/include/hal/i2s_types.h \ - $(IDF_PATH)/components/driver/include/driver/i2s.h \ - $(IDF_PATH)/components/hal/include/hal/ledc_types.h \ - $(IDF_PATH)/components/driver/include/driver/ledc.h \ - $(IDF_PATH)/components/hal/include/hal/rmt_types.h \ - $(IDF_PATH)/components/driver/include/driver/rmt.h \ - $(IDF_PATH)/components/hal/include/hal/sigmadelta_types.h \ - $(IDF_PATH)/components/driver/include/driver/sigmadelta.h \ - $(IDF_PATH)/components/hal/include/hal/spi_types.h \ - $(IDF_PATH)/components/driver/include/driver/spi_common.h \ - $(IDF_PATH)/components/driver/include/driver/spi_master.h \ - $(IDF_PATH)/components/driver/include/driver/spi_slave.h \ - $(IDF_PATH)/components/driver/include/driver/spi_slave_hd.h \ - $(IDF_PATH)/components/hal/include/hal/timer_types.h \ - $(IDF_PATH)/components/driver/include/driver/timer.h \ - $(IDF_PATH)/components/hal/include/hal/touch_sensor_types.h \ - $(IDF_PATH)/components/driver/include/driver/touch_sensor_common.h \ - $(IDF_PATH)/components/hal/include/hal/twai_types.h \ - $(IDF_PATH)/components/driver/include/driver/twai.h \ - $(IDF_PATH)/components/hal/include/hal/uart_types.h \ - $(IDF_PATH)/components/soc/$(IDF_TARGET)/include/soc/uart_channel.h \ - $(IDF_PATH)/components/driver/include/driver/uart.h \ - $(IDF_PATH)/components/esp_netif/include/esp_netif.h \ - $(IDF_PATH)/components/esp_netif/include/esp_netif_net_stack.h \ - $(IDF_PATH)/components/esp-tls/esp_tls.h \ - $(IDF_PATH)/components/mqtt/esp-mqtt/include/mqtt_client.h \ - $(IDF_PATH)/components/lwip/include/apps/ping/ping_sock.h \ - $(IDF_PATH)/components/lwip/include/apps/esp_sntp.h \ - $(IDF_PATH)/components/mdns/include/mdns.h \ - $(IDF_PATH)/components/esp_http_client/include/esp_http_client.h \ - $(IDF_PATH)/components/esp_websocket_client/include/esp_websocket_client.h \ - $(IDF_PATH)/components/esp_http_server/include/esp_http_server.h \ - $(IDF_PATH)/components/esp_https_server/include/esp_https_server.h \ - $(IDF_PATH)/components/esp_local_ctrl/include/esp_local_ctrl.h \ - $(IDF_PATH)/components/esp_serial_slave_link/include/esp_serial_slave_link/essl.h \ - $(IDF_PATH)/components/esp_serial_slave_link/include/esp_serial_slave_link/essl_sdio.h \ - $(IDF_PATH)/components/esp_serial_slave_link/include/esp_serial_slave_link/essl_spi.h \ - $(IDF_PATH)/components/mbedtls/esp_crt_bundle/include/esp_crt_bundle.h \ - $(IDF_PATH)/components/protocomm/include/common/protocomm.h \ - $(IDF_PATH)/components/protocomm/include/security/protocomm_security.h \ - $(IDF_PATH)/components/protocomm/include/security/protocomm_security0.h \ - $(IDF_PATH)/components/protocomm/include/security/protocomm_security1.h \ - $(IDF_PATH)/components/protocomm/include/transports/protocomm_ble.h \ - $(IDF_PATH)/components/protocomm/include/transports/protocomm_console.h \ - $(IDF_PATH)/components/protocomm/include/transports/protocomm_httpd.h \ - $(IDF_PATH)/components/wifi_provisioning/include/wifi_provisioning/manager.h \ - $(IDF_PATH)/components/wifi_provisioning/include/wifi_provisioning/scheme_ble.h \ - $(IDF_PATH)/components/wifi_provisioning/include/wifi_provisioning/scheme_softap.h \ - $(IDF_PATH)/components/wifi_provisioning/include/wifi_provisioning/scheme_console.h \ - $(IDF_PATH)/components/wifi_provisioning/include/wifi_provisioning/wifi_config.h \ - $(IDF_PATH)/components/wifi_provisioning/include/wifi_provisioning/wifi_scan.h \ - $(IDF_PATH)/components/hal/include/hal/spi_flash_types.h \ - $(IDF_PATH)/components/spi_flash/include/esp_flash_spi_init.h \ - $(IDF_PATH)/components/spi_flash/include/esp_flash.h \ - $(IDF_PATH)/components/spi_flash/include/esp_partition.h \ - $(IDF_PATH)/components/bootloader_support/include/esp_flash_encrypt.h \ - $(IDF_PATH)/components/bootloader_support/include/bootloader_random.h \ - $(IDF_PATH)/components/spiffs/include/esp_spiffs.h \ - $(IDF_PATH)/components/driver/include/driver/sdmmc_types.h \ - $(IDF_PATH)/components/sdmmc/include/sdmmc_cmd.h \ - $(IDF_PATH)/components/driver/include/driver/sdmmc_host.h \ - $(IDF_PATH)/components/driver/include/driver/sdspi_host.h \ - $(IDF_PATH)/components/hal/include/hal/sdio_slave_types.h \ - $(IDF_PATH)/components/driver/include/driver/sdio_slave.h \ - $(IDF_PATH)/components/nvs_flash/include/nvs.h \ - $(IDF_PATH)/components/nvs_flash/include/nvs_flash.h \ - $(IDF_PATH)/components/openthread/include/esp_openthread.h \ - $(IDF_PATH)/components/openthread/include/esp_openthread_lock.h \ - $(IDF_PATH)/components/openthread/include/esp_openthread_types.h \ - $(IDF_PATH)/components/openthread/include/openthread-core-esp32x-config.h \ - $(IDF_PATH)/components/vfs/include/esp_vfs.h \ - $(IDF_PATH)/components/vfs/include/esp_vfs_dev.h \ - $(IDF_PATH)/components/vfs/include/esp_vfs_eventfd.h \ - $(IDF_PATH)/components/vfs/include/esp_vfs_semihost.h \ - $(IDF_PATH)/components/fatfs/vfs/esp_vfs_fat.h \ - $(IDF_PATH)/components/fatfs/diskio/diskio_impl.h \ - $(IDF_PATH)/components/fatfs/diskio/diskio_sdmmc.h \ - $(IDF_PATH)/components/fatfs/diskio/diskio_wl.h \ - $(IDF_PATH)/components/fatfs/diskio/diskio_rawflash.h \ - $(IDF_PATH)/components/wear_levelling/include/wear_levelling.h \ - $(IDF_PATH)/components/console/esp_console.h \ - $(IDF_PATH)/components/heap/include/esp_heap_caps.h \ - $(IDF_PATH)/components/heap/include/esp_heap_trace.h \ - $(IDF_PATH)/components/heap/include/esp_heap_caps_init.h \ - $(IDF_PATH)/components/heap/include/multi_heap.h \ - $(IDF_PATH)/components/esp_hw_support/include/esp_intr_alloc.h \ - $(IDF_PATH)/components/esp_system/include/esp_int_wdt.h \ - $(IDF_PATH)/components/esp_system/include/esp_task_wdt.h \ - $(IDF_PATH)/components/esp_hw_support/include/esp_crc.h \ - $(IDF_PATH)/components/esp_system/include/esp_freertos_hooks.h \ - $(IDF_PATH)/components/esp_ipc/include/esp_ipc.h \ - $(IDF_PATH)/components/esp_system/include/esp_expression_with_stack.h \ - $(IDF_PATH)/components/app_update/include/esp_ota_ops.h \ - $(IDF_PATH)/components/esp_https_ota/include/esp_https_ota.h \ - $(IDF_PATH)/components/esp_hw_support/include/esp_async_memcpy.h \ - $(IDF_PATH)/components/esp_hw_support/include/esp_random.h \ - $(IDF_PATH)/components/esp_hw_support/include/esp_sleep.h \ - $(IDF_PATH)/components/log/include/esp_log.h \ - $(IDF_PATH)/components/esp_rom/include/esp_rom_sys.h \ - $(IDF_PATH)/components/esp_system/include/esp_system.h \ - $(IDF_PATH)/components/esp_common/include/esp_idf_version.h \ - $(IDF_PATH)/components/ulp/include/ulp_common.h \ - $(IDF_PATH)/components/app_trace/include/esp_app_trace.h \ - $(IDF_PATH)/components/app_trace/include/esp_sysview_trace.h \ - $(IDF_PATH)/components/esp_pm/include/esp_pm.h \ - $(IDF_PATH)/components/esp_pm/include/$(IDF_TARGET)/pm.h \ - $(IDF_PATH)/components/esp_timer/include/esp_timer.h \ - $(IDF_PATH)/components/esp_event/include/esp_event.h \ - $(IDF_PATH)/components/esp_event/include/esp_event_base.h \ - $(IDF_PATH)/components/efuse/include/esp_efuse.h \ - $(IDF_PATH)/components/bootloader_support/include/esp_app_format.h \ - $(IDF_PATH)/components/pthread/include/esp_pthread.h \ - $(IDF_PATH)/components/freertos/include/freertos/task.h \ - $(IDF_PATH)/components/freertos/include/freertos/queue.h \ - $(IDF_PATH)/components/freertos/include/freertos/semphr.h \ - $(IDF_PATH)/components/freertos/include/freertos/timers.h \ - $(IDF_PATH)/components/freertos/include/freertos/event_groups.h \ - $(IDF_PATH)/components/freertos/include/freertos/stream_buffer.h \ - $(IDF_PATH)/components/freertos/include/freertos/message_buffer.h \ - $(IDF_PATH)/components/esp_ringbuf/include/freertos/ringbuf.h \ - $(IDF_PATH)/components/esp_common/include/esp_err.h \ - $(IDF_PATH)/components/esp_common/include/esp_check.h \ - $(IDF_PATH)/components/esp_system/include/esp_system.h \ - $(IDF_PATH)/components/freemodbus/common/include/esp_modbus_common.h \ - $(IDF_PATH)/components/freemodbus/common/include/esp_modbus_slave.h \ - $(IDF_PATH)/components/freemodbus/common/include/esp_modbus_master.h \ - $(IDF_PATH)/components/perfmon/include/xtensa_perfmon_access.h \ - $(IDF_PATH)/components/perfmon/include/xtensa_perfmon_apis.h \ - $(IDF_PATH)/components/perfmon/include/xtensa_perfmon_masks.h \ - $(IDF_PATH)/components/ieee802154/include/esp_ieee802154.h \ - $(IDF_PATH)/components/ieee802154/include/esp_ieee802154_types.h - -## Target specific headers are in seperate Doxyfile files -@INCLUDE = $(IDF_PATH)/docs/doxygen/Doxyfile_$(IDF_TARGET) - -## Get warnings for functions that have no documentation for their parameters or return value -## -WARN_NO_PARAMDOC = YES - -## Enable preprocessing and remove __attribute__(...) expressions from the INPUT files -## -ENABLE_PREPROCESSING = YES -MACRO_EXPANSION = YES -EXPAND_ONLY_PREDEF = YES -PREDEFINED = \ - $(ENV_DOXYGEN_DEFINES) \ - __attribute__(x)= \ - _Static_assert()= \ - IDF_DEPRECATED(X)= \ - IRAM_ATTR= \ - configSUPPORT_DYNAMIC_ALLOCATION=1 \ - configSUPPORT_STATIC_ALLOCATION=1 \ - configQUEUE_REGISTRY_SIZE=1 \ - configUSE_RECURSIVE_MUTEXES=1 \ - configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS=1 \ - configNUM_THREAD_LOCAL_STORAGE_POINTERS=1 \ - configUSE_APPLICATION_TASK_TAG=1 \ - configTASKLIST_INCLUDE_COREID=1 \ - "ESP_EVENT_DECLARE_BASE(x)=extern esp_event_base_t x" - -## Do not complain about not having dot -## -HAVE_DOT = NO - -## Generate XML that is required for Breathe -## -GENERATE_XML = YES -XML_OUTPUT = xml - -GENERATE_HTML = NO -HAVE_DOT = NO -GENERATE_LATEX = NO -GENERATE_MAN = YES -GENERATE_RTF = NO - -## Skip distracting progress messages -## -QUIET = YES diff --git a/docs/doxygen/Doxyfile_esp32 b/docs/doxygen/Doxyfile_esp32 index 53f16c43fe..4f6ef7e2e8 100644 --- a/docs/doxygen/Doxyfile_esp32 +++ b/docs/doxygen/Doxyfile_esp32 @@ -1,12 +1,12 @@ INPUT += \ - $(IDF_PATH)/components/soc/$(IDF_TARGET)/include/soc/dac_channel.h \ - $(IDF_PATH)/components/driver/$(IDF_TARGET)/include/driver/dac.h \ - $(IDF_PATH)/components/hal/include/hal/mcpwm_types.h \ - $(IDF_PATH)/components/driver/include/driver/mcpwm.h \ - $(IDF_PATH)/components/hal/include/hal/pcnt_types.h \ - $(IDF_PATH)/components/driver/include/driver/pcnt.h \ - $(IDF_PATH)/components/soc/$(IDF_TARGET)/include/soc/rtc_io_channel.h \ - $(IDF_PATH)/components/soc/$(IDF_TARGET)/include/soc/touch_sensor_channel.h \ - $(IDF_PATH)/components/driver/$(IDF_TARGET)/include/driver/touch_sensor.h \ - $(IDF_PATH)/components/esp_hw_support/include/soc/esp32/himem.h \ - $(IDF_PATH)/components/ulp/include/$(IDF_TARGET)/ulp.h + $(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/dac_channel.h \ + $(PROJECT_PATH)/components/driver/$(IDF_TARGET)/include/driver/dac.h \ + $(PROJECT_PATH)/components/hal/include/hal/mcpwm_types.h \ + $(PROJECT_PATH)/components/driver/include/driver/mcpwm.h \ + $(PROJECT_PATH)/components/hal/include/hal/pcnt_types.h \ + $(PROJECT_PATH)/components/driver/include/driver/pcnt.h \ + $(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/rtc_io_channel.h \ + $(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/touch_sensor_channel.h \ + $(PROJECT_PATH)/components/driver/$(IDF_TARGET)/include/driver/touch_sensor.h \ + $(PROJECT_PATH)/components/esp_hw_support/include/soc/esp32/himem.h \ + $(PROJECT_PATH)/components/ulp/include/$(IDF_TARGET)/ulp.h diff --git a/docs/doxygen/Doxyfile_esp32c3 b/docs/doxygen/Doxyfile_esp32c3 index df3e780e9e..4afae97962 100644 --- a/docs/doxygen/Doxyfile_esp32c3 +++ b/docs/doxygen/Doxyfile_esp32c3 @@ -1,4 +1,4 @@ INPUT += \ - $(IDF_PATH)/components/driver/esp32c3/include/driver/temp_sensor.h \ - $(IDF_PATH)/components/esp_hw_support/include/soc/esp32c3/esp_ds.h \ - $(IDF_PATH)/components/esp_hw_support/include/soc/esp32c3/esp_hmac.h + $(PROJECT_PATH)/components/driver/esp32c3/include/driver/temp_sensor.h \ + $(PROJECT_PATH)/components/esp_hw_support/include/soc/esp32c3/esp_ds.h \ + $(PROJECT_PATH)/components/esp_hw_support/include/soc/esp32c3/esp_hmac.h diff --git a/docs/doxygen/Doxyfile_esp32s2 b/docs/doxygen/Doxyfile_esp32s2 index f71db98952..c1fdf45624 100644 --- a/docs/doxygen/Doxyfile_esp32s2 +++ b/docs/doxygen/Doxyfile_esp32s2 @@ -1,17 +1,21 @@ INPUT += \ - $(IDF_PATH)/components/soc/$(IDF_TARGET)/include/soc/dac_channel.h \ - $(IDF_PATH)/components/driver/$(IDF_TARGET)/include/driver/dac.h \ - $(IDF_PATH)/components/hal/include/hal/pcnt_types.h \ - $(IDF_PATH)/components/driver/include/driver/pcnt.h \ - $(IDF_PATH)/components/soc/$(IDF_TARGET)/include/soc/rtc_io_channel.h \ - $(IDF_PATH)/components/driver/esp32s2/include/driver/temp_sensor.h \ - $(IDF_PATH)/components/soc/$(IDF_TARGET)/include/soc/touch_sensor_channel.h \ - $(IDF_PATH)/components/driver/$(IDF_TARGET)/include/driver/touch_sensor.h \ - $(IDF_PATH)/components/esp_hw_support/include/soc/esp32s2/esp_ds.h \ - $(IDF_PATH)/components/esp_hw_support/include/soc/esp32s2/esp_hmac.h \ - $(IDF_PATH)/components/ulp/include/esp32s2/ulp_riscv.h \ - $(IDF_PATH)/components/ulp/include/$(IDF_TARGET)/ulp.h \ - $(IDF_PATH)/components/touch_element/include/touch_element/touch_element.h \ - $(IDF_PATH)/components/touch_element/include/touch_element/touch_button.h \ - $(IDF_PATH)/components/touch_element/include/touch_element/touch_slider.h \ - $(IDF_PATH)/components/touch_element/include/touch_element/touch_matrix.h + $(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/dac_channel.h \ + $(PROJECT_PATH)/components/driver/$(IDF_TARGET)/include/driver/dac.h \ + $(PROJECT_PATH)/components/hal/include/hal/pcnt_types.h \ + $(PROJECT_PATH)/components/driver/include/driver/pcnt.h \ + $(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/rtc_io_channel.h \ + $(PROJECT_PATH)/components/driver/esp32s2/include/driver/temp_sensor.h \ + $(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/touch_sensor_channel.h \ + $(PROJECT_PATH)/components/driver/$(IDF_TARGET)/include/driver/touch_sensor.h \ + $(PROJECT_PATH)/components/esp_hw_support/include/soc/esp32s2/esp_ds.h \ + $(PROJECT_PATH)/components/esp_hw_support/include/soc/esp32s2/esp_hmac.h \ + $(PROJECT_PATH)/components/ulp/include/esp32s2/ulp_riscv.h \ + $(PROJECT_PATH)/components/ulp/include/$(IDF_TARGET)/ulp.h \ + $(PROJECT_PATH)/components/touch_element/include/touch_element/touch_element.h \ + $(PROJECT_PATH)/components/touch_element/include/touch_element/touch_button.h \ + $(PROJECT_PATH)/components/touch_element/include/touch_element/touch_slider.h \ + $(PROJECT_PATH)/components/touch_element/include/touch_element/touch_matrix.h \ + $(PROJECT_PATH)/components/usb/include/usb/usb_helpers.h \ + $(PROJECT_PATH)/components/usb/include/usb/usb_host.h \ + $(PROJECT_PATH)/components/usb/include/usb/usb_types_ch9.h \ + $(PROJECT_PATH)/components/usb/include/usb/usb_types_stack.h diff --git a/docs/doxygen/Doxyfile_esp32s3 b/docs/doxygen/Doxyfile_esp32s3 index ccee7a0e58..1f081a8981 100644 --- a/docs/doxygen/Doxyfile_esp32s3 +++ b/docs/doxygen/Doxyfile_esp32s3 @@ -1,8 +1,14 @@ INPUT += \ - $(IDF_PATH)/components/ulp/include/$(IDF_TARGET)/ulp.h \ - $(IDF_PATH)/components/hal/include/hal/mcpwm_types.h \ - $(IDF_PATH)/components/driver/include/driver/mcpwm.h \ - $(IDF_PATH)/components/hal/include/hal/pcnt_types.h \ - $(IDF_PATH)/components/driver/include/driver/pcnt.h \ - $(IDF_PATH)/components/soc/$(IDF_TARGET)/include/soc/touch_sensor_channel.h \ - $(IDF_PATH)/components/driver/$(IDF_TARGET)/include/driver/touch_sensor.h + $(PROJECT_PATH)/components/ulp/include/$(IDF_TARGET)/ulp.h \ + $(PROJECT_PATH)/components/esp_hw_support/include/soc/$(IDF_TARGET)/esp_hmac.h \ + $(PROJECT_PATH)/components/esp_hw_support/include/soc/$(IDF_TARGET)/esp_ds.h \ + $(PROJECT_PATH)/components/hal/include/hal/mcpwm_types.h \ + $(PROJECT_PATH)/components/driver/include/driver/mcpwm.h \ + $(PROJECT_PATH)/components/hal/include/hal/pcnt_types.h \ + $(PROJECT_PATH)/components/driver/include/driver/pcnt.h \ + $(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/touch_sensor_channel.h \ + $(PROJECT_PATH)/components/driver/$(IDF_TARGET)/include/driver/touch_sensor.h \ + $(PROJECT_PATH)/components/usb/include/usb/usb_helpers.h \ + $(PROJECT_PATH)/components/usb/include/usb/usb_host.h \ + $(PROJECT_PATH)/components/usb/include/usb/usb_types_ch9.h \ + $(PROJECT_PATH)/components/usb/include/usb/usb_types_stack.h diff --git a/docs/en/COPYRIGHT.rst b/docs/en/COPYRIGHT.rst index 2a8b688ef5..ea02eb0a4b 100644 --- a/docs/en/COPYRIGHT.rst +++ b/docs/en/COPYRIGHT.rst @@ -19,7 +19,7 @@ These third party libraries can be included into the application (firmware) prod * :component:`Xtensa header files` are Copyright (C) 2013 Tensilica Inc and are licensed under the MIT License as reproduced in the individual header files. -* Original parts of FreeRTOS_ (components/freertos) are Copyright (C) 2017 Amazon.com, Inc. or its affiliates are licensed under the MIT License, as described in :component_file:`license.txt`. +* Original parts of FreeRTOS_ (components/freertos) are Copyright (C) 2017 Amazon.com, Inc. or its affiliates are licensed under the MIT License, as described in :component_file:`license.txt`. * Original parts of LWIP_ (components/lwip) are Copyright (C) 2001, 2002 Swedish Institute of Computer Science and are licensed under the BSD License as described in :component_file:`COPYING file`. @@ -57,7 +57,7 @@ These third party libraries can be included into the application (firmware) prod * :component:`Asio `, Copyright (c) 2003-2018 Christopher M. Kohlhoff is licensed under the Boost Software License as described in :component_file:`COPYING file`. -* :component:`ESP-MQTT ` MQTT Package (contiki-mqtt) - Copyright (c) 2014, Stephen Robinson, MQTT-ESP - Tuan PM is licensed under Apache License 2,0 as described in :component_file:`LICENSE file `. +* :component:`ESP-MQTT ` MQTT Package (contiki-mqtt) - Copyright (c) 2014, Stephen Robinson, MQTT-ESP - Tuan PM is licensed under Apache License 2.0 as described in :component_file:`LICENSE file `. * :component:`BLE Mesh ` is adapted from Zephyr Project, Copyright (c) 2017-2018 Intel Corporation and licensed under Apache License 2.0 diff --git a/docs/en/api-guides/blufi.rst b/docs/en/api-guides/blufi.rst index d9743dba67..9d7bfb120b 100644 --- a/docs/en/api-guides/blufi.rst +++ b/docs/en/api-guides/blufi.rst @@ -4,6 +4,7 @@ BluFi Overview -------- + The BluFi for {IDF_TARGET_NAME} is a Wi-Fi network configuration function via Bluetooth channel. It provides a secure protocol to pass Wi-Fi configuration and credentials to the {IDF_TARGET_NAME}. Using this information {IDF_TARGET_NAME} can then e.g. connect to an AP or establish a SoftAP. Fragmenting, data encryption, checksum verification in the BluFi layer are the key elements of this process. @@ -12,6 +13,7 @@ You can customize symmetric encryption, asymmetric encryption and checksum suppo The BluFi Flow --------------- + The BluFi networking flow includes the configuration of the SoftAP and Station. The following uses Station as an example to illustrate the core parts of the procedure, including broadcast, connection, service discovery, negotiation of the shared key, data transmission, connection status backhaul. @@ -42,8 +44,8 @@ The following uses Station as an example to illustrate the core parts of the pro 2. The data lengths before and after symmetric encryption/decryption must stay the same. It also supports in-place encryption and decryption. -The flow chart of BluFi ------------------------ +The Flow Chart of BluFi +-------------------------- .. seqdiag:: :caption: BluFi Flow Chart @@ -78,64 +80,72 @@ The frame formats for the communication between the mobile phone App and {IDF_TA The frame format with no fragment (8 bit): -+-----------------+----------------+ -| Description | Value | -+=================+================+ -| LSB - Type | 1 | -+-----------------+----------------+ -| Frame Control | 1 | -+-----------------+----------------+ -| Sequence Number | 1 | -+-----------------+----------------+ -| Data Length | 1 | -+-----------------+----------------+ -| Data | ${Data Length} | -+-----------------+----------------+ -| MSB - CheckSum | 2 | -+-----------------+----------------+ +.. list-table:: + :header-rows: 1 + :widths: 25 25 + + * - Description + - Value + * - Type (Least Significant Bit) + - 1 + * - Frame Control + - 1 + * - Sequence Number + - 1 + * - Data Length + - 1 + * - Data + - ${Data Length} + * - CheckSum (Most Siginificant Bit) + - 2 If the **Frame Ctrl** bit is enabled, the **Total length** bit indicates the length of remaining part of the frame. It can tell the remote how much memory needs to be alloced. The frame format with fragments(8 bit): -+--------------------+-------------------------------------------+ -| Description | Value | -+====================+===========================================+ -| LSB - Type | 1 | -+--------------------+-------------------------------------------+ -| FrameControl(Frag) | 1 | -+--------------------+-------------------------------------------+ -| SequenceNumber | 1 | -+--------------------+-------------------------------------------+ -| DataLength | 1 | -+--------------------+----------------------+--------------------+ -| | Total Content Length | 2 | -+ Data +----------------------+--------------------+ -| | Content | ${Data Length} - 2 | -+--------------------+----------------------+--------------------+ -| MSB - CheckSum | 2 | -+--------------------+-------------------------------------------+ +.. list-table:: + :header-rows: 1 + :widths: 25 25 + + * - Description + - Value + * - Type (Least Significant Bit) + - 1 + * - Frame Control (Frag) + - 1 + * - Sequence Number + - 1 + * - Data Length + - 1 + * - Data + - * Total Content Length: 2 + * Content: ${Data Length} - 2 + * - CheckSum (Most Siginificant Bit) + - 2 -Normally, the control frame does not contain data bits, except for Ack Frame. +Normally, the control frame does not contain data bits, except for ACK Frame. -The format of Ack Frame(8 bit): +The format of ACK Frame(8 bit): + +.. list-table:: + :header-rows: 1 + :widths: 25 25 + + * - Description + - Value + * - Type - ACK (Least Significant Bit) + - 1 + * - Frame Control + - 1 + * - Sequence Number + - 1 + * - Data Length + - 1 + * - Data + - Acked Sequence Number: 2 + * - CheckSum (Most Siginificant Bit) + - 2 -+------------------+--------------------------------------------+ -| Description | Value | -+------------------+--------------------------------------------+ -| LSB - Type (Ack) | 1 | -+------------------+--------------------------------------------+ -| Frame Control | 1 | -+------------------+--------------------------------------------+ -| SequenceNumber | 1 | -+------------------+--------------------------------------------+ -| DataLength | 1 | -+------------------+-----------------------+--------------------+ -+ Data + Acked Sequence Number + 2 + -| | | | -+------------------+-----------------------+--------------------+ -| MSB - CheckSum | 2 | -+------------------+--------------------------------------------+ 1. Type @@ -145,235 +155,248 @@ The format of Ack Frame(8 bit): * The data frame supports to be encrypted and verified. - **1.1 Control Frame (0x0 b’00)** +1.1 Control Frame (Binary: 0x0 b’00) - +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ - | Control Frame (Binary) | Implication | Explanation | Note | - +=========================+==============================================================+===============================================================+===============================================================+ - | 0x0 (b’000000) | Ack | The data field of the Ack frame uses the same | The data field consumes a byte and its value is | - | | | sequence value of the frame to reply to. | the same as the sequence field of the frame to reply to. | - +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ - | 0x1 (b’000001) | Set ESP device to the security mode. | To inform ESP device of the security mode to use | The data field consumes a byte. | - | | | when sending data, which is allowed to be reset | The higher 4 bits are for the security mode setting | - | | | multiple times during the process. | of the control frame, and the lower 4 bits are for | - | | | Each setting affects the subsequent security mode used. | the security mode setting of the data frame. | - + + + If it is not set, ESP device will send the control frame +---------------------------------------------------------------+ - | | | and data frame with no checksum and encryption by default. | b’0000: no checksum and no encryption; | - + + + The data transmission from the mobile phone to ESP device is +---------------------------------------------------------------+ - | | | controlled by this control frame. | b’0001: with checksum but no encryption; | - + + + +---------------------------------------------------------------+ - | | | | b’0010: no checksum but with encryption; | - + + + +---------------------------------------------------------------+ - | | | | b’0011: with both checksum and encryption. | - +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ - | 0x2 (b’000010) | Set the opmode of Wi-Fi. | The frame contains opmode settings for | data[0] is for opmode settings, including: | - + + + configuring for the Wi-Fi mode of ESP device. +---------------------------------------------------------------+ - | | | | 0x00: NULL; | - + + + +---------------------------------------------------------------+ - | | | | 0x01: STA; | - + + + +---------------------------------------------------------------+ - | | | | 0x02: SoftAP; | - + + + +---------------------------------------------------------------+ - | | | | 0x03: SoftAP&STA. | - + + + +---------------------------------------------------------------+ - | | | | Please set the SSID/Password/Max Connection Number of | - | | | | the AP mode in the first place if an AP gets involved. | - +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ - | 0x3 (b’000011) | Connect ESP device to the AP. | To notify ESP device that the essential information has been | No data field is contained. | - | | | sent and it is allowed to connect to the AP. | | - +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ - | 0x4 (b’000100) | Disconnect ESP device from the AP. | | No data field is contained. | - +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ - | 0x5 (b’000101) | To get the information of ESP device’s Wi-Fi mode and | | No data field is contained. | - | | it's status. | | When receiving this control frame, ESP device will send back | - | | | | a follow-up frame of Wi-Fi connection state report to | - | | | | the mobile phone with the information of the current opmode, | - | | | | connection status, SSID and so on. | - | | | | The types of information sent to the mobile phone is | - | | | | defined by the application installed on the phone. | - +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ - | 0x6 (b’000110) | Disconnect the STA device from the SoftAP (in SoftAP mode). | | Date[0~5] is taken as the MAC address for the STA device. | - | | | | If there is a second STA device, then it uses data[6-11] | - | | | | and the rest can be done in the same manner. | - +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ - | 0x7 (b'000111) | Get the version information. | | | - +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ - | 0x8 (b’001000) | Disconnect the BLE GATT link. | | ESP device will disconnect the BLE GATT link | - | | | | after receives this command. | - +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ - | 0x9 (b’001001) | Get the Wi-Fi list. | To get ESP device to scan the Wi-Fi access points around. | No data field is contained. | - | | | | When receiving this control frame, | - | | | | ESP device will send back a follow-up frame of Wi-Fi lis | - | | | | report to the mobile phone. | - +-------------------------+--------------------------------------------------------------+---------------------------------------------------------------+---------------------------------------------------------------+ +.. list-table:: + :header-rows: 1 + :widths: 5 15 20 30 + + * - Control Frame + - Implication + - Explanation + - Note - **1.2 Data Frame (0x1 b’01)** + * - 0x0 (b’000000) + - ACK + - The data field of the ACK frame uses the same sequence value of the frame to reply to. + - The data field consumes a byte and its value is the same as the sequence field of the frame to reply to. + + * - 0x1 (b’000001) + - Set ESP device to the security mode. + - To inform ESP device of the security mode to use when sending data, which is allowed to be reset multiple times during the process. Each setting affects the subsequent security mode used. - +------------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - |Data Frame(Binary)| Implication | Explanation | Note | - +==================+====================================================+===============================================================+=======================================================================+ - | 0x0 (b’000000) | Send the negotiation data. | The negotiation data will be sent to the callback | The length of the data depends on the length field. | - | | | function registered in the application layer. | | - +------------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0x1 (b’000001) | Send the BSSID for STA mode. | To send the BSSID of the AP for the STA device to | The length of the data depends on the length field. | - | | | connect under the condition that the SSID is hidden. | When the transmission direction is ESP device to the mobile phone, | - | | | | it means to provide the mobile phone with the needed information. | - +------------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0x2 (b’000010) | Send the SSID for STA mode. | To send the SSID of the AP for the STA device to connect. | The length of the data depends on the length field. | - | | | | When the transmission direction is ESP device to the mobile phone, | - | | | | it means to provide the mobile phone with the needed information. | - +------------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0x3 (b’000011) | Send the password for STA mode. | To send the password of the AP for the STA device to connect. | The length of the data depends on the length field. | - | | | | When the transmission direction is ESP device to the mobile phone, | - | | | | it means to provide the mobile phone with the needed information. | - +------------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0x4 (b’000100) | Send the SSID for SoftAP mode. | | The length of the data depends on the length field. | - | | | | When the transmission direction is ESP device to the mobile phone, | - | | | | it means to provide the mobile phone with the needed information. | - +------------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0x5 (b’000101) | Send the password for SoftAPmode. | | The length of the data depends on the length field. | - | | | | When the transmission direction is ESP device to the mobile phone, | - | | | | it means to provide the mobile phone with the needed information. | - +------------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0x6 (b’000110) | Set the maximum connection number for SoftAP mode. | | data[0] represents the value of the connection number, | - | | | | ranging from 1 to 4. When the transmission direction is ESP device | - | | | | to the mobile phone, it means to provide the mobile phone with | - | | | | the needed information. | - +------------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0x7 (b’000111) | Set the authentication mode for the SoftAP. | | data[0]: | - + + + +-----------------------------------------------------------------------+ - | | | | 0x00: OPEN | - + + + +-----------------------------------------------------------------------+ - | | | | 0x01: WEP | - + + + +-----------------------------------------------------------------------+ - | | | | 0x02: WPA_PSK | - + + + +-----------------------------------------------------------------------+ - | | | | 0x03: WPA2_PSK | - + + + +-----------------------------------------------------------------------+ - | | | | 0x04: WPA_WPA2_PSK | - + + + +-----------------------------------------------------------------------+ - | | | | When the transmission direction is ESP device to the mobile phone, | - | | | | it means to provide the mobile phone with the needed information. | - +------------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0x8 (b’001000) | Set the channel amount for SoftAP mode. | | data[0] represents the quantity of the supported channels, | - | | | | ranging from 1 to 14. | - | | | | When the transmission direction is ESP device to the mobile phone, | - | | | | it means to provide the mobile phone with the needed information. | - +------------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0x9 (b’001001) | Username | It provides the username of the GATT client when using | The length of the data depends on the length field. | - | | | encryption of enterprise level. | | - +------------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0xa (b’001010) | CA Certification | It provides the CA Certification when using encryption | The length of the data depends on the length field. | - | | | of enterprise level. | The frame supports to be fragmented if the data length is not enough. | - +------------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0xb (b’001011) | Client Certification | It provides the client certification when | The length of the data depends on the length field. | - | | | using encryption of enterprise level. | The frame supports to be fragmented if the data length is not enough. | - | | | Whether the private key is contained or not | | - | | | depends on the content of the certification. | | - +------------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0xc (b’001100) | Server Certification | It provides the sever certification when using | The length of the data depends on the length field. | - | | | encryption of enterprise level. Whether the private key is | The frame supports to be fragmented if the data length is not enough. | - | | | contained or not depends on the content of the certification. | | - +------------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0xd (b’001101) | ClientPrivate Key | It provides the private key of the client when | The length of the data depends on the length field. | - | | | using encryption of enterprise level. | The frame supports to be fragmented if the data length is not enough. | - +------------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0xe (b’001110) | ServerPrivate Key | It provides the private key of the sever when | The length of the data depends on the length field. | - | | | using encryption of enterprise level. | The frame supports to be fragmented if the data length is not enough. | - +------------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0xf (b’001111) | Wi-Fi Connection State Report | To notify the phone of the ESP device's Wi-Fi status, | data[0] represents opmode, including: | - + + + including STA status and SoftAP status. +-----------------------------------------------------------------------+ - | | | It is for the STA device to connect to the | 0x00: NULL | - + + + mobile phone or the SoftAP. +-----------------------------------------------------------------------+ - | | | However, when the mobile phone receives the Wi-Fi status, | 0x01: STA | - + + + it can reply to other frames in addition to this frame. +-----------------------------------------------------------------------+ - | | | | 0x02: SoftAP | - + + + +-----------------------------------------------------------------------+ - | | | | 0x03: SoftAP&STA | - + + + +-----------------------------------------------------------------------+ - | | | | data[1]:the connection state of the STA device, | - | | | | 0x0 indicates a connection state, | - | | | | and others represent a disconnected state; | - + + + +-----------------------------------------------------------------------+ - | | | | data[2]:the connection state of the SoftAP, | - | | | | that is, how many STA devices have been connected. | - + + + +-----------------------------------------------------------------------+ - | | | | data[3] and the subsequent is in accordance with the | - | | | | format of SSID/BSSID information. | - +------------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0x10 (b’010000) | Version | | data[0]= great versiondata[1]= sub version | - +------------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0x11 (b’010001) | Wi-Fi List | To send the Wi-Fi list to ESP device. | The format of the data frame is length + RSSI + SSID | - | | | | and it supports to be sent into fragments | - | | | | if the data length is too long. | - +------------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0x12 (b’010010) | Report Error | To notify the mobile phone that there is an error with BluFi. | 0x00: sequence error | - + + + +-----------------------------------------------------------------------+ - | | | | 0x01: checksum error | - + + + +-----------------------------------------------------------------------+ - | | | | 0x02: decrypt error | - + + + +-----------------------------------------------------------------------+ - | | | | 0x03: encrypt error | - + + + +-----------------------------------------------------------------------+ - | | | | 0x04: init security error | - + + + +-----------------------------------------------------------------------+ - | | | | 0x05: dh malloc error | - + + + +-----------------------------------------------------------------------+ - | | | | 0x06: dh param error | - + + + +-----------------------------------------------------------------------+ - | | | | 0x07: read param error | - + + + +-----------------------------------------------------------------------+ - | | | | 0x08: make public error | - +------------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ - | 0x13 (b’010011) | Custom Data | To send or receive custom data. | The data frame supports to be sent into | - | | | | fragments if the data length is too long. | - +------------------+----------------------------------------------------+---------------------------------------------------------------+-----------------------------------------------------------------------+ + If it is not set, ESP device will send the control frame and data frame with no checksum and encryption by default. The data transmission from the mobile phone to ESP device is controlled by this control frame. + - The data field consumes a byte. The higher 4 bits are for the security mode setting of the control frame, and the lower 4 bits are for the security mode setting of the data frame. + + * b’0000: no checksum and no encryption; + * b’0001: with checksum but no encryption; + * b’0010: no checksum but with encryption; + * b’0011: with both checksum and encryption. + + * - 0x2 (b’000010) + - Set the opmode of Wi-Fi. + - The frame contains opmode settings for configuring the Wi-Fi mode of ESP device. + - data[0] is for opmode settings, including: + + * 0x00: NULL + * 0x01: STA + * 0x02: SoftAP + * 0x03: SoftAP & STA + + Please set the SSID/Password/Max Connection Number of the AP mode in the first place if an AP gets involved. + + * - 0x3 (b’000011) + - Connect ESP device to the AP. + - To notify ESP device that the essential information has been sent and it is allowed to connect to the AP. + - No data field is contained. + + * - 0x4 (b’000100) + - Disconnect ESP device from the AP. + - + - No data field is contained. + + * - 0x5 (b’000101) + - To get the information of ESP device’s Wi-Fi mode and it’s status. + - + - * No data field is contained. When receiving this control frame, ESP device will send back a follow-up frame of Wi-Fi connection state report to the mobile phone with the information of the current opmode, connection status, SSID and so on. + * The types of information sent to the mobile phone is defined by the application installed on the phone. + + * - 0x6 (b’000110) + - Disconnect the STA device from the SoftAP (in SoftAP mode). + - + - Date[0~5] is taken as the MAC address for the STA device. If there is a second STA device, then it uses data[6-11] and the rest can be done in the same manner. + + * - 0x7 (b’000111) + - Get the version information. + - + - + + * - 0x8 (b’001000) + - Disconnect the BLE GATT link. + - + - ESP device will disconnect the BLE GATT link after receives this command. + + * - 0x9 (b’001001) + - Get the Wi-Fi list. + - To get ESP device to scan the Wi-Fi access points around. + - No data field is contained. When receiving this control frame, ESP device will send back a follow-up frame of Wi-Fi list report to the mobile phone. + + + +1.2 Data Frame (Binary: 0x1 b’01) + +.. list-table:: + :header-rows: 1 + :widths: 5 15 20 30 + + * - Data Frame + - Implication + - Explanation + - Note + * - 0x0 (b’000000) + - Send the negotiation data. + - The negotiation data will be sent to the callback function registered in the application layer. + - The length of the data depends on the length field. + * - 0x1 (b’000001) + - Send the BSSID for STA mode. + - To send the BSSID of the AP for the STA device to connect under the condition that the SSID is hidden. + - Please refer to Note 1 below. + * - 0x2 (b’000010) + - Send the SSID for STA mode. + - To send the SSID of the AP for the STA device to connect. + - Please refer to Note 1 below. + * - 0x3 (b’000011) + - Send the password for STA mode. + - To send the password of the AP for the STA device to connect. + - Please refer to Note 1 below. + * - 0x4 (b’000100) + - Send the SSID for SoftAP mode. + - + - Please refer to Note 1 below. + * - 0x5 (b’000101) + - Send the password for SoftAPmode. + - + - Please refer to Note 1 below. + * - 0x6 (b’000110) + - Set the maximum connection number for SoftAP mode. + - + - data[0] represents the value of the connection number, ranging from 1 to 4. When the transmission direction is ESP device to the mobile phone, it means to provide the mobile phone with the needed information. + * - 0x7 (b’000111) + - Set the authentication mode for the SoftAP. + - + - data[0]: + + * 0x00: OPEN + * 0x01: WEP + * 0x02: WPA_PSK + * 0x03: WPA2_PSK + * 0x04: WPA_WPA2_PSK + + When the transmission direction is ESP device to the mobile phone, it means to provide the mobile phone with the needed information. + * - 0x8 (b’001000) + - Set the number of channels for SoftAP mode. + - + - data[0] represents the quantity of the supported channels, ranging from 1 to 14. When the transmission direction is ESP device to the mobile phone, it means to provide the mobile phone with the needed information. + * - 0x9 (b’001001) + - Username + - It provides the username of the GATT client when using encryption of enterprise level. + - The length of the data depends on the length field. + * - 0xa (b’001010) + - CA Certification + - It provides the CA Certification when using encryption of enterprise level. + - Please refer to Note 2 below. + * - 0xb (b’001011) + - Client Certification + - It provides the client certification when using encryption of enterprise level. Whether the private key is contained or not depends on the content of the certification. + - Please refer to Note 2 below. + * - 0xc (b’001100) + - Server Certification + - It provides the sever certification when using encryption of enterprise level. Whether the private key is contained or not depends on the content of the certification. + - Please refer to Note 2 below. + * - 0xd (b’001101) + - Client Private Key + - It provides the private key of the client when using encryption of enterprise level. + - Please refer to Note 2 below. + * - 0xe (b’001110) + - Server Private Key + - It provides the private key of the sever when using encryption of enterprise level. + - Please refer to Note 2 below. + * - 0xf (b’001111) + - Wi-Fi Connection State Report + - To notify the phone of the ESP device’s Wi-Fi status, including STA status and SoftAP status. It is for the STA device to connect to the mobile phone or the SoftAP. However, when the mobile phone receives the Wi-Fi status, it can reply to other frames in addition to this frame. + - data[0] represents opmode, including: + + * 0x00: NULL + * 0x01: STA + * 0x02: SoftAP + * 0x03: SoftAP & STA + + data[1]:the connection state of the STA device, 0x0 indicates a connection state, and others represent a disconnected state; + + data[2]:the connection state of the SoftAP, that is, how many STA devices have been connected. + + data[3] and the subsequent is in accordance with the format of SSID/BSSID information. + * - 0x10 (b’010000) + - Version + - + - * data[0]= great version + * data[1]= sub version + * - 0x11 (b’010001) + - Wi-Fi List + - To send the Wi-Fi list to ESP device. + - The format of the data frame is length + RSSI + SSID and it supports to be sent into fragments if the data length is too long. + * - 0x12 (b’010010) + - Report Error + - To notify the mobile phone that there is an error with BluFi. + - * 0x00: sequence error + * 0x01: checksum error + * 0x02: decrypt error + * 0x03: encrypt error + * 0x04: init security error + * 0x05: dh malloc error + * 0x06: dh param error + * 0x07: read param error + * 0x08: make public error + * - 0x13 (b’010011) + - Custom Data + - To send or receive custom data. + - The data frame supports to be sent into fragments if the data length is too long. + +.. note:: + + - Note 1: The length of the data depends on the length field. When the transmission direction is ESP device to the mobile phone, it means to provide the mobile phone with the needed information. + + - Note 2: The length of the data depends on the length field. The frame supports to be fragmented if the data length is not enough. 2. Frame Control Control field, takes 1 byte and each bit has a different meaning. - +--------------------+------------------------------------------------------------------------------------------------+ - | Bit | Meaning | - +====================+================================================================================================+ - | 0x01 | Indicates whether the frame is encrypted. | - + +------------------------------------------------------------------------------------------------+ - | | 1 means encryption, and 0 means unencrypted. | - + +------------------------------------------------------------------------------------------------+ - | | The encrypted part of the frame includes | - | | the full clear data before the DATA field is encrypted (no checksum). | - + +------------------------------------------------------------------------------------------------+ - | | Control frame is not encrypted, so this bit is 0. | - +--------------------+------------------------------------------------------------------------------------------------+ - | 0x02 | The data field that indicates whether a frame contains | - | | a checksum (such as SHA1,MD5,CRC, etc.) for the end of | - | | the frame data field includes SEQUCNE + data length + clear text. | - | | Both the control frame and the data frame can contain a check bit or not. | - +--------------------+------------------------------------------------------------------------------------------------+ - | 0x04 | Represents the data direction. | - +--------------------+------------------------------------------------------------------------------------------------+ - | | 0 means the mobile phone to ESP device; | - +--------------------+------------------------------------------------------------------------------------------------+ - | | 1 means ESP device to the mobile phone. | - +--------------------+------------------------------------------------------------------------------------------------+ - | 0x08 | Indicates whether the other person is required to reply to an ACK. | - +--------------------+------------------------------------------------------------------------------------------------+ - | | 0 indicates no requirement; | - +--------------------+------------------------------------------------------------------------------------------------+ - | | 1 indicates to reply Ack. | - +--------------------+------------------------------------------------------------------------------------------------+ - | 0x10 | Indicates whether there are subsequent data fragments. | - +--------------------+------------------------------------------------------------------------------------------------+ - | | 0 indicates that there are no subsequent data fragments for this frame; | - +--------------------+------------------------------------------------------------------------------------------------+ - | | 1 indicates that there are subsequent data fragments and used to transmit longer data. | - +--------------------+------------------------------------------------------------------------------------------------+ - | | In the case of a frag frame, | - | | the total length of the current content section + subsequent content section is given, | - | | in the first 2 bytes of the data field (that is, the content data of the maximum support 64K). | - +--------------------+------------------------------------------------------------------------------------------------+ - | 0x10~0x80 reserved | | - +--------------------+------------------------------------------------------------------------------------------------+ + +.. list-table:: + :header-rows: 1 + :widths: 10 35 + + * - Bit + - Meaning + * - 0x01 + - Indicates whether the frame is encrypted. + + * 1 means encryption + * 0 means unencrypted + + The encrypted part of the frame includes the full clear data before the DATA field is encrypted (no checksum). Control frame is not encrypted, so this bit is 0. + * - 0x02 + - The data field that indicates whether a frame contains a checksum (such as SHA1,MD5,CRC, etc.) for the end of the frame. Data field includes sequence + data length + clear text. Both the control frame and the data frame can contain a check bit or not. + * - 0x04 + - Represents the data direction. + + * 0 means the mobile phone to ESP device; + * 1 means ESP device to the mobile phone. + * - 0x08 + - Indicates whether the other person is required to reply to an ACK. + + * 0 indicates no requirement; + * 1 indicates to reply ACK. + * - 0x10 + - Indicates whether there are subsequent data fragments. + + * 0 indicates that there are no subsequent data fragments for this frame; + * 1 indicates that there are subsequent data fragments and used to transmit longer data. + + In the case of a frag frame, the total length of the current content section + subsequent content section is given, in the first 2 bytes of the data field (that is, the content data of the maximum support 64 K). + * - 0x10~0x80 + - reserved 3. Sequence Control @@ -448,7 +471,7 @@ GATT Related Instructions UUID >>>>> -BluFi Service UUID: 0xFFFF,16 bit +BluFi Service UUID: 0xFFFF, 16 bit BluFi (the mobile -> {IDF_TARGET_NAME}): 0xFF01, writable diff --git a/docs/en/api-guides/bootloader.rst b/docs/en/api-guides/bootloader.rst index c413204bd4..1228d03582 100644 --- a/docs/en/api-guides/bootloader.rst +++ b/docs/en/api-guides/bootloader.rst @@ -10,7 +10,7 @@ The ESP-IDF Software 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; 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 it. +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_BOOTLOADER_OFFSET} in the flash. @@ -46,7 +46,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 from flash and uses these settings to load it. 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 and re-configures the flash, it reads values from the currently selected app binary header not the bootloader header. This allows an OTA update to change the SPI flash settings in use. +The :ref:`first-stage-bootloader` in ROM reads the :ref:`second-stage-bootloader` header information from flash and uses this infomation 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 @@ -66,21 +66,21 @@ Sometimes it is desirable to have a way for the device to fall back to a known-g To roll back to the original "factory" device configuration and clear any user settings, configure the config item :ref:`CONFIG_BOOTLOADER_FACTORY_RESET` in the bootloader. -The factory reset mechanism allows to reset the device to factory settings in two ways: +The factory reset mechanism allows the device to be factory reset in two ways: -- Clear one or more data partitions. :ref:`CONFIG_BOOTLOADER_DATA_FACTORY_RESET` allows customers to select which data partitions will be erased when the factory reset is executed. +- Clear one or more data partitions. The :ref:`CONFIG_BOOTLOADER_DATA_FACTORY_RESET` option allows users to specify which data partitions will be erased when the factory reset is executed. - Can specify the names of partitions as a comma-delimited list with optional spaces for readability. (Like this: ``nvs, phy_init, nvs_custom``). + Users can specify the names of partitions as a comma-delimited list with optional spaces for readability. (Like this: ``nvs, phy_init, nvs_custom``). - Make sure that the names of partitions specified in the partition table and here are the same. Partitions of type "app" cannot be specified here. + Make sure that the names of partitions specified in the option are the same as those found in the partition table. Partitions of type "app" cannot be specified here. -- Boot from "factory" app partition. :ref:`CONFIG_BOOTLOADER_OTA_DATA_ERASE` - the device will boot from the default "factory" app partition (or if there is no factory app partition in the partition table then the default ota app partition) after a factory reset. This is done by erasing the OTA data partition which holds the currently selected OTA partition slot. The "factory" app partition slot (if it exists) is never updated via OTA, so resetting to this allows reverting to a "known good" firmware application. +- Boot from "factory" app partition. Enabling the :ref:`CONFIG_BOOTLOADER_OTA_DATA_ERASE` option will cause the device to boot from the default "factory" app partition after a factory reset (or if there is no factory app partition in the partition table then the default ota app partition is selected instead). This reset process involves erasing the OTA data partition which holds the currently selected OTA partition slot. The "factory" app partition slot (if it exists) is never updated via OTA, so resetting to this allows reverting to a "known good" firmware application. Either or both of these configuration options can be enabled independently. In addition, the following configuration options control the reset condition: -- :ref:`CONFIG_BOOTLOADER_NUM_PIN_FACTORY_RESET`- number of the GPIO input for factory reset uses to trigger a factory reset, this GPIO must be pulled low or high (configurable) on reset to trigger this. +- :ref:`CONFIG_BOOTLOADER_NUM_PIN_FACTORY_RESET`- The input GPIO number used to trigger a factory reset. This GPIO must be pulled low or high (configurable) on reset to trigger this. - :ref:`CONFIG_BOOTLOADER_HOLD_TIME_GPIO`- this is hold time of GPIO for reset/test mode (by default 5 seconds). The GPIO must be held continuously for this period of time after reset before a factory reset or test partition boot (as applicable) is performed. @@ -90,6 +90,7 @@ In addition, the following configuration options control the reset condition: Boot from Test Firmware ------------------------ + It's possible to write a special firmware app for testing in production, and boot this firmware when needed. The project partition table will need a dedicated app partition entry for this testing app, type ``app`` and subtype ``test`` (see :doc:`/api-guides/partition-tables`). Implementing a dedicated test app firmware requires creating a totally separate ESP-IDF project for the test app (each project in ESP-IDF only builds one app). The test app can be developed and tested independently of the main project, and then integrated at production testing time as a pre-compiled .bin file which is flashed to the address of the main project's test app partition. @@ -98,7 +99,7 @@ To support this functionality in the main project's bootloader, set the configur - :ref:`CONFIG_BOOTLOADER_NUM_PIN_APP_TEST` - GPIO number to boot TEST partition. The selected GPIO will be configured as an input with internal pull-up enabled. To trigger a test app, this GPIO must be pulled low on reset. - After the GPIO input is deactivated and the device reboots, the normally configured application will boot (factory or any OTA app partition slot). + Once the GPIO input is released (allowing it to be pulled up) and the device has been reboot, the normally configured application will boot (factory or any OTA app partition slot). - :ref:`CONFIG_BOOTLOADER_HOLD_TIME_GPIO` - this is hold time of GPIO for reset/test mode (by default 5 seconds). The GPIO must be held low continuously for this period of time after reset before a factory reset or test partition boot (as applicable) is performed. @@ -115,7 +116,7 @@ Watchdog By default, the hardware RTC Watchdog timer remains running while the bootloader is running and will automatically reset the chip if no app has successfully started after 9 seconds. - The timeout period can be adjusted by setting :ref:`CONFIG_BOOTLOADER_WDT_TIME_MS` and recompiling the bootloader. -- The app's behaviour can be adjusted so the RTC Watchdog remains enabled after app startup. The Watchdog would need to be explicitly reset or "fed" by the app to avoid a reset. To do this, set the :ref:`CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE` option, modify the app as needed, and then recompile the app. +- The app's behaviour can be adjusted so the RTC Watchdog remains enabled after app startup. The Watchdog would need to be explicitly reset (i.e., fed) by the app to avoid a reset. To do this, set the :ref:`CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE` option, modify the app as needed, and then recompile the app. - The RTC Watchdog can be disabled in the bootloader by disabling the :ref:`CONFIG_BOOTLOADER_WDT_ENABLE` setting and recompiling the bootloader. This is not recommended. .. _bootloader-size: @@ -144,18 +145,17 @@ Options to work around this are: - Reduce :ref:`bootloader log level `. Setting log level to Warning, Error or None all significantly reduce the final binary size (but may make it harder to debug). - Set :ref:`CONFIG_PARTITION_TABLE_OFFSET` to a higher value than 0x8000, to place the partition table later in the flash. This increases the space available for the bootloader. If the :doc:`partition table ` CSV file contains explicit partition offsets, they will need changing so no partition has an offset lower than ``CONFIG_PARTITION_TABLE_OFFSET + 0x1000``. (This includes the default partition CSV files supplied with ESP-IDF.) -When Secure Boot V2 is enabled, there is also an absolute binary size limit of {IDF_TARGET_MAX_BOOTLOADER_SIZE} (excluding the 4KB signature), because the bootloader is first loaded into a fixed size buffer for verification. +When Secure Boot V2 is enabled, there is also an absolute binary size limit of {IDF_TARGET_MAX_BOOTLOADER_SIZE} (excluding the 4 KB signature), because the bootloader is first loaded into a fixed size buffer for verification. Fast boot from Deep Sleep ------------------------- -The bootloader has the :ref:`CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP` option which allows to reduce the wake-up time (useful to reduce consumption). This option is available when :ref:`CONFIG_SECURE_BOOT` option is disabled. Reduction of time is achieved due to the lack of image verification. During the first boot, the bootloader stores the address of the application being launched in the RTC FAST memory. And during the awakening, this address is used for booting without any checks, thus fast loading is achieved. +The bootloader has the :ref:`CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP` option which allows the wake-up time from deep sleep to be reduced (useful for reducing power consumption). This option is available when :ref:`CONFIG_SECURE_BOOT` option is disabled. Reduction of time is achieved due to the lack of image verification. During the first boot, the bootloader stores the address of the application being launched in the RTC FAST memory. And during the awakening, this address is used for booting without any checks, thus fast loading is achieved. Custom bootloader ----------------- -The current bootloader implementation allows a project to extend it or modify it. There are two ways of doing it: by implementing hooks or by overriding it. -Both ways are presented in :example:`custom_bootloader` folder in ESP-IDF examples: +The current bootloader implementation allows a project to extend it or modify it. There are two ways of doing it: by implementing hooks or by overriding it. Both ways are presented in :example:`custom_bootloader` folder in ESP-IDF examples: * `bootloader_hooks` which presents how to connect some hooks to the bootloader initialization * `bootloader_override` which presents how to override the bootloader implementation diff --git a/docs/en/api-guides/build-system.rst b/docs/en/api-guides/build-system.rst index 9885bf3e3b..03c0d5737f 100644 --- a/docs/en/api-guides/build-system.rst +++ b/docs/en/api-guides/build-system.rst @@ -781,16 +781,16 @@ Browse the :idf_file:`/tools/cmake/project.cmake` file and supporting functions Example Component CMakeLists ============================ -Because the build environment tries to set reasonable defaults that will work most -of the time, component ``CMakeLists.txt`` can be very small or even empty (see `Minimal Component CMakeLists`_). However, overriding `component variables`_ is usually required for some functionality. +Because the build environment tries to set reasonable defaults that will work most of the time, component ``CMakeLists.txt`` can be very small or even empty (see `Minimal Component CMakeLists`_). However, overriding `component variables`_ is usually required for some functionality. Here are some more advanced examples of component CMakeLists files. +.. _add_conditional_config: + Adding conditional configuration -------------------------------- -The configuration system can be used to conditionally compile some files -depending on the options selected in the project configuration. +The configuration system can be used to conditionally compile some files depending on the options selected in the project configuration. .. highlight:: none @@ -1019,6 +1019,8 @@ For example projects or other projects where you don't want to specify a full sd To override the name of this file or to specify multiple files, set the ``SDKCONFIG_DEFAULTS`` environment variable or set ``SDKCONFIG_DEFAULTS`` in top-level CMakeLists.txt. If specifying multiple files, use semicolon as the list separator. File names not specified as full paths are resolved relative to current project. +Some of the IDF examples include a ``sdkconfig.ci`` file. This is part of the continuous integration (CI) test framework and is ignored by the normal build process. + Target-dependent sdkconfig defaults ----------------------------------- diff --git a/docs/en/api-guides/fatal-errors.rst b/docs/en/api-guides/fatal-errors.rst index 65354fd238..cc35275668 100644 --- a/docs/en/api-guides/fatal-errors.rst +++ b/docs/en/api-guides/fatal-errors.rst @@ -12,14 +12,17 @@ In certain situations, execution of the program can not be continued in a well d - CPU Exceptions: |CPU_EXCEPTIONS_LIST| - System level checks and safeguards: - - :doc:`Interrupt watchdog <../api-reference/system/wdts>` timeout - - :doc:`Task watchdog <../api-reference/system/wdts>` timeout (only fatal if :ref:`CONFIG_ESP_TASK_WDT_PANIC` is set) - - Cache access error - - Brownout detection event - - Stack overflow - - Stack smashing protection check - - Heap integrity check - - Undefined behavior sanitizer (UBSAN) checks + .. list:: + + - :doc:`Interrupt watchdog <../api-reference/system/wdts>` timeout + - :doc:`Task watchdog <../api-reference/system/wdts>` timeout (only fatal if :ref:`CONFIG_ESP_TASK_WDT_PANIC` is set) + - Cache access error + :CONFIG_ESP_SYSTEM_MEMPROT_FEATURE: - Memory protection fault + - Brownout detection event + - Stack overflow + - Stack smashing protection check + - Heap integrity check + - Undefined behavior sanitizer (UBSAN) checks - Failed assertions, via ``assert``, ``configASSERT`` and similar macros. @@ -207,7 +210,7 @@ If :doc:`IDF Monitor ` is used, Program Counter values will b MSTATUS : 0x00001881 MTVEC : 0x40380001 MCAUSE : 0x00000007 MTVAL : 0x00000000 MHARTID : 0x00000000 - Moreover, it is also capable of generating and printing a backtrace thanks to the stack dump provided by the board in the panic handler. + Moreover, the :doc:`IDF Monitor ` is also capable of generating and printing a backtrace thanks to the stack dump provided by the board in the panic handler. The output looks like this: :: @@ -224,7 +227,7 @@ If :doc:`IDF Monitor ` is used, Program Counter values will b #5 0x00000000 in ?? () Backtrace stopped: frame did not save the PC - While this is very handy efficient, it requires the user to use :doc:`IDF Monitor `. Thus, in order to generate and print a backtrace while using another monitor program, it is possible to activate :ref:`CONFIG_ESP_SYSTEM_USE_EH_FRAME` option from the menuconfig. + While the backtrace above is very handy, it requires the user to use :doc:`IDF Monitor `. Thus, in order to generate and print a backtrace while using another monitor program, it is possible to activate :ref:`CONFIG_ESP_SYSTEM_USE_EH_FRAME` option from the menuconfig. This option will let the compiler generate DWARF information for each function of the project. Then, when a CPU exception occurs, the panic handler will parse these data and determine the backtrace of the task that failed. The output looks like this: @@ -232,12 +235,11 @@ If :doc:`IDF Monitor ` is used, Program Counter values will b Backtrace: 0x42009e9a:0x3fc92120 0x42009ea6:0x3fc92120 0x42009ec2:0x3fc92130 0x42024620:0x3fc92150 0x40387d7c:0x3fc92160 0xfffffffe:0x3fc92170 - These PC:SP pairs represent PC, the Program Counter and SP, the Stack Pointer for each stack frame of the current task. + These ``PC:SP`` pairs represent the PC (Program Counter) and SP (Stack Pointer) for each stack frame of the current task. - The main benefit of this option is that this trace is generate by the board itself. Its drawback is that it results in a larger compiled binary, with an increase that can go from 20% to 100%. Finally, it is highly advised to not use this option for production as it results in the presence of debug information within the final binary. + The main benefit of the :ref:`CONFIG_ESP_SYSTEM_USE_EH_FRAME` option is that the backtrace is generated by the board itself (without the need for :doc:`IDF Monitor `). However, the option's drawback is that it results in an increase of the compiled binary's size (ranging from 20% to 100% increase in size). Furthermore, this option causes debug information to be included within the compiled binary. Therefore, users are strongly advised not to enable this option in mass/final production builds. - To find the location where a fatal error has happened, look at the lines which follow the "Backtrace" line. Fatal error location is the top line, and subsequent lines show the call stack. .. _GDB-Stub: @@ -374,6 +376,20 @@ Indicates that interrupt watchdog timeout has occured. See :doc:`Watchdogs <../a In some situations ESP-IDF will temporarily disable access to external SPI Flash and SPI RAM via caches. For example, this happens with spi_flash APIs are used to read/write/erase/mmap regions of SPI Flash. In these situations, tasks are suspended, and interrupt handlers not registered with ``ESP_INTR_FLAG_IRAM`` are disabled. Make sure that any interrupt handlers registered with this flag have all the code and data in IRAM/DRAM. Refer to the :ref:`SPI flash API documentation ` for more details. +.. only:: CONFIG_ESP_SYSTEM_MEMPROT_FEATURE + + Memory protection fault + ^^^^^^^^^^^^^^^^^^^^^^^ + + {IDF_TARGET_NAME} Permission Control feature is used in ESP-IDF to prevent the following types of memory access: + + * writing to instruction RAM after the program is loaded + * executing code from data RAM (areas used for heap and static .data and .bss) + + Such operations are not necessary for most programs. Prohibiting such operations typically makes software vulnerabilities harder to exploit. Applications which rely on dynamic loading or self-modifying code may disable this protection using :ref:`CONFIG_ESP_SYSTEM_MEMPROT_FEATURE` Kconfig option. + + When the fault occurs, the panic handler reports the address of the fault and the type of memory access that caused it. + Other Fatal Errors ------------------ diff --git a/docs/en/api-guides/hlinterrupts.rst b/docs/en/api-guides/hlinterrupts.rst index c5e28cb119..abb65aaf94 100644 --- a/docs/en/api-guides/hlinterrupts.rst +++ b/docs/en/api-guides/hlinterrupts.rst @@ -9,16 +9,39 @@ The Xtensa architecture has support for 32 interrupts, divided over 8 levels, pl Interrupt Levels ---------------- -===== ================= ==================================================== -Level Symbol Remark -===== ================= ==================================================== -1 N/A Exception and level 0 interrupts. Handled by ESP-IDF -2-3 N/A Medium level interrupts. Handled by ESP-IDF -4 xt_highint4 Normally used by ESP-IDF debug logic -5 xt_highint5 Free to use -NMI xt_nmi Free to use -dbg xt_debugexception Debug exception. Called on e.g. a BREAK instruction. -===== ================= ==================================================== +.. only:: esp32 + + ===== ================= ==================================================== + Level Symbol Remark + ===== ================= ==================================================== + 1 N/A Exception and level 0 interrupts. Handled by ESP-IDF + 2-3 N/A Medium level interrupts. Handled by ESP-IDF + 4 xt_highint4 Free to use :ref:`(See 1) ` + 5 xt_highint5 Normally used by ESP-IDF debug logic :ref:`(See 1) ` + NMI xt_nmi Free to use + dbg xt_debugexception Debug exception. Called on e.g. a BREAK instruction. :ref:`(See 2) ` + ===== ================= ==================================================== + + + .. _hlinterrupts-pin-notes: + + The following notes give more information about the items in the tables above. + + 1. ESP-IDF debug logic can be configured to run on `xt_highint4` or `xt_highint5` in :ref:`CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL`. Bluetooth's interrupt can be configured to run on level 4 by enabling :ref:`CONFIG_BTDM_CTRL_HLI`. If :ref:`CONFIG_BTDM_CTRL_HLI` is enabled, ESP-IDF debug logic must be running on level 5 interrupt. + 2. If :ref:`CONFIG_BTDM_CTRL_HLI` is enabled, `xt_debugexception` is used to fix `live lock issue `_ in ESP32 ECO3. + +.. only:: not esp32 + + ===== ================= ==================================================== + Level Symbol Remark + ===== ================= ==================================================== + 1 N/A Exception and level 0 interrupts. Handled by ESP-IDF + 2-3 N/A Medium level interrupts. Handled by ESP-IDF + 4 xt_highint4 Normally used by ESP-IDF debug logic + 5 xt_highint5 Free to use + NMI xt_nmi Free to use + dbg xt_debugexception Debug exception. Called on e.g. a BREAK instruction. + ===== ================= ==================================================== Using these symbols is done by creating an assembly file (suffix .S) and defining the named symbols, like this:: @@ -31,7 +54,7 @@ Using these symbols is done by creating an assembly file (suffix .S) and definin rsr a0, EXCSAVE_5 rfi 5 -For a real-life example, see the :component_file:`esp_system/port/soc/{IDF_TARGET_PATH_NAME}/dport_panic_highint_hdl.S` file; the panic handler interrupt is implemented there. +For a real-life example, see the :component_file:`esp_system/port/soc/{IDF_TARGET_PATH_NAME}/highint_hdl.S` file; the panic handler interrupt is implemented there. Notes @@ -41,6 +64,10 @@ Notes (The panic handler interrupt does call normal C code, but this is OK because there is no intention of returning to the normal code flow afterwards.) + .. only:: esp32 + + And if :ref:`CONFIG_BTDM_CTRL_HLI` is enabled, it does call normal C code in high-level interrupt, but this is OK becase we add some protection for it. + - Make sure your assembly code gets linked in. If the interrupt handler symbol is the only symbol the rest of the code uses from this file, the linker will take the default ISR instead and not link the assembly file into the final project. To get around this, in the assembly file, define a symbol, like this:: diff --git a/docs/en/api-guides/index.rst b/docs/en/api-guides/index.rst index 22ce505dbd..d049edff82 100644 --- a/docs/en/api-guides/index.rst +++ b/docs/en/api-guides/index.rst @@ -28,6 +28,7 @@ API Guides Linker Script Generation Memory Types lwIP TCP/IP Stack + OpenThread Partition Tables Performance RF Calibration @@ -43,4 +44,5 @@ API Guides :esp32: Unit Testing (Legacy GNU Make) :SOC_USB_OTG_SUPPORTED: USB OTG Console :SOC_USB_SERIAL_JTAG_SUPPORTED: USB Serial/JTAG Controller Console - WiFi Driver + Wi-Fi Driver + Wi-Fi Security diff --git a/docs/en/api-guides/jtag-debugging/configure-other-jtag.rst b/docs/en/api-guides/jtag-debugging/configure-other-jtag.rst index cd4a03ae1f..0d28f2b4fb 100644 --- a/docs/en/api-guides/jtag-debugging/configure-other-jtag.rst +++ b/docs/en/api-guides/jtag-debugging/configure-other-jtag.rst @@ -5,6 +5,19 @@ Configure Other JTAG Interface Refer to section :ref:`jtag-debugging-selecting-jtag-adapter` for guidance what JTAG interface to select, so it is able to operate with OpenOCD and {IDF_TARGET_NAME}. Then follow three configuration steps below to get it working. +.. only:: SOC_USB_SERIAL_JTAG_SUPPORTED + + Configure eFuses + ^^^^^^^^^^^^^^^^ + + By default, {IDF_TARGET_NAME} JTAG interface is connected to the :doc:`built-in USB_SERIAL_JTAG peripheral `. To use an external JTAG adapter instead, you need to switch the JTAG interface to the GPIO pins. This can be done by burning eFuses using ``espefuse.py`` tool. + + Burning eFuses is an irreversible operation, so consider both options below before starting the process. + + - Burning ``DIS_USB_JTAG`` eFuse will permanently disable the connection between USB_SERIAL_JTAG and the JTAG port of the CPU. JTAG interface can then be connected to |jtag-gpio-list|. Note that USB CDC functionality of USB_SERIAL_JTAG will still be useable, i.e. flashing and monitoring over USB CDC will still work. + + - Burning ``JTAG_SEL_ENABLE`` eFuse will enable selection of JTAG interface by a strapping pin, |jtag-sel-gpio|. If the strapping pin is low when {IDF_TARGET_NAME} is reset, JTAG interface will use |jtag-gpio-list|. If the strapping pin is high, USB_SERIAL_JTAG will be used as the JTAG interface. + Configure Hardware ^^^^^^^^^^^^^^^^^^ diff --git a/docs/en/api-guides/jtag-debugging/esp32c3.inc b/docs/en/api-guides/jtag-debugging/esp32c3.inc index 14373a45a5..4c065b6a57 100644 --- a/docs/en/api-guides/jtag-debugging/esp32c3.inc +++ b/docs/en/api-guides/jtag-debugging/esp32c3.inc @@ -125,6 +125,9 @@ * - MTMS / GPIO4 - TMS +.. |jtag-sel-gpio| replace:: GPIO10 +.. |jtag-gpio-list| replace:: GPIO4-GPIO7 + --- .. run-openocd-d3 diff --git a/docs/en/api-guides/jtag-debugging/esp32s3.inc b/docs/en/api-guides/jtag-debugging/esp32s3.inc index d83f3bd074..cd274ca066 100644 --- a/docs/en/api-guides/jtag-debugging/esp32s3.inc +++ b/docs/en/api-guides/jtag-debugging/esp32s3.inc @@ -111,15 +111,18 @@ * - ESP32-S3 Pin - JTAG Signal - * - MTDO + * - MTDO / GPIO40 - TDO - * - MTDI + * - MTDI / GPIO41 - TDI - * - MTCK + * - MTCK / GPIO39 - TCK - * - MTMS + * - MTMS / GPIO42 - TMS +.. |jtag-sel-gpio| replace:: GPIO3 +.. |jtag-gpio-list| replace:: GPIO39-GPIO42 + --- .. run-openocd-d3 diff --git a/docs/en/api-guides/jtag-debugging/index.rst b/docs/en/api-guides/jtag-debugging/index.rst index 1ba519de07..a889499007 100644 --- a/docs/en/api-guides/jtag-debugging/index.rst +++ b/docs/en/api-guides/jtag-debugging/index.rst @@ -13,15 +13,15 @@ This document provides a guide to installing OpenOCD for {IDF_TARGET_NAME} and d :ref:`jtag-debugging-setup-openocd` Procedure to install OpenOCD and verify that it is installed. :ref:`jtag-debugging-configuring-target` - Configuration of OpenOCD software and set up JTAG adapter hardware that will make together a debugging target. + Configuration of OpenOCD software and setting up of JTAG adapter hardware, which together make up the debugging target. :ref:`jtag-debugging-launching-debugger` Steps to start up a debug session with GDB from :ref:`jtag-debugging-using-debugger-eclipse` and from :ref:`jtag-debugging-using-debugger-command-line`. :ref:`jtag-debugging-examples` If you are not familiar with GDB, check this section for debugging examples provided from :ref:`jtag-debugging-examples-eclipse` as well as from :ref:`jtag-debugging-examples-command-line`. :ref:`jtag-debugging-building-openocd` - Procedure to build OpenOCD from sources for :doc:`Windows `, :doc:`Linux ` and :doc:`MacOS ` operating systems. + Procedure to build OpenOCD from sources for :doc:`Windows `, :doc:`Linux ` and :doc:`macOS ` operating systems. :ref:`jtag-debugging-tips-and-quirks` - This section provides collection of tips and quirks related JTAG debugging of {IDF_TARGET_NAME} with OpenOCD and GDB. + This section provides collection of tips and quirks related to JTAG debugging of {IDF_TARGET_NAME} with OpenOCD and GDB. .. include:: {IDF_TARGET_PATH_NAME}.inc @@ -36,24 +36,24 @@ Introduction .. only:: esp32 - The ESP32 has two powerful Xtensa cores, allowing for a great deal of variety of program architectures. The FreeRTOS OS that comes with ESP-IDF is capable of multi-core preemptive multithreading, allowing for an intuitive way of writing software. + The ESP32 has two powerful Xtensa cores, allowing for a great deal of variety of program architectures. The FreeRTOS OS that comes with ESP-IDF is capable of multi-core preemptive scheduling, allowing for an intuitive way of writing software. - The downside of the ease of programming is that debugging without the right tools is harder: figuring out a bug that is caused by two threads, running even simultaneously on two different CPU cores, can take a long time when all you have are printf statements. A better and in many cases quicker way to debug such problems is by using a debugger, connected to the processors over a debug port. + The downside of the ease of programming is that debugging without the right tools is harder: figuring out a bug that is caused by two threads, running even simultaneously on two different CPU cores, can take a long time when all you have are ``printf()`` statements. A better (and in many cases quicker) way to debug such problems is by using a debugger, connected to the processors over a debug port. -Espressif has ported OpenOCD to support the {IDF_TARGET_NAME} processor and the multicore FreeRTOS, which will be the foundation of most {IDF_TARGET_NAME} apps, and has written some tools to help with features OpenOCD does not support natively. +Espressif has ported OpenOCD to support the {IDF_TARGET_NAME} processor and the multi-core FreeRTOS (which is the foundation of most {IDF_TARGET_NAME} apps). Additionally, some extra tools have been written to provide extra features that OpenOCD does not support natively. -This document provides a guide to installing OpenOCD for {IDF_TARGET_NAME} and debugging using GDB under Linux, Windows and MacOS. Except for OS specific installation procedures, the s/w user interface and use procedures are the same across all supported operating systems. +This document provides a guide to installing OpenOCD for {IDF_TARGET_NAME} and debugging using GDB under Linux, Windows and macOS. Except for OS specific installation procedures, the s/w user interface and use procedures are the same across all supported operating systems. .. note:: - Screenshots presented in this document have been made for Eclipse Neon 3 running on Ubuntu 16.04 LTS. There may be some small differences in what a particular user interface looks like, depending on whether you are using Windows, MacOS or Linux and / or a different release of Eclipse. + Screenshots presented in this document have been made for Eclipse Neon 3 running on Ubuntu 16.04 LTS. There may be some small differences in what a particular user interface looks like, depending on whether you are using Windows, macOS or Linux and / or a different release of Eclipse. .. _jtag-debugging-how-it-works: How it Works? ------------- -The key software and hardware to perform debugging of {IDF_TARGET_NAME} with OpenOCD over JTAG (Joint Test Action Group) interface is presented below and includes {IDF_TARGET_TOOLCHAIN_PREFIX}-gdb debugger, OpenOCD on chip debugger and JTAG adapter connected to {IDF_TARGET_NAME} target. +The key software and hardware components that perform debugging of {IDF_TARGET_NAME} with OpenOCD over JTAG (Joint Test Action Group) interface is presented in the diagram below under the "Debugging With JTAG" label. These components include {IDF_TARGET_TOOLCHAIN_PREFIX}-gdb debugger, OpenOCD on chip debugger, and the JTAG adapter connected to {IDF_TARGET_NAME} target. .. figure:: ../../../_static/jtag-debugging-overview.jpg :align: center @@ -62,26 +62,23 @@ The key software and hardware to perform debugging of {IDF_TARGET_NAME} with Ope JTAG debugging - overview diagram -Under "Application Loading and Monitoring" there is another software and hardware to compile, build and flash application to {IDF_TARGET_NAME}, as well as to provide means to monitor diagnostic messages from {IDF_TARGET_NAME}. +Likewise, the "Application Loading and Monitoring" label indicates the key software and hardware components that allow an application to be compiled, built, and flashed to {IDF_TARGET_NAME}, as well as to provide means to monitor diagnostic messages from {IDF_TARGET_NAME}. -Debugging using JTAG and application loading / monitoring is integrated under the `Eclipse `_ environment, to provide quick and easy transition from writing, compiling and loading the code to debugging, back to writing the code, and so on. All the software is available for Windows, Linux and MacOS platforms. +"Debugging With JTAG" and "Application Loading and Monitoring" is integrated under the `Eclipse `_ IDE in order to provide a quick and easy transition between writing/compiling/loading/debugging code. The Eclipse IDE (and the integrated debugging software) is available for Windows, Linux and macOS platforms. Depending on user preferences, both the debugger and ``idf.py build`` can also be used directly from terminal/command line, instead of Eclipse. .. only:: not SOC_USB_SERIAL_JTAG_SUPPORTED - If the |devkit-name-with-link| is used, then connection from PC to {IDF_TARGET_NAME} is done effectively with a single USB cable. This is made possible by the FT2232H chip, which provides two USB channels, one for JTAG and the one for UART connection. + If the |devkit-name-with-link| is used, then connection from PC to {IDF_TARGET_NAME} is done effectively with a single USB cable. This is made possible by the FT2232H chip, which provides two USB channels, one for JTAG and the other for UART connection. .. only:: SOC_USB_SERIAL_JTAG_SUPPORTED - The connection from PC to {IDF_TARGET_NAME} is done effectively with a single USB cable. This is made possible by the {IDF_TARGET_NAME} chip itself, which provides two USB channels, one for JTAG and one for the USB terminal connection. The USB cable should be connected the D+/D- USB pins of {IDF_TARGET_NAME} and not to the serial RxD/TxD throught an USB-to-UART chip. The proper connection is explained later in subsection :ref:`jtag-debugging-configuring-target`. + The connection from PC to {IDF_TARGET_NAME} is done effectively with a single USB cable. This is made possible by the {IDF_TARGET_NAME} chip itself, which provides two USB channels, one for JTAG and the other for the USB terminal connection. The USB cable should be connected to the D+/D- USB pins of {IDF_TARGET_NAME} and not to the serial RxD/TxD through a USB-to-UART chip. The proper connection is explained later in subsection :ref:`jtag-debugging-configuring-target`. .. only:: esp32c3 .. note:: - Debugging through the USB interface implemented in ESP32-C3 requires to have a chip with revision 3 or newer. Please use other debugging options (e.g. with ESP-Prog) for chip revision 1 and 2. The easiest way to determine the chip revision is to look for the `Chip is ESP32-C3 (revision 3)` message near the end of a successful chip flashing done by `idf.py flash`. - -Depending on user preferences, both `debugger` and `idf.py build` can be operated directly from terminal/command line, instead from Eclipse. - + Debugging through the USB interface implemented in {IDF_TARGET_NAME} requires to have a chip with revision 3 or newer. Please use other debugging options (e.g. with ESP-Prog) for chip revision 1 and 2. The easiest way to determine the chip revision is to look for the ``Chip is ESP32-C3 (revision 3)`` message near the end of a successful chip flashing done by ``idf.py flash``. .. _jtag-debugging-selecting-jtag-adapter: @@ -94,7 +91,7 @@ Selecting JTAG Adapter .. only:: SOC_USB_SERIAL_JTAG_SUPPORTED - The quickest and most convenient way to start with JTAG debugging is through an USB cable connected to the D+/D- USB pins of {IDF_TARGET_NAME}. No need for an external JTAG adapter and extra wiring / cable to connect JTAG to {IDF_TARGET_NAME}. + The quickest and most convenient way to start with JTAG debugging is through a USB cable connected to the D+/D- USB pins of {IDF_TARGET_NAME}. No need for an external JTAG adapter and extra wiring / cable to connect JTAG to {IDF_TARGET_NAME}. If you decide to use separate JTAG adapter, look for one that is compatible with both the voltage levels on the {IDF_TARGET_NAME} as well as with the OpenOCD software. The JTAG port on the {IDF_TARGET_NAME} is an industry-standard JTAG port which lacks (and does not need) the TRST pin. The JTAG I/O pins all are powered from the VDD_3P3_RTC pin (which normally would be powered by a 3.3 V rail) so the JTAG adapter needs to be able to work with JTAG pins in that voltage range. @@ -137,7 +134,7 @@ If any of these steps do not work, please go back to the :ref:`setting up the to Configuring {IDF_TARGET_NAME} Target ------------------------------------- -Once OpenOCD is installed, move to configuring {IDF_TARGET_NAME} target (i.e {IDF_TARGET_NAME} board with JTAG interface). You will do it in the following three steps: +Once OpenOCD is installed, you can proceed to configuring the {IDF_TARGET_NAME} target (i.e {IDF_TARGET_NAME} board with JTAG interface). Configuring the target is split into the following three steps: * Configure and connect JTAG interface * Run OpenOCD @@ -147,7 +144,7 @@ Once OpenOCD is installed, move to configuring {IDF_TARGET_NAME} target (i.e {ID Configure and connect JTAG interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -This step depends on JTAG and {IDF_TARGET_NAME} board you are using - see the two cases described below. +This step depends on the JTAG and {IDF_TARGET_NAME} board you are using (see the two cases described below). .. toctree:: :maxdepth: 1 @@ -175,12 +172,11 @@ Open a terminal and set it up for using the ESP-IDF as described in the :ref:`se .. note:: - The files provided after ``-f`` above are specific for |run-openocd-device-name|. You may need to provide different files depending on used hardware. For guidance see :ref:`jtag-debugging-tip-openocd-configure-target`. + The files provided after ``-f`` above are specific for |run-openocd-device-name|. You may need to provide different files depending on the hardware that is used. For guidance see :ref:`jtag-debugging-tip-openocd-configure-target`. .. only:: esp32c3 - For example, ``board/esp32c3-ftdi.cfg`` can be used for a custom board with an FT2232H or FT232H chip used for JTAG connection, - or with ESP-Prog. + For example, ``board/esp32c3-ftdi.cfg`` can be used for a custom board with an FT2232H or FT232H chip used for JTAG connection, or with ESP-Prog. .. highlight:: none @@ -190,10 +186,9 @@ You should now see similar output (this log is for |run-openocd-device-name|): :start-after: run-openocd-output :end-before: --- -* If there is an error indicating permission problems, please see the "Permissions delegation" bit in the OpenOCD README file in ``~/esp/openocd-esp32`` directory. -* In case there is an error finding configuration files, e.g. |run-openocd-cfg-file-err|, check ``OPENOCD_SCRIPTS`` environment variable is set correctly. This variable is used by OpenOCD to look for the files specified after ``-f``. See :ref:`jtag-debugging-setup-openocd` section for details. Also check if the file is indeed under provided path. -* If you see JTAG errors (...all ones/...all zeroes) please check your connections, whether no other signals are connected to JTAG besides {IDF_TARGET_NAME}'s pins, and see if everything is powered on. - +* If there is an error indicating permission problems, please see section on "Permissions delegation" in the OpenOCD README file located in the ``~/esp/openocd-esp32`` directory. +* In case there is an error in finding the configuration files, e.g. |run-openocd-cfg-file-err|, check if the ``OPENOCD_SCRIPTS`` environment variable is set correctly. This variable is used by OpenOCD to look for the files specified after the ``-f`` option. See :ref:`jtag-debugging-setup-openocd` section for details. Also check if the file is indeed under the provided path. +* If you see JTAG errors (e.g., ``...all ones`` or ``...all zeroes``), please check your JTAG connections, whether other signals are connected to JTAG besides {IDF_TARGET_NAME}'s pins, and see if everything is powered on correctly. .. _jtag-upload-app-debug: @@ -218,7 +213,7 @@ OpenOCD flashing command ``program_esp`` has the following format: - ``reset`` - Optional. Reset target after programing. - ``exit`` - Optional. Finally exit OpenOCD. -You are now ready to start application debugging. Follow steps described in section below. +You are now ready to start application debugging. Follow the steps described in the section below. .. _jtag-debugging-launching-debugger: @@ -268,7 +263,7 @@ Please refer to separate documents listed below, that describe build process. Windows Linux - MacOS + macOS The examples of invoking OpenOCD in this document assume using pre-built binary distribution described in section :ref:`jtag-debugging-setup-openocd`. diff --git a/docs/en/api-guides/lwip.rst b/docs/en/api-guides/lwip.rst index 93697dc9ad..b3b5df9a1b 100644 --- a/docs/en/api-guides/lwip.rst +++ b/docs/en/api-guides/lwip.rst @@ -281,6 +281,58 @@ A number of configuration items are available to modify the task and the queues - :ref:`CONFIG_LWIP_TCPIP_TASK_STACK_SIZE` - :ref:`CONFIG_LWIP_TCPIP_TASK_AFFINITY` +IPv6 Support +------------ + +Both IPv4 and IPv6 are supported as dual stack and enabled by default (IPv6 may be disabled if it's not needed, see :ref:`lwip-ram-usage`). +IPv6 support is limited to *Stateless Autoconfiguration* only, *Stateful configuration* is not supported in ESP-IDF (not in upstream lwip). +IPv6 Address configuration is defined by means of these protocols or services: + +- **SLAAC** IPv6 Stateless Address Autoconfiguration (RFC-2462) +- **DHCPv6** Dynamic Host Configuration Protocol for IPv6 (RFC-8415) + +None of these two types of address configuration is enabled by default, so the device uses only Link Local addresses or statically defined addresses. + +.. _lwip-ivp6-autoconfig: + +Stateless Autoconfiguration Process +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To enable address autoconfiguration using Router Advertisement protocol please enable: + +- :ref:`CONFIG_LWIP_IPV6_AUTOCONFIG` + +This configuration option enables IPv6 autoconfiguration for all network interfaces +(in contrast to the upstream lwIP, where the autoconfiguration needs to be explicitly enabled for each netif with ``netif->ip6_autoconfig_enabled=1`` + +.. _lwip-ivp6-dhcp6: + +DHCPv6 +^^^^^^ + +DHCPv6 in lwIP is very simple and support only stateless configuration. It could be enabled using: + +- :ref:`CONFIG_LWIP_IPV6_DHCP6` + +Since the DHCPv6 works only in its stateless configuration, the :ref:`lwip-ivp6-autoconfig` has to be enabled, too, by means of :ref:`CONFIG_LWIP_IPV6_AUTOCONFIG`. +Moreover, the DHCPv6 needs to be explicitly enabled form the application code using + + dhcp6_enable_stateless(netif); + +DNS servers in IPv6 autoconfiguration +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In order to autoconfigure DNS server(s), especially in IPv6 only networks, we have these two options + +- Recursive domain name system -- this belongs to the Neighbor Discovery Protocol (NDP), uses :ref:`lwip-ivp6-autoconfig`. + Number of servers must be set :ref:`CONFIG_LWIP_IPV6_RDNSS_MAX_DNS_SERVERS`, this is option is disabled (set to 0) by default. + +- DHCPv6 stateless configuration -- uses :ref:`lwip-ivp6-dhcp6` to configure DNS servers. Note that the this configuration + assumes IPv6 Router Advertisement Flags (RFC-5175) to be set to + + - Managed Address Configuration Flag = 0 + - Other Configuration Flag = 1 + esp-lwip custom modifications ----------------------------- diff --git a/docs/en/api-guides/openthread.rst b/docs/en/api-guides/openthread.rst new file mode 100644 index 0000000000..4b0d5b354c --- /dev/null +++ b/docs/en/api-guides/openthread.rst @@ -0,0 +1,108 @@ +OpenThread +========== + +`OpenThread `_ is a IP stack running on the 802.15.4 MAC layer which features mesh network and low power consumption. + +Mode of the OpenThread stack +---------------------------- + +OpenThread can run under the following modes on Espressif chips: + +Standalone node ++++++++++++++++ + +The full OpenThread stack and the application layer runs on the same chip. This mode is available on chips with 15.4 radio such as ESP32-H2. + +Radio Co-Processor (RCP) +++++++++++++++++++++++++ + +The chip will be connected to another host running the OpenThread IP stack. It will send and received 15.4 packets on behalf of the host. This mode is available on chips with 15.4 radio such as ESP32-H2. The underlying transport between the chip and the host can be SPI or UART. For sake of latency, we recommend to use SPI as the underlying transport. + +OpenThread host ++++++++++++++++ + +For chips without 15.4 radio, it can be connected to an RCP and run OpenThread under host mode. This mode enables OpenThread on Wi-Fi chips such as ESP32, ESP32-S2, ESP32-S3 and ESP32-C3. The following diagram shows how devices work under different modes: + +.. blockdiag:: + :caption: OpenThread device modes + :align: center + + blockdiag openthread-device-modes { + + # global attributes + node_height = 90; + node_width = 220; + span_width = 100 + default_shape = roundedbox; + default_group_color = none; + + # node labels + HOST_NODE [label="OpenThread \nhost\n(ESP32)", fontsize=14]; + RCP [label="Radio \nCo-Processor\n(ESP32-H2)", fontsize=14]; + STANDALONE [label="Standalone \nnode\n (ESP32-H2)", fontsize=14]; + + # node connections + labels + RCP -> STANDALONE [label="15.4 radio", dir=both, style=dashed]; + + # arrange nodes vertically + group { + orientation = portrait; + HOST_NODE -> RCP [label="SPI", dir=both]; + } + } + + +How To Write an OpenThread Application +-------------------------------------- + +The OpenThread :example:`openthread/ot_cli` example will be a good place to start at. It demonstrates basic OpenThread initialization and simple socket-based server and client. + +Before OpenThread initialization +++++++++++++++++++++++++++++++++ + +- s1.1 The main task calls :cpp:func:`esp_vfs_eventfd_register` to initialize the eventfd virtual filesystem. The eventfd file system is used for task notification in the OpenThread driver. + +- s1.2 The main task calls :cpp:func:`nvs_flash_init` to initialize the NVS where the Thread network data is stored. + +- s1.3 **Optional**, The main task calls :cpp:func:`esp_netif_init` only when it wants to create the network interface for Thread. + +- s1.4: The main task calls :cpp:func:`esp_event_loop_create` to create the system Event task and initialize an application event's callback function. + +OpenThread stack initialization ++++++++++++++++++++++++++++++++ +- s2.1: Call :cpp:func:`esp_openthread_init` to initialize the OpenThread stack. + +OpenThread network interface initialization ++++++++++++++++++++++++++++++++++++++++++++ +The whole stage is **optional** and only required if the application wants to create the network interface for Thread. +- s3.1: Call :cpp:func:`esp_netif_new` with `ESP_NETIF_DEFAULT_OPENTHREAD` to create the interface. +- s3.2: Call :cpp:func:`esp_openthread_netif_glue_init` to create the OpenThread interface handlers. +- s3.3: Call :cpp:func:`esp_netif_attach` to attach the handlers to the interface. + +The OpenThread main loop +++++++++++++++++++++++++ + +- s4.3: Call :cpp:func:`esp_openthread_launch_mainloop` to launch the OpenThread main loop. Note that this is a busy loop and will not return until the OpenThread stack is terminated. + +Calling OpenThread APIs +++++++++++++++++++++++++ + +The OpenThread APIs are not thread-safe. When calling OpenThread APIs from other tasks, make sure to hold the lock with :cpp:func:`esp_openthread_lock_acquire` and release the lock with :cpp:func:`esp_openthread_lock_release` afterwards. + +Deinitialization +++++++++++++++++ + +The following steps are required to deintialize the OpenThread stack: +- Call :cpp:func:`esp_netif_destroy` and :cpp:func:`esp_openthread_netif_glue_deinit` to deintialize the OpenThread network interface if you have created one. +- Call :cpp:func:`esp_openthread_deinit` to deintialize the OpenThread stack. + +The OpenThread border router +---------------------------- + +The OpenThread border router connects the Thread network with other IP networks. It will provide IPv6 connectivity, service registration and commission functionality. +To launch an OpenThread border router on a ESP chip, you need to connect an RCP to a Wi-Fi capable chip such as ESP32. +Call :cpp:func:`esp_openthread_border_router_init` during the initialization will launch all the border routing functionalities. + +You may refer to the :example:`openthread/ot_br` example and the README for further border router details. + + diff --git a/docs/en/api-guides/partition-tables.rst b/docs/en/api-guides/partition-tables.rst index 42b5920d9b..f0ec74944c 100644 --- a/docs/en/api-guides/partition-tables.rst +++ b/docs/en/api-guides/partition-tables.rst @@ -29,7 +29,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 (64KB) 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 will run 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:: @@ -99,7 +99,7 @@ See enum :cpp:type:`esp_partition_subtype_t` for the full list of subtypes defin - OTA never updates the factory partition. - If you want to conserve flash usage in an OTA project, you can remove the factory partition and use ``ota_0`` instead. - + - ``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`. @@ -176,7 +176,7 @@ The ESP-IDF build system will automatically check if generated binaries fit in t Currently these checks are performed for the following binaries: -* Bootloader binary must fit in space before partition table (see :ref:`bootloader-size`) +* Bootloader binary must fit in space before partition table (see :ref:`bootloader-size`). * App binary should fit in at least one partition of type "app". If the app binary doesn't fit in any app partition, the build will fail. If it only fits in some of the app partitions, a warning is printed about this. .. note:: diff --git a/docs/en/api-guides/performance/ram-usage.rst b/docs/en/api-guides/performance/ram-usage.rst index 96d3560170..b106cbf6bf 100644 --- a/docs/en/api-guides/performance/ram-usage.rst +++ b/docs/en/api-guides/performance/ram-usage.rst @@ -129,6 +129,7 @@ The following options will reduce IRAM usage of some ESP-IDF features: .. list:: - Enable :ref:`CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH`. Provided these functions are not (incorrectly) used from ISRs, this option is safe to enable in all configurations. + - Enable :ref:`CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH`. Enabling this option will place snapshot-related functions, such as ``vTaskGetSnapshot`` or ``uxTaskGetSnapshotAll``, in flash. - Disable Wi-Fi options :ref:`CONFIG_ESP32_WIFI_IRAM_OPT` and/or :ref:`CONFIG_ESP32_WIFI_RX_IRAM_OPT`. Disabling these options will free available IRAM at the cost of Wi-Fi performance. :esp32c3 or esp32s3: - :ref:`CONFIG_SPI_FLASH_ROM_IMPL` enabling this option will free some IRAM but will mean that esp_flash bugfixes and new flash chip support is not available. :esp32: - :ref:`CONFIG_SPI_FLASH_ROM_DRIVER_PATCH` disabling this option will free some IRAM but is only available in some flash configurations (see the configuration item help text). diff --git a/docs/en/api-guides/performance/size.rst b/docs/en/api-guides/performance/size.rst index 47bb22ead1..cfe293edcc 100644 --- a/docs/en/api-guides/performance/size.rst +++ b/docs/en/api-guides/performance/size.rst @@ -404,6 +404,16 @@ FreeModBus If using Modbus, enable or disable :ref:`CONFIG_FMB_COMM_MODE_TCP_EN`, :ref:`CONFIG_FMB_COMM_MODE_RTU_EN`, :ref:`CONFIG_FMB_COMM_MODE_ASCII_EN` as applicable for the necessary functionality. +VFS +@@@ + +:doc:`Virtual filesystem ` feature in ESP-IDF allows multiple filesystem drivers and file-like peripheral drivers to be accessed using standard I/O functions (``open``, ``read``, ``write``, etc.) and C library functions (``fopen``, ``fread``, ``fwrite``, etc.). When filesystem or file-like peripheral driver functionality is not used in the application this feature can be fully or partially disabled. VFS component provides the following configuration options: + +* :ref:`CONFIG_VFS_SUPPORT_TERMIOS` — can be disabled if the application doesn't use ``termios`` family of functions. Currently, these functions are implemented only for UART VFS driver. Most applications can disable this option. Disabling this option reduces the code size by about 1.8 kB. +* :ref:`CONFIG_VFS_SUPPORT_SELECT` — can be disabled if the application doesn't use ``select`` function with file descriptors. Currently, only the UART and eventfd VFS drivers implement ``select`` support. Note that when this option is disabled, ``select`` can still be used for socket file descriptors. Disabling this option reduces the code size by about 2.7 kB. +* :ref:`CONFIG_VFS_SUPPORT_DIR` — can be disabled if the application doesn't use directory related functions, such as ``readdir`` (see the description of this option for the complete list). Applications which only open, read and write specific files and don't need to enumerate or create directories can disable this option, reducing the code size by 0.5 kB or more, depending on the filesystem drivers in use. +* :ref:`CONFIG_VFS_SUPPORT_IO` — can be disabled if the application doesn't use filesystems or file-like peripheral drivers. This disables all VFS functionality, including the three options mentioned above. When this option is disabled, :doc:`console ` can't be used. Note that the application can still use standard I/O functions with socket file descriptors when this option is disabled. Compared to the default configuration, disabling this option reduces code size by about 9.4 kB. + Bootloader Size --------------- diff --git a/docs/en/api-guides/tools/idf-component-manager.rst b/docs/en/api-guides/tools/idf-component-manager.rst new file mode 100644 index 0000000000..3700256194 --- /dev/null +++ b/docs/en/api-guides/tools/idf-component-manager.rst @@ -0,0 +1,72 @@ +********************* +IDF Component Manager +********************* + +The IDF Component manager is a tool that downloads dependencies for any ESP-IDF CMake project. The download happens automatically during a run of CMake. It can source components either from `the component registry `_ or from a git repository. + +A list of components can be found on ``_ + +Activating the Component Manager +================================ + +If CMake is started using ``idf.py`` or `ESP-IDF VSCode Extension `_ then the component manager will be activated by default. + +If CMake is used directly or with some CMake-based IDE like CLion, it's necessary to set the ``IDF_COMPONENT_MANAGER`` environment variable to ``1`` to enable the component manager integration with the build system. + +Using with a project +==================== + +Dependencies for each component in the project are defined in a separate manifest file named ``idf_component.yml`` placed in the root of the component. The manifest file template can be created for a component by running ``idf.py create-manifest --component=my_component``. When a new manifest is added to one of the components in the project it's necessary to reconfigure it manually by running ``idf.py reconfigure``. Then build will track changes in ``idf_component.yml`` manifests and automatically triggers CMake when necessary. + +There is an example application: example:`build_system/cmake/component_manager` that uses components installed by the component manager. + +It's not necessary to have a manifest for components that don't need any managed dependencies. + +When CMake configures the project (e.g. ``idf.py reconfigure``) component manager does a few things: + +- Processes ``idf_component.yml`` manifests for every component in the project and recursively solves dependencies +- Creates a ``dependencies.lock`` file in the root of the project with a full list of dependencies +- Downloads all dependencies to the ``managed_components`` directory + +The lock-file ``dependencies.lock`` and content of ``managed_components`` directory is not supposed to be modified by a user. When the component manager runs it always make sure they are up to date. If these files were accidentally modified it's possible to re-run the component manager by triggering CMake with ``idf.py reconfigure`` + +Defining dependencies in the manifest +===================================== + +.. code-block:: yaml + + dependencies: + # Required IDF version + idf: ">=4.1" + # Defining a dependency from the registry: + # https://components.espressif.com/component/example/cmp + example/cmp: ">=1.0.0" + + # # Other ways to define dependencies + # + # # For components maintained by Espressif only name can be used. + # # Same as `espressif/cmp` + # component: "~1.0.0" + # + # # Or in a longer form with extra parameters + # component2: + # version: ">=2.0.0" + # + # # For transient dependencies `public` flag can be set. + # # `public` flag doesn't affect the `main` component. + # # All dependencies of `main` are public by default. + # public: true + # + # # For components hosted on non-default registry: + # service_url: "https://componentregistry.company.com" + # + # # For components in git repository: + # test_component: + # path: test_component + # git: ssh://git@gitlab.com/user/components.git + # + # # For test projects during component development + # # components can be used from a local directory + # # with relative or absolute path + # some_local_component: + # path: ../../projects/component diff --git a/docs/en/api-guides/tools/index.rst b/docs/en/api-guides/tools/index.rst index 862cbb4367..49b85291c3 100644 --- a/docs/en/api-guides/tools/index.rst +++ b/docs/en/api-guides/tools/index.rst @@ -8,3 +8,4 @@ Tools IDF Monitor IDF Docker image IDF Windows Installer + IDF Component Manager diff --git a/docs/en/api-guides/unit-tests.rst b/docs/en/api-guides/unit-tests.rst index a74dfd49cf..e1b403971c 100644 --- a/docs/en/api-guides/unit-tests.rst +++ b/docs/en/api-guides/unit-tests.rst @@ -2,7 +2,7 @@ Unit Testing in {IDF_TARGET_NAME} ================================= :link_to_translation:`zh_CN:[中文]` -ESP-IDF comes with two possibilities to test software. +ESP-IDF provides the following methods to test software. - A unit test application which runs on the target and that is based on the Unity - unit test framework. These unit tests are integrated in the ESP-IDF repository and are placed in the ``test`` subdirectories of each component respectively. Target-based unit tests are covered in this document. - Linux-host based unit tests in which all the hardware is abstracted via mocks. Linux-host based tests are still under development and only a small fraction of IDF components supports them currently. They are covered here: :doc:`target based unit testing `. @@ -29,7 +29,7 @@ Tests are added in a function in the C file as follows: .. note:: There is no need to add a main function with ``UNITY_BEGIN()`` and ``​UNITY_END()`` in each test case. ``unity_platform.c`` will run ``UNITY_BEGIN()`` autonomously, and run the test cases, then call ``​UNITY_END()``. -The ``test`` subdirectory should contain a :ref:`component CMakeLists.txt `, since they are themselves, components. ESP-IDF uses the ``unity`` test framework and should be specified as a requirement for the component. Normally, components :ref:`should list their sources manually `; for component tests however, this requirement is relaxed and the use of the ``SRC_DIRS`` argument in ``idf_component_register`` is advised. +The ``test`` subdirectory should contain a :ref:`component CMakeLists.txt `, since they are themselves components (i.e., a test component). ESP-IDF uses the Unity test framework located in the ``unity`` component. Thus, each test component should specify the ``unity`` component as a component requirement using the ``REQUIRES`` argument. Normally, components :ref:`should list their sources manually `; for component tests however, this requirement is relaxed and the use of the ``SRC_DIRS`` argument in ``idf_component_register`` is advised. Overall, the minimal ``test`` subdirectory ``CMakeLists.txt`` file should contain the following: @@ -321,4 +321,4 @@ The unit test needs to set the component property ``USE_MOCK`` for the component idf_component_set_property(spi_flash USE_MOCK 1) -Refer to the :component_file:`NVS host unit test ` for more information on how to use and control CMock inside a unit test. +Refer to the :component_file:`NVS host unit test ` for more information on how to use and control CMock inside a unit test. \ No newline at end of file diff --git a/docs/en/api-guides/usb-serial-jtag-console.rst b/docs/en/api-guides/usb-serial-jtag-console.rst index b2834d9d4c..0bdfeec4fd 100644 --- a/docs/en/api-guides/usb-serial-jtag-console.rst +++ b/docs/en/api-guides/usb-serial-jtag-console.rst @@ -46,7 +46,9 @@ Limitations There are several limitations to the USB console feature. These may or may not be significant, depending on the type of application being developed, and the development workflow. -1. If the application accidentally reconfigures the USB peripheral pins, or disables the USB Serial/JTAG Controller, the device will disappear from the system. After fixing the issue in the application, you will need to manually put the {IDF_TARGET_NAME} into download mode by pulling low GPIO0 and resetting the chip. +{IDF_TARGET_BOOT_PIN:default = "GPIO0", esp32c3 = "GPIO9"} + +1. If the application accidentally reconfigures the USB peripheral pins, or disables the USB Serial/JTAG Controller, the device will disappear from the system. After fixing the issue in the application, you will need to manually put the {IDF_TARGET_NAME} into download mode by pulling low {IDF_TARGET_BOOT_PIN} and resetting the chip. 2. If the application enters light sleep (including automatic light sleep) or deep sleep mode, USB CDC device will disappear from the system. diff --git a/docs/en/api-guides/wifi-security.rst b/docs/en/api-guides/wifi-security.rst new file mode 100644 index 0000000000..3691516682 --- /dev/null +++ b/docs/en/api-guides/wifi-security.rst @@ -0,0 +1,95 @@ +Wi-Fi Security +============== + +{IDF_TARGET_NAME} Wi-Fi Security Features +----------------------------------------- +- Support for Protected Management Frames (PMF) +- Support for WPA3-Personal + +In addition to traditional security methods (WEP/WPA-TKIP/WPA2-CCMP), {IDF_TARGET_NAME} Wi-Fi supports state-of-the-art security protocols, namely Protected Management Frames based on 802.11w standard and Wi-Fi Protected Access 3 (WPA3-Personal). Together, PMF and WPA3 provide better privacy and robustness against known attacks on traditional modes. + +Protected Management Frames (PMF) +--------------------------------- + +Introduction +++++++++++++ + +In Wi-Fi, management frames such as beacons, probes, (de)authentication, (dis)association are used by non-AP stations to scan and connect to an AP. Unlike data frames, these frames are sent unencrypted. +An attacker can use eavesdropping and packet injection to send spoofed (de)authentication/(dis)association frames at the right time, leading to the following attacks in case of unprotected management frame exchanges. + + - DOS attack on one or all clients in the range of the attacker. + - Tearing down existing association on AP side by sending association request. + - Forcing a client to perform 4-way handshake again in case PSK is compromised in order to get PTK. + - Getting SSID of hidden network from association request. + - Launching man-in-the-middle attack by forcing clients to deauth from legitimate AP and associating to a rogue one. + +PMF provides protection against these attacks by encrypting unicast management frames and providing integrity checks for broadcast management frames. These include deauthentication, disassociation and robust management frames. It also provides Secure Association (SA) teardown mechanism to prevent spoofed association/authentication frames from disconnecting already connected clients. + +API & Usage ++++++++++++ + +:cpp:func:`esp_wifi_set_config` can be used to configure PMF mode by setting appropriate flags in `pmf_cfg` parameter. Currently, PMF is supported only in Station mode. +While setting up a Station, configure PMF using two flags ``capable`` and ``required`` like below. + + .. code-block:: c + + wifi_config_t wifi_config = { + .sta = { + .ssid = EXAMPLE_WIFI_SSID, + .password = EXAMPLE_WIFI_PASSWORD, + .pmf_cfg = { + .capable = true, + .required = false + } + } + }; + +{IDF_TARGET_NAME} supports three modes of PMF by combination of these two flags - + - PMF Optional : ``.capable = true, .required = false`` + - PMF Required : ``.capable = true, .required = true`` + - PMF Disabled : ``.capable = false, .required = false`` + + Depending on what AP side PMF Mode is, the resulting connnection will behave differently. The table below summarises all possible outcomes - + ++--------------+------------------------+---------------------------+ +| STA Setting | AP Setting | Outcome | ++==============+========================+===========================+ +| PMF Optional | PMF Optional/Required | Mgmt Frames Protected | ++--------------+------------------------+---------------------------+ +| PMF Optional | PMF Disabled | Mgmt Frames Not Protected | ++--------------+------------------------+---------------------------+ +| PMF Required | PMF Optional/Required | Mgmt Frames Protected | ++--------------+------------------------+---------------------------+ +| PMF Required | PMF Disabled | STA refuses Connection | ++--------------+------------------------+---------------------------+ +| PMF Disabled | PMF Optional/Disabled | Mgmt Frames Not Protected | ++--------------+------------------------+---------------------------+ +| PMF Disabled | PMF Required | AP refuses Connection | ++--------------+------------------------+---------------------------+ + +PMF Optional Mode, which is shown in the example of ``wifi_confit_t``, is suggested to be used in all Station configurations. This is to take the additional security benefit of PMF whenever possible without breaking connections with legacy AP's. + +WPA3-Personal +------------- + +Introduction +++++++++++++ + +Wi-Fi Protected Access-3 (WPA3) is a set of enhancements to Wi-Fi access security intended to replace the current WPA2 standard. It includes new features and capabilities that offer significantly better protection against different types of attacks. It improves upon WPA2-Personal in following ways: + + - WPA3 uses Simultaneous Authentication of Equals (SAE), which is password-authenticated key agreement method based on Diffie-Hellman key exchange. Unlike WPA2, the technology is resistant to offline-dictionary attack, where the attacker attempts to determine shared password based on captured 4-way handshake without any further network interaction. + - Disallows outdated protocols such as TKIP, which is susceptible to simple attacks like MIC key recovery attack. + - Mandates Protected Management Frames (PMF), which provides protection for unicast and multicast robust management frames which include Disassoc and Deauth frames. This means that the attacker cannot disrupt an established WPA3 session by sending forged Assoc frames to the AP or Deauth/Disassoc frames to the Station. + - Provides forward secrecy, which means the captured data cannot be decrypted even if password is compromised after data transmission. + +Please refer to `Security `_ section of Wi-Fi Alliance's official website for further details. + +Setting up WPA3 with {IDF_TARGET_NAME} +++++++++++++++++++++++++++++++++++++++ + +In IDF Menuconfig under Wi-Fi component, a config option "Enable WPA3-Personal" is provided to Enable/Disable WPA3. By default it is kept enabled, if disabled {IDF_TARGET_NAME} will not be able to establish a WPA3 connection. Currently, WPA3 is supported only in the Station mode. Additionally, since PMF is mandated by WPA3 protocol, PMF Mode should be set to either Optional or Required while setting WiFi config. + +Refer to `Protected Management Frames (PMF)`_ on how to set this mode. + +After these settings are done, Station is ready to use WPA3-Personal. Application developers need not worry about the underlying security mode of the AP. WPA3-Personal is now the highest supported protocol in terms of security, so it will be automatically selected for the connection whenever available. For example, if an AP is configured to be in WPA3 Transition Mode, where it will advertise as both WPA2 and WPA3 capable, Station will choose WPA3 for the connection with above settings. +Note that Wi-Fi stack size requirement will increase 3kB when WPA3 is used. diff --git a/docs/en/api-guides/wifi.rst b/docs/en/api-guides/wifi.rst index 2476b4c474..d268ac5d34 100644 --- a/docs/en/api-guides/wifi.rst +++ b/docs/en/api-guides/wifi.rst @@ -7,7 +7,7 @@ Wi-Fi Driver ------------------------------------ - Support Station-only mode, AP-only mode, Station/AP-coexistence mode - Support IEEE 802.11B, IEEE 802.11G, IEEE 802.11N and APIs to configure the protocol mode -- Support WPA/WPA2/WPA2-Enterprise and WPS +- Support WPA/WPA2/WPA3/WPA2-Enterprise and WPS - Support AMPDU, HT40, QoS and other key features - Support Modem-sleep - Support an Espressif-specific protocol which, in turn, supports up to **1 km** of data traffic @@ -1403,41 +1403,12 @@ Wi-Fi Vendor IE Configuration By default, all Wi-Fi management frames are processed by the Wi-Fi driver, and the application does not need to care about them. Some applications, however, may have to handle the beacon, probe request, probe response and other management frames. For example, if you insert some vendor-specific IE into the management frames, it is only the management frames which contain this vendor-specific IE that will be processed. In {IDF_TARGET_NAME}, :cpp:func:`esp_wifi_set_vendor_ie()` and :cpp:func:`esp_wifi_set_vendor_ie_cb()` are responsible for this kind of tasks. -Wi-Fi Security -------------------------------- -In addition to traditional security methods (WEP/WPA-TKIP/WPA2-CCMP), {IDF_TARGET_NAME} Wi-Fi now supports state-of-the-art security protocols, namely Protected Management Frames based on 802.11w standard and Wi-Fi Protected Access 3 (WPA3-Personal). Together, PMF and WPA3 provide better privacy and robustness against known attacks in traditional modes. - -Protected Management Frames (PMF) -++++++++++++++++++++++++++++++++++ - -In Wi-Fi, management frames such as beacons, probes, (de)authentication, (dis)association are used by non-AP stations to scan and connect to an AP. Unlike data frames, these frames are sent unencrypted. -An attacker can use eavesdropping and packet injection to send spoofed (de)authentication/(dis)association frames at the right time, leading to following attacks in case of unprotected management frame exchanges. - - - DOS attack on one or all clients in the range of the attacker. - - Tearing down existing association on AP side by sending association request. - - Forcing a client to perform 4-way handshake again in case PSK is compromised in order to get PTK. - - Getting SSID of hidden network from association request. - - Launching man-in-the-middle attack by forcing clients to deauth from legitimate AP and associating to a rogue one. - -PMF provides protection against these attacks by encrypting unicast management frames and providing integrity checks for broadcast management frames. These include deauthentication, disassociation and robust management frames. It also provides Secure Association (SA) teardown mechanism to prevent spoofed association/authentication frames from disconnecting already connected clients. - -{IDF_TARGET_NAME} supports the following three modes of operation with respect to PMF. - - - PMF not supported: In this mode, {IDF_TARGET_NAME} indicates to AP that it is not capable of supporting management protection during association. In effect, security in this mode will be equivalent to that in traditional mode. - - PMF capable, but not required: In this mode, {IDF_TARGET_NAME} indicates to AP that it is capable of supporting PMF. The management protection will be used if AP mandates PMF or is at least capable of supporting PMF. - - PMF capable and required: In this mode, {IDF_TARGET_NAME} will only connect to AP, if AP supports PMF. If not, {IDF_TARGET_NAME} will refuse to connect to the AP. - -:cpp:func:`esp_wifi_set_config` can be used to configure PMF mode by setting appropriate flags in `pmf_cfg` parameter. Currently, PMF is supported only in Station mode. - - -WPA3-Personal -+++++++++++++++++++++++++++++++++ - -Wi-Fi Protected Access-3 (WPA3) is a set of enhancements to Wi-Fi access security intended to replace the current WPA2 standard. In order to provide more robust authentication, WPA3 uses Simultaneous Authentication of Equals (SAE), which is password-authenticated key agreement method based on Diffie-Hellman key exchange. Unlike WPA2, the technology is resistant to offline-dictionary attack, where the attacker attempts to determine shared password based on captured 4-way handshake without any further network interaction. WPA3 also provides forward secrecy, which means the captured data cannot be decrypted even if password is compromised after data transmission. Please refer to `Security `_ section of Wi-Fi Alliance's official website for further details. - -In order to enable WPA3-Personal, "Enable WPA3-Personal" should be selected in menuconfig. If enabled, {IDF_TARGET_NAME} uses SAE for authentication if supported by the AP. Since PMF is a mandatory requirement for WPA3, PMF capability should be at least set to "PMF capable, but not required" for {IDF_TARGET_NAME} to use WPA3 mode. Application developers need not worry about the underlying security mode as highest available is chosen from security standpoint. Note that Wi-Fi stack size requirement will increase approximately by 3k when WPA3 is used. Currently, WPA3 is supported only in Station mode. +Wi-Fi Easy Connect™ (DPP) +-------------------------- +Wi-Fi Easy Connect\ :sup:`TM` (or Device Provisioning Protocol) is a secure and standardized provisioning protocol for configuration of Wi-Fi Devices. +More information can be found on the API reference page :doc:`esp_dpp <../api-reference/network/esp_dpp>`. WPA2-Enterprise +++++++++++++++++++++++++++++++++ diff --git a/docs/en/api-reference/index.rst b/docs/en/api-reference/index.rst index 0709667b7d..21189adb58 100644 --- a/docs/en/api-reference/index.rst +++ b/docs/en/api-reference/index.rst @@ -14,4 +14,4 @@ API Reference Storage System Configuration Options - Error Codes Reference \ No newline at end of file + Error Codes Reference diff --git a/docs/en/api-reference/network/esp_dpp.rst b/docs/en/api-reference/network/esp_dpp.rst new file mode 100644 index 0000000000..7e8ebeebb0 --- /dev/null +++ b/docs/en/api-reference/network/esp_dpp.rst @@ -0,0 +1,26 @@ +Wi-Fi Easy Connect\ :sup:`TM` (DPP) +=================================== + +Wi-Fi Easy Connect\ :sup:`TM`, also known as Device Provisioning Protocol (DPP) or Easy Connect, is a provisioning protocol certified by Wi-Fi Alliance. It is a secure and standardized provisioning protocol for configuration of Wi-Fi Devices. With Easy Connect adding a new device to a network is as simple as scanning a QR Code. This reduces complexity and enhances user experience while onboarding devices without UI like Smart Home and IoT products. Unlike old protocols like WiFi Protected Setup (WPS), Wi-Fi Easy Connect incorporates strong encryption through public key cryptography to ensure networks remain secure as new devices are added. +Easy Connect brings many benefits in the User Experience: + + - Simple and intuitive to use; no lengthy instructions to follow for new device setup + - No need to remember and enter passwords into the device being provisioned + - Works with electronic or printed QR codes, or human-readable strings + - Supports both WPA2 and WPA3 networks + +Please refer to Wi-Fi Alliance's official page on `Easy Connect `_ for more information. + +{IDF_TARGET_NAME} supports Enrollee mode of Easy Connect with QR Code as the provisioning method. A display is required to display this QR Code. Users can scan this QR Code using their capable device and provision the {IDF_TARGET_NAME} to their Wi-Fi network. The provisioning device needs to be connected to the AP which need not support Wi-Fi Easy Connect™. +Easy Connect is still an evolving protocol. Of known platforms that support the QR Code method are some Android smartphones with Android 10 or higher. To use Easy Connect no additional App needs to be installed on the supported smartphone. + +Application Example +------------------- + +Example on how to provision {IDF_TARGET_NAME} using a supported smartphone: :example:`wifi/wifi_easy_connect/dpp-enrollee`. + + +API Reference +------------- + +.. include-build-file:: inc/esp_dpp.inc diff --git a/docs/en/api-reference/network/esp_eth.rst b/docs/en/api-reference/network/esp_eth.rst index 07b51867b3..e18e662404 100644 --- a/docs/en/api-reference/network/esp_eth.rst +++ b/docs/en/api-reference/network/esp_eth.rst @@ -26,7 +26,7 @@ Basic Ethernet Concepts Ethernet is an asynchronous Carrier Sense Multiple Access with Collision Detect (CSMA/CD) protocol/interface. It is generally not well suited for low power applications. However, with ubiquitous deployment, internet connectivity, high data rates and limitless rage expandability, Ethernet can accommodate nearly all wired communications. -Normal IEEE 802.3 compliant Ethernet frames are between 64 and 1518 bytes in length. They are made up of five or six different fields: a destination MAC address (DA), a source MAC address (SA), a type/length field, data payload, an optional padding field and a Cyclic Redundancy Check (CRC). +Normal IEEE 802.3 compliant Ethernet frames are between 64 and 1518 bytes in length. They are made up of five or six different fields: a destination MAC address (DA), a source MAC address (SA), a type/length field, data payload, an optional padding field and a Cyclic Redundancy Check (CRC). Additionally, when transmitted on the Ethernet medium, a 7-byte preamble field and Start-of-Frame (SOF) delimiter byte are appended to the beginning of the Ethernet packet. Thus the traffic on the twist-pair cabling will appear as shown blow: @@ -41,16 +41,16 @@ Preamble and Start-of-Frame Delimiter The preamble contains seven bytes of ``55H``, it allows the receiver to lock onto the stream of data before the actual frame arrives. The Start-of-Frame Delimiter (SFD) is a binary sequence ``10101011`` (as seen on the physical medium). It is sometimes considered to be part of the preamble. -When transmitting and receiving data, the preamble and SFD bytes will automatically be generated or stripped from the packets. +When transmitting and receiving data, the preamble and SFD bytes will automatically be generated or stripped from the packets. Destination Address ^^^^^^^^^^^^^^^^^^^ The destination address field contains a 6-byte length MAC address of the device that the packet is directed to. -If the Least Significant bit in the first byte of the MAC address is set, the address is a multi-cast destination. +If the Least Significant bit in the first byte of the MAC address is set, the address is a multi-cast destination. For example, 01-00-00-00-F0-00 and 33-45-67-89-AB-CD are multi-cast addresses, while 00-00-00-00-F0-00 and 32-45-67-89-AB-CD are not. -Packets with multi-cast destination addresses are designed to arrive and be important to a selected group of Ethernet nodes. -If the destination address field is the reserved multi-cast address, i.e. FF-FF-FF-FF-FF-FF, the packet is a broadcast packet and it will be directed to everyone sharing the network. +Packets with multi-cast destination addresses are designed to arrive and be important to a selected group of Ethernet nodes. +If the destination address field is the reserved multi-cast address, i.e. FF-FF-FF-FF-FF-FF, the packet is a broadcast packet and it will be directed to everyone sharing the network. If the Least Significant bit in the first byte of the MAC address is clear, the address is a uni-cast address and will be designed for usage by only the addressed node. Normally the EMAC controller incorporates receive filters which can be used to discard or accept packets with multi-cast, broadcast and/or uni-cast destination addresses. @@ -61,7 +61,7 @@ Source Address The source address field contains a 6-byte length MAC address of the node which created the Ethernet packet. Users of Ethernet must generate a unique MAC address for each controller used. -MAC addresses consist of two portions. The first three bytes are known as the Organizationally Unique Identifier (OUI). OUIs are distributed by the IEEE. +MAC addresses consist of two portions. The first three bytes are known as the Organizationally Unique Identifier (OUI). OUIs are distributed by the IEEE. The last three bytes are address bytes at the discretion of the company that purchased the OUI. More information about MAC Address used in ESP-IDF, please see :ref:`MAC Address Allocation `. When transmitting packets, the assigned source MAC address must be written into the transmit buffer by the host controller. @@ -89,7 +89,7 @@ Padding and FCS The padding field is a variable length field added to meet IEEE 802.3 specification requirements when small data payloads are used. The DA, SA, type, payload and padding of an Ethernet packet must be no smaller than 60 bytes. -Adding the required 4-byte FCS field, packets must be no smaller than 64 bytes. +Adding the required 4-byte FCS field, packets must be no smaller than 64 bytes. If the data field is less than 46 bytes long, a padding field is required. The FCS field is a 4-byte field which contains an industry standard 32-bit CRC calculated with the data from the DA, SA, type, payload and padding fields. @@ -99,7 +99,7 @@ Normally, the host controller does not need to concern itself with padding and t However, the padding and CRC fields will be written into the receive buffer when packets arrive, so they may be evaluated by the host controller if needed. .. note:: - Besides the basic data frame described above, there're two other common frame types in 10/100 Mbps Ethernet: control frames and VLAN tagged frames. + Besides the basic data frame described above, there're two other common frame types in 10/100 Mbps Ethernet: control frames and VLAN tagged frames. They're not supported in ESP-IDF. .. ------------------------------ Driver Operation -------------------------------- @@ -109,17 +109,19 @@ However, the padding and CRC fields will be written into the receive buffer when Configure MAC and PHY --------------------- -Ethernet driver is composed of two parts: MAC and PHY. The communication between MAC and PHY can have diverse choices: **MII** (Media Independent Interface), **RMII** (Reduced Media Independent Interface) and etc. +Ethernet driver is composed of two parts: MAC and PHY. -.. figure:: ../../../_static/rmii-interface.png - :align: center - :scale: 80 % - :alt: Ethernet RMII Interface - :figclass: align-center +.. only:: SOC_EMAC_SUPPORTED - Ethernet RMII Interface + The communication between MAC and PHY can have diverse choices: **MII** (Media Independent Interface), **RMII** (Reduced Media Independent Interface) and etc. -.. only:: esp32 + .. figure:: ../../../_static/rmii-interface.png + :align: center + :scale: 80 % + :alt: Ethernet RMII Interface + :figclass: align-center + + Ethernet RMII Interface One of the obvious difference between MII and RMII is the signal consumption. For MII, it usually costs up to 18 signals. Instead, RMII interface can reduce the consumption to 9. @@ -160,19 +162,23 @@ We need to setup necessary parameters for MAC and PHY respectively based on your Configuration for MAC is described in :cpp:class:`eth_mac_config_t`, including: -* :cpp:member:`sw_reset_timeout_ms`: software reset timeout value, in milliseconds, typically MAC reset should be finished within 100ms. -* :cpp:member:`rx_task_stack_size` and :cpp:member:`rx_task_prio`: the MAC driver creates a dedicated task to process incoming packets, these two parameters are used to set the stack size and priority of the task. -* :cpp:member:`smi_mdc_gpio_num` and :cpp:member:`smi_mdio_gpio_num`: the GPIO number used to connect the SMI signals. -* :cpp:member:`interface`: configuration of MAC Data interface to PHY (MII/RMII). -* :cpp:member:`clock_config`: configuration of EMAC Interface clock (``REF_CLK`` mode and GPIO number in case of RMII). -* :cpp:member:`flags`: specifying extra features that the MAC driver should have, it could be useful in some special situations. The value of this field can be OR'd with macros prefixed with ``ETH_MAC_FLAG_``. For example, if the MAC driver should work when cache is disabled, then you should configure this field with :c:macro:`ETH_MAC_FLAG_WORK_WITH_CACHE_DISABLE`. +.. list:: + + * :cpp:member:`sw_reset_timeout_ms`: software reset timeout value, in milliseconds, typically MAC reset should be finished within 100ms. + * :cpp:member:`rx_task_stack_size` and :cpp:member:`rx_task_prio`: the MAC driver creates a dedicated task to process incoming packets, these two parameters are used to set the stack size and priority of the task. + * :cpp:member:`flags`: specifying extra features that the MAC driver should have, it could be useful in some special situations. The value of this field can be OR'd with macros prefixed with ``ETH_MAC_FLAG_``. For example, if the MAC driver should work when cache is disabled, then you should configure this field with :c:macro:`ETH_MAC_FLAG_WORK_WITH_CACHE_DISABLE`. + :SOC_EMAC_SUPPORTED: * :cpp:member:`smi_mdc_gpio_num` and :cpp:member:`smi_mdio_gpio_num`: the GPIO number used to connect the SMI signals. + :SOC_EMAC_SUPPORTED: * :cpp:member:`interface`: configuration of MAC Data interface to PHY (MII/RMII). + :SOC_EMAC_SUPPORTED: * :cpp:member:`clock_config`: configuration of EMAC Interface clock (``REF_CLK`` mode and GPIO number in case of RMII). Configuration for PHY is described in :cpp:class:`eth_phy_config_t`, including: -* :cpp:member:`phy_addr`: multiple PHY device can share the same SMI bus, so each PHY needs a unique address. Usually this address is configured during hardware design by pulling up/down some PHY strapping pins. You can set the value from 0 to 15 based on your Ethernet board. Especially, if the SMI bus is shared by only one PHY device, setting this value to -1 can enable the driver to detect the PHY address automatically. -* :cpp:member:`reset_timeout_ms`: reset timeout value, in milliseconds, typically PHY reset should be finished within 100ms. -* :cpp:member:`autonego_timeout_ms`: auto-negotiation timeout value, in milliseconds. Ethernet driver will start negotiation with the peer Ethernet node automatically, to determine to duplex and speed mode. This value usually depends on the ability of the PHY device on your board. -* :cpp:member:`reset_gpio_num`: if your board also connect the PHY reset pin to one of the GPIO, then set it here. Otherwise, set this field to -1. +.. list:: + + * :cpp:member:`phy_addr`: multiple PHY device can share the same SMI bus, so each PHY needs a unique address. Usually this address is configured during hardware design by pulling up/down some PHY strapping pins. You can set the value from 0 to 15 based on your Ethernet board. Especially, if the SMI bus is shared by only one PHY device, setting this value to -1 can enable the driver to detect the PHY address automatically. + * :cpp:member:`reset_timeout_ms`: reset timeout value, in milliseconds, typically PHY reset should be finished within 100ms. + * :cpp:member:`autonego_timeout_ms`: auto-negotiation timeout value, in milliseconds. Ethernet driver will start negotiation with the peer Ethernet node automatically, to determine to duplex and speed mode. This value usually depends on the ability of the PHY device on your board. + * :cpp:member:`reset_gpio_num`: if your board also connect the PHY reset pin to one of the GPIO, then set it here. Otherwise, set this field to -1. 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`. @@ -182,49 +188,115 @@ Create MAC and PHY Instance Ethernet driver is implemented in an Object-Oriented style. Any operation on MAC and PHY should be based on the instance of them two. +.. only:: SOC_EMAC_SUPPORTED + + Internal EMAC + External PHY + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + .. highlight:: c + + :: + + eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); // apply default MAC configuration + mac_config.smi_mdc_gpio_num = CONFIG_EXAMPLE_ETH_MDC_GPIO; // alter the GPIO used for MDC signal + mac_config.smi_mdio_gpio_num = CONFIG_EXAMPLE_ETH_MDIO_GPIO; // alter the GPIO used for MDIO signal + esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&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_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); + + Optional Runtime MAC Clock Configuration + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + EMAC ``REF_CLK`` can be optionally configured from user application code. + + .. highlight:: c + + :: + + eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); // apply default MAC configuration + + // ... + + mac_config.interface = EMAC_DATA_INTERFACE_RMII; // alter EMAC Data Interface + mac_config.clock_config.rmii.clock_mode = EMAC_CLK_OUT; // select EMAC REF_CLK mode + mac_config.clock_config.rmii.clock_gpio = EMAC_CLK_OUT_GPIO; // select GPIO number used to input/output EMAC REF_CLK + esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config); // create MAC instance + + +SPI-Ethernet Module +^^^^^^^^^^^^^^^^^^^ + .. highlight:: c :: - eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); // apply default MAC configuration - mac_config.smi_mdc_gpio_num = 23; // alter the GPIO used for MDC signal - mac_config.smi_mdio_gpio_num = 18; // alter the GPIO used for MDIO signal - esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config); // create MAC instance + eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); // apply default MAC configuration + 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 + // Install GPIO interrupt service (as the SPI-Ethernet module is interrupt driven) + gpio_install_isr_service(0); + // SPI bus configuration + spi_device_handle_t spi_handle = NULL; + spi_bus_config_t buscfg = { + .miso_io_num = CONFIG_EXAMPLE_ETH_SPI_MISO_GPIO, + .mosi_io_num = CONFIG_EXAMPLE_ETH_SPI_MOSI_GPIO, + .sclk_io_num = CONFIG_EXAMPLE_ETH_SPI_SCLK_GPIO, + .quadwp_io_num = -1, + .quadhd_io_num = -1, + }; + ESP_ERROR_CHECK(spi_bus_initialize(CONFIG_EXAMPLE_ETH_SPI_HOST, &buscfg, 1)); + // Allocate SPI device from the bus + spi_device_interface_config_t devcfg = { + .command_bits = 1, + .address_bits = 7, + .mode = 0, + .clock_speed_hz = CONFIG_EXAMPLE_ETH_SPI_CLOCK_MHZ * 1000 * 1000, + .spics_io_num = CONFIG_EXAMPLE_ETH_SPI_CS_GPIO, + .queue_size = 20 + }; + ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_EXAMPLE_ETH_SPI_HOST, &devcfg, &spi_handle)); + /* dm9051 ethernet driver is based on spi driver */ + eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(spi_handle); + dm9051_config.int_gpio_num = CONFIG_EXAMPLE_ETH_SPI_INT_GPIO; + esp_eth_mac_t *mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config); + esp_eth_phy_t *phy = esp_eth_phy_new_dm9051(&phy_config); - eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); // apply default PHY configuration - phy_config.phy_addr = 1; // alter the PHY address according to your board design - phy_config.reset_gpio_num = 5; // 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 - // 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:: - Care should be taken, when creating MAC and PHY instance for SPI-Ethernet modules (e.g. DM9051), the constructor function must have the same suffix (e.g. `esp_eth_mac_new_dm9051` and `esp_eth_phy_new_dm9051`). This is because we don't have other choices but the integrated PHY. - Besides that, we have to create an SPI device handle firstly and then pass it to the MAC constructor function. More instructions on creating SPI device handle, please refer to :doc:`SPI Master <../peripherals/spi_master>`. + * When creating MAC and PHY instance for SPI-Ethernet modules (e.g. DM9051), the constructor function must have the same suffix (e.g. `esp_eth_mac_new_dm9051` and `esp_eth_phy_new_dm9051`). This is because we don't have other choices but the integrated PHY. + * We have to create an SPI device handle firstly and then pass it to the MAC constructor function. More instructions on creating SPI device handle, please refer to :doc:`SPI Master <../peripherals/spi_master>`. + * The SPI device configuration (i.e. `spi_device_interface_config_t`) can be different for other Ethernet modules. Please check out your module's spec and the examples in esp-idf. -Optional Runtime MAC Clock Configuration -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -EMAC ``REF_CLK`` can be optionally configured from user application code. - -.. highlight:: c - -:: - - eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); // apply default MAC configuration - - // ... - - mac_config.interface = EMAC_DATA_INTERFACE_RMII; // alter EMAC Data Interface - mac_config.clock_config.rmii.clock_mode = EMAC_CLK_OUT; // select EMAC REF_CLK mode - mac_config.clock_config.rmii.clock_gpio = EMAC_CLK_OUT_GPIO; // select GPIO number used to input/output EMAC REF_CLK - esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config); // create MAC instance Install Driver -------------- +To install the Ethernet driver, we need to combine the instance of MAC and PHY and set some additional high-level configurations (i.e. not specific to either MAC or PHY) in :cpp:class:`esp_eth_config_t`: + +* :cpp:member:`mac`: instance that created from MAC generator (e.g. :cpp:func:`esp_eth_mac_new_esp32`). +* :cpp:member:`phy`: instance that created from PHY generator (e.g. :cpp:func:`esp_eth_phy_new_ip101`). +* :cpp:member:`check_link_period_ms`: Ethernet driver starts an OS timer to check the link status periodically, this field is used to set the interval, in milliseconds. +* :cpp:member:`stack_input`: In most of Ethernet IoT applications, any Ethernet frame that received by driver should be passed to upper layer (e.g. TCP/IP stack). This field is set to a function which is responsible to deal with the incoming frames. You can even update this field at runtime via function :cpp:func:`esp_eth_update_input_path` after driver installation. +* :cpp:member:`on_lowlevel_init_done` and :cpp:member:`on_lowlevel_deinit_done`: These two fields are used to specify the hooks which get invoked when low level hardware has been initialized or de-initialized. + +ESP-IDF provides a default configuration for driver installation in macro :c:macro:`ETH_DEFAULT_CONFIG`. + +.. highlight:: c + +:: + + esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy); // apply default driver configuration + esp_eth_handle_t eth_handle = NULL; // after driver installed, we will get the handle of the driver + esp_eth_driver_install(&config, ð_handle); // install driver + Ethernet driver also includes event-driven model, which will send useful and important event to user space. We need to initialize the event loop before installing the Ethernet driver. For more information about event-driven programming, please refer to :doc:`ESP Event <../system/esp_event>`. .. highlight:: c @@ -244,7 +316,7 @@ Ethernet driver also includes event-driven model, which will send useful and imp esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr); ESP_LOGI(TAG, "Ethernet Link Up"); ESP_LOGI(TAG, "Ethernet HW Addr %02x:%02x:%02x:%02x:%02x:%02x", - mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); + mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); break; case ETHERNET_EVENT_DISCONNECTED: ESP_LOGI(TAG, "Ethernet Link Down"); @@ -263,24 +335,6 @@ Ethernet driver also includes event-driven model, which will send useful and imp esp_event_loop_create_default(); // create a default event loop that running in background esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, NULL); // register Ethernet event handler (to deal with user specific stuffs when event like link up/down happened) -To install the Ethernet driver, we need to combine the instance of MAC and PHY and set some additional high-level configurations (i.e. not specific to either MAC or PHY) in :cpp:class:`esp_eth_config_t`: - -* :cpp:member:`mac`: instance that created from MAC generator (e.g. :cpp:func:`esp_eth_mac_new_esp32`). -* :cpp:member:`phy`: instance that created from PHY generator (e.g. :cpp:func:`esp_eth_phy_new_ip101`). -* :cpp:member:`check_link_period_ms`: Ethernet driver starts an OS timer to check the link status periodically, this field is used to set the interval, in milliseconds. -* :cpp:member:`stack_input`: In most of Ethernet IoT applications, any Ethernet frame that received by driver should be passed to upper layer (e.g. TCP/IP stack). This field is set to a function which is responsible to deal with the incoming frames. You can even update this field at runtime via function :cpp:func:`esp_eth_update_input_path` after driver installation. -* :cpp:member:`on_lowlevel_init_done` and :cpp:member:`on_lowlevel_deinit_done`: These two fields are used to specify the hooks which get invoked when low level hardware has been initialized or de-initialized. - -ESP-IDF provides a default configuration for driver installation in macro :c:macro:`ETH_DEFAULT_CONFIG`. - -.. highlight:: c - -:: - - esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy); // apply default driver configuration - esp_eth_handle_t eth_handle = NULL; // after driver installed, we will get the handle of the driver - esp_eth_driver_install(&config, ð_handle); // install driver - Start Ethernet Driver --------------------- @@ -303,8 +357,8 @@ The TCP/IP stack used in ESP-IDF is called LwIP, for more information about it, To connect Ethernet driver to TCP/IP stack, these three steps need to follow: 1. Create network interface for Ethernet driver -2. Register IP event handlers -3. Attach the network interface to Ethernet driver +2. Attach the network interface to Ethernet driver +3. Register IP event handlers More information about network interface, please refer to :doc:`Network Interface `. @@ -330,12 +384,14 @@ More information about network interface, please refer to :doc:`Network Interfac esp_netif_init()); // Initialize TCP/IP network interface (should be called only once in application) esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH(); // apply default network interface configuration for Ethernet esp_netif_t *eth_netif = esp_netif_new(&cfg); // create network interface for Ethernet driver - esp_eth_set_default_handlers(eth_netif); // set default handlers to process TCP/IP stuffs - esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL); // register user defined IP event handlers esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle)); // attach Ethernet driver to TCP/IP stack + esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL); // register user defined IP event handlers esp_eth_start(eth_handle); // start Ethernet driver state machine +.. warning:: + It is recommended to fully initialize the Ethernet driver and network interface prior registering user's Ethernet/IP event handlers, i.e. register the event handlers as the last thing prior starting the Ethernet driver. Such approach ensures that Ethernet/IP events get executed first by the Ethernet driver or network interface and so the system is in expected state when executing user's handlers. + .. _misc-operation-of-driver: Misc control of Ethernet driver @@ -350,7 +406,7 @@ The following functions should only be invoked after the Ethernet driver has bee .. highlight:: c :: - + /* get MAC address */ uint8_t mac_addr[6]; memset(mac_addr, 0, sizeof(mac_addr)); diff --git a/docs/en/api-reference/network/esp_openthread.rst b/docs/en/api-reference/network/esp_openthread.rst new file mode 100644 index 0000000000..0843047962 --- /dev/null +++ b/docs/en/api-reference/network/esp_openthread.rst @@ -0,0 +1,31 @@ +Thread +========== + +Introduction +------------ + +`Thread `_ is a IP-based mesh networking protocol. It's based on the 802.15.4 physical and MAC layer. + +Application Examples +-------------------- + +The :example:`openthread` directory of ESP-IDF examples contains the following applications: + +- The OpenThread interactive shell :example:`openthread/ot_cli`. +- The Thread border router :example:`openthread/ot_br`. +- The Thread radio co-processor :example:`openthread/ot_rcp`. + + +API Reference +------------- + +For manipulating the Thread network, the OpenThread api shall be used. +The OpenThread api docs can be found at the `OpenThread official website `_. + +ESP-IDF provides extra apis for launching and managing the OpenThread stack, binding to network interfaces and border routing features. + +.. include-build-file:: inc/esp_openthread.inc +.. include-build-file:: inc/esp_openthread_types.inc +.. include-build-file:: inc/esp_openthread_lock.inc +.. include-build-file:: inc/esp_openthread_netif_glue.inc +.. include-build-file:: inc/esp_openthread_border_router.inc diff --git a/docs/en/api-reference/network/index.rst b/docs/en/api-reference/network/index.rst index f4a0977a7a..6762211d46 100644 --- a/docs/en/api-reference/network/index.rst +++ b/docs/en/api-reference/network/index.rst @@ -13,6 +13,7 @@ Wi-Fi SmartConfig ESP-NOW ESP-WIFI-MESH + EasyConnect Code examples for the Wi-Fi API are provided in the :example:`wifi` directory of ESP-IDF examples. @@ -29,6 +30,16 @@ Ethernet Code examples for the Ethernet API are provided in the :example:`ethernet` directory of ESP-IDF examples. +Thread +========== + +.. toctree:: + :maxdepth: 1 + + Thread + +Thread is an IPv6-based mesh networking technology for IoT. +Code examples for the Thread API are provided in the :example:`openthread` directory of ESP-IDF examples. IP Network Layer ================ diff --git a/docs/en/api-reference/peripherals/adc.rst b/docs/en/api-reference/peripherals/adc.rst index 1723b56d55..d9865c47ec 100644 --- a/docs/en/api-reference/peripherals/adc.rst +++ b/docs/en/api-reference/peripherals/adc.rst @@ -1,5 +1,5 @@ -Analog to Digital Converter -=========================== +Analog to Digital Converter (ADC) +================================= {IDF_TARGET_ADC1_CH0: default="GPIO 0", esp32="GPIO 36"} {IDF_TARGET_ADC2_CH7: default="GPIO 0", esp32="GPIO 27"} diff --git a/docs/en/api-reference/peripherals/dac.rst b/docs/en/api-reference/peripherals/dac.rst index 50251ca9a2..06f4005a27 100644 --- a/docs/en/api-reference/peripherals/dac.rst +++ b/docs/en/api-reference/peripherals/dac.rst @@ -1,5 +1,5 @@ -Digital To Analog Converter -=========================== +Digital To Analog Converter (DAC) +================================= {IDF_TARGET_DAC_CH_1: default = "GPIO25", esp32 = "GPIO25", esp32s2 = "GPIO17"} {IDF_TARGET_DAC_CH_2: default = "GPIO26", esp32 = "GPIO26", esp32s2 = "GPIO18"} diff --git a/docs/en/api-reference/peripherals/dedic_gpio.rst b/docs/en/api-reference/peripherals/dedic_gpio.rst index 9f9c675957..89b83e948b 100644 --- a/docs/en/api-reference/peripherals/dedic_gpio.rst +++ b/docs/en/api-reference/peripherals/dedic_gpio.rst @@ -4,7 +4,7 @@ Dedicated GPIO Overview -------- -The dedicated GPIO is designed for CPU interaction with GPIO matrix and IO MUX. Any GPIO that is configured as "dedicated" can be access by CPU instructions directly, which makes it easy to achieve a high GPIO flip speed, and simulate serial/parallel interface in a bit-banging way. +The dedicated GPIO is designed for CPU interaction with GPIO matrix and IO MUX. Any GPIO that is configured as "dedicated" can be access by CPU instructions directly, which makes it easy to achieve a high GPIO flip speed, and simulate serial/parallel interface in a bit-banging way. As toggling a GPIO in this "CPU Dedicated" way costs few overhead, it would be great for cases like performance measurement using an oscilloscope. Create/Destroy GPIO Bundle @@ -75,7 +75,7 @@ GPIO Bundle Operations .. note:: The functions above just wrap the customized instructions defined for {IDF_TARGET_NAME}, for the details of those instructions, please refer to *{IDF_TARGET_NAME} Technical Reference Manual* > *IO MUX and GPIO Matrix (GPIO, IO_MUX)* [`PDF <{IDF_TARGET_TRM_EN_URL}#iomuxgpio>`__]. -.. only:: esp32s2 +.. only:: SOC_DEDIC_GPIO_HAS_INTERRUPT Interrupt Handling ------------------ @@ -112,11 +112,21 @@ For advanced users, they can always manipulate the GPIOs by writing assembly cod 1. Allocate a GPIO bundle: :cpp:func:`dedic_gpio_new_bundle` 2. Query the mask occupied by that bundle: :cpp:func:`dedic_gpio_get_out_mask` or/and :cpp:func:`dedic_gpio_get_in_mask` 3. Call CPU LL apis (e.g. `cpu_ll_write_dedic_gpio_mask`) or write assembly code with that mask +4. The fasted way of toggling IO is to use the dedicated "set/clear" instructions: -For details of supported dedicated GPIO instructions, please refer to *{IDF_TARGET_NAME} Technical Reference Manual* > *IO MUX and GPIO Matrix (GPIO, IO_MUX)* [`PDF <{IDF_TARGET_TRM_EN_URL}#iomuxgpio>`__]. ++----------+---------------------------+---------------------------+------------------------------------------------------------------------+ +| CPU Arch | Set bits of GPIO | Clear bits of GPIO | Remarks | ++==========+===========================+===========================+========================================================================+ +| Xtensa | set_bit_gpio_out imm[7:0] | clr_bit_gpio_out imm[7:0] | immediate value width depends on the number of dedicated GPIO channels | ++----------+---------------------------+---------------------------+------------------------------------------------------------------------+ +| RISC-V | csrrsi rd, csr, imm[4:0] | csrrci rd, csr, imm[4:0] | can only control the lowest 4 GPIO channels | ++----------+---------------------------+---------------------------+------------------------------------------------------------------------+ + + +For details of supported dedicated GPIO instructions, please refer to *{IDF_TARGET_NAME} Technical Reference Manual* > *IO MUX and GPIO Matrix (GPIO, IO_MUX)* [`PDF <{IDF_TARGET_TRM_EN_URL}#iomuxgpio>`__]. The supported dedicated CPU instructions are also wrapped inside `soc/cpu_ll.h` as helper inline functions. .. note:: - Writing assembly code in application could make your code hard to port between targets, because those customized instructions are not guaranteed to remain the same format in different targets. + Writing assembly code in application could make your code hard to port between targets, because those customized instructions are not guaranteed to remain the same format on different targets. Application Example diff --git a/docs/en/api-reference/peripherals/ds.rst b/docs/en/api-reference/peripherals/ds.rst index 125b9be28e..0e1b506ba8 100644 --- a/docs/en/api-reference/peripherals/ds.rst +++ b/docs/en/api-reference/peripherals/ds.rst @@ -1,5 +1,5 @@ -Digital Signature -================= +Digital Signature (DS) +====================== The Digital Signature (DS) module provides hardware acceleration of signing messages based on RSA. It uses pre-encrypted parameters to calculate a signature. diff --git a/docs/en/api-reference/peripherals/gpio.rst b/docs/en/api-reference/peripherals/gpio.rst index 2f3d0ce214..93a5e05523 100644 --- a/docs/en/api-reference/peripherals/gpio.rst +++ b/docs/en/api-reference/peripherals/gpio.rst @@ -6,33 +6,801 @@ Overview .. only:: esp32 - The {IDF_TARGET_NAME} chip features 34 physical GPIO pads. Some GPIO pads cannot be used or do not have the corresponding pin on the chip package. For more details, see *{IDF_TARGET_NAME} Technical Reference Manual* > *IO MUX and GPIO Matrix (GPIO, IO_MUX)* [`PDF <{IDF_TARGET_TRM_EN_URL}#iomuxgpio>`__]. Each pad can be used as a general purpose I/O or can be connected to an internal peripheral signal. + The {IDF_TARGET_NAME} chip features 34 physical GPIO pads. Some GPIO pads cannot be used or do not have the corresponding pin on the chip package. For more details, see *{IDF_TARGET_NAME} Technical Reference Manual* > *IO MUX and GPIO Matrix (GPIO, IO_MUX)* [`PDF <{IDF_TARGET_TRM_EN_URL}#iomuxgpio>`__]. + + Each pad can be used as a general purpose I/O or can be connected to an internal peripheral signal. The table below provides more information on pin usage, and please note the comments in the table for GPIOs with restrictions. + + .. list-table:: + :header-rows: 1 + :widths: 8 12 12 20 + + * - GPIO + - Analog Function + - RTC GPIO + - Comments + + * - GPIO0 + - ADC2_CH1 + - RTC_GPIO11 + - Strapping pin + + * - GPIO1 + - + - + - TXD + + * - GPIO2 + - ADC2_CH2 + - RTC_GPIO12 + - Strapping pin + + * - GPIO3 + - + - + - RXD + + * - GPIO4 + - ADC2_CH0 + - RTC_GPIO10 + - + + * - GPIO5 + - + - + - Strapping pin + + * - GPIO6 + - + - + - SPI0/1 + + * - GPIO7 + - + - + - SPI0/1 + + * - GPIO8 + - + - + - SPI0/1 + + * - GPIO9 + - + - + - SPI0/1 + + * - GPIO10 + - + - + - SPI0/1 + + * - GPIO11 + - + - + - SPI0/1 + + * - GPIO12 + - ADC2_CH5 + - RTC_GPIO15 + - Strapping pin; JTAG + + * - GPIO13 + - ADC2_CH4 + - RTC_GPIO14 + - JTAG + + * - GPIO14 + - ADC2_CH6 + - RTC_GPIO16 + - JTAG + + * - GPIO15 + - ADC2_CH3 + - RTC_GPIO13 + - Strapping pin; JTAG + + * - GPIO16 + - + - + - SPI0/1 + + * - GPIO17 + - + - + - SPI0/1 + + * - GPIO18 + - + - + - + + * - GPIO19 + - + - + - + + * - GPIO20 + - + - + - This pin is only available on ESP32-PICO-V3 chip package + + * - GPIO21 + - + - + - + + * - GPIO22 + - + - + - + + * - GPIO23 + - + - + - + + * - GPIO25 + - ADC2_CH8 + - RTC_GPIO6 + - + + * - GPIO26 + - ADC2_CH9 + - RTC_GPIO7 + - + + * - GPIO27 + - ADC2_CH7 + - RTC_GPIO17 + - + + * - GPIO32 + - ADC1_CH4 + - RTC_GPIO9 + - + + * - GPIO33 + - ADC1_CH5 + - RTC_GPIO8 + - + + * - GPIO34 + - ADC1_CH6 + - RTC_GPIO4 + - GPI + + * - GPIO35 + - ADC1_CH7 + - RTC_GPIO5 + - GPI + + * - GPIO36 + - ADC1_CH0 + - RTC_GPIO0 + - GPI + + * - GPIO37 + - ADC1_CH1 + - RTC_GPIO1 + - GPI + + * - GPIO38 + - ADC1_CH2 + - RTC_GPIO2 + - GPI + + * - GPIO39 + - ADC1_CH3 + - RTC_GPIO3 + - GPI + + .. note:: + + - Strapping pin: GPIO0, GPIO2, GPIO5, GPIO12 (MTDI), and GPIO15 (MTDO) are strapping pins. For more infomation, please refer to `ESP32 datasheet `_. + - SPI0/1: GPIO6-11 and GPIO16-17 are usually connected to the SPI flash and PSRAM integrated on the module and therefore should not be used for other purposes. + - JTAG: GPIO12-15 are usually used for inline debug. + - GPI: GPIO34-39 can only be set as input mode and do not have software-enabled pullup or pulldown functions. + - TXD & RXD are usually used for flashing and debugging. + - ADC2: ADC2 pins cannot be used when Wi-Fi is used. So, if you’re using Wi-Fi and you’re having trouble getting the value from an ADC2 GPIO, you may consider using an ADC1 GPIO instead, that should solve your problem. For more details, please refer to `ADC limitations `_. - - Note that GPIO6-11 are usually used for SPI flash. - - GPIO34-39 can only be set as input mode and do not have software pullup or pulldown functions. .. only:: esp32s2 The {IDF_TARGET_NAME} chip features 43 physical GPIO pads. Some GPIO pads cannot be used or do not have the corresponding pin on the chip package. For more details, see *{IDF_TARGET_NAME} Technical Reference Manual* > *IO MUX and GPIO Matrix (GPIO, IO_MUX)* [`PDF <{IDF_TARGET_TRM_EN_URL}#iomuxgpio>`__]. Each pad can be used as a general purpose I/O or can be connected to an internal peripheral signal. - - Note that GPIO26-32 are usually used for SPI flash. - - GPIO46 is fixed to pull-down and is input only + The table below provides more information on pin usage, and please note the comments in the table for GPIOs with restrictions. + + .. list-table:: + :header-rows: 1 + :widths: 8 12 12 20 + + * - GPIO + - Analog Function + - RTC GPIO + - Comment + + * - GPIO0 + - + - RTC_GPIO0 + - Strapping pin + + * - GPIO1 + - ADC1_CH0 + - RTC_GPIO1 + - + + * - GPIO2 + - ADC1_CH1 + - RTC_GPIO2 + - + + * - GPIO3 + - ADC1_CH2 + - RTC_GPIO3 + - + + * - GPIO4 + - ADC1_CH3 + - RTC_GPIO4 + - + + * - GPIO5 + - ADC1_CH4 + - RTC_GPIO5 + - + + * - GPIO6 + - ADC1_CH5 + - RTC_GPIO6 + - + + * - GPIO7 + - ADC1_CH6 + - RTC_GPIO7 + - + + * - GPIO8 + - ADC1_CH7 + - RTC_GPIO8 + - + + * - GPIO9 + - ADC1_CH8 + - RTC_GPIO9 + - + + * - GPIO10 + - ADC1_CH9 + - RTC_GPIO10 + - + + * - GPIO11 + - ADC2_CH0 + - RTC_GPIO11 + - + + * - GPIO12 + - ADC2_CH1 + - RTC_GPIO12 + - + + * - GPIO13 + - ADC2_CH2 + - RTC_GPIO13 + - + + * - GPIO14 + - ADC2_CH3 + - RTC_GPIO14 + - + + * - GPIO15 + - ADC2_CH4 + - RTC_GPIO15 + - + + * - GPIO16 + - ADC2_CH5 + - RTC_GPIO16 + - + + * - GPIO17 + - ADC2_CH6 + - RTC_GPIO17 + - + + * - GPIO18 + - ADC2_CH7 + - RTC_GPIO18 + - + + * - GPIO19 + - ADC2_CH8 + - RTC_GPIO19 + - + + * - GPIO20 + - ADC2_CH9 + - RTC_GPIO20 + - + + * - GPIO21 + - + - RTC_GPIO21 + - + + * - GPIO26 + - + - + - SPI0/1 + + * - GPIO27 + - + - + - SPI0/1 + + * - GPIO28 + - + - + - SPI0/1 + + * - GPIO29 + - + - + - SPI0/1 + + * - GPIO30 + - + - + - SPI0/1 + + * - GPIO31 + - + - + - SPI0/1 + + * - GPIO32 + - + - + - SPI0/1 + + * - GPIO33 + - + - + - + + * - GPIO34 + - + - + - + + * - GPIO35 + - + - + - + + * - GPIO36 + - + - + - + + * - GPIO37 + - + - + - + + * - GPIO38 + - + - + - + + * - GPIO39 + - + - + - JTAG + + * - GPIO40 + - + - + - JTAG + + * - GPIO41 + - + - + - JTAG + + * - GPIO42 + - + - + - JTAG + + * - GPIO43 + - + - + - + + * - GPIO44 + - + - + - + + * - GPIO45 + - + - + - Strapping pin + + * - GPIO46 + - + - + - GPI;Strapping pin + + .. note:: + + - Strapping pin: GPIO0, GPIO45 and GPIO46 are strapping pins. For more infomation, please refer to `ESP32-S2 datasheet `_ + - SPI0/1: GPIO26-32 are usually used for SPI flash and PSRAM and not recommended for other uses. + - JTAG: GPIO39-42 are usually used for inline debug. + - GPI: GPIO46 is fixed to pull-down and is input only. + .. only:: esp32c3 The {IDF_TARGET_NAME} chip features 22 physical GPIO pads. Some GPIO pads cannot be used or do not have the corresponding pin on the chip package. For more details, see *{IDF_TARGET_NAME} Technical Reference Manual* > *IO MUX and GPIO Matrix (GPIO, IO_MUX)* [`PDF <{IDF_TARGET_TRM_EN_URL}#iomuxgpio>`__]. Each pad can be used as a general purpose I/O or can be connected to an internal peripheral signal. - - Note that GPIO12-17 are usually used for SPI flash. - - Note that GPIO 18 and 19 are used by USB-JTAG by default. In order to use them as GPIOs, USB-JTAG will be disabled by the drivers. - - {IDF_TARGET_NAME} doesn't have separate "RTC GPIO" support. However, GPIO0-5 keep the rtc feature, which can be used for power-management and analog subsystem. + The table below provides more information on pin usage, and please note the comments in the table for GPIOs with restrictions. + + + .. list-table:: + :header-rows: 1 + :widths: 12 12 22 + + * - GPIO + - Analog Function + - Comment + + * - GPIO0 + - ADC1_CH0 + - RTC + + * - GPIO1 + - ADC1_CH1 + - RTC + + * - GPIO2 + - ADC1_CH2 + - Strapping pin;RTC + + * - GPIO3 + - ADC1_CH3 + - RTC + + * - GPIO4 + - ADC1_CH4 + - RTC + + * - GPIO5 + - ADC2_CH0 + - RTC + + * - GPIO6 + - + - + + * - GPIO7 + - + - + + * - GPIO8 + - + - Strapping pin + + * - GPIO9 + - + - Strapping pin + + * - GPIO10 + - + - + + * - GPIO11 + - + - + + * - GPIO12 + - + - SPI0/1 + + * - GPIO13 + - + - SPI0/1 + + * - GPIO14 + - + - SPI0/1 + + * - GPIO15 + - + - SPI0/1 + + * - GPIO16 + - + - SPI0/1 + + * - GPIO17 + - + - SPI0/1 + + * - GPIO18 + - + - USB-JTAG + + * - GPIO19 + - + - USB-JTAG + + * - GPIO20 + - + - + + * - GPIO21 + - + - + + .. note:: + + - Strapping pin: GPIO2, GPIO8 and GPIO9 are strapping pins. For more infomation, please refer to `ESP32-C3 datasheet `_. + - SPI0/1: GPIO12-17 are usually used for SPI flash and PSRAM and not recommended for other uses. + - USB-JTAG: GPIO 18 and 19 are used by USB-JTAG by default. In order to use them as GPIOs, USB-JTAG will be disabled by the drivers. + - RTC: GPIO0-5 can be used when in deep sleep. + + + .. only:: esp32s3 The {IDF_TARGET_NAME} chip features 45 physical GPIO pads. Some GPIO pads cannot be used or do not have the corresponding pin on the chip package. For more details, see *{IDF_TARGET_NAME} Technical Reference Manual* > *IO MUX and GPIO Matrix (GPIO, IO_MUX)* [`PDF <{IDF_TARGET_TRM_EN_URL}#iomuxgpio>`__]. Each pad can be used as a general purpose I/O or can be connected to an internal peripheral signal. - - Note that GPIO26-32 are usually used for SPI flash. - - Note that GPIO 19 and 20 are used by USB-JTAG by default. In order to use them as GPIOs, USB-JTAG will be disabled by the drivers. - - Note that when using SPI eight-line mode, GPIO33~37 are connected to IO4~IO7 and DQS. On ESP32-S3R8 / ESP32-S3R8V board GPIO33~37 are not recommended for other uses. + The table below provides more information on pin usage, and please note the comments in the table for GPIOs with restrictions. + + .. list-table:: + :header-rows: 1 + :widths: 8 12 12 20 + + * - GPIO + - Analog Function + - RTC GPIO + - Comment + + * - GPIO0 + - + - RTC_GPIO0 + - Strapping pin + + * - GPIO1 + - ADC1_CH0 + - RTC_GPIO1 + - + + * - GPIO2 + - ADC1_CH1 + - RTC_GPIO2 + - + + * - GPIO3 + - ADC1_CH2 + - RTC_GPIO3 + - Strapping pin + + * - GPIO4 + - ADC1_CH3 + - RTC_GPIO4 + - + + * - GPIO5 + - ADC1_CH4 + - RTC_GPIO5 + - + + * - GPIO6 + - ADC1_CH5 + - RTC_GPIO6 + - + + * - GPIO7 + - ADC1_CH6 + - RTC_GPIO7 + - + + * - GPIO8 + - ADC1_CH7 + - RTC_GPIO8 + - + + * - GPIO9 + - ADC1_CH8 + - RTC_GPIO9 + - + + * - GPIO10 + - ADC1_CH9 + - RTC_GPIO10 + - + + * - GPIO11 + - ADC2_CH0 + - RTC_GPIO11 + - + + * - GPIO12 + - ADC2_CH1 + - RTC_GPIO12 + - + + * - GPIO13 + - ADC2_CH2 + - RTC_GPIO13 + - + + * - GPIO14 + - ADC2_CH3 + - RTC_GPIO14 + - + + * - GPIO15 + - ADC2_CH4 + - RTC_GPIO15 + - + + * - GPIO16 + - ADC2_CH5 + - RTC_GPIO16 + - + + * - GPIO17 + - ADC2_CH6 + - RTC_GPIO17 + - + + * - GPIO18 + - ADC2_CH7 + - RTC_GPIO18 + - + + * - GPIO19 + - ADC2_CH8 + - RTC_GPIO19 + - USB-JTAG + + * - GPIO20 + - ADC2_CH9 + - RTC_GPIO20 + - USB-JTAG + + * - GPIO21 + - + - RTC_GPIO21 + - + + * - GPIO26 + - + - + - SPI0/1 + + * - GPIO27 + - + - + - SPI0/1 + + * - GPIO28 + - + - + - SPI0/1 + + * - GPIO29 + - + - + - SPI0/1 + + * - GPIO30 + - + - + - SPI0/1 + + * - GPIO31 + - + - + - SPI0/1 + + * - GPIO32 + - + - + - SPI0/1 + + * - GPIO33 + - + - + - SPI0/1 + + * - GPIO34 + - + - + - SPI0/1 + + * - GPIO35 + - + - + - SPI0/1 + + * - GPIO36 + - + - + - SPI0/1 + + * - GPIO37 + - + - + - SPI0/1 + + * - GPIO38 + - + - + - + + * - GPIO39 + - + - + - + + * - GPIO40 + - + - + - + + * - GPIO41 + - + - + - + + * - GPIO42 + - + - + - + + * - GPIO43 + - + - + - + + * - GPIO44 + - + - + - + + * - GPIO45 + - + - + - Strapping pin + + * - GPIO46 + - + - + - Strapping pin + + * - GPIO47 + - + - + - + + * - GPIO48 + - + - + - + + .. Note:: + + - Strapping pin: GPIO0, GPIO3, GPIO45 and GPIO46 are strapping pins. + - SPI0/1: GPIO26-32 are usually used for SPI flash and PSRAM and not recommended for other uses. When using Octal Flash or Octal PSRAM or both, GPIO33~37 are connected to SPIIO4 ~ SPIIO7 and SPIDQS. Therefore on ESP32-S3R8 / ESP32-S3R8V board GPIO33~37 are also not recommended for other uses. + - USB-JTAG: GPIO 19 and 20 are used by USB-JTAG by default. In order to use them as GPIOs, USB-JTAG will be disabled by the drivers. + .. only:: SOC_RTCIO_INPUT_OUTPUT_SUPPORTED @@ -63,5 +831,3 @@ API Reference - Normal GPIO .. include-build-file:: inc/rtc_io.inc .. include-build-file:: inc/rtc_io_types.inc - - diff --git a/docs/en/api-reference/peripherals/hmac.rst b/docs/en/api-reference/peripherals/hmac.rst index ae594443ef..a431158fa6 100644 --- a/docs/en/api-reference/peripherals/hmac.rst +++ b/docs/en/api-reference/peripherals/hmac.rst @@ -1,5 +1,5 @@ -HMAC -==== +Hash-based Message Authentication Code (HMAC) +============================================= The HMAC (Hash-based Message Authentication Code) module provides hardware acceleration for SHA256-HMAC generation using a key burned into an eFuse block. HMACs work with pre-shared secret keys and provide authenticity and integrity to a message. diff --git a/docs/en/api-reference/peripherals/i2c.rst b/docs/en/api-reference/peripherals/i2c.rst index 7e6022b37b..29e95101a3 100644 --- a/docs/en/api-reference/peripherals/i2c.rst +++ b/docs/en/api-reference/peripherals/i2c.rst @@ -1,5 +1,5 @@ -I2C Driver -========== +Inter-Integrated Circuit (I2C) +============================== :link_to_translation:`zh_CN:[中文]` diff --git a/docs/en/api-reference/peripherals/i2s.rst b/docs/en/api-reference/peripherals/i2s.rst index feb582dc25..aa3f830ee7 100644 --- a/docs/en/api-reference/peripherals/i2s.rst +++ b/docs/en/api-reference/peripherals/i2s.rst @@ -1,27 +1,18 @@ -I2S -=== +Inter-IC Sound (I2S) +==================== -.. only:: esp32c3 - - .. warning:: - - This document is not updated for ESP32-C3 yet. +{IDF_TARGET_I2S_NUM:default="two", esp32s2="one", esp32c3="one"} Overview -------- I2S (Inter-IC Sound) is a serial, synchronous communication protocol that is usually used for transmitting audio data between two digital audio devices. -.. only:: esp32 - - {IDF_TARGET_NAME} contains two I2S peripherals. These peripherals can be configured to input and output sample data via the I2S driver. - -.. only:: esp32s2 - - {IDF_TARGET_NAME} contains one I2S peripheral. These peripherals can be configured to input and output sample data via the I2S driver. +{IDF_TARGET_NAME} contains {IDF_TARGET_I2S_NUM} I2S peripheral(s). These peripherals can be configured to input and output sample data via the I2S driver. An I2S bus consists of the following lines: +- Master clock line (operational) - Bit clock line - Channel select line - Serial data line @@ -30,29 +21,33 @@ Each I2S controller has the following features that can be configured using the - Operation as system master or slave - Capable of acting as transmitter or receiver -- Dedicated DMA controller that allows for streaming sample data without requiring the CPU to copy each data sample +- DMA controller that allows for streaming sample data without requiring the CPU to copy each data sample Each controller can operate in half-duplex communication mode. Thus, the two controllers can be combined to establish full-duplex communication. -I2S0 output can be routed directly to the digital-to-analog converter's (DAC) output channels (GPIO 25 & GPIO 26) to produce direct analog output without involving any external I2S codecs. I2S0 can also be used for transmitting PDM (Pulse-density modulation) signals. - -The I2S peripherals also support LCD mode for communicating data over a parallel bus, as used by some LCD displays and camera modules. LCD mode has the following operational modes: - -- LCD master transmitting mode -- Camera slave receiving mode -- ADC/DAC mode - .. only:: esp32 + I2S0 output can be routed directly to the digital-to-analog converter's (DAC) output channels (GPIO 25 & GPIO 26) to produce direct analog output without involving any external I2S codecs. I2S0 can also be used for transmitting PDM (Pulse-density modulation) signals. + +.. only:: esp32 or esp32s2 + + The I2S peripherals also support LCD mode for communicating data over a parallel bus, as used by some LCD displays and camera modules. LCD mode has the following operational modes: + + - LCD master transmitting mode + - Camera slave receiving mode + - ADC/DAC mode + For more information, see *{IDF_TARGET_NAME} Technical Reference Manual* > *I2S Controller (I2S)* > LCD Mode [`PDF <{IDF_TARGET_TRM_EN_URL}#camlcdctrl>`__]. -.. note:: +.. only:: SOC_I2S_SUPPORTS_APLL - For high accuracy clock applications, use the APLL_CLK clock source, which has the frequency range of 16 ~ 128 MHz. You can enable the APLL_CLK clock source by setting :cpp:member:`i2s_config_t::use_apll` to ``TRUE``. + .. note:: - If :cpp:member:`i2s_config_t::use_apll` = ``TRUE`` and :cpp:member:`i2s_config_t::fixed_mclk` > ``0``, then the master clock output frequency for I2S will be equal to the value of :cpp:member:`i2s_config_t::fixed_mclk`, which means that the mclk frequency is provided by the user, instead of being calculated by the driver. + For high accuracy clock applications, use the APLL_CLK clock source, which has the frequency range of 16 ~ 128 MHz. You can enable the APLL_CLK clock source by setting :cpp:member:`i2s_config_t::use_apll` to ``TRUE``. - The clock rate of the word select line, which is called audio left-right clock rate (LRCK) here, is always the divisor of the master clock output frequency and for which the following is always true: 0 < MCLK/LRCK/channels/bits_per_sample < 64. + If :cpp:member:`i2s_config_t::use_apll` = ``TRUE`` and :cpp:member:`i2s_config_t::fixed_mclk` > ``0``, then the master clock output frequency for I2S will be equal to the value of :cpp:member:`i2s_config_t::fixed_mclk`, which means that the mclk frequency is provided by the user, instead of being calculated by the driver. + + The clock rate of the word select line, which is called audio left-right clock rate (LRCK) here, is always the divisor of the master clock output frequency and for which the following is always true: 0 < MCLK/LRCK/channels/bits_per_sample < 64. Functional Overview @@ -68,26 +63,50 @@ Install the I2S driver by calling the function :cpp:func`i2s_driver_install` and - The structure :cpp:type:`i2s_config_t` with defined communication parameters - Event queue size and handle +Once :cpp:func`i2s_driver_install` returns ``ESP_OK``, it means I2S has started. + Configuration example: -.. code-block:: c +.. only:: not SOC_I2S_SUPPORTS_TDM - static const int i2s_num = 0; // i2s port number + .. code-block:: c - static const i2s_config_t i2s_config = { - .mode = I2S_MODE_MASTER | I2S_MODE_TX, - .sample_rate = 44100, - .bits_per_sample = 16, - .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, - .communication_format = I2S_COMM_FORMAT_STAND_I2S, - .intr_alloc_flags = 0, // default interrupt priority - .dma_buf_count = 8, - .dma_buf_len = 64, - .use_apll = false - }; + static const int i2s_num = 0; // i2s port number - i2s_driver_install(I2S_NUM, &i2s_config, 0, NULL); + i2s_config_t i2s_config = { + .mode = I2S_MODE_MASTER | I2S_MODE_TX, + .sample_rate = 44100, + .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, + .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, + .communication_format = I2S_COMM_FORMAT_STAND_I2S + .tx_desc_auto_clear = false, + .dma_buf_count = 8, + .dma_buf_len = 64, + .use_apll = false, + .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 // Interrupt level 1, default 0 + }; + i2s_driver_install(I2S_NUM, &i2s_config, 0, NULL); + +.. only:: SOC_I2S_SUPPORTS_TDM + + .. code-block:: c + + static const int i2s_num = 0; // i2s port number + + i2s_config_t i2s_config = { + .mode = I2S_MODE_MASTER | I2S_MODE_TX, + .sample_rate = 44100, + .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, + .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, + .communication_format = I2S_COMM_FORMAT_STAND_I2S, + .tx_desc_auto_clear = false, + .dma_buf_count = 8, + .dma_buf_len = 64, + .bits_per_chan = I2S_BITS_PER_SAMPLE_16BIT + }; + + i2s_driver_install(I2S_NUM, &i2s_config, 0, NULL); Setting Communication Pins ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -95,20 +114,24 @@ Setting Communication Pins Once the driver is installed, configure physical GPIO pins to which signals will be routed. For this, call the function :cpp:func`i2s_set_pin` and pass the following arguments to it: - Port number -- The structure :cpp:type:`i2s_pin_config_t` defining the GPIO pin numbers to which the driver should route the BCK, WS, DATA out, and DATA in signals. If you want to keep a currently allocated pin number for a specific signal, or if this signal is unused, then pass the macro :c:macro:`I2S_PIN_NO_CHANGE`. See the example below. +- The structure :cpp:type:`i2s_pin_config_t` defining the GPIO pin numbers to which the driver should route the MCK, BCK, WS, DATA out, and DATA in signals. If you want to keep a currently allocated pin number for a specific signal, or if this signal is unused, then pass the macro :c:macro:`I2S_PIN_NO_CHANGE`. See the example below. + +.. note:: + + MCK only takes effect in `I2S_MODE_MASTER` mode. .. code-block:: c static const i2s_pin_config_t pin_config = { - .bck_io_num = 26, - .ws_io_num = 25, - .data_out_num = 22, + .mck_io_num = 0, + .bck_io_num = 4, + .ws_io_num = 5, + .data_out_num = 18, .data_in_num = I2S_PIN_NO_CHANGE }; i2s_set_pin(i2s_num, &pin_config); - Running I2S Communication ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -117,14 +140,17 @@ To perform a transmission: - Prepare the data for sending - Call the function :cpp:func:`i2s_write` and pass the data buffer address and data length to it -The function will write the data to the I2S DMA Tx buffer, and then the data will be transmitted automatically. +The function will write the data to the DMA Tx buffer, and then the data will be transmitted automatically. .. code-block:: c i2s_write(I2S_NUM, samples_data, ((bits+8)/16)*SAMPLE_PER_CYCLE*4, &i2s_bytes_write, 100); +To retrieve received data, use the function :cpp:func:`i2s_read`. It will retrieve the data from the DMA Rx buffer, once the data is received by the I2S controller. -To retrieve received data, use the function :cpp:func:`i2s_read`. It will retrieve the data from the I2S DMA Rx buffer, once the data is received by the I2S controller. +.. code-block:: c + + i2s_read(I2S_NUM, data_recv, ((bits+8)/16)*SAMPLE_PER_CYCLE*4, &i2s_bytes_read, 100); You can temporarily stop the I2S driver by calling the function :cpp:func:`i2s_stop`, which will disable the I2S Tx/Rx units until the function :cpp:func:`i2s_start` is called. If the function :cpp:func`i2s_driver_install` is used, the driver will start up automatically eliminating the need to call :cpp:func:`i2s_start`. @@ -140,83 +166,186 @@ Application Example A code example for the I2S driver can be found in the directory :example:`peripherals/i2s`. -In addition, there are two short configuration examples for the I2S driver. +.. only:: SOC_I2S_SUPPORTS_ADC or SOC_I2S_SUPPORTS_DAC + In addition, there are two short configuration examples for the I2S driver. + +.. only:: not SOC_I2S_SUPPORTS_ADC or SOC_I2S_SUPPORTS_DAC + + In addition, there is a short configuration examples for the I2S driver. I2S configuration ^^^^^^^^^^^^^^^^^ -.. code-block:: c +Example for general usage. - #include "driver/i2s.h" - #include "freertos/queue.h" +.. only:: not SOC_I2S_SUPPORTS_TDM - static const int i2s_num = 0; // i2s port number + .. code-block:: c - static const i2s_config_t i2s_config = { - .mode = I2S_MODE_MASTER | I2S_MODE_TX, - .sample_rate = 44100, - .bits_per_sample = 16, - .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, - .communication_format = I2S_COMM_FORMAT_STAND_I2S, - .intr_alloc_flags = 0, // default interrupt priority - .dma_buf_count = 8, - .dma_buf_len = 64, - .use_apll = false - }; + #include "driver/i2s.h" - static const i2s_pin_config_t pin_config = { - .bck_io_num = 26, - .ws_io_num = 25, - .data_out_num = 22, - .data_in_num = I2S_PIN_NO_CHANGE - }; + static const int i2s_num = 0; // i2s port number - ... + i2s_config_t i2s_config = { + .mode = I2S_MODE_MASTER | I2S_MODE_TX, + .sample_rate = 44100, + .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, + .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, + .communication_format = I2S_COMM_FORMAT_STAND_I2S + .tx_desc_auto_clear = false, + .dma_buf_count = 8, + .dma_buf_len = 64, + .use_apll = false, + .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 // Interrupt level 1, default 0 + }; + + static const i2s_pin_config_t pin_config = { + .bck_io_num = 4, + .ws_io_num = 5, + .data_out_num = 18, + .data_in_num = I2S_PIN_NO_CHANGE + }; i2s_driver_install(i2s_num, &i2s_config, 0, NULL); //install and start i2s driver - i2s_set_pin(i2s_num, &pin_config); - i2s_set_sample_rates(i2s_num, 22050); //set sample rates + ... + /* You can reset parameters by calling 'i2s_set_clk' + * + * The low 16 bits are the valid data bits in one chan and the high 16 bits are + * the total bits in one chan. If high 16 bits is smaller than low 16 bits, it will + * be set to a same value as low 16 bits. + */ + uint32_t bits_cfg = (I2S_BITS_PER_CHAN_32BIT << 16) | I2S_BITS_PER_SAMPLE_16BIT; + i2s_set_clk(i2s_num, 22050, bits_cfg, I2S_CHANNEL_STEREO); + ... i2s_driver_uninstall(i2s_num); //stop & destroy i2s driver +.. only:: SOC_I2S_SUPPORTS_TDM -Configuring I2S to use internal DAC for analog output -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + .. code-block:: c -.. code-block:: c + #include "driver/i2s.h" - #include "driver/i2s.h" - #include "freertos/queue.h" + static const int i2s_num = 0; // i2s port number - static const int i2s_num = 0; // i2s port number + i2s_config_t i2s_config = { + .mode = I2S_MODE_MASTER | I2S_MODE_TX, + .sample_rate = 44100, + .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, + .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, + .communication_format = I2S_COMM_FORMAT_STAND_I2S + .tx_desc_auto_clear = false, + .dma_buf_count = 8, + .dma_buf_len = 64 + }; - static const i2s_config_t i2s_config = { - .mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN, - .sample_rate = 44100, - .bits_per_sample = 16, /* the DAC module will only take the 8bits from MSB */ - .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, - .intr_alloc_flags = 0, // default interrupt priority - .dma_buf_count = 8, - .dma_buf_len = 64, - .use_apll = false - }; - - ... + static const i2s_pin_config_t pin_config = { + .bck_io_num = 4, + .ws_io_num = 5, + .data_out_num = 18, + .data_in_num = I2S_PIN_NO_CHANGE + }; i2s_driver_install(i2s_num, &i2s_config, 0, NULL); //install and start i2s driver + i2s_set_pin(i2s_num, &pin_config); - i2s_set_pin(i2s_num, NULL); //for internal DAC, this will enable both of the internal channels - - //You can call i2s_set_dac_mode to set built-in DAC output mode. - //i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN); - - i2s_set_sample_rates(i2s_num, 22050); //set sample rates + ... + /* You can reset parameters by calling 'i2s_set_clk' + * + * The low 16 bits are the valid data bits in one chan and the high 16 bits are + * the total bits in one chan. If high 16 bits is smaller than low 16 bits, it will + * be set to a same value as low 16 bits. + */ + uint32_t bits_cfg = (I2S_BITS_PER_CHAN_32BIT << 16) | I2S_BITS_PER_SAMPLE_16BIT; + i2s_set_clk(i2s_num, 22050, bits_cfg, I2S_CHANNEL_STEREO); + ... i2s_driver_uninstall(i2s_num); //stop & destroy i2s driver + I2S on {IDF_TARGET_NAME} support TDM mode, up to 16 channels are available in TDM mode. If you want to use TDM mode, set field ``channel_format`` of :cpp:type:`i2s_config_t` to ``I2S_CHANNEL_FMT_MULTIPLE``. Then enable the channels by setting ``chan_mask`` using masks in :cpp:type:`i2s_channel_t`, the number of active channels and total channels will be calculate automatically. Also you can set a particular total channel number for it, but it shouldn't be smaller than the largest channel you use. + + If active channels are discrete, the inactive channels within total channels will be filled by a constant automatically. But if ``skip_msk`` is enabled, these inactive channels will be skiped. + + .. code-block:: c + + #include "driver/i2s.h" + + static const int i2s_num = 0; // i2s port number + + i2s_config_t i2s_config = { + .mode = I2S_MODE_MASTER | I2S_MODE_TX, + .sample_rate = 44100, + .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, + .channel_format = I2S_CHANNEL_FMT_MULTIPLE, + .communication_format = I2S_COMM_FORMAT_STAND_I2S + .tx_desc_auto_clear = false, + .dma_buf_count = 8, + .dma_buf_len = 64, + .chan_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH2 + }; + + static const i2s_pin_config_t pin_config = { + .bck_io_num = 4, + .ws_io_num = 5, + .data_out_num = 18, + .data_in_num = I2S_PIN_NO_CHANGE + }; + + i2s_driver_install(i2s_num, &i2s_config, 0, NULL); //install and start i2s driver + i2s_set_pin(i2s_num, &pin_config); + + ... + /* You can reset parameters by calling 'i2s_set_clk' + * + * The low 16 bits are the valid data bits in one chan and the high 16 bits are + * the total bits in one chan. If high 16 bits is smaller than low 16 bits, it will + * be set to a same value as low 16 bits. + */ + uint32_t bits_cfg = (I2S_BITS_PER_CHAN_32BIT << 16) | I2S_BITS_PER_SAMPLE_16BIT; + i2s_set_clk(i2s_port_t i2s_num, 22050, bits_cfg, I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1); // set clock + ... + + i2s_driver_uninstall(i2s_num); //stop & destroy i2s driver + +.. only:: SOC_I2S_SUPPORTS_ADC or SOC_I2S_SUPPORTS_DAC + + Configuring I2S to use internal DAC for analog output + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + .. code-block:: c + + #include "driver/i2s.h" + #include "freertos/queue.h" + + static const int i2s_num = 0; // i2s port number + + static const i2s_config_t i2s_config = { + .mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN, + .sample_rate = 44100, + .bits_per_sample = 16, /* the DAC module will only take the 8bits from MSB */ + .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, + .intr_alloc_flags = 0, // default interrupt priority + .dma_buf_count = 8, + .dma_buf_len = 64, + .use_apll = false + }; + + ... + + i2s_driver_install(i2s_num, &i2s_config, 0, NULL); //install and start i2s driver + + i2s_set_pin(i2s_num, NULL); //for internal DAC, this will enable both of the internal channels + + //You can call i2s_set_dac_mode to set built-in DAC output mode. + //i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN); + + i2s_set_sample_rates(i2s_num, 22050); //set sample rates + + i2s_driver_uninstall(i2s_num); //stop & destroy i2s driver + API Reference ------------- diff --git a/docs/en/api-reference/peripherals/index.rst b/docs/en/api-reference/peripherals/index.rst index d52fbd8e7f..730983ee9d 100644 --- a/docs/en/api-reference/peripherals/index.rst +++ b/docs/en/api-reference/peripherals/index.rst @@ -6,33 +6,34 @@ Peripherals API .. toctree:: :maxdepth: 1 - ADC - :SOC_DAC_SUPPORTED: DAC - General Purpose Timer - GPIO (including RTC low power I/O) - :SOC_DEDICATED_GPIO_SUPPORTED: Dedicated GPIO - :SOC_HMAC_SUPPORTED: HMAC - :SOC_DIG_SIGN_SUPPORTED: Digital Signature - I2C - I2S - LED Control - :SOC_MCPWM_SUPPORTED: MCPWM - :SOC_PCNT_SUPPORTED: Pulse Counter - Remote Control - :esp32 or esp32s3: SD Pull-up Requirements - :SOC_SDMMC_HOST_SUPPORTED: SDMMC Host - SD SPI Host - :SOC_SDIO_SLAVE_SUPPORTED: SDIO Slave - Sigma-delta Modulation - SPI Master - SPI Slave - :esp32: Secure Element - :esp32s2: SPI Slave Half Duplex - :SOC_TEMP_SENSOR_SUPPORTED: Temp sensor - :SOC_TOUCH_SENSOR_NUM: Touch Sensor - :esp32s2: Touch Element - TWAI - UART - :SOC_USB_OTG_SUPPORTED: USB Device + adc + :SOC_DAC_SUPPORTED: dac + timer + gpio + :SOC_DEDICATED_GPIO_SUPPORTED: dedic_gpio + :SOC_HMAC_SUPPORTED: hmac + :SOC_DIG_SIGN_SUPPORTED: ds + i2c + i2s + ledc + :SOC_MCPWM_SUPPORTED: mcpwm + :SOC_PCNT_SUPPORTED: pcnt + rmt + :esp32 or esp32s3: sd_pullup_requirements + :SOC_SDMMC_HOST_SUPPORTED: sdmmc_host + sdspi_host + :SOC_SDIO_SLAVE_SUPPORTED: sdio_slave + sigmadelta + spi_master + spi_slave + :esp32: secure_element + :esp32s2: spi_slave_hd + :SOC_TEMP_SENSOR_SUPPORTED: temp_sensor + :SOC_TOUCH_SENSOR_NUM: touch_pad + :esp32s2: touch_element + twai + uart + :SOC_USB_OTG_SUPPORTED: usb_device + :SOC_USB_OTG_SUPPORTED: usb_host Code examples for this API section are provided in the :example:`peripherals` directory of ESP-IDF examples. \ No newline at end of file diff --git a/docs/en/api-reference/peripherals/ledc.rst b/docs/en/api-reference/peripherals/ledc.rst index dcda4b7719..54d0fda5a4 100644 --- a/docs/en/api-reference/peripherals/ledc.rst +++ b/docs/en/api-reference/peripherals/ledc.rst @@ -1,5 +1,5 @@ -LED Control -=========== +LED Control (LEDC) +================== {IDF_TARGET_LEDC_CHAN_NUM:default="8", esp32="16", esp32s2="8", esp32c3="6"} :link_to_translation:`zh_CN:[中文]` @@ -201,4 +201,3 @@ API Reference .. include-build-file:: inc/ledc.inc .. include-build-file:: inc/ledc_types.inc - diff --git a/docs/en/api-reference/peripherals/mcpwm.rst b/docs/en/api-reference/peripherals/mcpwm.rst index 0e9234a144..eac872c950 100644 --- a/docs/en/api-reference/peripherals/mcpwm.rst +++ b/docs/en/api-reference/peripherals/mcpwm.rst @@ -1,5 +1,5 @@ -MCPWM -===== +Motor Control Pulse Width Modulator (MCPWM) +=========================================== {IDF_TARGET_NAME} has two MCPWM units which can be used to control different types of motors. Each unit has three pairs of PWM outputs. @@ -23,7 +23,7 @@ More detailed block diagram of the MCPWM unit is shown below. Each A/B pair may MCPWM Block Diagram -Description of this API starts with configuration of MCPWM's **Timer** and **Generator** submodules to provide the basic motor control functionality. Then it discusses more advanced submodules and functionalities of a **Fault Handler**, signal **Capture**, **Carrier** and **Interrupts**. +Description of this API starts with configuration of MCPWM's **Timer** and **Generator** submodules to provide the basic motor control functionality. Then it discusses more advanced submodules and functionalities of a **Fault Handler**, signal **Capture** and **Carrier**. Contents -------- @@ -31,10 +31,10 @@ Contents * `Configure`_ a basic functionality of the outputs * `Operate`_ the outputs to drive a motor * `Adjust`_ how the motor is driven +* `Synchronize`_ sync timers to work together * `Capture`_ external signals to provide additional control over the outputs * Use `Fault Handler`_ to detect and manage faults * Add a higher frequency `Carrier`_, if output signals are passed through an isolation transformer -* Configuration and handling of `Interrupts`_. * Extra configuration of `Resolution`_. @@ -85,15 +85,59 @@ There are couple of ways to adjust a signal on the outputs and changing how the * Set specific PWM frequency by calling :cpp:func:`mcpwm_set_frequency`. This may be required to adjust to electrical or mechanical characteristics of particular motor and driver. To check what frequency is set, use function :cpp:func:`mcpwm_get_frequency`. * Introduce a dead time between outputs A and B when they are changing the state to reverse direction of the motor rotation. This is to make up for on/off switching delay of the motor driver FETs. The dead time options are defined in :cpp:type:`mcpwm_deadtime_type_t` and enabled by calling :cpp:func:`mcpwm_deadtime_enable`. To disable this functionality call :cpp:func:`mcpwm_deadtime_disable`. -* Synchronize outputs of operator submodules, e.g. to get raising edge of PWM0A/B and PWM1A/B to start exactly at the same time, or shift them between each other by a given phase. Synchronization is triggered by ``SYNC SIGNALS`` shown on the :ref:`block diagram ` of the MCPWM above, and defined in :cpp:type:`mcpwm_sync_signal_t`. To attach the signal to a GPIO call :cpp:func:`mcpwm_gpio_init`. You can then enable synchronization with function :cpp:func:`mcpwm_sync_enable`. As input parameters provide MCPWM unit, timer to synchronize, the synchronization signal and a phase to delay the timer. +* Synchronize outputs of operator submodules, e.g. to get raising edge of PWM0A/B and PWM1A/B to start exactly at the same time, or shift them between each other by a given phase. Synchronization is triggered by ``SYNC SIGNALS`` shown on the :ref:`block diagram ` of the MCPWM above, and defined in :cpp:type:`mcpwm_sync_signal_t`. To attach the signal to a GPIO call :cpp:func:`mcpwm_gpio_init`. You can then enable synchronization with function :cpp:func:`mcpwm_sync_configure`. As input parameters provide MCPWM unit, timer to synchronize, the synchronization signal and a phase to delay the timer. .. note:: - Synchronization signals are referred to using two different enumerations. First one :cpp:type:`mcpwm_io_signals_t` is used together with function :cpp:func:`mcpwm_gpio_init` when selecting a GPIO as the signal input source. The second one :cpp:type:`mcpwm_sync_signal_t` is used when enabling or disabling synchronization with :cpp:func:`mcpwm_sync_enable` or :cpp:func:`mcpwm_sync_disable`. + Synchronization signals are referred to using two different enumerations. First one :cpp:type:`mcpwm_io_signals_t` is used together with function :cpp:func:`mcpwm_gpio_init` when selecting a GPIO as the signal input source. The second one :cpp:type:`mcpwm_sync_signal_t` is used when enabling or disabling synchronization with :cpp:func:`mcpwm_sync_configure` or :cpp:func:`mcpwm_sync_disable`. * Vary the pattern of the A/B output signals by getting MCPWM counters to count up, down and up/down (automatically changing the count direction). Respective configuration is done when calling :cpp:func:`mcpwm_init`, as discussed in section `Configure`_, and selecting one of counter types from :cpp:type:`mcpwm_counter_type_t`. For explanation of how A/B PWM output signals are generated, see *{IDF_TARGET_NAME} Technical Reference Manual* > *Motor Control PWM (MCPWM)* [`PDF <{IDF_TARGET_TRM_EN_URL}#mcpwm>`__]. + +Synchronize +----------- + +Each PWM timer has a synchronization input and a synchronization output. The synchronization input can be selected from other timers' synchronization outputs or GPIO signals via the GPIO matrix. Timer's synchronization signal can be generated from either the input sync signal or when the count value reaches peak/zero. Thus, the PWM timers can be chained together with their phase-locked. During synchronization, the PWM timer clock prescaler will reset its counter in order to synchronize the PWM timer clock. + +The functionality is enabled in following steps: + +1. Make sure the PWM timer and operator are already configured so that sync will inherit its config (count mode, freq and duty). +2. Enabling sync input of the timer by invoking :cpp:func:`mcpwm_sync_configure`, selecting desired signal input from :cpp:type:`mcpwm_sync_signal_t`, and setting the desired phase range from 0 to 999 which is mapped to 0%~99.9%. 0 means zero phase is applied and output is fired at the same time. And selecting desired counting direction. +3. Enabling one of sync event source from another timer or from external GPIO input. + +To sync with another timer: + +Enabling sync output of another timer by invoking :cpp:func:`mcpwm_set_timer_sync_output` and selecting desired event to generate sync output from :cpp:type:`mcpwm_timer_sync_trigger_t`. + +To sync with GPIO positive edge input (negative edge requires :cpp:func:`mcpwm_sync_invert_gpio_synchro`): + +Configuring GPIOs to act as the sync signal inputs by calling functions :cpp:func:`mcpwm_gpio_init` or :cpp:func:`mcpwm_set_pin`, which were described in section `Configure`_. + +It's normal condition that chained sync signal may have tens or even hundreds of nanoseconds of delay between each timer output due to hardware limitation. To sync two timers accurately it is required to have the third timer occupied to produce sync event that can be consumed parallel by other two timer, so that those two timer will have no delay between each other but have the same delay between the timer which provides events. Another solution is introducing an external GPIO event source so that all three timers can be synced together with no delay. + +.. only:: SOC_MCPWM_SWSYNC_CAN_PROPAGATE + + Software sync event which triggered on one timer can be propagated to other timers on {IDF_TARGET_NAME}, which can be used as a tricky way to get all three timers synced without any extra requirement. + + .. code-block:: c + + // configure timer0 as trigger source + mcpwm_set_timer_sync_output(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_SWSYNC_SOURCE_SYNCIN); + mcpwm_sync_config_t sync_conf = { + .sync_sig = MCPWM_SELECT_TIMER0_SYNC, + .timer_val = 0, + .count_direction = MCPWM_TIMER_DIRECTION_UP, + }; + mcpwm_sync_configure(TARGET_MCPWM_UNIT, MCPWM_TIMER_0, &sync_conf); + mcpwm_sync_configure(TARGET_MCPWM_UNIT, MCPWM_TIMER_1, &sync_conf); + mcpwm_sync_configure(TARGET_MCPWM_UNIT, MCPWM_TIMER_2, &sync_conf); + // then send soft sync event to timer0 + mcpwm_timer_trigger_soft_sync(MCPWM_UNIT_0, MCPWM_TIMER_0); + +If not required anymore, the capture functionality may be disabled with :cpp:func:`mcpwm_sync_disable`. + + Capture ------- @@ -109,11 +153,13 @@ One of requirements of BLDC (Brushless DC, see figure below) motor control is se The capture functionality may be used for other types of motors or tasks. The functionality is enabled in two steps: 1. Configuration of GPIOs to act as the capture signal inputs by calling functions :cpp:func:`mcpwm_gpio_init` or :cpp:func:`mcpwm_set_pin`, that were described in section `Configure`_. -2. Enabling of the functionality itself by invoking :cpp:func:`mcpwm_capture_enable`, selecting desired signal input from :cpp:type:`mcpwm_capture_signal_t`, setting the signal edge with :cpp:type:`mcpwm_capture_on_edge_t` and the signal count prescaler. +2. Enabling of the functionality itself by invoking :cpp:func:`mcpwm_capture_enable_channel`, selecting desired signal input from :cpp:type:`mcpwm_capture_channel_id_t`, setting the signal edge, signal count prescaler and user callback within :cpp:type:`mcpwm_capture_config_t` -Within the second step above a 32-bit capture timer is enabled. The timer runs continuously driven by the APB clock. The clock frequency is typically 80 MHz. On each capture event the capture timer’s value is stored in time-stamp register that may be then checked by calling :cpp:func:`mcpwm_capture_signal_get_value`. The edge of the last signal may be checked with :cpp:func:`mcpwm_capture_signal_get_edge`. +Within the second step above a 32-bit capture timer is enabled. The timer runs continuously driven by the APB clock. The clock frequency is typically 80 MHz. On each capture event the capture timer’s value is stored in time-stamp register that may be then checked by calling :cpp:func:`mcpwm_capture_signal_get_value`. The edge of the last signal may be checked with :cpp:func:`mcpwm_capture_signal_get_edge`. Those data are also provided inside callback function as event data :cpp:type:`cap_event_data_t` -If not required anymore, the capture functionality may be disabled with :cpp:func:`mcpwm_capture_disable`. +If not required anymore, the capture functionality may be disabled with :cpp:func:`mcpwm_capture_disable_channel`. + +Capture prescale is different from other modules as it is applied to the input signal, not the timer source. Prescaler has maintained its own level state with the initial value set to low and is detecting the positive edge of the input signal to change its internal state. That means if two pairs of positive and negative edges are passed to input, the prescaler's internal state will change twice. ISR will report on this internal state change, not the input signal. For example, setting prescale to 2 will generate ISR callback on each positive edge of input if both edge is selected via :cpp:type:`mcpwm_capture_config_t`. Or each 2 positive edges of input if only one edge is selected though :cpp:type:`mcpwm_capture_config_t`. Fault Handler @@ -158,7 +204,7 @@ To disable carrier functionality call :cpp:func:`mcpwm_carrier_disable`. Interrupts ---------- -Registering of the MCPWM interrupt handler is possible by calling :cpp:func:`mcpwm_isr_register`. +Registering of the MCPWM interrupt handler is possible by calling :cpp:func:`mcpwm_isr_register`. Note if :cpp:func:`mcpwm_capture_enable_channel` is used then a default ISR routine will be installed hence please do not call this function to register any more. Resolution @@ -171,15 +217,16 @@ Note that, these two APIs won't update the frequency and duty automatically, to To get PWM pulse that is below 15Hz, please set the resolution to a lower value. For high frequency PWM with limited step range, please set them with higher value. + Application Example ------------------- -Examples of using MCPWM for motor control: :example:`peripherals/mcpwm`: +MCPWM example are located under: :example:`peripherals/mcpwm`: -* Demonstration how to use each submodule of the MCPWM - :example:`peripherals/mcpwm/mcpwm_basic_config` -* Control of BLDC (brushless DC) motor with hall sensor feedback - :example:`peripherals/mcpwm/mcpwm_bldc_control` +* Control of BLDC (brushless DC) motor with hall sensor feedback - :example:`peripherals/mcpwm/mcpwm_bldc_hall_control` * Brushed DC motor control - :example:`peripherals/mcpwm/mcpwm_brushed_dc_control` * Servo motor control - :example:`peripherals/mcpwm/mcpwm_servo_control` +* HC-SR04 sensor with capture - :example:`peripherals/mcpwm/mcpwm_capture_hc_sr04` API Reference diff --git a/docs/en/api-reference/peripherals/pcnt.rst b/docs/en/api-reference/peripherals/pcnt.rst index 22433e8358..6cb0e81e2e 100644 --- a/docs/en/api-reference/peripherals/pcnt.rst +++ b/docs/en/api-reference/peripherals/pcnt.rst @@ -1,5 +1,5 @@ -Pulse Counter -============= +Pulse Counter (PCNT) +==================== {IDF_TARGET_PCNT_UNIT_NUM:default="8", esp32s2="4"} {IDF_TARGET_PCNT_MAX_UNIT_NUM:default="7", esp32s2="3"} diff --git a/docs/en/api-reference/peripherals/rmt.rst b/docs/en/api-reference/peripherals/rmt.rst index 35dd8c6f13..7495ebcee5 100644 --- a/docs/en/api-reference/peripherals/rmt.rst +++ b/docs/en/api-reference/peripherals/rmt.rst @@ -1,5 +1,5 @@ -RMT -=== +Remote Control (RMT) +==================== The RMT (Remote Control) module driver can be used to send and receive infrared remote control signals. Due to flexibility of RMT module, the driver can also be used to generate or receive many other types of signals. @@ -261,6 +261,11 @@ Transmit Mode Parameters * Binary level on the output to apply the carrier - :cpp:func:`rmt_set_tx_carrier`, selected from :cpp:type:`rmt_carrier_level_t` * Determines the binary level on the output when transmitter is idle - :cpp:func:`rmt_set_idle_level()`, selected from :cpp:type:`rmt_idle_level_t` +.. only:: SOC_RMT_SUPPORT_TX_LOOP_COUNT + + * Enable or disable loop count feature to automatically transmit items for N iterations, then trigger an ISR callback - :cpp:func:`rmt_set_tx_loop_count` + * Enable automatically stopping when the number of iterations matches the set loop count. Note this is not reliable for target that doesn't support `SOC_RMT_SUPPORT_TX_LOOP_AUTOSTOP`. - :cpp:func:`rmt_enable_tx_loop_autostop` + Receive Mode Parameters ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/en/api-reference/peripherals/spi_master.rst b/docs/en/api-reference/peripherals/spi_master.rst index 59cdbcdfec..2e6ffe15da 100644 --- a/docs/en/api-reference/peripherals/spi_master.rst +++ b/docs/en/api-reference/peripherals/spi_master.rst @@ -28,7 +28,7 @@ Overview of {IDF_TARGET_NAME}'s SPI peripherals - SPI2 and SPI3 are general purpose SPI controllers, sometimes referred to as HSPI and VSPI, respectively. They are open to users. SPI2 and SPI3 have independent bus signals with the same respective names. Each bus has three CS lines to drive up to same number of SPI slaves. -.. only:: esp32s2 +.. only:: esp32s2 or esp32s3 - SPI2 and SPI3 are general purpose SPI controllers. They are open to users. SPI2 and SPI3 have independent signal buses with the same respective names. SPI2 has {IDF_TARGET_SPI2_CS_NUM} CS lines. SPI3 has {IDF_TARGET_SPI3_CS_NUM} CS lines. Each CS line can be used to drive one SPI slave. @@ -47,12 +47,16 @@ Term Definition **Host** The SPI controller peripheral inside {IDF_TARGET_NAME} that initiates SPI transmissions over the bus, and acts as an SPI Master. **Device** SPI slave device. An SPI bus may be connected to one or more Devices. Each Device shares the MOSI, MISO and SCLK signals but is only active on the bus when the Host asserts the Device's individual CS line. **Bus** A signal bus, common to all Devices connected to one Host. In general, a bus includes the following lines: MISO, MOSI, SCLK, one or more CS lines, and, optionally, QUADWP and QUADHD. So Devices are connected to the same lines, with the exception that each Device has its own CS line. Several Devices can also share one CS line if connected in the daisy-chain manner. -**MISO** Master In, Slave Out, a.k.a. Q. Data transmission from a Device to Host. -**MOSI** Master Out, Slave In, a.k.a. D. Data transmission from a Host to Device. +**MOSI** Master Out, Slave In, a.k.a. D. Data transmission from a Host to Device. Also data0 signal in Octal/OPI mode. +**MISO** Master In, Slave Out, a.k.a. Q. Data transmission from a Device to Host. Also data1 signal in Octal/OPI mode. **SCLK** Serial Clock. Oscillating signal generated by a Host that keeps the transmission of data bits in sync. **CS** Chip Select. Allows a Host to select individual Device(s) connected to the bus in order to send or receive data. -**QUADWP** Write Protect signal. Only used for 4-bit (qio/qout) transactions. -**QUADHD** Hold signal. Only used for 4-bit (qio/qout) transactions. +**QUADWP** Write Protect signal. Used for 4-bit (qio/qout) transactions. Also for data2 signal in Octal/OPI mode. +**QUADHD** Hold signal. Used for 4-bit (qio/qout) transactions. Also for data3 signal in Octal/OPI mode. +**DATA4** Data4 signal in Octal/OPI mode. +**DATA5** Data5 signal in Octal/OPI mode. +**DATA6** Data6 signal in Octal/OPI mode. +**DATA7** Data7 signal in Octal/OPI mode. **Assertion** The action of activating a line. **De-assertion** The action of returning the line back to inactive (back to idle) status. **Transaction** One instance of a Host asserting a CS line, transferring data to and from a Device, and de-asserting the CS line. Transactions are atomic, which means they can never be interrupted by another transaction. @@ -144,6 +148,59 @@ All the tasks that use interrupt transactions can be blocked by the queue. At th The :cpp:func:`spi_device_polling_end` routine needs an overhead of at least 1 us to unblock other tasks when the transaction is finished. It is strongly recommended to wrap a series of polling transactions using the functions :cpp:func:`spi_device_acquire_bus` and :cpp:func:`spi_device_release_bus` to avoid the overhead. For more information, see :ref:`bus_acquiring`. +.. _transaction-line-mode: + +Transaction Line Mode +^^^^^^^^^^^^^^^^^^^^^ + +Supported line modes for {IDF_TARGET_NAME} are listed as follows, to make use of these modes, set the member `flags` in the struct :cpp:type:`spi_transaction_t` as shown in the `Transaction Flag` column. If you want to check if corresponding IO pins are set or not, set the member `flags` in the :cpp:type:`spi_bus_config_t` as shown in the `Bus IO setting Flag` column. + + +.. only:: not SOC_SPI_SUPPORT_OCT + + +--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+ + | Mode name | Command Line Width | Address Line Width | Data Line Width | Transaction Flag | Bus IO setting Flag | + +==============+====================+====================+=================+============================+=========================+ + | Normal SPI | 1 | 1 | 1 | 0 | 0 | + +--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+ + | Dual Output | 1 | 1 | 2 | SPI_TRANS_MODE_DIO | | + | | | | | | | + | | | | | | SPICOMMON_BUSFLAG_DUAL | + +--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+ + | Dual I/O | 1 | 2 | 2 | SPI_TRANS_MODE_DIO | | | + | | | | | SPI_TRANS_MULTILINE_ADDR | | + +--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+ + | Quad Output | 1 | 1 | 4 | SPI_TRANS_MODE_QIO | | + +--------------+--------------------+--------------------+-----------------+----------------------------+ | + | Quad I/O | 1 | 4 | 4 | SPI_TRANS_MODE_QIO | | SPICOMMON_BUSFLAG_QUAD | + | | | | | SPI_TRANS_MULTILINE_ADDR | | + +--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+ + +.. only:: SOC_SPI_SUPPORT_OCT + + +--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+ + | Mode name | Command Line Width | Address Line Width | Data Line Width | Transaction Flag | Bus IO setting Flag | + +==============+====================+====================+=================+============================+=========================+ + | Normal SPI | 1 | 1 | 1 | 0 | 0 | + +--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+ + | Dual Output | 1 | 1 | 2 | SPI_TRANS_MODE_DIO | | + | | | | | | | + | | | | | | SPICOMMON_BUSFLAG_DUAL | + +--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+ + | Dual I/O | 1 | 2 | 2 | SPI_TRANS_MODE_DIO | | | + | | | | | SPI_TRANS_MULTILINE_ADDR | | + +--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+ + | Quad Output | 1 | 1 | 4 | SPI_TRANS_MODE_QIO | | + +--------------+--------------------+--------------------+-----------------+----------------------------+ | + | Quad I/O | 1 | 4 | 4 | SPI_TRANS_MODE_QIO | | SPICOMMON_BUSFLAG_QUAD | + | | | | | SPI_TRANS_MULTILINE_ADDR | | + +--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+ + | Octal Output | 1 | 1 | 8 | SPI_TRANS_MODE_OCT | | + +--------------+--------------------+--------------------+-----------------+----------------------------+ | + | OPI | 8 | 8 | 8 | SPI_TRANS_MODE_OCT | | SPICOMMON_BUSFLAG_OCTAL | + | | | | | SPI_TRANS_MULTILINE_ADDR | | | + | | | | | SPI_TRANS_MULTILINE_CMD | | + +--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+ Command and Address Phases ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -152,6 +209,8 @@ During the command and address phases, the members :cpp:member:`cmd` and :cpp:me If the lengths of the command and address phases need to be variable, declare the struct :cpp:type:`spi_transaction_ext_t`, set the flags :cpp:type:`SPI_TRANS_VARIABLE_CMD` and/or :cpp:type:`SPI_TRANS_VARIABLE_ADDR` in the member :cpp:member:`spi_transaction_ext_t::base` and configure the rest of base as usual. Then the length of each phase will be equal to :cpp:member:`command_bits` and :cpp:member:`address_bits` set in the struct :cpp:type:`spi_transaction_ext_t`. +If the command and address phase need to be as the same number of lines as data phase, you need to set `SPI_TRANS_MULTILINE_CMD` and/or `SPI_TRANS_MULTILINE_ADDR` to the `flags` member in the struct :cpp:type:`spi_transaction_t`. Also see :ref:`transaction-line-mode`. + Write and Read Phases ^^^^^^^^^^^^^^^^^^^^^ @@ -163,6 +222,8 @@ Normally, the data that needs to be transferred to or from a Device will be read If these requirements are not satisfied, the transaction efficiency will be affected due to the allocation and copying of temporary buffers. +If using more than one data lines to transmit, please set `SPI_DEVICE_HALFDUPLEX` flag for the member `flags` in the struct :cpp:type:`spi_device_interface_config_t`. And the member `flags` in the struct :cpp:type:`spi_transaction_t` should be set as described in :ref:`transaction-line-mode`. + .. only:: esp32 .. note:: @@ -378,10 +439,10 @@ The main parameter that determines the transfer speed for large transactions is Transaction Duration ^^^^^^^^^^^^^^^^^^^^ -{IDF_TARGET_TRANS_TIME_INTR_DMA:default="28", esp32="28", esp32s2="23", esp32c3="28"} -{IDF_TARGET_TRANS_TIME_POLL_DMA:default="10", esp32="10", esp32s2="9", esp32c3="10"} -{IDF_TARGET_TRANS_TIME_INTR_CPU:default="25", esp32="25", esp32s2="22", esp32c3="27"} -{IDF_TARGET_TRANS_TIME_POLL_CPU:default="8", esp32="8", esp32s2="8", esp32c3="9"} +{IDF_TARGET_TRANS_TIME_INTR_DMA:default="28", esp32="28", esp32s2="23", esp32c3="28", esp32s3="26"} +{IDF_TARGET_TRANS_TIME_POLL_DMA:default="10", esp32="10", esp32s2="9", esp32c3="10", esp32s3="11"} +{IDF_TARGET_TRANS_TIME_INTR_CPU:default="25", esp32="25", esp32s2="22", esp32c3="27", esp32s3="24"} +{IDF_TARGET_TRANS_TIME_POLL_CPU:default="8", esp32="8", esp32s2="8", esp32c3="9", esp32s3="9"} Transaction duration includes setting up SPI peripheral registers, copying data to FIFOs or setting up DMA links, and the time for SPI transaction. diff --git a/docs/en/api-reference/peripherals/spi_slave.rst b/docs/en/api-reference/peripherals/spi_slave.rst index f574ec2395..9eac56573e 100644 --- a/docs/en/api-reference/peripherals/spi_slave.rst +++ b/docs/en/api-reference/peripherals/spi_slave.rst @@ -7,7 +7,7 @@ SPI Slave driver is a program that controls {IDF_TARGET_NAME}'s SPI peripherals Overview of {IDF_TARGET_NAME}'s SPI peripherals ----------------------------------------------- -.. only:: esp32 or esp32s2 +.. only:: esp32 or esp32s2 or esp32s3 {IDF_TARGET_NAME} integrates two general purpose SPI controllers which can be used as slave nodes driven by an off-chip SPI master @@ -158,7 +158,7 @@ You can also configure a GPIO pin through which the Device will signal to the Ho SCLK Frequency Requirements ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -{IDF_TARGET_MAX_FREQ:default="40", esp32="10", esp32s2="40", esp32c3="60"} +{IDF_TARGET_MAX_FREQ:default="40", esp32="10", esp32s2="40", esp32c3="60", esp32s3="60} The SPI slaves are designed to operate at up to {IDF_TARGET_MAX_FREQ} MHz. The data cannot be recognized or received correctly if the clock is too fast or does not have a 50% duty cycle. @@ -216,4 +216,3 @@ API Reference ------------- .. include-build-file:: inc/spi_slave.inc - diff --git a/docs/en/api-reference/peripherals/temp_sensor.rst b/docs/en/api-reference/peripherals/temp_sensor.rst index c77de66b57..a9e9fcb1be 100644 --- a/docs/en/api-reference/peripherals/temp_sensor.rst +++ b/docs/en/api-reference/peripherals/temp_sensor.rst @@ -1,5 +1,5 @@ Temperature Sensor -================== +=================== Overview -------- diff --git a/docs/en/api-reference/peripherals/timer.rst b/docs/en/api-reference/peripherals/timer.rst index 6118321e65..1868514e59 100644 --- a/docs/en/api-reference/peripherals/timer.rst +++ b/docs/en/api-reference/peripherals/timer.rst @@ -35,8 +35,8 @@ First of all, the timer should be initialized by calling the function :cpp:func: .. list:: - :not esp32: - **Clock Source**: Select the clock source, which together with the **Divider** define the resolution of the working timer. By default the clock source is APB_CLK (typically 80 MHz). - - **Divider**: Sets how quickly the timer's counter is "ticking". The setting :cpp:member:`divider` is used as a divisor of the clock source. + :not esp32: - **Clock Source**: Select the clock source, which together with the **Divider** define the resolution of the working timer. + - **Divider**: Sets how quickly the timer's counter is "ticking". The setting :cpp:member:`divider` is used as a divisor of the clock source that by default is APB_CLK running at 80 MHz. For more information of APB_CLK frequency, please check *{IDF_TARGET_NAME} Technical Reference Manual* > *Reset and Clock* [`PDF <{IDF_TARGET_TRM_EN_URL}#resclk>`__] chapter for more details. - **Mode**: Sets if the counter should be incrementing or decrementing. It can be defined using :cpp:member:`counter_dir` by selecting one of the values from :cpp:type:`timer_count_dir_t`. - **Counter Enable**: If the counter is enabled, it will start incrementing / decrementing immediately after calling :cpp:func:`timer_init`. You can change the behavior with :cpp:member:`counter_en` by selecting one of the values from :cpp:type:`timer_start_t`. - **Alarm Enable**: Can be set using :cpp:member:`alarm_en`. diff --git a/docs/en/api-reference/peripherals/twai.rst b/docs/en/api-reference/peripherals/twai.rst index 617cc06183..676106dece 100644 --- a/docs/en/api-reference/peripherals/twai.rst +++ b/docs/en/api-reference/peripherals/twai.rst @@ -1,5 +1,5 @@ -TWAI -==== +Two-Wire Automotive Interface (TWAI) +==================================== .. -------------------------------- Overview ----------------------------------- @@ -124,6 +124,8 @@ The TWAI driver contains an alert feature that is used to notify the application - No more messages queued for transmission * - ``TWAI_ALERT_TX_SUCCESS`` - The previous transmission was successful + * - ``TWAI_ALERT_RX_DATA`` + - A frame has been received and added to the RX queue * - ``TWAI_ALERT_BELOW_ERR_WARN`` - Both error counters have dropped below error warning limit * - ``TWAI_ALERT_ERR_ACTIVE`` diff --git a/docs/en/api-reference/peripherals/uart.rst b/docs/en/api-reference/peripherals/uart.rst index fc18adfe42..57016cedbe 100644 --- a/docs/en/api-reference/peripherals/uart.rst +++ b/docs/en/api-reference/peripherals/uart.rst @@ -1,5 +1,5 @@ -UART -==== +Universal Asynchronous Receiver/Transmitter (UART) +================================================== {IDF_TARGET_UART_NUM:default = "UART_NUM_1", esp32 = "UART_NUM_2", esp32s3 = "UART_NUM_2"} diff --git a/docs/en/api-reference/peripherals/usb_host.rst b/docs/en/api-reference/peripherals/usb_host.rst new file mode 100644 index 0000000000..91a2ae44d1 --- /dev/null +++ b/docs/en/api-reference/peripherals/usb_host.rst @@ -0,0 +1,26 @@ +USB Host +======== + +.. warning:: + The USB Host Library API is a beta version thus is subject to change. + +The following document lists the API and types of the USB Host Library (that is currently under development). + +API Reference +------------- + +The API of the USB Host Library is separated into the following header files. However, it is sufficient for applications to only ``#include "usb/usb_host.h"`` and all of USB Host Library headers will also be included. + +- :component_file:`usb/include/usb/usb_host.h` contains the functions and types of the USB Host Library +- :component_file:`usb/include/usb/usb_helpers.h` contains various helper functions that are related to the USB protocol such as descriptor parsing. +- :component_file:`usb/include/usb/usb_types_stack.h` contains types that are are used across multiple layers of the USB Host stack. +- :component_file:`usb/include/usb/usb_types_ch9.h` contains types and macros related to Chapter 9 of the USB2.0 specification (i.e., descriptors and standard requests). + + +.. include-build-file:: inc/usb_host.inc + +.. include-build-file:: inc/usb_helpers.inc + +.. include-build-file:: inc/usb_types_stack.inc + +.. include-build-file:: inc/usb_types_ch9.inc diff --git a/docs/en/api-reference/protocols/asio.rst b/docs/en/api-reference/protocols/asio.rst index 559759e9e0..0306a5ae1c 100644 --- a/docs/en/api-reference/protocols/asio.rst +++ b/docs/en/api-reference/protocols/asio.rst @@ -36,8 +36,7 @@ ESP examples are based on standard asio :example:`protocols/asio`: - :example:`protocols/asio/udp_echo_server` - :example:`protocols/asio/tcp_echo_server` -- :example:`protocols/asio/chat_client` -- :example:`protocols/asio/chat_server` +- :example:`protocols/asio/asio_chat` - :example:`protocols/asio/ssl_client_server` Please refer to the specific example README.md for details diff --git a/docs/en/api-reference/protocols/esp_local_ctrl.rst b/docs/en/api-reference/protocols/esp_local_ctrl.rst index 01df8a40a9..436c0753fe 100644 --- a/docs/en/api-reference/protocols/esp_local_ctrl.rst +++ b/docs/en/api-reference/protocols/esp_local_ctrl.rst @@ -24,6 +24,11 @@ Initialization of the **esp_local_ctrl** service over BLE transport is performed } } }, + .proto_sec = { + .version = PROTOCOM_SEC0, + .custom_handle = NULL, + .pop = NULL, + }, .handlers = { /* User defined handler functions */ .get_prop_values = get_property_values, @@ -65,6 +70,11 @@ Similarly for HTTPS transport: .transport_config = { .httpd = &https_conf }, + .proto_sec = { + .version = PROTOCOM_SEC0, + .custom_handle = NULL, + .pop = NULL, + }, .handlers = { /* User defined handler functions */ .get_prop_values = get_property_values, @@ -79,6 +89,11 @@ Similarly for HTTPS transport: /* Start esp_local_ctrl service */ ESP_ERROR_CHECK(esp_local_ctrl_start(&config)); +You may set security for transport in ESP local control using following options: + +1. `PROTOCOM_SEC1`: specifies that end to end encryption is used. +2. `PROTOCOM_SEC0`: specifies that data will be exchanged as a plain text. +3. `PROTOCOM_SEC_CUSTOM`: you can define your own security requirement. Please note that you will also have to provide `custom_handle` of type `protocomm_security_t *` in this context. Creating a property ------------------- diff --git a/docs/en/api-reference/protocols/esp_spi_slave_protocol.rst b/docs/en/api-reference/protocols/esp_spi_slave_protocol.rst index 608a714ba9..fd41922fc8 100644 --- a/docs/en/api-reference/protocols/esp_spi_slave_protocol.rst +++ b/docs/en/api-reference/protocols/esp_spi_slave_protocol.rst @@ -31,7 +31,7 @@ Introduction ------------ In the half duplex mode, the master has to use the protocol defined by the slave to communicate -with the slave. Each transaction may consists of the following phases (list by the order they +with the slave. Each transaction may consist of the following phases (list by the order they should exist): - Command: 8-bit, master to slave diff --git a/docs/en/api-reference/protocols/modbus.rst b/docs/en/api-reference/protocols/modbus.rst index aea7ad9b3e..c646147431 100644 --- a/docs/en/api-reference/protocols/modbus.rst +++ b/docs/en/api-reference/protocols/modbus.rst @@ -4,7 +4,6 @@ ESP-Modbus Overview -------- - The Modbus serial communication protocol is de facto standard protocol widely used to connect industrial electronic devices. Modbus allows communication among many devices connected to the same network, for example, a system that measures temperature and humidity and communicates the results to a computer. The Modbus protocol uses several types of data: Holding Registers, Input Registers, Coils (single bit output), Discrete Inputs. Versions of the Modbus protocol exist for serial port and for Ethernet and other protocols that support the Internet protocol suite. There are many variants of Modbus protocols, some of them are: @@ -13,115 +12,651 @@ There are many variants of Modbus protocols, some of them are: * ``Modbus ASCII`` — This is used in serial communication and makes use of ASCII characters for protocol communication. The ASCII format uses a longitudinal redundancy check checksum. Modbus ASCII messages are framed by leading colon (":") and trailing newline (CR/LF). * ``Modbus TCP/IP or Modbus TCP`` — This is a Modbus variant used for communications over TCP/IP networks, connecting over port 502. It does not require a checksum calculation, as lower layers already provide checksum protection. +The following document (and included code snippets) requires some familiarity with the Modbus protocol. Refer to the Modbus Organization's with protocol specifications for specifics. -Modbus port specific API overview -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Messaging Model And Data Mapping +-------------------------------- +Modbus is an application protocol that defines rules for messaging structure and data organization that are independent of the data transmission medium. Traditional serial Modbus is a register-based protocol that defines message transactions that occur between master(s) and slave devices (multiple masters are allowed on using Modbus TCP/IP). The slave devices listen for communication from the master and simply respond as instructed. The master(s) always controls communication and may communicate directly to one slave, or all connected slaves, but the slaves cannot communicate directly with each other. -ESP-IDF supports Modbus Serial/TCP slave and master protocol stacks (port) and provides Modbus controller interface API to interact with user application. +.. figure:: ../../../_static/modbus-segment.png + :align: center + :scale: 80% + :alt: Modbus segment diagram + :figclass: align-center -The functions below are used to create and then initialize actual Modbus controller interface for Serial/TCP port accordingly: + Modbus segment diagram -.. doxygenfunction:: mbc_slave_init -.. doxygenfunction:: mbc_master_init -.. doxygenfunction:: mbc_slave_init_tcp -.. doxygenfunction:: mbc_master_init_tcp +.. note:: It is assumed that the number of slaves and their register maps are known by the Modbus master before the start of stack. +The register map of each slave device is usually part of its device manual. A Slave device usually permits configuration of its short slave address and communication options that are used within the device's network segment. -Modbus common interface API overview -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The Modbus protocol allows devices to map data to four types of registers (Holding, Input, Discrete, Coil). The figure below illustrates an example mapping of a device's data to the four types of registers. +.. figure:: ../../../_static/modbus-data-mapping.png + :align: center + :scale: 80% + :alt: Modbus data mapping + :figclass: align-center -The function initializes the Modbus controller interface and its active context (tasks, RTOS objects and other resources). + Modbus data mapping -.. doxygenfunction:: mbc_slave_setup -.. doxygenfunction:: mbc_master_setup +The following sections give an overview of how to use the ESP_Modbus component found under `components/freemodbus`. The sections cover initialization of a Modbus port, and the setup a master or slave device accordingly: -The function is used to setup communication parameters of the Modbus stack. See the Modbus controller API documentation for more information. -Note: The communication structure provided as a parameter is different for serial and TCP communication mode. +- :ref:`modbus_api_port_initialization` +- :ref:`modbus_api_slave_overview` +- :ref:`modbus_api_master_overview` -:cpp:func:`mbc_slave_set_descriptor`: Initialization of slave descriptor. +.. _modbus_api_port_initialization: + +Modbus Port Initialization +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The ESP_Modbus supports Modbus SERIAL and TCP ports and a port must be initialized before calling any other Modbus API. The functions below are used to create and then initialize Modbus controller interface (either master or slave) over a particular transmission medium (either Serial or TCP/IP): + +- :cpp:func:`mbc_slave_init` +- :cpp:func:`mbc_master_init` +- :cpp:func:`mbc_slave_init_tcp` +- :cpp:func:`mbc_master_init_tcp` + +The API call uses the first parameter to recognize the type of port being initialized. Supported enumeration for different ports: :cpp:enumerator:`MB_PORT_SERIAL_MASTER`, :cpp:enumerator:`MB_PORT_SERIAL_SLAVE` accordingly. +The parameters :cpp:enumerator:`MB_PORT_TCP_MASTER`, :cpp:enumerator:`MB_PORT_TCP_SLAVE` are reserved for internal usage. + +.. code:: c + + void* master_handler = NULL; // Pointer to allocate interface structure + // Initialization of Modbus master for serial port + esp_err_t err = mbc_master_init(MB_PORT_SERIAL_MASTER, &master_handler); + if (master_handler == NULL || err != ESP_OK) { + ESP_LOGE(TAG, "mb controller initialization fail."); + } + +This example code to initialize slave port: + +.. code:: c + + void* slave_handler = NULL; // Pointer to allocate interface structure + // Initialization of Modbus slave for TCP + esp_err_t err = mbc_slave_init_tcp(&slave_handler); + if (slave_handler == NULL || err != ESP_OK) { + // Error handling is performed here + ESP_LOGE(TAG, "mb controller initialization fail."); + } + +.. _modbus_api_master_overview: + +Modbus Master API Overview +-------------------------- + +The following overview describes how to setup Modbus master communication. The overview reflects a typical programming workflow and is broken down into the sections provided below: + +1. :ref:`modbus_api_port_initialization` - Initialization of Modbus controller interface for the selected port. +2. :ref:`modbus_api_master_configure_descriptor` - Configure data descriptors to access slave parameters. +3. :ref:`modbus_api_master_setup_communication_options` - Allows to setup communication options for selected port. +4. :ref:`modbus_api_master_start_communication` - Start stack and sending / receiving data. +5. :ref:`modbus_api_master_destroy` - Destroy Modbus controller and its resources. + +.. _modbus_api_master_configure_descriptor: + +Configuring Master Data Access +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The architectural approach of ESP_Modbus includes one level above standard Modbus IO driver. +The additional layer is called Modbus controller and its goal is to add an abstraction such as CID - characteristic identifier. +The CID is linked to a corresponding Modbus registers through the table called Data Dictionary and represents device physical parameter (such as temperature, humidity, etc.) in specific Modbus slave device. +This approach allows the upper layer (e.g., MESH or MQTT) to be isolated from Modbus specifics thus simplify Modbus integration with other protocols/networks. + +The Data Dictionary is the list in the Modbus master which shall be defined by user to link each CID to its corresponding Modbus registers representation using Register Mapping table of the Modbus slave being used. +Each element in this data dictionary is of type :cpp:type:`mb_parameter_descriptor_t` and represents the description of one physical characteristic: + +.. list-table:: Table 1 Modbus master Data Dictionary description + :widths: 8 10 82 + :header-rows: 1 + + * - Field + - Description + - Detailed information + * - ``cid`` + - Characteristic ID + - The identifier of characteristic (must be unique). + * - ``param_key`` + - Characteristic Name + - String description of the characteristic. + * - ``param_units`` + - Characteristic Units + - Physical Units of the characteristic. + * - ``mb_slave_addr`` + - Modbus Slave Address + - The short address of the device with correspond parameter UID. + * - ``mb_param_type`` + - Modbus Register Type + - Type of Modbus register area. + :cpp:enumerator:`MB_PARAM_INPUT`, :cpp:enumerator:`MB_PARAM_HOLDING`, :cpp:enumerator:`MB_PARAM_COIL`, :cpp:enumerator:`MB_PARAM_DISCRETE` - represents Input , Holding, Coil and Discrete input register area accordingly; + * - ``mb_reg_start`` + - Modbus Register Start + - Relative register address of the characteristic in the register area. + * - ``mb_size`` + - Modbus Register Size + - Length of characteristic in registers. + * - ``param_offset`` + - Instance Offset + - Offset to instance of the characteristic in bytes. It is used to calculate the absolute address to the characteristic in the storage structure. + It is optional field and can be set to zero if the parameter is not used in the application. + * - ``param_type`` + - Data Type + - Specifies type of the characteristic. + :cpp:enumerator:`PARAM_TYPE_U8`, :cpp:enumerator:`PARAM_TYPE_U16`, :cpp:enumerator:`PARAM_TYPE_U32` - Unsigned integer 8/16/32 bit type; + :cpp:enumerator:`PARAM_TYPE_FLOAT` - IEEE754 floating point format; + :cpp:enumerator:`PARAM_TYPE_ASCII` - ASCII string or binary data; + * - ``param_size`` + - Data Size + - The storage size of the characteristic (bytes). + * - ``param_opts`` + - Parameter Options + - Limits, options of characteristic used during processing of alarm in user application (optional) + * - ``access`` + - Parameter access type + - Can be used in user application to define the behavior of the characteristic during processing of data in user application; + :cpp:enumerator:`PAR_PERMS_READ_WRITE_TRIGGER`, :cpp:enumerator:`PAR_PERMS_READ`, :cpp:enumerator:`PAR_PERMS_READ_WRITE_TRIGGER`; + +.. note:: The ``cid`` and ``param_key`` have to be unique. Please use the prefix to the parameter key if you have several similar parameters in your register map table. + +.. list-table:: Table 2 Example Register mapping table of Modbus slave + :widths: 5 5 2 10 5 5 68 + :header-rows: 1 + + * - CID + - Register + - Length + - Range + - Type + - Units + - Description + * - 0 + - 30000 + - 4 + - MAX_UINT + - U32 + - Not defined + - Serial number of device (4 bytes) read-only + * - 1 + - 30002 + - 2 + - MAX_UINT + - U16 + - Not defined + - Software version (4 bytes) read-only + * - 2 + - 40000 + - 4 + - -20..40 + - FLOAT + - DegC + - Room temperature in DegC. Writing a temperature value to this register for single point calibration. + +.. code:: c + + // Enumeration of modbus slave addresses accessed by master device + enum { + MB_DEVICE_ADDR1 = 1, + MB_DEVICE_ADDR2, + MB_SLAVE_COUNT + }; + + // Enumeration of all supported CIDs for device + enum { + CID_SER_NUM1 = 0, + CID_SW_VER1, + CID_TEMP_DATA_1, + CID_SER_NUM2, + CID_SW_VER2, + CID_TEMP_DATA_2 + }; + + // Example Data Dictionary for Modbus parameters in 2 slaves in the segment + mb_parameter_descriptor_t device_parameters[] = { + // CID, Name, Units, Modbus addr, register type, Modbus Reg Start Addr, Modbus Reg read length, + // Instance offset (NA), Instance type, Instance length (bytes), Options (NA), Permissions + { CID_SER_NUM1, STR("Serial_number_1"), STR("--"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 0, 2, + 0, PARAM_TYPE_U32, 4, OPTS( 0,0,0 ), PAR_PERMS_READ_WRITE_TRIGGER }, + { CID_SW_VER1, STR("Software_version_1"), STR("--"), MB_DEVICE_ADDR1, MB_PARAM_INPUT, 2, 1, + 0, PARAM_TYPE_U16, 2, OPTS( 0,0,0 ), PAR_PERMS_READ_WRITE_TRIGGER }, + { CID_TEMP_DATA_1, STR("Temperature_1"), STR("C"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 0, 2, + 0, PARAM_TYPE_FLOAT, 4, OPTS( 16, 30, 1 ), PAR_PERMS_READ_WRITE_TRIGGER }, + { CID_SER_NUM2, STR("Serial_number_2"), STR("--"), MB_DEVICE_ADDR2, MB_PARAM_INPUT, 0, 2, + 0, PARAM_TYPE_U32, 4, OPTS( 0,0,0 ), PAR_PERMS_READ_WRITE_TRIGGER }, + { CID_SW_VER2, STR("Software_version_2"), STR("--"), MB_DEVICE_ADDR2, MB_PARAM_INPUT, 2, 1, + 0, PARAM_TYPE_U16, 2, OPTS( 0,0,0 ), PAR_PERMS_READ_WRITE_TRIGGER }, + { CID_TEMP_DATA_2, STR("Temperature_2"), STR("C"), MB_DEVICE_ADDR2, MB_PARAM_HOLDING, 0, 2, + 0, PARAM_TYPE_FLOAT, 4, OPTS( 20, 30, 1 ), PAR_PERMS_READ_WRITE_TRIGGER }, + }; + // Calculate number of parameters in the table + uint16_t num_device_parameters = (sizeof(device_parameters) / sizeof(device_parameters[0])); + +During initialization of the Modbus stack, a pointer to the Data Dictionary (called descriptor) must be provided as the parameter of the function below. :cpp:func:`mbc_master_set_descriptor`: Initialization of master descriptor. -The Modbus stack uses parameter description tables (descriptors) for communication. These are different for master and slave implementation of stack and should be assigned by the API call before start of communication. +.. code:: c -.. doxygenfunction:: mbc_slave_start -.. doxygenfunction:: mbc_master_start - -Modbus controller start function. Starts stack and interface and allows communication. - -.. doxygenfunction:: mbc_slave_destroy -.. doxygenfunction:: mbc_master_destroy - -This function stops Modbus communication stack and destroys controller interface. - -There are some configurable parameters of modbus_controller interface and Modbus stack that can be configured using KConfig values in "Modbus configuration" menu. The most important option in KConfig menu is "Enable Modbus stack support ..." for appropriate communication mode that allows to select master or slave stack for implementation. See the examples for more information about how to use these API functions. + ESP_ERROR_CHECK(mbc_master_set_descriptor(&device_parameters[0], num_device_parameters)); +The Data Dictionary can be initialized from SD card, MQTT or other source before start of stack. Once the initialization and setup is done, the Modbus controller allows the reading of complex parameters from any slave included in descriptor table using its CID. -Modbus slave interface API overview -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +.. _modbus_api_master_setup_communication_options: + +Master Communication Options +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Calling the setup function allows for specific communication options to be defined for port. + +:cpp:func:`mbc_master_setup` + +The communication structure provided as a parameter is different for serial and TCP communication mode. + +Example setup for serial port: + +.. code:: c + + mb_communication_info_t comm_info = { + .port = MB_PORT_NUM, // Serial port number + .mode = MB_MODE_RTU, // Modbus mode of communication (MB_MODE_RTU or MB_MODE_ASCII) + .baudrate = 9600, // Modbus communication baud rate + .parity = MB_PARITY_NONE // parity option for serial port + }; + + ESP_ERROR_CHECK(mbc_master_setup((void*)&comm_info)); + +Modbus master TCP port requires additional definition of IP address table where number of addresses should be equal to number of unique slave addresses in master Modbus Data Dictionary: + +The order of IP address string corresponds to short slave address in the Data Dictionary. + +.. code:: c + + #define MB_SLAVE_COUNT 2 // Number of slaves in the segment being accessed (as defined in Data Dictionary) + + char* slave_ip_address_table[MB_SLAVE_COUNT] = { + "192.168.1.2", // Address corresponds to UID1 and set to predefined value by user + "192.168.1.3", // corresponds to UID2 in the segment + NULL // end of table + }; + + mb_communication_info_t comm_info = { + .ip_port = MB_TCP_PORT, // Modbus TCP port number (default = 502) + .ip_addr_type = MB_IPV4, // version of IP protocol + .ip_mode = MB_MODE_TCP, // Port communication mode + .ip_addr = (void*)slave_ip_address_table, // assign table of IP addresses + .ip_netif_ptr = esp_netif_ptr // esp_netif_ptr pointer to the corresponding network interface + }; + + ESP_ERROR_CHECK(mbc_master_setup((void*)&comm_info)); + +.. note:: Refer to :doc:`esp_netif component <../network/esp_netif>` for more information about network interface initialization. + +The slave IP addresses in the table can be assigned automatically using mDNS service as described in the example. +Refer to :example:`protocols/modbus/tcp/mb_tcp_master` for more information. + +.. note:: RS485 communication requires call to UART specific APIs to setup communication mode and pins. Refer to :ref:`uart-api-running-uart-communication` section of UART documentation. -The slave stack requires the user defined structures which represent Modbus parameters accessed by stack. These structures should be prepared by user and be assigned to the modbus_controller interface using :cpp:func:`mbc_slave_set_descriptor()` API call before start of communication. -The interface API functions below are used for Modbus slave application: +.. _modbus_api_master_start_communication: -.. doxygenfunction:: mbc_slave_set_descriptor +Master Communication +^^^^^^^^^^^^^^^^^^^^ -The function initializes Modbus communication descriptors for each type of Modbus register area (Holding Registers, Input Registers, Coils (single bit output), Discrete Inputs). Once areas are initialized and the :cpp:func:`mbc_slave_start()` API is called the Modbus stack can access the data in user data structures by request from master. See the :cpp:type:`mb_register_area_descriptor_t` and example for more information. +The starting of the Modbus controller is the final step in enabling communication. This is performed using function below: -.. doxygenfunction:: mbc_slave_check_event +:cpp:func:`mbc_master_start` -The blocking call to function waits for event specified in the input parameter as event mask. Once master access the parameter and event mask matches the parameter the application task will be unblocked and function will return ESP_OK. See the :cpp:type:`mb_event_group_t` for more information about Modbus event masks. +.. code:: c + + esp_err_t err = mbc_master_start(); + if (err != ESP_OK) { + ESP_LOGE(TAG, "mb controller start fail, err=%x.", err); + } + +The list of functions below are used by the Modbus master stack from a user's application: -.. doxygenfunction:: mbc_slave_get_param_info +:cpp:func:`mbc_master_send_request`: This function executes a blocking Modbus request. The master sends a data request (as defined in parameter request structure :cpp:type:`mb_param_request_t`) and then blocks until a response from corresponding slave and returns the status of command execution. This function provides a standard way for read/write access to Modbus devices in the network. -The function gets information about accessed parameters from modbus controller event queue. The KConfig 'CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE' key can be used to configure the notification queue size. The timeout parameter allows to specify timeout for waiting notification. The :cpp:type:`mb_param_info_t` structure contain information about accessed parameter. +:cpp:func:`mbc_master_get_cid_info`: The function gets information about each characteristic supported in the data dictionary and returns the characteristic's description in the form of the :cpp:type:`mb_parameter_descriptor_t` structure. Each characteristic is accessed using its CID. + +:cpp:func:`mbc_master_get_parameter`: The function reads the data of a characteristic defined in the parameters of a Modbus slave device. The additional data for request is taken from parameter description table. + +Example: + +.. code:: c + + const mb_parameter_descriptor_t* param_descriptor = NULL; + uint8_t temp_data[4] = {0}; // temporary buffer to hold maximum CID size + uint8_t type = 0; + .... + + // Get the information for characteristic cid from data dictionary + esp_err_t err = mbc_master_get_cid_info(cid, ¶m_descriptor); + if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) { + err = mbc_master_get_parameter(param_descriptor->cid, (char*)param_descriptor->param_key, (uint8_t*)temp_data, &type); + if (err == ESP_OK) { + ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = (0x%08x) read successful.", + param_descriptor->cid, + (char*)param_descriptor->param_key, + (char*)param_descriptor->param_units, + *(uint32_t*)temp_data); + } else { + ESP_LOGE(TAG, "Characteristic #%d (%s) read fail, err = 0x%x (%s).", + param_descriptor->cid, + (char*)param_descriptor->param_key, + (int)err, + (char*)esp_err_to_name(err)); + } + } else { + ESP_LOGE(TAG, "Could not get information for characteristic %d.", cid); + } -Modbus master interface API overview -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - -The Modbus master implementation requires parameter description table be defined before start of stack. This table describes characteristics (physical parameters like temperature, humidity, etc.) and links them to Modbus registers in specific slave device in the Modbus segment. The table has to be assigned to the modbus_controller interface using :cpp:func:`mbc_master_set_descriptor()` API call before start of communication. - -Below are the interface API functions that are used to setup and use Modbus master stack from user application and can be executed in next order: - -.. doxygenfunction:: mbc_master_set_descriptor - -Assigns parameter description table for Modbus controller interface. The table has to be prepared by user according to particular implementation. -Note: TCP communication stack requires to setup additional information about modbus slaves that corresponds to each address(index) used in description table. This information with IP addresses of the slaves is assigned using communication structure and interface setup call. - -.. doxygenfunction:: mbc_master_send_request - -This function sends data request as defined in parameter request, waits response from corresponded slave and returns status of command execution. This function provides a standard way for read/write access to Modbus devices in the network. - -.. doxygenfunction:: mbc_master_get_cid_info - -The function gets information about supported characteristic defined as cid. It will check if characteristic is supported and returns its description. - -.. doxygenfunction:: mbc_master_get_parameter - -The function reads data of characteristic defined in parameters from Modbus slave device and returns its data. The additional data for request is taken from parameter description table. - -.. doxygenfunction:: mbc_master_set_parameter +:cpp:func:`mbc_master_set_parameter` The function writes characteristic's value defined as a name and cid parameter in corresponded slave device. The additional data for parameter request is taken from master parameter description table. +.. code:: c + + uint8_t type = 0; // Type of parameter + uint8_t temp_data[4] = {0}; // temporary buffer + + esp_err_t err = mbc_master_set_parameter(CID_TEMP_DATA_2, "Temperature_2", (uint8_t*)temp_data, &type); + if (err == ESP_OK) { + ESP_LOGI(TAG, "Set parameter data successfully."); + } else { + ESP_LOGE(TAG, "Set data fail, err = 0x%x (%s).", (int)err, (char*)esp_err_to_name(err)); + } + + +.. _modbus_api_master_destroy: + +Modbus Master Teardown +^^^^^^^^^^^^^^^^^^^^^^ + +This function stops Modbus communication stack and destroys controller interface and free all used active objects. + +:cpp:func:`mbc_master_destroy` + +.. code:: c + + ESP_ERROR_CHECK(mbc_master_destroy()); + + +.. _modbus_api_slave_overview: + +Modbus Slave API Overview +------------------------- + +The sections below represent typical programming workflow for the slave API which should be called in following order: + +1. :ref:`modbus_api_port_initialization` - Initialization of Modbus controller interface for the selected port. +2. :ref:`modbus_api_slave_configure_descriptor` - Configure data descriptors to access slave parameters. +3. :ref:`modbus_api_slave_setup_communication_options` - Allows to setup communication options for selected port. +4. :ref:`modbus_api_slave_communication` - Start stack and sending / receiving data. Filter events when master accesses the register areas. +5. :ref:`modbus_api_slave_destroy` - Destroy Modbus controller and its resources. + +.. _modbus_api_slave_configure_descriptor: + +Configuring Slave Data Access +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following functions must be called when the Modbus controller slave port is already initialized. Refer to :ref:`modbus_api_port_initialization`. + +The slave stack requires the user to define structures (memory storage areas) that store the Modbus parameters accessed by stack. These structures should be prepared by the user and be assigned to the Modbus controller interface using :cpp:func:`mbc_slave_set_descriptor` API call before the start of communication. The slave task can call the :cpp:func:`mbc_slave_check_event` function which will block until the Modbus master access the slave. The slave task can then get information about the data being accessed. + +.. note:: One slave can define several area descriptors per each type of Modbus register area with different start_offset. + +Register area is defined by using the :cpp:type:`mb_register_area_descriptor_t` structure. + +.. list-table:: Table 3 Modbus register area descriptor + :widths: 8 92 + :header-rows: 1 + + * - Field + - Description + * - ``start_offset`` + - Zero based register relative offset for defined register area. Example: register address = 40002 ( 4x register area - Function 3 - holding register ), start_offset = 2 + * - ``type`` + - Type of the Modbus register area. Refer to :cpp:type:`mb_param_type_t` for more information. + * - ``address`` + - A pointer to the memory area which is used to store the register data for this area descriptor. + * - ``size`` + - The size of the memory area in bytes which is used to store register data. + +:cpp:func:`mbc_slave_set_descriptor` + +The function initializes Modbus communication descriptors for each type of Modbus register area (Holding Registers, Input Registers, Coils (single bit output), Discrete Inputs). Once areas are initialized and the :cpp:func:`mbc_slave_start()` API is called the Modbus stack can access the data in user data structures by request from master. + +.. code:: c + + #define MB_REG_INPUT_START_AREA0 (0) + #define MB_REG_HOLDING_START_AREA0 (0) + #define MB_REG_HOLD_CNT (100) + #define MB_REG_INPUT_CNT (100) + + mb_register_area_descriptor_t reg_area; // Modbus register area descriptor structure + unit16_t holding_reg_area[MB_REG_HOLD_CNT] = {0}; // storage area for holding registers + unit16_t input_reg_area[MB_REG_INPUT_CNT] = {0}; // storage area for input registers + + reg_area.type = MB_PARAM_HOLDING; // Set type of register area + reg_area.start_offset = MB_REG_HOLDING_START_AREA0; // Offset of register area in Modbus protocol + reg_area.address = (void*)&holding_reg_area[0]; // Set pointer to storage instance + reg_area.size = sizeof(holding_reg_area) << 1; // Set the size of register storage area in bytes + ESP_ERROR_CHECK(mbc_slave_set_descriptor(reg_area)); + + reg_area.type = MB_PARAM_INPUT; + reg_area.start_offset = MB_REG_INPUT_START_AREA0; + reg_area.address = (void*)&input_reg_area[0]; + reg_area.size = sizeof(input_reg_area) << 1; + ESP_ERROR_CHECK(mbc_slave_set_descriptor(reg_area)); + + +At least one area descriptor per each Modbus register type must be set in order to provide register access to its area. If the master tries to access an undefined area, the stack will generate a Modbus exception. + +Direct access to register area from user application must be protected by critical section: + +.. code:: c + + portENTER_CRITICAL(¶m_lock); + holding_reg_area[2] += 10; + portEXIT_CRITICAL(¶m_lock); + + +.. _modbus_api_slave_setup_communication_options: + +Slave Communication Options +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The function initializes the Modbus controller interface and its active context (tasks, RTOS objects and other resources). + +:cpp:func:`mbc_slave_setup` + +The function is used to setup communication parameters of the Modbus stack. + +Example initialization of Modbus TCP communication: + +.. code:: c + + esp_netif_init(); + ... + + mb_communication_info_t comm_info = { + .ip_port = MB_TCP_PORT, // Modbus TCP port number (default = 502) + .ip_addr_type = MB_IPV4, // version of IP protocol + .ip_mode = MB_MODE_TCP, // Port communication mode + .ip_addr = NULL, // This field keeps the client IP address to bind, NULL - bind to any client + .ip_netif_ptr = esp_netif_ptr // esp_netif_ptr - pointer to the corresponding network interface + }; + + // Setup communication parameters and start stack + ESP_ERROR_CHECK(mbc_slave_setup((void*)&comm_info)); + +Example initialization of Modbus serial communication: + +.. code:: c + + #define MB_SLAVE_DEV_SPEED 9600 + #define MB_SLAVE_ADDR 1 + #define MB_SLAVE_PORT_NUM 2 + ... + + // Setup communication parameters and start stack + mb_communication_info_t comm_info = { + .mode = MB_MODE_RTU, // Communication type + .slave_addr = MB_SLAVE_ADDR, // Short address of the slave + .port = MB_SLAVE_PORT_NUM, // UART physical port number + .baudrate = MB_SLAVE_DEV_SPEED, // Baud rate for communication + .parity = MB_PARITY_NONE // Parity option + }; + + ESP_ERROR_CHECK(mbc_slave_setup((void*)&comm_info)); + +.. _modbus_api_slave_communication: + +Slave Communication +^^^^^^^^^^^^^^^^^^^ + +The function below is used to start Modbus controller interface and allows communication. + +:cpp:func:`mbc_slave_start` + +.. code:: c + + ESP_ERROR_CHECK(mbc_slave_start()); + +:cpp:func:`mbc_slave_check_event` + +The blocking call to function waits for a event specified (represented as an event mask parameter). Once the master accesses the parameter and the event mask matches the parameter type, the application task will be unblocked and function will return the corresponding event :cpp:type:`mb_event_group_t` which describes the type of register access being done. + +:cpp:func:`mbc_slave_get_param_info` + +The function gets information about accessed parameters from the Modbus controller event queue. The KConfig :ref:`CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE` key can be used to configure the notification queue size. The timeout parameter allows a timeout to be specified when waiting for a notification. The :cpp:type:`mb_param_info_t` structure contains information about accessed parameter. + +.. list-table:: Table 4 Description of the register info structure: :cpp:type:`mb_param_info_t` + :widths: 10 90 + :header-rows: 1 + + * - Field + - Description + * - ``time_stamp`` + - the time stamp of the event when defined parameter is accessed + * - ``mb_offset`` + - start Modbus register accessed by master + * - ``type`` + - type of the Modbus register area being accessed (See the :cpp:type:`mb_event_group_t` for more information) + * - ``address`` + - memory address that corresponds to accessed register in defined area descriptor + * - ``size`` + - number of registers being accessed by master + +Example to get event when holding or input registers accessed in the slave: + +.. code:: c + + #define MB_READ_MASK (MB_EVENT_INPUT_REG_RD | MB_EVENT_HOLDING_REG_RD) + #define MB_WRITE_MASK (MB_EVENT_HOLDING_REG_WR) + #define MB_READ_WRITE_MASK (MB_READ_MASK | MB_WRITE_MASK) + #define MB_PAR_INFO_GET_TOUT (10 / portTICK_RATE_MS) + .... + + // The function blocks while waiting for register access + mb_event_group_t event = mbc_slave_check_event(MB_READ_WRITE_MASK); + + // Get information about data accessed from master + ESP_ERROR_CHECK(mbc_slave_get_param_info(®_info, MB_PAR_INFO_GET_TOUT)); + const char* rw_str = (event & MB_READ_MASK) ? "READ" : "WRITE"; + + // Filter events and process them accordingly + if (event & (MB_EVENT_HOLDING_REG_WR | MB_EVENT_HOLDING_REG_RD)) { + ESP_LOGI(TAG, "HOLDING %s (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", + rw_str, + (uint32_t)reg_info.time_stamp, + (uint32_t)reg_info.mb_offset, + (uint32_t)reg_info.type, + (uint32_t)reg_info.address, + (uint32_t)reg_info.size); + } else if (event & (MB_EVENT_INPUT_REG_RD)) { + ESP_LOGI(TAG, "INPUT %s (%u us), ADDR:%u, TYPE:%u, INST_ADDR:0x%.4x, SIZE:%u", + rw_str, + (uint32_t)reg_info.time_stamp, + (uint32_t)reg_info.mb_offset, + (uint32_t)reg_info.type, + (uint32_t)reg_info.address, + (uint32_t)reg_info.size); + } + +.. _modbus_api_slave_destroy: + +Modbus Slave Teardown +^^^^^^^^^^^^^^^^^^^^^ + +This function stops the Modbus communication stack, destroys the controller interface, and frees all used active objects allocated for the slave. + +:cpp:func:`mbc_slave_destroy` + +.. code:: c + + ESP_ERROR_CHECK(mbc_slave_destroy()); + +Possible Communication Issues And Solutions +------------------------------------------- + +If the examples do not work as expected and slave and master boards are not able to communicate correctly, it is possible to find the reason for errors. The most important errors are described in master example output and formatted as below: + +.. highlight:: none + +:: + + E (1692332) MB_CONTROLLER_MASTER: mbc_master_get_parameter(111): SERIAL master get parameter failure error=(0x107) (ESP_ERR_TIMEOUT). + + +.. list-table:: Table 5 Modbus error codes and troubleshooting + :widths: 5 30 65 + :header-rows: 1 + + * - Error + - Description + - Possible solution + * - 0x106 + - ``ESP_ERR_NOT_SUPPORTED`` - Invalid register request - slave returned an exception because the requested register is not supported. + - Refer to slave register map. Check the master data dictionary for correctness. + * - 0x107 + - ``ESP_ERR_TIMEOUT`` - Slave response timeout - Modbus slave did not send response during configured slave response timeout. + - Measure and increase the maximum slave response timeout `idf.py menuconfig`, option :ref:`CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND`. + Check physical connection or network configuration and make sure that the slave response can reach the master side. + If the application has some high performance tasks with higher priority than :ref:`CONFIG_FMB_PORT_TASK_PRIO` it is recommended to place Modbus tasks on the other core using an option :ref:`CONFIG_FMB_PORT_TASK_AFFINITY`. + Configure the Modbus task's priority :ref:`CONFIG_FMB_PORT_TASK_PRIO` to ensure that the task gets sufficient processing time to handle Modbus stack events. + * - 0x108 + - ``ESP_ERR_INVALID_RESPONSE`` - Received unsupported response from slave or frame check failure. Master can not execute command handler because the command is either not supported or is incorrect. + - Check the physical connection then refer to register map of your slave to configure the master data dictionary properly. + * - 0x103 + - ``ESP_ERR_INVALID_STATE`` - Critical failure or FSM sequence failure or master FSM is busy processing previous request. + - Make sure your physical connection is working properly. Increase task stack size and check Modbus initialization sequence. Application Example ------------------- - The examples below use the FreeModbus library port for serial TCP slave and master implementations accordingly. The selection of stack is performed through KConfig menu option "Enable Modbus stack support ..." for appropriate communication mode and related configuration keys. -: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` +- :example:`protocols/modbus/serial/mb_master` +- :example:`protocols/modbus/tcp/mb_tcp_slave` +- :example:`protocols/modbus/tcp/mb_tcp_master` Please refer to the specific example README.md for details. +Protocol References +------------------- + + - ``https://modbus.org/specs.php``: Modbus Organization with protocol specifications. + +API Reference +------------- + +.. include-build-file:: inc/esp_modbus_common.inc +.. include-build-file:: inc/esp_modbus_master.inc +.. include-build-file:: inc/esp_modbus_slave.inc + diff --git a/docs/en/api-reference/provisioning/index.rst b/docs/en/api-reference/provisioning/index.rst index 18150c2e6f..0443208486 100644 --- a/docs/en/api-reference/provisioning/index.rst +++ b/docs/en/api-reference/provisioning/index.rst @@ -18,3 +18,10 @@ Code examples for above API are provided in the :example:`provisioning` director SmartConfig <../network/esp_smartconfig> Code example for above API is provided in :example:`wifi/smart_config` + +.. toctree:: + :maxdepth: 1 + + EasyConnect <../network/esp_dpp> + +Code example for above API is provided in :example:`wifi/wifi_easy_connect/dpp-enrollee` diff --git a/docs/en/api-reference/storage/fatfs.rst b/docs/en/api-reference/storage/fatfs.rst index 9333fd8993..855ec530f9 100644 --- a/docs/en/api-reference/storage/fatfs.rst +++ b/docs/en/api-reference/storage/fatfs.rst @@ -25,11 +25,11 @@ Most applications use the following workflow when working with ``esp_vfs_fat_`` 2. Call :cpp:func:`ff_diskio_register` to register the disk I/O driver for the drive number used in Step 1. -3. Call the FatFs function ``f_mount``, and optionally ``f_fdisk``, ``f_mkfs``, to mount the filesystem using the same drive number which was passed to :cpp:func:`esp_vfs_fat_register`. For more information, see `FatFs documentation `. +3. Call the FatFs function ``f_mount``, and optionally ``f_fdisk``, ``f_mkfs``, to mount the filesystem using the same drive number which was passed to :cpp:func:`esp_vfs_fat_register`. For more information, see `FatFs documentation `_. -4. Call the C standard library and POSIX API functions to perform such actions on files as open, read, write, erase, copy, etc. Use paths starting with the path prefix passed to :cpp:func:`esp_vfs_register` (for example, ``"/sdcard/hello.txt"``). +4. Call the C standard library and POSIX API functions to perform such actions on files as open, read, write, erase, copy, etc. Use paths starting with the path prefix passed to :cpp:func:`esp_vfs_register` (for example, ``"/sdcard/hello.txt"``). The filesystem uses `8.3 filenames `_ format (SFN) by default. If you need to use long filenames (LFN), enable the :ref:`CONFIG_FATFS_LONG_FILENAMES` option. More details on the FatFs filenames are available `here `_. -5. Optionally, by enabling the option `CONFIG_FATFS_USE_FASTSEEK`, use the POSIX lseek function to perform it faster, the fast seek will not work for files in write mode, so to take advantage of fast seek, you should open (or close and then reopen) the file in read-only mode. +5. Optionally, by enabling the option :ref:`CONFIG_FATFS_USE_FASTSEEK`, use the POSIX lseek function to perform it faster, the fast seek will not work for files in write mode, so to take advantage of fast seek, you should open (or close and then reopen) the file in read-only mode. 6. Optionally, call the FatFs library functions directly. In this case, use paths without a VFS prefix (for example, ``"/hello.txt"``). diff --git a/docs/en/api-reference/storage/spi_flash_concurrency.rst b/docs/en/api-reference/storage/spi_flash_concurrency.rst index 8e6e581768..a226b0a15a 100644 --- a/docs/en/api-reference/storage/spi_flash_concurrency.rst +++ b/docs/en/api-reference/storage/spi_flash_concurrency.rst @@ -24,7 +24,7 @@ There are no such constraints and impacts for flash chips on other SPI buses tha For differences between IRAM, DRAM, and flash cache, please refer to the :ref:`application memory layout ` documentation. -.. only: not CONFIG_FREERTOS_UNICORE +.. only:: not CONFIG_FREERTOS_UNICORE To avoid reading flash cache accidentally, when one CPU initiates a flash write or erase operation, the other CPU is put into a blocked state, and all non-IRAM-safe interrupts are disabled on all CPUs until the flash operation completes. diff --git a/docs/en/api-reference/storage/vfs.rst b/docs/en/api-reference/storage/vfs.rst index 4adbd1110c..5c56f8111e 100644 --- a/docs/en/api-reference/storage/vfs.rst +++ b/docs/en/api-reference/storage/vfs.rst @@ -1,4 +1,252 @@ -.. include:: ../../../../components/vfs/README.rst +Virtual filesystem component +============================ + +:link_to_translation:`zh_CN:[中文]` + +Overview +-------- + +Virtual filesystem (VFS) component provides a unified interface for drivers which can perform operations on file-like objects. These can be real filesystems (FAT, SPIFFS, etc.) or device drivers which provide a file-like interface. + +This component allows C library functions, such as fopen and fprintf, to work with FS drivers. At a high level, each FS driver is associated with some path prefix. When one of C library functions needs to open a file, the VFS component searches for the FS driver associated with the file path and forwards the call to that driver. VFS also forwards read, write, and other calls for the given file to the same FS driver. + +For example, one can register a FAT filesystem driver with the ``/fat`` prefix and call ``fopen("/fat/file.txt", "w")``. The VFS component will then call the function ``open`` of the FAT driver and pass the argument ``/file.txt`` to it together with appropriate mode flags. All subsequent calls to C library functions for the returned ``FILE*`` stream will also be forwarded to the FAT driver. + + +FS registration +--------------- + +To register an FS driver, an application needs to define an instance of the :cpp:type:`esp_vfs_t` structure and populate it with function pointers to FS APIs: + +.. highlight:: c + +:: + + esp_vfs_t myfs = { + .flags = ESP_VFS_FLAG_DEFAULT, + .write = &myfs_write, + .open = &myfs_open, + .fstat = &myfs_fstat, + .close = &myfs_close, + .read = &myfs_read, + }; + + ESP_ERROR_CHECK(esp_vfs_register("/data", &myfs, NULL)); + +Depending on the way how the FS driver declares its API functions, either ``read``, ``write``, etc., or ``read_p``, ``write_p``, etc., should be used. + +Case 1: API functions are declared without an extra context pointer (the FS driver is a singleton):: + + ssize_t myfs_write(int fd, const void * data, size_t size); + + // In definition of esp_vfs_t: + .flags = ESP_VFS_FLAG_DEFAULT, + .write = &myfs_write, + // ... other members initialized + + // When registering FS, context pointer (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):: + + ssize_t myfs_write(myfs_t* fs, int fd, const void * data, size_t size); + + // In definition of 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_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)); + +Synchronous input/output multiplexing +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Synchronous input/output multiplexing by :cpp:func:`select` is supported in the VFS component. The implementation +works in the following way. + +1. :cpp:func:`select` is called with file descriptors which could belong to various VFS drivers. +2. The file descriptors are divided into groups each belonging to one VFS driver. +3. The file descriptors belonging to non-socket VFS drivers are handed over to the given VFS drivers by :cpp:func:`start_select` + described later on this page. This function represents the driver-specific implementation of :cpp:func:`select` for + the given driver. This should be a non-blocking call which means the function should immediately return after setting up + the environment for checking events related to the given file descriptors. +4. The file descriptors belonging to the socket VFS driver are handed over to the socket driver by + :cpp:func:`socket_select` described later on this page. This is a blocking call which means that it will return only + if there is an event related to socket file descriptors or a non-socket driver signals :cpp:func:`socket_select` + to exit. +5. Results are collected from each VFS driver and all drivers are stopped by deinitiazation + of the environment for checking events. +6. The :cpp:func:`select` call ends and returns the appropriate results. + +Non-socket VFS drivers +"""""""""""""""""""""" + +If you want to use :cpp:func:`select` with a file descriptor belonging to a non-socket VFS driver +then you need to register the driver with functions :cpp:func:`start_select` and +:cpp:func:`end_select` similarly to the following example: + +.. highlight:: c + +:: + + // In definition of esp_vfs_t: + .start_select = &uart_start_select, + .end_select = &uart_end_select, + // ... other members initialized + +:cpp:func:`start_select` is called for setting up the environment for +detection of read/write/error conditions on file descriptors belonging to the +given VFS driver. + +:cpp:func:`end_select` is called to stop/deinitialize/free the +environment which was setup by :cpp:func:`start_select`. + +.. note:: + :cpp:func:`end_select` might be called without a previous :cpp:func:`start_select` call in some rare + circumstances. :cpp:func:`end_select` should fail gracefully if this is the case. + +Please refer to the +reference implementation for the UART peripheral in +:component_file:`vfs/vfs_uart.c` and most particularly to the functions +:cpp:func:`esp_vfs_dev_uart_register`, :cpp:func:`uart_start_select`, and +:cpp:func:`uart_end_select` for more information. + +Please check the following examples that demonstrate the use of :cpp:func:`select` with VFS file descriptors: + - :example:`peripherals/uart/uart_select` + - :example:`system/select` + +Socket VFS drivers +"""""""""""""""""" + +A socket VFS driver is using its own internal implementation of :cpp:func:`select` and non-socket VFS drivers notify +it upon read/write/error conditions. + +A socket VFS driver needs to be registered with the following functions defined: + +.. highlight:: c + +:: + + // In definition of 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` is the internal implementation of :cpp:func:`select` for the socket driver. It works only +with file descriptors belonging to the socket VFS. + +:cpp:func:`get_socket_select_semaphore` returns the signalization object (semaphore) which will be used in non-socket +drivers to stop the waiting in :cpp:func:`socket_select`. + +:cpp:func:`stop_socket_select` call is used to stop the waiting in :cpp:func:`socket_select` by passing the object +returned by :cpp:func:`get_socket_select_semaphore`. + +:cpp:func:`stop_socket_select_isr` has the same functionality as :cpp:func:`stop_socket_select` but it can be used +from ISR. + +Please see :component_file:`lwip/port/esp32/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 enable the + :envvar:`CONFIG_LWIP_USE_ONLY_LWIP_SELECT` option to reduce the code size and improve performance. + +.. note:: + Don't change the socket driver during an active :cpp:func:`select` call or you might experience some undefined + behavior. + +Paths +----- + +Each registered FS has a path prefix associated with it. This prefix can be considered as a "mount point" of this partition. + +In case when mount points are nested, the mount point with the longest matching path prefix is used when opening the file. For instance, suppose that the following filesystems are registered in VFS: + +- FS 1 on /data +- FS 2 on /data/static + +Then: + +- FS 1 will be used when opening a file called ``/data/log.txt`` +- FS 2 will be used when opening a file called ``/data/static/index.html`` +- Even if ``/index.html"`` does not exist in FS 2, FS 1 will *not* be searched for ``/static/index.html``. + +As a general rule, mount point names must start with the path separator (``/``) and must contain at least one character after path separator. However, an empty mount point name is also supported and might be used in cases when an application needs to provide a "fallback" filesystem or to override VFS functionality altogether. Such filesystem will be used if no prefix matches the path given. + +VFS does not handle dots (``.``) in path names in any special way. VFS does not treat ``..`` as a reference to the parent directory. In the above example, using a path ``/data/static/../log.txt`` will not result in a call to FS 1 to open ``/log.txt``. Specific FS drivers (such as FATFS) might handle dots in file names differently. + +When opening files, the FS driver receives only relative paths to files. For example: + +1. The ``myfs`` driver is registered with ``/data`` as a path prefix. +2. The application calls ``fopen("/data/config.json", ...)``. +3. The VFS component calls ``myfs_open("/config.json", ...)``. +4. The ``myfs`` driver opens the ``/config.json`` file. + +VFS does not impose any limit on total file path length, but it does limit the FS path prefix to ``ESP_VFS_PATH_MAX`` characters. Individual FS drivers may have their own filename length limitations. + + +File descriptors +---------------- + +File descriptors are small positive integers from ``0`` to ``FD_SETSIZE - 1``, where ``FD_SETSIZE`` is defined in newlib's ``sys/types.h``. The largest file descriptors (configured by ``CONFIG_LWIP_MAX_SOCKETS``) are reserved for sockets. The VFS component contains a lookup-table called ``s_fd_table`` for mapping global file descriptors to VFS driver indexes registered in the ``s_vfs`` array. + + +Standard IO streams (stdin, stdout, stderr) +------------------------------------------- + +If the menuconfig option ``UART for console output`` is not set to ``None``, then ``stdin``, ``stdout``, and ``stderr`` are configured to read from, and write to, a UART. It is possible to use UART0 or UART1 for standard IO. By default, UART0 is used with 115200 baud rate; TX pin is GPIO1; RX pin is GPIO3. These parameters can be changed in menuconfig. + +Writing to ``stdout`` or ``stderr`` will send characters to the UART transmit FIFO. Reading from ``stdin`` will retrieve characters from the UART receive FIFO. + +By default, VFS uses simple functions for reading from and writing to UART. Writes busy-wait until all data is put into UART FIFO, and reads are non-blocking, returning only the data present in the FIFO. Due to this non-blocking read behavior, higher level C library calls, such as ``fscanf("%d\n", &var);``, might not have desired results. + +Applications which use the UART driver can instruct VFS to use the driver's interrupt driven, blocking read and write functions instead. This can be done using a call to the ``esp_vfs_dev_uart_use_driver`` function. It is also possible to revert to the basic non-blocking functions using a call to ``esp_vfs_dev_uart_use_nonblocking``. + +VFS also provides an optional newline conversion feature for input and output. Internally, most applications send and receive lines terminated by the LF (''\n'') character. Different terminal programs may require different line termination, such as CR or CRLF. Applications can configure this separately for input and output either via menuconfig, or by calls to the functions ``esp_vfs_dev_uart_port_set_rx_line_endings`` and ``esp_vfs_dev_uart_port_set_tx_line_endings``. + + + +Standard streams and FreeRTOS tasks +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``FILE`` objects for ``stdin``, ``stdout``, and ``stderr`` are shared between all FreeRTOS tasks, but the pointers to these objects are stored in per-task ``struct _reent``. + +The following code is transferred to ``fprintf(__getreent()->_stderr, "42\n");`` by the preprocessor: + +.. highlight:: c + +:: + + fprintf(stderr, "42\n"); + + +The ``__getreent()`` function returns a per-task pointer to ``struct _reent`` in newlib libc. This structure is allocated on the TCB of each task. When a task is initialized, ``_stdin``, ``_stdout``, and ``_stderr`` members of ``struct _reent`` are set to the values of ``_stdin``, ``_stdout``, and ``_stderr`` of ``_GLOBAL_REENT`` (i.e., the structure which is used before FreeRTOS is started). + +Such a design has the following consequences: + +- It is possible to set ``stdin``, ``stdout``, and ``stderr`` for any given task without affecting other tasks, e.g., by doing ``stdin = fopen("/dev/uart/1", "r")``. +- Closing default ``stdin``, ``stdout``, or ``stderr`` using ``fclose`` will close the ``FILE`` stream object, which will affect all other tasks. +- To change the default ``stdin``, ``stdout``, ``stderr`` streams for new tasks, modify ``_GLOBAL_REENT->_stdin`` (``_stdout``, ``_stderr``) before creating the task. + +Event fds +------------------------------------------- + +``eventfd()`` call is a powerful tool to notify a ``select()`` based loop of custom events. The ``eventfd()`` implementation in ESP-IDF is generally the same as described in ``man(2) eventfd`` except for: + +- ``esp_vfs_eventfd_register()`` has to be called before calling ``eventfd()`` +- Options ``EFD_CLOEXEC``, ``EFD_NONBLOCK`` and ``EFD_SEMAPHORE`` are not supported in flags. +- Option ``EFD_SUPPORT_ISR`` has been added in flags. This flag is required to read and the write the eventfd in an interrupt handler. + +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. + API Reference ------------- diff --git a/docs/en/api-reference/system/inc/espefuse_summary_ESP32-C3.rst b/docs/en/api-reference/system/inc/espefuse_summary_ESP32-C3.rst index 89d1059feb..7f87e9954a 100644 --- a/docs/en/api-reference/system/inc/espefuse_summary_ESP32-C3.rst +++ b/docs/en/api-reference/system/inc/espefuse_summary_ESP32-C3.rst @@ -8,7 +8,6 @@ EFUSE_NAME (Block) Description = [Meaningful Value] [Readable/Writeable] (Hex Value) ---------------------------------------------------------------------------------------- Config fuses: - DIS_RTC_RAM_BOOT (BLOCK0) Disables boot from RTC RAM = False R/W (0b0) DIS_ICACHE (BLOCK0) Disables ICache = False R/W (0b0) DIS_DOWNLOAD_ICACHE (BLOCK0) Disables Icache when SoC is in Download mode = False R/W (0b0) DIS_FORCE_DOWNLOAD (BLOCK0) Disables forcing chip into Download mode = False R/W (0b0) @@ -50,6 +49,8 @@ OPTIONAL_UNIQUE_ID (BLOCK2)(0 errors): Optional unique 128-bit ID = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W BLOCK2_VERSION (BLOCK2) Version of BLOCK2 = No calibration R/W (0b000) + CUSTOM_MAC (BLOCK3) Custom MAC Address + = 00:00:00:00:00:00 (OK) R/W Jtag Config fuses: JTAG_SEL_ENABLE (BLOCK0) Set this bit to enable selection between usb_to_jt = False R/W (0b0) diff --git a/docs/en/api-reference/system/inc/espefuse_summary_ESP32-S2.rst b/docs/en/api-reference/system/inc/espefuse_summary_ESP32-S2.rst index b9c94b033e..ab6a8d4f10 100644 --- a/docs/en/api-reference/system/inc/espefuse_summary_ESP32-S2.rst +++ b/docs/en/api-reference/system/inc/espefuse_summary_ESP32-S2.rst @@ -66,6 +66,8 @@ OPTIONAL_UNIQUE_ID (BLOCK2)(0 errors): Optional unique 128-bit ID = 7d 33 b8 bb 0b 13 b3 c8 71 37 0e e8 7c ab d5 92 R/W BLOCK2_VERSION (BLOCK2) Version of BLOCK2 = With calibration R/W (0b001) + CUSTOM_MAC (BLOCK3) Custom MAC Address + = 00:00:00:00:00:00 (OK) R/W Security fuses: SOFT_DIS_JTAG (BLOCK0) Software disables JTAG. When software disabled, JT = False R/W (0b0) diff --git a/docs/en/api-reference/system/inc/espefuse_summary_ESP32-S3.rst b/docs/en/api-reference/system/inc/espefuse_summary_ESP32-S3.rst index 041f8abedc..8248dd1ffc 100644 --- a/docs/en/api-reference/system/inc/espefuse_summary_ESP32-S3.rst +++ b/docs/en/api-reference/system/inc/espefuse_summary_ESP32-S3.rst @@ -27,7 +27,6 @@ ADC2_MODE3_D1 (BLOCK2) ADC2 calibration 16 = -4 R/W (0b100001) Config fuses: - DIS_RTC_RAM_BOOT (BLOCK0) Disables boot from RTC RAM = False R/W (0b0) DIS_ICACHE (BLOCK0) Disables ICache = False R/W (0b0) DIS_DCACHE (BLOCK0) Disables DCache = False R/W (0b0) DIS_DOWNLOAD_ICACHE (BLOCK0) Disables Icache when SoC is in Download mode = False R/W (0b0) @@ -66,6 +65,8 @@ OPTIONAL_UNIQUE_ID (BLOCK2)(0 errors): Optional unique 128-bit ID = 7d 33 b8 bb 0b 13 b3 c8 71 37 0e e8 7c ab d5 92 R/W BLOCK2_VERSION (BLOCK2) Version of BLOCK2 = With calibration R/W (0b001) + CUSTOM_MAC (BLOCK3) Custom MAC Address + = 00:00:00:00:00:00 (OK) R/W Security fuses: SOFT_DIS_JTAG (BLOCK0) Software disables JTAG. When software disabled, JT = False R/W (0b000) diff --git a/docs/en/api-reference/system/ipc.rst b/docs/en/api-reference/system/ipc.rst index 4240c51050..2f34d10ffa 100644 --- a/docs/en/api-reference/system/ipc.rst +++ b/docs/en/api-reference/system/ipc.rst @@ -35,9 +35,53 @@ mutex hence simultaneous IPC calls are not possible. Care should taken to avoid deadlock when writing functions to be executed by IPC, especially when attempting to take a mutex within the function. +.. _hi_priority_ipc: + +Hi-priority IPC +--------------- + +In some cases, we need to quickly get the state of the other CPU (for example, in the core dump, in the GDB stub, in some unit tests, in the dport workaround, etc.), and usually it can be implemented as a fairly simple function and can be written in assembler. +For these purposes, the IPC API has special functions :cpp:func:`esp_ipc_isr_asm_call` and :cpp:func:`esp_ipc_isr_asm_call_blocking`. +The `esp_ipc_isr_asm...(asm_func, arg)` functions trigger the High-priority interrupt (4 level) on the other CPU. The given assembler function (asm_func) will run on the other CPU in the context of the interrupt. This assembler function will be called by the CALLX0 command therefore it must be written in assembler. + +:cpp:func:`esp_ipc_isr_asm_call` - triggers the Hi-priority interrupt on a particular core to execute a given function. The CPU which called this function will be blocked until the other CPU begins execution of the given function. + +:cpp:func:`esp_ipc_isr_asm_call_blocking` is similar but will block the calling CPU until the other CPU has completed the execution of the given function. + +:cpp:func:`esp_ipc_isr_stall_other_cpu` stalls the other CPU and the calling CPU disables interrupts with level 3 and lower. To finish stalling the other CPU call :cpp:func:`esp_ipc_isr_release_other_cpu`. The stalled CPU disables interrupts with level 5 and lower. + +Functions executed by Hi-priority IPC must be functions of type `void func(void *arg)`. Examples of a assembler function see in :idf_file:`components/esp_ipc/src/esp_ipc_isr/esp_ipc_isr_routines.S`, :idf_file:`components/esp_ipc/test/test_ipc_isr.S` and below. In the asm function, you can use only a few registers as they were saved in the interrupt handler before calling this function, their use is safe. The registers:`a2` as `void *arg`, a3 and a4 are free for use. + +Some feature: + +- The asm function should be placed in the IRAM memory and aligned on a memory address multiple of 4. +- As the asm function is run in the context of the High-priority interrupt, a C function can no be called because the windows spill is disabled. +- Use only a2, a3 and a4 registers in the asm function (to workaround it see esp_complex_asm_func). +- A CPU, that called these APIs `esp_ipc_isr_asm...(asm_func, arg)`, disables interrupts with level 3 and lower. +- A CPU, where the asm function is executed, disables interrupts with level 5 and lower. +- You do not need to take care about handling of the Hi-priority interrupt. + + +.. code-block:: asm + + /* esp_test_ipc_isr_get_cycle_count_other_cpu(void *arg) */ + // this function puts CCOUNT of the other CPU in the arg. + // use only a2, a3 and a4 regs here. + .section .iram1, "ax" + .align 4 + .global esp_test_ipc_isr_get_cycle_count_other_cpu + .type esp_test_ipc_isr_get_cycle_count_other_cpu, @function + // Args: + // a2 - void* arg + esp_test_ipc_isr_get_cycle_count_other_cpu: + rsr.ccount a3 + s32i a3, a2, 0 + ret + + +This number of registers available for use is sufficient for most simple cases. But if you need to run a more complex asm function, you can pass as an argument a pointer to a structure that can accept additional registers to a buffer to make them free to use. Remember to restore them before returning See the :example:`system/ipc/ipc_isr`. + API Reference ------------- .. include-build-file:: inc/esp_ipc.inc - - diff --git a/docs/en/api-reference/system/power_management.rst b/docs/en/api-reference/system/power_management.rst index a33df04d7e..d195388716 100644 --- a/docs/en/api-reference/system/power_management.rst +++ b/docs/en/api-reference/system/power_management.rst @@ -56,15 +56,18 @@ Power management locks have acquire/release counters. If the lock has been acqui {IDF_TARGET_NAME} supports three types of locks described in the table below. -============================ ====================================================== -Lock Description -============================ ====================================================== -``ESP_PM_CPU_FREQ_MAX`` Requests CPU frequency to be at the maximum value set with :cpp:func:`esp_pm_configure`. For {IDF_TARGET_NAME}, this value can be set to 80 MHz, 160 MHz, or 240 MHz. +.. list-table:: + :header-rows: 1 + :widths: 25 60 -``ESP_PM_APB_FREQ_MAX`` Requests the APB frequency to be at the maximum supported value. For {IDF_TARGET_NAME}, this is 80 MHz. - -``ESP_PM_NO_LIGHT_SLEEP`` Disables automatic switching to light sleep. -============================ ====================================================== + * - Lock + - Description + * - ``ESP_PM_CPU_FREQ_MAX`` + - Requests CPU frequency to be at the maximum value set with :cpp:func:`esp_pm_configure`. For {IDF_TARGET_NAME}, this value can be set to 80 MHz, 160 MHz, or 240 MHz. + * - ``ESP_PM_APB_FREQ_MAX`` + - Requests the APB frequency to be at the maximum supported value. For {IDF_TARGET_NAME}, this is 80 MHz. + * - ``ESP_PM_NO_LIGHT_SLEEP`` + - Disables automatic switching to light sleep. {IDF_TARGET_NAME} Power Management Algorithm --------------------------------------- diff --git a/docs/en/api-reference/system/system.rst b/docs/en/api-reference/system/system.rst index 194a401ea7..bd64c5ca06 100644 --- a/docs/en/api-reference/system/system.rst +++ b/docs/en/api-reference/system/system.rst @@ -102,14 +102,14 @@ The custom base MAC addresses should be allocated such that derived MAC addresse It is also possible to call the function :cpp:func:`esp_netif_set_mac` to set the specific MAC used by a network interface, after network initialization. It's recommended to use the Base MAC approach documented here instead, to avoid the possibility of the original MAC address briefly appearing on the network before it is changed. -.. This API is ESP32-only, see IDF-1326 + +Custom MAC address in eFuse +@@@@@@@@@@@@@@@@@@@@@@@@@@@ + +When reading custom MAC addresses from eFuse, ESP-IDF provides a helper function :cpp:func:`esp_efuse_mac_get_custom`. This loads the MAC address from eFuse BLK3. This function assumes that the custom base MAC address is stored in the following format: + .. only:: esp32 - Custom MAC address in eFuse - @@@@@@@@@@@@@@@@@@@@@@@@@@@ - - When reading custom MAC addresses from eFuse, ESP-IDF provides a helper function :cpp:func:`esp_efuse_mac_get_custom`. This loads the MAC address from eFuse BLK3. This function assumes that the custom base MAC address is stored in the following format: - +-----------------+-----------+---------------+------------------------------+ | Field | # of bits | Range of bits | Notes | +=================+===========+===============+==============================+ @@ -122,7 +122,25 @@ The custom base MAC addresses should be allocated such that derived MAC addresse | MAC address CRC | 8 | 7:0 | CRC-8-CCITT, polynomial 0x07 | +-----------------+-----------+---------------+------------------------------+ - Once MAC address has been obtained using :cpp:func:`esp_efuse_mac_get_custom`, call :cpp:func:`esp_base_mac_addr_set` to set this MAC address as base MAC address. + .. note:: + + If the 3/4 coding scheme is enabled, all eFuse fields in this block must be burnt at the same time. + +.. only:: not esp32 + + +-----------------+-----------+---------------+ + | Field | # of bits | Range of bits | + +=================+===========+===============+ + | MAC address | 48 | 200:248 | + +-----------------+-----------+---------------+ + + .. note:: + + The eFuse BLK3 uses RS-coding during a burn operation it means that all eFuse fields in this block must be burnt at the same time. + +Once MAC address has been obtained using :cpp:func:`esp_efuse_mac_get_custom`, call :cpp:func:`esp_base_mac_addr_set` to set this MAC address as base MAC address. + + .. _local-mac-addresses: diff --git a/docs/en/api-reference/system/wdts.rst b/docs/en/api-reference/system/wdts.rst index 894c70d740..372a6bde4c 100644 --- a/docs/en/api-reference/system/wdts.rst +++ b/docs/en/api-reference/system/wdts.rst @@ -4,7 +4,7 @@ Watchdogs Overview -------- -The ESP-IDF has support for two types of watchdogs: The Interrupt Watchdog Timer +The ESP-IDF has support for multiple types of watchdogs, with the two main ones being: The Interrupt Watchdog Timer and the Task Watchdog Timer (TWDT). The Interrupt Watchdog Timer and the TWDT can both be enabled using :ref:`project-configuration-menu`, however the TWDT can also be enabled during runtime. The Interrupt Watchdog is responsible for detecting @@ -101,13 +101,13 @@ timeout at runtime by calling :cpp:func:`esp_task_wdt_init`. The following config options control TWDT configuration at startup. They are all enabled by default: -{IDF_TARGET_IDLE_TASK:default="Idle task", esp32="CPU0 Idle task"} +{IDF_TARGET_IDLE_TASK:default="Idle task", esp32="CPU0 Idle task", esp32s3="CPU0 Idle task"} .. list:: - :ref:`CONFIG_ESP_TASK_WDT` - the TWDT is initialized automatically during startup. If this option is disabled, it is still possible to initialize the Task WDT at runtime by calling :cpp:func:`esp_task_wdt_init`. - :ref:`CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0` - {IDF_TARGET_IDLE_TASK} is subscribed to the TWDT during startup. If this option is disabled, it is still possible to subscribe the idle task by calling :cpp:func:`esp_task_wdt_add` at any time. - :esp32: - :ref:`CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1` - CPU1 Idle task is subscribed to the TWDT during startup. + :not CONFIG_FREERTOS_UNICORE: - :ref:`CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1` - CPU1 Idle task is subscribed to the TWDT during startup. JTAG and watchdogs @@ -124,6 +124,26 @@ panics from either watchdogs will be generated when the {IDF_TARGET_NAME} is con OpenOCD via JTAG. +.. only:: SOC_XT_WDT_SUPPORTED + + XTAL32K Watchdog Timer (XTWDT) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + The XTAL32K watchdog makes sure the (optional) external 32 KHz crystal or oscillator is functioning correctly. + + When `XTAL32K_CLK` works as the clock source of `RTC_SLOW_CLK` and stops oscillating, the XTAL32K watchdog timer will detect this and generate an interrupt. + It also provides functionality for automatically switching over to the internal, but less accurate oscillator as the `RTC_SLOW_CLK` source. + + Since the switch to the backup clock is done in hardware it can also happen during deep sleep. This means that even if `XTAL32K_CLK` stops functioning while the chip in deep sleep, waiting for a timer to expire, it will still be able to wake-up as planned. + + If the `XTAL32K_CLK` starts functioning normally again, you can call `esp_xt_wdt_restore_clk` to switch back to this clock source and re-enable the watchdog timer. + + Configuration + @@@@@@@@@@@@@ + + When the external 32KHz crystal or oscillator is selected (:ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_RTC_CLK_SRC`) the XTAL32K watchdog can be enabled via the :ref:`CONFIG_ESP_XT_WDT` configuration + flag. The timeout is configured by setting :ref:`CONFIG_ESP_XT_WDT_TIMEOUT`. The automatic backup clock functionality is enabled via the ref:`CONFIG_ESP_XT_WDT_BACKUP_CLK_ENABLE` configuration. + Interrupt Watchdog API Reference -------------------------------- diff --git a/docs/en/api-reference/template.rst b/docs/en/api-reference/template.rst index 0ad41e8800..4681d60387 100644 --- a/docs/en/api-reference/template.rst +++ b/docs/en/api-reference/template.rst @@ -61,7 +61,7 @@ API Reference 1. This repository provides for automatic update of API reference documentation using :doc:`code markup retrieved by Doxygen from header files <../contribute/documenting-code>`. - 1. Update is done on each documentation build by invoking Sphinx extension :idf_file:`docs/idf_extensions/run_doxygen.py` for all header files listed in the ``INPUT`` statement of :idf_file:`docs/doxygen/Doxyfile_common`. + 1. Update is done on each documentation build by invoking Sphinx extension :`esp_extensions/run_doxygen.py` for all header files listed in the ``INPUT`` statement of :idf_file:`docs/doxygen/Doxyfile`. 1. Each line of the ``INPUT`` statement (other than a comment that begins with ``##``) contains a path to header file ``*.h`` that will be used to generate corresponding ``*.inc`` files:: @@ -94,10 +94,10 @@ API Reference See `Breathe documentation `_ for additional information. - To provide a link to header file, use the :ref:`link custom role ` as follows:: + To provide a link to header file, use the `link custom role` directive as follows:: * :component_file:`path_to/header_file.h` - 1. In any case, to generate API reference, the file :idf_file:`docs/doxygen/Doxyfile_common` should be updated with paths to ``*.h`` headers that are being documented. + 1. In any case, to generate API reference, the file :idf_file:`docs/doxygen/Doxyfile` should be updated with paths to ``*.h`` headers that are being documented. 1. When changes are committed and documentation is build, check how this section has been rendered. :doc:`Correct annotations <../contribute/documenting-code>` in respective header files, if required. diff --git a/docs/en/conf.py b/docs/en/conf.py index eb43458dda..a2fa8030db 100644 --- a/docs/en/conf.py +++ b/docs/en/conf.py @@ -11,7 +11,7 @@ try: except ImportError: import os import sys - sys.path.insert(0, os.path.abspath('..')) + sys.path.insert(0, os.path.abspath('../')) from conf_common import * # noqa: F403,F401 # General information about the project. diff --git a/docs/en/contribute/add-ons-reference.rst b/docs/en/contribute/add-ons-reference.rst deleted file mode 100644 index d0be0269b3..0000000000 --- a/docs/en/contribute/add-ons-reference.rst +++ /dev/null @@ -1,197 +0,0 @@ -Documentation Add-ons and Extensions Reference -============================================== - -:link_to_translation:`zh_CN:[中文]` - -This documentation is created using `Sphinx `_ application that renders text source files in `reStructuredText `_ (``.rst``) format located in :idf:`docs` directory. For some more details on that process, please refer to section :doc:`documenting-code`. - -Besides Sphinx, there are several other applications that help to provide nicely formatted and easy to navigate documentation. These applications are listed in section :ref:`setup-for-building-documentation` with the installed version numbers provided in file :idf_file:`docs/requirements.txt`. - -We build ESP-IDF documentation for two languages (English, Simplified Chinese) and for multiple chips. Therefore we don't run ``sphinx`` directly, there is a wrapper Python program ``build_docs.py`` that runs Sphinx. - -On top of that, we have created a couple of custom add-ons and extensions to help integrate documentation with underlining `ESP-IDF`_ repository and further improve navigation as well as maintenance of documentation. - -The purpose of this section is to provide a quick reference to the add-ons and the extensions. - -Documentation Folder Structure ------------------------------- - -* The ESP-IDF repository contains a dedicated documentation folder :idf:`docs` in the root. -* The ``docs`` folder contains localized documentation in :idf:`docs/en` (English) and :idf:`docs/zh_CN` (simplified Chinese) subfolders. -* Graphics files and fonts common to localized documentation are contained in :idf:`docs/_static` subfolder. -* Remaining files in the root of ``docs`` as well as ``docs/en`` and ``docs/zh_CN`` provide configuration and scripts used to automate documentation processing including the add-ons and extensions. -* Sphinx extensions are provided in two directories, ``extensions`` and ``idf_extensions``. -* A ``_build`` directory is created in the ``docs`` folder by ``build_docs.py``. This directory is not added to the `ESP-IDF`_ repository. - - -Add-ons and Extensions Reference --------------------------------- - -Config Files -^^^^^^^^^^^^ - -:idf_file:`docs/conf_common.py` - This file contains configuration common to each localized documentation (e.g. English, Chinese). The contents of this file is imported to standard Sphinx configuration file ``conf.py`` located in respective language folders (e.g. ``docs/en``, ``docs/zh_CN``) during build for each language. - -:idf_file:`docs/sphinx-known-warnings.txt` - There are couple of spurious Sphinx warnings that cannot be resolved without doing update to the Sphinx source code itself. For such specific cases, respective warnings are documented in ``sphinx-known-warnings.txt`` file, that is checked during documentation build, to ignore the spurious warnings. - - -Scripts -^^^^^^^ - -:idf_file:`docs/build_docs.py` - - Top-level executable program which runs a Sphinx build for one or more language/target combinations. Run ``build_docs.py --help`` for full command line options. - - When ``build_docs.py`` runs Sphinx it sets the ``idf_target`` configuration variable, sets a Sphinx tag with the same name as the configuration variable, and uses some environment variables to communicate paths to :ref:`IDF-Specific Extensions`. - -:idf_file:`docs/check_lang_folder_sync.sh` - To reduce potential discrepancies when maintaining concurrent language version, the structure and filenames of language folders ``docs/en`` and ``docs/zh_CN`` folders should be kept identical. The script ``check_lang_folder_sync.sh`` is run on each documentation build to verify if this condition is met. - -.. note:: - - If a new content is provided in e.g. English, and there is no any translation yet, then the corresponding file in ``zh_CN`` folder should contain an ``.. include::`` directive pointing to the source file in English. This will automatically include the English version visible to Chinese readers. For example if a file ``docs/zh_CN/contribute/documenting-code.rst`` does not have a Chinese translation, then it should contain ``.. include:: ../../en/contribute/documenting-code.rst`` instead. - -Non-Docs Scripts -^^^^^^^^^^^^^^^^ - -These scripts are used to build docs but also used for other purposes: - -:idf_file:`tools/gen_esp_err_to_name.py` - This script is traversing the `ESP-IDF`_ directory structure looking for error codes and messages in source code header files to generate an ``.inc`` file to include in documentation under :doc:`../api-reference/error-codes`. - -:idf_file:`tools/kconfig_new/confgen.py` - Options to configure ESP-IDF's :idf:`components` are contained in ``Kconfig`` files located inside directories of individual components, e.g. :idf_file:`components/bt/Kconfig`. This script is traversing the ``component`` directories to collect configuration options and generate an ``.inc`` file to include in documentation under :ref:`configuration-options-reference`. - -Generic Extensions -^^^^^^^^^^^^^^^^^^ - -These are Sphinx extensions developed for IDF that don't rely on any IDF-docs-specific behaviour or configuration: - -:idf_file:`docs/extensions/toctree_filter.py` - Sphinx extensions overrides the ``:toctree:`` directive to allow filtering entries based on whether a tag is set, as ``:tagname: toctree_entry``. See the Python file for a more complete description. - -:idf_file:`docs/extensions/list_filter.py` - Sphinx extensions that provides a ``.. list::`` directive that allows filtering of entries in lists based on whether a tag is set, as ``:tagname: - list content``. See the Python file for a more complete description. - -:idf_file:`docs/extensions/html_redirects.py` - During documentation lifetime, some source files are moved between folders or renamed. This Sphinx extension adds a mechanism to redirect documentation pages that have changed URL by generating in the Sphinx output static HTML redirect pages. The script is used together with a redirection list ``html_redirect_pages``. ``conf_common.py`` builds this list from :idf_file:`docs/page_redirects.txt`. - - -Third Party Extensions -^^^^^^^^^^^^^^^^^^^^^^ - -- ``sphinxcontrib`` extensions for blockdiag, seqdiag, actdiag, nwdiag, rackdiag & packetdiag diagrams. -- `Sphinx selective exclude`_ ``eager_only`` extension. - -.. _idf-specific extensions: - -IDF-Specific Extensions -^^^^^^^^^^^^^^^^^^^^^^^ - -Build System Integration -######################## - -:idf:`docs/idf_extensions/build_system/` - -Python package implementing a Sphinx extension to pull IDF build system information into the docs build. - -* Creates a dummy CMake IDF project and runs CMake to generate metadata. -* Registers some new configuration variables and emits a new Sphinx event, both for use by other extensions. - -Configuration Variables -@@@@@@@@@@@@@@@@@@@@@@@ - -* ``docs_root`` - The absolute path of the $IDF_PATH/docs directory -* ``idf_path`` - The value of IDF_PATH variable, or the absolute path of IDF_PATH if environment unset -* ``build_dir`` - The build directory passed in by ``build_docs.py``, default will be like ``_build//`` -* ``idf_target`` - The IDF_TARGET value. Expected that ``build_docs.py`` set this on the Sphinx command line - -New Event -@@@@@@@@@ - -``idf-info`` event is emitted early in the build, after the dummy project CMake run is complete. - -Arguments are ``(app, project_description)``, where ``project_description`` is a dict containing the values parsed from ``project_description.json`` in the CMake build directory. - -Other IDF-specific extensions subscribe to this event and use it to set up some docs parameters based on build system info. - -Other Extensions -################ - -:idf_file:`docs/idf_extensions/include_build_file.py` - The ``include-build-file`` directive is like the built-in ``include-file`` directive, but file path is evaluated relative to ``build_dir``. - -:idf_file:`docs/idf_extensions/kconfig_reference.py` - Subscribes to ``idf-info`` event and uses confgen to generate ``kconfig.inc`` from the components included in the default project build. This file is then included into :doc:`/api-reference/kconfig`. - -:idf_file:`docs/idf_extensions/link_roles.py` - This is an implementation of a custom `Sphinx Roles `_ to help linking from documentation to specific files and folders in `ESP-IDF`_. For description of implemented roles, please see :ref:`link-custom-roles` and :ref:`link-language-versions`. - -:idf_file:`docs/idf_extensions/esp_err_definitions.py` - Small wrapper extension that calls ``gen_esp_err_to_name.py`` and updates the included .rst file if it has changed. - -:idf_file:`docs/idf_extensions/gen_toolchain_links.py` - There couple of places in documentation that provide links to download the toolchain. To provide one source of this information and reduce effort to manually update several files, this script generates toolchain download links and toolchain unpacking code snippets based on information found in :idf_file:`tools/toolchain_versions.mk`. - -:idf_file:`docs/idf_extensions/gen_version_specific_includes.py` - Another extension to automatically generate reStructuredText Text ``.inc`` snippets with version-based content for this ESP-IDF version. - -:idf_file:`docs/idf_extensions/util.py` - A collection of utility functions useful primarily when building documentation locally (see :ref:`setup-for-building-documentation`) to reduce the time to generate documentation on a second and subsequent builds. - -:idf_file:`docs/idf_extensions/format_idf_target.py` - An extension for replacing generic target related names with the idf_target passed to the Sphinx command line. - - This is a {\IDF_TARGET_NAME}, with /{\IDF_TARGET_PATH_NAME}/soc.c, compiled with `{\IDF_TARGET_TOOLCHAIN_PREFIX}-gcc` - with `CONFIG_{\IDF_TARGET_CFG_PREFIX}_MULTI_DOC` - will, if the backspaces are removed, render as - This is a {IDF_TARGET_NAME}, with /{IDF_TARGET_PATH_NAME}/soc.c, compiled with `{IDF_TARGET_TOOLCHAIN_PREFIX}-gcc` with `CONFIG_{IDF_TARGET_CFG_PREFIX}_MULTI_DOC`. - - - Also supports markup for defining local (single .rst-file) substitions with the following syntax: - {\IDF_TARGET_TX_PIN:default="IO3",esp32="IO4",esp32s2="IO5"} - - This will define a replacement of the tag {\IDF_TARGET_TX_PIN} in the current rst-file. - - The extension also overrides the default ``.. include::`` directive in order to format any included content using the same rules. - - These replacements cannot be used inside markup that rely on alignment of characters, e.g. tables. - -:idf_file:`docs/idf_extensions/latex_builder.py` - An extension for adding ESP-IDF specific functionality to the latex builder. Overrides the default Sphinx latex builder. - - Creates and adds the espidf.sty latex package to the output directory, which contains some macros for run-time variables such as IDF-Target. - -:idf_file:`docs/idf_extensions/gen_defines.py` - Sphinx extension to integrate defines from IDF into the Sphinx build, runs after the IDF dummy project has been built. - - Parses defines and adds them as sphinx tags. - - Emits the new 'idf-defines-generated' event which has a dictionary of raw text define values that other extensions can use to generate relevant data. - -:idf_file:`docs/idf_extensions/exclude_docs.py` - Sphinx extension that updates the excluded documents according to the conditional_include_dict {tag:documents}. If the tag is set, then the list of documents will be included. - - Also responsible for excluding documents when building with the config value ``docs_to_build`` set. In these cases all documents not listed in ``docs_to_build`` will be excluded. - - Subscribes to ``idf-defines-generated`` as it relies on the sphinx tags to determine which documents to exclude - -:idf_file:`docs/idf_extensions/run_doxygen.py` - Subscribes to ``idf-defines-generated`` event and runs Doxygen (:idf_file:`docs/doxygen/Doxyfile_common`) to generate XML files describing key headers, and then runs Breathe to convert these to ``.inc`` files which can be included directly into API reference pages. - - Pushes a number of target-specific custom environment variables into Doxygen, including all macros defined in the project's default ``sdkconfig.h`` file and all macros defined in all ``soc`` component ``xxx_caps.h`` headers. This means that public API headers can depend on target-specific configuration options or ``soc`` capabilities headers options as ``#ifdef`` & ``#if`` preprocessor selections in the header. - - This means we can generate different Doxygen files, depending on the target we are building docs for. - - Please refer to :doc:`documenting-code` and :doc:`../api-reference/template`, section **API Reference** for additional details on this process. - -Related Documents -------------------- - -* :doc:`documenting-code` - - -.. _ESP-IDF: https://github.com/espressif/esp-idf/ -.. _Sphinx selective exclude: https://github.com/pfalcon/sphinx_selective_exclude diff --git a/docs/en/contribute/documenting-code.rst b/docs/en/contribute/documenting-code.rst index f7e422b33a..98c9504f67 100644 --- a/docs/en/contribute/documenting-code.rst +++ b/docs/en/contribute/documenting-code.rst @@ -83,8 +83,8 @@ Go one extra mile Here are a couple of tips on how you can make your documentation even better and more useful to the reader and writer. -When writing codes, please follow the guidelines below: - +When writing codes, please follow the guidelines below: + 1. Add code snippets to illustrate implementation. To do so, enclose snippet using ``@code{c}`` and ``@endcode`` commands. :: * @@ -164,422 +164,26 @@ When it comes to text, please follow guidelines below to provide well formatted :align: center :scale: 50% :alt: Keep the line number for EN and CN files consistent (click to enlarge) - + Keep the line number for EN and CN documents consistent (click to enlarge) -.. _link-custom-roles: - -Linking Examples ----------------- - -When linking to examples on GitHub, do not use absolute/hardcoded URLs. Instead, use docutils custom roles that will generate links for you. These auto-generated links point to the tree or blob for the git commit ID (or tag) of the repository. This is needed to ensure that links do not get broken when files in master branch are moved around or deleted. The roles will transparently handle files that are located in submodules and will link to the submodule's repository with the correct commit ID. - -The following roles are provided: - -- ``:idf:`path``` - points to directory inside ESP-IDF -- ``:idf_file:`path``` - points to file inside ESP-IDF -- ``:idf_raw:`path``` - points to raw view of the file inside ESP-IDF -- ``:component:`path``` - points to directory inside ESP-IDF components dir -- ``:component_file:`path``` - points to file inside ESP-IDF components dir -- ``:component_raw:`path``` - points to raw view of the file inside ESP-IDF components dir -- ``:example:`path``` - points to directory inside ESP-IDF examples dir -- ``:example_file:`path``` - points to file inside ESP-IDF examples dir -- ``:example_raw:`path``` - points to raw view of the file inside ESP-IDF examples dir - -Example implementation:: - - * :example:`get-started/hello_world` - * :example:`Hello World! ` - -How it renders: - -* :example:`get-started/hello_world` -* :example:`Hello World! ` - -A check is added to the CI build script, which searches RST files for presence of hard-coded links (identified by tree/master, blob/master, or raw/master part of the URL). This check can be run manually: ``cd docs`` and then ``make gh-linkcheck``. - - -.. _link-language-versions: - -Linking Language Versions -------------------------- - -Switching between documentation in different languages may be done using ``:link_to_translation:`` custom role. The role placed on a page of documentation provides a link to the same page in a language specified as a parameter. Examples below show how to enter links to Chinese and English versions of documentation:: - - :link_to_translation:`zh_CN:中文版` - :link_to_translation:`en:English` - -The language is specified using standard abbreviations like ``en`` or ``zh_CN``. The text after last semicolon is not standardized and may be entered depending on the context where the link is placed, e.g.:: - - :link_to_translation:`en:see description in English` - - -.. _add-illustrations: - -Add Illustrations ------------------ - -Consider adding diagrams and pictures to illustrate described concepts. - -Sometimes it is better to add an illustration than writing a lengthy paragraph to describe a complex idea, a data structure or an algorithm. This repository is using `blockdiag `_ suite of tools to generate diagram images from simple text files. - -The following types of diagrams are supported: - -* `Block diagram `_ -* `Sequence diagram `_ -* `Activity diagram `_ -* `Logical network diagram `_ - -With this suite of tools, it is possible to generate beautiful diagram images from simple text format (similar to graphviz’s DOT format). The diagram elements are laid out automatically. The diagram code is then converted into ".png" graphics and integrated "behind the scenes" into **Sphinx** documents. - -For the diagram preparation, you can use an on-line `interactive shell`_ that instantly shows the rendered image. - -Below are couple of diagram examples: - -* Simple **block diagram** / ``blockdiag`` - `Wi-Fi Buffer Configuration `_ -* Slightly more complicated **block diagram** - `Wi-Fi programming model `_ -* **Sequence diagram** / ``seqdiag`` - `Scan for a Specific AP in All Channels `_ -* **Packet diagram** / ``packetdiag`` - `NVS Page Structure `_ - -Try them out by modifying the source code and see the diagram instantly rendering below. - -.. note:: - - There may be slight differences in rendering of font used by the `interactive shell`_ compared to the font used in the esp-idf documentation. - - -Add Notes ---------- - -Working on a document, you might need to: - -- Place some suggestions on what should be added or modified in future. -- Leave a reminder for yourself or somebody else to follow up. - -In this case, add a todo note to your reST file using the directive ``.. todo::``. For example: - -.. code-block:: none - - .. todo:: - - Add a package diagram. - -If you add ``.. todolist::`` to a reST file, the directive will be replaced by a list of all todo notes from the whole documentation. - -By default, the directives ``.. todo::`` and ``.. todolist::`` are ignored by documentation builders. If you want the notes and the list of notes to be visible in your locally built documentation, do the following: - -1. Open your local ``conf_common.py`` file. -2. Find the parameter ``todo_include_todos``. -3. Change its value from ``False`` to ``True``. - -Before pushing your changes to origin, please set the value of ``todo_include_todos`` back to ``False``. - -For more details about the extension, see `sphinx.ext.todo `_ documentation. - -Writing generic documentation for multiple chips ------------------------------------------------- - -The documentation for all of Espressif's chips is built from the same files. To faciliate the writing of documents that can be re-used for multiple different chips (called below "targets"), we provide you with the following functionality: - -Exclusion of content based on chip-target -"""""""""""""""""""""""""""""""""""""""""""" - -Occasionally there will be content that is only relevant for one of targets. When this is the case, you can exclude that content by using the ''.. only:: TAG'' directive, where you replace 'TAG' with one of the following names: - -Chip name: - -* esp32 -* esp32s2 -* esp32c3 - -Define identifiers from 'sdkconfig.h', generated by the default menuconfig settings for the target, e.g: - -* CONFIG_FREERTOS_UNICORE - -Define identifiers from the soc '\*_caps' headers, e.g: - -* SOC_BT_SUPPORTED -* SOC_CAN_SUPPORTED - -Example: - -.. code-block:: none - - .. only:: esp32 - - ESP32 specific content. - -This directive also supports the boolean operators 'and', 'or' and 'not'. Example: - -.. code-block:: none - - .. only:: SOC_BT_SUPPORTED and CONFIG_FREERTOS_UNICORE - - BT specific content only relevant for single-core targets. - -This functionality is provided by the `Sphinx selective exclude `_ extension. - -A weakness in this extension is that it does not correctly handle the case where you exclude a section, that is directly followed by a labeled new section. In these cases everything will render correctly, but the label will not correctly link to the section that follows. A temporary work-around for the cases where this can't be avoided is the following: - -.. code-block:: none - - .. only:: esp32 - - .. _section_1_label: - - Section 1 - ^^^^^^^^^ - - Section one content - - .. _section_2_label: - - .. only:: not esp32 - - .. _section_2_label: - - Section 2 - ^^^^^^^^^ - Section 2 content - -The :TAG: role is used for excluding content from a table of content tree. For example: - -.. code-block:: none - - .. toctree:: - :maxdepth: 1 - - :esp32: configure-wrover - configure-other-jtag - -When building the documents, Sphinx will use the above mentioned directive and role to include or exclude content based on the target tag it was called with. - -.. note:: - - If excluding an entire document from the toctree based on targets, it's necessary to also update the ``exclude_patterns`` list in :idf_file:`docs/conf_common.py` to exclude the file for other targets, or a Sphinx warning "WARNING: document isn't included in any toctree" will be generated.. - - The recommended way of doing it is adding the document to one of the list that gets included in ``conditional_include_dict`` in :idf_file:`docs/conf_common.py`, e.g. a document which should only be shown for BT capable targets should be added to ``BT_DOCS``. :idf_file:`docs/idf_extensions/exclude_docs.py` will then take care of adding it to ``exclude_patterns`` if the corresponding tag is not set. - -If you need to exclude content inside a list or bullet points, then this should be done by using the '':TAG:'' role inside the ''.. list:: '' directive. - -.. code-block:: none - - .. list:: - - :esp32: - ESP32 specific content - :SOC_BT_SUPPORTED: - BT specific content - - Common bullet point - - Also common bullet point - - -Substitution macros -""""""""""""""""""" -When you need to refer to the chip's name, toolchain name, path or other common names that depend on the target type you can consider using the substitution macros supplied by :idf_file:`docs/idf_extensions/format_idf_target.py`. - -For example, the following reStructuredText content: - - This is a {\IDF_TARGET_NAME}, with /{\IDF_TARGET_PATH_NAME}/soc.c, compiled with `{\IDF_TARGET_TOOLCHAIN_PREFIX}-gcc` with `CONFIG_{\IDF_TARGET_CFG_PREFIX}_MULTI_DOC` - -Would render in the documentation as: - - This is a {IDF_TARGET_NAME}, with /{IDF_TARGET_PATH_NAME}/soc.c, compiled with `{IDF_TARGET_TOOLCHAIN_PREFIX}-gcc` with `CONFIG_{IDF_TARGET_CFG_PREFIX}_MULTI_DOC`. - -This extension also supports markup for defining local (within a single source file) substitutions. Place a definition like the following into a single line of the RST file: - - {\IDF_TARGET_SUFFIX:default="DEFAULT_VALUE", esp32="ESP32_VALUE", esp32s2="ESP32S2_VALUE", esp32c3="ESP32C3_VALUE"} - -This will define a target-dependent substitution of the tag {\IDF_TARGET_SUFFIX} in the current RST file. For example: - - {\IDF_TARGET_TX_PIN:default="IO3", esp32="IO4", esp32s2="IO5", esp32c3="IO6"} - -Will define a substitution for the tag {\IDF_TARGET_TX_PIN}, which would be replaced by the text IO5 if sphinx was called with the tag esp32s2. - -.. note:: - - These single-file definitions can be placed anywhere in the .rst file (on their own line), but the name of the directive must start with ``IDF_TARGET_``. - - -Put it all together -------------------- - -Once documentation is ready, follow instruction in :doc:`../api-reference/template` and create a single file, that will merge all individual pieces of prepared documentation. Finally add a link to this file to respective ``.. toctree::`` in ``index.rst`` file located in ``/docs`` folder or subfolders. - - -OK, but I am new to Sphinx! ---------------------------- - -1. No worries. All the software you need is well documented. It is also open source and free. Start by checking `Sphinx`_ documentation. If you are not clear how to write using rst markup language, see `reStructuredText Primer `_. You can also use markdown (.md) files, and find out more about the specific markdown syntax that we use on `Recommonmark parser's documentation page `_. - -2. Check the source files of this documentation to understand what is behind of what you see now on the screen. Sources are maintained on GitHub in `espressif/esp-idf`_ repository in :idf:`docs` folder. You can go directly to the source file of this page by scrolling up and clicking the link in the top right corner. When on GitHub, see what's really inside, open source files by clicking ``Raw`` button. - -3. You will likely want to see how documentation builds and looks like before posting it on the GitHub. There are two options to do so: - - * Install `Sphinx`_, `Breathe`_, `Blockdiag `_ and `Doxygen `_ to build it locally, see chapter below. - - * Set up an account on `Read the Docs `_ and build documentation in the cloud. Read the Docs provides document building and hosting for free and their service works really quick and great. - -4. To preview documentation before building, use `Sublime Text `_ editor together with `OmniMarkupPreviewer `_ plugin. - - -.. _setup-for-building-documentation: - -Setup for building documentation locally ----------------------------------------- - -Install Dependencies -"""""""""""""""""""" - -You can setup environment to build documentation locally on your PC by installing: - -1. Doxygen - http://doxygen.nl/ -2. Sphinx - https://github.com/sphinx-doc/sphinx/#readme-for-sphinx -3. Breathe - https://github.com/michaeljones/breathe#breathe -4. Document theme "sphinx_idf_theme" - https://github.com/espressif/sphinx_idf_theme -5. Custom 404 page "sphinx-notfound-page" - https://github.com/readthedocs/sphinx-notfound-page -6. Blockdiag - http://blockdiag.com/en/index.html -7. Recommonmark - https://github.com/rtfd/recommonmark - -The package "sphinx_idf_theme" is added to have the same "look and feel" of `ESP-IDF Programming Guide `_. - -Do not worry about being confronted with several packages to install. Besides Doxygen, all remaining packages are written in pure Python. Therefore installation of all of them is combined into one simple step. - -.. important:: Docs building now supports Python 3 only. Python 2 installations will not work. - -Doxygen -@@@@@@@ - -Installation of Doxygen is OS dependent: - -**Linux** - -:: - - sudo apt-get install doxygen - -**Windows** - install in MSYS2 console - -:: - - pacman -S doxygen - -**MacOS** - -:: - - brew install doxygen - -.. note:: - - If you are installing on Windows MSYS2 system (Linux and MacOS users should skip this note, Windows users who don't use MSYS2 will need to find other alternatives), **before** going further, execute two extra steps below. These steps are required to install dependencies of "blockdiag" discussed under :ref:`add-illustrations`. - - 1. Update all the system packages: - - :: - - $ pacman -Syu - - This process will likely require restarting of the MSYS2 MINGW32 console and repeating above commands, until update is complete. - - 2. Install *pillow*, that is one of dependences of the *blockdiag*: - - :: - - $ pacman -S mingw32/mingw-w64-i686-python-pillow - - Check the log on the screen that ``mingw-w64-i686-python-pillow-4.3.0-1`` or newer is installed. Previous versions of *pillow* will not work. - - A downside of Windows installation is that fonts of the `blockdiag pictures ` do not render correctly, you will see some random characters instead. Until this issue is fixed, you can use the `interactive shell`_ to see how the complete picture looks like. - - -Remaining applications -@@@@@@@@@@@@@@@@@@@@@@ - - -All remaining applications are `Python `_ packages and you can install them in one step as follows: - -:: - - cd ~/esp/esp-idf/docs - pip install --user -r requirements.txt - -.. note:: - - Installation steps assume that ESP-IDF is placed in ``~/esp/esp-idf`` directory, that is default location of ESP-IDF used in documentation. - Building Documentation -"""""""""""""""""""""" +---------------------- +The documentation is built with the `esp-docs` Python package, which is a wrapper around `Sphinx `_ -:: +To install it simply do:: - cd ~/esp/esp-idf/docs + pip install esp-docs -Now you should be ready to build documentation by invoking:: +After a successful install then the documentation can be built from the docs folder with:: - ./build_docs.py build + build-docs build -This will build docs for all supported ESP-IDF languages & targets. This can take some time, although jobs will run in parallel up to the number of CPU cores you have (can modify this with the ``--sphinx-parallel-builds`` option, see ``./build_docs.py --help`` for details). +or for specific target and language with:: -To build for a single language and target combination only:: + build-docs -t esp32 -l en build - ./build_docs.py -l en -t esp32 build - -Choices for language (``-l``) are ``en`` and ``zh_CN``. Choices for target (``-t``) are any supported ESP-IDF build system target (for example ``esp32`` and ``esp32s2``). - -Build documentation will be placed in ``_build///html`` folder. To see it, open the ``index.html`` inside this directory in a web browser. - -Building a subset of the documentation -"""""""""""""""""""""""""""""""""""""" -Since building the full documentation can be quite slow, it might be useful to just build just the subset of the documentation you are interested in. - -This can be achieved by listing the document you want to build:: - - ./build_docs.py -l en -t esp32 -i api-reference/peripherals/can.rst build - -Building multiple documents is also possible:: - - ./build_docs.py -l en -t esp32 -i api-reference/peripherals/can.rst api-reference/peripherals/adc.rst build - -As well as wildcards:: - - ./build_docs.py -l en -t esp32 -i api-reference/peripherals/* build - -Note that this is a feature intended to simply testing and debugging during writing of documentation. The HTML output won't be perfect, i.e. it will not build a proper index that lists all the documents, and any references to documents that are not built will result in warnings. - -Fast build -"""""""""" -Another trick to speed up building is to skip including doxygen generated API documention into the Sphinx build process, skipping this drastically reduces build time. - -This can be achieved by adding the fast-build argument:: - - ./build_docs.py build -f - -or by setting the environment variable `DOCS_FAST_BUILD`. Note that the the `-f` argument is a subargument to `build` and thus must be listed after `build`. - -Building PDF -"""""""""""" - -It is also possible to build latex files and a PDF of the documentation using ``build_docs.py``. To do this the following Latex packages are required to be installed: - - * latexmk - * texlive-latex-recommended - * texlive-fonts-recommended - * texlive-xetex - -The following fonts are also required to be installed: - - * Freefont Serif, Sans and Mono OpenType fonts, available as the package ``fonts-freefont-otf`` on Ubuntu - * Lmodern, available as the package ``fonts-lmodern`` on Ubuntu - * Fandol, can be downloaded from `here `_ - -Now you can build the PDF for a target by invoking:: - - ./build_docs.py -bs latex -l en -t esp32 build - -Or alternatively build both html and PDF:: - - ./build_docs.py -bs html latex -l en -t esp32 build - -Latex files and the PDF will be placed in ``_build///latex`` folder. +For more in-depth documentation about `esp-docs` features please see the `esp-doc` documentation. Wrap up ------- @@ -594,12 +198,10 @@ Related Documents ----------------- * :doc:`../api-reference/template` -* :doc:`add-ons-reference` .. _espressif/esp-idf: https://github.com/espressif/esp-idf/ .. _interactive shell: http://interactive.blockdiag.com/?compression=deflate&src=eJxlUMFOwzAMvecrrO3aITYQQirlAIIzEseJQ5q4TUSIq8TVGIh_J2m7jbKc7Ge_5_dSO1Lv2soWvoVYgieNoMh7VGzJR9FJtugZ7lYQ0UcKEbYNOY36rRQHZHUPT68vV5tceGLbWCUzPfeaFFMoBZzecVc56vWwJFnWMmJ59CCZg617xpOFbTSyw0pmvT_HJ7hxtFNGBr6wvuu5SCkchcrZ1vAeXZomznh5YgTqfcpR02cBO6vZVDeXBRjMjKEcFRbLh8f18-Z2UUBDnqP9wmp9ncRmSSfND2ldGo2h_zse407g0Mxc1q7HzJ3-4jzYYTJjtQH3iSV-fgFzx50J -.. _Sphinx: https://www.sphinx-doc.org/ .. _Breathe: https://breathe.readthedocs.io diff --git a/docs/en/contribute/install-pre-commit-hook.rst b/docs/en/contribute/install-pre-commit-hook.rst index 344f6369cd..b3ced10d06 100644 --- a/docs/en/contribute/install-pre-commit-hook.rst +++ b/docs/en/contribute/install-pre-commit-hook.rst @@ -6,7 +6,7 @@ Required Dependency Python 3.6.1 or above. This is our recommendation python version for IDF developers. -If you still have versions not compatible, please do not install pre-commit hook and update your python versions. +If you still have python versions not compatible, please do not install pre-commit hook and update your python versions. Install pre-commit ------------------ @@ -30,17 +30,29 @@ Run ``pre-commit uninstall`` What's More? ------------ -For detailed usage, Please refer to the documentation of pre-commit_. +For detailed usage, please refer to the documentation of pre-commit_. -.. _pre-commit: http://www.pre-commit.com/ +.. _pre-commit: https://www.pre-commit.com/ Common Problems For Windows Users --------------------------------- -1. ``/usr/bin/env: python: Permission denied.`` +``/usr/bin/env: python: Permission denied.`` If you're in Git Bash or MSYS terminal, please check the python executable location by run ``which python``. If the executable is under ``~/AppData/Local/Microsoft/WindowsApps/``, then it's a link to Windows AppStore, not a real one. Please install python manually and update this in your ``PATH`` environment variable. + + +Your %USERPROFILE% contains non-ASCII characters + + ``pre-commit`` may fail when initializing an environment for a particular hook when the path of ``pre-commit``'s cache contains non-ASCII characters. The solution is to set ``PRE_COMMIT_HOME`` to a path containing only standard characters before running pre-commit. + + - CMD: ``set PRE_COMMIT_HOME=C:\somepath\pre-commit`` + - PowerShell: ``$Env:PRE_COMMIT_HOME = "C:\somepath\pre-commit"`` + - git bash: ``export PRE_COMMIT_HOME="/c/somepath/pre-commit"`` + + + diff --git a/docs/en/get-started/index.rst b/docs/en/get-started/index.rst index bb4ef6a268..8c24a6b666 100644 --- a/docs/en/get-started/index.rst +++ b/docs/en/get-started/index.rst @@ -286,14 +286,7 @@ The tools installer downloads a number of files attached to GitHub Releases. If Windows ------- -To prefer the Espressif download server when running the ESP-IDF Tools Installer check out the following option in the installer window: ``Use Espressif download server instead of downloading tool packages from GitHub.`` - -.. figure:: ../../_static/esp-idf-installer-download-server.png - :align: center - :alt: Configuring the ESP-IDF Tools Setup Wizard Espressif download server - :figclass: align-center - - Configuring the ESP-IDF Tools Setup Wizard Espressif download server +To prefer the Espressif download server when running the ESP-IDF Tools Installer, mark the **Use Espressif download mirror instead of GitHub** in the screen **Select Components** section **Optimization**. Linux and macOS --------------- diff --git a/docs/en/hw-reference/esp32/get-started-devkitc.rst b/docs/en/hw-reference/esp32/get-started-devkitc.rst index 4263c8701c..c325ef5ca0 100644 --- a/docs/en/hw-reference/esp32/get-started-devkitc.rst +++ b/docs/en/hw-reference/esp32/get-started-devkitc.rst @@ -3,7 +3,7 @@ ESP32-DevKitC V4 Getting Started Guide :link_to_translation:`zh_CN:[中文]` -This guide shows how to start using the ESP32-DevKitC V4 development board. For description of other versions of ESP32-DevKitC check :doc:`../../hw-reference/index`. +This guide shows how to start using the ESP32-DevKitC V4 development board. What You Need @@ -27,6 +27,7 @@ To cover a wide range of user requirements, the following versions of ESP32-DevK - different ESP32 modules + - `ESP32-WROOM-DA `_ - `ESP32-WROOM-32E `_ - `ESP32-WROOM-32UE `_ - `ESP32-WROOM-32D `_ @@ -55,31 +56,34 @@ The following figure and the table below describe the key components, interfaces ESP32-DevKitC V4 with ESP32-WROOM-32 module soldered -+--------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Key Component | Description | -+====================+======================================================================================================================================================================================+ -| ESP32-WROOM-32 | A module with ESP32 at its core. | -+--------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| EN | Reset button. | -+--------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Boot | Download button. Holding down **Boot** and then pressing **EN** initiates Firmware Download mode for downloading firmware through the serial port. | -+--------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| USB-to-UART Bridge | Single USB-UART bridge chip provides transfer rates of up to 3 Mbps. | -+--------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Micro USB Port | USB interface. Power supply for the board as well as the communication interface between a computer and the ESP32 module. | -+--------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 5V Power On LED | Turns on when the USB or an external 5V power supply is connected to the board. For details see the schematics in `Related Documents`_. | -+--------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| I/O | Most of the pins on the ESP module are broken out to the pin headers on the board. You can program ESP32 to enable multiple functions such as PWM, ADC, DAC, I2C, I2S, SPI, etc. | -+--------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +.. list-table:: + :widths: 25 75 + :header-rows: 1 - .. note:: + * - Key Component + - Description + * - ESP32-WROOM-32 + - A module with ESP32 at its core. For more information, see `ESP32-WROOM-32 Datasheet`_. + * - EN + - Reset button. + * - Boot + - Download button. Holding down **Boot** and then pressing **EN** initiates Firmware Download mode for downloading firmware through the serial port. + * - USB-to-UART Bridge + - Single USB-UART bridge chip provides transfer rates of up to 3 Mbps. + * - Micro USB Port + - USB interface. Power supply for the board as well as the communication interface between a computer and the ESP32-WROOM-32 module. + * - 5V Power On LED + - Turns on when the USB or an external 5V power supply is connected to the board. For details see the schematics in `Related Documents`_. + * - I/O + - Most of the pins on the ESP module are broken out to the pin headers on the board. You can program ESP32 to enable multiple functions such as PWM, ADC, DAC, I2C, I2S, SPI, etc. - The pins D0, D1, D2, D3, CMD and CLK are used internally for communication between ESP32 and SPI flash memory. They are grouped on both sides near the USB connector. Avoid using these pins, as it may disrupt access to the SPI flash memory / SPI RAM. +.. note:: - .. note:: + The pins D0, D1, D2, D3, CMD and CLK are used internally for communication between ESP32 and SPI flash memory. They are grouped on both sides near the USB connector. Avoid using these pins, as it may disrupt access to the SPI flash memory / SPI RAM. - The pins GPIO16 and GPIO17 are available for use only on the boards with the modules ESP32-WROOM and ESP32-SOLO-1. The boards with ESP32-WROVER modules have the pins reserved for internal use. +.. note:: + + The pins GPIO16 and GPIO17 are available for use only on the boards with the modules ESP32-WROOM and ESP32-SOLO-1. The boards with ESP32-WROVER modules have the pins reserved for internal use. Power Supply Options @@ -154,8 +158,7 @@ No. Name Type Function P: Power supply; I: Input; - O: Output; - T: High impedance. + O: Output. Pin Layout ^^^^^^^^^^^ @@ -201,10 +204,10 @@ Board Dimensions .. figure:: ../../../_static/esp32-devkitc-dimensions-back.jpg :align: center - :alt: ESP32 DevKitC board dimensions - back + :alt: Dimensions of ESP32-DevKitC board with ESP32-WROOM-32 module soldered - back :figclass: align-center - ESP32 DevKitC board dimensions - back + Dimensions of ESP32-DevKitC board with ESP32-WROOM-32 module soldered - back Related Documents @@ -212,6 +215,7 @@ Related Documents * `ESP32-DevKitC V4 schematics`_ (PDF) * `ESP32 Datasheet`_ (PDF) +* `ESP32-WROOM-DA Datasheet`_ (PDF) * `ESP32-WROOM-32 Datasheet`_ (PDF) * `ESP32-WROOM-32D and ESP32-WROOM-32U Datasheet`_ (PDF) * `ESP32-WROVER Datasheet`_ (PDF) @@ -226,8 +230,10 @@ For further design documentation for the board, please contact us at `sales@espr .. _ESP32-WROOM-32D and ESP32-WROOM-32U Datasheet: https://www.espressif.com/sites/default/files/documentation/esp32-wroom-32d_esp32-wroom-32u_datasheet_en.pdf .. _ESP32-WROVER Datasheet: https://espressif.com/sites/default/files/documentation/esp32-wrover_datasheet_en.pdf .. _ESP32-WROVER-B Datasheet: https://www.espressif.com/sites/default/files/documentation/esp32-wrover-b_datasheet_en.pdf +.. _ESP32-WROOM-DA Datasheet: https://www.espressif.com/sites/default/files/documentation/esp32-wroom-da_datasheet_en.pdf .. _ESP Product Selector: https://products.espressif.com/#/product-selector?names= + .. toctree:: :hidden: diff --git a/docs/en/hw-reference/esp32/get-started-wrover-kit.rst b/docs/en/hw-reference/esp32/get-started-wrover-kit.rst index 1055794c3d..19b17d9e4d 100644 --- a/docs/en/hw-reference/esp32/get-started-wrover-kit.rst +++ b/docs/en/hw-reference/esp32/get-started-wrover-kit.rst @@ -2,7 +2,7 @@ ESP-WROVER-KIT V4.1 Getting Started Guide ========================================= :link_to_translation:`zh_CN:[中文]` -This guide shows how to get started with the ESP-WROVER-KIT V4.1 development board and also provides information about its functionality and configuration options. For the description of other ESP-WROVER-KIT versions, please check :doc:`../../hw-reference/index`. +This guide shows how to get started with the ESP-WROVER-KIT V4.1 development board and also provides information about its functionality and configuration options. What You Need @@ -22,7 +22,7 @@ ESP-WROVER-KIT is an ESP32-based development board produced by `Espressif ` * MicroSD - :ref:`MicroSD Card / J4 ` * LCD - :ref:`LCD / U5 ` -* PSRAM - ESP32-WROVER-B's PSRAM +* PSRAM - ESP32-WROVER-E's PSRAM .. _get-started-esp-wrover-kit-v4.1-xtal: @@ -306,7 +309,7 @@ MicroSD Card 4 MTMS / GPIO14 CLK 5 GPIO2 DATA0 6 GPIO4 DATA1 -7 GPIO21 CD +7 GPIO21 Card Detect ==== ============== =============== @@ -367,7 +370,7 @@ Related Documents * `ESP-WROVER-KIT V4.1 schematic`_ (PDF) * `ESP-WROVER-KIT V4.1 layout `_ (DXF) may be opened online with `Autodesk Viewer `_ * `ESP32 Datasheet `_ (PDF) -* `ESP32-WROVER-B Datasheet `_ (PDF) +* `ESP32-WROVER-E Datasheet `_ (PDF) * :doc:`../../api-guides/jtag-debugging/index` * :doc:`../../hw-reference/index` diff --git a/docs/en/hw-reference/esp32c3/user-guide-devkitc-02.rst b/docs/en/hw-reference/esp32c3/user-guide-devkitc-02.rst index b1c01b0507..b150a52e3a 100644 --- a/docs/en/hw-reference/esp32c3/user-guide-devkitc-02.rst +++ b/docs/en/hw-reference/esp32c3/user-guide-devkitc-02.rst @@ -41,6 +41,8 @@ Description of Components ESP32-C3-DevKitC-02 - front +The key components of the board are described in a counter-clockwise direction. + .. list-table:: :widths: 30 70 :header-rows: 1 @@ -53,7 +55,7 @@ Description of Components - Power regulator that converts a 5 V supply into a 3.3 V output. * - 5 V Power On LED - Turns on when the USB power is connected to the board. - * - I/O Connector + * - Pin Headers - All available GPIO pins (except for the SPI bus for flash) are broken out to the pin headers on the board. For details, please see :ref:`user-guide-c3-devkitc-02-v1-header-blocks`. * - Boot Button - Download button. Holding down **Boot** and then pressing **Reset** initiates Firmware Download mode for downloading firmware through the serial port. @@ -81,7 +83,7 @@ Required Hardware .. note:: - Be sure to use a good quality USB cable. Some cables are for charging only and do not provide the needed data lines nor work for programming the boards. + 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 ^^^^^^^^^^^^^^ @@ -127,11 +129,11 @@ Power Supply Options There are three mutually exclusive ways to provide power to the board: -- Micro-USB port, default power supply +- 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. +It is recommended to use the first option: Micro-USB Port. .. _user-guide-c3-devkitc-02-v1-header-blocks: @@ -185,7 +187,7 @@ No. Name Type [1]_ Function === ==== ========== ==================================== .. [1] P: Power supply; I: Input; O: Output; T: High impedance. -.. [2] GPIO2, GPIO8, and GPIO9 are strapping pins of the ESP32-C3 chip. During the chip's system reset, the latches of the strapping pins sample the voltage level as strapping bits, and hold these bits until the chip is powered down or shut down. For description and application of strapping pins, please refer to Section Strapping Pins in `ESP32-C3 Datasheet`_. +.. [2] GPIO2, GPIO8, and GPIO9 are strapping pins of the ESP32-C3 chip. 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 Section Strapping Pins in `ESP32-C3 Datasheet`_. Pin Layout ^^^^^^^^^^^ diff --git a/docs/en/hw-reference/esp32c3/user-guide-devkitm-1.rst b/docs/en/hw-reference/esp32c3/user-guide-devkitm-1.rst index c74c62d18e..ca5486061c 100644 --- a/docs/en/hw-reference/esp32c3/user-guide-devkitm-1.rst +++ b/docs/en/hw-reference/esp32c3/user-guide-devkitm-1.rst @@ -42,6 +42,8 @@ Description of Components ESP32-C3-DevKitM-1 - front +The key components of the board are described in a counter-clockwise direction. + .. list-table:: :widths: 30 70 :header-rows: 1 @@ -54,7 +56,7 @@ Description of Components - Power regulator that converts a 5 V supply into a 3.3 V output. * - 5 V Power On LED - Turns on when the USB power is connected to the board. - * - I/O Connector + * - Pin Headers - All available GPIO pins (except for the SPI bus for flash) are broken out to the pin headers on the board. For details, please see :ref:`user-guide-c3-devkitm-1-v1-header-blocks`. * - Boot Button - Download button. Holding down **Boot** and then pressing **Reset** initiates Firmware Download mode for downloading firmware through the serial port. @@ -62,10 +64,10 @@ Description of Components - USB interface. Power supply for the board as well as the communication interface between a computer and the ESP32-C3FN4 chip. * - Reset Button - Press this button to restart the system. - * - USB to UART Bridge + * - USB-to-UART Bridge - Single USB-UART bridge chip provides transfer rates up to 3 Mbps. * - RGB LED - - Addressable RGB LED (WS2812), driven by GPIO8. + - Addressable RGB LED, driven by GPIO8. Start Application Development @@ -80,6 +82,10 @@ Required Hardware - 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 ^^^^^^^^^^^^^^ @@ -124,11 +130,11 @@ Power Supply Options There are three mutually exclusive ways to provide power to the board: -- Micro-USB port, default power supply +- 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. +It is recommended to use the first option: Micro-USB Port. .. _user-guide-c3-devkitm-1-v1-header-blocks: @@ -182,7 +188,7 @@ No. Name Type [1]_ Function === ==== ========== ==================================== .. [1] P: Power supply; I: Input; O: Output; T: High impedance. -.. [2] GPIO2, GPIO8, and GPIO9 are strapping pins of the ESP32-C3FN4 chip. During the chip's system reset, the latches of the strapping pins sample the voltage level as strapping bits, and hold these bits until the chip is powered down or shut down. For description and application of strapping pins, please refer to Section Strapping Pins in `ESP32-C3 Datasheet`_. +.. [2] GPIO2, GPIO8, and GPIO9 are strapping pins of the ESP32-C3FN4 chip. 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 Section Strapping Pins in `ESP32-C3 Datasheet`_. Pin Layout ^^^^^^^^^^^ diff --git a/docs/en/hw-reference/esp32s2/user-guide-devkitm-1-v1.rst b/docs/en/hw-reference/esp32s2/user-guide-devkitm-1-v1.rst index 1c6c536221..ef10353df1 100644 --- a/docs/en/hw-reference/esp32s2/user-guide-devkitm-1-v1.rst +++ b/docs/en/hw-reference/esp32s2/user-guide-devkitm-1-v1.rst @@ -6,9 +6,9 @@ ESP32-S2-DevKitM-1(U) This user guide provides information on Espressif's small-sized development board ESP32-S2-DevKitM-1(U). -ESP32-S2-DevKitM-1(U) is a general-purpose development board based on `ESP32-S2FH4 `__ chip, which falls into ESP32-S2 chip family. With a rich peripheral set and optimized pinout, this board allows rapid prototyping. +ESP32-S2-DevKitM-1(U) is a general-purpose development board based on `ESP32-S2FH4 `__ chip, which falls into ESP32-S2 chip series. With a rich peripheral set and optimized pinout, this board allows rapid prototyping. -ESP32-S2-DevKitM-1 is embedded with `ESP32-S2-MINI-1 `__ module (on-board PCB antenna), while ESP32-S2-DevKitM-1U with `ESP32-S2-MINI-1U `__ module (U.FL connector to support external IPEX antenna). +ESP32-S2-DevKitM-1 is embedded with `ESP32-S2-MINI-1 `__ module (on-board PCB antenna), while ESP32-S2-DevKitM-1U with `ESP32-S2-MINI-1U `__ module (external antenna connector). +----------------------+-----------------------+ | |ESP32-S2-DevKitM-1| | |ESP32-S2-DevKitM-1U| | @@ -24,6 +24,7 @@ The document consists of the following major sections: - `Getting started`_: Provides an overview of the ESP32-S2-DevKitM-1(U) and hardware/software setup instructions to get started. - `Hardware reference`_: Provides more detailed information about the ESP32-S2-DevKitM-1(U)'s hardware. +- `Hardware Revision Details`_: Revision history, known issues, and links to user guides for previous versions (if any) of ESP32-S2-DevKitM-1(U). - `Related Documents`_: Gives links to related documentation. Getting Started @@ -73,6 +74,8 @@ Description of Components ESP32-S2-DevKitM-1U - front +The key components of the board are described in a clockwise direction. + .. list-table:: :widths: 30 70 :header-rows: 1 @@ -80,13 +83,13 @@ Description of Components * - Key Component - Description * - ESP32-S2-MINI-1 or ESP32-S2-MINI-1U - - ESP32-S2-MINI-1 and ESP32-S2-MINI-1U are two powerful, generic Wi-Fi MCU modules that integrate ESP32-S2FH4 chip. ESP32-S2-MINI-1 comes with a PCB antenna, and ESP32-S2-MINI-1U with a U.FL connector for external IPEX antenna. They both feature a 4 MB external SPI flash. + - ESP32-S2-MINI-1 and ESP32-S2-MINI-1U are two powerful, generic Wi-Fi MCU modules that integrate ESP32-S2FH4 chip. ESP32-S2-MINI-1 comes with a PCB antenna, and ESP32-S2-MINI-1U with an external antenna connector. They both feature a 4 MB external SPI flash. + * - Pin Headers + - 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-S2FH4 chip to enable multiple functions such as SPI, I2S, UART, I2C, touch sensors, PWM etc. For details, please see :ref:`user-guide-devkitm-1-v1-header-blocks`. * - 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. - * - 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-S2FH4 chip to enable multiple functions such as SPI, I2S, UART, I2C, touch sensors, PWM etc. For details, please see :ref:`user-guide-devkitm-1-v1-header-blocks`. * - Reset Button - Reset button. * - Micro-USB Port @@ -94,12 +97,11 @@ Description of Components * - 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. + - Addressable RGB LED, driven by GPIO18. * - 5 V to 3.3 V LDO - Power regulator that converts a 5 V supply into a 3.3 V output. - * - U.FL Connector - - On **ESP32-S2-MINI-1U** module only. Connects to an external IPEX antenna. - + * - External Antenna Connector + - On **ESP32-S2-MINI-1U** module only. For connector dimensions, please refer to Section External Antenna Connector Dimensions in `ESP32-S2-MINI-1 & ESP32-S2-MINI-1U Datasheet `_. Start Application Development ----------------------------- @@ -111,11 +113,15 @@ Required Hardware - ESP32-S2-DevKitM-1(U) - + For ESP32-S2-DevKitM-1U, an IPEX antenna is also required. + + For ESP32-S2-DevKitM-1U, an antenna is also required. - 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 ^^^^^^^^^^^^^^ @@ -123,7 +129,7 @@ Please proceed to :doc:`../../get-started/index`, where Section :ref:`get-starte .. note:: - ESP32-S2 family chip only is only supported in ESP-IDF master or version v4.2 and higher. + ESP32-S2 series of chips only is only supported in ESP-IDF master or version v4.2 and higher. Hardware Reference ================== @@ -146,46 +152,46 @@ Power Supply Options 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 +- 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. +It is recommended to use the first option: Micro-USB Port. .. _user-guide-devkitm-1-v1-header-blocks: Header Block ------------ -The two tables below provide the **Name** and **Function** of I/O header pins on both sides of the board, as shown in :ref:`user-guide-devkitm-1-v1-board-front`. The numbering and names are the same as in the `ESP32-S2-DevKitM-1(U) Schematics `_ (PDF). +The two tables below provide the **Name** and **Function** of the pin headers on both sides of the board (J1 and J3). The pin header names are shown in :ref:`user-guide-devkitm-1-v1-board-front`. The numbering is the same as in the `ESP32-S2-DevKitM-1(U) Schematics `_ (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 -11 9 I/O/T RTC_GPIO9, GPIO9, TOUCH9, ADC1_CH8, FSPIHD -12 10 I/O/T RTC_GPIO10, GPIO10, TOUCH10, ADC1_CH9, FSPICS0, FSPIIO4 -13 11 I/O/T RTC_GPIO11, GPIO11, TOUCH11, ADC2_CH0, FSPID, FSPIIO5 -14 12 I/O/T RTC_GPIO12, GPIO12, TOUCH12, ADC2_CH1, FSPICLK, FSPIIO6 -15 13 I/O/T RTC_GPIO13, GPIO13, TOUCH13, ADC2_CH2, FSPIQ, FSPIIO7 -16 14 I/O/T RTC_GPIO14, GPIO14, TOUCH14, ADC2_CH3, FSPIWP, FSPIDQS -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, DAC_1 -20 5V P 5 V power supply -21 G G Ground -=== ==== ===== ======================================================== +=== ==== ========== ============================================================= +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 +11 9 I/O/T RTC_GPIO9, GPIO9, TOUCH9, ADC1_CH8, FSPIHD +12 10 I/O/T RTC_GPIO10, GPIO10, TOUCH10, ADC1_CH9, FSPICS0, FSPIIO4 +13 11 I/O/T RTC_GPIO11, GPIO11, TOUCH11, ADC2_CH0, FSPID, FSPIIO5 +14 12 I/O/T RTC_GPIO12, GPIO12, TOUCH12, ADC2_CH1, FSPICLK, FSPIIO6 +15 13 I/O/T RTC_GPIO13, GPIO13, TOUCH13, ADC2_CH2, FSPIQ, FSPIIO7 +16 14 I/O/T RTC_GPIO14, GPIO14, TOUCH14, ADC2_CH3, FSPIWP, FSPIDQS +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, DAC_1 +20 5V P 5 V power supply +21 G G Ground +=== ==== ========== ============================================================= J3 ^^^ @@ -212,16 +218,33 @@ No. Name Type Function 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 18 I/O/T RTC_GPIO18, GPIO18, U1RXD, ADC2_CH7, DAC_2, CLK_OUT3 +21 18 I/O/T RTC_GPIO18, GPIO18, U1RXD, ADC2_CH7, DAC_2, CLK_OUT3, RGB LED === ==== ===== ======================================================== +.. [#] P: Power supply; I: Input; O: Output; T: High impedance. + +Pin Layout +^^^^^^^^^^^ +.. figure:: ../../../_static/esp32-s2-devkitm-1-v1-pin-layout.png + :align: center + :scale: 15% + :alt: ESP32-S2-DevKitM-1(U) (click to enlarge) + :figclass: align-center + + ESP32-S2-DevKitM-1(U) Pin Layout (click to enlarge) + +Hardware Revision Details +========================= + +This is the first revision of this board released. + Related Documents ================= * `ESP32-S2-DevKitM-1(U) Schematics `_ (PDF) * `ESP32-S2-DevKitM-1(U) PCB Layout `_ (PDF) * `ESP32-S2-DevKitM-1(U) Dimensions `_ (PDF) -* `ESP32-S2 Family Datasheet `_ (PDF) +* `ESP32-S2 Series Datasheet `_ (PDF) * `ESP32-S2-MINI-1 & ESP32-S2-MINI-1U Datasheet `_ (PDF) * `ESP Product Selector `_ -For other design documentation for the board, please contact us at sales@espressif.com. +For other design documentation for the board, please contact us at `sales@espressif.com `_. diff --git a/docs/en/hw-reference/esp32s2/user-guide-s2-devkitc-1.rst b/docs/en/hw-reference/esp32s2/user-guide-s2-devkitc-1.rst index 54fa6b6356..dae19a5b6d 100644 --- a/docs/en/hw-reference/esp32s2/user-guide-s2-devkitc-1.rst +++ b/docs/en/hw-reference/esp32s2/user-guide-s2-devkitc-1.rst @@ -50,7 +50,7 @@ The key components of the board are described in a clockwise direction. * - Key Component - Description * - ESP32-S2-SOLO or ESP32-S2-SOLO-U - - ESP32-S2-SOLO and ESP32-S2-SOLO-U are two general-purpose Wi-Fi modules. ESP32-S2-SOLO comes with an on-board PCB antenna and ESP32-S2-SOLO-U comes with a connector for an external antenna. ESP32-S2-SOLO or ESP32-S2-SOLO-U on the board may come either with a 4 MB flash, or a 8 MB flash plus a 2 MB PSRAM embedded in the chip. + - ESP32-S2-SOLO and ESP32-S2-SOLO-U are two general-purpose Wi-Fi modules. ESP32-S2-SOLO comes with an on-board PCB antenna and ESP32-S2-SOLO-U comes with a connector for an external antenna. ESP32-S2-SOLO or ESP32-S2-SOLO-U on the board may come either with a 4 MB flash, or a 4 MB flash plus a 2 MB PSRAM embedded in the chip. * - 3.3 V Power On LED - Turns on when the USB power is connected to the board. * - USB-to-UART Bridge 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 index 21ce8a9885..acb98224b1 100644 --- 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 @@ -17,6 +17,7 @@ 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 @@ -48,7 +49,6 @@ If you order a few samples, each ESP32-S2-Saola-1 comes in an individual package For retail orders, please go to https://www.espressif.com/en/company/contact/buy-a-sample. - Wholesale Orders ^^^^^^^^^^^^^^^^ @@ -59,6 +59,8 @@ For wholesale orders, please go to https://www.espressif.com/en/contact-us/sales 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 @@ -66,6 +68,8 @@ Description of Components 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 @@ -74,22 +78,21 @@ Description of Components - 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. - * - I/O Connector + * - 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. - * - USB to UART Bridge - - Single USB-UART bridge chip provides transfer rates up to 3 Mbps. - * - 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. * - 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 ----------------------------- @@ -102,6 +105,10 @@ Required Hardware - 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 ^^^^^^^^^^^^^^ @@ -109,7 +116,7 @@ Please proceed to :doc:`../../get-started/index`, where Section :ref:`get-starte .. note:: - ESP32-S2 only supports ESP-IDF master or version v4.2 and higher. + ESP32-S2 series of chips only supports ESP-IDF master or version v4.2 and higher. Hardware Reference ================== @@ -132,42 +139,44 @@ Power Supply Options 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 +- 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 I/O header pins on both sides of the board. The numbering and names are the same as in the `ESP32-S2-Saola-1 Schematics`_ (PDF). +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 -=== ==== ===== =================================== +=== ==== ========== ====================================== +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 ^^^ @@ -194,24 +203,26 @@ No. Name Type Function 18 IO21 I/O GPIO21 19 IO20 I/O GPIO20, ADC2_CH3, USB_D+ 20 IO19 I/O GPIO19, ADC2_CH3, USB_D- -21 IO18 I/O GPIO18, ADC2_CH3, DAC_2 +21 IO18 I/O GPIO18, ADC2_CH3, DAC_2, RGB LED === ==== ===== ==================================== - P: Power supply; - I: Input; - O: Output; - T: High impedance. +.. [#] 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-Saola1 (click to enlarge) + :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 ================= @@ -222,7 +233,7 @@ Related Documents * `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. +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 diff --git a/docs/en/libraries-and-frameworks/cloud-frameworks.rst b/docs/en/libraries-and-frameworks/cloud-frameworks.rst index c3bb2839b9..822cf9bb11 100644 --- a/docs/en/libraries-and-frameworks/cloud-frameworks.rst +++ b/docs/en/libraries-and-frameworks/cloud-frameworks.rst @@ -3,6 +3,12 @@ Cloud Frameworks {IDF_TARGET_NAME} supports multiple cloud frameworks using agents built on top of ESP-IDF. Here are the pointers to various supported cloud frameworks' agents and examples: + +ESP RainMaker +------------- + +`ESP RainMaker `_ is a complete solution for accelerated AIoT development. `ESP RainMaker on GitHub `_. + AWS IoT ------- diff --git a/docs/en/libraries-and-frameworks/index.rst b/docs/en/libraries-and-frameworks/index.rst index 42a8862e9a..de793bedd6 100644 --- a/docs/en/libraries-and-frameworks/index.rst +++ b/docs/en/libraries-and-frameworks/index.rst @@ -5,4 +5,5 @@ Libraries and Frameworks .. toctree:: :maxdepth: 1 - Cloud Frameworks \ No newline at end of file + Cloud Frameworks + Espressif's Libraries and Frameworks diff --git a/docs/en/libraries-and-frameworks/libs-frameworks.rst b/docs/en/libraries-and-frameworks/libs-frameworks.rst new file mode 100644 index 0000000000..05856e7724 --- /dev/null +++ b/docs/en/libraries-and-frameworks/libs-frameworks.rst @@ -0,0 +1,81 @@ +Espressif's Frameworks +====================== + +Here you will find a collection of the official Espressif libraries and frameworks. + +Espressif Audio Development Framework +------------------------------------- + +The ESP-ADF is a comprehensive framework for audio applications including: + +* CODEC's HAL +* Music Players and Recorders +* Audio Processing +* Bluetooth Speakers +* Internet Radios +* Hands-free devices +* Speech Recognition + +This framework is available at GitHub: `ESP-ADF `_. + +ESP-CSI +------- + +ESP-CSI is an experimental implementation that uses the Wi-Fi Channel State Information to detect the presence of a human body. + +See `ESP-CSI `_ project for more information about it. + +Espressif DSP Library +--------------------- + +The library provides algorithms optimized specifically for digital signal processing applications. +This library supports: + +* Matrix multiplication +* Dot product +* FFT (Fast Fourier Transform) +* IIR (Infinite Impulse Response) +* FIR (Finite Impulse Response) +* Vector math operations + +This library is available here: `ESP-DSP library `_. + +ESP-WIFI-MESH Development Framework +----------------------------------- + +This framework is based on the ESP-WIFI-MESH protocol with the following features: + +* Fast network configuration +* Stable upgrade +* Efficient debugging +* LAN control +* Various application demos + +`ESP-MDF `_. + +ESP-WHO +------- + +The ESP-WHO is a face detection and recognition framework using the ESP32 and camera. +To know more about the project, see `ESP-WHO `_ on GitHub. + +ESP RainMaker +------------- + +`ESP RainMaker `_ is a complete solution for accelerated AIoT development. +Using ESP RainMaker, you can create AIoT devices from the firmware to the integration with voice-assistant, phone apps and cloud backend. + +`ESP RainMaker on GitHub `_. + +ESP-IoT-Solution +---------------- + +`ESP-IoT-Solution `_ contains commonly used device drivers and code frameworks when developing IoT systems. The device drivers and code frameworks within the ESP-IoT-Solution are organized as separate components, allowing them to be easily integrated into an ESP-IDF project. + +ESP-IoT-Solution includes: + +* Device drivers for sensors, display, audio, GUI, input, actuators, etc. +* Framework and documentation for low power, security, storage, etc. +* Guide for Espressif open source solutions from practical application point. + +`ESP-IoT-Solution on GitHub `_. diff --git a/docs/en/security/flash-encryption.rst b/docs/en/security/flash-encryption.rst index e92c824c10..5b64fe7612 100644 --- a/docs/en/security/flash-encryption.rst +++ b/docs/en/security/flash-encryption.rst @@ -193,6 +193,7 @@ During the development stage, there is a frequent need to program different plai Hence, two different flash encryption configurations were created: for development and for production. For details on these configurations, see Section `Flash Encryption Configuration`_. + Flash Encryption Configuration ------------------------------ @@ -201,10 +202,8 @@ The following flash encryption modes are available: - :ref:`flash-enc-development-mode` - recommended for use ONLY DURING DEVELOPMENT, as it does not prevent modification and readout of encrypted flash contents. - :ref:`flash-enc-release-mode` - recommended for manufacturing and production to prevent physical readout of encrypted flash contents. - This section provides information on the mentioned flash encryption modes and step by step instructions on how to use them. - .. _flash-enc-development-mode: Development Mode @@ -230,8 +229,8 @@ To test flash encryption process, take the following steps: - :ref:`Enable flash encryption on boot ` - :ref:`Select encryption mode ` (**Development mode** by default) - :esp32: - :ref: `Select UART ROM download mode ` (**enabled** by default. Note that for the esp32 target, the choice is only available when :ref:`CONFIG_ESP32_REV_MIN` level is set to 3 (ESP32 V3)). - :not esp32: - :ref: `Select UART ROM download mode ` (**enabled** by default.) + :esp32: - :ref:`Select UART ROM download mode ` (**enabled** by default. Note that for the esp32 target, the choice is only available when :ref:`CONFIG_ESP32_REV_MIN` level is set to 3 (ESP32 V3)). + :not esp32: - :ref:`Select UART ROM download mode ` (**enabled** by default.) :esp32s2 or esp32s3: - Set :ref:`Size of generated AES-XTS key ` - :ref:`Select the appropriate bootloader log verbosity ` - Save the configuration and exit. @@ -256,7 +255,6 @@ A sample output of the first {IDF_TARGET_NAME} boot after enabling flash encrypt :start-after: first_boot_enc :end-before: ------ - A sample output of subsequent {IDF_TARGET_NAME} boots just mentions that flash encryption is already enabled: .. include:: {IDF_TARGET_PATH_NAME}_log.inc @@ -311,7 +309,6 @@ To use a host generated key, take the following steps: espsecure.py generate_flash_encryption_key my_flash_encryption_key.bin - 3. **Before the first encrypted boot**, burn the key into your device's eFuse using the command below. This action can be done **only once**. .. only:: not SOC_FLASH_ENCRYPTION_XTS_AES @@ -326,15 +323,15 @@ To use a host generated key, take the following steps: espefuse.py --port PORT burn_key BLOCK my_flash_encryption_key.bin KEYPURPOSE - where `BLOCK` is a free keyblock between `BLOCK_KEY0` and `BLOCK_KEY5`. And `KEYPURPOSE` is either `AES_256_KEY_1`, `XTS_AES_256_KEY_2`, `XTS_AES_128_KEY`. See `{IDF_TARGET_NAME} Technical Reference Manual <{IDF_TARGET_TRM_EN_URL}>`_ for a description of the key purposes. + where ``BLOCK`` is a free keyblock between ``BLOCK_KEY0`` and ``BLOCK_KEY5``. And ``KEYPURPOSE`` is either ``AES_256_KEY_1``, ``XTS_AES_256_KEY_2``, ``XTS_AES_128_KEY``. See `{IDF_TARGET_NAME} Technical Reference Manual <{IDF_TARGET_TRM_EN_URL}>`_ for a description of the key purposes. - AES-128 (256-bit key) - `XTS_AES_128_KEY`: + AES-128 (256-bit key) - ``XTS_AES_128_KEY``: .. code-block:: bash espefuse.py --port PORT burn_key BLOCK my_flash_encryption_key.bin XTS_AES_128_KEY - AES-256 (512-bit key) - `XTS_AES_256_KEY_1` and `XTS_AES_256_KEY_2`. It is not fully supported yet in espefuse.py and espsecure.py. Need to do the following steps: + AES-256 (512-bit key) - ``XTS_AES_256_KEY_1`` and ``XTS_AES_256_KEY_2``. It is not fully supported yet in espefuse.py and espsecure.py. Need to do the following steps: .. code-block:: bash @@ -348,7 +345,7 @@ To use a host generated key, take the following steps: espefuse.py --port PORT burn_key BLOCK my_flash_encryption_key.bin XTS_AES_128_KEY - where `BLOCK` is a free keyblock between `BLOCK_KEY0` and `BLOCK_KEY5`. + where ``BLOCK`` is a free keyblock between ``BLOCK_KEY0`` and ``BLOCK_KEY5``. If the key is not burned and the device is started after enabling flash encryption, the {IDF_TARGET_NAME} will generate a random key that software cannot access or modify. @@ -706,9 +703,9 @@ Key Points About Flash Encryption :esp32: - The flash encryption algorithm is AES-256, where the key is "tweaked" with the offset address of each 32 byte block of flash. This means that every 32-byte block (two consecutive 16 byte AES blocks) is encrypted with a unique key derived from the flash encryption key. - :esp32s2 or esp32s3: - Flash memory contents is encrypted using XTS-AES-128 or XTS-AES-256. The flash encryption key is 256 bits and 512 bits respectively and stored one or two ``BLOCK_KEYN`` eFuses internal to the chip and, by default, is protected from software access. + :esp32s2 or esp32s3: - Flash memory contents is encrypted using XTS-AES-128 or XTS-AES-256. The flash encryption key is 256 bits and 512 bits respectively and stored in one or two ``BLOCK_KEYN`` eFuses internal to the chip and, by default, is protected from software access. - :esp32c3: - Flash memory contents is encrypted using XTS-AES-128. The flash encryption key is 256 bits and stored one``BLOCK_KEYN`` eFuse internal to the chip and, by default, is protected from software access. + :esp32c3: - Flash memory contents is encrypted using XTS-AES-128. The flash encryption key is 256 bits and stored in one ``BLOCK_KEYN`` eFuse internal to the chip and, by default, is protected from software access. - Flash access is transparent via the flash cache mapping feature of {IDF_TARGET_NAME} - any flash regions which are mapped to the address space will be transparently decrypted when read. @@ -733,6 +730,7 @@ Limitations of Flash Encryption Flash encryption protects firmware against unauthorised readout and modification. It is important to understand the limitations of the flash encryption feature: .. list:: + - Flash encryption is only as strong as the key. For this reason, we recommend keys are generated on the device during first boot (default behaviour). If generating keys off-device, ensure proper procedure is followed and don't share the same key between all production devices. - Not all data is stored encrypted. If storing data on flash, check if the method you are using (library, API, etc.) supports flash encryption. - Flash encryption does not prevent an attacker from understanding the high-level layout of the flash. This is because the same AES key is used for every pair of adjacent 16 byte AES blocks. When these adjacent 16 byte blocks contain identical content (such as empty or padding areas), these blocks will encrypt to produce matching pairs of encrypted blocks. This may allow an attacker to make high-level comparisons between encrypted devices (i.e. to tell if two devices are probably running the same firmware version). @@ -751,8 +749,8 @@ It is recommended to use flash encryption in combination with Secure Boot. Howev .. only:: esp32 - :ref:`Plaintext serial flash updates ` are only possible if the :ref:`Re-flashable ` Secure Boot mode is selected and a Secure Boot key was pre-generated and burned to the {IDF_TARGET_NAME} (refer to :ref:`Secure Boot `). In such configuration, ``idf.py bootloader`` will produce a pre-digested bootloader and secure boot digest file for flashing at offset 0x0. When following the plaintext serial re-flashing steps it is necessary to re-flash this file before flashing other plaintext data. - - :ref:`Re-flashing via Pregenerated Flash Encryption Key ` is still possible, provided the bootloader is not re-flashed. Re-flashing the bootloader requires the same :ref:`Re-flashable ` option to be enabled in the Secure Boot config. + - :ref:`Re-flashing via Pregenerated Flash Encryption Key ` is still possible, provided the bootloader is not re-flashed. Re-flashing the bootloader requires the same :ref:`Re-flashable ` option to be enabled in the Secure Boot config. .. _flash-encryption-advanced-features: @@ -854,7 +852,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 or the firmware bootloader, this value is set to the maximum ``0xF``. + On the first boot of the firmware 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. @@ -956,7 +954,7 @@ The following sections provide some reference information about the operation of - There is a particular mapping from each of the 19 block offset bits to the 256 bits of the flash encryption key to determine which bit is XORed with which. See the variable ``_FLASH_ENCRYPTION_TWEAK_PATTERN`` in the ``espsecure.py`` source code for complete mapping. - - To see the full flash encryption algorithm implemented in Python, refer to the `_flash_encryption_operation()` function in the ``espsecure.py`` source code. + - To see the full flash encryption algorithm implemented in Python, refer to the ``_flash_encryption_operation()`` function in the ``espsecure.py`` source code. .. only:: SOC_FLASH_ENCRYPTION_XTS_AES_256 @@ -964,9 +962,10 @@ The following sections provide some reference information about the operation of Flash Encryption Algorithm ^^^^^^^^^^^^^^^^^^^^^^^^^^ + - {IDF_TARGET_NAME} use the XTS-AES block cipher mode with 256 bit or 512 bit key size for flash encryption. - - XTS-AES is a block chiper mode specifically designed for disc encryption and addresses the weaknesses other potential modes (e.g. AES-CTR) have for this use case. A detailed description of the XTS-AES algorithm can be found in `IEEE Std 1619-2007 `_. + - XTS-AES is a block cipher mode specifically designed for disc encryption and addresses the weaknesses other potential modes (e.g. AES-CTR) have for this use case. A detailed description of the XTS-AES algorithm can be found in `IEEE Std 1619-2007 `_. - The flash encryption key is stored in one or two ``BLOCK_KEYN`` eFuses and, by default, is protected from further writes or software readout. @@ -978,6 +977,7 @@ The following sections provide some reference information about the operation of Flash Encryption Algorithm ^^^^^^^^^^^^^^^^^^^^^^^^^^ + - {IDF_TARGET_NAME} use the XTS-AES block chiper mode with 256 bit size for flash encryption. - XTS-AES is a block chiper mode specifically designed for disc encryption and addresses the weaknesses other potential modes (e.g. AES-CTR) have for this use case. A detailed description of the XTS-AES algorithm can be found in `IEEE Std 1619-2007 `_. diff --git a/docs/en/security/secure-boot-v2.rst b/docs/en/security/secure-boot-v2.rst index 222f3ba109..c1a1710512 100644 --- a/docs/en/security/secure-boot-v2.rst +++ b/docs/en/security/secure-boot-v2.rst @@ -26,7 +26,7 @@ Background ---------- Secure Boot protects a device from running unsigned code (verification at time of load). A new RSA based secure boot -verification scheme (Secure Boot V2) has been introduced for ESP32-S2, ESP32-C3 ECO3 onwards, and ESP32 ECO3 onwards. +verification scheme (Secure Boot V2) has been introduced for ESP32-S2, ESP32-S3, ESP32-C3 ECO3 onwards, and ESP32 ECO3 onwards. - The software bootloader’s RSA-PSS signature is verified by the Mask ROM and it is executed post successful verification. - The verified software bootloader verifies the RSA-PSS signature of the application image before it is executed. @@ -36,11 +36,11 @@ Advantages - The RSA public key is stored on the device. The corresponding RSA private key is kept secret on a server and is never accessed by the device. - .. only:: esp32 +.. only:: esp32 - Only one public key can be generated and stored in ESP32 ECO3 during manufacturing. - .. only:: esp32s2 or esp32c3 +.. only:: esp32s2 or esp32c3 or esp32s3 - Up to three public keys can be generated and stored in the chip during manufacturing. @@ -117,7 +117,7 @@ A signature block is “valid” if the first byte is 0xe7 and a valid CRC32 is Only one signature block can be appended to the bootloader or application image in ESP32 ECO3. - .. only:: esp32s2 or esp32c3 + .. only:: esp32s2 or esp32c3 or esp32s3 Upto 3 signature blocks can be appended to the bootloader or application image in {IDF_TARGET_NAME}. @@ -152,15 +152,15 @@ eFuse usage - ABS_DONE_1 - Enables secure boot protection on boot. - - BLK2 - Stores the SHA-256 digest of the public key. SHA-256 hash of public key modulus, exponent, precalculated R & M’ values (represented as 776 bytes – offsets 36 to 812 - as per the :ref:`signature-block-format`) is written to an eFuse key block. + - BLK2 - Stores the SHA-256 digest of the public key. SHA-256 hash of public key modulus, exponent, precalculated R & M’ values (represented as 776 bytes – offsets 36 to 812 - as per the :ref:`signature-block-format`) is written to an eFuse key block. The write-protection bit must be set, but the read-protection bit must not. -.. only:: esp32s2 or esp32c3 +.. only:: esp32s2 or esp32c3 or esp32s3 - SECURE_BOOT_EN - Enables secure boot protection on boot. - - KEY_PURPOSE_X - Set the purpose of the key block on {IDF_TARGET_NAME} by programming SECURE_BOOT_DIGESTX (X = 0, 1, 2) into KEY_PURPOSE_X (X = 0, 1, 2, 3, 4, 5). Example: If KEY_PURPOSE_2 is set to SECURE_BOOT_DIGEST1, then BLOCK_KEY2 will have the Secure Boot V2 public key digest. + - KEY_PURPOSE_X - Set the purpose of the key block on {IDF_TARGET_NAME} by programming SECURE_BOOT_DIGESTX (X = 0, 1, 2) into KEY_PURPOSE_X (X = 0, 1, 2, 3, 4, 5). Example: If KEY_PURPOSE_2 is set to SECURE_BOOT_DIGEST1, then BLOCK_KEY2 will have the Secure Boot V2 public key digest. The write-protection bit must be set (this field does not have a read-protection bit). - - BLOCK_KEYX - The block contains the data corresponding to its purpose programmed in KEY_PURPOSE_X. Stores the SHA-256 digest of the public key. SHA-256 hash of public key modulus, exponent, precalculated R & M’ values (represented as 776 bytes – offsets 36 to 812 - as per the :ref:`signature-block-format`) is written to an eFuse key block. + - BLOCK_KEYX - The block contains the data corresponding to its purpose programmed in KEY_PURPOSE_X. Stores the SHA-256 digest of the public key. SHA-256 hash of public key modulus, exponent, precalculated R & M’ values (represented as 776 bytes – offsets 36 to 812 - as per the :ref:`signature-block-format`) is written to an eFuse key block. The write-protection bit must be set, but the read-protection bit must not. - KEY_REVOKEX - The revocation bits corresponding to each of the 3 key block. Ex. Setting KEY_REVOKE2 revokes the key block whose key purpose is SECURE_BOOT_DIGEST2. @@ -168,6 +168,8 @@ eFuse usage To ensure no trusted keys can be added later by an attacker, each unused key digest slot should be revoked (KEY_REVOKEX). It will be checked during app startup in :cpp:func:`esp_secure_boot_init_checks` and fixed unless :ref:`CONFIG_SECURE_BOOT_ALLOW_UNUSED_DIGEST_SLOTS` is enabled. +The key(s) must be readable in order to give software access to it. If the key(s) is read-protected then the software reads the key(s) as all zeros and the signature verification process occurs with error, bootloader and app can not be run. + .. _secure-boot-v2-howto: How To Enable Secure Boot V2 @@ -183,7 +185,7 @@ How To Enable Secure Boot V2 4. Select the desired UART ROM download mode in "UART ROM download mode". By default the UART ROM download mode has been kept enabled in order to prevent permanently disabling it in the development phase, this option is a potentially insecure option. It is recommended to disable the UART download mode for better security. -.. only:: esp32s2 or esp32c3 +.. only:: esp32s2 or esp32c3 or esp32s3 2. The "Secure Boot V2" option will be selected and the "App Signing Scheme" would be set to RSA by default. @@ -267,7 +269,7 @@ Secure Boot Best Practices * Enable all secure boot options in the Secure Boot Configuration. These include flash encryption, disabling of JTAG, disabling BASIC ROM interpeter, and disabling the UART bootloader encrypted flash access. * Use secure boot in combination with :doc:`flash encryption` to prevent local readout of the flash contents. -.. only:: esp32s2 or esp32c3 +.. only:: esp32s2 or esp32c3 or esp32s3 Key Management -------------- diff --git a/docs/extensions/README.md b/docs/extensions/README.md deleted file mode 100644 index e32b49af06..0000000000 --- a/docs/extensions/README.md +++ /dev/null @@ -1 +0,0 @@ -See docs/en/contribute/add-ons-reference.rst (or in the IDF docs) for details. diff --git a/docs/extensions/google_analytics.py b/docs/extensions/google_analytics.py deleted file mode 100644 index e565318169..0000000000 --- a/docs/extensions/google_analytics.py +++ /dev/null @@ -1,30 +0,0 @@ -# Embeds a google analytics tracking tag in every HTML page -def setup(app): - app.add_config_value('google_analytics_id', None, 'html') - app.connect('html-page-context', google_analytics_embed) - - return {'parallel_read_safe': True, 'parallel_write_safe': True, 'version': '0.1'} - - -def google_analytics_embed(app, pagename, templatename, context, doctree): - - ga_id = app.config.google_analytics_id - if not ga_id: - return - - metatags = context.get('metatags', '') - - google_analytics_snippet = """ - - - """.format(ga_id, ga_id) - - # Prepend the google analytics to the HTML metatags (which will be passed to the sphinx templating engine) - metatags = google_analytics_snippet + metatags - context['metatags'] = metatags diff --git a/docs/extensions/html_redirects.py b/docs/extensions/html_redirects.py deleted file mode 100644 index 52b6a32373..0000000000 --- a/docs/extensions/html_redirects.py +++ /dev/null @@ -1,82 +0,0 @@ -# Copyright 2018-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. -# - - -# Mechanism to generate static HTML redirect pages in the output -# -# Uses redirect_template.html and the list of pages given in -# the file conf.html_redirect_pages -# -# Redirections can be internal or absolute (i.e., external). -# - Internal redirects are supplied without quotation marks and must be relative to the document root -# - External redirects are wrapped in doulbe quotation marks and are used verbatim -# -# Adapted from ideas in https://tech.signavio.com/2017/managing-sphinx-redirects -import os.path - -from sphinx.builders.html import StandaloneHTMLBuilder - -REDIRECT_TEMPLATE = """ - - - - - - -

Page has moved here.

- - -""" - - -def setup(app): - app.add_config_value('html_redirect_pages', [], 'html') - # attaching to this event is a hack, but it's a convenient stage in the build - # to create HTML redirects - app.connect('html-collect-pages', create_redirect_pages) - - return {'parallel_read_safe': True, 'parallel_write_safe': True, 'version': '0.1'} - - -def create_redirect_pages(app): - if not isinstance(app.builder, StandaloneHTMLBuilder): - return # only relevant for standalone HTML output - - for (old_url, new_url) in app.config.html_redirect_pages: - if old_url.startswith('/'): - print('Stripping leading / from URL in config file...') - old_url = old_url[1:] - out_file = app.builder.get_outfilename(old_url) - - if new_url.startswith('\"') and new_url.endswith('\"'): - # This is an absolute redirect. Slice away the surrouding quotation marks and copy the url verbatim - new_url = new_url[1:-1] - else: - # This is an internal redirect. Find the relative url to the target document - new_url = app.builder.get_relative_uri(old_url, new_url) - - print('HTML file %s redirects to URL %s' % (out_file, new_url)) - out_dir = os.path.dirname(out_file) - if not os.path.exists(out_dir): - os.makedirs(out_dir) - - content = REDIRECT_TEMPLATE.replace('$NEWURL', new_url) - - with open(out_file, 'w') as rp: - rp.write(content) - - return [] diff --git a/docs/extensions/list_filter.py b/docs/extensions/list_filter.py deleted file mode 100644 index e1a81b328c..0000000000 --- a/docs/extensions/list_filter.py +++ /dev/null @@ -1,60 +0,0 @@ -import re - -from docutils import nodes -from docutils.parsers.rst import Directive - - -def setup(app): - app.add_directive('list', ListFilter) - - return {'parallel_read_safe': True, 'parallel_write_safe': True, 'version': '0.1'} - - -class ListFilter(Directive): - """ - Provides a list implementation directive that support clauses of the kind - - .. list:: - - - Content - :filter: - Content - - Content - - Where the :filter: part becomes selective to only include the content if - one of the provided tags is set, same as the logic used by the "only" directive. - - The directive also works for numbered list. - - """ - RE_PATTERN = re.compile(r'^\s*:(.+?):\s*(.+)$') - has_content = True - required_arguments = 0 - optional_arguments = 0 - final_argument_whitespace = True - option_spec = {} - - def run(self): - # Raise an error if the directive does not have contents. - self.assert_has_content() - - # Remove all list entries that should not be on display - env = self.state.document.settings.env - filt_data = [self.filter_entry(env, e) for e in self.content.data if e is not None] - - # Clean up deleted values from content - self.content.data = [data for data in filt_data if data is not None] - self.content.items = [items for data, items in zip(filt_data, self.content.items) if data is not None] - - # Parse the filtered content and return the new node - node = nodes.paragraph() - self.state.nested_parse(self.content, self.content_offset, node) - - return [node] - - def filter_entry(self, env, entry): - m = self.RE_PATTERN.match(entry) - if m is not None: - tag_filter, entry = m.groups() - if not env.app.builder.tags.eval_condition(tag_filter): - return None - return entry diff --git a/docs/extensions/toctree_filter.py b/docs/extensions/toctree_filter.py deleted file mode 100644 index 8f0a455d89..0000000000 --- a/docs/extensions/toctree_filter.py +++ /dev/null @@ -1,43 +0,0 @@ -# Based on https://stackoverflow.com/a/46600038 with some modifications -import re - -from sphinx.directives.other import TocTree - - -def setup(app): - app.add_directive('toctree', TocTreeFilt, override=True) - - return {'parallel_read_safe': True, 'parallel_write_safe': True, 'version': '0.1'} - - -class TocTreeFilt(TocTree): - """ - Override normal toctree directive to support clauses of the kind - - :filter: Name - - Where the :filter: part becomes selective to only include the document if - one of the provided tags is set, same as the logic used by the "only" directive. - - If no :filter: is supplied, works the same as default Sphinx :toctree: - - Note that excluding via filter doesn't prevent Sphinx from finding these .rst files - when it scan the src/ directory, so it's also necessary to make sure that the files - are covered by the exclude_patterns list in conf.py - """ - RE_PATTERN = re.compile(r'^\s*:(.+?):\s*(.+)$') - - def run(self): - # Remove all TOC entries that should not be on display - env = self.state.document.settings.env - self.content = [self.filter_entry(env, e) for e in self.content if e is not None] - - return super(TocTreeFilt, self).run() - - def filter_entry(self, env, entry): - m = self.RE_PATTERN.match(entry) - if m is not None: - tag_filter, entry = m.groups() - if not env.app.builder.tags.eval_condition(tag_filter): - return None - return entry diff --git a/docs/get_github_rev.py b/docs/get_github_rev.py deleted file mode 100644 index 7dc2da5635..0000000000 --- a/docs/get_github_rev.py +++ /dev/null @@ -1,15 +0,0 @@ -import subprocess - - -# Get revision used for constructing github URLs -def get_github_rev(): - path = subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD']).strip().decode('utf-8') - try: - tag = subprocess.check_output(['git', 'describe', '--exact-match']).strip().decode('utf-8') - except subprocess.CalledProcessError: - tag = None - print('Git commit ID: ', path) - if tag: - print('Git tag: ', tag) - return tag - return path diff --git a/docs/idf_extensions/README.md b/docs/idf_extensions/README.md deleted file mode 100644 index 0d7cb9d910..0000000000 --- a/docs/idf_extensions/README.md +++ /dev/null @@ -1,2 +0,0 @@ -See docs/en/contribute/add-ons-reference.rst (or in the IDF docs) for details. - diff --git a/docs/idf_extensions/build_system/__init__.py b/docs/idf_extensions/build_system/__init__.py deleted file mode 100644 index 27d0e8cf01..0000000000 --- a/docs/idf_extensions/build_system/__init__.py +++ /dev/null @@ -1,97 +0,0 @@ -# Sphinx extension to integrate IDF build system information -# into the Sphinx Build -# -# Runs early in the Sphinx process, runs CMake to generate the dummy IDF project -# in this directory - including resolving paths, etc. -# -# Then emits the new 'idf-info' event which has information read from IDF -# build system, that other extensions can use to generate relevant data. -import json -import os.path -import shutil -import subprocess -import sys - -# this directory also contains the dummy IDF project -project_path = os.path.abspath(os.path.dirname(__file__)) - -# Targets which needs --preview to build -PREVIEW_TARGETS = ['esp32s3'] - - -def setup(app): - # Setup some common paths - - try: - build_dir = os.environ['BUILDDIR'] # TODO see if we can remove this - except KeyError: - build_dir = os.path.dirname(app.doctreedir.rstrip(os.sep)) - - try: - os.mkdir(build_dir) - except OSError: - pass - - try: - os.mkdir(os.path.join(build_dir, 'inc')) - except OSError: - pass - - # Fill in a default IDF_PATH if it's missing (ie when Read The Docs is building the docs) - try: - idf_path = os.environ['IDF_PATH'] - except KeyError: - idf_path = os.path.realpath(os.path.join(os.path.dirname(__file__), '..')) - - app.add_config_value('docs_root', os.path.join(idf_path, 'docs'), 'env') - app.add_config_value('idf_path', idf_path, 'env') - app.add_config_value('build_dir', build_dir, 'env') # not actually an IDF thing - app.add_event('idf-info') - - # we want this to run early in the docs build but unclear exactly when - app.connect('config-inited', generate_idf_info) - - return {'parallel_read_safe': True, 'parallel_write_safe': True, 'version': '0.1'} - - -def generate_idf_info(app, config): - print('Running CMake on dummy project to get build info...') - build_dir = os.path.dirname(app.doctreedir.rstrip(os.sep)) - cmake_build_dir = os.path.join(build_dir, 'build_dummy_project') - idf_py_path = os.path.join(app.config.idf_path, 'tools', 'idf.py') - print('Running idf.py...') - idf_py = [sys.executable, - idf_py_path, - '-B', - cmake_build_dir, - '-C', - project_path, - '-D', - 'SDKCONFIG={}'.format(os.path.join(build_dir, 'dummy_project_sdkconfig')) - ] - - # force a clean idf.py build w/ new sdkconfig each time - # (not much slower than 'reconfigure', avoids any potential config & build versioning problems - shutil.rmtree(cmake_build_dir, ignore_errors=True) - print('Starting new dummy IDF project... ') - - if (app.config.idf_target in PREVIEW_TARGETS): - subprocess.check_call(idf_py + ['--preview', 'set-target', app.config.idf_target]) - else: - subprocess.check_call(idf_py + ['set-target', app.config.idf_target]) - - print('Running CMake on dummy project...') - subprocess.check_call(idf_py + ['reconfigure']) - - with open(os.path.join(cmake_build_dir, 'project_description.json')) as f: - project_description = json.load(f) - if project_description['target'] != app.config.idf_target: - # this shouldn't really happen unless someone has been moving around directories inside _build, as - # the cmake_build_dir path should be target-specific - raise RuntimeError(('Error configuring the dummy IDF project for {}. ' + - 'Target in project description is {}. ' + - 'Is build directory contents corrupt?') - .format(app.config.idf_target, project_description['target'])) - app.emit('idf-info', project_description) - - return [] diff --git a/docs/idf_extensions/esp_err_definitions.py b/docs/idf_extensions/esp_err_definitions.py deleted file mode 100644 index ecf9719300..0000000000 --- a/docs/idf_extensions/esp_err_definitions.py +++ /dev/null @@ -1,14 +0,0 @@ -# Extension to generate esp_err definition as .rst -from .util import call_with_python, copy_if_modified - - -def setup(app): - app.connect('idf-info', generate_err_defs) - return {'parallel_read_safe': True, 'parallel_write_safe': True, 'version': '0.1'} - - -def generate_err_defs(app, project_description): - # Generate 'esp_err_defs.inc' file with ESP_ERR_ error code definitions from inc file - esp_err_inc_path = '{}/inc/esp_err_defs.inc'.format(app.config.build_dir) - call_with_python('{}/tools/gen_esp_err_to_name.py --rst_output {}.in'.format(app.config.idf_path, esp_err_inc_path)) - copy_if_modified(esp_err_inc_path + '.in', esp_err_inc_path) diff --git a/docs/idf_extensions/exclude_docs.py b/docs/idf_extensions/exclude_docs.py deleted file mode 100644 index d06721377f..0000000000 --- a/docs/idf_extensions/exclude_docs.py +++ /dev/null @@ -1,53 +0,0 @@ -from sphinx.util import get_matching_files -from sphinx.util.matching import compile_matchers - - -# Updates the excluded documents according to the conditional_include_dict {tag:documents} -def update_exclude_patterns(app, config): - - # Default to building all if option not set - if config.docs_to_build: - build_subset(app, config) - - include_set = set() - exclude_set = set() - - for tag, docs in config.conditional_include_dict.items(): - if not app.tags.has(tag): - exclude_set.update(docs) - else: - include_set.update(docs) - # Do not exclude docs that have been explicitly included, e.g. if a doc is listed in both - # ESP32_DOCS and ESP32S2_DOCS it will be included for those targets. - app.config.exclude_patterns.extend(exclude_set - include_set) - - -def build_subset(app, config): - # Convert to list of docs to build - docs_to_build = config.docs_to_build.split(',') - - # Exclude all documents which were not set as docs_to_build when build_docs were called - exclude_docs = [filename for filename in get_matching_files(app.srcdir, compile_matchers(docs_to_build))] - docs = [filename for filename in get_matching_files(app.srcdir, compile_matchers(exclude_docs))] - - app.config.exclude_patterns.extend(exclude_docs) - - # Get all docs that will be built - docs = [filename for filename in get_matching_files(app.srcdir, compile_matchers(exclude_docs))] - if not docs: - raise ValueError('No documents to build') - print('Building a subset of the documents: {}'.format(docs)) - - # Sphinx requires a master document, if there is a document name 'index' then we pick that - index_docs = [doc for doc in docs if 'index' in doc] - if index_docs: - config.master_doc = index_docs[0].replace('.rst', '') - else: - config.master_doc = docs[0].replace('.rst', '') - - -def setup(app): - # Tags are generated together with defines - app.connect('config-inited', update_exclude_patterns) - - return {'parallel_read_safe': True, 'parallel_write_safe': True, 'version': '0.1'} diff --git a/docs/idf_extensions/format_idf_target.py b/docs/idf_extensions/format_idf_target.py deleted file mode 100644 index d0641eef1a..0000000000 --- a/docs/idf_extensions/format_idf_target.py +++ /dev/null @@ -1,229 +0,0 @@ -import os -import os.path -import re - -from docutils import io, nodes, statemachine, utils -from docutils.parsers.rst import directives -from docutils.utils.error_reporting import ErrorString, SafeString -from sphinx.directives.other import Include as BaseInclude -from sphinx.util import logging - - -def setup(app): - sub = StringSubstituter() - - # Config values not available when setup is called - app.connect('config-inited', lambda _, config: sub.init_sub_strings(config)) - app.connect('source-read', sub.substitute_source_read_cb) - - # Override the default include directive to include formatting with idf_target - # This is needed since there are no source-read events for includes - app.add_directive('include', FormatedInclude, override=True) - - return {'parallel_read_safe': True, 'parallel_write_safe': True, 'version': '0.2'} - - -def check_content(content, docname): - # Log warnings for any {IDF_TARGET} expressions that haven't been replaced - logger = logging.getLogger(__name__) - - errors = re.findall(r'{IDF_TARGET.*?}', content) - - for err in errors: - logger.warning('Badly formated string substitution: {}'.format(err), location=docname) - - -class StringSubstituter: - """ Allows for string substitution of target related strings - before any markup is parsed - - Supports the following replacements (examples shown is for target=esp32s2): - {IDF_TARGET_NAME}, replaced with the current target name, e.g. ESP32-S2 Beta - {IDF_TARGET_TOOLCHAIN_PREFIX}, replaced with the toolchain prefix, e.g. xtensa-esp32-elf - {IDF_TARGET_PATH_NAME}, replaced with the path name, e.g. esp32s2 - {IDF_TARGET_CFG_PREFIX}, replaced with the prefix used for config parameters, e.g. ESP32S2 - {IDF_TARGET_TRM_EN_URL}, replaced with the url to the English technical reference manual - {IDF_TARGET_TRM_CH_URL}, replaced with the url to the Chinese technical reference manual - - Also supports defines of local (single rst file) with the format: - {IDF_TARGET_TX_PIN:default="IO3",esp32="IO4",esp32s2="IO5"} - - This will define a replacement of the tag {IDF_TARGET_TX_PIN} in the current rst-file, see e.g. uart.rst for example - - """ - TARGET_NAMES = {'esp32': 'ESP32', 'esp32s2': 'ESP32-S2', 'esp32s3': 'ESP32-S3', 'esp32c3': 'ESP32-C3'} - TOOLCHAIN_PREFIX = {'esp32': 'xtensa-esp32-elf', 'esp32s2': 'xtensa-esp32s2-elf', 'esp32s3': 'xtensa-esp32s3-elf', 'esp32c3': 'riscv32-esp-elf'} - CONFIG_PREFIX = {'esp32': 'ESP32', 'esp32s2': 'ESP32S2', 'esp32s3': 'ESP32S3', 'esp32c3': 'ESP32C3'} - - TRM_EN_URL = {'esp32': 'https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf', - 'esp32s2': 'https://www.espressif.com/sites/default/files/documentation/esp32-s2_technical_reference_manual_en.pdf', - 'esp32s3': 'https://www.espressif.com/sites/default/files/documentation/esp32-s3_technical_reference_manual_en.pdf', - 'esp32c3': 'https://www.espressif.com/sites/default/files/documentation/esp32-c3_technical_reference_manual_en.pdf'} - - TRM_CN_URL = {'esp32': 'https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_cn.pdf', - 'esp32s2': 'https://www.espressif.com/sites/default/files/documentation/esp32-s2_technical_reference_manual_cn.pdf', - 'esp32s3': 'https://www.espressif.com/sites/default/files/documentation/esp32-s3_technical_reference_manual_cn.pdf', - 'esp32c3': 'https://www.espressif.com/sites/default/files/documentation/esp32-c3_technical_reference_manual_cn.pdf'} - RE_PATTERN = re.compile(r'^\s*{IDF_TARGET_(\w+?):(.+?)}', re.MULTILINE) - - def __init__(self): - self.substitute_strings = {} - self.local_sub_strings = {} - - def add_pair(self, tag, replace_value): - self.substitute_strings[tag] = replace_value - - def init_sub_strings(self, config): - self.target_name = config.idf_target - - self.add_pair('{IDF_TARGET_NAME}', self.TARGET_NAMES[config.idf_target]) - self.add_pair('{IDF_TARGET_PATH_NAME}', config.idf_target) - self.add_pair('{IDF_TARGET_TOOLCHAIN_PREFIX}', self.TOOLCHAIN_PREFIX[config.idf_target]) - self.add_pair('{IDF_TARGET_CFG_PREFIX}', self.CONFIG_PREFIX[config.idf_target]) - self.add_pair('{IDF_TARGET_TRM_EN_URL}', self.TRM_EN_URL[config.idf_target]) - self.add_pair('{IDF_TARGET_TRM_CN_URL}', self.TRM_CN_URL[config.idf_target]) - - def add_local_subs(self, matches): - - for sub_def in matches: - if len(sub_def) != 2: - raise ValueError('IDF_TARGET_X substitution define invalid, val={}'.format(sub_def)) - - tag = '{' + 'IDF_TARGET_{}'.format(sub_def[0]) + '}' - - match_default = re.match(r'^\s*default(\s*)=(\s*)\"(.*?)\"', sub_def[1]) - - if match_default is None: - # There should always be a default value - raise ValueError('No default value in IDF_TARGET_X substitution define, val={}'.format(sub_def)) - - match_target = re.match(r'^.*{}(\s*)=(\s*)\"(.*?)\"'.format(self.target_name), sub_def[1]) - - if match_target is None: - sub_value = match_default.groups()[2] - else: - sub_value = match_target.groups()[2] - - self.local_sub_strings[tag] = sub_value - - def substitute(self, content): - # Add any new local tags that matches the reg.ex. - sub_defs = re.findall(self.RE_PATTERN, content) - - if len(sub_defs) != 0: - self.add_local_subs(sub_defs) - - # Remove the tag defines - content = re.sub(self.RE_PATTERN,'', content) - - for key in self.local_sub_strings: - content = content.replace(key, self.local_sub_strings[key]) - - self.local_sub_strings = {} - - for key in self.substitute_strings: - content = content.replace(key, self.substitute_strings[key]) - - return content - - def substitute_source_read_cb(self, app, docname, source): - source[0] = self.substitute(source[0]) - - check_content(source[0], docname) - - -class FormatedInclude(BaseInclude): - - """ - Include and format content read from a separate source file. - - Code is based on the default include directive from docutils - but extended to also format the content according to IDF target. - - """ - def run(self): - - # For code or literal include blocks we run the normal include - if 'literal' in self.options or 'code' in self.options: - return super(FormatedInclude, self).run() - - """Include a file as part of the content of this reST file.""" - if not self.state.document.settings.file_insertion_enabled: - raise self.warning('"%s" directive disabled.' % self.name) - source = self.state_machine.input_lines.source( - self.lineno - self.state_machine.input_offset - 1) - - source_dir = os.path.dirname(os.path.abspath(source)) - - rel_filename, filename = self.env.relfn2path(self.arguments[0]) - self.arguments[0] = filename - self.env.note_included(filename) - path = directives.path(self.arguments[0]) - - if path.startswith('<') and path.endswith('>'): - path = os.path.join(self.standard_include_path, path[1:-1]) - path = os.path.normpath(os.path.join(source_dir, path)) - - path = utils.relative_path(None, path) - path = nodes.reprunicode(path) - - encoding = self.options.get( - 'encoding', self.state.document.settings.input_encoding) - e_handler = self.state.document.settings.input_encoding_error_handler - tab_width = self.options.get( - 'tab-width', self.state.document.settings.tab_width) - try: - self.state.document.settings.record_dependencies.add(path) - include_file = io.FileInput(source_path=path, - encoding=encoding, - error_handler=e_handler) - except UnicodeEncodeError: - raise self.severe(u'Problems with "%s" directive path:\n' - 'Cannot encode input file path "%s" ' - '(wrong locale?).' % - (self.name, SafeString(path))) - except IOError as error: - raise self.severe(u'Problems with "%s" directive path:\n%s.' % - (self.name, ErrorString(error))) - startline = self.options.get('start-line', None) - endline = self.options.get('end-line', None) - try: - if startline or (endline is not None): - lines = include_file.readlines() - rawtext = ''.join(lines[startline:endline]) - else: - rawtext = include_file.read() - except UnicodeError as error: - raise self.severe(u'Problem with "%s" directive:\n%s' % - (self.name, ErrorString(error))) - - # Format input - sub = StringSubstituter() - config = self.state.document.settings.env.config - sub.init_sub_strings(config) - rawtext = sub.substitute(rawtext) - - # start-after/end-before: no restrictions on newlines in match-text, - # and no restrictions on matching inside lines vs. line boundaries - after_text = self.options.get('start-after', None) - if after_text: - # skip content in rawtext before *and incl.* a matching text - after_index = rawtext.find(after_text) - if after_index < 0: - raise self.severe('Problem with "start-after" option of "%s" ' - 'directive:\nText not found.' % self.name) - rawtext = rawtext[after_index + len(after_text):] - before_text = self.options.get('end-before', None) - if before_text: - # skip content in rawtext after *and incl.* a matching text - before_index = rawtext.find(before_text) - if before_index < 0: - raise self.severe('Problem with "end-before" option of "%s" ' - 'directive:\nText not found.' % self.name) - rawtext = rawtext[:before_index] - - include_lines = statemachine.string2lines(rawtext, tab_width, - convert_whitespace=True) - - self.state_machine.insert_input(include_lines, path) - return [] diff --git a/docs/idf_extensions/gen_defines.py b/docs/idf_extensions/gen_defines.py deleted file mode 100644 index 5962da2c4a..0000000000 --- a/docs/idf_extensions/gen_defines.py +++ /dev/null @@ -1,84 +0,0 @@ -# Sphinx extension to integrate defines into the Sphinx Build -# -# Runs after the IDF dummy project has been built -# -# Then emits the new 'idf-defines-generated' event which has a dictionary of raw text define values -# that other extensions can use to generate relevant data. - -import glob -import os -import pprint -import re -import subprocess - - -def generate_defines(app, project_description): - sdk_config_path = os.path.join(project_description['build_dir'], 'config') - - # Parse kconfig macros to pass into doxygen - # - # TODO: this should use the set of "config which can't be changed" eventually, - # not the header - defines = get_defines(os.path.join(project_description['build_dir'], - 'config', 'sdkconfig.h'), sdk_config_path) - - # Add all SOC _caps.h headers and kconfig macros to the defines - # - # kind of a hack, be nicer to add a component info dict in project_description.json - soc_path = [p for p in project_description['build_component_paths'] if p.endswith('/soc')][0] - soc_headers = glob.glob(os.path.join(soc_path, project_description['target'], - 'include', 'soc', '*_caps.h')) - assert len(soc_headers) > 0 - - for soc_header in soc_headers: - defines.update(get_defines(soc_header, sdk_config_path)) - - # write a list of definitions to make debugging easier - with open(os.path.join(app.config.build_dir, 'macro-definitions.txt'), 'w') as f: - pprint.pprint(defines, f) - print('Saved macro list to %s' % f.name) - - add_tags(app, defines) - - app.emit('idf-defines-generated', defines) - - -def get_defines(header_path, sdk_config_path): - defines = {} - # Note: we run C preprocessor here without any -I arguments (except "sdkconfig.h"), so assumption is - # that these headers are all self-contained and don't include any other headers - # not in the same directory - print('Reading macros from %s...' % (header_path)) - processed_output = subprocess.check_output(['xtensa-esp32-elf-gcc', '-I', sdk_config_path, - '-dM', '-E', header_path]).decode() - for line in processed_output.split('\n'): - line = line.strip() - m = re.search('#define ([^ ]+) ?(.*)', line) - if m: - name = m.group(1) - value = m.group(2) - if name.startswith('_'): - continue # toolchain macro - if (' ' in value) or ('=' in value): - value = '' # macros that expand to multiple tokens (ie function macros) cause doxygen errors, so just mark as 'defined' - defines[name] = value - - return defines - - -def add_tags(app, defines): - # try to parse define values as ints and add to tags - for name, value in defines.items(): - try: - define_value = int(value.strip('()')) - if define_value > 0: - app.tags.add(name) - except ValueError: - continue - - -def setup(app): - app.connect('idf-info', generate_defines) - app.add_event('idf-defines-generated') - - return {'parallel_read_safe': True, 'parallel_write_safe': True, 'version': '0.2'} diff --git a/docs/idf_extensions/gen_idf_tools_links.py b/docs/idf_extensions/gen_idf_tools_links.py deleted file mode 100644 index c999d84e66..0000000000 --- a/docs/idf_extensions/gen_idf_tools_links.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generate toolchain download links from toolchain info makefile -from __future__ import print_function - -import os.path - -from .util import call_with_python, copy_if_modified - - -def setup(app): - # we don't actually need idf-info, just a convenient event to trigger this on - app.connect('idf-info', generate_idf_tools_links) - - return {'parallel_read_safe': True, 'parallel_write_safe': True, 'version': '0.1'} - - -def generate_idf_tools_links(app, project_description): - print('Generating IDF Tools list') - os.environ['IDF_MAINTAINER'] = '1' - tools_rst = os.path.join(app.config.build_dir, 'inc', 'idf-tools-inc.rst') - tools_rst_tmp = os.path.join(app.config.build_dir, 'idf-tools-inc.rst') - call_with_python('{}/tools/idf_tools.py gen-doc --output {}'.format(app.config.idf_path, tools_rst_tmp)) - copy_if_modified(tools_rst_tmp, tools_rst) diff --git a/docs/idf_extensions/gen_toolchain_links.py b/docs/idf_extensions/gen_toolchain_links.py deleted file mode 100644 index cde0266b75..0000000000 --- a/docs/idf_extensions/gen_toolchain_links.py +++ /dev/null @@ -1,88 +0,0 @@ -# Generate toolchain download links from toolchain info makefile -from __future__ import print_function - -import os.path -from collections import namedtuple - -from .util import copy_if_modified - -BASE_URL = 'https://dl.espressif.com/dl/' - -PlatformInfo = namedtuple('PlatformInfo', [ - 'platform_name', - 'platform_archive_suffix', - 'extension', - 'unpack_cmd', - 'unpack_code' -]) - - -def setup(app): - # we don't actually need idf-info, just a convenient event to trigger this on - app.connect('idf-info', generate_toolchain_download_links) - - return {'parallel_read_safe': True, 'parallel_write_safe': True, 'version': '0.1'} - - -def generate_toolchain_download_links(app, project_description): - print('Generating toolchain download links') - toolchain_tmpdir = '{}/toolchain_inc'.format(app.config.build_dir) - toolchain_versions = os.path.join(app.config.idf_path, 'tools/toolchain_versions.mk') - gen_toolchain_links(toolchain_versions, toolchain_tmpdir) - copy_if_modified(toolchain_tmpdir, '{}/inc'.format(app.config.build_dir)) - - -def gen_toolchain_links(versions_file, out_dir): - version_vars = {} - with open(versions_file) as f: - for line in f: - name, var = line.partition('=')[::2] - version_vars[name.strip()] = var.strip() - - gcc_version = version_vars['CURRENT_TOOLCHAIN_GCC_VERSION'] - toolchain_desc = version_vars['CURRENT_TOOLCHAIN_COMMIT_DESC_SHORT'] - - unpack_code_linux_macos = """ -:: - - mkdir -p ~/esp - cd ~/esp - tar -x{}f ~/Downloads/{} -""" - - scratch_build_code_linux_macos = """ -:: - - git clone https://github.com/espressif/crosstool-NG.git - cd crosstool-NG - git checkout {} - git submodule update --init - ./bootstrap && ./configure --enable-local && make -""" - - platform_info = [ - PlatformInfo('linux64', 'linux-amd64', 'tar.gz', 'z', unpack_code_linux_macos), - PlatformInfo('linux32', 'linux-i686','tar.gz', 'z', unpack_code_linux_macos), - PlatformInfo('osx', 'macos', 'tar.gz', 'z', unpack_code_linux_macos), - PlatformInfo('win32', 'win32', 'zip', None, None) - ] - - try: - os.mkdir(out_dir) - except OSError: - pass - - with open(os.path.join(out_dir, 'download-links.inc'), 'w') as links_file: - for p in platform_info: - archive_name = 'xtensa-esp32-elf-gcc{}-{}-{}.{}'.format( - gcc_version.replace('.', '_'), toolchain_desc, p.platform_archive_suffix, p.extension) - - print('.. |download_link_{}| replace:: {}{}'.format( - p.platform_name, BASE_URL, archive_name), file=links_file) - - if p.unpack_code is not None: - with open(os.path.join(out_dir, 'unpack-code-%s.inc' % p.platform_name), 'w') as f: - print(p.unpack_code.format(p.unpack_cmd, archive_name), file=f) - - with open(os.path.join(out_dir, 'scratch-build-code.inc'), 'w') as code_file: - print(scratch_build_code_linux_macos.format(toolchain_desc), file=code_file) diff --git a/docs/idf_extensions/gen_version_specific_includes.py b/docs/idf_extensions/gen_version_specific_includes.py deleted file mode 100755 index 214d4ba552..0000000000 --- a/docs/idf_extensions/gen_version_specific_includes.py +++ /dev/null @@ -1,218 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# Sphinx extension to generate ReSTructured Text .inc snippets -# with version-based content for this IDF version - -from __future__ import print_function, unicode_literals - -import os -import re -import subprocess -from io import open - -from .util import copy_if_modified - -TEMPLATES = { - 'en': { - 'git-clone-bash': """ -.. code-block:: bash - - mkdir -p ~/esp - cd ~/esp - git clone %(clone_args)s--recursive https://github.com/espressif/esp-idf.git - """, - - 'git-clone-windows': """ -.. code-block:: batch - - mkdir %%userprofile%%\\esp - cd %%userprofile%%\\esp - git clone %(clone_args)s--recursive https://github.com/espressif/esp-idf.git - """, - - 'git-clone-notes': { - 'template': """ -.. note:: - - %(extra_note)s - -.. note:: - - %(zipfile_note)s -""", - 'master': 'This command will clone the master branch, which has the latest development ("bleeding edge") ' - 'version of ESP-IDF. It is fully functional and updated on weekly basis with the most recent features and bugfixes.', - 'branch': 'The ``git clone`` option ``-b %(clone_arg)s`` tells git to clone the %(ver_type)s in the ESP-IDF repository ``git clone`` ' - 'corresponding to this version of the documentation.', - 'zipfile': { - 'stable': 'As a fallback, it is also possible to download a zip file of this stable release from the `Releases page`_. ' - 'Do not download the "Source code" zip file(s) generated automatically by GitHub, they do not work with ESP-IDF.', - 'unstable': 'GitHub\'s "Download zip file" feature does not work with ESP-IDF, a ``git clone`` is required. As a fallback, ' - '`Stable version`_ can be installed without Git.' - }, # zipfile - }, # git-clone-notes - 'version-note': { - 'master': """ -.. note:: - This is documentation for the master branch (latest version) of ESP-IDF. This version is under continual development. - `Stable version`_ documentation is available, as well as other :doc:`/versions`. -""", - 'stable': """ -.. note:: - This is documentation for stable version %s of ESP-IDF. Other :doc:`/versions` are also available. -""", - 'branch': """ -.. note:: - This is documentation for %s ``%s`` of ESP-IDF. Other :doc:`/versions` are also available. -""" - }, # version-note - }, # en - 'zh_CN': { - 'git-clone-bash': """ -.. code-block:: bash - - mkdir -p ~/esp - cd ~/esp - git clone %(clone_args)s--recursive https://github.com/espressif/esp-idf.git - """, - - 'git-clone-windows': """ -.. code-block:: batch - - mkdir %%userprofile%%\\esp - cd %%userprofile%%\\esp - git clone %(clone_args)s--recursive https://github.com/espressif/esp-idf.git - """, - - 'git-clone-notes': { - 'template': """ -.. note:: - - %(extra_note)s - -.. note:: - - %(zipfile_note)s -""", - 'master': '此命令将克隆 master 分支,该分支保存着 ESP-IDF 的最新版本,它功能齐全,每周都会更新一些新功能并修正一些错误。', - 'branch': '``git clone`` 命令的 ``-b %(clone_arg)s`` 选项告诉 git 从 ESP-IDF 仓库中克隆与此版本的文档对应的分支。', - 'zipfile': { - 'stable': '作为备份,还可以从 `Releases page`_ 下载此稳定版本的 zip 文件。不要下载由 GitHub 自动生成的"源代码"的 zip 文件,它们不适用于 ESP-IDF。', - 'unstable': 'GitHub 中"下载 zip 文档"的功能不适用于 ESP-IDF,所以需要使用 ``git clone`` 命令。作为备份,可以在没有安装 Git 的环境中下载 ' - '`Stable version`_ 的 zip 归档文件。' - }, # zipfile - }, # git-clone - 'version-note': { - 'master': """ -.. note:: - 这是ESP-IDF master 分支(最新版本)的文档,该版本在持续开发中。还有 `Stable version`_ 的文档,以及其他版本的文档 :doc:`/versions` 供参考。 -""", - 'stable': """ -.. note:: - 这是ESP-IDF 稳定版本 %s 的文档,还有其他版本的文档 :doc:`/versions` 供参考。 -""", - 'branch': """ -.. note:: - 这是ESP-IDF %s ``%s`` 版本的文档,还有其他版本的文档 :doc:`/versions` 供参考。 -""" - }, # version-note - } # zh_CN -} - - -def setup(app): - # doesn't need to be this event specifically, but this is roughly the right time - app.connect('idf-info', generate_version_specific_includes) - return {'parallel_read_safe': True, 'parallel_write_safe': True, 'version': '0.1'} - - -def generate_version_specific_includes(app, project_description): - language = app.config.language - tmp_out_dir = os.path.join(app.config.build_dir, 'version_inc') - if not os.path.exists(tmp_out_dir): - print('Creating directory %s' % tmp_out_dir) - os.mkdir(tmp_out_dir) - - template = TEMPLATES[language] - - version, ver_type, is_stable = get_version() - - write_git_clone_inc_files(template, tmp_out_dir, version, ver_type, is_stable) - write_version_note(template['version-note'], tmp_out_dir, version, ver_type, is_stable) - copy_if_modified(tmp_out_dir, os.path.join(app.config.build_dir, 'inc')) - print('Done') - - -def write_git_clone_inc_files(templates, out_dir, version, ver_type, is_stable): - def out_file(basename): - p = os.path.join(out_dir, '%s.inc' % basename) - print('Writing %s...' % p) - return p - - if version == 'master': - clone_args = '' - else: - clone_args = '-b %s ' % version - - with open(out_file('git-clone-bash'), 'w', encoding='utf-8') as f: - f.write(templates['git-clone-bash'] % locals()) - - with open(out_file('git-clone-windows'), 'w', encoding='utf-8') as f: - f.write(templates['git-clone-windows'] % locals()) - - with open(out_file('git-clone-notes'), 'w', encoding='utf-8') as f: - template = templates['git-clone-notes'] - - zipfile = template['zipfile'] - - if version == 'master': - extra_note = template['master'] - zipfile_note = zipfile['unstable'] - else: - extra_note = template['branch'] % {'clone_arg': version, 'ver_type': ver_type} - zipfile_note = zipfile['stable'] if is_stable else zipfile['unstable'] - - f.write(template['template'] % locals()) - - print('Wrote git-clone-xxx.inc files') - - -def write_version_note(template, out_dir, version, ver_type, is_stable): - if version == 'master': - content = template['master'] - elif ver_type == 'tag' and is_stable: - content = template['stable'] % version - else: - content = template['branch'] % (ver_type, version) - out_file = os.path.join(out_dir, 'version-note.inc') - with open(out_file, 'w', encoding='utf-8') as f: - f.write(content) - print('%s written' % out_file) - - -def get_version(): - """ - Returns a tuple of (name of branch/tag/commit-id, type branch/tag/commit, is_stable) - """ - # Use git to look for a tag - try: - tag = subprocess.check_output(['git', 'describe', '--exact-match']).strip().decode('utf-8') - is_stable = re.match(r'v[0-9\.]+$', tag) is not None - return (tag, 'tag', is_stable) - except subprocess.CalledProcessError: - pass - - # No tag, look at branch name from CI, this will give the correct branch name even if the ref for the branch we - # merge into has moved forward before the pipeline runs - branch = os.environ.get('CI_COMMIT_REF_NAME', None) - if branch is not None: - return (branch, 'branch', False) - - # Try to find the branch name even if docs are built locally - branch = subprocess.check_output(['git', 'rev-parse', '--abbrev-ref', 'HEAD']).strip().decode('utf-8') - if branch != 'HEAD': - return (branch, 'branch', False) - - # As a last resort we return commit SHA-1, should never happen in CI/docs that should be published - return (subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD']).strip().decode('utf-8'), 'commit', False) diff --git a/docs/idf_extensions/include_build_file.py b/docs/idf_extensions/include_build_file.py deleted file mode 100644 index c6143bdc79..0000000000 --- a/docs/idf_extensions/include_build_file.py +++ /dev/null @@ -1,23 +0,0 @@ -import os.path - -from docutils.parsers.rst import directives -from docutils.parsers.rst.directives.misc import Include as BaseInclude -from sphinx.util.docutils import SphinxDirective - - -class IncludeBuildFile(BaseInclude, SphinxDirective): - """ - Like the standard "Include" directive, but relative to the app - build directory - """ - def run(self): - abspath = os.path.join(self.env.config.build_dir, self.arguments[0]) - self.arguments[0] = abspath - self.env.note_included(abspath) - return super(IncludeBuildFile, self).run() - - -def setup(app): - directives.register_directive('include-build-file', IncludeBuildFile) - - return {'parallel_read_safe': True, 'parallel_write_safe': True, 'version': '0.1'} diff --git a/docs/idf_extensions/kconfig_reference.py b/docs/idf_extensions/kconfig_reference.py deleted file mode 100644 index 37ec03732f..0000000000 --- a/docs/idf_extensions/kconfig_reference.py +++ /dev/null @@ -1,63 +0,0 @@ -# Extension to generate the KConfig reference list -import os.path -import subprocess -import sys - -from .util import copy_if_modified - - -def setup(app): - # The idf_build_system extension will emit this event once it - # has parsed the IDF project's information - app.connect('idf-info', generate_reference) - - return {'parallel_read_safe': True, 'parallel_write_safe': True, 'version': '0.1'} - - -def generate_reference(app, project_description): - build_dir = os.path.dirname(app.doctreedir.rstrip(os.sep)) - - # Generate 'kconfig.inc' file from components' Kconfig files - print('Generating kconfig.inc from kconfig contents') - kconfig_inc_path = '{}/inc/kconfig.inc'.format(build_dir) - temp_sdkconfig_path = '{}/sdkconfig.tmp'.format(build_dir) - - kconfigs = project_description['config_environment']['COMPONENT_KCONFIGS'].split(';') - kconfig_projbuilds = project_description['config_environment']['COMPONENT_KCONFIGS_PROJBUILD'].split(';') - - sdkconfig_renames = set() - # TODO: this should be generated in project description as well, if possible - for k in kconfigs + kconfig_projbuilds: - component_dir = os.path.dirname(k) - sdkconfig_rename = os.path.join(component_dir, 'sdkconfig.rename') - if os.path.exists(sdkconfig_rename): - sdkconfig_renames.add(sdkconfig_rename) - - kconfigs_source_path = '{}/inc/kconfigs_source.in'.format(build_dir) - kconfig_projbuilds_source_path = '{}/inc/kconfig_projbuilds_source.in'.format(build_dir) - - prepare_kconfig_files_args = [sys.executable, - '{}/tools/kconfig_new/prepare_kconfig_files.py'.format(app.config.idf_path), - '--env', 'COMPONENT_KCONFIGS={}'.format(' '.join(kconfigs)), - '--env', 'COMPONENT_KCONFIGS_PROJBUILD={}'.format(' '.join(kconfig_projbuilds)), - '--env', 'COMPONENT_KCONFIGS_SOURCE_FILE={}'.format(kconfigs_source_path), - '--env', 'COMPONENT_KCONFIGS_PROJBUILD_SOURCE_FILE={}'.format(kconfig_projbuilds_source_path), - ] - subprocess.check_call(prepare_kconfig_files_args) - - confgen_args = [sys.executable, - '{}/tools/kconfig_new/confgen.py'.format(app.config.idf_path), - '--kconfig', './Kconfig', - '--sdkconfig-rename', './sdkconfig.rename', - '--config', temp_sdkconfig_path, - '--env', 'COMPONENT_KCONFIGS={}'.format(' '.join(kconfigs)), - '--env', 'COMPONENT_KCONFIGS_PROJBUILD={}'.format(' '.join(kconfig_projbuilds)), - '--env', 'COMPONENT_SDKCONFIG_RENAMES={}'.format(' '.join(sdkconfig_renames)), - '--env', 'COMPONENT_KCONFIGS_SOURCE_FILE={}'.format(kconfigs_source_path), - '--env', 'COMPONENT_KCONFIGS_PROJBUILD_SOURCE_FILE={}'.format(kconfig_projbuilds_source_path), - '--env', 'IDF_PATH={}'.format(app.config.idf_path), - '--env', 'IDF_TARGET={}'.format(app.config.idf_target), - '--output', 'docs', kconfig_inc_path + '.in' - ] - subprocess.check_call(confgen_args, cwd=app.config.idf_path) - copy_if_modified(kconfig_inc_path + '.in', kconfig_inc_path) diff --git a/docs/idf_extensions/latex_builder.py b/docs/idf_extensions/latex_builder.py deleted file mode 100644 index 8a1f2f6454..0000000000 --- a/docs/idf_extensions/latex_builder.py +++ /dev/null @@ -1,56 +0,0 @@ -import os - -from sphinx.builders.latex import LaTeXBuilder - - -# Overrides the default Sphinx latex build -class IdfLatexBuilder(LaTeXBuilder): - - def __init__(self, app): - - # Sets up the latex_documents config value, done here instead of conf.py since it depends on the runtime value 'idf_target' - self.init_latex_documents(app) - - super().__init__(app) - - def init_latex_documents(self, app): - - file_name = app.config.pdf_file + '.tex' - - if app.config.language == 'zh_CN': - latex_documents = [('index', file_name, u'ESP-IDF 编程指南', u'乐鑫信息科技', 'manual')] - else: - # Default to english naming - latex_documents = [('index', file_name, u'ESP-IDF Programming Guide', u'Espressif Systems', 'manual')] - - app.config.latex_documents = latex_documents - - def prepare_latex_macros(self, package_path, config): - - PACKAGE_NAME = 'espidf.sty' - latex_package = '' - with open(package_path, 'r') as template: - - latex_package = template.read() - - idf_target_title = config.idf_target_title_dict[config.idf_target] - latex_package = latex_package.replace('', idf_target_title) - - # Release name for the PDF front page, remove '_' as this is used for subscript in Latex - idf_release_name = 'Release {}'.format(config.version.replace('_', '-')) - latex_package = latex_package.replace('', idf_release_name) - - with open(os.path.join(self.outdir, PACKAGE_NAME), 'w') as package_file: - package_file.write(latex_package) - - def finish(self): - super().finish() - - TEMPLATE_PATH = '../latex_templates/espidf.sty' - self.prepare_latex_macros(os.path.join(self.confdir,TEMPLATE_PATH), self.config) - - -def setup(app): - app.add_builder(IdfLatexBuilder, override=True) - - return {'parallel_read_safe': True, 'parallel_write_safe': True, 'version': '0.1'} diff --git a/docs/idf_extensions/link_roles.py b/docs/idf_extensions/link_roles.py deleted file mode 100644 index 0a8c936079..0000000000 --- a/docs/idf_extensions/link_roles.py +++ /dev/null @@ -1,179 +0,0 @@ -# based on http://protips.readthedocs.io/link-roles.html - -from __future__ import print_function, unicode_literals - -import os -import re -import subprocess -from collections import namedtuple - -from docutils import nodes -from get_github_rev import get_github_rev -from sphinx.transforms.post_transforms import SphinxPostTransform - - -# Creates a dict of all submodules with the format {submodule_path : (url relative to git root), commit)} -def get_submodules(): - git_root = subprocess.check_output(['git', 'rev-parse', '--show-toplevel']).strip().decode('utf-8') - gitmodules_file = os.path.join(git_root, '.gitmodules') - - submodules = subprocess.check_output(['git', 'submodule', 'status']).strip().decode('utf-8').split('\n') - - submodule_dict = {} - Submodule = namedtuple('Submodule', 'url rev') - for sub in submodules: - sub_info = sub.lstrip().split(' ') - - # Get short hash, 7 digits - rev = sub_info[0].lstrip('-')[0:7] - path = sub_info[1].lstrip('./') - - config_key_arg = 'submodule.{}.url'.format(path) - rel_url = subprocess.check_output(['git', 'config', '--file', gitmodules_file, '--get', config_key_arg]).decode('utf-8').lstrip('./').rstrip('\n') - - submodule_dict[path] = Submodule(rel_url, rev) - - return submodule_dict - - -def url_join(*url_parts): - """ Make a URL out of multiple components, assume first part is the https:// part and - anything else is a path component """ - result = '/'.join(url_parts) - result = re.sub(r'([^:])//+', r'\1/', result) # remove any // that isn't in the https:// part - return result - - -def github_link(link_type, idf_rev, submods, root_path, app_config): - def role(name, rawtext, text, lineno, inliner, options={}, content=[]): - msgs = [] - BASE_URL = 'https://github.com/' - IDF_REPO = 'espressif/esp-idf' - - def warning(msg): - system_msg = inliner.reporter.warning(msg) - system_msg.line = lineno - msgs.append(system_msg) - - # Redirects to submodule repo if path is a submodule, else default to IDF repo - def redirect_submodule(path, submods, rev): - for key, value in submods.items(): - # Add path separator to end of submodule path to ensure we are matching a directory - if path.lstrip('/').startswith(os.path.join(key, '')): - return value.url.replace('.git', ''), value.rev, re.sub('^/{}/'.format(key), '', path) - - return IDF_REPO, rev, path - - # search for a named link (:label) with descriptive label vs a plain URL - m = re.search(r'(.*)\s*<(.*)>', text) - if m: - link_text = m.group(1) - link = m.group(2) - else: - link_text = text - link = text - - rel_path = root_path + link - abs_path = os.path.join(app_config.idf_path, rel_path.lstrip('/')) - - repo, repo_rev, rel_path = redirect_submodule(rel_path, submods, idf_rev) - - line_no = None - url = url_join(BASE_URL, repo, link_type, repo_rev, rel_path) - - if '#L' in abs_path: - # drop any URL line number from the file, line numbers take the form #Lnnn or #Lnnn-Lnnn for a range - abs_path, line_no = abs_path.split('#L') - line_no = re.search(r'^(\d+)(?:-L(\d+))?', line_no) - if line_no is None: - warning("Line number anchor in URL %s doesn't seem to be valid" % link) - else: - line_no = tuple(int(ln_group) for ln_group in line_no.groups() if ln_group) # tuple of (nnn,) or (nnn, NNN) for ranges - elif '#' in abs_path: # drop any other anchor from the line - abs_path = abs_path.split('#')[0] - warning('URL %s seems to contain an unusable anchor after the #, only line numbers are supported' % link) - - is_dir = (link_type == 'tree') - - if not os.path.exists(abs_path): - warning('IDF path %s does not appear to exist (absolute path %s)' % (rel_path, abs_path)) - elif is_dir and not os.path.isdir(abs_path): - # note these "wrong type" warnings are not strictly needed as GitHub will apply a redirect, - # but the may become important in the future (plus make for cleaner links) - warning('IDF path %s is not a directory but role :%s: is for linking to a directory, try :%s_file:' % (rel_path, name, name)) - elif not is_dir and os.path.isdir(abs_path): - warning('IDF path %s is a directory but role :%s: is for linking to a file' % (rel_path, name)) - - # check the line number is valid - if line_no: - if is_dir: - warning('URL %s contains a line number anchor but role :%s: is for linking to a directory' % (rel_path, name, name)) - elif os.path.exists(abs_path) and not os.path.isdir(abs_path): - with open(abs_path, 'r') as f: - lines = len(f.readlines()) - if any(True for ln in line_no if ln > lines): - warning('URL %s specifies a range larger than file (file has %d lines)' % (rel_path, lines)) - - if tuple(sorted(line_no)) != line_no: # second line number comes before first one! - warning('URL %s specifies a backwards line number range' % rel_path) - - node = nodes.reference(rawtext, link_text, refuri=url, **options) - return [node], msgs - return role - - -class translation_link(nodes.Element): - """Node for "link_to_translation" role.""" - - -# Linking to translation is done at the "writing" stage to avoid issues with the info being cached between builders -def link_to_translation(name, rawtext, text, lineno, inliner, options={}, content=[]): - node = translation_link() - node['expr'] = (rawtext, text, options) - return [node], [] - - -class TranslationLinkNodeTransform(SphinxPostTransform): - # Transform needs to happen early to ensure the new reference node is also transformed - default_priority = 0 - - def run(self, **kwargs): - - # Only output relative links if building HTML - for node in self.document.traverse(translation_link): - if 'html' in self.app.builder.name: - rawtext, text, options = node['expr'] - (language, link_text) = text.split(':') - env = self.document.settings.env - docname = env.docname - doc_path = env.doc2path(docname, None, None) - return_path = '../' * doc_path.count('/') # path back to the root from 'docname' - # then take off 3 more paths for language/release/targetname and build the new URL - url = '{}.html'.format(os.path.join(return_path, '../../..', language, env.config.release, - env.config.idf_target, docname)) - node.replace_self(nodes.reference(rawtext, link_text, refuri=url, **options)) - else: - node.replace_self([]) - - -def setup(app): - rev = get_github_rev() - submods = get_submodules() - - # links to files or folders on the GitHub - app.add_role('idf', github_link('tree', rev, submods, '/', app.config)) - app.add_role('idf_file', github_link('blob', rev, submods, '/', app.config)) - app.add_role('idf_raw', github_link('raw', rev, submods, '/', app.config)) - app.add_role('component', github_link('tree', rev, submods, '/components/', app.config)) - app.add_role('component_file', github_link('blob', rev, submods, '/components/', app.config)) - app.add_role('component_raw', github_link('raw', rev, submods, '/components/', app.config)) - app.add_role('example', github_link('tree', rev, submods, '/examples/', app.config)) - app.add_role('example_file', github_link('blob', rev, submods, '/examples/', app.config)) - app.add_role('example_raw', github_link('raw', rev, submods, '/examples/', app.config)) - - # link to the current documentation file in specific language version - app.add_role('link_to_translation', link_to_translation) - app.add_node(translation_link) - app.add_post_transform(TranslationLinkNodeTransform) - - return {'parallel_read_safe': True, 'parallel_write_safe': True, 'version': '0.5'} diff --git a/docs/idf_extensions/run_doxygen.py b/docs/idf_extensions/run_doxygen.py deleted file mode 100644 index e2e90e5775..0000000000 --- a/docs/idf_extensions/run_doxygen.py +++ /dev/null @@ -1,315 +0,0 @@ -# Extension to generate Doxygen XML include files, with IDF config & soc macros included -from __future__ import print_function, unicode_literals - -import os -import os.path -import re -import subprocess -from io import open - -from .util import copy_if_modified - -ALL_KINDS = [ - ('function', 'Functions'), - ('union', 'Unions'), - ('struct', 'Structures'), - ('define', 'Macros'), - ('typedef', 'Type Definitions'), - ('enum', 'Enumerations') -] -"""list of items that will be generated for a single API file -""" - - -def setup(app): - # The idf_build_system extension will emit this event once it has generated documentation macro definitions - app.connect('idf-defines-generated', generate_doxygen) - return {'parallel_read_safe': True, 'parallel_write_safe': True, 'version': '0.2'} - - -def generate_doxygen(app, defines): - build_dir = os.path.dirname(app.doctreedir.rstrip(os.sep)) - - # Call Doxygen to get XML files from the header files - print('Calling Doxygen to generate latest XML files') - doxy_env = os.environ - doxy_env.update({ - 'ENV_DOXYGEN_DEFINES': ' '.join('{}={}'.format(key, value) for key, value in defines.items()), - 'IDF_PATH': app.config.idf_path, - 'IDF_TARGET': app.config.idf_target, - }) - doxyfile_dir = os.path.join(app.config.docs_root, 'doxygen') - doxyfile_main = os.path.join(doxyfile_dir, 'Doxyfile_common') - doxyfile_target = os.path.join(doxyfile_dir, 'Doxyfile_' + app.config.idf_target) - print('Running doxygen with doxyfiles {} and {}'.format(doxyfile_main, doxyfile_target)) - - # It's possible to have doxygen log warnings to a file using WARN_LOGFILE directive, - # but in some cases it will still log an error to stderr and return success! - # - # So take all of stderr and redirect it to a logfile (will contain warnings and errors) - logfile = os.path.join(build_dir, 'doxygen-warning-log.txt') - - with open(logfile, 'w') as f: - # note: run Doxygen in the build directory, so the xml & xml_in files end up in there - subprocess.check_call(['doxygen', doxyfile_main], env=doxy_env, cwd=build_dir, stderr=f) - - # Doxygen has generated XML files in 'xml' directory. - # Copy them to 'xml_in', only touching the files which have changed. - copy_if_modified(os.path.join(build_dir, 'xml/'), os.path.join(build_dir, 'xml_in/')) - - # Generate 'api_name.inc' files from the Doxygen XML files - doxygen_paths = [doxyfile_main, doxyfile_target] - convert_api_xml_to_inc(app, doxygen_paths) - - -def convert_api_xml_to_inc(app, doxyfiles): - """ Generate header_file.inc files - with API reference made of doxygen directives - for each header file - specified in the 'INPUT' statement of the Doxyfile. - """ - build_dir = app.config.build_dir - - xml_directory_path = '{}/xml'.format(build_dir) - inc_directory_path = '{}/inc'.format(build_dir) - - fast_build = os.environ.get('DOCS_FAST_BUILD', None) - - if not os.path.isdir(xml_directory_path): - raise RuntimeError('Directory {} does not exist!'.format(xml_directory_path)) - - if not os.path.exists(inc_directory_path): - os.makedirs(inc_directory_path) - - header_paths = [p for d in doxyfiles for p in get_doxyfile_input_paths(app, d)] - - print("Generating 'api_name.inc' files with Doxygen directives") - for header_file_path in header_paths: - api_name = get_api_name(header_file_path) - inc_file_path = inc_directory_path + '/' + api_name + '.inc' - rst_output = generate_directives(header_file_path, xml_directory_path) - - previous_rst_output = '' - if os.path.isfile(inc_file_path): - with open(inc_file_path, 'r', encoding='utf-8') as inc_file_old: - previous_rst_output = inc_file_old.read() - - if previous_rst_output != rst_output: - with open(inc_file_path, 'w', encoding='utf-8') as inc_file: - inc_file.write(rst_output) - - # For fast builds we wipe the doxygen api documention. - # Parsing this output during the sphinx build process is - # what takes 95% of the build time - if fast_build: - with open(inc_file_path, 'w', encoding='utf-8') as inc_file: - inc_file.write('') - app.tags.add('fast_build') - - -def get_doxyfile_input_paths(app, doxyfile_path): - """Get contents of Doxyfile's INPUT statement. - - Returns: - Contents of Doxyfile's INPUT. - - """ - if not os.path.isfile(doxyfile_path): - raise RuntimeError("Doxyfile '{}' does not exist!".format(doxyfile_path)) - - print("Getting Doxyfile's INPUT") - - with open(doxyfile_path, 'r', encoding='utf-8') as input_file: - line = input_file.readline() - # read contents of Doxyfile until 'INPUT' statement - while line: - if line.find('INPUT') == 0: - break - line = input_file.readline() - - doxyfile_INPUT = [] - line = input_file.readline() - # skip input_file contents until end of 'INPUT' statement - while line: - if line.isspace(): - # we have reached the end of 'INPUT' statement - break - # process only lines that are not comments - if line.find('#') == -1: - # extract header file path inside components folder - m = re.search('components/(.*\.h)', line) # noqa: W605 - regular expression - header_file_path = m.group(1) - - # Replace env variable used for multi target header - header_file_path = header_file_path.replace('$(IDF_TARGET)', app.config.idf_target) - - doxyfile_INPUT.append(header_file_path) - - # proceed reading next line - line = input_file.readline() - - return doxyfile_INPUT - - -def get_api_name(header_file_path): - """Get name of API from header file path. - - Args: - header_file_path: path to the header file. - - Returns: - The name of API. - - """ - api_name = '' - regex = r'.*/(.*)\.h' - m = re.search(regex, header_file_path) - if m: - api_name = m.group(1) - - return api_name - - -def generate_directives(header_file_path, xml_directory_path): - """Generate API reference with Doxygen directives for a header file. - - Args: - header_file_path: a path to the header file with API. - - Returns: - Doxygen directives for the header file. - - """ - - api_name = get_api_name(header_file_path) - - # in XLT file name each "_" in the api name is expanded by Doxygen to "__" - xlt_api_name = api_name.replace('_', '__') - xml_file_path = '%s/%s_8h.xml' % (xml_directory_path, xlt_api_name) - - rst_output = '' - rst_output = ".. File automatically generated by 'gen-dxd.py'\n" - rst_output += '\n' - rst_output += get_rst_header('Header File') - rst_output += '* :component_file:`' + header_file_path + '`\n' - rst_output += '\n' - - try: - import xml.etree.cElementTree as ET - except ImportError: - import xml.etree.ElementTree as ET - - tree = ET.ElementTree(file=xml_file_path) - for kind, label in ALL_KINDS: - rst_output += get_directives(tree, kind) - - return rst_output - - -def get_rst_header(header_name): - """Get rst formatted code with a header. - - Args: - header_name: name of header. - - Returns: - Formatted rst code with the header. - - """ - - rst_output = '' - rst_output += header_name + '\n' - rst_output += '^' * len(header_name) + '\n' - rst_output += '\n' - - return rst_output - - -def select_unions(innerclass_list): - """Select unions from innerclass list. - - Args: - innerclass_list: raw list with unions and structures - extracted from Dogygen's xml file. - - Returns: - Doxygen directives with unions selected from the list. - - """ - - rst_output = '' - for line in innerclass_list.splitlines(): - # union is denoted by "union" at the beginning of line - if line.find('union') == 0: - union_id, union_name = re.split(r'\t+', line) - rst_output += '.. doxygenunion:: ' - rst_output += union_name - rst_output += '\n' - - return rst_output - - -def select_structs(innerclass_list): - """Select structures from innerclass list. - - Args: - innerclass_list: raw list with unions and structures - extracted from Dogygen's xml file. - - Returns: - Doxygen directives with structures selected from the list. - Note: some structures are excluded as described on code below. - - """ - - rst_output = '' - for line in innerclass_list.splitlines(): - # structure is denoted by "struct" at the beginning of line - if line.find('struct') == 0: - # skip structures that are part of union - # they are documented by 'doxygenunion' directive - if line.find('::') > 0: - continue - struct_id, struct_name = re.split(r'\t+', line) - rst_output += '.. doxygenstruct:: ' - rst_output += struct_name - rst_output += '\n' - rst_output += ' :members:\n' - rst_output += '\n' - - return rst_output - - -def get_directives(tree, kind): - """Get directives for specific 'kind'. - - Args: - tree: the ElementTree 'tree' of XML by Doxygen - kind: name of API "kind" to be generated - - Returns: - Doxygen directives for selected 'kind'. - Note: the header with "kind" name is included. - - """ - - rst_output = '' - if kind in ['union', 'struct']: - innerclass_list = '' - for elem in tree.iterfind('compounddef/innerclass'): - innerclass_list += elem.attrib['refid'] + '\t' + elem.text + '\n' - if kind == 'union': - rst_output += select_unions(innerclass_list) - else: - rst_output += select_structs(innerclass_list) - else: - for elem in tree.iterfind( - 'compounddef/sectiondef/memberdef[@kind="%s"]' % kind): - name = elem.find('name') - rst_output += '.. doxygen%s:: ' % kind - rst_output += name.text + '\n' - if rst_output: - all_kinds_dict = dict(ALL_KINDS) - rst_output = get_rst_header(all_kinds_dict[kind]) + rst_output + '\n' - - return rst_output diff --git a/docs/idf_extensions/util.py b/docs/idf_extensions/util.py deleted file mode 100644 index 24163c19ad..0000000000 --- a/docs/idf_extensions/util.py +++ /dev/null @@ -1,81 +0,0 @@ -# Utility functions used in conf.py -# -# Copyright 2017 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. - -from __future__ import unicode_literals - -import os -import shutil -import sys -from io import open - -try: - import urllib.request - _urlretrieve = urllib.request.urlretrieve -except ImportError: - # Python 2 fallback - import urllib - _urlretrieve = urllib.urlretrieve - - -def files_equal(path_1, path_2): - if not os.path.exists(path_1) or not os.path.exists(path_2): - return False - file_1_contents = '' - with open(path_1, 'r', encoding='utf-8') as f_1: - file_1_contents = f_1.read() - file_2_contents = '' - with open(path_2, 'r', encoding='utf-8') as f_2: - file_2_contents = f_2.read() - return file_1_contents == file_2_contents - - -def copy_file_if_modified(src_file_path, dst_file_path): - if not files_equal(src_file_path, dst_file_path): - dst_dir_name = os.path.dirname(dst_file_path) - if not os.path.isdir(dst_dir_name): - os.makedirs(dst_dir_name) - shutil.copy(src_file_path, dst_file_path) - - -def copy_if_modified(src_path, dst_path): - if os.path.isfile(src_path): - copy_file_if_modified(src_path, dst_path) - return - - src_path_len = len(src_path) - for root, dirs, files in os.walk(src_path): - for src_file_name in files: - src_file_path = os.path.join(root, src_file_name) - dst_file_path = os.path.join(dst_path + root[src_path_len:], src_file_name) - copy_file_if_modified(src_file_path, dst_file_path) - - -def download_file_if_missing(from_url, to_path): - filename_with_path = to_path + '/' + os.path.basename(from_url) - exists = os.path.isfile(filename_with_path) - if exists: - print("The file '%s' already exists" % (filename_with_path)) - else: - tmp_file, header = _urlretrieve(from_url) - with open(filename_with_path, 'wb') as fobj: - with open(tmp_file, 'rb') as tmp: - fobj.write(tmp.read()) - - -def call_with_python(cmd): - # using sys.executable ensures that the scripts are called with the same Python interpreter - if os.system('{} {}'.format(sys.executable, cmd)) != 0: - raise RuntimeError('{} failed'.format(cmd)) diff --git a/docs/latex_templates/espidf.sty b/docs/latex_templates/espidf.sty deleted file mode 100644 index 3ff7a67206..0000000000 --- a/docs/latex_templates/espidf.sty +++ /dev/null @@ -1,7 +0,0 @@ -\NeedsTeXFormat{LaTeX2e}[1995/12/01] -\ProvidesPackage{espidf}[2020/03/25 v0.1.0 LaTeX package (ESP-IDF markup)] - -\newcommand{\idfTarget}{} -\newcommand{\idfReleaseName}{} - -\endinput diff --git a/docs/latex_templates/preamble.tex b/docs/latex_templates/preamble.tex deleted file mode 100644 index 67d4890599..0000000000 --- a/docs/latex_templates/preamble.tex +++ /dev/null @@ -1,129 +0,0 @@ -% package with esp-idf specific macros -\usepackage{espidf} - -\setcounter{secnumdepth}{2} -\setcounter{tocdepth}{2} - -\usepackage{amsmath,amsfonts,amssymb,amsthm} -\usepackage{graphicx} -%%% reduce spaces for Table of contents, figures and tables -%%% it is used "\addtocontents{toc}{\vskip -1.2cm}" etc. in the document -\usepackage[notlot,nottoc,notlof]{} - -\usepackage{color} -\usepackage{transparent} -\usepackage{eso-pic} -\usepackage{lipsum} - -%%% Needed for displaying Chinese in English documentation -\usepackage{xeCJK} - -\usepackage{footnotebackref} %%link at the footnote to go to the place of footnote in the text - -%% spacing between line -\usepackage{setspace} -\singlespacing - - -\definecolor{myred}{RGB}{229, 32, 26} -\definecolor{mygrayy}{RGB}{127, 127, 127} -\definecolor{myblack}{RGB}{64, 64, 64} - - -%%%%%%%%%%% datetime -\usepackage{datetime} - -\newdateformat{MonthYearFormat}{% - \monthname[\THEMONTH], \THEYEAR} - - -%% RO, LE will not work for 'oneside' layout. -%% Change oneside to twoside in document class -\usepackage{fancyhdr} -\pagestyle{fancy} -\fancyhf{} - -% Header and footer -\makeatletter - \fancypagestyle{normal}{ - \fancyhf{} - \fancyhead[L]{\nouppercase{\leftmark}} - \fancyfoot[C]{\py@HeaderFamily\thepage \\ \href{https://www.espressif.com/en/company/documents/documentation_feedback?docId=4287§ions=&version=\idfReleaseName}{Submit Document Feedback}} - \fancyfoot[L]{Espressif Systems} - \fancyfoot[R]{\idfReleaseName} - \renewcommand{\headrulewidth}{0.4pt} - \renewcommand{\footrulewidth}{0.4pt} - } -\makeatother - -\renewcommand{\headrulewidth}{0.5pt} -\renewcommand{\footrulewidth}{0.5pt} - - -% Define a spacing for section, subsection and subsubsection -% http://tex.stackexchange.com/questions/108684/spacing-before-and-after-section-titles - -\titlespacing*{\section}{0pt}{6pt plus 0pt minus 0pt}{6pt plus 0pt minus 0pt} -\titlespacing*{\subsection}{0pt}{18pt plus 64pt minus 0pt}{0pt} -\titlespacing*{\subsubsection}{0pt}{12pt plus 0pt minus 0pt}{0pt} -\titlespacing*{\paragraph} {0pt}{3.25ex plus 1ex minus .2ex}{1.5ex plus .2ex} -\titlespacing*{\subparagraph} {0pt}{3.25ex plus 1ex minus .2ex}{1.5ex plus .2ex} - -% Define the colors of table of contents -% This is helpful to understand http://tex.stackexchange.com/questions/110253/what-the-first-argument-for-lsubsection-actually-is -\definecolor{LochmaraColor}{HTML}{1020A0} - -% Hyperlinks -\hypersetup{ - colorlinks = true, - allcolors = {LochmaraColor}, -} - - -\RequirePackage{tocbibind} %%% comment this to remove page number for following -\addto\captionsenglish{\renewcommand{\contentsname}{Table of contents}} -\addto\captionsenglish{\renewcommand{\listfigurename}{List of figures}} -\addto\captionsenglish{\renewcommand{\listtablename}{List of tables}} -% \addto\captionsenglish{\renewcommand{\chaptername}{Chapter}} - - - - -%%reduce spacing for itemize -\usepackage{enumitem} -\setlist{nosep} - -%%%%%%%%%%% Quote Styles at the top of chapter -\usepackage{epigraph} -\setlength{\epigraphwidth}{0.8\columnwidth} -\newcommand{\chapterquote}[2]{\epigraphhead[60]{\epigraph{\textit{#1}}{\textbf {\textit{--#2}}}}} -%%%%%%%%%%% Quote for all places except Chapter -\newcommand{\sectionquote}[2]{{\quote{\textit{``#1''}}{\textbf {\textit{--#2}}}}} - -% Insert 22pt white space before roc title. \titlespacing at line 65 changes it by -22 later on. -\renewcommand*\contentsname{\hspace{0pt}Contents} - - -% Define section, subsection and subsubsection font size and color -\usepackage{sectsty} -\definecolor{AllportsColor}{HTML}{A02010} -\allsectionsfont{\color{AllportsColor}} - -\usepackage{titlesec} -\titleformat{\section} -{\color{AllportsColor}\LARGE\bfseries}{\thesection.}{1em}{} - -\titleformat{\subsection} -{\color{AllportsColor}\Large\bfseries}{\thesubsection.}{1em}{} - -\titleformat{\subsubsection} -{\color{AllportsColor}\large\bfseries}{\thesubsubsection.}{1em}{} - -\titleformat{\paragraph} -{\color{AllportsColor}\large\bfseries}{\theparagraph}{1em}{} - -\titleformat{\subparagraph} - {\normalfont\normalsize\bfseries}{\thesubparagraph}{1em}{} - -\titleformat{\subsubparagraph} - {\normalfont\normalsize\bfseries}{\thesubsubparagraph}{1em}{} diff --git a/docs/latex_templates/titlepage.tex b/docs/latex_templates/titlepage.tex deleted file mode 100644 index 43e24080b0..0000000000 --- a/docs/latex_templates/titlepage.tex +++ /dev/null @@ -1,39 +0,0 @@ -\makeatletter -\newgeometry{left=0cm,right=0cm,bottom=2cm} - - -\cfoot{www.espressif.com} - -\renewcommand{\headrulewidth}{0pt} - -{\color{myred}\rule{30pt}{2.1cm}} - \hspace{0.2cm} - \begin{minipage}[b]{18cm} - {\fontsize{36pt}{48pt}\textbf{\idfTarget}}\\ - - {\fontsize{28pt}{18pt}\textbf{\color{mygrayy}\@title}} - \end{minipage} - \hspace{\stretch{1}} - -\vspace{48em} - - -\begin{flushright} - \setlength\parindent{8em} - \begin{minipage}[b]{2cm} - \sphinxlogo - \end{minipage} - \hspace{0.2cm} - \rule{3pt}{1.9cm} - \hspace{0.2cm} - \begin{minipage}[b]{7cm} - {\large{\idfReleaseName}}\smallskip\newline - {\large{\@author}}\smallskip\newline - {\large{\@date}}\smallskip - \end{minipage} - {\color{myred}\rule{30pt}{1.9cm}} -\end{flushright} - - -\restoregeometry -\makeatother diff --git a/docs/requirements.txt b/docs/requirements.txt index 930e8d10a5..16bd54ca82 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,22 +1 @@ -# This is a list of python packages used to generate documentation. This file is used with pip: -# pip install --user -r requirements.txt -# -# matplotlib is currently required only by the script generate_chart.py -matplotlib==3.3.1 ; python_version>="3" -matplotlib==2.0.1 ; python_version=="2.7" -cairosvg==2.5.1 # required by sphinxcontrib-svg2pdfconverter[CairoSVG] -sphinx==2.3.1 -breathe==4.14.1 -sphinx-copybutton==0.3.0 -sphinx-notfound-page -sphinxcontrib-blockdiag==2.0.0 -sphinxcontrib-seqdiag==2.0.0 -sphinxcontrib-actdiag==2.0.0 -sphinxcontrib-nwdiag==2.0.0 -sphinxcontrib-wavedrom==2.0.0 -sphinxcontrib-svg2pdfconverter[CairoSVG]==1.1.0 -nwdiag==2.0.0 -recommonmark -future>=0.16.0 # for ../tools/gen_esp_err_to_name.py -sphinx_selective_exclude==1.0.3 -sphinx_idf_theme==0.3.0 +esp-docs==0.1.1 diff --git a/docs/sanitize_version.py b/docs/sanitize_version.py deleted file mode 100644 index 1047ec5a78..0000000000 --- a/docs/sanitize_version.py +++ /dev/null @@ -1,43 +0,0 @@ -# Tiny Python module to sanitize a Git version into something that can be used in a URL -# -# (this is used in multiple places: conf_common.py and in tools/ci/docs_deploy -# -# 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. -import os - - -def sanitize_version(original_version): - """ Given a version (probably output from 'git describe --always' or similar), return - a URL-safe sanitized version. (this is used as 'release' config variable when building - the docs.) - - Will override the original version with the Gitlab CI CI_COMMIT_REF_NAME environment variable if - this is present. - - Also follows the RTD-ism that master branch is named 'latest' - - """ - - try: - version = os.environ['CI_COMMIT_REF_NAME'] - except KeyError: - version = original_version - - if version == 'master': - return 'latest' - - version = version.replace('/', '-') - - return version diff --git a/docs/test/README.md b/docs/test/README.md deleted file mode 100644 index f52c801f36..0000000000 --- a/docs/test/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# Documentation Test Folder - -This folder contains the files needed for running tests the ESP-IDF documentation building system. - -Tests are divided into two categories: unit tests and integration tests: - -## Unit Tests - -The Sphinx IDF extensions are unit-tested in [test_sphinx_idf_extensions.py](test_sphinx_idf_extensions.py) - -## Integration Tests -Due to the thigh integration with Sphinx some functionality is difficult to test with simple unit tests. - - To check that the output from the Sphinx build process is as expected [test_docs.py](test_docs.py) builds a test subset of the documentation, found in the [en](en/) folder. The HTML output is then checked to see that it contains the expected content. - -# Running Tests - -Both [test_sphinx_idf_extensions.py](test_sphinx_idf_extensions.py) and [test_docs.py](test_docs.py) are run as part of the `host_test` stage of the CI pipeline. - -It's also possible to run the tests locally by running the following commands from the test folder: - -* `./test_sphinx_idf_extensions.py` -* `./test_docs.py` - -Note that [test_docs.py](test_docs.py) tries to build a test subset of the documentation, and thus requires your environment to be set up for building documents. See [Documenting Code](https://docs.espressif.com/projects/esp-idf/en/latest/contribute/documenting-code.html) for instructions on how to set up the `build_docs` environment. \ No newline at end of file diff --git a/docs/test/en/bt_page.rst b/docs/test/en/bt_page.rst deleted file mode 100644 index a9a3b249b1..0000000000 --- a/docs/test/en/bt_page.rst +++ /dev/null @@ -1,7 +0,0 @@ -Bluetooth -========= -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed iaculis, est ut blandit faucibus, dolor libero luctus tortor, finibus luctus neque elit et lacus. - -Sed at enim sed felis vehicula vehicula. Etiam ex ante, lacinia non purus quis, luctus ornare nibh. Phasellus rhoncus massa vitae tincidunt semper. - -Ut dapibus iaculis metus, vel consectetur diam euismod placerat. Maecenas nibh mauris, maximus et accumsan sit amet, lacinia at felis. Curabitur commodo eu lacus gravida volutpat. In hac habitasse platea dictumst. Quisque et tellus pulvinar, convallis nunc nec, sollicitudin mi. Curabitur et purus justo. Fusce non turpis quis nisi eleifend placerat a vitae. \ No newline at end of file diff --git a/docs/test/en/conf.py b/docs/test/en/conf.py deleted file mode 100644 index c2e02b5f20..0000000000 --- a/docs/test/en/conf.py +++ /dev/null @@ -1,33 +0,0 @@ -# -*- coding: utf-8 -*- -# -# English Language RTD & Sphinx config file -# -# Uses ../conf_common.py for most non-language-specific settings. -# Importing conf_common adds all the non-language-specific -# parts to this conf module -try: - from conf_common import * # noqa: F403,F401 -except ImportError: - import os - import sys - sys.path.insert(0, os.path.abspath('../..')) - from conf_common import * # noqa: F403,F401 - -# General information about the project. -project = u'ESP-IDF Programming Guide' -copyright = u'2016 - 2020, Espressif Systems (Shanghai) CO., LTD' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -language = 'en' -html_copy_source = False - - -html_logo = None -latex_logo = None -html_static_path = [] - -conditional_include_dict = {'esp32':['esp32_page.rst'], - 'esp32s2':['esp32s2_page.rst'], - 'SOC_BT_SUPPORTED':['bt_page.rst'], - } diff --git a/docs/test/en/esp32_page.rst b/docs/test/en/esp32_page.rst deleted file mode 100644 index baa745e7aa..0000000000 --- a/docs/test/en/esp32_page.rst +++ /dev/null @@ -1,3 +0,0 @@ -ESP32 Page -============ -{ESP32_CONTENT} \ No newline at end of file diff --git a/docs/test/en/esp32s2_page.rst b/docs/test/en/esp32s2_page.rst deleted file mode 100644 index 4c0155bdc5..0000000000 --- a/docs/test/en/esp32s2_page.rst +++ /dev/null @@ -1,19 +0,0 @@ -ESP32S2 Page -============ -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed iaculis, est ut blandit faucibus, dolor libero luctus tortor, finibus luctus neque elit et lacus. - -Sed at enim sed felis vehicula vehicula. Etiam ex ante, lacinia non purus quis, luctus ornare nibh. Phasellus rhoncus massa vitae tincidunt semper. - -Ut dapibus iaculis metus, vel consectetur diam euismod placerat. Maecenas nibh mauris, maximus et accumsan sit amet, lacinia at felis. Curabitur commodo eu lacus gravida volutpat. In hac habitasse platea dictumst. Quisque et tellus pulvinar, convallis nunc nec, sollicitudin mi. Curabitur et purus justo. Fusce non turpis quis nisi eleifend placerat a vitae. - -.. only:: esp32 - - ESP32 Content. !ESP32_CONTENT! - -.. only:: esp32s2 - - ESP32 S2 Content. !ESP32_S2_CONTENT! - -.. only:: SOC_BT_SUPPORTED - - Bluetooth Content. !BT_CONTENT! diff --git a/docs/test/en/idf_target_format.rst b/docs/test/en/idf_target_format.rst deleted file mode 100644 index 0966553a9b..0000000000 --- a/docs/test/en/idf_target_format.rst +++ /dev/null @@ -1,3 +0,0 @@ -IDF Target Format -================= - diff --git a/docs/test/en/index.rst b/docs/test/en/index.rst deleted file mode 100644 index 173c72ae5e..0000000000 --- a/docs/test/en/index.rst +++ /dev/null @@ -1,10 +0,0 @@ -Build docs test index -===================== - - -.. toctree:: - - :esp32s2: ESP32-S2 Page - :esp32: ESP32 Page !ESP32_CONTENT! - :SOC_BT_SUPPORTED: BT Page !BT_CONTENT! - IDF Target Format diff --git a/docs/test/page_redirects.txt b/docs/test/page_redirects.txt deleted file mode 100644 index f3070f5a22..0000000000 --- a/docs/test/page_redirects.txt +++ /dev/null @@ -1,7 +0,0 @@ -# Redirects from "old URL" "new URL" -# -# Space delimited -# -# New URL should be relative to document root, only) -# -# Empty lines and lines starting with # are ignored diff --git a/docs/test/test_docs.py b/docs/test/test_docs.py deleted file mode 100755 index bea1e1af90..0000000000 --- a/docs/test/test_docs.py +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/env python3 - -import os -import subprocess -import sys -import unittest - -CURRENT_DIR = os.path.dirname(os.path.realpath(__file__)) -ESP32_DOC = 'esp32_page' -ESP32_S2_DOC = 'esp32s2_page' -BT_DOC = 'bt_page' -LINK_ROLES_DOC = 'link_roles' -IDF_FORMAT_DOC = 'idf_target_format' - - -class DocBuilder(): - build_docs_py_path = os.path.join(CURRENT_DIR, '..', 'build_docs.py') - - def __init__(self, src_dir, build_dir, target, language): - self.language = language - self.target = target - self.src_dir = src_dir - self.build_dir = build_dir - self.html_out_dir = os.path.join(CURRENT_DIR, build_dir, language, target, 'html') - - def build(self, opt_args=[]): - args = [sys.executable, self.build_docs_py_path, '-b', self.build_dir, '-s', self.src_dir, '-t', self.target, '-l', self.language] - args.extend(opt_args) - return subprocess.call(args) - - -class TestDocs(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.builder = DocBuilder('test', '_build/test_docs', 'esp32s2', 'en') - cls.build_ret_flag = cls.builder.build() - - def setUp(self): - if self.build_ret_flag: - self.fail('Build docs failed with return: {}'.format(self.build_ret_flag)) - - def assert_str_not_in_doc(self, doc_name, str_to_find): - with open(os.path.join(self.builder.html_out_dir, doc_name)) as f: - content = f.read() - self.assertFalse(str_to_find in content, 'Found {} in {}'.format(str_to_find, doc_name)) - - def assert_str_in_doc(self, doc_name, str_to_find): - with open(os.path.join(self.builder.html_out_dir, doc_name)) as f: - content = f.read() - self.assertTrue(str_to_find in content, 'Did not find {} in {}'.format(str_to_find, doc_name)) - - def test_only_dir(self): - # Test that ESP32 content was excluded - self.assert_str_not_in_doc(ESP32_S2_DOC + '.html', '!ESP32_CONTENT!') - - # Test that ESP32 S2 content was included - self.assert_str_in_doc(ESP32_S2_DOC + '.html', '!ESP32_S2_CONTENT!') - - # Test that BT content was excluded - self.assert_str_not_in_doc(ESP32_S2_DOC + '.html', '!BT_CONTENT!') - - def test_toctree_filter(self): - # ESP32 page should NOT be built - esp32_doc = os.path.join(self.builder.html_out_dir, ESP32_DOC + '.html') - self.assertFalse(os.path.isfile(esp32_doc), 'Found {}'.format(esp32_doc)) - self.assert_str_not_in_doc('index.html', '!ESP32_CONTENT!') - - esp32s2_doc = os.path.join(self.builder.html_out_dir, ESP32_S2_DOC + '.html') - self.assertTrue(os.path.isfile(esp32s2_doc), '{} not found'.format(esp32s2_doc)) - - # Spot check a few other tags - # No Bluetooth on ESP32 S2 - bt_doc = os.path.join(self.builder.html_out_dir, BT_DOC + '.html') - self.assertFalse(os.path.isfile(bt_doc), 'Found {}'.format(bt_doc)) - self.assert_str_not_in_doc('index.html', '!BT_CONTENT!') - - def test_link_roles(self): - print('test') - - -class TestBuildSubset(unittest.TestCase): - def test_build_subset(self): - builder = DocBuilder('test', '_build/test_build_subset', 'esp32', 'en') - - docs_to_build = 'esp32_page.rst' - - self.assertFalse(builder.build(['-i', docs_to_build])) - - # Check that we only built the input docs - bt_doc = os.path.join(builder.html_out_dir, BT_DOC + '.html') - esp32_doc = os.path.join(builder.html_out_dir, ESP32_DOC + '.html') - self.assertFalse(os.path.isfile(bt_doc), 'Found {}'.format(bt_doc)) - self.assertTrue(os.path.isfile(esp32_doc), 'Found {}'.format(esp32_doc)) - - -if __name__ == '__main__': - unittest.main() diff --git a/docs/test/test_sphinx_idf_extensions.py b/docs/test/test_sphinx_idf_extensions.py deleted file mode 100755 index a87fee8064..0000000000 --- a/docs/test/test_sphinx_idf_extensions.py +++ /dev/null @@ -1,117 +0,0 @@ -#!/usr/bin/env python3 - -import os -import sys -import unittest -from tempfile import TemporaryDirectory -from unittest.mock import MagicMock - -from sphinx.util import tags - -try: - from idf_extensions import exclude_docs -except ImportError: - sys.path.append('..') - from idf_extensions import exclude_docs - -from idf_extensions import format_idf_target, gen_idf_tools_links, link_roles - - -class TestFormatIdfTarget(unittest.TestCase): - - def setUp(self): - self.str_sub = format_idf_target.StringSubstituter() - - config = MagicMock() - config.idf_target = 'esp32' - self.str_sub.init_sub_strings(config) - - def test_add_subs(self): - - self.assertEqual(self.str_sub.substitute_strings['{IDF_TARGET_NAME}'], 'ESP32') - self.assertEqual(self.str_sub.substitute_strings['{IDF_TARGET_PATH_NAME}'], 'esp32') - self.assertEqual(self.str_sub.substitute_strings['{IDF_TARGET_TOOLCHAIN_PREFIX}'], 'xtensa-esp32-elf') - self.assertEqual(self.str_sub.substitute_strings['{IDF_TARGET_CFG_PREFIX}'], 'ESP32') - self.assertEqual(self.str_sub.substitute_strings['{IDF_TARGET_TRM_EN_URL}'], - 'https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf') - self.assertEqual(self.str_sub.substitute_strings['{IDF_TARGET_TRM_CN_URL}'], - 'https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_cn.pdf') - - def test_sub(self): - content = ('This is a {IDF_TARGET_NAME}, with {IDF_TARGET_PATH_NAME}/soc.c, compiled with ' - '{IDF_TARGET_TOOLCHAIN_PREFIX}-gcc with CONFIG_{IDF_TARGET_CFG_PREFIX}_MULTI_DOC. ' - 'TRM can be found at {IDF_TARGET_TRM_EN_URL} or {IDF_TARGET_TRM_CN_URL}') - - expected = ('This is a ESP32, with esp32/soc.c, compiled with xtensa-esp32-elf-gcc with CONFIG_ESP32_MULTI_DOC. ' - 'TRM can be found at https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf ' - 'or https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_cn.pdf') - - self.assertEqual(self.str_sub.substitute(content), expected) - - def test_local_sub(self): - content = ('{IDF_TARGET_TX_PIN:default="IO3", esp32="IO4", esp32s2="IO5"}' - 'The {IDF_TARGET_NAME} UART {IDF_TARGET_TX_PIN} uses for TX') - - expected = 'The ESP32 UART IO4 uses for TX' - self.assertEqual(self.str_sub.substitute(content), expected) - - def test_local_sub_default(self): - content = ('{IDF_TARGET_TX_PIN:default="IO3", esp32s2="IO5"}' - 'The {IDF_TARGET_NAME} UART {IDF_TARGET_TX_PIN} uses for TX') - - expected = 'The ESP32 UART IO3 uses for TX' - self.assertEqual(self.str_sub.substitute(content), expected) - - def test_local_sub_no_default(self): - content = ('{IDF_TARGET_TX_PIN: esp32="IO4", esp32s2="IO5"}' - 'The {IDF_TARGET_NAME} UART {IDF_TARGET_TX_PIN} uses for TX') - - self.assertRaises(ValueError, self.str_sub.substitute, content) - - -class TestExclude(unittest.TestCase): - - def setUp(self): - self.app = MagicMock() - self.app.tags = tags.Tags() - self.app.config.conditional_include_dict = {'esp32':['esp32.rst', 'bt.rst'], 'esp32s2':['esp32s2.rst']} - self.app.config.docs_to_build = None - self.app.config.exclude_patterns = [] - - def test_update_exclude_pattern(self): - self.app.tags.add('esp32') - exclude_docs.update_exclude_patterns(self.app, self.app.config) - docs_to_build = set(self.app.config.conditional_include_dict['esp32']) - - # Check that the set of docs to build and the set of docs to exclude do not overlap - self.assertFalse(docs_to_build & set(self.app.config.exclude_patterns)) - - -class TestGenIDFToolLinks(unittest.TestCase): - def setUp(self): - self.app = MagicMock() - self.app.config.build_dir = '_build' - self.app.config.idf_path = os.environ['IDF_PATH'] - - def test_gen_idf_tool_links(self): - - with TemporaryDirectory() as temp_dir: - self.app.config.build_dir = temp_dir - gen_idf_tools_links.generate_idf_tools_links(self.app, None) - self.assertTrue(os.path.isfile(os.path.join(self.app.config.build_dir, 'inc', 'idf-tools-inc.rst'))) - - -class TestLinkRoles(unittest.TestCase): - def test_get_submodules(self): - submod_dict = link_roles.get_submodules() - - # Test a known submodule to see if it's in the dict - test_submod_name = 'components/asio/asio' - self.assertIn(test_submod_name, submod_dict) - self.assertIsNotNone(submod_dict[test_submod_name].url) - self.assertIsNotNone(submod_dict[test_submod_name].rev) - self.assertIsNotNone(submod_dict[test_submod_name].url) - - -if __name__ == '__main__': - unittest.main() diff --git a/docs/zh_CN/api-guides/blufi.rst b/docs/zh_CN/api-guides/blufi.rst index 6d443d6f26..51a191bf1b 100644 --- a/docs/zh_CN/api-guides/blufi.rst +++ b/docs/zh_CN/api-guides/blufi.rst @@ -4,7 +4,8 @@ BluFi 概览 ----- -BluFi 是一款基于蓝牙通道的 Wi-Fi 网络配置功能,适用于 ESP32。它通过安全协议将 Wi-Fi 配置和证书传输到 ESP32,然后 ESP32 可基于这些信息连接到 AP 或建立 SoftAP。 + +BluFi 是一款基于蓝牙通道的 Wi-Fi 网络配置功能,适用于 {IDF_TARGET_NAME}。它通过安全协议将 Wi-Fi 的 SSID、密码等配置信息传输到 {IDF_TARGET_NAME},然后 {IDF_TARGET_NAME} 可基于这些信息连接到 AP 或建立 SoftAP。 BluFi 流程的关键部分包括数据的分片、加密、校验和验证。 @@ -12,42 +13,39 @@ BluFi 流程的关键部分包括数据的分片、加密、校验和验证。 BluFi 流程 ---------- + BluFi 配网功能包含配置 SoftAP 和 Station 两部分。 -下面以配置 Station 为例说明配置步骤。 -BluFi 配网的配置 Station 包含广播、连接、服务发现、协商共享密钥、传输数据、回传连接状态等步骤。 +下面以配置 Station 为例说明配置步骤。BluFi 配网的配置 Station 包含广播、连接、服务发现、协商共享密钥、传输数据、回传连接状态等步骤。 -ESP32 配网流程 --------------- +1. {IDF_TARGET_NAME} 开启 GATT Server 模式,发送带有特定 *advertising data* 的广播。你可以自定义该广播,该广播不属于 BluFi Profile。 -1. ESP32 开启 GATT Server 功能,发送带有特定 *adv data* 的广播。你可以自定义该广播,该广播不属于 BluFi Profile。 +2. 使用手机 APP 搜索到该特定广播,手机作为 GATT Client 连接 {IDF_TARGET_NAME}。你可以决定使用哪款手机 APP。 -2. 使用手机 APP 搜索到该特定广播,手机作为 GATT Client 连接 ESP32。你可以决定使用哪款手机 APP。 +3. GATT 连接建立成功后,手机会向 {IDF_TARGET_NAME} 发送数据帧进行密钥协商(详情见 :ref:`frame_formats` )。 -3. GATT 连接建立成功后,手机向 ESP32 发送“协商过程”数据帧(详情见 :ref:`frame_formats` )。 +4. {IDF_TARGET_NAME} 收到密钥协商的数据帧后,会按照使用者自定义的协商方法来解析。 -4. ESP32 收到“协商过程”数据帧后,会按照使用者自定义的协商过程来解析。 +5. 手机与 {IDF_TARGET_NAME} 进行密钥协商。协商过程可使用 DH/RSA/ECC 等加密算法。 -5. 手机与 ESP32 进行密钥协商。协商过程可使用 DH/RSA/ECC 等加密算法进行。 +6. 协商结束后,手机端向 {IDF_TARGET_NAME} 发送控制帧,用于设置安全模式。 -6. 协商结束后,手机端向 ESP32 发送“设置安全模式”控制帧。 +7. {IDF_TARGET_NAME} 收到控制帧后,使用共享密钥以及安全配置对通信数据进行加密和解密。 -7. ESP32 收到“设置安全模式”控制帧后,使用经过协商的共享密钥以及配置的安全策略对通信数据进行加密和解密。 +8. 手机向 {IDF_TARGET_NAME} 发送 :ref:`frame_formats` 中定义的数据帧,包括 SSID、密码等 Wi-Fi 配置信息。 -8. 手机向 ESP32 发送“BluFi 传输格式”定义的 SSID、Password 等用于 Wi-Fi 连接的必要信息。 +9. 手机向 {IDF_TARGET_NAME} 发送 Wi-Fi 连接请求的控制帧。{IDF_TARGET_NAME} 收到这个控制帧之后,会认为手机已将必要的信息已经传输完毕,准备连接 Wi-Fi。 -9. 手机向 ESP32 发送“Wi-Fi 连接请求”控制帧,ESP32 收到之后,识别为手机已将必要的信息传输完毕,准备连接 Wi-Fi。 - -10. ESP32 连接到 Wi-Fi 后,发送“Wi-Fi 连接状态报告”控制帧到手机,以报告连接状态。至此配网结束。 +10. {IDF_TARGET_NAME} 连接到 Wi-Fi 后,发送 Wi-Fi 连接状态报告的控制帧到手机,以报告连接状态。至此配网结束。 .. note:: - 1. 安全模式设置可在任何时候进行,ESP32 收到安全模式的配置后,会根据安全模式指定的模式进行安全相关的操作。 + 1. {IDF_TARGET_NAME} 收到安全模式配置的控制帧后,会根据定义的安全模式进行相关操作。 2. 进行对称加密和解密时,加密和解密前后的数据长度必须一致,支持原地加密和解密。 -配网流程图 ------------ +BluFi 流程图 +--------------- .. seqdiag:: :caption: BluFi Flow Chart @@ -61,344 +59,371 @@ ESP32 配网流程 span_height = 10; default_fontsize = 12; - Phone <- ESP32 [label="广播"]; - Phone -> ESP32 [label="建立 GATT 链接"]; - Phone <- ESP32 [label="协商密钥"]; - Phone -> ESP32 [label="协商密钥"]; - Phone -> ESP32 [label="CTRL: 设置 ESP32 手机安全模式"]; - Phone -> ESP32 [label="DATA: SSID"]; - Phone -> ESP32 [label="DATA: Password"]; - Phone -> ESP32 [label="DATA: 其他信息,如 CA 认证"]; - Phone -> ESP32 [label="CTRL: 连接到 AP"]; - Phone <- ESP32 [label="DATA: 连接状态报告"]; + Phone <- {IDF_TARGET_NAME} [label="广播"]; + Phone -> {IDF_TARGET_NAME} [label="建立 GATT 链接"]; + Phone <- {IDF_TARGET_NAME} [label="协商密钥"]; + Phone -> {IDF_TARGET_NAME} [label="协商密钥"]; + Phone -> {IDF_TARGET_NAME} [label="CTRL: 设置 {IDF_TARGET_NAME} 为手机安全模式"]; + Phone -> {IDF_TARGET_NAME} [label="DATA: SSID"]; + Phone -> {IDF_TARGET_NAME} [label="DATA: Password"]; + Phone -> {IDF_TARGET_NAME} [label="DATA: 其他信息,如 CA 认证"]; + Phone -> {IDF_TARGET_NAME} [label="CTRL: 连接到 AP"]; + Phone <- {IDF_TARGET_NAME} [label="DATA: 连接状态报告"]; } .. _frame_formats: -BluFi 传输格式 --------------- +BluFi 中定义的帧格式 +---------------------------- -手机 APP 与 ESP32 之间的 BluFi 通信格式定义如下: +手机 APP 与 {IDF_TARGET_NAME} 之间的 BluFi 通信格式定义如下: -帧不分片情况下的标准格式 (8 bit): +帧不分片情况下的格式 (8 位): -+-----------------+----------------+ -| Description | Value | -+=================+================+ -| LSB - Type | 1 | -+-----------------+----------------+ -| Frame Control | 1 | -+-----------------+----------------+ -| Sequence Number | 1 | -+-----------------+----------------+ -| Data Length | 1 | -+-----------------+----------------+ -| Data | ${Data Length} | -+-----------------+----------------+ -| MSB - CheckSum | 2 | -+-----------------+----------------+ +.. list-table:: + :header-rows: 1 + :widths: 25 25 + + * - 描述 + - 值 + * - 类型字段(最低有效位) + - 1 + * - 帧控制字段 + - 1 + * - 序列号字段 + - 1 + * - 数据长度字段 + - 1 + * - 数据字段 + - ${Data Length} + * - 校验字段(最高有效位) + - 2 -如果 **Frame Control** 帧中的 **More Frag** 使能,则 **Total Content Length** 为数据帧中剩余部分的总长度,用于报告终端需要分配多少内存。 +如果使能 **帧控制** 位,则 **总长度** 位表示帧的剩余部分的总长度,用于报告终端需要分配多少内存。 -帧分片格式(8 bit): +帧分片格式(8 位): -+--------------------+-------------------------------------------+ -| Description | Value | -+====================+===========================================+ -| LSB - Type | 1 | -+--------------------+-------------------------------------------+ -| FrameControl(Frag) | 1 | -+--------------------+-------------------------------------------+ -| SequenceNumber | 1 | -+--------------------+-------------------------------------------+ -| DataLength | 1 | -+--------------------+----------------------+--------------------+ -| | Total Content Length | 2 | -+ Data +----------------------+--------------------+ -| | Content | ${Data Length} - 2 | -+--------------------+----------------------+--------------------+ -| MSB - CheckSum | 2 | -+--------------------+-------------------------------------------+ +.. list-table:: + :header-rows: 1 + :widths: 25 25 + + * - 描述 + - 值 + * - 类型字段(最低有效位) + - 1 + * - 帧控制字段(分片) + - 1 + * - 序列号字段 + - 1 + * - 数据长度字段 + - 1 + * - 数据字段 + - * Total Content Length: 2 + * Content: ${Data Length} - 2 + * - 校验字段(最高有效位) + - 2 -通常情况下,控制帧不包含数据位,Ack 帧类型除外。 +通常情况下,控制帧不包含数据位,ACK 帧类型除外。 -Ack 帧格式(8 bit): +ACK 帧格式(8 bit): -+------------------+--------------------------------------------+ -| Description | Value | -+------------------+--------------------------------------------+ -| LSB - Type (Ack) | 1 | -+------------------+--------------------------------------------+ -| Frame Control | 1 | -+------------------+--------------------------------------------+ -| SequenceNumber | 1 | -+------------------+--------------------------------------------+ -| DataLength | 1 | -+------------------+-----------------------+--------------------+ -+ Data + Acked Sequence Number + 2 + -| | | | -+------------------+-----------------------+--------------------+ -| MSB - CheckSum | 2 | -+------------------+--------------------------------------------+ +.. list-table:: + :header-rows: 1 + :widths: 25 25 + + * - 描述 + - 值 + * - 类型字段 - ACK(最低有效位) + - 1 + * - 帧控制字段 + - 1 + * - 序列号字段 + - 1 + * - 数据长度字段 + - 1 + * - 数据字段 + - ACK 序列号: 2 + * - 校验字段(最高有效位) + - 2 -1. Type + +1. 类型字段 - 类型域,占 1 byte。分为 Type 和 Subtype(子类型域)两部分, Type 占低 2 bit,Subtype 占高 6 bit。 + 类型字段,占 1 字节。分为类型字段和子类型字段两部分,类型字段占低 2 位,子类型字段占高 6 位。 * 控制帧,暂不进行加密,可校验; * 数据帧,可加密,可校验。 - **1.1 控制帧 (0x0 b’00)** +1.1 控制帧 (二进制:0x0 b’00) - +------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ - | 控制帧 (二进制) | 含义 | 解释 | 备注 | - +==================+===================================+================================================================+======================================================================+ - | 0x0 (b’000000) | Ack | 用来回复对方发的帧, | Data 域使用1 byte Sequence 值, | - | | | Ack 帧的 Data 域使用回复对象帧的 Sequence 值。 | 与恢复对象帧的Sequence 值相同。 | - +------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ - | 0x1 (b’000001) | Set ESP32 to the security mode. | 通知 ESP32 发送数据时使用的安全模式, | Data 域占用 1 byte。 | - | | | 在该过程中可设置多次,每次设置后影响后续安全模式。 | 高 4 bit 为控制帧的安全模式,低 4bit 为数据帧的安全模式。 | - + + + 在不设置的情况下,ESP32 默认控制帧和数据帧均为无校验、无加密。 +----------------------------------------------------------------------+ - | | | 手机到 ESP32 方向依赖于帧 Control 域。 | b’0000:无校验、无加密; | - + + + +----------------------------------------------------------------------+ - | | | | b’0001:有校验、无加密; | - + + + +----------------------------------------------------------------------+ - | | | | b’0010:无校验、有加密; | - + + + +----------------------------------------------------------------------+ - | | | | b’0011:有校验、有加密。 | - +------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ - | 0x2 (b’000010) | Set the Wi-Fi opmode of ESP32. | 设置 ESP32 的 Wi-Fi 模式,帧包含 opmode 信息。 | data[0] 用于表示 opmode 类型,包括: | - + + + +----------------------------------------------------------------------+ - | | | | 0x00: NULL; | - + + + +----------------------------------------------------------------------+ - | | | | 0x01: STA; | - + + + +----------------------------------------------------------------------+ - | | | | 0x02: SoftAP; | - + + + +----------------------------------------------------------------------+ - | | | | 0x03: SoftAP&STA. | - + + + +----------------------------------------------------------------------+ - | | | | 如果设置有包含 AP,请尽量优先 | - | | | | 设置 AP 模式的SSID/Password/Max Conn Number 等。 | - +------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ - | 0x3 (b’000011) | Connect ESP32 to the AP. | 通知 ESP32,必要的信息已经发送完毕,可以连接 AP。 | 不包含 Data 域。 | - +------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ - | 0x4 (b’000100) | Disconnect ESP32 from the AP. | 通知 ESP32 断开与 AP 的连接 | 不包含 Data 域。 | - +------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ - | 0x5 (b’000101) | Get the status of Wi-Fi. | 获取 ESP32 的 Wi-Fi 模式和状态等信息。 | 不包含 Data 域。 | - | | | | ESP32 收到此控制帧后,后续会通过 Wi-Fi 连接状态 | - | | | | 报告 (Wi-Fi Connection State Report) 数据帧来回复手机端当前 | - | | | | 所处的 opmode、连接状态、SSID 等信息。提供给手机端的信息由应用决定。 | - +------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ - | 0x6 (b’000110) | Disconnect the STA device | 处于 SoftAP 模式时,踢掉某个 STA 设备。 | data[0~5] 为 STA 设备的 MAC 地址, | - | | from the SoftAP in SoftAP mode. | | 如有多个 STA,则 [6-11] 为第二个,依次类推。 | - +------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ - | 0x7 (b'000111) | Get the version. | | | - +------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ - | 0x8 (b’001000) | Tell ESP32 to disconnect | 通知 ESP32 断开蓝牙连接。 | ESP32 收到该指令后主动断开蓝牙连接。 | - | | the BLE GATT link. | | | - +------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ - | 0x9 (b’001001) | Tell ESP32 to get the Wi-Fi list. | 通知 ESP32 扫描周围的 Wi-Fi 热点 | 不包含 Data 域。 | - | | | | ESP32 收到此控制帧后,会发送包含 Wi-Fi 热点 | - | | | | 报告 (Wi-Fi List Report) 的数据帧回复 | - | | | | 手机端 ESP32 周围的 Wi-Fi 热点。 | - +------------------+-----------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+ +.. list-table:: + :header-rows: 1 + :widths: 5 15 20 30 + + * - 控制帧 + - 含义 + - 解释 + - 备注 - **1.2 数据帧 (0x1 b’01)** + * - 0x0 (b’000000) + - ACK + - ACK 帧的数据字段使用回复对象帧的序列值。 + - 数据字段占用 1 字节,其序列值与回复对象帧的序列值相同。 + + * - 0x1 (b’000001) + - 将 ESP 设备设置为安全模式。 + - 通知 ESP 设备发送数据时使用的安全模式,在数据发送过程中可多次重置,每次设置后会影响后续使用的安全模式。 + + 如果不设置,ESP 设备将默认发送不带校验和加密的控制帧和数据帧。从手机到 ESP 设备的数据传输是由这个控制帧控制的。 + - 数据字段占一个字节。高 4 位用于控制帧的安全模式设置,低 4 位用于数据帧的安全模式设置。 - +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ - |数据帧 (二进制)| 含义 | 解释 | 备注 | - +===============+========================================+================================================+======================================================+ - | 0x0 (b’000000)| Negotiation data. | 用来发送协商数据,传输到应用层注册的回调函数。 | 数据长度与 Length 域有关。 | - +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ - | 0x1 (b’000001)| BSSID for STA mode. | STA 将要连接的 AP 的 BSSID(用于隐藏SSID)。 | 数据长度与 Length 域有关。 | - + + + +------------------------------------------------------+ - | | | | 当传输方向为 ESP32 到手机时, | - | | | | 表示向手机端提供信息。 | - +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ - | 0x2 (b’000010)| SSID for STA mode. | STA 将要连接的 AP 的 SSID。 | 数据长度与 Length 域有关。 | - + + + +------------------------------------------------------+ - | | | | 当传输方向为 ESP32 到手机时, | - | | | | 表示向手机端提供信息。 | - +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ - | 0x3 (b’000011)| Password for STA mode. | STA 将要连接的 AP 的密码。 | 数据长度与 Length 域有关。 | - + + + +------------------------------------------------------+ - | | | | 当传输方向为 ESP32 到手机时, | - | | | | 表示向手机端提供信息。 | - +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ - | 0x4 (b’000100)| SSID for SoftAP mode. | SoftAP 模式使用的 SSID。 | 数据长度与 Length 域有关。 | - + + + +------------------------------------------------------+ - | | | | 当传输方向为 ESP32 到手机时, | - | | | | 表示向手机端提供信息。 | - +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ - | 0x5 (b’000101)| Password for SoftAPmode. | SoftAP 模式使用的密码。 | 数据长度与 Length 域有关。 | - + + + +------------------------------------------------------+ - | | | | 当传输方向为 ESP32 到手机时, | - | | | | 表示向手机端提供信息。 | - +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ - | 0x6 (b’000110)| Max connection number for SoftAP mode. | AP 模式的最大连接数。 | data[0] 表示连接数的值,范围 1~4。 | - + + + +------------------------------------------------------+ - | | | | 当传输方向为 ESP32 到手机时, | - | | | | 表示向手机端提供信息。 | - +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ - | 0x7 (b’000111)| Authentication mode for SoftAP mode. | AP 模式的认证模式。 | data[0]: | - + + + +------------------------------------------------------+ - | | | | 0x00: OPEN; | - + + + +------------------------------------------------------+ - | | | | 0x01: WEP; | - + + + +------------------------------------------------------+ - | | | | 0x02: WPA_PSK; | - + + + +------------------------------------------------------+ - | | | | 0x03: WPA2_PSK; | - + + + +------------------------------------------------------+ - | | | | 0x04: WPA_WPA2_PSK. | - + + + +------------------------------------------------------+ - | | | | 当传输方向为 ESP32 到手机时, | - | | | | 表示向手机端提供信息。 | - +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ - | 0x8 (b’001000)| Channel for SoftAP mode. | SoftAP 模式的通道数量。 | data[0] 表示通道的数量,范围 1~14。 | - + + + +------------------------------------------------------+ - | | | | 当传输方向为 ESP32 到手机时, | - | | | | 表示向手机端提供信息。 | - +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ - | 0x9 (b’001001)| Username. | 使用企业级加密时,Client 端的用户名。 | 数据长度与 Length 域有关。 | - +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ - | 0xa (b’001010)| CA certification. | 进行企业级加密时使用的 CA 证书。 | 数据长度与 Length 域有关, | - | | | | 长度不够,可用分片。 | - +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ - | 0xb (b’001011)| Client certification. | 进行企业级加密时,Client 端的证书。 | 数据长度与 Length 域有关, | - + + +------------------------------------------------+ 长度不够,可用分片。 + - | | | 可包含或不包含私钥,由证书内容决定。 | | - +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ - | 0xc (b’001100)| Server certification. | 进行企业级加密时,Server 端的证书。 | 数据长度与 Length 域有关, | - + + +------------------------------------------------+ 长度不够,可用分片。 + - | | | 可包含或不包含私钥,由证书内容决定。 | | - +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ - | 0xd (b’001101)| Client private key. | 进行企业级加密时,Client 端的私钥。 | 数据长度与 Length 域有关, | - | | | | 长度不够,可用分片。 | - +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ - | 0xe (b’001110)| Server private key. | 进行企业级加密时,Server 端的私钥。 | 数据长度与 Length 域有关, | - | | | | 长度不够,可用分片。 | - +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ - | 0xf (b’001111)| Wi-Fi connection state report. | 通知手机 ESP32 的 Wi-Fi 状态, | data[0] 表示 opmode,包括: | - | | | 包括 STA状态和 SoftAP 状态, | | - | | | 用于手机配置 STA 连接时的通知, | | - | | | 或有 STA 连接上 SoftAP 时的通知。 | | - + + +------------------------------------------------+------------------------------------------------------+ - | | | 但收到手机询问 Wi-Fi 状态时, | 0x00: NULL; | - + + + 除了回复此帧外,还可回复其他数据帧。 +------------------------------------------------------+ - | | | | 0x01: STA; | - + + + +------------------------------------------------------+ - | | | | 0x02: SoftAP; | - + + + +------------------------------------------------------+ - | | | | 0x03: SoftAP&STA | - + + + +------------------------------------------------------+ - | | | | data[1]:STA 的连接状态, | - | | | | 0x0 表示处于连接状态, | - | | | | 其他表示处于非连接状态; | - + + + +------------------------------------------------------+ - | | | | data[2]:SoftAP 的连接状态, | - | | | | 即表示有多少 STA 已经连接。 | - + + + +------------------------------------------------------+ - | | | | data[3] 及以后:为按照本协议格式 SSID\BSSID 等信息。 | - +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ - | 0x10 b’010000 | Version. | | data[0]= great version | - + + + +------------------------------------------------------+ - | | | | data[1]=sub version | - +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ - |0x11 (b’010001)| Wi-Fi list. | 通知手机 ESP32 周围的 Wi-Fi 热点列表。 | 数据帧数据格式为 Length + RSSI + SSID, | - | | | | 数据较长时可分片发送。 | - +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ - |0x12 (b’010010)| Report error. | 通知手机 BluFi 过程出现异常错误。 | 0x00: sequence error; | - + + + +------------------------------------------------------+ - | | | | 0x01: checksum error; | - + + + +------------------------------------------------------+ - | | | | 0x02: decrypt error; | - + + + +------------------------------------------------------+ - | | | | 0x03: encrypt error; | - + + + +------------------------------------------------------+ - | | | | 0x04: init security error; | - + + + +------------------------------------------------------+ - | | | | 0x05: dh malloc error; | - + + + +------------------------------------------------------+ - | | | | 0x06: dh param error; | - + + + +------------------------------------------------------+ - | | | | 0x07: read param error; | - + + + +------------------------------------------------------+ - | | | | 0x08: make public error. | - +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ - |0x13 (b’010011)| Custom data. | 用户发送或者接收自定义数据。 | 数据较长时可分片发送。 | - +---------------+----------------------------------------+------------------------------------------------+------------------------------------------------------+ + * b’0000:无校验、无加密; + * b’0001:有校验、无加密; + * b’0010:无校验、有加密; + * b’0011:有校验、有加密。 + + * - 0x2 (b’000010) + - 设置 Wi-Fi 的 opmode。 + - 该帧包含设置 ESP 设备 Wi-Fi 模式 (opmode) 的设置信息。 + - data[0] 用于设置 opmode,包括: + + * 0x00: NULL + * 0x01: STA + * 0x02: SoftAP + * 0x03: SoftAP & STA + + 如果设置中包含 AP,请尽量优先设置 AP 模式的 SSID/密码/最大连接数等。 + + * - 0x3 (b’000011) + - 将 ESP 设备连接至 AP。 + - 通知 ESP 设备必要的信息已经发送完毕,可以连接至 AP。 + - 不包含数据字段。 + + * - 0x4 (b’000100) + - 断开 ESP 设备与 AP 的连接。 + - + - 不包含数据字段。 + + * - 0x5 (b’000101) + - 获取 ESP 设备的 Wi-Fi 模式和状态等信息。 + - + - * 不包含数据字段。ESP 设备收到此控制帧后,会向手机回发一个报告 Wi-Fi 连接状态的帧来告知手机端当前所处的 opmode、连接状态、SSID 等信息。 + * 提供给手机端的信息类型由手机上的应用程序决定。 + + * - 0x6 (b’000110) + - 断开 STA 设备与 SoftAP 的连接(SoftAP 模式)。 + - + - data[0~5] 为 STA 设备的 MAC 地址,如有多个 STA 设备,则第二个使用 data[6-11],依次类推。 + + * - 0x7 (b’000111) + - 获取版本信息。 + - + - + + * - 0x8 (b’001000) + - 断开 BLE GATT 连接。 + - + - ESP 设备收到该指令后主动断开 BLE GATT 连接。 + + * - 0x9 (b’001001) + - 获取 Wi-Fi 列表。 + - 通知 ESP 设备扫描周围的 Wi-Fi 热点。 + - 不包含数据字段。 ESP 设备收到此控制帧后,会向手机回发一个包含 Wi-Fi 热点报告的帧。 + + + +1.2 数据帧 (二进制:0x1 b’01) + +.. list-table:: + :header-rows: 1 + :widths: 5 15 20 30 + + * - 数据帧 + - 含义 + - 解释 + - 备注 + * - 0x0 (b’000000) + - 发送协商数据。 + - 协商数据会发送到应用层注册的回调函数中。 + - 数据的长度取决于数据长度字段。 + * - 0x1 (b’000001) + - 发送 STA 模式的 BSSID。 + - 在 SSID 隐藏的情况下,发送 STA 设备要连接的 AP 的 BSSID。 + - 请参考备注 1。 + * - 0x2 (b’000010) + - 发送 STA 模式的 SSID + - 发送 STA 设备要连接的 AP 的 SSID。 + - 请参考备注 1。 + * - 0x3 (b’000011) + - 发送 STA 模式的密码。 + - 发送 STA 设备要连接的 AP 的密码。 + - 请参考备注 1。 + * - 0x4 (b’000100) + - 发送 SoftAP 模式的 SSID。 + - + - 请参考备注 1。 + * - 0x5 (b’000101) + - 发送 SoftAPmode 模式的密码。 + - + - 请参考备注 1。 + * - 0x6 (b’000110) + - 设置 SoftAPmode 模式的最大连接数。 + - + - data[0] 为连接数的值,范围从 1 到 4。当传输方向是 ESP 设备到手机时,表示向手机端提供所需信息。 + * - 0x7 (b’000111) + - 设置 SoftAP 的认证模式。 + - + - data[0] 包括: + + * 0x00: OPEN + * 0x01: WEP + * 0x02: WPA_PSK + * 0x03: WPA2_PSK + * 0x04: WPA_WPA2_PSK + + 当传输方向是 ESP 设备到手机时,表示向手机端提供所需信息。 + * - 0x8 (b’001000) + - 设置 SoftAP 模式的通道数量。 + - + - data[0] 代表支持的通道的数量,范围从 1 到 14。当传输方向是 ESP 设备到手机时,表示向手机端提供所需信息。 + * - 0x9 (b’001001) + - 用户名 + - 在进行企业级加密时提供 GATT 客户端的用户名。 + - 数据的长度取决于数据长度字段。 + * - 0xa (b’001010) + - CA 认证 + - 在进行企业级加密时提供 CA 认证。 + - 请参考备注 2。 + * - 0xb (b’001011) + - 客户端认证 + - 在进行企业级加密时提供客户端认证。是否包含私钥,取决于认证的内容。 + - 请参考备注 2。 + * - 0xc (b’001100) + - 服务端认证 + - 在进行企业级加密时提供服务端认证。是否包含私钥,取决于认证的内容。 + - 请参考备注 2。 + * - 0xd (b’001101) + - 客户端私钥 + - 在进行企业级加密时提供客户端私钥。 + - 请参考备注 2。 + * - 0xe (b’001110) + - 服务端私钥 + - 在进行企业级加密时提供服务端私钥。 + - 请参考备注 2。 + * - 0xf (b’001111) + - Wi-Fi 连接状态报告 + - 通知手机 ESP 设备的 Wi-Fi 状态,包括 STA 状态和 SoftAP 状态。用于 STA 设备连接手机或 SoftAP。但是,当手机接收到 Wi-Fi 状态时,除了本帧之外,还可以回复其他帧。 + - data[0] 表示 opmode,包括: + + * 0x00: NULL + * 0x01: STA + * 0x02: SoftAP + * 0x03: SoftAP & STA + + data[1]:STA 设备的连接状态,0x0 表示处于连接状态,其他表示处于非连接状态; + + data[2]:SoftAP 的连接状态,即表示有多少 STA 设备已经连接。 + + data[3]及后面的数据是按照 SSID/BSSID 格式提供的信息。 + * - 0x10 (b’010000) + - 版本 + - + - * data[0]= 主版本 + * data[1]= 子版本 + * - 0x11 (b’010001) + - Wi-Fi 热点列表 + - 将 Wi-Fi 热点列表发送给 ESP 设备 + - 数据帧的格式为 length + RSSI + SSID,数据较长时可分片发送。 + * - 0x12 (b’010010) + - 报告异常 + - 通知手机 BluFi 过程出现异常 + - * 0x00: sequence error + * 0x01: checksum error + * 0x02: decrypt error + * 0x03: encrypt error + * 0x04: init security error + * 0x05: dh malloc error + * 0x06: dh param error + * 0x07: read param error + * 0x08: make public error + * - 0x13 (b’010011) + - 自定义数据 + - 用户发送或者接收自定义数据。 + - 数据较长时可分片发送。 + +.. note:: + + - 备注 1: 数据的长度取决于数据长度字段。当传输方向是 ESP 设备到手机时,表示向手机端提供所需信息。 + + - 备注 2: 数据的长度取决于数据长度字段。如果数据长度不够,该帧可用分片。 2. Frame Control - 帧控制域,占 1 byte,每个 bit 表示不同含义。 - - +----------------+-------------------------------------------------------------------------------------------------------------------------------+ - | 位 | 含义 | - +================+===============================================================================================================================+ - | 0x01 | 表示帧是否加密。 | - + +-------------------------------------------------------------------------------------------------------------------------------+ - | | 1 表示加密,0 表示未加密。 | - + +-------------------------------------------------------------------------------------------------------------------------------+ - | | 加密部分帧括完整的 DATA 域加密之前的明文(不帧含末尾的校验)。 | - + +-------------------------------------------------------------------------------------------------------------------------------+ - | | 控制帧暂不加密,故控制帧此位为 0。 | - +----------------+-------------------------------------------------------------------------------------------------------------------------------+ - | 0x02 | 表示帧 Data 域结尾是否帧含校验(例如 SHA1,MD5,CRC等)需要校验的数据域包括 sequcne + data length + 明文 data。 | - + +-------------------------------------------------------------------------------------------------------------------------------+ - | | 控制帧和数据帧都可以包含校验位或不包含。 | - +----------------+-------------------------------------------------------------------------------------------------------------------------------+ - | 0x04 | 表示数据方向。 | - + +-------------------------------------------------------------------------------------------------------------------------------+ - | | 0 表示手机发向 ESP32; | - + +-------------------------------------------------------------------------------------------------------------------------------+ - | | 1 表示 ESP32 发向手机。 | - +----------------+-------------------------------------------------------------------------------------------------------------------------------+ - | 0x08 | 表示是否要求对方回复 ack。 | - + +-------------------------------------------------------------------------------------------------------------------------------+ - | | 0 表示不要求; | - + +-------------------------------------------------------------------------------------------------------------------------------+ - | | 1 表示要求回复 ack。 | - +----------------+-------------------------------------------------------------------------------------------------------------------------------+ - | 0x10 | 表示是否有后续的数据分片。 | - + +-------------------------------------------------------------------------------------------------------------------------------+ - | | 0 表示此帧没有后续数据分片; | - + +-------------------------------------------------------------------------------------------------------------------------------+ - | | 1 表示还有后续数据分片,用来传输较长的数据。 | - + +-------------------------------------------------------------------------------------------------------------------------------+ - | | 如果是 Frag 帧,则告知当前 content 部分+后续 content 部分的总长度,位于 Data 域的前 2 字节(即最大支持 64K 的 content 数据)。 | - +----------------+-------------------------------------------------------------------------------------------------------------------------------+ - | 0x10~0x80 保留 | | - +----------------+-------------------------------------------------------------------------------------------------------------------------------+ + 帧控制字段,占 1 字节,每个位表示不同含义。 -3. Sequence Control +.. list-table:: + :header-rows: 1 + :widths: 10 35 - 序列控制域。帧发送时,无论帧的类型是什么,序列 (Sequence) 都会自动加 1,用来防止重放攻击 (Replay Attack)。每次重现连接后,序列清零。 + * - 位 + - 含义 + * - 0x01 + - 表示帧是否加密。 -4. Length + * 1 表示加密 + * 0 表示未加密 - Data 域的长度,不包含 CheckSum。 + 该帧的加密部分包括数据字段加密之前的完整明文数据(不包括校验部分)。控制帧暂不加密,故控制帧此位为 0。 + * - 0x02 + - 该数据字段表示帧尾是否包含校验位,如 SHA1、MD5、CRC 等。该数据字段包含序列 + 数据长度 + 明文。控制帧和数据帧都可以选择包含或不包含校验位。 + * - 0x04 + - 表示数据方向。 -5. Data + * 0 表示传输方向是手机到 ESP 设备 + * 1 表示传输方向是 ESP 设备到手机 + * - 0x08 + - 表示是否要求对方回复 ACK。 - 不同的 Type 或 Subtype,Data 域的含义均不同。请参考上方表格。 + * 0 表示不要求; + * 1 表示要求回复 ACK。 + * - 0x10 + - 表示是否有后续的数据分片。 -6. CheckSum + * 0 表示此帧没有后续数据分片; + * 1 表示还有后续数据分片,用来传输较长的数据。 + + 对于分片帧,在数据字段的前两个字节中会给定当前内容部分 + 随后内容部分的总长度(即最大支持 64 K 的数据内容)。 + * - 0x10~0x80 + - 保留 - 此域为 2 byte 的校验,用来校验『序列 + 数据长度 + 明文数据』。 +3. 序列控制 -ESP32 端的安全实现 ------------------- + 序列控制字段。帧发送时,无论帧的类型是什么,序列都会自动加 1,用来防止重放攻击 (Replay Attack)。每次重新连接后,序列清零。 -1. 保证数据安全 +4. 长度 - 为了保证 Wi-Fi SSID 和密码的传输过程是安全的,需要使用对称加密算法(例如 AES、DES等)对报文进行加密。在使用对称加密算法之前,需要使用非对称加密算法(DH、RSA、ECC 等)协商出(或生成出)一个共享密钥。 + 数据字段的长度,不包含校验部分。 + +5. 数据 + + 对于不同的类型或子类型,数据字段的含义均不同。请参考上方表格。 + +6. 校验 + + 此字段占两个字节,用来校验“序列 + 数据长度 + 明文数据”。 + +{IDF_TARGET_NAME} 端的安全实现 +---------------------------------- + +1. 数据安全 + + 为了保证 Wi-Fi SSID 和密码的传输过程是安全的,需要使用对称加密算法(例如 AES、DES 等)对报文进行加密。在使用对称加密算法之前,需要使用非对称加密算法(DH、RSA、ECC 等)协商出(或生成出)一个共享密钥。 2. 保证数据完整性 - 保证数据完整性,需要加入校验算法(例如 SHA1、MD5、CRC 等)。 + 为了保证数据完整性,需要加入校验算法,例如 SHA1、MD5、CRC 等。 3. 身份安全(签名) @@ -406,37 +431,39 @@ ESP32 端的安全实现 4. 防止重放攻击 (Replay Attack) - 加入帧发送序列(Sequence),并且序列参与数据校验。 + 添加其到序列字段中,并且在数据校验过程中使用。 - 在 ESP32 端的代码中,你可以决定和开发密钥协商等安全处理的流程参考上述流程图)。手机应用向 ESP32 发送协商数据,将传送给应用层处理。如果应用层不处理,可使用 BluFi 提供的 DH 加密算法来磋商密钥。应用层需向 BluFi 注册以下几个与安全相关的函数: + 在 {IDF_TARGET_NAME} 端的代码中,你可以决定和开发如密钥协商等安全处理的流程。手机应用向 {IDF_TARGET_NAME} 发送协商数据,数据会传送给应用层处理。如果应用层不处理,可使用 BluFi 提供的 DH 加密算法来协商密钥。 + + 应用层需向 BluFi 注册以下几个与安全相关的函数: .. code-block:: c - typedef void (*esp_blufi_negotiate_data_handler_t)(uint8_t *data, int len, uint8_t **output_data, int *output_len, bool *need_free); + typedef void (*esp_blufi_negotiate_data_handler_t)(uint8_t *data, int len, uint8_t **output_data, int *output_len, bool *need_free) -该函数用来接收协商期间的正常数据 (normal data),处理完成后,需要将待发送的数据使用 output_data 和 output_len 传出。 +该函数用来接收协商期间的正常数据 (normal data),数据处理完成后,需要将待发送的数据使用 output_data 和 output_len 传出。 -BluFi 会在调用完 negotiate_data_handler 后,发送 negotiate_data_handler 传出的 output_data。 +BluFi 会在调用完 Negotiate_data_handler 后,发送 Negotiate_data_handler 传出的 output_data。 -这里的两个『*』,因为需要发出去的数据长度未知,所以需要函数自行分配 (malloc) 或者指向全局变量,通过 need_free 通知是否需要释放内存。 +这里的两个 “*”,因为需要发出去的数据长度未知,所以需要函数自行分配 (malloc) 或者指向全局变量,并告知是否需要通过 NEED_FREE 释放内存。 .. code-block:: c - typedef int (* esp_blufi_encrypt_func_t)(uint8_t iv8, uint8_t *crypt_data, int crypt_len); + typedef int (* esp_blufi_encrypt_func_t)(uint8_t iv8, uint8_t *crypt_data, int crypt_len) -加密和解密的数据长度必须一致。其中 iv8 为帧的 8 bit 序列 (sequence),可作为 iv 的某 8 bit 来使用。 +加密和解密的数据长度必须一致。其中 IV8 为帧的 8 位序列,可作为 IV 的某 8 个位来使用。 .. code-block:: c - typedef int (* esp_blufi_decrypt_func_t)(uint8_t iv8, uint8_t *crypt_data, int crypt_len); + typedef int (* esp_blufi_decrypt_func_t)(uint8_t iv8, uint8_t *crypt_data, int crypt_len) -加密和解密的数据长度必须一致。其中 iv8 为帧的 8 bit 序列 (sequence),可作为 iv 的某 8 bit 来使用。 +加密和解密的数据长度必须一致。其中 IV8 为帧的 8 位序列,可作为 IV 的某 8 个位来使用。 .. code-block:: c - typedef uint16_t (*esp_blufi_checksum_func_t)(uint8_t iv8, uint8_t *data, int len); + typedef uint16_t (*esp_blufi_checksum_func_t)(uint8_t iv8, uint8_t *data, int len) -该函数用来计算 CheckSum,返回值为 CheckSum 的值。BluFi 会使用该函数返回值与包末尾的 CheckSum 做比较。 +该函数用来进行校验,返回值为校验的值。BluFi 会使用该函数返回值与帧的校验值进行比较。 GATT 相关说明 ------------- @@ -446,6 +473,6 @@ UUID BluFi Service UUID: 0xFFFF,16 bit -BluFi (手机 -> ESP32) 特性:0xFF01,主要权限:可写 +BluFi (手机 -> {IDF_TARGET_NAME})特性:0xFF01,主要权限:可写 -BluFi (ESP32 -> 手机) 特性:0xFF02,主要权限:可读可通知 \ No newline at end of file +BluFi ({IDF_TARGET_NAME} -> 手机)特性:0xFF02,主要权限:可读可通知 diff --git a/docs/zh_CN/api-guides/bootloader.rst b/docs/zh_CN/api-guides/bootloader.rst index 978246c9d6..d10c9ba661 100644 --- a/docs/zh_CN/api-guides/bootloader.rst +++ b/docs/zh_CN/api-guides/bootloader.rst @@ -1,14 +1,20 @@ -引导加载程序(Bootloader) +引导加载程序 (Bootloader) ========================== + :link_to_translation:`en:[English]` -引导加载程序(Bootloader)主要执行以下任务: +{IDF_TARGET_BOOTLOADER_OFFSET:default="0x0", esp32="0x1000", esp32s2="0x1000"} + +ESP-IDF 软件引导加载程序 (Bootloader) 主要执行以下任务: 1. 内部模块的最小化初始配置; -2. 根据分区表和 ota_data(如果存在)选择需要引导的应用程序(app)分区; -3. 将此应用程序映像加载到 RAM(IRAM 和 DRAM)中,最后把控制权转交给应用程序。 +2. 如果配置了 :doc:`/security/flash-encryption` 和/或 :doc:`Secure `,则对其进行初始化。 +3. 根据分区表和 ota_data(如果存在)选择需要引导的应用程序 (app) 分区; +4. 将此应用程序镜像加载到 RAM(IRAM 和 DRAM)中,最后把控制权转交给此应用程序。 -引导加载程序位于 Flash 的 `0x1000` 偏移地址处。 +引导加载程序位于 flash 的 {IDF_TARGET_BOOTLOADER_OFFSET} 偏移地址处。 + +关于启动过程以及 ESP-IDF 引导加载程序的更多信息,请参考 :doc:`startup`。 .. _bootloader-compatibility: @@ -19,87 +25,143 @@ 但不支持引导从 ESP-IDF 旧版本中构建的程序。如果现有产品可能需要将应用程序降级到旧版本,那么在手动更新 ESP-IDF 时,请继续使用旧版本 ESP-IDF 引导加载程序的二进制文件。 +.. note:: + + 如果在生产中测试现有产品的 OTA 更新,请确保测试中使用的 ESP-IDF 引导加载程序二进制文件与生产中部署的相同。 + +.. only:: esp32 + + ESP-IDF V2.1 之前的版本 + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + 与新版本相比,ESP-IDF V2.1 之前的版本构建的引导加载程序对硬件的配置更少。使用这些早期 ESP-IDF 版本的引导加载程序并构建新应用程序时,请启用配置选项 :ref:`CONFIG_ESP32_COMPATIBLE_PRE_V2_1_BOOTLOADERS`。 + + ESP-IDF V3.1 之前的版本 + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + ESP-IDF V3.1 之前的版本构建的引导加载程序不支持分区表二进制文件中的 MD5 校验。使用这些 ESP-IDF 版本的引导加载程序并构建新应用程序时,请启用配置选项 :ref:`CONFIG_ESP32_COMPATIBLE_PRE_V3_1_BOOTLOADERS`。 + +配置 SPI Flash +^^^^^^^^^^^^^^^^^^^^^^^ + +每个 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 的配置。 + +.. only:: esp32 + + ESP-IDF V4.0 版本之前的引导加载程序使用其自身的文件头来配置 SPI flash,这意味着无法在 OTA 更新时更改 SPI flash 配置。为了与旧引导加载程序兼容,应用程序在其启动期间使用应用程序文件头中的配置信息重新初始化 flash 配置。 + +日志级别 +--------- + +引导加载程序日志的级别默认为 "Info"。通过设置 :ref:`CONFIG_BOOTLOADER_LOG_LEVEL` 选项,可以增加或减少这个等级。这个日志级别与应用程序中使用的日志级别是分开的(见 :doc:`/api-reference/system/log`)。 + +降低引导加载程序日志的详细程度可以稍微缩短整个项目的启动时间。 + 恢复出厂设置 ------------ -用户可以编写一个基本的工作固件,然后将其加载到工厂分区(factory)中。 -接下来,通过 OTA(空中升级)更新固件,更新后的固件会被保存到某个 OTA app 分区中,OTA 数据分区也会做相应更新以指示从该分区引导应用程序。 +在更新出现问题时,最好能有一种方法让设备回到已知的正常状态,这时可选择恢复出厂设置。 -如果你希望回滚到出厂固件并清除设置,则需要设置 :ref:`CONFIG_BOOTLOADER_FACTORY_RESET`。出厂重置机制允许将设备重置为出厂模式: +要回到原始出厂设置并清除所有用户设置,请在引导加载程序中配置 :ref:`CONFIG_BOOTLOADER_FACTORY_RESET`。 -- 清除一个或多个数据分区。 -- 从工厂分区启动。 +以下两种方式可以将设备恢复出厂设置。 -:ref:`CONFIG_BOOTLOADER_DATA_FACTORY_RESET` - 允许用户选择在恢复出厂设置时需要擦除的数据分区。可以通过逗号来分隔多个分区的名字,并适当增加空格以便阅读(例如 "nvs, phy_init, nvs_custom, ...")。请确保此处指定的名称和分区表中的名称相同,且不含有 “app” 类型的分区。 +- 清除一个或多个数据分区。:ref:`CONFIG_BOOTLOADER_DATA_FACTORY_RESET` 选项允许用户选择哪些数据分区在恢复出厂设置时需要被擦除。 -:ref:`CONFIG_BOOTLOADER_OTA_DATA_ERASE` - 恢复出厂模式后,设备会从工厂分区启动,OTA 数据分区会被清除。 + 用户可以使用以逗号分隔的列表形式指定分区的名称,为了提高可读性,可以选择添加空格(如:``nvs, phy_init, nvs_custom``)。 -:ref:`CONFIG_BOOTLOADER_NUM_PIN_FACTORY_RESET`- 设置用于触发出厂重置的 GPIO 编号,必须在芯片复位时将此 GPIO 拉低才能触发出厂重置事件。 + 请确保选项里指定的分区名称和分区表中的名称相同。此处不能指定 “app” 类型的分区。 -:ref:`CONFIG_BOOTLOADER_HOLD_TIME_GPIO`- 设置进入重置或测试模式所需要的保持时间(默认为 5 秒)。设备复位后,GPIO 必须在这段时间内持续保持低电平,然后才会执行出厂重置或引导测试分区。 +- 从“工厂”应用分区启动。当启用 :ref:`CONFIG_BOOTLOADER_OTA_DATA_ERASE` 选项,恢复出厂设置后,设备将从默认的“工厂”应用分区启动(如果分区表中没有“工厂”应用分区,则从默认的 OTA 应用分区启动)。这个恢复过程是通过擦除 OTA 数据分区来完成的,OTA 数据分区中保存了当前选择的 OTA 分区槽。“工厂”应用分区槽(如果存在)永远不会通过 OTA 更新,因此重置为从“工厂”应用分区启动则意味着让固件应用程序恢复正常状态。 -示例分区表如下:: +这两个配置选项都可以独立启用。 - # Name, Type, SubType, Offset, Size, Flags - # 注意,如果你增大了引导加载程序的大小,请确保更新偏移量,避免和其它分区发生重叠 - nvs, data, nvs, 0x9000, 0x4000 - otadata, data, ota, 0xd000, 0x2000 - phy_init, data, phy, 0xf000, 0x1000 - factory, 0, 0, 0x10000, 1M - test, 0, test, , 512K - ota_0, 0, ota_0, , 512K - ota_1, 0, ota_1, , 512K +此外,以下配置选项用于配置触发恢复出厂设置的条件: + +- :ref:`CONFIG_BOOTLOADER_NUM_PIN_FACTORY_RESET`- 输入管脚 (GPIO) 的编号,该管脚用于触发恢复出厂设置。必须在重置时将此管脚拉低或拉高(可配置)才能触发出厂重置事件。 + +- :ref:`CONFIG_BOOTLOADER_HOLD_TIME_GPIO`- 管脚电平保持时间(默认为 5 秒)。设备重置后,管脚电平必须保持该设定的时间,才能执行恢复出厂设置或引导测试分区(如适用)。 + +- :ref:`CONFIG_BOOTLOADER_FACTORY_RESET_PIN_LEVEL` - 设置管脚电平高低。设备重置后,根据此设置将管脚拉高或拉低,才能触发出厂重置事件。如果管脚具有内部上拉,则上拉会在管脚采样前生效。有关管脚内部上拉的详细信息,请参考 {IDF_TARGET_NAME} 的技术规格书。 .. _bootloader_boot_from_test_firmware: -从测试应用程序分区启动 ------------------------- -用户可以编写特殊固件用于生产环境中测试,然后在需要的时候运行。此时需要在分区表中专门申请一块分区用于保存该测试固件(详情请参阅 :doc:`分区表 `)。如果想要触发测试固件,还需要设置 :ref:`CONFIG_BOOTLOADER_APP_TEST`。 +从测试固件启动 +------------------- -:ref:`CONFIG_BOOTLOADER_NUM_PIN_APP_TEST` - 设置引导测试分区的 GPIO 管脚编号,该 GPIO 会被配置为输入模式,并且会使能内部上拉电阻。若想触发测试固件,该 GPIO 必须在芯片复位时拉低。设备重启时如果该 GPIO 没有被激活(即处于高电平状态),那么会加载常规配置的应用程序(可能位于工厂分区或者 OTA 分区)。 +用户可以编写特殊固件用于生产环境中测试,并在需要的时候运行。此时需要在项目分区表中专门申请一块分区用于保存该测试固件,其类型为 app,子类型为 test(详情请参考 :doc:`/api-guides/partition-tables`)。 -:ref:`CONFIG_BOOTLOADER_HOLD_TIME_GPIO` - 设置进入重置或测试模式所需要的保持时间(默认为 5 秒)。设备复位后,GPIO 必须在这段时间内持续保持低电平,然后才会执行出厂重置或引导测试分区。 +实现该测试应用固件需要为测试应用创建一个完全独立的 ESP-IDF 项目(ESP-IDF 中的每个项目仅构建一个应用)。该测试应用可以独立于主项目进行开发和测试,然后在生成测试时作为一个预编译 .bin 文件集成到主项目的测试应用程序分区的地址。 + +为了使主项目的引导加载程序支持这个功能,请设置 :ref:`CONFIG_BOOTLOADER_APP_TEST` 并配置以下两个选项: + +- :ref:`CONFIG_BOOTLOADER_NUM_PIN_APP_TEST` - 设置启动 TEST 分区的管脚编号。选中的管脚将被配置为启用了内部上拉的输入。要触发测试应用,必须在重置时将此管脚 拉低。 + + 当管脚输入被释放(则被拉高)并将设备重新启动后,正常配置的应用程序将启动(工厂或任意 OTA 应用分区槽)。 + +- :ref:`CONFIG_BOOTLOADER_HOLD_TIME_GPIO` - 设置 GPIO 电平保持的时间(默认为 5 秒)。设备重置后,管脚在设定的时间内必须持续保持低电平,然后才会执行出厂重置或引导测试分区(如适用)。 + +回滚 +-------- + +回滚和反回滚功能也必须在引导程序中配置。 + +请参考 :doc:`OTA API 参考文档 ` 中的 :ref:`app_rollback` 和 :ref:`anti-rollback` 章节。 + +看门狗 +---------- + +默认情况下,硬件 RTC 看门狗定时器在引导加载程序运行时保持运行,如果 9 秒后没有应用程序成功启动,它将自动重置芯片。 + +- 可以通过设置 :ref:`CONFIG_BOOTLOADER_WDT_TIME_MS` 并重新编译引导加载程序来调整超时时间。 +- 可以通过调整应用程序的行为使 RTC 看门狗在应用程序启动后保持启用。看门狗需要由应用程序显示地重置(即“喂狗”),以避免重置。为此,请设置 :ref:`CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE` 选项,根据需要修改应用程序,然后重新编译应用程序。 +- 通过禁用 :ref:`CONFIG_BOOTLOADER_WDT_ENABLE` 设置并重新编译引导加载程序,可以在引导加载程序中禁用 RTC 看门狗,但并不建议这样做。 .. _bootloader-size: -Bootloader Size ---------------- +引导加载程序大小 +--------------------- {IDF_TARGET_DEFAULT_MAX_BOOTLOADER_SIZE:default = "0x8000 (32768)", esp32 = "0x7000 (28672)", esp32s2 = "0x7000 (28672)"} {IDF_TARGET_MAX_BOOTLOADER_SIZE:default = "64KB (0x10000 bytes)", esp32 = "48KB (0xC000 bytes)"} {IDF_TARGET_MAX_PARTITION_TABLE_OFFSET:default = "0x12000", esp32 = "0xE000"} .. Above is calculated as 0x1000 at start of flash + IDF_TARGET_MAX_BOOTLOADER_SIZE + 0x1000 signature sector -When enabling additional bootloader functions, including :doc:`/security/flash-encryption` or Secure Boot, and especially if setting a high :ref:`CONFIG_BOOTLOADER_LOG_LEVEL` level, then it is important to monitor the bootloader .bin file's size. +当需要启用额外的引导加载程序功能,包括 :doc:`/security/flash-encryption` 或安全启动,尤其是设置高级别 :ref:`CONFIG_BOOTLOADER_LOG_LEVEL` 时,监控引导加载程序 .bin 文件的大小变得非常重要。 -When using the default :ref:`CONFIG_PARTITION_TABLE_OFFSET` value 0x8000, the size limit is {IDF_TARGET_DEFAULT_MAX_BOOTLOADER_SIZE} bytes. +当使用默认的 :ref:`CONFIG_PARTITION_TABLE_OFFSET` 值 0x8000 时,二进制文件最大可为 {IDF_TARGET_DEFAULT_MAX_BOOTLOADER_SIZE} 字节。 -If the bootloader binary is too large, then the bootloader build will fail with an error "Bootloader binary size [..] is too large for partition table offset". If the bootloader binary is flashed anyhow then the {IDF_TARGET_NAME} will fail to boot - errors will be logged about either invalid partition table or invalid bootloader checksum. +如果引导加载程序二进制文件过大,则引导加载程序会构建将失败并显示 "Bootloader binary size [..] is too large for partition table offset" 的错误。如果此二进制文件已经被烧录,那么 {IDF_TARGET_NAME} 将无法启动 - 日志中将记录无效分区表或无效引导加载程序校验和的错误。 .. note:: - The bootloader size check only happens in the CMake Build System, when using the legacy GNU Make Build System the size is not checked but the {IDF_TARGET_NAME} will fail to boot if bootloader is too large. + 对引导加载程序大小检查仅发生在 CMake 构建系统中,若使用的是旧版 GNU Make 构建系统,则不会检查大小,但如果引导加载程序太大,{IDF_TARGET_NAME} 将无法启动。 -Options to work around this are: +可以使用如下方法解决此问题: -- Set :ref:`bootloader compiler optimization ` back to "Size" if it has been changed from this default value. -- Reduce :ref:`bootloader log level `. Setting log level to Warning, Error or None all significantly reduce the final binary size (but may make it harder to debug). -- Set :ref:`CONFIG_PARTITION_TABLE_OFFSET` to a higher value than 0x8000, to place the partition table later in the flash. This increases the space available for the bootloader. If the :doc:`partition table ` CSV file contains explicit partition offsets, they will need changing so no partition has an offset lower than ``CONFIG_PARTITION_TABLE_OFFSET + 0x1000``. (This includes the default partition CSV files supplied with ESP-IDF.) +- 将 :ref:`bootloader 编译器优化 ` 重新设置回默认值“Size”。 +- 降低 :ref:`引导加载程序日志级别 `。将日志级别设置为 Warning, Error 或 None 都会显著减少最终二进制文件的大小(但也可能会让调试变得更加困难)。 +- 将 :ref:`CONFIG_PARTITION_TABLE_OFFSET` 设置为高于 0x8000 的值,以便稍后将分区表放置在 flash 中,这样可以增加引导加载程序的可用空间。如果 :doc:`分区表 ` 的 CSV 文件包含明确的分区偏移量,则需要修改这些偏移量,从而保证没有分区的偏移量低于 ``CONFIG_PARTITION_TABLE_OFFSET + 0x1000``。(这包括随 ESP-IDF 提供的默认分区 CSV 文件) -When Secure Boot V2 is enabled, there is also an absolute binary size limit of {IDF_TARGET_MAX_BOOTLOADER_SIZE} (excluding the 4KB signature), because the bootloader is first loaded into a fixed size buffer for verification. +当启用 Secure Boot V2 时,由于引导加载程序最先加载到固定大小的缓冲区中进行验证,对二进制文件大小的绝对限制为 {IDF_TARGET_MAX_BOOTLOADER_SIZE}(不包括 4 KB 签名)。 从深度睡眠中快速启动 ---------------------- -引导加载程序有 :ref:`CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP` 选项,可以减少唤醒时间(有利于降低消耗)。当 :ref:`CONFIG_SECURE_BOOT` 选项禁用时,该选项可用。由于无需固件校验,唤醒时间减少。在第一次启动时,引导加载程序将启动的应用程序的地址存储在 RTC FAST 存储器中。而在唤醒过程中,这个地址用于启动而无需任何检查,从而实现了快速加载。 -自定义引导程序 --------------- -用户可以重写当前的引导加载程序,具体做法是,复制 `/esp-idf/components/bootloader` 文件夹到项目组件目录中,然后编辑 ``/your_project/components/bootloader/subproject/main/bootloader_start.c`` 文件。 +引导加载程序有 :ref:`CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP` 选项,可以减少从深度睡眠中唤醒的时间(有利于降低功耗)。当 :ref:`CONFIG_SECURE_BOOT` 选项禁用时,该选项可用。由于无需镜像校验,唤醒时间减少。在第一次启动时,引导加载程序将启动的应用程序的地址存储在 RTC FAST 存储器中。而在唤醒过程中,这个地址用于启动而无需任何检查,从而实现了快速加载。 -在引导加载程序的代码中,用户不能使用其他组件提供的驱动和函数,如果确实需要,请将该功能的实现部分放在项目的 bootloader 目录中(注意,这会增加引导程序的大小)。 +自定义引导加载程序 +---------------------- -如果引导程序过大,则可能与内存中的分区表重叠,分区表默认烧录在 -偏移量 0x8000 处。增加 :ref:`分区表偏移量值 ` ,将分区表放在 flash 中靠后的区域,这样可以增加引导程序的可用空间。 +用户可以扩展或修改当前的引导加载程序,具体有两种方法:使用钩子实现或重写覆盖当前程序。这两种方法在 ESP-IDF 示例的 :example:`custom_bootloader` 文件夹中都有呈现。 -.. note:: 初次将引导程序复制到现有项目中时,由于路径发生了意外变化,项目可能无法构建。对于这种情况,请运行 ``idf.py fullclean`` (或删除项目构建目录),然后重新构建。 +* `bootloader_hooks` 介绍了如何将钩子与引导加载程序初始化连接。 +* `bootloader_override` 介绍了如何覆盖引导加载程序的实现。 +在引导加载程序的代码中,用户不能使用其他组件提供的驱动和函数,如果确实需要,请将该功能的实现部分放在项目的 `bootloader_components` 目录中(注意,这会增加引导加载程序的大小)。 + +如果引导加载程序过大,则可能与内存中的分区表重叠,分区表默认烧录在偏移量 0x8000 处。增加 :ref:`分区表偏移量 ` ,将分区表放在 flash 中靠后的区域,这样可以增加引导程序的可用空间。 + +.. note:: 上述任意一种自定义引导程序的方法都需要使用 CMake 构建系统(即不支持传统的 Make 构建系统)。 diff --git a/docs/zh_CN/api-guides/build-system.rst b/docs/zh_CN/api-guides/build-system.rst index a9c9d4c646..93a3da90d7 100644 --- a/docs/zh_CN/api-guides/build-system.rst +++ b/docs/zh_CN/api-guides/build-system.rst @@ -99,9 +99,10 @@ idf.py - ``idf.py app``,``idf.py bootloader``,``idf.py partition_table`` 仅可用于从适用的项目中构建应用程序、引导程序或分区表。 - ``idf.py app-flash`` 等匹配命令,仅将项目的特定部分烧录至 {IDF_TARGET_NAME}。 - ``idf.py -p PORT erase_flash`` 会使用 esptool.py 擦除 {IDF_TARGET_NAME} 的整个 Flash。 -- ``idf.py size`` 会打印应用程序相关的大小信息,``idf.py size-components`` 和 ``idf.py size-files`` 这两个命令相似,分别用于打印每个组件或源文件的详细信息。如果您在运行 CMake(或 ``idf.py``)时定义了变量 ``-DOUTPUT_JSON=1``,那么输出的格式会变成 JSON 而不是可读文本。 +- ``idf.py size`` 会打印应用程序相关的大小信息,``size-components`` 和 ``size-files`` 这两个命令相似,分别用于打印每个组件或源文件的详细信息。如果您在运行 CMake(或 ``idf.py``)时定义了变量 ``-DOUTPUT_JSON=1``,那么输出的格式会变成 JSON 而不是可读文本。详情请查看 ``idf.py-size``。 - ``idf.py reconfigure`` 命令会重新运行 CMake_ (即便无需重新运行)。正常使用时,并不需要运行此命令,但当源码树中添加/删除文件后或更改 CMake cache 变量时,此命令会非常有用,例如,``idf.py -DNAME='VALUE' reconfigure`` 会将 CMake cache 中的变量 ``NAME`` 的值设置为 ``VALUE``。 - ``idf.py python-clean`` 会从 IDF 目录中删除生成的 Python 字节码,Python 字节码可能会在切换 IDF 和 Python 版本时引发问题,因此建议在切换 Python 后运行该命令。 +- ``idf.py docs`` 将在浏览器中直接打开项目目标芯片和对应版本的文档链接。请使用 ``idf.py docs --help`` 查看所有选项。 同时调用多个 ``idf.py`` 命令时,命令的输入顺序并不重要,它们会按照正确的顺序依次执行,并保证每一条命令都生效(即先构建后烧录,先擦除后烧录等)。 @@ -363,7 +364,7 @@ ESP-IDF 适用于所有支持的 Python 版本。即使您系统中默认的 ``p ESP-IDF 在搜索所有待构建的组件时,会按照 ``COMPONENT_DIRS`` 指定的顺序依次进行,这意味着在默认情况下,首先搜索 ESP-IDF 内部组件(``IDF_PATH/components``),然后是 ``EXTRA_COMPONENT_DIRS`` 中的组件,最后是项目组件(``PROJECT_DIR/components``)。如果这些目录中的两个或者多个包含具有相同名字的组件,则使用搜索到的最后一个位置的组件。这就允许将组件复制到项目目录中再修改以覆盖 ESP-IDF 组件,如果使用这种方式,ESP-IDF 目录本身可以保持不变。 -.. 注解:: 如果在现有项目中通过将组件移动到一个新位置来覆盖它,项目不会自动看到新组件的路径。请运行 ``idf.py reconfigure`` 命令后(或删除项目构建文件夹)再重新构建。 +.. 注解:: 如果在现有项目中通过将组件移动到一个新位置来覆盖它,项目不会自动看到新组件的路径。请运行 ``idf.py reconfigure`` 命令后(或删除项目构建文件夹)再重新构建。 .. _minimum_cmakelists: @@ -449,7 +450,7 @@ ESP-IDF 在搜索所有待构建的组件时,会按照 ``COMPONENT_DIRS`` 指 .. highlight:: cmake -在编译特定组件的源文件时,可以使用 ``target_compile_options`` 命令来传递编译器选项:: +在编译特定组件的源文件时,可以使用 `target_compile_options`_ 函数来传递编译器选项:: target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-unused-variable) @@ -650,12 +651,54 @@ Spark Plug 组件 - 将 ``COMPONENTS`` 设置为所需组件的最小列表,可以显著减少项目的构建时间。 +.. _component-circular-dependencies: + +循环依赖 +--------------------- + +一个项目中可能包含组件 A 和组件 B,而组件 A 依赖(``REQUIRES`` 或 ``PRIV_REQUIRES``)组件 B,组件 B 又依赖组件 A。这就是所谓的依赖循环或循环依赖。 + +CMake 通常会在链接器命令行上重复两次组件库名称来自动处理循环依赖。然而这种方法并不总是有效,还是可能构建失败并出现关于 “Undefined reference to ...” 的链接器错误,这通常是由于引用了循环依赖中某一组件中定义的符号。如果存在较大的循环依赖关系,即 A->B->C->D->A,这种情况极有可能发生。 + +最好的解决办法是重构组件以消除循环依赖关系。在大多数情况下,没有循环依赖的软件架构具有模块化和分层清晰的特性,并且从长远来看更容易维护。然而,移除循环依赖关系并不容易做到。 + +要绕过由循环依赖引起的链接器错误,最简单的解决方法是增加其中一个组件库的 CMake `LINK_INTERFACE_MULTIPLICITY`_ 属性。 这会让 CMake 在链接器命令行上对此库及其依赖项重复两次以上。 + +例如: + +.. code-block:: cmake + + set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY LINK_INTERFACE_MULTIPLICITY 3) + +- 这一行应该放在组件 CMakeLists.txt 文件 ``idf_component_register`` 之后。 +- 可以的话,将此行放置在因依赖其他组件而造成循环依赖的组件中。实际上,该行可以放在循环内的任何一个组件中,但建议将其放置在拥有链接器错误提示信息中显示的源文件的组件中,或是放置在定义了链接器错误提示信息中所提到的符号的组件,先从这些组件开始是个不错的选择。 +- 通常将值增加到 3(默认值是 2)就足够了,但如果不起作用,可以尝试逐步增加这个数字。 +- 注意,增加这个选项会使链接器的命令行变长,链接阶段变慢。 + +高级解决方法:未定义符号 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +如果只有一两个符号导致循环依赖,而所有其他依赖都是线性的,那么有一种替代方法可以避免链接器错误:在链接时将“反向”依赖所需的特定符号指定为未定义符号。 + +例如,如果组件 A 依赖于组件 B,但组件 B 也需要引用组件 A 的 ``reverse_ops`` (但不依赖组件 A 中的其他内容),那么你可以在组件 B 的 CMakeLists.txt 中添加如下一行,以在链接时避免这出现循环。 + +.. code-block:: cmake + + # 该符号是由“组件 A”在链接时提供 + target_link_libraries(${COMPONENT_LIB} INTERFACE "-u reverse_ops") + +- ``-u`` 参数意味着链接器将始终在链接中包含此符号,而不管依赖项顺序如何。 +- 该行应该放在组件 CMakeLists.txt 文件中的 ``idf_component_register`` 之后。 +- 如果“组件 B”不需要访问“组件 A”的任何头文件,只需链接几个符号,那么这一行可以用来代替 B 对 A 的任何 “REQUIRES”。这样则进一步简化了构建系统中的组件结构。 + +请参考 `target_link_libraries`_ 文档以了解更多关于此 CMake 函数的信息。 + .. _component-requirements-implementation: 构建系统中依赖处理的实现细节 ---------------------------- -- 在 CMake 配置进程的早期阶段会运行 ``expand_requirements.cmake`` 脚本。该脚本会对所有组件的 CMakeLists.txt 文件进行局部的运算,得到一张组件依赖关系图(此图可能会有闭环)。此图用于在构建目录中生成 ``component_depends.cmake`` 文件。 +- 在 CMake 配置进程的早期阶段会运行 ``expand_requirements.cmake`` 脚本。该脚本会对所有组件的 CMakeLists.txt 文件进行局部的运算,得到一张组件依赖关系图(:ref:`此图可能会有闭环 `)。此图用于在构建目录中生成 ``component_depends.cmake`` 文件。 - CMake 主进程会导入该文件,并以此来确定要包含到构建系统中的组件列表(内部使用的 ``BUILD_COMPONENTS`` 变量)。``BUILD_COMPONENTS`` 变量已排好序,依赖组件会排在前面。由于组件依赖关系图中可能存在闭环,因此不能保证每个组件都满足该排序规则。如果给定相同的组件集和依赖关系,那么最终的排序结果应该是确定的。 - CMake 会将 ``BUILD_COMPONENTS`` 的值以 “Component names:” 的形式打印出来。 - 然后执行构建系统中包含的每个组件的配置。 @@ -976,6 +1019,8 @@ ExternalProject 的依赖与构建清理 如若需要覆盖此文件的名称或指定多个文件,请设置 ``SDKCONFIG_DEFAULTS`` 环境变量或在顶层 CMakeLists.txt 文件中设置 ``SDKCONFIG_DEFAULTS``。在指定多个文件时,使用分号作为分隔符。未指定完整路径的文件名将以当前项目的相对路径来解析。 +一些 IDF 示例中包含了 ``sdkconfig.ci`` 文件。该文件是 CI(持续集成)测试框架的一部分,在正常构建过程中会被忽略。 + 依赖于硬件目标的 sdkconfig 默认值 --------------------------------- @@ -1099,7 +1144,7 @@ CMake 在许多开源的 C/C++ 项目中广泛使用,用户可以在自己的 每当使用 ESP-IDF 构建系统时,CMake 变量 ``ESP_PLATFORM`` 都会被设置为 1。如果要在通用的 CMake 代码加入 IDF 特定的代码时,可以采用 ``if (ESP_PLATFORM)`` 的形式加以分隔。 -外部库中使用 ESP-IDF 组件 +外部库中使用 ESP-IDF 组件 -------------------------- 上述示例中假设的是外部库 ``foo`` (或 ``import_lib`` 示例中的 ``tinyxml`` 库)除了常见的 API 如 libc、libstdc++ 等外不需要使用其它 ESP-IDF API。如果外部库需要使用其它 ESP-IDF 组件提供的 API,则需要在外部 CMakeLists.txt 文件中通过添加对库目标 ``idf::`` 的依赖关系。 @@ -1109,12 +1154,12 @@ CMake 在许多开源的 C/C++ 项目中广泛使用,用户可以在自己的 add_library(foo bar.c fizz.cpp buzz.cpp) if(ESP_PLATFORM) - # 在 ESP-IDF 中、 bar.c 需要包含 spi_flash 组件中的 esp_spi_flash.h + # 在 ESP-IDF 中、 bar.c 需要包含 spi_flash 组件中的 esp_spi_flash.h target_link_libraries(foo PRIVATE idf::spi_flash) endif() -组件中使用预建库 +组件中使用预建库 ================= .. highlight:: cmake @@ -1151,11 +1196,11 @@ ESP-IDF 提供了一个模板 CMake 项目,可以基于此轻松创建应用 # 导入提供 ESP-IDF CMake 构建系统 API 的 CMake 文件 include($ENV{IDF_PATH}/tools/cmake/idf.cmake) - # 在构建中导入 ESP-IDF 组件,可以视作等同 add_subdirectory() + # 在构建中导入 ESP-IDF 组件,可以视作等同 add_subdirectory() # 但为 ESP-IDF 构建增加额外的构建过程 # 具体构建过程 idf_build_process(esp32) - + # 创建项目可执行文件 # 使用其别名 idf::newlib 将其链接到 newlib 组件 add_executable(${CMAKE_PROJECT_NAME}.elf main.c) @@ -1201,7 +1246,7 @@ idf 构建命令 .. code-block:: none - idf_build_process(target + idf_build_process(target [PROJECT_DIR project_dir] [PROJECT_VER project_ver] [PROJECT_NAME project_name] @@ -1331,7 +1376,7 @@ idf 组件命令 - EMBED_FILES - 嵌入组件的二进制文件 - EMBED_TXTFILES - 嵌入组件的文本文件 - + .. _cmake-component-properties: idf 组件属性 @@ -1450,16 +1495,16 @@ ESP-IDF 构建系统的列表文件位于 :idf:`/tools/cmake` 中。实现构建 :scale: 100% :caption: ESP-IDF Build System Process :align: center - + blockdiag idf-build-system-process { 初始化 -> 枚举 枚举 -> 处理 处理 -> 完成 } -初始化 +初始化 ^^^^^^^ - + 该阶段为构建设置必要的参数。 - 在将 ``idf.cmake`` 导入 ``project.cmake`` 后,将执行以下步骤: @@ -1495,7 +1540,7 @@ ESP-IDF 构建系统的列表文件位于 :idf:`/tools/cmake` 中。实现构建 完成 ^^^^^^^ 该阶段是 ``idf_build_process()`` 剩余的步骤。 - + - 创建可执行文件并将其链接到组件库中。 - 生成 project_description.json 等项目元数据文件并且显示所建项目等相关信息。 @@ -1583,6 +1628,7 @@ CMake 中不可用的功能 .. _target_compile_options: https://cmake.org/cmake/help/v3.5/command/target_compile_options.html .. _target_link_libraries: https://cmake.org/cmake/help/v3.5/command/target_link_libraries.html#command:target_link_libraries .. _cmake_toolchain_file: https://cmake.org/cmake/help/v3.5/variable/CMAKE_TOOLCHAIN_FILE.html +.. _LINK_INTERFACE_MULTIPLICITY: https://cmake.org/cmake/help/v3.5/prop_tgt/LINK_INTERFACE_MULTIPLICITY.html .. _quirc: https://github.com/dlbeer/quirc .. _pyenv: https://github.com/pyenv/pyenv#readme .. _virtualenv: https://virtualenv.pypa.io/en/stable/ diff --git a/docs/zh_CN/api-guides/fatal-errors.rst b/docs/zh_CN/api-guides/fatal-errors.rst index 626121bbc6..f306927588 100644 --- a/docs/zh_CN/api-guides/fatal-errors.rst +++ b/docs/zh_CN/api-guides/fatal-errors.rst @@ -207,6 +207,36 @@ MSTATUS : 0x00001881 MTVEC : 0x40380001 MCAUSE : 0x00000007 MTVAL : 0x00000000 MHARTID : 0x00000000 + 此外,由于紧急处理程序中提供了堆栈转储,因此 :doc:`IDF 监视器 ` 也可以生成并打印回溯。 + 输出结果如下: + + :: + + Backtrace: + + 0x42006686 in bar (ptr=ptr@entry=0x0) at ../main/hello_world_main.c:18 + 18 *ptr = 0x42424242; + #0 0x42006686 in bar (ptr=ptr@entry=0x0) at ../main/hello_world_main.c:18 + #1 0x42006692 in foo () at ../main/hello_world_main.c:22 + #2 0x420066ac in app_main () at ../main/hello_world_main.c:28 + #3 0x42015ece in main_task (args=) at /Users/user/esp/components/freertos/port/port_common.c:142 + #4 0x403859b8 in vPortEnterCritical () at /Users/user/esp/components/freertos/port/riscv/port.c:130 + #5 0x00000000 in ?? () + Backtrace stopped: frame did not save the PC + + 虽然以上的回溯信息非常方便,但要求用户使用 :doc:`IDF 监视器 `。因此,如果用户希望使用其它的串口监控软件也能显示堆栈回溯信息,则需要在 menuconfig 中启用 :ref:`CONFIG_ESP_SYSTEM_USE_EH_FRAME` 选项。 + + 该选项会让编译器为项目的每个函数生成 DWARF 信息。然后,当 CPU 异常发生时,紧急处理程序将解析这些数据并生成出错任务的堆栈回溯信息。输出结果如下: + + :: + + Backtrace: 0x42009e9a:0x3fc92120 0x42009ea6:0x3fc92120 0x42009ec2:0x3fc92130 0x42024620:0x3fc92150 0x40387d7c:0x3fc92160 0xfffffffe:0x3fc92170 + + 这些 ``PC:SP`` 对代表当前任务每一个栈帧的程序计数器值(Program Counter)和栈顶地址(Stack Pointer)。 + + + :ref:`CONFIG_ESP_SYSTEM_USE_EH_FRAME` 选项的主要优点是,回溯信息可以由程序自己解析生成并打印 (而不依靠 :doc:`IDF 监视器 `)。但是该选项会导致编译后的二进制文件更大(增幅可达 20% 甚至 100%)。此外,该选项会将调试信息也保存在二进制文件里。因此,强烈不建议用户在量产/生产版本中启用该选项。 + 若要查找发生严重错误的代码位置,请查看 "Backtrace" 的后面几行,发生严重错误的代码显示在顶行,后续几行显示的是调用堆栈。 .. _GDB-Stub: @@ -489,4 +519,4 @@ UBSAN 报告的错误类型为以下几种: * - ``builtin_unreachable`` - 调用 ``__builtin_unreachable`` 函数 * - ``pointer_overflow`` - - 指针运算过程中的溢出 \ No newline at end of file + - 指针运算过程中的溢出 diff --git a/docs/zh_CN/api-guides/index.rst b/docs/zh_CN/api-guides/index.rst index e23b69ae91..e0b8a7db3f 100644 --- a/docs/zh_CN/api-guides/index.rst +++ b/docs/zh_CN/api-guides/index.rst @@ -27,6 +27,7 @@ API 指南 JTAG 调试 链接脚本生成机制 lwIP TCP/IP 协议栈 + OpenThread Memory Types 分区表 Performance @@ -44,3 +45,4 @@ API 指南 :SOC_USB_OTG_SUPPORTED: USB 控制台 :SOC_USB_SERIAL_JTAG_SUPPORTED: USB Serial/JTAG Controller Console Wi-Fi 驱动 + Wi-Fi Security diff --git a/docs/zh_CN/api-guides/jtag-debugging/index.rst b/docs/zh_CN/api-guides/jtag-debugging/index.rst index faf74c79fa..c29b6c719e 100644 --- a/docs/zh_CN/api-guides/jtag-debugging/index.rst +++ b/docs/zh_CN/api-guides/jtag-debugging/index.rst @@ -2,24 +2,24 @@ JTAG 调试 ========= :link_to_translation:`en:[English]` -本文将指导安装 {IDF_TARGET_NAME} 的 OpenOCD 调试环境,并介绍如何使用 GDB 来调试 {IDF_TARGET_NAME} 的应用程序。本文的组织结构如下: +本文将介绍如何安装 {IDF_TARGET_NAME} 的 OpenOCD 调试环境,以及如何使用 GDB 来调试 {IDF_TARGET_NAME} 的应用程序。本文结构如下: :ref:`jtag-debugging-introduction` 介绍本指南主旨。 :ref:`jtag-debugging-how-it-works` - 介绍 {IDF_TARGET_NAME},JTAG(Joint Test Action Group)接口,OpenOCD 和 GDB 是如何相互连接从而实现 {IDF_TARGET_NAME} 的调试功能。 + 介绍 {IDF_TARGET_NAME}、JTAG(Joint Test Action Group)接口、OpenOCD 和 GDB 如何相互连接,从而实现 {IDF_TARGET_NAME} 的调试功能。 :ref:`jtag-debugging-selecting-jtag-adapter` 介绍有关 JTAG 硬件适配器的选择及参照标准。 :ref:`jtag-debugging-setup-openocd` 介绍如何安装官方预编译好的 OpenOCD 软件包并验证是否安装成功。 :ref:`jtag-debugging-configuring-target` - 介绍如何设置 OpenOCD 软件并安装 JTAG 硬件适配器,这两者共同组成最终的调试目标。 + 介绍如何设置 OpenOCD 软件并安装 JTAG 硬件,两项共同构成调试目标. :ref:`jtag-debugging-launching-debugger` 介绍如何从 :ref:`Eclipse 集成开发环境 ` 和 :ref:`命令行终端 ` 启动 GDB 调试会话。 :ref:`jtag-debugging-examples` - 如果你对 GDB 不太熟悉,本小节会分别针对 :ref:`Eclipse 集成开发环境 ` 和 :ref:`命令行终端 ` 来讲解调试的范例。 + 如果您不熟悉 GDB,请查看此小节以获取 :ref:`Eclipse 集成开发环境 ` 以及 :ref:`命令行终端 ` 提供的调试示例。 :ref:`jtag-debugging-building-openocd` - 介绍如何在 :doc:`Windows `,:doc:`Linux ` 和 :doc:`MacOS ` 操作系统上从源码构建 OpenOCD。 + 介绍如何在 :doc:`Windows `,:doc:`Linux ` 和 :doc:`macOS ` 操作系统上从源码构建 OpenOCD。 :ref:`jtag-debugging-tips-and-quirks` 介绍使用 OpenOCD 和 GDB 通过 JTAG 接口调试 {IDF_TARGET_NAME} 时的注意事项和补充内容。 @@ -36,25 +36,24 @@ JTAG 调试 .. only:: esp32 - ESP32 具有两个强大的 Xtensa 内核,支持多种程序架构。ESP-IDF 自带的 FreeRTOS 操作系统具有多核抢占式多线程的功能,它允许用户以更加直观的方式编写软件。 + ESP32 具有两个强大的 Xtensa 内核,支持多种程序架构。ESP-IDF 自带的 FreeRTOS 操作系统支持多核抢占式调度,允许用户以更加直观的方式编写软件。 + + 与此相对地,由于缺乏合适的工具,简便的编程方式也会给程序的调试带来困难,比如找出由两个线程引起的错误,并且这两个线程在单独的 CPU 核上同时运行,那么仅凭 ``printf`` 语句会花费很长时间来定位该错误。调试此类问题更好(往往也更快)的方法是使用调试器,将其连接到处理器的调试端口。 - 与此相对地,简便的编程方式会给程序的调试带来困难(如果没有合适的工具),比如找出由两个线程引起的错误,并且这两个线程在单独的 CPU 核上同时运行,仅凭 ``printf`` 语句会花费很长的时间来定位到该错误。在大多数情况下,调试此类问题更快的方法是使用调试器,连接到处理器的调试端口。 +乐鑫已完成 OpenOCD 移植,以支持 {IDF_TARGET_NAME} 处理器和多核 FreeRTOS 架构(此作为大多数 {IDF_TARGET_NAME} 应用程序的基础)。此外,乐鑫还提供了一些 OpenOCD 本身并不支持的工具,以进一步丰富调试功能。 -乐鑫已经为 {IDF_TARGET_NAME} 处理器和多核 FreeRTOS 架构移植好了 OpenOCD,它将成为大多数 {IDF_TARGET_NAME} 应用程序的基础。此外,乐鑫还提供了一些 OpenOCD 本身并不支持的工具来进一步丰富调试的功能。 - -本文将指导如何在 Linux,Windows 和 MacOS 环境下为 {IDF_TARGET_NAME} 安装 OpenOCD,并使用 GDB 进行软件调试。除了个别操作系统的安装过程有所差别以外,软件用户界面和使用流程都是一样的。 +本文将介绍如何在 Linux、Windows 和 macOS 环境下为 {IDF_TARGET_NAME} 安装 OpenOCD,并使用 GDB 进行软件调试。除部分安装流程有所不同外,所有操作系统的软件用户界面和使用流程都是相同的。 .. note:: - 本文使用的图片素材来自于 Ubuntu 16.04 LTS 上 Eclipse Neon 3 软件的截图,不同的操作系统(Windows, MacOS 或者 Linux)和 Eclipse 软件版本在用户界面上可能会有细微的差别。 + 本文使用的图片素材来自于 Ubuntu 16.04 LTS 上 Eclipse Neon 3 软件的截图,不同的操作系统(Windows、macOS 或 Linux)或不同的 Eclipse 软件版本在用户界面上可能会有细微差别。 .. _jtag-debugging-how-it-works: 工作原理 -------- -通过 JTAG(Joint Test Action Group)接口使用 OpenOCD 调试 {IDF_TARGET_NAME} 时所需要的一些关键的软件和硬件包括 **{IDF_TARGET_TOOLCHAIN_PREFIX}-gdb -调试器**,**OpenOCD 片上调试器** 和连接到 **{IDF_TARGET_NAME}** 目标的 **JTAG 适配器**。 +通过 JTAG(Joint Test Action Group)接口使用 OpenOCD 调试 {IDF_TARGET_NAME} 时所需要的关键软件和硬件包括 **{IDF_TARGET_TOOLCHAIN_PREFIX}-gdb 调试器**、**OpenOCD 片上调试器** 和连接到 **{IDF_TARGET_NAME}** 目标的 **JTAG 适配器**,如下图 “Application Loading and Monitoring” 标志所示。 .. figure:: ../../../_static/jtag-debugging-overview_zh.jpg :align: center @@ -63,27 +62,46 @@ JTAG 调试 JTAG 调试 - 概述图 -在 “Application Loading and Monitoring” 下还有另外一组软件和硬件,它们用来编译、构建和烧写应用程序到 {IDF_TARGET_NAME} 上,以及监视来自 {IDF_TARGET_NAME} 的运行诊断信息。 +“Application Loading and Monitoring” 标志显示一组关键的软件和硬件组件,可用于编译、构建和烧写应用程序到 {IDF_TARGET_NAME} 上,以及监视来自 {IDF_TARGET_NAME} 的运行诊断信息。 -`Eclipse `__ 环境集成了 JTAG 调试和应用程序加载、监视的功能,它使得软件从编写、编译、加载到调试的迭代过程变得更加快速而简单。所有的软件均适用于 Windows,Linux 和 MacOS 平台。 +`Eclipse `__ 环境集成了 JTAG 调试和应用程序加载、监视的功能,使得软件从编写、编译、加载到调试的迭代过程变得更加快速简单。Eclipse IDE 及其集成的调试软件均适用于 Windows、Linux 和 macOS 平台。 -如果你使用的是 |devkit-name-with-link|,得益于板载的 FT232H 芯片,PC 和 {IDF_TARGET_NAME} 的连接仅仅需要一根 USB 线即可完成。FT232H 提供了两路 USB 通道,一路连接到 JTAG,另一路连接到 UART。 +.. only:: not SOC_USB_SERIAL_JTAG_SUPPORTED + + 若使用 |devkit-name-with-link|,由于其板载 FT232H 芯片,仅需一根 USB 线即可连接 PC 与 {IDF_TARGET_NAME}。FT232H 提供了两路 USB 通道,一路连接到 JTAG,另一路连接到 UART。 -根据用户的喜好,除了使用 Eclipse 集成开发环境,还可以直接在命令行终端运行 `debugger` 和 `idf.py build`。 +.. only:: SOC_USB_SERIAL_JTAG_SUPPORTED + + 仅需一根 USB 线即可高效连接 PC 与 {IDF_TARGET_NAME},因为 {IDF_TARGET_NAME} 芯片本身提供了两路 USB 通道,一路连接到 JTAG,另一路连接到 USB 终端。应将 USB 线连接到 {IDF_TARGET_NAME} 的 D+/D- USB 管脚,而非通过 USB-UART 芯片连接到串行 RxD/TxD。后文中 :ref:`jtag-debugging-configuring-target` 小节将对此进行解释。 + +.. only:: esp32c3 + + .. note:: + + {IDF_TARGET_NAME} 中的 USB 接口只能用于调试版本 3 或更新版本的芯片,对于版本 1 或 2 的芯片,请使用其他调试板(例如 ESP-Prog)。确定芯片版本最简单的方法是通过 `idf.py flash` 完成芯片烧写,并在底部寻找 `芯片为 ESP32-C3 (版本 3)` 信息。 + +根据用户喜好,除了使用 Eclipse 集成开发环境,还可以直接在命令行终端运行 `debugger` 和 `idf.py build`。 .. _jtag-debugging-selecting-jtag-adapter: 选择 JTAG 适配器 ---------------- -上手 JTAG 最快速便捷的方式是使用 |devkit-name-with-link|,因为它板载了 JTAG 调试接口,无需使用外部的 JTAG 硬件适配器和额外的线缆来连接 JTAG 与 {IDF_TARGET_NAME}。|devkit-name| 采用 FT2232H 提供的 JTAG 接口,可以稳定运行在 20 MHz 的时钟频率,外接的适配器很难达到这个速度。 +.. only:: not SOC_USB_SERIAL_JTAG_SUPPORTED -如果你想使用单独的 JTAG 适配器,请确保其与 {IDF_TARGET_NAME} 的电平电压和 OpenOCD 软件都兼容。{IDF_TARGET_NAME} 使用的是业界标准的 JTAG 接口,它省略了(实际上也并不需要)TRST 信号脚。JTAG 使用的 IO 引脚由 VDD_3P3_RTC 电源引脚供电(通常连接到外部 3.3 V 的电源轨),因此 JTAG 硬件适配器的引脚需要能够在该电压范围内正常工作。 + 上手 JTAG 最快速便捷的方式是使用 |devkit-name-with-link|,因为它板载了 JTAG 调试接口,无需使用外部 JTAG 硬件适配器和额外线缆来连接 JTAG 与 {IDF_TARGET_NAME}。|devkit-name| 采用 FT2232H 提供的 JTAG 接口,可以稳定运行在 20 MHz 的时钟频率,外接的适配器很难达到这个速度。 -在软件方面,OpenOCD 支持相当多数量的 JTAG 适配器,可以参阅 `OpenOCD 支持的适配器列表 `_ (尽管上面显示的器件不太完整),这个页面还列出了兼容 SWD 接口的适配器,但是请注意,{IDF_TARGET_NAME} 目前并不支持 SWD。此外那些被硬编码为只支持特定产品线的 JTAG 适配器也不能在 {IDF_TARGET_NAME} 上工作,比如用于 STM32 产品家族的 ST-LINK 适配器。 +.. only:: not SOC_USB_SERIAL_JTAG_SUPPORTED -JTAG 正常工作至少需要连接的信号线有:TDI,TDO,TCK,TMS 和 GND。某些 JTAG 适配器还需要 {IDF_TARGET_NAME} 提供一路电源到适配器的某个引脚上(比如 Vtar)用以设置适配器的工作电压。SRST 信号线是可选的,它可以连接到 {IDF_TARGET_NAME} 的 CH_PD 引脚上,尽管目前 OpenOCD 对该信号线的支持还非常有限。 + 上手 JTAG 最快速便捷的方式是将一根 USB 线连接到 {IDF_TARGET_NAME} 的 D+/D- USB 管脚,无需使用外部 JTAG 适配器和额外线缆。 +如果您想使用单独的 JTAG 适配器,请确保其与 {IDF_TARGET_NAME} 的电平电压和 OpenOCD 软件都兼容。{IDF_TARGET_NAME} 使用的是业界标准的 JTAG 接口,它未使用(实际上也并不需要)TRST 信号脚。JTAG 使用的 IO 管脚由 VDD_3P3_RTC 电源管脚供电(通常连接到外部 3.3 V 的电源轨),因此 JTAG 硬件适配器的管脚需要能够在该电压范围内正常工作。 + +在软件方面,OpenOCD 支持相当多数量的 JTAG 适配器,请参阅 `OpenOCD 支持的适配器列表 `_ (请注意这一列表并不完整),其中还列出了兼容 SWD 接口的适配器,但请注意,{IDF_TARGET_NAME} 目前并不支持 SWD。此外,被硬编码为只支持特定产品线的 JTAG 适配器也无法在 {IDF_TARGET_NAME} 上工作,例如仅针对 STM32 系列产品的 ST-LINK 适配器。 + +JTAG 正常工作至少需要连接的信号线有:TDI、TDO、TCK、TMS 和 GND。一些 JTAG 适配器还需要 {IDF_TARGET_NAME} 提供一路电源到适配器的某个管脚上(比如 Vtar),用于设置适配器的工作电压。您也可以选择将 SRST 信号线连接到 {IDF_TARGET_NAME} 的 CH_PD 管脚上,但请注意,目前 OpenOCD 对该信号线提供的支持相当有限。 + +`ESP-Prog `_ 中展示了使用外部电路板进行调试的实例,方法是将其连接到 {IDF_TARGET_NAME} 的 JTAG 管脚上。 .. _jtag-debugging-setup-openocd: @@ -92,33 +110,33 @@ JTAG 正常工作至少需要连接的信号线有:TDI,TDO,TCK,TMS 和 G .. highlight:: bash -如果你已经按照 :doc:`快速入门 <../../get-started/index>` 一文中的介绍安装好了 ESP-IDF 及其 CMake 构建系统,那么 OpenOCD 已经被默认安装到了你的开发系统中。在 :ref:`设置开发环境 ` 结束后,你应该能够在终端中运行如下 OpenOCD 命令:: +如果您已经按照 :doc:`快速入门 <../../get-started/index>` 完成了 ESP-IDF 及其 CMake 构建系统的安装,那么 OpenOCD 已经被默认安装到了您的开发系统中。在 :ref:`设置开发环境 ` 结束后,您应该能够在终端中运行如下 OpenOCD 命令:: openocd --version .. highlight:: none -终端会输出以下信息(实际版本号可能会比这里列出的更新):: +终端会输出以下信息(实际版本号可能会更新):: Open On-Chip Debugger v0.10.0-esp32-20190708 (2019-07-08-11:04) Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html -你还可以检查 ``OPENOCD_SCRIPTS`` 环境变量的值来确认 OpenOCD 配置文件的路径,Linux 和 macOS 用户可以在终端输入 ``echo $OPENOCD_SCRIPTS``,Windows 用户需要输入 ``echo %OPENOCD_SCRIPTS%``。如果终端打印了有效的路径,则表明 OpenOCD 已经被正确安装。 +您还可以检查 ``OPENOCD_SCRIPTS`` 环境变量的值,以确认 OpenOCD 配置文件的路径,Linux 和 macOS 用户可以在终端输入 ``echo $OPENOCD_SCRIPTS``,Windows 用户需要输入 ``echo %OPENOCD_SCRIPTS%``。如果终端输出了有效路径,则表明您已经正确安装 OpenOCD。 -如果上述步骤没有成功执行,请返回快速入门手册,参考其中 :ref:`设置安装工具 ` 章节的说明。 +如果无法执行上述步骤,请再次阅读快速入门手册,参考 :ref:`设置安装工具 ` 章节。 .. note:: - 另外,我们还可以从源代码编译 OpenOCD 工具,相关详细信息请参阅 :ref:`jtag-debugging-building-openocd` 章节。 + 另外也可以从源代码编译 OpenOCD 工具,详细信息请参阅 :ref:`jtag-debugging-building-openocd` 章节。 .. _jtag-debugging-configuring-target: 配置 {IDF_TARGET_NAME} 目标板 ---------------------------- -安装好 OpenOCD 之后就可以配置 {IDF_TARGET_NAME} 目标(即带 JTAG 接口的 {IDF_TARGET_NAME} 板),具体可以通过以下三个步骤进行: +OpenOCD 安装完成后就可以配置 {IDF_TARGET_NAME} 目标(即带 JTAG 接口的 {IDF_TARGET_NAME} 板),具体分为以下三个步骤: - 配置并连接 JTAG 接口 - 运行 OpenOCD @@ -128,7 +146,7 @@ JTAG 正常工作至少需要连接的信号线有:TDI,TDO,TCK,TMS 和 G 配置并连接 JTAG 接口 ~~~~~~~~~~~~~~~~~~~~ -此步骤取决于您使用的 JTAG 和 {IDF_TARGET_NAME} 板,请参考以下两种情况。 +此步骤取决于使用的 JTAG 和 {IDF_TARGET_NAME} 板,请参考以下两种情况。 .. toctree:: :maxdepth: 1 @@ -148,7 +166,7 @@ JTAG 正常工作至少需要连接的信号线有:TDI,TDO,TCK,TMS 和 G .. highlight:: bash -打开终端,按照快速入门中的指南 :ref:`设置好开发环境 ` ,然后运行如下命令,启动 OpenOCD(该命令在 Windows,Linux,和 macOS 中通用): +打开终端,按照快速入门指南中的 :ref:`设置好开发环境 ` 章节进行操作,然后运行如下命令,以启动 OpenOCD(该命令适用于 Windows、Linux 和 macOS): .. include:: {IDF_TARGET_PATH_NAME}.inc :start-after: run-openocd @@ -156,45 +174,48 @@ JTAG 正常工作至少需要连接的信号线有:TDI,TDO,TCK,TMS 和 G .. note:: - 上述命令中 ``-f`` 选项后跟的配置文件专用于 |run-openocd-device-name|。您可能需要根据具体使用的硬件而选择或修改不同的配置文件,相关指导请参阅 :ref:`jtag-debugging-tip-openocd-configure-target`。 + 上述命令中 ``-f`` 选项后跟的配置文件专用于 |run-openocd-device-name|。基于具体使用的硬件,您可能需要选择不同的配置文件,具体内容请参阅 :ref:`jtag-debugging-tip-openocd-configure-target`。 + + .. only:: esp32c3 + + 例如,对于带有用于 JTAG 连接的 FT2232H 或 FT232H 芯片的定制板,或带有 ESP-Prog 的定制板,可使用 ``board/esp32c3-ftdi.cfg``。 .. highlight:: none -现在应该可以看到如下输入(此日志来自 |run-openocd-device-name|): +现在您应该可以看到如下输出(此日志来自 |run-openocd-device-name|): .. include:: {IDF_TARGET_PATH_NAME}.inc :start-after: run-openocd-output :end-before: --- -- 如果出现指示权限问题的错误,请参阅 ``~/esp/openocd-esp32`` 目录下 OpenOCD README 文件中关于 “Permissions delegation” 的说明。 -- 如果发现配置文件有错误,例如 |run-openocd-cfg-file-err|,请检查 ``-s`` 后面的路径,OpenOCD 会根据此路径来查找 ``-f`` 指定的文件。此外,还需要检查配置文件是否确实位于该路径下。 -- 如果看到 JTAG 错误(输出全是 1 或者全是 0),请检查硬件连接,除了 {IDF_TARGET_NAME} 的引脚之外是否还有其他信号连接到了 JTAG,并查看是否所有器件都已经上电。 - +* 如果出现指示权限问题的错误,请打开 ``~/esp/openocd-esp32`` 目录,参阅 OpenOCD README 文件中关于 “Permissions delegation” 的说明。 +* 如果遇到无法找到配置文件的错误,例如 |run-openocd-cfg-file-err|,请检查 ``OPENOCD_SCRIPTS`` 环境变量是否设置正确,OpenOCD 根据此变量来查找 ``-f`` 指定的文件,详见 :ref:`jtag-debugging-setup-openocd`。此外,还需要检查配置文件是否确实位于该路径下。 +* 如果出现 JTAG 错误(例如输出为 ``...all ones`` 或 ``...all zeroes``),请检查硬件连接是否正确,除了 {IDF_TARGET_NAME} 的管脚之外是否还有其他信号连接到了 JTAG,并查看是否所有器件都已经上电。 .. _jtag-upload-app-debug: 上传待调试的应用程序 ~~~~~~~~~~~~~~~~~~~~ -您可以像往常一样构建并上传 {IDF_TARGET_NAME} 应用程序,具体请参阅 :ref:`get-started-build` 章节。 +按照正常步骤构建并上传 {IDF_TARGET_NAME} 应用程序,具体请参阅 :ref:`get-started-build` 章节。 -除此以外,还支持使用 OpenOCD 通过 JTAG 接口将应用程序镜像烧写到闪存中,命令如下: +除此以外,您还可以使用 OpenOCD 通过 JTAG 接口将应用程序镜像烧写到闪存中,命令如下: .. include:: {IDF_TARGET_PATH_NAME}.inc :start-after: run-openocd-upload :end-before: --- -其中 OpenOCD 的烧写命令 ``program_esp`` 具有以下格式: +其中 OpenOCD 的烧写命令 ``program_esp`` 格式如下: ``program_esp [verify] [reset] [exit]`` - - ``image_file`` - 程序镜像文件存放的路径 - - ``offset`` - 镜像烧写到闪存中的偏移地址 - - ``verify`` - 烧写完成后校验闪存中的内容(可选) - - ``reset`` - 烧写完成后重启目标(可选) - - ``exit`` - 烧写完成后退出 OpenOCD(可选) +- ``image_file`` - 程序镜像文件存放的路径 +- ``offset`` - 镜像烧写到闪存中的偏移地址 +- ``verify`` - 烧写完成后校验闪存中的内容(可选) +- ``reset`` - 烧写完成后重启目标(可选) +- ``exit`` - 烧写完成后退出 OpenOCD(可选) -现在可以进行应用程序的调试了,请按照以下章节中讲解的步骤进行操作。 +现在可以调试应用程序了,请按照以下章节中的步骤进行操作。 .. _jtag-debugging-launching-debugger: @@ -202,14 +223,14 @@ JTAG 正常工作至少需要连接的信号线有:TDI,TDO,TCK,TMS 和 G 启动调试器 ---------- -{IDF_TARGET_NAME} 的工具链中带有 GNU 调试器(简称 GDB) ``{IDF_TARGET_TOOLCHAIN_PREFIX}-gdb``,它和其它工具链软件存放在同一个 bin 目录下。除了直接在命令行终端中调用并操作 GDB 外,还可以在 IDE (例如 Eclipse,Visual Studio Code 等)中调用它,在图形用户界面的帮助下间接操作 GDB,无需在终端中输入任何命令。 +{IDF_TARGET_NAME} 的工具链中带有 GNU 调试器(简称 GDB),它和其它工具链软件共同存放于 {IDF_TARGET_TOOLCHAIN_PREFIX}-gdb 中。除了直接在命令行终端中调用并操作 GDB 外,也可以在 IDE (例如 Eclipse、Visual Studio Code 等)中进行调用,使用图形用户界面间接操作 GDB,这一方法无需在终端中输入任何命令。 关于以上两种调试器的使用方法,详见以下链接。 * :ref:`jtag-debugging-using-debugger-eclipse` * :ref:`jtag-debugging-using-debugger-command-line` -建议首先检查调试器是否能在 :ref:`命令行终端 ` 下正常工作,然后再转到使用 Eclipse 等 :ref:`集成开发环境 ` 下进行调试工作。 +建议首先检查调试器能否在 :ref:`命令行终端 ` 下正常工作,然后再使用 Eclipse :ref:`集成开发环境 ` 进行调试工作。 .. _jtag-debugging-examples: @@ -217,7 +238,7 @@ JTAG 正常工作至少需要连接的信号线有:TDI,TDO,TCK,TMS 和 G 调试范例 -------- -本节适用于不熟悉 GDB 的用户,将使用 :example:`get-started/blink` 下简单的应用程序来演示 :ref:`调试会话的工作流程 `,同时会介绍以下常用的调试操作: +本节适用于不熟悉 GDB 的用户,下文将使用 :example:`get-started/blink` 下简单的应用程序来演示 :ref:`调试会话的工作流程 `,同时会介绍以下常用的调试操作: 1. :ref:`jtag-debugging-examples-eclipse-01` 2. :ref:`jtag-debugging-examples-eclipse-02` @@ -227,9 +248,9 @@ JTAG 正常工作至少需要连接的信号线有:TDI,TDO,TCK,TMS 和 G 6. :ref:`jtag-debugging-examples-eclipse-06` 7. :ref:`jtag-debugging-examples-eclipse-07` -此外还会提供 :ref:`在命令行终端进行调试 ` 的案例。 +此外还会提供在 :ref:`在命令行终端进行调试 ` 下使用 GDB 调试的案例。 -在演示之前,请设置好 {IDF_TARGET_NAME} 目标板并加载 :example:`get-started/blink` 至 {IDF_TARGET_NAME} 中。 +在演示之前,请完成 {IDF_TARGET_NAME} 目标板设置并加载 :example:`get-started/blink` 至 {IDF_TARGET_NAME} 中。 .. _jtag-debugging-building-openocd: @@ -237,18 +258,18 @@ JTAG 正常工作至少需要连接的信号线有:TDI,TDO,TCK,TMS 和 G 从源码构建 OpenOCD ------------------ -请参阅以下文档,它们分别介绍了在各大操作系统平台上从源码构建 OpenOCD 的流程。 +以下文档分别介绍了如何在各操作系统平台上从源码构建 OpenOCD。 .. toctree:: :maxdepth: 1 Windows Linux - MacOS + macOS -本文档演示所使用的 OpenOCD 是 :ref:`jtag-debugging-setup-openocd` 章节中介绍的预编译好的二进制发行版。 +本文档在演示中所使用的 OpenOCD 是预编译好的二进制发行版,在 :ref:`jtag-debugging-setup-openocd` 章节中有所介绍。 -如果要使用本地从源代码编译的 OpenOCD 程序,需要将相应可执行文件的路径修改为 ``src/openocd``,并设置 ``OPENOCD_SCRIPTS`` 环境变量,这样 OpenOCD 才能找到配置文件。Linux 和 macOS 用户可以执行: +如果要使用本地从源代码编译的 OpenOCD 程序,需要将相应可执行文件的路径修改为 ``src/openocd``,并设置 ``OPENOCD_SCRIPTS`` 环境变量,使得 OpenOCD 能够找到配置文件。Linux 和 macOS 用户可以执行: .. code-block:: bash @@ -262,13 +283,13 @@ Windows 用户可以执行: cd %USERPROFILE%\esp\openocd-esp32 set "OPENOCD_SCRIPTS=%CD%\tcl" -运行本地编译的 OpenOCD 的示例如下(Linux 和 macOS 用户): +针对 Linux 和 macOS 用户,运行本地编译的 OpenOCD 的示例: .. include:: {IDF_TARGET_PATH_NAME}.inc :start-after: run-openocd-src-linux :end-before: --- -Windows 用户: +Windows 用户的示例如下: .. include:: {IDF_TARGET_PATH_NAME}.inc :start-after: run-openocd-src-win @@ -279,7 +300,7 @@ Windows 用户: 注意事项和补充内容 -------------------- -本节列出了本指南中提到的所有注意事项和补充内容的链接。 +本节列出了上文中提到的所有注意事项和补充内容的链接。 .. toctree:: :maxdepth: 2 diff --git a/docs/zh_CN/api-guides/openthread.rst b/docs/zh_CN/api-guides/openthread.rst new file mode 100644 index 0000000000..4d1abad6ce --- /dev/null +++ b/docs/zh_CN/api-guides/openthread.rst @@ -0,0 +1 @@ +.. include:: ../../en/api-guides/openthread.rst diff --git a/docs/zh_CN/api-guides/partition-tables.rst b/docs/zh_CN/api-guides/partition-tables.rst index 23a95fd14c..2efde1f858 100644 --- a/docs/zh_CN/api-guides/partition-tables.rst +++ b/docs/zh_CN/api-guides/partition-tables.rst @@ -96,7 +96,7 @@ 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 镜像文件。 - + - OTA 升级永远都不会更新 factory 分区中的内容。 - 如果您希望在 OTA 项目中预留更多 flash,可以删除 factory 分区,转而使用 ota_0 分区。 @@ -169,12 +169,37 @@ Flags 字段 python gen_esp32part.py binary_partitions.bin +分区大小检查 +--------------------- + +ESP-IDF 构建系统将自动检查生成的二进制文件大小与可用的分区大小是否匹配,如果二进制文件太大,则会构建失败并报错。 + +目前会对以下二进制文件进行检查: + +* 引导加载程序的二进制文件的大小要适合分区表前的区域大小(分区表前的区域都分配给了引导加载程序),具体请参考 :ref:`bootloader-size`。 +* 应用程序二进制文件应至少适合一个 “app" 类型的分区。如果不适合任何应用程序分区,则会构建失败。如果只适合某些应用程序分区,则会打印相关警告。 + +.. note:: + + 即使分区大小检查返回错误并导致构建失败,仍然会生成可以烧录的二进制文件(它们对于可用空间来说过大,因此无法正常工作)。 + +.. note:: + + 只有在使用 CMake 构建系统时才会对构建系统二进制文件大小进行检查。如果使用传统的 GNU Make 构建系统时,则可以手动检查文件大小,或在启动时会产生错误记录。 + MD5 校验和 ~~~~~~~~~~ 二进制格式的分区表中含有一个 MD5 校验和。这个 MD5 校验和是根据分区表内容计算的,可在设备启动阶段,用于验证分区表的完整性。 -注意,一些版本较老的启动加载器无法支持 MD5 校验,如果发现 MD5 校验和则将报错 ``invalid magic number 0xebeb``。此时,用户可通过 ``gen_esp32part.py`` 的 ``--disable-md5sum`` 选项或者 :ref:`CONFIG_PARTITION_TABLE_MD5` 选项关闭 MD5 校验。 +.. only:: esp32 + + 用户可通过 ``gen_esp32part.py`` 的 ``--disable-md5sum`` 选项或者 :ref:`CONFIG_PARTITION_TABLE_MD5` 选项关闭 MD5 校验。对于 :ref:`ESP-IDF v3.1 版本前的引导加载程序 `,因为它不支持 MD5 校验,所以无法正常启动并报错 ``invalid magic number 0xebeb``,此时用户可以使用此选项关闭 MD5 校验。 + +.. only:: not esp32 + + 用户可通过 ``gen_esp32part.py`` 的 ``--disable-md5sum`` 选项或者 :ref:`CONFIG_PARTITION_TABLE_MD5` 选项关闭 MD5 校验。 + 烧写分区表 ---------- diff --git a/docs/zh_CN/api-guides/tools/idf-component-manager.rst b/docs/zh_CN/api-guides/tools/idf-component-manager.rst new file mode 100644 index 0000000000..8017f17fbc --- /dev/null +++ b/docs/zh_CN/api-guides/tools/idf-component-manager.rst @@ -0,0 +1 @@ +.. include:: ../../../en/api-guides/tools/idf-component-manager.rst diff --git a/docs/zh_CN/api-guides/tools/index.rst b/docs/zh_CN/api-guides/tools/index.rst index ef6903c591..41438ae874 100644 --- a/docs/zh_CN/api-guides/tools/index.rst +++ b/docs/zh_CN/api-guides/tools/index.rst @@ -8,3 +8,4 @@ IDF 监视器 IDF Docker image IDF Windows Installer + IDF Component Manager diff --git a/docs/zh_CN/api-guides/unit-tests.rst b/docs/zh_CN/api-guides/unit-tests.rst index 1d49ab3d8a..459bb3c16e 100644 --- a/docs/zh_CN/api-guides/unit-tests.rst +++ b/docs/zh_CN/api-guides/unit-tests.rst @@ -2,7 +2,10 @@ ============================ :link_to_translation:`en:[English]` -ESP-IDF 中附带了一个基于 ``Unity`` 的单元测试应用程序框架,且所有的单元测试用例分别保存在 ESP-IDF 仓库中每个组件的 ``test`` 子目录中。 +ESP-IDF 提供以下方法测试软件。 + +- 一种是在目标芯片上运行并基于 ``Unity`` 测试框架的应用程序。这些单元测试用例都保存在 ESP-IDF 仓库中,分别存放在每个组件的 ``test`` 子目录中。本文主要介绍这种单元测试方法。 +- 另一种是基于 Linux 主机的单元测试,其中所有硬件行为都通过 Mock 组件进行模拟。此测试方法目前仍在开发中,只有一小部分 IDF 组件支持了 Mock,具体请参考 :doc:`基于 Linux 主机的单元测试 `。 添加常规测试用例 ---------------- @@ -24,9 +27,9 @@ ESP-IDF 中附带了一个基于 ``Unity`` 的单元测试应用程序框架, - 第二个参数用方括号中的标识符来表示,标识符用来对相关测试或具有特定属性的测试进行分组。 .. note:: - 没有必要在每个测试用例中使用 ``UNITY_BEGIN()`` 和 ``UNITY_END()`` 来声明主函数的区域, ``unity_platform.c`` 会自动调用 ``UNITY_BEGIN()``, 然后运行测试用例,最后调用 ``UNITY_END()``。 + 没有必要在每个测试用例中使用 ``UNITY_BEGIN()`` 和 ``UNITY_END()`` 来声明主函数的区域, ``unity_platform.c`` 会自动调用 ``UNITY_BEGIN()``,然后运行测试用例,最后调用 ``UNITY_END()``。 -``test`` 子目录应包含 :ref:`组件 CMakeLists.txt `,因为他们本身就是一种组件。ESP-IDF 使用了 ``unity`` 测试框架,需要将其指定为组件的依赖项。通常,组件 :ref:`需要手动指定待编译的源文件 ;但是,对于测试组件来说,这个要求被放宽为仅建议将参数 ``SRC_DIRS`` 用于 ``idf_component_register``。 +``test`` 子目录应包含 :ref:`组件 CMakeLists.txt `,因为他们本身就是一种组件(即测试组件)。ESP-IDF 使用了 Unity 测试框架, 位于 ``unity`` 组件里。因此,每个测试组件都需要通过 ``REQUIRES`` 参数将 ``unity`` 组件设为依赖项。通常,组件需要 :ref:`手动指定待编译的源文件 `,但是,对于测试组件来说,这个要求被放宽为仅建议将参数 ``SRC_DIRS`` 用于 ``idf_component_register``。 总的来说,``test`` 子目录下最小的 CMakeLists.txt 文件可能如下所示: @@ -72,7 +75,7 @@ ESP-IDF 中附带了一个基于 ``Unity`` 的单元测试应用程序框架, TEST_CASE_MULTIPLE_DEVICES("gpio multiple devices test example", "[driver]", gpio_master_test, gpio_slave_test); -宏 ``TEST_CASE_MULTIPLE_DEVICES`` 用来声明多设备测试用例, +宏 ``TEST_CASE_MULTIPLE_DEVICES`` 用来声明多设备测试用例。 - 第一个参数指定测试用例的名字。 - 第二个参数是测试用例的描述。 @@ -143,13 +146,13 @@ DUT2(slave)终端:: - 请勿将测试代码放在 ``test/芯片版本`` 目录下面,然后用 CMakeLists.txt 来选择其中一个进行编译。这是因为测试代码比实现代码更容易被复用。如果你将一些代码放在 ``test/esp32`` 目录下来避免 esp32s2 芯片执行它,一旦你需要在新的芯片(比如 esp32s3 )中启用该测试,你会发现这种结构非常难以保持代码的整洁。 -- 请勿继续使用 ``CONFIG_IDF_TARGET_xxx`` 宏来禁止某些测试在一些芯片上编译。这种 方法会让被禁止的测试项目难以追踪和重新打开。并且,相比于白名单式的 ``#if CONFIG_IDF_TARGET_xxx`` ,黑名单式的 ``#if !disabled`` 能避免新芯片引入时,这些测试被自动关闭。但对于用于测试的一些实现, ``#if CONFIG_IDF_TARGET_xxx`` 仍可用于给不同芯片版本选择实现代码。测试项目和测试实现区分如下: +- 请勿继续使用 ``CONFIG_IDF_TARGET_xxx`` 宏来禁止某些测试在一些芯片上编译。这种方法会让被禁止的测试项目难以追踪和重新打开。并且,相比于白名单式的 ``#if CONFIG_IDF_TARGET_xxx``,黑名单式的 ``#if !disabled`` 能避免新芯片引入时这些测试被自动关闭。但对于用于测试的一些实现,``#if CONFIG_IDF_TARGET_xxx`` 仍可用于给不同芯片版本选择实现代码。测试项目和测试实现区分如下: - - 测试项目:某些你会在一些芯片上执行,而在另外一些上跳过的项目,例如: + - 测试项目:那些会在一些芯片上执行,而在另外一些上跳过的项目,例如: - 有三个测试项目 SD 1-bit 、 SD 4-bit 和 SDSPI 。对于不支持 SD Host 外设的ESP32-S2 芯片,只有 SDSPI 一个项目需要被执行。 + 有三个测试项目 SD 1-bit、SD 4-bit 和 SDSPI。对于不支持 SD Host 外设的 ESP32-S2 芯片,只有 SDSPI 一个项目需要被执行。 - - 测试实现:某些代码始终会发生,但采取不同的做法。例如: + - 测试实现:一些始终会发生的代码,但采取不同的实现方式。例如: ESP8266 芯片没有 SDIO_PKT_LEN 寄存器。如果在测试过程中需要获取从设备的数据长度,你可以用不同方式读取的 ``#if CONFIG_IDF_TARGET_`` 宏来保护不同的实现代码。 @@ -243,6 +246,8 @@ DUT2(slave)终端:: 第一次执行此用例时,输入 ``1`` 来运行第一阶段(触发深度睡眠)。在重启 DUT 并再次选择运行此用例后,输入 ``2`` 来运行第二阶段。只有在最后一个阶段通过并且之前所有的阶段都成功触发了复位的情况下,该测试才算通过。 +.. _cache-compensated-timer: + 带缓存补偿定时器的定时代码 ----------------------------------------- @@ -274,13 +279,24 @@ DUT2(slave)终端:: Mocks ---------- -ESP-IDF 有一个集成 CMock mocking 框架的组件。CMock 通常使用 Unity 作为一个子模块,但由于一些 Espressif 内部 CI 的限制,我们仍然将 Unity 作为 ESP-IDF 中的一个普通模块。 +嵌入式系统中单元测试的最大问题之一是硬件依赖性极强。所以 ESP-IDF 有一个集成了 `CMock `_ mocking 框架的组件。理想情况下,除了需要被测试的组件 *(待测组件)* 之外的所有组件都要被模拟。这样,测试环境就可以完全控制与被测组件之间的所有交互。但是,在模拟过程中如果遇到过于具体而导致的困难,用户可以在测试代码中包含“真正”(非模拟)代码。 -要使用 IDF 提供的 Unity 组件(不是子模块),构建系统需要传递一个环境变量 ``UNITY_IDR`` 给 CMock。该变量仅包含 IDF 中 Unity 目录的路径,如 ``export "UNITY_DIR=${IDF_PATH}/components/unity/unity"``。 +除了常规的 IDF 要求,``ruby`` 是生成 Mock 的必要条件,具体请参考 :component_file:`cmock/CMock/docs/CMock_Summary.md` 了解 CMock 工作原理以及如何创建和使用 Mock。 -关于 CMock 中 Unity 目录是如何确定的,请参考 :component_file:`cmock/CMock/lib/cmock_generator.rb`。 +在 IDF 中,与编写普通组件或不需要 Mock 的单元测试相比,需要 Mock 的组件以及单元测试内部需要进行一些修改。 -在组件的 CMakeLists.txt 中创建组件的 mock 的 cmake 编译命令可能如下所示: +修改需要模拟的组件 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +要被模拟的组件需要一个单独的 ``mock`` 目录,用来包含实现模拟的文件。最重要的是,该目录下要包含用于配置 CMock 的 ``mock_config.yaml`` 文件。关于此配置文件中选项的含义以及如何编写自己的配置文件,请参考 :component_file:`CMock 文档 `。 ``mock`` 目录中可能还需要包括其它与 Mock 有关的文件。 + +此外,组件的 ``CMakeLists.txt`` 文件中需要一个“开关”来决定是否编译 Mock。通常可以通过检查特定组件的属性 ``USE_MOCK`` 来实现。例如,``spi_flash`` 组件在其 ``CMakeLists.txt`` 中执行以下代码,以检查是否应该编译 Mock。 + +.. code-block:: cmake + + idf_component_get_property(spi_flash_mock ${COMPONENT_NAME} USE_MOCK) + +在组件的 CMakeLists.txt 中创建组件的 Mock 的 CMake 编译命令可能如下所示: .. code-block:: cmake @@ -290,6 +306,19 @@ ESP-IDF 有一个集成 CMock mocking 框架的组件。CMock 通常使用 Unity COMMAND ${CMAKE_COMMAND} -E env "UNITY_DIR=${IDF_PATH}/components/unity/unity" ruby ${CMOCK_DIR}/lib/cmock.rb -o${CMAKE_CURRENT_SOURCE_DIR}/mock/mock_config.yaml ${MOCK_HEADERS} ) -${MOCK_OUTPUT} 包含所有 CMock 生成的输出文件,${MOCK_HEADERS} 包含所有要 mock 的头文件, ${CMOCK_DIR} 需要设置为 IDF 内的 CMock 目录。${CMAKE_COMMAND} 会自动设置。 +``${MOCK_OUTPUT}`` 包含所有 CMock 生成的输出文件,``${MOCK_HEADERS}`` 包含所有要 Mock 的头文件,``${CMOCK_DIR}`` 需要设置为 IDF 内的 CMock 目录。``${CMAKE_COMMAND}`` 会由 IDF 构建系统自动设置。 -更多关于 CMock 如何工作以及如何创建和使用 mock 的信息,请参考 :component_file:`cmock/CMock/docs/CMock_Summary.md`。 \ No newline at end of file +使用 CMock 要特别注意的一个方面是:CMock 通常使用 Unity 作为一个子模块,但由于一些 Espressif 内部 CI 的限制,我们仍然将 Unity 作为 ESP-IDF 中的一个普通模块。要使用 IDF 提供的 Unity 组件(不是子模块),构建系统需要传递一个环境变量 ``UNITY_IDR`` 给 CMock。该变量仅包含 IDF 中 Unity 目录的路径,如 ``export "UNITY_DIR=${IDF_PATH}/components/unity/unity"``。关于 CMock 中 Unity 目录是如何确定的,请参考 :component_file:`cmock/CMock/lib/cmock_generator.rb`。 + +更多细节可参考 :component_file:`spi_flash ` 目录下启用 Mock 的 ``CMakeLists.txt`` 示例文件。 + +修改单元测试文件 +^^^^^^^^^^^^^^^^^^^^^^^^ + +单元测试要为需要模拟的组件设置 ``USE_MOCK`` 组件属性。这会让依赖组件编译 Mock,而不是实际的组件。例如,在 NVS 主机测试的 :component_file:`CMakeLists.txt ` 中,以下代码用于启用 ``spi_flash`` Mock。 + +.. code-block:: cmake + + idf_component_set_property(spi_flash USE_MOCK 1) + +关于如何在单元测试中使用及控制 CMock,请参考 :component_file:`NVS 主机单元测 `。 \ No newline at end of file diff --git a/docs/zh_CN/api-guides/wifi-security.rst b/docs/zh_CN/api-guides/wifi-security.rst new file mode 100644 index 0000000000..ae682a8363 --- /dev/null +++ b/docs/zh_CN/api-guides/wifi-security.rst @@ -0,0 +1 @@ +.. include:: ../../en/api-guides/wifi-security.rst diff --git a/docs/zh_CN/api-reference/network/esp_dpp.rst b/docs/zh_CN/api-reference/network/esp_dpp.rst new file mode 100644 index 0000000000..66b50a4e34 --- /dev/null +++ b/docs/zh_CN/api-reference/network/esp_dpp.rst @@ -0,0 +1 @@ +.. include:: ../../../en/api-reference/network/esp_dpp.rst diff --git a/docs/zh_CN/api-reference/network/esp_openthread.rst b/docs/zh_CN/api-reference/network/esp_openthread.rst new file mode 100644 index 0000000000..299652af27 --- /dev/null +++ b/docs/zh_CN/api-reference/network/esp_openthread.rst @@ -0,0 +1 @@ +.. include:: ../../../en/api-reference/network/esp_openthread.rst diff --git a/docs/zh_CN/api-reference/network/index.rst b/docs/zh_CN/api-reference/network/index.rst index 4964066e52..92f1f8c72f 100644 --- a/docs/zh_CN/api-reference/network/index.rst +++ b/docs/zh_CN/api-reference/network/index.rst @@ -13,6 +13,7 @@ Wi-Fi Smart Config ESP-NOW ESP-WIFI-MESH + EasyConnect 本部分的 Wi-Fi API 示例代码存放在 ESP-IDF 示例项目的 :example:`wifi` 目录下。 @@ -29,6 +30,16 @@ ESP-WIFI-MESH 的示例代码存放在 ESP-IDF 示例项目的 :example:`mesh` 本部分的以太网 API 示例代码存放在 ESP-IDF 示例项目的 :example:`ethernet` 目录下。 +Thread +======== + +.. toctree:: + :maxdepth: 1 + + Thread + +本部分的Thread API 示例代码存放在 ESP-IDF 示例项目的 :example:`openthread` 目录下。 + IP 网络层协议 ================ diff --git a/docs/zh_CN/api-reference/peripherals/i2c.rst b/docs/zh_CN/api-reference/peripherals/i2c.rst index 8ab0e18f13..a88d8604b9 100644 --- a/docs/zh_CN/api-reference/peripherals/i2c.rst +++ b/docs/zh_CN/api-reference/peripherals/i2c.rst @@ -21,7 +21,7 @@ I2C 具有简单且制造成本低廉等优点,主要用于低速外围设备 驱动程序的功能 --------------- -I2C 驱动程序管理在 I2C 总线上设备的通信,该驱动程序具备以下功能: +I2C 驱动程序管理在 I2C 总线上设备的通信,该驱动程序具备以下功能: - 在主机模式下读写字节 - 支持从机模式 @@ -37,7 +37,7 @@ I2C 驱动程序管理在 I2C 总线上设备的通信,该驱动程序具备 2. :ref:`i2c-api-install-driver`- 激活一个 I2C 控制器的驱动,该控制器可为主机也可为从机 3. 根据是为主机还是从机配置驱动程序,选择合适的项目 - a) :ref:`i2c-api-master-mode` - 发起通信(主机模式) + a) :ref:`i2c-api-master-mode` - 发起通信(主机模式) b) :ref:`i2c-api-slave-mode` - 响应主机消息(从机模式) 4. :ref:`i2c-api-interrupt-handling` - 配置 I2C 中断服务 @@ -148,6 +148,25 @@ I2C 驱动程序管理在 I2C 总线上设备的通信,该驱动程序具备 1. :c:macro:`I2C_SCLK_SRC_FLAG_AWARE_DFS`:当 APB 时钟改变时,时钟的波特率不会改变。 2. :c:macro:`I2C_SCLK_SRC_FLAG_LIGHT_SLEEP`:支持轻度睡眠模式,APB 时钟则不支持。 +.. only:: esp32s3 + + .. list-table:: {IDF_TARGET_NAME} 时钟源特性 + :widths: 5 5 50 20 + :header-rows: 1 + + * - 时钟名称 + - 时钟频率 + - SCL 的最大频率 + - 时钟功能 + * - XTAL 时钟 + - 40 MHz + - 2 MHz + - / + * - RTC 时钟 + - 20 MHz + - 1 MHz + - :c:macro:`I2C_SCLK_SRC_FLAG_AWARE_DFS`, :c:macro:`I2C_SCLK_SRC_FLAG_LIGHT_SLEEP` + .. only:: esp32c3 .. list-table:: {IDF_TARGET_NAME} 时钟源特性 @@ -185,9 +204,9 @@ I2C 驱动程序管理在 I2C 总线上设备的通信,该驱动程序具备 配置好 I2C 驱动程序后,使用以下参数调用函数 :cpp:func:`i2c_driver_install` 安装驱动程序: - 端口号,从 :cpp:type:`i2c_port_t` 中二选一 -- 主机或从机模式,从 :cpp:type:`i2c_mode_t` 中选择 -- (仅限从机模式)分配用于在从机模式下发送和接收数据的缓存区大小。I2C 是一个以主机为中心的总线,数据只能根据主机的请求从从机传输到主机。因此,从机通常有一个发送缓存区,供从应用程序写入数据使用。数据保留在发送缓存区中,由主机自行读取。 -- 用于分配中断的标志(请参考 ESP_INTR_FLAG_* values in :component_file:`esp_hw_support/include/esp_intr_alloc.h`) +- 主机或从机模式,从 :cpp:type:`i2c_mode_t` 中选择 +- (仅限从机模式)分配用于在从机模式下发送和接收数据的缓存区大小。I2C 是一个以主机为中心的总线,数据只能根据主机的请求从从机传输到主机。因此,从机通常有一个发送缓存区,供从应用程序写入数据使用。数据保留在发送缓存区中,由主机自行读取。 +- 用于分配中断的标志(请参考 :component_file:`esp_hw_support/include/esp_intr_alloc.h` 中 ESP_INTR_FLAG_* 值) .. _i2c-api-master-mode: @@ -225,7 +244,7 @@ I2C 驱动程序管理在 I2C 总线上设备的通信,该驱动程序具备 函数 :cpp:func:`i2c_master_write_byte` 和 :cpp:func:`i2c_master_write` 都有额外的实参,规定主机是否应确认其有无接受到 ACK 位。 -2. 通过调用 :cpp:func:`i2c_master_cmd_begin` 来触发 I2C 控制器执行命令链接。一旦开始执行,就不能再修改命令链接。 +2. 通过调用 :cpp:func:`i2c_master_cmd_begin` 来触发 I2C 控制器执行命令链接。一旦开始执行,就不能再修改命令链接。 3. 命令发送后,通过调用 :cpp:func:`i2c_cmd_link_delete` 释放命令链接使用的资源。 @@ -278,7 +297,7 @@ API 为从机提供以下功能: - :cpp:func:`i2c_slave_write_buffer` - 发送缓存区是用于存储从机要以 FIFO 顺序发送给主机的所有数据。在主机请求接收前,这些数据一直存储在发送缓存区。函数 :cpp:func:`i2c_slave_write_buffer` 有一个参数,用于指定发送缓存区已满时的块时间。这将允许从机应用程序在指定的超时设定内等待发送缓存区中足够的可用空间。 + 发送缓存区是用于存储从机要以 FIFO 顺序发送给主机的所有数据。在主机请求接收前,这些数据一直存储在发送缓存区。函数 :cpp:func:`i2c_slave_write_buffer` 有一个参数,用于指定发送缓存区已满时的块时间。这将允许从机应用程序在指定的超时设定内等待发送缓存区中足够的可用空间。 在 :example:`peripherals/i2c` 中可找到介绍如何使用这些功能的代码示例。 @@ -321,15 +340,15 @@ API 为从机提供以下功能: - :cpp:func:`i2c_set_data_mode` -上述每个函数都有一个 *_get_* 对应项来检查当前设置的值。例如,调用 :cpp:func:`i2c_get_timeout` 来检查 I2C 超时值。 +上述每个函数都有一个 *_get_* 对应项来检查当前设置的值。例如,调用 :cpp:func:`i2c_get_timeout` 来检查 I2C 超时值。 -要检查在驱动程序配置过程中设置的参数默认值,请参考文件 :component_file:`driver/i2c.c` 并查找带有后缀 ``_DEFAULT`` 的定义。 +要检查在驱动程序配置过程中设置的参数默认值,请参考文件 :component_file:`driver/i2c.c` 并查找带有后缀 ``_DEFAULT`` 的定义。 通过函数 :cpp:func:`i2c_set_pin` 可以为 SDA 和 SCL 信号选择不同的管脚并改变上拉配置。如果要修改已经输入的值,请使用函数 :cpp:func:`i2c_param_config`。 .. 注解 :: - {IDF_TARGET_NAME} 的内部上拉电阻范围为几万欧姆,因此在大多数情况下,它们本身不足以用作 I2C 上拉电阻。建议用户使用阻值在 `I2C 总线协议规范 `_ 规定范围内的上拉电阻。 + {IDF_TARGET_NAME} 的内部上拉电阻范围为几万欧姆,因此在大多数情况下,它们本身不足以用作 I2C 上拉电阻。建议用户使用阻值在 `I2C 总线协议规范 `_ 规定范围内的上拉电阻。 .. _i2c-api-error-handling: @@ -349,13 +368,14 @@ API 为从机提供以下功能: 删除驱动程序 ^^^^^^^^^^^^^ -当使用 :cpp:func:`i2c_driver_install` 建立 I2C 通信,一段时间后不再需要 I2C 通信时,可以通过调用 :cpp:func:`i2c_driver_delete` 来移除驱动程序以释放分配的资源。 +当使用 :cpp:func:`i2c_driver_install` 建立 I2C 通信,一段时间后不再需要 I2C 通信时,可以通过调用 :cpp:func:`i2c_driver_delete` 来移除驱动程序以释放分配的资源。 +由于函数 :cpp:func:`i2c_driver_delete` 无法保证线程安全性,请在调用该函数移除驱动程序前务必确保所有的线程都已停止使用驱动程序。 应用示例 ---------- -I2C 主机和从机示例::example:`peripherals/i2c` +I2C 主机和从机示例::example:`peripherals/i2c`。 API 参考 diff --git a/docs/zh_CN/api-reference/peripherals/index.rst b/docs/zh_CN/api-reference/peripherals/index.rst index 373b041ed5..3089a2a45e 100644 --- a/docs/zh_CN/api-reference/peripherals/index.rst +++ b/docs/zh_CN/api-reference/peripherals/index.rst @@ -6,33 +6,34 @@ .. toctree:: :maxdepth: 1 - ADC - :SOC_DAC_SUPPORTED: DAC - 通用定时器 - GPIO (including RTC low power I/O) - :SOC_DEDICATED_GPIO_SUPPORTED: Dedicated GPIO - :SOC_HMAC_SUPPORTED: HMAC - :SOC_DIG_SIGN_SUPPORTED: Digital Signature - I2C - I2S - LED 控制器 - :SOC_MCPWM_SUPPORTED: MCPWM - :SOC_PCNT_SUPPORTED: Pulse Counter - Remote Control - :esp32 or esp32s3: SD Pull-up Requirements - :SOC_SDMMC_HOST_SUPPORTED: SDMMC Host - SD SPI Host - :SOC_SDIO_SLAVE_SUPPORTED: SDIO Slave - Sigma-delta Modulation - SPI Master - SPI Slave - :esp32: Secure Element - :esp32s2: SPI Slave Half Duplex - :SOC_TEMP_SENSOR_SUPPORTED: Temp sensor - :SOC_TOUCH_SENSOR_NUM: 触摸传感器 - :esp32s2: Touch Element - TWAI - UART - :SOC_USB_OTG_SUPPORTED: USB Device + adc + :SOC_DAC_SUPPORTED: dac + timer + gpio + :SOC_DEDICATED_GPIO_SUPPORTED: dedic_gpio + :SOC_HMAC_SUPPORTED: hmac + :SOC_DIG_SIGN_SUPPORTED: ds + i2c + i2s + ledc + :SOC_MCPWM_SUPPORTED: mcpwm + :SOC_PCNT_SUPPORTED: pcnt + rmt + :esp32 or esp32s3: sd_pullup_requirements + :SOC_SDMMC_HOST_SUPPORTED: sdmmc_host + sdspi_host + :SOC_SDIO_SLAVE_SUPPORTED: sdio_slave + sigmadelta + spi_master + spi_slave + :esp32: secure_element + :esp32s2: spi_slave_hd + :SOC_TEMP_SENSOR_SUPPORTED: temp_sensor + :SOC_TOUCH_SENSOR_NUM: touch_pad + :esp32s2: touch_element + twai + uart + :SOC_USB_OTG_SUPPORTED: usb_device + :SOC_USB_OTG_SUPPORTED: usb_host 本部分的 API 示例代码存放在 ESP-IDF 示例项目的 :example:`peripherals` 目录下。 \ No newline at end of file diff --git a/docs/zh_CN/api-reference/peripherals/ledc.rst b/docs/zh_CN/api-reference/peripherals/ledc.rst index fcf197218a..2b5090f32e 100644 --- a/docs/zh_CN/api-reference/peripherals/ledc.rst +++ b/docs/zh_CN/api-reference/peripherals/ledc.rst @@ -196,10 +196,8 @@ LED PWM 控制器 API 会在设定的频率和占空比分辨率超过 LED PWM 使用 LEDC 基本实例请参照 :example:`peripherals/ledc/ledc_basic`。 - API 参考 ------------- .. include-build-file:: inc/ledc.inc .. include-build-file:: inc/ledc_types.inc - diff --git a/docs/zh_CN/api-reference/peripherals/timer.rst b/docs/zh_CN/api-reference/peripherals/timer.rst index 81c69646a4..89eea0d816 100644 --- a/docs/zh_CN/api-reference/peripherals/timer.rst +++ b/docs/zh_CN/api-reference/peripherals/timer.rst @@ -42,8 +42,8 @@ .. list:: - :not esp32: - **时钟源**: 选择时钟源,它同时钟分频器一起决定了定时器的分辨率。默认的时钟源是 APB_CLK (一般是 80 MHz)。 - - **分频器**: 设置定时器中计数器计数的速度,:cpp:member:`divider` 的设置将用作输入时钟源的除数。 + :not esp32: - **时钟源**: 选择时钟源,与时钟分频器一起决定了定时器的分辨率。 + - **分频器**: 设置定时器中计数器计数的速度,:cpp:member:`divider` 的设置将用作输入时钟源的除数。默认的时钟源是 APB_CLK (一般是 80 MHz)。更多有关 APB_CLK 时钟频率信息,请查看 *{IDF_TARGET_NAME} 技术参考手册* > *复位和时钟* [`PDF <{IDF_TARGET_TRM_CN_URL}#resclk>`__] 章节。 - **模式**: 设置计数器是递增还是递减。可通过从 :cpp:type:`timer_count_dir_t` 中选取一个值,后使用 :cpp:member:`counter_dir` 来选择模式。 - **计数器使能**: 如果计数器已使能,则在调用 :cpp:func:`timer_init` 后计数器将立即开始递增/递减。您可通过从 :cpp:type:`timer_start_t` 中选取一个值,后使用 :cpp:member:`counter_en` 改变此行为。 - **报警使能**: 可使用 :cpp:member:`alarm_en` 设置。 diff --git a/docs/zh_CN/api-reference/peripherals/usb_host.rst b/docs/zh_CN/api-reference/peripherals/usb_host.rst new file mode 100644 index 0000000000..64ba8042f5 --- /dev/null +++ b/docs/zh_CN/api-reference/peripherals/usb_host.rst @@ -0,0 +1 @@ +.. include:: ../../../en/api-reference/peripherals/usb_host.rst \ No newline at end of file diff --git a/docs/zh_CN/api-reference/storage/spi_flash_concurrency.rst b/docs/zh_CN/api-reference/storage/spi_flash_concurrency.rst index a5000ba3ac..4df013c0b5 100644 --- a/docs/zh_CN/api-reference/storage/spi_flash_concurrency.rst +++ b/docs/zh_CN/api-reference/storage/spi_flash_concurrency.rst @@ -24,7 +24,7 @@ SPI1 Flash 并发约束 请参阅 :ref:`应用程序内存分布 `,查看 IRAM、DRAM 和 flash cache 的区别。 -.. only: not CONFIG_FREERTOS_UNICORE +.. only:: not CONFIG_FREERTOS_UNICORE 为避免意外读取 flash cache,一个 CPU 在启动 flash 写入或擦除操作时,另一个 CPU 将阻塞,并且在 flash 操作完成前,所有 CPU 上,所有的非 IRAM 安全的中断都会被禁用。 diff --git a/docs/zh_CN/api-reference/storage/vfs.rst b/docs/zh_CN/api-reference/storage/vfs.rst index 0a7e78a679..ab3bc4c2f8 100644 --- a/docs/zh_CN/api-reference/storage/vfs.rst +++ b/docs/zh_CN/api-reference/storage/vfs.rst @@ -1,4 +1,171 @@ -.. include:: ../../../../components/vfs/README_CN.rst +虚拟文件系统组件 +============================ + +:link_to_translation:`en:[English]` + +概述 +-------- + +虚拟文件系统 (VFS) 组件可为一些驱动提供一个统一接口。有了该接口,用户可像操作普通文件一样操作虚拟文件。这类驱动程序可以是 FAT、SPIFFS 等真实文件系统,也可以是有文件类接口的设备驱动程序。 + +VFS 组件支持 C 库函数(如 fopen 和 fprintf 等)与文件系统 (FS) 驱动程序协同工作。在高层级,每个 FS 驱动程序均与某些路径前缀相关联。当一个 C 库函数需要打开文件时,VFS 组件将搜索与该文件所在文件路径相关联的 FS 驱动程序,并将调用传递给该驱动程序。针对该文件的读取、写入等其他操作的调用也将传递给这个驱动程序。 + +例如,您可以使用 ``/fat`` 前缀注册 FAT 文件系统驱动,之后即可调用 ``fopen("/fat/file.txt", "w")``。之后,VFS 将调用 FAT 驱动的 ``open`` 函数,并将参数 ``/file.txt`` 和合适的打开模式传递给 ``open`` 函数;后续对返回的 ``FILE*`` 数据流调用 C 库函数也同样会传递给 FAT 驱动。 + +注册 FS 驱动程序 +--------------------- + +如需注册 FS 驱动程序,首先要定义一个 :cpp:type:`esp_vfs_t` 结构体实例,并用指向 FS API 的函数指针填充它。 + +.. highlight:: c + +:: + + esp_vfs_t myfs = { + .flags = ESP_VFS_FLAG_DEFAULT, + .write = &myfs_write, + .open = &myfs_open, + .fstat = &myfs_fstat, + .close = &myfs_close, + .read = &myfs_read, + }; + + ESP_ERROR_CHECK(esp_vfs_register("/data", &myfs, NULL)); + +在上述代码中需要用到 ``read``、 ``write`` 或 ``read_p``、 ``write_p``,具体使用哪组函数由 FS 驱动程序 API 的声明方式决定。 + +示例 1:声明 API 函数时不带额外的上下文指针参数,即 FS 驱动程序为单例模式,此时使用 ``write`` :: + + ssize_t myfs_write(int fd, const void * data, size_t size); + + // In definition of esp_vfs_t: + .flags = ESP_VFS_FLAG_DEFAULT, + .write = &myfs_write, + // ... other members initialized + + // When registering FS, context pointer (third argument) is 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: + .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_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)); + +同步输入/输出多路复用 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +如需通过 :cpp:func:`select` 使用同步输入/输出多路复用,首先需要把 :cpp:func:`start_select` 和 :cpp:func:`end_select` 注册到 VFS,如下所示: + +.. highlight:: c + +:: + + // In definition of 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` 设置的资源。请在 :component_file:`vfs/vfs_uart.c` 中查看 UART 外设参考实现、:cpp:func:`esp_vfs_dev_uart_register`、:cpp:func:`uart_start_select` 和 :cpp:func:`uart_end_select` 函数。 + +请参考以下示例,查看如何使用 VFS 文件描述符调用 :cpp:func:`select`: + +- :example:`peripherals/uart/uart_select` +- :example:`system/select` + +如果 :cpp:func:`select` 用于套接字文件描述符,您可以启用 :envvar:`CONFIG_LWIP_USE_ONLY_LWIP_SELECT` 选项来减少代码量,提高性能。 + +路径 +----- + +已注册的 FS 驱动程序均有一个路径前缀与之关联,此路径前缀即为分区的挂载点。 + +如果挂载点中嵌套了其他挂载点,则在打开文件时使用具有最长匹配路径前缀的挂载点。例如,假设以下文件系统已在 VFS 中注册: + +- 在 /data 下注册 FS 驱动程序 1 +- 在 /data/static 下注册 FS 驱动程序 2 + +那么: + +- 打开 ``/data/log.txt`` 会调用驱动程序 FS 1; +- 打开 ``/data/static/index.html`` 需调用 FS 驱动程序 2; +- 即便 FS 驱动程序 2 中没有 ``/index.html``,也不会在 FS 驱动程序 1 中查找 ``/static/index.html``。 + +挂载点名称必须以路径分隔符 (``/``) 开头,且分隔符后至少包含一个字符。但在以下情况中,VFS 同样支持空的挂载点名称:1. 应用程序需要提供一个”最后方案“下使用的文件系统;2. 应用程序需要同时覆盖 VFS 功能。如果没有与路径匹配的前缀,就会使用到这种文件系统。 + +VFS 不会对路径中的点 (``.``) 进行特殊处理,也不会将 ``..`` 视为对父目录的引用。在上述示例中,使用 ``/data/static/../log.txt`` 路径不会调用 FS 驱动程序 1 打开 ``/log.txt``。特定的 FS 驱动程序(如 FATFS)可能以不同的方式处理文件名中的点。 + +执行打开文件操作时,FS 驱动程序仅得到文件的相对路径(挂载点前缀已经被去除): + +1. 以 ``/data`` 为路径前缀注册 ``myfs`` 驱动; +2. 应用程序调用 ``fopen("/data/config.json", ...)``; +3. VFS 调用 ``myfs_open("/config.json", ...)``; +4. ``myfs`` 驱动打开 ``/config.json`` 文件。 + +VFS 对文件路径长度没有限制,但文件系统路径前缀受 ``ESP_VFS_PATH_MAX`` 限制,即路径前缀上限为 ``ESP_VFS_PATH_MAX``。各个文件系统驱动则可能会对自己的文件名长度设置一些限制。 + + +文件描述符 +---------------- + +文件描述符是一组很小的正整数,从 ``0`` 到 ``FD_SETSIZE - 1``,``FD_SETSIZE`` 在 newlib ``sys/types.h`` 中定义。最大文件描述符由 ``CONFIG_LWIP_MAX_SOCKETS`` 定义,且为套接字保留。VFS 中包含一个名为 ``s_fd_table`` 的查找表,用于将全局文件描述符映射至 ``s_vfs`` 数组中注册的 VFS 驱动索引。 + + +标准 IO 流 (stdin, stdout, stderr) +------------------------------------------- + +如果 menuconfig 中 ``UART for console output`` 选项没有设置为 ``None``,则 ``stdin``、 ``stdout`` 和 ``stderr`` 将默认从 UART 读取或写入。UART0 或 UART1 可用作标准 IO。默认情况下,UART0 使用 115200 波特率,TX 管脚为 GPIO1,RX 管脚为 GPIO3。您可以在 menuconfig 中更改上述参数。 + +对 ``stdout`` 或 ``stderr`` 执行写入操作将会向 UART 发送 FIFO 发送字符,对 ``stdin`` 执行读取操作则会从 UART 接收 FIFO 中取出字符。 + +默认情况下,VFS 使用简单的函数对 UART 进行读写操作。在所有数据放进 UART FIFO 之前,写操作将处于 busy-wait 状态,读操处于非阻塞状态,仅返回 FIFO 中已有数据。由于读操作为非阻塞,高层级 C 库函数调用(如 ``fscanf("%d\n", &var);``)可能获取不到所需结果。 + +如果应用程序使用 UART 驱动,则可以调用 ``esp_vfs_dev_uart_use_driver`` 函数来指导 VFS 使用驱动中断、读写阻塞功能等。您也可以调用 ``esp_vfs_dev_uart_use_nonblocking`` 来恢复非阻塞函数。 + +VFS 还为输入和输出提供换行符转换功能(可选)。多数应用程序在程序内部发送或接收以 LF (''\n'') 结尾的行,但不同的终端程序可能需要不同的换行符,比如 CR 或 CRLF。应用程序可以通过 menuconfig 或者调用 ``esp_vfs_dev_uart_port_set_rx_line_endings`` 和 ``esp_vfs_dev_uart_port_set_tx_line_endings`` 为输入输出配置换行符。 + + +标准流和 FreeRTOS 任务 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``stdin``、``stdout`` 和 ``stderr`` 的 ``FILE`` 对象在所有 FreeRTOS 任务之间共享,指向这些对象的指针分别存储在每个任务的 ``struct _reent`` 中。 + +预处理器把如下代码: + +.. highlight:: c + +:: + + fprintf(stderr, "42\n"); + +解释为: + +.. highlight:: c + +:: + + fprintf(__getreent()->_stderr, "42\n"); + +其中 ``__getreent()`` 函数将为每个任务返回一个指向 ``struct _reent`` 的指针。每个任务的 TCB 均拥有一个 ``struct _reent`` 结构体,任务初始化后,``struct _reent`` 结构体中的 ``_stdin``、``_stdout`` 和 ``_stderr`` 将会被赋予 ``_GLOBAL_REENT`` 中 ``_stdin``、 ``_stdout`` 和 ``_stderr`` 的值,``_GLOBAL_REENT`` 即为 FreeRTOS 启动之前所用结构体。 + +这样设计带来的结果是: + +- 允许重定向给定任务的 ``stdin``、 ``stdout`` 和 ``stderr``,而不影响其他任务,例如通过 ``stdin = fopen("/dev/uart/1", "r")``; +- 但使用 ``fclose`` 关闭默认 ``stdin``、 ``stdout`` 或 ``stderr`` 将同时关闭相应的 ``FILE`` 流对象,因此会影响其他任务; +- 如需更改新任务的默认 ``stdin``、 ``stdout`` 和 ``stderr`` 流,请在创建新任务之前修改 ``_GLOBAL_REENT->_stdin`` (``_stdout``、``_stderr``)。 + 应用示例 ------------------- diff --git a/docs/zh_CN/api-reference/system/power_management.rst b/docs/zh_CN/api-reference/system/power_management.rst index 8e770a104b..c3d83a3c87 100644 --- a/docs/zh_CN/api-reference/system/power_management.rst +++ b/docs/zh_CN/api-reference/system/power_management.rst @@ -6,7 +6,7 @@ 概述 -------- -ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求,调整外围总线 (APB) 频率、CPU 频率,并使芯片进入 Light-sleep 模式,尽可能减少运行应用程序的功耗。 +ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求,调整外围总线 (APB) 频率和 CPU 频率,并使芯片进入 Light-sleep 模式,尽可能减少运行应用程序的功耗。 应用程序组件可以通过创建和获取电源管理锁来控制功耗。 @@ -16,7 +16,7 @@ ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求, - RTOS 可以要求 CPU 在有任务准备开始运行时以最高配置频率工作。 - 一些外设可能需要中断才能启用,因此其驱动也会要求禁用 Light-sleep 模式。 -因为请求较高的 APB 频率或 CPU 频率,以及禁用 Light-sleep 模式会增加功耗,请将组件使用的电源管理锁降到最少。 +请求较高的 APB 频率或 CPU 频率以及禁用 Light-sleep 模式会增加功耗,因此请将组件使用的电源管理锁降到最少。 电源管理配置 ------------- @@ -25,20 +25,27 @@ ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求, 启用电源管理功能将会增加中断延迟。额外延迟与多个因素有关,例如:CPU 频率、单/双核模式、是否需要进行频率切换等。CPU 频率为 240 MHz 且未启用频率调节时,最小额外延迟为 0.2 us;如果启用频率调节,且在中断入口将频率由 40 MHz 调节至 80 MHz,则最大额外延迟为 40 us。 -应用程序可以通过调用 :cpp:func:`esp_pm_configure` 函数启用动态调频 (DFS) 功能和自动 Light-sleep 模式。此函数的参数为 :cpp:class:`esp_pm_config_{IDF_TARGET_PATH_NAME}_t`,定义了频率调节的相关设置。在此参数结构中,需要初始化下面三个字段: +通过调用 :cpp:func:`esp_pm_configure` 函数可以在应用程序中启用动态调频 (DFS) 功能和自动 Light-sleep 模式。此函数的参数 :cpp:class:`esp_pm_config_{IDF_TARGET_PATH_NAME}_t` 定义了频率调节的相关设置。在此参数结构中,需要初始化以下三个字段: - ``max_freq_mhz``:最大 CPU 频率 (MHz),即获取 ``ESP_PM_CPU_FREQ_MAX`` 锁后所使用的频率。该字段通常设置为 :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_DEFAULT_CPU_FREQ_MHZ`。 - - ``min_freq_mhz``:最小 CPU 频率 (MHz),即仅获取 ``ESP_PM_APB_FREQ_MAX`` 锁后所使用的频率。该字段可设置为晶振 (XTAL) 频率值,或者 XTAL 频率值除以整数。注意,10 MHz 是生成 1 MHz 的 REF_TICK 默认时钟所需的最小频率。 - - ``light_sleep_enable``:没有获取任何管理锁时,决定系统是否需要自动进入 Light-sleep 状态 (``true``/``false``)。 -或者,如果在 menuconfig 中启用了 :ref:`CONFIG_PM_DFS_INIT_AUTO` 选项,最大 CPU 频率将由 :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_DEFAULT_CPU_FREQ_MHZ` 设置决定,最小 CPU 频率将锁定为 XTAL 频率。 + + 如果在 menuconfig 中启用了 :ref:`CONFIG_PM_DFS_INIT_AUTO` 选项,最大 CPU 频率将由 :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_DEFAULT_CPU_FREQ_MHZ` 设置决定,最小 CPU 频率将锁定为 XTAL 频率。 .. note:: - 1. 自动 Light-sleep 模式基于 FreeRTOS Tickless Idle 功能,因此如果在 menuconfig 中没有启用 :ref:`CONFIG_FREERTOS_USE_TICKLESS_IDLE` 选项,在请求自动 Light-sleep 时,:cpp:func:`esp_pm_configure` 将会返回 `ESP_ERR_NOT_SUPPORTED` 错误。 - 2. 在 Light-sleep 状态下,外设设有时钟门控,不会产生来自 GPIO 和内部外设的中断。:doc:`sleep_modes` 文档中所提到的唤醒源可用于从 Light-sleep 状态触发唤醒。例如,EXT0 和 EXT1 唤醒源就可以通过 GPIO 唤醒芯片。 + 自动 Light-sleep 模式基于 FreeRTOS Tickless Idle 功能,因此如果在 menuconfig 中没有启用 :ref:`CONFIG_FREERTOS_USE_TICKLESS_IDLE` 选项,在请求自动 Light-sleep 时,:cpp:func:`esp_pm_configure` 将会返回 `ESP_ERR_NOT_SUPPORTED` 错误。 + +.. note:: + + Light-sleep 状态下,外设设有时钟门控,不会产生来自 GPIO 和内部外设的中断。:doc:`sleep_modes` 文档中所提到的唤醒源可用于从 Light-sleep 状态触发唤醒。 + +.. only:: SOC_PM_SUPPORT_EXT_WAKEUP + + 例如,EXT0 和 EXT1 唤醒源可以通过 GPIO 唤醒芯片。 + 电源管理锁 ---------------------- @@ -47,24 +54,26 @@ ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求, 电源管理锁设有获取/释放计数器,如果已多次获取电源管理锁,则需要将电源管理锁释放相同次数以解除限制。 -{IDF_TARGET_NAME} 支持下表中所述的三种电源管理锁。 +{IDF_TARGET_NAME} 支持下表中三种电源管理锁。 -============================ ====================================================== -电源管理锁 描述 -============================ ====================================================== -``ESP_PM_CPU_FREQ_MAX`` 请求使用 :cpp:func:`esp_pm_configure` 将 CPU 频率设置为最大值。{IDF_TARGET_NAME} 可以将该值设置为 80 MHz、160 MHz 或 240 MHz。 +.. list-table:: + :header-rows: 1 + :widths: 25 60 -``ESP_PM_APB_FREQ_MAX`` 请求将 APB 频率设置为最大值,{IDF_TARGET_NAME} 支持的最大频率为 80 MHz。 - -``ESP_PM_NO_LIGHT_SLEEP`` 禁止自动切换至 Light-sleep 模式。 -============================ ====================================================== + * - 电源管理锁 + - 描述 + * - ``ESP_PM_CPU_FREQ_MAX`` + - 请求使用 :cpp:func:`esp_pm_configure` 将 CPU 频率设置为最大值。{IDF_TARGET_NAME} 可以将该值设置为 80 MHz、160 MHz 或 240 MHz。 + * - ``ESP_PM_APB_FREQ_MAX`` + - 请求将 APB 频率设置为最大值,{IDF_TARGET_NAME} 支持的最大频率为 80 MHz。 + * - ``ESP_PM_NO_LIGHT_SLEEP`` + - 禁止自动切换至 Light-sleep 模式。 {IDF_TARGET_NAME} 电源管理算法 -------------------------------- 下表列出了启用动态调频时如何切换 CPU 频率和 APB 频率。您可以使用 :cpp:func:`esp_pm_configure` 或者 :ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_DEFAULT_CPU_FREQ_MHZ` 指定 CPU 最大频率。 - .. only:: esp32 .. include:: inc/power_management_esp32.rst @@ -73,6 +82,7 @@ ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求, .. include:: inc/power_management_esp32s2_and_later.rst + 如果没有获取任何管理锁,调用 :cpp:func:`esp_pm_configure` 将启动 Light-sleep 模式。 Light-sleep 模式持续时间由以下因素决定: - 处于阻塞状态的 FreeRTOS 任务数(有限超时) @@ -80,12 +90,15 @@ ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求, 您也可以设置 Light-sleep 模式在最近事件(任务解除阻塞,或计时器超时)之前持续多久才唤醒芯片。 +为了跳过不必要的唤醒,可以将 `skip_unhandled_events` 选项设置为 true 来初始化 esp_timer。带有此标志的定时器不会唤醒系统,有助于减少功耗。 + + 动态调频和外设驱动 ------------------------------------------------ 启用动态调频后,APB 频率可在一个 RTOS 滴答周期内多次更改。有些外设不受 APB 频率变更的影响,但有些外设可能会出现问题。例如,Timer Group 外设定时器会继续计数,但定时器计数的速度将随 APB 频率的变更而变更。 -下面的外设不受 APB 频率变更的影响: +以下外设不受 APB 频率变更的影响: - **UART**:如果 REF_TICK 用作时钟源,则 UART 不受 APB 频率变更影响。请查看 :cpp:class:`uart_config_t` 中的 `use_ref_tick`。 - **LEDC**:如果 REF_TICK 用作时钟源,则 LEDC 不受 APB 频率变更影响。请查看 :cpp:func:`ledc_timer_config` 函数。 @@ -100,14 +113,14 @@ ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求, 启用以下驱动程序时,将占用 ``ESP_PM_APB_FREQ_MAX`` 锁: - .. list:: - **SPI slave**:从调用 :cpp:func:`spi_slave_initialize` 至 :cpp:func:`spi_slave_free` 期间。 - **Ethernet**:从调用 :cpp:func:`esp_eth_driver_install` 至 :cpp:func:`esp_eth_driver_uninstall` 期间。 - **WiFi**:从调用 :cpp:func:`esp_wifi_start` 至 :cpp:func:`esp_wifi_stop` 期间。如果启用了调制解调器睡眠模式,广播关闭时将释放此管理锁。 - **TWAI**:从调用 :cpp:func:`twai_driver_install` 至 :cpp:func:`twai_driver_uninstall` 期间。 - :SOC_BT_SUPPORTED: - **Bluetooth**:从调用 :cpp:func:`esp_bt_controller_enable` 至 :cpp:func:`esp_bt_controller_disable` 期间。如果启用了蓝牙调制解调器,广播关闭时将释放此管理锁。但依然占用 ``ESP_PM_NO_LIGHT_SLEEP`` 锁。 + :SOC_BT_SUPPORTED and esp32: - **Bluetooth**:从调用 :cpp:func:`esp_bt_controller_enable` 至 :cpp:func:`esp_bt_controller_disable` 期间。如果启用了蓝牙调制解调器,广播关闭时将释放此管理锁。但依然占用 ``ESP_PM_NO_LIGHT_SLEEP`` 锁,除非将 :ref:`CONFIG_BTDM_CTRL_LOW_POWER_CLOCK` 选项设置为 “外部 32 kHz 晶振”。 + :SOC_BT_SUPPORTED and esp32c3: - **Bluetooth**:从调用 :cpp:func:`esp_bt_controller_enable` 至 :cpp:func:`esp_bt_controller_disable` 期间。如果启用了蓝牙调制解调器,广播关闭时将释放此管理锁。但依然占用 ``ESP_PM_NO_LIGHT_SLEEP`` 锁。 以下外设驱动程序无法感知动态调频,应用程序需自己获取/释放管理锁: @@ -118,7 +131,6 @@ ESP-IDF 中集成的电源管理算法可以根据应用程序组件的需求, - Timer group :esp32: - MCPWM - API 参考 ------------- diff --git a/docs/zh_CN/contribute/add-ons-reference.rst b/docs/zh_CN/contribute/add-ons-reference.rst deleted file mode 100644 index 687ca710f4..0000000000 --- a/docs/zh_CN/contribute/add-ons-reference.rst +++ /dev/null @@ -1,197 +0,0 @@ -文档的附加工具和扩展功能指南 -============================= - -:link_to_translation:`en:[English]` - -ESP-IDF 文档由 `Sphinx `_ 应用程序生成,使用 Sphinx 对 :idf:`docs` 目录中的 `reStructuredText `_ (``.rst``) 格式文档进行渲染。关于渲染过程的详细信息,请参阅 :doc:`documenting-code`。 - -除 Sphinx 外,我们也使用了其它几种可为用户提供格式精美、便于查找的文档的应用程序。:ref:`setup-for-building-documentation` 中列出了这些应用程序,:idf_file:`docs/requirements.txt` 中列出了其相应的版本号。 - -ESP-IDF 中包含多种芯片的双语文档(英文,简体中文)。如运行 Sphinx,不需直接使用 ``sphinx``,可运行 Python 程序包 ``build_docs.py``。 - -在此基础上,我们也开发了一些自定义的附加工具和扩展功能,旨在帮助整合 `ESP-IDF`_ 目录下的各个文档以及更好地查找和维护文档内容。 - -本章节主要帮您快速了解这些附加工具和扩展功能。 - -文件夹结构 --------------- - -* ESP-IDF 根目录下包含一个专门放置文档的文件夹 :idf:`docs`。 -* ``docs`` 目录下的 :idf:`docs/en` (英文)和 :idf:`docs/zh_CN` (简体中文)子文件夹中包含本地化文档。 -* 图像文件和本地化文档通用的字体包位于 :idf:`docs/_static` 子文件夹中。 -* ``docs`` 根目录下以及 ``docs/en`` 和 ``docs/zh_CN`` 中的其它文件则提供了自动生成文档过程中所使用的配置和脚本,其中就包括本章节提到的附加工具和扩展功能。 -* ``extensions`` 和 ``idf_extensions`` 两目录中提供了 Sphinx 的扩展功能。· -* 使用 ``build_docs.py``,``docs`` 文件夹中将自动创建一个 ``_build`` 目录。这个目录不会被添加到 `ESP-IDF`_ 项目库中。 - - -附加工具和扩展功能指南 --------------------------------- - -配置文件 -^^^^^^^^^^^^ - -:idf_file:`docs/conf_common.py` - 该文件中包含每个本地化文档(包括英文文档、中文文档)所通用的配置信息。在文档每一次的构建过程中,该文件中的内容都将被导入至相应语言文件夹(包括,``docs/en``、``docs/zh_CN``)下的标准 Sphinx 配置文件 ``conf.py`` 中。 - -:idf_file:`docs/sphinx-known-warnings.txt` - Sphinx 中存在一些伪错误警报,这些警报只能通过更新 Sphinx 源代码本身来解决。针对这一情况,我们将这些伪错误警报列在了 ``sphinx-known-warnings.txt`` 文件中,每一次生成文档时系统都将检测该文件并忽略这些伪错误警报。 - - -脚本 -^^^^^^^ - -:idf_file:`docs/build_docs.py` - - 最高级可执行程序,负责运行 Sphinx 为单个或多个语言/目标生成文档。运行 ``build_docs.py --help`` 可查阅所有命令选项。 - - 当使用 ``build_docs.py`` 运行 Sphinx 时,系统将为 ``idf_target`` 配置变量,并设置一个与该配置变量相同名称的 Sphinx 标签,然后使用一些环境变量将路径发送至 :ref:`IDF-Specific Extensions`。 - -:idf_file:`docs/check_lang_folder_sync.sh` - 同时更新双语文档时,语言文件夹 ``docs/en`` 和 ``docs/zh_CN`` 下的文档结构和文件名应保持一致,以减少两文档间的不一致。每一次生成文档时都将运行 ``check_lang_folder_sync.sh`` 脚本,检测是否出现上述不一致的情况。 - -.. note:: - - 若一个新的章节为英语版本,且暂时还没有中文翻译,那么 ``zh_CN`` 文件夹中相应的中文文件内应写入 ``.. include::`` 指令,路径指向英文源文件。这样,中文读者将也可以看到英文版源文件。例如,如果 ``docs/zh_CN/contribute/documenting-code.rst`` 这一文件还没有中文翻译,则该文件中应写入 ``.. include:: ../../en/contribute/documenting-code.rst``。 - -非文档脚本 -^^^^^^^^^^^^^^^^ - -以下脚本除了生成文档之外,也可以用于其它用途: - -:idf_file:`tools/gen_esp_err_to_name.py` - 该脚本将检测整个 `ESP-IDF`_ 库,在源代码头文件中查找是否有错误代码和信息,然后在 :doc:`../api-reference/error-codes` 内生成一个 ``.inc`` 文件记录这些信息。 - -:idf_file:`tools/kconfig_new/confgen.py` - ESP-IDF :idf:`components` 的配置选项包含在每个组件目录下的 ``Kconfig`` 文件中,如 :idf_file:`components/bt/Kconfig`。该脚本将检测所有 ``component`` 目录并记录检测到的配置选项,然后在 :ref:`configuration-options-reference` 内生成一个 ``.inc`` 文件记录这些信息。 - -通用扩展 -^^^^^^^^^^^^^^^^^^ - -以下是专为 IDF 开发的 Sphinx 扩展,这些扩展不依赖于任何特定的 IDF 文档操作或配置: - -:idf_file:`docs/extensions/toctree_filter.py` - Sphinx 扩展功能,优先于 ``:toctree:`` 指令,允许系统根据是否有标签(如 ``:tagname: toctree_entry``)来过滤条目。完整描述请参考 Python 文件。 - -:idf_file:`docs/extensions/list_filter.py` - Sphinx 扩展功能,提供一个 ``.. list::`` 指令,允许系统根据是否有标签(如 ``:tagname: - list content``)来过滤条目列表。完整描述请参考 Python 文件。 - -:idf_file:`docs/extensions/html_redirects.py` - 在文档的维护过程中,一些源文件可能会转移位置或被重命名。这个 Sphinx 扩展功能便添加了一个重新导向机制,通过在 Sphinx 输出中生成静态 HTML 重新导向页面来为 URL 地址已改变的文档重新导向。该脚本与重新导向列表 ``html_redirect_pages`` 一起使用。``conf_common.py`` 将负责从 :idf_file:`docs/page_redirects.txt` 中生成这个重新导向列表。 - - -第三方扩展 -^^^^^^^^^^^^^^^^^^^^^^ - -- ``sphinxcontrib`` 为 blockdiag、seqdiag、actdiag、nwdiag、rackdiag & packetdiag 等图表的扩展 -- `Sphinx selective exclude`_ 为 ``eager_only`` 的扩展 - -.. _idf-specific extensions: - -IDF 专属扩展 -^^^^^^^^^^^^^^^^^^^^^^^ - -构建系统集成 -################### - -:idf:`docs/idf_extensions/build_system/` - -Python 包实现了一个 Sphinx 扩展功能,即将 IDF 构建系统信息拉入文档构建中 - -* 创建一个 CMake IDF 项目模型,并运行 CMake 生成元数据。 -* 注册一些新的配置变量并发出一个 Sphinx 新事件,这些信息都用于其它扩展功能中。 - -配置变量 -@@@@@@@@@@@@@ - -* ``docs_root`` - $IDF_PATH/docs 目录的绝对路径 -* ``idf_path`` - IDF_PATH 变量的值,未设置环境时为 IDF_PATH 的绝对路径 -* ``build_dir`` - 运行 ``build_docs.py`` 时自动创建的文档生成目录,默认为 ``_build//`` -* ``idf_target`` - IDF_TARGET 的值。``build_docs.py`` 应负责在 Sphinx 命令行中设置该值。 - -新事件 -@@@@@@@@@ - -CMake 项目模型运行完成后,系统将在构建初期发出 ``idf-info`` 事件。 - -参数为 ``(app, project_description)``,其中 ``project_description`` 是一个字典,其中包含从 CMake 构建目录中的 ``project_description.json`` 内解析出的值。 - -其它 IDF 专属的扩展功能均订阅该事件,并使用该事件根据系统构建信息来设置一些文档参数。 - -其它扩展 -############# - -:idf_file:`docs/idf_extensions/include_build_file.py` - ``include-build-file`` 指令相当于是内置的 ``include-file`` 指令,只是文件路径是相对于 ``build_dir`` 来评估的。 - -:idf_file:`docs/idf_extensions/kconfig_reference.py` - 订阅 ``idf-info`` 事件,并使用 confgen 从默认构建项目所使用的组件中生成 ``kconfig.inc`` 文件。之后,这个文件将被存储至 :doc:`/api-reference/kconfig` 中。 - -:idf_file:`docs/idf_extensions/link_roles.py` - 一个自定义的 `Sphinx 角色 `_ 的实现功能,帮助从文档链接到 `ESP-IDF`_ 项目中具体的文件和文件夹处。有关具体实现了哪些角色,请参阅 :ref:`link-custom-roles` 和 :ref:`link-language-versions`。 - -:idf_file:`docs/idf_extensions/esp_err_definitions.py` - 小扩展包,调用 ``gen_esp_err_to_name.py`` 并更新修改后的 .rst 文件。 - -:idf_file:`docs/idf_extensions/gen_toolchain_links.py` - 文档内许多地方提供了下载工具链的链接。为了整合这些链接,减少需要分别手动更新这些链接的时间,该脚本会根据 :idf_file:`tools/toolchain_versions.mk` 内的信息生成工具链下载链接和工具链解压代码片段。 - -:idf_file:`docs/idf_extensions/gen_version_specific_includes.py` - 也是一个自动生成 reStructuredText 文本 ``.inc`` 的扩展功能,其中内容是基于当前 ESP-IDF 版本所写。 - -:idf_file:`docs/idf_extensions/util.py` - 提供一系列实用功能,主要提高本地化生成文档(请参见 :ref:`setup-for-building-documentation`)的效率,节省后续再次生成文本所需时间。 - -:idf_file:`docs/idf_extensions/format_idf_target.py` - 通过将 idf_target 发送至 Sphinx 命令行替换 target 相关名称的扩展功能。例如: - - This is a {\IDF_TARGET_NAME}, with /{\IDF_TARGET_PATH_NAME}/soc.c, compiled with `{\IDF_TARGET_TOOLCHAIN_PREFIX}-gcc` with `CONFIG_{\IDF_TARGET_CFG_PREFIX}_MULTI_DOC` - - 删掉退格键后,将被渲染为 - - This is a {IDF_TARGET_NAME}, with /{IDF_TARGET_PATH_NAME}/soc.c, compiled with `{IDF_TARGET_TOOLCHAIN_PREFIX}-gcc` with `CONFIG_{IDF_TARGET_CFG_PREFIX}_MULTI_DOC`. - - 同时,也支持使用以下语法标记本地(单个 rst 文件)替代文件的定义: - {\IDF_TARGET_TX_PIN:default="IO3",esp32="IO4",esp32s2="IO5"} - - 这样将在当前的 rst 文件中定义标签 {\IDF_TARGET_TX_PIN} 的替换名称。 - - 为了使用相同的格式规则规范文档内容,该扩展功能优先于默认的 ``.. include::`` 指令。 - - 在依赖于字符排列方式的格式内无法使用这一替换方式,例如,表格内。 - -:idf_file:`docs/idf_extensions/latex_builder.py` - 一个在 latex 生成器内添加 ESP-IDF 专属功能的扩展,优先于默认的 Sphinx latex 生成器。 - - 在输出目录内创建并添加 espidf.sty latex 包,其中包含一些运行时所需变量的宏包,如 IDF-Target。 - -:idf_file:`docs/idf_extensions/gen_defines.py` - Sphinx 扩展,将 IDF 中的定义整合入 Sphinx 构建过程中,在 IDF 项目模型创建完成后开始运行。 - - 解析这些定义值,并将其添加为 Sphinx 标签。 - - 发出新的 'idf-defines-generated' 事件,其中有一个包含所有原始定义值的字典,其它扩展功能可以使用这些原始值生成相关数据。 - -:idf_file:`docs/idf_extensions/exclude_docs.py` - Sphinx 扩展,根据 conditional_include_dict {tag:documents} 标签更新已被排除的文档。如果文档设置有这个标签,则其将被添加至文档列表内。 - - 同时也负责在使用 config 值 ``docs_to_build`` 生成文档时,排除不相关文档。此时,未在 ``docs_to_build`` 列表内的文档都将被排除。 - - 订阅 ``idf-defines-generated`` 事件,因为该扩展功能需要根据 Sphinx 标签来决定需排除哪些文档。 - -:idf_file:`docs/idf_extensions/run_doxygen.py` - 订阅 ``idf-defines-generated`` 事件,运行 Doxygen (:idf_file:`docs/doxygen/Doxyfile_common`) 生成描述密钥头文件的 XML 文件,然后运行 Breathe 将这些文件转换为可直接被添加至 API 参考页面的 ``.inc`` 文件。 - - 将一些特定目标的自定义环境变量推入 Doxygen 中,包括项目的默认 ``sdkconfig.h`` 文件内定义的所有宏包以及 ``soc`` 部件 ``xxx_caps.h`` 的头文件中定义的所有宏包。这意味着,公共 API 头文件可以依赖于特定目标的配置选项或者 ``soc`` 功能头文件选项,如头文件中 ``#ifdef`` & ``#if`` 预处理器选项。 - - 也就是说,我们可以根据生成文档的目标来生成不同的 Doxygen 文件。 - - 有关这一流程的更多信息,请参考 :doc:`documenting-code` 和 :doc:`../api-reference/template` 中的 **API 参考** 章节。 - -相关文档 ------------------ - -* :doc:`documenting-code` - - -.. _ESP-IDF: https://github.com/espressif/esp-idf/ -.. _Sphinx selective exclude: https://github.com/pfalcon/sphinx_selective_exclude diff --git a/docs/zh_CN/contribute/documenting-code.rst b/docs/zh_CN/contribute/documenting-code.rst index d205c6a086..4104704e13 100644 --- a/docs/zh_CN/contribute/documenting-code.rst +++ b/docs/zh_CN/contribute/documenting-code.rst @@ -1,605 +1 @@ -编写代码文档 -============ - -:link_to_translation:`en:[English]` - -本文简要介绍了 `espressif/esp-idf`_ 项目库采用的文件风格以及如何在项目库中添加新文件。 - -概述 ----- - -在项目库内编写代码文档时,请遵循 `Doxygen 代码注释风格 `_。要采用这一风格,您可以将 ``@param`` 等特殊命令插入到标准注释块中,比如:: - - /** - * @param ratio this is oxygen to air ratio - */ - -Doxygen 会解析代码,提取命令和后续文本,生成代码文档。 - -注释块通常包含对功能的记述,如下所示。 - -.. image:: ../../_static/doc-code-documentation-inline.png - :align: center - :alt: 内联代码样本文档 - -Doxygen 支持多种排版风格,对于文档中可以包含的细节非常灵活。请参考数据丰富、条理清晰的 `Doxygen 手册 `_ 熟悉 Doxygen 特性。 - - -为什么需要 Doxygen? --------------------- - -使用 Doxygen 的最终目的是确保所有代码编写风格一致,以便在代码变更时使用 `Sphinx`_ 和 `Breathe`_ 等工具协助筹备、自动更新 API 文档。 - -使用这类工具时,上文代码渲染后呈现效果如下: - -.. image:: ../../_static/doc-code-documentation-rendered.png - :align: center - :alt: 渲染后的内联代码样本文档 - - -尝试一下! ----------- - -在本项目库编写代码文档时,请遵守下列准则。 - -1. 写明代码的基本内容:函数、结构体、类型定义、枚举、宏等。请详细说明代码的用途、功能和限制,因为在阅读他人的文档时你也想看到这些信息。 - -2. 函数文档需简述该函数的功能,并解释输入参数和返回值的含义。 - -3. 请不要在参数或除空格外的其他字符前面添加数据类型。所有空格和换行符都会压缩为一个空格。如需换行,请执行换行操作两次。 - - .. image:: ../../_static/doc-code-function.png - :align: center - :alt: 内联函数样本文档及渲染后的效果 - -4. 如果函数没有输入参数或返回值,请跳过 ``@param`` 或 ``@return``。 - - .. image:: ../../_static/doc-code-void-function.png - :align: center - :alt: 隐式内联函数样本文档及渲染后的效果 - -5. 为 ``define``、``struct`` 和 ``enum`` 的成员编写文档时,请在每一项后添加注释,如下所示。 - - .. image:: ../../_static/doc-code-member.png - :align: center - :alt: 内联函数成员样本文档及渲染后的效果 - -6. 请在命令后换行(如下文中的 ``@return`` ),呈现排版精美的列表。 :: - - * - * @return - * - ESP_OK if erase operation was successful - * - ESP_ERR_NVS_INVALID_HANDLE if handle has been closed or is NULL - * - ESP_ERR_NVS_READ_ONLY if handle was opened as read only - * - ESP_ERR_NVS_NOT_FOUND if the requested key doesn't exist - * - other error codes from the underlying storage driver - * - -7. 头文件的功能概览和库文件应当存在同一个项目库之下,放入单独的 ``README.rst`` 文件。如果目录下包含不同 API 的头文件,应将文件命名为 ``apiname-readme.rst``。 - - -进阶 ----- - -以下小贴士可以帮助你进一步提高文档质量,增强可读性。 - -对于代码,请遵循下列准则: - -1. 添加代码片段举例说明。请在片段前后添加 ``@code{c}`` 和 ``@endcode`` 命令。 :: - - * - * @code{c} - * // Example of using nvs_get_i32: - * int32_t max_buffer_size = 4096; // default value - * esp_err_t err = nvs_get_i32(my_handle, "max_buffer_size", &max_buffer_size); - * assert(err == ESP_OK || err == ESP_ERR_NVS_NOT_FOUND); - * // if ESP_ERR_NVS_NOT_FOUND was returned, max_buffer_size will still - * // have its default value. - * @endcode - * - - 代码片段应放入所介绍功能的注释块中。 - -2. 使用 ``@attention`` 或 ``@note`` 命令高亮显示重要信息。 :: - - * - * @attention - * 1. This API only impact WIFI_MODE_STA or WIFI_MODE_APSTA mode - * 2. If the ESP32 is connected to an AP, call esp_wifi_disconnect to disconnect. - * - - 上述例子介绍了如何使用编号列表。 - -3. 给相似的函数编写文档时,可在前后使用 ``/**@{*/`` 和 ``/**@}*/`` 标记命令。 :: - - /**@{*/ - /** - * @brief common description of similar functions - * - */ - void first_similar_function (void); - void second_similar_function (void); - /**@}*/ - - 示例请参照 :component_file:`nvs_flash/include/nvs.h`。 - -4. 如果想跳过重复的宏定义、枚举项等代码,不添加描述,请在代码前后添加 ``/** @cond */`` 和 ``/** @endcond */`` 命令。示例请参照 :component_file:`driver/include/driver/gpio.h`。 - -5. 使用 markdown 增强文档可读性,添加页眉、链接、表格及更多内容。 :: - - * - * [{IDF_TARGET_NAME} 技术参考手册]({IDF_TARGET_TRM_CN_URL}) - * - -.. note:: - - 代码片段、注释、链接等内容如没有附在所述对象对应的注释块中,将不会添加到文档中。 - -6. 准备一个或更多完整的代码示例和描述,将描述放入单独的 ``README.md`` 文件中,置于 :idf:`examples` 目录的特定文件夹中。 - -统一文档格式 ------------------- - -对于 Markdown (.md) 或 reST (.rst) 文档中的文本类信息,请遵守下列规范保证文档格式统一。 - -1. 请确保一个段落仅有一行,同段落中不用断行,如下图所示。通过断行来提高可读性的准则仅限用于书写代码。对于文本类信息,可以通过添加空白行来增加段落,从而提高可读性。 - - .. figure:: ../../_static/doc-format1-recommend.png - :align: center - :scale: 30% - :alt: 推荐一个段落仅有一行(点击放大) - - 一个段落仅有一行(点击放大) - - .. figure:: ../../_static/doc-format2-notrecommend.png - :align: center - :scale: 30% - :alt: 不推荐段落内断行(点击放大) - - 不推荐段落内断行(点击放大) - -2. 请确保中文与英文文档中的行号一一对应,如下图所示。这个方法可以提高日后更新文档的效率。当工程师需要更新文档时,可以迅速定位到对应中文或英文文档的同一行进行更新。对于翻译人员来说,如果文档仅更新了英文版本,译员可以在对应的中文版本中迅速找到需要更新的地方。此外,通过比较中英文文档中的总行数,可以快速判断中文文档是否进行了及时更新。 - - .. figure:: ../../_static/doc-format3-recommend.png - :align: center - :scale: 50% - :alt: 中英文文档中行号一一对应(点击放大) - - 中英文文档行号一一对应(点击放大) - -.. _link-custom-roles: - -链接到示例 ----------- - -链接到 GitHub 上的示例时,请不要使用绝对 URLs 或硬编码 URLs。请使用 Docutils 自定义角色生成链接。自动生成的链接指向项目库中 git commit 编号(或标记)的 tree 或 blob。这种做法可以确保 master 分支上的文件移动或删除时,链接不会失效。Docutils 自定义角色将以透明的方式处理子模块中的文件,并使用正确的 commit ID 链接到子模块目录中。 - -有如下角色可以选择: - -- ``:idf:`path``` - 指向 ESP-IDF 内的目录 -- ``:idf_file:`path``` - 指向 ESP-IDF 内的文件 -- ``:idf_raw:`path``` - 指向 ESP-IDF 内的原始格式文件 -- ``:component:`path``` - 指向 ESP-IDF components 内的文件夹 -- ``:component_file:`path``` - 指向 ESP-IDF components 内的文件 -- ``:component_raw:`path``` - 指向 ESP-IDF components 内的原始格式文件 -- ``:example:`path``` - 指向 ESP-IDF examples 内的文件夹 -- ``:example_file:`path``` - 指向 ESP-IDF examples 内的文件 -- ``:example_raw:`path``` - 指向 inside ESP-IDF examples 内的原始格式文件 - -示例:: - - * :example:`get-started/hello_world` - * :example:`Hello World! ` - -渲染效果: - -* :example:`get-started/hello_world` -* :example:`Hello World! ` - -CI build 脚本中添加了检查功能,查找 RST 文件中的硬编码链接(通过 URL 的 tree/master、blob/master 或 raw/master 部分识别)。该功能可通过 ``cd docs`` 和 ``make gh-linkcheck`` 命令手动运行。 - - -.. _link-language-versions: - -链接到其他语言文档 ------------------- - -要切换不同语言的文档,可使用 ``:link_to_translation:`` 自定义角色。文档页面中的角色提供其他语言版本的链接。下文的例子说明了如何在文档中添加中英文版本的链接:: - - :link_to_translation:`zh_CN:中文版` - :link_to_translation:`en:English` - -语言用 ``en`` 或 ``zh_CN`` 等标准简写表示。最后一个分号后的文本非标准化内容,可根据链接的位置自行输入,如:: - - :link_to_translation:`en:see description in English` - - -.. _add-illustrations: - -添加图例 --------- - -请考虑使用图表和图片解释表述的概念。 - -相比于长篇的表述,图例有时可以更好地描述复杂的理念、数据结构或算法。本项目库使用 `blockdiag `_ 工具包由简单的文本文件生成图表。 - -工具包支持下列图表类型: - -* `框图 `_ -* `时序图 `_ -* `活动图 `_ -* `逻辑网络图 `_ - -使用该工具包,可以将简单的文本(与 graphviz 的 DOT 格式类似)转换成美观的图片。图中内容自动排版。图标代码之后会转换为 ".png" 图片,在后台添加进 **Sphinx** 文档中。 - -要查看图表的渲染效果,可使用线上的 `interactive shell`_ 即时显示生成的图片。 - -下面是一些图表示例: - -* 简单的 **框图** / ``blockdiag`` - `Wi-Fi Buffer 配置 `_ -* 稍复杂的 **框图** - `Wi-Fi 编程模型 `_ -* **时序图** / ``seqdiag`` - `在所有信道中扫描特定 AP `_ -* **包图** / ``packetdiag`` - `NVS 页面结构 `_ - -尝试修改源代码,看看图表会发生什么变化。 - -.. note:: - - `interactive shell`_ 使用的字体和 esp-idf 文档使用的字体渲染后显示的效果略有不同。 - - -添加注释 --------- - -写文档时,您可能需要: - -- 留下建议,说明之后哪些内容需要添加或修改。 -- 提醒自己或其他人跟进。 - -这时,您可以使用 ``.. todo::`` 命令在 reST 文件中添加待做事项。如: - -.. code-block:: none - - .. todo:: - - Add a package diagram. - -如果在 reST 文件中添加 ``.. todolist::`` 命令,整篇文档中的所有待做事项将会罗列成表。 - -默认情况下,文档生成器会忽视 ``.. todo::`` 和 ``.. todolist::`` 命令。如果您想在本地生成的文档中显示注释和注释列表,请执行下列步骤: - -1. 打开本地的 ``conf_common.py`` 文件。 -2. 找到 ``todo_include_todos`` 参数。 -3. 将该参数的值由 ``False`` 改为 ``True``。 - -将改动推送到远端分支之前,请把 ``todo_include_todos`` 的值重置为 ``False``。 - -更多关于扩展的信息,请参阅 `sphinx.ext.todo `_ 的相关文档。 - -为不同芯片书写通用文档 ----------------------- - -乐鑫各芯片的文档是基于现有文档完成的。为提高文档写作效率,使所写文档可重复用于其它芯片(以下称“目标”)文档中,我们为您提供以下功能: - -依据目标类型排除内容 -""""""""""""""""""""" - -有时会出现某一内容只适用于一个目标的情况。这种情况下,你可以使用 ''.. only:: TAG'' 指令将这部分内容设为某个目标的专属内容,'TAG' 处替换为以下名称: - -芯片名称: - -* esp32 -* esp32s2 -* esp32c3 - -从 'sdkconfig.h' 中定义标识符,标识符由目标的默认 menuconfig 设置生成,例如: - -* CONFIG_FREERTOS_UNICORE - -从 soc '\*_caps' 头文件中定义标识符,例如: - -* SOC_BT_SUPPORTED -* SOC_CAN_SUPPORTED - -示例: - -.. code-block:: none - - .. only:: esp32 - - ESP32 specific content. - -该指令也支持布尔逻辑操作符 'and'、'or' 和 'not'。示例: - -.. code-block:: none - - .. only:: SOC_BT_SUPPORTED and CONFIG_FREERTOS_UNICORE - - BT specific content only relevant for single-core targets. - -该功能由 `Sphinx selective exclude `_ 的扩展提供。 - -这个扩展有一个缺点,当你想要排除某个章节时,而这个章节后直接跟着一个加了标签的新章节,此时该功能无法成功操作。这种情况下,章节的标签将无法正确链接到下一节,但其它内容都可正确渲染。如遇这一情况,可暂时使用以下应急方法: - -.. code-block:: none - - .. only:: esp32 - - .. _section_1_label: - - Section 1 - ^^^^^^^^^ - - Section one content - - .. _section_2_label: - - .. only:: not esp32 - - .. _section_2_label: - - Section 2 - ^^^^^^^^^ - Section 2 content - -':TAG:' 角色的作用为从树形目录中排除特定内容。例如: - -.. code-block:: none - - .. toctree:: - :maxdepth: 1 - - :esp32: configure-wrover - configure-other-jtag - -生成文档时,Sphinx 会使用上述提到的指令和角色,根据其被调用的目标标签来添加或排除某些内容。 - -.. note:: - - 如希望根据目标的标签从 toctree 中排除一整个文档,则需同时更新 :idf_file:`docs/conf_common.py` 中的 ``exclude_patterns`` 列表,为其它目标排除该文档。否则,Sphinx 将发出一条错误警报:WARNING: document isn't included in any toctree。 - - 对此推荐的解决方案是:将这个文档添加到 :idf_file:`docs/conf_common.py` ``conditional_include_dict`` 中的一个列表里,例如,一个仅供支持蓝牙的目标可见的文档应被添加至 ``BT_DOCS``。此后,如果该文档未设置对应的标签,则 :idf_file:`docs/idf_extensions/exclude_docs.py` 会将其添加至 ``exclude_patterns``。 - -如果你需要从一个列表或项目符号条目中排除某一内容,应通过在 ''.. list:: '' 指令中使用 '':TAG:'' 角色来完成。 - -.. code-block:: none - - .. list:: - - :esp32: - ESP32 specific content - :SOC_BT_SUPPORTED: - BT specific content - - Common bullet point - - Also common bullet point - - -替代宏 -""""""""""" -如果你需要指向根据目标类型定义的芯片名称、工具链名称、路径名称或其它通用名称,可以选择使用 :idf_file:`docs/idf_extensions/format_idf_target.py` 提供的替代宏。 - -例如,以下 reStructuredText 内容: - - This is a {\IDF_TARGET_NAME}, with /{\IDF_TARGET_PATH_NAME}/soc.c, compiled with `{\IDF_TARGET_TOOLCHAIN_PREFIX}-gcc` with `CONFIG_{\IDF_TARGET_CFG_PREFIX}_MULTI_DOC` - -将在文档中渲染为: - - This is a {IDF_TARGET_NAME}, with /{IDF_TARGET_PATH_NAME}/soc.c, compiled with `{IDF_TARGET_TOOLCHAIN_PREFIX}-gcc` with `CONFIG_{IDF_TARGET_CFG_PREFIX}_MULTI_DOC`. - -这一扩展也支持定义本地(在单个源文件中)替代名称的标记。请在 RST 文件的一行中插入以下定义语言: - - {\IDF_TARGET_SUFFIX:default="DEFAULT_VALUE", esp32="ESP32_VALUE", esp32s2="ESP32S2_VALUE", esp32c3="ESP32C3_VALUE"} - -这样将在当前的 RST 文件中根据目标类型为 {\IDF_TARGET_SUFFIX} 标签定义一个替代名称。例如: - - {\IDF_TARGET_TX_PIN:default="IO3", esp32="IO4", esp32s2="IO5", esp32c3="IO6"} - -上例将为 {\IDF_TARGET_TX_PIN} 标签定义一个替代名称,当使用 esp32s2 标签调用 sphinx 时,{\IDF_TARGET_TX_PIN} 将被替代为 "IO5"。 - -.. note:: - - 这样的单个文档定义指令可置于 .rst 文档中的任意位置(单独一行),指令名须以 ``IDF_TARGET_`` 为开头。 - - -汇总文档 --------- - -文档准备好后,请参照 :doc:`../api-reference/template` 的要求创建一个文件,汇总所有准备好的文档。最后,在文件中添加链接指向 ``/docs`` 文件夹或子文件夹下 ``index.rst`` 文件的 ``.. toctree::``。 - - -Sphinx 新手怎么办 ------------------- - -1. 不要担心。所有需要的软件均有详细文档,并且开源、免费。您可以先查看 `Sphinx`_ 文档。如果您不清楚如何用 rst markup 语言写作,请查看 `reStructuredText Primer `_。您也可以使用 markdown (.md) 文件,查找更多在 `Recommonmark parser' 文档页面 `_ 使用的特定 markdown 句法信息。 - -2. 查看本文档的源文件,了解本文档使用的代码。源文件存储于 GitHub `espressif/esp-idf`_ 项目库的 :idf:`docs` 文件夹下。您可以滑动到页面上方,点击右上角的链接,直接查看本页面的源文件。您也可以通过点击 ``Raw`` 按键打开源文件,在 GitHub 上查看文件的代码。 - -3. 想要查看在上传至 GitHub 前文档如何生成、呈现,有两种方式: - - * 安装`Sphinx`_、`Breathe`_、`Blockdiag `_ 和 `Doxygen `_ 本地生成文档,具体可查看下文。 - - * 在 `Read the Docs `_ 建立账号,在云端生成文档。 Read the Docs 免费提供文档生成和存储,且速度快、质量高。 - -4. 在生成文档前预览,可使用 `Sublime Text `_ 编辑器和 `OmniMarkupPreviewer `_ 插件。 - - -.. _setup-for-building-documentation: - -搭建环境本地生成文档 --------------------- - -安装依赖项 -""""""""""""" - -您可以安装下列包,通过搭建环境在电脑上本地生成文档: - -1. Doxygen - http://doxygen.nl/ -2. Sphinx - https://github.com/sphinx-doc/sphinx/#readme-for-sphinx -3. Breathe - https://github.com/michaeljones/breathe#breathe -4. "sphinx_idf_theme" 文档主题 - https://github.com/espressif/sphinx_idf_theme -5. "sphinx-notfound-page" 自定义 404 页面 - https://github.com/readthedocs/sphinx-notfound-page -6. Blockdiag - http://blockdiag.com/en/index.html -7. Recommonmark - https://github.com/rtfd/recommonmark - -添加 "sphinx_idf_theme" 包之后,文档将与 `ESP-IDF 编程指南 `_ 的风格保持一致。 - -不用担心需要安装太多包。除 Doxygen 之外,其他包均使用纯 Python 语言,可一键安装。 - -.. important:: 目前仅支持 Python 3 版本生成文档,无法使用 Python 2。 - -Doxygen -@@@@@@@ - -Doxygen 的安装取决于操作系统: - -**Linux** - -:: - - sudo apt-get install doxygen - -**Windows** - 在 MSYS2 控制台中安装 - -:: - - pacman -S doxygen - -**MacOS** - -:: - - brew install doxygen - -.. note:: - - 如果您是在 Windows MSYS2 系统上安装(Linux 和 MacOS 用户可以跳过此说明,不使用 MSYS2 的 Windows 用户需找到其它可替代系统),在安装 **之前**,请完成以下两步。这是安装 :ref:`add-illustrations` 提到的 "blockdiag" 依赖项的必须步骤。 - - 1. 更新所有系统包: - - :: - - $ pacman -Syu - - 该过程可能需要重启 MSYS2 MINGW32 控制台并重复上述命令,直至更新完成。 - - 2. 安装 *blockdiag* 的依赖项之一 *pillow*: - - :: - - $ pacman -S mingw32/mingw-w64-i686-python-pillow - - 查看屏幕上的记录,确定 ``mingw-w64-i686-python-pillow-4.3.0-1`` 或更新的版本已安装。旧版本 *pillow* 无法运行。 - - Windows 安装 Doxygen 的缺点是 `blockdiag pictures `_ 字体不能正确加载,可能会存在乱码。在此问题解决之前,您可以使用 `interactive shell`_ 查看完整图片。 - - -其它应用 -@@@@@@@@@@@ - - -其他所有应用都是 `Python `_ 包,可以按照下列步骤一键安装: - -:: - - cd ~/esp/esp-idf/docs - pip install --user -r requirements.txt - -.. note:: - - 安装步骤设定将 ESP-IDF 放在 ``~/esp/esp-idf`` 目录下,这是文档中使用的 ESP-IDF 默认地址。 - -生成文档 -""""""""" - -:: - - cd ~/esp/esp-idf/docs - -现在可以调用如下命令生成文档:: - - ./build_docs.py build - -运行该命令后,系统将为 ESP-IDF 中所有可支持的语言和目标生成文档。这一过程将需要一些时间,但各文档会并行进行,速度取决于系统中 CPU 内核的个数(可通过 ``--sphinx-parallel-builds`` 选项修改该进程,详情可见 ``./build_docs.py --help``)。 - -如需生成某一目标 (esp32) 某一语种 (en) 的全部文档,即 ``en`` 文件夹下所有文档,运行:: - - ./build_docs.py -l en -t esp32 build - -其中,语言 (``-l``) 可选择 ``en`` 和 ``zh_CN``;目标 (``-t``) 可选择 ESP-IDF 中任意可支持的构建目标(如 ``esp32`` 和 ``esp32s2``)。 - -生成后的文档将位于 ``_build///html`` 文件夹中。如需查阅,请在网页浏览器中打开该目录里的 ``index.html``。 - -生成文档子集 -"""""""""""""" -编译某一语言的所有文档可能速度较慢,因此,也可以选择只生成所需的某个文档或部分所选文档。 - -在指令中列出你需要生成的文档名称即可:: - - ./build_docs.py -l en -t esp32 -i api-reference/peripherals/can.rst build - -也可以同时生成多个文档:: - - ./build_docs.py -l en -t esp32 -i api-reference/peripherals/can.rst api-reference/peripherals/adc.rst build - -还可以使用通配符,选择生成所有符合条件的文档:: - - ./build_docs.py -l en -t esp32 -i api-reference/peripherals/* build - -请注意,这一功能仅用于文档写作过程中的检查和测试。其生成的 HTML 页面并非渲染完成后的格式,比如,运行这一指令并不会生成一个列有所有文档的索引,而且如果其中涉及到任何还未生成的文档参考都将导致错误警报出现。 - -快速生成文档 -"""""""""""""""" -可以通过跳过 doxygen 生成的 API 文档直接进入 Sphinx 构建过程来加速文档生成,这样做可以大幅缩短文档构建时间。 - -可通过添加如下参数来实现:: - - ./build_docs.py build -f - -或者通过设置环境变量 `DOCS_FAST_BUILD`。请注意 `-f` 参数是 `build` 的一个子参数,因此必须放在 `build` 后面。 - -生成 PDF -"""""""""""" - -可以使用 ``build_docs.py`` 生成文档的 latex 和 PDF 格式,需安装以下 latex 工具包: - - * latexmk - * texlive-latex-recommended - * texlive-fonts-recommended - * texlive-xetex - -同时,也需要安装以下字体: - - * Freefont Serif、Sans 和 Mono OpenType fonts,类似于 Ubuntu 上的 ``fonts-freefont-otf`` 包 - * Lmodern,类似于 Ubuntu 上的 ``fonts-lmodern`` 包 - * Fandol,可从 `这里 `_ 下载 - -现在,可通过以下指令生成文档的 PDF 格式:: - - ./build_docs.py -bs latex -l en -t esp32 build - -或者,也可以同时生成 html 和 PDF 格式:: - - ./build_docs.py -bs html latex -l en -t esp32 build - -Latex 和 PDF 文件将位于 ``_build///latex`` 文件夹中。 - -大功告成 --------- - -我们喜欢可以做酷炫事情的好代码。 -但我们更喜欢有清晰文档的好代码,可以让读者快速上手,做酷炫的事情。 - -尝试一下,贡献你的代码和文档! - - -相关文档 --------- - -* :doc:`../api-reference/template` -* :doc:`add-ons-reference` - - -.. _espressif/esp-idf: https://github.com/espressif/esp-idf/ - -.. _interactive shell: http://interactive.blockdiag.com/?compression=deflate&src=eJxlUMFOwzAMvecrrO3aITYQQirlAIIzEseJQ5q4TUSIq8TVGIh_J2m7jbKc7Ge_5_dSO1Lv2soWvoVYgieNoMh7VGzJR9FJtugZ7lYQ0UcKEbYNOY36rRQHZHUPT68vV5tceGLbWCUzPfeaFFMoBZzecVc56vWwJFnWMmJ59CCZg617xpOFbTSyw0pmvT_HJ7hxtFNGBr6wvuu5SCkchcrZ1vAeXZomznh5YgTqfcpR02cBO6vZVDeXBRjMjKEcFRbLh8f18-Z2UUBDnqP9wmp9ncRmSSfND2ldGo2h_zse407g0Mxc1q7HzJ3-4jzYYTJjtQH3iSV-fgFzx50J - -.. _Sphinx: http://www.sphinx-doc.org/ -.. _Breathe: https://breathe.readthedocs.io +.. include:: ../../en/contribute/documenting-code.rst diff --git a/docs/zh_CN/get-started/index.rst b/docs/zh_CN/get-started/index.rst index b3736b2763..92b5a384e5 100644 --- a/docs/zh_CN/get-started/index.rst +++ b/docs/zh_CN/get-started/index.rst @@ -286,14 +286,7 @@ ESP-IDF 工具安装器会下载 Github 发布版本中附带的一些工具, Windows 操作系统 ----------------- -如果希望在运行 ESP-IDF 工具安装器时优先选择 Espressif 下载服务器,请在安装程序窗口中勾选 ``Use Espressif download server instead of downloading tool packages from GitHub.`` 选项。 - -.. figure:: ../../_static/esp-idf-installer-download-server.png - :align: center - :alt: 配置 ESP-IDF 工具安装向导优先选择 Espressif 下载服务器 - :figclass: align-center - - 配置 ESP-IDF 工具安装向导优先选择 Espressif 下载服务器 +如果希望在运行 ESP-IDF 工具安装器时优先选择 Espressif 下载服务器,请在 **Select Components** 窗口中的 **Optimization** 部分勾选 **Use Espressif download mirror instead of GitHub** 选项。 Linux 和 macOS 操作系统 -------------------------- diff --git a/docs/zh_CN/hw-reference/esp32/get-started-devkitc.rst b/docs/zh_CN/hw-reference/esp32/get-started-devkitc.rst index 271e23d320..a1e70ed725 100644 --- a/docs/zh_CN/hw-reference/esp32/get-started-devkitc.rst +++ b/docs/zh_CN/hw-reference/esp32/get-started-devkitc.rst @@ -3,8 +3,7 @@ ESP32-DevKitC V4 入门指南 :link_to_translation:`en: [English]` -本指南介绍了如何开始使用 ESP32-DevKitC V4 开发板。有关 ESP32-DevKitC 其他版本的介绍,请见::doc:`../../hw-reference/index`。 - +本指南介绍了如何开始使用 ESP32-DevKitC V4 开发板。 准备工作 ----------- @@ -27,13 +26,14 @@ ESP32-DevKitC V4 是 `乐鑫 `_ 一款基于 ESP32 的小 - 可选多款 ESP32 模组 - - `ESP32-WROOM-32E `_ - - `ESP32-WROOM-32UE `_ - - `ESP32-WROOM-32D `_ - - `ESP32-WROOM-32U `_ + - `ESP32-WROOM-32E `_ + - `ESP32-WROOM-32UE `_ + - `ESP32-WROOM-32D `_ + - `ESP32-WROOM-32U `_ - `ESP32-SOLO-1 `_ - - `ESP32-WROVER-E `_ - - `ESP32-WROVER-IE `_ + - `ESP32-WROVER-E `_ + - `ESP32-WROVER-IE `_ + - `ESP32-WROOM-DA `_ - 可选排针或排母 @@ -49,11 +49,11 @@ ESP32-DevKitC V4 开发板的主要组件、接口及控制方式见下。 .. _get-started-esp32-devkitc-board-front: .. figure:: ../../../_static/esp32-devkitc-functional-overview.jpg - :align: center - :alt: ESP32-DevKitC V4(板载 ESP32-WROOM-32) - :figclass: align-center + :align: center + :alt: ESP32-DevKitC V4(板载 ESP32-WROOM-32) + :figclass: align-center -ESP32-DevKitC V4(板载 ESP32-WROOM-32) + ESP32-DevKitC V4(板载 ESP32-WROOM-32) .. list-table:: @@ -68,10 +68,10 @@ ESP32-DevKitC V4(板载 ESP32-WROOM-32) - 复位按键。 * - Boot - 下载按键。按下 **Boot** 键并保持,同时按一下 **EN** 键(此时不要松开 **Boot** 键)进入“固件下载”模式,通过串口下载固件。 - * - USB-to-UART 桥接器 | 单芯片 USB-UART 桥接器,可提供高达 3 Mbps 的传输速率。 - - Micro USB 端口 - * - USB 接口。 - - 可用作电路板的供电电源,或连接 PC 和 ESP32-WROOM-32 模组的通信接口。 + * - USB-to-UART 桥接器 + - 单芯片 USB-UART 桥接器,可提供高达 3 Mbps 的传输速率。 + * - Micro USB 接口。 + - USB 接口,可用作电路板的供电电源,或连接 PC 和 ESP32-WROOM-32 模组的通信接口。 * - 5V Power On LED - 开发板通电后(USB 或外部 5 V),该指示灯将亮起。更多信息,请见 `相关文档`_ 中的原理图。 * - I/O @@ -99,6 +99,77 @@ ESP32-DevKitC V4(板载 ESP32-WROOM-32) 上述供电模式 **不可同时连接**,否则可能会损坏开发板和/或电源。 +排针 +------------ + +下表列出了开发板两侧排针(J1 和 J3)的名称和功能,排针名称如图 :ref:`get-started-esp32-devkitc-board-front` 中所示,排针编号与 `ESP32-DevKitC V4 原理图`_ (PDF) 一致。 + +J1 +^^^ +==== ==== ===== =================================== +编号 名称 类型 功能 +==== ==== ===== =================================== +1 3V3 P 3.3 V 电源 +2 EN I CHIP_PU, Reset +3 IO36 I GPIO36, ADC1_CH0, S_VP +4 IO39 I GPIO39, ADC1_CH3, S_VN +5 IO34 I GPIO34, ADC1_CH6, VDET_1 +6 IO35 I GPIO35, ADC1_CH7, VDET_2 +7 IO32 I/O GPIO32, ADC1_CH4, TOUCH_CH9, XTAL_32K_P +8 IO33 I/O GPIO33, ADC1_CH5, TOUCH_CH8, XTAL_32K_N +9 IO25 I/O GPIO25, ADC1_CH8, DAC_1 +10 IO26 I/O GPIO26, ADC2_CH9, DAC_2 +11 IO27 I/O GPIO27, ADC2_CH7, TOUCH_CH7 +12 IO14 I/O GPIO14, ADC2_CH6, TOUCH_CH6, MTMS +13 IO12 I/O GPIO12, ADC2_CH5, TOUCH_CH5, MTDI +14 GND G 接地 +15 IO13 I/O GPIO13, ADC2_CH4, TOUCH_CH4, MTCK +16 IO9 I/O GPIO9, D2 +17 IO10 I/O GPIO10, D3 +18 IO11 I/O GPIO11, CMD +19 5V0 P 5 V 电源 +==== ==== ===== =================================== + +J3 +^^^ +==== ==== ===== =================================== +编号 名称 类型 功能 +==== ==== ===== =================================== +1 GND G 接地 +2 IO23 I/O GPIO23 +3 IO22 I/O GPIO22 +4 IO1 I/O GPIO1, U0TXD +5 IO3 I/O GPIO3, U0RXD +6 IO21 I/O GPIO21 +7 GND G 接地 +8 IO19 I/O GPIO19 +9 IO18 I/O GPIO18 +10 IO5 I/O GPIO5 +11 IO17 I/O GPIO17 +12 IO16 I/O GPIO16 +13 IO4 I/O GPIO4, ADC2_CH0, TOUCH_CH0 +14 IO0 I/O GPIO0, ADC2_CH1, TOUCH_CH1, Boot +16 IO2 I/O GPIO2, ADC2_CH2, TOUCH_CH2 +17 IO15 I/O GPIO15, ADC2_CH3, TOUCH_CH3, MTDO +17 IO8 I/O GPIO8, D1 +18 IO7 I/O GPIO7, D0 +19 IO6 I/O GPIO6, SCK +==== ==== ===== =================================== + + P:电源; + I:输入; + O:输出。 + +管脚布局 +^^^^^^^^^^^ +.. figure:: ../../../_static/esp32-devkitC-v4-pinout.jpg + :align: center + :scale: 45% + :alt: ESP32-DevKitC 管脚布局(点击放大) + :figclass: align-center + + ESP32-DevKitC 管脚布局(点击放大) + 有关 C15 的提示 -------------------- @@ -110,13 +181,14 @@ ESP32-DevKitC V4(板载 ESP32-WROOM-32) 用户如果认为 C15 可能影响开发板的使用,则可以将 C15 完全移除。C15 在开发板上的具体位置见下图黄色部分。 -.. figure:: ../../../_static/esp32-devkitc-c15-location.png - :align: center - :alt: C15(黄色)在 ESP32-DevKitC V4 开发板上的位置 - :figclass: align-center - :width: 30% -C15(黄色)在 ESP32-DevKitC V4 开发板上的位置 +.. figure:: ../../../_static/esp32-devkitc-c15-location.png + :align: center + :alt: C15(黄色)在 ESP32-DevKitC V4 开发板上的位置 + :figclass: align-center + :width: 30% + + C15(黄色)在 ESP32-DevKitC V4 开发板上的位置 应用程序开发 @@ -130,11 +202,12 @@ ESP32-DevKitC V4 上电前,请首先确认开发板完好无损。 ------------- .. figure:: ../../../_static/esp32-devkitc-dimensions-back.jpg - :align: center - :alt: ESP32-DevKitC 开发板尺寸 -- 仰视图 - :figclass: align-center + :align: center + :alt: ESP32-DevKitC 开发板尺寸(板载 ESP32-WROOM-32 模组)-- 仰视图 + :figclass: align-center + :width: 30% -ESP32-DevKitC 开发板尺寸 -- 仰视图 + ESP32-DevKitC 开发板尺寸(板载 ESP32-WROOM-32 模组)-- 仰视图 相关文档 @@ -146,6 +219,7 @@ ESP32-DevKitC 开发板尺寸 -- 仰视图 * `《ESP32-WROOM-32D & ESP32-WROOM-32U 技术规格书》 `_ (PDF) * `《ESP32-WROVER 技术规格书》 `_ (PDF) * `《ESP32-WROVER-B 技术规格书》 `_ (PDF) +* `《ESP32-WROOM-DA 技术规格书》 `_ (PDF) * `乐鑫产品选型工具 `__ .. toctree:: diff --git a/docs/zh_CN/hw-reference/esp32/get-started-wrover-kit.rst b/docs/zh_CN/hw-reference/esp32/get-started-wrover-kit.rst index deb5dd54c1..f63132374a 100644 --- a/docs/zh_CN/hw-reference/esp32/get-started-wrover-kit.rst +++ b/docs/zh_CN/hw-reference/esp32/get-started-wrover-kit.rst @@ -2,7 +2,7 @@ ESP-WROVER-KIT V4.1 入门指南 ========================================= :link_to_translation:`en:[English]` -本指南介绍了如何开始使用 ESP-WROVER-KIT V4.1 开发板及其功能和相关配置。有关 ESP-WROVER-KIT 其他版本的介绍,请见::doc:`../../hw-reference/index`。 +本指南介绍了如何开始使用 ESP-WROVER-KIT V4.1 开发板及其功能和相关配置。 准备工作 @@ -22,7 +22,7 @@ ESP-WROVER-KIT 是 `乐鑫 `_ 一款基于 ESP32 的开 ESP-WROVER-KIT 开发板已集成了如下组件: -- ESP32-WROVER-B 模组 +- ESP32-WROVER-E 模组 - LCD 屏 - MicroSD 卡槽 @@ -74,6 +74,9 @@ ESP-WROVER-KIT 开发板的主要组件、接口及控制方式见下。 下表将从图片右上角开始,以顺时针顺序介绍图 1 中的主要组件,然后按同样顺序介绍图 2 中的主要组件。 + + + .. list-table:: :widths: 25 75 :header-rows: 1 @@ -86,7 +89,7 @@ ESP-WROVER-KIT 开发板的主要组件、接口及控制方式见下。 - 32.768 kHz 晶振,可提供 Deep-sleep 下使用的低功耗时钟。 * - 0 欧电阻 - ESP-WROVER-KIT 开发板设计了一个 0 欧电阻,可在测量 ESP32 系列模组在不同功耗模式下的电流时,直接移除或替换为分流器。 - * - ESP32-WROVER-B 模组 + * - ESP32-WROVER-E 模组 - 这款 ESP32 模组内置 64-Mbit PSRAM,可提供灵活的额外存储空间和数据处理能力。 * - 诊断 LED 信号灯 - 本开发板 FT2232 芯片的 GPIO 管脚连接了 4 个红色 LED 信号灯,以备后用。 @@ -165,7 +168,7 @@ ESP32 模组的部分管脚/终端已被板上组件占用或用于外部硬件 部分管脚具备多个功能,可供板上组件或外部硬件设备同时使用,比如 GPIO0 和 GPIO2。由于管脚限制,一些外围设备不可同时使用,比如,由于 JTAG 和 SD 卡槽需共用部分管脚,因此一些使用 SD 卡功能的应用无法同时进行 JTAG 调试。 -其他情况下,不同外设可同时使用。比如,LCD 屏幕和 SD 卡仅共用一个 GPIO21 管脚,可以同时使用。该管脚可为 LCD 屏幕提供 D/C(数据/控制)信号,并用于读取来自 SD 卡槽的 CD 信号(卡检测信号)。如无需使用卡检测功能,开发人员还可以通过移除 R167 来禁用该功能。此时,LCD 和 SD 卡槽可同时使用。 +其他情况下,不同外设可同时使用。比如,LCD 屏幕和 SD 卡仅共用一个 GPIO21 管脚,可以同时使用。该管脚可为 LCD 屏幕提供 D/C(数据/控制)信号,并用于读取来自 SD 卡槽的卡检测信号。如无需使用卡检测功能,开发人员还可以通过移除 R167 来禁用该功能。此时,LCD 和 SD 卡槽可同时使用。 更多外设共享管脚的介绍,请见下一章节中的表格。 @@ -251,7 +254,7 @@ JP1 连接器包括 14 x 2 个排针,具体功能可见下表中间 “I/O” * LED - :ref:`RGB LED ` * MicroSD - :ref:`MicroSD Card / J4 ` * LCD - :ref:`LCD / U5 ` -* PSRAM - ESP32-WROVER-B 的 PSRAM +* PSRAM - ESP32-WROVER-E 的 PSRAM .. _get-started-esp-wrover-kit-v4.1-xtal: @@ -368,7 +371,7 @@ MicroSD 卡 4. MTMS / GPIO14 CLK 5. GPIO2 DATA0 6. GPIO4 DATA1 -7. GPIO21 CD +7. GPIO21 Card Detect ==== ============== =============== @@ -429,7 +432,7 @@ USB 供电 使能 UART 通信 * `ESP-WROVER-KIT V4.1 原理图`_ (PDF) * `ESP-WROVER-KIT V4.1 布局 `_ (DXF) * `《ESP32 技术规格书》 `_ (PDF) -* `《ESP32-WROVER-B 技术规格书》 `_ (PDF) +* `《ESP32-WROVER-E 技术规格书》 `_ (PDF) * :doc:`../../api-guides/jtag-debugging/index` * :doc:`../../hw-reference/index` diff --git a/docs/zh_CN/hw-reference/esp32c3/user-guide-devkitc-02.rst b/docs/zh_CN/hw-reference/esp32c3/user-guide-devkitc-02.rst index 04b18956c9..e246d4c96d 100644 --- a/docs/zh_CN/hw-reference/esp32c3/user-guide-devkitc-02.rst +++ b/docs/zh_CN/hw-reference/esp32c3/user-guide-devkitc-02.rst @@ -41,6 +41,8 @@ ESP32-C3-DevKitC-02 是一款入门级开发板,使用配置 4 MB SPI flash ESP32-C3-DevKitC-02 - 正面 +以下按照逆时针的顺序依次介绍开发板上的主要组件。 + .. list-table:: :widths: 30 70 :header-rows: 1 @@ -49,19 +51,19 @@ ESP32-C3-DevKitC-02 是一款入门级开发板,使用配置 4 MB SPI flash - 介绍 * - ESP32-C3-WROOM-02 - ESP32-C3-WROOM-02 是乐鑫推出的一款通用型 Wi-Fi 和低功耗蓝牙双模模组,功能强大。该模组采用 PCB 板载天线,配置了 4 MB SPI flash。 - * - 5 V 转 3.3 V LDO + * - 5 V to 3.3 V LDO(5 V 转 3.3 V LDO) - 电源转换器,输入 5 V,输出 3.3 V。 - * - 5 V 电源指示灯 + * - 5 V Power On LED(5 V 电源指示灯) - 开发板连接 USB 电源后,该指示灯亮起。 - * - I/O 连接器 + * - Pin Headers(排针) - 所有可用 GPIO 管脚(除 Flash 的 SPI 总线)均已引出至开发板的排针。请查看 :ref:`user-guide-c3-devkitc-02-v1-header-blocks` 获取更多信息。 - * - Boot 键 + * - Boot Button(Boot 键) - 下载按键。按住 **Boot** 键的同时按一下 **Reset** 键进入“固件下载”模式,通过串口下载固件。 - * - Micro-USB 接口 + * - Micro-USB Port(Micro-USB 接口) - USB 接口。可用作开发板的供电电源或 PC 和 ESP32-C3 芯片的通信接口。 - * - Reset 键 + * - Reset Button(Reset 键) - 复位按键。 - * - USB 至 UART 桥接器 + * - USB-to-UART Bridge(USB 至 UART 桥接器) - 单芯片 USB 至 UART 桥接器,可提供高达 3 Mbps 的传输速率。 * - RGB LED - 可寻址 RGB 发光二极管,由 GPIO8 驱动。 @@ -80,7 +82,7 @@ ESP32-C3-DevKitC-02 是一款入门级开发板,使用配置 4 MB SPI flash .. 注解:: - 请确保使用优质 USB 数据线。部分数据线仅可用于充电,无法用于数据传输和编程。 + 请确保使用适当的 USB 数据线。部分数据线仅可用于充电,无法用于数据传输和编程。 软件设置 ^^^^^^^^ @@ -184,7 +186,7 @@ J3 .. [1] P:电源;I:输入;O:输出;T:可设置为高阻。 -.. [2] GPIO2、GPIO8、GPIO9 为 ESP32-C3 芯片的 Strapping 管脚。在芯片的系统复位过程中,Strapping 管脚对自己管脚上的电平采样并存储到锁存器中,并一直保持到芯片掉电或关闭。具体描述和应用,请参考 `ESP32-C3 技术规格书`_ 的 Strapping 管脚章节。 +.. [2] GPIO2、GPIO8、GPIO9 为 ESP32-C3 芯片的 Strapping 管脚。在芯片上电和系统复位过程中,Strapping 管脚根据管脚的二进制电压值控制芯片功能。Strapping 管脚的具体描述和应用,请参考 `ESP32-C3 技术规格书`_ 的 Strapping 管脚章节。 管脚布局 diff --git a/docs/zh_CN/hw-reference/esp32c3/user-guide-devkitm-1.rst b/docs/zh_CN/hw-reference/esp32c3/user-guide-devkitm-1.rst index 3c331f4fcc..08630c6b5b 100644 --- a/docs/zh_CN/hw-reference/esp32c3/user-guide-devkitm-1.rst +++ b/docs/zh_CN/hw-reference/esp32c3/user-guide-devkitm-1.rst @@ -41,6 +41,8 @@ ESP32-C3-DevKitM-1 是一款入门级开发板,使用以尺寸小而得名的 ESP32-C3-DevKitM-1 - 正面 +以下按照逆时针的顺序依次介绍开发板上的主要组件。 + .. list-table:: :widths: 30 70 :header-rows: 1 @@ -49,22 +51,22 @@ ESP32-C3-DevKitM-1 是一款入门级开发板,使用以尺寸小而得名的 - 介绍 * - ESP32-C3-MINI-1 - ESP32-C3-MINI-1 是一款通用型 Wi-Fi 和低功耗蓝牙双模模组,采用 PCB 板载天线。该款模组集成配置 4 MB 嵌入式 flash 的 `ESP32-C3FN4 `_ 芯片。由于 flash 直接封装在芯片中,ESP32-C3-MINI-1 模组具有更小的封装尺寸。 - * - 5 V 转 3.3 V LDO + * - 5 V to 3.3 V LDO(5 V 转 3.3 V LDO) - 电源转换器,输入 5 V,输出 3.3 V。 - * - 5 V 电源指示灯 + * - 5 V Power On LED(5 V 电源指示灯) - 开发板连接 USB 电源后,该指示灯亮起。 - * - I/O 连接器 + * - Pin Headers(排针) - 所有可用 GPIO 管脚(除 flash 的 SPI 总线)均已引出至开发板的排针。请查看 :ref:`user-guide-c3-devkitm-1-v1-header-blocks` 获取更多信息。 - * - Boot 键 + * - Boot Button(Boot 键) - 下载按键。按住 **Boot** 键的同时按一下 **Reset** 键进入“固件下载”模式,通过串口下载固件。 - * - Micro-USB 接口 + * - Micro-USB Port(Micro-USB 接口) - USB 接口。可用作开发板的供电电源或 PC 和 ESP32-C3FN4 芯片的通信接口。 - * - Reset 键 + * - Reset Button(Reset 键) - 复位按键。 - * - USB 至 UART 桥接器 + * - USB-to-UART Bridge(USB 至 UART 桥接器) - 单芯片 USB 至 UART 桥接器,可提供高达 3 Mbps 的传输速率。 * - RGB LED - - 可寻址 RGB 发光二极管 (WS2812),由 GPIO8 驱动。 + - 可寻址 RGB 发光二极管,由 GPIO8 驱动。 开始开发应用 ------------ @@ -78,6 +80,10 @@ ESP32-C3-DevKitM-1 是一款入门级开发板,使用以尺寸小而得名的 - USB 2.0 数据线(标准 A 型转 Micro-B 型) - 电脑 (Windows、Linux 或 macOS) +.. 注解:: + + 请确保使用适当的 USB 数据线。部分数据线仅可用于充电,无法用于数据传输和编程。 + 软件设置 ^^^^^^^^ @@ -179,7 +185,7 @@ J3 ==== ==== ========== ================================ .. [1] P:电源;I:输入;O:输出;T:可设置为高阻。 -.. [2] GPIO2、GPIO8、GPIO9 为 ESP32-C3FN4 芯片的 Strapping 管脚。在芯片的系统复位过程中,Strapping 管脚对自己管脚上的电平采样并存储到锁存器中,并一直保持到芯片掉电或关闭。Strapping 管脚的具体描述和应用,请参考 `ESP32-C3 技术规格书`_ 的 Strapping 管脚章节。 +.. [2] GPIO2、GPIO8、GPIO9 为 ESP32-C3FN4 芯片的 Strapping 管脚。在芯片上电和系统复位过程中,Strapping 管脚根据管脚的二进制电压值控制芯片功能。Strapping 管脚的具体描述和应用,请参考 `ESP32-C3 技术规格书`_ 的 Strapping 管脚章节。 管脚布局 ^^^^^^^^ diff --git a/docs/zh_CN/hw-reference/esp32s2/user-guide-devkitm-1-v1.rst b/docs/zh_CN/hw-reference/esp32s2/user-guide-devkitm-1-v1.rst index b7e1ea5739..f4e1670afb 100644 --- a/docs/zh_CN/hw-reference/esp32s2/user-guide-devkitm-1-v1.rst +++ b/docs/zh_CN/hw-reference/esp32s2/user-guide-devkitm-1-v1.rst @@ -8,7 +8,7 @@ ESP32-S2-DevKitM-1(U) ESP32-S2-DevKitM-1(U) 是一款基于 `ESP32-S2FH4 `__ 芯片(ESP32-S2 系列)的通用型开发板。该款开发板具有丰富的外设和优化的引脚布局,令产品开发更快捷。 -ESP32-S2-DevKitM-1 搭载的是 `ESP32-S2-MINI-1 `__ 模组 (PCB 板载天线),ESP32-S2-DevKitM-1U 搭载的是 `ESP32-S2-MINI-1U `__ 模组 (U.FL 座子连接外部 IPEX 天线)。 +ESP32-S2-DevKitM-1 搭载的是 `ESP32-S2-MINI-1 `__ 模组 (PCB 板载天线),ESP32-S2-DevKitM-1U 搭载的是 `ESP32-S2-MINI-1U `__ 模组 (外部天线连接器)。 +----------------------+-----------------------+ | |ESP32-S2-DevKitM-1| | |ESP32-S2-DevKitM-1U| | @@ -24,6 +24,7 @@ ESP32-S2-DevKitM-1 搭载的是 `ESP32-S2-MINI-1 `_ 的外部天线连接器尺寸章节。 开始开发应用 ------------ @@ -110,11 +113,15 @@ ESP32-S2-DevKitM-1(U) 是乐鑫一款搭载 ESP32-S2-MINI-1 或 ESP32-S2-MINI-1U - ESP32-S2-DevKitM-1(U) - + 如使用 ESP32-S2-DevKitM-1U,还需准备 IPEX 天线 + + 如使用 ESP32-S2-DevKitM-1U,还需准备天线 -- USB 2.0 数据线(标准 A 型转 Micro-B型) +- USB 2.0 数据线(标准 A 型转 Micro-B 型) - 电脑 (Windows、Linux 或 macOS) +.. 注解:: + + 请确保使用适当的 USB 数据线。部分数据线仅可用于充电,无法用于数据传输和编程。 + 软件设置 ^^^^^^^^ @@ -145,46 +152,46 @@ ESP32-S2-DevKitM-1(U) 的主要组件和连接方式如下图所示。 您可从以下三种供电方式中任选其一给 ESP32-S2-DevKitM-1(U) 供电: -- Micro USB 端口供电(默认) -- 5V 和 GND 管脚供电 -- 3V3 和 GND 管脚供电 +- Micro-USB 接口供电(默认) +- 5V 和 GND 排针供电 +- 3V3 和 GND 排针供电 -建议选择第一种供电方式:Micro USB 端口供电。 +建议选择第一种供电方式:Micro-USB 接口供电。 .. _user-guide-devkitm-1-v1-header-blocks: 排针 ---- -下表列出了开发板两侧排针的 **名称** 和 **功能**,开发板排针图可前往 :ref:`user-guide-devkitm-1-v1-board-front` 查看。表格中的序号和名称与 `ESP32-S2-DevKitM-1(U) 原理图 `_ (PDF)一致。 +下表列出了开发板两侧排针(J1 和 J3)的 **名称** 和 **功能**,排针的名称如图 :ref:`user-guide-devkitm-1-v1-board-front` 所示,排针的序号与 `ESP32-S2-DevKitM-1(U) 原理图 `_ (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 -11 9 I/O/T RTC_GPIO9, GPIO9, TOUCH9, ADC1_CH8, FSPIHD -12 10 I/O/T RTC_GPIO10, GPIO10, TOUCH10, ADC1_CH9, FSPICS0, FSPIIO4 -13 11 I/O/T RTC_GPIO11, GPIO11, TOUCH11, ADC2_CH0, FSPID, FSPIIO5 -14 12 I/O/T RTC_GPIO12, GPIO12, TOUCH12, ADC2_CH1, FSPICLK, FSPIIO6 -15 13 I/O/T RTC_GPIO13, GPIO13, TOUCH13, ADC2_CH2, FSPIQ, FSPIIO7 -16 14 I/O/T RTC_GPIO14, GPIO14, TOUCH14, ADC2_CH3, FSPIWP, FSPIDQS -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, DAC_1 -20 5V P 5 V 电源 -21 G G 接地 -==== ==== ===== ============================================================ +==== ==== ========= ========================================================================= +序号 名称 类型 [#]_ 功能 +==== ==== ========= ========================================================================= +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 +11 9 I/O/T RTC_GPIO9, GPIO9, TOUCH9, ADC1_CH8, FSPIHD +12 10 I/O/T RTC_GPIO10, GPIO10, TOUCH10, ADC1_CH9, FSPICS0, FSPIIO4 +13 11 I/O/T RTC_GPIO11, GPIO11, TOUCH11, ADC2_CH0, FSPID, FSPIIO5 +14 12 I/O/T RTC_GPIO12, GPIO12, TOUCH12, ADC2_CH1, FSPICLK, FSPIIO6 +15 13 I/O/T RTC_GPIO13, GPIO13, TOUCH13, ADC2_CH2, FSPIQ, FSPIIO7 +16 14 I/O/T RTC_GPIO14, GPIO14, TOUCH14, ADC2_CH3, FSPIWP, FSPIDQS +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, DAC_1 +20 5V P 5 V 电源 +21 G G 接地 +==== ==== ========= ========================================================================= J3 ^^^ @@ -211,9 +218,26 @@ J3 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 18 I/O/T RTC_GPIO18, GPIO18, U1RXD, ADC2_CH7, DAC_2, CLK_OUT3 +21 18 I/O/T RTC_GPIO18, GPIO18, U1RXD, ADC2_CH7, DAC_2, CLK_OUT3, RGB LED ==== ==== ===== ======================================================== +.. [#] P:电源;I:输入;O:输出;T:可设置为高阻。 + +管脚布局 +^^^^^^^^ +.. figure:: ../../../_static/esp32-s2-devkitm-1-v1-pin-layout.png + :align: center + :scale: 15% + :alt: ESP32-S2-DevKitM-1(U) 管脚布局(点击放大) + :figclass: align-center + + ESP32-S2-DevKitM-1(U) 管脚布局(点击放大) + +硬件版本 +========== + +无历史版本。 + 相关文档 ======== * `ESP32-S2-DevKitM-1(U) 原理图 `_ (PDF) @@ -223,4 +247,4 @@ J3 * `ESP32-S2-MINI-1 & ESP32-S2-MINI-1U 技术规格书 `_ (PDF) * `乐鑫产品选型工具 `__ -有关本开发板的更多设计文档,请联系我们的商务部门 sales@espressif.com。 +有关本开发板的更多设计文档,请联系我们的商务部门 `sales@espressif.com `_。 diff --git a/docs/zh_CN/hw-reference/esp32s2/user-guide-s2-devkitc-1.rst b/docs/zh_CN/hw-reference/esp32s2/user-guide-s2-devkitc-1.rst index 19a0dfeea3..2306ad219c 100644 --- a/docs/zh_CN/hw-reference/esp32s2/user-guide-s2-devkitc-1.rst +++ b/docs/zh_CN/hw-reference/esp32s2/user-guide-s2-devkitc-1.rst @@ -50,7 +50,7 @@ ESP32-S2-DevKitC-1 是一款入门级开发板,使用带有 4 MB SPI flash 的 * - 主要组件 - 介绍 * - ESP32-S2-SOLO 或 ESP32-S2-SOLO-U - - ESP32-S2-SOLO 和 ESP32-S2-SOLO-U 是两款通用型 Wi-Fi 模组。ESP32-S2-SOLO 采用 PCB 板载天线,ESP32-S2-SOLO-U 采用连接器连接外部天线。开发板上的 ESP32-S2-SOLO 或 ESP32-S2-SOLO-U 模组可配置 4 MB flash,也可配置 8 MB flash 加 2 MB PSRAM(芯片内置)。 + - ESP32-S2-SOLO 和 ESP32-S2-SOLO-U 是两款通用型 Wi-Fi 模组。ESP32-S2-SOLO 采用 PCB 板载天线,ESP32-S2-SOLO-U 采用连接器连接外部天线。开发板上的 ESP32-S2-SOLO 或 ESP32-S2-SOLO-U 模组可配置 4 MB flash,也可配置 4 MB flash 加 2 MB PSRAM(芯片内置)。 * - 3.3 V Power On LED(3.3 V 电源指示灯) - 开发板连接 USB 电源后,该指示灯亮起。 * - USB-to-UART Bridge(USB 转 UART 桥接器) 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 index bf69d1e2b6..2964cbadd7 100644 --- 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 @@ -15,9 +15,10 @@ ESP32-S2-Saola-1 本指南包括如下内容: -- `入门指南`_: 简要介绍了 ESP32-S2-Saola-1 和硬件、软件设置指南。 -- `硬件参考`_: 详细介绍了 ESP32-S2-Saola-1 的硬件。 -- `相关文档`_: 列出了相关文档的链接。 +- `入门指南`_:简要介绍了 ESP32-S2-Saola-1 和硬件、软件设置指南。 +- `硬件参考`_:详细介绍了 ESP32-S2-Saola-1 的硬件。 +- `硬件版本`_:介绍硬件历史版本和已知问题,并提供链接至历史版本开发板的入门指南(如有)。 +- `相关文档`_:列出了相关文档的链接。 入门指南 ======== @@ -58,6 +59,8 @@ ESP32-S2-Saola-1 是乐鑫一款基于 ESP32-S2 的小型开发板。板上的 组件介绍 -------- +.. _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 - 正面 @@ -65,6 +68,8 @@ ESP32-S2-Saola-1 是乐鑫一款基于 ESP32-S2 的小型开发板。板上的 ESP32-S2-Saola-1 - 正面 +以下按照顺时针的顺序依次介绍开发板上的主要组件。 + .. list-table:: :widths: 30 70 :header-rows: 1 @@ -73,18 +78,18 @@ ESP32-S2-Saola-1 是乐鑫一款基于 ESP32-S2 的小型开发板。板上的 - 介绍 * - ESP32-S2-WROVER - ESP32-S2-WROVER 集成 ESP32-S2,是通用型 Wi-Fi MCU 模组,功能强大。该模组采用 PCB 板载天线,配置了 4 MB SPI flash 和 2 MB SPI PSRAM。 - * - I/O 连接器 + * - Pin Headers(排针) - 所有可用 GPIO 管脚(除 Flash 和 PSRAM 的 SPI 总线)均已引出至开发板的排针。用户可对 ESP32-S2 芯片编程,使能 SPI、I2S、UART、I2C、触摸传感器、PWM 等多种功能。 - * - USB 至 UART 桥接器 - - 单芯片 USB 至 UART 桥接器,可提供高达 3 Mbps 的传输速率。 - * - Boot 键。 - - 下载按键。按住 **Boot** 键的同时按一下 **Reset** 键进入“固件下载”模式,通过串口下载固件。 - * - Reset 键。 - - 复位按键。 - * - 3.3 V 电源指示灯 + * - 3.3 V Power On LED(3.3 V 电源指示灯) - 开发板连接 USB 电源后,该指示灯亮起。 - * - Micro-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 驱动。 @@ -100,6 +105,10 @@ ESP32-S2-Saola-1 是乐鑫一款基于 ESP32-S2 的小型开发板。板上的 - USB 2.0 数据线(标准 A 型转 Micro-B型) - 电脑 (Windows、Linux 或 macOS) +.. 注解:: + + 请确保使用适当的 USB 数据线。部分数据线仅可用于充电,无法用于数据传输和编程。 + 软件设置 ^^^^^^^^ @@ -107,7 +116,7 @@ ESP32-S2-Saola-1 是乐鑫一款基于 ESP32-S2 的小型开发板。板上的 .. 注解:: - ESP32-S2 仅支持 ESP-IDF master 分支或 v4.2 以上版本。 + ESP32-S2 系列芯片仅支持 ESP-IDF master 分支或 v4.2 以上版本。 硬件参考 ======== @@ -130,19 +139,105 @@ ESP32-S2-Saola-1 的主要组件和连接方式如下图所示。 您可从以下三种供电方式中任选其一给 ESP32-S2-Saola-1 供电: -- Micro USB 端口供电(默认) -- 5V 和 GND 管脚供电 -- 3V3 和 GND 管脚供电 +- Micro-USB 接口供电(默认) +- 5V 和 GND 排针供电 +- 3V3 和 GND 排针供电 -建议选择第一种供电方式:Micro USB 端口供电。 +建议选择第一种供电方式: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_CH3, USB_D+ +20 IO19 I/O GPIO19, ADC2_CH3, USB_D- +21 IO18 I/O GPIO18, ADC2_CH3, 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 原理图`_ (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/libraries-and-frameworks/libs-frameworks.rst b/docs/zh_CN/libraries-and-frameworks/libs-frameworks.rst new file mode 100644 index 0000000000..aed78f596e --- /dev/null +++ b/docs/zh_CN/libraries-and-frameworks/libs-frameworks.rst @@ -0,0 +1 @@ +.. include:: ../../en/libraries-and-frameworks/libs-frameworks.rst diff --git a/docs/zh_CN/security/flash-encryption.rst b/docs/zh_CN/security/flash-encryption.rst index d0b441e9d7..e47bc0a9cf 100644 --- a/docs/zh_CN/security/flash-encryption.rst +++ b/docs/zh_CN/security/flash-encryption.rst @@ -1,534 +1,649 @@ - Flash 加密 ============ +{IDF_TARGET_CRYPT_CNT:default="SPI_BOOT_CRYPT_CNT",esp32="FLASH_CRYPT_CNT"} + +{IDF_TARGET_ESP32_V3_ONLY:default="", esp32="(ESP32 V3 only)"} + +{IDF_TARGET_ENCRYPT_COMMAND:default="espsecure.py encrypt_flash_data --aes_xts", esp32="espsecure.py encrypt_flash_data"} + :link_to_translation:`en:[English]` -本文档将介绍 {IDF_TARGET_NAME} 的 Flash 加密功能,并通过示例展示用户如何在开发及生产过程中使用此功能。本文档旨在引导用户快速入门如何测试及验证 Flash 加密的相关操作。有关 Flash 加密块的详细信息可参见 `{IDF_TARGET_NAME} 技术参考手册`_。 +本文档旨在引导用户快速了解 {IDF_TARGET_NAME} 的 flash 加密功能,通过应用程序代码示例向用户演示如何在开发及生产过程中测试及验证 flash 加密的相关操作。 -.. _{IDF_TARGET_NAME} 技术参考手册: {IDF_TARGET_TRM_CN_URL} 概述 ------ -Flash 加密功能用于加密与 {IDF_TARGET_NAME} 搭载使用的 SPI Flash 中的内容。启用 Flash 加密功能后,物理读取 SPI Flash 便无法恢复大部分 Flash 内容。通过明文数据烧录 {IDF_TARGET_NAME} 可应用加密功能,(若已启用加密功能)引导加载程序会在首次启动时对数据进行加密。 +flash 加密功能用于加密与 {IDF_TARGET_NAME} 搭载使用的片外 flash 中的内容。启用 flash 加密功能后,固件会以明文形式烧录,然后在首次启动时将数据进行加密。因此,物理读取 flash 将无法恢复大部分 flash 内容。 -启用 Flash 加密后,系统将默认加密下列类型的 Flash 数据: +启用 flash 加密后,系统将默认加密下列类型的 flash 数据: - - 引导加载程序 - - 分区表 - - 所有 “app” 类型的分区 +- 固件引导加载程序 +- 分区表 +- 所有 “app” 类型的分区 - 其他类型的 Flash 数据将视情况进行加密: +其他类型的数据将视情况进行加密: - - 安全启动引导加载程序摘要(如果已启用安全启动) - - 分区表中标有“加密”标记的分区 +- 任何在分区表中标有“加密”标志的分区。详情请见 :ref:`encrypted-partition-flag`。 +- 如果启用了安全启动,则可以加密安全启动引导程序摘要(见下文)。 .. only:: esp32 - Flash 加密与 :doc:`安全启动` 功能各自独立,您可以在关闭安全启动的状态下使用 Flash 加密。但是,为了安全的计算机环境,二者应同时使用。在关闭安全启动的状态下,需运行其他配置来确保 Flash 加密的有效性。详细信息可参见 :ref:`flash-encryption-without-secure-boot`。 + :doc:`安全启动` 是一个独立的功能,可以与 flash 加密一起使用,从而创建更安全的环境。 .. important:: - 启用 Flash 加密将限制后续 {IDF_TARGET_NAME} 更新。请务必阅读本文档(包括 :ref:`flash-encryption-limitations`)了解启用 Flash 加密的影响。 + + 对于生产用途,flash 加密仅应在“发布”模式下启用。 + +.. important:: + + 启用 flash 加密将限制后续 {IDF_TARGET_NAME} 更新。在使用 flash 加密功能前,请务必阅读本文档了解其影响。 .. _flash-encryption-efuse: -Flash 加密过程中使用的 eFuse +相关 eFuses ------------------------------ -Flash 加密操作由 {IDF_TARGET_NAME} 上的多个 eFuse 控制。以下是这些 eFuse 列表及其描述: - :: +Flash 加密操作由 {IDF_TARGET_NAME} 上的多个 eFuse 控制。以下是这些 eFuse 列表及其描述,下表中的各 eFuse 名称也在 espefuse.py 工具中使用,为了能在 eFuse API 中使用,请在名称前加上 ``ESP_EFUSE_``,如:esp_efuse_read_field_bit(ESP_EFUSE_DISABLE_DL_ENCRYPT)。 - eFuse 描述 是否可锁定为 默认 - 读取/写入 值 +.. Comment: As text in cells of list-table header rows does not wrap, it is necessary to make 0 header rows and apply bold typeface to the first row. Otherwise, the table goes beyond the html page limits on the right. - .. code-block:: none +.. only:: not SOC_FLASH_ENCRYPTION_XTS_AES - 编码方案 该 2 位宽 eFuse 控制 BLOCK1 中使用的实际 是 0 - 位数,从而获得最终的 256 位 AES 密钥。编码 - 方案值解码如下: - 0: 256 bits - 1: 192 bits - 2: 128 bits - 最终的 AES 密钥根据 FLASH_CRYPT_CONFIG 的 - 值产生。 + .. list-table:: Flash 加密过程中使用的 eFuses + :widths: 25 40 10 + :header-rows: 0 - BLOCK1 存储 AES 密钥的 256 位宽 eFuse 块 是 x + * - **eFuse** + - **描述** + - **位深** + * - ``CODING_SCHEME`` + - 控制用于产生最终 256 位 AES 密钥的 block1 的实际位数。可能的值:``0`` 代表 256 位,``1`` 代表 192 位,``2`` 代表 128 位。最终的 AES 密钥根据 ``FLASH_CRYPT_CONFIG`` 值得出 + - 2 + * - ``flash_encryption`` (block1) + - AES 密钥存储 + - 256 位密钥块 + * - ``FLASH_CRYPT_CONFIG`` + - 控制 AES 加密过程 + - 4 + * - ``DISABLE_DL_ENCRYPT`` + - 设置后,在固件下载模式运行时禁用 flash 加密操作 + - 1 + * - ``DISABLE_DL_DECRYPT`` + - 设置后,在 UART 固件下载模式运行时禁用 flash 解密操作 + - 1 + * - ``{IDF_TARGET_CRYPT_CNT}`` + - 在启动时启用/禁用加密。如果设置了偶数个比特位(0、2、4、6),则在启动时加密 flash。如果设置了奇数个比特位(1、3、5、7),则在启动时不加密 flash + - 7 - FLASH_CRYPT_CONFIG 4 位宽 eFuse,控制 AES 加密进程 是 0xF - download_dis_encrypt 设置后,在 UART 下载模式运行时关闭 Flash 加 是 0 - 密操作 +.. only:: SOC_FLASH_ENCRYPTION_XTS_AES_256 - download_dis_decrypt 设置后,在 UART 下载模式运行时关闭 Flash 解 是 0 - 密操作 + .. list-table:: Flash 加密过程中使用的 eFuses + :widths: 25 40 10 + :header-rows: 0 - FLASH_CRYPT_CNT 7 位 eFuse,在启动时启用/关闭加密功能 是 0 + * - **eFuse** + - **描述** + - **位深** + * - ``BLOCK_KEYN`` + - AES 密钥存储,N 在 0-5 之间 + - XTS_AES_128 有一个 256 位密钥块,XTS_AES_256 有两个 256 位密钥块(共 512 位) + * - ``KEY_PURPOSE_N`` + - 控制 eFuse 块 ``BLOCK_KEYN`` 的目的,其中 N 在 0-5 之间。可能的值:``2`` 代表 ``XTS_AES_256_KEY_1``,``3`` 代表 ``XTS_AES_256_KEY_2``,``4`` 代表 ``XTS_AES_128_KEY``。最终 AES 密钥是基于其中一个或两个目的 eFuses 值推导。有关各种可能的组合,请参阅 *{IDF_TARGET_NAME} 技术参考手册* > *外部内存加密和解密(XTS_AES)* [PDF <{IDF_TARGET_TRM_CN_URL}#extmemencr>__]。 + - 4 + * - ``DIS_DOWNLOAD_MANUAL_ENCRYPT`` + - 设置后,在下载启动模式下禁用 flash 加密 + - 1 + * - ``{IDF_TARGET_CRYPT_CNT}`` + - 设置 SPI 启动模式后,可启用加密和解密。如果在 eFuse 中设置了 1 或 3 个比特位,则启用该功能,否则将禁用。 + - 3 - 偶数位(0,2,4,6): - 启动时加密 Flash - 奇数位(1,3,5,7): - 启动时不加密 Flash +.. only:: SOC_FLASH_ENCRYPTION_XTS_AES and not SOC_FLASH_ENCRYPTION_XTS_AES_256 + + .. list-table:: Flash 加密过程中使用的 eFuses + :widths: 25 40 10 + :header-rows: 0 + + * - **eFuse** + - **描述** + - **位深** + * - ``BLOCK_KEYN`` + - AES 密钥存储,N 在 0-5 之间 + - 256 位密钥块 + * - ``KEY_PURPOSE_N`` + - 控制 eFuse 块 ``BLOCK_KEYN`` 的目的,其中 N 在 0 到 5 之间。对于 flash 加密,唯一的有效值是 4,代表 ``XTS_AES_128_KEY`` + - 4 + * - ``DIS_DOWNLOAD_MANUAL_ENCRYPT`` + - 设置后,则在下载引导模式时禁用 flash 加密 + - 1 + * - ``{IDF_TARGET_CRYPT_CNT}`` + - 设置 SPI 启动模式后,可启用加密和解密。如果在 eFuse 中设置 1 或 3 个比特位,则启用该功能,否则将禁用。 + - 3 + +.. note:: + * 上表中列出的所有 eFuse 位都提供读/写访问控制。 + * 这些位的默认值是 0。 + +对上述 eFuse 位的读写访问由 ``WR_DIS`` 和 ``RD_DIS`` 寄存器中的相应字段控制。有关 {IDF_TARGET_NAME} eFuse 的详细信息,请参考 :doc:`eFuse 管理器 <../api-reference/system/efuse>`。要使用 espefuse.py 更改 eFuse 字段的保护位,请使用以下两个命令:read_protect_efuse 和 write_protect_efuse。例如 ``espefuse.py write_protect_efuse DISABLE_DL_ENCRYPT``。 -对上述位的读写访问由 ``efuse_wr_disable`` 和 ``efuse_rd_disable`` 寄存器中的相应位控制。有关 {IDF_TARGET_NAME} eFuse 的详细信息可参见 :doc:`eFuse 管理器 <../api-reference/system/efuse>`。 Flash 的加密过程 ------------------ -假设 eFuse 值处于默认状态,且第二阶段的引导加载程序编译为支持 Flash 加密,则 Flash 加密过程执行如下: +假设 eFuse 值处于默认状态,且固件的引导加载程序编译为支持 flash 加密,则 flash 加密的具体过程如下: -- 首次上电复位时,Flash 中的所有数据都是未加密形式(明文数据)。第一阶段加载器 (Rom) 将在 IRAM 中加载第二阶段加载器。 -- 第二阶段引导加载程序将读取 flash_crypt_cnt (=00000000b) eFuse 值,因为该值为 0(偶数位),第二阶段引导加载程序将配置并启用 Flash 加密块,同时将 ``FLASH_CRYPT_CFG`` eFuse 的值编程为 0xF。 -- Flash 加密块将生成 AES-256 位密钥,并将其储存于 BLOCK1 eFuse 中。该操作在硬件中执行,软件将无法访问此密钥。 -- 接着,Flash 加密块将加密 Flash 的内容(根据分区表的标记值)。原地加密可能会有耗时(取决于大分区的耗时)。 -- 随后,第二阶段引导加载程序将在 flash_crypt_cnt (=00000001b) 中设置第一个可用位,从而标记已加密的 Flash 内容(偶数位)。 -- 在 :ref:`flash_enc_release_mode` 下,第二阶段引导加载程序将把 ``download_dis_encrypt``、``download_dis_decrypt`` 和 ``download_dis_cache`` 的 eFuse 位改写为 1,防止 UART 引导加载程序解密 Flash 的内容。同时也将写保护 ``FLASH_CRYPT_CNT`` 的 eFuse 位。 -- 在 :ref:`flash_enc_development_mode` 下,第二阶段引导加载程序将仅改写 ``download_dis_decrypt`` 和 ``download_dis_cache`` 的 eFuse 位,从而允许 UART 引导加载程序重新烧录加密的二进制文件。同时将不会写保护 ``FLASH_CRYPT_CNT`` 的 eFuse 位。 -- 然后,第二阶段引导加载程序重启设备并开始执行加密映像,同时将透明解密 Flash 的内容并将其加载至 IRAM。 +.. only:: not SOC_FLASH_ENCRYPTION_XTS_AES -在开发阶段常需编写不同的明文 Flash 映像,以及测试 Flash 的加密过程。这要求 UART 下载模式能够根据需求不断加载新的明文映像。但是,在量产和生产过程中,出于安全考虑,UART 下载模式不应有权限访问 Flash 内容。因此需要有两种不同的 {IDF_TARGET_NAME} 配置:一种用于开发,另一种用于生产。以下章节介绍了 Flash 加密的 :ref:`flash_enc_development_mode` 和 :ref:`flash_enc_release_mode` 及其使用指南。 + 1. 第一次开机复位时,flash 中的所有数据都是未加密的(明文)。ROM 引导加载程序加载固件引导加载程序。 -.. important:: - 顾名思义,开发模式应 **仅开发过程** 使用,因为该模式可以修改和回读加密的 Flash 内容。 + 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>`__]。 -设置 Flash 加密的步骤 + 3. 固件的引导加载程序使用 RNG(随机数生成)模块生成 AES-256 位密钥,然后将其写入 ``flash_encryption`` eFuse 中。由于 ``flash_encryption`` eFuse 已设置编写和读取保护位,将无法通过软件访问密钥。Flash 加密操作完全在硬件中完成,无法通过软件访问密钥。 + + 4. Flash 加密块将加密 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 位不受写入保护。 + + 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 中。 + +.. only:: SOC_FLASH_ENCRYPTION_XTS_AES_256 + + 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>`__]。 + + 3. 固件的引导加载程序使用 RNG(随机数生成)模块生成 256 位或 512 位密钥,具体取决于 :ref:`生成的 AES-XTS 密钥的大小 `,然后分别将其写入一个或两个 `BLOCK_KEYN` eFuses。软件也为存储密钥的块更新了 ``KEY_PURPOSE_N``。由于一或两个 ``BLOCK_KEYN`` eFuse 已设置编写和读取保护位,将无法通过软件访问密钥。``KEY_PURPOSE_N`` 字段也受写保护。Flash 加密操作完全在硬件中完成,无法通过软件访问密钥。 + + 4. Flash 加密块将加密 flash 的内容(固件的引导加载程序、应用程序、以及标有“加密”标志的分区)。就地加密可能会耗些时间(对于大分区最多需要一分钟)。 + + 5. 固件引导加载程序将在 ``{IDF_TARGET_CRYPT_CNT}`` (0b001) 中设置第一个可用位来对已加密的 flash 内容进行标记。设置奇数位。 + + 6. 对于 :ref:`flash-enc-development-mode`,固件引导加载程序允许 UART 引导加载程序重新烧录加密后的二进制文件。同时,``{IDF_TARGET_CRYPT_CNT}`` eFuse 位不受写入保护。此外,默认情况下,固件引导加载程序设置 ``DIS_BOOT_REMAP``、 ``DIS_DOWNLOAD_ICACHE``、 ``DIS_DOWNLOAD_DCACHE``、 ``HARD_DIS_JTAG`` 和 ``DIS_LEGACY_SPI_BOOT`` eFuse 位。 + + 7. 对于 :ref:`flash-enc-release-mode`,固件引导加载程序设置所有在开发模式下设置的 eFuse 位。它还写保护 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 位。要修改此行为,请参阅 :ref:`uart-bootloader-encryption`。 + + 8. 重新启动设备以开始执行加密镜像。固件引导加载程序调用 flash 解密块来解密 flash 内容,然后将解密的内容加载到 IRAM 中。 + +.. only:: SOC_FLASH_ENCRYPTION_XTS_AES and not SOC_FLASH_ENCRYPTION_XTS_AES_256 + + 1. 第一次开机复位时,flash 中的所有数据都是未加密的(明文)。ROM 引导加载程序加载固件引导加载程序。 + + 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 加密操作完全在硬件中完成,无法通过软件访问密钥。 + + 4. Flash 加密块将加密 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 位。 + + 7. 对于 :ref:`flash-enc-release-mode`,固件引导加载程序设置所有在开发模式下设置的 eFuse 位以及 ``DIS_DOWNLOAD_MANUAL_ENCRYPT``。它还写保护 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 位。要修改此行为,请参阅 :ref:`uart-bootloader-encryption`。 + + 8. 重新启动设备以开始执行加密镜像。固件引导加载程序调用 flash 解密块来解密 flash 内容,然后将解密的内容加载到 IRAM 中。 + +在开发阶段常需编写不同的明文 flash 镜像并测试 flash 的加密过程。这要求固件下载模式能够根据需求不断加载新的明文镜像。但是,在制造和生产过程中,出于安全考虑,固件下载模式不应有权限访问 flash 内容。 + +因此需要有两种不同的 flash 加密配置:一种用于开发,另一种用于生产。详情请参考 :ref:`flash-encryption-configuration`。 + +.. _flash-encryption-configuration: + +Flash 加密设置 ---------------------- -.. _flash_enc_development_mode: +提供以下 flash 加密模式: + +- :ref:`flash-enc-development-mode` - 建议仅在开发过程中使用,因为它不会阻止修改和读取加密的 flash 内容。 +- :ref:`flash-enc-release-mode` - 建议用于制造和生产,以防止物理读取加密的 flash 内容。 + +本节将详细介绍上述 flash 加密模式,并且逐步说明如何使用它们。 + +.. _flash-enc-development-mode: 开发模式 ^^^^^^^^^^ -可使用 {IDF_TARGET_NAME} 内部生成的密钥或外部主机生成的密钥在开发中运行 Flash 加密。 - -使用 {IDF_TARGET_NAME} 生成的 Flash 加密密钥 -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -正如上文所说,:ref:`flash_enc_development_mode` 允许用户使用 UART 下载模式多次下载明文映像。需完成以下步骤测试 Flash 加密过程: - -- 确保您的 {IDF_TARGET_NAME} 设备有 :ref:`flash-encryption-efuse` 中所示的 Flash 加密 eFuse 的默认设置。 - -- 可在 ``$IDF_PATH/examples/security/flash_encryption`` 文件夹中找到 Flash 加密的示例应用程序。该示例应用程序中有显示 Flash 加密的状态(启用或关闭)以及 ``FLASH_CRYPT_CNT`` eFuse 值。 - -- 在第二阶段引导加载程序中启用 Flash 加密支持。请前往 :ref:`project-configuration-menu`,选择 "Security Features"。 - -- 选择 :ref:`Enable flash encryption on boot `。 - -- 默认设置模式为 **开发模式**。 - -- 在引导加载程序 config 下选择适当详细程度的日志。 - -.. only:: esp32 - - - 启用 Flash 加密将增大引导加载程序,因而可能需更新分区表偏移。请参见 :ref:`bootloader-size`。 - -- 保存配置并退出。 - -构建并烧录完整的映像包括:引导加载程序、分区表和 app。这些分区最初以未加密形式写入 Flash。 - - :: - - idf.py flash monitor - -一旦烧录完成,设备将重置,在下次启动时,第二阶段引导加载程序将加密 Flash 的 app 分区,然后重置该分区。现在,示例应用程序将在运行时解密并执行命令。以下是首次启用 Flash 加密后 {IDF_TARGET_NAME} 启动时的样例输出。 - - :: - - --- idf_monitor on /dev/cu.SLAB_USBtoUART 115200 --- - --- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H --- - ets Jun 8 2016 00:22:57 - - rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) - configsip: 0, SPIWP:0xee - clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 - mode:DIO, clock div:2 - load:0x3fff0018,len:4 - load:0x3fff001c,len:8452 - load:0x40078000,len:13608 - load:0x40080400,len:6664 - entry 0x40080764 - I (28) boot: ESP-IDF v4.0-dev-850-gc4447462d-dirty 2nd stage bootloader - I (29) boot: compile time 15:37:14 - I (30) boot: Enabling RNG early entropy source... - I (35) boot: SPI Speed : 40MHz - I (39) boot: SPI Mode : DIO - I (43) boot: SPI Flash Size : 4MB - I (47) boot: Partition Table: - I (51) boot: ## Label Usage Type ST Offset Length - I (58) boot: 0 nvs WiFi data 01 02 0000a000 00006000 - I (66) boot: 1 phy_init RF data 01 01 00010000 00001000 - I (73) boot: 2 factory factory app 00 00 00020000 00100000 - I (81) boot: End of partition table - I (85) esp_image: segment 0: paddr=0x00020020 vaddr=0x3f400020 size=0x0808c ( 32908) map - I (105) esp_image: segment 1: paddr=0x000280b4 vaddr=0x3ffb0000 size=0x01ea4 ( 7844) load - I (109) esp_image: segment 2: paddr=0x00029f60 vaddr=0x40080000 size=0x00400 ( 1024) load - 0x40080000: _WindowOverflow4 at esp-idf/esp-idf/components/freertos/xtensa_vectors.S:1778 - - I (114) esp_image: segment 3: paddr=0x0002a368 vaddr=0x40080400 size=0x05ca8 ( 23720) load - I (132) esp_image: segment 4: paddr=0x00030018 vaddr=0x400d0018 size=0x126a8 ( 75432) map - 0x400d0018: _flash_cache_start at ??:? - - I (159) esp_image: segment 5: paddr=0x000426c8 vaddr=0x400860a8 size=0x01f4c ( 8012) load - 0x400860a8: prvAddNewTaskToReadyList at esp-idf/esp-idf/components/freertos/tasks.c:4561 - - I (168) boot: Loaded app from partition at offset 0x20000 - I (168) boot: Checking flash encryption... - I (168) flash_encrypt: Generating new flash encryption key... - I (187) flash_encrypt: Read & write protecting new key... - I (187) flash_encrypt: Setting CRYPT_CONFIG efuse to 0xF - W (188) flash_encrypt: Not disabling UART bootloader encryption - I (195) flash_encrypt: Disable UART bootloader decryption... - I (201) flash_encrypt: Disable UART bootloader MMU cache... - I (208) flash_encrypt: Disable JTAG... - I (212) flash_encrypt: Disable ROM BASIC interpreter fallback... - I (219) esp_image: segment 0: paddr=0x00001020 vaddr=0x3fff0018 size=0x00004 ( 4) - I (227) esp_image: segment 1: paddr=0x0000102c vaddr=0x3fff001c size=0x02104 ( 8452) - I (239) esp_image: segment 2: paddr=0x00003138 vaddr=0x40078000 size=0x03528 ( 13608) - I (249) esp_image: segment 3: paddr=0x00006668 vaddr=0x40080400 size=0x01a08 ( 6664) - I (657) esp_image: segment 0: paddr=0x00020020 vaddr=0x3f400020 size=0x0808c ( 32908) map - I (669) esp_image: segment 1: paddr=0x000280b4 vaddr=0x3ffb0000 size=0x01ea4 ( 7844) - I (672) esp_image: segment 2: paddr=0x00029f60 vaddr=0x40080000 size=0x00400 ( 1024) - 0x40080000: _WindowOverflow4 at esp-idf/esp-idf/components/freertos/xtensa_vectors.S:1778 - - I (676) esp_image: segment 3: paddr=0x0002a368 vaddr=0x40080400 size=0x05ca8 ( 23720) - I (692) esp_image: segment 4: paddr=0x00030018 vaddr=0x400d0018 size=0x126a8 ( 75432) map - 0x400d0018: _flash_cache_start at ??:? - - I (719) esp_image: segment 5: paddr=0x000426c8 vaddr=0x400860a8 size=0x01f4c ( 8012) - 0x400860a8: prvAddNewTaskToReadyList at esp-idf/esp-idf/components/freertos/tasks.c:4561 - - I (722) flash_encrypt: Encrypting partition 2 at offset 0x20000... - I (13229) flash_encrypt: Flash encryption completed - I (13229) boot: Resetting with flash encryption enabled... +在开发过程中,可使用 {IDF_TARGET_NAME} 内部生成的密钥或外部主机生成的密钥进行 flash 加密。 - 启用 Flash 加密后,在下次启动时输出将显示已启用 Flash 加密。 +使用 {IDF_TARGET_NAME} 生成的密钥 +""""""""""""""""""""""""""""""""""""" - :: +开发模式允许用户使用固件下载模式下载多个明文镜像。 - rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) - configsip: 0, SPIWP:0xee - clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 - mode:DIO, clock div:2 - load:0x3fff0018,len:4 - load:0x3fff001c,len:8452 - load:0x40078000,len:13652 - ho 0 tail 12 room 4 - load:0x40080400,len:6664 - entry 0x40080764 - I (30) boot: ESP-IDF v4.0-dev-850-gc4447462d-dirty 2nd stage bootloader - I (30) boot: compile time 16:32:53 - I (31) boot: Enabling RNG early entropy source... - I (37) boot: SPI Speed : 40MHz - I (41) boot: SPI Mode : DIO - I (45) boot: SPI Flash Size : 4MB - I (49) boot: Partition Table: - I (52) boot: ## Label Usage Type ST Offset Length - I (60) boot: 0 nvs WiFi data 01 02 0000a000 00006000 - I (67) boot: 1 phy_init RF data 01 01 00010000 00001000 - I (75) boot: 2 factory factory app 00 00 00020000 00100000 - I (82) boot: End of partition table - I (86) esp_image: segment 0: paddr=0x00020020 vaddr=0x3f400020 size=0x0808c ( 32908) map - I (107) esp_image: segment 1: paddr=0x000280b4 vaddr=0x3ffb0000 size=0x01ea4 ( 7844) load - I (111) esp_image: segment 2: paddr=0x00029f60 vaddr=0x40080000 size=0x00400 ( 1024) load - 0x40080000: _WindowOverflow4 at esp-idf/esp-idf/components/freertos/xtensa_vectors.S:1778 +测试 flash 加密过程需完成以下步骤: - I (116) esp_image: segment 3: paddr=0x0002a368 vaddr=0x40080400 size=0x05ca8 ( 23720) load - I (134) esp_image: segment 4: paddr=0x00030018 vaddr=0x400d0018 size=0x126a8 ( 75432) map - 0x400d0018: _flash_cache_start at ??:? +1. 确保您的 {IDF_TARGET_NAME} 设备有 :ref:`flash-encryption-efuse` 中所示的 flash 加密 eFuse 的默认设置。 - I (162) esp_image: segment 5: paddr=0x000426c8 vaddr=0x400860a8 size=0x01f4c ( 8012) load - 0x400860a8: prvAddNewTaskToReadyList at esp-idf/esp-idf/components/freertos/tasks.c:4561 + 请参考如何检查 :ref:`flash-encryption-status`。 - I (171) boot: Loaded app from partition at offset 0x20000 - I (171) boot: Checking flash encryption... - I (171) flash_encrypt: flash encryption is enabled (3 plaintext flashes left) - I (178) boot: Disabling RNG early entropy source... - I (184) cpu_start: Pro cpu up. - I (188) cpu_start: Application information: - I (193) cpu_start: Project name: flash-encryption - I (198) cpu_start: App version: v4.0-dev-850-gc4447462d-dirty - I (205) cpu_start: Compile time: Jun 17 2019 16:32:52 - I (211) cpu_start: ELF file SHA256: 8770c886bdf561a7... - I (217) cpu_start: ESP-IDF: v4.0-dev-850-gc4447462d-dirty - I (224) cpu_start: Starting app cpu, entry point is 0x40080e4c - 0x40080e4c: call_start_cpu1 at esp-idf/esp-idf/components/{IDF_TARGET_PATH_NAME}/cpu_start.c:265 +2. 在 :ref:`项目配置菜单 `,执行以下操作: - I (0) cpu_start: App cpu up. - I (235) heap_init: Initializing. RAM available for dynamic allocation: - I (241) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM - I (247) heap_init: At 3FFB2EC8 len 0002D138 (180 KiB): DRAM - I (254) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM - I (260) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM - I (266) heap_init: At 40087FF4 len 0001800C (96 KiB): IRAM - I (273) cpu_start: Pro cpu start user code - I (291) cpu_start: Starting scheduler on PRO CPU. - I (0) cpu_start: Starting scheduler on APP CPU. + .. list:: - Sample program to check Flash Encryption - This is {IDF_TARGET_NAME} chip with 2 CPU cores, WiFi/BT/BLE, silicon revision 1, 4MB external flash - Flash encryption feature is enabled - Flash encryption mode is DEVELOPMENT - Flash in encrypted mode with flash_crypt_cnt = 1 - Halting... + - :ref:`启动时使能 flash 加密 ` + - :ref:`选择加密模式 ` (默认是 **开发模式**) + :esp32: - :ref:`选择 UART ROM 下载模式 ` (默认是 **启用**。 对于 esp32 芯片,该选项仅在 :ref:`CONFIG_ESP32_REV_MIN` 级别设置为 3 时 (ESP32 V3) 可用)。 + :not esp32: - :ref:`选择 UART ROM 下载模式 ` (默认是 **启用**) + :esp32s2 or esp32s3: - 设置 :ref:`生成的 AES-XTS 密钥大小 ` + - :ref:`选择适当详细程度的引导加载程序日志 ` + - 保存配置并退出。 -在此阶段,如果用户希望以加密格式将已修改的明文应用程序映像更新到 Flash 中,可使用以下命令: +启用 flash 加密将增大引导加载程序,因而可能需更新分区表偏移量。请参考 :ref:`引导加载程序大小 `。 - :: +3. 运行以下命令来构建和烧录完整的镜像。 - idf.py encrypted-app-flash monitor + .. code-block:: bash -.. _encrypt_partitions: + idf.py flash monitor -加密多重分区 -^^^^^^^^^^^^^ + .. note:: -如果所有分区都需以加密格式更新,则可使用以下命令: + 这个命令不包括任何应该写入 flash 分区的用户文件。请在运行此命令前手动写入这些文件,否则在写入前应单独对这些文件进行加密。 - :: +该命令将向 flash 写入未加密的镜像:固件引导加载程序、分区表和应用程序。烧录完成后,{IDF_TARGET_NAME} 将重置。在下一次启动时,固件引导加载程序会加密:固件引导加载程序、应用程序分区和标记为“加密”的分区,然后复位。就地加密可能需要时间,对于大分区最多需要一分钟。之后,应用程序在运行时解密并执行命令。 + +下面是启用 flash 加密后 {IDF_TARGET_NAME} 首次启动时的样例输出: + +.. include:: {IDF_TARGET_PATH_NAME}_log.inc + :start-after: first_boot_enc + :end-before: ------ + +启用 flash 加密后,在下次启动时输出将显示已启用 flash 加密,样例输出如下: + +.. include:: {IDF_TARGET_PATH_NAME}_log.inc + :start-after: already_en_enc + :end-before: ------ + +在此阶段,如果用户需要更新或重新烧录二进制文件,请参考 :ref:`encrypt-partitions`。 - idf.py encrypted-flash monitor .. _pregenerated-flash-encryption-key: -使用主机生成的 Flash 加密密钥 -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +使用主机生成的密钥 +"""""""""""""""""""""""" -可在主机中预生成 Flash 加密密钥,并将其烧录到 {IDF_TARGET_NAME} 的 eFuse 密钥块中。这样,无需明文 Flash 更新便可以在主机上预加密数据并将其烧录到 {IDF_TARGET_NAME} 中。该功能允许在 :ref:`flash_enc_development_mode` 和 :ref:`flash_enc_release_mode` modes 两模式下加密烧录。 +可在主机中预生成 flash 加密密钥,并将其烧录到 eFuse 密钥块中。这样,无需明文 flash 更新便可以在主机上预加密数据并将其烧录。该功能可在 :ref:`flash-enc-development-mode` 和 :ref:`flash-enc-release-mode` 两模式下使用。如果没有预生成的密钥,数据将以明文形式烧录,然后 {IDF_TARGET_NAME} 对数据进行就地加密。 -- 确保您的 {IDF_TARGET_NAME} 设备有 :ref:`flash-encryption-efuse` 中所示 Flash 加密 eFuse 的默认设置。 +.. note:: -- 使用 espsecure.py 随机生成一个密钥:: + 不建议在生产中使用该方法,除非为每个设备都单独生成一个密钥。 - espsecure.py generate_flash_encryption_key my_flash_encryption_key.bin +使用主机生成的密钥需完成以下步骤: -- 将该密钥烧录到设备上(一次性)。 **该步骤须在第一次加密启动前完成**,否则 {IDF_TARGET_NAME} 将随机生成一个软件无权限访问或修改的密钥:: +1. 确保您的 {IDF_TARGET_NAME} 设备有 :ref:`flash-encryption-efuse` 中所示的 flash 加密 eFuse 的默认设置。 + + 请参考如何检查 :ref:`flash-encryption-status`。 + +2. 通过运行以下命令生成一个随机密钥: + +.. only:: esp32s2 + + 如果 :ref:`生成的 AES-XTS 密钥大小 ` 是 AES-256(512 位密钥),则需要使用 `XTS_AES_256_KEY_1` 和 `XTS_AES_256_KEY_2`。espsecure 不支持 512 位密钥,但可以变通一下。 + + .. code-block:: bash + + espsecure.py generate_flash_encryption_key my_flash_encryption_key1.bin + + espsecure.py generate_flash_encryption_key my_flash_encryption_key2.bin + + # To use encrypt_flash_data with XTS_AES_256 requires combining the two binary files to one 64 byte file + cat my_flash_encryption_key1.bin my_flash_encryption_key2.bin > my_flash_encryption_key.bin + + 如果 :ref:`生成的 AES-XTS 密钥大小 ` 是 AES-128(256 位密钥),则需要使用 `XTS_AES_128_KEY`。 + + .. code-block:: bash + + espsecure.py generate_flash_encryption_key my_flash_encryption_key.bin + + +.. only:: not SOC_FLASH_ENCRYPTION_XTS_AES_256 + + .. code-block:: bash + + espsecure.py generate_flash_encryption_key my_flash_encryption_key.bin + +3. **在第一次加密启动前**,使用以下命令将该密钥烧录到设备上,这个操作只能执行 **一次**。 + +.. only:: not SOC_FLASH_ENCRYPTION_XTS_AES + + .. code-block:: bash espefuse.py --port PORT burn_key flash_encryption my_flash_encryption_key.bin -- 在第二阶段引导加载程序中启用 Flash 加密支持。请前往 :ref:`project-configuration-menu`,选择 “Security Features”。 +.. only:: SOC_FLASH_ENCRYPTION_XTS_AES_256 -- 选择 :ref:`Enable flash encryption on boot `。 + .. code-block:: bash -- 模式默认设置为 **开发模式**。 + espefuse.py --port PORT burn_key BLOCK my_flash_encryption_key.bin KEYPURPOSE + + 其中 ``BLOCK`` 是 ``BLOCK_KEY0`` 和 ``BLOCK_KEY5`` 之间的空闲密钥区。而 ``KEYPURPOSE`` 是 ``AES_256_KEY_1``、``XTS_AES_256_KEY_2`` 或 ``XTS_AES_128_KEY``。关于密钥目的的描述清参考 `{IDF_TARGET_NAME} 技术参考手册 <{IDF_TARGET_TRM_CN_URL}>`_。 -- 在引导加载程序 config 下选择适当详细程度的日志。 + AES-128(256 位密钥)- ``XTS_AES_128_KEY``: -.. only:: esp32 + .. code-block:: bash - - 启用 Flash 加密将增大引导加载程序,因而可能需要更新分区表偏移。可参见 See :ref:`bootloader-size`。 + espefuse.py --port PORT burn_key BLOCK my_flash_encryption_key.bin XTS_AES_128_KEY -- 保存配置并退出。 + AES-256(512 位密钥)- ``XTS_AES_256_KEY_1`` 和 ``XTS_AES_256_KEY_2``。espefuse.py 和 espsecure.py 中还没有完全支持。需要进行如下操作: -构建并烧录完整的映像包括:引导加载程序、分区表和 app。这些分区最初以未加密形式写入 Flash + .. code-block:: bash - :: + espefuse.py --port PORT burn_key BLOCK my_flash_encryption_key1.bin XTS_AES_256_KEY_1 - idf.py flash monitor + espefuse.py --port PORT burn_key BLOCK+1 my_flash_encryption_key2.bin XTS_AES_256_KEY_2 -下次启动时,第二阶段引导加载程序将加密 Flash 的 app 分区并重置该分区。现在,示例应用程序将在运行时解密并执行命令。 +.. only:: SOC_FLASH_ENCRYPTION_XTS_AES and not SOC_FLASH_ENCRYPTION_XTS_AES_256 -在此阶段,如果用户希望将新的明文应用程序映像更新到 Flash,应调用以下命令 + .. code-block:: bash - :: + espefuse.py --port PORT burn_key BLOCK my_flash_encryption_key.bin XTS_AES_128_KEY - idf.py encrypted-app-flash monitor + 其中 ``BLOCK`` 是 ``BLOCK_KEY0`` 和 ``BLOCK_KEY5`` 之间的一个空闲密钥区。 -如何以加密格式重新编程所有分区,可参考 :ref:`encrypt_partitions`。 +如果未烧录密钥并在启用 flash 加密后启动设备,{IDF_TARGET_NAME} 将生成随机密钥,该密钥软件无法访问或修改。 -.. _flash_enc_release_mode: +4. 在 :ref:`项目配置菜单 ` 中进行如下设置: -释放模式 + - :ref:`启动时启用 flash 加密功能 ` + - :ref:`选择加密模式 ` (默认为 **开发模式**) + - :ref:`选择适当详细程度的引导加载程序日志 ` + - 保存配置并退出 + +启用 flash 加密将增大引导加载程序,因而可能需更新分区表偏移量。请参考 :ref:`引导加载程序大小 `。 + +5. 运行以下命令来构建并烧录完整的镜像: + + .. code-block:: bash + + idf.py flash monitor + + .. note:: + + 这个命令不包括任何应该被写入 flash 分区的用户文件。请在运行此命令前手动写入这些文件,否则在写入前应单独对这些文件进行加密。 + + 该命令将向 flash 写入未加密的镜像:固件引导加载程序、分区表和应用程序。烧录完成后,{IDF_TARGET_NAME} 将重置。在下一次启动时,固件引导加载程序会加密:固件引导加载程序、应用程序分区和标记为 ``加密`` 的分区,然后复位。就地加密可能需要时间,对于大的分区来说可能耗时一分钟。之后,应用程序在运行时被解密并执行。 + +如果使用开发模式,那么更新和重新烧录二进制文件最简单的方法是 :ref:`encrypt-partitions`。 + +如果使用发布模式,那么可以在主机上预先加密二进制文件,然后将其作为密文烧录。具体请参考 :ref:`manual-encryption`。 + + +.. _encrypt-partitions: + +重新烧录更新后的分区 +"""""""""""""""""""""""""""""" + +如果用户以明文方式更新了应用程序代码并需要重新烧录,则需要在烧录前对其进行加密。请运行以下命令一次完成应用程序的加密与烧录: + +.. code-block:: bash + + idf.py encrypted-app-flash monitor + +如果所有分区都需要以加密形式更新,请运行: + +.. code-block:: bash + + idf.py encrypted-flash monitor + + +.. _flash-enc-release-mode: + +发布模式 ^^^^^^^^^^ -在释放模式下,UART 引导加载程序无法执行 Flash 加密操作,**只能** 使用 OTA 方案下载新的明文映像,该方案将在写入 Flash 前加密明文映像。 +在发布模式下,UART 引导加载程序无法执行 flash 加密操作,**只能** 使用 OTA 方案下载新的明文镜像,该方案将在写入 flash 前加密明文镜像。 -- 确保您的 {IDF_TARGET_NAME} 设备有 :ref:`flash-encryption-efuse` 中所示 Flash 加密 eFuse 的默认设置。 +使用该模式需要执行以下步骤: -- 在第二阶段引导加载程序中启用 Flash 加密支持。请前往 :ref:`project-configuration-menu`,选择 “Security Features”。 +1. 确保您的 {IDF_TARGET_NAME} 设备有 :ref:`flash-encryption-efuse` 中所示的 flash 加密 eFuse 的默认设置。 -- 选择 :ref:`Enable flash encryption on boot `。 + 请参考如何检查 :ref:`flash-encryption-status`。 -- 选择 **释放模式**,模式默认设置为 **开发模式**。请注意,**一旦选择了释放模式,``download_dis_encrypt`` 和 ``download_dis_decrypt`` eFuse 位将被编程为禁止 UART 引导加载程序访问 Flash 的内容**。 +2. 在 :ref:`项目配置菜单 `,执行以下操作: -- 在引导加载程序 config 下选择适当详细程度的日志。 + .. list:: -.. only:: esp32 + - :ref:`启动时使能 flash 加密 ` + :esp32: - :ref:`选择发布模式 ` (注意一旦选择了发布模式,``DISABLE_DL_ENCRYPT`` 和 ``DISABLE_DL_DECRYPT`` eFuse 位将被编程为在 ROM 下载模式下禁用 flash 加密硬件) + :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:`选择适当详细程度的引导加载程序日志 ` + - 保存配置并退出 - - 启用 Flash 加密将增大引导加载程序,因而可能需要更新分区表偏移。可参见 See :ref:`bootloader-size`。 +启用 flash 加密将增大引导加载程序,因而可能需更新分区表偏移量。请参考 :ref:`引导加载程序大小 `。 -- 保存配置并退出。 +3. 运行以下命令来构建并烧录完整的镜像: -构建并烧录完整的映像包括:引导加载程序、分区表和 app。这些分区最初以未加密形式写入 Flash + .. code-block:: bash - :: + idf.py flash monitor - idf.py flash monitor -下次启动时,第二阶段引导加载程序将加密 Flash app 分区并重置该分区。现在,示例应用程序应正确执行命令。 + .. note:: -一旦在释放模式下启用 Flash 加密,引导加载程序将写保护 ``FLASH_CRYPT_CNT`` eFuse。 + 这个命令不包括任何应该被写入 flash 分区的用户文件。请在运行此命令前手动写入这些文件,否则在写入前应单独对这些文件进行加密。 + + 该命令将向 flash 写入未加密的镜像:固件引导加载程序、分区表和应用程序。烧录完成后,{IDF_TARGET_NAME} 将重置。在下一次启动时,固件引导加载程序会加密:固件引导加载程序、应用程序分区和标记为 ``加密`` 的分区,然后复位。就地加密可能需要时间,对于大的分区来说可能耗时一分钟。之后,应用程序在运行时被解密并执行。 -应使用 OTA 方案对字段中的明文进行后续更新。详情可参见 :doc:`OTA <../api-reference/system/ota>`。 +一旦在发布模式下启用 flash 加密,引导加载程序将写保护 ``{IDF_TARGET_CRYPT_CNT}`` eFuse。 + +请使用 :ref:`OTA 方案 ` 对字段中的明文进行后续更新。 + +.. note:: + + 如果用户已经预先生成了 flash 加密密钥并存储了一个副本,并且 UART 下载模式没有通过 :ref:`CONFIG_SECURE_UART_ROM_DL_MODE` {IDF_TARGET_ESP32_V3_ONLY} 永久禁用,那么可以通过使用 ``{IDF_TARGET_ENCRYPT_COMMAND}`` 预加密文件,从而在在本地更新 flash,然后烧录密文。请参考 :ref:`manual-encryption`。 + +.. _flash-encrypt-best-practices: + +最佳实践 +^^^^^^^^^^^^^^ + +在生产中使用 flash 加密时: + +.. list:: + + - 不要在多个设备之间重复使用同一个 flash 加密密钥,这样攻击者就无法从一台设备上复制加密数据后再将其转移到第二台设备上。 + :esp32: - 在使用 ESP32 V3 时,如果生产设备不需要 UART ROM 下载模式,那么则该禁用该模式以增加设备安全性。这可以通过在应用程序启动时调用 :cpp:func:`esp_efuse_disable_rom_download_mode` 来实现。或者,可将项目 :ref:`CONFIG_ESP32_REV_MIN` 级别配置为 3(仅针对 ESP32 V3),然后选择 :ref:`CONFIG_SECURE_UART_ROM_DL_MODE` 为“永久性的禁用 ROM 下载模式(推荐)”。在早期的 ESP32 版本上无法禁用 ROM 下载模式。 + :not esp32: - 如果不需要 UART ROM 下载模式,则应完全禁用该模式,或者永久设置为“安全下载模式”。安全下载模式永久性地将可用的命令限制在基本的 flash 只读和只写。默认在发布模式下第一次启动时设置为安全下载模式。要完全禁用下载模式,请选择 :ref:`CONFIG_SECURE_UART_ROM_DL_MODE` 为“永久禁用 ROM 下载模式(推荐)”或在运行时调用 :cpp:func:`esp_efuse_disable_rom_download_mode`。 + - 启用 :doc:`安全启动` 作为额外的保护层,防止攻击者在启动前有选择地破坏 flash 中某部分。 可能出现的错误 -^^^^^^^^^^^^^^^^ +----------------- -启用 Flash 加密后,如果 ``FLASH_CRYPT_CNT`` eFuse 值中有奇数位,则所有(标有加密标志的)分区都应包含加密密文。以下为 {IDF_TARGET_NAME} 加载明文数据会产生的三种典型错误情况: +一旦启用 flash 加密,``{IDF_TARGET_CRYPT_CNT}`` 的 eFuse 值将设置为奇数位。这意味着所有标有加密标志的分区都会包含加密的密本。如果 {IDF_TARGET_NAME} 错误地加载了明文数据,则会出现以下三种典型的错误情况: -1. 如果通过明文引导加载程序映像重新更新了引导加载程序分区,则 ROM 加载器将无法加载 引导加载程序,并会显示以下错误类型: - - :: - - rst:0x3 (SW_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) - flash read err, 1000 - ets_main.c 371 - ets Jun 8 2016 00:22:57 - - rst:0x7 (TG0WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) - flash read err, 1000 - ets_main.c 371 - ets Jun 8 2016 00:22:57 - - rst:0x7 (TG0WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) - flash read err, 1000 - ets_main.c 371 - ets Jun 8 2016 00:22:57 - - rst:0x7 (TG0WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) - flash read err, 1000 - ets_main.c 371 - ets Jun 8 2016 00:22:57 - - rst:0x7 (TG0WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) - flash read err, 1000 - ets_main.c 371 - ets Jun 8 2016 00:22:57 - -2. 如果引导加载程序已加密,但使用明文分区表映像重新更新了分区表,则引导加载程序将无法读取分区表,并会显示以下错误类型: - - :: - - rst:0x3 (SW_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) - configsip: 0, SPIWP:0xee - clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 - mode:DIO, clock div:2 - load:0x3fff0018,len:4 - load:0x3fff001c,len:10464 - ho 0 tail 12 room 4 - load:0x40078000,len:19168 - load:0x40080400,len:6664 - entry 0x40080764 - I (60) boot: ESP-IDF v4.0-dev-763-g2c55fae6c-dirty 2nd stage bootloader - I (60) boot: compile time 19:15:54 - I (62) boot: Enabling RNG early entropy source... - I (67) boot: SPI Speed : 40MHz - I (72) boot: SPI Mode : DIO - I (76) boot: SPI Flash Size : 4MB - E (80) flash_parts: partition 0 invalid magic number 0x94f6 - E (86) boot: Failed to verify partition table - E (91) boot: load partition table error! - -3. 如果引导加载程序和分区表已加密,但使用明文应用程序映像重新更新了应用程序,则引导加载程序将无法加载新的应用程序,并会显示以下错误类型: - - :: - - rst:0x3 (SW_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) - configsip: 0, SPIWP:0xee - clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 - mode:DIO, clock div:2 - load:0x3fff0018,len:4 - load:0x3fff001c,len:8452 - load:0x40078000,len:13616 - load:0x40080400,len:6664 - entry 0x40080764 - I (56) boot: ESP-IDF v4.0-dev-850-gc4447462d-dirty 2nd stage bootloader - I (56) boot: compile time 15:37:14 - I (58) boot: Enabling RNG early entropy source... - I (64) boot: SPI Speed : 40MHz - I (68) boot: SPI Mode : DIO - I (72) boot: SPI Flash Size : 4MB - I (76) boot: Partition Table: - I (79) boot: ## Label Usage Type ST Offset Length - I (87) boot: 0 nvs WiFi data 01 02 0000a000 00006000 - I (94) boot: 1 phy_init RF data 01 01 00010000 00001000 - I (102) boot: 2 factory factory app 00 00 00020000 00100000 - I (109) boot: End of partition table - E (113) esp_image: image at 0x20000 has invalid magic byte - W (120) esp_image: image at 0x20000 has invalid SPI mode 108 - W (126) esp_image: image at 0x20000 has invalid SPI size 11 - E (132) boot: Factory app partition is not bootable - E (138) boot: No bootable app partitions in the partition table - -Flash 加密的要点 -------------------- - -- 使用 AES-256 加密 Flash 的内容。Flash 加密密钥存储于 eFuse 内部的芯片中,并(默认)受保护防止软件访问。 - -- `flash 加密算法` 采用的是 AES-256,其中密钥随着 Flash 的每个 32 字节块的偏移地址“调整”。这意味着,每个 32 字节块(2 个连续的 16 字节 AES 块)使用从 Flash 加密密钥中产生的一个特殊密钥进行加密。 - -- 通过 {IDF_TARGET_NAME} 的 Flash 缓存映射功能,Flash 可支持透明访问——读取任何映射到地址空间的 Flash 区域时,都将透明解密该区域。 - - 为便于访问,某些数据分区最好保持未加密状态,或者也可使用对已加密数据无效的 Flash 友好型更新算法。由于 NVS 库无法与 Flash 加密直接兼容,因此无法加密非易失性存储器的 NVS 分区。详情可参见 :ref:`NVS 加密 `。 - -- 如果可能已启用 Flash 加密,则编写 :ref:`使用加密 flash ` 的代码时,编程人员须小心谨慎。 - -- 如果已启用安全启动,则重新烧录加密设备的引导加载程序则需要“可重新烧录”的安全启动摘要(可参见 :ref:`flash-encryption-and-secure-boot`)。 +1. 如果通过 **明文固件引导加载程序镜像** 重新烧录了引导加载程序分区,则 ROM 加载器将无法加载固件引导加载程序,并会显示以下错误类型: .. only:: esp32 - .. note:: 同时启用安全启动和 Flash 加密后,引导加载程序 app 二进制文件 ``bootloader.bin`` 可能会过大。参见 :ref:`bootloader-size`。 + .. code-block:: bash -.. important:: - 在首次启动加密过程中,请勿中断 {IDF_TARGET_NAME} 的电源。如果电源中断,Flash 的内容将受到破坏,并需要重新烧录未加密数据。而这类重新烧录将不计入烧录限制次数。 + rst:0x3 (SW_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) + flash read err, 1000 + ets_main.c 371 + ets Jun 8 2016 00:22:57 -.. _using-encrypted-flash: + rst:0x7 (TG0WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) + flash read err, 1000 + ets_main.c 371 + ets Jun 8 2016 00:22:57 -使用加密的 Flash -------------------- + rst:0x7 (TG0WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) + flash read err, 1000 + ets_main.c 371 + ets Jun 8 2016 00:22:57 -{IDF_TARGET_NAME} app 代码可通过调用函数 :cpp:func:`esp_flash_encryption_enabled` 来确认当前是否已启用 Flash 加密。同时,设备可通过调用函数 :cpp:func:`esp_get_flash_encryption_mode` 来识别使用的 Flash 加密模式。 + rst:0x7 (TG0WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) + flash read err, 1000 + ets_main.c 371 + ets Jun 8 2016 00:22:57 -启用 Flash 加密后,使用代码访问 Flash 内容时需加注意。 + rst:0x7 (TG0WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) + flash read err, 1000 + ets_main.c 371 + ets Jun 8 2016 00:22:57 -Flash 加密的范围 -^^^^^^^^^^^^^^^^^^ +.. only:: not esp32 -只要 ``FLASH_CRYPT_CNT`` eFuse 设置为奇数位的值,所有通过 MMU 的 Flash 缓存访问的 Flash 内容都将被透明解密。包括: + .. code-block:: bash + + rst:0x3 (SW_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) + invalid header: 0xb414f76b + invalid header: 0xb414f76b + invalid header: 0xb414f76b + invalid header: 0xb414f76b + invalid header: 0xb414f76b + invalid header: 0xb414f76b + invalid header: 0xb414f76b + + .. note:: + + 不同应用程序中无效头文件的值不同。 + +.. note:: + + 如果 flash 内容被擦除或损坏,也会出现这个错误。 + +2. 如果固件的引导加载程序已加密,但通过 **明文分区表镜像** 重新烧录了分区表,引导加载程序将无法读取分区表,从而出现以下错误: + + .. code-block:: bash + + rst:0x3 (SW_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) + configsip: 0, SPIWP:0xee + clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 + mode:DIO, clock div:2 + load:0x3fff0018,len:4 + load:0x3fff001c,len:10464 + ho 0 tail 12 room 4 + load:0x40078000,len:19168 + load:0x40080400,len:6664 + entry 0x40080764 + I (60) boot: ESP-IDF v4.0-dev-763-g2c55fae6c-dirty 2nd stage bootloader + I (60) boot: compile time 19:15:54 + I (62) boot: Enabling RNG early entropy source... + I (67) boot: SPI Speed : 40MHz + I (72) boot: SPI Mode : DIO + I (76) boot: SPI Flash Size : 4MB + E (80) flash_parts: partition 0 invalid magic number 0x94f6 + E (86) boot: Failed to verify partition table + E (91) boot: load partition table error! + +3. 如果引导加载程序和分区表已加密,但使用 **明文应用程序镜像** 重新烧录了应用程序,引导加载程序将无法加载应用程序,从而出现以下错误: + + .. code-block:: bash + + rst:0x3 (SW_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) + configsip: 0, SPIWP:0xee + clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 + mode:DIO, clock div:2 + load:0x3fff0018,len:4 + load:0x3fff001c,len:8452 + load:0x40078000,len:13616 + load:0x40080400,len:6664 + entry 0x40080764 + I (56) boot: ESP-IDF v4.0-dev-850-gc4447462d-dirty 2nd stage bootloader + I (56) boot: compile time 15:37:14 + I (58) boot: Enabling RNG early entropy source... + I (64) boot: SPI Speed : 40MHz + I (68) boot: SPI Mode : DIO + I (72) boot: SPI Flash Size : 4MB + I (76) boot: Partition Table: + I (79) boot: ## Label Usage Type ST Offset Length + I (87) boot: 0 nvs WiFi data 01 02 0000a000 00006000 + I (94) boot: 1 phy_init RF data 01 01 00010000 00001000 + I (102) boot: 2 factory factory app 00 00 00020000 00100000 + I (109) boot: End of partition table + E (113) esp_image: image at 0x20000 has invalid magic byte + W (120) esp_image: image at 0x20000 has invalid SPI mode 108 + W (126) esp_image: image at 0x20000 has invalid SPI size 11 + E (132) boot: Factory app partition is not bootable + E (138) boot: No bootable app partitions in the partition table + + +.. _flash-encryption-status: + +{IDF_TARGET_NAME} flash 加密状态 +----------------------------------------- + +1. 确保您的 {IDF_TARGET_NAME} 设备有 :ref:`flash-encryption-efuse` 中所示的 flash 加密 eFuse 的默认设置。 + +要检查您的 {IDF_TARGET_NAME} 设备上是否启用了 flash 加密,请执行以下操作之一: + +- 将应用示例 :example:`security/flash_encryption` 烧录到您的设备上。此应用程序会打印 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 值,以及是否启用了 flash 加密。 + +- :doc:`查询设备所连接的串口名称 <../get-started/establish-serial-connection>`,在以下命令中将 ``PORT`` 替换为串口名称后运行: + + .. code-block:: bash + + espefuse.py -p PORT summary + + +.. _reading-writing-content: + +在加密的 flash 中读写数据 +------------------------------------- + +{IDF_TARGET_NAME} 应用程序代码可以通过调用函数 :cpp:func:`esp_flash_encryption_enabled` 来检查当前是否启用了 flash 加密。此外,设备可以通过调用函数 :cpp:func:`esp_get_flash_encryption_mode` 来识别 flash 加密模式。 + +一旦启用 flash 加密,使用代码访问 flash 内容时要更加小心。 + + +Flash 加密范围 +^^^^^^^^^^^^^^^^^^^^^^^^^ + +当 ``{IDF_TARGET_CRYPT_CNT}`` eFuse 设置为奇数位的值,所有通过 MMU 的 flash 缓存访问的 flash 内容都将被透明解密。包括: - Flash 中可执行的应用程序代码 (IROM)。 -- 所有存储于 Flash 中的只读数据 (DROM)。 +- 所有存储于 flash 中的只读数据 (DROM)。 - 通过函数 :cpp:func:`spi_flash_mmap` 访问的任意数据。 -- ROM 引导加载程序读取的软件引导加载程序映像。 +- ROM 引导加载程序读取的固件引导加载程序镜像。 .. important:: - MMU Flash 缓存将无条件解密所有数据。Flash 中未加密存储的数据将通过 Flash 缓存“被透明解密”,并在软件中存储为随机垃圾数据。 -读取加密的 Flash + MMU flash 缓存将无条件解密所有数据。Flash 中未加密存储的数据将通过 flash 缓存“被透明解密”,并在软件中存储为随机垃圾数据。 + + +读取加密的 flash ^^^^^^^^^^^^^^^^^^ -如在不使用 Flash 缓存 MMU 映射的情况下读取数据,推荐使用分区读取函数 :cpp:func:`esp_partition_read`。使用该函数时,只有从加密分区读取的数据才会被解密。其他分区的数据将以未加密形式读取。这样,软件便能同样访问加密和未加密的 Flash。 +如果需要在不使用 flash 缓存 MMU 映射的情况下读取数据,推荐使用分区读取函数 :cpp:func:`esp_partition_read`。该函数只会解密从加密分区读取的数据。从未加密分区读取的数据不会被解密。这样,软件便能以相同的方式访问加密和未加密的 flash。 -通过其他 SPI 读取 API 读取的数据均未解密: +也可以使用以下 SPI flash API 函数: -- 通过函数 :cpp:func:`spi_flash_read` 读取的数据均未解密。 -- 通过 ROM 函数 :cpp:func:`SPIRead` 读取的数据均未解密(esp-idf app 不支持该函数)。 -- 使用非易失性存储器 (NVS) API 存储的数据始终从 Flash 加密的角度进行存储和读取解密。如有需要,则由库提供加密功能。详情可参见 :ref:`NVS 加密 `。 +- 通过函数 :cpp:func:`esp_flash_read` 读取不会被解密的原(加密)数据。 +- 通过函数 :cpp:func:`esp_flash_read_encrypted` 读取和解密数据。 -写入加密的 Flash +ROM 函数 :cpp:func:`SPIRead` 可以在不解密的情况下读取数据,但是在 esp-idf 应用程序中不支持该函数。 + +使用非易失性存储器 (NVS) API 存储的数据始终从 flash 加密的角度进行存储和读取解密。如有需要,则由库提供加密功能。详情可参考 :ref:`NVS 加密 `。 + + +写入加密的 flash ^^^^^^^^^^^^^^^^^^ -在可能的情况下,推荐使用分区写入函数 ``esp_partition_write``。使用该函数时,只有向加密分区写入的数据才会被加密。而写入其他分区的数据均未加密。这样,软件便可同样访问加密和未加密的 Flash。 +推荐使用分区写入函数 :cpp:func:`esp_partition_write`。此函数只会在将数据写入加密分区时加密数据,而写入未加密分区的数据不会被加密。通过这种方式,软件可以以相同的方式访问加密和非加密 flash。 -当 write_encrypted 参数设置为“是”时,函数 ``esp_spi_flash_write`` 将写入数据。否则,数据将以未加密形式写入。 +也可以使用函数 :cpp:func:`esp_flash_write_encrypted` 预加密和写入数据。 -ROM 函数 ``esp_rom_spiflash_write_encrypted`` 将在 Flash 中写入加密数据,而 ROM 函数 ``SPIWrite`` 将在 Flash 中写入未加密数据(esp-idf app 不支持上述函数)。 +此外,esp-idf 应用程序中存在但不支持以下 ROM 函数: + +- ``esp_rom_spiflash_write_encrypted`` 预加密并将数据写入 flash +- ``SPIWrite`` 将未加密的数据写入 flash + +由于数据是按块加密的,加密数据最小的写入大小为 16 字节,对齐也是 16 字节。 -由于数据均采用块加密方式,加密数据最小的写入大小为 16 字节(16字节对齐)。 .. _updating-encrypted-flash: -更新加密的 Flash +更新加密的 flash ------------------- .. _updating-encrypted-flash-ota: @@ -536,83 +651,122 @@ ROM 函数 ``esp_rom_spiflash_write_encrypted`` 将在 Flash 中写入加密数 OTA 更新 ^^^^^^^^^^ -只要使用了函数 ``esp_partition_write``,则加密分区的 OTA 更新将自动以加密形式写入。 +如果使用函数 :cpp:func:`esp_partition_write`,对加密分区的 OTA 更新将自动以加密形式写入。 + +在为已加密设备的 OTA 更新构建应用程序镜像之前,启用项目配置菜单中的 :ref:`启动时使能 flash 加密 ` 选项。 + +请参考 :doc:`OTA <../api-reference/system/ota>` 获取更多关于 ESP-IDF OTA 更新的信息。 + .. _updating-encrypted-flash-serial: -关闭 Flash 加密 +通过串口更新加密 flash +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +通过串行引导加载程序烧录加密设备,需要串行引导加载程序下载接口没有通过 eFuse 被永久禁用。 + +在开发模式下,推荐的方法是 :ref:`encrypt-partitions`。 + +在发布模式下,如果主机上有存储在 eFuse 中的相同密钥的副本,那么就可以在主机上对文件进行预加密,然后进行烧录,具体请参考 :ref:`manual-encryption`。 + +关闭 flash 加密 ----------------- -若因某些原因意外启用了 Flash 加密,则接下来烧录明文数据时将使 {IDF_TARGET_NAME} 软砖(设备不断重启,并报错 ``flash read err, 1000``)。 - -可通过写入 ``FLASH_CRYPT_CNT`` eFuse 再次关闭 Flash 加密(仅适用于开发模式下): - -- 首先,前往 :ref:`project-configuration-menu`,在“安全性能”目录下关闭 :ref:`启用 Flash 加密启动 `。 -- 退出 menuconfig 并保存最新配置。 -- 再次运行 ``idf.py menuconfig`` 并复核是否确认已关闭该选项!*如果该选项仍处于已启用状态,则引导加载程序会在启动后立即重新启用加密*。 -- 在未启用 Flash 加密的状态下,运行 ``idf.py flash`` 构建并烧录新的引导加载程序与 app。 -- 运行 ``espefuse.py`` (``components/esptool_py/esptool`` 中)以关闭 FLASH_CRYPT_CNT:: - - espefuse.py burn_efuse FLASH_CRYPT_CNT - -重置 {IDF_TARGET_NAME},Flash 加密应处于关闭状态,引导加载程序将正常启动。 - -.. _flash-encryption-limitations: - -Flash 加密的局限性 --------------------- - -Flash 加密可防止从加密 Flash 中读取明文,从而保护固件防止未经授权的读取与修改。了解 Flash 加密系统的局限之处亦十分重要: - -- Flash 加密功能与密钥同样稳固。因而,推荐您首次启动设备时在设备上生成密钥(默认行为)。如果在设备外生成密钥,请确保遵循正确的后续步骤。 - -- 并非所有数据都是加密存储。因而在 Flash 上存储数据时,请检查您使用的存储方式(库、API等)是否支持 Flash 加密。 - -- Flash 加密无法防止攻击者获取 Flash 的高层次布局信息。这是因为同一个 AES 密钥要用于每对相邻的 16 字节 AES 块。当这些相邻的 16 字节块中包含相同内容时(如空白或填充区域),这些字节块将加密以产生匹配的加密块对。这可能使得攻击者可在加密设备间进行高层次对比(例如,确认两设备是否可能在运行相同的固件版本)。 - -- 出于相同原因,攻击者始终可获知一对相邻的 16 字节块(32 字节对齐)何时包含相同内容。因此,在 Flash 上存储敏感数据时应牢记这点,并进行相关设置避免该情况发生(可使用计数器字节或每 16 字节设置不同的值即可)。 +如果意外启用了 flash 加密,则明文数据的 flash 会使 {IDF_TARGET_NAME} 无法正常启动。设备将不断重启,并报错 ``flash read err, 1000`` 或 ``invalid header: 0xXXXXXX``。 .. only:: esp32 - - 单独使用 Flash 加密可能无法防止攻击者修改本设备的固件。为防止设备上运行未经授权的固件,可搭配 Flash 加密使用 :doc:`安全启动 `。 + 对于开发模式下的 flash 加密,可以通过烧录 ``{IDF_TARGET_CRYPT_CNT}`` efuse 来关闭加密。每个芯片仅有 3 次机会,请执行以下步骤: + +.. only:: not esp32 + + 对于开发模式下的 flash 加密,可以通过烧录 ``{IDF_TARGET_CRYPT_CNT}`` efuse 来关闭加密。每个芯片仅有 1 次机会,请执行以下步骤: + +#. 在 :ref:`项目配置菜单 ` 中,禁用 :ref:`启动时使能 flash 加密 ` 选项,然后保存并退出。 +#. 再次打开项目配置菜单,再次检查你是否已经禁用了该选项,如果这个选项仍被启用,引导加载程序在启动时将立即重新启用加密功能。 +#. 在禁用 flash 加密后,通过运行 ``idf.py flash`` 来构建和烧录新的引导加载程序和应用程序。 +#. 使用 ``espefuse.py`` (在 ``components/esptool_py/esptool`` 中)以关闭 ``{IDF_TARGET_CRYPT_CNT}``,运行: + + .. code-block:: bash + + espefuse.py burn_efuse {IDF_TARGET_CRYPT_CNT} + +重置 {IDF_TARGET_NAME},flash 加密应处于关闭状态,引导加载程序将正常启动。 + + +Flash 加密的要点 +--------------------------------- + +.. list:: + + :esp32: - 使用 AES-256 加密 flash。Flash 加密密钥存储于芯片内部的 ``flash_encryption`` eFuse 中,并(默认)受保护,防止软件访问。 + + :esp32: - Flash 加密算法采用的是 AES-256,其中密钥随着 flash 的每个 32 字节块的偏移地址“调整”。这意味着,每个 32 字节块(2 个连续的 16 字节 AES 块)使用从 flash 加密密钥中产生的一个特殊密钥进行加密。 + + :esp32s2 or esp32s3: - 使用 XTS-AES-128 或 XTS-AES-256 加密 flash。Flash 加密密钥分别为 256 位和 512 位,存储于芯片内部一个或两个 ``BLOCK_KEYN`` eFuse 中,并(默认)受保护,防止软件访问。 + + :esp32c3: - 使用 XTS-AES-128 加密 flash。 Flash 加密密钥为 256 位,存储于芯片内部的 ``BLOCK_KEYN`` eFuse 中,并(默认)受保护,防止软件访问。 + + - 通过 {IDF_TARGET_NAME} 的 flash 缓存映射功能,flash 可支持透明访问——任何映射到地址空间的 flash 区域在读取时都将被透明地解密。 + + 为便于访问,某些数据分区最好保持未加密状态,或者也可使用对已加密数据无效的 flash 友好型更新算法。由于 NVS 库无法与 flash 加密直接兼容,因此无法加密非易失性存储器的 NVS 分区。详情可参见 :ref:`NVS 加密 `。 + + - 如果以后可能需要启用 flash 加密,则编程人员在编写 :ref:`使用加密 flash ` 代码时需小心谨慎。 + + - 如果已启用安全启动,重新烧录加密设备的引导加载程序则需要“可重新烧录”的安全启动摘要(可参考 :ref:`flash-encryption-and-secure-boot`)。 + + 启用 flash 加密将增大引导加载程序,因此可能需更新分区表偏移量。请参考 :ref:`引导加载程序大小 `。 + + .. important:: + + 在首次启动加密过程中,请勿切断 {IDF_TARGET_NAME} 的电源。如果电源被切断,flash 的内容将受到破坏,并需要重新烧录未加密数据。而这类重新烧录将不计入烧录限制次数。 + + +.. _flash-encryption-limitations: + +Flash 加密的局限性 +-------------------- + +flash 加密可以保护固件,防止未经授权的读取与修改。了解 flash 加密系统的局限之处亦十分重要: + +.. list:: + + - Flash 加密功能与密钥同样稳固。因而,推荐您首次启动设备时在设备上生成密钥(默认行为)。如果在设备外生成密钥,请确保遵循正确的后续步骤,不要在所有生产设备之间使用相同的密钥。 + - 并非所有数据都是加密存储。因而在 flash 上存储数据时,请检查您使用的存储方式(库、API 等)是否支持 flash 加密。 + - Flash 加密无法防止攻击者获取 flash 的高层次布局信息。这是因为每对相邻的 16 字节 AES 块都使用相邻的 AES 密钥。当这些相邻的 16 字节块中包含相同内容时(如空白或填充区域),这些字节块将加密以产生匹配的加密块对。这让攻击者可在加密设备间进行高层次对比(例如,确认两设备是否可能运行相同的固件版本)。 + :esp32: - 出于相同原因,攻击者始终可获知一对相邻的 16 字节块(32 字节对齐)何时包含相同的 16 字节序列。因此,在 flash 上存储敏感数据时应牢记这点,可进行相关设置避免该情况发生(可使用计数器字节或每 16 字节设置不同的值即可)。具体请参考 :ref:`NVS 加密 `。 + - 单独使用 flash 加密可能无法防止攻击者修改本设备的固件。为防止设备上运行未经授权的固件,可搭配 flash 加密使用 :doc:`安全启动 `。 .. _flash-encryption-and-secure-boot: Flash 加密与安全启动 ---------------------- -推荐搭配使用 Flash 加密与安全启动。但是,如果已启用安全启动,则重新烧录设备时会受到其他限制: +推荐 flash 加密与安全启动搭配使用。但是,如果已启用安全启动,则重新烧录设备时会受到其他限制: -- :ref:`updating-encrypted-flash-ota` 不受限制(如果新的 app 已使用安全启动签名密钥进行正确签名)。 +- 如果新的应用程序已使用安全启动签名密钥正确签名,则 :ref:`updating-encrypted-flash-ota` 不受限制。 .. only:: esp32 - - 只有当选择 :ref:`可再次烧录 ` 安全启动模式,且安全启动密钥已预生成并烧录至 {IDF_TARGET_NAME}(可参见 :ref:`安全启动 `),则 :ref:`明文串行 flash 更新 ` 可实现。在该配置下,``idf.py bootloader`` 将生成简化的引导加载程序和安全启动摘要文件,用于在偏移量 0x0 处进行烧录。当进行明文串行重新烧录步骤时,须在烧录其他明文数据前重新烧录此文件。 + - 只有当选择 :ref:`可再次烧录 ` 安全启动模式,且安全启动密钥已预生成并烧录至 {IDF_TARGET_NAME} 时(可参见 :ref:`安全启动 `),:ref:`明文串行 flash 更新 ` 才可能实现。在该配置下,``idf.py bootloader`` 将生成简化的引导加载程序和安全启动摘要文件,在偏移量 0x0 处进行烧录。当进行明文串行重新烧录步骤时,需在烧录其他明文数据前重新烧录此文件。 - - 假设未重新烧录引导加载程序,:ref:`使用预生成的 Flash 加密密钥重新烧录 ` 仍可实现。重新烧录引导加载程序时,需在安全启动配置中启用相同的 :ref:`可重新烧录 ` 选项。 + - 如果未重新烧录引导加载程序,则仍然可以 :ref:`使用预生成的 flash 加密密钥重新烧录 `。重新烧录引导加载程序时,需在安全启动配置中启用相同的 :ref:`可重新烧录 ` 选项。 .. _flash-encryption-without-secure-boot: -使用无安全启动的 Flash 加密 ------------------------------ - -尽管 Flash 加密与安全启动可独立使用,但强烈建议您将这二者 **搭配使用** 以确保更高的安全性。 - -.. _flash-encryption-advanced-features: - Flash 加密的高级功能 ----------------------- +-------------------------------- -以下信息可帮助您使用 Flash 加密的高级功能: +以下部分介绍了 flash 加密的高级功能。 + +.. _encrypted-partition-flag: 加密分区标志 ^^^^^^^^^^^^^ -部分分区默认为已加密。除此之外,可将任意分区标记为需加密: +部分分区默认为已加密。通过在分区的标志字段中添加 “encrypted” 标志,可在分区表描述中将其他分区标记为需要加密。在这些标记分区中的数据会和应用程序分区一样视为加密数据。 -在 :doc:`分区表 <../api-guides/partition-tables>` 文档对 CSV 文件的描述中有标志字段。 - -该字段通常保留为空白。如果在字段中写入"encrypted",则这个分区将在分区表中标记为已加密,此处写入的数据也视为加密数据(app 分区同样适用):: +.. code-block:: bash # Name, Type, SubType, Offset, Size, Flags nvs, data, nvs, 0x9000, 0x6000 @@ -620,87 +774,214 @@ Flash 加密的高级功能 factory, app, factory, 0x10000, 1M secret_data, 0x40, 0x01, 0x20000, 256K, encrypted +请参考 :doc:`分区表 <../api-guides/partition-tables>` 获取更多关于分区表描述的具体信息。 + +关于分区加密您还需要了解以下信息: + - 默认分区表都不包含任何加密数据分区。 +- 启用 flash 加密后,"app" 分区一般都视为加密分区,因此无需标记。 +- 如果未启用 flash 加密,则 "encrypted" 标记无效。 +- 将可选 ``phy`` 分区标记为 "encrypted",可以防止物理访问读取或修改 ``phy_init`` 数据。 +- ``nvs`` 分区无法标记为 "encrypted" 因为 NVS 库与 flash 加密不直接兼容。 -- "app"分区一般都视为加密分区,因此无需将其标记为已加密。 - -- 如果未启用 Flash 加密,则"encrypted"标记无效。 - -- 可将带有 ``phy_init`` 数据的可选 ``phy`` 分区标记为已加密,保护该数据防止物理访问读取或修改。 - -- ``nvs`` 分区无法标记为已加密。 .. _uart-bootloader-encryption: 启用 UART 引导加载程序加密/解密 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -默认情况下,首次启动 Flash 加密过程中将烧录 eFuse ``DISABLE_DL_ENCRYPT``、``DISABLE_DL_DECRYPT`` 和 ``DISABLE_DL_CACHE``: +在第一次启动时,flash 加密过程默认会烧录以下 eFuse: -- ``DISABLE_DL_ENCRYPT`` 在 UART 引导加载程序启动模式下运行时,终止 Flash 加密操作。 -- ``DISABLE_DL_DECRYPT`` 在 UART 引导加载程序模式下运行时,终止透明 Flash 解密(即使 FLASH_CRYPT_CNT 已设置为在正常操作中启用 Flash 透明解密)。 -- ``DISABLE_DL_CACHE`` 在 UART 引导加载程序模式下运行时终止整个 MMU flash 缓存。 +.. only:: esp32 -为了完整保存数据,可在首次启动前仅烧录部分 eFuse,并写保护其他部分(未设置值为 0)。例如:: + - ``DISABLE_DL_ENCRYPT`` 在 UART 引导加载程序启动模式下运行时,禁止 flash 加密操作。 + - ``DISABLE_DL_DECRYPT`` 在 UART 引导加载程序模式下运行时,禁止透明 flash 解密(即使 eFuse ``{IDF_TARGET_CRYPT_CNT}`` 已设置为在正常操作中启用 flash 透明解密)。 + - ``DISABLE_DL_CACHE`` 在 UART 引导加载程序模式下运行时禁止整个 MMU flash 缓存。 - espefuse.py --port PORT burn_efuse DISABLE_DL_DECRYPT - espefuse.py --port PORT write_protect_efuse DISABLE_DL_ENCRYPT +.. only:: not esp32 -(请注意,一个写保护位即可关闭这 3 个 eFuse,因此,写保护一个 eFuse 将写保护上述所有 eFuse。所以,在写保护前须设置任意位)。 + .. list:: -.. important:: - 由于 ``esptool.py`` 不支持读取加密的 Flash,因此目前基本无法通过写保护这些 eFuse 来将其保持为未设状态。 + - ``DIS_DOWNLOAD_MANUAL_ENCRYPT`` 在 UART 引导加载程序启动模式下运行时,禁止 flash 加密操作。 + :esp32s2 or esp32s3: - ``DIS_DOWNLOAD_ICACHE`` 和 ``DIS_DOWNLOAD_DCACHE`` 在 UART 引导加载程序模式下运行时禁止整个 MMU flash 缓存。 + :esp32c3: - ``DIS_DOWNLOAD_ICACHE`` 在 UART 引导加载程序模式下运行时禁止整个 MMU flash 缓存。 + :esp32s2: - ``HARD_DIS_JTAG`` 禁用 JTAG。 + :esp32c3: - ``DIS_PAD_JTAG`` 和 ``DIS_USB_JTAG`` 禁用 JTAG。 + :esp32s3: - ``HARD_DIS_JTAG`` 和 ``DIS_USB_JTAG`` 禁用 JTAG。 + - ``DIS_LEGACY_SPI_BOOT`` 禁用传统的 SPI 启动模式。 -.. important:: - 如果保留 ``DISABLE_DL_DECRYPT`` 未设置(为 0),则实际上将使 Flash 加密无效,因为此时有物理访问权限的攻击者便可使用 UART 引导加载程序模式(使用自定义存根代码)读取 Flash 的内容。 +为了能启用这些功能,可在首次启动前仅烧录部分 eFuse,并用未设置值 0 写保护其他部分。例如: -.. _setting-flash-crypt-config: +.. only:: esp32 -设置 FLASH_CRYPT_CONFIG -^^^^^^^^^^^^^^^^^^^^^^^^^^^ + .. code-block:: bash -``FLASH_CRYPT_CONFIG`` eFuse 决定 Flash 加密密钥中随块偏移“调整”的位数。详情可参见 :ref:`flash-encryption-algorithm`。 + espefuse.py --port PORT burn_efuse DISABLE_DL_DECRYPT + espefuse.py --port PORT write_protect_efuse DISABLE_DL_ENCRYPT -首次启动 引导加载程序时,该值始终设置为最大 `0xF`。 +.. only:: not esp32 -可手动写入这些 eFuse,并在首次启动前对其写保护,以便选择不同的调整值。但不推荐该操作。 + .. code-block:: bash + + espefuse.py --port PORT burn_efuse DIS_DOWNLOAD_MANUAL_ENCRYPT + espefuse.py --port PORT write_protect_efuse DIS_DOWNLOAD_MANUAL_ENCRYPT + + .. note:: + + 请注意在写保护前设置所有适当的位! + + 一个位可以控制三个 eFuse 的写保护,这意味着写保护一个 eFuse 位将写保护所有未设置的 eFuse 位。 + + 由于 ``esptool.py`` 目前不支持读取加密 flash,所以对这些 eFuse 进行写保护从而使其保持未设置目前来说并不是很有用。 + +.. only:: esp32 + + .. important:: + + 保持 ``DISABLE_DL_DECRYPT`` 未设置 (0) 会使 flash 加密无效。 + + 对芯片具有物理访问权限的攻击者会使用 UART 引导加载程序模式(使用自定义存根代码)读取 flash 的内容。 + + +.. only:: esp32 + + .. _setting-flash-crypt-config: + + 设置 FLASH_CRYPT_CONFIG + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + ``FLASH_CRYPT_CONFIG`` eFuse 决定 flash 加密密钥中随块偏移“调整”的位数。详情可参考 :ref:`flash-encryption-algorithm`。 + + 首次启动固件引导加载程序时,该值始终设置为最大值 `0xF`。 + + 可手动写入这些 eFuse,并在首次启动前对其写保护,以便选择不同的调整值。但不推荐该操作。 + + 强烈建议在 ``FLASH_CRYPT_CONFIG`` 未设置时,不要对其进行写保护。否则,它的值将永久为零,而 flash 加密密钥中则无调整位。这导致 flash 加密算法等同于 AES ECB 模式。 + +JTAG 调试 +^^^^^^^^^^^^^^ + +默认情况下,当启用 flash 加密(开发或发布模式)时,将通过 eFuse 禁用 JTAG 调试。引导加载程序在首次启动时执行此操作,同时启用 flash 加密。 + +请参考 :ref:`jtag-debugging-security-features` 了解更多关于使用 JTAG 调试与 flash 加密的信息。 + + +.. _manual-encryption: + +手动加密文件 +^^^^^^^^^^^^^^^^^^^^ + +手动加密或解密文件需要在 eFuse 中预烧录 flash 加密密钥(请参阅 :ref:`pregenerated-flash-encryption-key`)并在主机上保留一份副本。 如果 flash 加密配置在开发模式下,那么则不需要保留密钥的副本或遵循这些步骤,可以使用更简单的 :ref:`encrypt-partitions` 步骤。 + +密钥文件应该是单个原始二进制文件(例如:``key.bin``)。 + +.. only:: SOC_FLASH_ENCRYPTION_XTS_AES_256 + + .. note:: + + 如果使用 AES-XTS-256,那么密钥文件将被生成两部分(``XTS_AES_256_KEY_1`` 和 ``XTS_AES_256_KEY_2``),可通过 ``espefuse.py`` 进行编程。 ``espsecure.py`` 目前仅支持用于加密/解密的单个密钥文件,因此用于 ``XTS_AES_256_KEY_1`` 和 ``XTS_AES_256_KEY_2`` 的各个文件应手动合并以创建一个 64 字节长的单个文件。 + +例如,以下是将文件 ``build/my-app.bin`` 进行加密、烧录到偏移量 0x10000 的步骤。运行 ``espsecure.py``,如下所示: + +.. only:: esp32 + + .. code-block:: bash + + espsecure.py encrypt_flash_data --keyfile /path/to/key.bin --address 0x10000 --output my-app-ciphertext.bin build/my-app.bin + +.. only:: not esp32 + + .. code-block:: bash + + espsecure.py encrypt_flash_data --aes_xts --keyfile /path/to/key.bin --address 0x10000 --output my-app-ciphertext.bin build/my-app.bin + +然后可以使用 ``esptool.py`` 将文件 ``my-app-ciphertext.bin`` 写入偏移量 0x10000。 关于为 ``esptool.py`` 推荐的所有命令行选项,请查看 idf.py build 成功时打印的输出。 + +.. note:: + + 如果 {IDF_TARGET_NAME} 在启动时无法识别烧录进去的密文文件,请检查密钥是否匹配以及命令行参数是否完全匹配,包括偏移量是否正确。 + + .. only:: esp32 + + 如果您的 ESP32 在 eFuse 中使用了非默认的 :ref:`FLASH_CRYPT_CONFIG 值 `,那么则需要向 ``espsecure.py`` 传递 ``--flash_crypt_conf`` 参数以设置匹配的值。如果设备自己设置了 flash 加密就不会出现这种情况,但如果手动烧录 eFuse 来启用 flash 加密就可能发生这种情况。 + +``espsecure.py decrypt_flash_data`` 命令可以使用同样的选项(和不同的输入/输出文件)来解密 flash 密文或之前加密的文件。 + + +.. only:: SOC_SPIRAM_SUPPORTED and not esp32 + + 片外 RAM + ------------ + + 启用 flash 加密后,任何通过缓存从片外 SPI RAM 读取和写入的数据也将被加密/解密。这个实现的方式以及使用的密钥与 flash 加密相同。如果启用 flash 加密,则片外 SPI RAM 的加密也会被启用,无法单独控制此功能。 -当 ``FLASH_CRYPT_CONFIG`` 的值为 0 时,强烈建议始终不对其进行写保护。如果该 eFuse 设置为 0,则 Flash 加密密钥中无调整位,且 Flash 加密算法相当于 AES ECB 模式。 技术细节 ----------- -下节将提供 Flash 加密操作的相关信息。 +以下章节将提供 flash 加密操作的相关信息。 -.. _flash-encryption-algorithm: +.. only:: not SOC_FLASH_ENCRYPTION_XTS_AES -Flash 加密算法 -^^^^^^^^^^^^^^^^ + .. _flash-encryption-algorithm: -- AES-256 在 16 字节的数据块上运行。Flash 加密引擎在 32 字节的数据块和 2 个 串行 AES 块上加密或解密数据。 + Flash 加密算法 + ^^^^^^^^^^^^^^^^ -- Flash 加密的主密钥存储于 eFuse (BLOCK1) 中,默认受保护防止进一步写入或软件读取。 + - AES-256 在 16 字节的数据块上运行。Flash 加密引擎在 32 字节的数据(2 个 串行 AES 块)上加密或解密数据。 -- AES-256 密钥大小为 256 位(32 字节),从 eFuse block 1 中读取。硬件 AES 引擎使用反字节序密钥于 eFuse 块中存储的字节序。 + - Flash 加密的主密钥存储于 ``flash_encryption`` eFuse 中,默认受保护防止进一步写入或软件读取。 - - 如果 ``CODING_SCHEME`` eFuse 设置为 0(默认“无”编码方案),则 eFuse 密钥块为 256 位,且密钥按原方式存储(反字节序)。 - - 如果 ``CODING_SCHEME`` eFuse 设置为 1(3/4 编码),则 eFuse 密钥块为 192 位(反字节序),信息熵总量减少。硬件 Flash 加密仍在 256 字节密钥上运行,在读取后(字节序未反向),密钥扩展为 ``key = key[0:255] + key[64:127]``。 + - AES-256 密钥大小为 256 位(32 字节),从 ``flash_encryption`` eFuse 中读取。与 ``flash_encryption`` 中的存储顺序相比,硬件 AES 引擎使用的是相反的字节顺序的密钥。 -- Flash 加密中使用了逆向 AES 算法,因此 Flash 加密的“加密”操作相当于 AES 解密,而其“解密”操作则相当于 AES 加密。这是为了优化性能,不会影响算法的有效性。 + - 如果 ``CODING_SCHEME`` eFuse 设置为 0(默认“无”编码方案),则 eFuse 密钥块为 256 位,且密钥按原方式存储(反字节序)。 + - 如果 ``CODING_SCHEME`` eFuse 设置为 1(3/4 编码),则 eFuse 密钥块为 192 位(反字节序),信息熵总量减少。硬件 flash 加密仍在 256 字节密钥上运行,在读取后(字节序未反向),密钥扩展为 ``key = key[0:255] + key[64:127]``。 -- 每个 32 字节块(2 个相邻的 16 字节 AES 块)都由一个特殊的密钥进行加密。该密钥由 eFuse 中 Flash 加密的主密钥产生,并随 Flash 中该字节块的偏移进行 XOR 运算(一次“密钥调整”)。 + - Flash 加密中使用了逆向 AES 算法,因此 flash 加密的“加密”操作相当于 AES 解密,而其“解密”操作则相当于 AES 加密。这是为了优化性能,不会影响算法的有效性。 -- 具体调整量取决于 ``FLASH_CRYPT_CONFIG`` eFuse 的设置。该 eFuse 共 4 位,每位可对特定范围的密钥位进行 XOR 运算: + - 每个 32 字节块(2 个相邻的 16 字节 AES 块)都由一个特殊的密钥进行加密。该密钥由 ``flash_encryption`` 中 flash 加密的主密钥产生,并随 flash 中该字节块的偏移进行 XOR 运算(一次“密钥调整”)。 - - Bit 1,对密钥的 0-66 位进行 XOR 运算。 - - Bit 2,对密钥的 67-131 位进行 XOR 运算。 - - Bit 3,对密钥的 132-194 位进行 XOR 运算。 - - Bit 4,对密钥的 195-256 位进行 XOR 运算。 + - 具体调整量取决于 ``FLASH_CRYPT_CONFIG`` eFuse 的设置。该 eFuse 共 4 位,每位可对特定范围的密钥位进行 XOR 运算: - 建议将 ``FLASH_CRYPT_CONFIG`` 的值始终保留为默认值 `0xF`,这样所有密钥位都随块偏移进行 XOR 运算。详情可参见 :ref:`setting-flash-crypt-config`。 + - Bit 1,对密钥的 0-66 位进行 XOR 运算。 + - Bit 2,对密钥的 67-131 位进行 XOR 运算。 + - Bit 3,对密钥的 132-194 位进行 XOR 运算。 + - Bit 4,对密钥的 195-256 位进行 XOR 运算。 -- 块偏移的 19 个高位(第 5-23 位)由 Flash 加密的主密钥进行 XOR 运算。选定该范围的原因为:Flash 的最大尺寸为 16MB(24 位),每个块大小为 32 字节,因而 5 个最低有效位始终为 0。 + 建议将 ``FLASH_CRYPT_CONFIG`` 的值始终保留为默认值 ``0xF``,这样所有密钥位都随块偏移进行 XOR 运算。详情可参见 :ref:`setting-flash-crypt-config`。 -- 从 19 个块偏移位中每个位到 Flash 加密密钥的 256 位都有一个特殊的映射,以决定与哪个位进行 XOR 运算。有关完整映射可参见 ``espsecure.py`` 源代码中的变量 ``_FLASH_ENCRYPTION_TWEAK_PATTERN``。 + - 块偏移的 19 个高位(第 5-23 位)由 flash 加密的主密钥进行 XOR 运算。选定该范围的原因为:flash 的大小最大为 16 MB(24 位),每个块大小为 32 字节,因而 5 个最低有效位始终为 0。 -- 有关在 Python 中实现的完整 Flash 加密算法,可参见 ``espsecure.py`` 源代码中的函数 `_flash_encryption_operation()`。 + - 从 19 个块偏移位中每个位到 flash 加密密钥的 256 位都有一个特殊的映射,以决定与哪个位进行 XOR 运算。有关完整映射可参见 ``espsecure.py`` 源代码中的变量 ``_FLASH_ENCRYPTION_TWEAK_PATTERN``。 + +- 有关在 Python 中实现的完整 flash 加密算法,可参见 ``espsecure.py`` 源代码中的函数 ``_flash_encryption_operation()``。 + +.. only:: SOC_FLASH_ENCRYPTION_XTS_AES_256 + + .. _flash-encryption-algorithm: + + Flash 加密算法 + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + + - {IDF_TARGET_NAME} 使用 XTS-AES 块密码模式进行 flash 加密,密钥大小为 256 位或 512 位。 + + - XTS-AES 是一种专门为光盘加密设计的块密码模式,它解决了其它潜在模式如 AES-CTR 在此使用情景下的不足。有关 XTS-AES 算法的详细描述,请参考 `IEEE Std 1619-2007 `_。 + + - Flash 加密的密钥存储于一个或两个 ``BLOCK_KEYN`` eFuse 中,默认受保护防止进一步写入或软件读取。 + + - 有关在 Python 中实现的完整 flash 加密算法,可参见 ``espsecure.py`` 源代码中的函数 ``_flash_encryption_operation()``。 + +.. only:: SOC_FLASH_ENCRYPTION_XTS_AES and not SOC_FLASH_ENCRYPTION_XTS_AES_256 + + .. _flash-encryption-algorithm: + + Flash 加密算法 + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + + - {IDF_TARGET_NAME} 使用 XTS-AES 块密码模式进行 flash 加密,密钥大小为 256 位。 + + - XTS-AES 是一种专门为光盘加密设计的块密码模式,它解决了其它潜在模式如 AES-CTR 在此使用情景下的不足。有关 XTS-AES 算法的详细描述,请参考 `IEEE Std 1619-2007 `_。 + + - Flash 加密的密钥存储于一个 ``BLOCK_KEYN`` eFuse 中,默认受保护防止进一步写入或软件读取。 + + - 有关在 Python 中实现的完整 flash 加密算法,可参见 ``espsecure.py`` 源代码中的函数 ``_flash_encryption_operation()``。 diff --git a/examples/README.md b/examples/README.md index fcd3826f78..191b5286b1 100644 --- a/examples/README.md +++ b/examples/README.md @@ -15,6 +15,7 @@ The examples are grouped into subdirectories by category. Each category director * `ethernet` Ethernet network examples. * `get-started` Simple examples with minimal functionality. Good start point for beginners. * `mesh` Wi-Fi Mesh examples. +* `network` Examples related to general network environment, test & analysis. * `openthread` OpenThread examples. * `peripherals` Examples showing driver functionality for the various onboard ESP32 peripherals. * `protocols` Examples showing network protocol interactions. diff --git a/examples/bluetooth/bluedroid/ble/ble_ancs/sdkconfig.defaults.esp32 b/examples/bluetooth/bluedroid/ble/ble_ancs/sdkconfig.defaults.esp32 index 66db63bca0..55915af404 100644 --- a/examples/bluetooth/bluedroid/ble/ble_ancs/sdkconfig.defaults.esp32 +++ b/examples/bluetooth/bluedroid/ble/ble_ancs/sdkconfig.defaults.esp32 @@ -410,10 +410,9 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32=y # -# Bluetooth controller(ESP32 Dual Mode Bluetooth) +# Bluetooth controller # CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y # CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY is not set @@ -454,7 +453,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # CONFIG_BTDM_COEX_BT_OPTIONS is not set -# end of Bluetooth controller(ESP32 Dual Mode Bluetooth) +# end of Bluetooth controller CONFIG_BTDM_CTRL_HW_CCA_EFF=0 CONFIG_BTDM_CTRL_DFT_TX_POWER_LEVEL_EFF=0 @@ -669,7 +668,7 @@ CONFIG_BT_ACL_CONNECTIONS=4 CONFIG_BT_SMP_ENABLE=y # CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN is not set CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 -CONFIG_BT_RESERVE_DRAM=0xdb5c +CONFIG_BTDM_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/ble_ancs/sdkconfig.defaults.esp32c3 b/examples/bluetooth/bluedroid/ble/ble_ancs/sdkconfig.defaults.esp32c3 index 178e59e007..b1f9689350 100644 --- a/examples/bluetooth/bluedroid/ble/ble_ancs/sdkconfig.defaults.esp32c3 +++ b/examples/bluetooth/bluedroid/ble/ble_ancs/sdkconfig.defaults.esp32c3 @@ -367,7 +367,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 @@ -382,7 +381,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # -# Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_MODE_EFF=1 CONFIG_BT_CTRL_BLE_MAX_ACT=10 @@ -426,7 +425,7 @@ CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF=7 CONFIG_BT_CTRL_SLEEP_MODE_EFF=0 CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 -# end of Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# end of Bluetooth controller # # MODEM SLEEP Options @@ -639,7 +638,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/ble_ancs/sdkconfig.defaults.esp32s3 b/examples/bluetooth/bluedroid/ble/ble_ancs/sdkconfig.defaults.esp32s3 index 3d19f688a2..d9423ad1e4 100644 --- a/examples/bluetooth/bluedroid/ble/ble_ancs/sdkconfig.defaults.esp32s3 +++ b/examples/bluetooth/bluedroid/ble/ble_ancs/sdkconfig.defaults.esp32s3 @@ -477,7 +477,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32S3=y CONFIG_BT_SOC_SUPPORT_5_0=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 @@ -550,7 +549,7 @@ CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 # -# Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # CONFIG_BT_CTRL_PINNED_TO_CORE_1 is not set @@ -559,7 +558,7 @@ CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # MODEM SLEEP Options # # end of MODEM SLEEP Options -# end of Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# end of Bluetooth controller CONFIG_BT_BLUEDROID_ENABLED=y # CONFIG_BT_NIMBLE_ENABLED is not set @@ -769,7 +768,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/ble_compatibility_test/sdkconfig.defaults.esp32 b/examples/bluetooth/bluedroid/ble/ble_compatibility_test/sdkconfig.defaults.esp32 index 6b79d45220..5bd79aa13d 100644 --- a/examples/bluetooth/bluedroid/ble/ble_compatibility_test/sdkconfig.defaults.esp32 +++ b/examples/bluetooth/bluedroid/ble/ble_compatibility_test/sdkconfig.defaults.esp32 @@ -410,10 +410,9 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32=y # -# Bluetooth controller(ESP32 Dual Mode Bluetooth) +# Bluetooth controller # CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y # CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY is not set @@ -454,7 +453,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # CONFIG_BTDM_COEX_BT_OPTIONS is not set -# end of Bluetooth controller(ESP32 Dual Mode Bluetooth) +# end of Bluetooth controller CONFIG_BTDM_CTRL_HW_CCA_EFF=0 CONFIG_BTDM_CTRL_DFT_TX_POWER_LEVEL_EFF=0 @@ -673,7 +672,7 @@ CONFIG_BT_ACL_CONNECTIONS=4 CONFIG_BT_SMP_ENABLE=y # CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN is not set CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 -CONFIG_BT_RESERVE_DRAM=0xdb5c +CONFIG_BTDM_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/ble_compatibility_test/sdkconfig.defaults.esp32c3 b/examples/bluetooth/bluedroid/ble/ble_compatibility_test/sdkconfig.defaults.esp32c3 index 178e59e007..b1f9689350 100644 --- a/examples/bluetooth/bluedroid/ble/ble_compatibility_test/sdkconfig.defaults.esp32c3 +++ b/examples/bluetooth/bluedroid/ble/ble_compatibility_test/sdkconfig.defaults.esp32c3 @@ -367,7 +367,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 @@ -382,7 +381,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # -# Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_MODE_EFF=1 CONFIG_BT_CTRL_BLE_MAX_ACT=10 @@ -426,7 +425,7 @@ CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF=7 CONFIG_BT_CTRL_SLEEP_MODE_EFF=0 CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 -# end of Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# end of Bluetooth controller # # MODEM SLEEP Options @@ -639,7 +638,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/ble_compatibility_test/sdkconfig.defaults.esp32s3 b/examples/bluetooth/bluedroid/ble/ble_compatibility_test/sdkconfig.defaults.esp32s3 index 3d19f688a2..d9423ad1e4 100644 --- a/examples/bluetooth/bluedroid/ble/ble_compatibility_test/sdkconfig.defaults.esp32s3 +++ b/examples/bluetooth/bluedroid/ble/ble_compatibility_test/sdkconfig.defaults.esp32s3 @@ -477,7 +477,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32S3=y CONFIG_BT_SOC_SUPPORT_5_0=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 @@ -550,7 +549,7 @@ CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 # -# Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # CONFIG_BT_CTRL_PINNED_TO_CORE_1 is not set @@ -559,7 +558,7 @@ CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # MODEM SLEEP Options # # end of MODEM SLEEP Options -# end of Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# end of Bluetooth controller CONFIG_BT_BLUEDROID_ENABLED=y # CONFIG_BT_NIMBLE_ENABLED is not set @@ -769,7 +768,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/ble_eddystone/sdkconfig.defaults.esp32c3 b/examples/bluetooth/bluedroid/ble/ble_eddystone/sdkconfig.defaults.esp32c3 index 178e59e007..b1f9689350 100644 --- a/examples/bluetooth/bluedroid/ble/ble_eddystone/sdkconfig.defaults.esp32c3 +++ b/examples/bluetooth/bluedroid/ble/ble_eddystone/sdkconfig.defaults.esp32c3 @@ -367,7 +367,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 @@ -382,7 +381,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # -# Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_MODE_EFF=1 CONFIG_BT_CTRL_BLE_MAX_ACT=10 @@ -426,7 +425,7 @@ CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF=7 CONFIG_BT_CTRL_SLEEP_MODE_EFF=0 CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 -# end of Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# end of Bluetooth controller # # MODEM SLEEP Options @@ -639,7 +638,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/ble_eddystone/sdkconfig.defaults.esp32s3 b/examples/bluetooth/bluedroid/ble/ble_eddystone/sdkconfig.defaults.esp32s3 index 3d19f688a2..d9423ad1e4 100644 --- a/examples/bluetooth/bluedroid/ble/ble_eddystone/sdkconfig.defaults.esp32s3 +++ b/examples/bluetooth/bluedroid/ble/ble_eddystone/sdkconfig.defaults.esp32s3 @@ -477,7 +477,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32S3=y CONFIG_BT_SOC_SUPPORT_5_0=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 @@ -550,7 +549,7 @@ CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 # -# Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # CONFIG_BT_CTRL_PINNED_TO_CORE_1 is not set @@ -559,7 +558,7 @@ CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # MODEM SLEEP Options # # end of MODEM SLEEP Options -# end of Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# end of Bluetooth controller CONFIG_BT_BLUEDROID_ENABLED=y # CONFIG_BT_NIMBLE_ENABLED is not set @@ -769,7 +768,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/ble_hid_device_demo/sdkconfig.defaults.esp32 b/examples/bluetooth/bluedroid/ble/ble_hid_device_demo/sdkconfig.defaults.esp32 index 52cb02588e..64d46d9ee6 100644 --- a/examples/bluetooth/bluedroid/ble/ble_hid_device_demo/sdkconfig.defaults.esp32 +++ b/examples/bluetooth/bluedroid/ble/ble_hid_device_demo/sdkconfig.defaults.esp32 @@ -410,10 +410,9 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32=y # -# Bluetooth controller(ESP32 Dual Mode Bluetooth) +# Bluetooth controller # CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y # CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY is not set @@ -454,7 +453,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # CONFIG_BTDM_COEX_BT_OPTIONS is not set -# end of Bluetooth controller(ESP32 Dual Mode Bluetooth) +# end of Bluetooth controller CONFIG_BTDM_CTRL_HW_CCA_EFF=0 CONFIG_BTDM_CTRL_DFT_TX_POWER_LEVEL_EFF=0 @@ -674,7 +673,7 @@ CONFIG_BT_ACL_CONNECTIONS=4 CONFIG_BT_SMP_ENABLE=y # CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN is not set CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 -CONFIG_BT_RESERVE_DRAM=0xdb5c +CONFIG_BTDM_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/ble_hid_device_demo/sdkconfig.defaults.esp32c3 b/examples/bluetooth/bluedroid/ble/ble_hid_device_demo/sdkconfig.defaults.esp32c3 index 178e59e007..b1f9689350 100644 --- a/examples/bluetooth/bluedroid/ble/ble_hid_device_demo/sdkconfig.defaults.esp32c3 +++ b/examples/bluetooth/bluedroid/ble/ble_hid_device_demo/sdkconfig.defaults.esp32c3 @@ -367,7 +367,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 @@ -382,7 +381,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # -# Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_MODE_EFF=1 CONFIG_BT_CTRL_BLE_MAX_ACT=10 @@ -426,7 +425,7 @@ CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF=7 CONFIG_BT_CTRL_SLEEP_MODE_EFF=0 CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 -# end of Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# end of Bluetooth controller # # MODEM SLEEP Options @@ -639,7 +638,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/ble_hid_device_demo/sdkconfig.defaults.esp32s3 b/examples/bluetooth/bluedroid/ble/ble_hid_device_demo/sdkconfig.defaults.esp32s3 index 3d19f688a2..d9423ad1e4 100644 --- a/examples/bluetooth/bluedroid/ble/ble_hid_device_demo/sdkconfig.defaults.esp32s3 +++ b/examples/bluetooth/bluedroid/ble/ble_hid_device_demo/sdkconfig.defaults.esp32s3 @@ -477,7 +477,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32S3=y CONFIG_BT_SOC_SUPPORT_5_0=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 @@ -550,7 +549,7 @@ CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 # -# Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # CONFIG_BT_CTRL_PINNED_TO_CORE_1 is not set @@ -559,7 +558,7 @@ CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # MODEM SLEEP Options # # end of MODEM SLEEP Options -# end of Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# end of Bluetooth controller CONFIG_BT_BLUEDROID_ENABLED=y # CONFIG_BT_NIMBLE_ENABLED is not set @@ -769,7 +768,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/ble_ibeacon/sdkconfig.defaults.esp32 b/examples/bluetooth/bluedroid/ble/ble_ibeacon/sdkconfig.defaults.esp32 index 12731ad6fa..6d8e7e6376 100644 --- a/examples/bluetooth/bluedroid/ble/ble_ibeacon/sdkconfig.defaults.esp32 +++ b/examples/bluetooth/bluedroid/ble/ble_ibeacon/sdkconfig.defaults.esp32 @@ -410,10 +410,9 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32=y # -# Bluetooth controller(ESP32 Dual Mode Bluetooth) +# Bluetooth controller # CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y # CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY is not set @@ -454,7 +453,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # CONFIG_BTDM_COEX_BT_OPTIONS is not set -# end of Bluetooth controller(ESP32 Dual Mode Bluetooth) +# end of Bluetooth controller CONFIG_BTDM_CTRL_HW_CCA_EFF=0 CONFIG_BTDM_CTRL_DFT_TX_POWER_LEVEL_EFF=0 @@ -671,7 +670,7 @@ CONFIG_BT_ACL_CONNECTIONS=4 # CONFIG_BT_BLE_HOST_QUEUE_CONG_CHECK is not set # CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN is not set CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 -CONFIG_BT_RESERVE_DRAM=0xdb5c +CONFIG_BTDM_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/ble_ibeacon/sdkconfig.defaults.esp32c3 b/examples/bluetooth/bluedroid/ble/ble_ibeacon/sdkconfig.defaults.esp32c3 index 178e59e007..b1f9689350 100644 --- a/examples/bluetooth/bluedroid/ble/ble_ibeacon/sdkconfig.defaults.esp32c3 +++ b/examples/bluetooth/bluedroid/ble/ble_ibeacon/sdkconfig.defaults.esp32c3 @@ -367,7 +367,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 @@ -382,7 +381,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # -# Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_MODE_EFF=1 CONFIG_BT_CTRL_BLE_MAX_ACT=10 @@ -426,7 +425,7 @@ CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF=7 CONFIG_BT_CTRL_SLEEP_MODE_EFF=0 CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 -# end of Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# end of Bluetooth controller # # MODEM SLEEP Options @@ -639,7 +638,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/ble_ibeacon/sdkconfig.defaults.esp32s3 b/examples/bluetooth/bluedroid/ble/ble_ibeacon/sdkconfig.defaults.esp32s3 index 3d19f688a2..d9423ad1e4 100644 --- a/examples/bluetooth/bluedroid/ble/ble_ibeacon/sdkconfig.defaults.esp32s3 +++ b/examples/bluetooth/bluedroid/ble/ble_ibeacon/sdkconfig.defaults.esp32s3 @@ -477,7 +477,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32S3=y CONFIG_BT_SOC_SUPPORT_5_0=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 @@ -550,7 +549,7 @@ CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 # -# Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # CONFIG_BT_CTRL_PINNED_TO_CORE_1 is not set @@ -559,7 +558,7 @@ CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # MODEM SLEEP Options # # end of MODEM SLEEP Options -# end of Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# end of Bluetooth controller CONFIG_BT_BLUEDROID_ENABLED=y # CONFIG_BT_NIMBLE_ENABLED is not set @@ -769,7 +768,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/ble_spp_client/sdkconfig.defaults.esp32 b/examples/bluetooth/bluedroid/ble/ble_spp_client/sdkconfig.defaults.esp32 index 92acd27f33..9b30e9aac3 100644 --- a/examples/bluetooth/bluedroid/ble/ble_spp_client/sdkconfig.defaults.esp32 +++ b/examples/bluetooth/bluedroid/ble/ble_spp_client/sdkconfig.defaults.esp32 @@ -416,10 +416,9 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32=y # -# Bluetooth controller(ESP32 Dual Mode Bluetooth) +# Bluetooth controller # CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y # CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY is not set @@ -460,7 +459,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # CONFIG_BTDM_COEX_BT_OPTIONS is not set -# end of Bluetooth controller(ESP32 Dual Mode Bluetooth) +# end of Bluetooth controller CONFIG_BTDM_CTRL_HW_CCA_EFF=0 CONFIG_BTDM_CTRL_DFT_TX_POWER_LEVEL_EFF=0 @@ -673,7 +672,7 @@ CONFIG_BT_ACL_CONNECTIONS=4 # CONFIG_BT_BLE_HOST_QUEUE_CONG_CHECK is not set # CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN is not set CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 -CONFIG_BT_RESERVE_DRAM=0xdb5c +CONFIG_BTDM_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/ble_spp_client/sdkconfig.defaults.esp32c3 b/examples/bluetooth/bluedroid/ble/ble_spp_client/sdkconfig.defaults.esp32c3 index 178e59e007..b1f9689350 100644 --- a/examples/bluetooth/bluedroid/ble/ble_spp_client/sdkconfig.defaults.esp32c3 +++ b/examples/bluetooth/bluedroid/ble/ble_spp_client/sdkconfig.defaults.esp32c3 @@ -367,7 +367,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 @@ -382,7 +381,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # -# Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_MODE_EFF=1 CONFIG_BT_CTRL_BLE_MAX_ACT=10 @@ -426,7 +425,7 @@ CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF=7 CONFIG_BT_CTRL_SLEEP_MODE_EFF=0 CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 -# end of Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# end of Bluetooth controller # # MODEM SLEEP Options @@ -639,7 +638,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/ble_spp_client/sdkconfig.defaults.esp32s3 b/examples/bluetooth/bluedroid/ble/ble_spp_client/sdkconfig.defaults.esp32s3 index 3d19f688a2..d9423ad1e4 100644 --- a/examples/bluetooth/bluedroid/ble/ble_spp_client/sdkconfig.defaults.esp32s3 +++ b/examples/bluetooth/bluedroid/ble/ble_spp_client/sdkconfig.defaults.esp32s3 @@ -477,7 +477,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32S3=y CONFIG_BT_SOC_SUPPORT_5_0=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 @@ -550,7 +549,7 @@ CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 # -# Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # CONFIG_BT_CTRL_PINNED_TO_CORE_1 is not set @@ -559,7 +558,7 @@ CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # MODEM SLEEP Options # # end of MODEM SLEEP Options -# end of Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# end of Bluetooth controller CONFIG_BT_BLUEDROID_ENABLED=y # CONFIG_BT_NIMBLE_ENABLED is not set @@ -769,7 +768,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/ble_spp_server/sdkconfig.defaults.esp32 b/examples/bluetooth/bluedroid/ble/ble_spp_server/sdkconfig.defaults.esp32 index 12731ad6fa..6d8e7e6376 100644 --- a/examples/bluetooth/bluedroid/ble/ble_spp_server/sdkconfig.defaults.esp32 +++ b/examples/bluetooth/bluedroid/ble/ble_spp_server/sdkconfig.defaults.esp32 @@ -410,10 +410,9 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32=y # -# Bluetooth controller(ESP32 Dual Mode Bluetooth) +# Bluetooth controller # CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y # CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY is not set @@ -454,7 +453,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # CONFIG_BTDM_COEX_BT_OPTIONS is not set -# end of Bluetooth controller(ESP32 Dual Mode Bluetooth) +# end of Bluetooth controller CONFIG_BTDM_CTRL_HW_CCA_EFF=0 CONFIG_BTDM_CTRL_DFT_TX_POWER_LEVEL_EFF=0 @@ -671,7 +670,7 @@ CONFIG_BT_ACL_CONNECTIONS=4 # CONFIG_BT_BLE_HOST_QUEUE_CONG_CHECK is not set # CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN is not set CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 -CONFIG_BT_RESERVE_DRAM=0xdb5c +CONFIG_BTDM_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/ble_spp_server/sdkconfig.defaults.esp32c3 b/examples/bluetooth/bluedroid/ble/ble_spp_server/sdkconfig.defaults.esp32c3 index 178e59e007..b1f9689350 100644 --- a/examples/bluetooth/bluedroid/ble/ble_spp_server/sdkconfig.defaults.esp32c3 +++ b/examples/bluetooth/bluedroid/ble/ble_spp_server/sdkconfig.defaults.esp32c3 @@ -367,7 +367,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 @@ -382,7 +381,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # -# Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_MODE_EFF=1 CONFIG_BT_CTRL_BLE_MAX_ACT=10 @@ -426,7 +425,7 @@ CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF=7 CONFIG_BT_CTRL_SLEEP_MODE_EFF=0 CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 -# end of Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# end of Bluetooth controller # # MODEM SLEEP Options @@ -639,7 +638,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/ble_spp_server/sdkconfig.defaults.esp32s3 b/examples/bluetooth/bluedroid/ble/ble_spp_server/sdkconfig.defaults.esp32s3 index 3d19f688a2..d9423ad1e4 100644 --- a/examples/bluetooth/bluedroid/ble/ble_spp_server/sdkconfig.defaults.esp32s3 +++ b/examples/bluetooth/bluedroid/ble/ble_spp_server/sdkconfig.defaults.esp32s3 @@ -477,7 +477,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32S3=y CONFIG_BT_SOC_SUPPORT_5_0=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 @@ -550,7 +549,7 @@ CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 # -# Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # CONFIG_BT_CTRL_PINNED_TO_CORE_1 is not set @@ -559,7 +558,7 @@ CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # MODEM SLEEP Options # # end of MODEM SLEEP Options -# end of Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# end of Bluetooth controller CONFIG_BT_BLUEDROID_ENABLED=y # CONFIG_BT_NIMBLE_ENABLED is not set @@ -769,7 +768,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/sdkconfig.defaults.esp32 b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/sdkconfig.defaults.esp32 index 92acd27f33..9b30e9aac3 100644 --- a/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/sdkconfig.defaults.esp32 +++ b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/sdkconfig.defaults.esp32 @@ -416,10 +416,9 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32=y # -# Bluetooth controller(ESP32 Dual Mode Bluetooth) +# Bluetooth controller # CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y # CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY is not set @@ -460,7 +459,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # CONFIG_BTDM_COEX_BT_OPTIONS is not set -# end of Bluetooth controller(ESP32 Dual Mode Bluetooth) +# end of Bluetooth controller CONFIG_BTDM_CTRL_HW_CCA_EFF=0 CONFIG_BTDM_CTRL_DFT_TX_POWER_LEVEL_EFF=0 @@ -673,7 +672,7 @@ CONFIG_BT_ACL_CONNECTIONS=4 # CONFIG_BT_BLE_HOST_QUEUE_CONG_CHECK is not set # CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN is not set CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 -CONFIG_BT_RESERVE_DRAM=0xdb5c +CONFIG_BTDM_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/sdkconfig.defaults.esp32c3 b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/sdkconfig.defaults.esp32c3 index 178e59e007..b1f9689350 100644 --- a/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/sdkconfig.defaults.esp32c3 +++ b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/sdkconfig.defaults.esp32c3 @@ -367,7 +367,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 @@ -382,7 +381,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # -# Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_MODE_EFF=1 CONFIG_BT_CTRL_BLE_MAX_ACT=10 @@ -426,7 +425,7 @@ CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF=7 CONFIG_BT_CTRL_SLEEP_MODE_EFF=0 CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 -# end of Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# end of Bluetooth controller # # MODEM SLEEP Options @@ -639,7 +638,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/sdkconfig.defaults.esp32s3 b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/sdkconfig.defaults.esp32s3 index 3d19f688a2..d9423ad1e4 100644 --- a/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/sdkconfig.defaults.esp32s3 +++ b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_client/sdkconfig.defaults.esp32s3 @@ -477,7 +477,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32S3=y CONFIG_BT_SOC_SUPPORT_5_0=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 @@ -550,7 +549,7 @@ CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 # -# Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # CONFIG_BT_CTRL_PINNED_TO_CORE_1 is not set @@ -559,7 +558,7 @@ CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # MODEM SLEEP Options # # end of MODEM SLEEP Options -# end of Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# end of Bluetooth controller CONFIG_BT_BLUEDROID_ENABLED=y # CONFIG_BT_NIMBLE_ENABLED is not set @@ -769,7 +768,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/sdkconfig.defaults.esp32 b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/sdkconfig.defaults.esp32 index 12731ad6fa..6d8e7e6376 100644 --- a/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/sdkconfig.defaults.esp32 +++ b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/sdkconfig.defaults.esp32 @@ -410,10 +410,9 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32=y # -# Bluetooth controller(ESP32 Dual Mode Bluetooth) +# Bluetooth controller # CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y # CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY is not set @@ -454,7 +453,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # CONFIG_BTDM_COEX_BT_OPTIONS is not set -# end of Bluetooth controller(ESP32 Dual Mode Bluetooth) +# end of Bluetooth controller CONFIG_BTDM_CTRL_HW_CCA_EFF=0 CONFIG_BTDM_CTRL_DFT_TX_POWER_LEVEL_EFF=0 @@ -671,7 +670,7 @@ CONFIG_BT_ACL_CONNECTIONS=4 # CONFIG_BT_BLE_HOST_QUEUE_CONG_CHECK is not set # CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN is not set CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 -CONFIG_BT_RESERVE_DRAM=0xdb5c +CONFIG_BTDM_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/sdkconfig.defaults.esp32c3 b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/sdkconfig.defaults.esp32c3 index 178e59e007..b1f9689350 100644 --- a/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/sdkconfig.defaults.esp32c3 +++ b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/sdkconfig.defaults.esp32c3 @@ -367,7 +367,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 @@ -382,7 +381,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # -# Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_MODE_EFF=1 CONFIG_BT_CTRL_BLE_MAX_ACT=10 @@ -426,7 +425,7 @@ CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF=7 CONFIG_BT_CTRL_SLEEP_MODE_EFF=0 CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 -# end of Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# end of Bluetooth controller # # MODEM SLEEP Options @@ -639,7 +638,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/sdkconfig.defaults.esp32s3 b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/sdkconfig.defaults.esp32s3 index 3d19f688a2..d9423ad1e4 100644 --- a/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/sdkconfig.defaults.esp32s3 +++ b/examples/bluetooth/bluedroid/ble/ble_throughput/throughput_server/sdkconfig.defaults.esp32s3 @@ -477,7 +477,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32S3=y CONFIG_BT_SOC_SUPPORT_5_0=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 @@ -550,7 +549,7 @@ CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 # -# Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # CONFIG_BT_CTRL_PINNED_TO_CORE_1 is not set @@ -559,7 +558,7 @@ CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # MODEM SLEEP Options # # end of MODEM SLEEP Options -# end of Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# end of Bluetooth controller CONFIG_BT_BLUEDROID_ENABLED=y # CONFIG_BT_NIMBLE_ENABLED is not set @@ -769,7 +768,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/gatt_client/sdkconfig.defaults.esp32 b/examples/bluetooth/bluedroid/ble/gatt_client/sdkconfig.defaults.esp32 index 92acd27f33..9b30e9aac3 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_client/sdkconfig.defaults.esp32 +++ b/examples/bluetooth/bluedroid/ble/gatt_client/sdkconfig.defaults.esp32 @@ -416,10 +416,9 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32=y # -# Bluetooth controller(ESP32 Dual Mode Bluetooth) +# Bluetooth controller # CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y # CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY is not set @@ -460,7 +459,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # CONFIG_BTDM_COEX_BT_OPTIONS is not set -# end of Bluetooth controller(ESP32 Dual Mode Bluetooth) +# end of Bluetooth controller CONFIG_BTDM_CTRL_HW_CCA_EFF=0 CONFIG_BTDM_CTRL_DFT_TX_POWER_LEVEL_EFF=0 @@ -673,7 +672,7 @@ CONFIG_BT_ACL_CONNECTIONS=4 # CONFIG_BT_BLE_HOST_QUEUE_CONG_CHECK is not set # CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN is not set CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 -CONFIG_BT_RESERVE_DRAM=0xdb5c +CONFIG_BTDM_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/gatt_client/sdkconfig.defaults.esp32c3 b/examples/bluetooth/bluedroid/ble/gatt_client/sdkconfig.defaults.esp32c3 index 178e59e007..b1f9689350 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_client/sdkconfig.defaults.esp32c3 +++ b/examples/bluetooth/bluedroid/ble/gatt_client/sdkconfig.defaults.esp32c3 @@ -367,7 +367,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 @@ -382,7 +381,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # -# Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_MODE_EFF=1 CONFIG_BT_CTRL_BLE_MAX_ACT=10 @@ -426,7 +425,7 @@ CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF=7 CONFIG_BT_CTRL_SLEEP_MODE_EFF=0 CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 -# end of Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# end of Bluetooth controller # # MODEM SLEEP Options @@ -639,7 +638,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/gatt_client/sdkconfig.defaults.esp32s3 b/examples/bluetooth/bluedroid/ble/gatt_client/sdkconfig.defaults.esp32s3 index 3d19f688a2..d9423ad1e4 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_client/sdkconfig.defaults.esp32s3 +++ b/examples/bluetooth/bluedroid/ble/gatt_client/sdkconfig.defaults.esp32s3 @@ -477,7 +477,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32S3=y CONFIG_BT_SOC_SUPPORT_5_0=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 @@ -550,7 +549,7 @@ CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 # -# Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # CONFIG_BT_CTRL_PINNED_TO_CORE_1 is not set @@ -559,7 +558,7 @@ CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # MODEM SLEEP Options # # end of MODEM SLEEP Options -# end of Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# end of Bluetooth controller CONFIG_BT_BLUEDROID_ENABLED=y # CONFIG_BT_NIMBLE_ENABLED is not set @@ -769,7 +768,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/gatt_client/tutorial/Gatt_Client_Example_Walkthrough.md b/examples/bluetooth/bluedroid/ble/gatt_client/tutorial/Gatt_Client_Example_Walkthrough.md index 68acc482b9..ba40fdc5f9 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_client/tutorial/Gatt_Client_Example_Walkthrough.md +++ b/examples/bluetooth/bluedroid/ble/gatt_client/tutorial/Gatt_Client_Example_Walkthrough.md @@ -209,7 +209,7 @@ static struct gattc_profile_inst gl_profile_tab[PROFILE_NUM] = { }; ``` -The initialization of the Application Profile table array includes defining the callback functions for each Profile. These are `gattc_profile_a_event_handler()` and `gattc_profile_a_event_handler()` respectively. In addition, the GATT interface is initialized to the default value of `ESP_GATT_IF_NONE`. Later on, when the Application Profile is registered, the BLE stack returns a GATT interface instance to use with that Application Profile. +The initialization of the Application Profile table array includes defining the callback function for Profile. It is `gattc_profile_event_handler()`. In addition, the GATT interface is initialized to the default value of `ESP_GATT_IF_NONE`. Later on, when the Application Profile is registered, the BLE stack returns a GATT interface instance to use with that Application Profile. The profile registration triggers an `ESP_GATTC_REG_EVT` event, which is handled by the `esp_gattc_cb()` event handler. The handler takes the GATT interface returned by the event and stores it in the profile table: diff --git a/examples/bluetooth/bluedroid/ble/gatt_security_client/sdkconfig.defaults.esp32 b/examples/bluetooth/bluedroid/ble/gatt_security_client/sdkconfig.defaults.esp32 index 66db63bca0..55915af404 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_security_client/sdkconfig.defaults.esp32 +++ b/examples/bluetooth/bluedroid/ble/gatt_security_client/sdkconfig.defaults.esp32 @@ -410,10 +410,9 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32=y # -# Bluetooth controller(ESP32 Dual Mode Bluetooth) +# Bluetooth controller # CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y # CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY is not set @@ -454,7 +453,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # CONFIG_BTDM_COEX_BT_OPTIONS is not set -# end of Bluetooth controller(ESP32 Dual Mode Bluetooth) +# end of Bluetooth controller CONFIG_BTDM_CTRL_HW_CCA_EFF=0 CONFIG_BTDM_CTRL_DFT_TX_POWER_LEVEL_EFF=0 @@ -669,7 +668,7 @@ CONFIG_BT_ACL_CONNECTIONS=4 CONFIG_BT_SMP_ENABLE=y # CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN is not set CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 -CONFIG_BT_RESERVE_DRAM=0xdb5c +CONFIG_BTDM_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/gatt_security_client/sdkconfig.defaults.esp32c3 b/examples/bluetooth/bluedroid/ble/gatt_security_client/sdkconfig.defaults.esp32c3 index 178e59e007..b1f9689350 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_security_client/sdkconfig.defaults.esp32c3 +++ b/examples/bluetooth/bluedroid/ble/gatt_security_client/sdkconfig.defaults.esp32c3 @@ -367,7 +367,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 @@ -382,7 +381,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # -# Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_MODE_EFF=1 CONFIG_BT_CTRL_BLE_MAX_ACT=10 @@ -426,7 +425,7 @@ CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF=7 CONFIG_BT_CTRL_SLEEP_MODE_EFF=0 CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 -# end of Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# end of Bluetooth controller # # MODEM SLEEP Options @@ -639,7 +638,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/gatt_security_client/sdkconfig.defaults.esp32s3 b/examples/bluetooth/bluedroid/ble/gatt_security_client/sdkconfig.defaults.esp32s3 index 3d19f688a2..d9423ad1e4 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_security_client/sdkconfig.defaults.esp32s3 +++ b/examples/bluetooth/bluedroid/ble/gatt_security_client/sdkconfig.defaults.esp32s3 @@ -477,7 +477,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32S3=y CONFIG_BT_SOC_SUPPORT_5_0=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 @@ -550,7 +549,7 @@ CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 # -# Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # CONFIG_BT_CTRL_PINNED_TO_CORE_1 is not set @@ -559,7 +558,7 @@ CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # MODEM SLEEP Options # # end of MODEM SLEEP Options -# end of Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# end of Bluetooth controller CONFIG_BT_BLUEDROID_ENABLED=y # CONFIG_BT_NIMBLE_ENABLED is not set @@ -769,7 +768,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/gatt_security_server/sdkconfig.defaults.esp32 b/examples/bluetooth/bluedroid/ble/gatt_security_server/sdkconfig.defaults.esp32 index 6b79d45220..5bd79aa13d 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_security_server/sdkconfig.defaults.esp32 +++ b/examples/bluetooth/bluedroid/ble/gatt_security_server/sdkconfig.defaults.esp32 @@ -410,10 +410,9 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32=y # -# Bluetooth controller(ESP32 Dual Mode Bluetooth) +# Bluetooth controller # CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y # CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY is not set @@ -454,7 +453,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # CONFIG_BTDM_COEX_BT_OPTIONS is not set -# end of Bluetooth controller(ESP32 Dual Mode Bluetooth) +# end of Bluetooth controller CONFIG_BTDM_CTRL_HW_CCA_EFF=0 CONFIG_BTDM_CTRL_DFT_TX_POWER_LEVEL_EFF=0 @@ -673,7 +672,7 @@ CONFIG_BT_ACL_CONNECTIONS=4 CONFIG_BT_SMP_ENABLE=y # CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN is not set CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 -CONFIG_BT_RESERVE_DRAM=0xdb5c +CONFIG_BTDM_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/gatt_security_server/sdkconfig.defaults.esp32c3 b/examples/bluetooth/bluedroid/ble/gatt_security_server/sdkconfig.defaults.esp32c3 index 178e59e007..b1f9689350 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_security_server/sdkconfig.defaults.esp32c3 +++ b/examples/bluetooth/bluedroid/ble/gatt_security_server/sdkconfig.defaults.esp32c3 @@ -367,7 +367,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 @@ -382,7 +381,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # -# Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_MODE_EFF=1 CONFIG_BT_CTRL_BLE_MAX_ACT=10 @@ -426,7 +425,7 @@ CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF=7 CONFIG_BT_CTRL_SLEEP_MODE_EFF=0 CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 -# end of Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# end of Bluetooth controller # # MODEM SLEEP Options @@ -639,7 +638,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/gatt_security_server/sdkconfig.defaults.esp32s3 b/examples/bluetooth/bluedroid/ble/gatt_security_server/sdkconfig.defaults.esp32s3 index 3d19f688a2..d9423ad1e4 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_security_server/sdkconfig.defaults.esp32s3 +++ b/examples/bluetooth/bluedroid/ble/gatt_security_server/sdkconfig.defaults.esp32s3 @@ -477,7 +477,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32S3=y CONFIG_BT_SOC_SUPPORT_5_0=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 @@ -550,7 +549,7 @@ CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 # -# Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # CONFIG_BT_CTRL_PINNED_TO_CORE_1 is not set @@ -559,7 +558,7 @@ CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # MODEM SLEEP Options # # end of MODEM SLEEP Options -# end of Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# end of Bluetooth controller CONFIG_BT_BLUEDROID_ENABLED=y # CONFIG_BT_NIMBLE_ENABLED is not set @@ -769,7 +768,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/gatt_server/sdkconfig.defaults.esp32 b/examples/bluetooth/bluedroid/ble/gatt_server/sdkconfig.defaults.esp32 index 12731ad6fa..6d8e7e6376 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_server/sdkconfig.defaults.esp32 +++ b/examples/bluetooth/bluedroid/ble/gatt_server/sdkconfig.defaults.esp32 @@ -410,10 +410,9 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32=y # -# Bluetooth controller(ESP32 Dual Mode Bluetooth) +# Bluetooth controller # CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y # CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY is not set @@ -454,7 +453,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # CONFIG_BTDM_COEX_BT_OPTIONS is not set -# end of Bluetooth controller(ESP32 Dual Mode Bluetooth) +# end of Bluetooth controller CONFIG_BTDM_CTRL_HW_CCA_EFF=0 CONFIG_BTDM_CTRL_DFT_TX_POWER_LEVEL_EFF=0 @@ -671,7 +670,7 @@ CONFIG_BT_ACL_CONNECTIONS=4 # CONFIG_BT_BLE_HOST_QUEUE_CONG_CHECK is not set # CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN is not set CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 -CONFIG_BT_RESERVE_DRAM=0xdb5c +CONFIG_BTDM_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/gatt_server/sdkconfig.defaults.esp32c3 b/examples/bluetooth/bluedroid/ble/gatt_server/sdkconfig.defaults.esp32c3 index 178e59e007..b1f9689350 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_server/sdkconfig.defaults.esp32c3 +++ b/examples/bluetooth/bluedroid/ble/gatt_server/sdkconfig.defaults.esp32c3 @@ -367,7 +367,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 @@ -382,7 +381,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # -# Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_MODE_EFF=1 CONFIG_BT_CTRL_BLE_MAX_ACT=10 @@ -426,7 +425,7 @@ CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF=7 CONFIG_BT_CTRL_SLEEP_MODE_EFF=0 CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 -# end of Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# end of Bluetooth controller # # MODEM SLEEP Options @@ -639,7 +638,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/gatt_server/sdkconfig.defaults.esp32s3 b/examples/bluetooth/bluedroid/ble/gatt_server/sdkconfig.defaults.esp32s3 index 3d19f688a2..d9423ad1e4 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_server/sdkconfig.defaults.esp32s3 +++ b/examples/bluetooth/bluedroid/ble/gatt_server/sdkconfig.defaults.esp32s3 @@ -477,7 +477,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32S3=y CONFIG_BT_SOC_SUPPORT_5_0=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 @@ -550,7 +549,7 @@ CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 # -# Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # CONFIG_BT_CTRL_PINNED_TO_CORE_1 is not set @@ -559,7 +558,7 @@ CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # MODEM SLEEP Options # # end of MODEM SLEEP Options -# end of Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# end of Bluetooth controller CONFIG_BT_BLUEDROID_ENABLED=y # CONFIG_BT_NIMBLE_ENABLED is not set @@ -769,7 +768,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/gatt_server/tutorial/Gatt_Server_Example_Walkthrough.md b/examples/bluetooth/bluedroid/ble/gatt_server/tutorial/Gatt_Server_Example_Walkthrough.md index 89dea52147..2f7ccdba80 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_server/tutorial/Gatt_Server_Example_Walkthrough.md +++ b/examples/bluetooth/bluedroid/ble/gatt_server/tutorial/Gatt_Server_Example_Walkthrough.md @@ -430,7 +430,7 @@ static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_ ## Creating Services -The register event is also used to create a profile attributes table by using the `esp_ble_gatts_create_attr_tab()` function, which takes an `esp_gatts_attr_db_t` type structure that has all the information of the service table. The way to create this table is: +The register event is also used to create a service by using the `esp_ble_gatts_create_service()`. When service creation is done, a callback event ESP_GATTS_CREATE_EVT is called to report status and service ID to the profile. The way to create service is: ```c … diff --git a/examples/bluetooth/bluedroid/ble/gatt_server_service_table/sdkconfig.defaults.esp32 b/examples/bluetooth/bluedroid/ble/gatt_server_service_table/sdkconfig.defaults.esp32 index 12731ad6fa..6d8e7e6376 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_server_service_table/sdkconfig.defaults.esp32 +++ b/examples/bluetooth/bluedroid/ble/gatt_server_service_table/sdkconfig.defaults.esp32 @@ -410,10 +410,9 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32=y # -# Bluetooth controller(ESP32 Dual Mode Bluetooth) +# Bluetooth controller # CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y # CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY is not set @@ -454,7 +453,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # CONFIG_BTDM_COEX_BT_OPTIONS is not set -# end of Bluetooth controller(ESP32 Dual Mode Bluetooth) +# end of Bluetooth controller CONFIG_BTDM_CTRL_HW_CCA_EFF=0 CONFIG_BTDM_CTRL_DFT_TX_POWER_LEVEL_EFF=0 @@ -671,7 +670,7 @@ CONFIG_BT_ACL_CONNECTIONS=4 # CONFIG_BT_BLE_HOST_QUEUE_CONG_CHECK is not set # CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN is not set CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 -CONFIG_BT_RESERVE_DRAM=0xdb5c +CONFIG_BTDM_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/gatt_server_service_table/sdkconfig.defaults.esp32c3 b/examples/bluetooth/bluedroid/ble/gatt_server_service_table/sdkconfig.defaults.esp32c3 index 178e59e007..b1f9689350 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_server_service_table/sdkconfig.defaults.esp32c3 +++ b/examples/bluetooth/bluedroid/ble/gatt_server_service_table/sdkconfig.defaults.esp32c3 @@ -367,7 +367,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 @@ -382,7 +381,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # -# Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_MODE_EFF=1 CONFIG_BT_CTRL_BLE_MAX_ACT=10 @@ -426,7 +425,7 @@ CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF=7 CONFIG_BT_CTRL_SLEEP_MODE_EFF=0 CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 -# end of Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# end of Bluetooth controller # # MODEM SLEEP Options @@ -639,7 +638,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/gatt_server_service_table/sdkconfig.defaults.esp32s3 b/examples/bluetooth/bluedroid/ble/gatt_server_service_table/sdkconfig.defaults.esp32s3 index 3d19f688a2..d9423ad1e4 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_server_service_table/sdkconfig.defaults.esp32s3 +++ b/examples/bluetooth/bluedroid/ble/gatt_server_service_table/sdkconfig.defaults.esp32s3 @@ -477,7 +477,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32S3=y CONFIG_BT_SOC_SUPPORT_5_0=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 @@ -550,7 +549,7 @@ CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 # -# Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # CONFIG_BT_CTRL_PINNED_TO_CORE_1 is not set @@ -559,7 +558,7 @@ CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # MODEM SLEEP Options # # end of MODEM SLEEP Options -# end of Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# end of Bluetooth controller CONFIG_BT_BLUEDROID_ENABLED=y # CONFIG_BT_NIMBLE_ENABLED is not set @@ -769,7 +768,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/gattc_multi_connect/sdkconfig.defaults.esp32 b/examples/bluetooth/bluedroid/ble/gattc_multi_connect/sdkconfig.defaults.esp32 index 92acd27f33..9b30e9aac3 100644 --- a/examples/bluetooth/bluedroid/ble/gattc_multi_connect/sdkconfig.defaults.esp32 +++ b/examples/bluetooth/bluedroid/ble/gattc_multi_connect/sdkconfig.defaults.esp32 @@ -416,10 +416,9 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32=y # -# Bluetooth controller(ESP32 Dual Mode Bluetooth) +# Bluetooth controller # CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y # CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY is not set @@ -460,7 +459,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # CONFIG_BTDM_COEX_BT_OPTIONS is not set -# end of Bluetooth controller(ESP32 Dual Mode Bluetooth) +# end of Bluetooth controller CONFIG_BTDM_CTRL_HW_CCA_EFF=0 CONFIG_BTDM_CTRL_DFT_TX_POWER_LEVEL_EFF=0 @@ -673,7 +672,7 @@ CONFIG_BT_ACL_CONNECTIONS=4 # CONFIG_BT_BLE_HOST_QUEUE_CONG_CHECK is not set # CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN is not set CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 -CONFIG_BT_RESERVE_DRAM=0xdb5c +CONFIG_BTDM_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/gattc_multi_connect/sdkconfig.defaults.esp32c3 b/examples/bluetooth/bluedroid/ble/gattc_multi_connect/sdkconfig.defaults.esp32c3 index 178e59e007..b1f9689350 100644 --- a/examples/bluetooth/bluedroid/ble/gattc_multi_connect/sdkconfig.defaults.esp32c3 +++ b/examples/bluetooth/bluedroid/ble/gattc_multi_connect/sdkconfig.defaults.esp32c3 @@ -367,7 +367,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 @@ -382,7 +381,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # -# Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_MODE_EFF=1 CONFIG_BT_CTRL_BLE_MAX_ACT=10 @@ -426,7 +425,7 @@ CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF=7 CONFIG_BT_CTRL_SLEEP_MODE_EFF=0 CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 -# end of Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# end of Bluetooth controller # # MODEM SLEEP Options @@ -639,7 +638,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble/gattc_multi_connect/sdkconfig.defaults.esp32s3 b/examples/bluetooth/bluedroid/ble/gattc_multi_connect/sdkconfig.defaults.esp32s3 index 3d19f688a2..d9423ad1e4 100644 --- a/examples/bluetooth/bluedroid/ble/gattc_multi_connect/sdkconfig.defaults.esp32s3 +++ b/examples/bluetooth/bluedroid/ble/gattc_multi_connect/sdkconfig.defaults.esp32s3 @@ -477,7 +477,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32S3=y CONFIG_BT_SOC_SUPPORT_5_0=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 @@ -550,7 +549,7 @@ CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 # -# Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # CONFIG_BT_CTRL_PINNED_TO_CORE_1 is not set @@ -559,7 +558,7 @@ CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # MODEM SLEEP Options # # end of MODEM SLEEP Options -# end of Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# end of Bluetooth controller CONFIG_BT_BLUEDROID_ENABLED=y # CONFIG_BT_NIMBLE_ENABLED is not set @@ -769,7 +768,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble_50/ble50_security_client/sdkconfig.defaults b/examples/bluetooth/bluedroid/ble_50/ble50_security_client/sdkconfig.defaults index 35138cc4a4..b9e05235d6 100644 --- a/examples/bluetooth/bluedroid/ble_50/ble50_security_client/sdkconfig.defaults +++ b/examples/bluetooth/bluedroid/ble_50/ble50_security_client/sdkconfig.defaults @@ -348,7 +348,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 @@ -372,7 +371,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # -# Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BTDM_CTRL_MODE_EFF=1 CONFIG_BTDM_CTRL_BLE_MAX_ACT=10 @@ -412,7 +411,7 @@ CONFIG_BTDM_CTRL_DFT_TX_POWER_LEVEL_EFF=7 CONFIG_BTDM_CTRL_SLEEP_MODE_EFF=0 CONFIG_BTDM_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BTDM_CTRL_HCI_TL_EFF=1 -# end of Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# end of Bluetooth controller CONFIG_BT_BLUEDROID_ENABLED=y # CONFIG_BT_NIMBLE_ENABLED is not set @@ -615,7 +614,7 @@ CONFIG_BT_SMP_ENABLE=y CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y CONFIG_BT_BLE_50_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c +CONFIG_BTDM_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble_50/ble50_security_client/sdkconfig.defaults.esp32c3 b/examples/bluetooth/bluedroid/ble_50/ble50_security_client/sdkconfig.defaults.esp32c3 index 78aa64c78a..d2705431cf 100644 --- a/examples/bluetooth/bluedroid/ble_50/ble50_security_client/sdkconfig.defaults.esp32c3 +++ b/examples/bluetooth/bluedroid/ble_50/ble50_security_client/sdkconfig.defaults.esp32c3 @@ -367,7 +367,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 @@ -382,7 +381,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # -# Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_MODE_EFF=1 CONFIG_BT_CTRL_BLE_MAX_ACT=10 @@ -426,7 +425,7 @@ CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF=7 CONFIG_BT_CTRL_SLEEP_MODE_EFF=0 CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 -# end of Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# end of Bluetooth controller # # MODEM SLEEP Options @@ -639,7 +638,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y CONFIG_BT_BLE_50_FEATURES_SUPPORTED=y # CONFIG_BT_BLE_42_FEATURES_SUPPORTED is not set -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble_50/ble50_security_client/sdkconfig.defaults.esp32s3 b/examples/bluetooth/bluedroid/ble_50/ble50_security_client/sdkconfig.defaults.esp32s3 index 6618f89b66..202928bee7 100644 --- a/examples/bluetooth/bluedroid/ble_50/ble50_security_client/sdkconfig.defaults.esp32s3 +++ b/examples/bluetooth/bluedroid/ble_50/ble50_security_client/sdkconfig.defaults.esp32s3 @@ -472,7 +472,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32S3=y CONFIG_BT_SOC_SUPPORT_5_0=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 @@ -545,14 +544,14 @@ CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 # -# Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# Bluetooth controller # # # MODEM SLEEP Options # # end of MODEM SLEEP Options -# end of Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# end of Bluetooth controller CONFIG_BT_BLUEDROID_ENABLED=y # CONFIG_BT_NIMBLE_ENABLED is not set @@ -760,7 +759,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y CONFIG_BT_BLE_50_FEATURES_SUPPORTED=y # CONFIG_BT_BLE_42_FEATURES_SUPPORTED is not set -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble_50/ble50_security_server/sdkconfig.defaults b/examples/bluetooth/bluedroid/ble_50/ble50_security_server/sdkconfig.defaults index 6f36c20f9e..f341a400fd 100644 --- a/examples/bluetooth/bluedroid/ble_50/ble50_security_server/sdkconfig.defaults +++ b/examples/bluetooth/bluedroid/ble_50/ble50_security_server/sdkconfig.defaults @@ -348,7 +348,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 @@ -372,7 +371,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # -# Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BTDM_CTRL_MODE_EFF=1 CONFIG_BTDM_CTRL_BLE_MAX_ACT=10 @@ -412,7 +411,7 @@ CONFIG_BTDM_CTRL_DFT_TX_POWER_LEVEL_EFF=7 CONFIG_BTDM_CTRL_SLEEP_MODE_EFF=0 CONFIG_BTDM_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BTDM_CTRL_HCI_TL_EFF=1 -# end of Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# end of Bluetooth controller CONFIG_BT_BLUEDROID_ENABLED=y # CONFIG_BT_NIMBLE_ENABLED is not set @@ -619,7 +618,6 @@ CONFIG_BT_SMP_ENABLE=y CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y CONFIG_BT_BLE_50_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble_50/ble50_security_server/sdkconfig.defaults.esp32c3 b/examples/bluetooth/bluedroid/ble_50/ble50_security_server/sdkconfig.defaults.esp32c3 index 78aa64c78a..d2705431cf 100644 --- a/examples/bluetooth/bluedroid/ble_50/ble50_security_server/sdkconfig.defaults.esp32c3 +++ b/examples/bluetooth/bluedroid/ble_50/ble50_security_server/sdkconfig.defaults.esp32c3 @@ -367,7 +367,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 @@ -382,7 +381,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # -# Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_MODE_EFF=1 CONFIG_BT_CTRL_BLE_MAX_ACT=10 @@ -426,7 +425,7 @@ CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF=7 CONFIG_BT_CTRL_SLEEP_MODE_EFF=0 CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 -# end of Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# end of Bluetooth controller # # MODEM SLEEP Options @@ -639,7 +638,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y CONFIG_BT_BLE_50_FEATURES_SUPPORTED=y # CONFIG_BT_BLE_42_FEATURES_SUPPORTED is not set -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble_50/ble50_security_server/sdkconfig.defaults.esp32s3 b/examples/bluetooth/bluedroid/ble_50/ble50_security_server/sdkconfig.defaults.esp32s3 index 6618f89b66..202928bee7 100644 --- a/examples/bluetooth/bluedroid/ble_50/ble50_security_server/sdkconfig.defaults.esp32s3 +++ b/examples/bluetooth/bluedroid/ble_50/ble50_security_server/sdkconfig.defaults.esp32s3 @@ -472,7 +472,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32S3=y CONFIG_BT_SOC_SUPPORT_5_0=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 @@ -545,14 +544,14 @@ CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 # -# Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# Bluetooth controller # # # MODEM SLEEP Options # # end of MODEM SLEEP Options -# end of Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# end of Bluetooth controller CONFIG_BT_BLUEDROID_ENABLED=y # CONFIG_BT_NIMBLE_ENABLED is not set @@ -760,7 +759,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y CONFIG_BT_BLE_50_FEATURES_SUPPORTED=y # CONFIG_BT_BLE_42_FEATURES_SUPPORTED is not set -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble_50/multi-adv/sdkconfig.defaults b/examples/bluetooth/bluedroid/ble_50/multi-adv/sdkconfig.defaults index 0cb3805766..9cd61576dd 100644 --- a/examples/bluetooth/bluedroid/ble_50/multi-adv/sdkconfig.defaults +++ b/examples/bluetooth/bluedroid/ble_50/multi-adv/sdkconfig.defaults @@ -348,7 +348,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 @@ -366,7 +365,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # -# Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BTDM_CTRL_MODE_EFF=1 CONFIG_BTDM_CTRL_BLE_MAX_ACT=10 @@ -406,7 +405,7 @@ CONFIG_BTDM_CTRL_DFT_TX_POWER_LEVEL_EFF=7 CONFIG_BTDM_CTRL_SLEEP_MODE_EFF=0 CONFIG_BTDM_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BTDM_CTRL_HCI_TL_EFF=1 -# end of Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# end of Bluetooth controller CONFIG_BT_BLUEDROID_ENABLED=y # CONFIG_BT_NIMBLE_ENABLED is not set @@ -606,7 +605,7 @@ CONFIG_BT_ACL_CONNECTIONS=4 CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y CONFIG_BT_BLE_50_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c +CONFIG_BTDM_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble_50/multi-adv/sdkconfig.defaults.esp32c3 b/examples/bluetooth/bluedroid/ble_50/multi-adv/sdkconfig.defaults.esp32c3 index 78aa64c78a..d2705431cf 100644 --- a/examples/bluetooth/bluedroid/ble_50/multi-adv/sdkconfig.defaults.esp32c3 +++ b/examples/bluetooth/bluedroid/ble_50/multi-adv/sdkconfig.defaults.esp32c3 @@ -367,7 +367,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 @@ -382,7 +381,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # -# Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_MODE_EFF=1 CONFIG_BT_CTRL_BLE_MAX_ACT=10 @@ -426,7 +425,7 @@ CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF=7 CONFIG_BT_CTRL_SLEEP_MODE_EFF=0 CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 -# end of Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# end of Bluetooth controller # # MODEM SLEEP Options @@ -639,7 +638,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y CONFIG_BT_BLE_50_FEATURES_SUPPORTED=y # CONFIG_BT_BLE_42_FEATURES_SUPPORTED is not set -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble_50/multi-adv/sdkconfig.defaults.esp32s3 b/examples/bluetooth/bluedroid/ble_50/multi-adv/sdkconfig.defaults.esp32s3 index 6618f89b66..202928bee7 100644 --- a/examples/bluetooth/bluedroid/ble_50/multi-adv/sdkconfig.defaults.esp32s3 +++ b/examples/bluetooth/bluedroid/ble_50/multi-adv/sdkconfig.defaults.esp32s3 @@ -472,7 +472,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32S3=y CONFIG_BT_SOC_SUPPORT_5_0=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 @@ -545,14 +544,14 @@ CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 # -# Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# Bluetooth controller # # # MODEM SLEEP Options # # end of MODEM SLEEP Options -# end of Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# end of Bluetooth controller CONFIG_BT_BLUEDROID_ENABLED=y # CONFIG_BT_NIMBLE_ENABLED is not set @@ -760,7 +759,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y CONFIG_BT_BLE_50_FEATURES_SUPPORTED=y # CONFIG_BT_BLE_42_FEATURES_SUPPORTED is not set -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble_50/peroidic_adv/sdkconfig.defaults b/examples/bluetooth/bluedroid/ble_50/peroidic_adv/sdkconfig.defaults index 0cb3805766..9cd61576dd 100644 --- a/examples/bluetooth/bluedroid/ble_50/peroidic_adv/sdkconfig.defaults +++ b/examples/bluetooth/bluedroid/ble_50/peroidic_adv/sdkconfig.defaults @@ -348,7 +348,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 @@ -366,7 +365,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # -# Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BTDM_CTRL_MODE_EFF=1 CONFIG_BTDM_CTRL_BLE_MAX_ACT=10 @@ -406,7 +405,7 @@ CONFIG_BTDM_CTRL_DFT_TX_POWER_LEVEL_EFF=7 CONFIG_BTDM_CTRL_SLEEP_MODE_EFF=0 CONFIG_BTDM_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BTDM_CTRL_HCI_TL_EFF=1 -# end of Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# end of Bluetooth controller CONFIG_BT_BLUEDROID_ENABLED=y # CONFIG_BT_NIMBLE_ENABLED is not set @@ -606,7 +605,7 @@ CONFIG_BT_ACL_CONNECTIONS=4 CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y CONFIG_BT_BLE_50_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c +CONFIG_BTDM_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble_50/peroidic_adv/sdkconfig.defaults.esp32c3 b/examples/bluetooth/bluedroid/ble_50/peroidic_adv/sdkconfig.defaults.esp32c3 index 78aa64c78a..d2705431cf 100644 --- a/examples/bluetooth/bluedroid/ble_50/peroidic_adv/sdkconfig.defaults.esp32c3 +++ b/examples/bluetooth/bluedroid/ble_50/peroidic_adv/sdkconfig.defaults.esp32c3 @@ -367,7 +367,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 @@ -382,7 +381,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # -# Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_MODE_EFF=1 CONFIG_BT_CTRL_BLE_MAX_ACT=10 @@ -426,7 +425,7 @@ CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF=7 CONFIG_BT_CTRL_SLEEP_MODE_EFF=0 CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 -# end of Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# end of Bluetooth controller # # MODEM SLEEP Options @@ -639,7 +638,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y CONFIG_BT_BLE_50_FEATURES_SUPPORTED=y # CONFIG_BT_BLE_42_FEATURES_SUPPORTED is not set -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble_50/peroidic_adv/sdkconfig.defaults.esp32s3 b/examples/bluetooth/bluedroid/ble_50/peroidic_adv/sdkconfig.defaults.esp32s3 index 6618f89b66..202928bee7 100644 --- a/examples/bluetooth/bluedroid/ble_50/peroidic_adv/sdkconfig.defaults.esp32s3 +++ b/examples/bluetooth/bluedroid/ble_50/peroidic_adv/sdkconfig.defaults.esp32s3 @@ -472,7 +472,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32S3=y CONFIG_BT_SOC_SUPPORT_5_0=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 @@ -545,14 +544,14 @@ CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 # -# Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# Bluetooth controller # # # MODEM SLEEP Options # # end of MODEM SLEEP Options -# end of Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# end of Bluetooth controller CONFIG_BT_BLUEDROID_ENABLED=y # CONFIG_BT_NIMBLE_ENABLED is not set @@ -760,7 +759,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y CONFIG_BT_BLE_50_FEATURES_SUPPORTED=y # CONFIG_BT_BLE_42_FEATURES_SUPPORTED is not set -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble_50/peroidic_sync/sdkconfig.defaults b/examples/bluetooth/bluedroid/ble_50/peroidic_sync/sdkconfig.defaults index 0cb3805766..9cd61576dd 100644 --- a/examples/bluetooth/bluedroid/ble_50/peroidic_sync/sdkconfig.defaults +++ b/examples/bluetooth/bluedroid/ble_50/peroidic_sync/sdkconfig.defaults @@ -348,7 +348,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 @@ -366,7 +365,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # -# Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BTDM_CTRL_MODE_EFF=1 CONFIG_BTDM_CTRL_BLE_MAX_ACT=10 @@ -406,7 +405,7 @@ CONFIG_BTDM_CTRL_DFT_TX_POWER_LEVEL_EFF=7 CONFIG_BTDM_CTRL_SLEEP_MODE_EFF=0 CONFIG_BTDM_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BTDM_CTRL_HCI_TL_EFF=1 -# end of Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# end of Bluetooth controller CONFIG_BT_BLUEDROID_ENABLED=y # CONFIG_BT_NIMBLE_ENABLED is not set @@ -606,7 +605,7 @@ CONFIG_BT_ACL_CONNECTIONS=4 CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y CONFIG_BT_BLE_50_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c +CONFIG_BTDM_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble_50/peroidic_sync/sdkconfig.defaults.esp32c3 b/examples/bluetooth/bluedroid/ble_50/peroidic_sync/sdkconfig.defaults.esp32c3 index 78aa64c78a..d2705431cf 100644 --- a/examples/bluetooth/bluedroid/ble_50/peroidic_sync/sdkconfig.defaults.esp32c3 +++ b/examples/bluetooth/bluedroid/ble_50/peroidic_sync/sdkconfig.defaults.esp32c3 @@ -367,7 +367,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 @@ -382,7 +381,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # -# Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_MODE_EFF=1 CONFIG_BT_CTRL_BLE_MAX_ACT=10 @@ -426,7 +425,7 @@ CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF=7 CONFIG_BT_CTRL_SLEEP_MODE_EFF=0 CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 -# end of Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# end of Bluetooth controller # # MODEM SLEEP Options @@ -639,7 +638,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y CONFIG_BT_BLE_50_FEATURES_SUPPORTED=y # CONFIG_BT_BLE_42_FEATURES_SUPPORTED is not set -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/ble_50/peroidic_sync/sdkconfig.defaults.esp32s3 b/examples/bluetooth/bluedroid/ble_50/peroidic_sync/sdkconfig.defaults.esp32s3 index 6618f89b66..202928bee7 100644 --- a/examples/bluetooth/bluedroid/ble_50/peroidic_sync/sdkconfig.defaults.esp32s3 +++ b/examples/bluetooth/bluedroid/ble_50/peroidic_sync/sdkconfig.defaults.esp32s3 @@ -472,7 +472,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32S3=y CONFIG_BT_SOC_SUPPORT_5_0=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 @@ -545,14 +544,14 @@ CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 # -# Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# Bluetooth controller # # # MODEM SLEEP Options # # end of MODEM SLEEP Options -# end of Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# end of Bluetooth controller CONFIG_BT_BLUEDROID_ENABLED=y # CONFIG_BT_NIMBLE_ENABLED is not set @@ -760,7 +759,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y CONFIG_BT_BLE_50_FEATURES_SUPPORTED=y # CONFIG_BT_BLE_42_FEATURES_SUPPORTED is not set -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/classic_bt/bt_hid_mouse_device/CMakeLists.txt b/examples/bluetooth/bluedroid/classic_bt/bt_hid_mouse_device/CMakeLists.txt new file mode 100644 index 0000000000..03756ccaba --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/bt_hid_mouse_device/CMakeLists.txt @@ -0,0 +1,7 @@ + +# 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.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(bt_hid_mouse_device) diff --git a/examples/peripherals/mcpwm/mcpwm_bldc_control/Makefile b/examples/bluetooth/bluedroid/classic_bt/bt_hid_mouse_device/Makefile similarity index 76% rename from examples/peripherals/mcpwm/mcpwm_bldc_control/Makefile rename to examples/bluetooth/bluedroid/classic_bt/bt_hid_mouse_device/Makefile index eb1842cc7b..9f94f135ec 100644 --- a/examples/peripherals/mcpwm/mcpwm_bldc_control/Makefile +++ b/examples/bluetooth/bluedroid/classic_bt/bt_hid_mouse_device/Makefile @@ -3,6 +3,6 @@ # project subdirectory. # -PROJECT_NAME := mcpwm_bldc_control_hall_sensor +PROJECT_NAME := bt_hid_mouse_device include $(IDF_PATH)/make/project.mk diff --git a/examples/bluetooth/bluedroid/classic_bt/bt_hid_mouse_device/README.md b/examples/bluetooth/bluedroid/classic_bt/bt_hid_mouse_device/README.md new file mode 100644 index 0000000000..16d12a71ac --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/bt_hid_mouse_device/README.md @@ -0,0 +1,11 @@ +| Supported Targets | ESP32 | +| ----------------- | ----- | + +# ESP-IDF HID Device over Bluetooth Classic Demo + +Demo of HID Device over Bluetooth Classic. + +This turns the device into a mouse, but can be altered to be any kind of HID device. + +After loading the code, connect with a computer to a device broadcasting +as "HID Mouse Example". The mouse should move left and right while they are connected. diff --git a/examples/bluetooth/bluedroid/classic_bt/bt_hid_mouse_device/main/CMakeLists.txt b/examples/bluetooth/bluedroid/classic_bt/bt_hid_mouse_device/main/CMakeLists.txt new file mode 100644 index 0000000000..5d47675980 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/bt_hid_mouse_device/main/CMakeLists.txt @@ -0,0 +1,7 @@ +#set(COMPONENT_SRCS "main.c") +#set(COMPONENT_ADD_INCLUDEDIRS "") + +#register_component() + +idf_component_register(SRCS "main.c" + INCLUDE_DIRS ".") diff --git a/examples/wifi/simple_sniffer/main/component.mk b/examples/bluetooth/bluedroid/classic_bt/bt_hid_mouse_device/main/component.mk similarity index 100% rename from examples/wifi/simple_sniffer/main/component.mk rename to examples/bluetooth/bluedroid/classic_bt/bt_hid_mouse_device/main/component.mk diff --git a/examples/bluetooth/bluedroid/classic_bt/bt_hid_mouse_device/main/main.c b/examples/bluetooth/bluedroid/classic_bt/bt_hid_mouse_device/main/main.c new file mode 100644 index 0000000000..c7d753fc82 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/bt_hid_mouse_device/main/main.c @@ -0,0 +1,436 @@ + +#include "esp_log.h" +#include "esp_hidd_api.h" +#include "esp_bt_main.h" +#include "esp_bt_device.h" +#include "esp_bt.h" +#include "esp_err.h" +#include "nvs.h" +#include "nvs_flash.h" +#include "esp_gap_bt_api.h" +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" + +#define BOOT_PROTO_MOUSE_RPT_ID 0x02 +typedef struct +{ + esp_hidd_app_param_t app_param; + esp_hidd_qos_param_t both_qos; + uint8_t protocol_mode; + SemaphoreHandle_t mouse_mutex; + xTaskHandle mouse_task_hdl; + uint8_t buffer[4]; + int8_t x_dir; +} local_param_t; + +static local_param_t s_local_param = {0}; + +bool check_report_id_type(uint8_t report_id, uint8_t report_type) +{ + bool ret = false; + xSemaphoreTake(s_local_param.mouse_mutex, portMAX_DELAY); + do { + if (report_type != ESP_HIDD_REPORT_TYPE_INPUT) { + break; + } + if (s_local_param.protocol_mode == ESP_HIDD_BOOT_MODE) { + if (report_id == BOOT_PROTO_MOUSE_RPT_ID) { + ret = true; + break; + } + } else { + if (report_id == 0) { + ret = true; + break; + } + } + } while (0); + + if (!ret) { + if (s_local_param.protocol_mode == ESP_HIDD_BOOT_MODE) { + esp_bt_hid_device_report_error(ESP_HID_PAR_HANDSHAKE_RSP_ERR_INVALID_REP_ID); + } else { + esp_bt_hid_device_report_error(ESP_HID_PAR_HANDSHAKE_RSP_ERR_INVALID_REP_ID); + } + } + xSemaphoreGive(s_local_param.mouse_mutex); + return ret; +} + +// send the buttons, change in x, and change in y +void send_mouse(uint8_t buttons, char dx, char dy, char wheel) +{ + xSemaphoreTake(s_local_param.mouse_mutex, portMAX_DELAY); + if (s_local_param.protocol_mode == ESP_HIDD_REPORT_MODE) { + s_local_param.buffer[0] = buttons; + s_local_param.buffer[1] = dx; + s_local_param.buffer[2] = dy; + s_local_param.buffer[3] = wheel; + esp_bt_hid_device_send_report(ESP_HIDD_REPORT_TYPE_INTRDATA, 0x00, 4, s_local_param.buffer); + } else if (s_local_param.protocol_mode == ESP_HIDD_BOOT_MODE) { + s_local_param.buffer[0] = buttons; + s_local_param.buffer[1] = dx; + s_local_param.buffer[2] = dy; + esp_bt_hid_device_send_report(ESP_HIDD_REPORT_TYPE_INTRDATA, BOOT_PROTO_MOUSE_RPT_ID, 3, s_local_param.buffer); + } + xSemaphoreGive(s_local_param.mouse_mutex); +} + +// move the mouse left and right +void mouse_move_task(void* pvParameters) { + const char* TAG = "mouse_move_task"; + + ESP_LOGI(TAG, "starting"); + for(;;) { + s_local_param.x_dir = 1; + int8_t step = 10; + for (int i = 0; i < 2; i++) { + xSemaphoreTake(s_local_param.mouse_mutex, portMAX_DELAY); + s_local_param.x_dir *= -1; + xSemaphoreGive(s_local_param.mouse_mutex); + for (int j = 0; j < 100; j++) { + send_mouse(0, s_local_param.x_dir * step, 0, 0); + vTaskDelay(50 / portTICK_PERIOD_MS); + } + } + vTaskDelay(1000 / portTICK_PERIOD_MS); + } +} + +static void print_bt_address(void) { + const char* TAG = "bt_address"; + const uint8_t* bd_addr; + + bd_addr = esp_bt_dev_get_address(); + ESP_LOGI(TAG, "my bluetooth address is %02X:%02X:%02X:%02X:%02X:%02X", + bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]); +} + +// a generic mouse descriptor +uint8_t hid_descriptor_mouse_boot_mode[] = { + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x02, // USAGE (Mouse) + 0xa1, 0x01, // COLLECTION (Application) + + 0x09, 0x01, // USAGE (Pointer) + 0xa1, 0x00, // COLLECTION (Physical) + + 0x05, 0x09, // USAGE_PAGE (Button) + 0x19, 0x01, // USAGE_MINIMUM (Button 1) + 0x29, 0x03, // USAGE_MAXIMUM (Button 3) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x95, 0x03, // REPORT_COUNT (3) + 0x75, 0x01, // REPORT_SIZE (1) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0x95, 0x01, // REPORT_COUNT (1) + 0x75, 0x05, // REPORT_SIZE (5) + 0x81, 0x03, // INPUT (Cnst,Var,Abs) + + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x30, // USAGE (X) + 0x09, 0x31, // USAGE (Y) + 0x09, 0x38, // USAGE (Wheel) + 0x15, 0x81, // LOGICAL_MINIMUM (-127) + 0x25, 0x7f, // LOGICAL_MAXIMUM (127) + 0x75, 0x08, // REPORT_SIZE (8) + 0x95, 0x03, // REPORT_COUNT (3) + 0x81, 0x06, // INPUT (Data,Var,Rel) + + 0xc0, // END_COLLECTION + 0xc0 // END_COLLECTION +}; +int hid_descriptor_mouse_boot_mode_len = sizeof(hid_descriptor_mouse_boot_mode); + +void esp_bt_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param) +{ + const char* TAG = "esp_bt_gap_cb"; + switch (event) { + case ESP_BT_GAP_AUTH_CMPL_EVT:{ + if (param->auth_cmpl.stat == ESP_BT_STATUS_SUCCESS) { + ESP_LOGI(TAG, "authentication success: %s", param->auth_cmpl.device_name); + esp_log_buffer_hex(TAG, param->auth_cmpl.bda, ESP_BD_ADDR_LEN); + } else { + ESP_LOGE(TAG, "authentication failed, status:%d", param->auth_cmpl.stat); + } + break; + } + case ESP_BT_GAP_PIN_REQ_EVT:{ + ESP_LOGI(TAG, "ESP_BT_GAP_PIN_REQ_EVT min_16_digit:%d", param->pin_req.min_16_digit); + if (param->pin_req.min_16_digit) { + ESP_LOGI(TAG, "Input pin code: 0000 0000 0000 0000"); + esp_bt_pin_code_t pin_code = {0}; + esp_bt_gap_pin_reply(param->pin_req.bda, true, 16, pin_code); + } else { + ESP_LOGI(TAG, "Input pin code: 1234"); + esp_bt_pin_code_t pin_code; + pin_code[0] = '1'; + pin_code[1] = '2'; + pin_code[2] = '3'; + pin_code[3] = '4'; + esp_bt_gap_pin_reply(param->pin_req.bda, true, 4, pin_code); + } + break; + } + +#if (CONFIG_BT_SSP_ENABLED == true) + case ESP_BT_GAP_CFM_REQ_EVT: + ESP_LOGI(TAG, "ESP_BT_GAP_CFM_REQ_EVT Please compare the numeric value: %d", param->cfm_req.num_val); + esp_bt_gap_ssp_confirm_reply(param->cfm_req.bda, true); + break; + case ESP_BT_GAP_KEY_NOTIF_EVT: + ESP_LOGI(TAG, "ESP_BT_GAP_KEY_NOTIF_EVT passkey:%d", param->key_notif.passkey); + break; + case ESP_BT_GAP_KEY_REQ_EVT: + ESP_LOGI(TAG, "ESP_BT_GAP_KEY_REQ_EVT Please enter passkey!"); + break; +#endif + case ESP_BT_GAP_MODE_CHG_EVT: + ESP_LOGI(TAG, "ESP_BT_GAP_MODE_CHG_EVT mode:%d", param->mode_chg.mode); + break; + default: + ESP_LOGI(TAG, "event: %d", event); + break; + } + return; +} + +void bt_app_task_start_up(void) +{ + s_local_param.mouse_mutex = xSemaphoreCreateMutex(); + memset(s_local_param.buffer, 0, 4); + xTaskCreate(mouse_move_task, "mouse_move_task", 2 * 1024, NULL, configMAX_PRIORITIES - 3, &s_local_param.mouse_task_hdl); + return; +} + +void bt_app_task_shut_down(void) +{ + if (s_local_param.mouse_task_hdl) { + vTaskDelete(s_local_param.mouse_task_hdl); + s_local_param.mouse_task_hdl = NULL; + } + + if (s_local_param.mouse_mutex) { + vSemaphoreDelete(s_local_param.mouse_mutex); + s_local_param.mouse_mutex = NULL; + } + return; +} + +void esp_bt_hidd_cb(esp_hidd_cb_event_t event, esp_hidd_cb_param_t *param) +{ + static const char* TAG = "esp_bt_hidd_cb"; + switch (event) { + case ESP_HIDD_INIT_EVT: + if (param->init.status == ESP_HIDD_SUCCESS) { + ESP_LOGI(TAG, "setting hid parameters"); + esp_bt_hid_device_register_app(&s_local_param.app_param, &s_local_param.both_qos, &s_local_param.both_qos); + } else { + ESP_LOGE(TAG, "init hidd failed!"); + } + break; + case ESP_HIDD_DEINIT_EVT: + break; + case ESP_HIDD_REGISTER_APP_EVT: + if (param->register_app.status == ESP_HIDD_SUCCESS) { + ESP_LOGI(TAG, "setting hid parameters success!"); + ESP_LOGI(TAG, "setting to connectable, discoverable"); + esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE); + if (param->register_app.in_use && param->register_app.bd_addr != NULL) { + ESP_LOGI(TAG, "start virtual cable plug!"); + esp_bt_hid_device_connect(param->register_app.bd_addr); + } + } else { + ESP_LOGE(TAG, "setting hid parameters failed!"); + } + break; + case ESP_HIDD_UNREGISTER_APP_EVT: + if (param->unregister_app.status == ESP_HIDD_SUCCESS) { + ESP_LOGI(TAG, "unregister app success!"); + } else { + ESP_LOGE(TAG, "unregister app failed!"); + } + break; + case ESP_HIDD_OPEN_EVT: + if (param->open.status == ESP_HIDD_SUCCESS) { + if (param->open.conn_status == ESP_HIDD_CONN_STATE_CONNECTING) { + ESP_LOGI(TAG, "connecting..."); + } else if (param->open.conn_status == ESP_HIDD_CONN_STATE_CONNECTED) { + ESP_LOGI(TAG, "connected to %02x:%02x:%02x:%02x:%02x:%02x", param->open.bd_addr[0], + param->open.bd_addr[1], param->open.bd_addr[2], param->open.bd_addr[3], param->open.bd_addr[4], + param->open.bd_addr[5]); + bt_app_task_start_up(); + ESP_LOGI(TAG, "making self non-discoverable and non-connectable."); + esp_bt_gap_set_scan_mode(ESP_BT_NON_CONNECTABLE, ESP_BT_NON_DISCOVERABLE); + } else { + ESP_LOGE(TAG, "unknown connection status"); + } + } else { + ESP_LOGE(TAG, "open failed!"); + } + break; + case ESP_HIDD_CLOSE_EVT: + ESP_LOGI(TAG, "ESP_HIDD_CLOSE_EVT"); + if (param->close.status == ESP_HIDD_SUCCESS) { + if (param->close.conn_status == ESP_HIDD_CONN_STATE_DISCONNECTING) { + ESP_LOGI(TAG, "disconnecting..."); + } else if (param->close.conn_status == ESP_HIDD_CONN_STATE_DISCONNECTED) { + ESP_LOGI(TAG, "disconnected!"); + bt_app_task_shut_down(); + ESP_LOGI(TAG, "making self discoverable and connectable again."); + esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE); + } else { + ESP_LOGE(TAG, "unknown connection status"); + } + } else { + ESP_LOGE(TAG, "close failed!"); + } + break; + case ESP_HIDD_SEND_REPORT_EVT: + ESP_LOGI(TAG, "ESP_HIDD_SEND_REPORT_EVT id:0x%02x, type:%d", param->send_report.report_id, + param->send_report.report_type); + break; + case ESP_HIDD_REPORT_ERR_EVT: + ESP_LOGI(TAG, "ESP_HIDD_REPORT_ERR_EVT"); + break; + case ESP_HIDD_GET_REPORT_EVT: + ESP_LOGI(TAG, "ESP_HIDD_GET_REPORT_EVT id:0x%02x, type:%d, size:%d", param->get_report.report_id, + param->get_report.report_type, param->get_report.buffer_size); + if (check_report_id_type(param->get_report.report_id, param->get_report.report_type)) { + xSemaphoreTake(s_local_param.mouse_mutex, portMAX_DELAY); + if (s_local_param.protocol_mode == ESP_HIDD_REPORT_MODE) { + esp_bt_hid_device_send_report(param->get_report.report_type, 0x00, 4, s_local_param.buffer); + } else if (s_local_param.protocol_mode == ESP_HIDD_BOOT_MODE) { + esp_bt_hid_device_send_report(param->get_report.report_type, 0x02, 3, s_local_param.buffer); + } + xSemaphoreGive(s_local_param.mouse_mutex); + } else { + ESP_LOGE(TAG, "check_report_id failed!"); + } + break; + case ESP_HIDD_SET_REPORT_EVT: + ESP_LOGI(TAG, "ESP_HIDD_SET_REPORT_EVT"); + break; + case ESP_HIDD_SET_PROTOCOL_EVT: + ESP_LOGI(TAG, "ESP_HIDD_SET_PROTOCOL_EVT"); + if (param->set_protocol.protocol_mode == ESP_HIDD_BOOT_MODE) { + ESP_LOGI(TAG, " - boot protocol"); + xSemaphoreTake(s_local_param.mouse_mutex, portMAX_DELAY); + s_local_param.x_dir = -1; + xSemaphoreGive(s_local_param.mouse_mutex); + } else if (param->set_protocol.protocol_mode == ESP_HIDD_REPORT_MODE) { + ESP_LOGI(TAG, " - report protocol"); + } + xSemaphoreTake(s_local_param.mouse_mutex, portMAX_DELAY); + s_local_param.protocol_mode = param->set_protocol.protocol_mode; + xSemaphoreGive(s_local_param.mouse_mutex); + break; + case ESP_HIDD_INTR_DATA_EVT: + ESP_LOGI(TAG, "ESP_HIDD_INTR_DATA_EVT"); + break; + case ESP_HIDD_VC_UNPLUG_EVT: + ESP_LOGI(TAG, "ESP_HIDD_VC_UNPLUG_EVT"); + if (param->vc_unplug.status == ESP_HIDD_SUCCESS) { + if (param->close.conn_status == ESP_HIDD_CONN_STATE_DISCONNECTED) { + ESP_LOGI(TAG, "disconnected!"); + bt_app_task_shut_down(); + ESP_LOGI(TAG, "making self discoverable and connectable again."); + esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE); + } else { + ESP_LOGE(TAG, "unknown connection status"); + } + } else { + ESP_LOGE(TAG, "close failed!"); + } + break; + default: + break; + } +} + +void app_main(void) { + const char* TAG = "app_main"; + esp_err_t ret; + + s_local_param.app_param.name = "Mouse"; + s_local_param.app_param.description = "Mouse Example"; + s_local_param.app_param.provider = "ESP32"; + s_local_param.app_param.subclass = ESP_HID_CLASS_MIC; + s_local_param.app_param.desc_list = hid_descriptor_mouse_boot_mode; + s_local_param.app_param.desc_list_len = hid_descriptor_mouse_boot_mode_len; + memset(&s_local_param.both_qos, 0, sizeof(esp_hidd_qos_param_t)); // don't set the qos parameters + s_local_param.protocol_mode = ESP_HIDD_REPORT_MODE; + + 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(); + } + ESP_ERROR_CHECK( ret ); + + ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_BLE)); + + esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); + if ((ret = esp_bt_controller_init(&bt_cfg)) != ESP_OK) { + ESP_LOGE(TAG, "initialize controller failed: %s\n", esp_err_to_name(ret)); + return; + } + + if ((ret = esp_bt_controller_enable(ESP_BT_MODE_CLASSIC_BT)) != ESP_OK) { + ESP_LOGE(TAG, "enable controller failed: %s\n", esp_err_to_name(ret)); + return; + } + + if ((ret = esp_bluedroid_init()) != ESP_OK) { + ESP_LOGE(TAG, "initialize bluedroid failed: %s\n", esp_err_to_name(ret)); + return; + } + + if ((ret = esp_bluedroid_enable()) != ESP_OK) { + ESP_LOGE(TAG, "enable bluedroid failed: %s\n", esp_err_to_name(ret)); + return; + } + + if ((ret = esp_bt_gap_register_callback(esp_bt_gap_cb)) != ESP_OK) { + ESP_LOGE(TAG, "gap register failed: %s\n", esp_err_to_name(ret)); + return; + } + + + ESP_LOGI(TAG, "setting device name"); + esp_bt_dev_set_device_name("HID Mouse Example"); + + ESP_LOGI(TAG, "setting cod major, peripheral"); + esp_bt_cod_t cod; + cod.major = ESP_BT_COD_MAJOR_DEV_PERIPHERAL; + esp_bt_gap_set_cod(cod ,ESP_BT_SET_COD_MAJOR_MINOR); + + vTaskDelay(2000 / portTICK_PERIOD_MS); + + ESP_LOGI(TAG, "register hid device callback"); + esp_bt_hid_device_register_callback(esp_bt_hidd_cb); + + ESP_LOGI(TAG, "starting hid device"); + esp_bt_hid_device_init(); + +#if (CONFIG_BT_SSP_ENABLED == true) + /* Set default parameters for Secure Simple Pairing */ + esp_bt_sp_param_t param_type = ESP_BT_SP_IOCAP_MODE; + esp_bt_io_cap_t iocap = ESP_BT_IO_CAP_NONE; + esp_bt_gap_set_security_param(param_type, &iocap, sizeof(uint8_t)); +#endif + + /* + * Set default parameters for Legacy Pairing + * Use variable pin, input pin code when pairing + */ + esp_bt_pin_type_t pin_type = ESP_BT_PIN_TYPE_VARIABLE; + esp_bt_pin_code_t pin_code; + esp_bt_gap_set_pin(pin_type, 0, pin_code); + + print_bt_address(); + ESP_LOGI(TAG, "exiting"); +} diff --git a/examples/bluetooth/bluedroid/classic_bt/bt_hid_mouse_device/sdkconfig.defaults b/examples/bluetooth/bluedroid/classic_bt/bt_hid_mouse_device/sdkconfig.defaults new file mode 100644 index 0000000000..c3ff70a003 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/bt_hid_mouse_device/sdkconfig.defaults @@ -0,0 +1,7 @@ +CONFIG_BT_ENABLED=y +CONFIG_BTDM_CTRL_MODE_BLE_ONLY=n +CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=y +CONFIG_BTDM_CTRL_MODE_BTDM=n +CONFIG_BT_CLASSIC_ENABLED=y +CONFIG_BT_HID_ENABLED=y +CONFIG_BT_HID_DEVICE_ENABLED=y diff --git a/examples/bluetooth/bluedroid/classic_bt/bt_spp_acceptor/README.md b/examples/bluetooth/bluedroid/classic_bt/bt_spp_acceptor/README.md index abecbdedbe..aef56168b9 100644 --- a/examples/bluetooth/bluedroid/classic_bt/bt_spp_acceptor/README.md +++ b/examples/bluetooth/bluedroid/classic_bt/bt_spp_acceptor/README.md @@ -43,4 +43,8 @@ After the program started, `bt_spp_initator` will connect it and send data. - To see the information of data, users shall set `SPP_SHOW_MODE` as `SPP_SHOW_DATA` or `SPP_SHOW_SPEED` in code(should be same with `bt_spp_initator`). -- We also show the Security Simple Pair in this SPP demo. Users can set the IO Capability and Security Mode for their device (security level is fixed level 4). The default security mode of this demo is `ESP_SPP_SEC_AUTHENTICATE` which support MITM (Man In The Middle) protection. For more information about Security Simple Pair on ESP32, please refer to [ESP32_SSP](./ESP32_SSP.md). \ No newline at end of file +- We also show the Security Simple Pair in this SPP demo. Users can set the IO Capability and Security Mode for their device (security level is fixed level 4). The default security mode of this demo is `ESP_SPP_SEC_AUTHENTICATE` which support MITM (Man In The Middle) protection. For more information about Security Simple Pair on ESP32, please refer to [ESP32_SSP](./ESP32_SSP.md). + +## FAQ +Q: How many SPP servers does ESP32 support? +A: For now, the maximum number of SPP servers is 6, which is limited by the maximum number of SDP records. When the SPP server is successfully started, the unique SCN (Server Channel Number) will be mapped to the SPP server. diff --git a/examples/bluetooth/bluedroid/classic_bt/bt_spp_initiator/README.md b/examples/bluetooth/bluedroid/classic_bt/bt_spp_initiator/README.md index e6b0d30d88..1a3a509436 100644 --- a/examples/bluetooth/bluedroid/classic_bt/bt_spp_initiator/README.md +++ b/examples/bluetooth/bluedroid/classic_bt/bt_spp_initiator/README.md @@ -119,3 +119,13 @@ To clearly show how the SSP aggregate with the SPP , we use the Commands and Eff - If you want to update the responses of HF Unit or want to update the log, please refer to `bt_app_spp.c`. - Task configuration part is in `example_spp_initiator_demo.c`. + +## FAQ +Q: How can we reach the maximum throughput when using SPP? +A: The default MTU size of classic Bluetooth SPP on ESP32 is 990 bytes, and higher throughput can be achieved in the case that data chunck size is close to the MTU size or multiple of MTU size. For example, sending 100 bytes data per second is much better than sending 10 bytes every 100 milliseconds. + +Q: What is the difference between the event `ESP_SPP_CONG_EVT` and the parameter `cong` of the event `ESP_SPP_WRITE_EVT`? +A: The event `ESP_SPP_CONG_EVT` shows the changing status from `congest` to `uncongest`, or form `uncongest` to `congest`. Congestion can have many causes, such as using out of the credit which is sent by peer, reaching the high watermark of the Tx buffer, the congestion at Bluetooth L2CAP layer and so on. The parameter `cong` of the event `ESP_SPP_WRITE_EVT` shows a snapshot of the state of the flow control manager after the write operation is completed. The user needs to carefully consider retransmitting or continuing to write according to these two events. The ESP32 offers an VFS mode of SPP which hides the details of retransmitting, but it will block the caller and is not more efficient than the callback mode. + +Q: How many SPP clients does ESP32 support? +A: The ESP32 supports maximum 8 SPP clients, which including virtual SPP connections. Virtual SPP connection means that SPP clients can connect to the different SPP servers running on the same peer device. However the number of SPP clients (excluding virtual connections) shall not exceed the number of Bluetooth ACL connections. diff --git a/examples/bluetooth/bluedroid/coex/gattc_gatts_coex/sdkconfig.defaults.esp32c3 b/examples/bluetooth/bluedroid/coex/gattc_gatts_coex/sdkconfig.defaults.esp32c3 index 178e59e007..b1f9689350 100644 --- a/examples/bluetooth/bluedroid/coex/gattc_gatts_coex/sdkconfig.defaults.esp32c3 +++ b/examples/bluetooth/bluedroid/coex/gattc_gatts_coex/sdkconfig.defaults.esp32c3 @@ -367,7 +367,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 @@ -382,7 +381,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # -# Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_MODE_EFF=1 CONFIG_BT_CTRL_BLE_MAX_ACT=10 @@ -426,7 +425,7 @@ CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF=7 CONFIG_BT_CTRL_SLEEP_MODE_EFF=0 CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 -# end of Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# end of Bluetooth controller # # MODEM SLEEP Options @@ -639,7 +638,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/coex/gattc_gatts_coex/sdkconfig.defaults.esp32s3 b/examples/bluetooth/bluedroid/coex/gattc_gatts_coex/sdkconfig.defaults.esp32s3 index 3d19f688a2..d9423ad1e4 100644 --- a/examples/bluetooth/bluedroid/coex/gattc_gatts_coex/sdkconfig.defaults.esp32s3 +++ b/examples/bluetooth/bluedroid/coex/gattc_gatts_coex/sdkconfig.defaults.esp32s3 @@ -477,7 +477,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32S3=y CONFIG_BT_SOC_SUPPORT_5_0=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 @@ -550,7 +549,7 @@ CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 # -# Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # CONFIG_BT_CTRL_PINNED_TO_CORE_1 is not set @@ -559,7 +558,7 @@ CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # MODEM SLEEP Options # # end of MODEM SLEEP Options -# end of Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# end of Bluetooth controller CONFIG_BT_BLUEDROID_ENABLED=y # CONFIG_BT_NIMBLE_ENABLED is not set @@ -769,7 +768,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/bluedroid/coex/gattc_gatts_coex/sdkconfig.defauts.esp32 b/examples/bluetooth/bluedroid/coex/gattc_gatts_coex/sdkconfig.defauts.esp32 index 52cb02588e..64d46d9ee6 100644 --- a/examples/bluetooth/bluedroid/coex/gattc_gatts_coex/sdkconfig.defauts.esp32 +++ b/examples/bluetooth/bluedroid/coex/gattc_gatts_coex/sdkconfig.defauts.esp32 @@ -410,10 +410,9 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32=y # -# Bluetooth controller(ESP32 Dual Mode Bluetooth) +# Bluetooth controller # CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y # CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY is not set @@ -454,7 +453,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # CONFIG_BTDM_COEX_BT_OPTIONS is not set -# end of Bluetooth controller(ESP32 Dual Mode Bluetooth) +# end of Bluetooth controller CONFIG_BTDM_CTRL_HW_CCA_EFF=0 CONFIG_BTDM_CTRL_DFT_TX_POWER_LEVEL_EFF=0 @@ -674,7 +673,7 @@ CONFIG_BT_ACL_CONNECTIONS=4 CONFIG_BT_SMP_ENABLE=y # CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN is not set CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 -CONFIG_BT_RESERVE_DRAM=0xdb5c +CONFIG_BTDM_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/blufi/main/blufi_example.h b/examples/bluetooth/blufi/main/blufi_example.h index d8b92f5d9e..a80e273e67 100644 --- a/examples/bluetooth/blufi/main/blufi_example.h +++ b/examples/bluetooth/blufi/main/blufi_example.h @@ -13,3 +13,4 @@ int blufi_security_init(void); void blufi_security_deinit(void); int esp_blufi_gap_register_callback(void); esp_err_t esp_blufi_host_init(void); +esp_err_t esp_blufi_host_and_cb_init(esp_blufi_callbacks_t *callbacks); diff --git a/examples/bluetooth/blufi/main/blufi_example_main.c b/examples/bluetooth/blufi/main/blufi_example_main.c index 67ff42cb29..4256d00de6 100644 --- a/examples/bluetooth/blufi/main/blufi_example_main.c +++ b/examples/bluetooth/blufi/main/blufi_example_main.c @@ -385,23 +385,11 @@ void app_main(void) return; } - ret = esp_blufi_host_init(); + ret = esp_blufi_host_and_cb_init(&example_callbacks); if (ret) { - BLUFI_ERROR("%s initialise host failed: %s\n", __func__, esp_err_to_name(ret)); + BLUFI_ERROR("%s initialise failed: %s\n", __func__, esp_err_to_name(ret)); return; } BLUFI_INFO("BLUFI VERSION %04x\n", esp_blufi_get_version()); - - ret = esp_blufi_register_callbacks(&example_callbacks); - if(ret){ - BLUFI_ERROR("%s blufi register failed, error code = %x\n", __func__, ret); - return; - } - - ret = esp_blufi_gap_register_callback(); - if(ret){ - BLUFI_ERROR("%s gap register failed, error code = %x\n", __func__, ret); - return; - } } diff --git a/examples/bluetooth/blufi/main/blufi_init.c b/examples/bluetooth/blufi/main/blufi_init.c index 052739b055..04dc13f4eb 100644 --- a/examples/bluetooth/blufi/main/blufi_init.c +++ b/examples/bluetooth/blufi/main/blufi_init.c @@ -3,10 +3,10 @@ #include "esp_blufi_api.h" #include "esp_log.h" #include "esp_blufi.h" +#include "blufi_example.h" #ifdef CONFIG_BT_BLUEDROID_ENABLED #include "esp_bt.h" #include "esp_bt_main.h" -#include "blufi_example.h" #include "esp_bt_device.h" #endif @@ -42,15 +42,40 @@ esp_err_t esp_blufi_host_init(void) } -int esp_blufi_gap_register_callback(void) +esp_err_t esp_blufi_gap_register_callback(void) { int rc; rc = esp_ble_gap_register_callback(esp_blufi_gap_event_handler); if(rc){ return rc; } - esp_blufi_profile_init(); - return 0; + return esp_blufi_profile_init(); +} + +esp_err_t esp_blufi_host_and_cb_init(esp_blufi_callbacks_t *example_callbacks) +{ + esp_err_t ret = ESP_OK; + + ret = esp_blufi_host_init(); + if (ret) { + BLUFI_ERROR("%s initialise host failed: %s\n", __func__, esp_err_to_name(ret)); + return ret; + } + + ret = esp_blufi_register_callbacks(example_callbacks); + if(ret){ + BLUFI_ERROR("%s blufi register failed, error code = %x\n", __func__, ret); + return ret; + } + + ret = esp_blufi_gap_register_callback(); + if(ret){ + BLUFI_ERROR("%s gap register failed, error code = %x\n", __func__, ret); + return ret; + } + + return ESP_OK; + } #endif /* CONFIG_BT_BLUEDROID_ENABLED */ @@ -115,14 +140,42 @@ esp_err_t esp_blufi_host_init(void) /* XXX Need to have template for store */ ble_store_config_init(); - nimble_port_freertos_init(bleprph_host_task); esp_blufi_btc_init(); + + nimble_port_freertos_init(bleprph_host_task); + return ESP_OK; } -int esp_blufi_gap_register_callback(void) +esp_err_t esp_blufi_gap_register_callback(void) { - return 0; + return ESP_OK; } +esp_err_t esp_blufi_host_and_cb_init(esp_blufi_callbacks_t *example_callbacks) +{ + esp_err_t ret = ESP_OK; + + ret = esp_blufi_register_callbacks(example_callbacks); + if(ret){ + BLUFI_ERROR("%s blufi register failed, error code = %x\n", __func__, ret); + return ret; + } + + ret = esp_blufi_gap_register_callback(); + if(ret){ + BLUFI_ERROR("%s gap register failed, error code = %x\n", __func__, ret); + return ret; + } + + ret = esp_blufi_host_init(); + if (ret) { + BLUFI_ERROR("%s initialise host failed: %s\n", __func__, esp_err_to_name(ret)); + return ret; + } + + return ret; +} + + #endif /* CONFIG_BT_NIMBLE_ENABLED */ diff --git a/examples/bluetooth/blufi/sdkconfig.defaults.esp32 b/examples/bluetooth/blufi/sdkconfig.defaults.esp32 index 61abce54cf..7cbc3025e5 100644 --- a/examples/bluetooth/blufi/sdkconfig.defaults.esp32 +++ b/examples/bluetooth/blufi/sdkconfig.defaults.esp32 @@ -398,10 +398,9 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32=y # -# Bluetooth controller(ESP32 Dual Mode Bluetooth) +# Bluetooth controller # CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y # CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY is not set @@ -442,7 +441,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # CONFIG_BTDM_COEX_BT_OPTIONS is not set -# end of Bluetooth controller(ESP32 Dual Mode Bluetooth) +# end of Bluetooth controller CONFIG_BTDM_CTRL_HW_CCA_EFF=0 CONFIG_BTDM_CTRL_DFT_TX_POWER_LEVEL_EFF=0 @@ -659,7 +658,7 @@ CONFIG_BT_ACL_CONNECTIONS=4 # CONFIG_BT_BLE_HOST_QUEUE_CONG_CHECK is not set # CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN is not set CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 -CONFIG_BT_RESERVE_DRAM=0xdb5c +CONFIG_BTDM_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/blufi/sdkconfig.defaults.esp32c3 b/examples/bluetooth/blufi/sdkconfig.defaults.esp32c3 index 1cea2f754e..269599cdb5 100644 --- a/examples/bluetooth/blufi/sdkconfig.defaults.esp32c3 +++ b/examples/bluetooth/blufi/sdkconfig.defaults.esp32c3 @@ -355,7 +355,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 @@ -370,7 +369,7 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # -# Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_MODE_EFF=1 CONFIG_BT_CTRL_BLE_MAX_ACT=10 @@ -412,7 +411,7 @@ CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF=7 CONFIG_BT_CTRL_SLEEP_MODE_EFF=0 CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 -# end of Bluetooth controller(ESP32C3 Bluetooth Low Energy) +# end of Bluetooth controller # # MODEM SLEEP Options @@ -625,7 +624,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/blufi/sdkconfig.defaults.esp32s3 b/examples/bluetooth/blufi/sdkconfig.defaults.esp32s3 index e569824663..42b8c99fea 100644 --- a/examples/bluetooth/blufi/sdkconfig.defaults.esp32s3 +++ b/examples/bluetooth/blufi/sdkconfig.defaults.esp32s3 @@ -465,7 +465,6 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y # Bluetooth # CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32S3=y CONFIG_BT_SOC_SUPPORT_5_0=y CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 @@ -538,7 +537,7 @@ CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 CONFIG_BT_CTRL_HCI_TL_EFF=1 # -# Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# Bluetooth controller # CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # CONFIG_BT_CTRL_PINNED_TO_CORE_1 is not set @@ -547,7 +546,7 @@ CONFIG_BT_CTRL_PINNED_TO_CORE_0=y # MODEM SLEEP Options # # end of MODEM SLEEP Options -# end of Bluetooth controller(ESP32S3 Bluetooth Low Energy) +# end of Bluetooth controller CONFIG_BT_BLUEDROID_ENABLED=y # CONFIG_BT_NIMBLE_ENABLED is not set @@ -754,7 +753,6 @@ CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_RPA_SUPPORTED=y # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_RESERVE_DRAM=0xdb5c # end of Bluedroid Options # end of Bluetooth diff --git a/examples/bluetooth/esp_ble_mesh/aligenie_demo/sdkconfig.defaults.esp32c3 b/examples/bluetooth/esp_ble_mesh/aligenie_demo/sdkconfig.defaults.esp32c3 index bb2450caf2..cfba1d0ff9 100644 --- a/examples/bluetooth/esp_ble_mesh/aligenie_demo/sdkconfig.defaults.esp32c3 +++ b/examples/bluetooth/esp_ble_mesh/aligenie_demo/sdkconfig.defaults.esp32c3 @@ -13,7 +13,6 @@ CONFIG_ESPTOOLPY_FLASHFREQ_80M=y # Override some defaults so BT stack is enabled # by default in this example CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE=y CONFIG_BT_CTRL_BLE_MESH_SCAN_DUPL_EN=y CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MANUAL=y diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/sdkconfig.defaults b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/sdkconfig.defaults index a11b8edbed..433436bb87 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/sdkconfig.defaults +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_coex_test/sdkconfig.defaults @@ -46,7 +46,7 @@ CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MANUAL=y CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST=y CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY=y CONFIG_BT_SMP_ENABLE=y -CONFIG_BT_RESERVE_DRAM=0x10000 +CONFIG_BTDM_RESERVE_DRAM=0x10000 # # ESP32-specific diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/fast_prov_client/sdkconfig.defaults.esp32c3 b/examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/fast_prov_client/sdkconfig.defaults.esp32c3 index d12cb753a0..fcefd4a641 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/fast_prov_client/sdkconfig.defaults.esp32c3 +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/fast_prov_client/sdkconfig.defaults.esp32c3 @@ -1,7 +1,6 @@ # Override some defaults so BT stack is enabled # by default in this example CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE=y CONFIG_BT_CTRL_BLE_MESH_SCAN_DUPL_EN=y CONFIG_BT_BTU_TASK_STACK_SIZE=4512 diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/fast_prov_client/sdkconfig.defaults.esp32s3 b/examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/fast_prov_client/sdkconfig.defaults.esp32s3 index be15b1ff5e..fcefd4a641 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/fast_prov_client/sdkconfig.defaults.esp32s3 +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/fast_prov_client/sdkconfig.defaults.esp32s3 @@ -1,7 +1,6 @@ # Override some defaults so BT stack is enabled # by default in this example CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32S3=y CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE=y CONFIG_BT_CTRL_BLE_MESH_SCAN_DUPL_EN=y CONFIG_BT_BTU_TASK_STACK_SIZE=4512 diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/fast_prov_server/sdkconfig.defaults.esp32c3 b/examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/fast_prov_server/sdkconfig.defaults.esp32c3 index 842596952b..a75be7d093 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/fast_prov_server/sdkconfig.defaults.esp32c3 +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/fast_prov_server/sdkconfig.defaults.esp32c3 @@ -1,7 +1,6 @@ # Override some defaults so BT stack is enabled # by default in this example CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE=y CONFIG_BT_CTRL_BLE_MESH_SCAN_DUPL_EN=y CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MANUAL=y diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/fast_prov_server/sdkconfig.defaults.esp32s3 b/examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/fast_prov_server/sdkconfig.defaults.esp32s3 index 1b684c187c..a75be7d093 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/fast_prov_server/sdkconfig.defaults.esp32s3 +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_fast_provision/fast_prov_server/sdkconfig.defaults.esp32s3 @@ -1,7 +1,6 @@ # Override some defaults so BT stack is enabled # by default in this example CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32S3=y CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE=y CONFIG_BT_CTRL_BLE_MESH_SCAN_DUPL_EN=y CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MANUAL=y diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/sdkconfig.defaults.esp32c3 b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/sdkconfig.defaults.esp32c3 index 3604e0480a..0a18a5e398 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/sdkconfig.defaults.esp32c3 +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/sdkconfig.defaults.esp32c3 @@ -1,7 +1,6 @@ # Override some defaults so BT stack is enabled # by default in this example CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE=y CONFIG_BT_CTRL_BLE_MESH_SCAN_DUPL_EN=y CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MANUAL=y diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/sdkconfig.defaults.esp32s3 b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/sdkconfig.defaults.esp32s3 index 1884086d0e..0a18a5e398 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/sdkconfig.defaults.esp32s3 +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_client/sdkconfig.defaults.esp32s3 @@ -1,7 +1,6 @@ # Override some defaults so BT stack is enabled # by default in this example CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32S3=y CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE=y CONFIG_BT_CTRL_BLE_MESH_SCAN_DUPL_EN=y CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MANUAL=y diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/sdkconfig.defaults.esp32c3 b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/sdkconfig.defaults.esp32c3 index 12ca77e1dd..fbb2f102d7 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/sdkconfig.defaults.esp32c3 +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/sdkconfig.defaults.esp32c3 @@ -1,7 +1,6 @@ # Override some defaults so BT stack is enabled # by default in this example CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE=y CONFIG_BT_CTRL_BLE_MESH_SCAN_DUPL_EN=y CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MANUAL=y diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/sdkconfig.defaults.esp32s3 b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/sdkconfig.defaults.esp32s3 index 33489399b3..fbb2f102d7 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/sdkconfig.defaults.esp32s3 +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_node/onoff_server/sdkconfig.defaults.esp32s3 @@ -1,7 +1,6 @@ # Override some defaults so BT stack is enabled # by default in this example CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32S3=y CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE=y CONFIG_BT_CTRL_BLE_MESH_SCAN_DUPL_EN=y CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MANUAL=y diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_provisioner/sdkconfig.defaults.esp32c3 b/examples/bluetooth/esp_ble_mesh/ble_mesh_provisioner/sdkconfig.defaults.esp32c3 index 035de4b184..a51201e7c5 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_provisioner/sdkconfig.defaults.esp32c3 +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_provisioner/sdkconfig.defaults.esp32c3 @@ -1,7 +1,6 @@ # Override some defaults so BT stack is enabled # by default in this example CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE=y CONFIG_BT_CTRL_BLE_MESH_SCAN_DUPL_EN=y CONFIG_BT_BTU_TASK_STACK_SIZE=4512 diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_provisioner/sdkconfig.defaults.esp32s3 b/examples/bluetooth/esp_ble_mesh/ble_mesh_provisioner/sdkconfig.defaults.esp32s3 index 7f5eadea41..a51201e7c5 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_provisioner/sdkconfig.defaults.esp32s3 +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_provisioner/sdkconfig.defaults.esp32s3 @@ -1,7 +1,6 @@ # Override some defaults so BT stack is enabled # by default in this example CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32S3=y CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE=y CONFIG_BT_CTRL_BLE_MESH_SCAN_DUPL_EN=y CONFIG_BT_BTU_TASK_STACK_SIZE=4512 diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_sensor_model/sensor_client/sdkconfig.defaults.esp32c3 b/examples/bluetooth/esp_ble_mesh/ble_mesh_sensor_model/sensor_client/sdkconfig.defaults.esp32c3 index 883572177f..40b895710b 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_sensor_model/sensor_client/sdkconfig.defaults.esp32c3 +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_sensor_model/sensor_client/sdkconfig.defaults.esp32c3 @@ -1,7 +1,6 @@ # Override some defaults so BT stack is enabled # by default in this example CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE=y CONFIG_BT_CTRL_BLE_MESH_SCAN_DUPL_EN=y CONFIG_BT_BTU_TASK_STACK_SIZE=4512 diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_sensor_model/sensor_client/sdkconfig.defaults.esp32s3 b/examples/bluetooth/esp_ble_mesh/ble_mesh_sensor_model/sensor_client/sdkconfig.defaults.esp32s3 index 585751ad9e..40b895710b 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_sensor_model/sensor_client/sdkconfig.defaults.esp32s3 +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_sensor_model/sensor_client/sdkconfig.defaults.esp32s3 @@ -1,7 +1,6 @@ # Override some defaults so BT stack is enabled # by default in this example CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32S3=y CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE=y CONFIG_BT_CTRL_BLE_MESH_SCAN_DUPL_EN=y CONFIG_BT_BTU_TASK_STACK_SIZE=4512 diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_sensor_model/sensor_server/sdkconfig.defaults.esp32c3 b/examples/bluetooth/esp_ble_mesh/ble_mesh_sensor_model/sensor_server/sdkconfig.defaults.esp32c3 index 12ca77e1dd..fbb2f102d7 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_sensor_model/sensor_server/sdkconfig.defaults.esp32c3 +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_sensor_model/sensor_server/sdkconfig.defaults.esp32c3 @@ -1,7 +1,6 @@ # Override some defaults so BT stack is enabled # by default in this example CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE=y CONFIG_BT_CTRL_BLE_MESH_SCAN_DUPL_EN=y CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MANUAL=y diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_sensor_model/sensor_server/sdkconfig.defaults.esp32s3 b/examples/bluetooth/esp_ble_mesh/ble_mesh_sensor_model/sensor_server/sdkconfig.defaults.esp32s3 index 33489399b3..fbb2f102d7 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_sensor_model/sensor_server/sdkconfig.defaults.esp32s3 +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_sensor_model/sensor_server/sdkconfig.defaults.esp32s3 @@ -1,7 +1,6 @@ # Override some defaults so BT stack is enabled # by default in this example CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32S3=y CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE=y CONFIG_BT_CTRL_BLE_MESH_SCAN_DUPL_EN=y CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MANUAL=y diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_vendor_model/vendor_client/sdkconfig.defaults.esp32c3 b/examples/bluetooth/esp_ble_mesh/ble_mesh_vendor_model/vendor_client/sdkconfig.defaults.esp32c3 index 83d0e49eb3..dfaa377627 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_vendor_model/vendor_client/sdkconfig.defaults.esp32c3 +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_vendor_model/vendor_client/sdkconfig.defaults.esp32c3 @@ -1,7 +1,6 @@ # Override some defaults so BT stack is enabled # by default in this example CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE=y CONFIG_BT_CTRL_BLE_MESH_SCAN_DUPL_EN=y CONFIG_BT_BTU_TASK_STACK_SIZE=4512 diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_vendor_model/vendor_client/sdkconfig.defaults.esp32s3 b/examples/bluetooth/esp_ble_mesh/ble_mesh_vendor_model/vendor_client/sdkconfig.defaults.esp32s3 index 76061212d3..dfaa377627 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_vendor_model/vendor_client/sdkconfig.defaults.esp32s3 +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_vendor_model/vendor_client/sdkconfig.defaults.esp32s3 @@ -1,7 +1,6 @@ # Override some defaults so BT stack is enabled # by default in this example CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32S3=y CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE=y CONFIG_BT_CTRL_BLE_MESH_SCAN_DUPL_EN=y CONFIG_BT_BTU_TASK_STACK_SIZE=4512 diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_vendor_model/vendor_server/sdkconfig.defaults.esp32c3 b/examples/bluetooth/esp_ble_mesh/ble_mesh_vendor_model/vendor_server/sdkconfig.defaults.esp32c3 index 12ca77e1dd..fbb2f102d7 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_vendor_model/vendor_server/sdkconfig.defaults.esp32c3 +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_vendor_model/vendor_server/sdkconfig.defaults.esp32c3 @@ -1,7 +1,6 @@ # Override some defaults so BT stack is enabled # by default in this example CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32C3=y CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE=y CONFIG_BT_CTRL_BLE_MESH_SCAN_DUPL_EN=y CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MANUAL=y diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_vendor_model/vendor_server/sdkconfig.defaults.esp32s3 b/examples/bluetooth/esp_ble_mesh/ble_mesh_vendor_model/vendor_server/sdkconfig.defaults.esp32s3 index 33489399b3..fbb2f102d7 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_vendor_model/vendor_server/sdkconfig.defaults.esp32s3 +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_vendor_model/vendor_server/sdkconfig.defaults.esp32s3 @@ -1,7 +1,6 @@ # Override some defaults so BT stack is enabled # by default in this example CONFIG_BT_ENABLED=y -CONFIG_BT_CTRL_ESP32S3=y CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE=y CONFIG_BT_CTRL_BLE_MESH_SCAN_DUPL_EN=y CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MANUAL=y diff --git a/examples/bluetooth/esp_ble_mesh/ble_mesh_wifi_coexist/main/cmd_wifi.c b/examples/bluetooth/esp_ble_mesh/ble_mesh_wifi_coexist/main/cmd_wifi.c index 40e67a3281..f496e7f2c2 100644 --- a/examples/bluetooth/esp_ble_mesh/ble_mesh_wifi_coexist/main/cmd_wifi.c +++ b/examples/bluetooth/esp_ble_mesh/ble_mesh_wifi_coexist/main/cmd_wifi.c @@ -23,7 +23,9 @@ typedef struct { struct arg_str *ip; struct arg_lit *server; struct arg_lit *udp; + struct arg_lit *version; struct arg_int *port; + struct arg_int *length; struct arg_int *interval; struct arg_int *time; struct arg_lit *abort; @@ -51,8 +53,8 @@ static const char *TAG = "iperf"; static EventGroupHandle_t wifi_event_group; const int CONNECTED_BIT = BIT0; const int DISCONNECTED_BIT = BIT1; -static esp_netif_t * sta_netif = NULL; -static esp_netif_t * ap_netif = NULL; +static esp_netif_t *sta_netif = NULL; +static esp_netif_t *ap_netif = NULL; static void scan_done_handler(void) { @@ -75,8 +77,8 @@ static void scan_done_handler(void) free(ap_list_buffer); } -static void wifi_event_handler(void* arg, esp_event_base_t event_base, - int32_t event_id, void* event_data) +static void wifi_event_handler(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) { switch (event_id) { case WIFI_EVENT_SCAN_DONE: @@ -102,8 +104,8 @@ static void wifi_event_handler(void* arg, esp_event_base_t event_base, return; } -static void ip_event_handler(void* arg, esp_event_base_t event_base, - int32_t event_id, void* event_data) +static void ip_event_handler(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) { switch (event_id) { case IP_EVENT_STA_GOT_IP: @@ -292,7 +294,7 @@ static int wifi_cmd_query(int argc, char **argv) static uint32_t wifi_get_local_ip(void) { int bits = xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, 0, 1, 0); - esp_netif_t * ifx = ap_netif; + esp_netif_t *ifx = ap_netif; esp_netif_ip_info_t ip_info; wifi_mode_t mode; @@ -323,6 +325,9 @@ static int wifi_cmd_iperf(int argc, char **argv) memset(&cfg, 0, sizeof(cfg)); + // wifi iperf only support IPV4 address + cfg.type = IPERF_IP_TYPE_IPV4; + if ( iperf_args.abort->count != 0) { iperf_stop(); return 0; @@ -337,15 +342,21 @@ static int wifi_cmd_iperf(int argc, char **argv) if (iperf_args.ip->count == 0) { cfg.flag |= IPERF_FLAG_SERVER; } else { - cfg.dip = esp_ip4addr_aton(iperf_args.ip->sval[0]); + cfg.destination_ip4 = esp_ip4addr_aton(iperf_args.ip->sval[0]); cfg.flag |= IPERF_FLAG_CLIENT; } - cfg.sip = wifi_get_local_ip(); - if (cfg.sip == 0) { + cfg.source_ip4 = wifi_get_local_ip(); + if (cfg.source_ip4 == 0) { return 0; } + if (iperf_args.length->count == 0) { + cfg.len_send_buf = 0; + } else { + cfg.len_send_buf = iperf_args.length->ival[0]; + } + if (iperf_args.udp->count == 0) { cfg.flag |= IPERF_FLAG_TCP; } else { @@ -386,8 +397,10 @@ static int wifi_cmd_iperf(int argc, char **argv) ESP_LOGI(TAG, "mode=%s-%s sip=%d.%d.%d.%d:%d, dip=%d.%d.%d.%d:%d, interval=%d, time=%d", cfg.flag & IPERF_FLAG_TCP ? "tcp" : "udp", cfg.flag & IPERF_FLAG_SERVER ? "server" : "client", - cfg.sip & 0xFF, (cfg.sip >> 8) & 0xFF, (cfg.sip >> 16) & 0xFF, (cfg.sip >> 24) & 0xFF, cfg.sport, - cfg.dip & 0xFF, (cfg.dip >> 8) & 0xFF, (cfg.dip >> 16) & 0xFF, (cfg.dip >> 24) & 0xFF, cfg.dport, + cfg.source_ip4 & 0xFF, (cfg.source_ip4 >> 8) & 0xFF, (cfg.source_ip4 >> 16) & 0xFF, + (cfg.source_ip4 >> 24) & 0xFF, cfg.sport, + cfg.destination_ip4 & 0xFF, (cfg.destination_ip4 >> 8) & 0xFF, (cfg.destination_ip4 >> 16) & 0xFF, + (cfg.destination_ip4 >> 24) & 0xFF, cfg.dport, cfg.interval, cfg.time); iperf_start(&cfg); @@ -471,7 +484,9 @@ void register_wifi(void) iperf_args.ip = arg_str0("c", "client", "", "run in client mode, connecting to "); iperf_args.server = arg_lit0("s", "server", "run in server mode"); iperf_args.udp = arg_lit0("u", "udp", "use UDP rather than TCP"); + iperf_args.version = arg_lit0("V", "ipv6_domain", "use IPV6 address rather than IPV4"); iperf_args.port = arg_int0("p", "port", "", "server port to listen on/connect to"); + iperf_args.length = arg_int0("l", "len", "", "set read/write buffer size"); iperf_args.interval = arg_int0("i", "interval", "", "seconds between periodic bandwidth reports"); iperf_args.time = arg_int0("t", "time", "